xref: /petsc/src/dm/tutorials/ex6.c (revision 732aec7a18f2199fb53bb9a2f3aef439a834ce31)
1c4762a1bSJed Brown static char help[] = "\n\n";
2c4762a1bSJed Brown 
3c4762a1bSJed Brown /*
4c4762a1bSJed Brown      Demonstrates using DM_BOUNDARY_GHOSTED how to handle a rotated boundary conditions where one edge
5c4762a1bSJed Brown     is connected to its immediate neighbor
6c4762a1bSJed Brown 
7c4762a1bSJed Brown     Consider the domain (with natural numbering)
8c4762a1bSJed Brown 
9c4762a1bSJed Brown      6   7   8
10c4762a1bSJed Brown      3   4   5
11c4762a1bSJed Brown      0   1   2
12c4762a1bSJed Brown 
13c4762a1bSJed Brown     The ghost points along the bottom (directly below the three columns above) should be 0 3 and 6
14c4762a1bSJed Brown     while the ghost points along the left side should be 0 1 2
15c4762a1bSJed Brown 
16c4762a1bSJed Brown     Note that the ghosted local vectors extend in both the x and y directions so, for example if we have a
17c4762a1bSJed Brown     single MPI process the ghosted vector has (in the original natural numbering)
18c4762a1bSJed Brown 
19c4762a1bSJed Brown      x  x  x  x  x
20c4762a1bSJed Brown      2  6  7  8  x
21c4762a1bSJed Brown      1  3  4  5  x
22c4762a1bSJed Brown      0  0  1  2  x
23c4762a1bSJed Brown      x  0  3  6  x
24c4762a1bSJed Brown 
25c4762a1bSJed Brown     where x indicates a location that is not updated by the communication and should be used.
26c4762a1bSJed Brown 
27c4762a1bSJed Brown     For this to make sense the number of grid points in the x and y directions must be the same
28c4762a1bSJed Brown 
29c4762a1bSJed Brown     This ghost point mapping was suggested by: Wenbo Zhao <zhaowenbo.npic@gmail.com>
30c4762a1bSJed Brown */
31c4762a1bSJed Brown 
32c4762a1bSJed Brown #include <petscdm.h>
33c4762a1bSJed Brown #include <petscdmda.h>
34c4762a1bSJed Brown 
main(int argc,char ** argv)35d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
36d71ae5a4SJacob Faibussowitsch {
37c4762a1bSJed Brown   PetscInt     M = 6;
38c4762a1bSJed Brown   DM           da;
39c4762a1bSJed Brown   Vec          local, global, natural;
40c4762a1bSJed Brown   PetscInt     i, start, end, *ifrom, x, y, xm, ym;
41c4762a1bSJed Brown   PetscScalar *xnatural;
42c4762a1bSJed Brown   IS           from, to;
43c4762a1bSJed Brown   AO           ao;
44c4762a1bSJed Brown   VecScatter   scatter1, scatter2;
45c4762a1bSJed Brown   PetscViewer  subviewer;
46c4762a1bSJed Brown 
47327415f7SBarry Smith   PetscFunctionBeginUser;
48*c8025a54SPierre Jolivet   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
49c4762a1bSJed Brown 
50c4762a1bSJed Brown   /* Create distributed array and get vectors */
519566063dSJacob 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));
529566063dSJacob Faibussowitsch   PetscCall(DMSetUp(da));
539566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(da, &global));
549566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(da, &local));
55c4762a1bSJed Brown 
56c4762a1bSJed Brown   /* construct global to local scatter for the left side of the domain to the ghost on the bottom */
579566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &x, &y, NULL, &xm, &ym, NULL));
58c4762a1bSJed Brown   if (!y) { /* only processes on the bottom of the domain fill up the ghost locations */
599566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, xm, 1, 1, &to));
60c4762a1bSJed Brown   } else {
619566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 0, &to));
62c4762a1bSJed Brown   }
639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(xm, &ifrom));
64ad540459SPierre Jolivet   for (i = x; i < x + xm; i++) ifrom[i - x] = M * i;
659566063dSJacob Faibussowitsch   PetscCall(DMDAGetAO(da, &ao));
669566063dSJacob Faibussowitsch   PetscCall(AOApplicationToPetsc(ao, xm, ifrom));
67c4762a1bSJed Brown   if (!y) {
689566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, xm, ifrom, PETSC_OWN_POINTER, &from));
69c4762a1bSJed Brown   } else {
709566063dSJacob Faibussowitsch     PetscCall(PetscFree(ifrom));
719566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, 0, NULL, PETSC_COPY_VALUES, &from));
72c4762a1bSJed Brown   }
739566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(global, from, local, to, &scatter1));
749566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&to));
759566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
76c4762a1bSJed Brown 
77c4762a1bSJed Brown   /* construct global to local scatter for the bottom side of the domain to the ghost on the right */
78c4762a1bSJed Brown   if (!x) { /* only processes on the left side of the domain fill up the ghost locations */
799566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, ym, xm + 2, xm + 2, &to));
80c4762a1bSJed Brown   } else {
819566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PETSC_COMM_SELF, 0, 0, 0, &to));
82c4762a1bSJed Brown   }
839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ym, &ifrom));
84ad540459SPierre Jolivet   for (i = y; i < y + ym; i++) ifrom[i - y] = i;
859566063dSJacob Faibussowitsch   PetscCall(DMDAGetAO(da, &ao));
869566063dSJacob Faibussowitsch   PetscCall(AOApplicationToPetsc(ao, ym, ifrom));
87c4762a1bSJed Brown   if (!x) {
889566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, ym, ifrom, PETSC_OWN_POINTER, &from));
89c4762a1bSJed Brown   } else {
909566063dSJacob Faibussowitsch     PetscCall(PetscFree(ifrom));
919566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, 0, NULL, PETSC_COPY_VALUES, &from));
92c4762a1bSJed Brown   }
939566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(global, from, local, to, &scatter2));
949566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&to));
959566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
96c4762a1bSJed Brown 
97c4762a1bSJed Brown   /*
98c4762a1bSJed Brown      fill the global vector with the natural global numbering for each local entry
99c4762a1bSJed Brown      this is only done for testing purposes since it is easy to see if the scatter worked correctly
100c4762a1bSJed Brown   */
1019566063dSJacob Faibussowitsch   PetscCall(DMDACreateNaturalVector(da, &natural));
1029566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(natural, &start, &end));
1039566063dSJacob Faibussowitsch   PetscCall(VecGetArray(natural, &xnatural));
104ad540459SPierre Jolivet   for (i = start; i < end; i++) xnatural[i - start] = i;
1059566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(natural, &xnatural));
1069566063dSJacob Faibussowitsch   PetscCall(DMDANaturalToGlobalBegin(da, natural, INSERT_VALUES, global));
1079566063dSJacob Faibussowitsch   PetscCall(DMDANaturalToGlobalEnd(da, natural, INSERT_VALUES, global));
1089566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&natural));
109c4762a1bSJed Brown 
110c4762a1bSJed Brown   /* scatter from global to local */
1119566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(scatter1, global, local, INSERT_VALUES, SCATTER_FORWARD));
1129566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(scatter1, global, local, INSERT_VALUES, SCATTER_FORWARD));
1139566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(scatter2, global, local, INSERT_VALUES, SCATTER_FORWARD));
1149566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(scatter2, global, local, INSERT_VALUES, SCATTER_FORWARD));
115c4762a1bSJed Brown   /*
116c4762a1bSJed Brown      normally here you would also call
1179566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(da,global,INSERT_VALUES,local));
1189566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(da,global,INSERT_VALUES,local));
119c4762a1bSJed Brown     to update all the interior ghost cells between neighboring processes.
120c4762a1bSJed Brown     We don't do it here since this is only a test of "special" ghost points.
121c4762a1bSJed Brown   */
122c4762a1bSJed Brown 
123c4762a1bSJed Brown   /* view each local ghosted vector */
1249566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetSubViewer(PETSC_VIEWER_STDOUT_WORLD, PETSC_COMM_SELF, &subviewer));
1259566063dSJacob Faibussowitsch   PetscCall(VecView(local, subviewer));
1269566063dSJacob Faibussowitsch   PetscCall(PetscViewerRestoreSubViewer(PETSC_VIEWER_STDOUT_WORLD, PETSC_COMM_SELF, &subviewer));
127c4762a1bSJed Brown 
1289566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&scatter1));
1299566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&scatter2));
1309566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&local));
1319566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&global));
1329566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&da));
1339566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
134b122ec5aSJacob Faibussowitsch   return 0;
135c4762a1bSJed Brown }
136c4762a1bSJed Brown 
137c4762a1bSJed Brown /*TEST
138c4762a1bSJed Brown 
139c4762a1bSJed Brown    test:
140c4762a1bSJed Brown 
141c4762a1bSJed Brown    test:
142c4762a1bSJed Brown       suffix: 2
143c4762a1bSJed Brown       nsize: 2
144c4762a1bSJed Brown 
145c4762a1bSJed Brown    test:
146c4762a1bSJed Brown       suffix: 4
147c4762a1bSJed Brown       nsize: 4
148c4762a1bSJed Brown 
149c4762a1bSJed Brown    test:
150c4762a1bSJed Brown       suffix: 9
151c4762a1bSJed Brown       nsize: 9
152c4762a1bSJed Brown 
153c4762a1bSJed Brown TEST*/
154