xref: /petsc/src/dm/interface/dm.c (revision 13bffc4c19c2998a938fbad31aa63d4d9e91fb7b)
1 #include <petsc/private/dmimpl.h>     /*I      "petscdm.h"     I*/
2 #include <petscsf.h>
3 #include <petscds.h>
4 
5 PetscClassId  DM_CLASSID;
6 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_CreateInterpolation;
7 
8 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0};
9 
10 #undef __FUNCT__
11 #define __FUNCT__ "DMCreate"
12 /*@
13   DMCreate - Creates an empty DM object. The type can then be set with DMSetType().
14 
15    If you never  call DMSetType()  it will generate an
16    error when you try to use the vector.
17 
18   Collective on MPI_Comm
19 
20   Input Parameter:
21 . comm - The communicator for the DM object
22 
23   Output Parameter:
24 . dm - The DM object
25 
26   Level: beginner
27 
28 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK
29 @*/
30 PetscErrorCode  DMCreate(MPI_Comm comm,DM *dm)
31 {
32   DM             v;
33   PetscErrorCode ierr;
34 
35   PetscFunctionBegin;
36   PetscValidPointer(dm,2);
37   *dm = NULL;
38   ierr = PetscSysInitializePackage();CHKERRQ(ierr);
39   ierr = VecInitializePackage();CHKERRQ(ierr);
40   ierr = MatInitializePackage();CHKERRQ(ierr);
41   ierr = DMInitializePackage();CHKERRQ(ierr);
42 
43   ierr = PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr);
44 
45   v->ltogmap                  = NULL;
46   v->bs                       = 1;
47   v->coloringtype             = IS_COLORING_GLOBAL;
48   ierr                        = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr);
49   ierr                        = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr);
50   v->defaultSection           = NULL;
51   v->defaultGlobalSection     = NULL;
52   v->defaultConstraintSection = NULL;
53   v->defaultConstraintMat     = NULL;
54   v->L                        = NULL;
55   v->maxCell                  = NULL;
56   v->bdtype                   = NULL;
57   v->dimEmbed                 = PETSC_DEFAULT;
58   {
59     PetscInt i;
60     for (i = 0; i < 10; ++i) {
61       v->nullspaceConstructors[i] = NULL;
62     }
63   }
64   ierr = PetscDSCreate(comm, &v->prob);CHKERRQ(ierr);
65   v->dmBC = NULL;
66   v->outputSequenceNum = -1;
67   v->outputSequenceVal = 0.0;
68   ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr);
69   ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr);
70   *dm = v;
71   PetscFunctionReturn(0);
72 }
73 
74 #undef __FUNCT__
75 #define __FUNCT__ "DMClone"
76 /*@
77   DMClone - Creates a DM object with the same topology as the original.
78 
79   Collective on MPI_Comm
80 
81   Input Parameter:
82 . dm - The original DM object
83 
84   Output Parameter:
85 . newdm  - The new DM object
86 
87   Level: beginner
88 
89 .keywords: DM, topology, create
90 @*/
91 PetscErrorCode DMClone(DM dm, DM *newdm)
92 {
93   PetscSF        sf;
94   Vec            coords;
95   void          *ctx;
96   PetscInt       dim;
97   PetscErrorCode ierr;
98 
99   PetscFunctionBegin;
100   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101   PetscValidPointer(newdm,2);
102   ierr = DMCreate(PetscObjectComm((PetscObject)dm), newdm);CHKERRQ(ierr);
103   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
104   ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr);
105   if (dm->ops->clone) {
106     ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr);
107   }
108   (*newdm)->setupcalled = PETSC_TRUE;
109   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
110   ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr);
111   ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr);
112   ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr);
113   if (dm->coordinateDM) {
114     DM           ncdm;
115     PetscSection cs;
116     PetscInt     pEnd = -1;
117 
118     ierr = DMGetDefaultSection(dm->coordinateDM, &cs);CHKERRQ(ierr);
119     if (cs) {ierr = PetscSectionGetChart(cs, NULL, &pEnd);CHKERRQ(ierr);}
120     if (pEnd >= 0) {
121       ierr = DMClone(dm->coordinateDM, &ncdm);CHKERRQ(ierr);
122       ierr = DMSetCoordinateDM(*newdm, ncdm);CHKERRQ(ierr);
123       ierr = DMSetDefaultSection(ncdm, cs);CHKERRQ(ierr);
124       ierr = DMDestroy(&ncdm);CHKERRQ(ierr);
125     }
126   }
127   ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr);
128   if (coords) {
129     ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr);
130   } else {
131     ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr);
132     if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);}
133   }
134   if (dm->maxCell) {
135     const PetscReal *maxCell, *L;
136     const DMBoundaryType *bd;
137     ierr = DMGetPeriodicity(dm,     &maxCell, &L, &bd);CHKERRQ(ierr);
138     ierr = DMSetPeriodicity(*newdm,  maxCell,  L,  bd);CHKERRQ(ierr);
139   }
140   PetscFunctionReturn(0);
141 }
142 
143 #undef __FUNCT__
144 #define __FUNCT__ "DMSetVecType"
145 /*@C
146        DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
147 
148    Logically Collective on DM
149 
150    Input Parameter:
151 +  da - initial distributed array
152 .  ctype - the vector type, currently either VECSTANDARD or VECCUSP
153 
154    Options Database:
155 .   -dm_vec_type ctype
156 
157    Level: intermediate
158 
159 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType()
160 @*/
161 PetscErrorCode  DMSetVecType(DM da,VecType ctype)
162 {
163   PetscErrorCode ierr;
164 
165   PetscFunctionBegin;
166   PetscValidHeaderSpecific(da,DM_CLASSID,1);
167   ierr = PetscFree(da->vectype);CHKERRQ(ierr);
168   ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr);
169   PetscFunctionReturn(0);
170 }
171 
172 #undef __FUNCT__
173 #define __FUNCT__ "DMGetVecType"
174 /*@C
175        DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector()
176 
177    Logically Collective on DM
178 
179    Input Parameter:
180 .  da - initial distributed array
181 
182    Output Parameter:
183 .  ctype - the vector type
184 
185    Level: intermediate
186 
187 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType
188 @*/
189 PetscErrorCode  DMGetVecType(DM da,VecType *ctype)
190 {
191   PetscFunctionBegin;
192   PetscValidHeaderSpecific(da,DM_CLASSID,1);
193   *ctype = da->vectype;
194   PetscFunctionReturn(0);
195 }
196 
197 #undef __FUNCT__
198 #define __FUNCT__ "VecGetDM"
199 /*@
200   VecGetDM - Gets the DM defining the data layout of the vector
201 
202   Not collective
203 
204   Input Parameter:
205 . v - The Vec
206 
207   Output Parameter:
208 . dm - The DM
209 
210   Level: intermediate
211 
212 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
213 @*/
214 PetscErrorCode VecGetDM(Vec v, DM *dm)
215 {
216   PetscErrorCode ierr;
217 
218   PetscFunctionBegin;
219   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
220   PetscValidPointer(dm,2);
221   ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr);
222   PetscFunctionReturn(0);
223 }
224 
225 #undef __FUNCT__
226 #define __FUNCT__ "VecSetDM"
227 /*@
228   VecSetDM - Sets the DM defining the data layout of the vector.
229 
230   Not collective
231 
232   Input Parameters:
233 + v - The Vec
234 - dm - The DM
235 
236   Note: This is NOT the same as DMCreateGlobalVector() since it does not change the view methods or perform other customization, but merely sets the DM member.
237 
238   Level: intermediate
239 
240 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType()
241 @*/
242 PetscErrorCode VecSetDM(Vec v, DM dm)
243 {
244   PetscErrorCode ierr;
245 
246   PetscFunctionBegin;
247   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
248   if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2);
249   ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr);
250   PetscFunctionReturn(0);
251 }
252 
253 #undef __FUNCT__
254 #define __FUNCT__ "DMSetMatType"
255 /*@C
256        DMSetMatType - Sets the type of matrix created with DMCreateMatrix()
257 
258    Logically Collective on DM
259 
260    Input Parameter:
261 +  dm - the DM context
262 .  ctype - the matrix type
263 
264    Options Database:
265 .   -dm_mat_type ctype
266 
267    Level: intermediate
268 
269 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType()
270 @*/
271 PetscErrorCode  DMSetMatType(DM dm,MatType ctype)
272 {
273   PetscErrorCode ierr;
274 
275   PetscFunctionBegin;
276   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
277   ierr = PetscFree(dm->mattype);CHKERRQ(ierr);
278   ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr);
279   PetscFunctionReturn(0);
280 }
281 
282 #undef __FUNCT__
283 #define __FUNCT__ "DMGetMatType"
284 /*@C
285        DMGetMatType - Gets the type of matrix created with DMCreateMatrix()
286 
287    Logically Collective on DM
288 
289    Input Parameter:
290 .  dm - the DM context
291 
292    Output Parameter:
293 .  ctype - the matrix type
294 
295    Options Database:
296 .   -dm_mat_type ctype
297 
298    Level: intermediate
299 
300 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType()
301 @*/
302 PetscErrorCode  DMGetMatType(DM dm,MatType *ctype)
303 {
304   PetscFunctionBegin;
305   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
306   *ctype = dm->mattype;
307   PetscFunctionReturn(0);
308 }
309 
310 #undef __FUNCT__
311 #define __FUNCT__ "MatGetDM"
312 /*@
313   MatGetDM - Gets the DM defining the data layout of the matrix
314 
315   Not collective
316 
317   Input Parameter:
318 . A - The Mat
319 
320   Output Parameter:
321 . dm - The DM
322 
323   Level: intermediate
324 
325 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType()
326 @*/
327 PetscErrorCode MatGetDM(Mat A, DM *dm)
328 {
329   PetscErrorCode ierr;
330 
331   PetscFunctionBegin;
332   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
333   PetscValidPointer(dm,2);
334   ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr);
335   PetscFunctionReturn(0);
336 }
337 
338 #undef __FUNCT__
339 #define __FUNCT__ "MatSetDM"
340 /*@
341   MatSetDM - Sets the DM defining the data layout of the matrix
342 
343   Not collective
344 
345   Input Parameters:
346 + A - The Mat
347 - dm - The DM
348 
349   Level: intermediate
350 
351 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType()
352 @*/
353 PetscErrorCode MatSetDM(Mat A, DM dm)
354 {
355   PetscErrorCode ierr;
356 
357   PetscFunctionBegin;
358   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
359   if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2);
360   ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr);
361   PetscFunctionReturn(0);
362 }
363 
364 #undef __FUNCT__
365 #define __FUNCT__ "DMSetOptionsPrefix"
366 /*@C
367    DMSetOptionsPrefix - Sets the prefix used for searching for all
368    DM options in the database.
369 
370    Logically Collective on DM
371 
372    Input Parameter:
373 +  da - the DM context
374 -  prefix - the prefix to prepend to all option names
375 
376    Notes:
377    A hyphen (-) must NOT be given at the beginning of the prefix name.
378    The first character of all runtime options is AUTOMATICALLY the hyphen.
379 
380    Level: advanced
381 
382 .keywords: DM, set, options, prefix, database
383 
384 .seealso: DMSetFromOptions()
385 @*/
386 PetscErrorCode  DMSetOptionsPrefix(DM dm,const char prefix[])
387 {
388   PetscErrorCode ierr;
389 
390   PetscFunctionBegin;
391   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
392   ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
393   if (dm->sf) {
394     ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);CHKERRQ(ierr);
395   }
396   if (dm->defaultSF) {
397     ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->defaultSF,prefix);CHKERRQ(ierr);
398   }
399   PetscFunctionReturn(0);
400 }
401 
402 #undef __FUNCT__
403 #define __FUNCT__ "DMAppendOptionsPrefix"
404 /*@C
405    DMAppendOptionsPrefix - Appends to the prefix used for searching for all
406    DM options in the database.
407 
408    Logically Collective on DM
409 
410    Input Parameters:
411 +  dm - the DM context
412 -  prefix - the prefix string to prepend to all DM option requests
413 
414    Notes:
415    A hyphen (-) must NOT be given at the beginning of the prefix name.
416    The first character of all runtime options is AUTOMATICALLY the hyphen.
417 
418    Level: advanced
419 
420 .keywords: DM, append, options, prefix, database
421 
422 .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix()
423 @*/
424 PetscErrorCode  DMAppendOptionsPrefix(DM dm,const char prefix[])
425 {
426   PetscErrorCode ierr;
427 
428   PetscFunctionBegin;
429   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
430   ierr = PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
431   PetscFunctionReturn(0);
432 }
433 
434 #undef __FUNCT__
435 #define __FUNCT__ "DMGetOptionsPrefix"
436 /*@C
437    DMGetOptionsPrefix - Gets the prefix used for searching for all
438    DM options in the database.
439 
440    Not Collective
441 
442    Input Parameters:
443 .  dm - the DM context
444 
445    Output Parameters:
446 .  prefix - pointer to the prefix string used is returned
447 
448    Notes: On the fortran side, the user should pass in a string 'prefix' of
449    sufficient length to hold the prefix.
450 
451    Level: advanced
452 
453 .keywords: DM, set, options, prefix, database
454 
455 .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix()
456 @*/
457 PetscErrorCode  DMGetOptionsPrefix(DM dm,const char *prefix[])
458 {
459   PetscErrorCode ierr;
460 
461   PetscFunctionBegin;
462   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
463   ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr);
464   PetscFunctionReturn(0);
465 }
466 
467 #undef __FUNCT__
468 #define __FUNCT__ "DMDestroy"
469 /*@
470     DMDestroy - Destroys a vector packer or DM.
471 
472     Collective on DM
473 
474     Input Parameter:
475 .   dm - the DM object to destroy
476 
477     Level: developer
478 
479 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
480 
481 @*/
482 PetscErrorCode  DMDestroy(DM *dm)
483 {
484   PetscInt       i, cnt = 0;
485   DMNamedVecLink nlink,nnext;
486   PetscErrorCode ierr;
487 
488   PetscFunctionBegin;
489   if (!*dm) PetscFunctionReturn(0);
490   PetscValidHeaderSpecific((*dm),DM_CLASSID,1);
491 
492   /* count all the circular references of DM and its contained Vecs */
493   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
494     if ((*dm)->localin[i])  cnt++;
495     if ((*dm)->globalin[i]) cnt++;
496   }
497   for (nlink=(*dm)->namedglobal; nlink; nlink=nlink->next) cnt++;
498   for (nlink=(*dm)->namedlocal; nlink; nlink=nlink->next) cnt++;
499   if ((*dm)->x) {
500     DM obj;
501     ierr = VecGetDM((*dm)->x, &obj);CHKERRQ(ierr);
502     if (obj == *dm) cnt++;
503   }
504 
505   if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; PetscFunctionReturn(0);}
506   /*
507      Need this test because the dm references the vectors that
508      reference the dm, so destroying the dm calls destroy on the
509      vectors that cause another destroy on the dm
510   */
511   if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0);
512   ((PetscObject) (*dm))->refct = 0;
513   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
514     if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()");
515     ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr);
516   }
517   nnext=(*dm)->namedglobal;
518   (*dm)->namedglobal = NULL;
519   for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */
520     nnext = nlink->next;
521     if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
522     ierr = PetscFree(nlink->name);CHKERRQ(ierr);
523     ierr = VecDestroy(&nlink->X);CHKERRQ(ierr);
524     ierr = PetscFree(nlink);CHKERRQ(ierr);
525   }
526   nnext=(*dm)->namedlocal;
527   (*dm)->namedlocal = NULL;
528   for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */
529     nnext = nlink->next;
530     if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name);
531     ierr = PetscFree(nlink->name);CHKERRQ(ierr);
532     ierr = VecDestroy(&nlink->X);CHKERRQ(ierr);
533     ierr = PetscFree(nlink);CHKERRQ(ierr);
534   }
535 
536   /* Destroy the list of hooks */
537   {
538     DMCoarsenHookLink link,next;
539     for (link=(*dm)->coarsenhook; link; link=next) {
540       next = link->next;
541       ierr = PetscFree(link);CHKERRQ(ierr);
542     }
543     (*dm)->coarsenhook = NULL;
544   }
545   {
546     DMRefineHookLink link,next;
547     for (link=(*dm)->refinehook; link; link=next) {
548       next = link->next;
549       ierr = PetscFree(link);CHKERRQ(ierr);
550     }
551     (*dm)->refinehook = NULL;
552   }
553   {
554     DMSubDomainHookLink link,next;
555     for (link=(*dm)->subdomainhook; link; link=next) {
556       next = link->next;
557       ierr = PetscFree(link);CHKERRQ(ierr);
558     }
559     (*dm)->subdomainhook = NULL;
560   }
561   {
562     DMGlobalToLocalHookLink link,next;
563     for (link=(*dm)->gtolhook; link; link=next) {
564       next = link->next;
565       ierr = PetscFree(link);CHKERRQ(ierr);
566     }
567     (*dm)->gtolhook = NULL;
568   }
569   {
570     DMLocalToGlobalHookLink link,next;
571     for (link=(*dm)->ltoghook; link; link=next) {
572       next = link->next;
573       ierr = PetscFree(link);CHKERRQ(ierr);
574     }
575     (*dm)->ltoghook = NULL;
576   }
577   /* Destroy the work arrays */
578   {
579     DMWorkLink link,next;
580     if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out");
581     for (link=(*dm)->workin; link; link=next) {
582       next = link->next;
583       ierr = PetscFree(link->mem);CHKERRQ(ierr);
584       ierr = PetscFree(link);CHKERRQ(ierr);
585     }
586     (*dm)->workin = NULL;
587   }
588 
589   ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr);
590   ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr);
591   ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr);
592 
593   if ((*dm)->ctx && (*dm)->ctxdestroy) {
594     ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr);
595   }
596   ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr);
597   ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr);
598   ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr);
599   ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr);
600   ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr);
601   ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr);
602 
603   ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr);
604   ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr);
605   ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr);
606   ierr = PetscSectionDestroy(&(*dm)->defaultConstraintSection);CHKERRQ(ierr);
607   ierr = MatDestroy(&(*dm)->defaultConstraintMat);CHKERRQ(ierr);
608   ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr);
609   ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr);
610   ierr = PetscSFDestroy(&(*dm)->sfNatural);CHKERRQ(ierr);
611 
612   ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr);
613   ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr);
614   ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr);
615   ierr = PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);CHKERRQ(ierr);
616 
617   ierr = PetscDSDestroy(&(*dm)->prob);CHKERRQ(ierr);
618   ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr);
619   /* if memory was published with SAWs then destroy it */
620   ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr);
621 
622   ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr);
623   /* We do not destroy (*dm)->data here so that we can reference count backend objects */
624   ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr);
625   PetscFunctionReturn(0);
626 }
627 
628 #undef __FUNCT__
629 #define __FUNCT__ "DMSetUp"
630 /*@
631     DMSetUp - sets up the data structures inside a DM object
632 
633     Collective on DM
634 
635     Input Parameter:
636 .   dm - the DM object to setup
637 
638     Level: developer
639 
640 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
641 
642 @*/
643 PetscErrorCode  DMSetUp(DM dm)
644 {
645   PetscErrorCode ierr;
646 
647   PetscFunctionBegin;
648   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
649   if (dm->setupcalled) PetscFunctionReturn(0);
650   if (dm->ops->setup) {
651     ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr);
652   }
653   dm->setupcalled = PETSC_TRUE;
654   PetscFunctionReturn(0);
655 }
656 
657 #undef __FUNCT__
658 #define __FUNCT__ "DMSetFromOptions"
659 /*@
660     DMSetFromOptions - sets parameters in a DM from the options database
661 
662     Collective on DM
663 
664     Input Parameter:
665 .   dm - the DM object to set options for
666 
667     Options Database:
668 +   -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros
669 .   -dm_vec_type <type>  - type of vector to create inside DM
670 .   -dm_mat_type <type>  - type of matrix to create inside DM
671 -   -dm_coloring_type    - <global or ghosted>
672 
673     Level: developer
674 
675 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
676 
677 @*/
678 PetscErrorCode  DMSetFromOptions(DM dm)
679 {
680   char           typeName[256];
681   PetscBool      flg;
682   PetscErrorCode ierr;
683 
684   PetscFunctionBegin;
685   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
686   if (dm->sf) {
687     ierr = PetscSFSetFromOptions(dm->sf);CHKERRQ(ierr);
688   }
689   if (dm->defaultSF) {
690     ierr = PetscSFSetFromOptions(dm->defaultSF);CHKERRQ(ierr);
691   }
692   ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr);
693   ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr);
694   ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr);
695   if (flg) {
696     ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr);
697   }
698   ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr);
699   if (flg) {
700     ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr);
701   }
702   ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr);
703   if (dm->ops->setfromoptions) {
704     ierr = (*dm->ops->setfromoptions)(PetscOptionsObject,dm);CHKERRQ(ierr);
705   }
706   /* process any options handlers added with PetscObjectAddOptionsHandler() */
707   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);CHKERRQ(ierr);
708   ierr = PetscOptionsEnd();CHKERRQ(ierr);
709   PetscFunctionReturn(0);
710 }
711 
712 #undef __FUNCT__
713 #define __FUNCT__ "DMView"
714 /*@C
715     DMView - Views a DM
716 
717     Collective on DM
718 
719     Input Parameter:
720 +   dm - the DM object to view
721 -   v - the viewer
722 
723     Level: beginner
724 
725 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
726 
727 @*/
728 PetscErrorCode  DMView(DM dm,PetscViewer v)
729 {
730   PetscErrorCode ierr;
731   PetscBool      isbinary;
732 
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
735   if (!v) {
736     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr);
737   }
738   ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr);
739   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
740   if (isbinary) {
741     PetscInt classid = DM_FILE_CLASSID;
742     char     type[256];
743 
744     ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
745     ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr);
746     ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
747   }
748   if (dm->ops->view) {
749     ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr);
750   }
751   PetscFunctionReturn(0);
752 }
753 
754 #undef __FUNCT__
755 #define __FUNCT__ "DMCreateGlobalVector"
756 /*@
757     DMCreateGlobalVector - Creates a global vector from a DM object
758 
759     Collective on DM
760 
761     Input Parameter:
762 .   dm - the DM object
763 
764     Output Parameter:
765 .   vec - the global vector
766 
767     Level: beginner
768 
769 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
770 
771 @*/
772 PetscErrorCode  DMCreateGlobalVector(DM dm,Vec *vec)
773 {
774   PetscErrorCode ierr;
775 
776   PetscFunctionBegin;
777   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
778   ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr);
779   PetscFunctionReturn(0);
780 }
781 
782 #undef __FUNCT__
783 #define __FUNCT__ "DMCreateLocalVector"
784 /*@
785     DMCreateLocalVector - Creates a local vector from a DM object
786 
787     Not Collective
788 
789     Input Parameter:
790 .   dm - the DM object
791 
792     Output Parameter:
793 .   vec - the local vector
794 
795     Level: beginner
796 
797 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
798 
799 @*/
800 PetscErrorCode  DMCreateLocalVector(DM dm,Vec *vec)
801 {
802   PetscErrorCode ierr;
803 
804   PetscFunctionBegin;
805   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
806   ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr);
807   PetscFunctionReturn(0);
808 }
809 
810 #undef __FUNCT__
811 #define __FUNCT__ "DMGetLocalToGlobalMapping"
812 /*@
813    DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM.
814 
815    Collective on DM
816 
817    Input Parameter:
818 .  dm - the DM that provides the mapping
819 
820    Output Parameter:
821 .  ltog - the mapping
822 
823    Level: intermediate
824 
825    Notes:
826    This mapping can then be used by VecSetLocalToGlobalMapping() or
827    MatSetLocalToGlobalMapping().
828 
829 .seealso: DMCreateLocalVector()
830 @*/
831 PetscErrorCode  DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog)
832 {
833   PetscErrorCode ierr;
834 
835   PetscFunctionBegin;
836   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
837   PetscValidPointer(ltog,2);
838   if (!dm->ltogmap) {
839     PetscSection section, sectionGlobal;
840 
841     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
842     if (section) {
843       PetscInt *ltog;
844       PetscInt pStart, pEnd, size, p, l;
845 
846       ierr = DMGetDefaultGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
847       ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
848       ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
849       ierr = PetscMalloc1(size, &ltog);CHKERRQ(ierr); /* We want the local+overlap size */
850       for (p = pStart, l = 0; p < pEnd; ++p) {
851         PetscInt dof, off, c;
852 
853         /* Should probably use constrained dofs */
854         ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
855         ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr);
856         for (c = 0; c < dof; ++c, ++l) {
857           ltog[l] = off+c;
858         }
859       }
860       ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1,size, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr);
861       ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr);
862     } else {
863       if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping");
864       ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr);
865     }
866   }
867   *ltog = dm->ltogmap;
868   PetscFunctionReturn(0);
869 }
870 
871 #undef __FUNCT__
872 #define __FUNCT__ "DMGetBlockSize"
873 /*@
874    DMGetBlockSize - Gets the inherent block size associated with a DM
875 
876    Not Collective
877 
878    Input Parameter:
879 .  dm - the DM with block structure
880 
881    Output Parameter:
882 .  bs - the block size, 1 implies no exploitable block structure
883 
884    Level: intermediate
885 
886 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping()
887 @*/
888 PetscErrorCode  DMGetBlockSize(DM dm,PetscInt *bs)
889 {
890   PetscFunctionBegin;
891   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
892   PetscValidPointer(bs,2);
893   if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet");
894   *bs = dm->bs;
895   PetscFunctionReturn(0);
896 }
897 
898 #undef __FUNCT__
899 #define __FUNCT__ "DMCreateInterpolation"
900 /*@
901     DMCreateInterpolation - Gets interpolation matrix between two DM objects
902 
903     Collective on DM
904 
905     Input Parameter:
906 +   dm1 - the DM object
907 -   dm2 - the second, finer DM object
908 
909     Output Parameter:
910 +  mat - the interpolation
911 -  vec - the scaling (optional)
912 
913     Level: developer
914 
915     Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
916         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation.
917 
918         For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors
919         EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
920 
921 
922 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen()
923 
924 @*/
925 PetscErrorCode  DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec)
926 {
927   PetscErrorCode ierr;
928 
929   PetscFunctionBegin;
930   PetscValidHeaderSpecific(dm1,DM_CLASSID,1);
931   PetscValidHeaderSpecific(dm2,DM_CLASSID,2);
932   ierr = PetscLogEventBegin(DM_CreateInterpolation,dm1,dm2,0,0);CHKERRQ(ierr);
933   ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr);
934   ierr = PetscLogEventEnd(DM_CreateInterpolation,dm1,dm2,0,0);CHKERRQ(ierr);
935   PetscFunctionReturn(0);
936 }
937 
938 #undef __FUNCT__
939 #define __FUNCT__ "DMCreateInjection"
940 /*@
941     DMCreateInjection - Gets injection matrix between two DM objects
942 
943     Collective on DM
944 
945     Input Parameter:
946 +   dm1 - the DM object
947 -   dm2 - the second, finer DM object
948 
949     Output Parameter:
950 .   mat - the injection
951 
952     Level: developer
953 
954    Notes:  For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by
955         DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection.
956 
957 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation()
958 
959 @*/
960 PetscErrorCode  DMCreateInjection(DM dm1,DM dm2,Mat *mat)
961 {
962   PetscErrorCode ierr;
963 
964   PetscFunctionBegin;
965   PetscValidHeaderSpecific(dm1,DM_CLASSID,1);
966   PetscValidHeaderSpecific(dm2,DM_CLASSID,2);
967   ierr = (*dm1->ops->getinjection)(dm1,dm2,mat);CHKERRQ(ierr);
968   PetscFunctionReturn(0);
969 }
970 
971 #undef __FUNCT__
972 #define __FUNCT__ "DMCreateColoring"
973 /*@
974     DMCreateColoring - Gets coloring for a DM
975 
976     Collective on DM
977 
978     Input Parameter:
979 +   dm - the DM object
980 -   ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL
981 
982     Output Parameter:
983 .   coloring - the coloring
984 
985     Level: developer
986 
987 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType()
988 
989 @*/
990 PetscErrorCode  DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring)
991 {
992   PetscErrorCode ierr;
993 
994   PetscFunctionBegin;
995   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
996   if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet");
997   ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr);
998   PetscFunctionReturn(0);
999 }
1000 
1001 #undef __FUNCT__
1002 #define __FUNCT__ "DMCreateMatrix"
1003 /*@
1004     DMCreateMatrix - Gets empty Jacobian for a DM
1005 
1006     Collective on DM
1007 
1008     Input Parameter:
1009 .   dm - the DM object
1010 
1011     Output Parameter:
1012 .   mat - the empty Jacobian
1013 
1014     Level: beginner
1015 
1016     Notes: This properly preallocates the number of nonzeros in the sparse matrix so you
1017        do not need to do it yourself.
1018 
1019        By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1020        the nonzero pattern call DMDASetMatPreallocateOnly()
1021 
1022        For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used
1023        internally by PETSc.
1024 
1025        For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires
1026        the indices for the global numbering for DMDAs which is complicated.
1027 
1028 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType()
1029 
1030 @*/
1031 PetscErrorCode  DMCreateMatrix(DM dm,Mat *mat)
1032 {
1033   PetscErrorCode ierr;
1034 
1035   PetscFunctionBegin;
1036   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1037   ierr = MatInitializePackage();CHKERRQ(ierr);
1038   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1039   PetscValidPointer(mat,3);
1040   ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr);
1041   PetscFunctionReturn(0);
1042 }
1043 
1044 #undef __FUNCT__
1045 #define __FUNCT__ "DMSetMatrixPreallocateOnly"
1046 /*@
1047   DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly
1048     preallocated but the nonzero structure and zero values will not be set.
1049 
1050   Logically Collective on DM
1051 
1052   Input Parameter:
1053 + dm - the DM
1054 - only - PETSC_TRUE if only want preallocation
1055 
1056   Level: developer
1057 .seealso DMCreateMatrix()
1058 @*/
1059 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1060 {
1061   PetscFunctionBegin;
1062   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1063   dm->prealloc_only = only;
1064   PetscFunctionReturn(0);
1065 }
1066 
1067 #undef __FUNCT__
1068 #define __FUNCT__ "DMGetWorkArray"
1069 /*@C
1070   DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1071 
1072   Not Collective
1073 
1074   Input Parameters:
1075 + dm - the DM object
1076 . count - The minium size
1077 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT)
1078 
1079   Output Parameter:
1080 . array - the work array
1081 
1082   Level: developer
1083 
1084 .seealso DMDestroy(), DMCreate()
1085 @*/
1086 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem)
1087 {
1088   PetscErrorCode ierr;
1089   DMWorkLink     link;
1090   size_t         dsize;
1091 
1092   PetscFunctionBegin;
1093   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1094   PetscValidPointer(mem,4);
1095   if (dm->workin) {
1096     link       = dm->workin;
1097     dm->workin = dm->workin->next;
1098   } else {
1099     ierr = PetscNewLog(dm,&link);CHKERRQ(ierr);
1100   }
1101   ierr = PetscDataTypeGetSize(dtype,&dsize);CHKERRQ(ierr);
1102   if (dsize*count > link->bytes) {
1103     ierr        = PetscFree(link->mem);CHKERRQ(ierr);
1104     ierr        = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr);
1105     link->bytes = dsize*count;
1106   }
1107   link->next   = dm->workout;
1108   dm->workout  = link;
1109   *(void**)mem = link->mem;
1110   PetscFunctionReturn(0);
1111 }
1112 
1113 #undef __FUNCT__
1114 #define __FUNCT__ "DMRestoreWorkArray"
1115 /*@C
1116   DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray()
1117 
1118   Not Collective
1119 
1120   Input Parameters:
1121 + dm - the DM object
1122 . count - The minium size
1123 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT)
1124 
1125   Output Parameter:
1126 . array - the work array
1127 
1128   Level: developer
1129 
1130 .seealso DMDestroy(), DMCreate()
1131 @*/
1132 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem)
1133 {
1134   DMWorkLink *p,link;
1135 
1136   PetscFunctionBegin;
1137   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1138   PetscValidPointer(mem,4);
1139   for (p=&dm->workout; (link=*p); p=&link->next) {
1140     if (link->mem == *(void**)mem) {
1141       *p           = link->next;
1142       link->next   = dm->workin;
1143       dm->workin   = link;
1144       *(void**)mem = NULL;
1145       PetscFunctionReturn(0);
1146     }
1147   }
1148   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out");
1149 }
1150 
1151 #undef __FUNCT__
1152 #define __FUNCT__ "DMSetNullSpaceConstructor"
1153 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace))
1154 {
1155   PetscFunctionBegin;
1156   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1157   if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field);
1158   dm->nullspaceConstructors[field] = nullsp;
1159   PetscFunctionReturn(0);
1160 }
1161 
1162 #undef __FUNCT__
1163 #define __FUNCT__ "DMCreateFieldIS"
1164 /*@C
1165   DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field
1166 
1167   Not collective
1168 
1169   Input Parameter:
1170 . dm - the DM object
1171 
1172   Output Parameters:
1173 + numFields  - The number of fields (or NULL if not requested)
1174 . fieldNames - The name for each field (or NULL if not requested)
1175 - fields     - The global indices for each field (or NULL if not requested)
1176 
1177   Level: intermediate
1178 
1179   Notes:
1180   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1181   PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with
1182   PetscFree().
1183 
1184 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix()
1185 @*/
1186 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1187 {
1188   PetscSection   section, sectionGlobal;
1189   PetscErrorCode ierr;
1190 
1191   PetscFunctionBegin;
1192   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1193   if (numFields) {
1194     PetscValidPointer(numFields,2);
1195     *numFields = 0;
1196   }
1197   if (fieldNames) {
1198     PetscValidPointer(fieldNames,3);
1199     *fieldNames = NULL;
1200   }
1201   if (fields) {
1202     PetscValidPointer(fields,4);
1203     *fields = NULL;
1204   }
1205   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
1206   if (section) {
1207     PetscInt *fieldSizes, **fieldIndices;
1208     PetscInt nF, f, pStart, pEnd, p;
1209 
1210     ierr = DMGetDefaultGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
1211     ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr);
1212     ierr = PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);CHKERRQ(ierr);
1213     ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr);
1214     for (f = 0; f < nF; ++f) {
1215       fieldSizes[f] = 0;
1216     }
1217     for (p = pStart; p < pEnd; ++p) {
1218       PetscInt gdof;
1219 
1220       ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
1221       if (gdof > 0) {
1222         for (f = 0; f < nF; ++f) {
1223           PetscInt fdof, fcdof;
1224 
1225           ierr           = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
1226           ierr           = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
1227           fieldSizes[f] += fdof-fcdof;
1228         }
1229       }
1230     }
1231     for (f = 0; f < nF; ++f) {
1232       ierr          = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr);
1233       fieldSizes[f] = 0;
1234     }
1235     for (p = pStart; p < pEnd; ++p) {
1236       PetscInt gdof, goff;
1237 
1238       ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
1239       if (gdof > 0) {
1240         ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
1241         for (f = 0; f < nF; ++f) {
1242           PetscInt fdof, fcdof, fc;
1243 
1244           ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
1245           ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
1246           for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) {
1247             fieldIndices[f][fieldSizes[f]] = goff++;
1248           }
1249         }
1250       }
1251     }
1252     if (numFields) *numFields = nF;
1253     if (fieldNames) {
1254       ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr);
1255       for (f = 0; f < nF; ++f) {
1256         const char *fieldName;
1257 
1258         ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr);
1259         ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr);
1260       }
1261     }
1262     if (fields) {
1263       ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr);
1264       for (f = 0; f < nF; ++f) {
1265         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr);
1266       }
1267     }
1268     ierr = PetscFree2(fieldSizes,fieldIndices);CHKERRQ(ierr);
1269   } else if (dm->ops->createfieldis) {
1270     ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr);
1271   }
1272   PetscFunctionReturn(0);
1273 }
1274 
1275 
1276 #undef __FUNCT__
1277 #define __FUNCT__ "DMCreateFieldDecomposition"
1278 /*@C
1279   DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems
1280                           corresponding to different fields: each IS contains the global indices of the dofs of the
1281                           corresponding field. The optional list of DMs define the DM for each subproblem.
1282                           Generalizes DMCreateFieldIS().
1283 
1284   Not collective
1285 
1286   Input Parameter:
1287 . dm - the DM object
1288 
1289   Output Parameters:
1290 + len       - The number of subproblems in the field decomposition (or NULL if not requested)
1291 . namelist  - The name for each field (or NULL if not requested)
1292 . islist    - The global indices for each field (or NULL if not requested)
1293 - dmlist    - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1294 
1295   Level: intermediate
1296 
1297   Notes:
1298   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1299   PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1300   and all of the arrays should be freed with PetscFree().
1301 
1302 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1303 @*/
1304 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1305 {
1306   PetscErrorCode ierr;
1307 
1308   PetscFunctionBegin;
1309   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1310   if (len) {
1311     PetscValidPointer(len,2);
1312     *len = 0;
1313   }
1314   if (namelist) {
1315     PetscValidPointer(namelist,3);
1316     *namelist = 0;
1317   }
1318   if (islist) {
1319     PetscValidPointer(islist,4);
1320     *islist = 0;
1321   }
1322   if (dmlist) {
1323     PetscValidPointer(dmlist,5);
1324     *dmlist = 0;
1325   }
1326   /*
1327    Is it a good idea to apply the following check across all impls?
1328    Perhaps some impls can have a well-defined decomposition before DMSetUp?
1329    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1330    */
1331   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1332   if (!dm->ops->createfielddecomposition) {
1333     PetscSection section;
1334     PetscInt     numFields, f;
1335 
1336     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
1337     if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);}
1338     if (section && numFields && dm->ops->createsubdm) {
1339       *len = numFields;
1340       if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);}
1341       if (islist)   {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);}
1342       if (dmlist)   {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);}
1343       for (f = 0; f < numFields; ++f) {
1344         const char *fieldName;
1345 
1346         ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr);
1347         if (namelist) {
1348           ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr);
1349           ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr);
1350         }
1351       }
1352     } else {
1353       ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr);
1354       /* By default there are no DMs associated with subproblems. */
1355       if (dmlist) *dmlist = NULL;
1356     }
1357   } else {
1358     ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr);
1359   }
1360   PetscFunctionReturn(0);
1361 }
1362 
1363 #undef __FUNCT__
1364 #define __FUNCT__ "DMCreateSubDM"
1365 /*@
1366   DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in.
1367                   The fields are defined by DMCreateFieldIS().
1368 
1369   Not collective
1370 
1371   Input Parameters:
1372 + dm - the DM object
1373 . numFields - number of fields in this subproblem
1374 - len       - The number of subproblems in the decomposition (or NULL if not requested)
1375 
1376   Output Parameters:
1377 . is - The global indices for the subproblem
1378 - dm - The DM for the subproblem
1379 
1380   Level: intermediate
1381 
1382 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1383 @*/
1384 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
1385 {
1386   PetscErrorCode ierr;
1387 
1388   PetscFunctionBegin;
1389   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1390   PetscValidPointer(fields,3);
1391   if (is) PetscValidPointer(is,4);
1392   if (subdm) PetscValidPointer(subdm,5);
1393   if (dm->ops->createsubdm) {
1394     ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
1395   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined");
1396   PetscFunctionReturn(0);
1397 }
1398 
1399 
1400 #undef __FUNCT__
1401 #define __FUNCT__ "DMCreateDomainDecomposition"
1402 /*@C
1403   DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems
1404                           corresponding to restrictions to pairs nested subdomains: each IS contains the global
1405                           indices of the dofs of the corresponding subdomains.  The inner subdomains conceptually
1406                           define a nonoverlapping covering, while outer subdomains can overlap.
1407                           The optional list of DMs define the DM for each subproblem.
1408 
1409   Not collective
1410 
1411   Input Parameter:
1412 . dm - the DM object
1413 
1414   Output Parameters:
1415 + len         - The number of subproblems in the domain decomposition (or NULL if not requested)
1416 . namelist    - The name for each subdomain (or NULL if not requested)
1417 . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
1418 . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
1419 - dmlist      - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined)
1420 
1421   Level: intermediate
1422 
1423   Notes:
1424   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1425   PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(),
1426   and all of the arrays should be freed with PetscFree().
1427 
1428 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition()
1429 @*/
1430 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
1431 {
1432   PetscErrorCode      ierr;
1433   DMSubDomainHookLink link;
1434   PetscInt            i,l;
1435 
1436   PetscFunctionBegin;
1437   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1438   if (len)           {PetscValidPointer(len,2);            *len         = 0;}
1439   if (namelist)      {PetscValidPointer(namelist,3);       *namelist    = NULL;}
1440   if (innerislist)   {PetscValidPointer(innerislist,4);    *innerislist = NULL;}
1441   if (outerislist)   {PetscValidPointer(outerislist,5);    *outerislist = NULL;}
1442   if (dmlist)        {PetscValidPointer(dmlist,6);         *dmlist      = NULL;}
1443   /*
1444    Is it a good idea to apply the following check across all impls?
1445    Perhaps some impls can have a well-defined decomposition before DMSetUp?
1446    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
1447    */
1448   if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
1449   if (dm->ops->createdomaindecomposition) {
1450     ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr);
1451     /* copy subdomain hooks and context over to the subdomain DMs */
1452     if (dmlist) {
1453       for (i = 0; i < l; i++) {
1454         for (link=dm->subdomainhook; link; link=link->next) {
1455           if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);}
1456         }
1457         (*dmlist)[i]->ctx = dm->ctx;
1458       }
1459     }
1460     if (len) *len = l;
1461   }
1462   PetscFunctionReturn(0);
1463 }
1464 
1465 
1466 #undef __FUNCT__
1467 #define __FUNCT__ "DMCreateDomainDecompositionScatters"
1468 /*@C
1469   DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
1470 
1471   Not collective
1472 
1473   Input Parameters:
1474 + dm - the DM object
1475 . n  - the number of subdomain scatters
1476 - subdms - the local subdomains
1477 
1478   Output Parameters:
1479 + n     - the number of scatters returned
1480 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
1481 . oscat - scatter from global vector to overlapping global vector entries on subdomain
1482 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
1483 
1484   Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution
1485   of general nonlinear problems with overlapping subdomain methods.  While merely having index sets that enable subsets
1486   of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
1487   solution and residual data.
1488 
1489   Level: developer
1490 
1491 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS()
1492 @*/
1493 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat)
1494 {
1495   PetscErrorCode ierr;
1496 
1497   PetscFunctionBegin;
1498   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1499   PetscValidPointer(subdms,3);
1500   if (dm->ops->createddscatters) {
1501     ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr);
1502   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionLocalScatter implementation defined");
1503   PetscFunctionReturn(0);
1504 }
1505 
1506 #undef __FUNCT__
1507 #define __FUNCT__ "DMRefine"
1508 /*@
1509   DMRefine - Refines a DM object
1510 
1511   Collective on DM
1512 
1513   Input Parameter:
1514 + dm   - the DM object
1515 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
1516 
1517   Output Parameter:
1518 . dmf - the refined DM, or NULL
1519 
1520   Note: If no refinement was done, the return value is NULL
1521 
1522   Level: developer
1523 
1524 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1525 @*/
1526 PetscErrorCode  DMRefine(DM dm,MPI_Comm comm,DM *dmf)
1527 {
1528   PetscErrorCode   ierr;
1529   DMRefineHookLink link;
1530 
1531   PetscFunctionBegin;
1532   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1533   ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr);
1534   if (*dmf) {
1535     (*dmf)->ops->creatematrix = dm->ops->creatematrix;
1536 
1537     ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr);
1538 
1539     (*dmf)->ctx       = dm->ctx;
1540     (*dmf)->leveldown = dm->leveldown;
1541     (*dmf)->levelup   = dm->levelup + 1;
1542 
1543     ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr);
1544     for (link=dm->refinehook; link; link=link->next) {
1545       if (link->refinehook) {
1546         ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr);
1547       }
1548     }
1549   }
1550   PetscFunctionReturn(0);
1551 }
1552 
1553 #undef __FUNCT__
1554 #define __FUNCT__ "DMRefineHookAdd"
1555 /*@C
1556    DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
1557 
1558    Logically Collective
1559 
1560    Input Arguments:
1561 +  coarse - nonlinear solver context on which to run a hook when restricting to a coarser level
1562 .  refinehook - function to run when setting up a coarser level
1563 .  interphook - function to run to update data on finer levels (once per SNESSolve())
1564 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1565 
1566    Calling sequence of refinehook:
1567 $    refinehook(DM coarse,DM fine,void *ctx);
1568 
1569 +  coarse - coarse level DM
1570 .  fine - fine level DM to interpolate problem to
1571 -  ctx - optional user-defined function context
1572 
1573    Calling sequence for interphook:
1574 $    interphook(DM coarse,Mat interp,DM fine,void *ctx)
1575 
1576 +  coarse - coarse level DM
1577 .  interp - matrix interpolating a coarse-level solution to the finer grid
1578 .  fine - fine level DM to update
1579 -  ctx - optional user-defined function context
1580 
1581    Level: advanced
1582 
1583    Notes:
1584    This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing
1585 
1586    If this function is called multiple times, the hooks will be run in the order they are added.
1587 
1588    This function is currently not available from Fortran.
1589 
1590 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1591 @*/
1592 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx)
1593 {
1594   PetscErrorCode   ierr;
1595   DMRefineHookLink link,*p;
1596 
1597   PetscFunctionBegin;
1598   PetscValidHeaderSpecific(coarse,DM_CLASSID,1);
1599   for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1600   ierr             = PetscMalloc(sizeof(struct _DMRefineHookLink),&link);CHKERRQ(ierr);
1601   link->refinehook = refinehook;
1602   link->interphook = interphook;
1603   link->ctx        = ctx;
1604   link->next       = NULL;
1605   *p               = link;
1606   PetscFunctionReturn(0);
1607 }
1608 
1609 #undef __FUNCT__
1610 #define __FUNCT__ "DMInterpolate"
1611 /*@
1612    DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd()
1613 
1614    Collective if any hooks are
1615 
1616    Input Arguments:
1617 +  coarse - coarser DM to use as a base
1618 .  restrct - interpolation matrix, apply using MatInterpolate()
1619 -  fine - finer DM to update
1620 
1621    Level: developer
1622 
1623 .seealso: DMRefineHookAdd(), MatInterpolate()
1624 @*/
1625 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine)
1626 {
1627   PetscErrorCode   ierr;
1628   DMRefineHookLink link;
1629 
1630   PetscFunctionBegin;
1631   for (link=fine->refinehook; link; link=link->next) {
1632     if (link->interphook) {
1633       ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr);
1634     }
1635   }
1636   PetscFunctionReturn(0);
1637 }
1638 
1639 #undef __FUNCT__
1640 #define __FUNCT__ "DMGetRefineLevel"
1641 /*@
1642     DMGetRefineLevel - Get's the number of refinements that have generated this DM.
1643 
1644     Not Collective
1645 
1646     Input Parameter:
1647 .   dm - the DM object
1648 
1649     Output Parameter:
1650 .   level - number of refinements
1651 
1652     Level: developer
1653 
1654 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
1655 
1656 @*/
1657 PetscErrorCode  DMGetRefineLevel(DM dm,PetscInt *level)
1658 {
1659   PetscFunctionBegin;
1660   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1661   *level = dm->levelup;
1662   PetscFunctionReturn(0);
1663 }
1664 
1665 #undef __FUNCT__
1666 #define __FUNCT__ "DMGlobalToLocalHookAdd"
1667 /*@C
1668    DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called
1669 
1670    Logically Collective
1671 
1672    Input Arguments:
1673 +  dm - the DM
1674 .  beginhook - function to run at the beginning of DMGlobalToLocalBegin()
1675 .  endhook - function to run after DMGlobalToLocalEnd() has completed
1676 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1677 
1678    Calling sequence for beginhook:
1679 $    beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
1680 
1681 +  dm - global DM
1682 .  g - global vector
1683 .  mode - mode
1684 .  l - local vector
1685 -  ctx - optional user-defined function context
1686 
1687 
1688    Calling sequence for endhook:
1689 $    endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
1690 
1691 +  global - global DM
1692 -  ctx - optional user-defined function context
1693 
1694    Level: advanced
1695 
1696 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1697 @*/
1698 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
1699 {
1700   PetscErrorCode          ierr;
1701   DMGlobalToLocalHookLink link,*p;
1702 
1703   PetscFunctionBegin;
1704   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1705   for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1706   ierr            = PetscMalloc(sizeof(struct _DMGlobalToLocalHookLink),&link);CHKERRQ(ierr);
1707   link->beginhook = beginhook;
1708   link->endhook   = endhook;
1709   link->ctx       = ctx;
1710   link->next      = NULL;
1711   *p              = link;
1712   PetscFunctionReturn(0);
1713 }
1714 
1715 #undef __FUNCT__
1716 #define __FUNCT__ "DMGlobalToLocalHook_Constraints"
1717 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
1718 {
1719   Mat cMat;
1720   Vec cVec;
1721   PetscSection section, cSec;
1722   PetscInt pStart, pEnd, p, dof;
1723   PetscErrorCode ierr;
1724 
1725   PetscFunctionBegin;
1726   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1727   ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr);
1728   if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
1729     ierr = DMGetDefaultSection(dm,&section);CHKERRQ(ierr);
1730     ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr);
1731     ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr);
1732     ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr);
1733     for (p = pStart; p < pEnd; p++) {
1734       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
1735       if (dof) {
1736         PetscScalar *vals;
1737         ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr);
1738         ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr);
1739       }
1740     }
1741     ierr = VecDestroy(&cVec);CHKERRQ(ierr);
1742   }
1743   PetscFunctionReturn(0);
1744 }
1745 
1746 #undef __FUNCT__
1747 #define __FUNCT__ "DMGlobalToLocalBegin"
1748 /*@
1749     DMGlobalToLocalBegin - Begins updating local vectors from global vector
1750 
1751     Neighbor-wise Collective on DM
1752 
1753     Input Parameters:
1754 +   dm - the DM object
1755 .   g - the global vector
1756 .   mode - INSERT_VALUES or ADD_VALUES
1757 -   l - the local vector
1758 
1759 
1760     Level: beginner
1761 
1762 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1763 
1764 @*/
1765 PetscErrorCode  DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
1766 {
1767   PetscSF                 sf;
1768   PetscErrorCode          ierr;
1769   DMGlobalToLocalHookLink link;
1770 
1771   PetscFunctionBegin;
1772   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1773   for (link=dm->gtolhook; link; link=link->next) {
1774     if (link->beginhook) {
1775       ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);
1776     }
1777   }
1778   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1779   if (sf) {
1780     const PetscScalar *gArray;
1781     PetscScalar       *lArray;
1782 
1783     if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1784     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1785     ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr);
1786     ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr);
1787     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1788     ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr);
1789   } else {
1790     ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1791   }
1792   PetscFunctionReturn(0);
1793 }
1794 
1795 #undef __FUNCT__
1796 #define __FUNCT__ "DMGlobalToLocalEnd"
1797 /*@
1798     DMGlobalToLocalEnd - Ends updating local vectors from global vector
1799 
1800     Neighbor-wise Collective on DM
1801 
1802     Input Parameters:
1803 +   dm - the DM object
1804 .   g - the global vector
1805 .   mode - INSERT_VALUES or ADD_VALUES
1806 -   l - the local vector
1807 
1808 
1809     Level: beginner
1810 
1811 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
1812 
1813 @*/
1814 PetscErrorCode  DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
1815 {
1816   PetscSF                 sf;
1817   PetscErrorCode          ierr;
1818   const PetscScalar      *gArray;
1819   PetscScalar            *lArray;
1820   DMGlobalToLocalHookLink link;
1821 
1822   PetscFunctionBegin;
1823   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1824   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1825   if (sf) {
1826     if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1827 
1828     ierr = VecGetArray(l, &lArray);CHKERRQ(ierr);
1829     ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr);
1830     ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr);
1831     ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr);
1832     ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr);
1833   } else {
1834     ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
1835   }
1836   ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr);
1837   for (link=dm->gtolhook; link; link=link->next) {
1838     if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);}
1839   }
1840   PetscFunctionReturn(0);
1841 }
1842 
1843 #undef __FUNCT__
1844 #define __FUNCT__ "DMLocalToGlobalHookAdd"
1845 /*@C
1846    DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
1847 
1848    Logically Collective
1849 
1850    Input Arguments:
1851 +  dm - the DM
1852 .  beginhook - function to run at the beginning of DMLocalToGlobalBegin()
1853 .  endhook - function to run after DMLocalToGlobalEnd() has completed
1854 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
1855 
1856    Calling sequence for beginhook:
1857 $    beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
1858 
1859 +  dm - global DM
1860 .  l - local vector
1861 .  mode - mode
1862 .  g - global vector
1863 -  ctx - optional user-defined function context
1864 
1865 
1866    Calling sequence for endhook:
1867 $    endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
1868 
1869 +  global - global DM
1870 .  l - local vector
1871 .  mode - mode
1872 .  g - global vector
1873 -  ctx - optional user-defined function context
1874 
1875    Level: advanced
1876 
1877 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
1878 @*/
1879 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx)
1880 {
1881   PetscErrorCode          ierr;
1882   DMLocalToGlobalHookLink link,*p;
1883 
1884   PetscFunctionBegin;
1885   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1886   for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
1887   ierr            = PetscMalloc(sizeof(struct _DMLocalToGlobalHookLink),&link);CHKERRQ(ierr);
1888   link->beginhook = beginhook;
1889   link->endhook   = endhook;
1890   link->ctx       = ctx;
1891   link->next      = NULL;
1892   *p              = link;
1893   PetscFunctionReturn(0);
1894 }
1895 
1896 #undef __FUNCT__
1897 #define __FUNCT__ "DMLocalToGlobalHook_Constraints"
1898 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
1899 {
1900   Mat cMat;
1901   Vec cVec;
1902   PetscSection section, cSec;
1903   PetscInt pStart, pEnd, p, dof;
1904   PetscErrorCode ierr;
1905 
1906   PetscFunctionBegin;
1907   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1908   ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr);
1909   if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
1910     ierr = DMGetDefaultSection(dm,&section);CHKERRQ(ierr);
1911     ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr);
1912     ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr);
1913     for (p = pStart; p < pEnd; p++) {
1914       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
1915       if (dof) {
1916         PetscInt d;
1917         PetscScalar *vals;
1918         ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr);
1919         ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr);
1920         /* for this to be the true transpose, we have to zero the values that
1921          * we just extracted */
1922         for (d = 0; d < dof; d++) {
1923           vals[d] = 0.;
1924         }
1925       }
1926     }
1927     ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr);
1928     ierr = VecDestroy(&cVec);CHKERRQ(ierr);
1929   }
1930   PetscFunctionReturn(0);
1931 }
1932 
1933 #undef __FUNCT__
1934 #define __FUNCT__ "DMLocalToGlobalBegin"
1935 /*@
1936     DMLocalToGlobalBegin - updates global vectors from local vectors
1937 
1938     Neighbor-wise Collective on DM
1939 
1940     Input Parameters:
1941 +   dm - the DM object
1942 .   l - the local vector
1943 .   mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point.
1944 -   g - the global vector
1945 
1946     Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation.
1947            INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one.
1948 
1949     Level: beginner
1950 
1951 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin()
1952 
1953 @*/
1954 PetscErrorCode  DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g)
1955 {
1956   PetscSF                 sf;
1957   PetscSection            s, gs;
1958   DMLocalToGlobalHookLink link;
1959   const PetscScalar      *lArray;
1960   PetscScalar            *gArray;
1961   PetscBool               isInsert;
1962   PetscErrorCode          ierr;
1963 
1964   PetscFunctionBegin;
1965   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1966   for (link=dm->ltoghook; link; link=link->next) {
1967     if (link->beginhook) {
1968       ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr);
1969     }
1970   }
1971   ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr);
1972   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
1973   ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
1974   switch (mode) {
1975   case INSERT_VALUES:
1976   case INSERT_ALL_VALUES:
1977     isInsert = PETSC_TRUE; break;
1978   case ADD_VALUES:
1979   case ADD_ALL_VALUES:
1980     isInsert = PETSC_FALSE; break;
1981   default:
1982     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
1983   }
1984   if (sf && !isInsert) {
1985     ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr);
1986     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1987     ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr);
1988     ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr);
1989     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
1990   } else if (s && isInsert) {
1991     PetscInt gStart, pStart, pEnd, p;
1992 
1993     ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr);
1994     ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
1995     ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr);
1996     ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr);
1997     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
1998     for (p = pStart; p < pEnd; ++p) {
1999       PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
2000 
2001       ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
2002       ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr);
2003       ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
2004       ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr);
2005       ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr);
2006       ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr);
2007       /* Ignore off-process data and points with no global data */
2008       if (!gdof || goff < 0) continue;
2009       if (dof != gdof) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
2010       /* If no constraints are enforced in the global vector */
2011       if (!gcdof) {
2012         for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d];
2013       /* If constraints are enforced in the global vector */
2014       } else if (cdof == gcdof) {
2015         const PetscInt *cdofs;
2016         PetscInt        cind = 0;
2017 
2018         ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr);
2019         for (d = 0, e = 0; d < dof; ++d) {
2020           if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;}
2021           gArray[goff-gStart+e++] = lArray[off+d];
2022         }
2023       } else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof);
2024     }
2025     ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr);
2026     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
2027   } else {
2028     ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
2029   }
2030   PetscFunctionReturn(0);
2031 }
2032 
2033 #undef __FUNCT__
2034 #define __FUNCT__ "DMLocalToGlobalEnd"
2035 /*@
2036     DMLocalToGlobalEnd - updates global vectors from local vectors
2037 
2038     Neighbor-wise Collective on DM
2039 
2040     Input Parameters:
2041 +   dm - the DM object
2042 .   l - the local vector
2043 .   mode - INSERT_VALUES or ADD_VALUES
2044 -   g - the global vector
2045 
2046 
2047     Level: beginner
2048 
2049 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd()
2050 
2051 @*/
2052 PetscErrorCode  DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g)
2053 {
2054   PetscSF                 sf;
2055   PetscSection            s;
2056   DMLocalToGlobalHookLink link;
2057   PetscBool               isInsert;
2058   PetscErrorCode          ierr;
2059 
2060   PetscFunctionBegin;
2061   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2062   ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr);
2063   ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
2064   switch (mode) {
2065   case INSERT_VALUES:
2066   case INSERT_ALL_VALUES:
2067     isInsert = PETSC_TRUE; break;
2068   case ADD_VALUES:
2069   case ADD_ALL_VALUES:
2070     isInsert = PETSC_FALSE; break;
2071   default:
2072     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode);
2073   }
2074   if (sf && !isInsert) {
2075     const PetscScalar *lArray;
2076     PetscScalar       *gArray;
2077 
2078     ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr);
2079     ierr = VecGetArray(g, &gArray);CHKERRQ(ierr);
2080     ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr);
2081     ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr);
2082     ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr);
2083   } else if (s && isInsert) {
2084   } else {
2085     ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr);
2086   }
2087   for (link=dm->ltoghook; link; link=link->next) {
2088     if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);}
2089   }
2090   PetscFunctionReturn(0);
2091 }
2092 
2093 #undef __FUNCT__
2094 #define __FUNCT__ "DMLocalToLocalBegin"
2095 /*@
2096    DMLocalToLocalBegin - Maps from a local vector (including ghost points
2097    that contain irrelevant values) to another local vector where the ghost
2098    points in the second are set correctly. Must be followed by DMLocalToLocalEnd().
2099 
2100    Neighbor-wise Collective on DM and Vec
2101 
2102    Input Parameters:
2103 +  dm - the DM object
2104 .  g - the original local vector
2105 -  mode - one of INSERT_VALUES or ADD_VALUES
2106 
2107    Output Parameter:
2108 .  l  - the local vector with correct ghost values
2109 
2110    Level: intermediate
2111 
2112    Notes:
2113    The local vectors used here need not be the same as those
2114    obtained from DMCreateLocalVector(), BUT they
2115    must have the same parallel data layout; they could, for example, be
2116    obtained with VecDuplicate() from the DM originating vectors.
2117 
2118 .keywords: DM, local-to-local, begin
2119 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2120 
2121 @*/
2122 PetscErrorCode  DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l)
2123 {
2124   PetscErrorCode          ierr;
2125 
2126   PetscFunctionBegin;
2127   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2128   ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2129   PetscFunctionReturn(0);
2130 }
2131 
2132 #undef __FUNCT__
2133 #define __FUNCT__ "DMLocalToLocalEnd"
2134 /*@
2135    DMLocalToLocalEnd - Maps from a local vector (including ghost points
2136    that contain irrelevant values) to another local vector where the ghost
2137    points in the second are set correctly. Must be preceded by DMLocalToLocalBegin().
2138 
2139    Neighbor-wise Collective on DM and Vec
2140 
2141    Input Parameters:
2142 +  da - the DM object
2143 .  g - the original local vector
2144 -  mode - one of INSERT_VALUES or ADD_VALUES
2145 
2146    Output Parameter:
2147 .  l  - the local vector with correct ghost values
2148 
2149    Level: intermediate
2150 
2151    Notes:
2152    The local vectors used here need not be the same as those
2153    obtained from DMCreateLocalVector(), BUT they
2154    must have the same parallel data layout; they could, for example, be
2155    obtained with VecDuplicate() from the DM originating vectors.
2156 
2157 .keywords: DM, local-to-local, end
2158 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin()
2159 
2160 @*/
2161 PetscErrorCode  DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l)
2162 {
2163   PetscErrorCode          ierr;
2164 
2165   PetscFunctionBegin;
2166   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2167   ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr);
2168   PetscFunctionReturn(0);
2169 }
2170 
2171 
2172 #undef __FUNCT__
2173 #define __FUNCT__ "DMCoarsen"
2174 /*@
2175     DMCoarsen - Coarsens a DM object
2176 
2177     Collective on DM
2178 
2179     Input Parameter:
2180 +   dm - the DM object
2181 -   comm - the communicator to contain the new DM object (or MPI_COMM_NULL)
2182 
2183     Output Parameter:
2184 .   dmc - the coarsened DM
2185 
2186     Level: developer
2187 
2188 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2189 
2190 @*/
2191 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
2192 {
2193   PetscErrorCode    ierr;
2194   DMCoarsenHookLink link;
2195 
2196   PetscFunctionBegin;
2197   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2198   ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr);
2199   ierr                      = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr);
2200   if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
2201   (*dmc)->ops->creatematrix = dm->ops->creatematrix;
2202   ierr                      = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr);
2203   (*dmc)->ctx               = dm->ctx;
2204   (*dmc)->levelup           = dm->levelup;
2205   (*dmc)->leveldown         = dm->leveldown + 1;
2206   ierr                      = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr);
2207   for (link=dm->coarsenhook; link; link=link->next) {
2208     if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);}
2209   }
2210   ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr);
2211   PetscFunctionReturn(0);
2212 }
2213 
2214 #undef __FUNCT__
2215 #define __FUNCT__ "DMCoarsenHookAdd"
2216 /*@C
2217    DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
2218 
2219    Logically Collective
2220 
2221    Input Arguments:
2222 +  fine - nonlinear solver context on which to run a hook when restricting to a coarser level
2223 .  coarsenhook - function to run when setting up a coarser level
2224 .  restricthook - function to run to update data on coarser levels (once per SNESSolve())
2225 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2226 
2227    Calling sequence of coarsenhook:
2228 $    coarsenhook(DM fine,DM coarse,void *ctx);
2229 
2230 +  fine - fine level DM
2231 .  coarse - coarse level DM to restrict problem to
2232 -  ctx - optional user-defined function context
2233 
2234    Calling sequence for restricthook:
2235 $    restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
2236 
2237 +  fine - fine level DM
2238 .  mrestrict - matrix restricting a fine-level solution to the coarse grid
2239 .  rscale - scaling vector for restriction
2240 .  inject - matrix restricting by injection
2241 .  coarse - coarse level DM to update
2242 -  ctx - optional user-defined function context
2243 
2244    Level: advanced
2245 
2246    Notes:
2247    This function is only needed if auxiliary data needs to be set up on coarse grids.
2248 
2249    If this function is called multiple times, the hooks will be run in the order they are added.
2250 
2251    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2252    extract the finest level information from its context (instead of from the SNES).
2253 
2254    This function is currently not available from Fortran.
2255 
2256 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2257 @*/
2258 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx)
2259 {
2260   PetscErrorCode    ierr;
2261   DMCoarsenHookLink link,*p;
2262 
2263   PetscFunctionBegin;
2264   PetscValidHeaderSpecific(fine,DM_CLASSID,1);
2265   for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2266   ierr               = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr);
2267   link->coarsenhook  = coarsenhook;
2268   link->restricthook = restricthook;
2269   link->ctx          = ctx;
2270   link->next         = NULL;
2271   *p                 = link;
2272   PetscFunctionReturn(0);
2273 }
2274 
2275 #undef __FUNCT__
2276 #define __FUNCT__ "DMRestrict"
2277 /*@
2278    DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd()
2279 
2280    Collective if any hooks are
2281 
2282    Input Arguments:
2283 +  fine - finer DM to use as a base
2284 .  restrct - restriction matrix, apply using MatRestrict()
2285 .  inject - injection matrix, also use MatRestrict()
2286 -  coarse - coarer DM to update
2287 
2288    Level: developer
2289 
2290 .seealso: DMCoarsenHookAdd(), MatRestrict()
2291 @*/
2292 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse)
2293 {
2294   PetscErrorCode    ierr;
2295   DMCoarsenHookLink link;
2296 
2297   PetscFunctionBegin;
2298   for (link=fine->coarsenhook; link; link=link->next) {
2299     if (link->restricthook) {
2300       ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr);
2301     }
2302   }
2303   PetscFunctionReturn(0);
2304 }
2305 
2306 #undef __FUNCT__
2307 #define __FUNCT__ "DMSubDomainHookAdd"
2308 /*@C
2309    DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
2310 
2311    Logically Collective
2312 
2313    Input Arguments:
2314 +  global - global DM
2315 .  ddhook - function to run to pass data to the decomposition DM upon its creation
2316 .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
2317 -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2318 
2319 
2320    Calling sequence for ddhook:
2321 $    ddhook(DM global,DM block,void *ctx)
2322 
2323 +  global - global DM
2324 .  block  - block DM
2325 -  ctx - optional user-defined function context
2326 
2327    Calling sequence for restricthook:
2328 $    restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
2329 
2330 +  global - global DM
2331 .  out    - scatter to the outer (with ghost and overlap points) block vector
2332 .  in     - scatter to block vector values only owned locally
2333 .  block  - block DM
2334 -  ctx - optional user-defined function context
2335 
2336    Level: advanced
2337 
2338    Notes:
2339    This function is only needed if auxiliary data needs to be set up on subdomain DMs.
2340 
2341    If this function is called multiple times, the hooks will be run in the order they are added.
2342 
2343    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
2344    extract the global information from its context (instead of from the SNES).
2345 
2346    This function is currently not available from Fortran.
2347 
2348 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate()
2349 @*/
2350 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx)
2351 {
2352   PetscErrorCode      ierr;
2353   DMSubDomainHookLink link,*p;
2354 
2355   PetscFunctionBegin;
2356   PetscValidHeaderSpecific(global,DM_CLASSID,1);
2357   for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */
2358   ierr               = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr);
2359   link->restricthook = restricthook;
2360   link->ddhook       = ddhook;
2361   link->ctx          = ctx;
2362   link->next         = NULL;
2363   *p                 = link;
2364   PetscFunctionReturn(0);
2365 }
2366 
2367 #undef __FUNCT__
2368 #define __FUNCT__ "DMSubDomainRestrict"
2369 /*@
2370    DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd()
2371 
2372    Collective if any hooks are
2373 
2374    Input Arguments:
2375 +  fine - finer DM to use as a base
2376 .  oscatter - scatter from domain global vector filling subdomain global vector with overlap
2377 .  gscatter - scatter from domain global vector filling subdomain local vector with ghosts
2378 -  coarse - coarer DM to update
2379 
2380    Level: developer
2381 
2382 .seealso: DMCoarsenHookAdd(), MatRestrict()
2383 @*/
2384 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm)
2385 {
2386   PetscErrorCode      ierr;
2387   DMSubDomainHookLink link;
2388 
2389   PetscFunctionBegin;
2390   for (link=global->subdomainhook; link; link=link->next) {
2391     if (link->restricthook) {
2392       ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr);
2393     }
2394   }
2395   PetscFunctionReturn(0);
2396 }
2397 
2398 #undef __FUNCT__
2399 #define __FUNCT__ "DMGetCoarsenLevel"
2400 /*@
2401     DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM.
2402 
2403     Not Collective
2404 
2405     Input Parameter:
2406 .   dm - the DM object
2407 
2408     Output Parameter:
2409 .   level - number of coarsenings
2410 
2411     Level: developer
2412 
2413 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2414 
2415 @*/
2416 PetscErrorCode  DMGetCoarsenLevel(DM dm,PetscInt *level)
2417 {
2418   PetscFunctionBegin;
2419   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2420   *level = dm->leveldown;
2421   PetscFunctionReturn(0);
2422 }
2423 
2424 
2425 
2426 #undef __FUNCT__
2427 #define __FUNCT__ "DMRefineHierarchy"
2428 /*@C
2429     DMRefineHierarchy - Refines a DM object, all levels at once
2430 
2431     Collective on DM
2432 
2433     Input Parameter:
2434 +   dm - the DM object
2435 -   nlevels - the number of levels of refinement
2436 
2437     Output Parameter:
2438 .   dmf - the refined DM hierarchy
2439 
2440     Level: developer
2441 
2442 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2443 
2444 @*/
2445 PetscErrorCode  DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[])
2446 {
2447   PetscErrorCode ierr;
2448 
2449   PetscFunctionBegin;
2450   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2451   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2452   if (nlevels == 0) PetscFunctionReturn(0);
2453   if (dm->ops->refinehierarchy) {
2454     ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr);
2455   } else if (dm->ops->refine) {
2456     PetscInt i;
2457 
2458     ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr);
2459     for (i=1; i<nlevels; i++) {
2460       ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr);
2461     }
2462   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet");
2463   PetscFunctionReturn(0);
2464 }
2465 
2466 #undef __FUNCT__
2467 #define __FUNCT__ "DMCoarsenHierarchy"
2468 /*@C
2469     DMCoarsenHierarchy - Coarsens a DM object, all levels at once
2470 
2471     Collective on DM
2472 
2473     Input Parameter:
2474 +   dm - the DM object
2475 -   nlevels - the number of levels of coarsening
2476 
2477     Output Parameter:
2478 .   dmc - the coarsened DM hierarchy
2479 
2480     Level: developer
2481 
2482 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation()
2483 
2484 @*/
2485 PetscErrorCode  DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
2486 {
2487   PetscErrorCode ierr;
2488 
2489   PetscFunctionBegin;
2490   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2491   if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative");
2492   if (nlevels == 0) PetscFunctionReturn(0);
2493   PetscValidPointer(dmc,3);
2494   if (dm->ops->coarsenhierarchy) {
2495     ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr);
2496   } else if (dm->ops->coarsen) {
2497     PetscInt i;
2498 
2499     ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr);
2500     for (i=1; i<nlevels; i++) {
2501       ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr);
2502     }
2503   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet");
2504   PetscFunctionReturn(0);
2505 }
2506 
2507 #undef __FUNCT__
2508 #define __FUNCT__ "DMCreateAggregates"
2509 /*@
2510    DMCreateAggregates - Gets the aggregates that map between
2511    grids associated with two DMs.
2512 
2513    Collective on DM
2514 
2515    Input Parameters:
2516 +  dmc - the coarse grid DM
2517 -  dmf - the fine grid DM
2518 
2519    Output Parameters:
2520 .  rest - the restriction matrix (transpose of the projection matrix)
2521 
2522    Level: intermediate
2523 
2524 .keywords: interpolation, restriction, multigrid
2525 
2526 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation()
2527 @*/
2528 PetscErrorCode  DMCreateAggregates(DM dmc, DM dmf, Mat *rest)
2529 {
2530   PetscErrorCode ierr;
2531 
2532   PetscFunctionBegin;
2533   PetscValidHeaderSpecific(dmc,DM_CLASSID,1);
2534   PetscValidHeaderSpecific(dmf,DM_CLASSID,2);
2535   ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr);
2536   PetscFunctionReturn(0);
2537 }
2538 
2539 #undef __FUNCT__
2540 #define __FUNCT__ "DMSetApplicationContextDestroy"
2541 /*@C
2542     DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed
2543 
2544     Not Collective
2545 
2546     Input Parameters:
2547 +   dm - the DM object
2548 -   destroy - the destroy function
2549 
2550     Level: intermediate
2551 
2552 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2553 
2554 @*/
2555 PetscErrorCode  DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**))
2556 {
2557   PetscFunctionBegin;
2558   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2559   dm->ctxdestroy = destroy;
2560   PetscFunctionReturn(0);
2561 }
2562 
2563 #undef __FUNCT__
2564 #define __FUNCT__ "DMSetApplicationContext"
2565 /*@
2566     DMSetApplicationContext - Set a user context into a DM object
2567 
2568     Not Collective
2569 
2570     Input Parameters:
2571 +   dm - the DM object
2572 -   ctx - the user context
2573 
2574     Level: intermediate
2575 
2576 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2577 
2578 @*/
2579 PetscErrorCode  DMSetApplicationContext(DM dm,void *ctx)
2580 {
2581   PetscFunctionBegin;
2582   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2583   dm->ctx = ctx;
2584   PetscFunctionReturn(0);
2585 }
2586 
2587 #undef __FUNCT__
2588 #define __FUNCT__ "DMGetApplicationContext"
2589 /*@
2590     DMGetApplicationContext - Gets a user context from a DM object
2591 
2592     Not Collective
2593 
2594     Input Parameter:
2595 .   dm - the DM object
2596 
2597     Output Parameter:
2598 .   ctx - the user context
2599 
2600     Level: intermediate
2601 
2602 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2603 
2604 @*/
2605 PetscErrorCode  DMGetApplicationContext(DM dm,void *ctx)
2606 {
2607   PetscFunctionBegin;
2608   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2609   *(void**)ctx = dm->ctx;
2610   PetscFunctionReturn(0);
2611 }
2612 
2613 #undef __FUNCT__
2614 #define __FUNCT__ "DMSetVariableBounds"
2615 /*@C
2616     DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI.
2617 
2618     Logically Collective on DM
2619 
2620     Input Parameter:
2621 +   dm - the DM object
2622 -   f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
2623 
2624     Level: intermediate
2625 
2626 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(),
2627          DMSetJacobian()
2628 
2629 @*/
2630 PetscErrorCode  DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec))
2631 {
2632   PetscFunctionBegin;
2633   dm->ops->computevariablebounds = f;
2634   PetscFunctionReturn(0);
2635 }
2636 
2637 #undef __FUNCT__
2638 #define __FUNCT__ "DMHasVariableBounds"
2639 /*@
2640     DMHasVariableBounds - does the DM object have a variable bounds function?
2641 
2642     Not Collective
2643 
2644     Input Parameter:
2645 .   dm - the DM object to destroy
2646 
2647     Output Parameter:
2648 .   flg - PETSC_TRUE if the variable bounds function exists
2649 
2650     Level: developer
2651 
2652 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2653 
2654 @*/
2655 PetscErrorCode  DMHasVariableBounds(DM dm,PetscBool  *flg)
2656 {
2657   PetscFunctionBegin;
2658   *flg =  (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
2659   PetscFunctionReturn(0);
2660 }
2661 
2662 #undef __FUNCT__
2663 #define __FUNCT__ "DMComputeVariableBounds"
2664 /*@C
2665     DMComputeVariableBounds - compute variable bounds used by SNESVI.
2666 
2667     Logically Collective on DM
2668 
2669     Input Parameters:
2670 .   dm - the DM object
2671 
2672     Output parameters:
2673 +   xl - lower bound
2674 -   xu - upper bound
2675 
2676     Level: advanced
2677 
2678     Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
2679 
2680 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2681 
2682 @*/
2683 PetscErrorCode  DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
2684 {
2685   PetscErrorCode ierr;
2686 
2687   PetscFunctionBegin;
2688   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
2689   PetscValidHeaderSpecific(xu,VEC_CLASSID,2);
2690   if (dm->ops->computevariablebounds) {
2691     ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr);
2692   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds.");
2693   PetscFunctionReturn(0);
2694 }
2695 
2696 #undef __FUNCT__
2697 #define __FUNCT__ "DMHasColoring"
2698 /*@
2699     DMHasColoring - does the DM object have a method of providing a coloring?
2700 
2701     Not Collective
2702 
2703     Input Parameter:
2704 .   dm - the DM object
2705 
2706     Output Parameter:
2707 .   flg - PETSC_TRUE if the DM has facilities for DMCreateColoring().
2708 
2709     Level: developer
2710 
2711 .seealso DMHasFunction(), DMCreateColoring()
2712 
2713 @*/
2714 PetscErrorCode  DMHasColoring(DM dm,PetscBool  *flg)
2715 {
2716   PetscFunctionBegin;
2717   *flg =  (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
2718   PetscFunctionReturn(0);
2719 }
2720 
2721 #undef  __FUNCT__
2722 #define __FUNCT__ "DMSetVec"
2723 /*@C
2724     DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear.
2725 
2726     Collective on DM
2727 
2728     Input Parameter:
2729 +   dm - the DM object
2730 -   x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems.
2731 
2732     Level: developer
2733 
2734 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext()
2735 
2736 @*/
2737 PetscErrorCode  DMSetVec(DM dm,Vec x)
2738 {
2739   PetscErrorCode ierr;
2740 
2741   PetscFunctionBegin;
2742   if (x) {
2743     if (!dm->x) {
2744       ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr);
2745     }
2746     ierr = VecCopy(x,dm->x);CHKERRQ(ierr);
2747   } else if (dm->x) {
2748     ierr = VecDestroy(&dm->x);CHKERRQ(ierr);
2749   }
2750   PetscFunctionReturn(0);
2751 }
2752 
2753 PetscFunctionList DMList              = NULL;
2754 PetscBool         DMRegisterAllCalled = PETSC_FALSE;
2755 
2756 #undef __FUNCT__
2757 #define __FUNCT__ "DMSetType"
2758 /*@C
2759   DMSetType - Builds a DM, for a particular DM implementation.
2760 
2761   Collective on DM
2762 
2763   Input Parameters:
2764 + dm     - The DM object
2765 - method - The name of the DM type
2766 
2767   Options Database Key:
2768 . -dm_type <type> - Sets the DM type; use -help for a list of available types
2769 
2770   Notes:
2771   See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D).
2772 
2773   Level: intermediate
2774 
2775 .keywords: DM, set, type
2776 .seealso: DMGetType(), DMCreate()
2777 @*/
2778 PetscErrorCode  DMSetType(DM dm, DMType method)
2779 {
2780   PetscErrorCode (*r)(DM);
2781   PetscBool      match;
2782   PetscErrorCode ierr;
2783 
2784   PetscFunctionBegin;
2785   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2786   ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr);
2787   if (match) PetscFunctionReturn(0);
2788 
2789   ierr = DMRegisterAll();CHKERRQ(ierr);
2790   ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr);
2791   if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
2792 
2793   if (dm->ops->destroy) {
2794     ierr             = (*dm->ops->destroy)(dm);CHKERRQ(ierr);
2795     dm->ops->destroy = NULL;
2796   }
2797   ierr = (*r)(dm);CHKERRQ(ierr);
2798   ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr);
2799   PetscFunctionReturn(0);
2800 }
2801 
2802 #undef __FUNCT__
2803 #define __FUNCT__ "DMGetType"
2804 /*@C
2805   DMGetType - Gets the DM type name (as a string) from the DM.
2806 
2807   Not Collective
2808 
2809   Input Parameter:
2810 . dm  - The DM
2811 
2812   Output Parameter:
2813 . type - The DM type name
2814 
2815   Level: intermediate
2816 
2817 .keywords: DM, get, type, name
2818 .seealso: DMSetType(), DMCreate()
2819 @*/
2820 PetscErrorCode  DMGetType(DM dm, DMType *type)
2821 {
2822   PetscErrorCode ierr;
2823 
2824   PetscFunctionBegin;
2825   PetscValidHeaderSpecific(dm, DM_CLASSID,1);
2826   PetscValidPointer(type,2);
2827   ierr = DMRegisterAll();CHKERRQ(ierr);
2828   *type = ((PetscObject)dm)->type_name;
2829   PetscFunctionReturn(0);
2830 }
2831 
2832 #undef __FUNCT__
2833 #define __FUNCT__ "DMConvert"
2834 /*@C
2835   DMConvert - Converts a DM to another DM, either of the same or different type.
2836 
2837   Collective on DM
2838 
2839   Input Parameters:
2840 + dm - the DM
2841 - newtype - new DM type (use "same" for the same type)
2842 
2843   Output Parameter:
2844 . M - pointer to new DM
2845 
2846   Notes:
2847   Cannot be used to convert a sequential DM to parallel or parallel to sequential,
2848   the MPI communicator of the generated DM is always the same as the communicator
2849   of the input DM.
2850 
2851   Level: intermediate
2852 
2853 .seealso: DMCreate()
2854 @*/
2855 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
2856 {
2857   DM             B;
2858   char           convname[256];
2859   PetscBool      sametype, issame;
2860   PetscErrorCode ierr;
2861 
2862   PetscFunctionBegin;
2863   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
2864   PetscValidType(dm,1);
2865   PetscValidPointer(M,3);
2866   ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr);
2867   ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr);
2868   {
2869     PetscErrorCode (*conv)(DM, DMType, DM*) = NULL;
2870 
2871     /*
2872        Order of precedence:
2873        1) See if a specialized converter is known to the current DM.
2874        2) See if a specialized converter is known to the desired DM class.
2875        3) See if a good general converter is registered for the desired class
2876        4) See if a good general converter is known for the current matrix.
2877        5) Use a really basic converter.
2878     */
2879 
2880     /* 1) See if a specialized converter is known to the current DM and the desired class */
2881     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2882     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2883     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2884     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2885     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2886     ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr);
2887     if (conv) goto foundconv;
2888 
2889     /* 2)  See if a specialized converter is known to the desired DM class. */
2890     ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr);
2891     ierr = DMSetType(B, newtype);CHKERRQ(ierr);
2892     ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr);
2893     ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr);
2894     ierr = PetscStrcat(convname,"_");CHKERRQ(ierr);
2895     ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr);
2896     ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr);
2897     ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr);
2898     if (conv) {
2899       ierr = DMDestroy(&B);CHKERRQ(ierr);
2900       goto foundconv;
2901     }
2902 
2903 #if 0
2904     /* 3) See if a good general converter is registered for the desired class */
2905     conv = B->ops->convertfrom;
2906     ierr = DMDestroy(&B);CHKERRQ(ierr);
2907     if (conv) goto foundconv;
2908 
2909     /* 4) See if a good general converter is known for the current matrix */
2910     if (dm->ops->convert) {
2911       conv = dm->ops->convert;
2912     }
2913     if (conv) goto foundconv;
2914 #endif
2915 
2916     /* 5) Use a really basic converter. */
2917     SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype);
2918 
2919 foundconv:
2920     ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2921     ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr);
2922     ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr);
2923   }
2924   ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr);
2925   PetscFunctionReturn(0);
2926 }
2927 
2928 /*--------------------------------------------------------------------------------------------------------------------*/
2929 
2930 #undef __FUNCT__
2931 #define __FUNCT__ "DMRegister"
2932 /*@C
2933   DMRegister -  Adds a new DM component implementation
2934 
2935   Not Collective
2936 
2937   Input Parameters:
2938 + name        - The name of a new user-defined creation routine
2939 - create_func - The creation routine itself
2940 
2941   Notes:
2942   DMRegister() may be called multiple times to add several user-defined DMs
2943 
2944 
2945   Sample usage:
2946 .vb
2947     DMRegister("my_da", MyDMCreate);
2948 .ve
2949 
2950   Then, your DM type can be chosen with the procedural interface via
2951 .vb
2952     DMCreate(MPI_Comm, DM *);
2953     DMSetType(DM,"my_da");
2954 .ve
2955    or at runtime via the option
2956 .vb
2957     -da_type my_da
2958 .ve
2959 
2960   Level: advanced
2961 
2962 .keywords: DM, register
2963 .seealso: DMRegisterAll(), DMRegisterDestroy()
2964 
2965 @*/
2966 PetscErrorCode  DMRegister(const char sname[],PetscErrorCode (*function)(DM))
2967 {
2968   PetscErrorCode ierr;
2969 
2970   PetscFunctionBegin;
2971   ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr);
2972   PetscFunctionReturn(0);
2973 }
2974 
2975 #undef __FUNCT__
2976 #define __FUNCT__ "DMLoad"
2977 /*@C
2978   DMLoad - Loads a DM that has been stored in binary  with DMView().
2979 
2980   Collective on PetscViewer
2981 
2982   Input Parameters:
2983 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or
2984            some related function before a call to DMLoad().
2985 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
2986            HDF5 file viewer, obtained from PetscViewerHDF5Open()
2987 
2988    Level: intermediate
2989 
2990   Notes:
2991    The type is determined by the data in the file, any type set into the DM before this call is ignored.
2992 
2993   Notes for advanced users:
2994   Most users should not need to know the details of the binary storage
2995   format, since DMLoad() and DMView() completely hide these details.
2996   But for anyone who's interested, the standard binary matrix storage
2997   format is
2998 .vb
2999      has not yet been determined
3000 .ve
3001 
3002 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad()
3003 @*/
3004 PetscErrorCode  DMLoad(DM newdm, PetscViewer viewer)
3005 {
3006   PetscBool      isbinary, ishdf5;
3007   PetscErrorCode ierr;
3008 
3009   PetscFunctionBegin;
3010   PetscValidHeaderSpecific(newdm,DM_CLASSID,1);
3011   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
3012   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
3013   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
3014   if (isbinary) {
3015     PetscInt classid;
3016     char     type[256];
3017 
3018     ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr);
3019     if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid);
3020     ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr);
3021     ierr = DMSetType(newdm, type);CHKERRQ(ierr);
3022     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
3023   } else if (ishdf5) {
3024     if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);}
3025   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
3026   PetscFunctionReturn(0);
3027 }
3028 
3029 /******************************** FEM Support **********************************/
3030 
3031 #undef __FUNCT__
3032 #define __FUNCT__ "DMPrintCellVector"
3033 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
3034 {
3035   PetscInt       f;
3036   PetscErrorCode ierr;
3037 
3038   PetscFunctionBegin;
3039   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
3040   for (f = 0; f < len; ++f) {
3041     ierr = PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr);
3042   }
3043   PetscFunctionReturn(0);
3044 }
3045 
3046 #undef __FUNCT__
3047 #define __FUNCT__ "DMPrintCellMatrix"
3048 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
3049 {
3050   PetscInt       f, g;
3051   PetscErrorCode ierr;
3052 
3053   PetscFunctionBegin;
3054   ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr);
3055   for (f = 0; f < rows; ++f) {
3056     ierr = PetscPrintf(PETSC_COMM_SELF, "  |");CHKERRQ(ierr);
3057     for (g = 0; g < cols; ++g) {
3058       ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr);
3059     }
3060     ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr);
3061   }
3062   PetscFunctionReturn(0);
3063 }
3064 
3065 #undef __FUNCT__
3066 #define __FUNCT__ "DMPrintLocalVec"
3067 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
3068 {
3069   PetscMPIInt    rank, numProcs;
3070   PetscInt       p;
3071   PetscErrorCode ierr;
3072 
3073   PetscFunctionBegin;
3074   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr);
3075   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr);
3076   ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr);
3077   for (p = 0; p < numProcs; ++p) {
3078     if (p == rank) {
3079       Vec x;
3080 
3081       ierr = VecDuplicate(X, &x);CHKERRQ(ierr);
3082       ierr = VecCopy(X, x);CHKERRQ(ierr);
3083       ierr = VecChop(x, tol);CHKERRQ(ierr);
3084       ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
3085       ierr = VecDestroy(&x);CHKERRQ(ierr);
3086       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
3087     }
3088     ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr);
3089   }
3090   PetscFunctionReturn(0);
3091 }
3092 
3093 #undef __FUNCT__
3094 #define __FUNCT__ "DMGetDefaultSection"
3095 /*@
3096   DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM.
3097 
3098   Input Parameter:
3099 . dm - The DM
3100 
3101   Output Parameter:
3102 . section - The PetscSection
3103 
3104   Level: intermediate
3105 
3106   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3107 
3108 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3109 @*/
3110 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section)
3111 {
3112   PetscErrorCode ierr;
3113 
3114   PetscFunctionBegin;
3115   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3116   PetscValidPointer(section, 2);
3117   if (!dm->defaultSection && dm->ops->createdefaultsection) {
3118     ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr);
3119     if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);}
3120   }
3121   *section = dm->defaultSection;
3122   PetscFunctionReturn(0);
3123 }
3124 
3125 #undef __FUNCT__
3126 #define __FUNCT__ "DMSetDefaultSection"
3127 /*@
3128   DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM.
3129 
3130   Input Parameters:
3131 + dm - The DM
3132 - section - The PetscSection
3133 
3134   Level: intermediate
3135 
3136   Note: Any existing Section will be destroyed
3137 
3138 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection()
3139 @*/
3140 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section)
3141 {
3142   PetscInt       numFields = 0;
3143   PetscInt       f;
3144   PetscErrorCode ierr;
3145 
3146   PetscFunctionBegin;
3147   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3148   if (section) {
3149     PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3150     ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3151   }
3152   ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr);
3153   dm->defaultSection = section;
3154   if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);}
3155   if (numFields) {
3156     ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr);
3157     for (f = 0; f < numFields; ++f) {
3158       PetscObject disc;
3159       const char *name;
3160 
3161       ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr);
3162       ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr);
3163       ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr);
3164     }
3165   }
3166   /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */
3167   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
3168   PetscFunctionReturn(0);
3169 }
3170 
3171 #undef __FUNCT__
3172 #define __FUNCT__ "DMGetDefaultConstraints"
3173 /*@
3174   DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation.
3175 
3176   not collective
3177 
3178   Input Parameter:
3179 . dm - The DM
3180 
3181   Output Parameter:
3182 + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section.  Returns NULL if there are no local constraints.
3183 - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section.  Returns NULL if there are no local constraints.
3184 
3185   Level: advanced
3186 
3187   Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat.
3188 
3189 .seealso: DMSetDefaultConstraints()
3190 @*/
3191 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat)
3192 {
3193   PetscErrorCode ierr;
3194 
3195   PetscFunctionBegin;
3196   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3197   if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);}
3198   if (section) {*section = dm->defaultConstraintSection;}
3199   if (mat) {*mat = dm->defaultConstraintMat;}
3200   PetscFunctionReturn(0);
3201 }
3202 
3203 #undef __FUNCT__
3204 #define __FUNCT__ "DMSetDefaultConstraints"
3205 /*@
3206   DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation.
3207 
3208   If a constraint matrix is specified, then it is applied during DMGlobalToLocalEnd() when mode is INSERT_VALUES, INSERT_BC_VALUES, or INSERT_ALL_VALUES.  Without a constraint matrix, the local vector l returned by DMGlobalToLocalEnd() contains values that have been scattered from a global vector without modification; with a constraint matrix A, l is modified by computing c = A * l, l[s[i]] = c[i], where the scatter s is defined by the PetscSection returned by DMGetDefaultConstraintMatrix().
3209 
3210   If a constraint matrix is specified, then its adjoint is applied during DMLocalToGlobalBegin() when mode is ADD_VALUES, ADD_BC_VALUES, or ADD_ALL_VALUES.  Without a constraint matrix, the local vector l is accumulated into a global vector without modification; with a constraint matrix A, l is first modified by computing c[i] = l[s[i]], l[s[i]] = 0, l = l + A'*c, which is the adjoint of the operation described above.
3211 
3212   collective on dm
3213 
3214   Input Parameters:
3215 + dm - The DM
3216 + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section.  Must have a local communicator (PETSC_COMM_SELF or derivative).
3217 - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section:  NULL indicates no constraints.  Must have a local communicator (PETSC_COMM_SELF or derivative).
3218 
3219   Level: advanced
3220 
3221   Note: This increments the references of the PetscSection and the Mat, so they user can destroy them
3222 
3223 .seealso: DMGetDefaultConstraints()
3224 @*/
3225 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat)
3226 {
3227   PetscMPIInt result;
3228   PetscErrorCode ierr;
3229 
3230   PetscFunctionBegin;
3231   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3232   if (section) {
3233     PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3234     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr);
3235     if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator");
3236   }
3237   if (mat) {
3238     PetscValidHeaderSpecific(mat,MAT_CLASSID,3);
3239     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr);
3240     if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator");
3241   }
3242   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3243   ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr);
3244   dm->defaultConstraintSection = section;
3245   ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
3246   ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr);
3247   dm->defaultConstraintMat = mat;
3248   PetscFunctionReturn(0);
3249 }
3250 
3251 #ifdef PETSC_USE_DEBUG
3252 #undef __FUNCT__
3253 #define __FUNCT__ "DMDefaultSectionCheckConsistency_Internal"
3254 /*
3255   DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections.
3256 
3257   Input Parameters:
3258 + dm - The DM
3259 . localSection - PetscSection describing the local data layout
3260 - globalSection - PetscSection describing the global data layout
3261 
3262   Level: intermediate
3263 
3264 .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3265 */
3266 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
3267 {
3268   MPI_Comm        comm;
3269   PetscLayout     layout;
3270   const PetscInt *ranges;
3271   PetscInt        pStart, pEnd, p, nroots;
3272   PetscMPIInt     size, rank;
3273   PetscBool       valid = PETSC_TRUE, gvalid;
3274   PetscErrorCode  ierr;
3275 
3276   PetscFunctionBegin;
3277   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3278   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3279   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
3280   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3281   ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
3282   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
3283   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
3284   ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
3285   ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
3286   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
3287   ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
3288   for (p = pStart; p < pEnd; ++p) {
3289     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d;
3290 
3291     ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
3292     ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
3293     ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
3294     ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3295     ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3296     ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
3297     if (!gdof) continue; /* Censored point */
3298     if ((gdof < 0 ? -(gdof+1) : gdof) != dof) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global dof %d for point %d not equal to local dof %d\n", rank, gdof, p, dof);CHKERRQ(ierr); valid = PETSC_FALSE;}
3299     if (gcdof && (gcdof != cdof)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global constraints %d for point %d not equal to local constraints %d\n", rank, gcdof, p, cdof);CHKERRQ(ierr); valid = PETSC_FALSE;}
3300     if (gdof < 0) {
3301       gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3302       for (d = 0; d < gsize; ++d) {
3303         PetscInt offset = -(goff+1) + d, r;
3304 
3305         ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
3306         if (r < 0) r = -(r+2);
3307         if ((r < 0) || (r >= size)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Point %d mapped to invalid process %d (%d, %d)\n", rank, p, r, gdof, goff);CHKERRQ(ierr); valid = PETSC_FALSE;break;}
3308       }
3309     }
3310   }
3311   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
3312   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
3313   ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr);
3314   if (!gvalid) {
3315     ierr = DMView(dm, NULL);CHKERRQ(ierr);
3316     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
3317   }
3318   PetscFunctionReturn(0);
3319 }
3320 #endif
3321 
3322 #undef __FUNCT__
3323 #define __FUNCT__ "DMGetDefaultGlobalSection"
3324 /*@
3325   DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM.
3326 
3327   Collective on DM
3328 
3329   Input Parameter:
3330 . dm - The DM
3331 
3332   Output Parameter:
3333 . section - The PetscSection
3334 
3335   Level: intermediate
3336 
3337   Note: This gets a borrowed reference, so the user should not destroy this PetscSection.
3338 
3339 .seealso: DMSetDefaultSection(), DMGetDefaultSection()
3340 @*/
3341 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section)
3342 {
3343   PetscErrorCode ierr;
3344 
3345   PetscFunctionBegin;
3346   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3347   PetscValidPointer(section, 2);
3348   if (!dm->defaultGlobalSection) {
3349     PetscSection s;
3350 
3351     ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr);
3352     if (!s)  SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
3353     if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection");
3354     ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr);
3355     ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr);
3356     ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr);
3357     ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr);
3358   }
3359   *section = dm->defaultGlobalSection;
3360   PetscFunctionReturn(0);
3361 }
3362 
3363 #undef __FUNCT__
3364 #define __FUNCT__ "DMSetDefaultGlobalSection"
3365 /*@
3366   DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM.
3367 
3368   Input Parameters:
3369 + dm - The DM
3370 - section - The PetscSection, or NULL
3371 
3372   Level: intermediate
3373 
3374   Note: Any existing Section will be destroyed
3375 
3376 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection()
3377 @*/
3378 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section)
3379 {
3380   PetscErrorCode ierr;
3381 
3382   PetscFunctionBegin;
3383   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3384   if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2);
3385   ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr);
3386   ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr);
3387   dm->defaultGlobalSection = section;
3388 #ifdef PETSC_USE_DEBUG
3389   if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);}
3390 #endif
3391   PetscFunctionReturn(0);
3392 }
3393 
3394 #undef __FUNCT__
3395 #define __FUNCT__ "DMGetDefaultSF"
3396 /*@
3397   DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set,
3398   it is created from the default PetscSection layouts in the DM.
3399 
3400   Input Parameter:
3401 . dm - The DM
3402 
3403   Output Parameter:
3404 . sf - The PetscSF
3405 
3406   Level: intermediate
3407 
3408   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3409 
3410 .seealso: DMSetDefaultSF(), DMCreateDefaultSF()
3411 @*/
3412 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf)
3413 {
3414   PetscInt       nroots;
3415   PetscErrorCode ierr;
3416 
3417   PetscFunctionBegin;
3418   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3419   PetscValidPointer(sf, 2);
3420   ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
3421   if (nroots < 0) {
3422     PetscSection section, gSection;
3423 
3424     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
3425     if (section) {
3426       ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr);
3427       ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr);
3428     } else {
3429       *sf = NULL;
3430       PetscFunctionReturn(0);
3431     }
3432   }
3433   *sf = dm->defaultSF;
3434   PetscFunctionReturn(0);
3435 }
3436 
3437 #undef __FUNCT__
3438 #define __FUNCT__ "DMSetDefaultSF"
3439 /*@
3440   DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM
3441 
3442   Input Parameters:
3443 + dm - The DM
3444 - sf - The PetscSF
3445 
3446   Level: intermediate
3447 
3448   Note: Any previous SF is destroyed
3449 
3450 .seealso: DMGetDefaultSF(), DMCreateDefaultSF()
3451 @*/
3452 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf)
3453 {
3454   PetscErrorCode ierr;
3455 
3456   PetscFunctionBegin;
3457   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3458   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
3459   ierr          = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr);
3460   dm->defaultSF = sf;
3461   PetscFunctionReturn(0);
3462 }
3463 
3464 #undef __FUNCT__
3465 #define __FUNCT__ "DMCreateDefaultSF"
3466 /*@C
3467   DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections
3468   describing the data layout.
3469 
3470   Input Parameters:
3471 + dm - The DM
3472 . localSection - PetscSection describing the local data layout
3473 - globalSection - PetscSection describing the global data layout
3474 
3475   Level: intermediate
3476 
3477 .seealso: DMGetDefaultSF(), DMSetDefaultSF()
3478 @*/
3479 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection)
3480 {
3481   MPI_Comm       comm;
3482   PetscLayout    layout;
3483   const PetscInt *ranges;
3484   PetscInt       *local;
3485   PetscSFNode    *remote;
3486   PetscInt       pStart, pEnd, p, nroots, nleaves = 0, l;
3487   PetscMPIInt    size, rank;
3488   PetscErrorCode ierr;
3489 
3490   PetscFunctionBegin;
3491   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3492   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3493   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
3494   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3495   ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr);
3496   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr);
3497   ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr);
3498   ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr);
3499   ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr);
3500   ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr);
3501   ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr);
3502   for (p = pStart; p < pEnd; ++p) {
3503     PetscInt gdof, gcdof;
3504 
3505     ierr     = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3506     ierr     = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3507     if (gcdof > (gdof < 0 ? -(gdof+1) : gdof)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d has %d constraints > %d dof", p, gcdof, (gdof < 0 ? -(gdof+1) : gdof));
3508     nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3509   }
3510   ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr);
3511   ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr);
3512   for (p = pStart, l = 0; p < pEnd; ++p) {
3513     const PetscInt *cind;
3514     PetscInt       dof, cdof, off, gdof, gcdof, goff, gsize, d, c;
3515 
3516     ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr);
3517     ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr);
3518     ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr);
3519     ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr);
3520     ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr);
3521     ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr);
3522     ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr);
3523     if (!gdof) continue; /* Censored point */
3524     gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof;
3525     if (gsize != dof-cdof) {
3526       if (gsize != dof) SETERRQ4(comm, PETSC_ERR_ARG_WRONG, "Global dof %d for point %d is neither the constrained size %d, nor the unconstrained %d", gsize, p, dof-cdof, dof);
3527       cdof = 0; /* Ignore constraints */
3528     }
3529     for (d = 0, c = 0; d < dof; ++d) {
3530       if ((c < cdof) && (cind[c] == d)) {++c; continue;}
3531       local[l+d-c] = off+d;
3532     }
3533     if (gdof < 0) {
3534       for (d = 0; d < gsize; ++d, ++l) {
3535         PetscInt offset = -(goff+1) + d, r;
3536 
3537         ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr);
3538         if (r < 0) r = -(r+2);
3539         if ((r < 0) || (r >= size)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d mapped to invalid process %d (%d, %d)", p, r, gdof, goff);
3540         remote[l].rank  = r;
3541         remote[l].index = offset - ranges[r];
3542       }
3543     } else {
3544       for (d = 0; d < gsize; ++d, ++l) {
3545         remote[l].rank  = rank;
3546         remote[l].index = goff+d - ranges[rank];
3547       }
3548     }
3549   }
3550   if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves);
3551   ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
3552   ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr);
3553   PetscFunctionReturn(0);
3554 }
3555 
3556 #undef __FUNCT__
3557 #define __FUNCT__ "DMGetPointSF"
3558 /*@
3559   DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM.
3560 
3561   Input Parameter:
3562 . dm - The DM
3563 
3564   Output Parameter:
3565 . sf - The PetscSF
3566 
3567   Level: intermediate
3568 
3569   Note: This gets a borrowed reference, so the user should not destroy this PetscSF.
3570 
3571 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3572 @*/
3573 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
3574 {
3575   PetscFunctionBegin;
3576   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3577   PetscValidPointer(sf, 2);
3578   *sf = dm->sf;
3579   PetscFunctionReturn(0);
3580 }
3581 
3582 #undef __FUNCT__
3583 #define __FUNCT__ "DMSetPointSF"
3584 /*@
3585   DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM.
3586 
3587   Input Parameters:
3588 + dm - The DM
3589 - sf - The PetscSF
3590 
3591   Level: intermediate
3592 
3593 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF()
3594 @*/
3595 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
3596 {
3597   PetscErrorCode ierr;
3598 
3599   PetscFunctionBegin;
3600   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3601   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
3602   ierr   = PetscSFDestroy(&dm->sf);CHKERRQ(ierr);
3603   ierr   = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr);
3604   dm->sf = sf;
3605   PetscFunctionReturn(0);
3606 }
3607 
3608 #undef __FUNCT__
3609 #define __FUNCT__ "DMGetDS"
3610 /*@
3611   DMGetDS - Get the PetscDS
3612 
3613   Input Parameter:
3614 . dm - The DM
3615 
3616   Output Parameter:
3617 . prob - The PetscDS
3618 
3619   Level: developer
3620 
3621 .seealso: DMSetDS()
3622 @*/
3623 PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
3624 {
3625   PetscFunctionBegin;
3626   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3627   PetscValidPointer(prob, 2);
3628   *prob = dm->prob;
3629   PetscFunctionReturn(0);
3630 }
3631 
3632 #undef __FUNCT__
3633 #define __FUNCT__ "DMSetDS"
3634 /*@
3635   DMSetDS - Set the PetscDS
3636 
3637   Input Parameters:
3638 + dm - The DM
3639 - prob - The PetscDS
3640 
3641   Level: developer
3642 
3643 .seealso: DMGetDS()
3644 @*/
3645 PetscErrorCode DMSetDS(DM dm, PetscDS prob)
3646 {
3647   PetscErrorCode ierr;
3648 
3649   PetscFunctionBegin;
3650   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3651   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2);
3652   ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr);
3653   dm->prob = prob;
3654   ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr);
3655   PetscFunctionReturn(0);
3656 }
3657 
3658 #undef __FUNCT__
3659 #define __FUNCT__ "DMGetNumFields"
3660 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
3661 {
3662   PetscErrorCode ierr;
3663 
3664   PetscFunctionBegin;
3665   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3666   ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr);
3667   PetscFunctionReturn(0);
3668 }
3669 
3670 #undef __FUNCT__
3671 #define __FUNCT__ "DMSetNumFields"
3672 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
3673 {
3674   PetscInt       Nf, f;
3675   PetscErrorCode ierr;
3676 
3677   PetscFunctionBegin;
3678   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3679   ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr);
3680   for (f = Nf; f < numFields; ++f) {
3681     PetscContainer obj;
3682 
3683     ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr);
3684     ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr);
3685     ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr);
3686   }
3687   PetscFunctionReturn(0);
3688 }
3689 
3690 #undef __FUNCT__
3691 #define __FUNCT__ "DMGetField"
3692 /*@
3693   DMGetField - Return the discretization object for a given DM field
3694 
3695   Not collective
3696 
3697   Input Parameters:
3698 + dm - The DM
3699 - f  - The field number
3700 
3701   Output Parameter:
3702 . field - The discretization object
3703 
3704   Level: developer
3705 
3706 .seealso: DMSetField()
3707 @*/
3708 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field)
3709 {
3710   PetscErrorCode ierr;
3711 
3712   PetscFunctionBegin;
3713   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3714   ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3715   PetscFunctionReturn(0);
3716 }
3717 
3718 #undef __FUNCT__
3719 #define __FUNCT__ "DMSetField"
3720 /*@
3721   DMSetField - Set the discretization object for a given DM field
3722 
3723   Logically collective on DM
3724 
3725   Input Parameters:
3726 + dm - The DM
3727 . f  - The field number
3728 - field - The discretization object
3729 
3730   Level: developer
3731 
3732 .seealso: DMGetField()
3733 @*/
3734 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field)
3735 {
3736   PetscErrorCode ierr;
3737 
3738   PetscFunctionBegin;
3739   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3740   ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr);
3741   PetscFunctionReturn(0);
3742 }
3743 
3744 #undef __FUNCT__
3745 #define __FUNCT__ "DMRestrictHook_Coordinates"
3746 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx)
3747 {
3748   DM dm_coord,dmc_coord;
3749   PetscErrorCode ierr;
3750   Vec coords,ccoords;
3751   Mat inject;
3752   PetscFunctionBegin;
3753   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3754   ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr);
3755   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3756   ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr);
3757   if (coords && !ccoords) {
3758     ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr);
3759     ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr);
3760     ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr);
3761     ierr = MatDestroy(&inject);CHKERRQ(ierr);
3762     ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr);
3763     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3764   }
3765   PetscFunctionReturn(0);
3766 }
3767 
3768 #undef __FUNCT__
3769 #define __FUNCT__ "DMSubDomainHook_Coordinates"
3770 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx)
3771 {
3772   DM dm_coord,subdm_coord;
3773   PetscErrorCode ierr;
3774   Vec coords,ccoords,clcoords;
3775   VecScatter *scat_i,*scat_g;
3776   PetscFunctionBegin;
3777   ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr);
3778   ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr);
3779   ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr);
3780   ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr);
3781   if (coords && !ccoords) {
3782     ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr);
3783     ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr);
3784     ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr);
3785     ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3786     ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3787     ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3788     ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3789     ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr);
3790     ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr);
3791     ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr);
3792     ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr);
3793     ierr = VecDestroy(&ccoords);CHKERRQ(ierr);
3794     ierr = VecDestroy(&clcoords);CHKERRQ(ierr);
3795     ierr = PetscFree(scat_i);CHKERRQ(ierr);
3796     ierr = PetscFree(scat_g);CHKERRQ(ierr);
3797   }
3798   PetscFunctionReturn(0);
3799 }
3800 
3801 #undef __FUNCT__
3802 #define __FUNCT__ "DMGetDimension"
3803 /*@
3804   DMGetDimension - Return the topological dimension of the DM
3805 
3806   Not collective
3807 
3808   Input Parameter:
3809 . dm - The DM
3810 
3811   Output Parameter:
3812 . dim - The topological dimension
3813 
3814   Level: beginner
3815 
3816 .seealso: DMSetDimension(), DMCreate()
3817 @*/
3818 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
3819 {
3820   PetscFunctionBegin;
3821   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3822   PetscValidPointer(dim, 2);
3823   *dim = dm->dim;
3824   PetscFunctionReturn(0);
3825 }
3826 
3827 #undef __FUNCT__
3828 #define __FUNCT__ "DMSetDimension"
3829 /*@
3830   DMSetDimension - Set the topological dimension of the DM
3831 
3832   Collective on dm
3833 
3834   Input Parameters:
3835 + dm - The DM
3836 - dim - The topological dimension
3837 
3838   Level: beginner
3839 
3840 .seealso: DMGetDimension(), DMCreate()
3841 @*/
3842 PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
3843 {
3844   PetscFunctionBegin;
3845   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3846   PetscValidLogicalCollectiveInt(dm, dim, 2);
3847   dm->dim = dim;
3848   PetscFunctionReturn(0);
3849 }
3850 
3851 #undef __FUNCT__
3852 #define __FUNCT__ "DMGetDimPoints"
3853 /*@
3854   DMGetDimPoints - Get the half-open interval for all points of a given dimension
3855 
3856   Collective on DM
3857 
3858   Input Parameters:
3859 + dm - the DM
3860 - dim - the dimension
3861 
3862   Output Parameters:
3863 + pStart - The first point of the given dimension
3864 . pEnd - The first point following points of the given dimension
3865 
3866   Note:
3867   The points are vertices in the Hasse diagram encoding the topology. This is explained in
3868   http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme,
3869   then the interval is empty.
3870 
3871   Level: intermediate
3872 
3873 .keywords: point, Hasse Diagram, dimension
3874 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum()
3875 @*/
3876 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
3877 {
3878   PetscInt       d;
3879   PetscErrorCode ierr;
3880 
3881   PetscFunctionBegin;
3882   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3883   ierr = DMGetDimension(dm, &d);CHKERRQ(ierr);
3884   if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d);
3885   ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr);
3886   PetscFunctionReturn(0);
3887 }
3888 
3889 #undef __FUNCT__
3890 #define __FUNCT__ "DMSetCoordinates"
3891 /*@
3892   DMSetCoordinates - Sets into the DM a global vector that holds the coordinates
3893 
3894   Collective on DM
3895 
3896   Input Parameters:
3897 + dm - the DM
3898 - c - coordinate vector
3899 
3900   Note:
3901   The coordinates do include those for ghost points, which are in the local vector
3902 
3903   Level: intermediate
3904 
3905 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3906 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM()
3907 @*/
3908 PetscErrorCode DMSetCoordinates(DM dm, Vec c)
3909 {
3910   PetscErrorCode ierr;
3911 
3912   PetscFunctionBegin;
3913   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3914   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3915   ierr            = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
3916   ierr            = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
3917   dm->coordinates = c;
3918   ierr            = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
3919   ierr            = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
3920   ierr            = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr);
3921   PetscFunctionReturn(0);
3922 }
3923 
3924 #undef __FUNCT__
3925 #define __FUNCT__ "DMSetCoordinatesLocal"
3926 /*@
3927   DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates
3928 
3929   Collective on DM
3930 
3931    Input Parameters:
3932 +  dm - the DM
3933 -  c - coordinate vector
3934 
3935   Note:
3936   The coordinates of ghost points can be set using DMSetCoordinates()
3937   followed by DMGetCoordinatesLocal(). This is intended to enable the
3938   setting of ghost coordinates outside of the domain.
3939 
3940   Level: intermediate
3941 
3942 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3943 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM()
3944 @*/
3945 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
3946 {
3947   PetscErrorCode ierr;
3948 
3949   PetscFunctionBegin;
3950   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3951   PetscValidHeaderSpecific(c,VEC_CLASSID,2);
3952   ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr);
3953   ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr);
3954 
3955   dm->coordinatesLocal = c;
3956 
3957   ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr);
3958   PetscFunctionReturn(0);
3959 }
3960 
3961 #undef __FUNCT__
3962 #define __FUNCT__ "DMGetCoordinates"
3963 /*@
3964   DMGetCoordinates - Gets a global vector with the coordinates associated with the DM.
3965 
3966   Not Collective
3967 
3968   Input Parameter:
3969 . dm - the DM
3970 
3971   Output Parameter:
3972 . c - global coordinate vector
3973 
3974   Note:
3975   This is a borrowed reference, so the user should NOT destroy this vector
3976 
3977   Each process has only the local coordinates (does NOT have the ghost coordinates).
3978 
3979   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
3980   and (x_0,y_0,z_0,x_1,y_1,z_1...)
3981 
3982   Level: intermediate
3983 
3984 .keywords: distributed array, get, corners, nodes, local indices, coordinates
3985 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM()
3986 @*/
3987 PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
3988 {
3989   PetscErrorCode ierr;
3990 
3991   PetscFunctionBegin;
3992   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
3993   PetscValidPointer(c,2);
3994   if (!dm->coordinates && dm->coordinatesLocal) {
3995     DM cdm = NULL;
3996 
3997     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
3998     ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr);
3999     ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr);
4000     ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
4001     ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr);
4002   }
4003   *c = dm->coordinates;
4004   PetscFunctionReturn(0);
4005 }
4006 
4007 #undef __FUNCT__
4008 #define __FUNCT__ "DMGetCoordinatesLocal"
4009 /*@
4010   DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM.
4011 
4012   Collective on DM
4013 
4014   Input Parameter:
4015 . dm - the DM
4016 
4017   Output Parameter:
4018 . c - coordinate vector
4019 
4020   Note:
4021   This is a borrowed reference, so the user should NOT destroy this vector
4022 
4023   Each process has the local and ghost coordinates
4024 
4025   For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4026   and (x_0,y_0,z_0,x_1,y_1,z_1...)
4027 
4028   Level: intermediate
4029 
4030 .keywords: distributed array, get, corners, nodes, local indices, coordinates
4031 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM()
4032 @*/
4033 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
4034 {
4035   PetscErrorCode ierr;
4036 
4037   PetscFunctionBegin;
4038   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4039   PetscValidPointer(c,2);
4040   if (!dm->coordinatesLocal && dm->coordinates) {
4041     DM cdm = NULL;
4042 
4043     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4044     ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr);
4045     ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr);
4046     ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
4047     ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr);
4048   }
4049   *c = dm->coordinatesLocal;
4050   PetscFunctionReturn(0);
4051 }
4052 
4053 #undef __FUNCT__
4054 #define __FUNCT__ "DMGetCoordinateDM"
4055 /*@
4056   DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates
4057 
4058   Collective on DM
4059 
4060   Input Parameter:
4061 . dm - the DM
4062 
4063   Output Parameter:
4064 . cdm - coordinate DM
4065 
4066   Level: intermediate
4067 
4068 .keywords: distributed array, get, corners, nodes, local indices, coordinates
4069 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4070 @*/
4071 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
4072 {
4073   PetscErrorCode ierr;
4074 
4075   PetscFunctionBegin;
4076   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4077   PetscValidPointer(cdm,2);
4078   if (!dm->coordinateDM) {
4079     if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM");
4080     ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr);
4081   }
4082   *cdm = dm->coordinateDM;
4083   PetscFunctionReturn(0);
4084 }
4085 
4086 #undef __FUNCT__
4087 #define __FUNCT__ "DMSetCoordinateDM"
4088 /*@
4089   DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates
4090 
4091   Logically Collective on DM
4092 
4093   Input Parameters:
4094 + dm - the DM
4095 - cdm - coordinate DM
4096 
4097   Level: intermediate
4098 
4099 .keywords: distributed array, get, corners, nodes, local indices, coordinates
4100 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4101 @*/
4102 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
4103 {
4104   PetscErrorCode ierr;
4105 
4106   PetscFunctionBegin;
4107   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4108   PetscValidHeaderSpecific(cdm,DM_CLASSID,2);
4109   ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr);
4110   dm->coordinateDM = cdm;
4111   ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr);
4112   PetscFunctionReturn(0);
4113 }
4114 
4115 #undef __FUNCT__
4116 #define __FUNCT__ "DMGetCoordinateDim"
4117 /*@
4118   DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values.
4119 
4120   Not Collective
4121 
4122   Input Parameter:
4123 . dm - The DM object
4124 
4125   Output Parameter:
4126 . dim - The embedding dimension
4127 
4128   Level: intermediate
4129 
4130 .keywords: mesh, coordinates
4131 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4132 @*/
4133 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
4134 {
4135   PetscFunctionBegin;
4136   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4137   PetscValidPointer(dim, 2);
4138   if (dm->dimEmbed == PETSC_DEFAULT) {
4139     dm->dimEmbed = dm->dim;
4140   }
4141   *dim = dm->dimEmbed;
4142   PetscFunctionReturn(0);
4143 }
4144 
4145 #undef __FUNCT__
4146 #define __FUNCT__ "DMSetCoordinateDim"
4147 /*@
4148   DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
4149 
4150   Not Collective
4151 
4152   Input Parameters:
4153 + dm  - The DM object
4154 - dim - The embedding dimension
4155 
4156   Level: intermediate
4157 
4158 .keywords: mesh, coordinates
4159 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4160 @*/
4161 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
4162 {
4163   PetscFunctionBegin;
4164   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4165   dm->dimEmbed = dim;
4166   PetscFunctionReturn(0);
4167 }
4168 
4169 #undef __FUNCT__
4170 #define __FUNCT__ "DMGetCoordinateSection"
4171 /*@
4172   DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
4173 
4174   Not Collective
4175 
4176   Input Parameter:
4177 . dm - The DM object
4178 
4179   Output Parameter:
4180 . section - The PetscSection object
4181 
4182   Level: intermediate
4183 
4184 .keywords: mesh, coordinates
4185 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection()
4186 @*/
4187 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
4188 {
4189   DM             cdm;
4190   PetscErrorCode ierr;
4191 
4192   PetscFunctionBegin;
4193   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4194   PetscValidPointer(section, 2);
4195   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4196   ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr);
4197   PetscFunctionReturn(0);
4198 }
4199 
4200 #undef __FUNCT__
4201 #define __FUNCT__ "DMSetCoordinateSection"
4202 /*@
4203   DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
4204 
4205   Not Collective
4206 
4207   Input Parameters:
4208 + dm      - The DM object
4209 . dim     - The embedding dimension, or PETSC_DETERMINE
4210 - section - The PetscSection object
4211 
4212   Level: intermediate
4213 
4214 .keywords: mesh, coordinates
4215 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection()
4216 @*/
4217 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
4218 {
4219   DM             cdm;
4220   PetscErrorCode ierr;
4221 
4222   PetscFunctionBegin;
4223   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4224   PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3);
4225   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
4226   ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr);
4227   if (dim == PETSC_DETERMINE) {
4228     PetscInt d = dim;
4229     PetscInt pStart, pEnd, vStart, vEnd, v, dd;
4230 
4231     ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
4232     ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4233     pStart = PetscMax(vStart, pStart);
4234     pEnd   = PetscMin(vEnd, pEnd);
4235     for (v = pStart; v < pEnd; ++v) {
4236       ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr);
4237       if (dd) {d = dd; break;}
4238     }
4239     ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);
4240   }
4241   PetscFunctionReturn(0);
4242 }
4243 
4244 #undef __FUNCT__
4245 #define __FUNCT__ "DMGetPeriodicity"
4246 /*@C
4247   DMSetPeriodicity - Set the description of mesh periodicity
4248 
4249   Input Parameters:
4250 + dm      - The DM object
4251 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4252 . L       - If we assume the mesh is a torus, this is the length of each coordinate
4253 - bd      - This describes the type of periodicity in each topological dimension
4254 
4255   Level: developer
4256 
4257 .seealso: DMGetPeriodicity()
4258 @*/
4259 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd)
4260 {
4261   PetscFunctionBegin;
4262   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4263   if (L)       *L       = dm->L;
4264   if (maxCell) *maxCell = dm->maxCell;
4265   if (bd)      *bd      = dm->bdtype;
4266   PetscFunctionReturn(0);
4267 }
4268 
4269 #undef __FUNCT__
4270 #define __FUNCT__ "DMSetPeriodicity"
4271 /*@C
4272   DMSetPeriodicity - Set the description of mesh periodicity
4273 
4274   Input Parameters:
4275 + dm      - The DM object
4276 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
4277 . L       - If we assume the mesh is a torus, this is the length of each coordinate
4278 - bd      - This describes the type of periodicity in each topological dimension
4279 
4280   Level: developer
4281 
4282 .seealso: DMGetPeriodicity()
4283 @*/
4284 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[])
4285 {
4286   PetscInt       dim, d;
4287   PetscErrorCode ierr;
4288 
4289   PetscFunctionBegin;
4290   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4291   PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4);
4292   ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr);
4293   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
4294   ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr);
4295   for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];}
4296   PetscFunctionReturn(0);
4297 }
4298 
4299 #undef __FUNCT__
4300 #define __FUNCT__ "DMLocatePoints"
4301 /*@
4302   DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells
4303 
4304   Not collective
4305 
4306   Input Parameters:
4307 + dm - The DM
4308 - v - The Vec of points
4309 
4310   Output Parameter:
4311 . cells - The local cell numbers for cells which contain the points
4312 
4313   Level: developer
4314 
4315 .keywords: point location, mesh
4316 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal()
4317 @*/
4318 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells)
4319 {
4320   PetscErrorCode ierr;
4321 
4322   PetscFunctionBegin;
4323   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4324   PetscValidHeaderSpecific(v,VEC_CLASSID,2);
4325   PetscValidPointer(cells,3);
4326   ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr);
4327   if (dm->ops->locatepoints) {
4328     ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr);
4329   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM");
4330   ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr);
4331   PetscFunctionReturn(0);
4332 }
4333 
4334 #undef __FUNCT__
4335 #define __FUNCT__ "DMGetOutputDM"
4336 /*@
4337   DMGetOutputDM - Retrieve the DM associated with the layout for output
4338 
4339   Input Parameter:
4340 . dm - The original DM
4341 
4342   Output Parameter:
4343 . odm - The DM which provides the layout for output
4344 
4345   Level: intermediate
4346 
4347 .seealso: VecView(), DMGetDefaultGlobalSection()
4348 @*/
4349 PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
4350 {
4351   PetscSection   section;
4352   PetscBool      hasConstraints;
4353   PetscErrorCode ierr;
4354 
4355   PetscFunctionBegin;
4356   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4357   PetscValidPointer(odm,2);
4358   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
4359   ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr);
4360   if (!hasConstraints) {
4361     *odm = dm;
4362     PetscFunctionReturn(0);
4363   }
4364   if (!dm->dmBC) {
4365     PetscSection newSection, gsection;
4366     PetscSF      sf;
4367 
4368     ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr);
4369     ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr);
4370     ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr);
4371     ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr);
4372     ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr);
4373     ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr);
4374     ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr);
4375     ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr);
4376   }
4377   *odm = dm->dmBC;
4378   PetscFunctionReturn(0);
4379 }
4380 
4381 #undef __FUNCT__
4382 #define __FUNCT__ "DMGetOutputSequenceNumber"
4383 /*@
4384   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
4385 
4386   Input Parameter:
4387 . dm - The original DM
4388 
4389   Output Parameters:
4390 + num - The output sequence number
4391 - val - The output sequence value
4392 
4393   Level: intermediate
4394 
4395   Note: This is intended for output that should appear in sequence, for instance
4396   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4397 
4398 .seealso: VecView()
4399 @*/
4400 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
4401 {
4402   PetscFunctionBegin;
4403   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4404   if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;}
4405   if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;}
4406   PetscFunctionReturn(0);
4407 }
4408 
4409 #undef __FUNCT__
4410 #define __FUNCT__ "DMSetOutputSequenceNumber"
4411 /*@
4412   DMSetOutputSequenceNumber - Set the sequence number/value for output
4413 
4414   Input Parameters:
4415 + dm - The original DM
4416 . num - The output sequence number
4417 - val - The output sequence value
4418 
4419   Level: intermediate
4420 
4421   Note: This is intended for output that should appear in sequence, for instance
4422   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4423 
4424 .seealso: VecView()
4425 @*/
4426 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
4427 {
4428   PetscFunctionBegin;
4429   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4430   dm->outputSequenceNum = num;
4431   dm->outputSequenceVal = val;
4432   PetscFunctionReturn(0);
4433 }
4434 
4435 #undef __FUNCT__
4436 #define __FUNCT__ "DMOutputSequenceLoad"
4437 /*@C
4438   DMOutputSequenceLoad - Retrieve the sequence value from a Viewer
4439 
4440   Input Parameters:
4441 + dm   - The original DM
4442 . name - The sequence name
4443 - num  - The output sequence number
4444 
4445   Output Parameter:
4446 . val  - The output sequence value
4447 
4448   Level: intermediate
4449 
4450   Note: This is intended for output that should appear in sequence, for instance
4451   a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system.
4452 
4453 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView()
4454 @*/
4455 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
4456 {
4457   PetscBool      ishdf5;
4458   PetscErrorCode ierr;
4459 
4460   PetscFunctionBegin;
4461   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
4462   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4463   PetscValidPointer(val,4);
4464   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
4465   if (ishdf5) {
4466 #if defined(PETSC_HAVE_HDF5)
4467     PetscScalar value;
4468 
4469     ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr);
4470     *val = PetscRealPart(value);
4471 #endif
4472   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
4473   PetscFunctionReturn(0);
4474 }
4475 
4476 #undef __FUNCT__
4477 #define __FUNCT__ "DMGetUseNatural"
4478 /*@
4479   DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution
4480 
4481   Not collective
4482 
4483   Input Parameter:
4484 . dm - The DM
4485 
4486   Output Parameter:
4487 . useNatural - The flag to build the mapping to a natural order during distribution
4488 
4489   Level: beginner
4490 
4491 .seealso: DMSetUseNatural(), DMCreate()
4492 @*/
4493 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
4494 {
4495   PetscFunctionBegin;
4496   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4497   PetscValidPointer(useNatural, 2);
4498   *useNatural = dm->useNatural;
4499   PetscFunctionReturn(0);
4500 }
4501 
4502 #undef __FUNCT__
4503 #define __FUNCT__ "DMSetUseNatural"
4504 /*@
4505   DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution
4506 
4507   Collective on dm
4508 
4509   Input Parameters:
4510 + dm - The DM
4511 - useNatural - The flag to build the mapping to a natural order during distribution
4512 
4513   Level: beginner
4514 
4515 .seealso: DMGetUseNatural(), DMCreate()
4516 @*/
4517 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
4518 {
4519   PetscFunctionBegin;
4520   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4521   PetscValidLogicalCollectiveInt(dm, useNatural, 2);
4522   dm->useNatural = useNatural;
4523   PetscFunctionReturn(0);
4524 }
4525