1 /*
2 Implementation of DMStag, defining dimension-independent functions in the
3 DM API. stag1d.c, stag2d.c, and stag3d.c may include dimension-specific
4 implementations of DM API functions, and other files here contain additional
5 DMStag-specific API functions, as well as internal functions.
6 */
7 #include <petsc/private/dmstagimpl.h>
8 #include <petscsf.h>
9
DMClone_Stag(DM dm,DM * newdm)10 static PetscErrorCode DMClone_Stag(DM dm,DM *newdm)
11 {
12 PetscErrorCode ierr;
13
14 PetscFunctionBegin;
15 /* Destroy the DM created by generic logic in DMClone() */
16 if (*newdm) {
17 ierr = DMDestroy(newdm);CHKERRQ(ierr);
18 }
19 ierr = DMStagDuplicateWithoutSetup(dm,PetscObjectComm((PetscObject)dm),newdm);CHKERRQ(ierr);
20 ierr = DMSetUp(*newdm);CHKERRQ(ierr);
21 PetscFunctionReturn(0);
22 }
23
DMDestroy_Stag(DM dm)24 static PetscErrorCode DMDestroy_Stag(DM dm)
25 {
26 PetscErrorCode ierr;
27 DM_Stag *stag;
28 PetscInt i;
29
30 PetscFunctionBegin;
31 stag = (DM_Stag*)dm->data;
32 for (i=0; i<DMSTAG_MAX_DIM; ++i) {
33 ierr = PetscFree(stag->l[i]);CHKERRQ(ierr);
34 }
35 ierr = VecScatterDestroy(&stag->gtol);CHKERRQ(ierr);
36 ierr = VecScatterDestroy(&stag->ltog_injective);CHKERRQ(ierr);
37 ierr = PetscFree(stag->neighbors);CHKERRQ(ierr);
38 ierr = PetscFree(stag->locationOffsets);CHKERRQ(ierr);
39 ierr = PetscFree(stag->coordinateDMType);CHKERRQ(ierr);
40 ierr = PetscFree(stag);CHKERRQ(ierr);
41 PetscFunctionReturn(0);
42 }
43
DMCreateGlobalVector_Stag(DM dm,Vec * vec)44 static PetscErrorCode DMCreateGlobalVector_Stag(DM dm,Vec *vec)
45 {
46 PetscErrorCode ierr;
47 DM_Stag * const stag = (DM_Stag*)dm->data;
48
49 PetscFunctionBegin;
50 ierr = VecCreateMPI(PetscObjectComm((PetscObject)dm),stag->entries,PETSC_DECIDE,vec);CHKERRQ(ierr);
51 ierr = VecSetDM(*vec,dm);CHKERRQ(ierr);
52 /* Could set some ops, as DMDA does */
53 ierr = VecSetLocalToGlobalMapping(*vec,dm->ltogmap);CHKERRQ(ierr);
54 PetscFunctionReturn(0);
55 }
56
DMCreateLocalVector_Stag(DM dm,Vec * vec)57 static PetscErrorCode DMCreateLocalVector_Stag(DM dm,Vec *vec)
58 {
59 PetscErrorCode ierr;
60 DM_Stag * const stag = (DM_Stag*)dm->data;
61
62 PetscFunctionBegin;
63 ierr = VecCreateSeq(PETSC_COMM_SELF,stag->entriesGhost,vec);CHKERRQ(ierr);
64 ierr = VecSetBlockSize(*vec,stag->entriesPerElement);CHKERRQ(ierr);
65 ierr = VecSetDM(*vec,dm);CHKERRQ(ierr);
66 PetscFunctionReturn(0);
67 }
68
DMCreateMatrix_Stag(DM dm,Mat * mat)69 static PetscErrorCode DMCreateMatrix_Stag(DM dm,Mat *mat)
70 {
71 PetscErrorCode ierr;
72 MatType matType;
73 PetscBool isaij,isshell;
74 PetscInt entries,width,nNeighbors,dim,dof[DMSTAG_MAX_STRATA],stencilWidth;
75 DMStagStencilType stencilType;
76 ISLocalToGlobalMapping ltogmap;
77
78 PetscFunctionBegin;
79 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
80 ierr = DMGetMatType(dm,&matType);CHKERRQ(ierr);
81 ierr = PetscStrcmp(matType,MATAIJ,&isaij);CHKERRQ(ierr);
82 ierr = PetscStrcmp(matType,MATSHELL,&isshell);CHKERRQ(ierr);
83 ierr = DMStagGetEntries(dm,&entries);CHKERRQ(ierr);
84 ierr = DMStagGetDOF(dm,&dof[0],&dof[1],&dof[2],&dof[3]);CHKERRQ(ierr);
85 ierr = DMStagGetStencilWidth(dm,&stencilWidth);CHKERRQ(ierr);
86 ierr = DMStagGetStencilType(dm,&stencilType);CHKERRQ(ierr);
87
88 if (isaij) {
89 /* This implementation gives a very dense stencil, which is likely unsuitable for
90 real applications. */
91 switch (stencilType) {
92 case DMSTAG_STENCIL_NONE:
93 nNeighbors = 1;
94 break;
95 case DMSTAG_STENCIL_STAR:
96 switch (dim) {
97 case 1 :
98 nNeighbors = 2*stencilWidth + 1;
99 break;
100 case 2 :
101 nNeighbors = 4*stencilWidth + 3;
102 break;
103 case 3 :
104 nNeighbors = 6*stencilWidth + 5;
105 break;
106 default : SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Unsupported dimension %d",dim);
107 }
108 break;
109 case DMSTAG_STENCIL_BOX:
110 switch (dim) {
111 case 1 :
112 nNeighbors = (2*stencilWidth + 1);
113 break;
114 case 2 :
115 nNeighbors = (2*stencilWidth + 1) * (2*stencilWidth + 1);
116 break;
117 case 3 :
118 nNeighbors = (2*stencilWidth + 1) * (2*stencilWidth + 1) * (2*stencilWidth + 1);
119 break;
120 default : SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Unsupported dimension %d",dim);
121 }
122 break;
123 default : SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Unsupported stencil");
124 }
125 width = (dof[0] + dof[1] + dof[2] + dof[3]) * nNeighbors;
126 ierr = MatCreateAIJ(PETSC_COMM_WORLD,entries,entries,PETSC_DETERMINE,PETSC_DETERMINE,width,NULL,width,NULL,mat);CHKERRQ(ierr);
127 } else if (isshell) {
128 ierr = MatCreate(PetscObjectComm((PetscObject)dm),mat);CHKERRQ(ierr);
129 ierr = MatSetSizes(*mat,entries,entries,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
130 ierr = MatSetType(*mat,MATSHELL);CHKERRQ(ierr);
131 ierr = MatSetUp(*mat);CHKERRQ(ierr);
132 } else SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Not implemented for Mattype %s",matType);
133
134 ierr = DMGetLocalToGlobalMapping(dm,<ogmap);CHKERRQ(ierr);
135 ierr = MatSetLocalToGlobalMapping(*mat,ltogmap,ltogmap);CHKERRQ(ierr);
136 ierr = MatSetDM(*mat,dm);CHKERRQ(ierr);
137 PetscFunctionReturn(0);
138 }
139
DMGetCompatibility_Stag(DM dm,DM dm2,PetscBool * compatible,PetscBool * set)140 static PetscErrorCode DMGetCompatibility_Stag(DM dm,DM dm2,PetscBool *compatible,PetscBool *set)
141 {
142 PetscErrorCode ierr;
143 const DM_Stag * const stag = (DM_Stag*)dm->data;
144 const DM_Stag * const stag2 = (DM_Stag*)dm2->data;
145 PetscInt dim,dim2,i;
146 MPI_Comm comm;
147 PetscMPIInt sameComm;
148 DMType type2;
149 PetscBool sameType;
150
151 PetscFunctionBegin;
152 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr);
153 ierr = PetscStrcmp(DMSTAG,type2,&sameType);CHKERRQ(ierr);
154 if (!sameType) {
155 ierr = PetscInfo1((PetscObject)dm,"DMStag compatibility check not implemented with DM of type %s\n",type2);CHKERRQ(ierr);
156 *set = PETSC_FALSE;
157 PetscFunctionReturn(0);
158 }
159
160 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
161 ierr = MPI_Comm_compare(comm,PetscObjectComm((PetscObject)dm2),&sameComm);CHKERRQ(ierr);
162 if (sameComm != MPI_IDENT) {
163 ierr = PetscInfo2((PetscObject)dm,"DMStag objects have different communicators: %d != %d\n",comm,PetscObjectComm((PetscObject)dm2));CHKERRQ(ierr);
164 *set = PETSC_FALSE;
165 PetscFunctionReturn(0);
166 }
167 ierr = DMGetDimension(dm ,&dim);CHKERRQ(ierr);
168 ierr = DMGetDimension(dm2,&dim2);CHKERRQ(ierr);
169 if (dim != dim2) {
170 ierr = PetscInfo((PetscObject)dm,"DMStag objects have different dimensions");CHKERRQ(ierr);
171 *set = PETSC_TRUE;
172 *compatible = PETSC_FALSE;
173 PetscFunctionReturn(0);
174 }
175 for (i=0; i<dim; ++i) {
176 if (stag->N[i] != stag2->N[i]) {
177 ierr = PetscInfo3((PetscObject)dm,"DMStag objects have different global numbers of elements in dimension %D: %D != %D\n",i,stag->n[i],stag2->n[i]);CHKERRQ(ierr);
178 *set = PETSC_TRUE;
179 *compatible = PETSC_FALSE;
180 PetscFunctionReturn(0);
181 }
182 if (stag->n[i] != stag2->n[i]) {
183 ierr = PetscInfo3((PetscObject)dm,"DMStag objects have different local numbers of elements in dimension %D: %D != %D\n",i,stag->n[i],stag2->n[i]);CHKERRQ(ierr);
184 *set = PETSC_TRUE;
185 *compatible = PETSC_FALSE;
186 PetscFunctionReturn(0);
187 }
188 if (stag->boundaryType[i] != stag2->boundaryType[i]) {
189 ierr = PetscInfo3((PetscObject)dm,"DMStag objects have different boundary types in dimension %d: %s != %s\n",i,stag->boundaryType[i],stag2->boundaryType[i]);CHKERRQ(ierr);
190 *set = PETSC_TRUE;
191 *compatible = PETSC_FALSE;
192 PetscFunctionReturn(0);
193 }
194 }
195 /* Note: we include stencil type and width in the notion of compatibility, as this affects
196 the "atlas" (local subdomains). This might be irritating in legitimate cases
197 of wanting to transfer between two other-wise compatible DMs with different
198 stencil characteristics. */
199 if (stag->stencilType != stag2->stencilType) {
200 ierr = PetscInfo2((PetscObject)dm,"DMStag objects have different ghost stencil types: %s != %s\n",DMStagStencilTypes[stag->stencilType],DMStagStencilTypes[stag2->stencilType]);CHKERRQ(ierr);
201 *set = PETSC_TRUE;
202 *compatible = PETSC_FALSE;
203 PetscFunctionReturn(0);
204 }
205 if (stag->stencilWidth != stag2->stencilWidth) {
206 ierr = PetscInfo2((PetscObject)dm,"DMStag objects have different ghost stencil widths: %D != %D\n",stag->stencilWidth,stag->stencilWidth);CHKERRQ(ierr);
207 *set = PETSC_TRUE;
208 *compatible = PETSC_FALSE;
209 PetscFunctionReturn(0);
210 }
211 *set = PETSC_TRUE;
212 *compatible = PETSC_TRUE;
213 PetscFunctionReturn(0);
214 }
215
216
217 /*
218 Note there are several orderings in play here.
219 In all cases, non-element dof are associated with the element that they are below/left/behind, and the order in 2D proceeds vertex/bottom edge/left edge/element (with all dof on each together).
220 Also in all cases, only subdomains which are the last in their dimension have partial elements.
221
222 1) "Natural" Ordering (not used). Number adding each full or partial (on the right or top) element, starting at the bottom left (i=0,j=0) and proceeding across the entire domain, row by row to get a global numbering.
223 2) Global ("PETSc") ordering. The same as natural, but restricted to each domain. So, traverse all elements (again starting at the bottom left and going row-by-row) on rank 0, then continue numbering with rank 1, and so on.
224 3) Local ordering. Including ghost elements (both interior and on the right/top/front to complete partial elements), use the same convention to create a local numbering.
225 */
226
DMLocalToGlobalBegin_Stag(DM dm,Vec l,InsertMode mode,Vec g)227 static PetscErrorCode DMLocalToGlobalBegin_Stag(DM dm,Vec l,InsertMode mode,Vec g)
228 {
229 PetscErrorCode ierr;
230 DM_Stag * const stag = (DM_Stag*)dm->data;
231
232 PetscFunctionBegin;
233 if (mode == ADD_VALUES) {
234 ierr = VecScatterBegin(stag->gtol,l,g,mode,SCATTER_REVERSE);CHKERRQ(ierr);
235 } else if (mode == INSERT_VALUES) {
236 if (stag->ltog_injective) {
237 ierr = VecScatterBegin(stag->ltog_injective,l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr);
238 } else {
239 ierr = VecScatterBegin(stag->gtol,l,g,mode,SCATTER_REVERSE_LOCAL);CHKERRQ(ierr);
240 }
241 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Unsupported InsertMode");
242 PetscFunctionReturn(0);
243 }
244
DMLocalToGlobalEnd_Stag(DM dm,Vec l,InsertMode mode,Vec g)245 static PetscErrorCode DMLocalToGlobalEnd_Stag(DM dm,Vec l,InsertMode mode,Vec g)
246 {
247 PetscErrorCode ierr;
248 DM_Stag * const stag = (DM_Stag*)dm->data;
249
250 PetscFunctionBegin;
251 if (mode == ADD_VALUES) {
252 ierr = VecScatterEnd(stag->gtol,l,g,mode,SCATTER_REVERSE);CHKERRQ(ierr);
253 } else if (mode == INSERT_VALUES) {
254 if (stag->ltog_injective) {
255 ierr = VecScatterEnd(stag->ltog_injective,l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr);
256 } else {
257 ierr = VecScatterEnd(stag->gtol,l,g,mode,SCATTER_REVERSE_LOCAL);CHKERRQ(ierr);
258 }
259 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Unsupported InsertMode");
260 PetscFunctionReturn(0);
261 }
262
DMGlobalToLocalBegin_Stag(DM dm,Vec g,InsertMode mode,Vec l)263 static PetscErrorCode DMGlobalToLocalBegin_Stag(DM dm,Vec g,InsertMode mode,Vec l)
264 {
265 PetscErrorCode ierr;
266 DM_Stag * const stag = (DM_Stag*)dm->data;
267
268 PetscFunctionBegin;
269 ierr = VecScatterBegin(stag->gtol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
270 PetscFunctionReturn(0);
271 }
272
DMGlobalToLocalEnd_Stag(DM dm,Vec g,InsertMode mode,Vec l)273 static PetscErrorCode DMGlobalToLocalEnd_Stag(DM dm,Vec g,InsertMode mode,Vec l)
274 {
275 PetscErrorCode ierr;
276 DM_Stag * const stag = (DM_Stag*)dm->data;
277
278 PetscFunctionBegin;
279 ierr = VecScatterEnd(stag->gtol,g,l,mode,SCATTER_FORWARD);CHKERRQ(ierr);
280 PetscFunctionReturn(0);
281 }
282
283 /*
284 If a stratum is active (non-zero dof), make it active in the coordinate DM.
285 */
DMCreateCoordinateDM_Stag(DM dm,DM * dmc)286 static PetscErrorCode DMCreateCoordinateDM_Stag(DM dm,DM *dmc)
287 {
288 PetscErrorCode ierr;
289 DM_Stag * const stag = (DM_Stag*)dm->data;
290 PetscInt dim;
291 PetscBool isstag,isproduct;
292
293 PetscFunctionBegin;
294
295 if (!stag->coordinateDMType) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Before creating a coordinate DM, a type must be specified with DMStagSetCoordinateDMType()");
296
297 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
298 ierr = PetscStrcmp(stag->coordinateDMType,DMSTAG,&isstag);CHKERRQ(ierr);
299 ierr = PetscStrcmp(stag->coordinateDMType,DMPRODUCT,&isproduct);CHKERRQ(ierr);
300 if (isstag) {
301 ierr = DMStagCreateCompatibleDMStag(dm,
302 stag->dof[0] > 0 ? dim : 0,
303 stag->dof[1] > 0 ? dim : 0,
304 stag->dof[2] > 0 ? dim : 0,
305 stag->dof[3] > 0 ? dim : 0,
306 dmc);CHKERRQ(ierr);
307 } else if (isproduct) {
308 ierr = DMCreate(PETSC_COMM_WORLD,dmc);CHKERRQ(ierr);
309 ierr = DMSetType(*dmc,DMPRODUCT);CHKERRQ(ierr);
310 ierr = DMSetDimension(*dmc,dim);CHKERRQ(ierr);
311 } else SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Unsupported coordinate DM type %s",stag->coordinateDMType);
312 PetscFunctionReturn(0);
313 }
314
DMGetNeighbors_Stag(DM dm,PetscInt * nRanks,const PetscMPIInt * ranks[])315 static PetscErrorCode DMGetNeighbors_Stag(DM dm,PetscInt *nRanks,const PetscMPIInt *ranks[])
316 {
317 PetscErrorCode ierr;
318 DM_Stag * const stag = (DM_Stag*)dm->data;
319 PetscInt dim;
320
321 PetscFunctionBegin;
322 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
323 switch (dim) {
324 case 1: *nRanks = 3; break;
325 case 2: *nRanks = 9; break;
326 case 3: *nRanks = 27; break;
327 default : SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Get neighbors not implemented for dim = %D",dim);
328 }
329 *ranks = stag->neighbors;
330 PetscFunctionReturn(0);
331 }
332
DMView_Stag(DM dm,PetscViewer viewer)333 static PetscErrorCode DMView_Stag(DM dm,PetscViewer viewer)
334 {
335 PetscErrorCode ierr;
336 DM_Stag * const stag = (DM_Stag*)dm->data;
337 PetscBool isascii,viewAllRanks;
338 PetscMPIInt rank,size;
339 PetscInt dim,maxRanksToView,i;
340
341 PetscFunctionBegin;
342 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
343 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size);CHKERRQ(ierr);
344 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
345 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
346 if (isascii) {
347 ierr = PetscViewerASCIIPrintf(viewer,"Dimension: %D\n",dim);CHKERRQ(ierr);
348 switch (dim) {
349 case 1:
350 ierr = PetscViewerASCIIPrintf(viewer,"Global size: %D\n",stag->N[0]);CHKERRQ(ierr);
351 break;
352 case 2:
353 ierr = PetscViewerASCIIPrintf(viewer,"Global sizes: %D x %D\n",stag->N[0],stag->N[1]);CHKERRQ(ierr);
354 ierr = PetscViewerASCIIPrintf(viewer,"Parallel decomposition: %D x %D ranks\n",stag->nRanks[0],stag->nRanks[1]);CHKERRQ(ierr);
355 break;
356 case 3:
357 ierr = PetscViewerASCIIPrintf(viewer,"Global sizes: %D x %D x %D\n",stag->N[0],stag->N[1],stag->N[2]);CHKERRQ(ierr);
358 ierr = PetscViewerASCIIPrintf(viewer,"Parallel decomposition: %D x %D x %D ranks\n",stag->nRanks[0],stag->nRanks[1],stag->nRanks[2]);CHKERRQ(ierr);
359 break;
360 default: SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"not implemented for dim==%D",dim);
361 }
362 ierr = PetscViewerASCIIPrintf(viewer,"Boundary ghosting:");CHKERRQ(ierr);
363 for (i=0; i<dim; ++i) {
364 ierr = PetscViewerASCIIPrintf(viewer," %s",DMBoundaryTypes[stag->boundaryType[i]]);CHKERRQ(ierr);
365 }
366 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
367 ierr = PetscViewerASCIIPrintf(viewer,"Elementwise ghost stencil: %s, width %D\n",DMStagStencilTypes[stag->stencilType],stag->stencilWidth);CHKERRQ(ierr);
368 ierr = PetscViewerASCIIPrintf(viewer,"Stratum dof:");CHKERRQ(ierr);
369 for (i=0; i<dim+1; ++i) {
370 ierr = PetscViewerASCIIPrintf(viewer," %D:%D",i,stag->dof[i]);CHKERRQ(ierr);
371 }
372 ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
373 if (dm->coordinateDM) {
374 ierr = PetscViewerASCIIPrintf(viewer,"Has coordinate DM\n");CHKERRQ(ierr);
375 }
376 maxRanksToView = 16;
377 viewAllRanks = (PetscBool)(size <= maxRanksToView);
378 if (viewAllRanks) {
379 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
380 switch (dim) {
381 case 1:
382 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local elements : %D (%D with ghosts)\n",rank,stag->n[0],stag->nGhost[0]);CHKERRQ(ierr);
383 break;
384 case 2:
385 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Rank coordinates (%d,%d)\n",rank,stag->rank[0],stag->rank[1]);CHKERRQ(ierr);
386 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local elements : %D x %D (%D x %D with ghosts)\n",rank,stag->n[0],stag->n[1],stag->nGhost[0],stag->nGhost[1]);CHKERRQ(ierr);
387 break;
388 case 3:
389 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Rank coordinates (%d,%d,%d)\n",rank,stag->rank[0],stag->rank[1],stag->rank[2]);CHKERRQ(ierr);
390 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local elements : %D x %D x %D (%D x %D x %D with ghosts)\n",rank,stag->n[0],stag->n[1],stag->n[2],stag->nGhost[0],stag->nGhost[1],stag->nGhost[2]);CHKERRQ(ierr);
391 break;
392 default: SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"not implemented for dim==%D",dim);
393 }
394 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local native entries: %d\n",rank,stag->entries);CHKERRQ(ierr);
395 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local entries total : %d\n",rank,stag->entriesGhost);CHKERRQ(ierr);
396 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
397 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
398 } else {
399 ierr = PetscViewerASCIIPrintf(viewer,"(Per-rank information omitted since >%D ranks used)\n",maxRanksToView);CHKERRQ(ierr);
400 }
401 }
402 PetscFunctionReturn(0);
403 }
404
DMSetFromOptions_Stag(PetscOptionItems * PetscOptionsObject,DM dm)405 static PetscErrorCode DMSetFromOptions_Stag(PetscOptionItems *PetscOptionsObject,DM dm)
406 {
407 PetscErrorCode ierr;
408 DM_Stag * const stag = (DM_Stag*)dm->data;
409 PetscInt dim;
410
411 PetscFunctionBegin;
412 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
413 ierr = PetscOptionsHead(PetscOptionsObject,"DMStag Options");CHKERRQ(ierr);
414 ierr = PetscOptionsInt("-stag_grid_x","Number of grid points in x direction","DMStagSetGlobalSizes",stag->N[0],&stag->N[0],NULL);CHKERRQ(ierr);
415 if (dim > 1) { ierr = PetscOptionsInt("-stag_grid_y","Number of grid points in y direction","DMStagSetGlobalSizes",stag->N[1],&stag->N[1],NULL);CHKERRQ(ierr); }
416 if (dim > 2) { ierr = PetscOptionsInt("-stag_grid_z","Number of grid points in z direction","DMStagSetGlobalSizes",stag->N[2],&stag->N[2],NULL);CHKERRQ(ierr); }
417 ierr = PetscOptionsInt("-stag_ranks_x","Number of ranks in x direction","DMStagSetNumRanks",stag->nRanks[0],&stag->nRanks[0],NULL);CHKERRQ(ierr);
418 if (dim > 1) { ierr = PetscOptionsInt("-stag_ranks_y","Number of ranks in y direction","DMStagSetNumRanks",stag->nRanks[1],&stag->nRanks[1],NULL);CHKERRQ(ierr); }
419 if (dim > 2) { ierr = PetscOptionsInt("-stag_ranks_z","Number of ranks in z direction","DMStagSetNumRanks",stag->nRanks[2],&stag->nRanks[2],NULL);CHKERRQ(ierr); }
420 ierr = PetscOptionsInt("-stag_stencil_width","Elementwise stencil width","DMStagSetStencilWidth",stag->stencilWidth,&stag->stencilWidth,NULL);CHKERRQ(ierr);
421 ierr = PetscOptionsEnum("-stag_stencil_type","Elementwise stencil stype","DMStagSetStencilType",DMStagStencilTypes,(PetscEnum)stag->stencilType,(PetscEnum*)&stag->stencilType,NULL);CHKERRQ(ierr);
422 ierr = PetscOptionsEnum("-stag_boundary_type_x","Treatment of (physical) boundaries in x direction","DMStagSetBoundaryTypes",DMBoundaryTypes,(PetscEnum)stag->boundaryType[0],(PetscEnum*)&stag->boundaryType[0],NULL);CHKERRQ(ierr);
423 ierr = PetscOptionsEnum("-stag_boundary_type_y","Treatment of (physical) boundaries in y direction","DMStagSetBoundaryTypes",DMBoundaryTypes,(PetscEnum)stag->boundaryType[1],(PetscEnum*)&stag->boundaryType[1],NULL);CHKERRQ(ierr);
424 ierr = PetscOptionsEnum("-stag_boundary_type_z","Treatment of (physical) boundaries in z direction","DMStagSetBoundaryTypes",DMBoundaryTypes,(PetscEnum)stag->boundaryType[2],(PetscEnum*)&stag->boundaryType[2],NULL);CHKERRQ(ierr);
425 ierr = PetscOptionsInt("-stag_dof_0","Number of dof per 0-cell (vertex/corner)","DMStagSetDOF",stag->dof[0],&stag->dof[0],NULL);CHKERRQ(ierr);
426 ierr = PetscOptionsInt("-stag_dof_1","Number of dof per 1-cell (edge)", "DMStagSetDOF",stag->dof[1],&stag->dof[1],NULL);CHKERRQ(ierr);
427 ierr = PetscOptionsInt("-stag_dof_2","Number of dof per 2-cell (face)", "DMStagSetDOF",stag->dof[2],&stag->dof[2],NULL);CHKERRQ(ierr);
428 ierr = PetscOptionsInt("-stag_dof_3","Number of dof per 3-cell (hexahedron)", "DMStagSetDOF",stag->dof[3],&stag->dof[3],NULL);CHKERRQ(ierr);
429 ierr = PetscOptionsTail();CHKERRQ(ierr);
430 PetscFunctionReturn(0);
431 }
432
433 /*MC
434 DMSTAG = "stag" - A DM object representing a "staggered grid" or a structured cell complex.
435
436 This implementation parallels the DMDA implementation in many ways, but allows degrees of freedom
437 to be associated with all "strata" in a logically-rectangular grid: vertices, edges, faces, and elements.
438
439 Level: beginner
440
441 .seealso: DM, DMPRODUCT, DMDA, DMPLEX, DMStagCreate1d(), DMStagCreate2d(), DMStagCreate3d(), DMType, DMCreate(), DMSetType()
442 M*/
443
DMCreate_Stag(DM dm)444 PETSC_EXTERN PetscErrorCode DMCreate_Stag(DM dm)
445 {
446 PetscErrorCode ierr;
447 DM_Stag *stag;
448 PetscInt i,dim;
449
450 PetscFunctionBegin;
451 PetscValidPointer(dm,1);
452 ierr = PetscNewLog(dm,&stag);CHKERRQ(ierr);
453 dm->data = stag;
454
455 stag->gtol = NULL;
456 stag->ltog_injective = NULL;
457 for (i=0; i<DMSTAG_MAX_STRATA; ++i) stag->dof[i] = 0;
458 for (i=0; i<DMSTAG_MAX_DIM; ++i) stag->l[i] = NULL;
459 stag->stencilType = DMSTAG_STENCIL_NONE;
460 stag->stencilWidth = 0;
461 for (i=0; i<DMSTAG_MAX_DIM; ++i) stag->nRanks[i] = -1;
462 stag->coordinateDMType = NULL;
463
464 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
465 if (dim != 1 && dim != 2 && dim != 3) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"DMSetDimension() must be called to set a dimension with value 1, 2, or 3");
466
467 ierr = PetscMemzero(dm->ops,sizeof(*(dm->ops)));CHKERRQ(ierr);
468 dm->ops->createcoordinatedm = DMCreateCoordinateDM_Stag;
469 dm->ops->createglobalvector = DMCreateGlobalVector_Stag;
470 dm->ops->createinterpolation = NULL;
471 dm->ops->createlocalvector = DMCreateLocalVector_Stag;
472 dm->ops->creatematrix = DMCreateMatrix_Stag;
473 dm->ops->destroy = DMDestroy_Stag;
474 dm->ops->getneighbors = DMGetNeighbors_Stag;
475 dm->ops->globaltolocalbegin = DMGlobalToLocalBegin_Stag;
476 dm->ops->globaltolocalend = DMGlobalToLocalEnd_Stag;
477 dm->ops->localtoglobalbegin = DMLocalToGlobalBegin_Stag;
478 dm->ops->localtoglobalend = DMLocalToGlobalEnd_Stag;
479 dm->ops->setfromoptions = DMSetFromOptions_Stag;
480 switch (dim) {
481 case 1: dm->ops->setup = DMSetUp_Stag_1d; break;
482 case 2: dm->ops->setup = DMSetUp_Stag_2d; break;
483 case 3: dm->ops->setup = DMSetUp_Stag_3d; break;
484 default : SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Unsupported dimension %d",dim);
485 }
486 dm->ops->clone = DMClone_Stag;
487 dm->ops->view = DMView_Stag;
488 dm->ops->getcompatibility = DMGetCompatibility_Stag;
489 PetscFunctionReturn(0);
490 }
491