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