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