11#include " Kokkos_Core.hpp"
22#include " Kokkos_DualView.hpp"
33
4+ using Entity_ID = int ;
5+
6+ enum memory {host, device};
7+
8+
49//
510// Note, this API is consistent with amanzi/ecoon/mesh_refactor src/mesh/MeshFramework.hh API
611//
712struct MeshFramework {
813 MeshFramework (const int size): mesh_size_(size) {}
914
1015 // In MeshFramework this function "compute" the result on Host
11- int getCellVolume (const int i) const {
16+ double getCellVolume (const Entity_ID i) const {
1217 return i;
1318 }
1419
1520 // In MeshFramework this function "compute" the result on Host
16- void getCellFaces ( const int id, Kokkos::View<const int *,Kokkos::HostSpace>& ret ) const {
21+ Kokkos::View<const Entity_ID *,Kokkos::HostSpace> getCellFaces ( const Entity_ID id ) const {
1722 // 2 Elements per entries
18- Kokkos::View<int *, Kokkos::HostSpace> tmp (" " ,2 );
23+ Kokkos::View<Entity_ID *, Kokkos::HostSpace> tmp (" " ,2 );
1924 for (int i = 0 ; i < 2 ; ++i){
2025 tmp (i) = value*i;
2126 }
22- ret = tmp;
27+ return tmp;
2328 }
2429
25- int meshSize () const { return mesh_size_; }
30+ Entity_ID getCellFace (Entity_ID c, std::size_t i) const {
31+ return value*i;
32+ }
33+
34+ Entity_ID meshSize () const { return mesh_size_; }
2635
2736private:
28- const int value = 10 ;
37+ const Entity_ID value = 10 ;
2938 int mesh_size_;
3039};
3140
32-
33- // NOTE: need this...
34- template <typename Data, typename ExecutionSpace = Kokkos::DefaultExecutionSpace>
35- struct CSR ;
36-
37-
38- using Entity_ID = int ;
39-
40- //
41- // Note, this API is consistent with amanzi/ecoon/mesh_refactor src/mesh/MeshCache.hh API.
42- //
43- // If it helped, these could be dual views?
44- //
41+ // MeshCache templated on the memory type
42+ // Defaulted to the device memory space
4543template <typename ExecutionSpace = Kokkos::DefaultExecutionSpace>
4644struct MeshCache {
45+
4746 using Double_View = Kokkos::View<double *, ExecutionSpace>; // ?????
4847 using cDouble_View = Kokkos::View<const double *, ExecutionSpace>; // ?????
4948 using Entity_ID_View = Kokkos::View<Entity_ID*, ExecutionSpace>;
5049 using cEntity_ID_View = Kokkos::View<const Entity_ID*, ExecutionSpace>;
5150
52- MeshCache (Teuchos::RCP<MeshFramework>& mf); // note, feel free to make shared_ptr or raw ptr for now...
53-
54- double getCellVolume (const Entity_ID c) const ;
55- Double_View cell_volumes; // note, this is public and can be used inside kernels directly
56- // is there a const problem with exposing this directly? Specifically,
57- // assume you have a const MeshCache. Can you still change
58- // mc.cell_volumes(3) = 1? Should this be cDoubleView?
59-
60- std::size_t getCellNumFaces (const Entity_ID c) const ;
61- cEntity_ID_View getCellFaces (const Entity_ID c) const ;
62- Entity_ID getCellFace (Entity_ID c, std::size_t i) const ;
63- CRS<Entity_ID, ExecutionSpace> cell_faces;
64- }
65-
66-
67-
68-
69- // MeshCache templated on the memory type
70- // Defaulted to the device memory space
71- template <typename ExecutionSpace = Kokkos::DefaultExecutionSpace>
72- struct MeshCache {
7351
7452 // Type to get CRS on DualViews
75- template <typename T, typename ExecutionSpace >
53+ template <typename T, typename ES >
7654 struct DualCrs {
77- Kokkos::DualView<int *, ExecutionSpace > row_map;
78- Kokkos::DualView<T, ExecutionSpace > entries;
55+ Kokkos::DualView<int *, ES > row_map;
56+ Kokkos::DualView<T, ES > entries;
7957 };
8058
8159 // Building a Mesh Cache on ExecutionSpace memory space.
@@ -91,7 +69,7 @@ struct MeshCache {
9169 for (int i = 0 ; i < mesh_size_ ; ++i){
9270 value_2d_.row_map .view_host ()(i) = i*2 ;
9371 Kokkos::View<const int *, Kokkos::HostSpace> tmp;
94- mf->getCellFaces (i,tmp );
72+ tmp = mf->getCellFaces (i);
9573 for (int j = 0 ; j < 2 ; ++j){
9674 value_2d_.entries .view_host ()(i*2 +j) = tmp (j);
9775 }
@@ -104,51 +82,50 @@ struct MeshCache {
10482 }
10583
10684 // This function can just be overloaded with the Kokkos::View type.
107- KOKKOS_INLINE_FUNCTION void getCellFaces (int id, Kokkos::View<const int *,ExecutionSpace>& ret) const {
108- ret = Kokkos::subview (value_2d_.entries .view_device (),
85+ template <memory MEM = device>
86+ KOKKOS_INLINE_FUNCTION auto getCellFaces (Entity_ID id) const {
87+ if constexpr (MEM == device){
88+ Kokkos::View<const int *,ExecutionSpace> ret = Kokkos::subview (value_2d_.entries .view_device (),
10989 Kokkos::make_pair (value_2d_.row_map .view_device ()(id),
11090 value_2d_.row_map .view_device ()(id + 1 )));
111- }
112- void getCellFaces ( int id, Kokkos::View< const int *,Kokkos::HostSpace>& ret) const {
113- Kokkos::subview (value_2d_.entries .view_host (),
91+ return ret;
92+ } else if (MEM == host) {
93+ Kokkos::View< const Entity_ID*,Kokkos::HostSpace> ret = Kokkos:: subview (value_2d_.entries .view_host (),
11494 Kokkos::make_pair (value_2d_.row_map .view_host ()(id),
11595 value_2d_.row_map .view_host ()(id + 1 )));
96+ return ret;
97+ }
11698 }
11799
118- // The following function cannot be overloaded with parameters
119- // Default: only use Device function
120- KOKKOS_INLINE_FUNCTION int getCellVolume (int i) const {
121- return value_1d_.view_device ()(i);
122- }
123-
124- // Duplicate function with host decoration
125- int getCellVolume_host (int i) const {
126- return value_1d_.view_host ()(i);
100+ template <memory MEM = device>
101+ KOKKOS_INLINE_FUNCTION Entity_ID getCellFace (Entity_ID c, int i) const {
102+ if constexpr (MEM == device){
103+ return value_2d_.entries .view_device ()(value_2d_.row_map .view_device ()(c)+i);
104+ } else if (MEM == host){
105+ return value_2d_.entries .view_host ()(value_2d_.row_map .view_host ()(c)+i);
106+ }
127107 }
128108
129- // Using C++ 17 with constexpr
130- #if V2
131- template <typename FExecutionSpace = Kokkos::HostSpace>
132- int getCellVolume (int i) const {
133- if constexpr (std::is_same<Kokkos::HostSpace,FExecutionSpace>::value) {
134- return value_1d_.view_host ()(i);
135- } else if (std::is_same<Kokkos::CudaSpace,FExecutionSpace>::value) {
109+ // The following function cannot be overloaded with parameters
110+ // Default: only use Device function
111+ template <memory MEM = device>
112+ KOKKOS_INLINE_FUNCTION double getCellVolume (Entity_ID i) const {
113+ if constexpr (MEM == device){
136114 return value_1d_.view_device ()(i);
115+ } else if (MEM == host) {
116+ return value_1d_.view_host ()(i);
137117 }
138118 }
139- #endif
140119
141120private:
142- Kokkos::DualView<int *,ExecutionSpace> value_1d_;
143- DualCrs<int *,ExecutionSpace> value_2d_;
121+ Kokkos::DualView<double *,ExecutionSpace> value_1d_;
122+ DualCrs<Entity_ID *,ExecutionSpace> value_2d_;
144123 MeshFramework* framework_mesh_;
145124 int mesh_size_;
146125};
147126
148-
149-
150-
151127void test_mesh () {
128+
152129 using DeviceSpace = Kokkos::CudaSpace;
153130 const int ncells = 10 ;
154131 MeshFramework m (ncells);
@@ -157,38 +134,52 @@ void test_mesh() {
157134 // ------- Mesh Framework -------
158135 // Only accessible on Host
159136 for (int i = 0 ; i < ncells ; ++i){
160- // 1d
161- assert (m.getCellVolume (i) == i);
162- // 2d
137+ if (m.getCellVolume (i) != i)
138+ printf (" ERROR %.1f != %d \n " ,m.getCellVolume (i),i);
163139 Kokkos::View<const int *, Kokkos::HostSpace> v_h;
164- m.getCellFaces (2 , v_h);
140+ v_h = m.getCellFaces (2 );
141+ for (int j = 0 ; j < 2 ; ++j){
142+ if (v_h (j) != j*10 )
143+ printf (" ERROR %d != %d \n " ,v_h (j),j*10 );
144+ }
165145 for (int j = 0 ; j < 2 ; ++j){
166- assert (v_h (j) == j*10 );
146+ if (m.getCellFace (2 ,j) != j*10 )
147+ printf (" ERROR %d != %d \n " ,m.getCellFace (2 ,j),j*10 );
167148 }
168149 }
169150
151+
170152 // ------- Mesh Cache -------
171153 // 1. Device Access (Default type of the mesh cache)
172154 Kokkos::parallel_for (
173- " " ,
174- ncells,
175- KOKKOS_LAMBDA (const int i){
176- // 1d
177- assert (mc.getCellVolume (i) == i);
178- // 2d
155+ ncells, KOKKOS_LAMBDA (const int i){
156+ if (mc.getCellVolume (i) != i)
157+ printf (" ERROR %.1f != %d \n " ,mc.getCellVolume (i),i);
179158 Kokkos::View<const int *, DeviceSpace> v_d;
180- mc.getCellFaces (2 ,v_d );
159+ v_d = mc.getCellFaces (2 );
181160 for (int j = 0 ; j < 2 ; ++j){
182- assert (v_d (j) == j*10 );
161+ if (v_d (j) != j*10 )
162+ printf (" ERROR %d != %d \n " ,v_d (j),j*10 );
163+ }
164+ for (int j = 0 ; j < 2 ; ++j){
165+ if (mc.getCellFace (2 ,j) != j*10 )
166+ printf (" ERROR %d != %d \n " ,mc.getCellFace (2 ,j),j*10 );
183167 }
184168 });
185169 // 2. Host Access
186170 for (int i = 0 ; i < ncells ; ++i){
187- // 1d
188- assert (mc.getCellVolume_host (i) == i);
189- // 2d
171+ if (mc.getCellVolume <memory::host>(i) != i)
172+ printf (" ERROR %.1f != %d \n " ,mc.getCellVolume <memory::host>(i),i);
190173 Kokkos::View<const int *, Kokkos::HostSpace> v_h;
191- mc.getCellFaces (2 , v_h);
174+ v_h = mc.getCellFaces <memory::host>(2 );
175+ for (int j = 0 ; j < 2 ; ++j){
176+ if (v_h (j) != j*10 )
177+ printf (" ERROR %d != %d \n " ,v_h (j),j*10 );
178+ }
179+ for (int j = 0 ; j < 2 ; ++j){
180+ if (mc.getCellFace <memory::host>(2 ,j) != j*10 )
181+ printf (" ERROR %d != %d \n " ,mc.getCellFace <memory::host>(2 ,j),j*10 );
182+ }
192183 }
193184} // test_mesh
194185
0 commit comments