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