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