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