1 /* Routines to convert between a (subset of) DMStag and DMDA */
2
3 #include <petscdmda.h> /*I "petscdmda.h" I*/
4 #include <petsc/private/dmstagimpl.h> /*I "petscdmstag.h" I*/
5 #include <petscdmdatypes.h>
6
DMStagCreateCompatibleDMDA(DM dm,DMStagStencilLocation loc,PetscInt c,DM * dmda)7 static PetscErrorCode DMStagCreateCompatibleDMDA(DM dm, DMStagStencilLocation loc, PetscInt c, DM *dmda)
8 {
9 DM_Stag *const stag = (DM_Stag *)dm->data;
10 PetscInt dim, i, j, stencilWidth, dof, N[DMSTAG_MAX_DIM];
11 DMDAStencilType stencilType;
12 PetscInt *l[DMSTAG_MAX_DIM];
13
14 PetscFunctionBegin;
15 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSTAG);
16 PetscCall(DMGetDimension(dm, &dim));
17
18 /* Create grid decomposition (to be adjusted later) */
19 for (i = 0; i < dim; ++i) {
20 PetscCall(PetscMalloc1(stag->nRanks[i], &l[i]));
21 for (j = 0; j < stag->nRanks[i]; ++j) l[i][j] = stag->l[i][j];
22 N[i] = stag->N[i];
23 }
24
25 /* dof */
26 dof = c < 0 ? -c : 1;
27
28 /* Determine/adjust sizes */
29 switch (loc) {
30 case DMSTAG_ELEMENT:
31 break;
32 case DMSTAG_LEFT:
33 case DMSTAG_RIGHT:
34 PetscCheck(dim >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Incompatible dim (%" PetscInt_FMT ") and loc(%s) combination", dim, DMStagStencilLocations[loc]);
35 l[0][stag->nRanks[0] - 1] += 1; /* extra vertex in direction 0 on last rank in dimension 0 */
36 N[0] += 1;
37 break;
38 case DMSTAG_UP:
39 case DMSTAG_DOWN:
40 PetscCheck(dim >= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Incompatible dim (%" PetscInt_FMT ") and loc(%s) combination", dim, DMStagStencilLocations[loc]);
41 l[1][stag->nRanks[1] - 1] += 1; /* extra vertex in direction 1 on last rank in dimension 1 */
42 N[1] += 1;
43 break;
44 case DMSTAG_BACK:
45 case DMSTAG_FRONT:
46 PetscCheck(dim >= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Incompatible dim (%" PetscInt_FMT ") and loc(%s) combination", dim, DMStagStencilLocations[loc]);
47 l[2][stag->nRanks[2] - 1] += 1; /* extra vertex in direction 2 on last rank in dimension 2 */
48 N[2] += 1;
49 break;
50 case DMSTAG_DOWN_LEFT:
51 case DMSTAG_DOWN_RIGHT:
52 case DMSTAG_UP_LEFT:
53 case DMSTAG_UP_RIGHT:
54 PetscCheck(dim >= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Incompatible dim (%" PetscInt_FMT ") and loc(%s) combination", dim, DMStagStencilLocations[loc]);
55 for (i = 0; i < 2; ++i) { /* extra vertex in direction i on last rank in dimension i = 0,1 */
56 l[i][stag->nRanks[i] - 1] += 1;
57 N[i] += 1;
58 }
59 break;
60 case DMSTAG_BACK_LEFT:
61 case DMSTAG_BACK_RIGHT:
62 case DMSTAG_FRONT_LEFT:
63 case DMSTAG_FRONT_RIGHT:
64 PetscCheck(dim >= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Incompatible dim (%" PetscInt_FMT ") and loc(%s) combination", dim, DMStagStencilLocations[loc]);
65 for (i = 0; i < 3; i += 2) { /* extra vertex in direction i on last rank in dimension i = 0,2 */
66 l[i][stag->nRanks[i] - 1] += 1;
67 N[i] += 1;
68 }
69 break;
70 case DMSTAG_BACK_DOWN:
71 case DMSTAG_BACK_UP:
72 case DMSTAG_FRONT_DOWN:
73 case DMSTAG_FRONT_UP:
74 PetscCheck(dim >= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Incompatible dim (%" PetscInt_FMT ") and loc(%s) combination", dim, DMStagStencilLocations[loc]);
75 for (i = 1; i < 3; ++i) { /* extra vertex in direction i on last rank in dimension i = 1,2 */
76 l[i][stag->nRanks[i] - 1] += 1;
77 N[i] += 1;
78 }
79 break;
80 case DMSTAG_BACK_DOWN_LEFT:
81 case DMSTAG_BACK_DOWN_RIGHT:
82 case DMSTAG_BACK_UP_LEFT:
83 case DMSTAG_BACK_UP_RIGHT:
84 case DMSTAG_FRONT_DOWN_LEFT:
85 case DMSTAG_FRONT_DOWN_RIGHT:
86 case DMSTAG_FRONT_UP_LEFT:
87 case DMSTAG_FRONT_UP_RIGHT:
88 PetscCheck(dim >= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Incompatible dim (%" PetscInt_FMT ") and loc(%s) combination", dim, DMStagStencilLocations[loc]);
89 for (i = 0; i < 3; ++i) { /* extra vertex in direction i on last rank in dimension i = 0,1,2 */
90 l[i][stag->nRanks[i] - 1] += 1;
91 N[i] += 1;
92 }
93 break;
94 default:
95 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for location %s", DMStagStencilLocations[loc]);
96 }
97
98 /* Use the same stencil type */
99 switch (stag->stencilType) {
100 case DMSTAG_STENCIL_STAR:
101 stencilType = DMDA_STENCIL_STAR;
102 stencilWidth = stag->stencilWidth;
103 break;
104 case DMSTAG_STENCIL_BOX:
105 stencilType = DMDA_STENCIL_BOX;
106 stencilWidth = stag->stencilWidth;
107 break;
108 default:
109 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported Stencil Type %d", stag->stencilType);
110 }
111
112 /* Create DMDA, using same boundary type */
113 switch (dim) {
114 case 1:
115 PetscCall(DMDACreate1d(PetscObjectComm((PetscObject)dm), stag->boundaryType[0], N[0], dof, stencilWidth, l[0], dmda));
116 break;
117 case 2:
118 PetscCall(DMDACreate2d(PetscObjectComm((PetscObject)dm), stag->boundaryType[0], stag->boundaryType[1], stencilType, N[0], N[1], stag->nRanks[0], stag->nRanks[1], dof, stencilWidth, l[0], l[1], dmda));
119 break;
120 case 3:
121 PetscCall(DMDACreate3d(PetscObjectComm((PetscObject)dm), stag->boundaryType[0], stag->boundaryType[1], stag->boundaryType[2], stencilType, N[0], N[1], N[2], stag->nRanks[0], stag->nRanks[1], stag->nRanks[2], dof, stencilWidth, l[0], l[1], l[2], dmda));
122 break;
123 default:
124 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "not implemented for dim %" PetscInt_FMT, dim);
125 }
126 for (i = 0; i < dim; ++i) PetscCall(PetscFree(l[i]));
127 PetscFunctionReturn(PETSC_SUCCESS);
128 }
129
130 /*
131 Helper function to get the number of extra points in a DMDA representation for a given canonical location.
132 */
DMStagDMDAGetExtraPoints(DM dm,DMStagStencilLocation locCanonical,PetscInt * extraPoint)133 static PetscErrorCode DMStagDMDAGetExtraPoints(DM dm, DMStagStencilLocation locCanonical, PetscInt *extraPoint)
134 {
135 PetscInt dim, d, nExtra[DMSTAG_MAX_DIM];
136
137 PetscFunctionBegin;
138 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSTAG);
139 PetscCall(DMGetDimension(dm, &dim));
140 PetscCheck(dim <= DMSTAG_MAX_DIM, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for %" PetscInt_FMT " dimensions", dim);
141 PetscCall(DMStagGetCorners(dm, NULL, NULL, NULL, NULL, NULL, NULL, &nExtra[0], &nExtra[1], &nExtra[2]));
142 for (d = 0; d < dim; ++d) extraPoint[d] = 0;
143 switch (locCanonical) {
144 case DMSTAG_ELEMENT:
145 break; /* no extra points */
146 case DMSTAG_LEFT:
147 extraPoint[0] = nExtra[0];
148 break; /* only extra point in x */
149 case DMSTAG_DOWN:
150 extraPoint[1] = nExtra[1];
151 break; /* only extra point in y */
152 case DMSTAG_BACK:
153 extraPoint[2] = nExtra[2];
154 break; /* only extra point in z */
155 case DMSTAG_DOWN_LEFT:
156 extraPoint[0] = nExtra[0];
157 extraPoint[1] = nExtra[1];
158 break; /* extra point in both x and y */
159 case DMSTAG_BACK_LEFT:
160 extraPoint[0] = nExtra[0];
161 extraPoint[2] = nExtra[2];
162 break; /* extra point in both x and z */
163 case DMSTAG_BACK_DOWN:
164 extraPoint[1] = nExtra[1];
165 extraPoint[2] = nExtra[2];
166 break; /* extra point in both y and z */
167 case DMSTAG_BACK_DOWN_LEFT:
168 extraPoint[0] = nExtra[0];
169 extraPoint[1] = nExtra[1];
170 extraPoint[2] = nExtra[2];
171 break; /* extra points in x,y,z */
172 default:
173 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for location (perhaps not canonical) %s", DMStagStencilLocations[locCanonical]);
174 }
175 PetscFunctionReturn(PETSC_SUCCESS);
176 }
177
178 /*
179 Function much like DMStagMigrateVec(), but which accepts an additional position argument to disambiguate which
180 type of DMDA to migrate to.
181 */
182
DMStagMigrateVecDMDA(DM dm,Vec vec,DMStagStencilLocation loc,PetscInt c,DM dmTo,Vec vecTo)183 static PetscErrorCode DMStagMigrateVecDMDA(DM dm, Vec vec, DMStagStencilLocation loc, PetscInt c, DM dmTo, Vec vecTo)
184 {
185 PetscInt i, j, k, d, dim, dof, dofToMax, start[DMSTAG_MAX_DIM], n[DMSTAG_MAX_DIM], extraPoint[DMSTAG_MAX_DIM];
186 Vec vecLocal;
187
188 PetscFunctionBegin;
189 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSTAG);
190 PetscValidHeaderSpecific(vec, VEC_CLASSID, 2);
191 PetscValidHeaderSpecificType(dmTo, DM_CLASSID, 5, DMDA);
192 PetscValidHeaderSpecific(vecTo, VEC_CLASSID, 6);
193 PetscCall(DMGetDimension(dm, &dim));
194 PetscCall(DMDAGetDof(dmTo, &dofToMax));
195 PetscCheck(-c <= dofToMax, PetscObjectComm((PetscObject)dmTo), PETSC_ERR_ARG_OUTOFRANGE, "Invalid negative component value. Must be >= -%" PetscInt_FMT, dofToMax);
196 PetscCall(DMStagGetCorners(dm, &start[0], &start[1], &start[2], &n[0], &n[1], &n[2], NULL, NULL, NULL));
197 PetscCall(DMStagDMDAGetExtraPoints(dm, loc, extraPoint));
198 PetscCall(DMStagGetLocationDOF(dm, loc, &dof));
199 PetscCall(DMGetLocalVector(dm, &vecLocal));
200 PetscCall(DMGlobalToLocalBegin(dm, vec, INSERT_VALUES, vecLocal));
201 PetscCall(DMGlobalToLocalEnd(dm, vec, INSERT_VALUES, vecLocal));
202 if (dim == 1) {
203 PetscScalar **arrTo;
204 PetscCall(DMDAVecGetArrayDOF(dmTo, vecTo, &arrTo));
205 if (c < 0) {
206 const PetscInt dofTo = -c;
207 for (i = start[0]; i < start[0] + n[0] + extraPoint[0]; ++i) {
208 for (d = 0; d < PetscMin(dof, dofTo); ++d) {
209 DMStagStencil pos;
210 pos.i = i;
211 pos.loc = loc;
212 pos.c = d;
213 PetscCall(DMStagVecGetValuesStencil(dm, vecLocal, 1, &pos, &arrTo[i][d]));
214 }
215 for (; d < dofTo; ++d) arrTo[i][d] = 0.0; /* Pad extra dof with zeros */
216 }
217 } else {
218 for (i = start[0]; i < start[0] + n[0] + extraPoint[0]; ++i) {
219 DMStagStencil pos;
220 pos.i = i;
221 pos.loc = loc;
222 pos.c = c;
223 PetscCall(DMStagVecGetValuesStencil(dm, vecLocal, 1, &pos, &arrTo[i][0]));
224 }
225 }
226 PetscCall(DMDAVecRestoreArrayDOF(dmTo, vecTo, &arrTo));
227 } else if (dim == 2) {
228 PetscScalar ***arrTo;
229 PetscCall(DMDAVecGetArrayDOF(dmTo, vecTo, &arrTo));
230 if (c < 0) {
231 const PetscInt dofTo = -c;
232 for (j = start[1]; j < start[1] + n[1] + extraPoint[1]; ++j) {
233 for (i = start[0]; i < start[0] + n[0] + extraPoint[0]; ++i) {
234 for (d = 0; d < PetscMin(dof, dofTo); ++d) {
235 DMStagStencil pos;
236 pos.i = i;
237 pos.j = j;
238 pos.loc = loc;
239 pos.c = d;
240 PetscCall(DMStagVecGetValuesStencil(dm, vecLocal, 1, &pos, &arrTo[j][i][d]));
241 }
242 for (; d < dofTo; ++d) arrTo[j][i][d] = 0.0; /* Pad extra dof with zeros */
243 }
244 }
245 } else {
246 for (j = start[1]; j < start[1] + n[1] + extraPoint[1]; ++j) {
247 for (i = start[0]; i < start[0] + n[0] + extraPoint[0]; ++i) {
248 DMStagStencil pos;
249 pos.i = i;
250 pos.j = j;
251 pos.loc = loc;
252 pos.c = c;
253 PetscCall(DMStagVecGetValuesStencil(dm, vecLocal, 1, &pos, &arrTo[j][i][0]));
254 }
255 }
256 }
257 PetscCall(DMDAVecRestoreArrayDOF(dmTo, vecTo, &arrTo));
258 } else if (dim == 3) {
259 PetscScalar ****arrTo;
260 PetscCall(DMDAVecGetArrayDOF(dmTo, vecTo, &arrTo));
261 if (c < 0) {
262 const PetscInt dofTo = -c;
263 for (k = start[2]; k < start[2] + n[2] + extraPoint[2]; ++k) {
264 for (j = start[1]; j < start[1] + n[1] + extraPoint[1]; ++j) {
265 for (i = start[0]; i < start[0] + n[0] + extraPoint[0]; ++i) {
266 for (d = 0; d < PetscMin(dof, dofTo); ++d) {
267 DMStagStencil pos;
268 pos.i = i;
269 pos.j = j;
270 pos.k = k;
271 pos.loc = loc;
272 pos.c = d;
273 PetscCall(DMStagVecGetValuesStencil(dm, vecLocal, 1, &pos, &arrTo[k][j][i][d]));
274 }
275 for (; d < dofTo; ++d) arrTo[k][j][i][d] = 0.0; /* Pad extra dof with zeros */
276 }
277 }
278 }
279 } else {
280 for (k = start[2]; k < start[2] + n[2] + extraPoint[2]; ++k) {
281 for (j = start[1]; j < start[1] + n[1] + extraPoint[1]; ++j) {
282 for (i = start[0]; i < start[0] + n[0] + extraPoint[0]; ++i) {
283 DMStagStencil pos;
284 pos.i = i;
285 pos.j = j;
286 pos.k = k;
287 pos.loc = loc;
288 pos.c = c;
289 PetscCall(DMStagVecGetValuesStencil(dm, vecLocal, 1, &pos, &arrTo[k][j][i][0]));
290 }
291 }
292 }
293 }
294 PetscCall(DMDAVecRestoreArrayDOF(dmTo, vecTo, &arrTo));
295 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %" PetscInt_FMT, dim);
296 PetscCall(DMRestoreLocalVector(dm, &vecLocal));
297 PetscFunctionReturn(PETSC_SUCCESS);
298 }
299
300 /* Transfer coordinates from a DMStag to a DMDA, specifying which location */
DMStagTransferCoordinatesToDMDA(DM dmstag,DMStagStencilLocation loc,DM dmda)301 static PetscErrorCode DMStagTransferCoordinatesToDMDA(DM dmstag, DMStagStencilLocation loc, DM dmda)
302 {
303 PetscInt dim, start[DMSTAG_MAX_DIM], n[DMSTAG_MAX_DIM], extraPoint[DMSTAG_MAX_DIM], d;
304 DM dmstagCoord, dmdaCoord;
305 DMType dmstagCoordType;
306 Vec stagCoord, daCoord;
307 PetscBool daCoordIsStag, daCoordIsProduct;
308
309 PetscFunctionBegin;
310 PetscValidHeaderSpecificType(dmstag, DM_CLASSID, 1, DMSTAG);
311 PetscValidHeaderSpecificType(dmda, DM_CLASSID, 3, DMDA);
312 PetscCall(DMGetDimension(dmstag, &dim));
313 PetscCall(DMGetCoordinateDM(dmstag, &dmstagCoord));
314 PetscCall(DMGetCoordinatesLocal(dmstag, &stagCoord)); /* Note local */
315 PetscCall(DMGetCoordinateDM(dmda, &dmdaCoord));
316 daCoord = NULL;
317 PetscCall(DMGetCoordinates(dmda, &daCoord));
318 if (!daCoord) {
319 PetscCall(DMCreateGlobalVector(dmdaCoord, &daCoord));
320 PetscCall(DMSetCoordinates(dmda, daCoord));
321 PetscCall(VecDestroy(&daCoord));
322 PetscCall(DMGetCoordinates(dmda, &daCoord));
323 }
324 PetscCall(DMGetType(dmstagCoord, &dmstagCoordType));
325 PetscCall(PetscStrcmp(dmstagCoordType, DMSTAG, &daCoordIsStag));
326 PetscCall(PetscStrcmp(dmstagCoordType, DMPRODUCT, &daCoordIsProduct));
327 PetscCall(DMStagGetCorners(dmstag, &start[0], &start[1], &start[2], &n[0], &n[1], &n[2], NULL, NULL, NULL));
328 PetscCall(DMStagDMDAGetExtraPoints(dmstag, loc, extraPoint));
329 if (dim == 1) {
330 PetscInt ex;
331 PetscScalar **cArrDa;
332 PetscCall(DMDAVecGetArrayDOF(dmdaCoord, daCoord, &cArrDa));
333 if (daCoordIsStag) {
334 PetscInt slot;
335 PetscScalar **cArrStag;
336 PetscCall(DMStagGetLocationSlot(dmstagCoord, loc, 0, &slot));
337 PetscCall(DMStagVecGetArrayRead(dmstagCoord, stagCoord, &cArrStag));
338 for (ex = start[0]; ex < start[0] + n[0] + extraPoint[0]; ++ex) cArrDa[ex][0] = cArrStag[ex][slot];
339 PetscCall(DMStagVecRestoreArrayRead(dmstagCoord, stagCoord, &cArrStag));
340 } else if (daCoordIsProduct) {
341 PetscScalar **cArrX;
342 PetscCall(DMStagGetProductCoordinateArraysRead(dmstag, &cArrX, NULL, NULL));
343 for (ex = start[0]; ex < start[0] + n[0] + extraPoint[0]; ++ex) cArrDa[ex][0] = cArrX[ex][0];
344 PetscCall(DMStagRestoreProductCoordinateArraysRead(dmstag, &cArrX, NULL, NULL));
345 } else SETERRQ(PetscObjectComm((PetscObject)dmstag), PETSC_ERR_SUP, "Stag to DA coordinate transfer only supported for DMStag coordinate DM of type DMstag or DMProduct");
346 PetscCall(DMDAVecRestoreArrayDOF(dmdaCoord, daCoord, &cArrDa));
347 } else if (dim == 2) {
348 PetscInt ex, ey;
349 PetscScalar ***cArrDa;
350 PetscCall(DMDAVecGetArrayDOF(dmdaCoord, daCoord, &cArrDa));
351 if (daCoordIsStag) {
352 PetscInt slot;
353 PetscScalar ***cArrStag;
354 PetscCall(DMStagGetLocationSlot(dmstagCoord, loc, 0, &slot));
355 PetscCall(DMStagVecGetArrayRead(dmstagCoord, stagCoord, &cArrStag));
356 for (ey = start[1]; ey < start[1] + n[1] + extraPoint[1]; ++ey) {
357 for (ex = start[0]; ex < start[0] + n[0] + extraPoint[0]; ++ex) {
358 for (d = 0; d < 2; ++d) cArrDa[ey][ex][d] = cArrStag[ey][ex][slot + d];
359 }
360 }
361 PetscCall(DMStagVecRestoreArrayRead(dmstagCoord, stagCoord, &cArrStag));
362 } else if (daCoordIsProduct) {
363 PetscScalar **cArrX, **cArrY;
364 PetscCall(DMStagGetProductCoordinateArraysRead(dmstag, &cArrX, &cArrY, NULL));
365 for (ey = start[1]; ey < start[1] + n[1] + extraPoint[1]; ++ey) {
366 for (ex = start[0]; ex < start[0] + n[0] + extraPoint[0]; ++ex) {
367 cArrDa[ey][ex][0] = cArrX[ex][0];
368 cArrDa[ey][ex][1] = cArrY[ey][0];
369 }
370 }
371 PetscCall(DMStagRestoreProductCoordinateArraysRead(dmstag, &cArrX, &cArrY, NULL));
372 } else SETERRQ(PetscObjectComm((PetscObject)dmstag), PETSC_ERR_SUP, "Stag to DA coordinate transfer only supported for DMStag coordinate DM of type DMstag or DMProduct");
373 PetscCall(DMDAVecRestoreArrayDOF(dmdaCoord, daCoord, &cArrDa));
374 } else if (dim == 3) {
375 PetscInt ex, ey, ez;
376 PetscScalar ****cArrDa;
377 PetscCall(DMDAVecGetArrayDOF(dmdaCoord, daCoord, &cArrDa));
378 if (daCoordIsStag) {
379 PetscInt slot;
380 PetscScalar ****cArrStag;
381 PetscCall(DMStagGetLocationSlot(dmstagCoord, loc, 0, &slot));
382 PetscCall(DMStagVecGetArrayRead(dmstagCoord, stagCoord, &cArrStag));
383 for (ez = start[2]; ez < start[2] + n[2] + extraPoint[2]; ++ez) {
384 for (ey = start[1]; ey < start[1] + n[1] + extraPoint[1]; ++ey) {
385 for (ex = start[0]; ex < start[0] + n[0] + extraPoint[0]; ++ex) {
386 for (d = 0; d < 3; ++d) cArrDa[ez][ey][ex][d] = cArrStag[ez][ey][ex][slot + d];
387 }
388 }
389 }
390 PetscCall(DMStagVecRestoreArrayRead(dmstagCoord, stagCoord, &cArrStag));
391 } else if (daCoordIsProduct) {
392 PetscScalar **cArrX, **cArrY, **cArrZ;
393 PetscCall(DMStagGetProductCoordinateArraysRead(dmstag, &cArrX, &cArrY, &cArrZ));
394 for (ez = start[2]; ez < start[2] + n[2] + extraPoint[2]; ++ez) {
395 for (ey = start[1]; ey < start[1] + n[1] + extraPoint[1]; ++ey) {
396 for (ex = start[0]; ex < start[0] + n[0] + extraPoint[0]; ++ex) {
397 cArrDa[ez][ey][ex][0] = cArrX[ex][0];
398 cArrDa[ez][ey][ex][1] = cArrY[ey][0];
399 cArrDa[ez][ey][ex][2] = cArrZ[ez][0];
400 }
401 }
402 }
403 PetscCall(DMStagRestoreProductCoordinateArraysRead(dmstag, &cArrX, &cArrY, &cArrZ));
404 } else SETERRQ(PetscObjectComm((PetscObject)dmstag), PETSC_ERR_SUP, "Stag to DA coordinate transfer only supported for DMStag coordinate DM of type DMstag or DMProduct");
405 PetscCall(DMDAVecRestoreArrayDOF(dmdaCoord, daCoord, &cArrDa));
406 } else SETERRQ(PetscObjectComm((PetscObject)dmstag), PETSC_ERR_SUP, "Unsupported dimension %" PetscInt_FMT, dim);
407 PetscFunctionReturn(PETSC_SUCCESS);
408 }
409
410 /*@
411 DMStagVecSplitToDMDA - create a `DMDA` and `Vec` from a subgrid of a `DMSTAG` and its `Vec`
412
413 Collective
414
415 Input Parameters:
416 + dm - the `DMSTAG` object
417 . vec - `Vec` object associated with `dm`
418 . loc - which subgrid to extract (see `DMStagStencilLocation`)
419 - c - which component to extract (see note below)
420
421 Output Parameters:
422 + pda - the `DMDA`
423 - pdavec - the new `Vec`
424
425 Level: advanced
426
427 Notes:
428 If a `c` value of `-k` is provided, the first `k` DOF for that position are extracted,
429 padding with zero values if needed. If a non-negative value is provided, a single
430 DOF is extracted.
431
432 The caller is responsible for destroying the created `DMDA` and `Vec`.
433
434 .seealso: [](ch_stag), `DMSTAG`, `DMDA`, `DMStagStencilLocation`, `DM`, `Vec`, `DMStagMigrateVec()`, `DMStagCreateCompatibleDMStag()`
435 @*/
DMStagVecSplitToDMDA(DM dm,Vec vec,DMStagStencilLocation loc,PetscInt c,DM * pda,Vec * pdavec)436 PetscErrorCode DMStagVecSplitToDMDA(DM dm, Vec vec, DMStagStencilLocation loc, PetscInt c, DM *pda, Vec *pdavec)
437 {
438 PetscInt dim, locdof;
439 DM da, coordDM;
440 Vec davec;
441 DMStagStencilLocation locCanonical;
442
443 PetscFunctionBegin;
444 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSTAG);
445 PetscValidHeaderSpecific(vec, VEC_CLASSID, 2);
446 PetscCall(DMGetDimension(dm, &dim));
447 PetscCall(DMStagGetLocationDOF(dm, loc, &locdof));
448 PetscCheck(c < locdof, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Location %s has %" PetscInt_FMT " dof, but component %" PetscInt_FMT " requested", DMStagStencilLocations[loc], locdof, c);
449 PetscCall(DMStagStencilLocationCanonicalize(loc, &locCanonical));
450 PetscCall(DMStagCreateCompatibleDMDA(dm, locCanonical, c, pda));
451 da = *pda;
452 PetscCall(DMSetUp(*pda));
453 if (dm->coordinates[0].dm != NULL) {
454 PetscCall(DMGetCoordinateDM(dm, &coordDM));
455 PetscCall(DMStagTransferCoordinatesToDMDA(dm, locCanonical, da));
456 }
457 PetscCall(DMCreateGlobalVector(da, pdavec));
458 davec = *pdavec;
459 PetscCall(DMStagMigrateVecDMDA(dm, vec, locCanonical, c, da, davec));
460 PetscFunctionReturn(PETSC_SUCCESS);
461 }
462