1 #include <petsc/private/dmforestimpl.h> /*I "petscdmforest.h" I*/
2 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/
3 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/
4 #include <petscsf.h>
5
6 PetscBool DMForestPackageInitialized = PETSC_FALSE;
7
8 typedef struct _DMForestTypeLink*DMForestTypeLink;
9
10 struct _DMForestTypeLink
11 {
12 char *name;
13 DMForestTypeLink next;
14 };
15
16 DMForestTypeLink DMForestTypeList;
17
DMForestPackageFinalize(void)18 static PetscErrorCode DMForestPackageFinalize(void)
19 {
20 DMForestTypeLink oldLink, link = DMForestTypeList;
21 PetscErrorCode ierr;
22
23 PetscFunctionBegin;
24 while (link) {
25 oldLink = link;
26 ierr = PetscFree(oldLink->name);CHKERRQ(ierr);
27 link = oldLink->next;
28 ierr = PetscFree(oldLink);CHKERRQ(ierr);
29 }
30 PetscFunctionReturn(0);
31 }
32
DMForestPackageInitialize(void)33 static PetscErrorCode DMForestPackageInitialize(void)
34 {
35 PetscErrorCode ierr;
36
37 PetscFunctionBegin;
38 if (DMForestPackageInitialized) PetscFunctionReturn(0);
39 DMForestPackageInitialized = PETSC_TRUE;
40
41 ierr = DMForestRegisterType(DMFOREST);CHKERRQ(ierr);
42 ierr = PetscRegisterFinalize(DMForestPackageFinalize);CHKERRQ(ierr);
43 PetscFunctionReturn(0);
44 }
45
46 /*@C
47 DMForestRegisterType - Registers a DMType as a subtype of DMFOREST (so that DMIsForest() will be correct)
48
49 Not Collective
50
51 Input parameter:
52 . name - the name of the type
53
54 Level: advanced
55
56 .seealso: DMFOREST, DMIsForest()
57 @*/
DMForestRegisterType(DMType name)58 PetscErrorCode DMForestRegisterType(DMType name)
59 {
60 DMForestTypeLink link;
61 PetscErrorCode ierr;
62
63 PetscFunctionBegin;
64 ierr = DMForestPackageInitialize();CHKERRQ(ierr);
65 ierr = PetscNew(&link);CHKERRQ(ierr);
66 ierr = PetscStrallocpy(name,&link->name);CHKERRQ(ierr);
67 link->next = DMForestTypeList;
68 DMForestTypeList = link;
69 PetscFunctionReturn(0);
70 }
71
72 /*@
73 DMIsForest - Check whether a DM uses the DMFOREST interface for hierarchically-refined meshes
74
75 Not Collective
76
77 Input parameter:
78 . dm - the DM object
79
80 Output parameter:
81 . isForest - whether dm is a subtype of DMFOREST
82
83 Level: intermediate
84
85 .seealso: DMFOREST, DMForestRegisterType()
86 @*/
DMIsForest(DM dm,PetscBool * isForest)87 PetscErrorCode DMIsForest(DM dm, PetscBool *isForest)
88 {
89 DMForestTypeLink link = DMForestTypeList;
90 PetscErrorCode ierr;
91
92 PetscFunctionBegin;
93 while (link) {
94 PetscBool sameType;
95 ierr = PetscObjectTypeCompare((PetscObject)dm,link->name,&sameType);CHKERRQ(ierr);
96 if (sameType) {
97 *isForest = PETSC_TRUE;
98 PetscFunctionReturn(0);
99 }
100 link = link->next;
101 }
102 *isForest = PETSC_FALSE;
103 PetscFunctionReturn(0);
104 }
105
106 /*@
107 DMForestTemplate - Create a new DM that will be adapted from a source DM. The new DM reproduces the configuration
108 of the source, but is not yet setup, so that the user can then define only the ways that the new DM should differ
109 (by, e.g., refinement or repartitioning). The source DM is also set as the adaptivity source DM of the new DM (see
110 DMForestSetAdaptivityForest()).
111
112 Collective on dm
113
114 Input Parameters:
115 + dm - the source DM object
116 - comm - the communicator for the new DM (this communicator is currently ignored, but is present so that DMForestTemplate() can be used within DMCoarsen())
117
118 Output Parameter:
119 . tdm - the new DM object
120
121 Level: intermediate
122
123 .seealso: DMForestSetAdaptivityForest()
124 @*/
DMForestTemplate(DM dm,MPI_Comm comm,DM * tdm)125 PetscErrorCode DMForestTemplate(DM dm, MPI_Comm comm, DM *tdm)
126 {
127 DM_Forest *forest = (DM_Forest*) dm->data;
128 DMType type;
129 DM base;
130 DMForestTopology topology;
131 MatType mtype;
132 PetscInt dim, overlap, ref, factor;
133 DMForestAdaptivityStrategy strat;
134 void *ctx;
135 PetscErrorCode (*map)(DM, PetscInt, PetscInt, const PetscReal[], PetscReal[], void*);
136 void *mapCtx;
137 PetscErrorCode ierr;
138
139 PetscFunctionBegin;
140 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
141 ierr = DMCreate(PetscObjectComm((PetscObject)dm),tdm);CHKERRQ(ierr);
142 ierr = DMGetType(dm,&type);CHKERRQ(ierr);
143 ierr = DMSetType(*tdm,type);CHKERRQ(ierr);
144 ierr = DMForestGetBaseDM(dm,&base);CHKERRQ(ierr);
145 ierr = DMForestSetBaseDM(*tdm,base);CHKERRQ(ierr);
146 ierr = DMForestGetTopology(dm,&topology);CHKERRQ(ierr);
147 ierr = DMForestSetTopology(*tdm,topology);CHKERRQ(ierr);
148 ierr = DMForestGetAdjacencyDimension(dm,&dim);CHKERRQ(ierr);
149 ierr = DMForestSetAdjacencyDimension(*tdm,dim);CHKERRQ(ierr);
150 ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr);
151 ierr = DMForestSetPartitionOverlap(*tdm,overlap);CHKERRQ(ierr);
152 ierr = DMForestGetMinimumRefinement(dm,&ref);CHKERRQ(ierr);
153 ierr = DMForestSetMinimumRefinement(*tdm,ref);CHKERRQ(ierr);
154 ierr = DMForestGetMaximumRefinement(dm,&ref);CHKERRQ(ierr);
155 ierr = DMForestSetMaximumRefinement(*tdm,ref);CHKERRQ(ierr);
156 ierr = DMForestGetAdaptivityStrategy(dm,&strat);CHKERRQ(ierr);
157 ierr = DMForestSetAdaptivityStrategy(*tdm,strat);CHKERRQ(ierr);
158 ierr = DMForestGetGradeFactor(dm,&factor);CHKERRQ(ierr);
159 ierr = DMForestSetGradeFactor(*tdm,factor);CHKERRQ(ierr);
160 ierr = DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx);CHKERRQ(ierr);
161 ierr = DMForestSetBaseCoordinateMapping(*tdm,map,mapCtx);CHKERRQ(ierr);
162 if (forest->ftemplate) {
163 ierr = (*forest->ftemplate)(dm, *tdm);CHKERRQ(ierr);
164 }
165 ierr = DMForestSetAdaptivityForest(*tdm,dm);CHKERRQ(ierr);
166 ierr = DMCopyDisc(dm,*tdm);CHKERRQ(ierr);
167 ierr = DMGetApplicationContext(dm,&ctx);CHKERRQ(ierr);
168 ierr = DMSetApplicationContext(*tdm,&ctx);CHKERRQ(ierr);
169 {
170 PetscBool isper;
171 const PetscReal *maxCell, *L;
172 const DMBoundaryType *bd;
173
174 ierr = DMGetPeriodicity(dm,&isper,&maxCell,&L,&bd);CHKERRQ(ierr);
175 ierr = DMSetPeriodicity(*tdm,isper,maxCell,L,bd);CHKERRQ(ierr);
176 }
177 ierr = DMCopyBoundary(dm,*tdm);CHKERRQ(ierr);
178 ierr = DMGetMatType(dm,&mtype);CHKERRQ(ierr);
179 ierr = DMSetMatType(*tdm,mtype);CHKERRQ(ierr);
180 PetscFunctionReturn(0);
181 }
182
183 static PetscErrorCode DMInitialize_Forest(DM dm);
184
DMClone_Forest(DM dm,DM * newdm)185 PETSC_EXTERN PetscErrorCode DMClone_Forest(DM dm, DM *newdm)
186 {
187 DM_Forest *forest = (DM_Forest*) dm->data;
188 const char *type;
189 PetscErrorCode ierr;
190
191 PetscFunctionBegin;
192 forest->refct++;
193 (*newdm)->data = forest;
194 ierr = PetscObjectGetType((PetscObject) dm, &type);CHKERRQ(ierr);
195 ierr = PetscObjectChangeTypeName((PetscObject) *newdm, type);CHKERRQ(ierr);
196 ierr = DMInitialize_Forest(*newdm);CHKERRQ(ierr);
197 PetscFunctionReturn(0);
198 }
199
DMDestroy_Forest(DM dm)200 static PetscErrorCode DMDestroy_Forest(DM dm)
201 {
202 DM_Forest *forest = (DM_Forest*) dm->data;
203 PetscErrorCode ierr;
204
205 PetscFunctionBegin;
206 if (--forest->refct > 0) PetscFunctionReturn(0);
207 if (forest->destroy) {ierr = (*forest->destroy)(dm);CHKERRQ(ierr);}
208 ierr = PetscSFDestroy(&forest->cellSF);CHKERRQ(ierr);
209 ierr = PetscSFDestroy(&forest->preCoarseToFine);CHKERRQ(ierr);
210 ierr = PetscSFDestroy(&forest->coarseToPreFine);CHKERRQ(ierr);
211 ierr = DMLabelDestroy(&forest->adaptLabel);CHKERRQ(ierr);
212 ierr = PetscFree(forest->adaptStrategy);CHKERRQ(ierr);
213 ierr = DMDestroy(&forest->base);CHKERRQ(ierr);
214 ierr = DMDestroy(&forest->adapt);CHKERRQ(ierr);
215 ierr = PetscFree(forest->topology);CHKERRQ(ierr);
216 ierr = PetscFree(forest);CHKERRQ(ierr);
217 PetscFunctionReturn(0);
218 }
219
220 /*@C
221 DMForestSetTopology - Set the topology of a DMForest during the pre-setup phase. The topology is a string (e.g.
222 "cube", "shell") and can be interpreted by subtypes of DMFOREST) to construct the base DM of a forest during
223 DMSetUp().
224
225 Logically collective on dm
226
227 Input parameters:
228 + dm - the forest
229 - topology - the topology of the forest
230
231 Level: intermediate
232
233 .seealso: DMForestGetTopology(), DMForestSetBaseDM()
234 @*/
DMForestSetTopology(DM dm,DMForestTopology topology)235 PetscErrorCode DMForestSetTopology(DM dm, DMForestTopology topology)
236 {
237 DM_Forest *forest = (DM_Forest*) dm->data;
238 PetscErrorCode ierr;
239
240 PetscFunctionBegin;
241 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
242 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the topology after setup");
243 ierr = PetscFree(forest->topology);CHKERRQ(ierr);
244 ierr = PetscStrallocpy((const char*)topology,(char**) &forest->topology);CHKERRQ(ierr);
245 PetscFunctionReturn(0);
246 }
247
248 /*@C
249 DMForestGetTopology - Get a string describing the topology of a DMForest.
250
251 Not collective
252
253 Input parameter:
254 . dm - the forest
255
256 Output parameter:
257 . topology - the topology of the forest (e.g., 'cube', 'shell')
258
259 Level: intermediate
260
261 .seealso: DMForestSetTopology()
262 @*/
DMForestGetTopology(DM dm,DMForestTopology * topology)263 PetscErrorCode DMForestGetTopology(DM dm, DMForestTopology *topology)
264 {
265 DM_Forest *forest = (DM_Forest*) dm->data;
266
267 PetscFunctionBegin;
268 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
269 PetscValidPointer(topology,2);
270 *topology = forest->topology;
271 PetscFunctionReturn(0);
272 }
273
274 /*@
275 DMForestSetBaseDM - During the pre-setup phase, set the DM that defines the base mesh of a DMForest forest. The
276 forest will be hierarchically refined from the base, and all refinements/coarsenings of the forest will share its
277 base. In general, two forest must share a base to be comparable, to do things like construct interpolators.
278
279 Logically collective on dm
280
281 Input Parameters:
282 + dm - the forest
283 - base - the base DM of the forest
284
285 Notes:
286 Currently the base DM must be a DMPLEX
287
288 Level: intermediate
289
290 .seealso: DMForestGetBaseDM()
291 @*/
DMForestSetBaseDM(DM dm,DM base)292 PetscErrorCode DMForestSetBaseDM(DM dm, DM base)
293 {
294 DM_Forest *forest = (DM_Forest*) dm->data;
295 PetscInt dim, dimEmbed;
296 PetscErrorCode ierr;
297
298 PetscFunctionBegin;
299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
300 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the base after setup");
301 ierr = PetscObjectReference((PetscObject)base);CHKERRQ(ierr);
302 ierr = DMDestroy(&forest->base);CHKERRQ(ierr);
303 forest->base = base;
304 if (base) {
305 PetscBool isper;
306 const PetscReal *maxCell, *L;
307 const DMBoundaryType *bd;
308
309 PetscValidHeaderSpecific(base, DM_CLASSID, 2);
310 ierr = DMGetDimension(base,&dim);CHKERRQ(ierr);
311 ierr = DMSetDimension(dm,dim);CHKERRQ(ierr);
312 ierr = DMGetCoordinateDim(base,&dimEmbed);CHKERRQ(ierr);
313 ierr = DMSetCoordinateDim(dm,dimEmbed);CHKERRQ(ierr);
314 ierr = DMGetPeriodicity(base,&isper,&maxCell,&L,&bd);CHKERRQ(ierr);
315 ierr = DMSetPeriodicity(dm,isper,maxCell,L,bd);CHKERRQ(ierr);
316 } else {
317 ierr = DMSetPeriodicity(dm,PETSC_FALSE,NULL,NULL,NULL);CHKERRQ(ierr);
318 }
319 PetscFunctionReturn(0);
320 }
321
322 /*@
323 DMForestGetBaseDM - Get the base DM of a DMForest forest. The forest will be hierarchically refined from the base,
324 and all refinements/coarsenings of the forest will share its base. In general, two forest must share a base to be
325 comparable, to do things like construct interpolators.
326
327 Not collective
328
329 Input Parameter:
330 . dm - the forest
331
332 Output Parameter:
333 . base - the base DM of the forest
334
335 Notes:
336 After DMSetUp(), the base DM will be redundantly distributed across MPI processes
337
338 Level: intermediate
339
340 .seealso: DMForestSetBaseDM()
341 @*/
DMForestGetBaseDM(DM dm,DM * base)342 PetscErrorCode DMForestGetBaseDM(DM dm, DM *base)
343 {
344 DM_Forest *forest = (DM_Forest*) dm->data;
345
346 PetscFunctionBegin;
347 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
348 PetscValidPointer(base, 2);
349 *base = forest->base;
350 PetscFunctionReturn(0);
351 }
352
DMForestSetBaseCoordinateMapping(DM dm,PetscErrorCode (* func)(DM,PetscInt,PetscInt,const PetscReal[],PetscReal[],void *),void * ctx)353 PetscErrorCode DMForestSetBaseCoordinateMapping(DM dm, PetscErrorCode (*func)(DM,PetscInt,PetscInt,const PetscReal [],PetscReal [],void*),void *ctx)
354 {
355 DM_Forest *forest = (DM_Forest*) dm->data;
356
357 PetscFunctionBegin;
358 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
359 forest->mapcoordinates = func;
360 forest->mapcoordinatesctx = ctx;
361 PetscFunctionReturn(0);
362 }
363
DMForestGetBaseCoordinateMapping(DM dm,PetscErrorCode (** func)(DM,PetscInt,PetscInt,const PetscReal[],PetscReal[],void *),void * ctx)364 PetscErrorCode DMForestGetBaseCoordinateMapping(DM dm, PetscErrorCode (**func) (DM,PetscInt,PetscInt,const PetscReal [],PetscReal [],void*),void *ctx)
365 {
366 DM_Forest *forest = (DM_Forest*) dm->data;
367
368 PetscFunctionBegin;
369 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
370 if (func) *func = forest->mapcoordinates;
371 if (ctx) *((void**) ctx) = forest->mapcoordinatesctx;
372 PetscFunctionReturn(0);
373 }
374
375 /*@
376 DMForestSetAdaptivityForest - During the pre-setup phase, set the forest from which the current forest will be
377 adapted (e.g., the current forest will be refined/coarsened/repartitioned from it) im DMSetUp(). Usually not needed
378 by users directly: DMForestTemplate() constructs a new forest to be adapted from an old forest and calls this
379 routine.
380
381 Note that this can be called after setup with adapt = NULL, which will clear all internal data related to the
382 adaptivity forest from dm. This way, repeatedly adapting does not leave stale DM objects in memory.
383
384 Logically collective on dm
385
386 Input Parameter:
387 + dm - the new forest, which will be constructed from adapt
388 - adapt - the old forest
389
390 Level: intermediate
391
392 .seealso: DMForestGetAdaptivityForest(), DMForestSetAdaptivityPurpose()
393 @*/
DMForestSetAdaptivityForest(DM dm,DM adapt)394 PetscErrorCode DMForestSetAdaptivityForest(DM dm,DM adapt)
395 {
396 DM_Forest *forest, *adaptForest, *oldAdaptForest;
397 DM oldAdapt;
398 PetscBool isForest;
399 PetscErrorCode ierr;
400
401 PetscFunctionBegin;
402 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
403 if (adapt) PetscValidHeaderSpecific(adapt, DM_CLASSID, 2);
404 ierr = DMIsForest(dm, &isForest);CHKERRQ(ierr);
405 if (!isForest) PetscFunctionReturn(0);
406 if (adapt != NULL && dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the adaptation forest after setup");
407 forest = (DM_Forest*) dm->data;
408 ierr = DMForestGetAdaptivityForest(dm,&oldAdapt);CHKERRQ(ierr);
409 adaptForest = (DM_Forest*) (adapt ? adapt->data : NULL);
410 oldAdaptForest = (DM_Forest*) (oldAdapt ? oldAdapt->data : NULL);
411 if (adaptForest != oldAdaptForest) {
412 ierr = PetscSFDestroy(&forest->preCoarseToFine);CHKERRQ(ierr);
413 ierr = PetscSFDestroy(&forest->coarseToPreFine);CHKERRQ(ierr);
414 if (forest->clearadaptivityforest) {ierr = (*forest->clearadaptivityforest)(dm);CHKERRQ(ierr);}
415 }
416 switch (forest->adaptPurpose) {
417 case DM_ADAPT_DETERMINE:
418 ierr = PetscObjectReference((PetscObject)adapt);CHKERRQ(ierr);
419 ierr = DMDestroy(&(forest->adapt));CHKERRQ(ierr);
420 forest->adapt = adapt;
421 break;
422 case DM_ADAPT_REFINE:
423 ierr = DMSetCoarseDM(dm,adapt);CHKERRQ(ierr);
424 break;
425 case DM_ADAPT_COARSEN:
426 case DM_ADAPT_COARSEN_LAST:
427 ierr = DMSetFineDM(dm,adapt);CHKERRQ(ierr);
428 break;
429 default:
430 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid adaptivity purpose");
431 }
432 PetscFunctionReturn(0);
433 }
434
435 /*@
436 DMForestGetAdaptivityForest - Get the forest from which the current forest is adapted.
437
438 Not collective
439
440 Input Parameter:
441 . dm - the forest
442
443 Output Parameter:
444 . adapt - the forest from which dm is/was adapted
445
446 Level: intermediate
447
448 .seealso: DMForestSetAdaptivityForest(), DMForestSetAdaptivityPurpose()
449 @*/
DMForestGetAdaptivityForest(DM dm,DM * adapt)450 PetscErrorCode DMForestGetAdaptivityForest(DM dm, DM *adapt)
451 {
452 DM_Forest *forest;
453 PetscErrorCode ierr;
454
455 PetscFunctionBegin;
456 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
457 forest = (DM_Forest*) dm->data;
458 switch (forest->adaptPurpose) {
459 case DM_ADAPT_DETERMINE:
460 *adapt = forest->adapt;
461 break;
462 case DM_ADAPT_REFINE:
463 ierr = DMGetCoarseDM(dm,adapt);CHKERRQ(ierr);
464 break;
465 case DM_ADAPT_COARSEN:
466 case DM_ADAPT_COARSEN_LAST:
467 ierr = DMGetFineDM(dm,adapt);CHKERRQ(ierr);
468 break;
469 default:
470 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"invalid adaptivity purpose");
471 }
472 PetscFunctionReturn(0);
473 }
474
475 /*@
476 DMForestSetAdaptivityPurpose - During the pre-setup phase, set whether the current DM is being adapted from its
477 source (set with DMForestSetAdaptivityForest()) for the purpose of refinement (DM_ADAPT_REFINE), coarsening
478 (DM_ADAPT_COARSEN), or undefined (DM_ADAPT_DETERMINE). This only matters for the purposes of reference counting:
479 during DMDestroy(), cyclic references can be found between DMs only if the cyclic reference is due to a fine/coarse
480 relationship (see DMSetFineDM()/DMSetCoarseDM()). If the purpose is not refinement or coarsening, and the user does
481 not maintain a reference to the post-adaptation forest (i.e., the one created by DMForestTemplate()), then this can
482 cause a memory leak. This method is used by subtypes of DMForest when automatically constructing mesh hierarchies.
483
484 Logically collective on dm
485
486 Input Parameters:
487 + dm - the forest
488 - purpose - the adaptivity purpose
489
490 Level: advanced
491
492 .seealso: DMForestTemplate(), DMForestSetAdaptivityForest(), DMForestGetAdaptivityForest(), DMAdaptFlag
493 @*/
DMForestSetAdaptivityPurpose(DM dm,DMAdaptFlag purpose)494 PetscErrorCode DMForestSetAdaptivityPurpose(DM dm, DMAdaptFlag purpose)
495 {
496 DM_Forest *forest;
497 PetscErrorCode ierr;
498
499 PetscFunctionBegin;
500 forest = (DM_Forest*) dm->data;
501 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the adaptation forest after setup");
502 if (purpose != forest->adaptPurpose) {
503 DM adapt;
504
505 ierr = DMForestGetAdaptivityForest(dm,&adapt);CHKERRQ(ierr);
506 ierr = PetscObjectReference((PetscObject)adapt);CHKERRQ(ierr);
507 ierr = DMForestSetAdaptivityForest(dm,NULL);CHKERRQ(ierr);
508
509 forest->adaptPurpose = purpose;
510
511 ierr = DMForestSetAdaptivityForest(dm,adapt);CHKERRQ(ierr);
512 ierr = DMDestroy(&adapt);CHKERRQ(ierr);
513 }
514 PetscFunctionReturn(0);
515 }
516
517 /*@
518 DMForestGetAdaptivityPurpose - Get whether the current DM is being adapted from its source (set with
519 DMForestSetAdaptivityForest()) for the purpose of refinement (DM_ADAPT_REFINE), coarsening (DM_ADAPT_COARSEN),
520 coarsening only the last level (DM_ADAPT_COARSEN_LAST) or undefined (DM_ADAPT_DETERMINE).
521 This only matters for the purposes of reference counting: during DMDestroy(), cyclic
522 references can be found between DMs only if the cyclic reference is due to a fine/coarse relationship (see
523 DMSetFineDM()/DMSetCoarseDM()). If the purpose is not refinement or coarsening, and the user does not maintain a
524 reference to the post-adaptation forest (i.e., the one created by DMForestTemplate()), then this can cause a memory
525 leak. This method is used by subtypes of DMForest when automatically constructing mesh hierarchies.
526
527 Not collective
528
529 Input Parameter:
530 . dm - the forest
531
532 Output Parameter:
533 . purpose - the adaptivity purpose
534
535 Level: advanced
536
537 .seealso: DMForestTemplate(), DMForestSetAdaptivityForest(), DMForestGetAdaptivityForest(), DMAdaptFlag
538 @*/
DMForestGetAdaptivityPurpose(DM dm,DMAdaptFlag * purpose)539 PetscErrorCode DMForestGetAdaptivityPurpose(DM dm, DMAdaptFlag *purpose)
540 {
541 DM_Forest *forest;
542
543 PetscFunctionBegin;
544 forest = (DM_Forest*) dm->data;
545 *purpose = forest->adaptPurpose;
546 PetscFunctionReturn(0);
547 }
548
549 /*@
550 DMForestSetAdjacencyDimension - During the pre-setup phase, set the dimension of interface points that determine
551 cell adjacency (for the purposes of partitioning and overlap).
552
553 Logically collective on dm
554
555 Input Parameters:
556 + dm - the forest
557 - adjDim - default 0 (i.e., vertices determine adjacency)
558
559 Level: intermediate
560
561 .seealso: DMForestGetAdjacencyDimension(), DMForestSetAdjacencyCodimension(), DMForestSetPartitionOverlap()
562 @*/
DMForestSetAdjacencyDimension(DM dm,PetscInt adjDim)563 PetscErrorCode DMForestSetAdjacencyDimension(DM dm, PetscInt adjDim)
564 {
565 PetscInt dim;
566 DM_Forest *forest = (DM_Forest*) dm->data;
567 PetscErrorCode ierr;
568
569 PetscFunctionBegin;
570 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
571 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the adjacency dimension after setup");
572 if (adjDim < 0) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"adjacency dim cannot be < 0: %d", adjDim);
573 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
574 if (adjDim > dim) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"adjacency dim cannot be > %d: %d", dim, adjDim);
575 forest->adjDim = adjDim;
576 PetscFunctionReturn(0);
577 }
578
579 /*@
580 DMForestSetAdjacencyCodimension - Like DMForestSetAdjacencyDimension(), but specified as a co-dimension (so that,
581 e.g., adjacency based on facets can be specified by codimension 1 in all cases)
582
583 Logically collective on dm
584
585 Input Parameters:
586 + dm - the forest
587 - adjCodim - default isthe dimension of the forest (see DMGetDimension()), since this is the codimension of vertices
588
589 Level: intermediate
590
591 .seealso: DMForestGetAdjacencyCodimension(), DMForestSetAdjacencyDimension()
592 @*/
DMForestSetAdjacencyCodimension(DM dm,PetscInt adjCodim)593 PetscErrorCode DMForestSetAdjacencyCodimension(DM dm, PetscInt adjCodim)
594 {
595 PetscInt dim;
596 PetscErrorCode ierr;
597
598 PetscFunctionBegin;
599 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
600 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
601 ierr = DMForestSetAdjacencyDimension(dm,dim-adjCodim);CHKERRQ(ierr);
602 PetscFunctionReturn(0);
603 }
604
605 /*@
606 DMForestGetAdjacencyDimension - Get the dimension of interface points that determine cell adjacency (for the
607 purposes of partitioning and overlap).
608
609 Not collective
610
611 Input Parameter:
612 . dm - the forest
613
614 Output Parameter:
615 . adjDim - default 0 (i.e., vertices determine adjacency)
616
617 Level: intermediate
618
619 .seealso: DMForestSetAdjacencyDimension(), DMForestGetAdjacencyCodimension(), DMForestSetPartitionOverlap()
620 @*/
DMForestGetAdjacencyDimension(DM dm,PetscInt * adjDim)621 PetscErrorCode DMForestGetAdjacencyDimension(DM dm, PetscInt *adjDim)
622 {
623 DM_Forest *forest = (DM_Forest*) dm->data;
624
625 PetscFunctionBegin;
626 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
627 PetscValidIntPointer(adjDim,2);
628 *adjDim = forest->adjDim;
629 PetscFunctionReturn(0);
630 }
631
632 /*@
633 DMForestGetAdjacencyCodimension - Like DMForestGetAdjacencyDimension(), but specified as a co-dimension (so that,
634 e.g., adjacency based on facets can be specified by codimension 1 in all cases)
635
636 Not collective
637
638 Input Parameter:
639 . dm - the forest
640
641 Output Parameter:
642 . adjCodim - default isthe dimension of the forest (see DMGetDimension()), since this is the codimension of vertices
643
644 Level: intermediate
645
646 .seealso: DMForestSetAdjacencyCodimension(), DMForestGetAdjacencyDimension()
647 @*/
DMForestGetAdjacencyCodimension(DM dm,PetscInt * adjCodim)648 PetscErrorCode DMForestGetAdjacencyCodimension(DM dm, PetscInt *adjCodim)
649 {
650 DM_Forest *forest = (DM_Forest*) dm->data;
651 PetscInt dim;
652 PetscErrorCode ierr;
653
654 PetscFunctionBegin;
655 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
656 PetscValidIntPointer(adjCodim,2);
657 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
658 *adjCodim = dim - forest->adjDim;
659 PetscFunctionReturn(0);
660 }
661
662 /*@
663 DMForestSetPartitionOverlap - During the pre-setup phase, set the amount of cell-overlap present in parallel
664 partitions of a forest, with values > 0 indicating subdomains that are expanded by that many iterations of adding
665 adjacent cells
666
667 Logically collective on dm
668
669 Input Parameters:
670 + dm - the forest
671 - overlap - default 0
672
673 Level: intermediate
674
675 .seealso: DMForestGetPartitionOverlap(), DMForestSetAdjacencyDimension(), DMForestSetAdjacencyCodimension()
676 @*/
DMForestSetPartitionOverlap(DM dm,PetscInt overlap)677 PetscErrorCode DMForestSetPartitionOverlap(DM dm, PetscInt overlap)
678 {
679 DM_Forest *forest = (DM_Forest*) dm->data;
680
681 PetscFunctionBegin;
682 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
683 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the overlap after setup");
684 if (overlap < 0) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"overlap cannot be < 0: %d", overlap);
685 forest->overlap = overlap;
686 PetscFunctionReturn(0);
687 }
688
689 /*@
690 DMForestGetPartitionOverlap - Get the amount of cell-overlap present in parallel partitions of a forest, with values
691 > 0 indicating subdomains that are expanded by that many iterations of adding adjacent cells
692
693 Not collective
694
695 Input Parameter:
696 . dm - the forest
697
698 Output Parameter:
699 . overlap - default 0
700
701 Level: intermediate
702
703 .seealso: DMForestGetPartitionOverlap(), DMForestSetAdjacencyDimension(), DMForestSetAdjacencyCodimension()
704 @*/
DMForestGetPartitionOverlap(DM dm,PetscInt * overlap)705 PetscErrorCode DMForestGetPartitionOverlap(DM dm, PetscInt *overlap)
706 {
707 DM_Forest *forest = (DM_Forest*) dm->data;
708
709 PetscFunctionBegin;
710 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
711 PetscValidIntPointer(overlap,2);
712 *overlap = forest->overlap;
713 PetscFunctionReturn(0);
714 }
715
716 /*@
717 DMForestSetMinimumRefinement - During the pre-setup phase, set the minimum level of refinement (relative to the base
718 DM, see DMForestGetBaseDM()) allowed in the forest. If the forest is being created by coarsening a previous forest
719 (see DMForestGetAdaptivityForest()) this limits the amount of coarsening.
720
721 Logically collective on dm
722
723 Input Parameters:
724 + dm - the forest
725 - minRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
726
727 Level: intermediate
728
729 .seealso: DMForestGetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestSetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest()
730 @*/
DMForestSetMinimumRefinement(DM dm,PetscInt minRefinement)731 PetscErrorCode DMForestSetMinimumRefinement(DM dm, PetscInt minRefinement)
732 {
733 DM_Forest *forest = (DM_Forest*) dm->data;
734
735 PetscFunctionBegin;
736 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
737 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the minimum refinement after setup");
738 forest->minRefinement = minRefinement;
739 PetscFunctionReturn(0);
740 }
741
742 /*@
743 DMForestGetMinimumRefinement - Get the minimum level of refinement (relative to the base DM, see
744 DMForestGetBaseDM()) allowed in the forest. If the forest is being created by coarsening a previous forest (see
745 DMForestGetAdaptivityForest()), this limits the amount of coarsening.
746
747 Not collective
748
749 Input Parameter:
750 . dm - the forest
751
752 Output Parameter:
753 . minRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
754
755 Level: intermediate
756
757 .seealso: DMForestSetMinimumRefinement(), DMForestGetMaximumRefinement(), DMForestGetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest()
758 @*/
DMForestGetMinimumRefinement(DM dm,PetscInt * minRefinement)759 PetscErrorCode DMForestGetMinimumRefinement(DM dm, PetscInt *minRefinement)
760 {
761 DM_Forest *forest = (DM_Forest*) dm->data;
762
763 PetscFunctionBegin;
764 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
765 PetscValidIntPointer(minRefinement,2);
766 *minRefinement = forest->minRefinement;
767 PetscFunctionReturn(0);
768 }
769
770 /*@
771 DMForestSetInitialRefinement - During the pre-setup phase, set the initial level of refinement (relative to the base
772 DM, see DMForestGetBaseDM()) allowed in the forest.
773
774 Logically collective on dm
775
776 Input Parameters:
777 + dm - the forest
778 - initefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
779
780 Level: intermediate
781
782 .seealso: DMForestSetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestGetBaseDM()
783 @*/
DMForestSetInitialRefinement(DM dm,PetscInt initRefinement)784 PetscErrorCode DMForestSetInitialRefinement(DM dm, PetscInt initRefinement)
785 {
786 DM_Forest *forest = (DM_Forest*) dm->data;
787
788 PetscFunctionBegin;
789 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
790 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the initial refinement after setup");
791 forest->initRefinement = initRefinement;
792 PetscFunctionReturn(0);
793 }
794
795 /*@
796 DMForestGetInitialRefinement - Get the initial level of refinement (relative to the base DM, see
797 DMForestGetBaseDM()) allowed in the forest.
798
799 Not collective
800
801 Input Parameter:
802 . dm - the forest
803
804 Output Paramater:
805 . initRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
806
807 Level: intermediate
808
809 .seealso: DMForestSetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestGetBaseDM()
810 @*/
DMForestGetInitialRefinement(DM dm,PetscInt * initRefinement)811 PetscErrorCode DMForestGetInitialRefinement(DM dm, PetscInt *initRefinement)
812 {
813 DM_Forest *forest = (DM_Forest*) dm->data;
814
815 PetscFunctionBegin;
816 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
817 PetscValidIntPointer(initRefinement,2);
818 *initRefinement = forest->initRefinement;
819 PetscFunctionReturn(0);
820 }
821
822 /*@
823 DMForestSetMaximumRefinement - During the pre-setup phase, set the maximum level of refinement (relative to the base
824 DM, see DMForestGetBaseDM()) allowed in the forest. If the forest is being created by refining a previous forest
825 (see DMForestGetAdaptivityForest()), this limits the amount of refinement.
826
827 Logically collective on dm
828
829 Input Parameters:
830 + dm - the forest
831 - maxRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
832
833 Level: intermediate
834
835 .seealso: DMForestGetMinimumRefinement(), DMForestSetMaximumRefinement(), DMForestSetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityDM()
836 @*/
DMForestSetMaximumRefinement(DM dm,PetscInt maxRefinement)837 PetscErrorCode DMForestSetMaximumRefinement(DM dm, PetscInt maxRefinement)
838 {
839 DM_Forest *forest = (DM_Forest*) dm->data;
840
841 PetscFunctionBegin;
842 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
843 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the maximum refinement after setup");
844 forest->maxRefinement = maxRefinement;
845 PetscFunctionReturn(0);
846 }
847
848 /*@
849 DMForestGetMaximumRefinement - Get the maximum level of refinement (relative to the base DM, see
850 DMForestGetBaseDM()) allowed in the forest. If the forest is being created by refining a previous forest (see
851 DMForestGetAdaptivityForest()), this limits the amount of refinement.
852
853 Not collective
854
855 Input Parameter:
856 . dm - the forest
857
858 Output Parameter:
859 . maxRefinement - default PETSC_DEFAULT (interpreted by the subtype of DMForest)
860
861 Level: intermediate
862
863 .seealso: DMForestSetMaximumRefinement(), DMForestGetMinimumRefinement(), DMForestGetInitialRefinement(), DMForestGetBaseDM(), DMForestGetAdaptivityForest()
864 @*/
DMForestGetMaximumRefinement(DM dm,PetscInt * maxRefinement)865 PetscErrorCode DMForestGetMaximumRefinement(DM dm, PetscInt *maxRefinement)
866 {
867 DM_Forest *forest = (DM_Forest*) dm->data;
868
869 PetscFunctionBegin;
870 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
871 PetscValidIntPointer(maxRefinement,2);
872 *maxRefinement = forest->maxRefinement;
873 PetscFunctionReturn(0);
874 }
875
876 /*@C
877 DMForestSetAdaptivityStrategy - During the pre-setup phase, set the strategy for combining adaptivity labels from multiple processes.
878 Subtypes of DMForest may define their own strategies. Two default strategies are DMFORESTADAPTALL, which indicates that all processes must agree
879 for a refinement/coarsening flag to be valid, and DMFORESTADAPTANY, which indicates that only one process needs to
880 specify refinement/coarsening.
881
882 Logically collective on dm
883
884 Input Parameters:
885 + dm - the forest
886 - adaptStrategy - default DMFORESTADAPTALL
887
888 Level: advanced
889
890 .seealso: DMForestGetAdaptivityStrategy()
891 @*/
DMForestSetAdaptivityStrategy(DM dm,DMForestAdaptivityStrategy adaptStrategy)892 PetscErrorCode DMForestSetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy adaptStrategy)
893 {
894 DM_Forest *forest = (DM_Forest*) dm->data;
895 PetscErrorCode ierr;
896
897 PetscFunctionBegin;
898 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
899 ierr = PetscFree(forest->adaptStrategy);CHKERRQ(ierr);
900 ierr = PetscStrallocpy((const char*) adaptStrategy,(char**)&forest->adaptStrategy);CHKERRQ(ierr);
901 PetscFunctionReturn(0);
902 }
903
904 /*@C
905 DMForestSetAdaptivityStrategy - Get the strategy for combining adaptivity labels from multiple processes. Subtypes
906 of DMForest may define their own strategies. Two default strategies are DMFORESTADAPTALL, which indicates that all
907 processes must agree for a refinement/coarsening flag to be valid, and DMFORESTADAPTANY, which indicates that only
908 one process needs to specify refinement/coarsening.
909
910 Not collective
911
912 Input Parameter:
913 . dm - the forest
914
915 Output Parameter:
916 . adaptStrategy - the adaptivity strategy (default DMFORESTADAPTALL)
917
918 Level: advanced
919
920 .seealso: DMForestSetAdaptivityStrategy()
921 @*/
DMForestGetAdaptivityStrategy(DM dm,DMForestAdaptivityStrategy * adaptStrategy)922 PetscErrorCode DMForestGetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy *adaptStrategy)
923 {
924 DM_Forest *forest = (DM_Forest*) dm->data;
925
926 PetscFunctionBegin;
927 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
928 PetscValidPointer(adaptStrategy,2);
929 *adaptStrategy = forest->adaptStrategy;
930 PetscFunctionReturn(0);
931 }
932
933 /*@
934 DMForestGetAdaptivitySuccess - Return whether the requested adaptation (refinement, coarsening, repartitioning,
935 etc.) was successful. PETSC_FALSE indicates that the post-adaptation forest is the same as the pre-adpatation
936 forest. A requested adaptation may have been unsuccessful if, for example, the requested refinement would have
937 exceeded the maximum refinement level.
938
939 Collective on dm
940
941 Input Parameter:
942
943 . dm - the post-adaptation forest
944
945 Output Parameter:
946
947 . success - PETSC_TRUE if the post-adaptation forest is different from the pre-adaptation forest.
948
949 Level: intermediate
950
951 .see
952 @*/
DMForestGetAdaptivitySuccess(DM dm,PetscBool * success)953 PetscErrorCode DMForestGetAdaptivitySuccess(DM dm, PetscBool *success)
954 {
955 DM_Forest *forest;
956 PetscErrorCode ierr;
957
958 PetscFunctionBegin;
959 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
960 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"DMSetUp() has not been called yet.");
961 forest = (DM_Forest *) dm->data;
962 ierr = (forest->getadaptivitysuccess)(dm,success);CHKERRQ(ierr);
963 PetscFunctionReturn(0);
964 }
965
966 /*@
967 DMForestSetComputeAdaptivitySF - During the pre-setup phase, set whether transfer PetscSFs should be computed
968 relating the cells of the pre-adaptation forest to the post-adaptiation forest. After DMSetUp() is called, these transfer PetscSFs can be accessed with DMForestGetAdaptivitySF().
969
970 Logically collective on dm
971
972 Input Parameters:
973 + dm - the post-adaptation forest
974 - computeSF - default PETSC_TRUE
975
976 Level: advanced
977
978 .seealso: DMForestGetComputeAdaptivitySF(), DMForestGetAdaptivitySF()
979 @*/
DMForestSetComputeAdaptivitySF(DM dm,PetscBool computeSF)980 PetscErrorCode DMForestSetComputeAdaptivitySF(DM dm, PetscBool computeSF)
981 {
982 DM_Forest *forest;
983
984 PetscFunctionBegin;
985 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
986 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot compute adaptivity PetscSFs after setup is called");
987 forest = (DM_Forest*) dm->data;
988 forest->computeAdaptSF = computeSF;
989 PetscFunctionReturn(0);
990 }
991
DMForestTransferVec(DM dmIn,Vec vecIn,DM dmOut,Vec vecOut,PetscBool useBCs,PetscReal time)992 PetscErrorCode DMForestTransferVec(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscBool useBCs, PetscReal time)
993 {
994 DM_Forest *forest;
995 PetscErrorCode ierr;
996
997 PetscFunctionBegin;
998 PetscValidHeaderSpecific(dmIn ,DM_CLASSID ,1);
999 PetscValidHeaderSpecific(vecIn ,VEC_CLASSID ,2);
1000 PetscValidHeaderSpecific(dmOut ,DM_CLASSID ,3);
1001 PetscValidHeaderSpecific(vecOut ,VEC_CLASSID ,4);
1002 forest = (DM_Forest *) dmIn->data;
1003 if (!forest->transfervec) SETERRQ(PetscObjectComm((PetscObject)dmIn),PETSC_ERR_SUP,"DMForestTransferVec() not implemented");
1004 ierr = (forest->transfervec)(dmIn,vecIn,dmOut,vecOut,useBCs,time);CHKERRQ(ierr);
1005 PetscFunctionReturn(0);
1006 }
1007
DMForestTransferVecFromBase(DM dm,Vec vecIn,Vec vecOut)1008 PetscErrorCode DMForestTransferVecFromBase(DM dm, Vec vecIn, Vec vecOut)
1009 {
1010 DM_Forest *forest;
1011 PetscErrorCode ierr;
1012
1013 PetscFunctionBegin;
1014 PetscValidHeaderSpecific(dm ,DM_CLASSID ,1);
1015 PetscValidHeaderSpecific(vecIn ,VEC_CLASSID ,2);
1016 PetscValidHeaderSpecific(vecOut ,VEC_CLASSID ,3);
1017 forest = (DM_Forest *) dm->data;
1018 if (!forest->transfervecfrombase) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DMForestTransferVecFromBase() not implemented");
1019 ierr = (forest->transfervecfrombase)(dm,vecIn,vecOut);CHKERRQ(ierr);
1020 PetscFunctionReturn(0);
1021 }
1022
1023 /*@
1024 DMForestGetComputeAdaptivitySF - Get whether transfer PetscSFs should be computed relating the cells of the
1025 pre-adaptation forest to the post-adaptiation forest. After DMSetUp() is called, these transfer PetscSFs can be
1026 accessed with DMForestGetAdaptivitySF().
1027
1028 Not collective
1029
1030 Input Parameter:
1031 . dm - the post-adaptation forest
1032
1033 Output Parameter:
1034 . computeSF - default PETSC_TRUE
1035
1036 Level: advanced
1037
1038 .seealso: DMForestSetComputeAdaptivitySF(), DMForestGetAdaptivitySF()
1039 @*/
DMForestGetComputeAdaptivitySF(DM dm,PetscBool * computeSF)1040 PetscErrorCode DMForestGetComputeAdaptivitySF(DM dm, PetscBool *computeSF)
1041 {
1042 DM_Forest *forest;
1043
1044 PetscFunctionBegin;
1045 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1046 forest = (DM_Forest*) dm->data;
1047 *computeSF = forest->computeAdaptSF;
1048 PetscFunctionReturn(0);
1049 }
1050
1051 /*@
1052 DMForestGetAdaptivitySF - Get PetscSFs that relate the pre-adaptation forest to the post-adaptation forest.
1053 Adaptation can be any combination of refinement, coarsening, repartition, and change of overlap, so there may be
1054 some cells of the pre-adaptation that are parents of post-adaptation cells, and vice versa. Therefore there are two
1055 PetscSFs: one that relates pre-adaptation coarse cells to post-adaptation fine cells, and one that relates
1056 pre-adaptation fine cells to post-adaptation coarse cells.
1057
1058 Not collective
1059
1060 Input Parameter:
1061 dm - the post-adaptation forest
1062
1063 Output Parameter:
1064 preCoarseToFine - pre-adaptation coarse cells to post-adaptation fine cells: BCast goes from pre- to post-
1065 coarseToPreFine - post-adaptation coarse cells to pre-adaptation fine cells: BCast goes from post- to pre-
1066
1067 Level: advanced
1068
1069 .seealso: DMForestGetComputeAdaptivitySF(), DMForestSetComputeAdaptivitySF()
1070 @*/
DMForestGetAdaptivitySF(DM dm,PetscSF * preCoarseToFine,PetscSF * coarseToPreFine)1071 PetscErrorCode DMForestGetAdaptivitySF(DM dm, PetscSF *preCoarseToFine, PetscSF *coarseToPreFine)
1072 {
1073 DM_Forest *forest;
1074 PetscErrorCode ierr;
1075
1076 PetscFunctionBegin;
1077 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1078 ierr = DMSetUp(dm);CHKERRQ(ierr);
1079 forest = (DM_Forest*) dm->data;
1080 if (preCoarseToFine) *preCoarseToFine = forest->preCoarseToFine;
1081 if (coarseToPreFine) *coarseToPreFine = forest->coarseToPreFine;
1082 PetscFunctionReturn(0);
1083 }
1084
1085 /*@
1086 DMForestSetGradeFactor - During the pre-setup phase, set the desired amount of grading in the mesh, e.g. give 2 to
1087 indicate that the diameter of neighboring cells should differ by at most a factor of 2. Subtypes of DMForest may
1088 only support one particular choice of grading factor.
1089
1090 Logically collective on dm
1091
1092 Input Parameters:
1093 + dm - the forest
1094 - grade - the grading factor
1095
1096 Level: advanced
1097
1098 .seealso: DMForestGetGradeFactor()
1099 @*/
DMForestSetGradeFactor(DM dm,PetscInt grade)1100 PetscErrorCode DMForestSetGradeFactor(DM dm, PetscInt grade)
1101 {
1102 DM_Forest *forest = (DM_Forest*) dm->data;
1103
1104 PetscFunctionBegin;
1105 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1106 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the grade factor after setup");
1107 forest->gradeFactor = grade;
1108 PetscFunctionReturn(0);
1109 }
1110
1111 /*@
1112 DMForestGetGradeFactor - Get the desired amount of grading in the mesh, e.g. give 2 to indicate that the diameter of
1113 neighboring cells should differ by at most a factor of 2. Subtypes of DMForest may only support one particular
1114 choice of grading factor.
1115
1116 Not collective
1117
1118 Input Parameter:
1119 . dm - the forest
1120
1121 Output Parameter:
1122 . grade - the grading factor
1123
1124 Level: advanced
1125
1126 .seealso: DMForestSetGradeFactor()
1127 @*/
DMForestGetGradeFactor(DM dm,PetscInt * grade)1128 PetscErrorCode DMForestGetGradeFactor(DM dm, PetscInt *grade)
1129 {
1130 DM_Forest *forest = (DM_Forest*) dm->data;
1131
1132 PetscFunctionBegin;
1133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1134 PetscValidIntPointer(grade,2);
1135 *grade = forest->gradeFactor;
1136 PetscFunctionReturn(0);
1137 }
1138
1139 /*@
1140 DMForestSetCellWeightFactor - During the pre-setup phase, set the factor by which the level of refinement changes
1141 the cell weight (see DMForestSetCellWeights()) when calculating partitions. The final weight of a cell will be
1142 (cellWeight) * (weightFactor^refinementLevel). A factor of 1 indicates that the weight of a cell does not depend on
1143 its level; a factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the
1144 computation associated with a cell is multiplied by a factor of 2 for each additional level of refinement.
1145
1146 Logically collective on dm
1147
1148 Input Parameters:
1149 + dm - the forest
1150 - weightsFactors - default 1.
1151
1152 Level: advanced
1153
1154 .seealso: DMForestGetCellWeightFactor(), DMForestSetCellWeights()
1155 @*/
DMForestSetCellWeightFactor(DM dm,PetscReal weightsFactor)1156 PetscErrorCode DMForestSetCellWeightFactor(DM dm, PetscReal weightsFactor)
1157 {
1158 DM_Forest *forest = (DM_Forest*) dm->data;
1159
1160 PetscFunctionBegin;
1161 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1162 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the weights factor after setup");
1163 forest->weightsFactor = weightsFactor;
1164 PetscFunctionReturn(0);
1165 }
1166
1167 /*@
1168 DMForestGetCellWeightFactor - Get the factor by which the level of refinement changes the cell weight (see
1169 DMForestSetCellWeights()) when calculating partitions. The final weight of a cell will be (cellWeight) *
1170 (weightFactor^refinementLevel). A factor of 1 indicates that the weight of a cell does not depend on its level; a
1171 factor of 2, for example, might be appropriate for sub-cycling time-stepping methods, when the computation
1172 associated with a cell is multiplied by a factor of 2 for each additional level of refinement.
1173
1174 Not collective
1175
1176 Input Parameter:
1177 . dm - the forest
1178
1179 Output Parameter:
1180 . weightsFactors - default 1.
1181
1182 Level: advanced
1183
1184 .seealso: DMForestSetCellWeightFactor(), DMForestSetCellWeights()
1185 @*/
DMForestGetCellWeightFactor(DM dm,PetscReal * weightsFactor)1186 PetscErrorCode DMForestGetCellWeightFactor(DM dm, PetscReal *weightsFactor)
1187 {
1188 DM_Forest *forest = (DM_Forest*) dm->data;
1189
1190 PetscFunctionBegin;
1191 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1192 PetscValidRealPointer(weightsFactor,2);
1193 *weightsFactor = forest->weightsFactor;
1194 PetscFunctionReturn(0);
1195 }
1196
1197 /*@
1198 DMForestGetCellChart - After the setup phase, get the local half-open interval of the chart of cells on this process
1199
1200 Not collective
1201
1202 Input Parameter:
1203 . dm - the forest
1204
1205 Output Parameters:
1206 + cStart - the first cell on this process
1207 - cEnd - one after the final cell on this process
1208
1209 Level: intermediate
1210
1211 .seealso: DMForestGetCellSF()
1212 @*/
DMForestGetCellChart(DM dm,PetscInt * cStart,PetscInt * cEnd)1213 PetscErrorCode DMForestGetCellChart(DM dm, PetscInt *cStart, PetscInt *cEnd)
1214 {
1215 DM_Forest *forest = (DM_Forest*) dm->data;
1216 PetscErrorCode ierr;
1217
1218 PetscFunctionBegin;
1219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1220 PetscValidIntPointer(cStart,2);
1221 PetscValidIntPointer(cEnd,2);
1222 if (((forest->cStart == PETSC_DETERMINE) || (forest->cEnd == PETSC_DETERMINE)) && forest->createcellchart) {
1223 ierr = forest->createcellchart(dm,&forest->cStart,&forest->cEnd);CHKERRQ(ierr);
1224 }
1225 *cStart = forest->cStart;
1226 *cEnd = forest->cEnd;
1227 PetscFunctionReturn(0);
1228 }
1229
1230 /*@
1231 DMForestGetCellSF - After the setup phase, get the PetscSF for overlapping cells between processes
1232
1233 Not collective
1234
1235 Input Parameter:
1236 . dm - the forest
1237
1238 Output Parameter:
1239 . cellSF - the PetscSF
1240
1241 Level: intermediate
1242
1243 .seealso: DMForestGetCellChart()
1244 @*/
DMForestGetCellSF(DM dm,PetscSF * cellSF)1245 PetscErrorCode DMForestGetCellSF(DM dm, PetscSF *cellSF)
1246 {
1247 DM_Forest *forest = (DM_Forest*) dm->data;
1248 PetscErrorCode ierr;
1249
1250 PetscFunctionBegin;
1251 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1252 PetscValidPointer(cellSF,2);
1253 if ((!forest->cellSF) && forest->createcellsf) {
1254 ierr = forest->createcellsf(dm,&forest->cellSF);CHKERRQ(ierr);
1255 }
1256 *cellSF = forest->cellSF;
1257 PetscFunctionReturn(0);
1258 }
1259
1260 /*@C
1261 DMForestSetAdaptivityLabel - During the pre-setup phase, set the label of the pre-adaptation forest (see
1262 DMForestGetAdaptivityForest()) that holds the adaptation flags (refinement, coarsening, or some combination). The
1263 interpretation of the label values is up to the subtype of DMForest, but DM_ADAPT_DETERMINE, DM_ADAPT_KEEP,
1264 DM_ADAPT_REFINE, and DM_ADAPT_COARSEN have been reserved as choices that should be accepted by all subtypes.
1265
1266 Logically collective on dm
1267
1268 Input Parameters:
1269 - dm - the forest
1270 + adaptLabel - the label in the pre-adaptation forest
1271
1272 Level: intermediate
1273
1274 .seealso DMForestGetAdaptivityLabel()
1275 @*/
DMForestSetAdaptivityLabel(DM dm,DMLabel adaptLabel)1276 PetscErrorCode DMForestSetAdaptivityLabel(DM dm, DMLabel adaptLabel)
1277 {
1278 DM_Forest *forest = (DM_Forest*) dm->data;
1279 PetscErrorCode ierr;
1280
1281 PetscFunctionBegin;
1282 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1283 if (adaptLabel) PetscValidHeaderSpecific(adaptLabel,DMLABEL_CLASSID,2);
1284 ierr = PetscObjectReference((PetscObject)adaptLabel);CHKERRQ(ierr);
1285 ierr = DMLabelDestroy(&forest->adaptLabel);CHKERRQ(ierr);
1286 forest->adaptLabel = adaptLabel;
1287 PetscFunctionReturn(0);
1288 }
1289
1290 /*@C
1291 DMForestGetAdaptivityLabel - Get the label of the pre-adaptation forest (see DMForestGetAdaptivityForest()) that
1292 holds the adaptation flags (refinement, coarsening, or some combination). The interpretation of the label values is
1293 up to the subtype of DMForest, but DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN have
1294 been reserved as choices that should be accepted by all subtypes.
1295
1296 Not collective
1297
1298 Input Parameter:
1299 . dm - the forest
1300
1301 Output Parameter:
1302 . adaptLabel - the name of the label in the pre-adaptation forest
1303
1304 Level: intermediate
1305
1306 .seealso DMForestSetAdaptivityLabel()
1307 @*/
DMForestGetAdaptivityLabel(DM dm,DMLabel * adaptLabel)1308 PetscErrorCode DMForestGetAdaptivityLabel(DM dm, DMLabel *adaptLabel)
1309 {
1310 DM_Forest *forest = (DM_Forest*) dm->data;
1311
1312 PetscFunctionBegin;
1313 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1314 *adaptLabel = forest->adaptLabel;
1315 PetscFunctionReturn(0);
1316 }
1317
1318 /*@
1319 DMForestSetCellWeights - Set the weights assigned to each of the cells (see DMForestGetCellChart()) of the current
1320 process: weights are used to determine parallel partitioning. Partitions will be created so that each process's
1321 ratio of weight to capacity (see DMForestSetWeightCapacity()) is roughly equal. If NULL, each cell receives a weight
1322 of 1.
1323
1324 Logically collective on dm
1325
1326 Input Parameters:
1327 + dm - the forest
1328 . weights - the array of weights for all cells, or NULL to indicate each cell has weight 1.
1329 - copyMode - how weights should reference weights
1330
1331 Level: advanced
1332
1333 .seealso: DMForestGetCellWeights(), DMForestSetWeightCapacity()
1334 @*/
DMForestSetCellWeights(DM dm,PetscReal weights[],PetscCopyMode copyMode)1335 PetscErrorCode DMForestSetCellWeights(DM dm, PetscReal weights[], PetscCopyMode copyMode)
1336 {
1337 DM_Forest *forest = (DM_Forest*) dm->data;
1338 PetscInt cStart, cEnd;
1339 PetscErrorCode ierr;
1340
1341 PetscFunctionBegin;
1342 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1343 ierr = DMForestGetCellChart(dm,&cStart,&cEnd);CHKERRQ(ierr);
1344 if (cEnd < cStart) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"cell chart [%d,%d) is not valid",cStart,cEnd);
1345 if (copyMode == PETSC_COPY_VALUES) {
1346 if (forest->cellWeightsCopyMode != PETSC_OWN_POINTER || forest->cellWeights == weights) {
1347 ierr = PetscMalloc1(cEnd-cStart,&forest->cellWeights);CHKERRQ(ierr);
1348 }
1349 ierr = PetscArraycpy(forest->cellWeights,weights,cEnd-cStart);CHKERRQ(ierr);
1350 forest->cellWeightsCopyMode = PETSC_OWN_POINTER;
1351 PetscFunctionReturn(0);
1352 }
1353 if (forest->cellWeightsCopyMode == PETSC_OWN_POINTER) {
1354 ierr = PetscFree(forest->cellWeights);CHKERRQ(ierr);
1355 }
1356 forest->cellWeights = weights;
1357 forest->cellWeightsCopyMode = copyMode;
1358 PetscFunctionReturn(0);
1359 }
1360
1361 /*@
1362 DMForestGetCellWeights - Get the weights assigned to each of the cells (see DMForestGetCellChart()) of the current
1363 process: weights are used to determine parallel partitioning. Partitions will be created so that each process's
1364 ratio of weight to capacity (see DMForestSetWeightCapacity()) is roughly equal. If NULL, each cell receives a weight
1365 of 1.
1366
1367 Not collective
1368
1369 Input Parameter:
1370 . dm - the forest
1371
1372 Output Parameter:
1373 . weights - the array of weights for all cells, or NULL to indicate each cell has weight 1.
1374
1375 Level: advanced
1376
1377 .seealso: DMForestSetCellWeights(), DMForestSetWeightCapacity()
1378 @*/
DMForestGetCellWeights(DM dm,PetscReal ** weights)1379 PetscErrorCode DMForestGetCellWeights(DM dm, PetscReal **weights)
1380 {
1381 DM_Forest *forest = (DM_Forest*) dm->data;
1382
1383 PetscFunctionBegin;
1384 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1385 PetscValidPointer(weights,2);
1386 *weights = forest->cellWeights;
1387 PetscFunctionReturn(0);
1388 }
1389
1390 /*@
1391 DMForestSetWeightCapacity - During the pre-setup phase, set the capacity of the current process when repartitioning
1392 a pre-adaptation forest (see DMForestGetAdaptivityForest()). After partitioning, the ratio of the weight of each
1393 process's cells to the process's capacity will be roughly equal for all processes. A capacity of 0 indicates that
1394 the current process should not have any cells after repartitioning.
1395
1396 Logically Collective on dm
1397
1398 Input parameters:
1399 + dm - the forest
1400 - capacity - this process's capacity
1401
1402 Level: advanced
1403
1404 .seealso DMForestGetWeightCapacity(), DMForestSetCellWeights(), DMForestSetCellWeightFactor()
1405 @*/
DMForestSetWeightCapacity(DM dm,PetscReal capacity)1406 PetscErrorCode DMForestSetWeightCapacity(DM dm, PetscReal capacity)
1407 {
1408 DM_Forest *forest = (DM_Forest*) dm->data;
1409
1410 PetscFunctionBegin;
1411 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1412 if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the weight capacity after setup");
1413 if (capacity < 0.) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Cannot have negative weight capacity; %f",capacity);
1414 forest->weightCapacity = capacity;
1415 PetscFunctionReturn(0);
1416 }
1417
1418 /*@
1419 DMForestGetWeightCapacity - Set the capacity of the current process when repartitioning a pre-adaptation forest (see
1420 DMForestGetAdaptivityForest()). After partitioning, the ratio of the weight of each process's cells to the
1421 process's capacity will be roughly equal for all processes. A capacity of 0 indicates that the current process
1422 should not have any cells after repartitioning.
1423
1424 Not collective
1425
1426 Input parameter:
1427 . dm - the forest
1428
1429 Output parameter:
1430 . capacity - this process's capacity
1431
1432 Level: advanced
1433
1434 .seealso DMForestSetWeightCapacity(), DMForestSetCellWeights(), DMForestSetCellWeightFactor()
1435 @*/
DMForestGetWeightCapacity(DM dm,PetscReal * capacity)1436 PetscErrorCode DMForestGetWeightCapacity(DM dm, PetscReal *capacity)
1437 {
1438 DM_Forest *forest = (DM_Forest*) dm->data;
1439
1440 PetscFunctionBegin;
1441 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1442 PetscValidRealPointer(capacity,2);
1443 *capacity = forest->weightCapacity;
1444 PetscFunctionReturn(0);
1445 }
1446
DMSetFromOptions_Forest(PetscOptionItems * PetscOptionsObject,DM dm)1447 PETSC_EXTERN PetscErrorCode DMSetFromOptions_Forest(PetscOptionItems *PetscOptionsObject,DM dm)
1448 {
1449 PetscBool flg, flg1, flg2, flg3, flg4;
1450 DMForestTopology oldTopo;
1451 char stringBuffer[256];
1452 PetscViewer viewer;
1453 PetscViewerFormat format;
1454 PetscInt adjDim, adjCodim, overlap, minRefinement, initRefinement, maxRefinement, grade;
1455 PetscReal weightsFactor;
1456 DMForestAdaptivityStrategy adaptStrategy;
1457 PetscErrorCode ierr;
1458
1459 PetscFunctionBegin;
1460 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1461 ierr = DMForestGetTopology(dm, &oldTopo);CHKERRQ(ierr);
1462 ierr = PetscOptionsHead(PetscOptionsObject,"DMForest Options");CHKERRQ(ierr);
1463 ierr = PetscOptionsString("-dm_forest_topology","the topology of the forest's base mesh","DMForestSetTopology",oldTopo,stringBuffer,sizeof(stringBuffer),&flg1);CHKERRQ(ierr);
1464 ierr = PetscOptionsViewer("-dm_forest_base_dm","load the base DM from a viewer specification","DMForestSetBaseDM",&viewer,&format,&flg2);CHKERRQ(ierr);
1465 ierr = PetscOptionsViewer("-dm_forest_coarse_forest","load the coarse forest from a viewer specification","DMForestSetCoarseForest",&viewer,&format,&flg3);CHKERRQ(ierr);
1466 ierr = PetscOptionsViewer("-dm_forest_fine_forest","load the fine forest from a viewer specification","DMForestSetFineForest",&viewer,&format,&flg4);CHKERRQ(ierr);
1467 if ((PetscInt) flg1 + (PetscInt) flg2 + (PetscInt) flg3 + (PetscInt) flg4 > 1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Specify only one of -dm_forest_{topology,base_dm,coarse_forest,fine_forest}");
1468 if (flg1) {
1469 ierr = DMForestSetTopology(dm,(DMForestTopology)stringBuffer);CHKERRQ(ierr);
1470 ierr = DMForestSetBaseDM(dm,NULL);CHKERRQ(ierr);
1471 ierr = DMForestSetAdaptivityForest(dm,NULL);CHKERRQ(ierr);
1472 }
1473 if (flg2) {
1474 DM base;
1475
1476 ierr = DMCreate(PetscObjectComm((PetscObject)dm),&base);CHKERRQ(ierr);
1477 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
1478 ierr = DMLoad(base,viewer);CHKERRQ(ierr);
1479 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1480 ierr = DMForestSetBaseDM(dm,base);CHKERRQ(ierr);
1481 ierr = DMDestroy(&base);CHKERRQ(ierr);
1482 ierr = DMForestSetTopology(dm,NULL);CHKERRQ(ierr);
1483 ierr = DMForestSetAdaptivityForest(dm,NULL);CHKERRQ(ierr);
1484 }
1485 if (flg3) {
1486 DM coarse;
1487
1488 ierr = DMCreate(PetscObjectComm((PetscObject)dm),&coarse);CHKERRQ(ierr);
1489 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
1490 ierr = DMLoad(coarse,viewer);CHKERRQ(ierr);
1491 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1492 ierr = DMForestSetAdaptivityForest(dm,coarse);CHKERRQ(ierr);
1493 ierr = DMDestroy(&coarse);CHKERRQ(ierr);
1494 ierr = DMForestSetTopology(dm,NULL);CHKERRQ(ierr);
1495 ierr = DMForestSetBaseDM(dm,NULL);CHKERRQ(ierr);
1496 }
1497 if (flg4) {
1498 DM fine;
1499
1500 ierr = DMCreate(PetscObjectComm((PetscObject)dm),&fine);CHKERRQ(ierr);
1501 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
1502 ierr = DMLoad(fine,viewer);CHKERRQ(ierr);
1503 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1504 ierr = DMForestSetAdaptivityForest(dm,fine);CHKERRQ(ierr);
1505 ierr = DMDestroy(&fine);CHKERRQ(ierr);
1506 ierr = DMForestSetTopology(dm,NULL);CHKERRQ(ierr);
1507 ierr = DMForestSetBaseDM(dm,NULL);CHKERRQ(ierr);
1508 }
1509 ierr = DMForestGetAdjacencyDimension(dm,&adjDim);CHKERRQ(ierr);
1510 ierr = PetscOptionsBoundedInt("-dm_forest_adjacency_dimension","set the dimension of points that define adjacency in the forest","DMForestSetAdjacencyDimension",adjDim,&adjDim,&flg,0);CHKERRQ(ierr);
1511 if (flg) {
1512 ierr = DMForestSetAdjacencyDimension(dm,adjDim);CHKERRQ(ierr);
1513 } else {
1514 ierr = DMForestGetAdjacencyCodimension(dm,&adjCodim);CHKERRQ(ierr);
1515 ierr = PetscOptionsBoundedInt("-dm_forest_adjacency_codimension","set the codimension of points that define adjacency in the forest","DMForestSetAdjacencyCodimension",adjCodim,&adjCodim,&flg,1);CHKERRQ(ierr);
1516 if (flg) {
1517 ierr = DMForestSetAdjacencyCodimension(dm,adjCodim);CHKERRQ(ierr);
1518 }
1519 }
1520 ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr);
1521 ierr = PetscOptionsBoundedInt("-dm_forest_partition_overlap","set the degree of partition overlap","DMForestSetPartitionOverlap",overlap,&overlap,&flg,0);CHKERRQ(ierr);
1522 if (flg) {
1523 ierr = DMForestSetPartitionOverlap(dm,overlap);CHKERRQ(ierr);
1524 }
1525 #if 0
1526 ierr = PetscOptionsBoundedInt("-dm_refine","equivalent to -dm_forest_set_minimum_refinement and -dm_forest_set_initial_refinement with the same value",NULL,minRefinement,&minRefinement,&flg,0);CHKERRQ(ierr);
1527 if (flg) {
1528 ierr = DMForestSetMinimumRefinement(dm,minRefinement);CHKERRQ(ierr);
1529 ierr = DMForestSetInitialRefinement(dm,minRefinement);CHKERRQ(ierr);
1530 }
1531 ierr = PetscOptionsBoundedInt("-dm_refine_hierarchy","equivalent to -dm_forest_set_minimum_refinement 0 and -dm_forest_set_initial_refinement",NULL,initRefinement,&initRefinement,&flg,0);CHKERRQ(ierr);
1532 if (flg) {
1533 ierr = DMForestSetMinimumRefinement(dm,0);CHKERRQ(ierr);
1534 ierr = DMForestSetInitialRefinement(dm,initRefinement);CHKERRQ(ierr);
1535 }
1536 #endif
1537 ierr = DMForestGetMinimumRefinement(dm,&minRefinement);CHKERRQ(ierr);
1538 ierr = PetscOptionsBoundedInt("-dm_forest_minimum_refinement","set the minimum level of refinement in the forest","DMForestSetMinimumRefinement",minRefinement,&minRefinement,&flg,0);CHKERRQ(ierr);
1539 if (flg) {
1540 ierr = DMForestSetMinimumRefinement(dm,minRefinement);CHKERRQ(ierr);
1541 }
1542 ierr = DMForestGetInitialRefinement(dm,&initRefinement);CHKERRQ(ierr);
1543 ierr = PetscOptionsBoundedInt("-dm_forest_initial_refinement","set the initial level of refinement in the forest","DMForestSetInitialRefinement",initRefinement,&initRefinement,&flg,0);CHKERRQ(ierr);
1544 if (flg) {
1545 ierr = DMForestSetInitialRefinement(dm,initRefinement);CHKERRQ(ierr);
1546 }
1547 ierr = DMForestGetMaximumRefinement(dm,&maxRefinement);CHKERRQ(ierr);
1548 ierr = PetscOptionsBoundedInt("-dm_forest_maximum_refinement","set the maximum level of refinement in the forest","DMForestSetMaximumRefinement",maxRefinement,&maxRefinement,&flg,0);CHKERRQ(ierr);
1549 if (flg) {
1550 ierr = DMForestSetMaximumRefinement(dm,maxRefinement);CHKERRQ(ierr);
1551 }
1552 ierr = DMForestGetAdaptivityStrategy(dm,&adaptStrategy);CHKERRQ(ierr);
1553 ierr = PetscOptionsString("-dm_forest_adaptivity_strategy","the forest's adaptivity-flag resolution strategy","DMForestSetAdaptivityStrategy",adaptStrategy,stringBuffer,sizeof(stringBuffer),&flg);CHKERRQ(ierr);
1554 if (flg) {
1555 ierr = DMForestSetAdaptivityStrategy(dm,(DMForestAdaptivityStrategy)stringBuffer);CHKERRQ(ierr);
1556 }
1557 ierr = DMForestGetGradeFactor(dm,&grade);CHKERRQ(ierr);
1558 ierr = PetscOptionsBoundedInt("-dm_forest_grade_factor","grade factor between neighboring cells","DMForestSetGradeFactor",grade,&grade,&flg,0);CHKERRQ(ierr);
1559 if (flg) {
1560 ierr = DMForestSetGradeFactor(dm,grade);CHKERRQ(ierr);
1561 }
1562 ierr = DMForestGetCellWeightFactor(dm,&weightsFactor);CHKERRQ(ierr);
1563 ierr = PetscOptionsReal("-dm_forest_cell_weight_factor","multiplying weight factor for cell refinement","DMForestSetCellWeightFactor",weightsFactor,&weightsFactor,&flg);CHKERRQ(ierr);
1564 if (flg) {
1565 ierr = DMForestSetCellWeightFactor(dm,weightsFactor);CHKERRQ(ierr);
1566 }
1567 ierr = PetscOptionsTail();CHKERRQ(ierr);
1568 PetscFunctionReturn(0);
1569 }
1570
DMCreateSubDM_Forest(DM dm,PetscInt numFields,const PetscInt fields[],IS * is,DM * subdm)1571 PetscErrorCode DMCreateSubDM_Forest(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
1572 {
1573 PetscErrorCode ierr;
1574
1575 PetscFunctionBegin;
1576 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);}
1577 ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
1578 PetscFunctionReturn(0);
1579 }
1580
DMRefine_Forest(DM dm,MPI_Comm comm,DM * dmRefined)1581 PetscErrorCode DMRefine_Forest(DM dm, MPI_Comm comm, DM *dmRefined)
1582 {
1583 DMLabel refine;
1584 DM fineDM;
1585 PetscErrorCode ierr;
1586
1587 PetscFunctionBegin;
1588 ierr = DMGetFineDM(dm,&fineDM);CHKERRQ(ierr);
1589 if (fineDM) {
1590 ierr = PetscObjectReference((PetscObject)fineDM);CHKERRQ(ierr);
1591 *dmRefined = fineDM;
1592 PetscFunctionReturn(0);
1593 }
1594 ierr = DMForestTemplate(dm,comm,dmRefined);CHKERRQ(ierr);
1595 ierr = DMGetLabel(dm,"refine",&refine);CHKERRQ(ierr);
1596 if (!refine) {
1597 ierr = DMLabelCreate(PETSC_COMM_SELF, "refine",&refine);CHKERRQ(ierr);
1598 ierr = DMLabelSetDefaultValue(refine,DM_ADAPT_REFINE);CHKERRQ(ierr);
1599 } else {
1600 ierr = PetscObjectReference((PetscObject) refine);CHKERRQ(ierr);
1601 }
1602 ierr = DMForestSetAdaptivityLabel(*dmRefined,refine);CHKERRQ(ierr);
1603 ierr = DMLabelDestroy(&refine);CHKERRQ(ierr);
1604 PetscFunctionReturn(0);
1605 }
1606
DMCoarsen_Forest(DM dm,MPI_Comm comm,DM * dmCoarsened)1607 PetscErrorCode DMCoarsen_Forest(DM dm, MPI_Comm comm, DM *dmCoarsened)
1608 {
1609 DMLabel coarsen;
1610 DM coarseDM;
1611 PetscErrorCode ierr;
1612
1613 PetscFunctionBegin;
1614 {
1615 PetscMPIInt mpiComparison;
1616 MPI_Comm dmcomm = PetscObjectComm((PetscObject)dm);
1617
1618 ierr = MPI_Comm_compare(comm, dmcomm, &mpiComparison);CHKERRQ(ierr);
1619 if (mpiComparison != MPI_IDENT && mpiComparison != MPI_CONGRUENT) SETERRQ(dmcomm,PETSC_ERR_SUP,"No support for different communicators yet");
1620 }
1621 ierr = DMGetCoarseDM(dm,&coarseDM);CHKERRQ(ierr);
1622 if (coarseDM) {
1623 ierr = PetscObjectReference((PetscObject)coarseDM);CHKERRQ(ierr);
1624 *dmCoarsened = coarseDM;
1625 PetscFunctionReturn(0);
1626 }
1627 ierr = DMForestTemplate(dm,comm,dmCoarsened);CHKERRQ(ierr);
1628 ierr = DMForestSetAdaptivityPurpose(*dmCoarsened,DM_ADAPT_COARSEN);CHKERRQ(ierr);
1629 ierr = DMGetLabel(dm,"coarsen",&coarsen);CHKERRQ(ierr);
1630 if (!coarsen) {
1631 ierr = DMLabelCreate(PETSC_COMM_SELF, "coarsen",&coarsen);CHKERRQ(ierr);
1632 ierr = DMLabelSetDefaultValue(coarsen,DM_ADAPT_COARSEN);CHKERRQ(ierr);
1633 } else {
1634 ierr = PetscObjectReference((PetscObject) coarsen);CHKERRQ(ierr);
1635 }
1636 ierr = DMForestSetAdaptivityLabel(*dmCoarsened,coarsen);CHKERRQ(ierr);
1637 ierr = DMLabelDestroy(&coarsen);CHKERRQ(ierr);
1638 PetscFunctionReturn(0);
1639 }
1640
DMAdaptLabel_Forest(DM dm,DMLabel label,DM * adaptedDM)1641 static PetscErrorCode DMAdaptLabel_Forest(DM dm, DMLabel label, DM *adaptedDM)
1642 {
1643 PetscBool success;
1644 PetscErrorCode ierr;
1645
1646 PetscFunctionBegin;
1647 ierr = DMForestTemplate(dm,PetscObjectComm((PetscObject)dm),adaptedDM);CHKERRQ(ierr);
1648 ierr = DMForestSetAdaptivityLabel(*adaptedDM,label);CHKERRQ(ierr);
1649 ierr = DMSetUp(*adaptedDM);CHKERRQ(ierr);
1650 ierr = DMForestGetAdaptivitySuccess(*adaptedDM,&success);CHKERRQ(ierr);
1651 if (!success) {
1652 ierr = DMDestroy(adaptedDM);CHKERRQ(ierr);
1653 *adaptedDM = NULL;
1654 }
1655 PetscFunctionReturn(0);
1656 }
1657
DMInitialize_Forest(DM dm)1658 static PetscErrorCode DMInitialize_Forest(DM dm)
1659 {
1660 PetscErrorCode ierr;
1661
1662 PetscFunctionBegin;
1663 ierr = PetscMemzero(dm->ops,sizeof(*(dm->ops)));CHKERRQ(ierr);
1664
1665 dm->ops->clone = DMClone_Forest;
1666 dm->ops->setfromoptions = DMSetFromOptions_Forest;
1667 dm->ops->destroy = DMDestroy_Forest;
1668 dm->ops->createsubdm = DMCreateSubDM_Forest;
1669 dm->ops->refine = DMRefine_Forest;
1670 dm->ops->coarsen = DMCoarsen_Forest;
1671 dm->ops->adaptlabel = DMAdaptLabel_Forest;
1672 PetscFunctionReturn(0);
1673 }
1674
1675 /*MC
1676
1677 DMFOREST = "forest" - A DM object that encapsulates a hierarchically refined mesh. Forests usually have a base DM
1678 (see DMForestGetBaseDM()), from which it is refined. The refinement and partitioning of forests is considered
1679 immutable after DMSetUp() is called. To adapt a mesh, one should call DMForestTemplate() to create a new mesh that
1680 will default to being identical to it, specify how that mesh should differ, and then calling DMSetUp() on the new
1681 mesh.
1682
1683 To specify that a mesh should be refined or coarsened from the previous mesh, a label should be defined on the
1684 previous mesh whose values indicate which cells should be refined (DM_ADAPT_REFINE) or coarsened (DM_ADAPT_COARSEN)
1685 and how (subtypes are free to allow additional values for things like anisotropic refinement). The label should be
1686 given to the *new* mesh with DMForestSetAdaptivityLabel().
1687
1688 Level: advanced
1689
1690 .seealso: DMType, DMCreate(), DMSetType(), DMForestGetBaseDM(), DMForestSetBaseDM(), DMForestTemplate(), DMForestSetAdaptivityLabel()
1691 M*/
1692
DMCreate_Forest(DM dm)1693 PETSC_EXTERN PetscErrorCode DMCreate_Forest(DM dm)
1694 {
1695 DM_Forest *forest;
1696 PetscErrorCode ierr;
1697
1698 PetscFunctionBegin;
1699 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1700 ierr = PetscNewLog(dm,&forest);CHKERRQ(ierr);
1701 dm->dim = 0;
1702 dm->data = forest;
1703 forest->refct = 1;
1704 forest->data = NULL;
1705 forest->topology = NULL;
1706 forest->adapt = NULL;
1707 forest->base = NULL;
1708 forest->adaptPurpose = DM_ADAPT_DETERMINE;
1709 forest->adjDim = PETSC_DEFAULT;
1710 forest->overlap = PETSC_DEFAULT;
1711 forest->minRefinement = PETSC_DEFAULT;
1712 forest->maxRefinement = PETSC_DEFAULT;
1713 forest->initRefinement = PETSC_DEFAULT;
1714 forest->cStart = PETSC_DETERMINE;
1715 forest->cEnd = PETSC_DETERMINE;
1716 forest->cellSF = NULL;
1717 forest->adaptLabel = NULL;
1718 forest->gradeFactor = 2;
1719 forest->cellWeights = NULL;
1720 forest->cellWeightsCopyMode = PETSC_USE_POINTER;
1721 forest->weightsFactor = 1.;
1722 forest->weightCapacity = 1.;
1723 ierr = DMForestSetAdaptivityStrategy(dm,DMFORESTADAPTALL);CHKERRQ(ierr);
1724 ierr = DMInitialize_Forest(dm);CHKERRQ(ierr);
1725 PetscFunctionReturn(0);
1726 }
1727