xref: /petsc/src/dm/impls/forest/forest.c (revision 3e58adeeb9dd67c2cbefdb8ac2b9ea974119bf57)
1 #include <petsc/private/dmforestimpl.h> /*I petscdmforest.h I*/
2 #include <petsc/private/dmimpl.h>       /*I petscdm.h */
3 #include <petscsf.h>
4 
5 PetscBool DMForestPackageInitialized = PETSC_FALSE;
6 
7 typedef struct _DMForestTypeLink *DMForestTypeLink;
8 
9 struct _DMForestTypeLink
10 {
11   char *name;
12   DMForestTypeLink next;
13 };
14 
15 DMForestTypeLink DMForestTypeList;
16 
17 #undef __FUNCT__
18 #define __FUNCT__ "DMForestPackageFinalize"
19 static PetscErrorCode DMForestPackageFinalize(void)
20 {
21   DMForestTypeLink oldLink, link = DMForestTypeList;
22   PetscErrorCode ierr;
23 
24   PetscFunctionBegin;
25   while (link) {
26     oldLink = link;
27     ierr = PetscFree(oldLink->name);
28     link = oldLink->next;
29     ierr = PetscFree(oldLink);CHKERRQ(ierr);
30   }
31   PetscFunctionReturn(0);
32 }
33 
34 #undef __FUNCT__
35 #define __FUNCT__ "DMForestPackageInitialize"
36 static PetscErrorCode DMForestPackageInitialize(void)
37 {
38   PetscErrorCode ierr;
39 
40   PetscFunctionBegin;
41   if (DMForestPackageInitialized) PetscFunctionReturn(0);
42   DMForestPackageInitialized = PETSC_TRUE;
43   ierr = DMForestRegisterType(DMFOREST);CHKERRQ(ierr);
44   ierr = PetscRegisterFinalize(DMForestPackageFinalize);CHKERRQ(ierr);
45   PetscFunctionReturn(0);
46 }
47 
48 #undef __FUNCT__
49 #define __FUNCT__ "DMForestRegisterType"
50 PetscErrorCode DMForestRegisterType(DMType name)
51 {
52   DMForestTypeLink link;
53   PetscErrorCode ierr;
54 
55   PetscFunctionBegin;
56   ierr = DMForestPackageInitialize();CHKERRQ(ierr);
57   ierr = PetscNew(&link);CHKERRQ(ierr);
58   ierr = PetscStrallocpy(name,&link->name);CHKERRQ(ierr);
59   link->next = DMForestTypeList;
60   DMForestTypeList = link;
61   PetscFunctionReturn(0);
62 }
63 
64 #undef __FUNCT__
65 #define __FUNCT__ "DMIsForest"
66 PetscErrorCode DMIsForest(DM dm, PetscBool *isForest)
67 {
68   DMForestTypeLink link = DMForestTypeList;
69   PetscErrorCode ierr;
70 
71   PetscFunctionBegin;
72   while (link) {
73     PetscBool sameType;
74     ierr = PetscObjectTypeCompare((PetscObject)dm,link->name,&sameType);CHKERRQ(ierr);
75     if (sameType) {
76       *isForest = PETSC_TRUE;
77       PetscFunctionReturn(0);
78     }
79     link = link->next;
80   }
81   *isForest = PETSC_FALSE;
82   PetscFunctionReturn(0);
83 }
84 
85 #undef __FUNCT__
86 #define __FUNCT__ "DMForestTemplate"
87 PETSC_EXTERN PetscErrorCode DMForestTemplate(DM dm, MPI_Comm comm, DM *tdm)
88 {
89   DM_Forest        *forest = (DM_Forest *) dm->data;
90   DMType           type;
91   DM               base;
92   DMForestTopology topology;
93   PetscInt         dim, overlap, ref, factor;
94   DMForestAdaptivityStrategy strat;
95   PetscErrorCode   (*map) (PetscInt, const PetscReal[], PetscReal[], void *);
96   void             *mapCtx;
97   PetscErrorCode   ierr;
98 
99   PetscFunctionBegin;
100   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101   ierr = DMCreate(PetscObjectComm((PetscObject)dm),tdm);CHKERRQ(ierr);
102   ierr = DMGetType(dm,&type);CHKERRQ(ierr);
103   ierr = DMSetType(*tdm,type);CHKERRQ(ierr);
104   ierr = DMForestGetBaseDM(dm,&base);CHKERRQ(ierr);
105   ierr = DMForestSetBaseDM(*tdm,base);CHKERRQ(ierr);
106   ierr = DMForestGetTopology(dm,&topology);CHKERRQ(ierr);
107   ierr = DMForestSetTopology(*tdm,topology);CHKERRQ(ierr);
108   ierr = DMForestGetAdjacencyDimension(dm,&dim);CHKERRQ(ierr);
109   ierr = DMForestSetAdjacencyDimension(*tdm,dim);CHKERRQ(ierr);
110   ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr);
111   ierr = DMForestSetPartitionOverlap(*tdm,overlap);CHKERRQ(ierr);
112   ierr = DMForestGetMinimumRefinement(dm,&ref);CHKERRQ(ierr);
113   ierr = DMForestSetMinimumRefinement(*tdm,ref);CHKERRQ(ierr);
114   ierr = DMForestGetMaximumRefinement(dm,&ref);CHKERRQ(ierr);
115   ierr = DMForestSetMaximumRefinement(*tdm,ref);CHKERRQ(ierr);
116   ierr = DMForestGetAdaptivityStrategy(dm,&strat);CHKERRQ(ierr);
117   ierr = DMForestSetAdaptivityStrategy(*tdm,strat);CHKERRQ(ierr);
118   ierr = DMForestGetGradeFactor(dm,&factor);CHKERRQ(ierr);
119   ierr = DMForestSetGradeFactor(*tdm,factor);CHKERRQ(ierr);
120   ierr = DMForestGetBaseCoordinateMapping(dm,&map,&mapCtx);CHKERRQ(ierr);
121   ierr = DMForestSetBaseCoordinateMapping(dm,map,mapCtx);CHKERRQ(ierr);
122   if (forest->ftemplate) {
123     ierr = (forest->ftemplate) (dm, *tdm);CHKERRQ(ierr);
124   }
125   ierr = DMForestSetAdaptivityForest(*tdm,dm);CHKERRQ(ierr);
126   PetscFunctionReturn(0);
127 }
128 
129 static PetscErrorCode DMInitialize_Forest(DM dm);
130 
131 #undef __FUNCT__
132 #define __FUNCT__ "DMClone_Forest"
133 PETSC_EXTERN PetscErrorCode DMClone_Forest(DM dm, DM *newdm)
134 {
135   DM_Forest        *forest = (DM_Forest *) dm->data;
136   const char       *type;
137   PetscErrorCode ierr;
138 
139   PetscFunctionBegin;
140   forest->refct++;
141   (*newdm)->data = forest;
142   ierr = PetscObjectGetType((PetscObject) dm, &type);CHKERRQ(ierr);
143   ierr = PetscObjectChangeTypeName((PetscObject) *newdm, type);CHKERRQ(ierr);
144   ierr = DMInitialize_Forest(*newdm);CHKERRQ(ierr);
145   PetscFunctionReturn(0);
146 }
147 
148 #undef __FUNCT__
149 #define __FUNCT__ "DMDestroy_Forest"
150 static PetscErrorCode DMDestroy_Forest(DM dm)
151 {
152   DM_Forest     *forest = (DM_Forest*) dm->data;
153   PetscErrorCode ierr;
154 
155   PetscFunctionBegin;
156   if (--forest->refct > 0) PetscFunctionReturn(0);
157   if (forest->destroy) {ierr = forest->destroy(dm);CHKERRQ(ierr);}
158   ierr = PetscSFDestroy(&forest->cellSF);CHKERRQ(ierr);
159   ierr = PetscFree(forest->adaptLabel);CHKERRQ(ierr);
160   ierr = PetscFree(forest->adaptStrategy);CHKERRQ(ierr);
161   ierr = DMDestroy(&forest->base);CHKERRQ(ierr);
162   ierr = DMDestroy(&forest->adapt);CHKERRQ(ierr);
163   ierr = PetscFree(forest->topology);CHKERRQ(ierr);
164   ierr = PetscFree(forest);CHKERRQ(ierr);
165   PetscFunctionReturn(0);
166 }
167 
168 #undef __FUNCT__
169 #define __FUNCT__ "DMForestSetTopology"
170 PetscErrorCode DMForestSetTopology(DM dm, DMForestTopology topology)
171 {
172   DM_Forest      *forest = (DM_Forest *) dm->data;
173   PetscErrorCode ierr;
174 
175   PetscFunctionBegin;
176   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
177   if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the topology after setup");
178   ierr = PetscFree(forest->topology);CHKERRQ(ierr);
179   ierr = PetscStrallocpy((const char *)topology,(char **) &forest->topology);CHKERRQ(ierr);
180   PetscFunctionReturn(0);
181 }
182 
183 #undef __FUNCT__
184 #define __FUNCT__ "DMForestGetTopology"
185 PetscErrorCode DMForestGetTopology(DM dm, DMForestTopology *topology)
186 {
187   DM_Forest      *forest = (DM_Forest *) dm->data;
188 
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
191   PetscValidPointer(topology,2);
192   *topology = forest->topology;
193   PetscFunctionReturn(0);
194 }
195 
196 #undef __FUNCT__
197 #define __FUNCT__ "DMForestSetBaseDM"
198 PetscErrorCode DMForestSetBaseDM(DM dm, DM base)
199 {
200   DM_Forest      *forest = (DM_Forest *) dm->data;
201   PetscInt       dim, dimEmbed;
202   PetscErrorCode ierr;
203 
204   PetscFunctionBegin;
205   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
206   if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the base after setup");
207   ierr = PetscObjectReference((PetscObject)base);CHKERRQ(ierr);
208   ierr = DMDestroy(&forest->base);CHKERRQ(ierr);
209   forest->base = base;
210   if (base) {
211     PetscValidHeaderSpecific(base, DM_CLASSID, 2);
212     ierr = DMGetDimension(base,&dim);CHKERRQ(ierr);
213     ierr = DMSetDimension(dm,dim);CHKERRQ(ierr);
214     ierr = DMGetCoordinateDim(base,&dimEmbed);CHKERRQ(ierr);
215     ierr = DMSetCoordinateDim(dm,dimEmbed);CHKERRQ(ierr);
216   }
217   PetscFunctionReturn(0);
218 }
219 
220 #undef __FUNCT__
221 #define __FUNCT__ "DMForestGetBaseDM"
222 PetscErrorCode DMForestGetBaseDM(DM dm, DM *base)
223 {
224   DM_Forest      *forest = (DM_Forest *) dm->data;
225 
226   PetscFunctionBegin;
227   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
228   PetscValidPointer(base, 2);
229   *base = forest->base;
230   PetscFunctionReturn(0);
231 }
232 
233 #undef __FUNCT__
234 #define __FUNCT__ "DMForestSetBaseCoordinateMapping"
235 PetscErrorCode DMForestSetBaseCoordinateMapping(DM dm, PetscErrorCode (*func)(PetscInt,const PetscReal [],PetscReal [],void *),void *ctx)
236 {
237   DM_Forest      *forest = (DM_Forest *) dm->data;
238 
239   PetscFunctionBegin;
240   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
241   forest->mapcoordinates = func;
242   forest->mapcoordinatesctx = ctx;
243   PetscFunctionReturn(0);
244 }
245 
246 #undef __FUNCT__
247 #define __FUNCT__ "DMForestGetBaseCoordinateMapping"
248 PetscErrorCode DMForestGetBaseCoordinateMapping(DM dm, PetscErrorCode (**func)(PetscInt,const PetscReal [],PetscReal [],void *),void *ctx)
249 {
250   DM_Forest      *forest = (DM_Forest *) dm->data;
251 
252   PetscFunctionBegin;
253   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
254   if (func) *func = forest->mapcoordinates;
255   if (ctx) *((void **) ctx) = forest->mapcoordinatesctx;
256   PetscFunctionReturn(0);
257 }
258 
259 #undef __FUNCT__
260 #define __FUNCT__ "DMForestSetAdaptivityForest"
261 PetscErrorCode DMForestSetAdaptivityForest(DM dm,DM adapt)
262 {
263   DM_Forest        *forest;
264   PetscErrorCode   ierr;
265 
266   PetscFunctionBegin;
267   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
268   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
269   forest = (DM_Forest *) dm->data;
270   if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the adaptation forest after setup");
271   ierr = PetscObjectReference((PetscObject)adapt);CHKERRQ(ierr);
272   ierr = DMDestroy(&(forest->adapt));CHKERRQ(ierr);
273   forest->adapt = adapt;
274   PetscFunctionReturn(0);
275 }
276 
277 #undef __FUNCT__
278 #define __FUNCT__ "DMForestGetAdaptivityForest"
279 PetscErrorCode DMForestGetAdaptivityForest(DM dm, DM *adapt)
280 {
281   DM_Forest        *forest;
282 
283   PetscFunctionBegin;
284   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
285   forest = (DM_Forest *) dm->data;
286   *adapt = forest->adapt;
287   PetscFunctionReturn(0);
288 }
289 
290 #undef __FUNCT__
291 #define __FUNCT__ "DMForestSetAdjacencyDimension"
292 PetscErrorCode DMForestSetAdjacencyDimension(DM dm, PetscInt adjDim)
293 {
294   PetscInt        dim;
295   DM_Forest      *forest = (DM_Forest *) dm->data;
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 adjacency dimension after setup");
301   if (adjDim < 0) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"adjacency dim cannot be < 0: %d", adjDim);
302   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
303   if (adjDim > dim) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"adjacency dim cannot be > %d: %d", dim, adjDim);
304   forest->adjDim = adjDim;
305   PetscFunctionReturn(0);
306 }
307 
308 #undef __FUNCT__
309 #define __FUNCT__ "DMForestSetAdjacencyCodimension"
310 PetscErrorCode DMForestSetAdjacencyCodimension(DM dm, PetscInt adjCodim)
311 {
312   PetscInt        dim;
313   PetscErrorCode  ierr;
314 
315   PetscFunctionBegin;
316   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
317   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
318   ierr = DMForestSetAdjacencyDimension(dm,dim-adjCodim);CHKERRQ(ierr);
319   PetscFunctionReturn(0);
320 }
321 
322 #undef __FUNCT__
323 #define __FUNCT__ "DMForestGetAdjacencyDimension"
324 PetscErrorCode DMForestGetAdjacencyDimension(DM dm, PetscInt *adjDim)
325 {
326   DM_Forest      *forest = (DM_Forest *) dm->data;
327 
328   PetscFunctionBegin;
329   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
330   PetscValidIntPointer(adjDim,2);
331   *adjDim = forest->adjDim;
332   PetscFunctionReturn(0);
333 }
334 
335 #undef __FUNCT__
336 #define __FUNCT__ "DMForestGetAdjacencyCodimension"
337 PetscErrorCode DMForestGetAdjacencyCodimension(DM dm, PetscInt *adjCodim)
338 {
339   DM_Forest      *forest = (DM_Forest *) dm->data;
340   PetscInt       dim;
341   PetscErrorCode ierr;
342 
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
345   PetscValidIntPointer(adjCodim,2);
346   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
347   *adjCodim = dim - forest->adjDim;
348   PetscFunctionReturn(0);
349 }
350 
351 #undef __FUNCT__
352 #define __FUNCT__ "DMForestSetPartitionOverlap"
353 PetscErrorCode DMForestSetPartitionOverlap(DM dm, PetscInt overlap)
354 {
355   DM_Forest      *forest = (DM_Forest *) dm->data;
356 
357   PetscFunctionBegin;
358   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
359   if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the overlap after setup");
360   if (overlap < 0) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"overlap cannot be < 0: %d", overlap);
361   forest->overlap = overlap;
362   PetscFunctionReturn(0);
363 }
364 
365 #undef __FUNCT__
366 #define __FUNCT__ "DMForestGetPartitionOverlap"
367 PetscErrorCode DMForestGetPartitionOverlap(DM dm, PetscInt *overlap)
368 {
369   DM_Forest      *forest = (DM_Forest *) dm->data;
370 
371   PetscFunctionBegin;
372   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
373   PetscValidIntPointer(overlap,2);
374   *overlap = forest->overlap;
375   PetscFunctionReturn(0);
376 }
377 
378 #undef __FUNCT__
379 #define __FUNCT__ "DMForestSetMinimumRefinement"
380 PetscErrorCode DMForestSetMinimumRefinement(DM dm, PetscInt minRefinement)
381 {
382   DM_Forest      *forest = (DM_Forest *) dm->data;
383 
384   PetscFunctionBegin;
385   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
386   if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the minimum refinement after setup");
387   forest->minRefinement = minRefinement;
388   PetscFunctionReturn(0);
389 }
390 
391 #undef __FUNCT__
392 #define __FUNCT__ "DMForestGetMinimumRefinement"
393 PetscErrorCode DMForestGetMinimumRefinement(DM dm, PetscInt *minRefinement)
394 {
395   DM_Forest      *forest = (DM_Forest *) dm->data;
396 
397   PetscFunctionBegin;
398   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
399   PetscValidIntPointer(minRefinement,2);
400   *minRefinement = forest->minRefinement;
401   PetscFunctionReturn(0);
402 }
403 
404 #undef __FUNCT__
405 #define __FUNCT__ "DMForestSetInitialRefinement"
406 PetscErrorCode DMForestSetInitialRefinement(DM dm, PetscInt initRefinement)
407 {
408   DM_Forest      *forest = (DM_Forest *) dm->data;
409 
410   PetscFunctionBegin;
411   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
412   if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the initial refinement after setup");
413   forest->initRefinement = initRefinement;
414   PetscFunctionReturn(0);
415 }
416 
417 #undef __FUNCT__
418 #define __FUNCT__ "DMForestGetInitialRefinement"
419 PetscErrorCode DMForestGetInitialRefinement(DM dm, PetscInt *initRefinement)
420 {
421   DM_Forest      *forest = (DM_Forest *) dm->data;
422 
423   PetscFunctionBegin;
424   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
425   PetscValidIntPointer(initRefinement,2);
426   *initRefinement = forest->initRefinement;
427   PetscFunctionReturn(0);
428 }
429 
430 #undef __FUNCT__
431 #define __FUNCT__ "DMForestSetMaximumRefinement"
432 PetscErrorCode DMForestSetMaximumRefinement(DM dm, PetscInt maxRefinement)
433 {
434   DM_Forest      *forest = (DM_Forest *) dm->data;
435 
436   PetscFunctionBegin;
437   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
438   if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the maximum refinement after setup");
439   forest->maxRefinement = maxRefinement;
440   PetscFunctionReturn(0);
441 }
442 
443 #undef __FUNCT__
444 #define __FUNCT__ "DMForestGetMaximumRefinement"
445 PetscErrorCode DMForestGetMaximumRefinement(DM dm, PetscInt *maxRefinement)
446 {
447   DM_Forest      *forest = (DM_Forest *) dm->data;
448 
449   PetscFunctionBegin;
450   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
451   PetscValidIntPointer(maxRefinement,2);
452   *maxRefinement = forest->maxRefinement;
453   PetscFunctionReturn(0);
454 }
455 
456 #undef __FUNCT__
457 #define __FUNCT__ "DMForestSetAdaptivityStrategy"
458 PetscErrorCode DMForestSetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy adaptStrategy)
459 {
460   DM_Forest      *forest = (DM_Forest *) dm->data;
461   PetscErrorCode ierr;
462 
463   PetscFunctionBegin;
464   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
465   ierr = PetscFree(forest->adaptStrategy);CHKERRQ(ierr);
466   ierr = PetscStrallocpy((const char *) adaptStrategy,(char **)&forest->adaptStrategy);CHKERRQ(ierr);
467   PetscFunctionReturn(0);
468 }
469 
470 #undef __FUNCT__
471 #define __FUNCT__ "DMForestGetAdaptivityStrategy"
472 PetscErrorCode DMForestGetAdaptivityStrategy(DM dm, DMForestAdaptivityStrategy *adaptStrategy)
473 {
474   DM_Forest      *forest = (DM_Forest *) dm->data;
475 
476   PetscFunctionBegin;
477   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
478   PetscValidPointer(adaptStrategy,2);
479   *adaptStrategy = forest->adaptStrategy;
480   PetscFunctionReturn(0);
481 }
482 
483 #undef __FUNCT__
484 #define __FUNCT__ "DMForestSetGradeFactor"
485 PetscErrorCode DMForestSetGradeFactor(DM dm, PetscInt grade)
486 {
487   DM_Forest      *forest = (DM_Forest *) dm->data;
488 
489   PetscFunctionBegin;
490   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
491   if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the grade factor after setup");
492   forest->gradeFactor = grade;
493   PetscFunctionReturn(0);
494 }
495 
496 #undef __FUNCT__
497 #define __FUNCT__ "DMForestGetGradeFactor"
498 PetscErrorCode DMForestGetGradeFactor(DM dm, PetscInt *grade)
499 {
500   DM_Forest      *forest = (DM_Forest *) dm->data;
501 
502   PetscFunctionBegin;
503   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
504   PetscValidIntPointer(grade,2);
505   *grade = forest->gradeFactor;
506   PetscFunctionReturn(0);
507 }
508 
509 #undef __FUNCT__
510 #define __FUNCT__ "DMForestSetCellWeightFactor"
511 PetscErrorCode DMForestSetCellWeightFactor(DM dm, PetscReal weightsFactor)
512 {
513   DM_Forest      *forest = (DM_Forest *) dm->data;
514 
515   PetscFunctionBegin;
516   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
517   if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the weights factor after setup");
518   forest->weightsFactor = weightsFactor;
519   PetscFunctionReturn(0);
520 }
521 
522 #undef __FUNCT__
523 #define __FUNCT__ "DMForestGetCellWeightFactor"
524 PetscErrorCode DMForestGetCellWeightFactor(DM dm, PetscReal *weightsFactor)
525 {
526   DM_Forest      *forest = (DM_Forest *) dm->data;
527 
528   PetscFunctionBegin;
529   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
530   PetscValidRealPointer(weightsFactor,2);
531   *weightsFactor = forest->weightsFactor;
532   PetscFunctionReturn(0);
533 }
534 
535 #undef __FUNCT__
536 #define __FUNCT__ "DMForestGetCellChart"
537 PetscErrorCode DMForestGetCellChart(DM dm, PetscInt *cStart, PetscInt *cEnd)
538 {
539   DM_Forest      *forest = (DM_Forest *) dm->data;
540   PetscErrorCode ierr;
541 
542   PetscFunctionBegin;
543   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
544   PetscValidIntPointer(cStart,2);
545   PetscValidIntPointer(cEnd,2);
546   if (((forest->cStart == PETSC_DETERMINE) || (forest->cEnd == PETSC_DETERMINE)) && forest->createcellchart) {
547     ierr = forest->createcellchart(dm,&forest->cStart,&forest->cEnd);CHKERRQ(ierr);
548   }
549   *cStart =  forest->cStart;
550   *cEnd   =  forest->cEnd;
551   PetscFunctionReturn(0);
552 }
553 
554 #undef __FUNCT__
555 #define __FUNCT__ "DMForestGetCellSF"
556 PetscErrorCode DMForestGetCellSF(DM dm, PetscSF *cellSF)
557 {
558   DM_Forest      *forest = (DM_Forest *) dm->data;
559   PetscErrorCode ierr;
560 
561   PetscFunctionBegin;
562   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
563   PetscValidPointer(cellSF,2);
564   if ((!forest->cellSF) && forest->createcellsf) {
565     ierr = forest->createcellsf(dm,&forest->cellSF);CHKERRQ(ierr);
566   }
567   *cellSF = forest->cellSF;
568   PetscFunctionReturn(0);
569 }
570 
571 #undef __FUNCT__
572 #define __FUNCT__ "DMForestSetAdaptivityLabel"
573 PetscErrorCode DMForestSetAdaptivityLabel(DM dm, const char * adaptLabel)
574 {
575   DM_Forest      *forest = (DM_Forest *) dm->data;
576   PetscErrorCode ierr;
577 
578   PetscFunctionBegin;
579   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
580   ierr = PetscFree(forest->adaptLabel);CHKERRQ(ierr);
581   ierr = PetscStrallocpy(adaptLabel,&forest->adaptLabel);CHKERRQ(ierr);
582   PetscFunctionReturn(0);
583 }
584 
585 #undef __FUNCT__
586 #define __FUNCT__ "DMForestGetAdaptivityLabel"
587 PetscErrorCode DMForestGetAdaptivityLabel(DM dm, const char ** adaptLabel)
588 {
589   DM_Forest      *forest = (DM_Forest *) dm->data;
590 
591   PetscFunctionBegin;
592   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
593   *adaptLabel = forest->adaptLabel;
594   PetscFunctionReturn(0);
595 }
596 
597 #undef __FUNCT__
598 #define __FUNCT__ "DMForestSetCellWeights"
599 PetscErrorCode DMForestSetCellWeights(DM dm, PetscReal weights[], PetscCopyMode copyMode)
600 {
601   DM_Forest      *forest = (DM_Forest *) dm->data;
602   PetscInt       cStart, cEnd;
603   PetscErrorCode ierr;
604 
605   PetscFunctionBegin;
606   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
607   ierr = DMForestGetCellChart(dm,&cStart,&cEnd);CHKERRQ(ierr);
608   if (cEnd < cStart) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"cell chart [%d,%d) is not valid",cStart,cEnd);
609   if (copyMode == PETSC_COPY_VALUES) {
610     if (forest->cellWeightsCopyMode != PETSC_OWN_POINTER || forest->cellWeights == weights) {
611       ierr = PetscMalloc1(cEnd-cStart,&forest->cellWeights);CHKERRQ(ierr);
612     }
613     ierr = PetscMemcpy(forest->cellWeights,weights,(cEnd-cStart)*sizeof(*weights));CHKERRQ(ierr);
614     forest->cellWeightsCopyMode = PETSC_OWN_POINTER;
615     PetscFunctionReturn(0);
616   }
617   if (forest->cellWeightsCopyMode == PETSC_OWN_POINTER) {
618     ierr = PetscFree(forest->cellWeights);CHKERRQ(ierr);
619   }
620   forest->cellWeights  = weights;
621   forest->cellWeightsCopyMode = copyMode;
622   PetscFunctionReturn(0);
623 }
624 
625 #undef __FUNCT__
626 #define __FUNCT__ "DMForestGetCellWeights"
627 PetscErrorCode DMForestGetCellWeights(DM dm, PetscReal **weights)
628 {
629   DM_Forest      *forest = (DM_Forest *) dm->data;
630 
631   PetscFunctionBegin;
632   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
633   PetscValidPointer(weights,2);
634   *weights = forest->cellWeights;
635   PetscFunctionReturn(0);
636 }
637 
638 #undef __FUNCT__
639 #define __FUNCT__ "DMForestSetWeightCapacity"
640 PetscErrorCode DMForestSetWeightCapacity(DM dm, PetscReal capacity)
641 {
642   DM_Forest      *forest = (DM_Forest *) dm->data;
643 
644   PetscFunctionBegin;
645   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
646   if (dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Cannot change the weight capacity after setup");
647   if (capacity < 0.) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"Cannot have negative weight capacity; %f",capacity);
648   forest->weightCapacity = capacity;
649   PetscFunctionReturn(0);
650 }
651 
652 #undef __FUNCT__
653 #define __FUNCT__ "DMForestGetWeightCapacity"
654 PetscErrorCode DMForestGetWeightCapacity(DM dm, PetscReal *capacity)
655 {
656   DM_Forest      *forest = (DM_Forest *) dm->data;
657 
658   PetscFunctionBegin;
659   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
660   PetscValidRealPointer(capacity,2);
661   *capacity = forest->weightCapacity;
662   PetscFunctionReturn(0);
663 }
664 
665 #undef __FUNCT__
666 #define __FUNCT__ "DMSetFromOptions_Forest"
667 PETSC_EXTERN PetscErrorCode DMSetFromOptions_Forest(PetscOptionItems *PetscOptionsObject,DM dm)
668 {
669   DM_Forest                  *forest = (DM_Forest *) dm->data;
670   PetscBool                  flg, flg1, flg2, flg3, flg4;
671   DMForestTopology           oldTopo;
672   char                       stringBuffer[256];
673   PetscViewer                viewer;
674   PetscViewerFormat          format;
675   PetscInt                   adjDim, adjCodim, overlap, minRefinement, initRefinement, maxRefinement, grade;
676   PetscReal                  weightsFactor;
677   DMForestAdaptivityStrategy adaptStrategy;
678   PetscErrorCode             ierr;
679 
680   PetscFunctionBegin;
681   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
682   forest->setFromOptions = PETSC_TRUE;
683   ierr = DMForestGetTopology(dm, &oldTopo);CHKERRQ(ierr);
684   ierr = PetscOptionsHead(PetscOptionsObject,"DMForest Options");CHKERRQ(ierr);
685   ierr = PetscOptionsString("-dm_forest_topology","the topology of the forest's base mesh","DMForestSetTopology",oldTopo,stringBuffer,256,&flg1);CHKERRQ(ierr);
686   ierr = PetscOptionsViewer("-dm_forest_base_dm","load the base DM from a viewer specification","DMForestSetBaseDM",&viewer,&format,&flg2);CHKERRQ(ierr);
687   ierr = PetscOptionsViewer("-dm_forest_coarse_forest","load the coarse forest from a viewer specification","DMForestSetCoarseForest",&viewer,&format,&flg3);CHKERRQ(ierr);
688   ierr = PetscOptionsViewer("-dm_forest_fine_forest","load the fine forest from a viewer specification","DMForestSetFineForest",&viewer,&format,&flg4);CHKERRQ(ierr);
689   if ((PetscInt) flg1 + (PetscInt) flg2 + (PetscInt) flg3 + (PetscInt) flg4 > 1) {
690     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_INCOMP,"Specify only one of -dm_forest_{topology,base_dm,coarse_forest,fine_forest}");
691   }
692   if (flg1) {
693     ierr = DMForestSetTopology(dm,(DMForestTopology)stringBuffer);CHKERRQ(ierr);
694     ierr = DMForestSetBaseDM(dm,NULL);CHKERRQ(ierr);
695     ierr = DMForestSetAdaptivityForest(dm,NULL);CHKERRQ(ierr);
696   }
697   if (flg2) {
698     DM         base;
699 
700     ierr = DMCreate(PetscObjectComm((PetscObject)dm),&base);CHKERRQ(ierr);
701     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
702     ierr = DMLoad(base,viewer);CHKERRQ(ierr);
703     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
704     ierr = DMForestSetBaseDM(dm,base);CHKERRQ(ierr);
705     ierr = DMDestroy(&base);CHKERRQ(ierr);
706     ierr = DMForestSetTopology(dm,NULL);CHKERRQ(ierr);
707     ierr = DMForestSetAdaptivityForest(dm,NULL);CHKERRQ(ierr);
708   }
709   if (flg3) {
710     DM         coarse;
711 
712     ierr = DMCreate(PetscObjectComm((PetscObject)dm),&coarse);CHKERRQ(ierr);
713     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
714     ierr = DMLoad(coarse,viewer);CHKERRQ(ierr);
715     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
716     ierr = DMForestSetAdaptivityForest(dm,coarse);CHKERRQ(ierr);
717     ierr = DMDestroy(&coarse);CHKERRQ(ierr);
718     ierr = DMForestSetTopology(dm,NULL);CHKERRQ(ierr);
719     ierr = DMForestSetBaseDM(dm,NULL);CHKERRQ(ierr);
720   }
721   if (flg4) {
722     DM         fine;
723 
724     ierr = DMCreate(PetscObjectComm((PetscObject)dm),&fine);CHKERRQ(ierr);
725     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
726     ierr = DMLoad(fine,viewer);CHKERRQ(ierr);
727     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
728     ierr = DMForestSetAdaptivityForest(dm,fine);CHKERRQ(ierr);
729     ierr = DMDestroy(&fine);CHKERRQ(ierr);
730     ierr = DMForestSetTopology(dm,NULL);CHKERRQ(ierr);
731     ierr = DMForestSetBaseDM(dm,NULL);CHKERRQ(ierr);
732   }
733   ierr = DMForestGetAdjacencyDimension(dm,&adjDim);CHKERRQ(ierr);
734   ierr = PetscOptionsInt("-dm_forest_adjacency_dimension","set the dimension of points that define adjacency in the forest","DMForestSetAdjacencyDimension",adjDim,&adjDim,&flg);CHKERRQ(ierr);
735   if (flg) {
736     ierr = DMForestSetAdjacencyDimension(dm,adjDim);CHKERRQ(ierr);
737   }
738   else {
739     ierr = DMForestGetAdjacencyCodimension(dm,&adjCodim);CHKERRQ(ierr);
740     ierr = PetscOptionsInt("-dm_forest_adjacency_codimension","set the codimension of points that define adjacency in the forest","DMForestSetAdjacencyCodimension",adjCodim,&adjCodim,&flg);CHKERRQ(ierr);
741     if (flg) {
742       ierr = DMForestSetAdjacencyCodimension(dm,adjCodim);CHKERRQ(ierr);
743     }
744   }
745   ierr = DMForestGetPartitionOverlap(dm,&overlap);CHKERRQ(ierr);
746   ierr = PetscOptionsInt("-dm_forest_partition_overlap","set the degree of partition overlap","DMForestSetPartitionOverlap",overlap,&overlap,&flg);CHKERRQ(ierr);
747   if (flg) {
748     ierr = DMForestSetPartitionOverlap(dm,overlap);CHKERRQ(ierr);
749   }
750 #if 0
751   ierr = PetscOptionsInt("-dm_refine","equivalent to -dm_forest_set_minimum_refinement and -dm_forest_set_initial_refinement with the same value",NULL,minRefinement,&minRefinement,&flg);CHKERRQ(ierr);
752   if (flg) {
753     ierr = DMForestSetMinimumRefinement(dm,minRefinement);CHKERRQ(ierr);
754     ierr = DMForestSetInitialRefinement(dm,minRefinement);CHKERRQ(ierr);
755   }
756   ierr = PetscOptionsInt("-dm_refine_hierarchy","equivalent to -dm_forest_set_minimum_refinement 0 and -dm_forest_set_initial_refinement",NULL,initRefinement,&initRefinement,&flg);CHKERRQ(ierr);
757   if (flg) {
758     ierr = DMForestSetMinimumRefinement(dm,0);CHKERRQ(ierr);
759     ierr = DMForestSetInitialRefinement(dm,initRefinement);CHKERRQ(ierr);
760   }
761 #endif
762   ierr = DMForestGetMinimumRefinement(dm,&minRefinement);CHKERRQ(ierr);
763   ierr = PetscOptionsInt("-dm_forest_minimum_refinement","set the minimum level of refinement in the forest","DMForestSetMinimumRefinement",minRefinement,&minRefinement,&flg);CHKERRQ(ierr);
764   if (flg) {
765     ierr = DMForestSetMinimumRefinement(dm,minRefinement);CHKERRQ(ierr);
766   }
767   ierr = DMForestGetInitialRefinement(dm,&initRefinement);CHKERRQ(ierr);
768   ierr = PetscOptionsInt("-dm_forest_initial_refinement","set the initial level of refinement in the forest","DMForestSetInitialRefinement",initRefinement,&initRefinement,&flg);CHKERRQ(ierr);
769   if (flg) {
770     ierr = DMForestSetInitialRefinement(dm,initRefinement);CHKERRQ(ierr);
771   }
772   ierr = DMForestGetMaximumRefinement(dm,&maxRefinement);CHKERRQ(ierr);
773   ierr = PetscOptionsInt("-dm_forest_maximum_refinement","set the maximum level of refinement in the forest","DMForestSetMaximumRefinement",maxRefinement,&maxRefinement,&flg);CHKERRQ(ierr);
774   if (flg) {
775     ierr = DMForestSetMaximumRefinement(dm,maxRefinement);CHKERRQ(ierr);
776   }
777   ierr = DMForestGetAdaptivityStrategy(dm,&adaptStrategy);CHKERRQ(ierr);
778   ierr = PetscOptionsString("-dm_forest_adaptivity_strategy","the forest's adaptivity-flag resolution strategy","DMForestSetAdaptivityStrategy",adaptStrategy,stringBuffer,256,&flg);CHKERRQ(ierr);
779   if (flg) {
780     ierr = DMForestSetAdaptivityStrategy(dm,(DMForestAdaptivityStrategy)stringBuffer);CHKERRQ(ierr);
781   }
782   ierr = DMForestGetGradeFactor(dm,&grade);CHKERRQ(ierr);
783   ierr = PetscOptionsInt("-dm_forest_grade_factor","grade factor between neighboring cells","DMForestSetGradeFactor",grade,&grade,&flg);CHKERRQ(ierr);
784   if (flg) {
785     ierr = DMForestSetGradeFactor(dm,grade);CHKERRQ(ierr);
786   }
787   ierr = DMForestGetCellWeightFactor(dm,&weightsFactor);CHKERRQ(ierr);
788   ierr = PetscOptionsReal("-dm_forest_cell_weight_factor","multiplying weight factor for cell refinement","DMForestSetCellWeightFactor",weightsFactor,&weightsFactor,&flg);CHKERRQ(ierr);
789   if (flg) {
790     ierr = DMForestSetCellWeightFactor(dm,weightsFactor);CHKERRQ(ierr);
791   }
792   ierr = PetscOptionsTail();CHKERRQ(ierr);
793   PetscFunctionReturn(0);
794 }
795 
796 #undef __FUNCT__
797 #define __FUNCT__ "DMCreateSubDM_Forest"
798 PetscErrorCode DMCreateSubDM_Forest(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
799 {
800   PetscErrorCode ierr;
801 
802   PetscFunctionBegin;
803   if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);}
804   ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
805   PetscFunctionReturn(0);
806 }
807 
808 #undef __FUNCT__
809 #define __FUNCT__ "DMRefine_Forest"
810 PetscErrorCode DMRefine_Forest(DM dm, MPI_Comm comm, DM *dmRefined)
811 {
812   DMLabel        refine;
813   DM             fineDM;
814   PetscErrorCode ierr;
815 
816   PetscFunctionBegin;
817   ierr = DMGetFineDM(dm,&fineDM);CHKERRQ(ierr);
818   if (fineDM) {
819     ierr = PetscObjectReference((PetscObject)fineDM);CHKERRQ(ierr);
820     *dmRefined = fineDM;
821     PetscFunctionReturn(0);
822   }
823   ierr = DMForestTemplate(dm,comm,dmRefined);CHKERRQ(ierr);
824   ierr = DMGetLabel(dm,"refine",&refine);CHKERRQ(ierr);
825   if (!refine) {
826     ierr = DMCreateLabel(dm,"refine");CHKERRQ(ierr);
827     ierr = DMGetLabel(dm,"refine",&refine);CHKERRQ(ierr);
828     ierr = DMLabelSetDefaultValue(refine,DM_FOREST_REFINE);CHKERRQ(ierr);
829   }
830   ierr = DMForestSetAdaptivityLabel(*dmRefined,"refine");CHKERRQ(ierr);
831   PetscFunctionReturn(0);
832 }
833 
834 #undef __FUNCT__
835 #define __FUNCT__ "DMCoarsen_Forest"
836 PetscErrorCode DMCoarsen_Forest(DM dm, MPI_Comm comm, DM *dmCoarsened)
837 {
838   DMLabel        coarsen;
839   DM             coarseDM;
840   PetscErrorCode ierr;
841 
842   PetscFunctionBegin;
843   ierr = DMGetCoarseDM(dm,&coarseDM);CHKERRQ(ierr);
844   if (coarseDM) {
845     ierr = PetscObjectReference((PetscObject)coarseDM);CHKERRQ(ierr);
846     *dmCoarsened = coarseDM;
847     PetscFunctionReturn(0);
848   }
849   ierr = DMForestTemplate(dm,comm,dmCoarsened);CHKERRQ(ierr);
850   ierr = DMGetLabel(dm,"coarsen",&coarsen);CHKERRQ(ierr);
851   if (!coarsen) {
852     ierr = DMCreateLabel(dm,"coarsen");CHKERRQ(ierr);
853     ierr = DMGetLabel(dm,"coarsen",&coarsen);CHKERRQ(ierr);
854     ierr = DMLabelSetDefaultValue(coarsen,DM_FOREST_COARSEN);CHKERRQ(ierr);
855   }
856   ierr = DMForestSetAdaptivityLabel(*dmCoarsened,"coarsen");CHKERRQ(ierr);
857   PetscFunctionReturn(0);
858 }
859 
860 #undef __FUNCT__
861 #define __FUNCT__ "DMInitialize_Forest"
862 static PetscErrorCode DMInitialize_Forest(DM dm)
863 {
864   PetscErrorCode ierr;
865 
866   PetscFunctionBegin;
867   ierr = PetscMemzero(dm->ops,sizeof(*(dm->ops)));CHKERRQ(ierr);
868 
869   dm->ops->clone          = DMClone_Forest;
870   dm->ops->setfromoptions = DMSetFromOptions_Forest;
871   dm->ops->destroy        = DMDestroy_Forest;
872   dm->ops->createsubdm    = DMCreateSubDM_Forest;
873   dm->ops->refine         = DMRefine_Forest;
874   dm->ops->coarsen        = DMCoarsen_Forest;
875   PetscFunctionReturn(0);
876 }
877 
878 #undef __FUNCT__
879 #define __FUNCT__ "DMCreate_Forest"
880 PETSC_EXTERN PetscErrorCode DMCreate_Forest(DM dm)
881 {
882   DM_Forest      *forest;
883   PetscErrorCode ierr;
884 
885   PetscFunctionBegin;
886   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
887   ierr                        = PetscNewLog(dm,&forest);CHKERRQ(ierr);
888   dm->dim                     = 0;
889   dm->data                    = forest;
890   forest->refct               = 1;
891   forest->data                = NULL;
892   forest->setFromOptions      = PETSC_FALSE;
893   forest->topology            = NULL;
894   forest->base                = NULL;
895   forest->adjDim              = PETSC_DEFAULT;
896   forest->overlap             = PETSC_DEFAULT;
897   forest->minRefinement       = PETSC_DEFAULT;
898   forest->maxRefinement       = PETSC_DEFAULT;
899   forest->initRefinement      = PETSC_DEFAULT;
900   forest->cStart              = PETSC_DETERMINE;
901   forest->cEnd                = PETSC_DETERMINE;
902   forest->cellSF              = 0;
903   forest->adaptLabel          = NULL;
904   forest->gradeFactor         = 2;
905   forest->cellWeights         = NULL;
906   forest->cellWeightsCopyMode = PETSC_USE_POINTER;
907   forest->weightsFactor       = 1.;
908   forest->weightCapacity      = 1.;
909   ierr = DMForestSetAdaptivityStrategy(dm,DMFORESTADAPTALL);CHKERRQ(ierr);
910   ierr = DMInitialize_Forest(dm);CHKERRQ(ierr);
911   PetscFunctionReturn(0);
912 }
913 
914