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