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