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