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