xref: /petsc/src/dm/tests/ex10k.kokkos.cxx (revision cd1bdac545d20179bf6a6b3f786454bb86c0c48d)
1*a90d8e38SSatish Balay static char help[] = "Tests DMDAVecGetKokkosOffsetView() and DMDAVecGetKokkosOffsetViewDOF() \n\n";
2*a90d8e38SSatish Balay 
3*a90d8e38SSatish Balay #include <petscdmda_kokkos.hpp>
4*a90d8e38SSatish Balay #include <petscdm.h>
5*a90d8e38SSatish Balay #include <petscdmda.h>
6*a90d8e38SSatish Balay 
7*a90d8e38SSatish Balay using Kokkos::Iterate;
8*a90d8e38SSatish Balay using Kokkos::MDRangePolicy;
9*a90d8e38SSatish Balay using Kokkos::Rank;
10*a90d8e38SSatish Balay using PetscScalarKokkosOffsetView2D      = Kokkos::Experimental::OffsetView<PetscScalar **, Kokkos::LayoutRight, Kokkos::DefaultExecutionSpace::memory_space>;
11*a90d8e38SSatish Balay using ConstPetscScalarKokkosOffsetView2D = Kokkos::Experimental::OffsetView<const PetscScalar **, Kokkos::LayoutRight, Kokkos::DefaultExecutionSpace::memory_space>;
12*a90d8e38SSatish Balay 
13*a90d8e38SSatish Balay using PetscScalarKokkosOffsetView3D      = Kokkos::Experimental::OffsetView<PetscScalar ***, Kokkos::LayoutRight, Kokkos::DefaultExecutionSpace::memory_space>;
14*a90d8e38SSatish Balay using ConstPetscScalarKokkosOffsetView3D = Kokkos::Experimental::OffsetView<const PetscScalar ***, Kokkos::LayoutRight, Kokkos::DefaultExecutionSpace::memory_space>;
15*a90d8e38SSatish Balay 
16*a90d8e38SSatish Balay /* can not define the type inside main, otherwise have this compilation error:
17*a90d8e38SSatish Balay    error: A type local to a function ("Node") cannot be used in the type of a
18*a90d8e38SSatish Balay    variable captured by an extended __device__ or __host__ __device__ lambda
19*a90d8e38SSatish Balay */
20*a90d8e38SSatish Balay typedef struct {
21*a90d8e38SSatish Balay   PetscScalar u, v, w;
22*a90d8e38SSatish Balay } Node;
23*a90d8e38SSatish Balay 
24*a90d8e38SSatish Balay using NodeKokkosOffsetView2D      = Kokkos::Experimental::OffsetView<Node **, Kokkos::LayoutRight, Kokkos::DefaultExecutionSpace::memory_space>;
25*a90d8e38SSatish Balay using ConstNodeKokkosOffsetView2D = Kokkos::Experimental::OffsetView<const Node **, Kokkos::LayoutRight, Kokkos::DefaultExecutionSpace::memory_space>;
26*a90d8e38SSatish Balay 
main(int argc,char ** argv)27*a90d8e38SSatish Balay int main(int argc, char **argv)
28*a90d8e38SSatish Balay {
29*a90d8e38SSatish Balay   DM              da;
30*a90d8e38SSatish Balay   PetscInt        M = 5, N = 7, xm, ym, xs, ys;
31*a90d8e38SSatish Balay   PetscInt        dof = 1, sw = 1;
32*a90d8e38SSatish Balay   DMBoundaryType  bx = DM_BOUNDARY_PERIODIC, by = DM_BOUNDARY_PERIODIC;
33*a90d8e38SSatish Balay   DMDAStencilType st = DMDA_STENCIL_STAR;
34*a90d8e38SSatish Balay   PetscReal       nrm;
35*a90d8e38SSatish Balay   Vec             g, l, gg, ll; /* global/local vectors of the da */
36*a90d8e38SSatish Balay 
37*a90d8e38SSatish Balay   PetscFunctionBeginUser;
38*a90d8e38SSatish Balay   PetscCall(PetscInitialize(&argc, &argv, nullptr, help));
39*a90d8e38SSatish Balay 
40*a90d8e38SSatish Balay   /* ===========================================================================
41*a90d8e38SSatish Balay     Show how to manage a multi-component DMDA with DMDAVecGetKokkosOffsetViewDOF
42*a90d8e38SSatish Balay    ============================================================================*/
43*a90d8e38SSatish Balay   PetscScalar                     ***garray; /* arrays of g, ll */
44*a90d8e38SSatish Balay   const PetscScalar               ***larray;
45*a90d8e38SSatish Balay   PetscScalarKokkosOffsetView3D      gview; /* views of gg, ll */
46*a90d8e38SSatish Balay   ConstPetscScalarKokkosOffsetView3D lview;
47*a90d8e38SSatish Balay 
48*a90d8e38SSatish Balay   dof = 2;
49*a90d8e38SSatish Balay   PetscCall(DMDACreate2d(PETSC_COMM_WORLD, bx, by, st, M, N, PETSC_DECIDE, PETSC_DECIDE, dof, sw, NULL, NULL, &da));
50*a90d8e38SSatish Balay   PetscCall(DMSetFromOptions(da));
51*a90d8e38SSatish Balay   PetscCall(DMSetUp(da));
52*a90d8e38SSatish Balay   PetscCall(DMDAGetCorners(da, &xs, &ys, 0, &xm, &ym, 0));
53*a90d8e38SSatish Balay   PetscCall(DMCreateGlobalVector(da, &g));
54*a90d8e38SSatish Balay   PetscCall(DMCreateLocalVector(da, &l));
55*a90d8e38SSatish Balay   PetscCall(DMCreateGlobalVector(da, &gg));
56*a90d8e38SSatish Balay   PetscCall(DMCreateLocalVector(da, &ll));
57*a90d8e38SSatish Balay 
58*a90d8e38SSatish Balay   /* Init g using array */
59*a90d8e38SSatish Balay   PetscCall(DMDAVecGetArrayDOFWrite(da, g, &garray));
60*a90d8e38SSatish Balay   for (PetscInt j = ys; j < ys + ym; j++) { /* run on host */
61*a90d8e38SSatish Balay     for (PetscInt i = xs; i < xs + xm; i++) {
62*a90d8e38SSatish Balay       for (PetscInt c = 0; c < dof; c++) garray[j][i][c] = 100 * j + 10 * (i + 1) + c;
63*a90d8e38SSatish Balay     }
64*a90d8e38SSatish Balay   }
65*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreArrayDOFWrite(da, g, &garray));
66*a90d8e38SSatish Balay 
67*a90d8e38SSatish Balay   /* Init gg using view */
68*a90d8e38SSatish Balay   PetscCall(DMDAVecGetKokkosOffsetViewDOFWrite(da, gg, &gview));
69*a90d8e38SSatish Balay   Kokkos::parallel_for(
70*a90d8e38SSatish Balay     "init 1", MDRangePolicy<Rank<3, Iterate::Right, Iterate::Right>>({ys, xs, 0}, {ys + ym, xs + xm, dof}),
71*a90d8e38SSatish Balay     KOKKOS_LAMBDA(PetscInt j, PetscInt i, PetscInt c) /* might run on device */
72*a90d8e38SSatish Balay     { gview(j, i, c) = 100 * j + 10 * (i + 1) + c; });
73*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreKokkosOffsetViewDOFWrite(da, gg, &gview));
74*a90d8e38SSatish Balay 
75*a90d8e38SSatish Balay   /* Scatter g, gg to l, ll */
76*a90d8e38SSatish Balay   PetscCall(DMGlobalToLocal(da, g, INSERT_VALUES, l));
77*a90d8e38SSatish Balay   PetscCall(DMGlobalToLocal(da, gg, INSERT_VALUES, ll));
78*a90d8e38SSatish Balay 
79*a90d8e38SSatish Balay   /* Do stencil on g with values from l that contains ghosts */
80*a90d8e38SSatish Balay   PetscCall(DMDAVecGetArrayDOFWrite(da, g, &garray));
81*a90d8e38SSatish Balay   PetscCall(DMDAVecGetArrayDOFRead(da, l, &larray));
82*a90d8e38SSatish Balay   for (PetscInt j = ys; j < ys + ym; j++) {
83*a90d8e38SSatish Balay     for (PetscInt i = xs; i < xs + xm; i++) {
84*a90d8e38SSatish Balay       for (PetscInt c = 0; c < dof; c++) garray[j][i][c] = (larray[j][i - 1][c] + larray[j][i + 1][c] + larray[j - 1][i][c] + larray[j + 1][i][c]) / 4.0;
85*a90d8e38SSatish Balay     }
86*a90d8e38SSatish Balay   }
87*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreArrayDOFWrite(da, g, &garray));
88*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreArrayDOFRead(da, l, &larray));
89*a90d8e38SSatish Balay 
90*a90d8e38SSatish Balay   /* Do stencil on gg with values from ll that contains ghosts */
91*a90d8e38SSatish Balay   PetscCall(DMDAVecGetKokkosOffsetViewDOFWrite(da, gg, &gview));
92*a90d8e38SSatish Balay   PetscCall(DMDAVecGetKokkosOffsetViewDOF(da, ll, &lview));
93*a90d8e38SSatish Balay   Kokkos::parallel_for(
94*a90d8e38SSatish Balay     "stencil 1", MDRangePolicy<Rank<3, Iterate::Right, Iterate::Right>>({ys, xs, 0}, {ys + ym, xs + xm, dof}),
95*a90d8e38SSatish Balay     KOKKOS_LAMBDA(PetscInt j, PetscInt i, PetscInt c) { gview(j, i, c) = (lview(j, i - 1, c) + lview(j, i + 1, c) + lview(j - 1, i, c) + lview(j + 1, i, c)) / 4.0; });
96*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreKokkosOffsetViewDOFWrite(da, gg, &gview));
97*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreKokkosOffsetViewDOF(da, ll, &lview));
98*a90d8e38SSatish Balay 
99*a90d8e38SSatish Balay   /* gg should be equal to g */
100*a90d8e38SSatish Balay   PetscCall(VecAXPY(g, -1.0, gg));
101*a90d8e38SSatish Balay   PetscCall(VecNorm(g, NORM_2, &nrm));
102*a90d8e38SSatish Balay   PetscCheck(nrm < PETSC_SMALL, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "gg is not equal to g");
103*a90d8e38SSatish Balay 
104*a90d8e38SSatish Balay   PetscCall(DMDestroy(&da));
105*a90d8e38SSatish Balay   PetscCall(VecDestroy(&l));
106*a90d8e38SSatish Balay   PetscCall(VecDestroy(&g));
107*a90d8e38SSatish Balay   PetscCall(VecDestroy(&ll));
108*a90d8e38SSatish Balay   PetscCall(VecDestroy(&gg));
109*a90d8e38SSatish Balay 
110*a90d8e38SSatish Balay   /* =============================================================================
111*a90d8e38SSatish Balay     Show how to manage a multi-component DMDA using DMDAVecGetKokkosOffsetView and
112*a90d8e38SSatish Balay     a customized struct type
113*a90d8e38SSatish Balay    ==============================================================================*/
114*a90d8e38SSatish Balay   Node                             **garray2; /* Node arrays of g, l */
115*a90d8e38SSatish Balay   const Node                       **larray2;
116*a90d8e38SSatish Balay   PetscScalarKokkosOffsetView2D      gview2; /* PetscScalar views of gg, ll */
117*a90d8e38SSatish Balay   ConstPetscScalarKokkosOffsetView2D lview2;
118*a90d8e38SSatish Balay   NodeKokkosOffsetView2D             gnview; /* Node views of gg, ll */
119*a90d8e38SSatish Balay   ConstNodeKokkosOffsetView2D        lnview;
120*a90d8e38SSatish Balay 
121*a90d8e38SSatish Balay   dof = sizeof(Node) / sizeof(PetscScalar);
122*a90d8e38SSatish Balay   PetscCall(DMDACreate2d(PETSC_COMM_WORLD, bx, by, st, M, N, PETSC_DECIDE, PETSC_DECIDE, sizeof(Node) / sizeof(PetscScalar), sw, NULL, NULL, &da));
123*a90d8e38SSatish Balay   PetscCall(DMSetFromOptions(da));
124*a90d8e38SSatish Balay   PetscCall(DMSetUp(da));
125*a90d8e38SSatish Balay   PetscCall(DMDAGetCorners(da, &xs, &ys, 0, &xm, &ym, 0));
126*a90d8e38SSatish Balay   PetscCall(DMCreateGlobalVector(da, &g));
127*a90d8e38SSatish Balay   PetscCall(DMCreateLocalVector(da, &l));
128*a90d8e38SSatish Balay   PetscCall(DMCreateGlobalVector(da, &gg));
129*a90d8e38SSatish Balay   PetscCall(DMCreateLocalVector(da, &ll));
130*a90d8e38SSatish Balay 
131*a90d8e38SSatish Balay   /* Init g using array */
132*a90d8e38SSatish Balay   PetscCall(DMDAVecGetArrayWrite(da, g, &garray2));
133*a90d8e38SSatish Balay   for (PetscInt j = ys; j < ys + ym; j++) {
134*a90d8e38SSatish Balay     for (PetscInt i = xs; i < xs + xm; i++) {
135*a90d8e38SSatish Balay       garray2[j][i].u = 100 * j + 10 * (i + 1) + 111;
136*a90d8e38SSatish Balay       garray2[j][i].v = 100 * j + 10 * (i + 1) + 222;
137*a90d8e38SSatish Balay       garray2[j][i].w = 100 * j + 10 * (i + 1) + 333;
138*a90d8e38SSatish Balay     }
139*a90d8e38SSatish Balay   }
140*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreArrayWrite(da, g, &garray2));
141*a90d8e38SSatish Balay 
142*a90d8e38SSatish Balay   /* Init gg using view */
143*a90d8e38SSatish Balay   PetscCall(DMDAVecGetKokkosOffsetViewWrite(da, gg, &gview2));
144*a90d8e38SSatish Balay   gnview = NodeKokkosOffsetView2D(reinterpret_cast<Node *>(gview2.data()), {gview2.begin(0) / dof, gview2.begin(1) / dof}, {gview2.end(0) / dof, gview2.end(1) / dof});
145*a90d8e38SSatish Balay   Kokkos::parallel_for(
146*a90d8e38SSatish Balay     "init 2", MDRangePolicy<Rank<2, Iterate::Right, Iterate::Right>>({ys, xs}, {ys + ym, xs + xm}), KOKKOS_LAMBDA(PetscInt j, PetscInt i) {
147*a90d8e38SSatish Balay       gnview(j, i).u = 100 * j + 10 * (i + 1) + 111;
148*a90d8e38SSatish Balay       gnview(j, i).v = 100 * j + 10 * (i + 1) + 222;
149*a90d8e38SSatish Balay       gnview(j, i).w = 100 * j + 10 * (i + 1) + 333;
150*a90d8e38SSatish Balay     });
151*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreKokkosOffsetViewWrite(da, gg, &gview2));
152*a90d8e38SSatish Balay 
153*a90d8e38SSatish Balay   /* Scatter g, gg to l, ll */
154*a90d8e38SSatish Balay   PetscCall(DMGlobalToLocal(da, g, INSERT_VALUES, l));
155*a90d8e38SSatish Balay   PetscCall(DMGlobalToLocal(da, gg, INSERT_VALUES, ll));
156*a90d8e38SSatish Balay 
157*a90d8e38SSatish Balay   /* Do stencil on g with values from l that contains ghosts */
158*a90d8e38SSatish Balay   PetscCall(DMDAVecGetArrayWrite(da, g, &garray2));
159*a90d8e38SSatish Balay   PetscCall(DMDAVecGetArray(da, l, &larray2));
160*a90d8e38SSatish Balay   for (PetscInt j = ys; j < ys + ym; j++) {
161*a90d8e38SSatish Balay     for (PetscInt i = xs; i < xs + xm; i++) {
162*a90d8e38SSatish Balay       garray2[j][i].u = (larray2[j][i - 1].u + larray2[j][i + 1].u + larray2[j - 1][i].u + larray2[j + 1][i].u) / 4.0;
163*a90d8e38SSatish Balay       garray2[j][i].v = (larray2[j][i - 1].v + larray2[j][i + 1].v + larray2[j - 1][i].v + larray2[j + 1][i].v) / 4.0;
164*a90d8e38SSatish Balay       garray2[j][i].w = (larray2[j][i - 1].w + larray2[j][i + 1].w + larray2[j - 1][i].w + larray2[j + 1][i].w) / 4.0;
165*a90d8e38SSatish Balay     }
166*a90d8e38SSatish Balay   }
167*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreArrayWrite(da, g, &garray2));
168*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreArray(da, l, &larray2));
169*a90d8e38SSatish Balay 
170*a90d8e38SSatish Balay   /* Do stencil on gg with values from ll that contains ghosts */
171*a90d8e38SSatish Balay   PetscCall(DMDAVecGetKokkosOffsetViewWrite(da, gg, &gview2)); /* write-only */
172*a90d8e38SSatish Balay   PetscCall(DMDAVecGetKokkosOffsetView(da, ll, &lview2));      /* read-only */
173*a90d8e38SSatish Balay   gnview = NodeKokkosOffsetView2D(reinterpret_cast<Node *>(gview2.data()), {gview2.begin(0) / dof, gview2.begin(1) / dof}, {gview2.end(0) / dof, gview2.end(1) / dof});
174*a90d8e38SSatish Balay   lnview = ConstNodeKokkosOffsetView2D(reinterpret_cast<const Node *>(lview2.data()), {lview2.begin(0) / dof, lview2.begin(1) / dof}, {lview2.end(0) / dof, lview2.end(1) / dof});
175*a90d8e38SSatish Balay   Kokkos::parallel_for(
176*a90d8e38SSatish Balay     "stencil 2", MDRangePolicy<Rank<2, Iterate::Right, Iterate::Right>>({ys, xs}, {ys + ym, xs + xm}), KOKKOS_LAMBDA(PetscInt j, PetscInt i) {
177*a90d8e38SSatish Balay       gnview(j, i).u = (lnview(j, i - 1).u + lnview(j, i + 1).u + lnview(j - 1, i).u + lnview(j + 1, i).u) / 4.0;
178*a90d8e38SSatish Balay       gnview(j, i).v = (lnview(j, i - 1).v + lnview(j, i + 1).v + lnview(j - 1, i).v + lnview(j + 1, i).v) / 4.0;
179*a90d8e38SSatish Balay       gnview(j, i).w = (lnview(j, i - 1).w + lnview(j, i + 1).w + lnview(j - 1, i).w + lnview(j + 1, i).w) / 4.0;
180*a90d8e38SSatish Balay     });
181*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreKokkosOffsetViewWrite(da, gg, &gview2));
182*a90d8e38SSatish Balay   PetscCall(DMDAVecRestoreKokkosOffsetView(da, ll, &lview2));
183*a90d8e38SSatish Balay 
184*a90d8e38SSatish Balay   /* gg should be equal to g */
185*a90d8e38SSatish Balay   PetscCall(VecAXPY(g, -1.0, gg));
186*a90d8e38SSatish Balay   PetscCall(VecNorm(g, NORM_2, &nrm));
187*a90d8e38SSatish Balay   PetscCheck(nrm < PETSC_SMALL, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "gg is not equal to g");
188*a90d8e38SSatish Balay 
189*a90d8e38SSatish Balay   PetscCall(DMDestroy(&da));
190*a90d8e38SSatish Balay   PetscCall(VecDestroy(&l));
191*a90d8e38SSatish Balay   PetscCall(VecDestroy(&g));
192*a90d8e38SSatish Balay   PetscCall(VecDestroy(&ll));
193*a90d8e38SSatish Balay   PetscCall(VecDestroy(&gg));
194*a90d8e38SSatish Balay   PetscCall(PetscFinalize());
195*a90d8e38SSatish Balay   return 0;
196*a90d8e38SSatish Balay }
197*a90d8e38SSatish Balay 
198*a90d8e38SSatish Balay /*TEST
199*a90d8e38SSatish Balay   build:
200*a90d8e38SSatish Balay     requires: kokkos_kernels
201*a90d8e38SSatish Balay 
202*a90d8e38SSatish Balay   test:
203*a90d8e38SSatish Balay     suffix: 1
204*a90d8e38SSatish Balay     nsize: 4
205*a90d8e38SSatish Balay     requires: kokkos_kernels
206*a90d8e38SSatish Balay     args: -dm_vec_type kokkos
207*a90d8e38SSatish Balay     output_file: output/empty.out
208*a90d8e38SSatish Balay 
209*a90d8e38SSatish Balay TEST*/
210