/* //@HEADER // ************************************************************************ // // Kokkos v. 2.0 // Copyright (2014) Sandia Corporation // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // the U.S. Government retains certain rights in this software. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the name of the Corporation nor the names of the // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Questions? Contact Christian R. Trott (crtrott@sandia.gov) // // ************************************************************************ //@HEADER */ // This example simulates one timestep of an explicit // finite-difference discretization of a time-dependent partial // differential equation (PDE). It shows how to take subviews of the // mesh in order to represent particular boundaries or the interior of // the mesh. #include #include #include typedef Kokkos::View mesh_type; // These View types represent subviews of the mesh. Some of the Views // have layout LayoutStride, meaning that they have run-time "strides" // in each dimension which may differ from that dimension. For // example, inner_mesh_type (which represents the interior of the // mesh) has to skip over the boundaries when computing its stride; // the dimensions of the interior mesh differ from these strides. You // may safely always use a LayoutStride layout when taking a subview // of a LayoutRight or LayoutLeft subview, but strided accesses may // cost a bit more, especially for 1-D Views. typedef Kokkos::View xz_plane_type; typedef Kokkos::View yz_plane_type; typedef Kokkos::View xy_plane_type; typedef Kokkos::View inner_mesh_type; // Functor to set all entries of a boundary of the mesh to a constant // value. The functor is templated on ViewType because different // boundaries may have different layouts. template struct set_boundary { ViewType a; double value; set_boundary (ViewType a_, double value_) : a (a_), value (value_) {} KOKKOS_INLINE_FUNCTION void operator() (const typename ViewType::size_type i) const { for (typename ViewType::size_type j = 0; j < a.extent(1); ++j) { a(i,j) = value; } } }; // Functor to set all entries of a boundary of the mesh to a constant // value. The functor is templated on ViewType because different // boundaries may have different layouts. template struct set_inner { ViewType a; double value; set_inner (ViewType a_, double value_) : a (a_), value (value_) {} KOKKOS_INLINE_FUNCTION void operator () (const typename ViewType::size_type i) const { typedef typename ViewType::size_type size_type; for (size_type j = 0; j < a.extent(1); ++j) { for (size_type k = 0; k < a.extent(2); ++k) { a(i,j,k) = value; } } } }; // Update the interior of the mesh. This simulates one timestep of a // finite-difference method. template struct update { ViewType a; const double dt; update (ViewType a_, const double dt_) : a (a_), dt (dt_) {} KOKKOS_INLINE_FUNCTION void operator() (typename ViewType::size_type i) const { typedef typename ViewType::size_type size_type; i++; for (size_type j = 1; j < a.extent(1)-1; j++) { for (size_type k = 1; k < a.extent(2)-1; k++) { a(i,j,k) += dt* (a(i,j,k+1) - a(i,j,k-1) + a(i,j+1,k) - a(i,j-1,k) + a(i+1,j,k) - a(i-1,j,k)); } } } }; int main (int narg, char* arg[]) { using Kokkos::ALL; using Kokkos::pair; using Kokkos::parallel_for; using Kokkos::subview; typedef mesh_type::size_type size_type; Kokkos::initialize (narg, arg); { // The number of mesh points along each dimension of the mesh, not // including boundaries. const size_type size = 100; // A is the full cubic 3-D mesh, including the boundaries. mesh_type A ("A", size+2, size+2, size+2); // Ai is the "inner" part of A, _not_ including the boundaries. // // A pair of indices in a particular dimension means the contiguous // zero-based index range in that dimension, including the first // entry of the pair but _not_ including the second entry. inner_mesh_type Ai = subview(A, pair (1, size+1), pair (1, size+1), pair (1, size+1)); // A has six boundaries, one for each face of the cube. // Create a View of each of these boundaries. // ALL() means "select all indices in that dimension." xy_plane_type Zneg_halo = subview(A, ALL (), ALL (), 0); xy_plane_type Zpos_halo = subview(A, ALL (), ALL (), 101); xz_plane_type Yneg_halo = subview(A, ALL (), 0, ALL ()); xz_plane_type Ypos_halo = subview(A, ALL (), 101, ALL ()); yz_plane_type Xneg_halo = subview(A, 0, ALL (), ALL ()); yz_plane_type Xpos_halo = subview(A, 101, ALL (), ALL ()); // Set the boundaries to their initial conditions. parallel_for (Zneg_halo.extent(0), set_boundary (Zneg_halo, 1)); parallel_for (Zpos_halo.extent(0), set_boundary (Zpos_halo, -1)); parallel_for (Yneg_halo.extent(0), set_boundary (Yneg_halo, 2)); parallel_for (Ypos_halo.extent(0), set_boundary (Ypos_halo, -2)); parallel_for (Xneg_halo.extent(0), set_boundary (Xneg_halo, 3)); parallel_for (Xpos_halo.extent(0), set_boundary (Xpos_halo, -3)); // Set the interior of the mesh to its initial condition. parallel_for (Ai.extent(0), set_inner (Ai, 0)); // Update the interior of the mesh. // This simulates one timestep with dt = 0.1. parallel_for (Ai.extent(0), update (A, 0.1)); Kokkos::fence(); printf ("Done\n"); } Kokkos::finalize (); }