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