xref: /petsc/src/dm/impls/plex/tests/ex47.c (revision f0af967ec07b491a4e17a7fbc1f9d6a783342afb)
1 static char help[] = "The main goal of this code is to retrieve the original element numbers as found in the "
2                      "initial partitions (sInitialPartition)... but after the call to DMPlexDistribute";
3 
4 #include <petsc.h>
5 
6 PetscReal sCoords2x5Mesh[18][2] = {
7   {0.00000000000000000e+00, 0.00000000000000000e+00},
8   {2.00000000000000000e+00, 0.00000000000000000e+00},
9   {0.00000000000000000e+00, 1.00000000000000000e+00},
10   {2.00000000000000000e+00, 1.00000000000000000e+00},
11   {9.99999999997387978e-01, 0.00000000000000000e+00},
12   {9.99999999997387978e-01, 1.00000000000000000e+00},
13   {0.00000000000000000e+00, 2.00000000000000011e-01},
14   {0.00000000000000000e+00, 4.00000000000000022e-01},
15   {0.00000000000000000e+00, 5.99999999999999978e-01},
16   {0.00000000000000000e+00, 8.00000000000000044e-01},
17   {2.00000000000000000e+00, 2.00000000000000011e-01},
18   {2.00000000000000000e+00, 4.00000000000000022e-01},
19   {2.00000000000000000e+00, 5.99999999999999978e-01},
20   {2.00000000000000000e+00, 8.00000000000000044e-01},
21   {9.99999999997387756e-01, 2.00000000000000011e-01},
22   {9.99999999997387978e-01, 4.00000000000000022e-01},
23   {9.99999999997387978e-01, 6.00000000000000089e-01},
24   {9.99999999997388089e-01, 8.00000000000000044e-01}
25 };
26 
27 //Connectivity of a 2x5 rectangular mesh of quads :
28 const PetscInt sConnectivity2x5Mesh[10][4] = {
29   {0,  4,  14, 6 },
30   {6,  14, 15, 7 },
31   {7,  15, 16, 8 },
32   {8,  16, 17, 9 },
33   {9,  17, 5,  2 },
34   {4,  1,  10, 14},
35   {14, 10, 11, 15},
36   {15, 11, 12, 16},
37   {16, 12, 13, 17},
38   {17, 13, 3,  5 }
39 };
40 
41 const PetscInt sInitialPartition2x5Mesh[2][5] = {
42   {0, 2, 4, 6, 8},
43   {1, 3, 5, 7, 9}
44 };
45 
46 const PetscInt sNLoclCells2x5Mesh = 5;
47 const PetscInt sNGlobVerts2x5Mesh = 18;
48 
49 int main(int argc, char **argv) {
50   const PetscInt  Nc                 = sNLoclCells2x5Mesh; //Same on each rank for this example...
51   const PetscInt  Nv                 = sNGlobVerts2x5Mesh;
52   const PetscInt *InitPartForRank[2] = {&sInitialPartition2x5Mesh[0][0], &sInitialPartition2x5Mesh[1][0]};
53   const PetscInt(*Conn)[4]           = sConnectivity2x5Mesh;
54 
55   const PetscInt   Ncor = 4;
56   const PetscInt   dim  = 2;
57   DM               dm, idm, ddm;
58   PetscSF          sfVert, sfMig, sfPart;
59   PetscPartitioner part;
60   PetscSection     s;
61   PetscInt        *cells, c;
62   PetscMPIInt      size, rank;
63   PetscBool        box = PETSC_FALSE, field = PETSC_FALSE;
64 
65   PetscFunctionBeginUser;
66   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
67   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
68   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
69   PetscCheck(size == 2, PETSC_COMM_WORLD, PETSC_ERR_SUP, "This is a 2 processors example only");
70   PetscCall(PetscOptionsGetBool(NULL, NULL, "-box", &box, NULL));
71   PetscCall(PetscOptionsGetBool(NULL, NULL, "-field", &field, NULL));
72 
73   PetscCall(DMPlexCreate(PETSC_COMM_WORLD, &dm));
74   if (box) {
75     PetscCall(DMSetType(dm, DMPLEX));
76     PetscCall(DMSetFromOptions(dm));
77   } else {
78     PetscCall(PetscMalloc1(Nc * Ncor, &cells));
79     for (c = 0; c < Nc; ++c) {
80       PetscInt cell = (InitPartForRank[rank])[c], cor;
81 
82       for (cor = 0; cor < Ncor; ++cor) cells[c * Ncor + cor] = Conn[cell][cor];
83     }
84     PetscCall(DMSetDimension(dm, dim));
85     PetscCall(DMPlexBuildFromCellListParallel(dm, Nc, PETSC_DECIDE, Nv, Ncor, cells, &sfVert, NULL));
86     PetscCall(PetscSFDestroy(&sfVert));
87     PetscCall(PetscFree(cells));
88     PetscCall(DMPlexInterpolate(dm, &idm));
89     PetscCall(DMDestroy(&dm));
90     dm = idm;
91   }
92   PetscCall(DMSetUseNatural(dm, PETSC_TRUE));
93   PetscCall(DMViewFromOptions(dm, NULL, "-dm_view"));
94 
95   if (field) {
96     const PetscInt Nf         = 1;
97     const PetscInt numComp[1] = {1};
98     const PetscInt numDof[3]  = {0, 0, 1};
99     const PetscInt numBC      = 0;
100 
101     PetscCall(DMSetNumFields(dm, Nf));
102     PetscCall(DMPlexCreateSection(dm, NULL, numComp, numDof, numBC, NULL, NULL, NULL, NULL, &s));
103     PetscCall(DMSetLocalSection(dm, s));
104     PetscCall(PetscSectionView(s, PETSC_VIEWER_STDOUT_WORLD));
105     PetscCall(PetscSectionDestroy(&s));
106   }
107 
108   PetscCall(DMPlexGetPartitioner(dm, &part));
109   PetscCall(PetscPartitionerSetFromOptions(part));
110 
111   PetscCall(DMPlexDistribute(dm, 0, &sfMig, &ddm));
112   PetscCall(PetscSFView(sfMig, PETSC_VIEWER_STDOUT_WORLD));
113   PetscCall(PetscSFCreateInverseSF(sfMig, &sfPart));
114   PetscCall(PetscObjectSetName((PetscObject)sfPart, "Inverse Migration SF"));
115   PetscCall(PetscSFView(sfPart, PETSC_VIEWER_STDOUT_WORLD));
116 
117   Vec          lGlobalVec, lNatVec;
118   PetscScalar *lNatVecArray;
119 
120   {
121     PetscSection s;
122 
123     PetscCall(DMGetGlobalSection(dm, &s));
124     PetscCall(PetscSectionView(s, PETSC_VIEWER_STDOUT_WORLD));
125   }
126   PetscCall(DMGetGlobalVector(dm, &lNatVec));
127   PetscCall(PetscObjectSetName((PetscObject)lNatVec, "Natural Vector (initial partition)"));
128 
129   //Copying the initial partition into the "natural" vector:
130   PetscCall(VecGetArray(lNatVec, &lNatVecArray));
131   for (c = 0; c < Nc; ++c) lNatVecArray[c] = (InitPartForRank[rank])[c];
132   PetscCall(VecRestoreArray(lNatVec, &lNatVecArray));
133 
134   PetscCall(DMGetGlobalVector(ddm, &lGlobalVec));
135   PetscCall(PetscObjectSetName((PetscObject)lGlobalVec, "Global Vector (reordered element numbers in the petsc distributed order)"));
136   PetscCall(VecZeroEntries(lGlobalVec));
137 
138   // The call to DMPlexNaturalToGlobalBegin/End does not produce our expected result...
139   // In lGlobalVec, we expect to have:
140   /*
141    * Process [0]
142    * 2.
143    * 4.
144    * 8.
145    * 3.
146    * 9.
147    * Process [1]
148    * 1.
149    * 5.
150    * 7.
151    * 0.
152    * 6.
153    *
154    * but we obtained:
155    *
156    * Process [0]
157    * 2.
158    * 4.
159    * 8.
160    * 0.
161    * 0.
162    * Process [1]
163    * 0.
164    * 0.
165    * 0.
166    * 0.
167    * 0.
168    */
169 
170   {
171     PetscSF nsf;
172 
173     PetscCall(DMPlexGetGlobalToNaturalSF(ddm, &nsf));
174     PetscCall(PetscSFView(nsf, NULL));
175   }
176   PetscCall(DMPlexNaturalToGlobalBegin(ddm, lNatVec, lGlobalVec));
177   PetscCall(DMPlexNaturalToGlobalEnd(ddm, lNatVec, lGlobalVec));
178 
179   PetscCall(VecView(lNatVec, PETSC_VIEWER_STDOUT_WORLD));
180   PetscCall(VecView(lGlobalVec, PETSC_VIEWER_STDOUT_WORLD));
181 
182   PetscCall(DMRestoreGlobalVector(dm, &lNatVec));
183   PetscCall(DMRestoreGlobalVector(ddm, &lGlobalVec));
184 
185   PetscCall(PetscSFDestroy(&sfMig));
186   PetscCall(PetscSFDestroy(&sfPart));
187   PetscCall(DMDestroy(&dm));
188   PetscCall(DMDestroy(&ddm));
189   PetscCall(PetscFinalize());
190   return 0;
191 }
192 
193 /*TEST
194 
195   testset:
196     args: -field -petscpartitioner_type simple
197     nsize: 2
198 
199     test:
200       suffix: 0
201       args:
202 
203     test:
204       suffix: 1
205       args: -box -dm_plex_simplex 0 -dm_plex_box_faces 2,5 -dm_distribute
206 
207 TEST*/
208