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