xref: /petsc/src/dm/tutorials/ex6.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
1c4762a1bSJed Brown 
2c4762a1bSJed Brown static char help[] = "\n\n";
3c4762a1bSJed Brown 
4c4762a1bSJed Brown /*
5c4762a1bSJed Brown      Demonstrates using DM_BOUNDARY_GHOSTED how to handle a rotated boundary conditions where one edge
6c4762a1bSJed Brown     is connected to its immediate neighbor
7c4762a1bSJed Brown 
8c4762a1bSJed Brown     Consider the domain (with natural numbering)
9c4762a1bSJed Brown 
10c4762a1bSJed Brown      6   7   8
11c4762a1bSJed Brown      3   4   5
12c4762a1bSJed Brown      0   1   2
13c4762a1bSJed Brown 
14c4762a1bSJed Brown     The ghost points along the bottom (directly below the three columns above) should be 0 3 and 6
15c4762a1bSJed Brown     while the ghost points along the left side should be 0 1 2
16c4762a1bSJed Brown 
17c4762a1bSJed Brown     Note that the ghosted local vectors extend in both the x and y directions so, for example if we have a
18c4762a1bSJed Brown     single MPI process the ghosted vector has (in the original natural numbering)
19c4762a1bSJed Brown 
20c4762a1bSJed Brown      x  x  x  x  x
21c4762a1bSJed Brown      2  6  7  8  x
22c4762a1bSJed Brown      1  3  4  5  x
23c4762a1bSJed Brown      0  0  1  2  x
24c4762a1bSJed Brown      x  0  3  6  x
25c4762a1bSJed Brown 
26c4762a1bSJed Brown     where x indicates a location that is not updated by the communication and should be used.
27c4762a1bSJed Brown 
28c4762a1bSJed Brown     For this to make sense the number of grid points in the x and y directions must be the same
29c4762a1bSJed Brown 
30c4762a1bSJed Brown     This ghost point mapping was suggested by: Wenbo Zhao <zhaowenbo.npic@gmail.com>
31c4762a1bSJed Brown */
32c4762a1bSJed Brown 
33c4762a1bSJed Brown #include <petscdm.h>
34c4762a1bSJed Brown #include <petscdmda.h>
35c4762a1bSJed Brown 
36*d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
37*d71ae5a4SJacob Faibussowitsch {
38c4762a1bSJed Brown   PetscInt     M = 6;
39c4762a1bSJed Brown   DM           da;
40c4762a1bSJed Brown   Vec          local, global, natural;
41c4762a1bSJed Brown   PetscInt     i, start, end, *ifrom, x, y, xm, ym;
42c4762a1bSJed Brown   PetscScalar *xnatural;
43c4762a1bSJed Brown   IS           from, to;
44c4762a1bSJed Brown   AO           ao;
45c4762a1bSJed Brown   VecScatter   scatter1, scatter2;
46c4762a1bSJed Brown   PetscViewer  subviewer;
47c4762a1bSJed Brown 
48327415f7SBarry Smith   PetscFunctionBeginUser;
499566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, (char *)0, help));
50c4762a1bSJed Brown 
51c4762a1bSJed Brown   /* Create distributed array and get vectors */
529566063dSJacob Faibussowitsch   PetscCall(DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_GHOSTED, DM_BOUNDARY_GHOSTED, DMDA_STENCIL_STAR, M, M, PETSC_DECIDE, PETSC_DECIDE, 1, 1, NULL, NULL, &da));
539566063dSJacob Faibussowitsch   PetscCall(DMSetUp(da));
549566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(da, &global));
559566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(da, &local));
56c4762a1bSJed Brown 
57c4762a1bSJed Brown   /* construct global to local scatter for the left side of the domain to the ghost on the bottom */
589566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &x, &y, NULL, &xm, &ym, NULL));
59c4762a1bSJed Brown   if (!y) { /* only processes on the bottom of the domain fill up the ghost locations */
609566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, xm, 1, 1, &to));
61c4762a1bSJed Brown   } else {
629566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 0, &to));
63c4762a1bSJed Brown   }
649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(xm, &ifrom));
65ad540459SPierre Jolivet   for (i = x; i < x + xm; i++) ifrom[i - x] = M * i;
669566063dSJacob Faibussowitsch   PetscCall(DMDAGetAO(da, &ao));
679566063dSJacob Faibussowitsch   PetscCall(AOApplicationToPetsc(ao, xm, ifrom));
68c4762a1bSJed Brown   if (!y) {
699566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, xm, ifrom, PETSC_OWN_POINTER, &from));
70c4762a1bSJed Brown   } else {
719566063dSJacob Faibussowitsch     PetscCall(PetscFree(ifrom));
729566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, 0, NULL, PETSC_COPY_VALUES, &from));
73c4762a1bSJed Brown   }
749566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(global, from, local, to, &scatter1));
759566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&to));
769566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
77c4762a1bSJed Brown 
78c4762a1bSJed Brown   /* construct global to local scatter for the bottom side of the domain to the ghost on the right */
79c4762a1bSJed Brown   if (!x) { /* only processes on the left side of the domain fill up the ghost locations */
809566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, ym, xm + 2, xm + 2, &to));
81c4762a1bSJed Brown   } else {
829566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 0, &to));
83c4762a1bSJed Brown   }
849566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ym, &ifrom));
85ad540459SPierre Jolivet   for (i = y; i < y + ym; i++) ifrom[i - y] = i;
869566063dSJacob Faibussowitsch   PetscCall(DMDAGetAO(da, &ao));
879566063dSJacob Faibussowitsch   PetscCall(AOApplicationToPetsc(ao, ym, ifrom));
88c4762a1bSJed Brown   if (!x) {
899566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, ym, ifrom, PETSC_OWN_POINTER, &from));
90c4762a1bSJed Brown   } else {
919566063dSJacob Faibussowitsch     PetscCall(PetscFree(ifrom));
929566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, 0, NULL, PETSC_COPY_VALUES, &from));
93c4762a1bSJed Brown   }
949566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(global, from, local, to, &scatter2));
959566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&to));
969566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
97c4762a1bSJed Brown 
98c4762a1bSJed Brown   /*
99c4762a1bSJed Brown      fill the global vector with the natural global numbering for each local entry
100c4762a1bSJed Brown      this is only done for testing purposes since it is easy to see if the scatter worked correctly
101c4762a1bSJed Brown   */
1029566063dSJacob Faibussowitsch   PetscCall(DMDACreateNaturalVector(da, &natural));
1039566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(natural, &start, &end));
1049566063dSJacob Faibussowitsch   PetscCall(VecGetArray(natural, &xnatural));
105ad540459SPierre Jolivet   for (i = start; i < end; i++) xnatural[i - start] = i;
1069566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(natural, &xnatural));
1079566063dSJacob Faibussowitsch   PetscCall(DMDANaturalToGlobalBegin(da, natural, INSERT_VALUES, global));
1089566063dSJacob Faibussowitsch   PetscCall(DMDANaturalToGlobalEnd(da, natural, INSERT_VALUES, global));
1099566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&natural));
110c4762a1bSJed Brown 
111c4762a1bSJed Brown   /* scatter from global to local */
1129566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(scatter1, global, local, INSERT_VALUES, SCATTER_FORWARD));
1139566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(scatter1, global, local, INSERT_VALUES, SCATTER_FORWARD));
1149566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(scatter2, global, local, INSERT_VALUES, SCATTER_FORWARD));
1159566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(scatter2, global, local, INSERT_VALUES, SCATTER_FORWARD));
116c4762a1bSJed Brown   /*
117c4762a1bSJed Brown      normally here you would also call
1189566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(da,global,INSERT_VALUES,local));
1199566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(da,global,INSERT_VALUES,local));
120c4762a1bSJed Brown     to update all the interior ghost cells between neighboring processes.
121c4762a1bSJed Brown     We don't do it here since this is only a test of "special" ghost points.
122c4762a1bSJed Brown   */
123c4762a1bSJed Brown 
124c4762a1bSJed Brown   /* view each local ghosted vector */
1259566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetSubViewer(PETSC_VIEWER_STDOUT_WORLD, PETSC_COMM_SELF, &subviewer));
1269566063dSJacob Faibussowitsch   PetscCall(VecView(local, subviewer));
1279566063dSJacob Faibussowitsch   PetscCall(PetscViewerRestoreSubViewer(PETSC_VIEWER_STDOUT_WORLD, PETSC_COMM_SELF, &subviewer));
128c4762a1bSJed Brown 
1299566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&scatter1));
1309566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&scatter2));
1319566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&local));
1329566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&global));
1339566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&da));
1349566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
135b122ec5aSJacob Faibussowitsch   return 0;
136c4762a1bSJed Brown }
137c4762a1bSJed Brown 
138c4762a1bSJed Brown /*TEST
139c4762a1bSJed Brown 
140c4762a1bSJed Brown    test:
141c4762a1bSJed Brown 
142c4762a1bSJed Brown    test:
143c4762a1bSJed Brown       suffix: 2
144c4762a1bSJed Brown       nsize: 2
145c4762a1bSJed Brown 
146c4762a1bSJed Brown    test:
147c4762a1bSJed Brown       suffix: 4
148c4762a1bSJed Brown       nsize: 4
149c4762a1bSJed Brown 
150c4762a1bSJed Brown    test:
151c4762a1bSJed Brown       suffix: 9
152c4762a1bSJed Brown       nsize: 9
153c4762a1bSJed Brown 
154c4762a1bSJed Brown TEST*/
155