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