xref: /petsc/src/dm/interface/dm.c (revision 1cc06b555e92f8ec64db10330b8bbd830e5bc876)
1d0295fc0SJunchao Zhang #include <petscvec.h>
2af0996ceSBarry Smith #include <petsc/private/dmimpl.h>      /*I      "petscdm.h"          I*/
3c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h> /*I      "petscdmlabel.h"     I*/
4e6f8dbb6SToby Isaac #include <petsc/private/petscdsimpl.h> /*I      "petscds.h"     I*/
53e922f36SToby Isaac #include <petscdmplex.h>
6f19dbd58SToby Isaac #include <petscdmfield.h>
70c312b8eSJed Brown #include <petscsf.h>
82764a2aaSMatthew G. Knepley #include <petscds.h>
947c6ae99SBarry Smith 
10f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
11f918ec44SMatthew G. Knepley   #include <petscfeceed.h>
12f918ec44SMatthew G. Knepley #endif
13f918ec44SMatthew G. Knepley 
14cea3dcb8SSatish Balay #if !defined(PETSC_HAVE_WINDOWS_COMPILERS)
15cea3dcb8SSatish Balay   #include <petsc/private/valgrind/memcheck.h>
1600d952a4SJed Brown #endif
1700d952a4SJed Brown 
18732e2eb9SMatthew G Knepley PetscClassId DM_CLASSID;
19d67d17b1SMatthew G. Knepley PetscClassId DMLABEL_CLASSID;
205b8ffe73SMark Adams PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction, DM_CreateInjection, DM_CreateMatrix, DM_CreateMassMatrix, DM_Load, DM_AdaptInterpolator;
2167a56275SMatthew G Knepley 
22ea78f98cSLisandro Dalcin const char *const DMBoundaryTypes[]          = {"NONE", "GHOSTED", "MIRROR", "PERIODIC", "TWIST", "DMBoundaryType", "DM_BOUNDARY_", NULL};
23d1b3049bSMatthew G. Knepley const char *const DMBoundaryConditionTypes[] = {"INVALID", "ESSENTIAL", "NATURAL", "INVALID", "INVALID", "ESSENTIAL_FIELD", "NATURAL_FIELD", "INVALID", "INVALID", "ESSENTIAL_BD_FIELD", "NATURAL_RIEMANN", "DMBoundaryConditionType", "DM_BC_", NULL};
240e762ea3SJed Brown const char *const DMBlockingTypes[]          = {"TOPOLOGICAL_POINT", "FIELD_NODE", "DMBlockingType", "DM_BLOCKING_", NULL};
259371c9d4SSatish Balay const char *const DMPolytopeTypes[]   = {"vertex",  "segment",       "tensor_segment",      "triangle", "quadrilateral", "tensor_quad",    "tetrahedron",  "hexahedron", "triangular_prism", "tensor_triangular_prism", "tensor_quadrilateral_prism",
269371c9d4SSatish Balay                                          "pyramid", "FV_ghost_cell", "interior_ghost_cell", "unknown",  "invalid",       "DMPolytopeType", "DM_POLYTOPE_", NULL};
272cbb9b06SVaclav Hapla const char *const DMCopyLabelsModes[] = {"replace", "keep", "fail", "DMCopyLabelsMode", "DM_COPY_LABELS_", NULL};
2860c22052SBarry Smith 
29a4121054SBarry Smith /*@
30bb7acecfSBarry Smith   DMCreate - Creates an empty `DM` object. `DM`s are the abstract objects in PETSc that mediate between meshes and discretizations and the
31bb7acecfSBarry Smith   algebraic solvers, time integrators, and optimization algorithms.
32a4121054SBarry Smith 
33d083f849SBarry Smith   Collective
34a4121054SBarry Smith 
35a4121054SBarry Smith   Input Parameter:
36bb7acecfSBarry Smith . comm - The communicator for the `DM` object
37a4121054SBarry Smith 
38a4121054SBarry Smith   Output Parameter:
39bb7acecfSBarry Smith . dm - The `DM` object
40a4121054SBarry Smith 
41a4121054SBarry Smith   Level: beginner
42a4121054SBarry Smith 
43bb7acecfSBarry Smith   Notes:
44bb7acecfSBarry Smith   See `DMType` for a brief summary of available `DM`.
45bb7acecfSBarry Smith 
46bb7acecfSBarry Smith   The type must then be set with `DMSetType()`. If you never call `DMSetType()` it will generate an
47bb7acecfSBarry Smith   error when you try to use the dm.
48bb7acecfSBarry Smith 
49*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetType()`, `DMType`, `DMDACreate()`, `DMDA`, `DMSLICED`, `DMCOMPOSITE`, `DMPLEX`, `DMMOAB`, `DMNETWORK`
50a4121054SBarry Smith @*/
51d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreate(MPI_Comm comm, DM *dm)
52d71ae5a4SJacob Faibussowitsch {
53a4121054SBarry Smith   DM      v;
54e5e52638SMatthew G. Knepley   PetscDS ds;
55a4121054SBarry Smith 
56a4121054SBarry Smith   PetscFunctionBegin;
571411c6eeSJed Brown   PetscValidPointer(dm, 2);
580298fd71SBarry Smith   *dm = NULL;
599566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
60a4121054SBarry Smith 
619566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView));
62e7c4fc90SDmitry Karpeev 
6362e5d2d2SJDBetteridge   ((PetscObject)v)->non_cyclic_references = &DMCountNonCyclicReferences;
6462e5d2d2SJDBetteridge 
6549be4549SMatthew G. Knepley   v->setupcalled          = PETSC_FALSE;
6649be4549SMatthew G. Knepley   v->setfromoptionscalled = PETSC_FALSE;
670298fd71SBarry Smith   v->ltogmap              = NULL;
68a4ea9b21SRichard Tran Mills   v->bind_below           = 0;
691411c6eeSJed Brown   v->bs                   = 1;
70171400e9SBarry Smith   v->coloringtype         = IS_COLORING_GLOBAL;
719566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &v->sf));
729566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &v->sectionSF));
73c58f1c22SToby Isaac   v->labels                    = NULL;
7434aa8a36SMatthew G. Knepley   v->adjacency[0]              = PETSC_FALSE;
7534aa8a36SMatthew G. Knepley   v->adjacency[1]              = PETSC_TRUE;
76c58f1c22SToby Isaac   v->depthLabel                = NULL;
77ba2698f1SMatthew G. Knepley   v->celltypeLabel             = NULL;
781bb6d2a8SBarry Smith   v->localSection              = NULL;
791bb6d2a8SBarry Smith   v->globalSection             = NULL;
803b8ba7d1SJed Brown   v->defaultConstraint.section = NULL;
813b8ba7d1SJed Brown   v->defaultConstraint.mat     = NULL;
8279769bd5SJed Brown   v->defaultConstraint.bias    = NULL;
836858538eSMatthew G. Knepley   v->coordinates[0].dim        = PETSC_DEFAULT;
846858538eSMatthew G. Knepley   v->coordinates[1].dim        = PETSC_DEFAULT;
856858538eSMatthew G. Knepley   v->sparseLocalize            = PETSC_TRUE;
8696173672SStefano Zampini   v->dim                       = PETSC_DETERMINE;
87435a35e8SMatthew G Knepley   {
88435a35e8SMatthew G Knepley     PetscInt i;
89435a35e8SMatthew G Knepley     for (i = 0; i < 10; ++i) {
900298fd71SBarry Smith       v->nullspaceConstructors[i]     = NULL;
91f9d4088aSMatthew G. Knepley       v->nearnullspaceConstructors[i] = NULL;
92435a35e8SMatthew G Knepley     }
93435a35e8SMatthew G Knepley   }
949566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
9507218a29SMatthew G. Knepley   PetscCall(DMSetRegionDS(v, NULL, NULL, ds, NULL));
969566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&ds));
979566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxCreate(&v->auxData));
9814f150ffSMatthew G. Knepley   v->dmBC              = NULL;
99a8fb8f29SToby Isaac   v->coarseMesh        = NULL;
100f4d763aaSMatthew G. Knepley   v->outputSequenceNum = -1;
101cdb7a50dSMatthew G. Knepley   v->outputSequenceVal = 0.0;
1029566063dSJacob Faibussowitsch   PetscCall(DMSetVecType(v, VECSTANDARD));
1039566063dSJacob Faibussowitsch   PetscCall(DMSetMatType(v, MATAIJ));
1044a7a4c06SLawrence Mitchell 
1051411c6eeSJed Brown   *dm = v;
1063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
107a4121054SBarry Smith }
108a4121054SBarry Smith 
10938221697SMatthew G. Knepley /*@
110bb7acecfSBarry Smith   DMClone - Creates a `DM` object with the same topology as the original.
11138221697SMatthew G. Knepley 
112d083f849SBarry Smith   Collective
11338221697SMatthew G. Knepley 
11438221697SMatthew G. Knepley   Input Parameter:
115bb7acecfSBarry Smith . dm - The original `DM` object
11638221697SMatthew G. Knepley 
11738221697SMatthew G. Knepley   Output Parameter:
118bb7acecfSBarry Smith . newdm  - The new `DM` object
11938221697SMatthew G. Knepley 
12038221697SMatthew G. Knepley   Level: beginner
12138221697SMatthew G. Knepley 
1221cb8cacdSPatrick Sanan   Notes:
123bb7acecfSBarry Smith   For some `DM` implementations this is a shallow clone, the result of which may share (reference counted) information with its parent. For example,
124bb7acecfSBarry Smith   `DMClone()` applied to a `DMPLEX` object will result in a new `DMPLEX` that shares the topology with the original `DMPLEX`. It does not
125bb7acecfSBarry Smith   share the `PetscSection` of the original `DM`.
1261bb6d2a8SBarry Smith 
127bb7acecfSBarry Smith   The clone is considered set up if the original has been set up.
12889706ed2SPatrick Sanan 
129bb7acecfSBarry Smith   Use `DMConvert()` for a general way to create new `DM` from a given `DM`
130bb7acecfSBarry Smith 
131*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMSetType()`, `DMSetLocalSection()`, `DMSetGlobalSection()`, `DMPLEX`, `DMSetType()`, `DMConvert()`
13238221697SMatthew G. Knepley @*/
133d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClone(DM dm, DM *newdm)
134d71ae5a4SJacob Faibussowitsch {
13538221697SMatthew G. Knepley   PetscSF  sf;
13638221697SMatthew G. Knepley   Vec      coords;
13738221697SMatthew G. Knepley   void    *ctx;
1386858538eSMatthew G. Knepley   PetscInt dim, cdim, i;
13938221697SMatthew G. Knepley 
14038221697SMatthew G. Knepley   PetscFunctionBegin;
14138221697SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14238221697SMatthew G. Knepley   PetscValidPointer(newdm, 2);
1439566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), newdm));
1449566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dm, *newdm, PETSC_COPY_VALUES, PETSC_TRUE, DM_COPY_LABELS_FAIL));
145ddf8437dSMatthew G. Knepley   (*newdm)->leveldown     = dm->leveldown;
146ddf8437dSMatthew G. Knepley   (*newdm)->levelup       = dm->levelup;
147c8a6034eSMark   (*newdm)->prealloc_only = dm->prealloc_only;
1489566063dSJacob Faibussowitsch   PetscCall(PetscFree((*newdm)->vectype));
1499566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*newdm)->vectype));
1509566063dSJacob Faibussowitsch   PetscCall(PetscFree((*newdm)->mattype));
1519566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*newdm)->mattype));
1529566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1539566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*newdm, dim));
154dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, clone, newdm);
1553f22bcbcSToby Isaac   (*newdm)->setupcalled = dm->setupcalled;
1569566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
1579566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(*newdm, sf));
1589566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dm, &ctx));
1599566063dSJacob Faibussowitsch   PetscCall(DMSetApplicationContext(*newdm, ctx));
1606858538eSMatthew G. Knepley   for (i = 0; i < 2; ++i) {
1616858538eSMatthew G. Knepley     if (dm->coordinates[i].dm) {
162be4c1c3eSMatthew G. Knepley       DM           ncdm;
163be4c1c3eSMatthew G. Knepley       PetscSection cs;
1645a0206caSToby Isaac       PetscInt     pEnd = -1, pEndMax = -1;
165be4c1c3eSMatthew G. Knepley 
1666858538eSMatthew G. Knepley       PetscCall(DMGetLocalSection(dm->coordinates[i].dm, &cs));
1679566063dSJacob Faibussowitsch       if (cs) PetscCall(PetscSectionGetChart(cs, NULL, &pEnd));
168712fec58SPierre Jolivet       PetscCall(MPIU_Allreduce(&pEnd, &pEndMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1695a0206caSToby Isaac       if (pEndMax >= 0) {
1706858538eSMatthew G. Knepley         PetscCall(DMClone(dm->coordinates[i].dm, &ncdm));
1716858538eSMatthew G. Knepley         PetscCall(DMCopyDisc(dm->coordinates[i].dm, ncdm));
1729566063dSJacob Faibussowitsch         PetscCall(DMSetLocalSection(ncdm, cs));
1736858538eSMatthew G. Knepley         if (i) PetscCall(DMSetCellCoordinateDM(*newdm, ncdm));
1746858538eSMatthew G. Knepley         else PetscCall(DMSetCoordinateDM(*newdm, ncdm));
1759566063dSJacob Faibussowitsch         PetscCall(DMDestroy(&ncdm));
176be4c1c3eSMatthew G. Knepley       }
177be4c1c3eSMatthew G. Knepley     }
1786858538eSMatthew G. Knepley   }
1799566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1809566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*newdm, cdim));
1819566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coords));
18238221697SMatthew G. Knepley   if (coords) {
1839566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(*newdm, coords));
18438221697SMatthew G. Knepley   } else {
1859566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinates(dm, &coords));
1869566063dSJacob Faibussowitsch     if (coords) PetscCall(DMSetCoordinates(*newdm, coords));
18738221697SMatthew G. Knepley   }
1886858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &coords));
1896858538eSMatthew G. Knepley   if (coords) {
1906858538eSMatthew G. Knepley     PetscCall(DMSetCellCoordinatesLocal(*newdm, coords));
1916858538eSMatthew G. Knepley   } else {
1926858538eSMatthew G. Knepley     PetscCall(DMGetCellCoordinates(dm, &coords));
1936858538eSMatthew G. Knepley     if (coords) PetscCall(DMSetCellCoordinates(*newdm, coords));
1946858538eSMatthew G. Knepley   }
19590b157c4SStefano Zampini   {
1964fb89dddSMatthew G. Knepley     const PetscReal *maxCell, *Lstart, *L;
1976858538eSMatthew G. Knepley 
1984fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
1994fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(*newdm, maxCell, Lstart, L));
200c6b900c6SMatthew G. Knepley   }
20134aa8a36SMatthew G. Knepley   {
20234aa8a36SMatthew G. Knepley     PetscBool useCone, useClosure;
20334aa8a36SMatthew G. Knepley 
2049566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, PETSC_DEFAULT, &useCone, &useClosure));
2059566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(*newdm, PETSC_DEFAULT, useCone, useClosure));
20634aa8a36SMatthew G. Knepley   }
2073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20838221697SMatthew G. Knepley }
20938221697SMatthew G. Knepley 
2109a42bb27SBarry Smith /*@C
211bb7acecfSBarry Smith        DMSetVecType - Sets the type of vector created with `DMCreateLocalVector()` and `DMCreateGlobalVector()`
2129a42bb27SBarry Smith 
21320f4b53cSBarry Smith    Logically Collective
2149a42bb27SBarry Smith 
215147403d9SBarry Smith    Input Parameters:
2169a42bb27SBarry Smith +  da - initial distributed array
217bb7acecfSBarry Smith -  ctype - the vector type, for example `VECSTANDARD`, `VECCUDA`, or `VECVIENNACL`
2189a42bb27SBarry Smith 
21920f4b53cSBarry Smith    Options Database Key:
220147403d9SBarry Smith .   -dm_vec_type ctype - the type of vector to create
2219a42bb27SBarry Smith 
2229a42bb27SBarry Smith    Level: intermediate
2239a42bb27SBarry Smith 
224*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMDestroy()`, `DM`, `DMDAInterpolationType`, `VecType`, `DMGetVecType()`, `DMSetMatType()`, `DMGetMatType()`,
225bb7acecfSBarry Smith           `VECSTANDARD`, `VECCUDA`, `VECVIENNACL`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`
2269a42bb27SBarry Smith @*/
227d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetVecType(DM da, VecType ctype)
228d71ae5a4SJacob Faibussowitsch {
2299a42bb27SBarry Smith   PetscFunctionBegin;
2309a42bb27SBarry Smith   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
2319566063dSJacob Faibussowitsch   PetscCall(PetscFree(da->vectype));
2329566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ctype, (char **)&da->vectype));
2333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2349a42bb27SBarry Smith }
2359a42bb27SBarry Smith 
236c0dedaeaSBarry Smith /*@C
237bb7acecfSBarry Smith        DMGetVecType - Gets the type of vector created with `DMCreateLocalVector()` and `DMCreateGlobalVector()`
238c0dedaeaSBarry Smith 
23920f4b53cSBarry Smith    Logically Collective
240c0dedaeaSBarry Smith 
241c0dedaeaSBarry Smith    Input Parameter:
242c0dedaeaSBarry Smith .  da - initial distributed array
243c0dedaeaSBarry Smith 
244c0dedaeaSBarry Smith    Output Parameter:
245c0dedaeaSBarry Smith .  ctype - the vector type
246c0dedaeaSBarry Smith 
247c0dedaeaSBarry Smith    Level: intermediate
248c0dedaeaSBarry Smith 
249*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMDestroy()`, `DM`, `DMDAInterpolationType`, `VecType`, `DMSetMatType()`, `DMGetMatType()`, `DMSetVecType()`
250c0dedaeaSBarry Smith @*/
251d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetVecType(DM da, VecType *ctype)
252d71ae5a4SJacob Faibussowitsch {
253c0dedaeaSBarry Smith   PetscFunctionBegin;
254c0dedaeaSBarry Smith   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
255c0dedaeaSBarry Smith   *ctype = da->vectype;
2563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
257c0dedaeaSBarry Smith }
258c0dedaeaSBarry Smith 
2595f1ad066SMatthew G Knepley /*@
260bb7acecfSBarry Smith   VecGetDM - Gets the `DM` defining the data layout of the vector
2615f1ad066SMatthew G Knepley 
26220f4b53cSBarry Smith   Not Collective
2635f1ad066SMatthew G Knepley 
2645f1ad066SMatthew G Knepley   Input Parameter:
265bb7acecfSBarry Smith . v - The `Vec`
2665f1ad066SMatthew G Knepley 
2675f1ad066SMatthew G Knepley   Output Parameter:
268bb7acecfSBarry Smith . dm - The `DM`
2695f1ad066SMatthew G Knepley 
2705f1ad066SMatthew G Knepley   Level: intermediate
2715f1ad066SMatthew G Knepley 
272bb7acecfSBarry Smith   Note:
273bb7acecfSBarry Smith   A `Vec` may not have a `DM` associated with it.
274bb7acecfSBarry Smith 
275*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecSetDM()`, `DMGetLocalVector()`, `DMGetGlobalVector()`, `DMSetVecType()`
2765f1ad066SMatthew G Knepley @*/
277d71ae5a4SJacob Faibussowitsch PetscErrorCode VecGetDM(Vec v, DM *dm)
278d71ae5a4SJacob Faibussowitsch {
2795f1ad066SMatthew G Knepley   PetscFunctionBegin;
2805f1ad066SMatthew G Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
2815f1ad066SMatthew G Knepley   PetscValidPointer(dm, 2);
2829566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)v, "__PETSc_dm", (PetscObject *)dm));
2833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2845f1ad066SMatthew G Knepley }
2855f1ad066SMatthew G Knepley 
2865f1ad066SMatthew G Knepley /*@
287bb7acecfSBarry Smith   VecSetDM - Sets the `DM` defining the data layout of the vector.
2885f1ad066SMatthew G Knepley 
28920f4b53cSBarry Smith   Not Collective
2905f1ad066SMatthew G Knepley 
2915f1ad066SMatthew G Knepley   Input Parameters:
292bb7acecfSBarry Smith + v - The `Vec`
293bb7acecfSBarry Smith - dm - The `DM`
2945f1ad066SMatthew G Knepley 
29520f4b53cSBarry Smith   Level: developer
29620f4b53cSBarry Smith 
297bb7acecfSBarry Smith   Note:
298bb7acecfSBarry Smith   This is rarely used, generally one uses `DMGetLocalVector()` or  `DMGetGlobalVector()` to create a vector associated with a given `DM`
299d9805387SMatthew G. Knepley 
300bb7acecfSBarry Smith   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.
301bb7acecfSBarry Smith 
302*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecGetDM()`, `DMGetLocalVector()`, `DMGetGlobalVector()`, `DMSetVecType()`
3035f1ad066SMatthew G Knepley @*/
304d71ae5a4SJacob Faibussowitsch PetscErrorCode VecSetDM(Vec v, DM dm)
305d71ae5a4SJacob Faibussowitsch {
3065f1ad066SMatthew G Knepley   PetscFunctionBegin;
3075f1ad066SMatthew G Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
308d7f50e27SLisandro Dalcin   if (dm) PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
3099566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)v, "__PETSc_dm", (PetscObject)dm));
3103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3115f1ad066SMatthew G Knepley }
3125f1ad066SMatthew G Knepley 
313521d9a4cSLisandro Dalcin /*@C
314bb7acecfSBarry Smith        DMSetISColoringType - Sets the type of coloring, `IS_COLORING_GLOBAL` or `IS_COLORING_LOCAL` that is created by the `DM`
3158f1509bcSBarry Smith 
31620f4b53cSBarry Smith    Logically Collective
3178f1509bcSBarry Smith 
3188f1509bcSBarry Smith    Input Parameters:
319bb7acecfSBarry Smith +  dm - the `DM` context
3208f1509bcSBarry Smith -  ctype - the matrix type
3218f1509bcSBarry Smith 
32220f4b53cSBarry Smith    Options Database Key:
3238f1509bcSBarry Smith .   -dm_is_coloring_type - global or local
3248f1509bcSBarry Smith 
3258f1509bcSBarry Smith    Level: intermediate
3268f1509bcSBarry Smith 
327*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMGetMatType()`,
328bb7acecfSBarry Smith           `DMGetISColoringType()`, `ISColoringType`, `IS_COLORING_GLOBAL`, `IS_COLORING_LOCAL`
3298f1509bcSBarry Smith @*/
330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetISColoringType(DM dm, ISColoringType ctype)
331d71ae5a4SJacob Faibussowitsch {
3328f1509bcSBarry Smith   PetscFunctionBegin;
3338f1509bcSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3348f1509bcSBarry Smith   dm->coloringtype = ctype;
3353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3368f1509bcSBarry Smith }
3378f1509bcSBarry Smith 
3388f1509bcSBarry Smith /*@C
339bb7acecfSBarry Smith        DMGetISColoringType - Gets the type of coloring, `IS_COLORING_GLOBAL` or `IS_COLORING_LOCAL` that is created by the `DM`
340521d9a4cSLisandro Dalcin 
34120f4b53cSBarry Smith    Logically Collective
342521d9a4cSLisandro Dalcin 
343521d9a4cSLisandro Dalcin    Input Parameter:
344bb7acecfSBarry Smith .  dm - the `DM` context
3458f1509bcSBarry Smith 
3468f1509bcSBarry Smith    Output Parameter:
3478f1509bcSBarry Smith .  ctype - the matrix type
3488f1509bcSBarry Smith 
34920f4b53cSBarry Smith    Options Database Key:
3508f1509bcSBarry Smith .   -dm_is_coloring_type - global or local
3518f1509bcSBarry Smith 
3528f1509bcSBarry Smith    Level: intermediate
3538f1509bcSBarry Smith 
354*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMGetMatType()`,
355bb7acecfSBarry Smith           `DMGetISColoringType()`, `ISColoringType`, `IS_COLORING_GLOBAL`, `IS_COLORING_LOCAL`
3568f1509bcSBarry Smith @*/
357d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetISColoringType(DM dm, ISColoringType *ctype)
358d71ae5a4SJacob Faibussowitsch {
3598f1509bcSBarry Smith   PetscFunctionBegin;
3608f1509bcSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3618f1509bcSBarry Smith   *ctype = dm->coloringtype;
3623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3638f1509bcSBarry Smith }
3648f1509bcSBarry Smith 
3658f1509bcSBarry Smith /*@C
366bb7acecfSBarry Smith        DMSetMatType - Sets the type of matrix created with `DMCreateMatrix()`
3678f1509bcSBarry Smith 
36820f4b53cSBarry Smith    Logically Collective
3698f1509bcSBarry Smith 
3708f1509bcSBarry Smith    Input Parameters:
371bb7acecfSBarry Smith +  dm - the `DM` context
372bb7acecfSBarry Smith -  ctype - the matrix type, for example `MATMPIAIJ`
373521d9a4cSLisandro Dalcin 
37420f4b53cSBarry Smith    Options Database Key:
375bb7acecfSBarry Smith .   -dm_mat_type ctype - the type of the matrix to create, for example mpiaij
376521d9a4cSLisandro Dalcin 
377521d9a4cSLisandro Dalcin    Level: intermediate
378521d9a4cSLisandro Dalcin 
379*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatType`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMGetMatType()`, `DMSetMatType()`, `DMGetMatType()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
380521d9a4cSLisandro Dalcin @*/
381d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatType(DM dm, MatType ctype)
382d71ae5a4SJacob Faibussowitsch {
383521d9a4cSLisandro Dalcin   PetscFunctionBegin;
384521d9a4cSLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3859566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->mattype));
3869566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ctype, (char **)&dm->mattype));
3873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
388521d9a4cSLisandro Dalcin }
389521d9a4cSLisandro Dalcin 
390c0dedaeaSBarry Smith /*@C
39120f4b53cSBarry Smith        DMGetMatType - Gets the type of matrix that would be created with `DMCreateMatrix()`
392c0dedaeaSBarry Smith 
39320f4b53cSBarry Smith    Logically Collective
394c0dedaeaSBarry Smith 
395c0dedaeaSBarry Smith    Input Parameter:
396bb7acecfSBarry Smith .  dm - the `DM` context
397c0dedaeaSBarry Smith 
398c0dedaeaSBarry Smith    Output Parameter:
399c0dedaeaSBarry Smith .  ctype - the matrix type
400c0dedaeaSBarry Smith 
401c0dedaeaSBarry Smith    Level: intermediate
402c0dedaeaSBarry Smith 
403*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMSetMatType()`, `DMSetMatType()`, `DMGetMatType()`
404c0dedaeaSBarry Smith @*/
405d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetMatType(DM dm, MatType *ctype)
406d71ae5a4SJacob Faibussowitsch {
407c0dedaeaSBarry Smith   PetscFunctionBegin;
408c0dedaeaSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
409c0dedaeaSBarry Smith   *ctype = dm->mattype;
4103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
411c0dedaeaSBarry Smith }
412c0dedaeaSBarry Smith 
413c688c046SMatthew G Knepley /*@
414bb7acecfSBarry Smith   MatGetDM - Gets the `DM` defining the data layout of the matrix
415c688c046SMatthew G Knepley 
41620f4b53cSBarry Smith   Not Collective
417c688c046SMatthew G Knepley 
418c688c046SMatthew G Knepley   Input Parameter:
419bb7acecfSBarry Smith . A - The `Mat`
420c688c046SMatthew G Knepley 
421c688c046SMatthew G Knepley   Output Parameter:
422bb7acecfSBarry Smith . dm - The `DM`
423c688c046SMatthew G Knepley 
424c688c046SMatthew G Knepley   Level: intermediate
425c688c046SMatthew G Knepley 
426bb7acecfSBarry Smith   Note:
427bb7acecfSBarry Smith   A matrix may not have a `DM` associated with it
428bb7acecfSBarry Smith 
429bb7acecfSBarry Smith   Developer Note:
430bb7acecfSBarry Smith   Since the `Mat` class doesn't know about the `DM` class the `DM` object is associated with the `Mat` through a `PetscObjectCompose()` operation
4318f1509bcSBarry Smith 
432*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatSetDM()`, `DMCreateMatrix()`, `DMSetMatType()`
433c688c046SMatthew G Knepley @*/
434d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDM(Mat A, DM *dm)
435d71ae5a4SJacob Faibussowitsch {
436c688c046SMatthew G Knepley   PetscFunctionBegin;
437c688c046SMatthew G Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
438c688c046SMatthew G Knepley   PetscValidPointer(dm, 2);
4399566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_dm", (PetscObject *)dm));
4403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
441c688c046SMatthew G Knepley }
442c688c046SMatthew G Knepley 
443c688c046SMatthew G Knepley /*@
444bb7acecfSBarry Smith   MatSetDM - Sets the `DM` defining the data layout of the matrix
445c688c046SMatthew G Knepley 
44620f4b53cSBarry Smith   Not Collective
447c688c046SMatthew G Knepley 
448c688c046SMatthew G Knepley   Input Parameters:
44920f4b53cSBarry Smith + A - The `Mat`
45020f4b53cSBarry Smith - dm - The `DM`
451c688c046SMatthew G Knepley 
452bb7acecfSBarry Smith   Level: developer
453c688c046SMatthew G Knepley 
454bb7acecfSBarry Smith   Note:
455bb7acecfSBarry Smith   This is rarely used in practice, rather `DMCreateMatrix()` is used to create a matrix associated with a particular `DM`
456bb7acecfSBarry Smith 
457bb7acecfSBarry Smith   Developer Note:
458bb7acecfSBarry Smith   Since the `Mat` class doesn't know about the `DM` class the `DM` object is associated with
459bb7acecfSBarry Smith   the `Mat` through a `PetscObjectCompose()` operation
4608f1509bcSBarry Smith 
461*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatGetDM()`, `DMCreateMatrix()`, `DMSetMatType()`
462c688c046SMatthew G Knepley @*/
463d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetDM(Mat A, DM dm)
464d71ae5a4SJacob Faibussowitsch {
465c688c046SMatthew G Knepley   PetscFunctionBegin;
466c688c046SMatthew G Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4678865f1eaSKarl Rupp   if (dm) PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
4689566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_dm", (PetscObject)dm));
4693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
470c688c046SMatthew G Knepley }
471c688c046SMatthew G Knepley 
4729a42bb27SBarry Smith /*@C
473bb7acecfSBarry Smith    DMSetOptionsPrefix - Sets the prefix prepended to all option names when searching through the options database
4749a42bb27SBarry Smith 
47520f4b53cSBarry Smith    Logically Collective
4769a42bb27SBarry Smith 
477d8d19677SJose E. Roman    Input Parameters:
478bb7acecfSBarry Smith +  da - the `DM` context
479bb7acecfSBarry Smith -  prefix - the prefix to prepend
4809a42bb27SBarry Smith 
48120f4b53cSBarry Smith    Level: advanced
48220f4b53cSBarry Smith 
48320f4b53cSBarry Smith    Note:
4849a42bb27SBarry Smith    A hyphen (-) must NOT be given at the beginning of the prefix name.
4859a42bb27SBarry Smith    The first character of all runtime options is AUTOMATICALLY the hyphen.
4869a42bb27SBarry Smith 
487*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscObjectSetOptionsPrefix()`, `DMSetFromOptions()`
4889a42bb27SBarry Smith @*/
489d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOptionsPrefix(DM dm, const char prefix[])
490d71ae5a4SJacob Faibussowitsch {
4919a42bb27SBarry Smith   PetscFunctionBegin;
4929a42bb27SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4939566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
4941baa6e33SBarry Smith   if (dm->sf) PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm->sf, prefix));
4951baa6e33SBarry Smith   if (dm->sectionSF) PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm->sectionSF, prefix));
4963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4979a42bb27SBarry Smith }
4989a42bb27SBarry Smith 
49931697293SDave May /*@C
500da81f932SPierre Jolivet    DMAppendOptionsPrefix - Appends an additional string to an already existing prefix used for searching for
501bb7acecfSBarry Smith    `DM` options in the options database.
50231697293SDave May 
50320f4b53cSBarry Smith    Logically Collective
50431697293SDave May 
50531697293SDave May    Input Parameters:
506bb7acecfSBarry Smith +  dm - the `DM` context
507bb7acecfSBarry Smith -  prefix - the string to append to the current prefix
50831697293SDave May 
50920f4b53cSBarry Smith    Level: advanced
51020f4b53cSBarry Smith 
51120f4b53cSBarry Smith    Note:
512bb7acecfSBarry Smith    If the `DM` does not currently have an options prefix then this value is used alone as the prefix as if `DMSetOptionsPrefix()` had been called.
51331697293SDave May    A hyphen (-) must NOT be given at the beginning of the prefix name.
51431697293SDave May    The first character of all runtime options is AUTOMATICALLY the hyphen.
51531697293SDave May 
516*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetOptionsPrefix()`, `DMGetOptionsPrefix()`, `PetscObjectAppendOptionsPrefix()`, `DMSetFromOptions()`
51731697293SDave May @*/
518d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAppendOptionsPrefix(DM dm, const char prefix[])
519d71ae5a4SJacob Faibussowitsch {
52031697293SDave May   PetscFunctionBegin;
52131697293SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5229566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, prefix));
5233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
52431697293SDave May }
52531697293SDave May 
52631697293SDave May /*@C
52731697293SDave May    DMGetOptionsPrefix - Gets the prefix used for searching for all
528bb7acecfSBarry Smith    DM options in the options database.
52931697293SDave May 
53031697293SDave May    Not Collective
53131697293SDave May 
5322fe279fdSBarry Smith    Input Parameter:
533bb7acecfSBarry Smith .  dm - the `DM` context
53431697293SDave May 
5352fe279fdSBarry Smith    Output Parameter:
53631697293SDave May .  prefix - pointer to the prefix string used is returned
53731697293SDave May 
53831697293SDave May    Level: advanced
53931697293SDave May 
54020f4b53cSBarry Smith    Fortran Note:
54120f4b53cSBarry Smith    Pass in a string 'prefix' of
54220f4b53cSBarry Smith    sufficient length to hold the prefix.
54320f4b53cSBarry Smith 
544*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetOptionsPrefix()`, `DMAppendOptionsPrefix()`, `DMSetFromOptions()`
54531697293SDave May @*/
546d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOptionsPrefix(DM dm, const char *prefix[])
547d71ae5a4SJacob Faibussowitsch {
54831697293SDave May   PetscFunctionBegin;
54931697293SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5509566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, prefix));
5513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55231697293SDave May }
55331697293SDave May 
55462e5d2d2SJDBetteridge static PetscErrorCode DMCountNonCyclicReferences_Internal(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
555d71ae5a4SJacob Faibussowitsch {
5566eb26441SStefano Zampini   PetscInt refct = ((PetscObject)dm)->refct;
55788bdff64SToby Isaac 
55888bdff64SToby Isaac   PetscFunctionBegin;
559aab5bcd8SJed Brown   *ncrefct = 0;
56088bdff64SToby Isaac   if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
56188bdff64SToby Isaac     refct--;
56288bdff64SToby Isaac     if (recurseCoarse) {
56388bdff64SToby Isaac       PetscInt coarseCount;
56488bdff64SToby Isaac 
56562e5d2d2SJDBetteridge       PetscCall(DMCountNonCyclicReferences_Internal(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE, &coarseCount));
56688bdff64SToby Isaac       refct += coarseCount;
56788bdff64SToby Isaac     }
56888bdff64SToby Isaac   }
56988bdff64SToby Isaac   if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
57088bdff64SToby Isaac     refct--;
57188bdff64SToby Isaac     if (recurseFine) {
57288bdff64SToby Isaac       PetscInt fineCount;
57388bdff64SToby Isaac 
57462e5d2d2SJDBetteridge       PetscCall(DMCountNonCyclicReferences_Internal(dm->fineMesh, PETSC_FALSE, PETSC_TRUE, &fineCount));
57588bdff64SToby Isaac       refct += fineCount;
57688bdff64SToby Isaac     }
57788bdff64SToby Isaac   }
57888bdff64SToby Isaac   *ncrefct = refct;
5793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58088bdff64SToby Isaac }
58188bdff64SToby Isaac 
58262e5d2d2SJDBetteridge /* Generic wrapper for DMCountNonCyclicReferences_Internal() */
58362e5d2d2SJDBetteridge PetscErrorCode DMCountNonCyclicReferences(PetscObject dm, PetscInt *ncrefct)
58462e5d2d2SJDBetteridge {
58562e5d2d2SJDBetteridge   PetscFunctionBegin;
58662e5d2d2SJDBetteridge   PetscCall(DMCountNonCyclicReferences_Internal((DM)dm, PETSC_TRUE, PETSC_TRUE, ncrefct));
5873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58862e5d2d2SJDBetteridge }
58962e5d2d2SJDBetteridge 
590d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroyLabelLinkList_Internal(DM dm)
591d71ae5a4SJacob Faibussowitsch {
5925d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
593354557abSToby Isaac 
594354557abSToby Isaac   PetscFunctionBegin;
595354557abSToby Isaac   /* destroy the labels */
596354557abSToby Isaac   while (next) {
597354557abSToby Isaac     DMLabelLink tmp = next->next;
598354557abSToby Isaac 
5995d80c0bfSVaclav Hapla     if (next->label == dm->depthLabel) dm->depthLabel = NULL;
600ba2698f1SMatthew G. Knepley     if (next->label == dm->celltypeLabel) dm->celltypeLabel = NULL;
6019566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&next->label));
6029566063dSJacob Faibussowitsch     PetscCall(PetscFree(next));
603354557abSToby Isaac     next = tmp;
604354557abSToby Isaac   }
6055d80c0bfSVaclav Hapla   dm->labels = NULL;
6063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
607354557abSToby Isaac }
608354557abSToby Isaac 
609d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroyCoordinates_Private(DMCoordinates *c)
610d71ae5a4SJacob Faibussowitsch {
6116858538eSMatthew G. Knepley   PetscFunctionBegin;
6126858538eSMatthew G. Knepley   c->dim = PETSC_DEFAULT;
6136858538eSMatthew G. Knepley   PetscCall(DMDestroy(&c->dm));
6146858538eSMatthew G. Knepley   PetscCall(VecDestroy(&c->x));
6156858538eSMatthew G. Knepley   PetscCall(VecDestroy(&c->xl));
6166858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&c->field));
6173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6186858538eSMatthew G. Knepley }
6196858538eSMatthew G. Knepley 
6201fb7b255SJunchao Zhang /*@C
621bb7acecfSBarry Smith     DMDestroy - Destroys a `DM`.
62247c6ae99SBarry Smith 
62320f4b53cSBarry Smith     Collective
62447c6ae99SBarry Smith 
62547c6ae99SBarry Smith     Input Parameter:
626bb7acecfSBarry Smith .   dm - the `DM` object to destroy
62747c6ae99SBarry Smith 
62847c6ae99SBarry Smith     Level: developer
62947c6ae99SBarry Smith 
630*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMType`, `DMSetType()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
63147c6ae99SBarry Smith @*/
632d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy(DM *dm)
633d71ae5a4SJacob Faibussowitsch {
6346eb26441SStefano Zampini   PetscInt       cnt;
635dfe15315SJed Brown   DMNamedVecLink nlink, nnext;
63647c6ae99SBarry Smith 
63747c6ae99SBarry Smith   PetscFunctionBegin;
6383ba16761SJacob Faibussowitsch   if (!*dm) PetscFunctionReturn(PETSC_SUCCESS);
6396bf464f9SBarry Smith   PetscValidHeaderSpecific((*dm), DM_CLASSID, 1);
64087e657c6SBarry Smith 
64188bdff64SToby Isaac   /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
64262e5d2d2SJDBetteridge   PetscCall(DMCountNonCyclicReferences_Internal(*dm, PETSC_TRUE, PETSC_TRUE, &cnt));
64388bdff64SToby Isaac   --((PetscObject)(*dm))->refct;
6449371c9d4SSatish Balay   if (--cnt > 0) {
6459371c9d4SSatish Balay     *dm = NULL;
6463ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6479371c9d4SSatish Balay   }
6483ba16761SJacob Faibussowitsch   if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(PETSC_SUCCESS);
6496bf464f9SBarry Smith   ((PetscObject)(*dm))->refct = 0;
6506eb26441SStefano Zampini 
6519566063dSJacob Faibussowitsch   PetscCall(DMClearGlobalVectors(*dm));
6529566063dSJacob Faibussowitsch   PetscCall(DMClearLocalVectors(*dm));
6536eb26441SStefano Zampini 
654f490541aSPeter Brune   nnext              = (*dm)->namedglobal;
6550298fd71SBarry Smith   (*dm)->namedglobal = NULL;
656f490541aSPeter Brune   for (nlink = nnext; nlink; nlink = nnext) { /* Destroy the named vectors */
6572348bcf4SPeter Brune     nnext = nlink->next;
6587a8be351SBarry Smith     PetscCheck(nlink->status == DMVEC_STATUS_IN, ((PetscObject)*dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "DM still has Vec named '%s' checked out", nlink->name);
6599566063dSJacob Faibussowitsch     PetscCall(PetscFree(nlink->name));
6609566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nlink->X));
6619566063dSJacob Faibussowitsch     PetscCall(PetscFree(nlink));
6622348bcf4SPeter Brune   }
663f490541aSPeter Brune   nnext             = (*dm)->namedlocal;
6640298fd71SBarry Smith   (*dm)->namedlocal = NULL;
665f490541aSPeter Brune   for (nlink = nnext; nlink; nlink = nnext) { /* Destroy the named local vectors */
666f490541aSPeter Brune     nnext = nlink->next;
6677a8be351SBarry Smith     PetscCheck(nlink->status == DMVEC_STATUS_IN, ((PetscObject)*dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "DM still has Vec named '%s' checked out", nlink->name);
6689566063dSJacob Faibussowitsch     PetscCall(PetscFree(nlink->name));
6699566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nlink->X));
6709566063dSJacob Faibussowitsch     PetscCall(PetscFree(nlink));
671f490541aSPeter Brune   }
6722348bcf4SPeter Brune 
673b17ce1afSJed Brown   /* Destroy the list of hooks */
674c833c3b5SJed Brown   {
675c833c3b5SJed Brown     DMCoarsenHookLink link, next;
676b17ce1afSJed Brown     for (link = (*dm)->coarsenhook; link; link = next) {
677b17ce1afSJed Brown       next = link->next;
6789566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
679b17ce1afSJed Brown     }
6800298fd71SBarry Smith     (*dm)->coarsenhook = NULL;
681c833c3b5SJed Brown   }
682c833c3b5SJed Brown   {
683c833c3b5SJed Brown     DMRefineHookLink link, next;
684c833c3b5SJed Brown     for (link = (*dm)->refinehook; link; link = next) {
685c833c3b5SJed Brown       next = link->next;
6869566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
687c833c3b5SJed Brown     }
6880298fd71SBarry Smith     (*dm)->refinehook = NULL;
689c833c3b5SJed Brown   }
690be081cd6SPeter Brune   {
691be081cd6SPeter Brune     DMSubDomainHookLink link, next;
692be081cd6SPeter Brune     for (link = (*dm)->subdomainhook; link; link = next) {
693be081cd6SPeter Brune       next = link->next;
6949566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
695be081cd6SPeter Brune     }
6960298fd71SBarry Smith     (*dm)->subdomainhook = NULL;
697be081cd6SPeter Brune   }
698baf369e7SPeter Brune   {
699baf369e7SPeter Brune     DMGlobalToLocalHookLink link, next;
700baf369e7SPeter Brune     for (link = (*dm)->gtolhook; link; link = next) {
701baf369e7SPeter Brune       next = link->next;
7029566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
703baf369e7SPeter Brune     }
7040298fd71SBarry Smith     (*dm)->gtolhook = NULL;
705baf369e7SPeter Brune   }
706d4d07f1eSToby Isaac   {
707d4d07f1eSToby Isaac     DMLocalToGlobalHookLink link, next;
708d4d07f1eSToby Isaac     for (link = (*dm)->ltoghook; link; link = next) {
709d4d07f1eSToby Isaac       next = link->next;
7109566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
711d4d07f1eSToby Isaac     }
712d4d07f1eSToby Isaac     (*dm)->ltoghook = NULL;
713d4d07f1eSToby Isaac   }
714aa1993deSMatthew G Knepley   /* Destroy the work arrays */
715aa1993deSMatthew G Knepley   {
716aa1993deSMatthew G Knepley     DMWorkLink link, next;
7177a8be351SBarry Smith     PetscCheck(!(*dm)->workout, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Work array still checked out");
718aa1993deSMatthew G Knepley     for (link = (*dm)->workin; link; link = next) {
719aa1993deSMatthew G Knepley       next = link->next;
7209566063dSJacob Faibussowitsch       PetscCall(PetscFree(link->mem));
7219566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
722aa1993deSMatthew G Knepley     }
7230298fd71SBarry Smith     (*dm)->workin = NULL;
724aa1993deSMatthew G Knepley   }
725c58f1c22SToby Isaac   /* destroy the labels */
7269566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(*dm));
727f4cdcedcSVaclav Hapla   /* destroy the fields */
7289566063dSJacob Faibussowitsch   PetscCall(DMClearFields(*dm));
729f4cdcedcSVaclav Hapla   /* destroy the boundaries */
730e6f8dbb6SToby Isaac   {
731e6f8dbb6SToby Isaac     DMBoundary next = (*dm)->boundary;
732e6f8dbb6SToby Isaac     while (next) {
733e6f8dbb6SToby Isaac       DMBoundary b = next;
734e6f8dbb6SToby Isaac 
735e6f8dbb6SToby Isaac       next = b->next;
7369566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
737e6f8dbb6SToby Isaac     }
738e6f8dbb6SToby Isaac   }
739b17ce1afSJed Brown 
7409566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmksp));
7419566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmsnes));
7429566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmts));
74352536dc3SBarry Smith 
74448a46eb9SPierre Jolivet   if ((*dm)->ctx && (*dm)->ctxdestroy) PetscCall((*(*dm)->ctxdestroy)(&(*dm)->ctx));
7459566063dSJacob Faibussowitsch   PetscCall(MatFDColoringDestroy(&(*dm)->fd));
7469566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap));
7479566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->vectype));
7489566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->mattype));
74988ed4aceSMatthew G Knepley 
7509566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->localSection));
7519566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->globalSection));
7529566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&(*dm)->map));
7539566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->defaultConstraint.section));
7549566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&(*dm)->defaultConstraint.mat));
7559566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&(*dm)->sf));
7569566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&(*dm)->sectionSF));
757736995cdSBlaise Bourdin   if ((*dm)->useNatural) {
75848a46eb9SPierre Jolivet     if ((*dm)->sfNatural) PetscCall(PetscSFDestroy(&(*dm)->sfNatural));
7599566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)(*dm)->sfMigration));
760736995cdSBlaise Bourdin   }
7619a2a23afSMatthew G. Knepley   {
7629a2a23afSMatthew G. Knepley     Vec     *auxData;
7639a2a23afSMatthew G. Knepley     PetscInt n, i, off = 0;
7649a2a23afSMatthew G. Knepley 
7659566063dSJacob Faibussowitsch     PetscCall(PetscHMapAuxGetSize((*dm)->auxData, &n));
7669566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &auxData));
7679566063dSJacob Faibussowitsch     PetscCall(PetscHMapAuxGetVals((*dm)->auxData, &off, auxData));
7689566063dSJacob Faibussowitsch     for (i = 0; i < n; ++i) PetscCall(VecDestroy(&auxData[i]));
7699566063dSJacob Faibussowitsch     PetscCall(PetscFree(auxData));
7709566063dSJacob Faibussowitsch     PetscCall(PetscHMapAuxDestroy(&(*dm)->auxData));
7719a2a23afSMatthew G. Knepley   }
77248a46eb9SPierre Jolivet   if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) PetscCall(DMSetFineDM((*dm)->coarseMesh, NULL));
7736eb26441SStefano Zampini 
7749566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->coarseMesh));
77548a46eb9SPierre Jolivet   if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) PetscCall(DMSetCoarseDM((*dm)->fineMesh, NULL));
7769566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->fineMesh));
7774fb89dddSMatthew G. Knepley   PetscCall(PetscFree((*dm)->Lstart));
7789566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->L));
7799566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->maxCell));
7806858538eSMatthew G. Knepley   PetscCall(DMDestroyCoordinates_Private(&(*dm)->coordinates[0]));
7816858538eSMatthew G. Knepley   PetscCall(DMDestroyCoordinates_Private(&(*dm)->coordinates[1]));
7829566063dSJacob Faibussowitsch   if ((*dm)->transformDestroy) PetscCall((*(*dm)->transformDestroy)(*dm, (*dm)->transformCtx));
7839566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->transformDM));
7849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&(*dm)->transform));
7856725e60dSJed Brown   PetscCall(VecScatterDestroy(&(*dm)->periodic.affine_to_local));
7866725e60dSJed Brown   PetscCall(VecDestroy(&(*dm)->periodic.affine));
7876636e97aSMatthew G Knepley 
7889566063dSJacob Faibussowitsch   PetscCall(DMClearDS(*dm));
7899566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->dmBC));
790e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
7919566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*dm));
792732e2eb9SMatthew G Knepley 
79348a46eb9SPierre Jolivet   if ((*dm)->ops->destroy) PetscCall((*(*dm)->ops->destroy)(*dm));
7949566063dSJacob Faibussowitsch   PetscCall(DMMonitorCancel(*dm));
795f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
7969566063dSJacob Faibussowitsch   PetscCallCEED(CeedElemRestrictionDestroy(&(*dm)->ceedERestrict));
7979566063dSJacob Faibussowitsch   PetscCallCEED(CeedDestroy(&(*dm)->ceed));
798f918ec44SMatthew G. Knepley #endif
799435a35e8SMatthew G Knepley   /* We do not destroy (*dm)->data here so that we can reference count backend objects */
8009566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(dm));
8013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80247c6ae99SBarry Smith }
80347c6ae99SBarry Smith 
804d7bf68aeSBarry Smith /*@
805bb7acecfSBarry Smith     DMSetUp - sets up the data structures inside a `DM` object
806d7bf68aeSBarry Smith 
80720f4b53cSBarry Smith     Collective
808d7bf68aeSBarry Smith 
809d7bf68aeSBarry Smith     Input Parameter:
810bb7acecfSBarry Smith .   dm - the `DM` object to setup
811d7bf68aeSBarry Smith 
812bb7acecfSBarry Smith     Level: intermediate
813d7bf68aeSBarry Smith 
814bb7acecfSBarry Smith     Note:
815bb7acecfSBarry Smith     This is usually called after various parameter setting operations and `DMSetFromOptions()` are called on the `DM`
816bb7acecfSBarry Smith 
817*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMSetType()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
818d7bf68aeSBarry Smith @*/
819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp(DM dm)
820d71ae5a4SJacob Faibussowitsch {
821d7bf68aeSBarry Smith   PetscFunctionBegin;
822171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8233ba16761SJacob Faibussowitsch   if (dm->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
824dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, setup);
8258387afaaSJed Brown   dm->setupcalled = PETSC_TRUE;
8263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
827d7bf68aeSBarry Smith }
828d7bf68aeSBarry Smith 
829d7bf68aeSBarry Smith /*@
830bb7acecfSBarry Smith     DMSetFromOptions - sets parameters in a `DM` from the options database
831d7bf68aeSBarry Smith 
83220f4b53cSBarry Smith     Collective
833d7bf68aeSBarry Smith 
834d7bf68aeSBarry Smith     Input Parameter:
835bb7acecfSBarry Smith .   dm - the `DM` object to set options for
836d7bf68aeSBarry Smith 
83720f4b53cSBarry Smith     Options Database Keys:
838bb7acecfSBarry Smith +   -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()` and `DMCreateMassMatrix()`, but do not fill it with zeros
839bb7acecfSBarry Smith .   -dm_vec_type <type>  - type of vector to create inside `DM`
840bb7acecfSBarry Smith .   -dm_mat_type <type>  - type of matrix to create inside `DM`
841a4ea9b21SRichard Tran Mills .   -dm_is_coloring_type - <global or local>
84220f4b53cSBarry Smith .   -dm_bind_below <n>   - bind (force execution on CPU) for `Vec` and `Mat` objects with local size (number of vector entries or matrix rows) below n; currently only supported for `DMDA`
84320f4b53cSBarry Smith . -dm_plex_filename <str>           - File containing a mesh
8449318fe57SMatthew G. Knepley . -dm_plex_boundary_filename <str>  - File containing a mesh boundary
845cd7e8a5eSksagiyam . -dm_plex_name <str>               - Name of the mesh in the file
8465dca41c3SJed Brown . -dm_plex_shape <shape>            - The domain shape, such as `BOX`, `SPHERE`, etc.
8479318fe57SMatthew G. Knepley . -dm_plex_cell <ct>                - Cell shape
8489318fe57SMatthew G. Knepley . -dm_plex_reference_cell_domain <bool> - Use a reference cell domain
8499318fe57SMatthew G. Knepley . -dm_plex_dim <dim>                - Set the topological dimension
850bb7acecfSBarry Smith . -dm_plex_simplex <bool>           - `PETSC_TRUE` for simplex elements, `PETSC_FALSE` for tensor elements
851bb7acecfSBarry Smith . -dm_plex_interpolate <bool>       - `PETSC_TRUE` turns on topological interpolation (creating edges and faces)
8529318fe57SMatthew G. Knepley . -dm_plex_scale <sc>               - Scale factor for mesh coordinates
8539318fe57SMatthew G. Knepley . -dm_plex_box_faces <m,n,p>        - Number of faces along each dimension
8549318fe57SMatthew G. Knepley . -dm_plex_box_lower <x,y,z>        - Specify lower-left-bottom coordinates for the box
8559318fe57SMatthew G. Knepley . -dm_plex_box_upper <x,y,z>        - Specify upper-right-top coordinates for the box
856bb7acecfSBarry Smith . -dm_plex_box_bd <bx,by,bz>        - Specify the `DMBoundaryType` for each direction
8579318fe57SMatthew G. Knepley . -dm_plex_sphere_radius <r>        - The sphere radius
8589318fe57SMatthew G. Knepley . -dm_plex_ball_radius <r>          - Radius of the ball
8599318fe57SMatthew G. Knepley . -dm_plex_cylinder_bd <bz>         - Boundary type in the z direction
8609318fe57SMatthew G. Knepley . -dm_plex_cylinder_num_wedges <n>  - Number of wedges around the cylinder
861bdf63967SMatthew G. Knepley . -dm_plex_reorder <order>          - Reorder the mesh using the specified algorithm
8629318fe57SMatthew G. Knepley . -dm_refine_pre <n>                - The number of refinements before distribution
8639318fe57SMatthew G. Knepley . -dm_refine_uniform_pre <bool>     - Flag for uniform refinement before distribution
8649318fe57SMatthew G. Knepley . -dm_refine_volume_limit_pre <v>   - The maximum cell volume after refinement before distribution
8659318fe57SMatthew G. Knepley . -dm_refine <n>                    - The number of refinements after distribution
866bdf63967SMatthew G. Knepley . -dm_extrude <l>                   - Activate extrusion and specify the number of layers to extrude
867d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_thickness <t>           - The total thickness of extruded layers
868d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_use_tensor <bool>       - Use tensor cells when extruding
869d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_symmetric <bool>        - Extrude layers symmetrically about the surface
870d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_normal <n0,...,nd>      - Specify the extrusion direction
871d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_thicknesses <t0,...,tl> - Specify thickness of each layer
872909dfd52SMatthew G. Knepley . -dm_plex_create_fv_ghost_cells    - Flag to create finite volume ghost cells on the boundary
873909dfd52SMatthew G. Knepley . -dm_plex_fv_ghost_cells_label <name> - Label name for ghost cells boundary
8749318fe57SMatthew G. Knepley . -dm_distribute <bool>             - Flag to redistribute a mesh among processes
8759318fe57SMatthew G. Knepley . -dm_distribute_overlap <n>        - The size of the overlap halo
8769318fe57SMatthew G. Knepley . -dm_plex_adj_cone <bool>          - Set adjacency direction
87720f4b53cSBarry Smith .  -dm_plex_adj_closure <bool>       - Set adjacency size
87820f4b53cSBarry Smith .   -dm_plex_check_symmetry        - Check that the adjacency information in the mesh is symmetric - `DMPlexCheckSymmetry()`
879bb7acecfSBarry Smith .   -dm_plex_check_skeleton        - Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes) - `DMPlexCheckSkeleton()`
880bb7acecfSBarry Smith .   -dm_plex_check_faces           - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type - `DMPlexCheckFaces()`
881bb7acecfSBarry Smith .   -dm_plex_check_geometry        - Check that cells have positive volume - `DMPlexCheckGeometry()`
882bb7acecfSBarry Smith .   -dm_plex_check_pointsf         - Check some necessary conditions for `PointSF` - `DMPlexCheckPointSF()`
883bb7acecfSBarry Smith .   -dm_plex_check_interface_cones - Check points on inter-partition interfaces have conforming order of cone points - `DMPlexCheckInterfaceCones()`
884384a6580SVaclav Hapla -   -dm_plex_check_all             - Perform all the checks above
885d7bf68aeSBarry Smith 
88695eb5ee5SVaclav Hapla     Level: intermediate
88795eb5ee5SVaclav Hapla 
888*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
889bb7acecfSBarry Smith          `DMPlexCheckSymmetry()`, `DMPlexCheckSkeleton()`, `DMPlexCheckFaces()`, `DMPlexCheckGeometry()`, `DMPlexCheckPointSF()`, `DMPlexCheckInterfaceCones()`,
890bb7acecfSBarry Smith          `DMSetOptionsPrefix()`, `DM`, `DMType`, `DMPLEX`, `DMDA`
891d7bf68aeSBarry Smith @*/
892d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions(DM dm)
893d71ae5a4SJacob Faibussowitsch {
8947781c08eSBarry Smith   char      typeName[256];
895ca266f36SBarry Smith   PetscBool flg;
896d7bf68aeSBarry Smith 
897d7bf68aeSBarry Smith   PetscFunctionBegin;
898171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89949be4549SMatthew G. Knepley   dm->setfromoptionscalled = PETSC_TRUE;
9009566063dSJacob Faibussowitsch   if (dm->sf) PetscCall(PetscSFSetFromOptions(dm->sf));
9019566063dSJacob Faibussowitsch   if (dm->sectionSF) PetscCall(PetscSFSetFromOptions(dm->sectionSF));
902dd4c3f67SMatthew G. Knepley   if (dm->coordinates[0].dm) PetscCall(DMSetFromOptions(dm->coordinates[0].dm));
903d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)dm);
9049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_preallocate_only", "only preallocate matrix, but do not set column indices", "DMSetMatrixPreallocateOnly", dm->prealloc_only, &dm->prealloc_only, NULL));
9059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_vec_type", "Vector type used for created vectors", "DMSetVecType", VecList, dm->vectype, typeName, 256, &flg));
9061baa6e33SBarry Smith   if (flg) PetscCall(DMSetVecType(dm, typeName));
9079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_mat_type", "Matrix type used for created matrices", "DMSetMatType", MatList, dm->mattype ? dm->mattype : typeName, typeName, sizeof(typeName), &flg));
9081baa6e33SBarry Smith   if (flg) PetscCall(DMSetMatType(dm, typeName));
909863027abSJed Brown   PetscCall(PetscOptionsEnum("-dm_blocking_type", "Topological point or field node blocking", "DMSetBlockingType", DMBlockingTypes, (PetscEnum)dm->blocking_type, (PetscEnum *)&dm->blocking_type, NULL));
9109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_is_coloring_type", "Global or local coloring of Jacobian", "DMSetISColoringType", ISColoringTypes, (PetscEnum)dm->coloringtype, (PetscEnum *)&dm->coloringtype, NULL));
9119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-dm_bind_below", "Set the size threshold (in entries) below which the Vec is bound to the CPU", "VecBindToCPU", dm->bind_below, &dm->bind_below, &flg));
912dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, setfromoptions, PetscOptionsObject);
913f9ba7244SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
914dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)dm, PetscOptionsObject));
915d0609cedSBarry Smith   PetscOptionsEnd();
9163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
917d7bf68aeSBarry Smith }
918d7bf68aeSBarry Smith 
919fc9bc008SSatish Balay /*@C
920bb7acecfSBarry Smith    DMViewFromOptions - View a `DM` in a particular way based on a request in the options database
921fe2efc57SMark 
92220f4b53cSBarry Smith    Collective
923fe2efc57SMark 
924fe2efc57SMark    Input Parameters:
925bb7acecfSBarry Smith +  dm - the `DM` object
92620f4b53cSBarry Smith .  obj - optional object that provides the prefix for the options database (if `NULL` then the prefix in obj is used)
927bb7acecfSBarry Smith -  optionname - option string that is used to activate viewing
928fe2efc57SMark 
929fe2efc57SMark    Level: intermediate
930bb7acecfSBarry Smith 
931bb7acecfSBarry Smith    Note:
932bb7acecfSBarry Smith    See `PetscObjectViewFromOptions()` for a list of values that can be provided in the options database to determine how the `DM` is viewed
933bb7acecfSBarry Smith 
934*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMView()`, `PetscObjectViewFromOptions()`, `DMCreate()`, `PetscObjectViewFromOptions()`
935fe2efc57SMark @*/
936d71ae5a4SJacob Faibussowitsch PetscErrorCode DMViewFromOptions(DM dm, PetscObject obj, const char name[])
937d71ae5a4SJacob Faibussowitsch {
938fe2efc57SMark   PetscFunctionBegin;
939fe2efc57SMark   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9409566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, obj, name));
9413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
942fe2efc57SMark }
943fe2efc57SMark 
944fe2efc57SMark /*@C
945bb7acecfSBarry Smith     DMView - Views a `DM`. Depending on the `PetscViewer` and its `PetscViewerFormat` it may print some ASCII information about the `DM` to the screen or a file or
946bb7acecfSBarry Smith     save the `DM` in a binary file to be loaded later or create a visualization of the `DM`
94747c6ae99SBarry Smith 
94820f4b53cSBarry Smith     Collective
94947c6ae99SBarry Smith 
950d8d19677SJose E. Roman     Input Parameters:
951bb7acecfSBarry Smith +   dm - the `DM` object to view
95247c6ae99SBarry Smith -   v - the viewer
95347c6ae99SBarry Smith 
95420f4b53cSBarry Smith     Level: beginner
95520f4b53cSBarry Smith 
956cd7e8a5eSksagiyam     Notes:
957bb7acecfSBarry Smith     Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` as the `PetscViewerFormat` one can save multiple `DMPLEX`
958bb7acecfSBarry Smith     meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
959bb7acecfSBarry Smith     before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
960cd7e8a5eSksagiyam 
961*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscViewer`, `PetscViewerFormat`, `PetscViewerSetFormat()`, `DMDestroy()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMLoad()`, `PetscObjectSetName()`
96247c6ae99SBarry Smith @*/
963d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView(DM dm, PetscViewer v)
964d71ae5a4SJacob Faibussowitsch {
96532c0f0efSBarry Smith   PetscBool         isbinary;
96676a8abe0SBarry Smith   PetscMPIInt       size;
96776a8abe0SBarry Smith   PetscViewerFormat format;
96847c6ae99SBarry Smith 
96947c6ae99SBarry Smith   PetscFunctionBegin;
970171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97148a46eb9SPierre Jolivet   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &v));
972b1b135c8SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);
97374903a4fSStefano Zampini   /* Ideally, we would like to have this test on.
97474903a4fSStefano Zampini      However, it currently breaks socket viz via GLVis.
97574903a4fSStefano Zampini      During DMView(parallel_mesh,glvis_viewer), each
97674903a4fSStefano Zampini      process opens a sequential ASCII socket to visualize
97774903a4fSStefano Zampini      the local mesh, and PetscObjectView(dm,local_socket)
97874903a4fSStefano Zampini      is internally called inside VecView_GLVis, incurring
97974903a4fSStefano Zampini      in an error here */
98074903a4fSStefano Zampini   /* PetscCheckSameComm(dm,1,v,2); */
9819566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckWritable(v));
982b1b135c8SBarry Smith 
9839566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(v, &format));
9849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9853ba16761SJacob Faibussowitsch   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
9869566063dSJacob Faibussowitsch   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)dm, v));
9879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERBINARY, &isbinary));
98832c0f0efSBarry Smith   if (isbinary) {
98955849f57SBarry Smith     PetscInt classid = DM_FILE_CLASSID;
99032c0f0efSBarry Smith     char     type[256];
99132c0f0efSBarry Smith 
9929566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWrite(v, &classid, 1, PETSC_INT));
993c6a7a370SJeremy L Thompson     PetscCall(PetscStrncpy(type, ((PetscObject)dm)->type_name, sizeof(type)));
9949566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWrite(v, type, 256, PETSC_CHAR));
99532c0f0efSBarry Smith   }
996dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, view, v);
9973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99847c6ae99SBarry Smith }
99947c6ae99SBarry Smith 
100047c6ae99SBarry Smith /*@
1001bb7acecfSBarry Smith     DMCreateGlobalVector - Creates a global vector from a `DM` object. A global vector is a parallel vector that has no duplicate values shared between MPI ranks,
1002bb7acecfSBarry Smith     that is it has no ghost locations.
100347c6ae99SBarry Smith 
100420f4b53cSBarry Smith     Collective
100547c6ae99SBarry Smith 
100647c6ae99SBarry Smith     Input Parameter:
1007bb7acecfSBarry Smith .   dm - the `DM` object
100847c6ae99SBarry Smith 
100947c6ae99SBarry Smith     Output Parameter:
101047c6ae99SBarry Smith .   vec - the global vector
101147c6ae99SBarry Smith 
1012073dac72SJed Brown     Level: beginner
101347c6ae99SBarry Smith 
1014*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `Vec`, `DMCreateLocalVector()`, `DMGetGlobalVector()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
1015bb7acecfSBarry Smith          `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`
101647c6ae99SBarry Smith @*/
1017d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateGlobalVector(DM dm, Vec *vec)
1018d71ae5a4SJacob Faibussowitsch {
101947c6ae99SBarry Smith   PetscFunctionBegin;
1020171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1021b9d85ea2SLisandro Dalcin   PetscValidPointer(vec, 2);
1022dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createglobalvector, vec);
102376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1024c6b011d8SStefano Zampini     DM vdm;
1025c6b011d8SStefano Zampini 
10269566063dSJacob Faibussowitsch     PetscCall(VecGetDM(*vec, &vdm));
10277a8be351SBarry Smith     PetscCheck(vdm, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DM type '%s' did not attach the DM to the vector", ((PetscObject)dm)->type_name);
1028c6b011d8SStefano Zampini   }
10293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
103047c6ae99SBarry Smith }
103147c6ae99SBarry Smith 
103247c6ae99SBarry Smith /*@
1033bb7acecfSBarry Smith     DMCreateLocalVector - Creates a local vector from a `DM` object.
103447c6ae99SBarry Smith 
103547c6ae99SBarry Smith     Not Collective
103647c6ae99SBarry Smith 
103747c6ae99SBarry Smith     Input Parameter:
1038bb7acecfSBarry Smith .   dm - the `DM` object
103947c6ae99SBarry Smith 
104047c6ae99SBarry Smith     Output Parameter:
104147c6ae99SBarry Smith .   vec - the local vector
104247c6ae99SBarry Smith 
1043073dac72SJed Brown     Level: beginner
104447c6ae99SBarry Smith 
104520f4b53cSBarry Smith     Note:
1046bb7acecfSBarry Smith     A local vector usually has ghost locations that contain values that are owned by different MPI ranks. A global vector has no ghost locations.
1047bb7acecfSBarry Smith 
1048*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `Vec`, `DMCreateGlobalVector()`, `DMGetLocalVector()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
1049bb7acecfSBarry Smith          `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`
105047c6ae99SBarry Smith @*/
1051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLocalVector(DM dm, Vec *vec)
1052d71ae5a4SJacob Faibussowitsch {
105347c6ae99SBarry Smith   PetscFunctionBegin;
1054171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1055b9d85ea2SLisandro Dalcin   PetscValidPointer(vec, 2);
1056dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createlocalvector, vec);
105776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1058c6b011d8SStefano Zampini     DM vdm;
1059c6b011d8SStefano Zampini 
10609566063dSJacob Faibussowitsch     PetscCall(VecGetDM(*vec, &vdm));
10617a8be351SBarry Smith     PetscCheck(vdm, PETSC_COMM_SELF, PETSC_ERR_LIB, "DM type '%s' did not attach the DM to the vector", ((PetscObject)dm)->type_name);
1062c6b011d8SStefano Zampini   }
10633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
106447c6ae99SBarry Smith }
106547c6ae99SBarry Smith 
10661411c6eeSJed Brown /*@
1067bb7acecfSBarry Smith    DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a `DM`.
10681411c6eeSJed Brown 
106920f4b53cSBarry Smith    Collective
10701411c6eeSJed Brown 
10711411c6eeSJed Brown    Input Parameter:
1072bb7acecfSBarry Smith .  dm - the `DM` that provides the mapping
10731411c6eeSJed Brown 
10741411c6eeSJed Brown    Output Parameter:
10751411c6eeSJed Brown .  ltog - the mapping
10761411c6eeSJed Brown 
1077bb7acecfSBarry Smith    Level: advanced
10781411c6eeSJed Brown 
10791411c6eeSJed Brown    Notes:
1080bb7acecfSBarry Smith    The global to local mapping allows one to set values into the global vector or matrix using `VecSetValuesLocal()` and `MatSetValuesLocal()`
10811411c6eeSJed Brown 
1082bb7acecfSBarry Smith    Vectors obtained with  `DMCreateGlobalVector()` and matrices obtained with `DMCreateMatrix()` already contain the global mapping so you do
1083bb7acecfSBarry Smith    need to use this function with those objects.
1084bb7acecfSBarry Smith 
1085bb7acecfSBarry Smith    This mapping can then be used by `VecSetLocalToGlobalMapping()` or `MatSetLocalToGlobalMapping()`.
1086bb7acecfSBarry Smith 
1087*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateLocalVector()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `VecSetLocalToGlobalMapping()`, `MatSetLocalToGlobalMapping()`,
1088bb7acecfSBarry Smith           `DMCreateMatrix()`
10891411c6eeSJed Brown @*/
1090d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalToGlobalMapping(DM dm, ISLocalToGlobalMapping *ltog)
1091d71ae5a4SJacob Faibussowitsch {
10920be3e97aSMatthew G. Knepley   PetscInt bs = -1, bsLocal[2], bsMinMax[2];
10931411c6eeSJed Brown 
10941411c6eeSJed Brown   PetscFunctionBegin;
10951411c6eeSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10961411c6eeSJed Brown   PetscValidPointer(ltog, 2);
10971411c6eeSJed Brown   if (!dm->ltogmap) {
109837d0c07bSMatthew G Knepley     PetscSection section, sectionGlobal;
109937d0c07bSMatthew G Knepley 
11009566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
110137d0c07bSMatthew G Knepley     if (section) {
1102a974ec88SMatthew G. Knepley       const PetscInt *cdofs;
110337d0c07bSMatthew G Knepley       PetscInt       *ltog;
1104ccf3bd66SMatthew G. Knepley       PetscInt        pStart, pEnd, n, p, k, l;
110537d0c07bSMatthew G Knepley 
11069566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
11079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
11089566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetStorageSize(section, &n));
11099566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n, &ltog)); /* We want the local+overlap size */
111037d0c07bSMatthew G Knepley       for (p = pStart, l = 0; p < pEnd; ++p) {
1111e6befd46SJed Brown         PetscInt bdof, cdof, dof, off, c, cind;
111237d0c07bSMatthew G Knepley 
111337d0c07bSMatthew G Knepley         /* Should probably use constrained dofs */
11149566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, p, &dof));
11159566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
11169566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, p, &cdofs));
11179566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &off));
11181a7dc684SMatthew G. Knepley         /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
11191a7dc684SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
1120ad540459SPierre Jolivet         if (dof) bs = bs < 0 ? bdof : PetscGCD(bs, bdof);
11215227eafbSStefano Zampini 
1122e6befd46SJed Brown         for (c = 0, cind = 0; c < dof; ++c, ++l) {
11235227eafbSStefano Zampini           if (cind < cdof && c == cdofs[cind]) {
1124e6befd46SJed Brown             ltog[l] = off < 0 ? off - c : -(off + c + 1);
1125e6befd46SJed Brown             cind++;
1126e6befd46SJed Brown           } else {
11275227eafbSStefano Zampini             ltog[l] = (off < 0 ? -(off + 1) : off) + c - cind;
1128e6befd46SJed Brown           }
112937d0c07bSMatthew G Knepley         }
113037d0c07bSMatthew G Knepley       }
1131bff27382SMatthew G. Knepley       /* Must have same blocksize on all procs (some might have no points) */
11329371c9d4SSatish Balay       bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
11339371c9d4SSatish Balay       bsLocal[1] = bs;
11349566063dSJacob Faibussowitsch       PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
11359371c9d4SSatish Balay       if (bsMinMax[0] != bsMinMax[1]) {
11369371c9d4SSatish Balay         bs = 1;
11379371c9d4SSatish Balay       } else {
11389371c9d4SSatish Balay         bs = bsMinMax[0];
11399371c9d4SSatish Balay       }
11407591dbb2SMatthew G. Knepley       bs = bs < 0 ? 1 : bs;
11417591dbb2SMatthew G. Knepley       /* Must reduce indices by blocksize */
1142ccf3bd66SMatthew G. Knepley       if (bs > 1) {
1143ca469d19SJed Brown         for (l = 0, k = 0; l < n; l += bs, ++k) {
1144ca469d19SJed Brown           // Integer division of negative values truncates toward zero(!), not toward negative infinity
1145ca469d19SJed Brown           ltog[k] = ltog[l] >= 0 ? ltog[l] / bs : -(-(ltog[l] + 1) / bs + 1);
1146ca469d19SJed Brown         }
1147ccf3bd66SMatthew G. Knepley         n /= bs;
1148ccf3bd66SMatthew G. Knepley       }
11499566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap));
1150dbbe0bcdSBarry Smith     } else PetscUseTypeMethod(dm, getlocaltoglobalmapping);
115137d0c07bSMatthew G Knepley   }
11521411c6eeSJed Brown   *ltog = dm->ltogmap;
11533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11541411c6eeSJed Brown }
11551411c6eeSJed Brown 
11561411c6eeSJed Brown /*@
1157bb7acecfSBarry Smith    DMGetBlockSize - Gets the inherent block size associated with a `DM`
11581411c6eeSJed Brown 
11591411c6eeSJed Brown    Not Collective
11601411c6eeSJed Brown 
11611411c6eeSJed Brown    Input Parameter:
1162bb7acecfSBarry Smith .  dm - the `DM` with block structure
11631411c6eeSJed Brown 
11641411c6eeSJed Brown    Output Parameter:
11651411c6eeSJed Brown .  bs - the block size, 1 implies no exploitable block structure
11661411c6eeSJed Brown 
11671411c6eeSJed Brown    Level: intermediate
11681411c6eeSJed Brown 
1169bb7acecfSBarry Smith    Note:
1170bb7acecfSBarry Smith    This might be the number of degrees of freedom at each grid point for a structured grid.
1171bb7acecfSBarry Smith 
1172bb7acecfSBarry Smith    Complex `DM` that represent multiphysics or staggered grids or mixed-methods do not generally have a single inherent block size, but
1173bb7acecfSBarry Smith    rather different locations in the vectors may have a different block size.
1174bb7acecfSBarry Smith 
1175*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `ISCreateBlock()`, `VecSetBlockSize()`, `MatSetBlockSize()`, `DMGetLocalToGlobalMapping()`
11761411c6eeSJed Brown @*/
1177d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBlockSize(DM dm, PetscInt *bs)
1178d71ae5a4SJacob Faibussowitsch {
11791411c6eeSJed Brown   PetscFunctionBegin;
11801411c6eeSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1181534a8f05SLisandro Dalcin   PetscValidIntPointer(bs, 2);
11827a8be351SBarry Smith   PetscCheck(dm->bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM does not have enough information to provide a block size yet");
11831411c6eeSJed Brown   *bs = dm->bs;
11843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11851411c6eeSJed Brown }
11861411c6eeSJed Brown 
118748eeb7c8SBarry Smith /*@C
1188bb7acecfSBarry Smith     DMCreateInterpolation - Gets the interpolation matrix between two `DM` objects. The resulting matrix map degrees of freedom in the vector obtained by
1189bb7acecfSBarry Smith     `DMCreateGlobalVector()` on the coarse `DM` to similar vectors on the fine grid `DM`.
119047c6ae99SBarry Smith 
119120f4b53cSBarry Smith     Collective
119247c6ae99SBarry Smith 
1193d8d19677SJose E. Roman     Input Parameters:
1194bb7acecfSBarry Smith +   dmc - the `DM` object
1195bb7acecfSBarry Smith -   dmf - the second, finer `DM` object
119647c6ae99SBarry Smith 
1197d8d19677SJose E. Roman     Output Parameters:
119847c6ae99SBarry Smith +  mat - the interpolation
1199bb7acecfSBarry Smith -  vec - the scaling (optional), see `DMCreateInterpolationScale()`
120047c6ae99SBarry Smith 
120147c6ae99SBarry Smith     Level: developer
120247c6ae99SBarry Smith 
120395452b02SPatrick Sanan     Notes:
1204bb7acecfSBarry Smith     For `DMDA` objects this only works for "uniform refinement", that is the refined mesh was obtained `DMRefine()` or the coarse mesh was obtained by
1205bb7acecfSBarry Smith     DMCoarsen(). The coordinates set into the `DMDA` are completely ignored in computing the interpolation.
1206d52bd9f3SBarry Smith 
1207bb7acecfSBarry Smith     For `DMDA` objects you can use this interpolation (more precisely the interpolation from the `DMGetCoordinateDM()`) to interpolate the mesh coordinate
1208bb7acecfSBarry Smith     vectors EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
120985afcc9aSBarry Smith 
1210*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolationScale()`
121147c6ae99SBarry Smith @*/
1212d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation(DM dmc, DM dmf, Mat *mat, Vec *vec)
1213d71ae5a4SJacob Faibussowitsch {
121447c6ae99SBarry Smith   PetscFunctionBegin;
1215a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1216a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
1217c7d20fa0SStefano Zampini   PetscValidPointer(mat, 3);
12189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateInterpolation, dmc, dmf, 0, 0));
1219dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createinterpolation, dmf, mat, vec);
12209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateInterpolation, dmc, dmf, 0, 0));
12213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
122247c6ae99SBarry Smith }
122347c6ae99SBarry Smith 
12243ad4599aSBarry Smith /*@
1225bb7acecfSBarry Smith     DMCreateInterpolationScale - Forms L = 1/(R*1) where 1 is the vector of all ones, and R is the transpose of the interpolation between the `DM`.
1226bb7acecfSBarry Smith     xcoarse = diag(L)*R*xfine preserves scale and is thus suitable for state (versus residual) restriction. In other words xcoarse is the coarse
1227bb7acecfSBarry Smith     representation of xfine.
12282ed6491fSPatrick Sanan 
12292ed6491fSPatrick Sanan   Input Parameters:
1230bb7acecfSBarry Smith +      dac - `DM` that defines a coarse mesh
1231bb7acecfSBarry Smith .      daf - `DM` that defines a fine mesh
12322ed6491fSPatrick Sanan -      mat - the restriction (or interpolation operator) from fine to coarse
12332ed6491fSPatrick Sanan 
12342ed6491fSPatrick Sanan   Output Parameter:
12352ed6491fSPatrick Sanan .    scale - the scaled vector
12362ed6491fSPatrick Sanan 
1237bb7acecfSBarry Smith   Level: advanced
12382ed6491fSPatrick Sanan 
123920f4b53cSBarry Smith   Developer Note:
1240bb7acecfSBarry Smith   If the fine-scale `DMDA` has the -dm_bind_below option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
1241e9c74fd6SRichard Tran Mills   on the restriction/interpolation operator to set the bindingpropagates flag to true.
1242e9c74fd6SRichard Tran Mills 
1243*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatRestrict()`, `MatInterpolate()`, `DMCreateInterpolation()`, DMCreateRestriction()`, `DMCreateGlobalVector()`
12442ed6491fSPatrick Sanan @*/
1245d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolationScale(DM dac, DM daf, Mat mat, Vec *scale)
1246d71ae5a4SJacob Faibussowitsch {
12472ed6491fSPatrick Sanan   Vec         fine;
12482ed6491fSPatrick Sanan   PetscScalar one = 1.0;
12499704db99SRichard Tran Mills #if defined(PETSC_HAVE_CUDA)
1250e9c74fd6SRichard Tran Mills   PetscBool bindingpropagates, isbound;
12519704db99SRichard Tran Mills #endif
12522ed6491fSPatrick Sanan 
12532ed6491fSPatrick Sanan   PetscFunctionBegin;
12549566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(daf, &fine));
12559566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dac, scale));
12569566063dSJacob Faibussowitsch   PetscCall(VecSet(fine, one));
12579704db99SRichard Tran Mills #if defined(PETSC_HAVE_CUDA)
12589704db99SRichard Tran Mills   /* If the 'fine' Vec is bound to the CPU, it makes sense to bind 'mat' as well.
12599704db99SRichard Tran Mills    * Note that we only do this for the CUDA case, right now, but if we add support for MatMultTranspose() via ViennaCL,
12609704db99SRichard Tran Mills    * we'll need to do it for that case, too.*/
12619566063dSJacob Faibussowitsch   PetscCall(VecGetBindingPropagates(fine, &bindingpropagates));
1262e9c74fd6SRichard Tran Mills   if (bindingpropagates) {
12639566063dSJacob Faibussowitsch     PetscCall(MatSetBindingPropagates(mat, PETSC_TRUE));
12649566063dSJacob Faibussowitsch     PetscCall(VecBoundToCPU(fine, &isbound));
12659566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(mat, isbound));
126683aa49f4SRichard Tran Mills   }
12679704db99SRichard Tran Mills #endif
12689566063dSJacob Faibussowitsch   PetscCall(MatRestrict(mat, fine, *scale));
12699566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fine));
12709566063dSJacob Faibussowitsch   PetscCall(VecReciprocal(*scale));
12713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12722ed6491fSPatrick Sanan }
12732ed6491fSPatrick Sanan 
12742ed6491fSPatrick Sanan /*@
1275bb7acecfSBarry Smith     DMCreateRestriction - Gets restriction matrix between two `DM` objects. The resulting matrix map degrees of freedom in the vector obtained by
1276bb7acecfSBarry Smith     `DMCreateGlobalVector()` on the fine `DM` to similar vectors on the coarse grid `DM`.
12773ad4599aSBarry Smith 
127820f4b53cSBarry Smith     Collective
12793ad4599aSBarry Smith 
1280d8d19677SJose E. Roman     Input Parameters:
1281bb7acecfSBarry Smith +   dmc - the `DM` object
1282bb7acecfSBarry Smith -   dmf - the second, finer `DM` object
12833ad4599aSBarry Smith 
12843ad4599aSBarry Smith     Output Parameter:
12853ad4599aSBarry Smith .  mat - the restriction
12863ad4599aSBarry Smith 
12873ad4599aSBarry Smith     Level: developer
12883ad4599aSBarry Smith 
1289bb7acecfSBarry Smith     Note:
1290bb7acecfSBarry Smith     This only works for `DMSTAG`. For many situations either the transpose of the operator obtained with `DMCreateInterpolation()` or that
1291bb7acecfSBarry Smith     matrix multiplied by the vector obtained with `DMCreateInterpolationScale()` provides the desired object.
12923ad4599aSBarry Smith 
1293*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRestrict()`, `DMInterpolate()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateInterpolation()`
12943ad4599aSBarry Smith @*/
1295d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateRestriction(DM dmc, DM dmf, Mat *mat)
1296d71ae5a4SJacob Faibussowitsch {
12973ad4599aSBarry Smith   PetscFunctionBegin;
1298a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1299a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
13005a84ad33SLisandro Dalcin   PetscValidPointer(mat, 3);
13019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateRestriction, dmc, dmf, 0, 0));
1302dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createrestriction, dmf, mat);
13039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateRestriction, dmc, dmf, 0, 0));
13043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13053ad4599aSBarry Smith }
13063ad4599aSBarry Smith 
130747c6ae99SBarry Smith /*@
1308bb7acecfSBarry Smith     DMCreateInjection - Gets injection matrix between two `DM` objects. This is an operator that applied to a vector obtained with
1309bb7acecfSBarry Smith     `DMCreateGlobalVector()` on the fine grid maps the values to a vector on the vector on the coarse `DM` by simply selecting the values
1310bb7acecfSBarry Smith     on the coarse grid points. This compares to the operator obtained by `DMCreateRestriction()` or the transpose of the operator obtained
1311bb7acecfSBarry Smith     by `DMCreateInterpolation()` that uses a "local weighted average" of the values around the coarse grid point as the coarse grid value.
131247c6ae99SBarry Smith 
131320f4b53cSBarry Smith     Collective
131447c6ae99SBarry Smith 
1315d8d19677SJose E. Roman     Input Parameters:
1316bb7acecfSBarry Smith +   dac - the `DM` object
1317bb7acecfSBarry Smith -   daf - the second, finer `DM` object
131847c6ae99SBarry Smith 
131947c6ae99SBarry Smith     Output Parameter:
13206dbf9973SLawrence Mitchell .   mat - the injection
132147c6ae99SBarry Smith 
132247c6ae99SBarry Smith     Level: developer
132347c6ae99SBarry Smith 
1324bb7acecfSBarry Smith    Note:
1325bb7acecfSBarry Smith     For `DMDA` objects this only works for "uniform refinement", that is the refined mesh was obtained `DMRefine()` or the coarse mesh was obtained by
1326bb7acecfSBarry Smith         `DMCoarsen()`. The coordinates set into the `DMDA` are completely ignored in computing the injection.
132785afcc9aSBarry Smith 
1328*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateInterpolation()`,
1329bb7acecfSBarry Smith           `DMCreateRestriction()`, `MatRestrict()`, `MatInterpolate()`
133047c6ae99SBarry Smith @*/
1331d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection(DM dac, DM daf, Mat *mat)
1332d71ae5a4SJacob Faibussowitsch {
133347c6ae99SBarry Smith   PetscFunctionBegin;
1334a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dac, DM_CLASSID, 1);
1335a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(daf, DM_CLASSID, 2);
13365a84ad33SLisandro Dalcin   PetscValidPointer(mat, 3);
13379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateInjection, dac, daf, 0, 0));
1338dbbe0bcdSBarry Smith   PetscUseTypeMethod(dac, createinjection, daf, mat);
13399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateInjection, dac, daf, 0, 0));
13403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134147c6ae99SBarry Smith }
134247c6ae99SBarry Smith 
1343b412c318SBarry Smith /*@
1344bb7acecfSBarry Smith   DMCreateMassMatrix - Gets the mass matrix between two `DM` objects, M_ij = \int \phi_i \psi_j where the \phi are Galerkin basis functions for a
1345bb7acecfSBarry Smith   a Galerkin finite element model on the `DM`
1346bd041c0cSMatthew G. Knepley 
134720f4b53cSBarry Smith   Collective
1348bd041c0cSMatthew G. Knepley 
1349d8d19677SJose E. Roman   Input Parameters:
1350bb7acecfSBarry Smith + dmc - the target `DM` object
1351bb7acecfSBarry Smith - dmf - the source `DM` object
1352bd041c0cSMatthew G. Knepley 
1353bd041c0cSMatthew G. Knepley   Output Parameter:
1354b4937a87SMatthew G. Knepley . mat - the mass matrix
1355bd041c0cSMatthew G. Knepley 
1356bd041c0cSMatthew G. Knepley   Level: developer
1357bd041c0cSMatthew G. Knepley 
1358bb7acecfSBarry Smith   Notes:
1359bb7acecfSBarry Smith   For `DMPLEX` the finite element model for the `DM` must have been already provided.
1360bb7acecfSBarry Smith 
136120f4b53cSBarry Smith   if `dmc` is `dmf` then x^t M x is an approximation to the L2 norm of the vector x which is obtained by `DMCreateGlobalVector()`
1362bb7acecfSBarry Smith 
1363*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMassMatrixLumped()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolation()`, `DMCreateInjection()`
1364bd041c0cSMatthew G. Knepley @*/
1365d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix(DM dmc, DM dmf, Mat *mat)
1366d71ae5a4SJacob Faibussowitsch {
1367bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
1368b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1369b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
13705a84ad33SLisandro Dalcin   PetscValidPointer(mat, 3);
13715b8ffe73SMark Adams   PetscCall(PetscLogEventBegin(DM_CreateMassMatrix, 0, 0, 0, 0));
1372dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createmassmatrix, dmf, mat);
13735b8ffe73SMark Adams   PetscCall(PetscLogEventEnd(DM_CreateMassMatrix, 0, 0, 0, 0));
13743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1375b4937a87SMatthew G. Knepley }
1376b4937a87SMatthew G. Knepley 
1377b4937a87SMatthew G. Knepley /*@
1378bb7acecfSBarry Smith   DMCreateMassMatrixLumped - Gets the lumped mass matrix for a given `DM`
1379b4937a87SMatthew G. Knepley 
138020f4b53cSBarry Smith   Collective
1381b4937a87SMatthew G. Knepley 
1382b4937a87SMatthew G. Knepley   Input Parameter:
1383bb7acecfSBarry Smith . dm - the `DM` object
1384b4937a87SMatthew G. Knepley 
1385b4937a87SMatthew G. Knepley   Output Parameter:
1386bb7acecfSBarry Smith . lm - the lumped mass matrix, which is a diagonal matrix, represented as a vector
1387b4937a87SMatthew G. Knepley 
1388b4937a87SMatthew G. Knepley   Level: developer
1389b4937a87SMatthew G. Knepley 
1390bb7acecfSBarry Smith   Note:
1391bb7acecfSBarry Smith   See `DMCreateMassMatrix()` for how to create the non-lumped version of the mass matrix.
1392bb7acecfSBarry Smith 
1393*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMassMatrix()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolation()`, `DMCreateInjection()`
1394b4937a87SMatthew G. Knepley @*/
1395d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped(DM dm, Vec *lm)
1396d71ae5a4SJacob Faibussowitsch {
1397b4937a87SMatthew G. Knepley   PetscFunctionBegin;
1398b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1399b4937a87SMatthew G. Knepley   PetscValidPointer(lm, 2);
1400dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createmassmatrixlumped, lm);
14013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1402bd041c0cSMatthew G. Knepley }
1403bd041c0cSMatthew G. Knepley 
1404bd041c0cSMatthew G. Knepley /*@
1405bb7acecfSBarry Smith     DMCreateColoring - Gets coloring of a graph associated with the `DM`. Often the graph represents the operator matrix associated with the discretization
1406bb7acecfSBarry Smith     of a PDE on the `DM`.
140747c6ae99SBarry Smith 
140820f4b53cSBarry Smith     Collective
140947c6ae99SBarry Smith 
1410d8d19677SJose E. Roman     Input Parameters:
1411bb7acecfSBarry Smith +   dm - the `DM` object
1412bb7acecfSBarry Smith -   ctype - `IS_COLORING_LOCAL` or `IS_COLORING_GLOBAL`
141347c6ae99SBarry Smith 
141447c6ae99SBarry Smith     Output Parameter:
141547c6ae99SBarry Smith .   coloring - the coloring
141647c6ae99SBarry Smith 
14171bf8429eSBarry Smith     Level: developer
14181bf8429eSBarry Smith 
1419ec5066bdSBarry Smith     Notes:
1420bb7acecfSBarry Smith     Coloring of matrices can also be computed directly from the sparse matrix nonzero structure via the `MatColoring` object or from the mesh from which the
1421bb7acecfSBarry Smith     matrix comes from (what this function provides). In general using the mesh produces a more optimal coloring (fewer colors).
1422ec5066bdSBarry Smith 
1423bb7acecfSBarry Smith     This produces a coloring with the distance of 2, see `MatSetColoringDistance()` which can be used for efficiently computing Jacobians with `MatFDColoringCreate()`
14241bf8429eSBarry Smith     For `DMDA` in three dimensions with periodic boundary conditions the number of grid points in each dimension must be divisible by 2*stencil_width + 1,
14251bf8429eSBarry Smith     otherwise an error will be generated.
1426ec5066bdSBarry Smith 
1427*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `ISColoring`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatType()`, `MatColoring`, `MatFDColoringCreate()`
1428aab9d709SJed Brown @*/
1429d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring(DM dm, ISColoringType ctype, ISColoring *coloring)
1430d71ae5a4SJacob Faibussowitsch {
143147c6ae99SBarry Smith   PetscFunctionBegin;
1432171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14335a84ad33SLisandro Dalcin   PetscValidPointer(coloring, 3);
1434dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getcoloring, ctype, coloring);
14353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
143647c6ae99SBarry Smith }
143747c6ae99SBarry Smith 
1438b412c318SBarry Smith /*@
1439bb7acecfSBarry Smith     DMCreateMatrix - Gets an empty matrix for a `DM` that is most commonly used to store the Jacobian of a discrete PDE operator.
144047c6ae99SBarry Smith 
144120f4b53cSBarry Smith     Collective
144247c6ae99SBarry Smith 
144347c6ae99SBarry Smith     Input Parameter:
1444bb7acecfSBarry Smith .   dm - the `DM` object
144547c6ae99SBarry Smith 
144647c6ae99SBarry Smith     Output Parameter:
144747c6ae99SBarry Smith .   mat - the empty Jacobian
144847c6ae99SBarry Smith 
144920f4b53cSBarry Smith     Options Database Key:
1450bb7acecfSBarry Smith . -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()` and `DMCreateMassMatrix()`, but do not fill it with zeros
1451f27dd7c6SMatthew G. Knepley 
145220f4b53cSBarry Smith     Level: beginner
145320f4b53cSBarry Smith 
145495452b02SPatrick Sanan     Notes:
145595452b02SPatrick Sanan     This properly preallocates the number of nonzeros in the sparse matrix so you
145694013140SBarry Smith     do not need to do it yourself.
145794013140SBarry Smith 
145894013140SBarry Smith     By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1459bb7acecfSBarry Smith     the nonzero pattern call `DMSetMatrixPreallocateOnly()`
146094013140SBarry Smith 
1461bb7acecfSBarry Smith     For `DMDA`, when you call `MatView()` on this matrix it is displayed using the global natural ordering, NOT in the ordering used
146294013140SBarry Smith     internally by PETSc.
146394013140SBarry Smith 
1464bb7acecfSBarry Smith     For `DMDA`, in general it is easiest to use `MatSetValuesStencil()` or `MatSetValuesLocal()` to put values into the matrix because
1465bb7acecfSBarry Smith     `MatSetValues()` requires the indices for the global numbering for the `DMDA` which is complic`ated to compute
146694013140SBarry Smith 
1467*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMSetMatType()`, `DMCreateMassMatrix()`
1468aab9d709SJed Brown @*/
1469d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix(DM dm, Mat *mat)
1470d71ae5a4SJacob Faibussowitsch {
147147c6ae99SBarry Smith   PetscFunctionBegin;
1472171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1473064a246eSJacob Faibussowitsch   PetscValidPointer(mat, 2);
14749566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
14759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateMatrix, 0, 0, 0, 0));
1476dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, creatematrix, mat);
147776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1478c6b011d8SStefano Zampini     DM mdm;
1479c6b011d8SStefano Zampini 
14809566063dSJacob Faibussowitsch     PetscCall(MatGetDM(*mat, &mdm));
14817a8be351SBarry Smith     PetscCheck(mdm, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DM type '%s' did not attach the DM to the matrix", ((PetscObject)dm)->type_name);
1482c6b011d8SStefano Zampini   }
1483e571a35bSMatthew G. Knepley   /* Handle nullspace and near nullspace */
1484e5e52638SMatthew G. Knepley   if (dm->Nf) {
1485e571a35bSMatthew G. Knepley     MatNullSpace nullSpace;
1486649ef022SMatthew Knepley     PetscInt     Nf, f;
1487e571a35bSMatthew G. Knepley 
14889566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
1489649ef022SMatthew Knepley     for (f = 0; f < Nf; ++f) {
1490649ef022SMatthew Knepley       if (dm->nullspaceConstructors[f]) {
14919566063dSJacob Faibussowitsch         PetscCall((*dm->nullspaceConstructors[f])(dm, f, f, &nullSpace));
14929566063dSJacob Faibussowitsch         PetscCall(MatSetNullSpace(*mat, nullSpace));
14939566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nullSpace));
1494649ef022SMatthew Knepley         break;
1495e571a35bSMatthew G. Knepley       }
1496649ef022SMatthew Knepley     }
1497649ef022SMatthew Knepley     for (f = 0; f < Nf; ++f) {
1498649ef022SMatthew Knepley       if (dm->nearnullspaceConstructors[f]) {
14999566063dSJacob Faibussowitsch         PetscCall((*dm->nearnullspaceConstructors[f])(dm, f, f, &nullSpace));
15009566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(*mat, nullSpace));
15019566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nullSpace));
1502e571a35bSMatthew G. Knepley       }
1503e571a35bSMatthew G. Knepley     }
1504e571a35bSMatthew G. Knepley   }
15059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateMatrix, 0, 0, 0, 0));
15063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
150747c6ae99SBarry Smith }
150847c6ae99SBarry Smith 
1509732e2eb9SMatthew G Knepley /*@
1510bb7acecfSBarry Smith   DMSetMatrixPreallocateSkip - When `DMCreateMatrix()` is called the matrix sizes and `ISLocalToGlobalMapping` will be
1511bb7acecfSBarry Smith   properly set, but the data structures to store values in the matrices will not be preallocated. This is most useful to reduce initialization costs when
1512bb7acecfSBarry Smith   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` will be used.
1513aa0f6e3cSJed Brown 
151420f4b53cSBarry Smith   Logically Collective
1515aa0f6e3cSJed Brown 
1516aa0f6e3cSJed Brown   Input Parameters:
1517bb7acecfSBarry Smith + dm - the `DM`
1518bb7acecfSBarry Smith - skip - `PETSC_TRUE` to skip preallocation
1519aa0f6e3cSJed Brown 
1520aa0f6e3cSJed Brown   Level: developer
1521aa0f6e3cSJed Brown 
1522*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMSetMatrixStructureOnly()`, `DMSetMatrixPreallocateOnly()`
1523aa0f6e3cSJed Brown @*/
1524d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixPreallocateSkip(DM dm, PetscBool skip)
1525d71ae5a4SJacob Faibussowitsch {
1526aa0f6e3cSJed Brown   PetscFunctionBegin;
1527aa0f6e3cSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1528aa0f6e3cSJed Brown   dm->prealloc_skip = skip;
15293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1530aa0f6e3cSJed Brown }
1531aa0f6e3cSJed Brown 
1532aa0f6e3cSJed Brown /*@
1533bb7acecfSBarry Smith   DMSetMatrixPreallocateOnly - When `DMCreateMatrix()` is called the matrix will be properly
1534732e2eb9SMatthew G Knepley     preallocated but the nonzero structure and zero values will not be set.
1535732e2eb9SMatthew G Knepley 
153620f4b53cSBarry Smith   Logically Collective
1537732e2eb9SMatthew G Knepley 
1538d8d19677SJose E. Roman   Input Parameters:
1539bb7acecfSBarry Smith + dm - the `DM`
1540bb7acecfSBarry Smith - only - `PETSC_TRUE` if only want preallocation
1541732e2eb9SMatthew G Knepley 
154220f4b53cSBarry Smith   Options Database Key:
1543bb7acecfSBarry Smith . -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()`, `DMCreateMassMatrix()`, but do not fill it with zeros
1544f27dd7c6SMatthew G. Knepley 
154520f4b53cSBarry Smith   Level: developer
154620f4b53cSBarry Smith 
1547*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixStructureOnly()`, `DMSetMatrixPreallocateSkip()`
1548732e2eb9SMatthew G Knepley @*/
1549d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1550d71ae5a4SJacob Faibussowitsch {
1551732e2eb9SMatthew G Knepley   PetscFunctionBegin;
1552732e2eb9SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1553732e2eb9SMatthew G Knepley   dm->prealloc_only = only;
15543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1555732e2eb9SMatthew G Knepley }
1556732e2eb9SMatthew G Knepley 
1557b06ff27eSHong Zhang /*@
1558bb7acecfSBarry Smith   DMSetMatrixStructureOnly - When `DMCreateMatrix()` is called, the matrix structure will be created
1559bb7acecfSBarry Smith     but the array for numerical values will not be allocated.
1560b06ff27eSHong Zhang 
156120f4b53cSBarry Smith   Logically Collective
1562b06ff27eSHong Zhang 
1563d8d19677SJose E. Roman   Input Parameters:
1564bb7acecfSBarry Smith + dm - the `DM`
1565da81f932SPierre Jolivet - only - `PETSC_TRUE` if you only want matrix structure
1566b06ff27eSHong Zhang 
1567b06ff27eSHong Zhang   Level: developer
1568bb7acecfSBarry Smith 
1569*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMSetMatrixPreallocateOnly()`, `DMSetMatrixPreallocateSkip()`
1570b06ff27eSHong Zhang @*/
1571d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1572d71ae5a4SJacob Faibussowitsch {
1573b06ff27eSHong Zhang   PetscFunctionBegin;
1574b06ff27eSHong Zhang   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1575b06ff27eSHong Zhang   dm->structure_only = only;
15763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1577b06ff27eSHong Zhang }
1578b06ff27eSHong Zhang 
1579863027abSJed Brown /*@
1580863027abSJed Brown   DMSetBlockingType - set the blocking granularity to be used for variable block size `DMCreateMatrix()` is called
1581863027abSJed Brown 
158220f4b53cSBarry Smith   Logically Collective
1583863027abSJed Brown 
1584863027abSJed Brown   Input Parameters:
1585863027abSJed Brown + dm - the `DM`
1586863027abSJed Brown - btype - block by topological point or field node
1587863027abSJed Brown 
158820f4b53cSBarry Smith   Options Database Key:
15890e762ea3SJed Brown . -dm_blocking_type [topological_point, field_node] - use topological point blocking or field node blocking
1590863027abSJed Brown 
159120f4b53cSBarry Smith   Level: advanced
159220f4b53cSBarry Smith 
1593*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `MatSetVariableBlockSizes()`
1594863027abSJed Brown @*/
1595863027abSJed Brown PetscErrorCode DMSetBlockingType(DM dm, DMBlockingType btype)
1596863027abSJed Brown {
1597863027abSJed Brown   PetscFunctionBegin;
1598863027abSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1599863027abSJed Brown   dm->blocking_type = btype;
16003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1601863027abSJed Brown }
1602863027abSJed Brown 
1603863027abSJed Brown /*@
1604863027abSJed Brown   DMGetBlockingType - get the blocking granularity to be used for variable block size `DMCreateMatrix()` is called
1605863027abSJed Brown 
1606863027abSJed Brown   Not Collective
1607863027abSJed Brown 
16082fe279fdSBarry Smith   Input Parameter:
1609863027abSJed Brown . dm - the `DM`
1610863027abSJed Brown 
16112fe279fdSBarry Smith   Output Parameter:
1612863027abSJed Brown . btype - block by topological point or field node
1613863027abSJed Brown 
1614863027abSJed Brown   Level: advanced
1615863027abSJed Brown 
1616*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `MatSetVariableBlockSizes()`
1617863027abSJed Brown @*/
1618863027abSJed Brown PetscErrorCode DMGetBlockingType(DM dm, DMBlockingType *btype)
1619863027abSJed Brown {
1620863027abSJed Brown   PetscFunctionBegin;
1621863027abSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1622863027abSJed Brown   PetscValidPointer(btype, 2);
1623863027abSJed Brown   *btype = dm->blocking_type;
16243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1625863027abSJed Brown }
1626863027abSJed Brown 
1627a89ea682SMatthew G Knepley /*@C
1628bb7acecfSBarry Smith   DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with `DMRestoreWorkArray()`
1629a89ea682SMatthew G Knepley 
1630a89ea682SMatthew G Knepley   Not Collective
1631a89ea682SMatthew G Knepley 
1632a89ea682SMatthew G Knepley   Input Parameters:
1633bb7acecfSBarry Smith + dm - the `DM` object
1634a5b23f4aSJose E. Roman . count - The minimum size
163520f4b53cSBarry Smith - dtype - MPI data type, often `MPIU_REAL`, `MPIU_SCALAR`, or `MPIU_INT`)
1636a89ea682SMatthew G Knepley 
1637a89ea682SMatthew G Knepley   Output Parameter:
1638a89ea682SMatthew G Knepley . array - the work array
1639a89ea682SMatthew G Knepley 
1640a89ea682SMatthew G Knepley   Level: developer
1641a89ea682SMatthew G Knepley 
1642bb7acecfSBarry Smith   Note:
1643da81f932SPierre Jolivet   A `DM` may stash the array between instantiations so using this routine may be more efficient than calling `PetscMalloc()`
1644bb7acecfSBarry Smith 
1645bb7acecfSBarry Smith   The array may contain nonzero values
1646bb7acecfSBarry Smith 
1647*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMRestoreWorkArray()`, `PetscMalloc()`
1648a89ea682SMatthew G Knepley @*/
1649d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetWorkArray(DM dm, PetscInt count, MPI_Datatype dtype, void *mem)
1650d71ae5a4SJacob Faibussowitsch {
1651aa1993deSMatthew G Knepley   DMWorkLink  link;
165269291d52SBarry Smith   PetscMPIInt dsize;
1653a89ea682SMatthew G Knepley 
1654a89ea682SMatthew G Knepley   PetscFunctionBegin;
1655a89ea682SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1656aa1993deSMatthew G Knepley   PetscValidPointer(mem, 4);
1657aa1993deSMatthew G Knepley   if (dm->workin) {
1658aa1993deSMatthew G Knepley     link       = dm->workin;
1659aa1993deSMatthew G Knepley     dm->workin = dm->workin->next;
1660aa1993deSMatthew G Knepley   } else {
16614dfa11a4SJacob Faibussowitsch     PetscCall(PetscNew(&link));
1662a89ea682SMatthew G Knepley   }
16639566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_size(dtype, &dsize));
16645056fcd2SBarry Smith   if (((size_t)dsize * count) > link->bytes) {
16659566063dSJacob Faibussowitsch     PetscCall(PetscFree(link->mem));
16669566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(dsize * count, &link->mem));
1667854ce69bSBarry Smith     link->bytes = dsize * count;
1668aa1993deSMatthew G Knepley   }
1669aa1993deSMatthew G Knepley   link->next  = dm->workout;
1670aa1993deSMatthew G Knepley   dm->workout = link;
1671cea3dcb8SSatish Balay #if defined(__MEMCHECK_H) && (defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) || defined(PLAT_amd64_darwin))
167200d952a4SJed Brown   VALGRIND_MAKE_MEM_NOACCESS((char *)link->mem + (size_t)dsize * count, link->bytes - (size_t)dsize * count);
167300d952a4SJed Brown   VALGRIND_MAKE_MEM_UNDEFINED(link->mem, (size_t)dsize * count);
167400d952a4SJed Brown #endif
1675aa1993deSMatthew G Knepley   *(void **)mem = link->mem;
16763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1677a89ea682SMatthew G Knepley }
1678a89ea682SMatthew G Knepley 
1679aa1993deSMatthew G Knepley /*@C
1680bb7acecfSBarry Smith   DMRestoreWorkArray - Restores a work array obtained with `DMCreateWorkArray()`
1681aa1993deSMatthew G Knepley 
1682aa1993deSMatthew G Knepley   Not Collective
1683aa1993deSMatthew G Knepley 
1684aa1993deSMatthew G Knepley   Input Parameters:
1685bb7acecfSBarry Smith + dm - the `DM` object
1686a5b23f4aSJose E. Roman . count - The minimum size
168720f4b53cSBarry Smith - dtype - MPI data type, often `MPIU_REAL`, `MPIU_SCALAR`, `MPIU_INT`
1688aa1993deSMatthew G Knepley 
1689aa1993deSMatthew G Knepley   Output Parameter:
1690aa1993deSMatthew G Knepley . array - the work array
1691aa1993deSMatthew G Knepley 
1692aa1993deSMatthew G Knepley   Level: developer
1693aa1993deSMatthew G Knepley 
169420f4b53cSBarry Smith   Developer Note:
1695bb7acecfSBarry Smith   count and dtype are ignored, they are only needed for `DMGetWorkArray()`
1696147403d9SBarry Smith 
1697*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMGetWorkArray()`
1698aa1993deSMatthew G Knepley @*/
1699d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestoreWorkArray(DM dm, PetscInt count, MPI_Datatype dtype, void *mem)
1700d71ae5a4SJacob Faibussowitsch {
1701aa1993deSMatthew G Knepley   DMWorkLink *p, link;
1702aa1993deSMatthew G Knepley 
1703aa1993deSMatthew G Knepley   PetscFunctionBegin;
1704aa1993deSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1705aa1993deSMatthew G Knepley   PetscValidPointer(mem, 4);
1706aa1993deSMatthew G Knepley   for (p = &dm->workout; (link = *p); p = &link->next) {
1707aa1993deSMatthew G Knepley     if (link->mem == *(void **)mem) {
1708aa1993deSMatthew G Knepley       *p            = link->next;
1709aa1993deSMatthew G Knepley       link->next    = dm->workin;
1710aa1993deSMatthew G Knepley       dm->workin    = link;
17110298fd71SBarry Smith       *(void **)mem = NULL;
17123ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
1713aa1993deSMatthew G Knepley     }
1714aa1993deSMatthew G Knepley   }
1715aa1993deSMatthew G Knepley   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Array was not checked out");
1716aa1993deSMatthew G Knepley }
1717e7c4fc90SDmitry Karpeev 
17188cda7954SMatthew G. Knepley /*@C
1719bb7acecfSBarry Smith   DMSetNullSpaceConstructor - Provide a callback function which constructs the nullspace for a given field, defined with `DMAddField()`, when function spaces
1720bb7acecfSBarry Smith   are joined or split, such as in `DMCreateSubDM()`
17218cda7954SMatthew G. Knepley 
172220f4b53cSBarry Smith   Logically Collective; No Fortran Support
17238cda7954SMatthew G. Knepley 
17248cda7954SMatthew G. Knepley   Input Parameters:
1725bb7acecfSBarry Smith + dm     - The `DM`
17268cda7954SMatthew G. Knepley . field  - The field number for the nullspace
17278cda7954SMatthew G. Knepley - nullsp - A callback to create the nullspace
17288cda7954SMatthew G. Knepley 
172920f4b53cSBarry Smith   Calling sequence of `nullsp`:
1730147403d9SBarry Smith .vb
1731147403d9SBarry Smith     PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1732147403d9SBarry Smith .ve
1733bb7acecfSBarry Smith +  dm        - The present `DM`
1734bb7acecfSBarry Smith .  origField - The field number given above, in the original `DM`
1735147403d9SBarry Smith .  field     - The field number in dm
1736147403d9SBarry Smith -  nullSpace - The nullspace for the given field
17378cda7954SMatthew G. Knepley 
173849762cbcSSatish Balay   Level: intermediate
173949762cbcSSatish Balay 
1740*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetNullSpaceConstructor()`, `DMSetNearNullSpaceConstructor()`, `DMGetNearNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
1741147403d9SBarry Smith @*/
1742d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM, PetscInt, PetscInt, MatNullSpace *))
1743d71ae5a4SJacob Faibussowitsch {
1744435a35e8SMatthew G Knepley   PetscFunctionBegin;
1745435a35e8SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17467a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1747435a35e8SMatthew G Knepley   dm->nullspaceConstructors[field] = nullsp;
17483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1749435a35e8SMatthew G Knepley }
1750435a35e8SMatthew G Knepley 
17518cda7954SMatthew G. Knepley /*@C
1752bb7acecfSBarry Smith   DMGetNullSpaceConstructor - Return the callback function which constructs the nullspace for a given field, defined with `DMAddField()`
17538cda7954SMatthew G. Knepley 
175420f4b53cSBarry Smith   Not Collective; No Fortran Support
17558cda7954SMatthew G. Knepley 
17568cda7954SMatthew G. Knepley   Input Parameters:
1757bb7acecfSBarry Smith + dm     - The `DM`
17588cda7954SMatthew G. Knepley - field  - The field number for the nullspace
17598cda7954SMatthew G. Knepley 
17608cda7954SMatthew G. Knepley   Output Parameter:
17618cda7954SMatthew G. Knepley . nullsp - A callback to create the nullspace
17628cda7954SMatthew G. Knepley 
176320f4b53cSBarry Smith   Calling sequence of `nullsp`:
1764147403d9SBarry Smith .vb
1765147403d9SBarry Smith     PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1766147403d9SBarry Smith .ve
1767147403d9SBarry Smith +  dm        - The present DM
1768147403d9SBarry Smith .  origField - The field number given above, in the original DM
1769147403d9SBarry Smith .  field     - The field number in dm
1770147403d9SBarry Smith -  nullSpace - The nullspace for the given field
17718cda7954SMatthew G. Knepley 
177249762cbcSSatish Balay    Level: intermediate
177349762cbcSSatish Balay 
1774*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMSetNullSpaceConstructor()`, `DMSetNearNullSpaceConstructor()`, `DMGetNearNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
1775147403d9SBarry Smith @*/
1776d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM, PetscInt, PetscInt, MatNullSpace *))
1777d71ae5a4SJacob Faibussowitsch {
17780a50eb56SMatthew G. Knepley   PetscFunctionBegin;
17790a50eb56SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1780f9d4088aSMatthew G. Knepley   PetscValidPointer(nullsp, 3);
17817a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
17820a50eb56SMatthew G. Knepley   *nullsp = dm->nullspaceConstructors[field];
17833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17840a50eb56SMatthew G. Knepley }
17850a50eb56SMatthew G. Knepley 
17868cda7954SMatthew G. Knepley /*@C
1787bb7acecfSBarry Smith   DMSetNearNullSpaceConstructor - Provide a callback function which constructs the near-nullspace for a given field, defined with `DMAddField()`
17888cda7954SMatthew G. Knepley 
178920f4b53cSBarry Smith   Logically Collective; No Fortran Support
17908cda7954SMatthew G. Knepley 
17918cda7954SMatthew G. Knepley   Input Parameters:
1792bb7acecfSBarry Smith + dm     - The `DM`
17938cda7954SMatthew G. Knepley . field  - The field number for the nullspace
17948cda7954SMatthew G. Knepley - nullsp - A callback to create the near-nullspace
17958cda7954SMatthew G. Knepley 
179620f4b53cSBarry Smith   Calling sequence of `nullsp`:
1797147403d9SBarry Smith .vb
1798147403d9SBarry Smith     PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1799147403d9SBarry Smith .ve
1800bb7acecfSBarry Smith +  dm        - The present `DM`
1801bb7acecfSBarry Smith .  origField - The field number given above, in the original `DM`
1802147403d9SBarry Smith .  field     - The field number in dm
1803147403d9SBarry Smith -  nullSpace - The nullspace for the given field
18048cda7954SMatthew G. Knepley 
180549762cbcSSatish Balay    Level: intermediate
180649762cbcSSatish Balay 
1807*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetNearNullSpaceConstructor()`, `DMSetNullSpaceConstructor()`, `DMGetNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`,
1808bb7acecfSBarry Smith           `MatNullSpace`
1809147403d9SBarry Smith @*/
1810d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM, PetscInt, PetscInt, MatNullSpace *))
1811d71ae5a4SJacob Faibussowitsch {
1812f9d4088aSMatthew G. Knepley   PetscFunctionBegin;
1813f9d4088aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18147a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1815f9d4088aSMatthew G. Knepley   dm->nearnullspaceConstructors[field] = nullsp;
18163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1817f9d4088aSMatthew G. Knepley }
1818f9d4088aSMatthew G. Knepley 
18198cda7954SMatthew G. Knepley /*@C
1820bb7acecfSBarry Smith   DMGetNearNullSpaceConstructor - Return the callback function which constructs the near-nullspace for a given field, defined with `DMAddField()`
18218cda7954SMatthew G. Knepley 
182220f4b53cSBarry Smith   Not Collective; No Fortran Support
18238cda7954SMatthew G. Knepley 
18248cda7954SMatthew G. Knepley   Input Parameters:
1825bb7acecfSBarry Smith + dm     - The `DM`
18268cda7954SMatthew G. Knepley - field  - The field number for the nullspace
18278cda7954SMatthew G. Knepley 
18288cda7954SMatthew G. Knepley   Output Parameter:
18298cda7954SMatthew G. Knepley . nullsp - A callback to create the near-nullspace
18308cda7954SMatthew G. Knepley 
183120f4b53cSBarry Smith   Calling sequence of `nullsp`:
1832147403d9SBarry Smith .vb
1833147403d9SBarry Smith     PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1834147403d9SBarry Smith .ve
1835bb7acecfSBarry Smith +  dm        - The present `DM`
1836bb7acecfSBarry Smith .  origField - The field number given above, in the original `DM`
1837147403d9SBarry Smith .  field     - The field number in dm
1838147403d9SBarry Smith -  nullSpace - The nullspace for the given field
18398cda7954SMatthew G. Knepley 
184049762cbcSSatish Balay    Level: intermediate
184149762cbcSSatish Balay 
1842*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMSetNearNullSpaceConstructor()`, `DMSetNullSpaceConstructor()`, `DMGetNullSpaceConstructor()`, `DMCreateSubDM()`,
1843bb7acecfSBarry Smith           `MatNullSpace`, `DMCreateSuperDM()`
1844147403d9SBarry Smith @*/
1845d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM, PetscInt, PetscInt, MatNullSpace *))
1846d71ae5a4SJacob Faibussowitsch {
1847f9d4088aSMatthew G. Knepley   PetscFunctionBegin;
1848f9d4088aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1849f9d4088aSMatthew G. Knepley   PetscValidPointer(nullsp, 3);
18507a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1851f9d4088aSMatthew G. Knepley   *nullsp = dm->nearnullspaceConstructors[field];
18523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1853f9d4088aSMatthew G. Knepley }
1854f9d4088aSMatthew G. Knepley 
18554f3b5142SJed Brown /*@C
1856bb7acecfSBarry Smith   DMCreateFieldIS - Creates a set of `IS` objects with the global indices of dofs for each field defined with `DMAddField()`
18574d343eeaSMatthew G Knepley 
185820f4b53cSBarry Smith   Not Collective; No Fortran Support
18594d343eeaSMatthew G Knepley 
18604d343eeaSMatthew G Knepley   Input Parameter:
1861bb7acecfSBarry Smith . dm - the `DM` object
18624d343eeaSMatthew G Knepley 
18634d343eeaSMatthew G Knepley   Output Parameters:
186420f4b53cSBarry Smith + numFields  - The number of fields (or `NULL` if not requested)
186520f4b53cSBarry Smith . fieldNames - The number of each field (or `NULL` if not requested)
186620f4b53cSBarry Smith - fields     - The global indices for each field (or `NULL` if not requested)
18674d343eeaSMatthew G Knepley 
18684d343eeaSMatthew G Knepley   Level: intermediate
18694d343eeaSMatthew G Knepley 
1870bb7acecfSBarry Smith   Note:
187121c9b008SJed Brown   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1872bb7acecfSBarry Smith   `PetscFree()`, every entry of fields should be destroyed with `ISDestroy()`, and both arrays should be freed with
1873bb7acecfSBarry Smith   `PetscFree()`.
187421c9b008SJed Brown 
1875bb7acecfSBarry Smith   Developer Note:
1876bb7acecfSBarry Smith   It is not clear why both this function and `DMCreateFieldDecomposition()` exist. Having two seems redundant and confusing. This function should
1877bb7acecfSBarry Smith   likely be removed.
1878bb7acecfSBarry Smith 
1879*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
1880bb7acecfSBarry Smith           `DMCreateFieldDecomposition()`
18814d343eeaSMatthew G Knepley @*/
1882d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1883d71ae5a4SJacob Faibussowitsch {
188437d0c07bSMatthew G Knepley   PetscSection section, sectionGlobal;
18854d343eeaSMatthew G Knepley 
18864d343eeaSMatthew G Knepley   PetscFunctionBegin;
18874d343eeaSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
188869ca1f37SDmitry Karpeev   if (numFields) {
1889534a8f05SLisandro Dalcin     PetscValidIntPointer(numFields, 2);
189069ca1f37SDmitry Karpeev     *numFields = 0;
189169ca1f37SDmitry Karpeev   }
189237d0c07bSMatthew G Knepley   if (fieldNames) {
189337d0c07bSMatthew G Knepley     PetscValidPointer(fieldNames, 3);
18940298fd71SBarry Smith     *fieldNames = NULL;
189569ca1f37SDmitry Karpeev   }
189669ca1f37SDmitry Karpeev   if (fields) {
189769ca1f37SDmitry Karpeev     PetscValidPointer(fields, 4);
18980298fd71SBarry Smith     *fields = NULL;
189969ca1f37SDmitry Karpeev   }
19009566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
190137d0c07bSMatthew G Knepley   if (section) {
19023a544194SStefano Zampini     PetscInt *fieldSizes, *fieldNc, **fieldIndices;
190337d0c07bSMatthew G Knepley     PetscInt  nF, f, pStart, pEnd, p;
190437d0c07bSMatthew G Knepley 
19059566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
19069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &nF));
19079566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(nF, &fieldSizes, nF, &fieldNc, nF, &fieldIndices));
19089566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
190937d0c07bSMatthew G Knepley     for (f = 0; f < nF; ++f) {
191037d0c07bSMatthew G Knepley       fieldSizes[f] = 0;
19119566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &fieldNc[f]));
191237d0c07bSMatthew G Knepley     }
191337d0c07bSMatthew G Knepley     for (p = pStart; p < pEnd; ++p) {
191437d0c07bSMatthew G Knepley       PetscInt gdof;
191537d0c07bSMatthew G Knepley 
19169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
191737d0c07bSMatthew G Knepley       if (gdof > 0) {
191837d0c07bSMatthew G Knepley         for (f = 0; f < nF; ++f) {
19193a544194SStefano Zampini           PetscInt fdof, fcdof, fpdof;
192037d0c07bSMatthew G Knepley 
19219566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
19229566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
19233a544194SStefano Zampini           fpdof = fdof - fcdof;
19243a544194SStefano Zampini           if (fpdof && fpdof != fieldNc[f]) {
19253a544194SStefano Zampini             /* Layout does not admit a pointwise block size */
19263a544194SStefano Zampini             fieldNc[f] = 1;
19273a544194SStefano Zampini           }
19283a544194SStefano Zampini           fieldSizes[f] += fpdof;
192937d0c07bSMatthew G Knepley         }
193037d0c07bSMatthew G Knepley       }
193137d0c07bSMatthew G Knepley     }
193237d0c07bSMatthew G Knepley     for (f = 0; f < nF; ++f) {
19339566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(fieldSizes[f], &fieldIndices[f]));
193437d0c07bSMatthew G Knepley       fieldSizes[f] = 0;
193537d0c07bSMatthew G Knepley     }
193637d0c07bSMatthew G Knepley     for (p = pStart; p < pEnd; ++p) {
193737d0c07bSMatthew G Knepley       PetscInt gdof, goff;
193837d0c07bSMatthew G Knepley 
19399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
194037d0c07bSMatthew G Knepley       if (gdof > 0) {
19419566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff));
194237d0c07bSMatthew G Knepley         for (f = 0; f < nF; ++f) {
194337d0c07bSMatthew G Knepley           PetscInt fdof, fcdof, fc;
194437d0c07bSMatthew G Knepley 
19459566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
19469566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
1947ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++fieldSizes[f]) fieldIndices[f][fieldSizes[f]] = goff++;
194837d0c07bSMatthew G Knepley         }
194937d0c07bSMatthew G Knepley       }
195037d0c07bSMatthew G Knepley     }
19518865f1eaSKarl Rupp     if (numFields) *numFields = nF;
195237d0c07bSMatthew G Knepley     if (fieldNames) {
19539566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nF, fieldNames));
195437d0c07bSMatthew G Knepley       for (f = 0; f < nF; ++f) {
195537d0c07bSMatthew G Knepley         const char *fieldName;
195637d0c07bSMatthew G Knepley 
19579566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
19589566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(fieldName, (char **)&(*fieldNames)[f]));
195937d0c07bSMatthew G Knepley       }
196037d0c07bSMatthew G Knepley     }
196137d0c07bSMatthew G Knepley     if (fields) {
19629566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nF, fields));
196337d0c07bSMatthew G Knepley       for (f = 0; f < nF; ++f) {
19643a544194SStefano Zampini         PetscInt bs, in[2], out[2];
19653a544194SStefano Zampini 
19669566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]));
19673a544194SStefano Zampini         in[0] = -fieldNc[f];
19683a544194SStefano Zampini         in[1] = fieldNc[f];
19691c2dc1cbSBarry Smith         PetscCall(MPIU_Allreduce(in, out, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
19703a544194SStefano Zampini         bs = (-out[0] == out[1]) ? out[1] : 1;
19719566063dSJacob Faibussowitsch         PetscCall(ISSetBlockSize((*fields)[f], bs));
197237d0c07bSMatthew G Knepley       }
197337d0c07bSMatthew G Knepley     }
19749566063dSJacob Faibussowitsch     PetscCall(PetscFree3(fieldSizes, fieldNc, fieldIndices));
1975dbbe0bcdSBarry Smith   } else PetscTryTypeMethod(dm, createfieldis, numFields, fieldNames, fields);
19763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19774d343eeaSMatthew G Knepley }
19784d343eeaSMatthew G Knepley 
197916621825SDmitry Karpeev /*@C
1980bb7acecfSBarry Smith   DMCreateFieldDecomposition - Returns a list of `IS` objects defining a decomposition of a problem into subproblems
1981bb7acecfSBarry Smith                           corresponding to different fields: each `IS` contains the global indices of the dofs of the
1982bb7acecfSBarry Smith                           corresponding field, defined by `DMAddField()`. The optional list of `DM`s define the `DM` for each subproblem.
1983bb7acecfSBarry Smith                           The same as `DMCreateFieldIS()` but also returns a `DM` for each field.
1984e7c4fc90SDmitry Karpeev 
198520f4b53cSBarry Smith   Not Collective; No Fortran Support
1986e7c4fc90SDmitry Karpeev 
1987e7c4fc90SDmitry Karpeev   Input Parameter:
1988bb7acecfSBarry Smith . dm - the `DM` object
1989e7c4fc90SDmitry Karpeev 
1990e7c4fc90SDmitry Karpeev   Output Parameters:
199120f4b53cSBarry Smith + len       - The number of fields (or `NULL` if not requested)
199220f4b53cSBarry Smith . namelist  - The name for each field (or `NULL` if not requested)
199320f4b53cSBarry Smith . islist    - The global indices for each field (or `NULL` if not requested)
199420f4b53cSBarry Smith - dmlist    - The `DM`s for each field subproblem (or `NULL`, if not requested; if `NULL` is returned, no `DM`s are defined)
1995e7c4fc90SDmitry Karpeev 
1996e7c4fc90SDmitry Karpeev   Level: intermediate
1997e7c4fc90SDmitry Karpeev 
1998bb7acecfSBarry Smith   Note:
1999e7c4fc90SDmitry Karpeev   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
2000bb7acecfSBarry Smith   `PetscFree()`, every entry of is should be destroyed with `ISDestroy()`, every entry of dm should be destroyed with `DMDestroy()`,
2001bb7acecfSBarry Smith   and all of the arrays should be freed with `PetscFree()`.
2002e7c4fc90SDmitry Karpeev 
2003bb7acecfSBarry Smith   Developer Note:
2004bb7acecfSBarry Smith   It is not clear why this function and `DMCreateFieldIS()` exist. Having two seems redundant and confusing.
2005bb7acecfSBarry Smith 
2006*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMCreateFieldIS()`, `DMCreateSubDM()`, `DMCreateDomainDecomposition()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
2007e7c4fc90SDmitry Karpeev @*/
2008d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
2009d71ae5a4SJacob Faibussowitsch {
2010e7c4fc90SDmitry Karpeev   PetscFunctionBegin;
2011e7c4fc90SDmitry Karpeev   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20128865f1eaSKarl Rupp   if (len) {
2013534a8f05SLisandro Dalcin     PetscValidIntPointer(len, 2);
20148865f1eaSKarl Rupp     *len = 0;
20158865f1eaSKarl Rupp   }
20168865f1eaSKarl Rupp   if (namelist) {
20178865f1eaSKarl Rupp     PetscValidPointer(namelist, 3);
2018ea78f98cSLisandro Dalcin     *namelist = NULL;
20198865f1eaSKarl Rupp   }
20208865f1eaSKarl Rupp   if (islist) {
20218865f1eaSKarl Rupp     PetscValidPointer(islist, 4);
2022ea78f98cSLisandro Dalcin     *islist = NULL;
20238865f1eaSKarl Rupp   }
20248865f1eaSKarl Rupp   if (dmlist) {
20258865f1eaSKarl Rupp     PetscValidPointer(dmlist, 5);
2026ea78f98cSLisandro Dalcin     *dmlist = NULL;
20278865f1eaSKarl Rupp   }
2028f3f0edfdSDmitry Karpeev   /*
2029f3f0edfdSDmitry Karpeev    Is it a good idea to apply the following check across all impls?
2030f3f0edfdSDmitry Karpeev    Perhaps some impls can have a well-defined decomposition before DMSetUp?
2031f3f0edfdSDmitry Karpeev    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
2032f3f0edfdSDmitry Karpeev    */
20337a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
203416621825SDmitry Karpeev   if (!dm->ops->createfielddecomposition) {
2035435a35e8SMatthew G Knepley     PetscSection section;
2036435a35e8SMatthew G Knepley     PetscInt     numFields, f;
2037435a35e8SMatthew G Knepley 
20389566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
20399566063dSJacob Faibussowitsch     if (section) PetscCall(PetscSectionGetNumFields(section, &numFields));
2040435a35e8SMatthew G Knepley     if (section && numFields && dm->ops->createsubdm) {
2041f25d98f1SMatthew G. Knepley       if (len) *len = numFields;
20429566063dSJacob Faibussowitsch       if (namelist) PetscCall(PetscMalloc1(numFields, namelist));
20439566063dSJacob Faibussowitsch       if (islist) PetscCall(PetscMalloc1(numFields, islist));
20449566063dSJacob Faibussowitsch       if (dmlist) PetscCall(PetscMalloc1(numFields, dmlist));
2045435a35e8SMatthew G Knepley       for (f = 0; f < numFields; ++f) {
2046435a35e8SMatthew G Knepley         const char *fieldName;
2047435a35e8SMatthew G Knepley 
20489566063dSJacob Faibussowitsch         PetscCall(DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL));
204903dc3394SMatthew G. Knepley         if (namelist) {
20509566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
20519566063dSJacob Faibussowitsch           PetscCall(PetscStrallocpy(fieldName, (char **)&(*namelist)[f]));
2052435a35e8SMatthew G Knepley         }
205303dc3394SMatthew G. Knepley       }
2054435a35e8SMatthew G Knepley     } else {
20559566063dSJacob Faibussowitsch       PetscCall(DMCreateFieldIS(dm, len, namelist, islist));
2056e7c4fc90SDmitry Karpeev       /* By default there are no DMs associated with subproblems. */
20570298fd71SBarry Smith       if (dmlist) *dmlist = NULL;
2058e7c4fc90SDmitry Karpeev     }
2059dbbe0bcdSBarry Smith   } else PetscUseTypeMethod(dm, createfielddecomposition, len, namelist, islist, dmlist);
20603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
206116621825SDmitry Karpeev }
206216621825SDmitry Karpeev 
2063412a4547SAlexis Marboeuf /*@C
206420f4b53cSBarry Smith   DMCreateSubDM - Returns an `IS` and `DM` encapsulating a subproblem defined by the fields passed in.
206520f4b53cSBarry Smith                   The fields are defined by `DMCreateFieldIS()`.
2066435a35e8SMatthew G Knepley 
2067435a35e8SMatthew G Knepley   Not collective
2068435a35e8SMatthew G Knepley 
2069435a35e8SMatthew G Knepley   Input Parameters:
2070bb7acecfSBarry Smith + dm        - The `DM` object
2071bb7acecfSBarry Smith . numFields - The number of fields to select
20722adcc780SMatthew G. Knepley - fields    - The field numbers of the selected fields
2073435a35e8SMatthew G Knepley 
2074435a35e8SMatthew G Knepley   Output Parameters:
2075bb7acecfSBarry Smith + is - The global indices for all the degrees of freedom in the new sub `DM`
2076bb7acecfSBarry Smith - subdm - The `DM` for the subproblem
2077435a35e8SMatthew G Knepley 
207820f4b53cSBarry Smith   Level: intermediate
207920f4b53cSBarry Smith 
2080bb7acecfSBarry Smith   Note:
2081bb7acecfSBarry Smith   You need to call `DMPlexSetMigrationSF()` on the original `DM` if you want the Global-To-Natural map to be automatically constructed
20825d3b26e6SMatthew G. Knepley 
2083*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateFieldIS()`, `DMCreateFieldDecomposition()`, `DMAddField()`, `DMCreateSuperDM()`, `DM`, `IS`, `DMPlexSetMigrationSF()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
2084435a35e8SMatthew G Knepley @*/
2085d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
2086d71ae5a4SJacob Faibussowitsch {
2087435a35e8SMatthew G Knepley   PetscFunctionBegin;
2088435a35e8SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2089dadcf809SJacob Faibussowitsch   PetscValidIntPointer(fields, 3);
20908865f1eaSKarl Rupp   if (is) PetscValidPointer(is, 4);
20918865f1eaSKarl Rupp   if (subdm) PetscValidPointer(subdm, 5);
2092dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createsubdm, numFields, fields, is, subdm);
20933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2094435a35e8SMatthew G Knepley }
2095435a35e8SMatthew G Knepley 
20962adcc780SMatthew G. Knepley /*@C
2097bb7acecfSBarry Smith   DMCreateSuperDM - Returns an arrays of `IS` and `DM` encapsulating a superproblem defined by multiple `DM`s passed in.
20982adcc780SMatthew G. Knepley 
20992adcc780SMatthew G. Knepley   Not collective
21002adcc780SMatthew G. Knepley 
2101d8d19677SJose E. Roman   Input Parameters:
2102bb7acecfSBarry Smith + dms - The `DM` objects
2103bb7acecfSBarry Smith - n - The number of `DM`s
21042adcc780SMatthew G. Knepley 
21052adcc780SMatthew G. Knepley   Output Parameters:
2106bb7acecfSBarry Smith + is - The global indices for each of subproblem within the super `DM`, or NULL
2107bb7acecfSBarry Smith - superdm - The `DM` for the superproblem
21082adcc780SMatthew G. Knepley 
210920f4b53cSBarry Smith   Level: intermediate
211020f4b53cSBarry Smith 
2111bb7acecfSBarry Smith   Note:
2112bb7acecfSBarry Smith   You need to call `DMPlexSetMigrationSF()` on the original `DM` if you want the Global-To-Natural map to be automatically constructed
21135d3b26e6SMatthew G. Knepley 
2114*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateSubDM()`, `DMPlexSetMigrationSF()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
21152adcc780SMatthew G. Knepley @*/
2116d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt n, IS **is, DM *superdm)
2117d71ae5a4SJacob Faibussowitsch {
21182adcc780SMatthew G. Knepley   PetscInt i;
21192adcc780SMatthew G. Knepley 
21202adcc780SMatthew G. Knepley   PetscFunctionBegin;
21212adcc780SMatthew G. Knepley   PetscValidPointer(dms, 1);
2122ad540459SPierre Jolivet   for (i = 0; i < n; ++i) PetscValidHeaderSpecific(dms[i], DM_CLASSID, 1);
21232adcc780SMatthew G. Knepley   if (is) PetscValidPointer(is, 3);
2124a42bd24dSMatthew G. Knepley   PetscValidPointer(superdm, 4);
2125bb7acecfSBarry Smith   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %" PetscInt_FMT, n);
2126bb7acecfSBarry Smith   if (n) {
2127b9d85ea2SLisandro Dalcin     DM dm = dms[0];
2128dbbe0bcdSBarry Smith     PetscCall((*dm->ops->createsuperdm)(dms, n, is, superdm));
21292adcc780SMatthew G. Knepley   }
21303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21312adcc780SMatthew G. Knepley }
21322adcc780SMatthew G. Knepley 
213316621825SDmitry Karpeev /*@C
2134bb7acecfSBarry Smith   DMCreateDomainDecomposition - Returns lists of `IS` objects defining a decomposition of a problem into subproblems
2135bb7acecfSBarry Smith                           corresponding to restrictions to pairs of nested subdomains: each `IS` contains the global
2136bb7acecfSBarry Smith                           indices of the dofs of the corresponding subdomains with in the dofs of the original `DM`.
2137bb7acecfSBarry Smith                           The inner subdomains conceptually define a nonoverlapping covering, while outer subdomains can overlap.
2138bb7acecfSBarry Smith                           The optional list of `DM`s define a `DM` for each subproblem.
213916621825SDmitry Karpeev 
214020f4b53cSBarry Smith   Not Collective
214116621825SDmitry Karpeev 
214216621825SDmitry Karpeev   Input Parameter:
2143bb7acecfSBarry Smith . dm - the `DM` object
214416621825SDmitry Karpeev 
214516621825SDmitry Karpeev   Output Parameters:
214620f4b53cSBarry Smith + n           - The number of subproblems in the domain decomposition (or `NULL` if not requested)
214720f4b53cSBarry Smith . namelist    - The name for each subdomain (or `NULL` if not requested)
21480298fd71SBarry Smith . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
21490298fd71SBarry Smith . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
215020f4b53cSBarry Smith - dmlist      - The `DM`s for each subdomain subproblem (or NULL, if not requested; if `NULL` is returned, no `DM`s are defined)
215116621825SDmitry Karpeev 
215216621825SDmitry Karpeev   Level: intermediate
215316621825SDmitry Karpeev 
2154bb7acecfSBarry Smith   Note:
215516621825SDmitry Karpeev   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
2156bb7acecfSBarry Smith   `PetscFree()`, every entry of is should be destroyed with `ISDestroy()`, every entry of dm should be destroyed with `DMDestroy()`,
2157bb7acecfSBarry Smith   and all of the arrays should be freed with `PetscFree()`.
215816621825SDmitry Karpeev 
2159bb7acecfSBarry Smith   Questions:
216020f4b53cSBarry Smith   The `dmlist` is for the inner subdomains or the outer subdomains or all subdomains?
2161bb7acecfSBarry Smith 
2162*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateFieldDecomposition()`, `DMDestroy()`, `DMCreateDomainDecompositionScatters()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldDecomposition()`
216316621825SDmitry Karpeev @*/
2164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *n, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
2165d71ae5a4SJacob Faibussowitsch {
2166be081cd6SPeter Brune   DMSubDomainHookLink link;
2167be081cd6SPeter Brune   PetscInt            i, l;
216816621825SDmitry Karpeev 
216916621825SDmitry Karpeev   PetscFunctionBegin;
217016621825SDmitry Karpeev   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21719371c9d4SSatish Balay   if (n) {
21729371c9d4SSatish Balay     PetscValidIntPointer(n, 2);
21739371c9d4SSatish Balay     *n = 0;
21749371c9d4SSatish Balay   }
21759371c9d4SSatish Balay   if (namelist) {
21769371c9d4SSatish Balay     PetscValidPointer(namelist, 3);
21779371c9d4SSatish Balay     *namelist = NULL;
21789371c9d4SSatish Balay   }
21799371c9d4SSatish Balay   if (innerislist) {
21809371c9d4SSatish Balay     PetscValidPointer(innerislist, 4);
21819371c9d4SSatish Balay     *innerislist = NULL;
21829371c9d4SSatish Balay   }
21839371c9d4SSatish Balay   if (outerislist) {
21849371c9d4SSatish Balay     PetscValidPointer(outerislist, 5);
21859371c9d4SSatish Balay     *outerislist = NULL;
21869371c9d4SSatish Balay   }
21879371c9d4SSatish Balay   if (dmlist) {
21889371c9d4SSatish Balay     PetscValidPointer(dmlist, 6);
21899371c9d4SSatish Balay     *dmlist = NULL;
21909371c9d4SSatish Balay   }
2191f3f0edfdSDmitry Karpeev   /*
2192f3f0edfdSDmitry Karpeev    Is it a good idea to apply the following check across all impls?
2193f3f0edfdSDmitry Karpeev    Perhaps some impls can have a well-defined decomposition before DMSetUp?
2194f3f0edfdSDmitry Karpeev    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
2195f3f0edfdSDmitry Karpeev    */
21967a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
219716621825SDmitry Karpeev   if (dm->ops->createdomaindecomposition) {
2198dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createdomaindecomposition, &l, namelist, innerislist, outerislist, dmlist);
219914a18fd3SPeter Brune     /* copy subdomain hooks and context over to the subdomain DMs */
2200f891f5b9SPatrick Sanan     if (dmlist && *dmlist) {
2201be081cd6SPeter Brune       for (i = 0; i < l; i++) {
2202be081cd6SPeter Brune         for (link = dm->subdomainhook; link; link = link->next) {
22039566063dSJacob Faibussowitsch           if (link->ddhook) PetscCall((*link->ddhook)(dm, (*dmlist)[i], link->ctx));
2204be081cd6SPeter Brune         }
2205648262bbSPatrick Sanan         if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
2206e7c4fc90SDmitry Karpeev       }
220714a18fd3SPeter Brune     }
2208bb7acecfSBarry Smith     if (n) *n = l;
220914a18fd3SPeter Brune   }
22103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2211e30e807fSPeter Brune }
2212e30e807fSPeter Brune 
2213e30e807fSPeter Brune /*@C
2214e30e807fSPeter Brune   DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
2215e30e807fSPeter Brune 
221620f4b53cSBarry Smith   Not Collective
2217e30e807fSPeter Brune 
2218e30e807fSPeter Brune   Input Parameters:
2219bb7acecfSBarry Smith + dm - the `DM` object
2220e30e807fSPeter Brune . n  - the number of subdomain scatters
2221e30e807fSPeter Brune - subdms - the local subdomains
2222e30e807fSPeter Brune 
2223e30e807fSPeter Brune   Output Parameters:
22246b867d5aSJose E. Roman + iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
2225e30e807fSPeter Brune . oscat - scatter from global vector to overlapping global vector entries on subdomain
2226e30e807fSPeter Brune - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
2227e30e807fSPeter Brune 
222820f4b53cSBarry Smith   Level: developer
222920f4b53cSBarry Smith 
2230bb7acecfSBarry Smith   Note:
2231bb7acecfSBarry Smith     This is an alternative to the iis and ois arguments in `DMCreateDomainDecomposition()` that allow for the solution
2232e30e807fSPeter Brune   of general nonlinear problems with overlapping subdomain methods.  While merely having index sets that enable subsets
2233e30e807fSPeter Brune   of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
2234e30e807fSPeter Brune   solution and residual data.
2235e30e807fSPeter Brune 
2236bb7acecfSBarry Smith   Questions:
2237bb7acecfSBarry Smith   Can the subdms input be anything or are they exactly the `DM` obtained from `DMCreateDomainDecomposition()`?
2238bb7acecfSBarry Smith 
2239*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateDomainDecomposition()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
2240e30e807fSPeter Brune @*/
2241d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDomainDecompositionScatters(DM dm, PetscInt n, DM *subdms, VecScatter **iscat, VecScatter **oscat, VecScatter **gscat)
2242d71ae5a4SJacob Faibussowitsch {
2243e30e807fSPeter Brune   PetscFunctionBegin;
2244e30e807fSPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2245e30e807fSPeter Brune   PetscValidPointer(subdms, 3);
2246dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createddscatters, n, subdms, iscat, oscat, gscat);
22473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2248e7c4fc90SDmitry Karpeev }
2249e7c4fc90SDmitry Karpeev 
225047c6ae99SBarry Smith /*@
2251bb7acecfSBarry Smith   DMRefine - Refines a `DM` object using a standard nonadaptive refinement of the underlying mesh
225247c6ae99SBarry Smith 
225320f4b53cSBarry Smith   Collective
225447c6ae99SBarry Smith 
2255d8d19677SJose E. Roman   Input Parameters:
2256bb7acecfSBarry Smith + dm   - the `DM` object
2257bb7acecfSBarry Smith - comm - the communicator to contain the new `DM` object (or `MPI_COMM_NULL`)
225847c6ae99SBarry Smith 
225947c6ae99SBarry Smith   Output Parameter:
226020f4b53cSBarry Smith . dmf - the refined `DM`, or `NULL`
2261ae0a1c52SMatthew G Knepley 
226220f4b53cSBarry Smith   Options Database Key:
2263412e9a14SMatthew G. Knepley . -dm_plex_cell_refiner <strategy> - chooses the refinement strategy, e.g. regular, tohex
2264412e9a14SMatthew G. Knepley 
226547c6ae99SBarry Smith   Level: developer
226647c6ae99SBarry Smith 
226720f4b53cSBarry Smith   Note:
226820f4b53cSBarry Smith   If no refinement was done, the return value is `NULL`
226920f4b53cSBarry Smith 
2270*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
227147c6ae99SBarry Smith @*/
2272d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefine(DM dm, MPI_Comm comm, DM *dmf)
2273d71ae5a4SJacob Faibussowitsch {
2274c833c3b5SJed Brown   DMRefineHookLink link;
227547c6ae99SBarry Smith 
227647c6ae99SBarry Smith   PetscFunctionBegin;
2277732e2eb9SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22789566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Refine, dm, 0, 0, 0));
2279dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, refine, comm, dmf);
22804057135bSMatthew G Knepley   if (*dmf) {
228143842a1eSJed Brown     (*dmf)->ops->creatematrix = dm->ops->creatematrix;
22828865f1eaSKarl Rupp 
22839566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmf));
22848865f1eaSKarl Rupp 
2285644e2e5bSBarry Smith     (*dmf)->ctx       = dm->ctx;
22860598a293SJed Brown     (*dmf)->leveldown = dm->leveldown;
2287656b349aSBarry Smith     (*dmf)->levelup   = dm->levelup + 1;
22888865f1eaSKarl Rupp 
22899566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmf, dm->mattype));
2290c833c3b5SJed Brown     for (link = dm->refinehook; link; link = link->next) {
22911baa6e33SBarry Smith       if (link->refinehook) PetscCall((*link->refinehook)(dm, *dmf, link->ctx));
2292c833c3b5SJed Brown     }
2293c833c3b5SJed Brown   }
22949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Refine, dm, 0, 0, 0));
22953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2296c833c3b5SJed Brown }
2297c833c3b5SJed Brown 
2298bb9467b5SJed Brown /*@C
2299c833c3b5SJed Brown    DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
2300c833c3b5SJed Brown 
230120f4b53cSBarry Smith    Logically Collective; No Fortran Support
2302c833c3b5SJed Brown 
23034165533cSJose E. Roman    Input Parameters:
2304bb7acecfSBarry Smith +  coarse - `DM` on which to run a hook when interpolating to a finer level
2305bb7acecfSBarry Smith .  refinehook - function to run when setting up the finer level
2306f826b5fcSPierre Jolivet .  interphook - function to run to update data on finer levels (once per `SNESSolve()`)
230720f4b53cSBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2308c833c3b5SJed Brown 
230920f4b53cSBarry Smith    Calling sequence of `refinehook`:
231020f4b53cSBarry Smith $  PetscErrorCode refinehook(DM coarse, DM fine, void *ctx);
2311bb7acecfSBarry Smith +  coarse - coarse level `DM`
2312bb7acecfSBarry Smith .  fine - fine level `DM` to interpolate problem to
2313c833c3b5SJed Brown -  ctx - optional user-defined function context
2314c833c3b5SJed Brown 
231520f4b53cSBarry Smith    Calling sequence of `interphook`:
231620f4b53cSBarry Smith $  PetscErrorCode interphook(DM coarse, Mat interp, DM fine, void *ctx)
2317bb7acecfSBarry Smith +  coarse - coarse level `DM`
2318c833c3b5SJed Brown .  interp - matrix interpolating a coarse-level solution to the finer grid
2319bb7acecfSBarry Smith .  fine - fine level `DM` to update
2320c833c3b5SJed Brown -  ctx - optional user-defined function context
2321c833c3b5SJed Brown 
2322c833c3b5SJed Brown    Level: advanced
2323c833c3b5SJed Brown 
2324c833c3b5SJed Brown    Notes:
2325bb7acecfSBarry Smith    This function is only needed if auxiliary data that is attached to the `DM`s via, for example, `PetscObjectCompose()`, needs to be
2326bb7acecfSBarry Smith    passed to fine grids while grid sequencing.
2327bb7acecfSBarry Smith 
2328bb7acecfSBarry Smith    The actual interpolation is done when `DMInterpolate()` is called.
2329c833c3b5SJed Brown 
2330c833c3b5SJed Brown    If this function is called multiple times, the hooks will be run in the order they are added.
2331c833c3b5SJed Brown 
2332*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `DMInterpolate()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2333c833c3b5SJed Brown @*/
2334d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHookAdd(DM coarse, PetscErrorCode (*refinehook)(DM, DM, void *), PetscErrorCode (*interphook)(DM, Mat, DM, void *), void *ctx)
2335d71ae5a4SJacob Faibussowitsch {
2336c833c3b5SJed Brown   DMRefineHookLink link, *p;
2337c833c3b5SJed Brown 
2338c833c3b5SJed Brown   PetscFunctionBegin;
2339c833c3b5SJed Brown   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
23403d8e3701SJed Brown   for (p = &coarse->refinehook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
23413ba16761SJacob Faibussowitsch     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
23423d8e3701SJed Brown   }
23439566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2344c833c3b5SJed Brown   link->refinehook = refinehook;
2345c833c3b5SJed Brown   link->interphook = interphook;
2346c833c3b5SJed Brown   link->ctx        = ctx;
23470298fd71SBarry Smith   link->next       = NULL;
2348c833c3b5SJed Brown   *p               = link;
23493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2350c833c3b5SJed Brown }
2351c833c3b5SJed Brown 
23523d8e3701SJed Brown /*@C
2353bb7acecfSBarry Smith    DMRefineHookRemove - remove a callback from the list of hooks, that have been set with `DMRefineHookAdd()`, to be run when interpolating
2354bb7acecfSBarry Smith     a nonlinear problem to a finer grid
23553d8e3701SJed Brown 
235620f4b53cSBarry Smith    Logically Collective; No Fortran Support
23573d8e3701SJed Brown 
23584165533cSJose E. Roman    Input Parameters:
2359bb7acecfSBarry Smith +  coarse - the `DM` on which to run a hook when restricting to a coarser level
2360bb7acecfSBarry Smith .  refinehook - function to run when setting up a finer level
2361bb7acecfSBarry Smith .  interphook - function to run to update data on finer levels
236220f4b53cSBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be `NULL`)
23633d8e3701SJed Brown 
23643d8e3701SJed Brown    Level: advanced
23653d8e3701SJed Brown 
2366bb7acecfSBarry Smith    Note:
23673d8e3701SJed Brown    This function does nothing if the hook is not in the list.
23683d8e3701SJed Brown 
2369*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefineHookAdd()`, `DMCoarsenHookRemove()`, `DMInterpolate()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
23703d8e3701SJed Brown @*/
2371d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHookRemove(DM coarse, PetscErrorCode (*refinehook)(DM, DM, void *), PetscErrorCode (*interphook)(DM, Mat, DM, void *), void *ctx)
2372d71ae5a4SJacob Faibussowitsch {
23733d8e3701SJed Brown   DMRefineHookLink link, *p;
23743d8e3701SJed Brown 
23753d8e3701SJed Brown   PetscFunctionBegin;
23763d8e3701SJed Brown   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
23773d8e3701SJed Brown   for (p = &coarse->refinehook; *p; p = &(*p)->next) { /* Search the list of current hooks */
23783d8e3701SJed Brown     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
23793d8e3701SJed Brown       link = *p;
23803d8e3701SJed Brown       *p   = link->next;
23819566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
23823d8e3701SJed Brown       break;
23833d8e3701SJed Brown     }
23843d8e3701SJed Brown   }
23853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23863d8e3701SJed Brown }
23873d8e3701SJed Brown 
2388c833c3b5SJed Brown /*@
2389bb7acecfSBarry Smith    DMInterpolate - interpolates user-defined problem data attached to a `DM` to a finer `DM` by running hooks registered by `DMRefineHookAdd()`
2390c833c3b5SJed Brown 
2391c833c3b5SJed Brown    Collective if any hooks are
2392c833c3b5SJed Brown 
23934165533cSJose E. Roman    Input Parameters:
2394bb7acecfSBarry Smith +  coarse - coarser `DM` to use as a base
2395bb7acecfSBarry Smith .  interp - interpolation matrix, apply using `MatInterpolate()`
2396bb7acecfSBarry Smith -  fine - finer `DM` to update
2397c833c3b5SJed Brown 
2398c833c3b5SJed Brown    Level: developer
2399c833c3b5SJed Brown 
2400bb7acecfSBarry Smith    Developer Note:
2401bb7acecfSBarry Smith    This routine is called `DMInterpolate()` while the hook is called `DMRefineHookAdd()`. It would be better to have an
2402bb7acecfSBarry Smith    an API with consistent terminology.
2403bb7acecfSBarry Smith 
2404*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefineHookAdd()`, `MatInterpolate()`
2405c833c3b5SJed Brown @*/
2406d71ae5a4SJacob Faibussowitsch PetscErrorCode DMInterpolate(DM coarse, Mat interp, DM fine)
2407d71ae5a4SJacob Faibussowitsch {
2408c833c3b5SJed Brown   DMRefineHookLink link;
2409c833c3b5SJed Brown 
2410c833c3b5SJed Brown   PetscFunctionBegin;
2411c833c3b5SJed Brown   for (link = fine->refinehook; link; link = link->next) {
24121baa6e33SBarry Smith     if (link->interphook) PetscCall((*link->interphook)(coarse, interp, fine, link->ctx));
24134057135bSMatthew G Knepley   }
24143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
241547c6ae99SBarry Smith }
241647c6ae99SBarry Smith 
2417eb3f98d2SBarry Smith /*@
24181f3379b2SToby Isaac    DMInterpolateSolution - Interpolates a solution from a coarse mesh to a fine mesh.
24191f3379b2SToby Isaac 
242020f4b53cSBarry Smith    Collective
24211f3379b2SToby Isaac 
24224165533cSJose E. Roman    Input Parameters:
2423bb7acecfSBarry Smith +  coarse - coarse `DM`
2424bb7acecfSBarry Smith .  fine   - fine `DM`
2425bb7acecfSBarry Smith .  interp - (optional) the matrix computed by `DMCreateInterpolation()`.  Implementations may not need this, but if it
2426bb7acecfSBarry Smith             is available it can avoid some recomputation.  If it is provided, `MatInterpolate()` will be used if
2427bb7acecfSBarry Smith             the coarse `DM` does not have a specialized implementation.
24281f3379b2SToby Isaac -  coarseSol - solution on the coarse mesh
24291f3379b2SToby Isaac 
24304165533cSJose E. Roman    Output Parameter:
24311f3379b2SToby Isaac .  fineSol - the interpolation of coarseSol to the fine mesh
24321f3379b2SToby Isaac 
24331f3379b2SToby Isaac    Level: developer
24341f3379b2SToby Isaac 
2435bb7acecfSBarry Smith    Note:
2436bb7acecfSBarry Smith    This function exists because the interpolation of a solution vector between meshes is not always a linear
24371f3379b2SToby Isaac    map.  For example, if a boundary value problem has an inhomogeneous Dirichlet boundary condition that is compressed
24381f3379b2SToby Isaac    out of the solution vector.  Or if interpolation is inherently a nonlinear operation, such as a method using
24391f3379b2SToby Isaac    slope-limiting reconstruction.
24401f3379b2SToby Isaac 
2441bb7acecfSBarry Smith    Developer Note:
2442bb7acecfSBarry Smith    This doesn't just interpolate "solutions" so its API name is questionable.
2443bb7acecfSBarry Smith 
2444*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMInterpolate()`, `DMCreateInterpolation()`
24451f3379b2SToby Isaac @*/
2446d71ae5a4SJacob Faibussowitsch PetscErrorCode DMInterpolateSolution(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
2447d71ae5a4SJacob Faibussowitsch {
24481f3379b2SToby Isaac   PetscErrorCode (*interpsol)(DM, DM, Mat, Vec, Vec) = NULL;
24491f3379b2SToby Isaac 
24501f3379b2SToby Isaac   PetscFunctionBegin;
24511f3379b2SToby Isaac   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
24521f3379b2SToby Isaac   if (interp) PetscValidHeaderSpecific(interp, MAT_CLASSID, 3);
24531f3379b2SToby Isaac   PetscValidHeaderSpecific(coarseSol, VEC_CLASSID, 4);
24541f3379b2SToby Isaac   PetscValidHeaderSpecific(fineSol, VEC_CLASSID, 5);
24551f3379b2SToby Isaac 
24569566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)coarse, "DMInterpolateSolution_C", &interpsol));
24571f3379b2SToby Isaac   if (interpsol) {
24589566063dSJacob Faibussowitsch     PetscCall((*interpsol)(coarse, fine, interp, coarseSol, fineSol));
24591f3379b2SToby Isaac   } else if (interp) {
24609566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(interp, coarseSol, fineSol));
246198921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)coarse), PETSC_ERR_SUP, "DM %s does not implement DMInterpolateSolution()", ((PetscObject)coarse)->type_name);
24623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24631f3379b2SToby Isaac }
24641f3379b2SToby Isaac 
24651f3379b2SToby Isaac /*@
2466bb7acecfSBarry Smith     DMGetRefineLevel - Gets the number of refinements that have generated this `DM` from some initial `DM`.
2467eb3f98d2SBarry Smith 
2468eb3f98d2SBarry Smith     Not Collective
2469eb3f98d2SBarry Smith 
2470eb3f98d2SBarry Smith     Input Parameter:
2471bb7acecfSBarry Smith .   dm - the `DM` object
2472eb3f98d2SBarry Smith 
2473eb3f98d2SBarry Smith     Output Parameter:
2474eb3f98d2SBarry Smith .   level - number of refinements
2475eb3f98d2SBarry Smith 
2476eb3f98d2SBarry Smith     Level: developer
2477eb3f98d2SBarry Smith 
2478bb7acecfSBarry Smith     Note:
2479bb7acecfSBarry Smith     This can be used, by example, to set the number of coarser levels associated with this `DM` for a multigrid solver.
2480bb7acecfSBarry Smith 
2481*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
2482eb3f98d2SBarry Smith @*/
2483d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRefineLevel(DM dm, PetscInt *level)
2484d71ae5a4SJacob Faibussowitsch {
2485eb3f98d2SBarry Smith   PetscFunctionBegin;
2486eb3f98d2SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2487eb3f98d2SBarry Smith   *level = dm->levelup;
24883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2489eb3f98d2SBarry Smith }
2490eb3f98d2SBarry Smith 
2491fef3a512SBarry Smith /*@
2492bb7acecfSBarry Smith     DMSetRefineLevel - Sets the number of refinements that have generated this `DM`.
2493fef3a512SBarry Smith 
2494fef3a512SBarry Smith     Not Collective
2495fef3a512SBarry Smith 
2496d8d19677SJose E. Roman     Input Parameters:
2497bb7acecfSBarry Smith +   dm - the `DM` object
2498fef3a512SBarry Smith -   level - number of refinements
2499fef3a512SBarry Smith 
2500fef3a512SBarry Smith     Level: advanced
2501fef3a512SBarry Smith 
250295452b02SPatrick Sanan     Notes:
2503bb7acecfSBarry Smith     This value is used by `PCMG` to determine how many multigrid levels to use
2504fef3a512SBarry Smith 
2505bb7acecfSBarry Smith     The values are usually set automatically by the process that is causing the refinements of an initial `DM` by calling this routine.
2506bb7acecfSBarry Smith 
2507*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRefineLevel()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
2508fef3a512SBarry Smith @*/
2509d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRefineLevel(DM dm, PetscInt level)
2510d71ae5a4SJacob Faibussowitsch {
2511fef3a512SBarry Smith   PetscFunctionBegin;
2512fef3a512SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2513fef3a512SBarry Smith   dm->levelup = level;
25143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2515fef3a512SBarry Smith }
2516fef3a512SBarry Smith 
2517d410b0cfSMatthew G. Knepley /*@
2518bb7acecfSBarry Smith   DMExtrude - Extrude a `DM` object from a surface
2519d410b0cfSMatthew G. Knepley 
252020f4b53cSBarry Smith   Collective
2521d410b0cfSMatthew G. Knepley 
2522f1a722f8SMatthew G. Knepley   Input Parameters:
2523bb7acecfSBarry Smith + dm     - the `DM` object
2524d410b0cfSMatthew G. Knepley - layers - the number of extruded cell layers
2525d410b0cfSMatthew G. Knepley 
2526d410b0cfSMatthew G. Knepley   Output Parameter:
252720f4b53cSBarry Smith . dme - the extruded `DM`, or `NULL`
2528d410b0cfSMatthew G. Knepley 
2529d410b0cfSMatthew G. Knepley   Level: developer
2530d410b0cfSMatthew G. Knepley 
253120f4b53cSBarry Smith   Note:
253220f4b53cSBarry Smith   If no extrusion was done, the return value is `NULL`
253320f4b53cSBarry Smith 
2534*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`
2535d410b0cfSMatthew G. Knepley @*/
2536d71ae5a4SJacob Faibussowitsch PetscErrorCode DMExtrude(DM dm, PetscInt layers, DM *dme)
2537d71ae5a4SJacob Faibussowitsch {
2538d410b0cfSMatthew G. Knepley   PetscFunctionBegin;
2539d410b0cfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2540dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, extrude, layers, dme);
2541d410b0cfSMatthew G. Knepley   if (*dme) {
2542d410b0cfSMatthew G. Knepley     (*dme)->ops->creatematrix = dm->ops->creatematrix;
25439566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dme));
2544d410b0cfSMatthew G. Knepley     (*dme)->ctx = dm->ctx;
25459566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dme, dm->mattype));
2546d410b0cfSMatthew G. Knepley   }
25473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2548d410b0cfSMatthew G. Knepley }
2549d410b0cfSMatthew G. Knepley 
2550d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasisTransformDM_Internal(DM dm, DM *tdm)
2551d71ae5a4SJacob Faibussowitsch {
2552ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2553ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2554ca3d3a14SMatthew G. Knepley   PetscValidPointer(tdm, 2);
2555ca3d3a14SMatthew G. Knepley   *tdm = dm->transformDM;
25563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2557ca3d3a14SMatthew G. Knepley }
2558ca3d3a14SMatthew G. Knepley 
2559d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasisTransformVec_Internal(DM dm, Vec *tv)
2560d71ae5a4SJacob Faibussowitsch {
2561ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2562ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2563ca3d3a14SMatthew G. Knepley   PetscValidPointer(tv, 2);
2564ca3d3a14SMatthew G. Knepley   *tv = dm->transform;
25653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2566ca3d3a14SMatthew G. Knepley }
2567ca3d3a14SMatthew G. Knepley 
2568ca3d3a14SMatthew G. Knepley /*@
2569bb7acecfSBarry Smith   DMHasBasisTransform - Whether the `DM` employs a basis transformation from functions in global vectors to functions in local vectors
2570ca3d3a14SMatthew G. Knepley 
2571ca3d3a14SMatthew G. Knepley   Input Parameter:
257220f4b53cSBarry Smith . dm - The `DM`
2573ca3d3a14SMatthew G. Knepley 
2574ca3d3a14SMatthew G. Knepley   Output Parameter:
257520f4b53cSBarry Smith . flg - `PETSC_TRUE` if a basis transformation should be done
2576ca3d3a14SMatthew G. Knepley 
2577ca3d3a14SMatthew G. Knepley   Level: developer
2578ca3d3a14SMatthew G. Knepley 
2579*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPlexGlobalToLocalBasis()`, `DMPlexLocalToGlobalBasis()`, `DMPlexCreateBasisRotation()`
2580ca3d3a14SMatthew G. Knepley @*/
2581d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasBasisTransform(DM dm, PetscBool *flg)
2582d71ae5a4SJacob Faibussowitsch {
2583ca3d3a14SMatthew G. Knepley   Vec tv;
2584ca3d3a14SMatthew G. Knepley 
2585ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2586ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2587534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
25889566063dSJacob Faibussowitsch   PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
2589ca3d3a14SMatthew G. Knepley   *flg = tv ? PETSC_TRUE : PETSC_FALSE;
25903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2591ca3d3a14SMatthew G. Knepley }
2592ca3d3a14SMatthew G. Knepley 
2593d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConstructBasisTransform_Internal(DM dm)
2594d71ae5a4SJacob Faibussowitsch {
2595ca3d3a14SMatthew G. Knepley   PetscSection s, ts;
2596ca3d3a14SMatthew G. Knepley   PetscScalar *ta;
2597ca3d3a14SMatthew G. Knepley   PetscInt     cdim, pStart, pEnd, p, Nf, f, Nc, dof;
2598ca3d3a14SMatthew G. Knepley 
2599ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
26009566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
26019566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
26029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
26039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
26049566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dm->transformDM));
26059566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm->transformDM, &ts));
26069566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(ts, Nf));
26079566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(ts, pStart, pEnd));
2608ca3d3a14SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
26099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
2610ca3d3a14SMatthew G. Knepley     /* We could start to label fields by their transformation properties */
2611ca3d3a14SMatthew G. Knepley     if (Nc != cdim) continue;
2612ca3d3a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
26139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, f, &dof));
2614ca3d3a14SMatthew G. Knepley       if (!dof) continue;
26159566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(ts, p, f, PetscSqr(cdim)));
26169566063dSJacob Faibussowitsch       PetscCall(PetscSectionAddDof(ts, p, PetscSqr(cdim)));
2617ca3d3a14SMatthew G. Knepley     }
2618ca3d3a14SMatthew G. Knepley   }
26199566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(ts));
26209566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm->transformDM, &dm->transform));
26219566063dSJacob Faibussowitsch   PetscCall(VecGetArray(dm->transform, &ta));
2622ca3d3a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
2623ca3d3a14SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
26249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(ts, p, f, &dof));
2625ca3d3a14SMatthew G. Knepley       if (dof) {
2626ca3d3a14SMatthew G. Knepley         PetscReal          x[3] = {0.0, 0.0, 0.0};
2627ca3d3a14SMatthew G. Knepley         PetscScalar       *tva;
2628ca3d3a14SMatthew G. Knepley         const PetscScalar *A;
2629ca3d3a14SMatthew G. Knepley 
2630ca3d3a14SMatthew G. Knepley         /* TODO Get quadrature point for this dual basis vector for coordinate */
26319566063dSJacob Faibussowitsch         PetscCall((*dm->transformGetMatrix)(dm, x, PETSC_TRUE, &A, dm->transformCtx));
26329566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalFieldRef(dm->transformDM, p, f, ta, (void *)&tva));
26339566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(tva, A, PetscSqr(cdim)));
2634ca3d3a14SMatthew G. Knepley       }
2635ca3d3a14SMatthew G. Knepley     }
2636ca3d3a14SMatthew G. Knepley   }
26379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(dm->transform, &ta));
26383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2639ca3d3a14SMatthew G. Knepley }
2640ca3d3a14SMatthew G. Knepley 
2641d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyTransform(DM dm, DM newdm)
2642d71ae5a4SJacob Faibussowitsch {
2643ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2644ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2645ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(newdm, DM_CLASSID, 2);
2646ca3d3a14SMatthew G. Knepley   newdm->transformCtx       = dm->transformCtx;
2647ca3d3a14SMatthew G. Knepley   newdm->transformSetUp     = dm->transformSetUp;
2648ca3d3a14SMatthew G. Knepley   newdm->transformDestroy   = NULL;
2649ca3d3a14SMatthew G. Knepley   newdm->transformGetMatrix = dm->transformGetMatrix;
26509566063dSJacob Faibussowitsch   if (newdm->transformSetUp) PetscCall(DMConstructBasisTransform_Internal(newdm));
26513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2652ca3d3a14SMatthew G. Knepley }
2653ca3d3a14SMatthew G. Knepley 
2654bb9467b5SJed Brown /*@C
2655bb7acecfSBarry Smith    DMGlobalToLocalHookAdd - adds a callback to be run when `DMGlobalToLocal()` is called
2656baf369e7SPeter Brune 
265720f4b53cSBarry Smith    Logically Collective
2658baf369e7SPeter Brune 
26594165533cSJose E. Roman    Input Parameters:
2660bb7acecfSBarry Smith +  dm - the `DM`
2661bb7acecfSBarry Smith .  beginhook - function to run at the beginning of `DMGlobalToLocalBegin()`
2662bb7acecfSBarry Smith .  endhook - function to run after `DMGlobalToLocalEnd()` has completed
266320f4b53cSBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2664baf369e7SPeter Brune 
266520f4b53cSBarry Smith    Calling sequence of `beginhook`:
266620f4b53cSBarry Smith $  PetscErrorCode  beginhook(DM fine, VecScatter out, VecScatter in, DM coarse, void *ctx)
2667baf369e7SPeter Brune +  dm - global DM
2668baf369e7SPeter Brune .  g - global vector
2669baf369e7SPeter Brune .  mode - mode
2670baf369e7SPeter Brune .  l - local vector
2671baf369e7SPeter Brune -  ctx - optional user-defined function context
2672baf369e7SPeter Brune 
267320f4b53cSBarry Smith    Calling sequence of `endhook`:
267420f4b53cSBarry Smith $  PetscErrorCode  endhook(DM fine, VecScatter out, VecScatter in, DM coarse, void *ctx)
2675baf369e7SPeter Brune +  global - global DM
2676baf369e7SPeter Brune -  ctx - optional user-defined function context
2677baf369e7SPeter Brune 
2678baf369e7SPeter Brune    Level: advanced
2679baf369e7SPeter Brune 
2680bb7acecfSBarry Smith    Note:
2681bb7acecfSBarry Smith    The hook may be used to provide, for example, values that represent boundary conditions in the local vectors that do not exist on the global vector.
2682bb7acecfSBarry Smith 
2683*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGlobalToLocal()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2684baf369e7SPeter Brune @*/
2685d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalHookAdd(DM dm, PetscErrorCode (*beginhook)(DM, Vec, InsertMode, Vec, void *), PetscErrorCode (*endhook)(DM, Vec, InsertMode, Vec, void *), void *ctx)
2686d71ae5a4SJacob Faibussowitsch {
2687baf369e7SPeter Brune   DMGlobalToLocalHookLink link, *p;
2688baf369e7SPeter Brune 
2689baf369e7SPeter Brune   PetscFunctionBegin;
2690baf369e7SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2691baf369e7SPeter Brune   for (p = &dm->gtolhook; *p; p = &(*p)->next) { } /* Scan to the end of the current list of hooks */
26929566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2693baf369e7SPeter Brune   link->beginhook = beginhook;
2694baf369e7SPeter Brune   link->endhook   = endhook;
2695baf369e7SPeter Brune   link->ctx       = ctx;
26960298fd71SBarry Smith   link->next      = NULL;
2697baf369e7SPeter Brune   *p              = link;
26983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2699baf369e7SPeter Brune }
2700baf369e7SPeter Brune 
2701d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
2702d71ae5a4SJacob Faibussowitsch {
27034c274da1SToby Isaac   Mat          cMat;
270479769bd5SJed Brown   Vec          cVec, cBias;
27054c274da1SToby Isaac   PetscSection section, cSec;
27064c274da1SToby Isaac   PetscInt     pStart, pEnd, p, dof;
27074c274da1SToby Isaac 
27084c274da1SToby Isaac   PetscFunctionBegin;
27094c274da1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27109566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, &cBias));
27114c274da1SToby Isaac   if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
27125db9a05bSToby Isaac     PetscInt nRows;
27135db9a05bSToby Isaac 
27149566063dSJacob Faibussowitsch     PetscCall(MatGetSize(cMat, &nRows, NULL));
27153ba16761SJacob Faibussowitsch     if (nRows <= 0) PetscFunctionReturn(PETSC_SUCCESS);
27169566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
27179566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(cMat, NULL, &cVec));
27189566063dSJacob Faibussowitsch     PetscCall(MatMult(cMat, l, cVec));
27199566063dSJacob Faibussowitsch     if (cBias) PetscCall(VecAXPY(cVec, 1., cBias));
27209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
27214c274da1SToby Isaac     for (p = pStart; p < pEnd; p++) {
27229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
27234c274da1SToby Isaac       if (dof) {
27244c274da1SToby Isaac         PetscScalar *vals;
27259566063dSJacob Faibussowitsch         PetscCall(VecGetValuesSection(cVec, cSec, p, &vals));
27269566063dSJacob Faibussowitsch         PetscCall(VecSetValuesSection(l, section, p, vals, INSERT_ALL_VALUES));
27274c274da1SToby Isaac       }
27284c274da1SToby Isaac     }
27299566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cVec));
27304c274da1SToby Isaac   }
27313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27324c274da1SToby Isaac }
27334c274da1SToby Isaac 
273447c6ae99SBarry Smith /*@
273501729b5cSPatrick Sanan     DMGlobalToLocal - update local vectors from global vector
273601729b5cSPatrick Sanan 
273720f4b53cSBarry Smith     Neighbor-wise Collective
273801729b5cSPatrick Sanan 
273901729b5cSPatrick Sanan     Input Parameters:
2740bb7acecfSBarry Smith +   dm - the `DM` object
274101729b5cSPatrick Sanan .   g - the global vector
2742bb7acecfSBarry Smith .   mode - `INSERT_VALUES` or `ADD_VALUES`
274301729b5cSPatrick Sanan -   l - the local vector
274401729b5cSPatrick Sanan 
274520f4b53cSBarry Smith     Level: beginner
274620f4b53cSBarry Smith 
274701729b5cSPatrick Sanan     Notes:
2748bb7acecfSBarry Smith     The communication involved in this update can be overlapped with computation by instead using
2749bb7acecfSBarry Smith     `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()`.
2750bb7acecfSBarry Smith 
2751bb7acecfSBarry Smith     `DMGlobalToLocalHookAdd()` may be used to provide additional operations that are performed during the update process.
275201729b5cSPatrick Sanan 
2753*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGlobalToLocalHookAdd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`,
2754bb7acecfSBarry Smith           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`,
2755bb7acecfSBarry Smith           `DMGlobalToLocalBegin()` `DMGlobalToLocalEnd()`
275601729b5cSPatrick Sanan @*/
2757d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocal(DM dm, Vec g, InsertMode mode, Vec l)
2758d71ae5a4SJacob Faibussowitsch {
275901729b5cSPatrick Sanan   PetscFunctionBegin;
27609566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dm, g, mode, l));
27619566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dm, g, mode, l));
27623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
276301729b5cSPatrick Sanan }
276401729b5cSPatrick Sanan 
276501729b5cSPatrick Sanan /*@
276647c6ae99SBarry Smith     DMGlobalToLocalBegin - Begins updating local vectors from global vector
276747c6ae99SBarry Smith 
276820f4b53cSBarry Smith     Neighbor-wise Collective
276947c6ae99SBarry Smith 
277047c6ae99SBarry Smith     Input Parameters:
2771bb7acecfSBarry Smith +   dm - the `DM` object
277247c6ae99SBarry Smith .   g - the global vector
2773bb7acecfSBarry Smith .   mode - `INSERT_VALUES` or `ADD_VALUES`
277447c6ae99SBarry Smith -   l - the local vector
277547c6ae99SBarry Smith 
277601729b5cSPatrick Sanan     Level: intermediate
277747c6ae99SBarry Smith 
2778bb7acecfSBarry Smith     Notes:
2779bb7acecfSBarry Smith     The operation is completed with `DMGlobalToLocalEnd()`
2780bb7acecfSBarry Smith 
2781bb7acecfSBarry Smith     One can perform local computations between the `DMGlobalToLocalBegin()` and  `DMGlobalToLocalEnd()` to overlap communication and computation
2782bb7acecfSBarry Smith 
2783bb7acecfSBarry Smith     `DMGlobalToLocal()` is a short form of  `DMGlobalToLocalBegin()` and  `DMGlobalToLocalEnd()`
2784bb7acecfSBarry Smith 
2785bb7acecfSBarry Smith     `DMGlobalToLocalHookAdd()` may be used to provide additional operations that are performed during the update process.
2786bb7acecfSBarry Smith 
2787*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`
278847c6ae99SBarry Smith @*/
2789d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalBegin(DM dm, Vec g, InsertMode mode, Vec l)
2790d71ae5a4SJacob Faibussowitsch {
27917128ae9fSMatthew G Knepley   PetscSF                 sf;
2792baf369e7SPeter Brune   DMGlobalToLocalHookLink link;
279347c6ae99SBarry Smith 
279447c6ae99SBarry Smith   PetscFunctionBegin;
2795171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2796baf369e7SPeter Brune   for (link = dm->gtolhook; link; link = link->next) {
27971baa6e33SBarry Smith     if (link->beginhook) PetscCall((*link->beginhook)(dm, g, mode, l, link->ctx));
2798baf369e7SPeter Brune   }
27999566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
28007128ae9fSMatthew G Knepley   if (sf) {
2801ae5cfb4aSMatthew G. Knepley     const PetscScalar *gArray;
2802ae5cfb4aSMatthew G. Knepley     PetscScalar       *lArray;
2803d0295fc0SJunchao Zhang     PetscMemType       lmtype, gmtype;
28047128ae9fSMatthew G Knepley 
28057a8be351SBarry Smith     PetscCheck(mode != ADD_VALUES, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", (int)mode);
28069566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(l, &lArray, &lmtype));
28079566063dSJacob Faibussowitsch     PetscCall(VecGetArrayReadAndMemType(g, &gArray, &gmtype));
28089566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastWithMemTypeBegin(sf, MPIU_SCALAR, gmtype, gArray, lmtype, lArray, MPI_REPLACE));
28099566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(l, &lArray));
28109566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayReadAndMemType(g, &gArray));
28117128ae9fSMatthew G Knepley   } else {
28129566063dSJacob Faibussowitsch     PetscCall((*dm->ops->globaltolocalbegin)(dm, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l));
28137128ae9fSMatthew G Knepley   }
28143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
281547c6ae99SBarry Smith }
281647c6ae99SBarry Smith 
281747c6ae99SBarry Smith /*@
281847c6ae99SBarry Smith     DMGlobalToLocalEnd - Ends updating local vectors from global vector
281947c6ae99SBarry Smith 
282020f4b53cSBarry Smith     Neighbor-wise Collective
282147c6ae99SBarry Smith 
282247c6ae99SBarry Smith     Input Parameters:
2823bb7acecfSBarry Smith +   dm - the `DM` object
282447c6ae99SBarry Smith .   g - the global vector
2825bb7acecfSBarry Smith .   mode - `INSERT_VALUES` or `ADD_VALUES`
282647c6ae99SBarry Smith -   l - the local vector
282747c6ae99SBarry Smith 
282801729b5cSPatrick Sanan     Level: intermediate
282947c6ae99SBarry Smith 
2830bb7acecfSBarry Smith     Note:
2831bb7acecfSBarry Smith     See `DMGlobalToLocalBegin()` for details.
2832bb7acecfSBarry Smith 
2833*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`
283447c6ae99SBarry Smith @*/
2835d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
2836d71ae5a4SJacob Faibussowitsch {
28377128ae9fSMatthew G Knepley   PetscSF                 sf;
2838ae5cfb4aSMatthew G. Knepley   const PetscScalar      *gArray;
2839ae5cfb4aSMatthew G. Knepley   PetscScalar            *lArray;
2840ca3d3a14SMatthew G. Knepley   PetscBool               transform;
2841baf369e7SPeter Brune   DMGlobalToLocalHookLink link;
2842d0295fc0SJunchao Zhang   PetscMemType            lmtype, gmtype;
284347c6ae99SBarry Smith 
284447c6ae99SBarry Smith   PetscFunctionBegin;
2845171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28469566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
28479566063dSJacob Faibussowitsch   PetscCall(DMHasBasisTransform(dm, &transform));
28487128ae9fSMatthew G Knepley   if (sf) {
28497a8be351SBarry Smith     PetscCheck(mode != ADD_VALUES, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", (int)mode);
28507128ae9fSMatthew G Knepley 
28519566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(l, &lArray, &lmtype));
28529566063dSJacob Faibussowitsch     PetscCall(VecGetArrayReadAndMemType(g, &gArray, &gmtype));
28539566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray, MPI_REPLACE));
28549566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(l, &lArray));
28559566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayReadAndMemType(g, &gArray));
28569566063dSJacob Faibussowitsch     if (transform) PetscCall(DMPlexGlobalToLocalBasis(dm, l));
28577128ae9fSMatthew G Knepley   } else {
28589566063dSJacob Faibussowitsch     PetscCall((*dm->ops->globaltolocalend)(dm, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l));
28597128ae9fSMatthew G Knepley   }
28609566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalHook_Constraints(dm, g, mode, l, NULL));
2861baf369e7SPeter Brune   for (link = dm->gtolhook; link; link = link->next) {
28629566063dSJacob Faibussowitsch     if (link->endhook) PetscCall((*link->endhook)(dm, g, mode, l, link->ctx));
2863baf369e7SPeter Brune   }
28643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
286547c6ae99SBarry Smith }
286647c6ae99SBarry Smith 
2867d4d07f1eSToby Isaac /*@C
2868d4d07f1eSToby Isaac    DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
2869d4d07f1eSToby Isaac 
287020f4b53cSBarry Smith    Logically Collective
2871d4d07f1eSToby Isaac 
28724165533cSJose E. Roman    Input Parameters:
2873bb7acecfSBarry Smith +  dm - the `DM`
2874bb7acecfSBarry Smith .  beginhook - function to run at the beginning of `DMLocalToGlobalBegin()`
2875bb7acecfSBarry Smith .  endhook - function to run after `DMLocalToGlobalEnd()` has completed
287620f4b53cSBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2877d4d07f1eSToby Isaac 
287820f4b53cSBarry Smith    Calling sequence of `beginhook`:
287920f4b53cSBarry Smith $  PetscErrorCode  beginhook(DM fine, Vec l, InsertMode mode, Vec g, void *ctx)
2880bb7acecfSBarry Smith +  dm - global `DM`
2881d4d07f1eSToby Isaac .  l - local vector
2882d4d07f1eSToby Isaac .  mode - mode
2883d4d07f1eSToby Isaac .  g - global vector
2884d4d07f1eSToby Isaac -  ctx - optional user-defined function context
2885d4d07f1eSToby Isaac 
288620f4b53cSBarry Smith    Calling sequence of `endhook`:
288720f4b53cSBarry Smith $  PetscErrorCode  endhook(DM fine, Vec l, InsertMode mode, Vec g, void *ctx)
2888bb7acecfSBarry Smith +  global - global `DM`
2889d4d07f1eSToby Isaac .  l - local vector
2890d4d07f1eSToby Isaac .  mode - mode
2891d4d07f1eSToby Isaac .  g - global vector
2892d4d07f1eSToby Isaac -  ctx - optional user-defined function context
2893d4d07f1eSToby Isaac 
2894d4d07f1eSToby Isaac    Level: advanced
2895d4d07f1eSToby Isaac 
2896*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobal()`, `DMRefineHookAdd()`, `DMGlobalToLocalHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2897d4d07f1eSToby Isaac @*/
2898d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalHookAdd(DM dm, PetscErrorCode (*beginhook)(DM, Vec, InsertMode, Vec, void *), PetscErrorCode (*endhook)(DM, Vec, InsertMode, Vec, void *), void *ctx)
2899d71ae5a4SJacob Faibussowitsch {
2900d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link, *p;
2901d4d07f1eSToby Isaac 
2902d4d07f1eSToby Isaac   PetscFunctionBegin;
2903d4d07f1eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2904d4d07f1eSToby Isaac   for (p = &dm->ltoghook; *p; p = &(*p)->next) { } /* Scan to the end of the current list of hooks */
29059566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2906d4d07f1eSToby Isaac   link->beginhook = beginhook;
2907d4d07f1eSToby Isaac   link->endhook   = endhook;
2908d4d07f1eSToby Isaac   link->ctx       = ctx;
2909d4d07f1eSToby Isaac   link->next      = NULL;
2910d4d07f1eSToby Isaac   *p              = link;
29113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2912d4d07f1eSToby Isaac }
2913d4d07f1eSToby Isaac 
2914d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2915d71ae5a4SJacob Faibussowitsch {
29164c274da1SToby Isaac   Mat          cMat;
29174c274da1SToby Isaac   Vec          cVec;
29184c274da1SToby Isaac   PetscSection section, cSec;
29194c274da1SToby Isaac   PetscInt     pStart, pEnd, p, dof;
29204c274da1SToby Isaac 
29214c274da1SToby Isaac   PetscFunctionBegin;
29224c274da1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29239566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
29244c274da1SToby Isaac   if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
29255db9a05bSToby Isaac     PetscInt nRows;
29265db9a05bSToby Isaac 
29279566063dSJacob Faibussowitsch     PetscCall(MatGetSize(cMat, &nRows, NULL));
29283ba16761SJacob Faibussowitsch     if (nRows <= 0) PetscFunctionReturn(PETSC_SUCCESS);
29299566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
29309566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(cMat, NULL, &cVec));
29319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
29324c274da1SToby Isaac     for (p = pStart; p < pEnd; p++) {
29339566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
29344c274da1SToby Isaac       if (dof) {
29354c274da1SToby Isaac         PetscInt     d;
29364c274da1SToby Isaac         PetscScalar *vals;
29379566063dSJacob Faibussowitsch         PetscCall(VecGetValuesSection(l, section, p, &vals));
29389566063dSJacob Faibussowitsch         PetscCall(VecSetValuesSection(cVec, cSec, p, vals, mode));
29394c274da1SToby Isaac         /* for this to be the true transpose, we have to zero the values that
29404c274da1SToby Isaac          * we just extracted */
2941ad540459SPierre Jolivet         for (d = 0; d < dof; d++) vals[d] = 0.;
29424c274da1SToby Isaac       }
29434c274da1SToby Isaac     }
29449566063dSJacob Faibussowitsch     PetscCall(MatMultTransposeAdd(cMat, cVec, l, l));
29459566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cVec));
29464c274da1SToby Isaac   }
29473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29484c274da1SToby Isaac }
294901729b5cSPatrick Sanan /*@
295001729b5cSPatrick Sanan     DMLocalToGlobal - updates global vectors from local vectors
295101729b5cSPatrick Sanan 
295220f4b53cSBarry Smith     Neighbor-wise Collective
295301729b5cSPatrick Sanan 
295401729b5cSPatrick Sanan     Input Parameters:
2955bb7acecfSBarry Smith +   dm - the `DM` object
295601729b5cSPatrick Sanan .   l - the local vector
2957bb7acecfSBarry Smith .   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.
295801729b5cSPatrick Sanan -   g - the global vector
295901729b5cSPatrick Sanan 
296020f4b53cSBarry Smith     Level: beginner
296120f4b53cSBarry Smith 
296201729b5cSPatrick Sanan     Notes:
296301729b5cSPatrick Sanan     The communication involved in this update can be overlapped with computation by using
2964bb7acecfSBarry Smith     `DMLocalToGlobalBegin()` and `DMLocalToGlobalEnd()`.
296501729b5cSPatrick Sanan 
2966bb7acecfSBarry Smith     In the `ADD_VALUES` case you normally would zero the receiving vector before beginning this operation.
2967bb7acecfSBarry Smith 
2968bb7acecfSBarry Smith     `INSERT_VALUES` is not supported for `DMDA`; in that case simply compute the values directly into a global vector instead of a local one.
2969bb7acecfSBarry Smith 
2970bb7acecfSBarry Smith     Use `DMLocalToGlobalHookAdd()` to add additional operations that are performed on the data during the update process
297101729b5cSPatrick Sanan 
2972*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalBegin()`, `DMLocalToGlobalHookAdd()`, `DMGlobaToLocallHookAdd()`
297301729b5cSPatrick Sanan @*/
2974d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobal(DM dm, Vec l, InsertMode mode, Vec g)
2975d71ae5a4SJacob Faibussowitsch {
297601729b5cSPatrick Sanan   PetscFunctionBegin;
29779566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, l, mode, g));
29789566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, l, mode, g));
29793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
298001729b5cSPatrick Sanan }
29814c274da1SToby Isaac 
298247c6ae99SBarry Smith /*@
298301729b5cSPatrick Sanan     DMLocalToGlobalBegin - begins updating global vectors from local vectors
29849a42bb27SBarry Smith 
298520f4b53cSBarry Smith     Neighbor-wise Collective
29869a42bb27SBarry Smith 
29879a42bb27SBarry Smith     Input Parameters:
2988bb7acecfSBarry Smith +   dm - the `DM` object
2989f6813fd5SJed Brown .   l - the local vector
2990aa624791SPierre Jolivet .   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.
29911eb28f2eSBarry Smith -   g - the global vector
29929a42bb27SBarry Smith 
299320f4b53cSBarry Smith     Level: intermediate
299420f4b53cSBarry Smith 
299595452b02SPatrick Sanan     Notes:
2996bb7acecfSBarry Smith     In the `ADD_VALUES` case you normally would zero the receiving vector before beginning this operation.
2997bb7acecfSBarry Smith 
2998bb7acecfSBarry Smith     `INSERT_VALUES is` not supported for `DMDA`, in that case simply compute the values directly into a global vector instead of a local one.
2999bb7acecfSBarry Smith 
3000bb7acecfSBarry Smith     Use `DMLocalToGlobalEnd()` to complete the communication process.
3001bb7acecfSBarry Smith 
3002bb7acecfSBarry Smith     `DMLocalToGlobal()` is a short form of  `DMLocalToGlobalBegin()` and  `DMLocalToGlobalEnd()`
3003bb7acecfSBarry Smith 
3004bb7acecfSBarry Smith     `DMLocalToGlobalHookAdd()` may be used to provide additional operations that are performed during the update process.
30059a42bb27SBarry Smith 
3006*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalBegin()`
30079a42bb27SBarry Smith @*/
3008d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalBegin(DM dm, Vec l, InsertMode mode, Vec g)
3009d71ae5a4SJacob Faibussowitsch {
30107128ae9fSMatthew G Knepley   PetscSF                 sf;
301184330215SMatthew G. Knepley   PetscSection            s, gs;
3012d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link;
3013ca3d3a14SMatthew G. Knepley   Vec                     tmpl;
3014ae5cfb4aSMatthew G. Knepley   const PetscScalar      *lArray;
3015ae5cfb4aSMatthew G. Knepley   PetscScalar            *gArray;
3016fa88e482SJed Brown   PetscBool               isInsert, transform, l_inplace = PETSC_FALSE, g_inplace = PETSC_FALSE;
3017d0295fc0SJunchao Zhang   PetscMemType            lmtype = PETSC_MEMTYPE_HOST, gmtype = PETSC_MEMTYPE_HOST;
30189a42bb27SBarry Smith 
30199a42bb27SBarry Smith   PetscFunctionBegin;
3020171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3021d4d07f1eSToby Isaac   for (link = dm->ltoghook; link; link = link->next) {
30221baa6e33SBarry Smith     if (link->beginhook) PetscCall((*link->beginhook)(dm, l, mode, g, link->ctx));
3023d4d07f1eSToby Isaac   }
30249566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalHook_Constraints(dm, l, mode, g, NULL));
30259566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
30269566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
30277128ae9fSMatthew G Knepley   switch (mode) {
30287128ae9fSMatthew G Knepley   case INSERT_VALUES:
30297128ae9fSMatthew G Knepley   case INSERT_ALL_VALUES:
3030d71ae5a4SJacob Faibussowitsch   case INSERT_BC_VALUES:
3031d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_TRUE;
3032d71ae5a4SJacob Faibussowitsch     break;
30337128ae9fSMatthew G Knepley   case ADD_VALUES:
30347128ae9fSMatthew G Knepley   case ADD_ALL_VALUES:
3035d71ae5a4SJacob Faibussowitsch   case ADD_BC_VALUES:
3036d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_FALSE;
3037d71ae5a4SJacob Faibussowitsch     break;
3038d71ae5a4SJacob Faibussowitsch   default:
3039d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", mode);
30407128ae9fSMatthew G Knepley   }
3041ca3d3a14SMatthew G. Knepley   if ((sf && !isInsert) || (s && isInsert)) {
30429566063dSJacob Faibussowitsch     PetscCall(DMHasBasisTransform(dm, &transform));
3043ca3d3a14SMatthew G. Knepley     if (transform) {
30449566063dSJacob Faibussowitsch       PetscCall(DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
30459566063dSJacob Faibussowitsch       PetscCall(VecCopy(l, tmpl));
30469566063dSJacob Faibussowitsch       PetscCall(DMPlexLocalToGlobalBasis(dm, tmpl));
30479566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tmpl, &lArray));
3048fa88e482SJed Brown     } else if (isInsert) {
30499566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(l, &lArray));
3050fa88e482SJed Brown     } else {
30519566063dSJacob Faibussowitsch       PetscCall(VecGetArrayReadAndMemType(l, &lArray, &lmtype));
3052fa88e482SJed Brown       l_inplace = PETSC_TRUE;
3053ca3d3a14SMatthew G. Knepley     }
3054fa88e482SJed Brown     if (s && isInsert) {
30559566063dSJacob Faibussowitsch       PetscCall(VecGetArray(g, &gArray));
3056fa88e482SJed Brown     } else {
30579566063dSJacob Faibussowitsch       PetscCall(VecGetArrayAndMemType(g, &gArray, &gmtype));
3058fa88e482SJed Brown       g_inplace = PETSC_TRUE;
3059fa88e482SJed Brown     }
3060ca3d3a14SMatthew G. Knepley     if (sf && !isInsert) {
30619566063dSJacob Faibussowitsch       PetscCall(PetscSFReduceWithMemTypeBegin(sf, MPIU_SCALAR, lmtype, lArray, gmtype, gArray, MPIU_SUM));
306284330215SMatthew G. Knepley     } else if (s && isInsert) {
306384330215SMatthew G. Knepley       PetscInt gStart, pStart, pEnd, p;
306484330215SMatthew G. Knepley 
30659566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gs));
30669566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
30679566063dSJacob Faibussowitsch       PetscCall(VecGetOwnershipRange(g, &gStart, NULL));
306884330215SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
3069b3b16f48SMatthew G. Knepley         PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
307084330215SMatthew G. Knepley 
30719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(s, p, &dof));
30729566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(gs, p, &gdof));
30739566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
30749566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(gs, p, &gcdof));
30759566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(s, p, &off));
30769566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(gs, p, &goff));
3077b3b16f48SMatthew G. Knepley         /* Ignore off-process data and points with no global data */
307803442857SMatthew G. Knepley         if (!gdof || goff < 0) continue;
30797a8be351SBarry Smith         PetscCheck(dof == gdof, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %" PetscInt_FMT " dof: %" PetscInt_FMT " gdof: %" PetscInt_FMT " cdof: %" PetscInt_FMT " gcdof: %" PetscInt_FMT, p, dof, gdof, cdof, gcdof);
3080b3b16f48SMatthew G. Knepley         /* If no constraints are enforced in the global vector */
3081b3b16f48SMatthew G. Knepley         if (!gcdof) {
308284330215SMatthew G. Knepley           for (d = 0; d < dof; ++d) gArray[goff - gStart + d] = lArray[off + d];
3083b3b16f48SMatthew G. Knepley           /* If constraints are enforced in the global vector */
3084b3b16f48SMatthew G. Knepley         } else if (cdof == gcdof) {
308584330215SMatthew G. Knepley           const PetscInt *cdofs;
308684330215SMatthew G. Knepley           PetscInt        cind = 0;
308784330215SMatthew G. Knepley 
30889566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetConstraintIndices(s, p, &cdofs));
3089b3b16f48SMatthew G. Knepley           for (d = 0, e = 0; d < dof; ++d) {
30909371c9d4SSatish Balay             if ((cind < cdof) && (d == cdofs[cind])) {
30919371c9d4SSatish Balay               ++cind;
30929371c9d4SSatish Balay               continue;
30939371c9d4SSatish Balay             }
3094b3b16f48SMatthew G. Knepley             gArray[goff - gStart + e++] = lArray[off + d];
309584330215SMatthew G. Knepley           }
30967a8be351SBarry Smith         } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %" PetscInt_FMT " dof: %" PetscInt_FMT " gdof: %" PetscInt_FMT " cdof: %" PetscInt_FMT " gcdof: %" PetscInt_FMT, p, dof, gdof, cdof, gcdof);
309784330215SMatthew G. Knepley       }
3098ca3d3a14SMatthew G. Knepley     }
3099fa88e482SJed Brown     if (g_inplace) {
31009566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayAndMemType(g, &gArray));
3101fa88e482SJed Brown     } else {
31029566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(g, &gArray));
3103fa88e482SJed Brown     }
3104ca3d3a14SMatthew G. Knepley     if (transform) {
31059566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tmpl, &lArray));
31069566063dSJacob Faibussowitsch       PetscCall(DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
3107fa88e482SJed Brown     } else if (l_inplace) {
31089566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayReadAndMemType(l, &lArray));
3109ca3d3a14SMatthew G. Knepley     } else {
31109566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(l, &lArray));
3111ca3d3a14SMatthew G. Knepley     }
31127128ae9fSMatthew G Knepley   } else {
31139566063dSJacob Faibussowitsch     PetscCall((*dm->ops->localtoglobalbegin)(dm, l, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), g));
31147128ae9fSMatthew G Knepley   }
31153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31169a42bb27SBarry Smith }
31179a42bb27SBarry Smith 
31189a42bb27SBarry Smith /*@
31199a42bb27SBarry Smith     DMLocalToGlobalEnd - updates global vectors from local vectors
312047c6ae99SBarry Smith 
312120f4b53cSBarry Smith     Neighbor-wise Collective
312247c6ae99SBarry Smith 
312347c6ae99SBarry Smith     Input Parameters:
3124bb7acecfSBarry Smith +   dm - the `DM` object
3125f6813fd5SJed Brown .   l - the local vector
3126bb7acecfSBarry Smith .   mode - `INSERT_VALUES` or `ADD_VALUES`
3127f6813fd5SJed Brown -   g - the global vector
312847c6ae99SBarry Smith 
312901729b5cSPatrick Sanan     Level: intermediate
313047c6ae99SBarry Smith 
3131bb7acecfSBarry Smith     Note:
3132bb7acecfSBarry Smith     See `DMLocalToGlobalBegin()` for full details
3133bb7acecfSBarry Smith 
3134*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalEnd()`
313547c6ae99SBarry Smith @*/
3136d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalEnd(DM dm, Vec l, InsertMode mode, Vec g)
3137d71ae5a4SJacob Faibussowitsch {
31387128ae9fSMatthew G Knepley   PetscSF                 sf;
313984330215SMatthew G. Knepley   PetscSection            s;
3140d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link;
3141ca3d3a14SMatthew G. Knepley   PetscBool               isInsert, transform;
314247c6ae99SBarry Smith 
314347c6ae99SBarry Smith   PetscFunctionBegin;
3144171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31459566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
31469566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
31477128ae9fSMatthew G Knepley   switch (mode) {
31487128ae9fSMatthew G Knepley   case INSERT_VALUES:
3149d71ae5a4SJacob Faibussowitsch   case INSERT_ALL_VALUES:
3150d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_TRUE;
3151d71ae5a4SJacob Faibussowitsch     break;
31527128ae9fSMatthew G Knepley   case ADD_VALUES:
3153d71ae5a4SJacob Faibussowitsch   case ADD_ALL_VALUES:
3154d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_FALSE;
3155d71ae5a4SJacob Faibussowitsch     break;
3156d71ae5a4SJacob Faibussowitsch   default:
3157d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", mode);
31587128ae9fSMatthew G Knepley   }
315984330215SMatthew G. Knepley   if (sf && !isInsert) {
3160ae5cfb4aSMatthew G. Knepley     const PetscScalar *lArray;
3161ae5cfb4aSMatthew G. Knepley     PetscScalar       *gArray;
3162ca3d3a14SMatthew G. Knepley     Vec                tmpl;
316384330215SMatthew G. Knepley 
31649566063dSJacob Faibussowitsch     PetscCall(DMHasBasisTransform(dm, &transform));
3165ca3d3a14SMatthew G. Knepley     if (transform) {
31669566063dSJacob Faibussowitsch       PetscCall(DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
31679566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tmpl, &lArray));
3168ca3d3a14SMatthew G. Knepley     } else {
31699566063dSJacob Faibussowitsch       PetscCall(VecGetArrayReadAndMemType(l, &lArray, NULL));
3170ca3d3a14SMatthew G. Knepley     }
31719566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(g, &gArray, NULL));
31729566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM));
3173ca3d3a14SMatthew G. Knepley     if (transform) {
31749566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tmpl, &lArray));
31759566063dSJacob Faibussowitsch       PetscCall(DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
3176ca3d3a14SMatthew G. Knepley     } else {
31779566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayReadAndMemType(l, &lArray));
3178ca3d3a14SMatthew G. Knepley     }
31799566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(g, &gArray));
318084330215SMatthew G. Knepley   } else if (s && isInsert) {
31817128ae9fSMatthew G Knepley   } else {
31829566063dSJacob Faibussowitsch     PetscCall((*dm->ops->localtoglobalend)(dm, l, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), g));
31837128ae9fSMatthew G Knepley   }
3184d4d07f1eSToby Isaac   for (link = dm->ltoghook; link; link = link->next) {
31859566063dSJacob Faibussowitsch     if (link->endhook) PetscCall((*link->endhook)(dm, g, mode, l, link->ctx));
3186d4d07f1eSToby Isaac   }
31873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
318847c6ae99SBarry Smith }
318947c6ae99SBarry Smith 
3190f089877aSRichard Tran Mills /*@
3191bb7acecfSBarry Smith    DMLocalToLocalBegin - Begins the process of mapping values from a local vector (that include ghost points
3192bc0a1609SRichard Tran Mills    that contain irrelevant values) to another local vector where the ghost
3193bb7acecfSBarry Smith    points in the second are set correctly from values on other MPI ranks. Must be followed by `DMLocalToLocalEnd()`.
3194f089877aSRichard Tran Mills 
319520f4b53cSBarry Smith    Neighbor-wise Collective
3196f089877aSRichard Tran Mills 
3197f089877aSRichard Tran Mills    Input Parameters:
3198bb7acecfSBarry Smith +  dm - the `DM` object
3199bc0a1609SRichard Tran Mills .  g - the original local vector
3200bb7acecfSBarry Smith -  mode - one of `INSERT_VALUES` or `ADD_VALUES`
3201f089877aSRichard Tran Mills 
3202bc0a1609SRichard Tran Mills    Output Parameter:
3203bc0a1609SRichard Tran Mills .  l  - the local vector with correct ghost values
3204f089877aSRichard Tran Mills 
3205f089877aSRichard Tran Mills    Level: intermediate
3206f089877aSRichard Tran Mills 
3207*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToLocalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMLocalToLocalEnd()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3208f089877aSRichard Tran Mills @*/
3209d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalBegin(DM dm, Vec g, InsertMode mode, Vec l)
3210d71ae5a4SJacob Faibussowitsch {
3211f089877aSRichard Tran Mills   PetscFunctionBegin;
3212f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32139f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
32149f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(l, VEC_CLASSID, 4);
32159f4ada15SMatthew G. Knepley   PetscUseTypeMethod(dm, localtolocalbegin, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
32163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3217f089877aSRichard Tran Mills }
3218f089877aSRichard Tran Mills 
3219f089877aSRichard Tran Mills /*@
3220bb7acecfSBarry Smith    DMLocalToLocalEnd - Maps from a local vector to another local vector where the ghost
3221bb7acecfSBarry Smith    points in the second are set correctly. Must be preceded by `DMLocalToLocalBegin()`.
3222f089877aSRichard Tran Mills 
322320f4b53cSBarry Smith    Neighbor-wise Collective
3224f089877aSRichard Tran Mills 
3225f089877aSRichard Tran Mills    Input Parameters:
3226bb7acecfSBarry Smith +  da - the `DM` object
3227bc0a1609SRichard Tran Mills .  g - the original local vector
3228bb7acecfSBarry Smith -  mode - one of `INSERT_VALUES` or `ADD_VALUES`
3229f089877aSRichard Tran Mills 
3230bc0a1609SRichard Tran Mills    Output Parameter:
3231bc0a1609SRichard Tran Mills .  l  - the local vector with correct ghost values
3232f089877aSRichard Tran Mills 
3233f089877aSRichard Tran Mills    Level: intermediate
3234f089877aSRichard Tran Mills 
3235*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToLocalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMLocalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3236f089877aSRichard Tran Mills @*/
3237d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
3238d71ae5a4SJacob Faibussowitsch {
3239f089877aSRichard Tran Mills   PetscFunctionBegin;
3240f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32419f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
32429f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(l, VEC_CLASSID, 4);
32439f4ada15SMatthew G. Knepley   PetscUseTypeMethod(dm, localtolocalend, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
32443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3245f089877aSRichard Tran Mills }
3246f089877aSRichard Tran Mills 
324747c6ae99SBarry Smith /*@
3248bb7acecfSBarry Smith     DMCoarsen - Coarsens a `DM` object using a standard, non-adaptive coarsening of the underlying mesh
324947c6ae99SBarry Smith 
325020f4b53cSBarry Smith     Collective
325147c6ae99SBarry Smith 
3252d8d19677SJose E. Roman     Input Parameters:
3253bb7acecfSBarry Smith +   dm - the `DM` object
325420f4b53cSBarry Smith -   comm - the communicator to contain the new `DM` object (or `MPI_COMM_NULL`)
325547c6ae99SBarry Smith 
325647c6ae99SBarry Smith     Output Parameter:
3257bb7acecfSBarry Smith .   dmc - the coarsened `DM`
325847c6ae99SBarry Smith 
325947c6ae99SBarry Smith     Level: developer
326047c6ae99SBarry Smith 
3261*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
326247c6ae99SBarry Smith @*/
3263d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
3264d71ae5a4SJacob Faibussowitsch {
3265b17ce1afSJed Brown   DMCoarsenHookLink link;
326647c6ae99SBarry Smith 
326747c6ae99SBarry Smith   PetscFunctionBegin;
3268171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32699566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Coarsen, dm, 0, 0, 0));
3270dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, coarsen, comm, dmc);
3271b9d85ea2SLisandro Dalcin   if (*dmc) {
3272a3574896SRichard Tran Mills     (*dmc)->bind_below = dm->bind_below; /* Propagate this from parent DM; otherwise -dm_bind_below will be useless for multigrid cases. */
32739566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dm, *dmc));
327443842a1eSJed Brown     (*dmc)->ops->creatematrix = dm->ops->creatematrix;
32759566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmc));
3276644e2e5bSBarry Smith     (*dmc)->ctx       = dm->ctx;
32770598a293SJed Brown     (*dmc)->levelup   = dm->levelup;
3278656b349aSBarry Smith     (*dmc)->leveldown = dm->leveldown + 1;
32799566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmc, dm->mattype));
3280b17ce1afSJed Brown     for (link = dm->coarsenhook; link; link = link->next) {
32819566063dSJacob Faibussowitsch       if (link->coarsenhook) PetscCall((*link->coarsenhook)(dm, *dmc, link->ctx));
3282b17ce1afSJed Brown     }
3283b9d85ea2SLisandro Dalcin   }
32849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Coarsen, dm, 0, 0, 0));
32857a8be351SBarry Smith   PetscCheck(*dmc, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
32863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3287b17ce1afSJed Brown }
3288b17ce1afSJed Brown 
3289bb9467b5SJed Brown /*@C
3290b17ce1afSJed Brown    DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
3291b17ce1afSJed Brown 
329220f4b53cSBarry Smith    Logically Collective; No Fortran Support
3293b17ce1afSJed Brown 
32944165533cSJose E. Roman    Input Parameters:
3295bb7acecfSBarry Smith +  fine - `DM` on which to run a hook when restricting to a coarser level
3296b17ce1afSJed Brown .  coarsenhook - function to run when setting up a coarser level
3297bb7acecfSBarry Smith .  restricthook - function to run to update data on coarser levels (called once per `SNESSolve()`)
329820f4b53cSBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3299b17ce1afSJed Brown 
330020f4b53cSBarry Smith    Calling sequence of `coarsenhook`:
330120f4b53cSBarry Smith $  PetscErrorCode  coarsenhook(DM fine, DM coarse, void *ctx);
3302bb7acecfSBarry Smith +  fine - fine level `DM`
3303bb7acecfSBarry Smith .  coarse - coarse level `DM` to restrict problem to
3304b17ce1afSJed Brown -  ctx - optional user-defined function context
3305b17ce1afSJed Brown 
330620f4b53cSBarry Smith    Calling sequence of `restricthook`:
330720f4b53cSBarry Smith $  PetscErrorCode  restricthook(DM fine, Mat mrestrict, Vec rscale, Mat inject, DM coarse, void *ctx)
3308bb7acecfSBarry Smith +  fine - fine level `DM`
3309bb7acecfSBarry Smith .  mrestrict - matrix restricting a fine-level solution to the coarse grid, usually the transpose of the interpolation
3310c833c3b5SJed Brown .  rscale - scaling vector for restriction
3311c833c3b5SJed Brown .  inject - matrix restricting by injection
3312b17ce1afSJed Brown .  coarse - coarse level DM to update
3313b17ce1afSJed Brown -  ctx - optional user-defined function context
3314b17ce1afSJed Brown 
3315b17ce1afSJed Brown    Level: advanced
3316b17ce1afSJed Brown 
3317b17ce1afSJed Brown    Notes:
3318bb7acecfSBarry Smith    This function is only needed if auxiliary data, attached to the `DM` with `PetscObjectCompose()`, needs to be set up or passed from the fine `DM` to the coarse `DM`.
3319b17ce1afSJed Brown 
3320b17ce1afSJed Brown    If this function is called multiple times, the hooks will be run in the order they are added.
3321b17ce1afSJed Brown 
3322b17ce1afSJed Brown    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3323bb7acecfSBarry Smith    extract the finest level information from its context (instead of from the `SNES`).
3324b17ce1afSJed Brown 
3325bb7acecfSBarry Smith    The hooks are automatically called by `DMRestrict()`
3326bb7acecfSBarry Smith 
3327*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3328b17ce1afSJed Brown @*/
3329d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHookAdd(DM fine, PetscErrorCode (*coarsenhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, Mat, Vec, Mat, DM, void *), void *ctx)
3330d71ae5a4SJacob Faibussowitsch {
3331b17ce1afSJed Brown   DMCoarsenHookLink link, *p;
3332b17ce1afSJed Brown 
3333b17ce1afSJed Brown   PetscFunctionBegin;
3334b17ce1afSJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
33351e3d8eccSJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
33363ba16761SJacob Faibussowitsch     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
33371e3d8eccSJed Brown   }
33389566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
3339b17ce1afSJed Brown   link->coarsenhook  = coarsenhook;
3340b17ce1afSJed Brown   link->restricthook = restricthook;
3341b17ce1afSJed Brown   link->ctx          = ctx;
33420298fd71SBarry Smith   link->next         = NULL;
3343b17ce1afSJed Brown   *p                 = link;
33443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3345b17ce1afSJed Brown }
3346b17ce1afSJed Brown 
3347dc822a44SJed Brown /*@C
3348bb7acecfSBarry Smith    DMCoarsenHookRemove - remove a callback set with `DMCoarsenHookAdd()`
3349dc822a44SJed Brown 
335020f4b53cSBarry Smith    Logically Collective; No Fortran Support
3351dc822a44SJed Brown 
33524165533cSJose E. Roman    Input Parameters:
3353bb7acecfSBarry Smith +  fine - `DM` on which to run a hook when restricting to a coarser level
3354dc822a44SJed Brown .  coarsenhook - function to run when setting up a coarser level
3355bb7acecfSBarry Smith .  restricthook - function to run to update data on coarser levels
335620f4b53cSBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3357dc822a44SJed Brown 
3358dc822a44SJed Brown    Level: advanced
3359dc822a44SJed Brown 
3360bb7acecfSBarry Smith    Note:
3361dc822a44SJed Brown    This function does nothing if the hook is not in the list.
3362dc822a44SJed Brown 
3363*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3364dc822a44SJed Brown @*/
3365d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHookRemove(DM fine, PetscErrorCode (*coarsenhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, Mat, Vec, Mat, DM, void *), void *ctx)
3366d71ae5a4SJacob Faibussowitsch {
3367dc822a44SJed Brown   DMCoarsenHookLink link, *p;
3368dc822a44SJed Brown 
3369dc822a44SJed Brown   PetscFunctionBegin;
3370dc822a44SJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
3371dc822a44SJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3372dc822a44SJed Brown     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3373dc822a44SJed Brown       link = *p;
3374dc822a44SJed Brown       *p   = link->next;
33759566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3376dc822a44SJed Brown       break;
3377dc822a44SJed Brown     }
3378dc822a44SJed Brown   }
33793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3380dc822a44SJed Brown }
3381dc822a44SJed Brown 
3382b17ce1afSJed Brown /*@
3383bb7acecfSBarry Smith    DMRestrict - restricts user-defined problem data to a coarser `DM` by running hooks registered by `DMCoarsenHookAdd()`
3384b17ce1afSJed Brown 
3385b17ce1afSJed Brown    Collective if any hooks are
3386b17ce1afSJed Brown 
33874165533cSJose E. Roman    Input Parameters:
3388bb7acecfSBarry Smith +  fine - finer `DM` from which the data is obtained
3389bb7acecfSBarry Smith .  restrct - restriction matrix, apply using `MatRestrict()`, usually the transpose of the interpolation
3390e91eccc2SStefano Zampini .  rscale - scaling vector for restriction
3391bb7acecfSBarry Smith .  inject - injection matrix, also use `MatRestrict()`
339220f4b53cSBarry Smith -  coarse - coarser `DM` to update
3393b17ce1afSJed Brown 
3394b17ce1afSJed Brown    Level: developer
3395b17ce1afSJed Brown 
3396bb7acecfSBarry Smith    Developer Note:
3397bb7acecfSBarry Smith    Though this routine is called `DMRestrict()` the hooks are added with `DMCoarsenHookAdd()`, a consistent terminology would be better
3398bb7acecfSBarry Smith 
3399*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `MatRestrict()`, `DMInterpolate()`, `DMRefineHookAdd()`
3400b17ce1afSJed Brown @*/
3401d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestrict(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse)
3402d71ae5a4SJacob Faibussowitsch {
3403b17ce1afSJed Brown   DMCoarsenHookLink link;
3404b17ce1afSJed Brown 
3405b17ce1afSJed Brown   PetscFunctionBegin;
3406b17ce1afSJed Brown   for (link = fine->coarsenhook; link; link = link->next) {
34071baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(fine, restrct, rscale, inject, coarse, link->ctx));
3408b17ce1afSJed Brown   }
34093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
341047c6ae99SBarry Smith }
341147c6ae99SBarry Smith 
3412bb9467b5SJed Brown /*@C
3413be081cd6SPeter Brune    DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
34145dbd56e3SPeter Brune 
341520f4b53cSBarry Smith    Logically Collective; No Fortran Support
34165dbd56e3SPeter Brune 
34174165533cSJose E. Roman    Input Parameters:
3418bb7acecfSBarry Smith +  global - global `DM`
3419bb7acecfSBarry Smith .  ddhook - function to run to pass data to the decomposition `DM` upon its creation
34205dbd56e3SPeter Brune .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
342120f4b53cSBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be `NULL`)
34225dbd56e3SPeter Brune 
342320f4b53cSBarry Smith    Calling sequence of `ddhook`:
342420f4b53cSBarry Smith $  PetscErrorCode ddhook(DM global, DM block, void *ctx)
3425bb7acecfSBarry Smith +  global - global `DM`
3426bb7acecfSBarry Smith .  block  - block `DM`
3427ec4806b8SPeter Brune -  ctx - optional user-defined function context
3428ec4806b8SPeter Brune 
342920f4b53cSBarry Smith    Calling sequence of `restricthook`:
343020f4b53cSBarry Smith $  PetscErrorCode restricthook(DM global, VecScatter out, VecScatter in, DM block, void *ctx)
3431bb7acecfSBarry Smith +  global - global `DM`
34325dbd56e3SPeter Brune .  out    - scatter to the outer (with ghost and overlap points) block vector
34335dbd56e3SPeter Brune .  in     - scatter to block vector values only owned locally
3434bb7acecfSBarry Smith .  block  - block `DM`
34355dbd56e3SPeter Brune -  ctx - optional user-defined function context
34365dbd56e3SPeter Brune 
34375dbd56e3SPeter Brune    Level: advanced
34385dbd56e3SPeter Brune 
34395dbd56e3SPeter Brune    Notes:
3440bb7acecfSBarry Smith    This function is only needed if auxiliary data needs to be set up on subdomain `DM`s.
34415dbd56e3SPeter Brune 
34425dbd56e3SPeter Brune    If this function is called multiple times, the hooks will be run in the order they are added.
34435dbd56e3SPeter Brune 
34445dbd56e3SPeter Brune    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3445bb7acecfSBarry Smith    extract the global information from its context (instead of from the `SNES`).
34465dbd56e3SPeter Brune 
3447*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSubDomainHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
34485dbd56e3SPeter Brune @*/
3449d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainHookAdd(DM global, PetscErrorCode (*ddhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, VecScatter, VecScatter, DM, void *), void *ctx)
3450d71ae5a4SJacob Faibussowitsch {
3451be081cd6SPeter Brune   DMSubDomainHookLink link, *p;
34525dbd56e3SPeter Brune 
34535dbd56e3SPeter Brune   PetscFunctionBegin;
34545dbd56e3SPeter Brune   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3455b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
34563ba16761SJacob Faibussowitsch     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
3457b3a6b972SJed Brown   }
34589566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
34595dbd56e3SPeter Brune   link->restricthook = restricthook;
3460be081cd6SPeter Brune   link->ddhook       = ddhook;
34615dbd56e3SPeter Brune   link->ctx          = ctx;
34620298fd71SBarry Smith   link->next         = NULL;
34635dbd56e3SPeter Brune   *p                 = link;
34643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34655dbd56e3SPeter Brune }
34665dbd56e3SPeter Brune 
3467b3a6b972SJed Brown /*@C
3468b3a6b972SJed Brown    DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid
3469b3a6b972SJed Brown 
347020f4b53cSBarry Smith    Logically Collective; No Fortran Support
3471b3a6b972SJed Brown 
34724165533cSJose E. Roman    Input Parameters:
3473bb7acecfSBarry Smith +  global - global `DM`
3474bb7acecfSBarry Smith .  ddhook - function to run to pass data to the decomposition `DM` upon its creation
3475b3a6b972SJed Brown .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
347620f4b53cSBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3477b3a6b972SJed Brown 
3478b3a6b972SJed Brown    Level: advanced
3479b3a6b972SJed Brown 
3480*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSubDomainHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3481b3a6b972SJed Brown @*/
3482d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainHookRemove(DM global, PetscErrorCode (*ddhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, VecScatter, VecScatter, DM, void *), void *ctx)
3483d71ae5a4SJacob Faibussowitsch {
3484b3a6b972SJed Brown   DMSubDomainHookLink link, *p;
3485b3a6b972SJed Brown 
3486b3a6b972SJed Brown   PetscFunctionBegin;
3487b3a6b972SJed Brown   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3488b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3489b3a6b972SJed Brown     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3490b3a6b972SJed Brown       link = *p;
3491b3a6b972SJed Brown       *p   = link->next;
34929566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3493b3a6b972SJed Brown       break;
3494b3a6b972SJed Brown     }
3495b3a6b972SJed Brown   }
34963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3497b3a6b972SJed Brown }
3498b3a6b972SJed Brown 
34995dbd56e3SPeter Brune /*@
3500bb7acecfSBarry Smith    DMSubDomainRestrict - restricts user-defined problem data to a block `DM` by running hooks registered by `DMSubDomainHookAdd()`
35015dbd56e3SPeter Brune 
35025dbd56e3SPeter Brune    Collective if any hooks are
35035dbd56e3SPeter Brune 
35044165533cSJose E. Roman    Input Parameters:
3505bb7acecfSBarry Smith +  fine - finer `DM` to use as a base
3506be081cd6SPeter Brune .  oscatter - scatter from domain global vector filling subdomain global vector with overlap
3507be081cd6SPeter Brune .  gscatter - scatter from domain global vector filling subdomain local vector with ghosts
3508bb7acecfSBarry Smith -  coarse - coarser `DM` to update
35095dbd56e3SPeter Brune 
35105dbd56e3SPeter Brune    Level: developer
35115dbd56e3SPeter Brune 
3512*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `MatRestrict()`
35135dbd56e3SPeter Brune @*/
3514d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainRestrict(DM global, VecScatter oscatter, VecScatter gscatter, DM subdm)
3515d71ae5a4SJacob Faibussowitsch {
3516be081cd6SPeter Brune   DMSubDomainHookLink link;
35175dbd56e3SPeter Brune 
35185dbd56e3SPeter Brune   PetscFunctionBegin;
3519be081cd6SPeter Brune   for (link = global->subdomainhook; link; link = link->next) {
35201baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(global, oscatter, gscatter, subdm, link->ctx));
35215dbd56e3SPeter Brune   }
35223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35235dbd56e3SPeter Brune }
35245dbd56e3SPeter Brune 
35255fe1f584SPeter Brune /*@
3526bb7acecfSBarry Smith     DMGetCoarsenLevel - Gets the number of coarsenings that have generated this `DM`.
35275fe1f584SPeter Brune 
35285fe1f584SPeter Brune     Not Collective
35295fe1f584SPeter Brune 
35305fe1f584SPeter Brune     Input Parameter:
3531bb7acecfSBarry Smith .   dm - the `DM` object
35325fe1f584SPeter Brune 
35335fe1f584SPeter Brune     Output Parameter:
35346a7d9d85SPeter Brune .   level - number of coarsenings
35355fe1f584SPeter Brune 
35365fe1f584SPeter Brune     Level: developer
35375fe1f584SPeter Brune 
3538*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMSetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
35395fe1f584SPeter Brune @*/
3540d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarsenLevel(DM dm, PetscInt *level)
3541d71ae5a4SJacob Faibussowitsch {
35425fe1f584SPeter Brune   PetscFunctionBegin;
35435fe1f584SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3544b9d85ea2SLisandro Dalcin   PetscValidIntPointer(level, 2);
35455fe1f584SPeter Brune   *level = dm->leveldown;
35463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35475fe1f584SPeter Brune }
35485fe1f584SPeter Brune 
35499a64c4a8SMatthew G. Knepley /*@
3550bb7acecfSBarry Smith     DMSetCoarsenLevel - Sets the number of coarsenings that have generated this `DM`.
35519a64c4a8SMatthew G. Knepley 
355220f4b53cSBarry Smith     Collective
35539a64c4a8SMatthew G. Knepley 
35549a64c4a8SMatthew G. Knepley     Input Parameters:
3555bb7acecfSBarry Smith +   dm - the `DM` object
35569a64c4a8SMatthew G. Knepley -   level - number of coarsenings
35579a64c4a8SMatthew G. Knepley 
35589a64c4a8SMatthew G. Knepley     Level: developer
35599a64c4a8SMatthew G. Knepley 
3560bb7acecfSBarry Smith     Note:
3561bb7acecfSBarry Smith     This is rarely used directly, the information is automatically set when a `DM` is created with `DMCoarsen()`
3562bb7acecfSBarry Smith 
3563*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetCoarsenLevel()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
35649a64c4a8SMatthew G. Knepley @*/
3565d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarsenLevel(DM dm, PetscInt level)
3566d71ae5a4SJacob Faibussowitsch {
35679a64c4a8SMatthew G. Knepley   PetscFunctionBegin;
35689a64c4a8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35699a64c4a8SMatthew G. Knepley   dm->leveldown = level;
35703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35719a64c4a8SMatthew G. Knepley }
35729a64c4a8SMatthew G. Knepley 
357347c6ae99SBarry Smith /*@C
3574bb7acecfSBarry Smith     DMRefineHierarchy - Refines a `DM` object, all levels at once
357547c6ae99SBarry Smith 
357620f4b53cSBarry Smith     Collective
357747c6ae99SBarry Smith 
3578d8d19677SJose E. Roman     Input Parameters:
3579bb7acecfSBarry Smith +   dm - the `DM` object
358047c6ae99SBarry Smith -   nlevels - the number of levels of refinement
358147c6ae99SBarry Smith 
358247c6ae99SBarry Smith     Output Parameter:
3583bb7acecfSBarry Smith .   dmf - the refined `DM` hierarchy
358447c6ae99SBarry Smith 
358547c6ae99SBarry Smith     Level: developer
358647c6ae99SBarry Smith 
3587*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMCoarsenHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
358847c6ae99SBarry Smith @*/
3589d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHierarchy(DM dm, PetscInt nlevels, DM dmf[])
3590d71ae5a4SJacob Faibussowitsch {
359147c6ae99SBarry Smith   PetscFunctionBegin;
3592171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35937a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
35943ba16761SJacob Faibussowitsch   if (nlevels == 0) PetscFunctionReturn(PETSC_SUCCESS);
3595b9d85ea2SLisandro Dalcin   PetscValidPointer(dmf, 3);
359647c6ae99SBarry Smith   if (dm->ops->refinehierarchy) {
3597dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, refinehierarchy, nlevels, dmf);
359847c6ae99SBarry Smith   } else if (dm->ops->refine) {
359947c6ae99SBarry Smith     PetscInt i;
360047c6ae99SBarry Smith 
36019566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &dmf[0]));
360248a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMRefine(dmf[i - 1], PetscObjectComm((PetscObject)dm), &dmf[i]));
3603ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No RefineHierarchy for this DM yet");
36043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
360547c6ae99SBarry Smith }
360647c6ae99SBarry Smith 
360747c6ae99SBarry Smith /*@C
3608bb7acecfSBarry Smith     DMCoarsenHierarchy - Coarsens a `DM` object, all levels at once
360947c6ae99SBarry Smith 
361020f4b53cSBarry Smith     Collective
361147c6ae99SBarry Smith 
3612d8d19677SJose E. Roman     Input Parameters:
3613bb7acecfSBarry Smith +   dm - the `DM` object
361447c6ae99SBarry Smith -   nlevels - the number of levels of coarsening
361547c6ae99SBarry Smith 
361647c6ae99SBarry Smith     Output Parameter:
3617bb7acecfSBarry Smith .   dmc - the coarsened `DM` hierarchy
361847c6ae99SBarry Smith 
361947c6ae99SBarry Smith     Level: developer
362047c6ae99SBarry Smith 
3621*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMRefineHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
362247c6ae99SBarry Smith @*/
3623d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
3624d71ae5a4SJacob Faibussowitsch {
362547c6ae99SBarry Smith   PetscFunctionBegin;
3626171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36277a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
36283ba16761SJacob Faibussowitsch   if (nlevels == 0) PetscFunctionReturn(PETSC_SUCCESS);
362947c6ae99SBarry Smith   PetscValidPointer(dmc, 3);
363047c6ae99SBarry Smith   if (dm->ops->coarsenhierarchy) {
3631dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, coarsenhierarchy, nlevels, dmc);
363247c6ae99SBarry Smith   } else if (dm->ops->coarsen) {
363347c6ae99SBarry Smith     PetscInt i;
363447c6ae99SBarry Smith 
36359566063dSJacob Faibussowitsch     PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &dmc[0]));
363648a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMCoarsen(dmc[i - 1], PetscObjectComm((PetscObject)dm), &dmc[i]));
3637ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No CoarsenHierarchy for this DM yet");
36383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
363947c6ae99SBarry Smith }
364047c6ae99SBarry Smith 
36411a266240SBarry Smith /*@C
3642bb7acecfSBarry Smith     DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the `DM` is destroyed
36431a266240SBarry Smith 
3644bb7acecfSBarry Smith     Logically Collective if the function is collective
36451a266240SBarry Smith 
36461a266240SBarry Smith     Input Parameters:
3647bb7acecfSBarry Smith +   dm - the `DM` object
36481a266240SBarry Smith -   destroy - the destroy function
36491a266240SBarry Smith 
36501a266240SBarry Smith     Level: intermediate
36511a266240SBarry Smith 
3652*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
3653f07f9ceaSJed Brown @*/
3654d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetApplicationContextDestroy(DM dm, PetscErrorCode (*destroy)(void **))
3655d71ae5a4SJacob Faibussowitsch {
36561a266240SBarry Smith   PetscFunctionBegin;
3657171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36581a266240SBarry Smith   dm->ctxdestroy = destroy;
36593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36601a266240SBarry Smith }
36611a266240SBarry Smith 
3662b07ff414SBarry Smith /*@
3663bb7acecfSBarry Smith     DMSetApplicationContext - Set a user context into a `DM` object
366447c6ae99SBarry Smith 
366547c6ae99SBarry Smith     Not Collective
366647c6ae99SBarry Smith 
366747c6ae99SBarry Smith     Input Parameters:
3668bb7acecfSBarry Smith +   dm - the `DM` object
366947c6ae99SBarry Smith -   ctx - the user context
367047c6ae99SBarry Smith 
367147c6ae99SBarry Smith     Level: intermediate
367247c6ae99SBarry Smith 
3673bb7acecfSBarry Smith     Note:
367435cb6cd3SPierre Jolivet     A user context is a way to pass problem specific information that is accessible whenever the `DM` is available
3675bb7acecfSBarry Smith 
3676*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
367747c6ae99SBarry Smith @*/
3678d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetApplicationContext(DM dm, void *ctx)
3679d71ae5a4SJacob Faibussowitsch {
368047c6ae99SBarry Smith   PetscFunctionBegin;
3681171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
368247c6ae99SBarry Smith   dm->ctx = ctx;
36833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
368447c6ae99SBarry Smith }
368547c6ae99SBarry Smith 
368647c6ae99SBarry Smith /*@
3687bb7acecfSBarry Smith     DMGetApplicationContext - Gets a user context from a `DM` object
368847c6ae99SBarry Smith 
368947c6ae99SBarry Smith     Not Collective
369047c6ae99SBarry Smith 
369147c6ae99SBarry Smith     Input Parameter:
3692bb7acecfSBarry Smith .   dm - the `DM` object
369347c6ae99SBarry Smith 
369447c6ae99SBarry Smith     Output Parameter:
369547c6ae99SBarry Smith .   ctx - the user context
369647c6ae99SBarry Smith 
369747c6ae99SBarry Smith     Level: intermediate
369847c6ae99SBarry Smith 
3699bb7acecfSBarry Smith     Note:
370035cb6cd3SPierre Jolivet     A user context is a way to pass problem specific information that is accessible whenever the `DM` is available
3701bb7acecfSBarry Smith 
3702*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
370347c6ae99SBarry Smith @*/
3704d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetApplicationContext(DM dm, void *ctx)
3705d71ae5a4SJacob Faibussowitsch {
370647c6ae99SBarry Smith   PetscFunctionBegin;
3707171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37081b2093e4SBarry Smith   *(void **)ctx = dm->ctx;
37093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
371047c6ae99SBarry Smith }
371147c6ae99SBarry Smith 
371208da532bSDmitry Karpeev /*@C
3713bb7acecfSBarry Smith     DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for `SNESVI`.
371408da532bSDmitry Karpeev 
371520f4b53cSBarry Smith     Logically Collective
371608da532bSDmitry Karpeev 
3717d8d19677SJose E. Roman     Input Parameters:
371808da532bSDmitry Karpeev +   dm - the DM object
371920f4b53cSBarry Smith -   f - the function that computes variable bounds used by SNESVI (use `NULL` to cancel a previous function that was set)
372008da532bSDmitry Karpeev 
372108da532bSDmitry Karpeev     Level: intermediate
372208da532bSDmitry Karpeev 
3723*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMComputeVariableBounds()`, `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`,
3724db781477SPatrick Sanan          `DMSetJacobian()`
372508da532bSDmitry Karpeev @*/
3726d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetVariableBounds(DM dm, PetscErrorCode (*f)(DM, Vec, Vec))
3727d71ae5a4SJacob Faibussowitsch {
372808da532bSDmitry Karpeev   PetscFunctionBegin;
37295a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
373008da532bSDmitry Karpeev   dm->ops->computevariablebounds = f;
37313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
373208da532bSDmitry Karpeev }
373308da532bSDmitry Karpeev 
373408da532bSDmitry Karpeev /*@
3735bb7acecfSBarry Smith     DMHasVariableBounds - does the `DM` object have a variable bounds function?
373608da532bSDmitry Karpeev 
373708da532bSDmitry Karpeev     Not Collective
373808da532bSDmitry Karpeev 
373908da532bSDmitry Karpeev     Input Parameter:
3740bb7acecfSBarry Smith .   dm - the `DM` object to destroy
374108da532bSDmitry Karpeev 
374208da532bSDmitry Karpeev     Output Parameter:
3743bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the variable bounds function exists
374408da532bSDmitry Karpeev 
374508da532bSDmitry Karpeev     Level: developer
374608da532bSDmitry Karpeev 
3747*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMComputeVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
374808da532bSDmitry Karpeev @*/
3749d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasVariableBounds(DM dm, PetscBool *flg)
3750d71ae5a4SJacob Faibussowitsch {
375108da532bSDmitry Karpeev   PetscFunctionBegin;
37525a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3753534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
375408da532bSDmitry Karpeev   *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
37553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
375608da532bSDmitry Karpeev }
375708da532bSDmitry Karpeev 
375808da532bSDmitry Karpeev /*@C
3759bb7acecfSBarry Smith     DMComputeVariableBounds - compute variable bounds used by `SNESVI`.
376008da532bSDmitry Karpeev 
376120f4b53cSBarry Smith     Logically Collective
376208da532bSDmitry Karpeev 
3763f899ff85SJose E. Roman     Input Parameter:
3764bb7acecfSBarry Smith .   dm - the `DM` object
376508da532bSDmitry Karpeev 
376608da532bSDmitry Karpeev     Output parameters:
376708da532bSDmitry Karpeev +   xl - lower bound
376808da532bSDmitry Karpeev -   xu - upper bound
376908da532bSDmitry Karpeev 
3770907376e6SBarry Smith     Level: advanced
3771907376e6SBarry Smith 
377220f4b53cSBarry Smith     Note:
377395452b02SPatrick Sanan     This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
377408da532bSDmitry Karpeev 
3775*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
377608da532bSDmitry Karpeev @*/
3777d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3778d71ae5a4SJacob Faibussowitsch {
377908da532bSDmitry Karpeev   PetscFunctionBegin;
37805a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
378108da532bSDmitry Karpeev   PetscValidHeaderSpecific(xl, VEC_CLASSID, 2);
37825a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(xu, VEC_CLASSID, 3);
3783dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, computevariablebounds, xl, xu);
37843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
378508da532bSDmitry Karpeev }
378608da532bSDmitry Karpeev 
3787b0ae01b7SPeter Brune /*@
3788bb7acecfSBarry Smith     DMHasColoring - does the `DM` object have a method of providing a coloring?
3789b0ae01b7SPeter Brune 
3790b0ae01b7SPeter Brune     Not Collective
3791b0ae01b7SPeter Brune 
3792b0ae01b7SPeter Brune     Input Parameter:
3793b0ae01b7SPeter Brune .   dm - the DM object
3794b0ae01b7SPeter Brune 
3795b0ae01b7SPeter Brune     Output Parameter:
3796bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateColoring()`.
3797b0ae01b7SPeter Brune 
3798b0ae01b7SPeter Brune     Level: developer
3799b0ae01b7SPeter Brune 
3800*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateColoring()`
3801b0ae01b7SPeter Brune @*/
3802d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasColoring(DM dm, PetscBool *flg)
3803d71ae5a4SJacob Faibussowitsch {
3804b0ae01b7SPeter Brune   PetscFunctionBegin;
38055a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3806534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
3807b0ae01b7SPeter Brune   *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
38083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3809b0ae01b7SPeter Brune }
3810b0ae01b7SPeter Brune 
38113ad4599aSBarry Smith /*@
3812bb7acecfSBarry Smith     DMHasCreateRestriction - does the `DM` object have a method of providing a restriction?
38133ad4599aSBarry Smith 
38143ad4599aSBarry Smith     Not Collective
38153ad4599aSBarry Smith 
38163ad4599aSBarry Smith     Input Parameter:
3817bb7acecfSBarry Smith .   dm - the `DM` object
38183ad4599aSBarry Smith 
38193ad4599aSBarry Smith     Output Parameter:
3820bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateRestriction()`.
38213ad4599aSBarry Smith 
38223ad4599aSBarry Smith     Level: developer
38233ad4599aSBarry Smith 
3824*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateRestriction()`, `DMHasCreateInterpolation()`, `DMHasCreateInjection()`
38253ad4599aSBarry Smith @*/
3826d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateRestriction(DM dm, PetscBool *flg)
3827d71ae5a4SJacob Faibussowitsch {
38283ad4599aSBarry Smith   PetscFunctionBegin;
38295a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3830534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
38313ad4599aSBarry Smith   *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
38323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38333ad4599aSBarry Smith }
38343ad4599aSBarry Smith 
3835a7058e45SLawrence Mitchell /*@
3836bb7acecfSBarry Smith     DMHasCreateInjection - does the `DM` object have a method of providing an injection?
3837a7058e45SLawrence Mitchell 
3838a7058e45SLawrence Mitchell     Not Collective
3839a7058e45SLawrence Mitchell 
3840a7058e45SLawrence Mitchell     Input Parameter:
3841bb7acecfSBarry Smith .   dm - the `DM` object
3842a7058e45SLawrence Mitchell 
3843a7058e45SLawrence Mitchell     Output Parameter:
3844bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateInjection()`.
3845a7058e45SLawrence Mitchell 
3846a7058e45SLawrence Mitchell     Level: developer
3847a7058e45SLawrence Mitchell 
3848*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateInjection()`, `DMHasCreateRestriction()`, `DMHasCreateInterpolation()`
3849a7058e45SLawrence Mitchell @*/
3850d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateInjection(DM dm, PetscBool *flg)
3851d71ae5a4SJacob Faibussowitsch {
3852a7058e45SLawrence Mitchell   PetscFunctionBegin;
38535a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3854534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
3855dbbe0bcdSBarry Smith   if (dm->ops->hascreateinjection) PetscUseTypeMethod(dm, hascreateinjection, flg);
3856ad540459SPierre Jolivet   else *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE;
38573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3858a7058e45SLawrence Mitchell }
3859a7058e45SLawrence Mitchell 
38600298fd71SBarry Smith PetscFunctionList DMList              = NULL;
3861264ace61SBarry Smith PetscBool         DMRegisterAllCalled = PETSC_FALSE;
3862264ace61SBarry Smith 
3863264ace61SBarry Smith /*@C
3864bb7acecfSBarry Smith   DMSetType - Builds a `DM`, for a particular `DM` implementation.
3865264ace61SBarry Smith 
386620f4b53cSBarry Smith   Collective
3867264ace61SBarry Smith 
3868264ace61SBarry Smith   Input Parameters:
3869bb7acecfSBarry Smith + dm     - The `DM` object
3870bb7acecfSBarry Smith - method - The name of the `DMType`, for example `DMDA`, `DMPLEX`
3871264ace61SBarry Smith 
3872264ace61SBarry Smith   Options Database Key:
3873bb7acecfSBarry Smith . -dm_type <type> - Sets the `DM` type; use -help for a list of available types
3874264ace61SBarry Smith 
3875264ace61SBarry Smith   Level: intermediate
3876264ace61SBarry Smith 
3877bb7acecfSBarry Smith   Note:
38780462cc06SPierre Jolivet   Of the `DM` is constructed by directly calling a function to construct a particular `DM`, for example, `DMDACreate2d()` or `DMPlexCreateBoxMesh()`
3879bb7acecfSBarry Smith 
3880*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMDA`, `DMPLEX`, `DMGetType()`, `DMCreate()`, `DMDACreate2d()`
3881264ace61SBarry Smith @*/
3882d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetType(DM dm, DMType method)
3883d71ae5a4SJacob Faibussowitsch {
3884264ace61SBarry Smith   PetscErrorCode (*r)(DM);
3885264ace61SBarry Smith   PetscBool match;
3886264ace61SBarry Smith 
3887264ace61SBarry Smith   PetscFunctionBegin;
3888264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38899566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, method, &match));
38903ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
3891264ace61SBarry Smith 
38929566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
38939566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(DMList, method, &r));
38947a8be351SBarry Smith   PetscCheck(r, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3895264ace61SBarry Smith 
3896dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, destroy);
38979566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(dm->ops, sizeof(*dm->ops)));
38989566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)dm, method));
38999566063dSJacob Faibussowitsch   PetscCall((*r)(dm));
39003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3901264ace61SBarry Smith }
3902264ace61SBarry Smith 
3903264ace61SBarry Smith /*@C
3904bb7acecfSBarry Smith   DMGetType - Gets the `DM` type name (as a string) from the `DM`.
3905264ace61SBarry Smith 
3906264ace61SBarry Smith   Not Collective
3907264ace61SBarry Smith 
3908264ace61SBarry Smith   Input Parameter:
3909bb7acecfSBarry Smith . dm  - The `DM`
3910264ace61SBarry Smith 
3911264ace61SBarry Smith   Output Parameter:
3912bb7acecfSBarry Smith . type - The `DMType` name
3913264ace61SBarry Smith 
3914264ace61SBarry Smith   Level: intermediate
3915264ace61SBarry Smith 
3916*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMDA`, `DMPLEX`, `DMSetType()`, `DMCreate()`
3917264ace61SBarry Smith @*/
3918d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetType(DM dm, DMType *type)
3919d71ae5a4SJacob Faibussowitsch {
3920264ace61SBarry Smith   PetscFunctionBegin;
3921264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3922c959eef4SJed Brown   PetscValidPointer(type, 2);
39239566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
3924264ace61SBarry Smith   *type = ((PetscObject)dm)->type_name;
39253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3926264ace61SBarry Smith }
3927264ace61SBarry Smith 
392867a56275SMatthew G Knepley /*@C
3929bb7acecfSBarry Smith   DMConvert - Converts a `DM` to another `DM`, either of the same or different type.
393067a56275SMatthew G Knepley 
393120f4b53cSBarry Smith   Collective
393267a56275SMatthew G Knepley 
393367a56275SMatthew G Knepley   Input Parameters:
3934bb7acecfSBarry Smith + dm - the `DM`
3935bb7acecfSBarry Smith - newtype - new `DM` type (use "same" for the same type)
393667a56275SMatthew G Knepley 
393767a56275SMatthew G Knepley   Output Parameter:
3938bb7acecfSBarry Smith . M - pointer to new `DM`
393967a56275SMatthew G Knepley 
394020f4b53cSBarry Smith   Level: intermediate
394120f4b53cSBarry Smith 
394267a56275SMatthew G Knepley   Notes:
3943bb7acecfSBarry Smith   Cannot be used to convert a sequential `DM` to a parallel or a parallel to sequential,
3944bb7acecfSBarry Smith   the MPI communicator of the generated `DM` is always the same as the communicator
3945bb7acecfSBarry Smith   of the input `DM`.
394667a56275SMatthew G Knepley 
3947*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetType()`, `DMCreate()`, `DMClone()`
394867a56275SMatthew G Knepley @*/
3949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
3950d71ae5a4SJacob Faibussowitsch {
395167a56275SMatthew G Knepley   DM        B;
395267a56275SMatthew G Knepley   char      convname[256];
3953c067b6caSMatthew G. Knepley   PetscBool sametype /*, issame */;
395467a56275SMatthew G Knepley 
395567a56275SMatthew G Knepley   PetscFunctionBegin;
395667a56275SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
395767a56275SMatthew G Knepley   PetscValidType(dm, 1);
395867a56275SMatthew G Knepley   PetscValidPointer(M, 3);
39599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, newtype, &sametype));
39609566063dSJacob Faibussowitsch   /* PetscCall(PetscStrcmp(newtype, "same", &issame)); */
3961c067b6caSMatthew G. Knepley   if (sametype) {
3962c067b6caSMatthew G. Knepley     *M = dm;
39639566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
39643ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3965c067b6caSMatthew G. Knepley   } else {
39660298fd71SBarry Smith     PetscErrorCode (*conv)(DM, DMType, DM *) = NULL;
396767a56275SMatthew G Knepley 
396867a56275SMatthew G Knepley     /*
396967a56275SMatthew G Knepley        Order of precedence:
397067a56275SMatthew G Knepley        1) See if a specialized converter is known to the current DM.
397167a56275SMatthew G Knepley        2) See if a specialized converter is known to the desired DM class.
397267a56275SMatthew G Knepley        3) See if a good general converter is registered for the desired class
397367a56275SMatthew G Knepley        4) See if a good general converter is known for the current matrix.
397467a56275SMatthew G Knepley        5) Use a really basic converter.
397567a56275SMatthew G Knepley     */
397667a56275SMatthew G Knepley 
397767a56275SMatthew G Knepley     /* 1) See if a specialized converter is known to the current DM and the desired class */
39789566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
39799566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
39809566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
39819566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
39829566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
39839566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)dm, convname, &conv));
398467a56275SMatthew G Knepley     if (conv) goto foundconv;
398567a56275SMatthew G Knepley 
398667a56275SMatthew G Knepley     /* 2)  See if a specialized converter is known to the desired DM class. */
39879566063dSJacob Faibussowitsch     PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &B));
39889566063dSJacob Faibussowitsch     PetscCall(DMSetType(B, newtype));
39899566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
39909566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
39919566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
39929566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
39939566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
39949566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
399567a56275SMatthew G Knepley     if (conv) {
39969566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&B));
399767a56275SMatthew G Knepley       goto foundconv;
399867a56275SMatthew G Knepley     }
399967a56275SMatthew G Knepley 
400067a56275SMatthew G Knepley #if 0
400167a56275SMatthew G Knepley     /* 3) See if a good general converter is registered for the desired class */
400267a56275SMatthew G Knepley     conv = B->ops->convertfrom;
40039566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&B));
400467a56275SMatthew G Knepley     if (conv) goto foundconv;
400567a56275SMatthew G Knepley 
400667a56275SMatthew G Knepley     /* 4) See if a good general converter is known for the current matrix */
400767a56275SMatthew G Knepley     if (dm->ops->convert) {
400867a56275SMatthew G Knepley       conv = dm->ops->convert;
400967a56275SMatthew G Knepley     }
401067a56275SMatthew G Knepley     if (conv) goto foundconv;
401167a56275SMatthew G Knepley #endif
401267a56275SMatthew G Knepley 
401367a56275SMatthew G Knepley     /* 5) Use a really basic converter. */
401498921bdaSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject)dm)->type_name, newtype);
401567a56275SMatthew G Knepley 
401667a56275SMatthew G Knepley   foundconv:
40179566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(DM_Convert, dm, 0, 0, 0));
40189566063dSJacob Faibussowitsch     PetscCall((*conv)(dm, newtype, M));
401912fa691eSMatthew G. Knepley     /* Things that are independent of DM type: We should consult DMClone() here */
402090b157c4SStefano Zampini     {
40214fb89dddSMatthew G. Knepley       const PetscReal *maxCell, *Lstart, *L;
40226858538eSMatthew G. Knepley 
40234fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
40244fb89dddSMatthew G. Knepley       PetscCall(DMSetPeriodicity(*M, maxCell, Lstart, L));
4025c8a6034eSMark       (*M)->prealloc_only = dm->prealloc_only;
40269566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->vectype));
40279566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*M)->vectype));
40289566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->mattype));
40299566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*M)->mattype));
403012fa691eSMatthew G. Knepley     }
40319566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(DM_Convert, dm, 0, 0, 0));
403267a56275SMatthew G Knepley   }
40339566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
40343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
403567a56275SMatthew G Knepley }
4036264ace61SBarry Smith 
4037264ace61SBarry Smith /*--------------------------------------------------------------------------------------------------------------------*/
4038264ace61SBarry Smith 
4039264ace61SBarry Smith /*@C
4040bb7acecfSBarry Smith   DMRegister -  Adds a new `DM` type implementation
40411c84c290SBarry Smith 
40421c84c290SBarry Smith   Not Collective
40431c84c290SBarry Smith 
40441c84c290SBarry Smith   Input Parameters:
404520f4b53cSBarry Smith + sname    - The name of a new user-defined creation routine
404620f4b53cSBarry Smith - function - The creation routine itself
404720f4b53cSBarry Smith 
404820f4b53cSBarry Smith   Level: advanced
40491c84c290SBarry Smith 
40501c84c290SBarry Smith   Notes:
405120f4b53cSBarry Smith   `DMRegister()` may be called multiple times to add several user-defined `DM`s
40521c84c290SBarry Smith 
40531c84c290SBarry Smith   Sample usage:
40541c84c290SBarry Smith .vb
4055bdf89e91SBarry Smith     DMRegister("my_da", MyDMCreate);
40561c84c290SBarry Smith .ve
40571c84c290SBarry Smith 
405820f4b53cSBarry Smith   Then, your `DM` type can be chosen with the procedural interface via
40591c84c290SBarry Smith .vb
40601c84c290SBarry Smith     DMCreate(MPI_Comm, DM *);
40611c84c290SBarry Smith     DMSetType(DM,"my_da");
40621c84c290SBarry Smith .ve
40631c84c290SBarry Smith    or at runtime via the option
40641c84c290SBarry Smith .vb
40651c84c290SBarry Smith     -da_type my_da
40661c84c290SBarry Smith .ve
4067264ace61SBarry Smith 
4068*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMSetType()`, `DMRegisterAll()`, `DMRegisterDestroy()`
4069264ace61SBarry Smith @*/
4070d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRegister(const char sname[], PetscErrorCode (*function)(DM))
4071d71ae5a4SJacob Faibussowitsch {
4072264ace61SBarry Smith   PetscFunctionBegin;
40739566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
40749566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&DMList, sname, function));
40753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4076264ace61SBarry Smith }
4077264ace61SBarry Smith 
4078b859378eSBarry Smith /*@C
4079bb7acecfSBarry Smith   DMLoad - Loads a DM that has been stored in binary  with `DMView()`.
4080b859378eSBarry Smith 
408120f4b53cSBarry Smith   Collective
4082b859378eSBarry Smith 
4083b859378eSBarry Smith   Input Parameters:
4084bb7acecfSBarry Smith + newdm - the newly loaded `DM`, this needs to have been created with `DMCreate()` or
4085bb7acecfSBarry Smith            some related function before a call to `DMLoad()`.
4086bb7acecfSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` or
4087bb7acecfSBarry Smith            `PETSCVIEWERHDF5` file viewer, obtained from `PetscViewerHDF5Open()`
4088b859378eSBarry Smith 
4089b859378eSBarry Smith    Level: intermediate
4090b859378eSBarry Smith 
4091b859378eSBarry Smith   Notes:
409255849f57SBarry Smith   The type is determined by the data in the file, any type set into the DM before this call is ignored.
4093b859378eSBarry Smith 
4094bb7acecfSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
4095bb7acecfSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
4096bb7acecfSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
4097cd7e8a5eSksagiyam 
4098*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscViewerBinaryOpen()`, `DMView()`, `MatLoad()`, `VecLoad()`
4099b859378eSBarry Smith @*/
4100d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
4101d71ae5a4SJacob Faibussowitsch {
41029331c7a4SMatthew G. Knepley   PetscBool isbinary, ishdf5;
4103b859378eSBarry Smith 
4104b859378eSBarry Smith   PetscFunctionBegin;
4105b859378eSBarry Smith   PetscValidHeaderSpecific(newdm, DM_CLASSID, 1);
4106b859378eSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
41079566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckReadable(viewer));
41089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
41099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
41109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Load, viewer, 0, 0, 0));
41119331c7a4SMatthew G. Knepley   if (isbinary) {
41129331c7a4SMatthew G. Knepley     PetscInt classid;
41139331c7a4SMatthew G. Knepley     char     type[256];
4114b859378eSBarry Smith 
41159566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
41167a8be351SBarry Smith     PetscCheck(classid == DM_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not DM next in file, classid found %d", (int)classid);
41179566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
41189566063dSJacob Faibussowitsch     PetscCall(DMSetType(newdm, type));
4119dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41209331c7a4SMatthew G. Knepley   } else if (ishdf5) {
4121dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41229331c7a4SMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
41239566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Load, viewer, 0, 0, 0));
41243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4125b859378eSBarry Smith }
4126b859378eSBarry Smith 
41277da65231SMatthew G Knepley /******************************** FEM Support **********************************/
41287da65231SMatthew G Knepley 
4129d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
4130d71ae5a4SJacob Faibussowitsch {
41311d47ebbbSSatish Balay   PetscInt f;
41321b30c384SMatthew G Knepley 
41337da65231SMatthew G Knepley   PetscFunctionBegin;
413463a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
413548a46eb9SPierre Jolivet   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f])));
41363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41377da65231SMatthew G Knepley }
41387da65231SMatthew G Knepley 
4139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
4140d71ae5a4SJacob Faibussowitsch {
41411b30c384SMatthew G Knepley   PetscInt f, g;
41427da65231SMatthew G Knepley 
41437da65231SMatthew G Knepley   PetscFunctionBegin;
414463a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
41451d47ebbbSSatish Balay   for (f = 0; f < rows; ++f) {
41469566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  |"));
414748a46eb9SPierre Jolivet     for (g = 0; g < cols; ++g) PetscCall(PetscPrintf(PETSC_COMM_SELF, " % 9.5g", (double)PetscRealPart(A[f * cols + g])));
41489566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, " |\n"));
41497da65231SMatthew G Knepley   }
41503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41517da65231SMatthew G Knepley }
4152e7c4fc90SDmitry Karpeev 
4153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
4154d71ae5a4SJacob Faibussowitsch {
41550c5b8624SToby Isaac   PetscInt           localSize, bs;
41560c5b8624SToby Isaac   PetscMPIInt        size;
41570c5b8624SToby Isaac   Vec                x, xglob;
41580c5b8624SToby Isaac   const PetscScalar *xarray;
4159e759306cSMatthew G. Knepley 
4160e759306cSMatthew G. Knepley   PetscFunctionBegin;
41619566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
41629566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, &x));
41639566063dSJacob Faibussowitsch   PetscCall(VecCopy(X, x));
41649566063dSJacob Faibussowitsch   PetscCall(VecChop(x, tol));
41659566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "%s:\n", name));
41660c5b8624SToby Isaac   if (size > 1) {
41679566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(x, &localSize));
41689566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xarray));
41699566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(x, &bs));
41709566063dSJacob Faibussowitsch     PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)dm), bs, localSize, PETSC_DETERMINE, xarray, &xglob));
41710c5b8624SToby Isaac   } else {
41720c5b8624SToby Isaac     xglob = x;
41730c5b8624SToby Isaac   }
41749566063dSJacob Faibussowitsch   PetscCall(VecView(xglob, PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)dm))));
41750c5b8624SToby Isaac   if (size > 1) {
41769566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xglob));
41779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xarray));
41780c5b8624SToby Isaac   }
41799566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
41803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4181e759306cSMatthew G. Knepley }
4182e759306cSMatthew G. Knepley 
418388ed4aceSMatthew G Knepley /*@
4184bb7acecfSBarry Smith   DMGetSection - Get the `PetscSection` encoding the local data layout for the `DM`.   This is equivalent to `DMGetLocalSection()`. Deprecated in v3.12
4185061576a5SJed Brown 
4186061576a5SJed Brown   Input Parameter:
4187bb7acecfSBarry Smith . dm - The `DM`
4188061576a5SJed Brown 
4189061576a5SJed Brown   Output Parameter:
4190bb7acecfSBarry Smith . section - The `PetscSection`
4191061576a5SJed Brown 
419220f4b53cSBarry Smith   Options Database Key:
4193bb7acecfSBarry Smith . -dm_petscsection_view - View the `PetscSection` created by the `DM`
4194061576a5SJed Brown 
4195061576a5SJed Brown   Level: advanced
4196061576a5SJed Brown 
4197061576a5SJed Brown   Notes:
4198bb7acecfSBarry Smith   Use `DMGetLocalSection()` in new code.
4199061576a5SJed Brown 
4200bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
4201061576a5SJed Brown 
4202*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetLocalSection()`, `DMSetLocalSection()`, `DMGetGlobalSection()`
4203061576a5SJed Brown @*/
4204d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSection(DM dm, PetscSection *section)
4205d71ae5a4SJacob Faibussowitsch {
4206061576a5SJed Brown   PetscFunctionBegin;
42079566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, section));
42083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4209061576a5SJed Brown }
4210061576a5SJed Brown 
4211061576a5SJed Brown /*@
4212bb7acecfSBarry Smith   DMGetLocalSection - Get the `PetscSection` encoding the local data layout for the `DM`.
421388ed4aceSMatthew G Knepley 
421488ed4aceSMatthew G Knepley   Input Parameter:
4215bb7acecfSBarry Smith . dm - The `DM`
421688ed4aceSMatthew G Knepley 
421788ed4aceSMatthew G Knepley   Output Parameter:
4218bb7acecfSBarry Smith . section - The `PetscSection`
421988ed4aceSMatthew G Knepley 
422020f4b53cSBarry Smith   Options Database Key:
4221bb7acecfSBarry Smith . -dm_petscsection_view - View the section created by the `DM`
4222e5893cccSMatthew G. Knepley 
422388ed4aceSMatthew G Knepley   Level: intermediate
422488ed4aceSMatthew G Knepley 
4225bb7acecfSBarry Smith   Note:
4226bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
422788ed4aceSMatthew G Knepley 
4228*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetGlobalSection()`
422988ed4aceSMatthew G Knepley @*/
4230d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section)
4231d71ae5a4SJacob Faibussowitsch {
423288ed4aceSMatthew G Knepley   PetscFunctionBegin;
423388ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
423488ed4aceSMatthew G Knepley   PetscValidPointer(section, 2);
42351bb6d2a8SBarry Smith   if (!dm->localSection && dm->ops->createlocalsection) {
4236e5e52638SMatthew G. Knepley     PetscInt d;
4237e5e52638SMatthew G. Knepley 
423845480ffeSMatthew G. Knepley     if (dm->setfromoptionscalled) {
423945480ffeSMatthew G. Knepley       PetscObject       obj = (PetscObject)dm;
424045480ffeSMatthew G. Knepley       PetscViewer       viewer;
424145480ffeSMatthew G. Knepley       PetscViewerFormat format;
424245480ffeSMatthew G. Knepley       PetscBool         flg;
424345480ffeSMatthew G. Knepley 
42449566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm(obj), obj->options, obj->prefix, "-dm_petscds_view", &viewer, &format, &flg));
42459566063dSJacob Faibussowitsch       if (flg) PetscCall(PetscViewerPushFormat(viewer, format));
424645480ffeSMatthew G. Knepley       for (d = 0; d < dm->Nds; ++d) {
42479566063dSJacob Faibussowitsch         PetscCall(PetscDSSetFromOptions(dm->probs[d].ds));
42489566063dSJacob Faibussowitsch         if (flg) PetscCall(PetscDSView(dm->probs[d].ds, viewer));
424945480ffeSMatthew G. Knepley       }
425045480ffeSMatthew G. Knepley       if (flg) {
42519566063dSJacob Faibussowitsch         PetscCall(PetscViewerFlush(viewer));
42529566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
42539566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&viewer));
425445480ffeSMatthew G. Knepley       }
425545480ffeSMatthew G. Knepley     }
4256dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createlocalsection);
42579566063dSJacob Faibussowitsch     if (dm->localSection) PetscCall(PetscObjectViewFromOptions((PetscObject)dm->localSection, NULL, "-dm_petscsection_view"));
42582f0f8703SMatthew G. Knepley   }
42591bb6d2a8SBarry Smith   *section = dm->localSection;
42603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
426188ed4aceSMatthew G Knepley }
426288ed4aceSMatthew G Knepley 
426388ed4aceSMatthew G Knepley /*@
4264bb7acecfSBarry Smith   DMSetSection - Set the `PetscSection` encoding the local data layout for the `DM`.  This is equivalent to `DMSetLocalSection()`. Deprecated in v3.12
4265061576a5SJed Brown 
4266061576a5SJed Brown   Input Parameters:
4267bb7acecfSBarry Smith + dm - The `DM`
4268bb7acecfSBarry Smith - section - The `PetscSection`
4269061576a5SJed Brown 
4270061576a5SJed Brown   Level: advanced
4271061576a5SJed Brown 
4272061576a5SJed Brown   Notes:
4273bb7acecfSBarry Smith   Use `DMSetLocalSection()` in new code.
4274061576a5SJed Brown 
4275bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4276061576a5SJed Brown 
4277*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetLocalSection()`, `DMSetGlobalSection()`
4278061576a5SJed Brown @*/
4279d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSection(DM dm, PetscSection section)
4280d71ae5a4SJacob Faibussowitsch {
4281061576a5SJed Brown   PetscFunctionBegin;
42829566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(dm, section));
42833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4284061576a5SJed Brown }
4285061576a5SJed Brown 
4286061576a5SJed Brown /*@
4287bb7acecfSBarry Smith   DMSetLocalSection - Set the `PetscSection` encoding the local data layout for the `DM`.
428888ed4aceSMatthew G Knepley 
428988ed4aceSMatthew G Knepley   Input Parameters:
4290bb7acecfSBarry Smith + dm - The `DM`
4291bb7acecfSBarry Smith - section - The `PetscSection`
429288ed4aceSMatthew G Knepley 
429388ed4aceSMatthew G Knepley   Level: intermediate
429488ed4aceSMatthew G Knepley 
4295bb7acecfSBarry Smith   Note:
4296bb7acecfSBarry Smith   Any existing Section will be destroyed
429788ed4aceSMatthew G Knepley 
4298*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscSection`, `DMGetLocalSection()`, `DMSetGlobalSection()`
429988ed4aceSMatthew G Knepley @*/
4300d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLocalSection(DM dm, PetscSection section)
4301d71ae5a4SJacob Faibussowitsch {
4302c473ab19SMatthew G. Knepley   PetscInt numFields = 0;
4303af122d2aSMatthew G Knepley   PetscInt f;
430488ed4aceSMatthew G Knepley 
430588ed4aceSMatthew G Knepley   PetscFunctionBegin;
430688ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4307b9d85ea2SLisandro Dalcin   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
43089566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
43099566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->localSection));
43101bb6d2a8SBarry Smith   dm->localSection = section;
43119566063dSJacob Faibussowitsch   if (section) PetscCall(PetscSectionGetNumFields(dm->localSection, &numFields));
4312af122d2aSMatthew G Knepley   if (numFields) {
43139566063dSJacob Faibussowitsch     PetscCall(DMSetNumFields(dm, numFields));
4314af122d2aSMatthew G Knepley     for (f = 0; f < numFields; ++f) {
43150f21e855SMatthew G. Knepley       PetscObject disc;
4316af122d2aSMatthew G Knepley       const char *name;
4317af122d2aSMatthew G Knepley 
43189566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(dm->localSection, f, &name));
43199566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, &disc));
43209566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName(disc, name));
4321af122d2aSMatthew G Knepley     }
4322af122d2aSMatthew G Knepley   }
4323e87a4003SBarry Smith   /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */
43249566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
43253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
432688ed4aceSMatthew G Knepley }
432788ed4aceSMatthew G Knepley 
43289435951eSToby Isaac /*@
4329bb7acecfSBarry Smith   DMGetDefaultConstraints - Get the `PetscSection` and `Mat` that specify the local constraint interpolation. See `DMSetDefaultConstraints()` for a description of the purpose of constraint interpolation.
43309435951eSToby Isaac 
433120f4b53cSBarry Smith   not Collective
4332e228b242SToby Isaac 
43339435951eSToby Isaac   Input Parameter:
4334bb7acecfSBarry Smith . dm - The `DM`
43359435951eSToby Isaac 
4336d8d19677SJose E. Roman   Output Parameters:
433720f4b53cSBarry Smith + 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.
433820f4b53cSBarry Smith . 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.
433979769bd5SJed Brown - bias - Vector containing bias to be added to constrained dofs
43409435951eSToby Isaac 
43419435951eSToby Isaac   Level: advanced
43429435951eSToby Isaac 
4343bb7acecfSBarry Smith   Note:
4344bb7acecfSBarry Smith   This gets borrowed references, so the user should not destroy the `PetscSection`, `Mat`, or `Vec`.
43459435951eSToby Isaac 
4346*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetDefaultConstraints()`
43479435951eSToby Isaac @*/
4348d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat, Vec *bias)
4349d71ae5a4SJacob Faibussowitsch {
43509435951eSToby Isaac   PetscFunctionBegin;
43519435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4352dbbe0bcdSBarry Smith   if (!dm->defaultConstraint.section && !dm->defaultConstraint.mat && dm->ops->createdefaultconstraints) PetscUseTypeMethod(dm, createdefaultconstraints);
43533b8ba7d1SJed Brown   if (section) *section = dm->defaultConstraint.section;
43543b8ba7d1SJed Brown   if (mat) *mat = dm->defaultConstraint.mat;
435579769bd5SJed Brown   if (bias) *bias = dm->defaultConstraint.bias;
43563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43579435951eSToby Isaac }
43589435951eSToby Isaac 
43599435951eSToby Isaac /*@
4360bb7acecfSBarry Smith   DMSetDefaultConstraints - Set the `PetscSection` and `Mat` that specify the local constraint interpolation.
43619435951eSToby Isaac 
436220f4b53cSBarry Smith   Collective
4363e228b242SToby Isaac 
43649435951eSToby Isaac   Input Parameters:
4365bb7acecfSBarry Smith + dm - The `DM`
4366bb7acecfSBarry Smith . 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).
436720f4b53cSBarry Smith . 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).
436820f4b53cSBarry Smith - bias - A bias vector to be added to constrained values in the local vector.  `NULL` indicates no bias.  Must have a local communicator (`PETSC_COMM_SELF` or derivative).
43699435951eSToby Isaac 
43709435951eSToby Isaac   Level: advanced
43719435951eSToby Isaac 
437220f4b53cSBarry Smith   Notes:
437320f4b53cSBarry Smith   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 + bias, l[s[i]] = c[i], where the scatter s is defined by the `PetscSection` returned by `DMGetDefaultConstraints()`.
437420f4b53cSBarry Smith 
437520f4b53cSBarry Smith   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.  Any bias, if specified, is ignored when accumulating.
437620f4b53cSBarry Smith 
4377bb7acecfSBarry Smith   This increments the references of the `PetscSection`, `Mat`, and `Vec`, so they user can destroy them.
43789435951eSToby Isaac 
4379*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDefaultConstraints()`
43809435951eSToby Isaac @*/
4381d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat, Vec bias)
4382d71ae5a4SJacob Faibussowitsch {
4383e228b242SToby Isaac   PetscMPIInt result;
43849435951eSToby Isaac 
43859435951eSToby Isaac   PetscFunctionBegin;
43869435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4387e228b242SToby Isaac   if (section) {
4388e228b242SToby Isaac     PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
43899566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)section), &result));
43907a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint section must have local communicator");
4391e228b242SToby Isaac   }
4392e228b242SToby Isaac   if (mat) {
4393e228b242SToby Isaac     PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
43949566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)mat), &result));
43957a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint matrix must have local communicator");
4396e228b242SToby Isaac   }
439779769bd5SJed Brown   if (bias) {
439879769bd5SJed Brown     PetscValidHeaderSpecific(bias, VEC_CLASSID, 4);
43999566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)bias), &result));
440079769bd5SJed Brown     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint bias must have local communicator");
440179769bd5SJed Brown   }
44029566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
44039566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->defaultConstraint.section));
44043b8ba7d1SJed Brown   dm->defaultConstraint.section = section;
44059566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)mat));
44069566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&dm->defaultConstraint.mat));
44073b8ba7d1SJed Brown   dm->defaultConstraint.mat = mat;
44089566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)bias));
44099566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&dm->defaultConstraint.bias));
441079769bd5SJed Brown   dm->defaultConstraint.bias = bias;
44113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44129435951eSToby Isaac }
44139435951eSToby Isaac 
4414497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
4415507e4973SMatthew G. Knepley /*
4416bb7acecfSBarry Smith   DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. Generates and error if they are not consistent.
4417507e4973SMatthew G. Knepley 
4418507e4973SMatthew G. Knepley   Input Parameters:
4419bb7acecfSBarry Smith + dm - The `DM`
4420bb7acecfSBarry Smith . localSection - `PetscSection` describing the local data layout
4421bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
4422507e4973SMatthew G. Knepley 
4423507e4973SMatthew G. Knepley   Level: intermediate
4424507e4973SMatthew G. Knepley 
4425*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMSetSectionSF()`
4426507e4973SMatthew G. Knepley */
4427d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
4428d71ae5a4SJacob Faibussowitsch {
4429507e4973SMatthew G. Knepley   MPI_Comm        comm;
4430507e4973SMatthew G. Knepley   PetscLayout     layout;
4431507e4973SMatthew G. Knepley   const PetscInt *ranges;
4432507e4973SMatthew G. Knepley   PetscInt        pStart, pEnd, p, nroots;
4433507e4973SMatthew G. Knepley   PetscMPIInt     size, rank;
4434507e4973SMatthew G. Knepley   PetscBool       valid = PETSC_TRUE, gvalid;
4435507e4973SMatthew G. Knepley 
4436507e4973SMatthew G. Knepley   PetscFunctionBegin;
44379566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4438507e4973SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
44409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
44419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(globalSection, &pStart, &pEnd));
44429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(globalSection, &nroots));
44439566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &layout));
44449566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
44459566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, nroots));
44469566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(layout));
44479566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRanges(layout, &ranges));
4448507e4973SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4449f741bcd2SMatthew G. Knepley     PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
4450507e4973SMatthew G. Knepley 
44519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(localSection, p, &dof));
44529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(localSection, p, &off));
44539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(localSection, p, &cdof));
44549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(globalSection, p, &gdof));
44559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(globalSection, p, &gcdof));
44569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &goff));
4457507e4973SMatthew G. Knepley     if (!gdof) continue; /* Censored point */
44589371c9d4SSatish Balay     if ((gdof < 0 ? -(gdof + 1) : gdof) != dof) {
44599371c9d4SSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "[%d]Global dof %" PetscInt_FMT " for point %" PetscInt_FMT " not equal to local dof %" PetscInt_FMT "\n", rank, gdof, p, dof));
44609371c9d4SSatish Balay       valid = PETSC_FALSE;
44619371c9d4SSatish Balay     }
44629371c9d4SSatish Balay     if (gcdof && (gcdof != cdof)) {
44639371c9d4SSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "[%d]Global constraints %" PetscInt_FMT " for point %" PetscInt_FMT " not equal to local constraints %" PetscInt_FMT "\n", rank, gcdof, p, cdof));
44649371c9d4SSatish Balay       valid = PETSC_FALSE;
44659371c9d4SSatish Balay     }
4466507e4973SMatthew G. Knepley     if (gdof < 0) {
4467507e4973SMatthew G. Knepley       gsize = gdof < 0 ? -(gdof + 1) - gcdof : gdof - gcdof;
4468507e4973SMatthew G. Knepley       for (d = 0; d < gsize; ++d) {
4469507e4973SMatthew G. Knepley         PetscInt offset = -(goff + 1) + d, r;
4470507e4973SMatthew G. Knepley 
44719566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(offset, size + 1, ranges, &r));
4472507e4973SMatthew G. Knepley         if (r < 0) r = -(r + 2);
44739371c9d4SSatish Balay         if ((r < 0) || (r >= size)) {
44749371c9d4SSatish Balay           PetscCall(PetscSynchronizedPrintf(comm, "[%d]Point %" PetscInt_FMT " mapped to invalid process %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, p, r, gdof, goff));
44759371c9d4SSatish Balay           valid = PETSC_FALSE;
44769371c9d4SSatish Balay           break;
44779371c9d4SSatish Balay         }
4478507e4973SMatthew G. Knepley       }
4479507e4973SMatthew G. Knepley     }
4480507e4973SMatthew G. Knepley   }
44819566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
44829566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
44831c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm));
4484507e4973SMatthew G. Knepley   if (!gvalid) {
44859566063dSJacob Faibussowitsch     PetscCall(DMView(dm, NULL));
4486507e4973SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
4487507e4973SMatthew G. Knepley   }
44883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4489507e4973SMatthew G. Knepley }
4490f741bcd2SMatthew G. Knepley #endif
4491507e4973SMatthew G. Knepley 
44925f06a3ddSJed Brown static PetscErrorCode DMGetIsoperiodicPointSF_Internal(DM dm, PetscSF *sf)
44936725e60dSJed Brown {
44946725e60dSJed Brown   PetscErrorCode (*f)(DM, PetscSF *);
44956725e60dSJed Brown   PetscFunctionBegin;
44966725e60dSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44976725e60dSJed Brown   PetscValidPointer(sf, 2);
44985f06a3ddSJed Brown   PetscCall(PetscObjectQueryFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", &f));
44996725e60dSJed Brown   if (f) PetscCall(f(dm, sf));
45006725e60dSJed Brown   else *sf = dm->sf;
45013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45026725e60dSJed Brown }
45036725e60dSJed Brown 
450488ed4aceSMatthew G Knepley /*@
4505bb7acecfSBarry Smith   DMGetGlobalSection - Get the `PetscSection` encoding the global data layout for the `DM`.
450688ed4aceSMatthew G Knepley 
450720f4b53cSBarry Smith   Collective
45088b1ab98fSJed Brown 
450988ed4aceSMatthew G Knepley   Input Parameter:
4510bb7acecfSBarry Smith . dm - The `DM`
451188ed4aceSMatthew G Knepley 
451288ed4aceSMatthew G Knepley   Output Parameter:
4513bb7acecfSBarry Smith . section - The `PetscSection`
451488ed4aceSMatthew G Knepley 
451588ed4aceSMatthew G Knepley   Level: intermediate
451688ed4aceSMatthew G Knepley 
4517bb7acecfSBarry Smith   Note:
4518bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
451988ed4aceSMatthew G Knepley 
4520*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetLocalSection()`
452188ed4aceSMatthew G Knepley @*/
4522d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section)
4523d71ae5a4SJacob Faibussowitsch {
452488ed4aceSMatthew G Knepley   PetscFunctionBegin;
452588ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
452688ed4aceSMatthew G Knepley   PetscValidPointer(section, 2);
45271bb6d2a8SBarry Smith   if (!dm->globalSection) {
4528fd59a867SMatthew G. Knepley     PetscSection s;
45296725e60dSJed Brown     PetscSF      sf;
4530fd59a867SMatthew G. Knepley 
45319566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &s));
45327a8be351SBarry Smith     PetscCheck(s, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
45337a8be351SBarry Smith     PetscCheck(dm->sf, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection");
45345f06a3ddSJed Brown     PetscCall(DMGetIsoperiodicPointSF_Internal(dm, &sf));
45356725e60dSJed Brown     PetscCall(PetscSectionCreateGlobalSection(s, sf, PETSC_FALSE, PETSC_FALSE, &dm->globalSection));
45369566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&dm->map));
45379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map));
45389566063dSJacob Faibussowitsch     PetscCall(PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view"));
453988ed4aceSMatthew G Knepley   }
45401bb6d2a8SBarry Smith   *section = dm->globalSection;
45413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
454288ed4aceSMatthew G Knepley }
454388ed4aceSMatthew G Knepley 
4544b21d0597SMatthew G Knepley /*@
4545bb7acecfSBarry Smith   DMSetGlobalSection - Set the `PetscSection` encoding the global data layout for the `DM`.
4546b21d0597SMatthew G Knepley 
4547b21d0597SMatthew G Knepley   Input Parameters:
4548bb7acecfSBarry Smith + dm - The `DM`
45492fe279fdSBarry Smith - section - The PetscSection, or `NULL`
4550b21d0597SMatthew G Knepley 
4551b21d0597SMatthew G Knepley   Level: intermediate
4552b21d0597SMatthew G Knepley 
4553bb7acecfSBarry Smith   Note:
4554bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4555b21d0597SMatthew G Knepley 
4556*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetGlobalSection()`, `DMSetLocalSection()`
4557b21d0597SMatthew G Knepley @*/
4558d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section)
4559d71ae5a4SJacob Faibussowitsch {
4560b21d0597SMatthew G Knepley   PetscFunctionBegin;
4561b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45625080bbdbSMatthew G Knepley   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
45639566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
45649566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
45651bb6d2a8SBarry Smith   dm->globalSection = section;
4566497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
45679566063dSJacob Faibussowitsch   if (section) PetscCall(DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section));
4568507e4973SMatthew G. Knepley #endif
45693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4570b21d0597SMatthew G Knepley }
4571b21d0597SMatthew G Knepley 
457288ed4aceSMatthew G Knepley /*@
4573bb7acecfSBarry Smith   DMGetSectionSF - Get the `PetscSF` encoding the parallel dof overlap for the `DM`. If it has not been set,
4574bb7acecfSBarry Smith   it is created from the default `PetscSection` layouts in the `DM`.
457588ed4aceSMatthew G Knepley 
457688ed4aceSMatthew G Knepley   Input Parameter:
4577bb7acecfSBarry Smith . dm - The `DM`
457888ed4aceSMatthew G Knepley 
457988ed4aceSMatthew G Knepley   Output Parameter:
4580bb7acecfSBarry Smith . sf - The `PetscSF`
458188ed4aceSMatthew G Knepley 
458288ed4aceSMatthew G Knepley   Level: intermediate
458388ed4aceSMatthew G Knepley 
4584bb7acecfSBarry Smith   Note:
4585bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
458688ed4aceSMatthew G Knepley 
4587*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetSectionSF()`, `DMCreateSectionSF()`
458888ed4aceSMatthew G Knepley @*/
4589d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf)
4590d71ae5a4SJacob Faibussowitsch {
459188ed4aceSMatthew G Knepley   PetscInt nroots;
459288ed4aceSMatthew G Knepley 
459388ed4aceSMatthew G Knepley   PetscFunctionBegin;
459488ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
459588ed4aceSMatthew G Knepley   PetscValidPointer(sf, 2);
459648a46eb9SPierre Jolivet   if (!dm->sectionSF) PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &dm->sectionSF));
45979566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL));
459888ed4aceSMatthew G Knepley   if (nroots < 0) {
459988ed4aceSMatthew G Knepley     PetscSection section, gSection;
460088ed4aceSMatthew G Knepley 
46019566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
460231ea6d37SMatthew G Knepley     if (section) {
46039566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gSection));
46049566063dSJacob Faibussowitsch       PetscCall(DMCreateSectionSF(dm, section, gSection));
460531ea6d37SMatthew G Knepley     } else {
46060298fd71SBarry Smith       *sf = NULL;
46073ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
460831ea6d37SMatthew G Knepley     }
460988ed4aceSMatthew G Knepley   }
46101bb6d2a8SBarry Smith   *sf = dm->sectionSF;
46113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
461288ed4aceSMatthew G Knepley }
461388ed4aceSMatthew G Knepley 
461488ed4aceSMatthew G Knepley /*@
4615bb7acecfSBarry Smith   DMSetSectionSF - Set the `PetscSF` encoding the parallel dof overlap for the `DM`
461688ed4aceSMatthew G Knepley 
461788ed4aceSMatthew G Knepley   Input Parameters:
4618bb7acecfSBarry Smith + dm - The `DM`
4619bb7acecfSBarry Smith - sf - The `PetscSF`
462088ed4aceSMatthew G Knepley 
462188ed4aceSMatthew G Knepley   Level: intermediate
462288ed4aceSMatthew G Knepley 
4623bb7acecfSBarry Smith   Note:
4624bb7acecfSBarry Smith   Any previous `PetscSF` is destroyed
462588ed4aceSMatthew G Knepley 
4626*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMCreateSectionSF()`
462788ed4aceSMatthew G Knepley @*/
4628d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf)
4629d71ae5a4SJacob Faibussowitsch {
463088ed4aceSMatthew G Knepley   PetscFunctionBegin;
463188ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4632b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
46339566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
46349566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sectionSF));
46351bb6d2a8SBarry Smith   dm->sectionSF = sf;
46363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
463788ed4aceSMatthew G Knepley }
463888ed4aceSMatthew G Knepley 
463988ed4aceSMatthew G Knepley /*@C
4640bb7acecfSBarry Smith   DMCreateSectionSF - Create the `PetscSF` encoding the parallel dof overlap for the `DM` based upon the `PetscSection`s
464188ed4aceSMatthew G Knepley   describing the data layout.
464288ed4aceSMatthew G Knepley 
464388ed4aceSMatthew G Knepley   Input Parameters:
4644bb7acecfSBarry Smith + dm - The `DM`
4645bb7acecfSBarry Smith . localSection - `PetscSection` describing the local data layout
4646bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
464788ed4aceSMatthew G Knepley 
46481bb6d2a8SBarry Smith   Level: developer
46491bb6d2a8SBarry Smith 
4650bb7acecfSBarry Smith   Note:
4651bb7acecfSBarry Smith   One usually uses `DMGetSectionSF()` to obtain the `PetscSF`
4652bb7acecfSBarry Smith 
4653bb7acecfSBarry Smith   Developer Note:
4654bb7acecfSBarry Smith   Since this routine has for arguments the two sections from the `DM` and puts the resulting `PetscSF`
4655bb7acecfSBarry Smith   directly into the `DM`, perhaps this function should not take the local and global sections as
4656bb7acecfSBarry Smith   input and should just obtain them from the `DM`?
46571bb6d2a8SBarry Smith 
4658*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
465988ed4aceSMatthew G Knepley @*/
4660d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection)
4661d71ae5a4SJacob Faibussowitsch {
466288ed4aceSMatthew G Knepley   PetscFunctionBegin;
466388ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46649566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphSection(dm->sectionSF, localSection, globalSection));
46653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
466688ed4aceSMatthew G Knepley }
4667af122d2aSMatthew G Knepley 
4668b21d0597SMatthew G Knepley /*@
4669bb7acecfSBarry Smith   DMGetPointSF - Get the `PetscSF` encoding the parallel section point overlap for the `DM`.
4670bb7acecfSBarry Smith 
4671bb7acecfSBarry Smith   Not collective but the resulting `PetscSF` is collective
4672b21d0597SMatthew G Knepley 
4673b21d0597SMatthew G Knepley   Input Parameter:
4674bb7acecfSBarry Smith . dm - The `DM`
4675b21d0597SMatthew G Knepley 
4676b21d0597SMatthew G Knepley   Output Parameter:
4677bb7acecfSBarry Smith . sf - The `PetscSF`
4678b21d0597SMatthew G Knepley 
4679b21d0597SMatthew G Knepley   Level: intermediate
4680b21d0597SMatthew G Knepley 
4681bb7acecfSBarry Smith   Note:
4682bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
4683b21d0597SMatthew G Knepley 
4684*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4685b21d0597SMatthew G Knepley @*/
4686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
4687d71ae5a4SJacob Faibussowitsch {
4688b21d0597SMatthew G Knepley   PetscFunctionBegin;
4689b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4690b21d0597SMatthew G Knepley   PetscValidPointer(sf, 2);
4691b21d0597SMatthew G Knepley   *sf = dm->sf;
46923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4693b21d0597SMatthew G Knepley }
4694b21d0597SMatthew G Knepley 
4695057b4bcdSMatthew G Knepley /*@
4696bb7acecfSBarry Smith   DMSetPointSF - Set the `PetscSF` encoding the parallel section point overlap for the `DM`.
4697bb7acecfSBarry Smith 
469820f4b53cSBarry Smith   Collective
4699057b4bcdSMatthew G Knepley 
4700057b4bcdSMatthew G Knepley   Input Parameters:
4701bb7acecfSBarry Smith + dm - The `DM`
4702bb7acecfSBarry Smith - sf - The `PetscSF`
4703057b4bcdSMatthew G Knepley 
4704057b4bcdSMatthew G Knepley   Level: intermediate
4705057b4bcdSMatthew G Knepley 
4706*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4707057b4bcdSMatthew G Knepley @*/
4708d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
4709d71ae5a4SJacob Faibussowitsch {
4710057b4bcdSMatthew G Knepley   PetscFunctionBegin;
4711057b4bcdSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4712b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47139566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47149566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sf));
4715057b4bcdSMatthew G Knepley   dm->sf = sf;
47163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4717057b4bcdSMatthew G Knepley }
4718057b4bcdSMatthew G Knepley 
47194f37162bSMatthew G. Knepley /*@
4720bb7acecfSBarry Smith   DMGetNaturalSF - Get the `PetscSF` encoding the map back to the original mesh ordering
47214f37162bSMatthew G. Knepley 
47224f37162bSMatthew G. Knepley   Input Parameter:
4723bb7acecfSBarry Smith . dm - The `DM`
47244f37162bSMatthew G. Knepley 
47254f37162bSMatthew G. Knepley   Output Parameter:
4726bb7acecfSBarry Smith . sf - The `PetscSF`
47274f37162bSMatthew G. Knepley 
47284f37162bSMatthew G. Knepley   Level: intermediate
47294f37162bSMatthew G. Knepley 
4730bb7acecfSBarry Smith   Note:
4731bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
47324f37162bSMatthew G. Knepley 
4733*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
47344f37162bSMatthew G. Knepley @*/
4735d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNaturalSF(DM dm, PetscSF *sf)
4736d71ae5a4SJacob Faibussowitsch {
47374f37162bSMatthew G. Knepley   PetscFunctionBegin;
47384f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47394f37162bSMatthew G. Knepley   PetscValidPointer(sf, 2);
47404f37162bSMatthew G. Knepley   *sf = dm->sfNatural;
47413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47424f37162bSMatthew G. Knepley }
47434f37162bSMatthew G. Knepley 
47444f37162bSMatthew G. Knepley /*@
47454f37162bSMatthew G. Knepley   DMSetNaturalSF - Set the PetscSF encoding the map back to the original mesh ordering
47464f37162bSMatthew G. Knepley 
47474f37162bSMatthew G. Knepley   Input Parameters:
47484f37162bSMatthew G. Knepley + dm - The DM
47494f37162bSMatthew G. Knepley - sf - The PetscSF
47504f37162bSMatthew G. Knepley 
47514f37162bSMatthew G. Knepley   Level: intermediate
47524f37162bSMatthew G. Knepley 
4753*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
47544f37162bSMatthew G. Knepley @*/
4755d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNaturalSF(DM dm, PetscSF sf)
4756d71ae5a4SJacob Faibussowitsch {
47574f37162bSMatthew G. Knepley   PetscFunctionBegin;
47584f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47594f37162bSMatthew G. Knepley   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47609566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47619566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sfNatural));
47624f37162bSMatthew G. Knepley   dm->sfNatural = sf;
47633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47644f37162bSMatthew G. Knepley }
47654f37162bSMatthew G. Knepley 
4766d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc)
4767d71ae5a4SJacob Faibussowitsch {
476834aa8a36SMatthew G. Knepley   PetscClassId id;
476934aa8a36SMatthew G. Knepley 
477034aa8a36SMatthew G. Knepley   PetscFunctionBegin;
47719566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId(disc, &id));
477234aa8a36SMatthew G. Knepley   if (id == PETSCFE_CLASSID) {
47739566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
477434aa8a36SMatthew G. Knepley   } else if (id == PETSCFV_CLASSID) {
47759566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE));
477617c1d62eSMatthew G. Knepley   } else {
47779566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
477834aa8a36SMatthew G. Knepley   }
47793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
478034aa8a36SMatthew G. Knepley }
478134aa8a36SMatthew G. Knepley 
4782d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew)
4783d71ae5a4SJacob Faibussowitsch {
478444a7f3ddSMatthew G. Knepley   RegionField *tmpr;
478544a7f3ddSMatthew G. Knepley   PetscInt     Nf = dm->Nf, f;
478644a7f3ddSMatthew G. Knepley 
478744a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
47883ba16761SJacob Faibussowitsch   if (Nf >= NfNew) PetscFunctionReturn(PETSC_SUCCESS);
47899566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NfNew, &tmpr));
479044a7f3ddSMatthew G. Knepley   for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f];
47919371c9d4SSatish Balay   for (f = Nf; f < NfNew; ++f) {
47929371c9d4SSatish Balay     tmpr[f].disc        = NULL;
47939371c9d4SSatish Balay     tmpr[f].label       = NULL;
47949371c9d4SSatish Balay     tmpr[f].avoidTensor = PETSC_FALSE;
47959371c9d4SSatish Balay   }
47969566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
479744a7f3ddSMatthew G. Knepley   dm->Nf     = NfNew;
479844a7f3ddSMatthew G. Knepley   dm->fields = tmpr;
47993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
480044a7f3ddSMatthew G. Knepley }
480144a7f3ddSMatthew G. Knepley 
480244a7f3ddSMatthew G. Knepley /*@
480320f4b53cSBarry Smith   DMClearFields - Remove all fields from the `DM`
480444a7f3ddSMatthew G. Knepley 
480520f4b53cSBarry Smith   Logically Collective
480644a7f3ddSMatthew G. Knepley 
480744a7f3ddSMatthew G. Knepley   Input Parameter:
480820f4b53cSBarry Smith . dm - The `DM`
480944a7f3ddSMatthew G. Knepley 
481044a7f3ddSMatthew G. Knepley   Level: intermediate
481144a7f3ddSMatthew G. Knepley 
4812*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumFields()`, `DMSetNumFields()`, `DMSetField()`
481344a7f3ddSMatthew G. Knepley @*/
4814d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearFields(DM dm)
4815d71ae5a4SJacob Faibussowitsch {
481644a7f3ddSMatthew G. Knepley   PetscInt f;
481744a7f3ddSMatthew G. Knepley 
481844a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
481944a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
482044a7f3ddSMatthew G. Knepley   for (f = 0; f < dm->Nf; ++f) {
48219566063dSJacob Faibussowitsch     PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
48229566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->fields[f].label));
482344a7f3ddSMatthew G. Knepley   }
48249566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
482544a7f3ddSMatthew G. Knepley   dm->fields = NULL;
482644a7f3ddSMatthew G. Knepley   dm->Nf     = 0;
48273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
482844a7f3ddSMatthew G. Knepley }
482944a7f3ddSMatthew G. Knepley 
4830689b5837SMatthew G. Knepley /*@
483120f4b53cSBarry Smith   DMGetNumFields - Get the number of fields in the `DM`
4832689b5837SMatthew G. Knepley 
483320f4b53cSBarry Smith   Not Collective
4834689b5837SMatthew G. Knepley 
4835689b5837SMatthew G. Knepley   Input Parameter:
483620f4b53cSBarry Smith . dm - The `DM`
4837689b5837SMatthew G. Knepley 
4838689b5837SMatthew G. Knepley   Output Parameter:
4839689b5837SMatthew G. Knepley . Nf - The number of fields
4840689b5837SMatthew G. Knepley 
4841689b5837SMatthew G. Knepley   Level: intermediate
4842689b5837SMatthew G. Knepley 
4843*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetNumFields()`, `DMSetField()`
4844689b5837SMatthew G. Knepley @*/
4845d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4846d71ae5a4SJacob Faibussowitsch {
48470f21e855SMatthew G. Knepley   PetscFunctionBegin;
48480f21e855SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4849534a8f05SLisandro Dalcin   PetscValidIntPointer(numFields, 2);
485044a7f3ddSMatthew G. Knepley   *numFields = dm->Nf;
48513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4852af122d2aSMatthew G Knepley }
4853af122d2aSMatthew G Knepley 
4854689b5837SMatthew G. Knepley /*@
485520f4b53cSBarry Smith   DMSetNumFields - Set the number of fields in the `DM`
4856689b5837SMatthew G. Knepley 
485720f4b53cSBarry Smith   Logically Collective
4858689b5837SMatthew G. Knepley 
4859689b5837SMatthew G. Knepley   Input Parameters:
486020f4b53cSBarry Smith + dm - The `DM`
4861689b5837SMatthew G. Knepley - Nf - The number of fields
4862689b5837SMatthew G. Knepley 
4863689b5837SMatthew G. Knepley   Level: intermediate
4864689b5837SMatthew G. Knepley 
4865*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumFields()`, `DMSetField()`
4866689b5837SMatthew G. Knepley @*/
4867d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4868d71ae5a4SJacob Faibussowitsch {
48690f21e855SMatthew G. Knepley   PetscInt Nf, f;
4870af122d2aSMatthew G Knepley 
4871af122d2aSMatthew G Knepley   PetscFunctionBegin;
4872af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48739566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
48740f21e855SMatthew G. Knepley   for (f = Nf; f < numFields; ++f) {
48750f21e855SMatthew G. Knepley     PetscContainer obj;
48760f21e855SMatthew G. Knepley 
48779566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)dm), &obj));
48789566063dSJacob Faibussowitsch     PetscCall(DMAddField(dm, NULL, (PetscObject)obj));
48799566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&obj));
4880af122d2aSMatthew G Knepley   }
48813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4882af122d2aSMatthew G Knepley }
4883af122d2aSMatthew G Knepley 
4884c1929be8SMatthew G. Knepley /*@
4885bb7acecfSBarry Smith   DMGetField - Return the `DMLabel` and discretization object for a given `DM` field
4886c1929be8SMatthew G. Knepley 
488720f4b53cSBarry Smith   Not Collective
4888c1929be8SMatthew G. Knepley 
4889c1929be8SMatthew G. Knepley   Input Parameters:
4890bb7acecfSBarry Smith + dm - The `DM`
4891c1929be8SMatthew G. Knepley - f  - The field number
4892c1929be8SMatthew G. Knepley 
489344a7f3ddSMatthew G. Knepley   Output Parameters:
489420f4b53cSBarry Smith + label - The label indicating the support of the field, or `NULL` for the entire mesh (pass in `NULL` if not needed)
489520f4b53cSBarry Smith - disc - The discretization object (pass in `NULL` if not needed)
4896c1929be8SMatthew G. Knepley 
489744a7f3ddSMatthew G. Knepley   Level: intermediate
4898c1929be8SMatthew G. Knepley 
4899*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMSetField()`
4900c1929be8SMatthew G. Knepley @*/
4901d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *disc)
4902d71ae5a4SJacob Faibussowitsch {
4903af122d2aSMatthew G Knepley   PetscFunctionBegin;
4904af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4905bb7acecfSBarry Smith   PetscValidPointer(disc, 4);
49067a8be351SBarry Smith   PetscCheck((f >= 0) && (f < dm->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, dm->Nf);
490744a7f3ddSMatthew G. Knepley   if (label) *label = dm->fields[f].label;
4908bb7acecfSBarry Smith   if (disc) *disc = dm->fields[f].disc;
49093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4910decb47aaSMatthew G. Knepley }
4911decb47aaSMatthew G. Knepley 
4912083401c6SMatthew G. Knepley /* Does not clear the DS */
4913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField_Internal(DM dm, PetscInt f, DMLabel label, PetscObject disc)
4914d71ae5a4SJacob Faibussowitsch {
4915083401c6SMatthew G. Knepley   PetscFunctionBegin;
49169566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, f + 1));
49179566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->fields[f].label));
49189566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
4919083401c6SMatthew G. Knepley   dm->fields[f].label = label;
4920bb7acecfSBarry Smith   dm->fields[f].disc  = disc;
49219566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
4922bb7acecfSBarry Smith   PetscCall(PetscObjectReference((PetscObject)disc));
49233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4924083401c6SMatthew G. Knepley }
4925083401c6SMatthew G. Knepley 
492646560f82SMatthew G. Knepley /*@C
4927bb7acecfSBarry Smith   DMSetField - Set the discretization object for a given `DM` field. Usually one would call `DMAddField()` which automatically handles
4928bb7acecfSBarry Smith   the field numbering.
4929c1929be8SMatthew G. Knepley 
493020f4b53cSBarry Smith   Logically Collective
4931c1929be8SMatthew G. Knepley 
4932c1929be8SMatthew G. Knepley   Input Parameters:
4933bb7acecfSBarry Smith + dm    - The `DM`
4934c1929be8SMatthew G. Knepley . f     - The field number
493520f4b53cSBarry Smith . label - The label indicating the support of the field, or `NULL` for the entire mesh
4936bb7acecfSBarry Smith - disc - The discretization object
4937c1929be8SMatthew G. Knepley 
493844a7f3ddSMatthew G. Knepley   Level: intermediate
4939c1929be8SMatthew G. Knepley 
4940*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`
4941c1929be8SMatthew G. Knepley @*/
4942d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject disc)
4943d71ae5a4SJacob Faibussowitsch {
4944decb47aaSMatthew G. Knepley   PetscFunctionBegin;
4945decb47aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4946e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
4947bb7acecfSBarry Smith   PetscValidHeader(disc, 4);
49487a8be351SBarry Smith   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
4949bb7acecfSBarry Smith   PetscCall(DMSetField_Internal(dm, f, label, disc));
4950bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, f, disc));
49519566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
49523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
495344a7f3ddSMatthew G. Knepley }
495444a7f3ddSMatthew G. Knepley 
495546560f82SMatthew G. Knepley /*@C
4956bb7acecfSBarry Smith   DMAddField - Add a field to a `DM` object. A field is a function space defined by of a set of discretization points (geometric entities)
4957bb7acecfSBarry Smith   and a discretization object that defines the function space associated with those points.
495844a7f3ddSMatthew G. Knepley 
495920f4b53cSBarry Smith   Logically Collective
496044a7f3ddSMatthew G. Knepley 
496144a7f3ddSMatthew G. Knepley   Input Parameters:
4962bb7acecfSBarry Smith + dm    - The `DM`
496320f4b53cSBarry Smith . label - The label indicating the support of the field, or `NULL` for the entire mesh
4964bb7acecfSBarry Smith - disc - The discretization object
496544a7f3ddSMatthew G. Knepley 
496644a7f3ddSMatthew G. Knepley   Level: intermediate
496744a7f3ddSMatthew G. Knepley 
4968bb7acecfSBarry Smith   Notes:
4969bb7acecfSBarry Smith   The label already exists or will be added to the `DM` with `DMSetLabel()`.
4970bb7acecfSBarry Smith 
4971da81f932SPierre Jolivet   For example, a piecewise continuous pressure field can be defined by coefficients at the cell centers of a mesh and piecewise constant functions
4972bb7acecfSBarry Smith   within each cell. Thus a specific function in the space is defined by the combination of a `Vec` containing the coefficients, a `DM` defining the
4973bb7acecfSBarry Smith   geometry entities, a `DMLabel` indicating a subset of those geometric entities, and a discretization object, such as a `PetscFE`.
4974bb7acecfSBarry Smith 
4975*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLabel()`, `DMSetField()`, `DMGetField()`, `PetscFE`
497644a7f3ddSMatthew G. Knepley @*/
4977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject disc)
4978d71ae5a4SJacob Faibussowitsch {
497944a7f3ddSMatthew G. Knepley   PetscInt Nf = dm->Nf;
498044a7f3ddSMatthew G. Knepley 
498144a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
498244a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4983064a246eSJacob Faibussowitsch   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
4984bb7acecfSBarry Smith   PetscValidHeader(disc, 3);
49859566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, Nf + 1));
498644a7f3ddSMatthew G. Knepley   dm->fields[Nf].label = label;
4987bb7acecfSBarry Smith   dm->fields[Nf].disc  = disc;
49889566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
4989bb7acecfSBarry Smith   PetscCall(PetscObjectReference((PetscObject)disc));
4990bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, Nf, disc));
49919566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
49923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4993af122d2aSMatthew G Knepley }
49946636e97aSMatthew G Knepley 
4995e5e52638SMatthew G. Knepley /*@
4996e0b68406SMatthew Knepley   DMSetFieldAvoidTensor - Set flag to avoid defining the field on tensor cells
4997e0b68406SMatthew Knepley 
499820f4b53cSBarry Smith   Logically Collective
4999e0b68406SMatthew Knepley 
5000e0b68406SMatthew Knepley   Input Parameters:
5001bb7acecfSBarry Smith + dm          - The `DM`
5002e0b68406SMatthew Knepley . f           - The field index
5003bb7acecfSBarry Smith - avoidTensor - `PETSC_TRUE` to skip defining the field on tensor cells
5004e0b68406SMatthew Knepley 
5005e0b68406SMatthew Knepley   Level: intermediate
5006e0b68406SMatthew Knepley 
5007*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetFieldAvoidTensor()`, `DMSetField()`, `DMGetField()`
5008e0b68406SMatthew Knepley @*/
5009d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFieldAvoidTensor(DM dm, PetscInt f, PetscBool avoidTensor)
5010d71ae5a4SJacob Faibussowitsch {
5011e0b68406SMatthew Knepley   PetscFunctionBegin;
501263a3b9bcSJacob Faibussowitsch   PetscCheck((f >= 0) && (f < dm->Nf), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Field %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", f, dm->Nf);
5013e0b68406SMatthew Knepley   dm->fields[f].avoidTensor = avoidTensor;
50143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5015e0b68406SMatthew Knepley }
5016e0b68406SMatthew Knepley 
5017e0b68406SMatthew Knepley /*@
5018e0b68406SMatthew Knepley   DMGetFieldAvoidTensor - Get flag to avoid defining the field on tensor cells
5019e0b68406SMatthew Knepley 
502020f4b53cSBarry Smith   Not Collective
5021e0b68406SMatthew Knepley 
5022e0b68406SMatthew Knepley   Input Parameters:
5023bb7acecfSBarry Smith + dm          - The `DM`
5024e0b68406SMatthew Knepley - f           - The field index
5025e0b68406SMatthew Knepley 
5026e0b68406SMatthew Knepley   Output Parameter:
5027e0b68406SMatthew Knepley . avoidTensor - The flag to avoid defining the field on tensor cells
5028e0b68406SMatthew Knepley 
5029e0b68406SMatthew Knepley   Level: intermediate
5030e0b68406SMatthew Knepley 
5031*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMSetField()`, `DMGetField()`, `DMSetFieldAvoidTensor()`, `DMSetField()`, `DMGetField()`
5032e0b68406SMatthew Knepley @*/
5033d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFieldAvoidTensor(DM dm, PetscInt f, PetscBool *avoidTensor)
5034d71ae5a4SJacob Faibussowitsch {
5035e0b68406SMatthew Knepley   PetscFunctionBegin;
503663a3b9bcSJacob Faibussowitsch   PetscCheck((f >= 0) && (f < dm->Nf), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Field %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", f, dm->Nf);
5037e0b68406SMatthew Knepley   *avoidTensor = dm->fields[f].avoidTensor;
50383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5039e0b68406SMatthew Knepley }
5040e0b68406SMatthew Knepley 
5041e0b68406SMatthew Knepley /*@
5042bb7acecfSBarry Smith   DMCopyFields - Copy the discretizations for the `DM` into another `DM`
5043e5e52638SMatthew G. Knepley 
504420f4b53cSBarry Smith   Collective
5045e5e52638SMatthew G. Knepley 
5046e5e52638SMatthew G. Knepley   Input Parameter:
5047bb7acecfSBarry Smith . dm - The `DM`
5048e5e52638SMatthew G. Knepley 
5049e5e52638SMatthew G. Knepley   Output Parameter:
5050bb7acecfSBarry Smith . newdm - The `DM`
5051e5e52638SMatthew G. Knepley 
5052e5e52638SMatthew G. Knepley   Level: advanced
5053e5e52638SMatthew G. Knepley 
5054*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetField()`, `DMSetField()`, `DMAddField()`, `DMCopyDS()`, `DMGetDS()`, `DMGetCellDS()`
5055e5e52638SMatthew G. Knepley @*/
5056d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyFields(DM dm, DM newdm)
5057d71ae5a4SJacob Faibussowitsch {
5058e5e52638SMatthew G. Knepley   PetscInt Nf, f;
5059e5e52638SMatthew G. Knepley 
5060e5e52638SMatthew G. Knepley   PetscFunctionBegin;
50613ba16761SJacob Faibussowitsch   if (dm == newdm) PetscFunctionReturn(PETSC_SUCCESS);
50629566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
50639566063dSJacob Faibussowitsch   PetscCall(DMClearFields(newdm));
5064e5e52638SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5065e5e52638SMatthew G. Knepley     DMLabel     label;
5066e5e52638SMatthew G. Knepley     PetscObject field;
506734aa8a36SMatthew G. Knepley     PetscBool   useCone, useClosure;
5068e5e52638SMatthew G. Knepley 
50699566063dSJacob Faibussowitsch     PetscCall(DMGetField(dm, f, &label, &field));
50709566063dSJacob Faibussowitsch     PetscCall(DMSetField(newdm, f, label, field));
50719566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, f, &useCone, &useClosure));
50729566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(newdm, f, useCone, useClosure));
507334aa8a36SMatthew G. Knepley   }
50743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
507534aa8a36SMatthew G. Knepley }
507634aa8a36SMatthew G. Knepley 
507734aa8a36SMatthew G. Knepley /*@
507834aa8a36SMatthew G. Knepley   DMGetAdjacency - Returns the flags for determining variable influence
507934aa8a36SMatthew G. Knepley 
508020f4b53cSBarry Smith   Not Collective
508134aa8a36SMatthew G. Knepley 
508234aa8a36SMatthew G. Knepley   Input Parameters:
508320f4b53cSBarry Smith + dm - The `DM` object
508420f4b53cSBarry Smith - f  - The field number, or `PETSC_DEFAULT` for the default adjacency
508534aa8a36SMatthew G. Knepley 
5086d8d19677SJose E. Roman   Output Parameters:
508734aa8a36SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
508834aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
508934aa8a36SMatthew G. Knepley 
509034aa8a36SMatthew G. Knepley   Level: developer
509134aa8a36SMatthew G. Knepley 
509220f4b53cSBarry Smith   Notes:
509320f4b53cSBarry Smith .vb
509420f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
509520f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
509620f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
509720f4b53cSBarry Smith .ve
509820f4b53cSBarry Smith   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
509920f4b53cSBarry Smith 
5100*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetAdjacency()`, `DMGetField()`, `DMSetField()`
510134aa8a36SMatthew G. Knepley @*/
5102d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure)
5103d71ae5a4SJacob Faibussowitsch {
510434aa8a36SMatthew G. Knepley   PetscFunctionBegin;
510534aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5106534a8f05SLisandro Dalcin   if (useCone) PetscValidBoolPointer(useCone, 3);
5107534a8f05SLisandro Dalcin   if (useClosure) PetscValidBoolPointer(useClosure, 4);
510834aa8a36SMatthew G. Knepley   if (f < 0) {
510934aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->adjacency[0];
511034aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->adjacency[1];
511134aa8a36SMatthew G. Knepley   } else {
511234aa8a36SMatthew G. Knepley     PetscInt Nf;
511334aa8a36SMatthew G. Knepley 
51149566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
51157a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
511634aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->fields[f].adjacency[0];
511734aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->fields[f].adjacency[1];
511834aa8a36SMatthew G. Knepley   }
51193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
512034aa8a36SMatthew G. Knepley }
512134aa8a36SMatthew G. Knepley 
512234aa8a36SMatthew G. Knepley /*@
512334aa8a36SMatthew G. Knepley   DMSetAdjacency - Set the flags for determining variable influence
512434aa8a36SMatthew G. Knepley 
512520f4b53cSBarry Smith   Not Collective
512634aa8a36SMatthew G. Knepley 
512734aa8a36SMatthew G. Knepley   Input Parameters:
512820f4b53cSBarry Smith + dm         - The `DM` object
512934aa8a36SMatthew G. Knepley . f          - The field number
513034aa8a36SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
513134aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
513234aa8a36SMatthew G. Knepley 
513334aa8a36SMatthew G. Knepley   Level: developer
513434aa8a36SMatthew G. Knepley 
513520f4b53cSBarry Smith   Notes:
513620f4b53cSBarry Smith .vb
513720f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
513820f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
513920f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
514020f4b53cSBarry Smith .ve
514120f4b53cSBarry Smith   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
514220f4b53cSBarry Smith 
5143*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetAdjacency()`, `DMGetField()`, `DMSetField()`
514434aa8a36SMatthew G. Knepley @*/
5145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure)
5146d71ae5a4SJacob Faibussowitsch {
514734aa8a36SMatthew G. Knepley   PetscFunctionBegin;
514834aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
514934aa8a36SMatthew G. Knepley   if (f < 0) {
515034aa8a36SMatthew G. Knepley     dm->adjacency[0] = useCone;
515134aa8a36SMatthew G. Knepley     dm->adjacency[1] = useClosure;
515234aa8a36SMatthew G. Knepley   } else {
515334aa8a36SMatthew G. Knepley     PetscInt Nf;
515434aa8a36SMatthew G. Knepley 
51559566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
51567a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
515734aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[0] = useCone;
515834aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[1] = useClosure;
5159e5e52638SMatthew G. Knepley   }
51603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5161e5e52638SMatthew G. Knepley }
5162e5e52638SMatthew G. Knepley 
5163b0441da4SMatthew G. Knepley /*@
5164b0441da4SMatthew G. Knepley   DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined
5165b0441da4SMatthew G. Knepley 
5166b0441da4SMatthew G. Knepley   Not collective
5167b0441da4SMatthew G. Knepley 
5168f899ff85SJose E. Roman   Input Parameter:
516920f4b53cSBarry Smith . dm - The `DM` object
5170b0441da4SMatthew G. Knepley 
5171d8d19677SJose E. Roman   Output Parameters:
5172b0441da4SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
5173b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5174b0441da4SMatthew G. Knepley 
5175b0441da4SMatthew G. Knepley   Level: developer
5176b0441da4SMatthew G. Knepley 
517720f4b53cSBarry Smith   Notes:
517820f4b53cSBarry Smith .vb
517920f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
518020f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
518120f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
518220f4b53cSBarry Smith .ve
518320f4b53cSBarry Smith 
5184*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5185b0441da4SMatthew G. Knepley @*/
5186d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure)
5187d71ae5a4SJacob Faibussowitsch {
5188b0441da4SMatthew G. Knepley   PetscInt Nf;
5189b0441da4SMatthew G. Knepley 
5190b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5191b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5192064a246eSJacob Faibussowitsch   if (useCone) PetscValidBoolPointer(useCone, 2);
5193064a246eSJacob Faibussowitsch   if (useClosure) PetscValidBoolPointer(useClosure, 3);
51949566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5195b0441da4SMatthew G. Knepley   if (!Nf) {
51969566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5197b0441da4SMatthew G. Knepley   } else {
51989566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, 0, useCone, useClosure));
5199b0441da4SMatthew G. Knepley   }
52003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5201b0441da4SMatthew G. Knepley }
5202b0441da4SMatthew G. Knepley 
5203b0441da4SMatthew G. Knepley /*@
5204b0441da4SMatthew G. Knepley   DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined
5205b0441da4SMatthew G. Knepley 
520620f4b53cSBarry Smith   Not Collective
5207b0441da4SMatthew G. Knepley 
5208b0441da4SMatthew G. Knepley   Input Parameters:
520920f4b53cSBarry Smith + dm         - The `DM` object
5210b0441da4SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
5211b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5212b0441da4SMatthew G. Knepley 
5213b0441da4SMatthew G. Knepley   Level: developer
5214b0441da4SMatthew G. Knepley 
521520f4b53cSBarry Smith   Notes:
521620f4b53cSBarry Smith .vb
521720f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
521820f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
521920f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
522020f4b53cSBarry Smith .ve
522120f4b53cSBarry Smith 
5222*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5223b0441da4SMatthew G. Knepley @*/
5224d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure)
5225d71ae5a4SJacob Faibussowitsch {
5226b0441da4SMatthew G. Knepley   PetscInt Nf;
5227b0441da4SMatthew G. Knepley 
5228b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5229b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52309566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5231b0441da4SMatthew G. Knepley   if (!Nf) {
52329566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5233b0441da4SMatthew G. Knepley   } else {
52349566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, 0, useCone, useClosure));
5235e5e52638SMatthew G. Knepley   }
52363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5237e5e52638SMatthew G. Knepley }
5238e5e52638SMatthew G. Knepley 
5239d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompleteBCLabels_Internal(DM dm)
5240d71ae5a4SJacob Faibussowitsch {
5241799db056SMatthew G. Knepley   DM           plex;
5242799db056SMatthew G. Knepley   DMLabel     *labels, *glabels;
5243799db056SMatthew G. Knepley   const char **names;
5244799db056SMatthew G. Knepley   char        *sendNames, *recvNames;
5245799db056SMatthew G. Knepley   PetscInt     Nds, s, maxLabels = 0, maxLen = 0, gmaxLen, Nl = 0, gNl, l, gl, m;
5246799db056SMatthew G. Knepley   size_t       len;
5247799db056SMatthew G. Knepley   MPI_Comm     comm;
5248799db056SMatthew G. Knepley   PetscMPIInt  rank, size, p, *counts, *displs;
5249783e2ec8SMatthew G. Knepley 
5250783e2ec8SMatthew G. Knepley   PetscFunctionBegin;
5251799db056SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5252799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
5253799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5254799db056SMatthew G. Knepley   PetscCall(DMGetNumDS(dm, &Nds));
5255799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5256799db056SMatthew G. Knepley     PetscDS  dsBC;
5257799db056SMatthew G. Knepley     PetscInt numBd;
5258799db056SMatthew G. Knepley 
525907218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC, NULL));
5260799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5261799db056SMatthew G. Knepley     maxLabels += numBd;
5262799db056SMatthew G. Knepley   }
5263799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(maxLabels, &labels));
5264799db056SMatthew G. Knepley   /* Get list of labels to be completed */
5265799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5266799db056SMatthew G. Knepley     PetscDS  dsBC;
5267799db056SMatthew G. Knepley     PetscInt numBd, bd;
5268799db056SMatthew G. Knepley 
526907218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC, NULL));
5270799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5271799db056SMatthew G. Knepley     for (bd = 0; bd < numBd; ++bd) {
5272799db056SMatthew G. Knepley       DMLabel      label;
5273799db056SMatthew G. Knepley       PetscInt     field;
5274799db056SMatthew G. Knepley       PetscObject  obj;
5275799db056SMatthew G. Knepley       PetscClassId id;
5276799db056SMatthew G. Knepley 
5277799db056SMatthew G. Knepley       PetscCall(PetscDSGetBoundary(dsBC, bd, NULL, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
52789566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, field, NULL, &obj));
52799566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
5280799db056SMatthew G. Knepley       if (!(id == PETSCFE_CLASSID) || !label) continue;
52819371c9d4SSatish Balay       for (l = 0; l < Nl; ++l)
52829371c9d4SSatish Balay         if (labels[l] == label) break;
5283799db056SMatthew G. Knepley       if (l == Nl) labels[Nl++] = label;
5284783e2ec8SMatthew G. Knepley     }
5285799db056SMatthew G. Knepley   }
5286799db056SMatthew G. Knepley   /* Get label names */
5287799db056SMatthew G. Knepley   PetscCall(PetscMalloc1(Nl, &names));
5288799db056SMatthew G. Knepley   for (l = 0; l < Nl; ++l) PetscCall(PetscObjectGetName((PetscObject)labels[l], &names[l]));
52899371c9d4SSatish Balay   for (l = 0; l < Nl; ++l) {
52909371c9d4SSatish Balay     PetscCall(PetscStrlen(names[l], &len));
52919371c9d4SSatish Balay     maxLen = PetscMax(maxLen, (PetscInt)len + 2);
52929371c9d4SSatish Balay   }
5293799db056SMatthew G. Knepley   PetscCall(PetscFree(labels));
5294712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&maxLen, &gmaxLen, 1, MPIU_INT, MPI_MAX, comm));
5295799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(Nl * gmaxLen, &sendNames));
5296c6a7a370SJeremy L Thompson   for (l = 0; l < Nl; ++l) PetscCall(PetscStrncpy(&sendNames[gmaxLen * l], names[l], gmaxLen));
5297799db056SMatthew G. Knepley   PetscCall(PetscFree(names));
5298799db056SMatthew G. Knepley   /* Put all names on all processes */
5299799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(size, &counts, size + 1, &displs));
5300799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgather(&Nl, 1, MPI_INT, counts, 1, MPI_INT, comm));
5301799db056SMatthew G. Knepley   for (p = 0; p < size; ++p) displs[p + 1] = displs[p] + counts[p];
5302799db056SMatthew G. Knepley   gNl = displs[size];
53039371c9d4SSatish Balay   for (p = 0; p < size; ++p) {
53049371c9d4SSatish Balay     counts[p] *= gmaxLen;
53059371c9d4SSatish Balay     displs[p] *= gmaxLen;
53069371c9d4SSatish Balay   }
5307799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(gNl * gmaxLen, &recvNames, gNl, &glabels));
5308799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgatherv(sendNames, counts[rank], MPI_CHAR, recvNames, counts, displs, MPI_CHAR, comm));
5309799db056SMatthew G. Knepley   PetscCall(PetscFree2(counts, displs));
5310799db056SMatthew G. Knepley   PetscCall(PetscFree(sendNames));
5311799db056SMatthew G. Knepley   for (l = 0, gl = 0; l < gNl; ++l) {
5312799db056SMatthew G. Knepley     PetscCall(DMGetLabel(dm, &recvNames[l * gmaxLen], &glabels[gl]));
5313799db056SMatthew G. Knepley     PetscCheck(glabels[gl], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Label %s missing on rank %d", &recvNames[l * gmaxLen], rank);
53149371c9d4SSatish Balay     for (m = 0; m < gl; ++m)
53159371c9d4SSatish Balay       if (glabels[m] == glabels[gl]) continue;
53169566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
5317799db056SMatthew G. Knepley     PetscCall(DMPlexLabelComplete(plex, glabels[gl]));
53189566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5319799db056SMatthew G. Knepley     ++gl;
5320783e2ec8SMatthew G. Knepley   }
5321799db056SMatthew G. Knepley   PetscCall(PetscFree2(recvNames, glabels));
53223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5323783e2ec8SMatthew G. Knepley }
5324783e2ec8SMatthew G. Knepley 
5325d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew)
5326d71ae5a4SJacob Faibussowitsch {
5327e5e52638SMatthew G. Knepley   DMSpace *tmpd;
5328e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5329e5e52638SMatthew G. Knepley 
5330e5e52638SMatthew G. Knepley   PetscFunctionBegin;
53313ba16761SJacob Faibussowitsch   if (Nds >= NdsNew) PetscFunctionReturn(PETSC_SUCCESS);
53329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NdsNew, &tmpd));
5333e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s];
53349371c9d4SSatish Balay   for (s = Nds; s < NdsNew; ++s) {
53359371c9d4SSatish Balay     tmpd[s].ds     = NULL;
53369371c9d4SSatish Balay     tmpd[s].label  = NULL;
53379371c9d4SSatish Balay     tmpd[s].fields = NULL;
53389371c9d4SSatish Balay   }
53399566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5340e5e52638SMatthew G. Knepley   dm->Nds   = NdsNew;
5341e5e52638SMatthew G. Knepley   dm->probs = tmpd;
53423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5343e5e52638SMatthew G. Knepley }
5344e5e52638SMatthew G. Knepley 
5345e5e52638SMatthew G. Knepley /*@
534620f4b53cSBarry Smith   DMGetNumDS - Get the number of discrete systems in the `DM`
5347e5e52638SMatthew G. Knepley 
534820f4b53cSBarry Smith   Not Collective
5349e5e52638SMatthew G. Knepley 
5350e5e52638SMatthew G. Knepley   Input Parameter:
535120f4b53cSBarry Smith . dm - The `DM`
5352e5e52638SMatthew G. Knepley 
5353e5e52638SMatthew G. Knepley   Output Parameter:
535420f4b53cSBarry Smith . Nds - The number of `PetscDS` objects
5355e5e52638SMatthew G. Knepley 
5356e5e52638SMatthew G. Knepley   Level: intermediate
5357e5e52638SMatthew G. Knepley 
5358*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDS()`, `DMGetCellDS()`
5359e5e52638SMatthew G. Knepley @*/
5360d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds)
5361d71ae5a4SJacob Faibussowitsch {
5362e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5363e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5364534a8f05SLisandro Dalcin   PetscValidIntPointer(Nds, 2);
5365e5e52638SMatthew G. Knepley   *Nds = dm->Nds;
53663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5367e5e52638SMatthew G. Knepley }
5368e5e52638SMatthew G. Knepley 
5369e5e52638SMatthew G. Knepley /*@
537020f4b53cSBarry Smith   DMClearDS - Remove all discrete systems from the `DM`
5371e5e52638SMatthew G. Knepley 
537220f4b53cSBarry Smith   Logically Collective
5373e5e52638SMatthew G. Knepley 
5374e5e52638SMatthew G. Knepley   Input Parameter:
537520f4b53cSBarry Smith . dm - The `DM`
5376e5e52638SMatthew G. Knepley 
5377e5e52638SMatthew G. Knepley   Level: intermediate
5378e5e52638SMatthew G. Knepley 
5379*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumDS()`, `DMGetDS()`, `DMSetField()`
5380e5e52638SMatthew G. Knepley @*/
5381d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearDS(DM dm)
5382d71ae5a4SJacob Faibussowitsch {
5383e5e52638SMatthew G. Knepley   PetscInt s;
5384e5e52638SMatthew G. Knepley 
5385e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5386e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5387e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
53889566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[s].ds));
538907218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dm->probs[s].dsIn));
53909566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->probs[s].label));
53919566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[s].fields));
5392e5e52638SMatthew G. Knepley   }
53939566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5394e5e52638SMatthew G. Knepley   dm->probs = NULL;
5395e5e52638SMatthew G. Knepley   dm->Nds   = 0;
53963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5397e5e52638SMatthew G. Knepley }
5398e5e52638SMatthew G. Knepley 
5399e5e52638SMatthew G. Knepley /*@
540020f4b53cSBarry Smith   DMGetDS - Get the default `PetscDS`
5401e5e52638SMatthew G. Knepley 
540220f4b53cSBarry Smith   Not Collective
5403e5e52638SMatthew G. Knepley 
5404e5e52638SMatthew G. Knepley   Input Parameter:
540520f4b53cSBarry Smith . dm - The `DM`
5406e5e52638SMatthew G. Knepley 
5407e5e52638SMatthew G. Knepley   Output Parameter:
540807218a29SMatthew G. Knepley . ds - The default `PetscDS`
5409e5e52638SMatthew G. Knepley 
5410e5e52638SMatthew G. Knepley   Level: intermediate
5411e5e52638SMatthew G. Knepley 
5412*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetCellDS()`, `DMGetRegionDS()`
5413e5e52638SMatthew G. Knepley @*/
541407218a29SMatthew G. Knepley PetscErrorCode DMGetDS(DM dm, PetscDS *ds)
5415d71ae5a4SJacob Faibussowitsch {
5416e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5417e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
541807218a29SMatthew G. Knepley   PetscValidPointer(ds, 2);
541907218a29SMatthew G. Knepley   PetscCheck(dm->Nds > 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Need to call DMCreateDS() before calling DMGetDS()");
542007218a29SMatthew G. Knepley   *ds = dm->probs[0].ds;
54213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5422e5e52638SMatthew G. Knepley }
5423e5e52638SMatthew G. Knepley 
5424e5e52638SMatthew G. Knepley /*@
542520f4b53cSBarry Smith   DMGetCellDS - Get the `PetscDS` defined on a given cell
5426e5e52638SMatthew G. Knepley 
542720f4b53cSBarry Smith   Not Collective
5428e5e52638SMatthew G. Knepley 
5429e5e52638SMatthew G. Knepley   Input Parameters:
543020f4b53cSBarry Smith + dm    - The `DM`
543120f4b53cSBarry Smith - point - Cell for the `PetscDS`
5432e5e52638SMatthew G. Knepley 
543307218a29SMatthew G. Knepley   Output Parameters:
543407218a29SMatthew G. Knepley + ds   - The `PetscDS` defined on the given cell
543507218a29SMatthew G. Knepley - dsIn - The `PetscDS` for input on the given cell, or NULL if the same ds
5436e5e52638SMatthew G. Knepley 
5437e5e52638SMatthew G. Knepley   Level: developer
5438e5e52638SMatthew G. Knepley 
5439*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDS()`, `DMSetRegionDS()`
5440e5e52638SMatthew G. Knepley @*/
544107218a29SMatthew G. Knepley PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *ds, PetscDS *dsIn)
5442d71ae5a4SJacob Faibussowitsch {
544307218a29SMatthew G. Knepley   PetscDS  dsDef = NULL;
5444e5e52638SMatthew G. Knepley   PetscInt s;
5445e5e52638SMatthew G. Knepley 
5446e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5447e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
544807218a29SMatthew G. Knepley   if (ds) PetscValidPointer(ds, 3);
544907218a29SMatthew G. Knepley   if (dsIn) PetscValidPointer(dsIn, 4);
545063a3b9bcSJacob Faibussowitsch   PetscCheck(point >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %" PetscInt_FMT, point);
545107218a29SMatthew G. Knepley   if (ds) *ds = NULL;
545207218a29SMatthew G. Knepley   if (dsIn) *dsIn = NULL;
5453e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5454e5e52638SMatthew G. Knepley     PetscInt val;
5455e5e52638SMatthew G. Knepley 
54569371c9d4SSatish Balay     if (!dm->probs[s].label) {
545707218a29SMatthew G. Knepley       dsDef = dm->probs[s].ds;
54589371c9d4SSatish Balay     } else {
54599566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(dm->probs[s].label, point, &val));
54609371c9d4SSatish Balay       if (val >= 0) {
546107218a29SMatthew G. Knepley         if (ds) *ds = dm->probs[s].ds;
546207218a29SMatthew G. Knepley         if (dsIn) *dsIn = dm->probs[s].dsIn;
54639371c9d4SSatish Balay         break;
54649371c9d4SSatish Balay       }
5465e5e52638SMatthew G. Knepley     }
5466e5e52638SMatthew G. Knepley   }
546707218a29SMatthew G. Knepley   if (ds && !*ds) *ds = dsDef;
54683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5469e5e52638SMatthew G. Knepley }
5470e5e52638SMatthew G. Knepley 
5471e5e52638SMatthew G. Knepley /*@
547220f4b53cSBarry Smith   DMGetRegionDS - Get the `PetscDS` for a given mesh region, defined by a `DMLabel`
5473e5e52638SMatthew G. Knepley 
547420f4b53cSBarry Smith   Not Collective
5475e5e52638SMatthew G. Knepley 
5476e5e52638SMatthew G. Knepley   Input Parameters:
547720f4b53cSBarry Smith + dm    - The `DM`
547820f4b53cSBarry Smith - label - The `DMLabel` defining the mesh region, or `NULL` for the entire mesh
5479e5e52638SMatthew G. Knepley 
5480b3cf3223SMatthew G. Knepley   Output Parameters:
548120f4b53cSBarry Smith + fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL`
548207218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL`
548307218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input in the given region, or `NULL`
5484e5e52638SMatthew G. Knepley 
5485e5e52638SMatthew G. Knepley   Level: advanced
5486e5e52638SMatthew G. Knepley 
548720f4b53cSBarry Smith   Note:
548820f4b53cSBarry Smith   If a non-`NULL` label is given, but there is no `PetscDS` on that specific label,
548920f4b53cSBarry Smith   the `PetscDS` for the full domain (if present) is returned. Returns with
549007218a29SMatthew G. Knepley   fields = `NULL` and ds = `NULL` if there is no `PetscDS` for the full domain.
549120f4b53cSBarry Smith 
5492*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionNumDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5493e5e52638SMatthew G. Knepley @*/
549407218a29SMatthew G. Knepley PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds, PetscDS *dsIn)
5495d71ae5a4SJacob Faibussowitsch {
5496e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5497e5e52638SMatthew G. Knepley 
5498e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5499e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5500e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
55019371c9d4SSatish Balay   if (fields) {
55029371c9d4SSatish Balay     PetscValidPointer(fields, 3);
55039371c9d4SSatish Balay     *fields = NULL;
55049371c9d4SSatish Balay   }
55059371c9d4SSatish Balay   if (ds) {
55069371c9d4SSatish Balay     PetscValidPointer(ds, 4);
55079371c9d4SSatish Balay     *ds = NULL;
55089371c9d4SSatish Balay   }
550907218a29SMatthew G. Knepley   if (dsIn) {
551007218a29SMatthew G. Knepley     PetscValidPointer(dsIn, 5);
551107218a29SMatthew G. Knepley     *dsIn = NULL;
551207218a29SMatthew G. Knepley   }
5513e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5514154ca461SJed Brown     if (dm->probs[s].label == label || !dm->probs[s].label) {
5515b3cf3223SMatthew G. Knepley       if (fields) *fields = dm->probs[s].fields;
5516b3cf3223SMatthew G. Knepley       if (ds) *ds = dm->probs[s].ds;
551707218a29SMatthew G. Knepley       if (dsIn) *dsIn = dm->probs[s].dsIn;
55183ba16761SJacob Faibussowitsch       if (dm->probs[s].label) PetscFunctionReturn(PETSC_SUCCESS);
5519b3cf3223SMatthew G. Knepley     }
5520e5e52638SMatthew G. Knepley   }
55213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5522e5e52638SMatthew G. Knepley }
5523e5e52638SMatthew G. Knepley 
5524e5e52638SMatthew G. Knepley /*@
5525bb7acecfSBarry Smith   DMSetRegionDS - Set the `PetscDS` for a given mesh region, defined by a `DMLabel`
5526083401c6SMatthew G. Knepley 
552720f4b53cSBarry Smith   Collective
5528083401c6SMatthew G. Knepley 
5529083401c6SMatthew G. Knepley   Input Parameters:
5530bb7acecfSBarry Smith + dm     - The `DM`
553120f4b53cSBarry Smith . label  - The `DMLabel` defining the mesh region, or `NULL` for the entire mesh
553207218a29SMatthew G. Knepley . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL` for all fields
553307218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region
553407218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input on the given cell, or `NULL` if it is the same `PetscDS`
5535083401c6SMatthew G. Knepley 
553620f4b53cSBarry Smith   Level: advanced
553720f4b53cSBarry Smith 
5538bb7acecfSBarry Smith   Note:
5539bb7acecfSBarry Smith   If the label has a `PetscDS` defined, it will be replaced. Otherwise, it will be added to the `DM`. If the `PetscDS` is replaced,
5540083401c6SMatthew G. Knepley   the fields argument is ignored.
5541083401c6SMatthew G. Knepley 
5542*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionNumDS()`, `DMGetDS()`, `DMGetCellDS()`
5543083401c6SMatthew G. Knepley @*/
554407218a29SMatthew G. Knepley PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds, PetscDS dsIn)
5545d71ae5a4SJacob Faibussowitsch {
5546083401c6SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5547083401c6SMatthew G. Knepley 
5548083401c6SMatthew G. Knepley   PetscFunctionBegin;
5549083401c6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5550083401c6SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
555107218a29SMatthew G. Knepley   if (fields) PetscValidHeaderSpecific(fields, IS_CLASSID, 3);
5552064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 4);
555307218a29SMatthew G. Knepley   if (dsIn) PetscValidHeaderSpecific(dsIn, PETSCDS_CLASSID, 5);
5554083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5555083401c6SMatthew G. Knepley     if (dm->probs[s].label == label) {
55569566063dSJacob Faibussowitsch       PetscCall(PetscDSDestroy(&dm->probs[s].ds));
555707218a29SMatthew G. Knepley       PetscCall(PetscDSDestroy(&dm->probs[s].dsIn));
5558083401c6SMatthew G. Knepley       dm->probs[s].ds   = ds;
555907218a29SMatthew G. Knepley       dm->probs[s].dsIn = dsIn;
55603ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
5561083401c6SMatthew G. Knepley     }
5562083401c6SMatthew G. Knepley   }
55639566063dSJacob Faibussowitsch   PetscCall(DMDSEnlarge_Static(dm, Nds + 1));
55649566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
55659566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fields));
55669566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ds));
556707218a29SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)dsIn));
5568083401c6SMatthew G. Knepley   if (!label) {
5569083401c6SMatthew G. Knepley     /* Put the NULL label at the front, so it is returned as the default */
5570083401c6SMatthew G. Knepley     for (s = Nds - 1; s >= 0; --s) dm->probs[s + 1] = dm->probs[s];
5571083401c6SMatthew G. Knepley     Nds = 0;
5572083401c6SMatthew G. Knepley   }
5573083401c6SMatthew G. Knepley   dm->probs[Nds].label  = label;
5574083401c6SMatthew G. Knepley   dm->probs[Nds].fields = fields;
5575083401c6SMatthew G. Knepley   dm->probs[Nds].ds     = ds;
557607218a29SMatthew G. Knepley   dm->probs[Nds].dsIn   = dsIn;
55773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5578083401c6SMatthew G. Knepley }
5579083401c6SMatthew G. Knepley 
5580083401c6SMatthew G. Knepley /*@
558120f4b53cSBarry Smith   DMGetRegionNumDS - Get the `PetscDS` for a given mesh region, defined by the region number
5582e5e52638SMatthew G. Knepley 
558320f4b53cSBarry Smith   Not Collective
5584e5e52638SMatthew G. Knepley 
5585e5e52638SMatthew G. Knepley   Input Parameters:
558620f4b53cSBarry Smith + dm  - The `DM`
5587e5e52638SMatthew G. Knepley - num - The region number, in [0, Nds)
5588e5e52638SMatthew G. Knepley 
5589e5e52638SMatthew G. Knepley   Output Parameters:
559020f4b53cSBarry Smith + label  - The region label, or `NULL`
559120f4b53cSBarry Smith . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL`
559207218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL`
559307218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input in the given region, or `NULL`
5594e5e52638SMatthew G. Knepley 
5595e5e52638SMatthew G. Knepley   Level: advanced
5596e5e52638SMatthew G. Knepley 
5597*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5598e5e52638SMatthew G. Knepley @*/
559907218a29SMatthew G. Knepley PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds, PetscDS *dsIn)
5600d71ae5a4SJacob Faibussowitsch {
5601e5e52638SMatthew G. Knepley   PetscInt Nds;
5602e5e52638SMatthew G. Knepley 
5603e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5604e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56059566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
560663a3b9bcSJacob Faibussowitsch   PetscCheck((num >= 0) && (num < Nds), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", num, Nds);
5607e5e52638SMatthew G. Knepley   if (label) {
5608e5e52638SMatthew G. Knepley     PetscValidPointer(label, 3);
5609e5e52638SMatthew G. Knepley     *label = dm->probs[num].label;
5610e5e52638SMatthew G. Knepley   }
5611b3cf3223SMatthew G. Knepley   if (fields) {
5612b3cf3223SMatthew G. Knepley     PetscValidPointer(fields, 4);
5613b3cf3223SMatthew G. Knepley     *fields = dm->probs[num].fields;
5614b3cf3223SMatthew G. Knepley   }
5615e5e52638SMatthew G. Knepley   if (ds) {
5616b3cf3223SMatthew G. Knepley     PetscValidPointer(ds, 5);
5617e5e52638SMatthew G. Knepley     *ds = dm->probs[num].ds;
5618e5e52638SMatthew G. Knepley   }
561907218a29SMatthew G. Knepley   if (dsIn) {
562007218a29SMatthew G. Knepley     PetscValidPointer(dsIn, 6);
562107218a29SMatthew G. Knepley     *dsIn = dm->probs[num].dsIn;
562207218a29SMatthew G. Knepley   }
56233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5624e5e52638SMatthew G. Knepley }
5625e5e52638SMatthew G. Knepley 
5626e5e52638SMatthew G. Knepley /*@
562720f4b53cSBarry Smith   DMSetRegionNumDS - Set the `PetscDS` for a given mesh region, defined by the region number
5628e5e52638SMatthew G. Knepley 
562920f4b53cSBarry Smith   Not Collective
5630e5e52638SMatthew G. Knepley 
5631e5e52638SMatthew G. Knepley   Input Parameters:
563220f4b53cSBarry Smith + dm     - The `DM`
5633083401c6SMatthew G. Knepley . num    - The region number, in [0, Nds)
563420f4b53cSBarry Smith . label  - The region label, or `NULL`
563507218a29SMatthew G. Knepley . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL` to prevent setting
563607218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL` to prevent setting
563707218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input on the given cell, or `NULL` if it is the same `PetscDS`
5638e5e52638SMatthew G. Knepley 
5639e5e52638SMatthew G. Knepley   Level: advanced
5640e5e52638SMatthew G. Knepley 
5641*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5642e5e52638SMatthew G. Knepley @*/
564307218a29SMatthew G. Knepley PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds, PetscDS dsIn)
5644d71ae5a4SJacob Faibussowitsch {
5645083401c6SMatthew G. Knepley   PetscInt Nds;
5646e5e52638SMatthew G. Knepley 
5647e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5648e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5649ad540459SPierre Jolivet   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
56509566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
565163a3b9bcSJacob Faibussowitsch   PetscCheck((num >= 0) && (num < Nds), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", num, Nds);
56529566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
56539566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->probs[num].label));
5654083401c6SMatthew G. Knepley   dm->probs[num].label = label;
5655083401c6SMatthew G. Knepley   if (fields) {
5656083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(fields, IS_CLASSID, 4);
56579566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)fields));
56589566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[num].fields));
5659083401c6SMatthew G. Knepley     dm->probs[num].fields = fields;
5660e5e52638SMatthew G. Knepley   }
5661083401c6SMatthew G. Knepley   if (ds) {
5662083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 5);
56639566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ds));
56649566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[num].ds));
5665083401c6SMatthew G. Knepley     dm->probs[num].ds = ds;
5666083401c6SMatthew G. Knepley   }
566707218a29SMatthew G. Knepley   if (dsIn) {
566807218a29SMatthew G. Knepley     PetscValidHeaderSpecific(dsIn, PETSCDS_CLASSID, 6);
566907218a29SMatthew G. Knepley     PetscCall(PetscObjectReference((PetscObject)dsIn));
567007218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dm->probs[num].dsIn));
567107218a29SMatthew G. Knepley     dm->probs[num].dsIn = dsIn;
567207218a29SMatthew G. Knepley   }
56733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5674e5e52638SMatthew G. Knepley }
5675e5e52638SMatthew G. Knepley 
5676e5e52638SMatthew G. Knepley /*@
567720f4b53cSBarry Smith   DMFindRegionNum - Find the region number for a given `PetscDS`, or -1 if it is not found.
56781d3af9e0SMatthew G. Knepley 
567920f4b53cSBarry Smith   Not Collective
56801d3af9e0SMatthew G. Knepley 
56811d3af9e0SMatthew G. Knepley   Input Parameters:
568220f4b53cSBarry Smith + dm  - The `DM`
568320f4b53cSBarry Smith - ds  - The `PetscDS` defined on the given region
56841d3af9e0SMatthew G. Knepley 
56851d3af9e0SMatthew G. Knepley   Output Parameter:
56861d3af9e0SMatthew G. Knepley . num - The region number, in [0, Nds), or -1 if not found
56871d3af9e0SMatthew G. Knepley 
56881d3af9e0SMatthew G. Knepley   Level: advanced
56891d3af9e0SMatthew G. Knepley 
5690*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionNumDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
56911d3af9e0SMatthew G. Knepley @*/
5692d71ae5a4SJacob Faibussowitsch PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num)
5693d71ae5a4SJacob Faibussowitsch {
56941d3af9e0SMatthew G. Knepley   PetscInt Nds, n;
56951d3af9e0SMatthew G. Knepley 
56961d3af9e0SMatthew G. Knepley   PetscFunctionBegin;
56971d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56981d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 2);
5699dadcf809SJacob Faibussowitsch   PetscValidIntPointer(num, 3);
57009566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
57019371c9d4SSatish Balay   for (n = 0; n < Nds; ++n)
57029371c9d4SSatish Balay     if (ds == dm->probs[n].ds) break;
57031d3af9e0SMatthew G. Knepley   if (n >= Nds) *num = -1;
57041d3af9e0SMatthew G. Knepley   else *num = n;
57053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57061d3af9e0SMatthew G. Knepley }
57071d3af9e0SMatthew G. Knepley 
57082df84da0SMatthew G. Knepley /*@C
5709bb7acecfSBarry Smith   DMCreateFEDefault - Create a `PetscFE` based on the celltype for the mesh
57102df84da0SMatthew G. Knepley 
571120f4b53cSBarry Smith   Not Collective
57122df84da0SMatthew G. Knepley 
5713f1a722f8SMatthew G. Knepley   Input Parameters:
5714bb7acecfSBarry Smith + dm     - The `DM`
57152df84da0SMatthew G. Knepley . Nc     - The number of components for the field
571620f4b53cSBarry Smith . prefix - The options prefix for the output `PetscFE`, or `NULL`
5717bb7acecfSBarry Smith - qorder - The quadrature order or `PETSC_DETERMINE` to use `PetscSpace` polynomial degree
57182df84da0SMatthew G. Knepley 
57192df84da0SMatthew G. Knepley   Output Parameter:
5720bb7acecfSBarry Smith . fem - The `PetscFE`
57212df84da0SMatthew G. Knepley 
572220f4b53cSBarry Smith   Level: intermediate
572320f4b53cSBarry Smith 
5724bb7acecfSBarry Smith   Note:
5725bb7acecfSBarry Smith   This is a convenience method that just calls `PetscFECreateByCell()` underneath.
57262df84da0SMatthew G. Knepley 
5727*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscFECreateByCell()`, `DMAddField()`, `DMCreateDS()`, `DMGetCellDS()`, `DMGetRegionDS()`
57282df84da0SMatthew G. Knepley @*/
5729d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFEDefault(DM dm, PetscInt Nc, const char prefix[], PetscInt qorder, PetscFE *fem)
5730d71ae5a4SJacob Faibussowitsch {
57312df84da0SMatthew G. Knepley   DMPolytopeType ct;
57322df84da0SMatthew G. Knepley   PetscInt       dim, cStart;
57332df84da0SMatthew G. Knepley 
57342df84da0SMatthew G. Knepley   PetscFunctionBegin;
57352df84da0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57362df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 2);
57372df84da0SMatthew G. Knepley   if (prefix) PetscValidCharPointer(prefix, 3);
57382df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, qorder, 4);
57392df84da0SMatthew G. Knepley   PetscValidPointer(fem, 5);
57409566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
57419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
57429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
57439566063dSJacob Faibussowitsch   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, Nc, ct, prefix, qorder, fem));
57443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57452df84da0SMatthew G. Knepley }
57462df84da0SMatthew G. Knepley 
57471d3af9e0SMatthew G. Knepley /*@
5748bb7acecfSBarry Smith   DMCreateDS - Create the discrete systems for the `DM` based upon the fields added to the `DM`
5749e5e52638SMatthew G. Knepley 
575020f4b53cSBarry Smith   Collective
5751e5e52638SMatthew G. Knepley 
5752e5e52638SMatthew G. Knepley   Input Parameter:
5753bb7acecfSBarry Smith . dm - The `DM`
5754e5e52638SMatthew G. Knepley 
575520f4b53cSBarry Smith   Options Database Key:
5756bb7acecfSBarry Smith . -dm_petscds_view - View all the `PetscDS` objects in this `DM`
575745480ffeSMatthew G. Knepley 
575820f4b53cSBarry Smith   Level: intermediate
575920f4b53cSBarry Smith 
5760*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetField`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
5761e5e52638SMatthew G. Knepley @*/
5762d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDS(DM dm)
5763d71ae5a4SJacob Faibussowitsch {
5764e5e52638SMatthew G. Knepley   MPI_Comm  comm;
5765083401c6SMatthew G. Knepley   PetscDS   dsDef;
5766083401c6SMatthew G. Knepley   DMLabel  *labelSet;
5767f9244615SMatthew G. Knepley   PetscInt  dE, Nf = dm->Nf, f, s, Nl, l, Ndef, k;
5768f9244615SMatthew G. Knepley   PetscBool doSetup = PETSC_TRUE, flg;
5769e5e52638SMatthew G. Knepley 
5770e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5771e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57723ba16761SJacob Faibussowitsch   if (!dm->fields) PetscFunctionReturn(PETSC_SUCCESS);
57739566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
57749566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
5775083401c6SMatthew G. Knepley   /* Determine how many regions we have */
57769566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(Nf, &labelSet));
5777083401c6SMatthew G. Knepley   Nl   = 0;
5778083401c6SMatthew G. Knepley   Ndef = 0;
5779083401c6SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5780083401c6SMatthew G. Knepley     DMLabel  label = dm->fields[f].label;
5781083401c6SMatthew G. Knepley     PetscInt l;
5782083401c6SMatthew G. Knepley 
5783f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
5784f918ec44SMatthew G. Knepley     /* Move CEED context to discretizations */
5785f918ec44SMatthew G. Knepley     {
5786f918ec44SMatthew G. Knepley       PetscClassId id;
5787f918ec44SMatthew G. Knepley 
57889566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(dm->fields[f].disc, &id));
5789f918ec44SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
5790f918ec44SMatthew G. Knepley         Ceed ceed;
5791f918ec44SMatthew G. Knepley 
57929566063dSJacob Faibussowitsch         PetscCall(DMGetCeed(dm, &ceed));
57939566063dSJacob Faibussowitsch         PetscCall(PetscFESetCeed((PetscFE)dm->fields[f].disc, ceed));
5794f918ec44SMatthew G. Knepley       }
5795f918ec44SMatthew G. Knepley     }
5796f918ec44SMatthew G. Knepley #endif
57979371c9d4SSatish Balay     if (!label) {
57989371c9d4SSatish Balay       ++Ndef;
57999371c9d4SSatish Balay       continue;
58009371c9d4SSatish Balay     }
58019371c9d4SSatish Balay     for (l = 0; l < Nl; ++l)
58029371c9d4SSatish Balay       if (label == labelSet[l]) break;
5803083401c6SMatthew G. Knepley     if (l < Nl) continue;
5804083401c6SMatthew G. Knepley     labelSet[Nl++] = label;
5805083401c6SMatthew G. Knepley   }
5806083401c6SMatthew G. Knepley   /* Create default DS if there are no labels to intersect with */
580707218a29SMatthew G. Knepley   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef, NULL));
5808083401c6SMatthew G. Knepley   if (!dsDef && Ndef && !Nl) {
5809b3cf3223SMatthew G. Knepley     IS        fields;
5810b3cf3223SMatthew G. Knepley     PetscInt *fld, nf;
5811b3cf3223SMatthew G. Knepley 
58129371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58139371c9d4SSatish Balay       if (!dm->fields[f].label) ++nf;
58147a8be351SBarry Smith     PetscCheck(nf, comm, PETSC_ERR_PLIB, "All fields have labels, but we are trying to create a default DS");
58159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
58169371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58179371c9d4SSatish Balay       if (!dm->fields[f].label) fld[nf++] = f;
58189566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
58199566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
58209566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
58219566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
582288f0c812SMatthew G. Knepley 
58239566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
582407218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, NULL, fields, dsDef, NULL));
58259566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
58269566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fields));
58272df9ee95SMatthew G. Knepley   }
582807218a29SMatthew G. Knepley   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef, NULL));
58299566063dSJacob Faibussowitsch   if (dsDef) PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
5830083401c6SMatthew G. Knepley   /* Intersect labels with default fields */
5831083401c6SMatthew G. Knepley   if (Ndef && Nl) {
58320122748bSMatthew G. Knepley     DM              plex;
5833083401c6SMatthew G. Knepley     DMLabel         cellLabel;
5834083401c6SMatthew G. Knepley     IS              fieldIS, allcellIS, defcellIS = NULL;
5835083401c6SMatthew G. Knepley     PetscInt       *fields;
5836083401c6SMatthew G. Knepley     const PetscInt *cells;
5837083401c6SMatthew G. Knepley     PetscInt        depth, nf = 0, n, c;
58380122748bSMatthew G. Knepley 
58399566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
58409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(plex, &depth));
58419566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(plex, "dim", depth, &allcellIS));
58429566063dSJacob Faibussowitsch     if (!allcellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, &allcellIS));
58435fedec97SMatthew G. Knepley     /* TODO This looks like it only works for one label */
5844083401c6SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
5845083401c6SMatthew G. Knepley       DMLabel label = labelSet[l];
5846083401c6SMatthew G. Knepley       IS      pointIS;
5847083401c6SMatthew G. Knepley 
58489566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&defcellIS));
58499566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(label, 1, &pointIS));
58509566063dSJacob Faibussowitsch       PetscCall(ISDifference(allcellIS, pointIS, &defcellIS));
58519566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pointIS));
5852083401c6SMatthew G. Knepley     }
58539566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&allcellIS));
5854083401c6SMatthew G. Knepley 
58559566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel));
58569566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(defcellIS, &n));
58579566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(defcellIS, &cells));
58589566063dSJacob Faibussowitsch     for (c = 0; c < n; ++c) PetscCall(DMLabelSetValue(cellLabel, cells[c], 1));
58599566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(defcellIS, &cells));
58609566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&defcellIS));
58619566063dSJacob Faibussowitsch     PetscCall(DMPlexLabelComplete(plex, cellLabel));
5862083401c6SMatthew G. Knepley 
58639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Ndef, &fields));
58649371c9d4SSatish Balay     for (f = 0; f < Nf; ++f)
58659371c9d4SSatish Balay       if (!dm->fields[f].label) fields[nf++] = f;
58669566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fieldIS));
58679566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fieldIS, "dm_fields_"));
58689566063dSJacob Faibussowitsch     PetscCall(ISSetType(fieldIS, ISGENERAL));
58699566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER));
5870083401c6SMatthew G. Knepley 
58719566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
587207218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, cellLabel, fieldIS, dsDef, NULL));
58739566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
58749566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&cellLabel));
58759566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
58769566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fieldIS));
58779566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5878083401c6SMatthew G. Knepley   }
5879083401c6SMatthew G. Knepley   /* Create label DSes
5880083401c6SMatthew G. Knepley      - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS
5881083401c6SMatthew G. Knepley   */
5882083401c6SMatthew G. Knepley   /* TODO Should check that labels are disjoint */
5883083401c6SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
5884083401c6SMatthew G. Knepley     DMLabel   label = labelSet[l];
588507218a29SMatthew G. Knepley     PetscDS   ds, dsIn = NULL;
5886083401c6SMatthew G. Knepley     IS        fields;
5887083401c6SMatthew G. Knepley     PetscInt *fld, nf;
5888083401c6SMatthew G. Knepley 
58899566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
58909371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58919371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) ++nf;
58929566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
58939371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58949371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f;
58959566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
58969566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
58979566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
58989566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
58999566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(ds, dE));
5900083401c6SMatthew G. Knepley     {
5901083401c6SMatthew G. Knepley       DMPolytopeType ct;
5902083401c6SMatthew G. Knepley       PetscInt       lStart, lEnd;
59035fedec97SMatthew G. Knepley       PetscBool      isCohesiveLocal = PETSC_FALSE, isCohesive;
59040122748bSMatthew G. Knepley 
59059566063dSJacob Faibussowitsch       PetscCall(DMLabelGetBounds(label, &lStart, &lEnd));
5906665f567fSMatthew G. Knepley       if (lStart >= 0) {
59079566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, lStart, &ct));
5908412e9a14SMatthew G. Knepley         switch (ct) {
5909412e9a14SMatthew G. Knepley         case DM_POLYTOPE_POINT_PRISM_TENSOR:
5910412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
5911412e9a14SMatthew G. Knepley         case DM_POLYTOPE_TRI_PRISM_TENSOR:
5912d71ae5a4SJacob Faibussowitsch         case DM_POLYTOPE_QUAD_PRISM_TENSOR:
5913d71ae5a4SJacob Faibussowitsch           isCohesiveLocal = PETSC_TRUE;
5914d71ae5a4SJacob Faibussowitsch           break;
5915d71ae5a4SJacob Faibussowitsch         default:
5916d71ae5a4SJacob Faibussowitsch           break;
5917412e9a14SMatthew G. Knepley         }
5918665f567fSMatthew G. Knepley       }
5919712fec58SPierre Jolivet       PetscCall(MPIU_Allreduce(&isCohesiveLocal, &isCohesive, 1, MPIU_BOOL, MPI_LOR, comm));
592007218a29SMatthew G. Knepley       if (isCohesive) {
592107218a29SMatthew G. Knepley         PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsIn));
592207218a29SMatthew G. Knepley         PetscCall(PetscDSSetCoordinateDimension(dsIn, dE));
592307218a29SMatthew G. Knepley       }
59245fedec97SMatthew G. Knepley       for (f = 0, nf = 0; f < Nf; ++f) {
59255fedec97SMatthew G. Knepley         if (label == dm->fields[f].label || !dm->fields[f].label) {
59265fedec97SMatthew G. Knepley           if (label == dm->fields[f].label) {
59279566063dSJacob Faibussowitsch             PetscCall(PetscDSSetDiscretization(ds, nf, NULL));
59289566063dSJacob Faibussowitsch             PetscCall(PetscDSSetCohesive(ds, nf, isCohesive));
592907218a29SMatthew G. Knepley             if (dsIn) {
593007218a29SMatthew G. Knepley               PetscCall(PetscDSSetDiscretization(dsIn, nf, NULL));
593107218a29SMatthew G. Knepley               PetscCall(PetscDSSetCohesive(dsIn, nf, isCohesive));
593207218a29SMatthew G. Knepley             }
59335fedec97SMatthew G. Knepley           }
59345fedec97SMatthew G. Knepley           ++nf;
59355fedec97SMatthew G. Knepley         }
59365fedec97SMatthew G. Knepley       }
5937e5e52638SMatthew G. Knepley     }
593807218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, label, fields, ds, dsIn));
593907218a29SMatthew G. Knepley     PetscCall(ISDestroy(&fields));
59409566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&ds));
594107218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dsIn));
5942e5e52638SMatthew G. Knepley   }
59439566063dSJacob Faibussowitsch   PetscCall(PetscFree(labelSet));
5944e5e52638SMatthew G. Knepley   /* Set fields in DSes */
5945083401c6SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5946083401c6SMatthew G. Knepley     PetscDS         ds     = dm->probs[s].ds;
594707218a29SMatthew G. Knepley     PetscDS         dsIn   = dm->probs[s].dsIn;
5948083401c6SMatthew G. Knepley     IS              fields = dm->probs[s].fields;
5949083401c6SMatthew G. Knepley     const PetscInt *fld;
59505fedec97SMatthew G. Knepley     PetscInt        nf, dsnf;
59515fedec97SMatthew G. Knepley     PetscBool       isCohesive;
5952e5e52638SMatthew G. Knepley 
59539566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsnf));
59549566063dSJacob Faibussowitsch     PetscCall(PetscDSIsCohesive(ds, &isCohesive));
59559566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(fields, &nf));
59569566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fields, &fld));
5957083401c6SMatthew G. Knepley     for (f = 0; f < nf; ++f) {
5958083401c6SMatthew G. Knepley       PetscObject  disc = dm->fields[fld[f]].disc;
59595fedec97SMatthew G. Knepley       PetscBool    isCohesiveField;
5960e5e52638SMatthew G. Knepley       PetscClassId id;
5961e5e52638SMatthew G. Knepley 
59625fedec97SMatthew G. Knepley       /* Handle DS with no fields */
59639566063dSJacob Faibussowitsch       if (dsnf) PetscCall(PetscDSGetCohesive(ds, f, &isCohesiveField));
59645fedec97SMatthew G. Knepley       /* If this is a cohesive cell, then regular fields need the lower dimensional discretization */
596507218a29SMatthew G. Knepley       if (isCohesive) {
596607218a29SMatthew G. Knepley         if (!isCohesiveField) {
596707218a29SMatthew G. Knepley           PetscObject bdDisc;
596807218a29SMatthew G. Knepley 
596907218a29SMatthew G. Knepley           PetscCall(PetscFEGetHeightSubspace((PetscFE)disc, 1, (PetscFE *)&bdDisc));
597007218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(ds, f, bdDisc));
597107218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(dsIn, f, disc));
597207218a29SMatthew G. Knepley         } else {
59739566063dSJacob Faibussowitsch           PetscCall(PetscDSSetDiscretization(ds, f, disc));
597407218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(dsIn, f, disc));
597507218a29SMatthew G. Knepley         }
597607218a29SMatthew G. Knepley       } else {
597707218a29SMatthew G. Knepley         PetscCall(PetscDSSetDiscretization(ds, f, disc));
597807218a29SMatthew G. Knepley       }
5979083401c6SMatthew G. Knepley       /* We allow people to have placeholder fields and construct the Section by hand */
59809566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(disc, &id));
5981e5e52638SMatthew G. Knepley       if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE;
5982e5e52638SMatthew G. Knepley     }
59839566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fields, &fld));
5984e5e52638SMatthew G. Knepley   }
5985f9244615SMatthew G. Knepley   /* Allow k-jet tabulation */
59869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)dm)->prefix, "-dm_ds_jet_degree", &k, &flg));
5987f9244615SMatthew G. Knepley   if (flg) {
59883b4aee56SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
59893b4aee56SMatthew G. Knepley       PetscDS  ds   = dm->probs[s].ds;
599007218a29SMatthew G. Knepley       PetscDS  dsIn = dm->probs[s].dsIn;
59913b4aee56SMatthew G. Knepley       PetscInt Nf, f;
59923b4aee56SMatthew G. Knepley 
59939566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(ds, &Nf));
599407218a29SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
599507218a29SMatthew G. Knepley         PetscCall(PetscDSSetJetDegree(ds, f, k));
599607218a29SMatthew G. Knepley         if (dsIn) PetscCall(PetscDSSetJetDegree(dsIn, f, k));
599707218a29SMatthew G. Knepley       }
59983b4aee56SMatthew G. Knepley     }
5999f9244615SMatthew G. Knepley   }
6000e5e52638SMatthew G. Knepley   /* Setup DSes */
6001e5e52638SMatthew G. Knepley   if (doSetup) {
600207218a29SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
600307218a29SMatthew G. Knepley       PetscCall(PetscDSSetUp(dm->probs[s].ds));
600407218a29SMatthew G. Knepley       if (dm->probs[s].dsIn) PetscCall(PetscDSSetUp(dm->probs[s].dsIn));
600507218a29SMatthew G. Knepley     }
6006e5e52638SMatthew G. Knepley   }
60073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6008e5e52638SMatthew G. Knepley }
6009e5e52638SMatthew G. Knepley 
6010e5e52638SMatthew G. Knepley /*@
6011bb7acecfSBarry Smith   DMComputeExactSolution - Compute the exact solution for a given `DM`, using the `PetscDS` information.
60127f96f943SMatthew G. Knepley 
601320f4b53cSBarry Smith   Collective
6014f2cacb80SMatthew G. Knepley 
60157f96f943SMatthew G. Knepley   Input Parameters:
6016bb7acecfSBarry Smith + dm   - The `DM`
60177f96f943SMatthew G. Knepley - time - The time
60187f96f943SMatthew G. Knepley 
60197f96f943SMatthew G. Knepley   Output Parameters:
602020f4b53cSBarry Smith + u    - The vector will be filled with exact solution values, or `NULL`
602120f4b53cSBarry Smith - u_t  - The vector will be filled with the time derivative of exact solution values, or `NULL`
602220f4b53cSBarry Smith 
602320f4b53cSBarry Smith   Level: developer
60247f96f943SMatthew G. Knepley 
6025bb7acecfSBarry Smith   Note:
6026bb7acecfSBarry Smith   The user must call `PetscDSSetExactSolution()` before using this routine
60277f96f943SMatthew G. Knepley 
6028*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscDSSetExactSolution()`
60297f96f943SMatthew G. Knepley @*/
6030d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t)
6031d71ae5a4SJacob Faibussowitsch {
60327f96f943SMatthew G. Knepley   PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
60337f96f943SMatthew G. Knepley   void   **ectxs;
6034f60fa741SMatthew G. Knepley   Vec      locu, locu_t;
60357f96f943SMatthew G. Knepley   PetscInt Nf, Nds, s;
60367f96f943SMatthew G. Knepley 
60377f96f943SMatthew G. Knepley   PetscFunctionBegin;
6038f2cacb80SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6039f60fa741SMatthew G. Knepley   if (u) {
6040f60fa741SMatthew G. Knepley     PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
6041f60fa741SMatthew G. Knepley     PetscCall(DMGetLocalVector(dm, &locu));
6042f60fa741SMatthew G. Knepley     PetscCall(VecSet(locu, 0.));
6043f60fa741SMatthew G. Knepley   }
6044f60fa741SMatthew G. Knepley   if (u_t) {
6045f60fa741SMatthew G. Knepley     PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4);
6046f60fa741SMatthew G. Knepley     PetscCall(DMGetLocalVector(dm, &locu_t));
6047f60fa741SMatthew G. Knepley     PetscCall(VecSet(locu_t, 0.));
6048f60fa741SMatthew G. Knepley   }
60499566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
60509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(Nf, &exacts, Nf, &ectxs));
60519566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
60527f96f943SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
60537f96f943SMatthew G. Knepley     PetscDS         ds;
60547f96f943SMatthew G. Knepley     DMLabel         label;
60557f96f943SMatthew G. Knepley     IS              fieldIS;
60567f96f943SMatthew G. Knepley     const PetscInt *fields, id = 1;
60577f96f943SMatthew G. Knepley     PetscInt        dsNf, f;
60587f96f943SMatthew G. Knepley 
605907218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds, NULL));
60609566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
60619566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fieldIS, &fields));
60629566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(exacts, Nf));
60639566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(ectxs, Nf));
6064f2cacb80SMatthew G. Knepley     if (u) {
6065f60fa741SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) PetscCall(PetscDSGetExactSolution(ds, fields[f], &exacts[fields[f]], &ectxs[fields[f]]));
6066f60fa741SMatthew G. Knepley       if (label) PetscCall(DMProjectFunctionLabelLocal(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, locu));
6067f60fa741SMatthew G. Knepley       else PetscCall(DMProjectFunctionLocal(dm, time, exacts, ectxs, INSERT_ALL_VALUES, locu));
60687f96f943SMatthew G. Knepley     }
6069f2cacb80SMatthew G. Knepley     if (u_t) {
60709566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(exacts, Nf));
60719566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ectxs, Nf));
6072f60fa741SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, fields[f], &exacts[fields[f]], &ectxs[fields[f]]));
6073f60fa741SMatthew G. Knepley       if (label) PetscCall(DMProjectFunctionLabelLocal(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, locu_t));
6074f60fa741SMatthew G. Knepley       else PetscCall(DMProjectFunctionLocal(dm, time, exacts, ectxs, INSERT_ALL_VALUES, locu_t));
6075f2cacb80SMatthew G. Knepley     }
60769566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fieldIS, &fields));
6077f2cacb80SMatthew G. Knepley   }
6078f2cacb80SMatthew G. Knepley   if (u) {
60799566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution"));
60809566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u, "exact_"));
6081f2cacb80SMatthew G. Knepley   }
6082f2cacb80SMatthew G. Knepley   if (u_t) {
60839566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution Time Derivative"));
60849566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u_t, "exact_t_"));
6085f2cacb80SMatthew G. Knepley   }
60869566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exacts, ectxs));
6087f60fa741SMatthew G. Knepley   if (u) {
6088f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(dm, locu, INSERT_ALL_VALUES, u));
6089f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(dm, locu, INSERT_ALL_VALUES, u));
6090f60fa741SMatthew G. Knepley     PetscCall(DMRestoreLocalVector(dm, &locu));
6091f60fa741SMatthew G. Knepley   }
6092f60fa741SMatthew G. Knepley   if (u_t) {
6093f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(dm, locu_t, INSERT_ALL_VALUES, u_t));
6094f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(dm, locu_t, INSERT_ALL_VALUES, u_t));
6095f60fa741SMatthew G. Knepley     PetscCall(DMRestoreLocalVector(dm, &locu_t));
6096f60fa741SMatthew G. Knepley   }
60973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60987f96f943SMatthew G. Knepley }
60997f96f943SMatthew G. Knepley 
610007218a29SMatthew G. Knepley static PetscErrorCode DMTransferDS_Internal(DM dm, DMLabel label, IS fields, PetscDS ds, PetscDS dsIn)
6101d71ae5a4SJacob Faibussowitsch {
610207218a29SMatthew G. Knepley   PetscDS dsNew, dsInNew = NULL;
610345480ffeSMatthew G. Knepley 
610445480ffeSMatthew G. Knepley   PetscFunctionBegin;
61059566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)ds), &dsNew));
610607218a29SMatthew G. Knepley   PetscCall(PetscDSCopy(ds, dm, dsNew));
610707218a29SMatthew G. Knepley   if (dsIn) {
610807218a29SMatthew G. Knepley     PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)dsIn), &dsInNew));
610907218a29SMatthew G. Knepley     PetscCall(PetscDSCopy(dsIn, dm, dsInNew));
611045480ffeSMatthew G. Knepley   }
611107218a29SMatthew G. Knepley   PetscCall(DMSetRegionDS(dm, label, fields, dsNew, dsInNew));
61129566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&dsNew));
611307218a29SMatthew G. Knepley   PetscCall(PetscDSDestroy(&dsInNew));
61143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
611545480ffeSMatthew G. Knepley }
611645480ffeSMatthew G. Knepley 
61177f96f943SMatthew G. Knepley /*@
6118bb7acecfSBarry Smith   DMCopyDS - Copy the discrete systems for the `DM` into another `DM`
6119e5e52638SMatthew G. Knepley 
612020f4b53cSBarry Smith   Collective
6121e5e52638SMatthew G. Knepley 
6122e5e52638SMatthew G. Knepley   Input Parameter:
6123bb7acecfSBarry Smith . dm - The `DM`
6124e5e52638SMatthew G. Knepley 
6125e5e52638SMatthew G. Knepley   Output Parameter:
6126bb7acecfSBarry Smith . newdm - The `DM`
6127e5e52638SMatthew G. Knepley 
6128e5e52638SMatthew G. Knepley   Level: advanced
6129e5e52638SMatthew G. Knepley 
6130*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCopyFields()`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
6131e5e52638SMatthew G. Knepley @*/
6132d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDS(DM dm, DM newdm)
6133d71ae5a4SJacob Faibussowitsch {
6134e5e52638SMatthew G. Knepley   PetscInt Nds, s;
6135e5e52638SMatthew G. Knepley 
6136e5e52638SMatthew G. Knepley   PetscFunctionBegin;
61373ba16761SJacob Faibussowitsch   if (dm == newdm) PetscFunctionReturn(PETSC_SUCCESS);
61389566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
61399566063dSJacob Faibussowitsch   PetscCall(DMClearDS(newdm));
6140e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
6141e5e52638SMatthew G. Knepley     DMLabel  label;
6142b3cf3223SMatthew G. Knepley     IS       fields;
614307218a29SMatthew G. Knepley     PetscDS  ds, dsIn, newds;
6144783e2ec8SMatthew G. Knepley     PetscInt Nbd, bd;
6145e5e52638SMatthew G. Knepley 
614607218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fields, &ds, &dsIn));
6147b8025e53SMatthew G. Knepley     /* TODO: We need to change all keys from labels in the old DM to labels in the new DM */
614807218a29SMatthew G. Knepley     PetscCall(DMTransferDS_Internal(newdm, label, fields, ds, dsIn));
6149d5b43468SJose E. Roman     /* Complete new labels in the new DS */
615007218a29SMatthew G. Knepley     PetscCall(DMGetRegionDS(newdm, label, NULL, &newds, NULL));
61519566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumBoundary(newds, &Nbd));
6152783e2ec8SMatthew G. Knepley     for (bd = 0; bd < Nbd; ++bd) {
6153b8025e53SMatthew G. Knepley       PetscWeakForm wf;
615445480ffeSMatthew G. Knepley       DMLabel       label;
6155783e2ec8SMatthew G. Knepley       PetscInt      field;
6156783e2ec8SMatthew G. Knepley 
61579566063dSJacob Faibussowitsch       PetscCall(PetscDSGetBoundary(newds, bd, &wf, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
61589566063dSJacob Faibussowitsch       PetscCall(PetscWeakFormReplaceLabel(wf, label));
6159783e2ec8SMatthew G. Knepley     }
6160e5e52638SMatthew G. Knepley   }
6161799db056SMatthew G. Knepley   PetscCall(DMCompleteBCLabels_Internal(newdm));
61623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6163e5e52638SMatthew G. Knepley }
6164e5e52638SMatthew G. Knepley 
6165e5e52638SMatthew G. Knepley /*@
6166bb7acecfSBarry Smith   DMCopyDisc - Copy the fields and discrete systems for the `DM` into another `DM`
6167e5e52638SMatthew G. Knepley 
616820f4b53cSBarry Smith   Collective
6169e5e52638SMatthew G. Knepley 
6170e5e52638SMatthew G. Knepley   Input Parameter:
6171bb7acecfSBarry Smith . dm - The `DM`
6172e5e52638SMatthew G. Knepley 
6173e5e52638SMatthew G. Knepley   Output Parameter:
6174bb7acecfSBarry Smith . newdm - The `DM`
6175e5e52638SMatthew G. Knepley 
6176e5e52638SMatthew G. Knepley   Level: advanced
6177e5e52638SMatthew G. Knepley 
6178bb7acecfSBarry Smith   Developer Note:
6179bb7acecfSBarry Smith   Really ugly name, nothing in PETSc is called a `Disc` plus it is an ugly abbreviation
6180bb7acecfSBarry Smith 
6181*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCopyFields()`, `DMCopyDS()`
6182e5e52638SMatthew G. Knepley @*/
6183d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDisc(DM dm, DM newdm)
6184d71ae5a4SJacob Faibussowitsch {
6185e5e52638SMatthew G. Knepley   PetscFunctionBegin;
61869566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, newdm));
61879566063dSJacob Faibussowitsch   PetscCall(DMCopyDS(dm, newdm));
61883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6189e5e52638SMatthew G. Knepley }
6190e5e52638SMatthew G. Knepley 
6191c73cfb54SMatthew G. Knepley /*@
6192bb7acecfSBarry Smith   DMGetDimension - Return the topological dimension of the `DM`
6193c73cfb54SMatthew G. Knepley 
619420f4b53cSBarry Smith   Not Collective
6195c73cfb54SMatthew G. Knepley 
6196c73cfb54SMatthew G. Knepley   Input Parameter:
6197bb7acecfSBarry Smith . dm - The `DM`
6198c73cfb54SMatthew G. Knepley 
6199c73cfb54SMatthew G. Knepley   Output Parameter:
6200c73cfb54SMatthew G. Knepley . dim - The topological dimension
6201c73cfb54SMatthew G. Knepley 
6202c73cfb54SMatthew G. Knepley   Level: beginner
6203c73cfb54SMatthew G. Knepley 
6204*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetDimension()`, `DMCreate()`
6205c73cfb54SMatthew G. Knepley @*/
6206d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
6207d71ae5a4SJacob Faibussowitsch {
6208c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6209c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6210534a8f05SLisandro Dalcin   PetscValidIntPointer(dim, 2);
6211c73cfb54SMatthew G. Knepley   *dim = dm->dim;
62123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6213c73cfb54SMatthew G. Knepley }
6214c73cfb54SMatthew G. Knepley 
6215c73cfb54SMatthew G. Knepley /*@
6216bb7acecfSBarry Smith   DMSetDimension - Set the topological dimension of the `DM`
6217c73cfb54SMatthew G. Knepley 
621820f4b53cSBarry Smith   Collective
6219c73cfb54SMatthew G. Knepley 
6220c73cfb54SMatthew G. Knepley   Input Parameters:
6221bb7acecfSBarry Smith + dm - The `DM`
6222c73cfb54SMatthew G. Knepley - dim - The topological dimension
6223c73cfb54SMatthew G. Knepley 
6224c73cfb54SMatthew G. Knepley   Level: beginner
6225c73cfb54SMatthew G. Knepley 
6226*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDimension()`, `DMCreate()`
6227c73cfb54SMatthew G. Knepley @*/
6228d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
6229d71ae5a4SJacob Faibussowitsch {
6230e5e52638SMatthew G. Knepley   PetscDS  ds;
623145480ffeSMatthew G. Knepley   PetscInt Nds, n;
6232f17e8794SMatthew G. Knepley 
6233c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6234c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6235c73cfb54SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6236c73cfb54SMatthew G. Knepley   dm->dim = dim;
6237d17bd122SMatthew G. Knepley   if (dm->dim >= 0) {
62389566063dSJacob Faibussowitsch     PetscCall(DMGetNumDS(dm, &Nds));
623945480ffeSMatthew G. Knepley     for (n = 0; n < Nds; ++n) {
624007218a29SMatthew G. Knepley       PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds, NULL));
62419566063dSJacob Faibussowitsch       if (ds->dimEmbed < 0) PetscCall(PetscDSSetCoordinateDimension(ds, dim));
624245480ffeSMatthew G. Knepley     }
6243d17bd122SMatthew G. Knepley   }
62443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6245c73cfb54SMatthew G. Knepley }
6246c73cfb54SMatthew G. Knepley 
6247793f3fe5SMatthew G. Knepley /*@
6248793f3fe5SMatthew G. Knepley   DMGetDimPoints - Get the half-open interval for all points of a given dimension
6249793f3fe5SMatthew G. Knepley 
625020f4b53cSBarry Smith   Collective
6251793f3fe5SMatthew G. Knepley 
6252793f3fe5SMatthew G. Knepley   Input Parameters:
6253bb7acecfSBarry Smith + dm - the `DM`
6254793f3fe5SMatthew G. Knepley - dim - the dimension
6255793f3fe5SMatthew G. Knepley 
6256793f3fe5SMatthew G. Knepley   Output Parameters:
6257793f3fe5SMatthew G. Knepley + pStart - The first point of the given dimension
6258aa049354SPatrick Sanan - pEnd - The first point following points of the given dimension
6259793f3fe5SMatthew G. Knepley 
626020f4b53cSBarry Smith   Level: intermediate
626120f4b53cSBarry Smith 
6262793f3fe5SMatthew G. Knepley   Note:
6263793f3fe5SMatthew G. Knepley   The points are vertices in the Hasse diagram encoding the topology. This is explained in
6264a8d69d7bSBarry Smith   https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme,
6265793f3fe5SMatthew G. Knepley   then the interval is empty.
6266793f3fe5SMatthew G. Knepley 
6267*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
6268793f3fe5SMatthew G. Knepley @*/
6269d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
6270d71ae5a4SJacob Faibussowitsch {
6271793f3fe5SMatthew G. Knepley   PetscInt d;
6272793f3fe5SMatthew G. Knepley 
6273793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
6274793f3fe5SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62759566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &d));
62767a8be351SBarry Smith   PetscCheck((dim >= 0) && (dim <= d), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %" PetscInt_FMT, dim);
6277dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getdimpoints, dim, pStart, pEnd);
62783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6279793f3fe5SMatthew G. Knepley }
6280793f3fe5SMatthew G. Knepley 
62816636e97aSMatthew G Knepley /*@
6282bb7acecfSBarry Smith   DMGetOutputDM - Retrieve the `DM` associated with the layout for output
6283f4d763aaSMatthew G. Knepley 
628420f4b53cSBarry Smith   Collective
62858f700142SStefano Zampini 
6286f4d763aaSMatthew G. Knepley   Input Parameter:
6287bb7acecfSBarry Smith . dm - The original `DM`
6288f4d763aaSMatthew G. Knepley 
6289f4d763aaSMatthew G. Knepley   Output Parameter:
6290bb7acecfSBarry Smith . odm - The `DM` which provides the layout for output
6291f4d763aaSMatthew G. Knepley 
6292f4d763aaSMatthew G. Knepley   Level: intermediate
6293f4d763aaSMatthew G. Knepley 
6294bb7acecfSBarry Smith   Note:
6295bb7acecfSBarry Smith   In some situations the vector obtained with `DMCreateGlobalVector()` excludes points for degrees of freedom that are associated with fixed (Dirichelet) boundary
6296bb7acecfSBarry Smith   conditions since the algebraic solver does not solve for those variables. The output `DM` includes these excluded points and its global vector contains the
6297bb7acecfSBarry Smith   locations for those dof so that they can be output to a file or other viewer along with the unconstrained dof.
6298bb7acecfSBarry Smith 
6299*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`, `DMGetGlobalSection()`, `DMCreateGlobalVector()`, `PetscSectionHasConstraints()`, `DMSetGlobalSection()`
6300f4d763aaSMatthew G. Knepley @*/
6301d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
6302d71ae5a4SJacob Faibussowitsch {
6303c26acbdeSMatthew G. Knepley   PetscSection section;
63042d4e4a49SMatthew G. Knepley   PetscBool    hasConstraints, ghasConstraints;
630514f150ffSMatthew G. Knepley 
630614f150ffSMatthew G. Knepley   PetscFunctionBegin;
630714f150ffSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
630814f150ffSMatthew G. Knepley   PetscValidPointer(odm, 2);
63099566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
63109566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
6311712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
63122d4e4a49SMatthew G. Knepley   if (!ghasConstraints) {
6313c26acbdeSMatthew G. Knepley     *odm = dm;
63143ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6315c26acbdeSMatthew G. Knepley   }
631614f150ffSMatthew G. Knepley   if (!dm->dmBC) {
6317c26acbdeSMatthew G. Knepley     PetscSection newSection, gsection;
631814f150ffSMatthew G. Knepley     PetscSF      sf;
631914f150ffSMatthew G. Knepley 
63209566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &dm->dmBC));
63219566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dm, dm->dmBC));
63229566063dSJacob Faibussowitsch     PetscCall(PetscSectionClone(section, &newSection));
63239566063dSJacob Faibussowitsch     PetscCall(DMSetLocalSection(dm->dmBC, newSection));
63249566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&newSection));
63259566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm->dmBC, &sf));
63269566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
63279566063dSJacob Faibussowitsch     PetscCall(DMSetGlobalSection(dm->dmBC, gsection));
63289566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&gsection));
632914f150ffSMatthew G. Knepley   }
633014f150ffSMatthew G. Knepley   *odm = dm->dmBC;
63313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
633214f150ffSMatthew G. Knepley }
6333f4d763aaSMatthew G. Knepley 
6334f4d763aaSMatthew G. Knepley /*@
6335cdb7a50dSMatthew G. Knepley   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
6336f4d763aaSMatthew G. Knepley 
6337f4d763aaSMatthew G. Knepley   Input Parameter:
6338bb7acecfSBarry Smith . dm - The original `DM`
6339f4d763aaSMatthew G. Knepley 
6340cdb7a50dSMatthew G. Knepley   Output Parameters:
6341cdb7a50dSMatthew G. Knepley + num - The output sequence number
6342cdb7a50dSMatthew G. Knepley - val - The output sequence value
6343f4d763aaSMatthew G. Knepley 
6344f4d763aaSMatthew G. Knepley   Level: intermediate
6345f4d763aaSMatthew G. Knepley 
6346bb7acecfSBarry Smith   Note:
6347bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6348bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6349bb7acecfSBarry Smith 
6350bb7acecfSBarry Smith   Developer Note:
6351bb7acecfSBarry Smith   The `DM` serves as a convenient place to store the current iteration value. The iteration is not
6352bb7acecfSBarry Smith   not directly related to the `DM`.
6353f4d763aaSMatthew G. Knepley 
6354*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`
6355f4d763aaSMatthew G. Knepley @*/
6356d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
6357d71ae5a4SJacob Faibussowitsch {
6358f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6359f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63609371c9d4SSatish Balay   if (num) {
63619371c9d4SSatish Balay     PetscValidIntPointer(num, 2);
63629371c9d4SSatish Balay     *num = dm->outputSequenceNum;
63639371c9d4SSatish Balay   }
63649371c9d4SSatish Balay   if (val) {
63659371c9d4SSatish Balay     PetscValidRealPointer(val, 3);
63669371c9d4SSatish Balay     *val = dm->outputSequenceVal;
63679371c9d4SSatish Balay   }
63683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6369f4d763aaSMatthew G. Knepley }
6370f4d763aaSMatthew G. Knepley 
6371f4d763aaSMatthew G. Knepley /*@
6372cdb7a50dSMatthew G. Knepley   DMSetOutputSequenceNumber - Set the sequence number/value for output
6373f4d763aaSMatthew G. Knepley 
6374f4d763aaSMatthew G. Knepley   Input Parameters:
6375bb7acecfSBarry Smith + dm - The original `DM`
6376cdb7a50dSMatthew G. Knepley . num - The output sequence number
6377cdb7a50dSMatthew G. Knepley - val - The output sequence value
6378f4d763aaSMatthew G. Knepley 
6379f4d763aaSMatthew G. Knepley   Level: intermediate
6380f4d763aaSMatthew G. Knepley 
6381bb7acecfSBarry Smith   Note:
6382bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6383bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6384f4d763aaSMatthew G. Knepley 
6385*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`
6386f4d763aaSMatthew G. Knepley @*/
6387d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
6388d71ae5a4SJacob Faibussowitsch {
6389f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6390f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6391f4d763aaSMatthew G. Knepley   dm->outputSequenceNum = num;
6392cdb7a50dSMatthew G. Knepley   dm->outputSequenceVal = val;
63933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6394cdb7a50dSMatthew G. Knepley }
6395cdb7a50dSMatthew G. Knepley 
6396cdb7a50dSMatthew G. Knepley /*@C
6397bb7acecfSBarry Smith  DMOutputSequenceLoad - Retrieve the sequence value from a `PetscViewer`
6398cdb7a50dSMatthew G. Knepley 
6399cdb7a50dSMatthew G. Knepley   Input Parameters:
6400bb7acecfSBarry Smith + dm   - The original `DM`
6401cdb7a50dSMatthew G. Knepley . name - The sequence name
6402cdb7a50dSMatthew G. Knepley - num  - The output sequence number
6403cdb7a50dSMatthew G. Knepley 
6404cdb7a50dSMatthew G. Knepley   Output Parameter:
6405cdb7a50dSMatthew G. Knepley . val  - The output sequence value
6406cdb7a50dSMatthew G. Knepley 
6407cdb7a50dSMatthew G. Knepley   Level: intermediate
6408cdb7a50dSMatthew G. Knepley 
6409bb7acecfSBarry Smith   Note:
6410bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6411bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6412bb7acecfSBarry Smith 
6413bb7acecfSBarry Smith   Developer Note:
6414bb7acecfSBarry Smith   It is unclear at the user API level why a `DM` is needed as input
6415cdb7a50dSMatthew G. Knepley 
6416*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetOutputSequenceNumber()`, `DMSetOutputSequenceNumber()`, `VecView()`
6417cdb7a50dSMatthew G. Knepley @*/
6418d71ae5a4SJacob Faibussowitsch PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
6419d71ae5a4SJacob Faibussowitsch {
6420cdb7a50dSMatthew G. Knepley   PetscBool ishdf5;
6421cdb7a50dSMatthew G. Knepley 
6422cdb7a50dSMatthew G. Knepley   PetscFunctionBegin;
6423cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6424cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
6425064a246eSJacob Faibussowitsch   PetscValidRealPointer(val, 5);
64269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6427cdb7a50dSMatthew G. Knepley   if (ishdf5) {
6428cdb7a50dSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6429cdb7a50dSMatthew G. Knepley     PetscScalar value;
6430cdb7a50dSMatthew G. Knepley 
64319566063dSJacob Faibussowitsch     PetscCall(DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer));
64324aeb217fSMatthew G. Knepley     *val = PetscRealPart(value);
6433cdb7a50dSMatthew G. Knepley #endif
6434cdb7a50dSMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
64353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6436f4d763aaSMatthew G. Knepley }
64378e4ac7eaSMatthew G. Knepley 
64388e4ac7eaSMatthew G. Knepley /*@
6439bb7acecfSBarry Smith   DMGetUseNatural - Get the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
64408e4ac7eaSMatthew G. Knepley 
644120f4b53cSBarry Smith   Not Collective
64428e4ac7eaSMatthew G. Knepley 
64438e4ac7eaSMatthew G. Knepley   Input Parameter:
6444bb7acecfSBarry Smith . dm - The `DM`
64458e4ac7eaSMatthew G. Knepley 
64468e4ac7eaSMatthew G. Knepley   Output Parameter:
6447bb7acecfSBarry Smith . useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
64488e4ac7eaSMatthew G. Knepley 
64498e4ac7eaSMatthew G. Knepley   Level: beginner
64508e4ac7eaSMatthew G. Knepley 
6451*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetUseNatural()`, `DMCreate()`
64528e4ac7eaSMatthew G. Knepley @*/
6453d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
6454d71ae5a4SJacob Faibussowitsch {
64558e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
64568e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6457534a8f05SLisandro Dalcin   PetscValidBoolPointer(useNatural, 2);
64588e4ac7eaSMatthew G. Knepley   *useNatural = dm->useNatural;
64593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
64608e4ac7eaSMatthew G. Knepley }
64618e4ac7eaSMatthew G. Knepley 
64628e4ac7eaSMatthew G. Knepley /*@
6463bb7acecfSBarry Smith   DMSetUseNatural - Set the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
64648e4ac7eaSMatthew G. Knepley 
646520f4b53cSBarry Smith   Collective
64668e4ac7eaSMatthew G. Knepley 
64678e4ac7eaSMatthew G. Knepley   Input Parameters:
6468bb7acecfSBarry Smith  + dm - The `DM`
6469bb7acecfSBarry Smith - useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
64708e4ac7eaSMatthew G. Knepley 
6471bb7acecfSBarry Smith   Note:
6472bb7acecfSBarry Smith   This also causes the map to be build after `DMCreateSubDM()` and `DMCreateSuperDM()`
64735d3b26e6SMatthew G. Knepley 
64748e4ac7eaSMatthew G. Knepley   Level: beginner
64758e4ac7eaSMatthew G. Knepley 
6476*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetUseNatural()`, `DMCreate()`, `DMPlexDistribute()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
64778e4ac7eaSMatthew G. Knepley @*/
6478d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
6479d71ae5a4SJacob Faibussowitsch {
64808e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
64818e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64828833efb5SBlaise Bourdin   PetscValidLogicalCollectiveBool(dm, useNatural, 2);
64838e4ac7eaSMatthew G. Knepley   dm->useNatural = useNatural;
64843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
64858e4ac7eaSMatthew G. Knepley }
6486c58f1c22SToby Isaac 
6487c58f1c22SToby Isaac /*@C
6488bb7acecfSBarry Smith   DMCreateLabel - Create a label of the given name if it does not already exist in the `DM`
6489c58f1c22SToby Isaac 
6490c58f1c22SToby Isaac   Not Collective
6491c58f1c22SToby Isaac 
6492c58f1c22SToby Isaac   Input Parameters:
6493bb7acecfSBarry Smith + dm   - The `DM` object
6494c58f1c22SToby Isaac - name - The label name
6495c58f1c22SToby Isaac 
6496c58f1c22SToby Isaac   Level: intermediate
6497c58f1c22SToby Isaac 
6498*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6499c58f1c22SToby Isaac @*/
6500d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabel(DM dm, const char name[])
6501d71ae5a4SJacob Faibussowitsch {
65025d80c0bfSVaclav Hapla   PetscBool flg;
65035d80c0bfSVaclav Hapla   DMLabel   label;
6504c58f1c22SToby Isaac 
6505c58f1c22SToby Isaac   PetscFunctionBegin;
6506c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6507c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
65089566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
6509c58f1c22SToby Isaac   if (!flg) {
65109566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
65119566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
65129566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
6513c58f1c22SToby Isaac   }
65143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6515c58f1c22SToby Isaac }
6516c58f1c22SToby Isaac 
6517c58f1c22SToby Isaac /*@C
6518bb7acecfSBarry Smith   DMCreateLabelAtIndex - Create a label of the given name at the given index. If it already exists in the `DM`, move it to this index.
65190fdc7489SMatthew Knepley 
65200fdc7489SMatthew Knepley   Not Collective
65210fdc7489SMatthew Knepley 
65220fdc7489SMatthew Knepley   Input Parameters:
6523bb7acecfSBarry Smith + dm   - The `DM` object
65240fdc7489SMatthew Knepley . l    - The index for the label
65250fdc7489SMatthew Knepley - name - The label name
65260fdc7489SMatthew Knepley 
65270fdc7489SMatthew Knepley   Level: intermediate
65280fdc7489SMatthew Knepley 
6529*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateLabel()`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
65300fdc7489SMatthew Knepley @*/
6531d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[])
6532d71ae5a4SJacob Faibussowitsch {
65330fdc7489SMatthew Knepley   DMLabelLink orig, prev = NULL;
65340fdc7489SMatthew Knepley   DMLabel     label;
65350fdc7489SMatthew Knepley   PetscInt    Nl, m;
65360fdc7489SMatthew Knepley   PetscBool   flg, match;
65370fdc7489SMatthew Knepley   const char *lname;
65380fdc7489SMatthew Knepley 
65390fdc7489SMatthew Knepley   PetscFunctionBegin;
65400fdc7489SMatthew Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6541064a246eSJacob Faibussowitsch   PetscValidCharPointer(name, 3);
65429566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
65430fdc7489SMatthew Knepley   if (!flg) {
65449566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
65459566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
65469566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
65470fdc7489SMatthew Knepley   }
65489566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
654963a3b9bcSJacob Faibussowitsch   PetscCheck(l < Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", l, Nl);
65500fdc7489SMatthew Knepley   for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) {
65519566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)orig->label, &lname));
65529566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &match));
65530fdc7489SMatthew Knepley     if (match) break;
65540fdc7489SMatthew Knepley   }
65553ba16761SJacob Faibussowitsch   if (m == l) PetscFunctionReturn(PETSC_SUCCESS);
65560fdc7489SMatthew Knepley   if (!m) dm->labels = orig->next;
65570fdc7489SMatthew Knepley   else prev->next = orig->next;
65580fdc7489SMatthew Knepley   if (!l) {
65590fdc7489SMatthew Knepley     orig->next = dm->labels;
65600fdc7489SMatthew Knepley     dm->labels = orig;
65610fdc7489SMatthew Knepley   } else {
65629371c9d4SSatish Balay     for (m = 0, prev = dm->labels; m < l - 1; ++m, prev = prev->next)
65639371c9d4SSatish Balay       ;
65640fdc7489SMatthew Knepley     orig->next = prev->next;
65650fdc7489SMatthew Knepley     prev->next = orig;
65660fdc7489SMatthew Knepley   }
65673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65680fdc7489SMatthew Knepley }
65690fdc7489SMatthew Knepley 
65700fdc7489SMatthew Knepley /*@C
6571bb7acecfSBarry Smith   DMGetLabelValue - Get the value in a `DMLabel` for the given point, with -1 as the default
6572c58f1c22SToby Isaac 
6573c58f1c22SToby Isaac   Not Collective
6574c58f1c22SToby Isaac 
6575c58f1c22SToby Isaac   Input Parameters:
6576bb7acecfSBarry Smith + dm   - The `DM` object
6577c58f1c22SToby Isaac . name - The label name
6578c58f1c22SToby Isaac - point - The mesh point
6579c58f1c22SToby Isaac 
6580c58f1c22SToby Isaac   Output Parameter:
6581c58f1c22SToby Isaac . value - The label value for this point, or -1 if the point is not in the label
6582c58f1c22SToby Isaac 
6583c58f1c22SToby Isaac   Level: beginner
6584c58f1c22SToby Isaac 
6585*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6586c58f1c22SToby Isaac @*/
6587d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
6588d71ae5a4SJacob Faibussowitsch {
6589c58f1c22SToby Isaac   DMLabel label;
6590c58f1c22SToby Isaac 
6591c58f1c22SToby Isaac   PetscFunctionBegin;
6592c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6593c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
65949566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
65957a8be351SBarry Smith   PetscCheck(label, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
65969566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, point, value));
65973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6598c58f1c22SToby Isaac }
6599c58f1c22SToby Isaac 
6600c58f1c22SToby Isaac /*@C
6601bb7acecfSBarry Smith   DMSetLabelValue - Add a point to a `DMLabel` with given value
6602c58f1c22SToby Isaac 
6603c58f1c22SToby Isaac   Not Collective
6604c58f1c22SToby Isaac 
6605c58f1c22SToby Isaac   Input Parameters:
6606bb7acecfSBarry Smith + dm   - The `DM` object
6607c58f1c22SToby Isaac . name - The label name
6608c58f1c22SToby Isaac . point - The mesh point
6609c58f1c22SToby Isaac - value - The label value for this point
6610c58f1c22SToby Isaac 
6611c58f1c22SToby Isaac   Output Parameter:
6612c58f1c22SToby Isaac 
6613c58f1c22SToby Isaac   Level: beginner
6614c58f1c22SToby Isaac 
6615*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelSetValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6616c58f1c22SToby Isaac @*/
6617d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6618d71ae5a4SJacob Faibussowitsch {
6619c58f1c22SToby Isaac   DMLabel label;
6620c58f1c22SToby Isaac 
6621c58f1c22SToby Isaac   PetscFunctionBegin;
6622c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6623c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
66249566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6625c58f1c22SToby Isaac   if (!label) {
66269566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
66279566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
6628c58f1c22SToby Isaac   }
66299566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, point, value));
66303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6631c58f1c22SToby Isaac }
6632c58f1c22SToby Isaac 
6633c58f1c22SToby Isaac /*@C
6634bb7acecfSBarry Smith   DMClearLabelValue - Remove a point from a `DMLabel` with given value
6635c58f1c22SToby Isaac 
6636c58f1c22SToby Isaac   Not Collective
6637c58f1c22SToby Isaac 
6638c58f1c22SToby Isaac   Input Parameters:
6639bb7acecfSBarry Smith + dm   - The `DM` object
6640c58f1c22SToby Isaac . name - The label name
6641c58f1c22SToby Isaac . point - The mesh point
6642c58f1c22SToby Isaac - value - The label value for this point
6643c58f1c22SToby Isaac 
6644c58f1c22SToby Isaac   Level: beginner
6645c58f1c22SToby Isaac 
6646*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelClearValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6647c58f1c22SToby Isaac @*/
6648d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6649d71ae5a4SJacob Faibussowitsch {
6650c58f1c22SToby Isaac   DMLabel label;
6651c58f1c22SToby Isaac 
6652c58f1c22SToby Isaac   PetscFunctionBegin;
6653c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6654c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
66559566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
66563ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
66579566063dSJacob Faibussowitsch   PetscCall(DMLabelClearValue(label, point, value));
66583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6659c58f1c22SToby Isaac }
6660c58f1c22SToby Isaac 
6661c58f1c22SToby Isaac /*@C
6662bb7acecfSBarry Smith   DMGetLabelSize - Get the value of `DMLabelGetNumValues()` of a `DMLabel` in the `DM`
6663c58f1c22SToby Isaac 
6664c58f1c22SToby Isaac   Not Collective
6665c58f1c22SToby Isaac 
6666c58f1c22SToby Isaac   Input Parameters:
6667bb7acecfSBarry Smith + dm   - The `DM` object
6668c58f1c22SToby Isaac - name - The label name
6669c58f1c22SToby Isaac 
6670c58f1c22SToby Isaac   Output Parameter:
6671c58f1c22SToby Isaac . size - The number of different integer ids, or 0 if the label does not exist
6672c58f1c22SToby Isaac 
6673c58f1c22SToby Isaac   Level: beginner
6674c58f1c22SToby Isaac 
6675bb7acecfSBarry Smith   Developer Note:
6676bb7acecfSBarry Smith   This should be renamed to something like `DMGetLabelNumValues()` or removed.
6677bb7acecfSBarry Smith 
6678*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetNumValues()`, `DMSetLabelValue()`, `DMGetLabel()`
6679c58f1c22SToby Isaac @*/
6680d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
6681d71ae5a4SJacob Faibussowitsch {
6682c58f1c22SToby Isaac   DMLabel label;
6683c58f1c22SToby Isaac 
6684c58f1c22SToby Isaac   PetscFunctionBegin;
6685c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6686c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6687534a8f05SLisandro Dalcin   PetscValidIntPointer(size, 3);
66889566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6689c58f1c22SToby Isaac   *size = 0;
66903ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
66919566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, size));
66923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6693c58f1c22SToby Isaac }
6694c58f1c22SToby Isaac 
6695c58f1c22SToby Isaac /*@C
6696bb7acecfSBarry Smith   DMGetLabelIdIS - Get the `DMLabelGetValueIS()` from a `DMLabel` in the `DM`
6697c58f1c22SToby Isaac 
6698c58f1c22SToby Isaac   Not Collective
6699c58f1c22SToby Isaac 
6700c58f1c22SToby Isaac   Input Parameters:
6701bb7acecfSBarry Smith + mesh - The `DM` object
6702c58f1c22SToby Isaac - name - The label name
6703c58f1c22SToby Isaac 
6704c58f1c22SToby Isaac   Output Parameter:
670520f4b53cSBarry Smith . ids - The integer ids, or `NULL` if the label does not exist
6706c58f1c22SToby Isaac 
6707c58f1c22SToby Isaac   Level: beginner
6708c58f1c22SToby Isaac 
6709*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetValueIS()`, `DMGetLabelSize()`
6710c58f1c22SToby Isaac @*/
6711d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
6712d71ae5a4SJacob Faibussowitsch {
6713c58f1c22SToby Isaac   DMLabel label;
6714c58f1c22SToby Isaac 
6715c58f1c22SToby Isaac   PetscFunctionBegin;
6716c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6717c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6718c58f1c22SToby Isaac   PetscValidPointer(ids, 3);
67199566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6720c58f1c22SToby Isaac   *ids = NULL;
6721dab2e251SBlaise Bourdin   if (label) {
67229566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, ids));
6723dab2e251SBlaise Bourdin   } else {
6724dab2e251SBlaise Bourdin     /* returning an empty IS */
67259566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, ids));
6726dab2e251SBlaise Bourdin   }
67273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6728c58f1c22SToby Isaac }
6729c58f1c22SToby Isaac 
6730c58f1c22SToby Isaac /*@C
6731c58f1c22SToby Isaac   DMGetStratumSize - Get the number of points in a label stratum
6732c58f1c22SToby Isaac 
6733c58f1c22SToby Isaac   Not Collective
6734c58f1c22SToby Isaac 
6735c58f1c22SToby Isaac   Input Parameters:
6736bb7acecfSBarry Smith + dm - The `DM` object
6737c58f1c22SToby Isaac . name - The label name
6738c58f1c22SToby Isaac - value - The stratum value
6739c58f1c22SToby Isaac 
6740c58f1c22SToby Isaac   Output Parameter:
6741bb7acecfSBarry Smith . size - The number of points, also called the stratum size
6742c58f1c22SToby Isaac 
6743c58f1c22SToby Isaac   Level: beginner
6744c58f1c22SToby Isaac 
6745*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetStratumSize()`, `DMGetLabelSize()`, `DMGetLabelIds()`
6746c58f1c22SToby Isaac @*/
6747d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
6748d71ae5a4SJacob Faibussowitsch {
6749c58f1c22SToby Isaac   DMLabel label;
6750c58f1c22SToby Isaac 
6751c58f1c22SToby Isaac   PetscFunctionBegin;
6752c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6753c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6754534a8f05SLisandro Dalcin   PetscValidIntPointer(size, 4);
67559566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6756c58f1c22SToby Isaac   *size = 0;
67573ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
67589566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize(label, value, size));
67593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6760c58f1c22SToby Isaac }
6761c58f1c22SToby Isaac 
6762c58f1c22SToby Isaac /*@C
6763c58f1c22SToby Isaac   DMGetStratumIS - Get the points in a label stratum
6764c58f1c22SToby Isaac 
6765c58f1c22SToby Isaac   Not Collective
6766c58f1c22SToby Isaac 
6767c58f1c22SToby Isaac   Input Parameters:
6768bb7acecfSBarry Smith + dm - The `DM` object
6769c58f1c22SToby Isaac . name - The label name
6770c58f1c22SToby Isaac - value - The stratum value
6771c58f1c22SToby Isaac 
6772c58f1c22SToby Isaac   Output Parameter:
677320f4b53cSBarry Smith . points - The stratum points, or `NULL` if the label does not exist or does not have that value
6774c58f1c22SToby Isaac 
6775c58f1c22SToby Isaac   Level: beginner
6776c58f1c22SToby Isaac 
6777*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetStratumIS()`, `DMGetStratumSize()`
6778c58f1c22SToby Isaac @*/
6779d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
6780d71ae5a4SJacob Faibussowitsch {
6781c58f1c22SToby Isaac   DMLabel label;
6782c58f1c22SToby Isaac 
6783c58f1c22SToby Isaac   PetscFunctionBegin;
6784c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6785c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6786c58f1c22SToby Isaac   PetscValidPointer(points, 4);
67879566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6788c58f1c22SToby Isaac   *points = NULL;
67893ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
67909566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, points));
67913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6792c58f1c22SToby Isaac }
6793c58f1c22SToby Isaac 
67944de306b1SToby Isaac /*@C
67959044fa66SMatthew G. Knepley   DMSetStratumIS - Set the points in a label stratum
67964de306b1SToby Isaac 
67974de306b1SToby Isaac   Not Collective
67984de306b1SToby Isaac 
67994de306b1SToby Isaac   Input Parameters:
6800bb7acecfSBarry Smith + dm - The `DM` object
68014de306b1SToby Isaac . name - The label name
68024de306b1SToby Isaac . value - The stratum value
68034de306b1SToby Isaac - points - The stratum points
68044de306b1SToby Isaac 
68054de306b1SToby Isaac   Level: beginner
68064de306b1SToby Isaac 
6807*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMClearLabelStratum()`, `DMLabelClearStratum()`, `DMLabelSetStratumIS()`, `DMGetStratumSize()`
68084de306b1SToby Isaac @*/
6809d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
6810d71ae5a4SJacob Faibussowitsch {
68114de306b1SToby Isaac   DMLabel label;
68124de306b1SToby Isaac 
68134de306b1SToby Isaac   PetscFunctionBegin;
68144de306b1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68154de306b1SToby Isaac   PetscValidCharPointer(name, 2);
68164de306b1SToby Isaac   PetscValidPointer(points, 4);
68179566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
68183ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
68199566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, points));
68203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68214de306b1SToby Isaac }
68224de306b1SToby Isaac 
6823c58f1c22SToby Isaac /*@C
6824bb7acecfSBarry Smith   DMClearLabelStratum - Remove all points from a stratum from a `DMLabel`
6825c58f1c22SToby Isaac 
6826c58f1c22SToby Isaac   Not Collective
6827c58f1c22SToby Isaac 
6828c58f1c22SToby Isaac   Input Parameters:
6829bb7acecfSBarry Smith + dm   - The `DM` object
6830c58f1c22SToby Isaac . name - The label name
6831c58f1c22SToby Isaac - value - The label value for this point
6832c58f1c22SToby Isaac 
6833c58f1c22SToby Isaac   Output Parameter:
6834c58f1c22SToby Isaac 
6835c58f1c22SToby Isaac   Level: beginner
6836c58f1c22SToby Isaac 
6837*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMLabelClearStratum()`, `DMSetLabelValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6838c58f1c22SToby Isaac @*/
6839d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
6840d71ae5a4SJacob Faibussowitsch {
6841c58f1c22SToby Isaac   DMLabel label;
6842c58f1c22SToby Isaac 
6843c58f1c22SToby Isaac   PetscFunctionBegin;
6844c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6845c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
68469566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
68473ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
68489566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
68493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6850c58f1c22SToby Isaac }
6851c58f1c22SToby Isaac 
6852c58f1c22SToby Isaac /*@
6853bb7acecfSBarry Smith   DMGetNumLabels - Return the number of labels defined by on the `DM`
6854c58f1c22SToby Isaac 
6855c58f1c22SToby Isaac   Not Collective
6856c58f1c22SToby Isaac 
6857c58f1c22SToby Isaac   Input Parameter:
6858bb7acecfSBarry Smith . dm   - The `DM` object
6859c58f1c22SToby Isaac 
6860c58f1c22SToby Isaac   Output Parameter:
6861c58f1c22SToby Isaac . numLabels - the number of Labels
6862c58f1c22SToby Isaac 
6863c58f1c22SToby Isaac   Level: intermediate
6864c58f1c22SToby Isaac 
6865*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabelByNum()`, `DMGetLabelName()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6866c58f1c22SToby Isaac @*/
6867d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
6868d71ae5a4SJacob Faibussowitsch {
68695d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6870c58f1c22SToby Isaac   PetscInt    n    = 0;
6871c58f1c22SToby Isaac 
6872c58f1c22SToby Isaac   PetscFunctionBegin;
6873c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6874534a8f05SLisandro Dalcin   PetscValidIntPointer(numLabels, 2);
68759371c9d4SSatish Balay   while (next) {
68769371c9d4SSatish Balay     ++n;
68779371c9d4SSatish Balay     next = next->next;
68789371c9d4SSatish Balay   }
6879c58f1c22SToby Isaac   *numLabels = n;
68803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6881c58f1c22SToby Isaac }
6882c58f1c22SToby Isaac 
6883c58f1c22SToby Isaac /*@C
6884c58f1c22SToby Isaac   DMGetLabelName - Return the name of nth label
6885c58f1c22SToby Isaac 
6886c58f1c22SToby Isaac   Not Collective
6887c58f1c22SToby Isaac 
6888c58f1c22SToby Isaac   Input Parameters:
6889bb7acecfSBarry Smith + dm - The `DM` object
6890c58f1c22SToby Isaac - n  - the label number
6891c58f1c22SToby Isaac 
6892c58f1c22SToby Isaac   Output Parameter:
6893c58f1c22SToby Isaac . name - the label name
6894c58f1c22SToby Isaac 
6895c58f1c22SToby Isaac   Level: intermediate
6896c58f1c22SToby Isaac 
6897bb7acecfSBarry Smith   Developer Note:
6898bb7acecfSBarry Smith   Some of the functions that appropriate on labels using their number have the suffix ByNum, others do not.
6899bb7acecfSBarry Smith 
6900*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabelByNum()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6901c58f1c22SToby Isaac @*/
6902d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
6903d71ae5a4SJacob Faibussowitsch {
69045d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6905c58f1c22SToby Isaac   PetscInt    l    = 0;
6906c58f1c22SToby Isaac 
6907c58f1c22SToby Isaac   PetscFunctionBegin;
6908c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6909c58f1c22SToby Isaac   PetscValidPointer(name, 3);
6910c58f1c22SToby Isaac   while (next) {
6911c58f1c22SToby Isaac     if (l == n) {
69129566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)next->label, name));
69133ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6914c58f1c22SToby Isaac     }
6915c58f1c22SToby Isaac     ++l;
6916c58f1c22SToby Isaac     next = next->next;
6917c58f1c22SToby Isaac   }
691863a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
6919c58f1c22SToby Isaac }
6920c58f1c22SToby Isaac 
6921c58f1c22SToby Isaac /*@C
6922bb7acecfSBarry Smith   DMHasLabel - Determine whether the `DM` has a label of a given name
6923c58f1c22SToby Isaac 
6924c58f1c22SToby Isaac   Not Collective
6925c58f1c22SToby Isaac 
6926c58f1c22SToby Isaac   Input Parameters:
6927bb7acecfSBarry Smith + dm   - The `DM` object
6928c58f1c22SToby Isaac - name - The label name
6929c58f1c22SToby Isaac 
6930c58f1c22SToby Isaac   Output Parameter:
6931bb7acecfSBarry Smith . hasLabel - `PETSC_TRUE` if the label is present
6932c58f1c22SToby Isaac 
6933c58f1c22SToby Isaac   Level: intermediate
6934c58f1c22SToby Isaac 
6935*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabel()`, `DMGetLabelByNum()`, `DMCreateLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6936c58f1c22SToby Isaac @*/
6937d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
6938d71ae5a4SJacob Faibussowitsch {
69395d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6940d67d17b1SMatthew G. Knepley   const char *lname;
6941c58f1c22SToby Isaac 
6942c58f1c22SToby Isaac   PetscFunctionBegin;
6943c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6944c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6945534a8f05SLisandro Dalcin   PetscValidBoolPointer(hasLabel, 3);
6946c58f1c22SToby Isaac   *hasLabel = PETSC_FALSE;
6947c58f1c22SToby Isaac   while (next) {
69489566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
69499566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, hasLabel));
6950c58f1c22SToby Isaac     if (*hasLabel) break;
6951c58f1c22SToby Isaac     next = next->next;
6952c58f1c22SToby Isaac   }
69533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6954c58f1c22SToby Isaac }
6955c58f1c22SToby Isaac 
6956c58f1c22SToby Isaac /*@C
695720f4b53cSBarry Smith   DMGetLabel - Return the label of a given name, or `NULL`, from a `DM`
6958c58f1c22SToby Isaac 
6959c58f1c22SToby Isaac   Not Collective
6960c58f1c22SToby Isaac 
6961c58f1c22SToby Isaac   Input Parameters:
6962bb7acecfSBarry Smith + dm   - The `DM` object
6963c58f1c22SToby Isaac - name - The label name
6964c58f1c22SToby Isaac 
6965c58f1c22SToby Isaac   Output Parameter:
696620f4b53cSBarry Smith . label - The `DMLabel`, or `NULL` if the label is absent
6967c58f1c22SToby Isaac 
6968bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
6969bb7acecfSBarry Smith +   "depth"       - Holds the depth (co-dimension) of each mesh point
6970bb7acecfSBarry Smith .   "celltype"    - Holds the topological type of each cell
6971bb7acecfSBarry Smith .   "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
6972bb7acecfSBarry Smith .   "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
6973bb7acecfSBarry Smith .   "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
6974bb7acecfSBarry Smith -  "Vertex Sets" - Mirrors the vertex sets defined by GMsh
69756d7c9049SMatthew G. Knepley 
6976c58f1c22SToby Isaac   Level: intermediate
6977c58f1c22SToby Isaac 
6978*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMHasLabel()`, `DMGetLabelByNum()`, `DMAddLabel()`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
6979c58f1c22SToby Isaac @*/
6980d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
6981d71ae5a4SJacob Faibussowitsch {
69825d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6983c58f1c22SToby Isaac   PetscBool   hasLabel;
6984d67d17b1SMatthew G. Knepley   const char *lname;
6985c58f1c22SToby Isaac 
6986c58f1c22SToby Isaac   PetscFunctionBegin;
6987c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6988c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6989c58f1c22SToby Isaac   PetscValidPointer(label, 3);
6990c58f1c22SToby Isaac   *label = NULL;
6991c58f1c22SToby Isaac   while (next) {
69929566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
69939566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
6994c58f1c22SToby Isaac     if (hasLabel) {
6995c58f1c22SToby Isaac       *label = next->label;
6996c58f1c22SToby Isaac       break;
6997c58f1c22SToby Isaac     }
6998c58f1c22SToby Isaac     next = next->next;
6999c58f1c22SToby Isaac   }
70003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7001c58f1c22SToby Isaac }
7002c58f1c22SToby Isaac 
7003c58f1c22SToby Isaac /*@C
7004bb7acecfSBarry Smith   DMGetLabelByNum - Return the nth label on a `DM`
7005c58f1c22SToby Isaac 
7006c58f1c22SToby Isaac   Not Collective
7007c58f1c22SToby Isaac 
7008c58f1c22SToby Isaac   Input Parameters:
7009bb7acecfSBarry Smith + dm - The `DM` object
7010c58f1c22SToby Isaac - n  - the label number
7011c58f1c22SToby Isaac 
7012c58f1c22SToby Isaac   Output Parameter:
7013c58f1c22SToby Isaac . label - the label
7014c58f1c22SToby Isaac 
7015c58f1c22SToby Isaac   Level: intermediate
7016c58f1c22SToby Isaac 
7017*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7018c58f1c22SToby Isaac @*/
7019d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
7020d71ae5a4SJacob Faibussowitsch {
70215d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7022c58f1c22SToby Isaac   PetscInt    l    = 0;
7023c58f1c22SToby Isaac 
7024c58f1c22SToby Isaac   PetscFunctionBegin;
7025c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7026c58f1c22SToby Isaac   PetscValidPointer(label, 3);
7027c58f1c22SToby Isaac   while (next) {
7028c58f1c22SToby Isaac     if (l == n) {
7029c58f1c22SToby Isaac       *label = next->label;
70303ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
7031c58f1c22SToby Isaac     }
7032c58f1c22SToby Isaac     ++l;
7033c58f1c22SToby Isaac     next = next->next;
7034c58f1c22SToby Isaac   }
703563a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
7036c58f1c22SToby Isaac }
7037c58f1c22SToby Isaac 
7038c58f1c22SToby Isaac /*@C
7039bb7acecfSBarry Smith   DMAddLabel - Add the label to this `DM`
7040c58f1c22SToby Isaac 
7041c58f1c22SToby Isaac   Not Collective
7042c58f1c22SToby Isaac 
7043c58f1c22SToby Isaac   Input Parameters:
7044bb7acecfSBarry Smith + dm   - The `DM` object
7045bb7acecfSBarry Smith - label - The `DMLabel`
7046c58f1c22SToby Isaac 
7047c58f1c22SToby Isaac   Level: developer
7048c58f1c22SToby Isaac 
7049*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7050c58f1c22SToby Isaac @*/
7051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddLabel(DM dm, DMLabel label)
7052d71ae5a4SJacob Faibussowitsch {
70535d80c0bfSVaclav Hapla   DMLabelLink l, *p, tmpLabel;
7054c58f1c22SToby Isaac   PetscBool   hasLabel;
7055d67d17b1SMatthew G. Knepley   const char *lname;
70565d80c0bfSVaclav Hapla   PetscBool   flg;
7057c58f1c22SToby Isaac 
7058c58f1c22SToby Isaac   PetscFunctionBegin;
7059c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70609566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
70619566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, lname, &hasLabel));
70627a8be351SBarry Smith   PetscCheck(!hasLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname);
70639566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(1, &tmpLabel));
7064c58f1c22SToby Isaac   tmpLabel->label  = label;
7065c58f1c22SToby Isaac   tmpLabel->output = PETSC_TRUE;
70665d80c0bfSVaclav Hapla   for (p = &dm->labels; (l = *p); p = &l->next) { }
70675d80c0bfSVaclav Hapla   *p = tmpLabel;
70689566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
70699566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "depth", &flg));
70705d80c0bfSVaclav Hapla   if (flg) dm->depthLabel = label;
70719566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "celltype", &flg));
7072ba2698f1SMatthew G. Knepley   if (flg) dm->celltypeLabel = label;
70733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7074c58f1c22SToby Isaac }
7075c58f1c22SToby Isaac 
7076c58f1c22SToby Isaac /*@C
70774a7ee7d0SMatthew G. Knepley   DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present
70784a7ee7d0SMatthew G. Knepley 
70794a7ee7d0SMatthew G. Knepley   Not Collective
70804a7ee7d0SMatthew G. Knepley 
70814a7ee7d0SMatthew G. Knepley   Input Parameters:
7082bb7acecfSBarry Smith + dm    - The `DM` object
7083bb7acecfSBarry Smith - label - The `DMLabel`, having the same name, to substitute
70844a7ee7d0SMatthew G. Knepley 
7085bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
7086bb7acecfSBarry Smith +  "depth"       - Holds the depth (co-dimension) of each mesh point
7087bb7acecfSBarry Smith .  "celltype"    - Holds the topological type of each cell
7088bb7acecfSBarry Smith .  "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
7089bb7acecfSBarry Smith .  "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
7090bb7acecfSBarry Smith .  "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
7091bb7acecfSBarry Smith - "Vertex Sets" - Mirrors the vertex sets defined by GMsh
70924a7ee7d0SMatthew G. Knepley 
70934a7ee7d0SMatthew G. Knepley   Level: intermediate
70944a7ee7d0SMatthew G. Knepley 
7095*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
70964a7ee7d0SMatthew G. Knepley @*/
7097d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabel(DM dm, DMLabel label)
7098d71ae5a4SJacob Faibussowitsch {
70994a7ee7d0SMatthew G. Knepley   DMLabelLink next = dm->labels;
71004a7ee7d0SMatthew G. Knepley   PetscBool   hasLabel, flg;
71014a7ee7d0SMatthew G. Knepley   const char *name, *lname;
71024a7ee7d0SMatthew G. Knepley 
71034a7ee7d0SMatthew G. Knepley   PetscFunctionBegin;
71044a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71054a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
71069566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
71074a7ee7d0SMatthew G. Knepley   while (next) {
71089566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
71099566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
71104a7ee7d0SMatthew G. Knepley     if (hasLabel) {
71119566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)label));
71129566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "depth", &flg));
71134a7ee7d0SMatthew G. Knepley       if (flg) dm->depthLabel = label;
71149566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "celltype", &flg));
71154a7ee7d0SMatthew G. Knepley       if (flg) dm->celltypeLabel = label;
71169566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&next->label));
71174a7ee7d0SMatthew G. Knepley       next->label = label;
71184a7ee7d0SMatthew G. Knepley       break;
71194a7ee7d0SMatthew G. Knepley     }
71204a7ee7d0SMatthew G. Knepley     next = next->next;
71214a7ee7d0SMatthew G. Knepley   }
71223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71234a7ee7d0SMatthew G. Knepley }
71244a7ee7d0SMatthew G. Knepley 
71254a7ee7d0SMatthew G. Knepley /*@C
7126bb7acecfSBarry Smith   DMRemoveLabel - Remove the label given by name from this `DM`
7127c58f1c22SToby Isaac 
7128c58f1c22SToby Isaac   Not Collective
7129c58f1c22SToby Isaac 
7130c58f1c22SToby Isaac   Input Parameters:
7131bb7acecfSBarry Smith + dm   - The `DM` object
7132c58f1c22SToby Isaac - name - The label name
7133c58f1c22SToby Isaac 
7134c58f1c22SToby Isaac   Output Parameter:
713520f4b53cSBarry Smith . label - The `DMLabel`, or `NULL` if the label is absent. Pass in `NULL` to call `DMLabelDestroy()` on the label, otherwise the
7136bb7acecfSBarry Smith           caller is responsible for calling `DMLabelDestroy()`.
7137c58f1c22SToby Isaac 
7138c58f1c22SToby Isaac   Level: developer
7139c58f1c22SToby Isaac 
7140*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabelBySelf()`
7141c58f1c22SToby Isaac @*/
7142d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
7143d71ae5a4SJacob Faibussowitsch {
714495d578d6SVaclav Hapla   DMLabelLink link, *pnext;
7145c58f1c22SToby Isaac   PetscBool   hasLabel;
7146d67d17b1SMatthew G. Knepley   const char *lname;
7147c58f1c22SToby Isaac 
7148c58f1c22SToby Isaac   PetscFunctionBegin;
7149c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7150e5472504SVaclav Hapla   PetscValidCharPointer(name, 2);
7151e5472504SVaclav Hapla   if (label) {
7152e5472504SVaclav Hapla     PetscValidPointer(label, 3);
7153c58f1c22SToby Isaac     *label = NULL;
7154e5472504SVaclav Hapla   }
71555d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
71569566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)link->label, &lname));
71579566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
7158c58f1c22SToby Isaac     if (hasLabel) {
715995d578d6SVaclav Hapla       *pnext = link->next; /* Remove from list */
71609566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &hasLabel));
716195d578d6SVaclav Hapla       if (hasLabel) dm->depthLabel = NULL;
71629566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &hasLabel));
7163ba2698f1SMatthew G. Knepley       if (hasLabel) dm->celltypeLabel = NULL;
716495d578d6SVaclav Hapla       if (label) *label = link->label;
71659566063dSJacob Faibussowitsch       else PetscCall(DMLabelDestroy(&link->label));
71669566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7167c58f1c22SToby Isaac       break;
7168c58f1c22SToby Isaac     }
7169c58f1c22SToby Isaac   }
71703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7171c58f1c22SToby Isaac }
7172c58f1c22SToby Isaac 
7173306894acSVaclav Hapla /*@
7174bb7acecfSBarry Smith   DMRemoveLabelBySelf - Remove the label from this `DM`
7175306894acSVaclav Hapla 
7176306894acSVaclav Hapla   Not Collective
7177306894acSVaclav Hapla 
7178306894acSVaclav Hapla   Input Parameters:
7179bb7acecfSBarry Smith + dm   - The `DM` object
7180bb7acecfSBarry Smith . label - The `DMLabel` to be removed from the `DM`
718120f4b53cSBarry Smith - failNotFound - Should it fail if the label is not found in the `DM`?
7182306894acSVaclav Hapla 
7183306894acSVaclav Hapla   Level: developer
7184306894acSVaclav Hapla 
7185bb7acecfSBarry Smith   Note:
7186306894acSVaclav Hapla   Only exactly the same instance is removed if found, name match is ignored.
7187bb7acecfSBarry Smith   If the `DM` has an exclusive reference to the label, the label gets destroyed and
7188306894acSVaclav Hapla   *label nullified.
7189306894acSVaclav Hapla 
7190*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()` `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabel()`
7191306894acSVaclav Hapla @*/
7192d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound)
7193d71ae5a4SJacob Faibussowitsch {
719443e45a93SVaclav Hapla   DMLabelLink link, *pnext;
7195306894acSVaclav Hapla   PetscBool   hasLabel = PETSC_FALSE;
7196306894acSVaclav Hapla 
7197306894acSVaclav Hapla   PetscFunctionBegin;
7198306894acSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7199306894acSVaclav Hapla   PetscValidPointer(label, 2);
72003ba16761SJacob Faibussowitsch   if (!*label && !failNotFound) PetscFunctionReturn(PETSC_SUCCESS);
7201306894acSVaclav Hapla   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2);
7202306894acSVaclav Hapla   PetscValidLogicalCollectiveBool(dm, failNotFound, 3);
72035d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
720443e45a93SVaclav Hapla     if (*label == link->label) {
7205306894acSVaclav Hapla       hasLabel = PETSC_TRUE;
720643e45a93SVaclav Hapla       *pnext   = link->next; /* Remove from list */
7207306894acSVaclav Hapla       if (*label == dm->depthLabel) dm->depthLabel = NULL;
7208ba2698f1SMatthew G. Knepley       if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL;
720943e45a93SVaclav Hapla       if (((PetscObject)link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */
72109566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&link->label));
72119566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7212306894acSVaclav Hapla       break;
7213306894acSVaclav Hapla     }
7214306894acSVaclav Hapla   }
72157a8be351SBarry Smith   PetscCheck(hasLabel || !failNotFound, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM");
72163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7217306894acSVaclav Hapla }
7218306894acSVaclav Hapla 
7219c58f1c22SToby Isaac /*@C
7220c58f1c22SToby Isaac   DMGetLabelOutput - Get the output flag for a given label
7221c58f1c22SToby Isaac 
7222c58f1c22SToby Isaac   Not Collective
7223c58f1c22SToby Isaac 
7224c58f1c22SToby Isaac   Input Parameters:
7225bb7acecfSBarry Smith + dm   - The `DM` object
7226c58f1c22SToby Isaac - name - The label name
7227c58f1c22SToby Isaac 
7228c58f1c22SToby Isaac   Output Parameter:
7229c58f1c22SToby Isaac . output - The flag for output
7230c58f1c22SToby Isaac 
7231c58f1c22SToby Isaac   Level: developer
7232c58f1c22SToby Isaac 
7233*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMSetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7234c58f1c22SToby Isaac @*/
7235d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
7236d71ae5a4SJacob Faibussowitsch {
72375d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7238d67d17b1SMatthew G. Knepley   const char *lname;
7239c58f1c22SToby Isaac 
7240c58f1c22SToby Isaac   PetscFunctionBegin;
7241c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7242dadcf809SJacob Faibussowitsch   PetscValidCharPointer(name, 2);
7243dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(output, 3);
7244c58f1c22SToby Isaac   while (next) {
7245c58f1c22SToby Isaac     PetscBool flg;
7246c58f1c22SToby Isaac 
72479566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
72489566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
72499371c9d4SSatish Balay     if (flg) {
72509371c9d4SSatish Balay       *output = next->output;
72513ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
72529371c9d4SSatish Balay     }
7253c58f1c22SToby Isaac     next = next->next;
7254c58f1c22SToby Isaac   }
725598921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7256c58f1c22SToby Isaac }
7257c58f1c22SToby Isaac 
7258c58f1c22SToby Isaac /*@C
7259bb7acecfSBarry Smith   DMSetLabelOutput - Set if a given label should be saved to a `PetscViewer` in calls to `DMView()`
7260c58f1c22SToby Isaac 
7261c58f1c22SToby Isaac   Not Collective
7262c58f1c22SToby Isaac 
7263c58f1c22SToby Isaac   Input Parameters:
7264bb7acecfSBarry Smith + dm     - The `DM` object
7265c58f1c22SToby Isaac . name   - The label name
7266bb7acecfSBarry Smith - output - `PETSC_TRUE` to save the label to the viewer
7267c58f1c22SToby Isaac 
7268c58f1c22SToby Isaac   Level: developer
7269c58f1c22SToby Isaac 
7270*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetOutputFlag()`, `DMGetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7271c58f1c22SToby Isaac @*/
7272d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
7273d71ae5a4SJacob Faibussowitsch {
72745d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7275d67d17b1SMatthew G. Knepley   const char *lname;
7276c58f1c22SToby Isaac 
7277c58f1c22SToby Isaac   PetscFunctionBegin;
7278c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7279534a8f05SLisandro Dalcin   PetscValidCharPointer(name, 2);
7280c58f1c22SToby Isaac   while (next) {
7281c58f1c22SToby Isaac     PetscBool flg;
7282c58f1c22SToby Isaac 
72839566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
72849566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
72859371c9d4SSatish Balay     if (flg) {
72869371c9d4SSatish Balay       next->output = output;
72873ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
72889371c9d4SSatish Balay     }
7289c58f1c22SToby Isaac     next = next->next;
7290c58f1c22SToby Isaac   }
729198921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7292c58f1c22SToby Isaac }
7293c58f1c22SToby Isaac 
7294c58f1c22SToby Isaac /*@
7295bb7acecfSBarry Smith   DMCopyLabels - Copy labels from one `DM` mesh to another `DM` with a superset of the points
7296c58f1c22SToby Isaac 
729720f4b53cSBarry Smith   Collective
7298c58f1c22SToby Isaac 
7299d8d19677SJose E. Roman   Input Parameters:
7300bb7acecfSBarry Smith + dmA - The `DM` object with initial labels
7301bb7acecfSBarry Smith . dmB - The `DM` object to which labels are copied
7302bb7acecfSBarry Smith . mode - Copy labels by pointers (`PETSC_OWN_POINTER`) or duplicate them (`PETSC_COPY_VALUES`)
7303bb7acecfSBarry Smith . all  - Copy all labels including "depth", "dim", and "celltype" (`PETSC_TRUE`) which are otherwise ignored (`PETSC_FALSE`)
7304bb7acecfSBarry Smith - emode - How to behave when a `DMLabel` in the source and destination `DM`s with the same name is encountered (see `DMCopyLabelsMode`)
7305c58f1c22SToby Isaac 
7306c58f1c22SToby Isaac   Level: intermediate
7307c58f1c22SToby Isaac 
7308bb7acecfSBarry Smith   Note:
73092cbb9b06SVaclav Hapla   This is typically used when interpolating or otherwise adding to a mesh, or testing.
7310c58f1c22SToby Isaac 
7311*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`
7312c58f1c22SToby Isaac @*/
7313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all, DMCopyLabelsMode emode)
7314d71ae5a4SJacob Faibussowitsch {
73152cbb9b06SVaclav Hapla   DMLabel     label, labelNew, labelOld;
7316c58f1c22SToby Isaac   const char *name;
7317c58f1c22SToby Isaac   PetscBool   flg;
73185d80c0bfSVaclav Hapla   DMLabelLink link;
7319c58f1c22SToby Isaac 
73205d80c0bfSVaclav Hapla   PetscFunctionBegin;
73215d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
73225d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
73235d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveEnum(dmA, mode, 3);
73245d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveBool(dmA, all, 4);
73257a8be351SBarry Smith   PetscCheck(mode != PETSC_USE_POINTER, PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects");
73263ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
73275d80c0bfSVaclav Hapla   for (link = dmA->labels; link; link = link->next) {
73285d80c0bfSVaclav Hapla     label = link->label;
73299566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
73305d80c0bfSVaclav Hapla     if (!all) {
73319566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &flg));
7332c58f1c22SToby Isaac       if (flg) continue;
73339566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "dim", &flg));
73347d5acc75SStefano Zampini       if (flg) continue;
73359566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &flg));
7336ba2698f1SMatthew G. Knepley       if (flg) continue;
73375d80c0bfSVaclav Hapla     }
73389566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dmB, name, &labelOld));
73392cbb9b06SVaclav Hapla     if (labelOld) {
73402cbb9b06SVaclav Hapla       switch (emode) {
7341d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_KEEP:
7342d71ae5a4SJacob Faibussowitsch         continue;
7343d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_REPLACE:
7344d71ae5a4SJacob Faibussowitsch         PetscCall(DMRemoveLabelBySelf(dmB, &labelOld, PETSC_TRUE));
7345d71ae5a4SJacob Faibussowitsch         break;
7346d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_FAIL:
7347d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in destination DM", name);
7348d71ae5a4SJacob Faibussowitsch       default:
7349d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Unhandled DMCopyLabelsMode %d", (int)emode);
73502cbb9b06SVaclav Hapla       }
73512cbb9b06SVaclav Hapla     }
73525d80c0bfSVaclav Hapla     if (mode == PETSC_COPY_VALUES) {
73539566063dSJacob Faibussowitsch       PetscCall(DMLabelDuplicate(label, &labelNew));
73545d80c0bfSVaclav Hapla     } else {
73555d80c0bfSVaclav Hapla       labelNew = label;
73565d80c0bfSVaclav Hapla     }
73579566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dmB, labelNew));
73589566063dSJacob Faibussowitsch     if (mode == PETSC_COPY_VALUES) PetscCall(DMLabelDestroy(&labelNew));
7359c58f1c22SToby Isaac   }
73603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7361c58f1c22SToby Isaac }
7362461a15a0SLisandro Dalcin 
7363609dae6eSVaclav Hapla /*@C
7364bb7acecfSBarry Smith   DMCompareLabels - Compare labels of two `DMPLEX` meshes
7365609dae6eSVaclav Hapla 
736620f4b53cSBarry Smith   Collective; No Fortran Support
7367609dae6eSVaclav Hapla 
7368609dae6eSVaclav Hapla   Input Parameters:
7369bb7acecfSBarry Smith + dm0 - First `DM` object
7370bb7acecfSBarry Smith - dm1 - Second `DM` object
7371609dae6eSVaclav Hapla 
7372609dae6eSVaclav Hapla   Output Parameters
73735efe38ccSVaclav Hapla + equal   - (Optional) Flag whether labels of dm0 and dm1 are the same
737420f4b53cSBarry Smith - message - (Optional) Message describing the difference, or `NULL` if there is no difference
7375609dae6eSVaclav Hapla 
7376609dae6eSVaclav Hapla   Level: intermediate
7377609dae6eSVaclav Hapla 
7378609dae6eSVaclav Hapla   Notes:
7379bb7acecfSBarry Smith   The output flag equal will be the same on all processes.
7380bb7acecfSBarry Smith 
738120f4b53cSBarry Smith   If equal is passed as `NULL` and difference is found, an error is thrown on all processes.
7382bb7acecfSBarry Smith 
738320f4b53cSBarry Smith   Make sure to pass equal is `NULL` on all processes or none of them.
7384609dae6eSVaclav Hapla 
73855efe38ccSVaclav Hapla   The output message is set independently on each rank.
7386bb7acecfSBarry Smith 
7387bb7acecfSBarry Smith   message must be freed with `PetscFree()`
7388bb7acecfSBarry Smith 
738920f4b53cSBarry Smith   If message is passed as `NULL` and a difference is found, the difference description is printed to stderr in synchronized manner.
7390bb7acecfSBarry Smith 
739120f4b53cSBarry Smith   Make sure to pass message as `NULL` on all processes or no processes.
7392609dae6eSVaclav Hapla 
7393609dae6eSVaclav Hapla   Labels are matched by name. If the number of labels and their names are equal,
7394bb7acecfSBarry Smith   `DMLabelCompare()` is used to compare each pair of labels with the same name.
7395609dae6eSVaclav Hapla 
7396*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`, `DMLabelCompare()`
7397609dae6eSVaclav Hapla @*/
7398d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompareLabels(DM dm0, DM dm1, PetscBool *equal, char **message)
7399d71ae5a4SJacob Faibussowitsch {
74005efe38ccSVaclav Hapla   PetscInt    n, i;
7401609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
74025efe38ccSVaclav Hapla   PetscBool   eq;
7403609dae6eSVaclav Hapla   MPI_Comm    comm;
74045efe38ccSVaclav Hapla   PetscMPIInt rank;
7405609dae6eSVaclav Hapla 
7406609dae6eSVaclav Hapla   PetscFunctionBegin;
7407609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm0, DM_CLASSID, 1);
7408609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm1, DM_CLASSID, 2);
7409609dae6eSVaclav Hapla   PetscCheckSameComm(dm0, 1, dm1, 2);
74105efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 3);
7411609dae6eSVaclav Hapla   if (message) PetscValidPointer(message, 4);
74129566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm0, &comm));
74139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
74145efe38ccSVaclav Hapla   {
74155efe38ccSVaclav Hapla     PetscInt n1;
74165efe38ccSVaclav Hapla 
74179566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm0, &n));
74189566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm1, &n1));
74195efe38ccSVaclav Hapla     eq = (PetscBool)(n == n1);
742048a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Number of labels in dm0 = %" PetscInt_FMT " != %" PetscInt_FMT " = Number of labels in dm1", n, n1));
7421712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
74225efe38ccSVaclav Hapla     if (!eq) goto finish;
74235efe38ccSVaclav Hapla   }
74245efe38ccSVaclav Hapla   for (i = 0; i < n; i++) {
7425609dae6eSVaclav Hapla     DMLabel     l0, l1;
7426609dae6eSVaclav Hapla     const char *name;
7427609dae6eSVaclav Hapla     char       *msgInner;
7428609dae6eSVaclav Hapla 
7429609dae6eSVaclav Hapla     /* Ignore label order */
74309566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm0, i, &l0));
74319566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)l0, &name));
74329566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm1, name, &l1));
7433609dae6eSVaclav Hapla     if (!l1) {
743463a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Label \"%s\" (#%" PetscInt_FMT " in dm0) not found in dm1", name, i));
74355efe38ccSVaclav Hapla       eq = PETSC_FALSE;
74365efe38ccSVaclav Hapla       break;
7437609dae6eSVaclav Hapla     }
74389566063dSJacob Faibussowitsch     PetscCall(DMLabelCompare(comm, l0, l1, &eq, &msgInner));
74399566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(msg, msgInner, sizeof(msg)));
74409566063dSJacob Faibussowitsch     PetscCall(PetscFree(msgInner));
74415efe38ccSVaclav Hapla     if (!eq) break;
7442609dae6eSVaclav Hapla   }
7443712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
7444609dae6eSVaclav Hapla finish:
74455efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
7446609dae6eSVaclav Hapla   if (message) {
7447609dae6eSVaclav Hapla     *message = NULL;
744848a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
74495efe38ccSVaclav Hapla   } else {
745048a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
74519566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
74525efe38ccSVaclav Hapla   }
74535efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
74545efe38ccSVaclav Hapla   if (equal) *equal = eq;
74557a8be351SBarry Smith   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels are not the same in dm0 and dm1");
74563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7457609dae6eSVaclav Hapla }
7458609dae6eSVaclav Hapla 
7459d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value)
7460d71ae5a4SJacob Faibussowitsch {
7461461a15a0SLisandro Dalcin   PetscFunctionBegin;
7462461a15a0SLisandro Dalcin   PetscValidPointer(label, 2);
7463461a15a0SLisandro Dalcin   if (!*label) {
74649566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
74659566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, label));
7466461a15a0SLisandro Dalcin   }
74679566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(*label, point, value));
74683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7469461a15a0SLisandro Dalcin }
7470461a15a0SLisandro Dalcin 
74710fdc7489SMatthew Knepley /*
74720fdc7489SMatthew Knepley   Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would
74730fdc7489SMatthew Knepley   like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every
74740fdc7489SMatthew Knepley   (label, id) pair in the DM.
74750fdc7489SMatthew Knepley 
74760fdc7489SMatthew Knepley   However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to
74770fdc7489SMatthew Knepley   each label.
74780fdc7489SMatthew Knepley */
7479d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal)
7480d71ae5a4SJacob Faibussowitsch {
74810fdc7489SMatthew Knepley   DMUniversalLabel ul;
74820fdc7489SMatthew Knepley   PetscBool       *active;
74830fdc7489SMatthew Knepley   PetscInt         pStart, pEnd, p, Nl, l, m;
74840fdc7489SMatthew Knepley 
74850fdc7489SMatthew Knepley   PetscFunctionBegin;
74869566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, &ul));
74879566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label));
74889566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
74899566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Nl, &active));
74900fdc7489SMatthew Knepley   ul->Nl = 0;
74910fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
74920fdc7489SMatthew Knepley     PetscBool   isdepth, iscelltype;
74930fdc7489SMatthew Knepley     const char *name;
74940fdc7489SMatthew Knepley 
74959566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
74969566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "depth", 6, &isdepth));
74979566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "celltype", 9, &iscelltype));
74980fdc7489SMatthew Knepley     active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE;
74990fdc7489SMatthew Knepley     if (active[l]) ++ul->Nl;
75000fdc7489SMatthew Knepley   }
75019566063dSJacob Faibussowitsch   PetscCall(PetscCalloc5(ul->Nl, &ul->names, ul->Nl, &ul->indices, ul->Nl + 1, &ul->offsets, ul->Nl + 1, &ul->bits, ul->Nl, &ul->masks));
75020fdc7489SMatthew Knepley   ul->Nv = 0;
75030fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
75040fdc7489SMatthew Knepley     DMLabel     label;
75050fdc7489SMatthew Knepley     PetscInt    nv;
75060fdc7489SMatthew Knepley     const char *name;
75070fdc7489SMatthew Knepley 
75080fdc7489SMatthew Knepley     if (!active[l]) continue;
75099566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
75109566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
75119566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
75129566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &ul->names[m]));
75130fdc7489SMatthew Knepley     ul->indices[m] = l;
75140fdc7489SMatthew Knepley     ul->Nv += nv;
75150fdc7489SMatthew Knepley     ul->offsets[m + 1] = nv;
75160fdc7489SMatthew Knepley     ul->bits[m + 1]    = PetscCeilReal(PetscLog2Real(nv + 1));
75170fdc7489SMatthew Knepley     ++m;
75180fdc7489SMatthew Knepley   }
75190fdc7489SMatthew Knepley   for (l = 1; l <= ul->Nl; ++l) {
75200fdc7489SMatthew Knepley     ul->offsets[l] = ul->offsets[l - 1] + ul->offsets[l];
75210fdc7489SMatthew Knepley     ul->bits[l]    = ul->bits[l - 1] + ul->bits[l];
75220fdc7489SMatthew Knepley   }
75230fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
75240fdc7489SMatthew Knepley     PetscInt b;
75250fdc7489SMatthew Knepley 
75260fdc7489SMatthew Knepley     ul->masks[l] = 0;
75270fdc7489SMatthew Knepley     for (b = ul->bits[l]; b < ul->bits[l + 1]; ++b) ul->masks[l] |= 1 << b;
75280fdc7489SMatthew Knepley   }
75299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ul->Nv, &ul->values));
75300fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
75310fdc7489SMatthew Knepley     DMLabel         label;
75320fdc7489SMatthew Knepley     IS              valueIS;
75330fdc7489SMatthew Knepley     const PetscInt *varr;
75340fdc7489SMatthew Knepley     PetscInt        nv, v;
75350fdc7489SMatthew Knepley 
75360fdc7489SMatthew Knepley     if (!active[l]) continue;
75379566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
75389566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
75399566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, &valueIS));
75409566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(valueIS, &varr));
7541ad540459SPierre Jolivet     for (v = 0; v < nv; ++v) ul->values[ul->offsets[m] + v] = varr[v];
75429566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(valueIS, &varr));
75439566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&valueIS));
75449566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(nv, &ul->values[ul->offsets[m]]));
75450fdc7489SMatthew Knepley     ++m;
75460fdc7489SMatthew Knepley   }
75479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
75480fdc7489SMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
75490fdc7489SMatthew Knepley     PetscInt  uval   = 0;
75500fdc7489SMatthew Knepley     PetscBool marked = PETSC_FALSE;
75510fdc7489SMatthew Knepley 
75520fdc7489SMatthew Knepley     for (l = 0, m = 0; l < Nl; ++l) {
75530fdc7489SMatthew Knepley       DMLabel  label;
75540649b39aSStefano Zampini       PetscInt val, defval, loc, nv;
75550fdc7489SMatthew Knepley 
75560fdc7489SMatthew Knepley       if (!active[l]) continue;
75579566063dSJacob Faibussowitsch       PetscCall(DMGetLabelByNum(dm, l, &label));
75589566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, p, &val));
75599566063dSJacob Faibussowitsch       PetscCall(DMLabelGetDefaultValue(label, &defval));
75609371c9d4SSatish Balay       if (val == defval) {
75619371c9d4SSatish Balay         ++m;
75629371c9d4SSatish Balay         continue;
75639371c9d4SSatish Balay       }
75640649b39aSStefano Zampini       nv     = ul->offsets[m + 1] - ul->offsets[m];
75650fdc7489SMatthew Knepley       marked = PETSC_TRUE;
75669566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc));
756763a3b9bcSJacob Faibussowitsch       PetscCheck(loc >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %" PetscInt_FMT " not found in compression array", val);
75680fdc7489SMatthew Knepley       uval += (loc + 1) << ul->bits[m];
75690fdc7489SMatthew Knepley       ++m;
75700fdc7489SMatthew Knepley     }
75719566063dSJacob Faibussowitsch     if (marked) PetscCall(DMLabelSetValue(ul->label, p, uval));
75720fdc7489SMatthew Knepley   }
75739566063dSJacob Faibussowitsch   PetscCall(PetscFree(active));
75740fdc7489SMatthew Knepley   *universal = ul;
75753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75760fdc7489SMatthew Knepley }
75770fdc7489SMatthew Knepley 
7578d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal)
7579d71ae5a4SJacob Faibussowitsch {
75800fdc7489SMatthew Knepley   PetscInt l;
75810fdc7489SMatthew Knepley 
75820fdc7489SMatthew Knepley   PetscFunctionBegin;
75839566063dSJacob Faibussowitsch   for (l = 0; l < (*universal)->Nl; ++l) PetscCall(PetscFree((*universal)->names[l]));
75849566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&(*universal)->label));
75859566063dSJacob Faibussowitsch   PetscCall(PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks));
75869566063dSJacob Faibussowitsch   PetscCall(PetscFree((*universal)->values));
75879566063dSJacob Faibussowitsch   PetscCall(PetscFree(*universal));
75880fdc7489SMatthew Knepley   *universal = NULL;
75893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75900fdc7489SMatthew Knepley }
75910fdc7489SMatthew Knepley 
7592d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel)
7593d71ae5a4SJacob Faibussowitsch {
75940fdc7489SMatthew Knepley   PetscFunctionBegin;
75950fdc7489SMatthew Knepley   PetscValidPointer(ulabel, 2);
75960fdc7489SMatthew Knepley   *ulabel = ul->label;
75973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75980fdc7489SMatthew Knepley }
75990fdc7489SMatthew Knepley 
7600d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm)
7601d71ae5a4SJacob Faibussowitsch {
76020fdc7489SMatthew Knepley   PetscInt Nl = ul->Nl, l;
76030fdc7489SMatthew Knepley 
76040fdc7489SMatthew Knepley   PetscFunctionBegin;
7605064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 3);
76060fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
76079566063dSJacob Faibussowitsch     if (preserveOrder) PetscCall(DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]));
76089566063dSJacob Faibussowitsch     else PetscCall(DMCreateLabel(dm, ul->names[l]));
76090fdc7489SMatthew Knepley   }
76100fdc7489SMatthew Knepley   if (preserveOrder) {
76110fdc7489SMatthew Knepley     for (l = 0; l < ul->Nl; ++l) {
76120fdc7489SMatthew Knepley       const char *name;
76130fdc7489SMatthew Knepley       PetscBool   match;
76140fdc7489SMatthew Knepley 
76159566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, ul->indices[l], &name));
76169566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, ul->names[l], &match));
761763a3b9bcSJacob Faibussowitsch       PetscCheck(match, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %" PetscInt_FMT " name %s does not match new name %s", l, name, ul->names[l]);
76180fdc7489SMatthew Knepley     }
76190fdc7489SMatthew Knepley   }
76203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76210fdc7489SMatthew Knepley }
76220fdc7489SMatthew Knepley 
7623d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value)
7624d71ae5a4SJacob Faibussowitsch {
76250fdc7489SMatthew Knepley   PetscInt l;
76260fdc7489SMatthew Knepley 
76270fdc7489SMatthew Knepley   PetscFunctionBegin;
76280fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
76290fdc7489SMatthew Knepley     DMLabel  label;
76300fdc7489SMatthew Knepley     PetscInt lval = (value & ul->masks[l]) >> ul->bits[l];
76310fdc7489SMatthew Knepley 
76320fdc7489SMatthew Knepley     if (lval) {
76339566063dSJacob Faibussowitsch       if (useIndex) PetscCall(DMGetLabelByNum(dm, ul->indices[l], &label));
76349566063dSJacob Faibussowitsch       else PetscCall(DMGetLabel(dm, ul->names[l], &label));
76359566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(label, p, ul->values[ul->offsets[l] + lval - 1]));
76360fdc7489SMatthew Knepley     }
76370fdc7489SMatthew Knepley   }
76383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76390fdc7489SMatthew Knepley }
7640a8fb8f29SToby Isaac 
7641a8fb8f29SToby Isaac /*@
7642bb7acecfSBarry Smith   DMGetCoarseDM - Get the coarse `DM`from which this `DM` was obtained by refinement
7643bb7acecfSBarry Smith 
764420f4b53cSBarry Smith   Not Collective
7645a8fb8f29SToby Isaac 
7646a8fb8f29SToby Isaac   Input Parameter:
7647bb7acecfSBarry Smith . dm - The `DM` object
7648a8fb8f29SToby Isaac 
7649a8fb8f29SToby Isaac   Output Parameter:
7650bb7acecfSBarry Smith . cdm - The coarse `DM`
7651a8fb8f29SToby Isaac 
7652a8fb8f29SToby Isaac   Level: intermediate
7653a8fb8f29SToby Isaac 
7654*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetCoarseDM()`, `DMCoarsen()`
7655a8fb8f29SToby Isaac @*/
7656d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
7657d71ae5a4SJacob Faibussowitsch {
7658a8fb8f29SToby Isaac   PetscFunctionBegin;
7659a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7660a8fb8f29SToby Isaac   PetscValidPointer(cdm, 2);
7661a8fb8f29SToby Isaac   *cdm = dm->coarseMesh;
76623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7663a8fb8f29SToby Isaac }
7664a8fb8f29SToby Isaac 
7665a8fb8f29SToby Isaac /*@
7666bb7acecfSBarry Smith   DMSetCoarseDM - Set the coarse `DM` from which this `DM` was obtained by refinement
7667a8fb8f29SToby Isaac 
7668a8fb8f29SToby Isaac   Input Parameters:
7669bb7acecfSBarry Smith + dm - The `DM` object
7670bb7acecfSBarry Smith - cdm - The coarse `DM`
7671a8fb8f29SToby Isaac 
7672a8fb8f29SToby Isaac   Level: intermediate
7673a8fb8f29SToby Isaac 
7674bb7acecfSBarry Smith   Note:
7675bb7acecfSBarry Smith   Normally this is set automatically by `DMRefine()`
7676bb7acecfSBarry Smith 
7677*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetCoarseDM()`, `DMCoarsen()`, `DMSetRefine()`, `DMSetFineDM()`
7678a8fb8f29SToby Isaac @*/
7679d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
7680d71ae5a4SJacob Faibussowitsch {
7681a8fb8f29SToby Isaac   PetscFunctionBegin;
7682a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7683a8fb8f29SToby Isaac   if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
768489d734beSBarry Smith   if (dm == cdm) cdm = NULL;
76859566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)cdm));
76869566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->coarseMesh));
7687a8fb8f29SToby Isaac   dm->coarseMesh = cdm;
76883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7689a8fb8f29SToby Isaac }
7690a8fb8f29SToby Isaac 
769188bdff64SToby Isaac /*@
7692bb7acecfSBarry Smith   DMGetFineDM - Get the fine mesh from which this `DM` was obtained by coarsening
769388bdff64SToby Isaac 
769488bdff64SToby Isaac   Input Parameter:
7695bb7acecfSBarry Smith . dm - The `DM` object
769688bdff64SToby Isaac 
769788bdff64SToby Isaac   Output Parameter:
7698bb7acecfSBarry Smith . fdm - The fine `DM`
769988bdff64SToby Isaac 
770088bdff64SToby Isaac   Level: intermediate
770188bdff64SToby Isaac 
7702*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetFineDM()`, `DMCoarsen()`, `DMRefine()`
770388bdff64SToby Isaac @*/
7704d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
7705d71ae5a4SJacob Faibussowitsch {
770688bdff64SToby Isaac   PetscFunctionBegin;
770788bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
770888bdff64SToby Isaac   PetscValidPointer(fdm, 2);
770988bdff64SToby Isaac   *fdm = dm->fineMesh;
77103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
771188bdff64SToby Isaac }
771288bdff64SToby Isaac 
771388bdff64SToby Isaac /*@
7714bb7acecfSBarry Smith   DMSetFineDM - Set the fine mesh from which this was obtained by coarsening
771588bdff64SToby Isaac 
771688bdff64SToby Isaac   Input Parameters:
7717bb7acecfSBarry Smith + dm - The `DM` object
7718bb7acecfSBarry Smith - fdm - The fine `DM`
771988bdff64SToby Isaac 
7720bb7acecfSBarry Smith   Level: developer
772188bdff64SToby Isaac 
7722bb7acecfSBarry Smith   Note:
7723bb7acecfSBarry Smith   Normally this is set automatically by `DMCoarsen()`
7724bb7acecfSBarry Smith 
7725*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetFineDM()`, `DMCoarsen()`, `DMRefine()`
772688bdff64SToby Isaac @*/
7727d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFineDM(DM dm, DM fdm)
7728d71ae5a4SJacob Faibussowitsch {
772988bdff64SToby Isaac   PetscFunctionBegin;
773088bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
773188bdff64SToby Isaac   if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2);
773289d734beSBarry Smith   if (dm == fdm) fdm = NULL;
77339566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fdm));
77349566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->fineMesh));
773588bdff64SToby Isaac   dm->fineMesh = fdm;
77363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
773788bdff64SToby Isaac }
773888bdff64SToby Isaac 
7739a6ba4734SToby Isaac /*@C
7740bb7acecfSBarry Smith   DMAddBoundary - Add a boundary condition to a model represented by a `DM`
7741a6ba4734SToby Isaac 
774220f4b53cSBarry Smith   Collective
7743783e2ec8SMatthew G. Knepley 
7744a6ba4734SToby Isaac   Input Parameters:
7745bb7acecfSBarry Smith + dm       - The `DM`, with a `PetscDS` that matches the problem being constrained
7746bb7acecfSBarry Smith . type     - The type of condition, e.g. `DM_BC_ESSENTIAL_ANALYTIC`, `DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
7747a6ba4734SToby Isaac . name     - The BC name
774845480ffeSMatthew G. Knepley . label    - The label defining constrained points
7749bb7acecfSBarry Smith . Nv       - The number of `DMLabel` values for constrained points
775045480ffeSMatthew G. Knepley . values   - An array of values for constrained points
7751a6ba4734SToby Isaac . field    - The field to constrain
775245480ffeSMatthew G. Knepley . Nc       - The number of constrained field components (0 will constrain all fields)
7753a6ba4734SToby Isaac . comps    - An array of constrained component numbers
7754a6ba4734SToby Isaac . bcFunc   - A pointwise function giving boundary values
775556cf3b9cSMatthew G. Knepley . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL
7756a6ba4734SToby Isaac - ctx      - An optional user context for bcFunc
7757a6ba4734SToby Isaac 
775845480ffeSMatthew G. Knepley   Output Parameter:
775945480ffeSMatthew G. Knepley . bd          - (Optional) Boundary number
776045480ffeSMatthew G. Knepley 
7761a6ba4734SToby Isaac   Options Database Keys:
7762a6ba4734SToby Isaac + -bc_<boundary name> <num> - Overrides the boundary ids
7763a6ba4734SToby Isaac - -bc_<boundary name>_comp <num> - Overrides the boundary components
7764a6ba4734SToby Isaac 
776520f4b53cSBarry Smith   Level: intermediate
776620f4b53cSBarry Smith 
7767bb7acecfSBarry Smith   Notes:
776837fdd005SBarry Smith   Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if `DM_BC_ESSENTIAL`, then the calling sequence is\:
776956cf3b9cSMatthew G. Knepley 
777020f4b53cSBarry Smith $ void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
777156cf3b9cSMatthew G. Knepley 
7772bb7acecfSBarry Smith   If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is:
777356cf3b9cSMatthew G. Knepley 
777420f4b53cSBarry Smith .vb
777520f4b53cSBarry Smith   void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
777620f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
777720f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
777820f4b53cSBarry Smith               PetscReal time, const PetscReal x[], PetscScalar bcval[])
777920f4b53cSBarry Smith .ve
778056cf3b9cSMatthew G. Knepley + dim - the spatial dimension
778156cf3b9cSMatthew G. Knepley . Nf - the number of fields
778256cf3b9cSMatthew G. Knepley . uOff - the offset into u[] and u_t[] for each field
778356cf3b9cSMatthew G. Knepley . uOff_x - the offset into u_x[] for each field
778456cf3b9cSMatthew G. Knepley . u - each field evaluated at the current point
778556cf3b9cSMatthew G. Knepley . u_t - the time derivative of each field evaluated at the current point
778656cf3b9cSMatthew G. Knepley . u_x - the gradient of each field evaluated at the current point
778756cf3b9cSMatthew G. Knepley . aOff - the offset into a[] and a_t[] for each auxiliary field
778856cf3b9cSMatthew G. Knepley . aOff_x - the offset into a_x[] for each auxiliary field
778956cf3b9cSMatthew G. Knepley . a - each auxiliary field evaluated at the current point
779056cf3b9cSMatthew G. Knepley . a_t - the time derivative of each auxiliary field evaluated at the current point
779156cf3b9cSMatthew G. Knepley . a_x - the gradient of auxiliary each field evaluated at the current point
779256cf3b9cSMatthew G. Knepley . t - current time
779356cf3b9cSMatthew G. Knepley . x - coordinates of the current point
779456cf3b9cSMatthew G. Knepley . numConstants - number of constant parameters
779556cf3b9cSMatthew G. Knepley . constants - constant parameters
779656cf3b9cSMatthew G. Knepley - bcval - output values at the current point
779756cf3b9cSMatthew G. Knepley 
7798*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DSGetBoundary()`, `PetscDSAddBoundary()`
7799a6ba4734SToby Isaac @*/
7800d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd)
7801d71ae5a4SJacob Faibussowitsch {
7802e5e52638SMatthew G. Knepley   PetscDS ds;
7803a6ba4734SToby Isaac 
7804a6ba4734SToby Isaac   PetscFunctionBegin;
7805a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7806783e2ec8SMatthew G. Knepley   PetscValidLogicalCollectiveEnum(dm, type, 2);
780745480ffeSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
780845480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nv, 5);
780945480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, field, 7);
781045480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 8);
781101a5d20dSJed Brown   PetscCheck(!dm->localSection, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot add boundary to DM after creating local section");
78129566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
7813799db056SMatthew G. Knepley   /* Complete label */
7814799db056SMatthew G. Knepley   if (label) {
7815799db056SMatthew G. Knepley     PetscObject  obj;
7816799db056SMatthew G. Knepley     PetscClassId id;
7817799db056SMatthew G. Knepley 
7818799db056SMatthew G. Knepley     PetscCall(DMGetField(dm, field, NULL, &obj));
7819799db056SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
7820799db056SMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
7821799db056SMatthew G. Knepley       DM plex;
7822799db056SMatthew G. Knepley 
7823799db056SMatthew G. Knepley       PetscCall(DMConvert(dm, DMPLEX, &plex));
7824799db056SMatthew G. Knepley       if (plex) PetscCall(DMPlexLabelComplete(plex, label));
7825799db056SMatthew G. Knepley       PetscCall(DMDestroy(&plex));
7826799db056SMatthew G. Knepley     }
7827799db056SMatthew G. Knepley   }
78289566063dSJacob Faibussowitsch   PetscCall(PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd));
78293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7830a6ba4734SToby Isaac }
7831a6ba4734SToby Isaac 
783245480ffeSMatthew G. Knepley /* TODO Remove this since now the structures are the same */
7833d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPopulateBoundary(DM dm)
7834d71ae5a4SJacob Faibussowitsch {
7835e5e52638SMatthew G. Knepley   PetscDS     ds;
7836dff059c6SToby Isaac   DMBoundary *lastnext;
7837e6f8dbb6SToby Isaac   DSBoundary  dsbound;
7838e6f8dbb6SToby Isaac 
7839e6f8dbb6SToby Isaac   PetscFunctionBegin;
78409566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
7841e5e52638SMatthew G. Knepley   dsbound = ds->boundary;
784247a1f5adSToby Isaac   if (dm->boundary) {
784347a1f5adSToby Isaac     DMBoundary next = dm->boundary;
784447a1f5adSToby Isaac 
784547a1f5adSToby Isaac     /* quick check to see if the PetscDS has changed */
78463ba16761SJacob Faibussowitsch     if (next->dsboundary == dsbound) PetscFunctionReturn(PETSC_SUCCESS);
784747a1f5adSToby Isaac     /* the PetscDS has changed: tear down and rebuild */
784847a1f5adSToby Isaac     while (next) {
784947a1f5adSToby Isaac       DMBoundary b = next;
785047a1f5adSToby Isaac 
785147a1f5adSToby Isaac       next = b->next;
78529566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
7853a6ba4734SToby Isaac     }
785447a1f5adSToby Isaac     dm->boundary = NULL;
7855a6ba4734SToby Isaac   }
785647a1f5adSToby Isaac 
7857dff059c6SToby Isaac   lastnext = &(dm->boundary);
7858e6f8dbb6SToby Isaac   while (dsbound) {
7859e6f8dbb6SToby Isaac     DMBoundary dmbound;
7860e6f8dbb6SToby Isaac 
78619566063dSJacob Faibussowitsch     PetscCall(PetscNew(&dmbound));
7862e6f8dbb6SToby Isaac     dmbound->dsboundary = dsbound;
786345480ffeSMatthew G. Knepley     dmbound->label      = dsbound->label;
786447a1f5adSToby Isaac     /* push on the back instead of the front so that it is in the same order as in the PetscDS */
7865dff059c6SToby Isaac     *lastnext = dmbound;
7866dff059c6SToby Isaac     lastnext  = &(dmbound->next);
7867dff059c6SToby Isaac     dsbound   = dsbound->next;
7868a6ba4734SToby Isaac   }
78693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7870a6ba4734SToby Isaac }
7871a6ba4734SToby Isaac 
7872bb7acecfSBarry Smith /* TODO: missing manual page */
7873d71ae5a4SJacob Faibussowitsch PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
7874d71ae5a4SJacob Faibussowitsch {
7875b95f2879SToby Isaac   DMBoundary b;
7876a6ba4734SToby Isaac 
7877a6ba4734SToby Isaac   PetscFunctionBegin;
7878a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7879534a8f05SLisandro Dalcin   PetscValidBoolPointer(isBd, 3);
7880a6ba4734SToby Isaac   *isBd = PETSC_FALSE;
78819566063dSJacob Faibussowitsch   PetscCall(DMPopulateBoundary(dm));
7882b95f2879SToby Isaac   b = dm->boundary;
7883a6ba4734SToby Isaac   while (b && !(*isBd)) {
7884e6f8dbb6SToby Isaac     DMLabel    label = b->label;
7885e6f8dbb6SToby Isaac     DSBoundary dsb   = b->dsboundary;
7886a6ba4734SToby Isaac     PetscInt   i;
7887a6ba4734SToby Isaac 
788845480ffeSMatthew G. Knepley     if (label) {
78899566063dSJacob Faibussowitsch       for (i = 0; i < dsb->Nv && !(*isBd); ++i) PetscCall(DMLabelStratumHasPoint(label, dsb->values[i], point, isBd));
7890a6ba4734SToby Isaac     }
7891a6ba4734SToby Isaac     b = b->next;
7892a6ba4734SToby Isaac   }
78933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7894a6ba4734SToby Isaac }
78954d6f44ffSToby Isaac 
78964d6f44ffSToby Isaac /*@C
7897bb7acecfSBarry Smith   DMProjectFunction - This projects the given function into the function space provided by a `DM`, putting the coefficients in a global vector.
7898a6e0b375SMatthew G. Knepley 
789920f4b53cSBarry Smith   Collective
79004d6f44ffSToby Isaac 
79014d6f44ffSToby Isaac   Input Parameters:
7902bb7acecfSBarry Smith + dm      - The `DM`
79030709b2feSToby Isaac . time    - The time
79044d6f44ffSToby Isaac . funcs   - The coordinate functions to evaluate, one per field
79054d6f44ffSToby Isaac . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
79064d6f44ffSToby Isaac - mode    - The insertion mode for values
79074d6f44ffSToby Isaac 
79084d6f44ffSToby Isaac   Output Parameter:
79094d6f44ffSToby Isaac . X - vector
79104d6f44ffSToby Isaac 
791120f4b53cSBarry Smith    Calling sequence of `funcs`:
791220f4b53cSBarry Smith $  PetscErrorCode funcs(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
79134d6f44ffSToby Isaac +  dim - The spatial dimension
79148ec8862eSJed Brown .  time - The time at which to sample
79154d6f44ffSToby Isaac .  x   - The coordinates
791677b739a6SMatthew Knepley .  Nc  - The number of components
79174d6f44ffSToby Isaac .  u   - The output field values
79184d6f44ffSToby Isaac -  ctx - optional user-defined function context
79194d6f44ffSToby Isaac 
79204d6f44ffSToby Isaac   Level: developer
79214d6f44ffSToby Isaac 
7922bb7acecfSBarry Smith   Developer Notes:
7923bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
7924bb7acecfSBarry Smith 
7925bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
7926bb7acecfSBarry Smith 
7927*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
79284d6f44ffSToby Isaac @*/
7929d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
7930d71ae5a4SJacob Faibussowitsch {
79314d6f44ffSToby Isaac   Vec localX;
79324d6f44ffSToby Isaac 
79334d6f44ffSToby Isaac   PetscFunctionBegin;
79344d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79359566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
7936f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
79379566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX));
79389566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
79399566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
79409566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
79413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79424d6f44ffSToby Isaac }
79434d6f44ffSToby Isaac 
7944a6e0b375SMatthew G. Knepley /*@C
7945bb7acecfSBarry Smith   DMProjectFunctionLocal - This projects the given function into the function space provided by a `DM`, putting the coefficients in a local vector.
7946a6e0b375SMatthew G. Knepley 
794720f4b53cSBarry Smith   Not Collective
7948a6e0b375SMatthew G. Knepley 
7949a6e0b375SMatthew G. Knepley   Input Parameters:
7950bb7acecfSBarry Smith + dm      - The `DM`
7951a6e0b375SMatthew G. Knepley . time    - The time
7952a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
7953a6e0b375SMatthew G. Knepley . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
7954a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
7955a6e0b375SMatthew G. Knepley 
7956a6e0b375SMatthew G. Knepley   Output Parameter:
7957a6e0b375SMatthew G. Knepley . localX - vector
7958a6e0b375SMatthew G. Knepley 
795920f4b53cSBarry Smith    Calling sequence of `funcs`:
796020f4b53cSBarry Smith $  PetscErrorCode funcs(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
7961a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
7962a6e0b375SMatthew G. Knepley .  x   - The coordinates
796377b739a6SMatthew Knepley .  Nc  - The number of components
7964a6e0b375SMatthew G. Knepley .  u   - The output field values
7965a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
7966a6e0b375SMatthew G. Knepley 
7967a6e0b375SMatthew G. Knepley   Level: developer
7968a6e0b375SMatthew G. Knepley 
7969bb7acecfSBarry Smith   Developer Notes:
7970bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
7971bb7acecfSBarry Smith 
7972bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
7973bb7acecfSBarry Smith 
7974*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
7975a6e0b375SMatthew G. Knepley @*/
7976d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
7977d71ae5a4SJacob Faibussowitsch {
79784d6f44ffSToby Isaac   PetscFunctionBegin;
79794d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7980064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
79819566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfunctionlocal)(dm, time, funcs, ctxs, mode, localX));
79823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79834d6f44ffSToby Isaac }
79844d6f44ffSToby Isaac 
7985a6e0b375SMatthew G. Knepley /*@C
7986bb7acecfSBarry Smith   DMProjectFunctionLabel - This projects the given function into the function space provided by the `DM`, putting the coefficients in a global vector, setting values only for points in the given label.
7987a6e0b375SMatthew G. Knepley 
798820f4b53cSBarry Smith   Collective
7989a6e0b375SMatthew G. Knepley 
7990a6e0b375SMatthew G. Knepley   Input Parameters:
7991bb7acecfSBarry Smith + dm      - The `DM`
7992a6e0b375SMatthew G. Knepley . time    - The time
7993bb7acecfSBarry Smith . label   - The `DMLabel` selecting the portion of the mesh for projection
7994a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
7995bb7acecfSBarry Smith . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs may be null.
7996a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
7997a6e0b375SMatthew G. Knepley 
7998a6e0b375SMatthew G. Knepley   Output Parameter:
7999a6e0b375SMatthew G. Knepley . X - vector
8000a6e0b375SMatthew G. Knepley 
800120f4b53cSBarry Smith    Calling sequence of `funcs`:
800220f4b53cSBarry Smith $  PetscErrorCode funcs(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
8003a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
8004a6e0b375SMatthew G. Knepley .  x   - The coordinates
800577b739a6SMatthew Knepley .  Nc  - The number of components
8006a6e0b375SMatthew G. Knepley .  u   - The output field values
8007a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
8008a6e0b375SMatthew G. Knepley 
8009a6e0b375SMatthew G. Knepley   Level: developer
8010a6e0b375SMatthew G. Knepley 
8011bb7acecfSBarry Smith   Developer Notes:
8012bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8013bb7acecfSBarry Smith 
8014bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8015bb7acecfSBarry Smith 
8016*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabelLocal()`, `DMComputeL2Diff()`
8017a6e0b375SMatthew G. Knepley @*/
8018d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLabel(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
8019d71ae5a4SJacob Faibussowitsch {
80202c53366bSMatthew G. Knepley   Vec localX;
80212c53366bSMatthew G. Knepley 
80222c53366bSMatthew G. Knepley   PetscFunctionBegin;
80232c53366bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80249566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
8025f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
80269566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
80279566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
80289566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
80299566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
80303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80312c53366bSMatthew G. Knepley }
80322c53366bSMatthew G. Knepley 
8033a6e0b375SMatthew G. Knepley /*@C
8034bb7acecfSBarry Smith   DMProjectFunctionLabelLocal - This projects the given function into the function space provided by the `DM`, putting the coefficients in a local vector, setting values only for points in the given label.
8035a6e0b375SMatthew G. Knepley 
803620f4b53cSBarry Smith   Not Collective
8037a6e0b375SMatthew G. Knepley 
8038a6e0b375SMatthew G. Knepley   Input Parameters:
8039bb7acecfSBarry Smith + dm      - The `DM`
8040a6e0b375SMatthew G. Knepley . time    - The time
8041bb7acecfSBarry Smith . label   - The `DMLabel` selecting the portion of the mesh for projection
8042a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
8043a6e0b375SMatthew G. Knepley . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
8044a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8045a6e0b375SMatthew G. Knepley 
8046a6e0b375SMatthew G. Knepley   Output Parameter:
8047a6e0b375SMatthew G. Knepley . localX - vector
8048a6e0b375SMatthew G. Knepley 
804920f4b53cSBarry Smith    Calling sequence of `funcs`:
805020f4b53cSBarry Smith $  PetscErrorCode funcs(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
8051a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
8052a6e0b375SMatthew G. Knepley .  x   - The coordinates
805377b739a6SMatthew Knepley .  Nc  - The number of components
8054a6e0b375SMatthew G. Knepley .  u   - The output field values
8055a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
8056a6e0b375SMatthew G. Knepley 
8057a6e0b375SMatthew G. Knepley   Level: developer
8058a6e0b375SMatthew G. Knepley 
8059bb7acecfSBarry Smith   Developer Notes:
8060bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8061bb7acecfSBarry Smith 
8062bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8063bb7acecfSBarry Smith 
8064*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
8065a6e0b375SMatthew G. Knepley @*/
8066d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
8067d71ae5a4SJacob Faibussowitsch {
80684d6f44ffSToby Isaac   PetscFunctionBegin;
80694d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8070064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
80719566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfunctionlabellocal)(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
80723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80734d6f44ffSToby Isaac }
80742716604bSToby Isaac 
8075a6e0b375SMatthew G. Knepley /*@C
8076bb7acecfSBarry Smith   DMProjectFieldLocal - This projects the given function of the input fields into the function space provided by the `DM`, putting the coefficients in a local vector.
8077a6e0b375SMatthew G. Knepley 
807820f4b53cSBarry Smith   Not Collective
8079a6e0b375SMatthew G. Knepley 
8080a6e0b375SMatthew G. Knepley   Input Parameters:
8081bb7acecfSBarry Smith + dm      - The `DM`
8082a6e0b375SMatthew G. Knepley . time    - The time
808320f4b53cSBarry Smith . localU  - The input field vector; may be `NULL` if projection is defined purely by coordinates
8084a6e0b375SMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8085a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8086a6e0b375SMatthew G. Knepley 
8087a6e0b375SMatthew G. Knepley   Output Parameter:
8088a6e0b375SMatthew G. Knepley . localX  - The output vector
8089a6e0b375SMatthew G. Knepley 
809020f4b53cSBarry Smith    Calling sequence of `funcs`:
809120f4b53cSBarry Smith .vb
809220f4b53cSBarry Smith    void funcs(PetscInt dim, PetscInt Nf, PetscInt NfAux,
809320f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
809420f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
809520f4b53cSBarry Smith               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
809620f4b53cSBarry Smith .ve
8097a6e0b375SMatthew G. Knepley +  dim          - The spatial dimension
8098a6e0b375SMatthew G. Knepley .  Nf           - The number of input fields
8099a6e0b375SMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8100a6e0b375SMatthew G. Knepley .  uOff         - The offset of each field in u[]
8101a6e0b375SMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8102a6e0b375SMatthew G. Knepley .  u            - The field values at this point in space
8103a6e0b375SMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8104a6e0b375SMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8105a6e0b375SMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8106a6e0b375SMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8107a6e0b375SMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8108a6e0b375SMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8109a6e0b375SMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8110a6e0b375SMatthew G. Knepley .  t            - The current time
8111a6e0b375SMatthew G. Knepley .  x            - The coordinates of this point
8112a6e0b375SMatthew G. Knepley .  numConstants - The number of constants
8113a6e0b375SMatthew G. Knepley .  constants    - The value of each constant
8114a6e0b375SMatthew G. Knepley -  f            - The value of the function at this point in space
8115a6e0b375SMatthew G. Knepley 
8116bb7acecfSBarry Smith   Note:
8117bb7acecfSBarry Smith   There are three different `DM`s that potentially interact in this function. The output `DM`, dm, specifies the layout of the values calculates by funcs.
8118bb7acecfSBarry Smith   The input `DM`, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
8119bb7acecfSBarry Smith   a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary `DM`, attached to the
8120a6e0b375SMatthew G. Knepley   auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
8121a6e0b375SMatthew G. Knepley 
8122a6e0b375SMatthew G. Knepley   Level: intermediate
8123a6e0b375SMatthew G. Knepley 
8124bb7acecfSBarry Smith   Developer Notes:
8125bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8126bb7acecfSBarry Smith 
8127bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8128bb7acecfSBarry Smith 
8129*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8130a6e0b375SMatthew G. Knepley @*/
8131d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), InsertMode mode, Vec localX)
8132d71ae5a4SJacob Faibussowitsch {
81338c6c5593SMatthew G. Knepley   PetscFunctionBegin;
81348c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8135eb8f539aSJed Brown   if (localU) PetscValidHeaderSpecific(localU, VEC_CLASSID, 3);
81368c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
81379566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfieldlocal)(dm, time, localU, funcs, mode, localX));
81383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81398c6c5593SMatthew G. Knepley }
81408c6c5593SMatthew G. Knepley 
8141a6e0b375SMatthew G. Knepley /*@C
8142a6e0b375SMatthew G. Knepley   DMProjectFieldLabelLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector, calculating only over the portion of the domain specified by the label.
8143a6e0b375SMatthew G. Knepley 
814420f4b53cSBarry Smith   Not Collective
8145a6e0b375SMatthew G. Knepley 
8146a6e0b375SMatthew G. Knepley   Input Parameters:
8147bb7acecfSBarry Smith + dm      - The `DM`
8148a6e0b375SMatthew G. Knepley . time    - The time
8149bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain to output
8150a6e0b375SMatthew G. Knepley . numIds  - The number of label ids to use
8151a6e0b375SMatthew G. Knepley . ids     - The label ids to use for marking
8152bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
815320f4b53cSBarry Smith . comps   - The components to set in the output, or `NULL` for all components
8154a6e0b375SMatthew G. Knepley . localU  - The input field vector
8155a6e0b375SMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8156a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8157a6e0b375SMatthew G. Knepley 
8158a6e0b375SMatthew G. Knepley   Output Parameter:
8159a6e0b375SMatthew G. Knepley . localX  - The output vector
8160a6e0b375SMatthew G. Knepley 
816120f4b53cSBarry Smith    Calling sequence of `funcs`:
816220f4b53cSBarry Smith .vb
816320f4b53cSBarry Smith    void funcs(PetscInt dim, PetscInt Nf, PetscInt NfAux,
816420f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
816520f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
816620f4b53cSBarry Smith               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
816720f4b53cSBarry Smith .ve
8168a6e0b375SMatthew G. Knepley +  dim          - The spatial dimension
8169a6e0b375SMatthew G. Knepley .  Nf           - The number of input fields
8170a6e0b375SMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8171a6e0b375SMatthew G. Knepley .  uOff         - The offset of each field in u[]
8172a6e0b375SMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8173a6e0b375SMatthew G. Knepley .  u            - The field values at this point in space
8174a6e0b375SMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8175a6e0b375SMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8176a6e0b375SMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8177a6e0b375SMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8178a6e0b375SMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8179a6e0b375SMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8180a6e0b375SMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8181a6e0b375SMatthew G. Knepley .  t            - The current time
8182a6e0b375SMatthew G. Knepley .  x            - The coordinates of this point
8183a6e0b375SMatthew G. Knepley .  numConstants - The number of constants
8184a6e0b375SMatthew G. Knepley .  constants    - The value of each constant
8185a6e0b375SMatthew G. Knepley -  f            - The value of the function at this point in space
8186a6e0b375SMatthew G. Knepley 
8187bb7acecfSBarry Smith   Note:
8188bb7acecfSBarry Smith   There are three different `DM`s that potentially interact in this function. The output `DM`, dm, specifies the layout of the values calculates by funcs.
8189bb7acecfSBarry Smith   The input `DM`, attached to localU, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
8190bb7acecfSBarry Smith   a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary `DM`, attached to the
8191a6e0b375SMatthew G. Knepley   auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
8192a6e0b375SMatthew G. Knepley 
8193a6e0b375SMatthew G. Knepley   Level: intermediate
8194a6e0b375SMatthew G. Knepley 
8195bb7acecfSBarry Smith   Developer Notes:
8196bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8197bb7acecfSBarry Smith 
8198bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8199bb7acecfSBarry Smith 
8200*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabel()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8201a6e0b375SMatthew G. Knepley @*/
8202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), InsertMode mode, Vec localX)
8203d71ae5a4SJacob Faibussowitsch {
82048c6c5593SMatthew G. Knepley   PetscFunctionBegin;
82058c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8206064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8207064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
82089566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
82093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82108c6c5593SMatthew G. Knepley }
82118c6c5593SMatthew G. Knepley 
82122716604bSToby Isaac /*@C
8213d29d7c6eSMatthew G. Knepley   DMProjectFieldLabel - This projects the given function of the input fields into the function space provided, putting the coefficients in a global vector, calculating only over the portion of the domain specified by the label.
8214d29d7c6eSMatthew G. Knepley 
821520f4b53cSBarry Smith   Not Collective
8216d29d7c6eSMatthew G. Knepley 
8217d29d7c6eSMatthew G. Knepley   Input Parameters:
8218bb7acecfSBarry Smith + dm      - The `DM`
8219d29d7c6eSMatthew G. Knepley . time    - The time
8220bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain to output
8221d29d7c6eSMatthew G. Knepley . numIds  - The number of label ids to use
8222d29d7c6eSMatthew G. Knepley . ids     - The label ids to use for marking
8223bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
822420f4b53cSBarry Smith . comps   - The components to set in the output, or `NULL` for all components
8225d29d7c6eSMatthew G. Knepley . U       - The input field vector
8226d29d7c6eSMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8227d29d7c6eSMatthew G. Knepley - mode    - The insertion mode for values
8228d29d7c6eSMatthew G. Knepley 
8229d29d7c6eSMatthew G. Knepley   Output Parameter:
8230d29d7c6eSMatthew G. Knepley . X       - The output vector
8231d29d7c6eSMatthew G. Knepley 
823220f4b53cSBarry Smith    Calling sequence of `funcs`:
823320f4b53cSBarry Smith .vb
823420f4b53cSBarry Smith   void func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
823520f4b53cSBarry Smith             const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
823620f4b53cSBarry Smith             const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
823720f4b53cSBarry Smith             PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
823820f4b53cSBarry Smith .ve
8239d29d7c6eSMatthew G. Knepley +  dim          - The spatial dimension
8240d29d7c6eSMatthew G. Knepley .  Nf           - The number of input fields
8241d29d7c6eSMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8242d29d7c6eSMatthew G. Knepley .  uOff         - The offset of each field in u[]
8243d29d7c6eSMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8244d29d7c6eSMatthew G. Knepley .  u            - The field values at this point in space
8245d29d7c6eSMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8246d29d7c6eSMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8247d29d7c6eSMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8248d29d7c6eSMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8249d29d7c6eSMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8250d29d7c6eSMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8251d29d7c6eSMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8252d29d7c6eSMatthew G. Knepley .  t            - The current time
8253d29d7c6eSMatthew G. Knepley .  x            - The coordinates of this point
8254d29d7c6eSMatthew G. Knepley .  numConstants - The number of constants
8255d29d7c6eSMatthew G. Knepley .  constants    - The value of each constant
8256d29d7c6eSMatthew G. Knepley -  f            - The value of the function at this point in space
8257d29d7c6eSMatthew G. Knepley 
8258bb7acecfSBarry Smith   Note:
8259bb7acecfSBarry Smith   There are three different `DM`s that potentially interact in this function. The output `DM`, dm, specifies the layout of the values calculates by funcs.
8260bb7acecfSBarry Smith   The input `DM`, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
8261bb7acecfSBarry Smith   a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary `DM`, attached to the
8262d29d7c6eSMatthew G. Knepley   auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
8263d29d7c6eSMatthew G. Knepley 
8264d29d7c6eSMatthew G. Knepley   Level: intermediate
8265d29d7c6eSMatthew G. Knepley 
8266bb7acecfSBarry Smith   Developer Notes:
8267bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8268bb7acecfSBarry Smith 
8269bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8270bb7acecfSBarry Smith 
8271*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8272d29d7c6eSMatthew G. Knepley @*/
8273d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFieldLabel(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec U, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), InsertMode mode, Vec X)
8274d71ae5a4SJacob Faibussowitsch {
8275d29d7c6eSMatthew G. Knepley   DM  dmIn;
8276d29d7c6eSMatthew G. Knepley   Vec localU, localX;
8277d29d7c6eSMatthew G. Knepley 
8278d29d7c6eSMatthew G. Knepley   PetscFunctionBegin;
8279d29d7c6eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8280d29d7c6eSMatthew G. Knepley   PetscCall(VecGetDM(U, &dmIn));
8281d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dmIn, &localU));
8282d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dm, &localX));
8283f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
828472fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalBegin(dmIn, U, mode, localU));
828572fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalEnd(dmIn, U, mode, localU));
8286d29d7c6eSMatthew G. Knepley   PetscCall(DMProjectFieldLabelLocal(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
8287d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
8288d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
8289d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dm, &localX));
8290d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dmIn, &localU));
82913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8292d29d7c6eSMatthew G. Knepley }
8293d29d7c6eSMatthew G. Knepley 
8294d29d7c6eSMatthew G. Knepley /*@C
8295ece3a9fcSMatthew G. Knepley   DMProjectBdFieldLabelLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector, calculating only over the portion of the domain boundary specified by the label.
8296ece3a9fcSMatthew G. Knepley 
829720f4b53cSBarry Smith   Not Collective
8298ece3a9fcSMatthew G. Knepley 
8299ece3a9fcSMatthew G. Knepley   Input Parameters:
8300bb7acecfSBarry Smith + dm      - The `DM`
8301ece3a9fcSMatthew G. Knepley . time    - The time
8302bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain boundary to output
8303ece3a9fcSMatthew G. Knepley . numIds  - The number of label ids to use
8304ece3a9fcSMatthew G. Knepley . ids     - The label ids to use for marking
8305bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
830620f4b53cSBarry Smith . comps   - The components to set in the output, or `NULL` for all components
8307ece3a9fcSMatthew G. Knepley . localU  - The input field vector
8308ece3a9fcSMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8309ece3a9fcSMatthew G. Knepley - mode    - The insertion mode for values
8310ece3a9fcSMatthew G. Knepley 
8311ece3a9fcSMatthew G. Knepley   Output Parameter:
8312ece3a9fcSMatthew G. Knepley . localX  - The output vector
8313ece3a9fcSMatthew G. Knepley 
831420f4b53cSBarry Smith    Calling sequence of `funcs`:
831520f4b53cSBarry Smith .vb
831620f4b53cSBarry Smith    void funcs(PetscInt dim, PetscInt Nf, PetscInt NfAux,
831720f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
831820f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
831920f4b53cSBarry Smith               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
832020f4b53cSBarry Smith .ve
8321ece3a9fcSMatthew G. Knepley +  dim          - The spatial dimension
8322ece3a9fcSMatthew G. Knepley .  Nf           - The number of input fields
8323ece3a9fcSMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8324ece3a9fcSMatthew G. Knepley .  uOff         - The offset of each field in u[]
8325ece3a9fcSMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8326ece3a9fcSMatthew G. Knepley .  u            - The field values at this point in space
8327ece3a9fcSMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8328ece3a9fcSMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8329ece3a9fcSMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8330ece3a9fcSMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8331ece3a9fcSMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8332ece3a9fcSMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8333ece3a9fcSMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8334ece3a9fcSMatthew G. Knepley .  t            - The current time
8335ece3a9fcSMatthew G. Knepley .  x            - The coordinates of this point
8336ece3a9fcSMatthew G. Knepley .  n            - The face normal
8337ece3a9fcSMatthew G. Knepley .  numConstants - The number of constants
8338ece3a9fcSMatthew G. Knepley .  constants    - The value of each constant
8339ece3a9fcSMatthew G. Knepley -  f            - The value of the function at this point in space
8340ece3a9fcSMatthew G. Knepley 
8341ece3a9fcSMatthew G. Knepley   Note:
8342bb7acecfSBarry Smith   There are three different `DM`s that potentially interact in this function. The output `DM`, dm, specifies the layout of the values calculates by funcs.
8343bb7acecfSBarry Smith   The input `DM`, attached to U, may be different. For example, you can input the solution over the full domain, but output over a piece of the boundary, or
8344bb7acecfSBarry Smith   a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary `DM`, attached to the
8345ece3a9fcSMatthew G. Knepley   auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations.
8346ece3a9fcSMatthew G. Knepley 
8347ece3a9fcSMatthew G. Knepley   Level: intermediate
8348ece3a9fcSMatthew G. Knepley 
8349bb7acecfSBarry Smith   Developer Notes:
8350bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8351bb7acecfSBarry Smith 
8352bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8353bb7acecfSBarry Smith 
8354*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8355ece3a9fcSMatthew G. Knepley @*/
8356d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), InsertMode mode, Vec localX)
8357d71ae5a4SJacob Faibussowitsch {
8358ece3a9fcSMatthew G. Knepley   PetscFunctionBegin;
8359ece3a9fcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8360064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8361064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
83629566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
83633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8364ece3a9fcSMatthew G. Knepley }
8365ece3a9fcSMatthew G. Knepley 
8366ece3a9fcSMatthew G. Knepley /*@C
83672716604bSToby Isaac   DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
83682716604bSToby Isaac 
836920f4b53cSBarry Smith   Collective
8370bb7acecfSBarry Smith 
83712716604bSToby Isaac   Input Parameters:
8372bb7acecfSBarry Smith + dm    - The `DM`
83730709b2feSToby Isaac . time  - The time
83742716604bSToby Isaac . funcs - The functions to evaluate for each field component
83752716604bSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8376574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
83772716604bSToby Isaac 
83782716604bSToby Isaac   Output Parameter:
83792716604bSToby Isaac . diff - The diff ||u - u_h||_2
83802716604bSToby Isaac 
83812716604bSToby Isaac   Level: developer
83822716604bSToby Isaac 
8383bb7acecfSBarry Smith   Developer Notes:
8384bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8385bb7acecfSBarry Smith 
8386bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8387bb7acecfSBarry Smith 
8388*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
83892716604bSToby Isaac @*/
8390d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
8391d71ae5a4SJacob Faibussowitsch {
83922716604bSToby Isaac   PetscFunctionBegin;
83932716604bSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8394b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
83959566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2diff)(dm, time, funcs, ctxs, X, diff));
83963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83972716604bSToby Isaac }
8398b698f381SToby Isaac 
8399b698f381SToby Isaac /*@C
8400b698f381SToby Isaac   DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
8401b698f381SToby Isaac 
840220f4b53cSBarry Smith   Collective
8403d083f849SBarry Smith 
8404b698f381SToby Isaac   Input Parameters:
8405bb7acecfSBarry Smith + dm    - The `DM`
8406b698f381SToby Isaac , time  - The time
8407b698f381SToby Isaac . funcs - The gradient functions to evaluate for each field component
8408b698f381SToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8409574a98acSMatthew G. Knepley . X     - The coefficient vector u_h, a global vector
8410b698f381SToby Isaac - n     - The vector to project along
8411b698f381SToby Isaac 
8412b698f381SToby Isaac   Output Parameter:
8413b698f381SToby Isaac . diff - The diff ||(grad u - grad u_h) . n||_2
8414b698f381SToby Isaac 
8415b698f381SToby Isaac   Level: developer
8416b698f381SToby Isaac 
8417bb7acecfSBarry Smith   Developer Notes:
8418bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8419bb7acecfSBarry Smith 
8420bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8421bb7acecfSBarry Smith 
8422*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2Diff()`, `DMComputeL2FieldDiff()`
8423b698f381SToby Isaac @*/
8424d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2GradientDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff)
8425d71ae5a4SJacob Faibussowitsch {
8426b698f381SToby Isaac   PetscFunctionBegin;
8427b698f381SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8428b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
84299566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2gradientdiff)(dm, time, funcs, ctxs, X, n, diff));
84303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8431b698f381SToby Isaac }
8432b698f381SToby Isaac 
84332a16baeaSToby Isaac /*@C
84342a16baeaSToby Isaac   DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
84352a16baeaSToby Isaac 
843620f4b53cSBarry Smith   Collective
8437d083f849SBarry Smith 
84382a16baeaSToby Isaac   Input Parameters:
8439bb7acecfSBarry Smith + dm    - The `DM`
84402a16baeaSToby Isaac . time  - The time
84412a16baeaSToby Isaac . funcs - The functions to evaluate for each field component
84422a16baeaSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8443574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
84442a16baeaSToby Isaac 
84452a16baeaSToby Isaac   Output Parameter:
84462a16baeaSToby Isaac . diff - The array of differences, ||u^f - u^f_h||_2
84472a16baeaSToby Isaac 
84482a16baeaSToby Isaac   Level: developer
84492a16baeaSToby Isaac 
8450bb7acecfSBarry Smith   Developer Notes:
8451bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8452bb7acecfSBarry Smith 
8453bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8454bb7acecfSBarry Smith 
8455*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
84562a16baeaSToby Isaac @*/
8457d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
8458d71ae5a4SJacob Faibussowitsch {
84592a16baeaSToby Isaac   PetscFunctionBegin;
84602a16baeaSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84612a16baeaSToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
84629566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2fielddiff)(dm, time, funcs, ctxs, X, diff));
84633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84642a16baeaSToby Isaac }
84652a16baeaSToby Isaac 
8466df0b854cSToby Isaac /*@C
8467bb7acecfSBarry Smith  DMGetNeighbors - Gets an array containing the MPI ranks of all the processes neighbors
8468502a2867SDave May 
8469502a2867SDave May  Not Collective
8470502a2867SDave May 
8471502a2867SDave May  Input Parameter:
8472bb7acecfSBarry Smith .  dm    - The `DM`
8473502a2867SDave May 
84740a19bb7dSprj-  Output Parameters:
84750a19bb7dSprj- +  nranks - the number of neighbours
84760a19bb7dSprj- -  ranks - the neighbors ranks
8477502a2867SDave May 
84789bdbcad8SBarry Smith  Level: beginner
84799bdbcad8SBarry Smith 
8480bb7acecfSBarry Smith  Note:
8481bb7acecfSBarry Smith  Do not free the array, it is freed when the `DM` is destroyed.
8482502a2867SDave May 
8483*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDAGetNeighbors()`, `PetscSFGetRootRanks()`
8484502a2867SDave May @*/
8485d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNeighbors(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
8486d71ae5a4SJacob Faibussowitsch {
8487502a2867SDave May   PetscFunctionBegin;
8488502a2867SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84899566063dSJacob Faibussowitsch   PetscCall((dm->ops->getneighbors)(dm, nranks, ranks));
84903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8491502a2867SDave May }
8492502a2867SDave May 
8493531c7667SBarry Smith #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
8494531c7667SBarry Smith 
8495531c7667SBarry Smith /*
8496531c7667SBarry Smith     Converts the input vector to a ghosted vector and then calls the standard coloring code.
84972b6f951bSStefano Zampini     This must be a different function because it requires DM which is not defined in the Mat library
8498531c7667SBarry Smith */
8499d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringApply_AIJDM(Mat J, MatFDColoring coloring, Vec x1, void *sctx)
8500d71ae5a4SJacob Faibussowitsch {
8501531c7667SBarry Smith   PetscFunctionBegin;
8502531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8503531c7667SBarry Smith     Vec x1local;
8504531c7667SBarry Smith     DM  dm;
85059566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
85067a8be351SBarry Smith     PetscCheck(dm, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_INCOMP, "IS_COLORING_LOCAL requires a DM");
85079566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &x1local));
85089566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, x1, INSERT_VALUES, x1local));
85099566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, x1, INSERT_VALUES, x1local));
8510531c7667SBarry Smith     x1 = x1local;
8511531c7667SBarry Smith   }
85129566063dSJacob Faibussowitsch   PetscCall(MatFDColoringApply_AIJ(J, coloring, x1, sctx));
8513531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8514531c7667SBarry Smith     DM dm;
85159566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
85169566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &x1));
8517531c7667SBarry Smith   }
85183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8519531c7667SBarry Smith }
8520531c7667SBarry Smith 
8521531c7667SBarry Smith /*@
8522bb7acecfSBarry Smith     MatFDColoringUseDM - allows a `MatFDColoring` object to use the `DM` associated with the matrix to compute a `IS_COLORING_LOCAL` coloring
8523531c7667SBarry Smith 
8524531c7667SBarry Smith     Input Parameter:
8525bb7acecfSBarry Smith .    coloring - the `MatFDColoring` object
8526531c7667SBarry Smith 
85279bdbcad8SBarry Smith     Level: advanced
85289bdbcad8SBarry Smith 
8529bb7acecfSBarry Smith     Developer Note:
8530bb7acecfSBarry Smith     this routine exists because the PETSc `Mat` library does not know about the `DM` objects
8531531c7667SBarry Smith 
8532*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatFDColoring`, `MatFDColoringCreate()`, `ISColoringType`
8533531c7667SBarry Smith @*/
8534d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringUseDM(Mat coloring, MatFDColoring fdcoloring)
8535d71ae5a4SJacob Faibussowitsch {
8536531c7667SBarry Smith   PetscFunctionBegin;
8537531c7667SBarry Smith   coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
85383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8539531c7667SBarry Smith }
85408320bc6fSPatrick Sanan 
85418320bc6fSPatrick Sanan /*@
8542bb7acecfSBarry Smith     DMGetCompatibility - determine if two `DM`s are compatible
85438320bc6fSPatrick Sanan 
85448320bc6fSPatrick Sanan     Collective
85458320bc6fSPatrick Sanan 
85468320bc6fSPatrick Sanan     Input Parameters:
8547bb7acecfSBarry Smith +    dm1 - the first `DM`
8548bb7acecfSBarry Smith -    dm2 - the second `DM`
85498320bc6fSPatrick Sanan 
85508320bc6fSPatrick Sanan     Output Parameters:
8551bb7acecfSBarry Smith +    compatible - whether or not the two `DM`s are compatible
8552bb7acecfSBarry Smith -    set - whether or not the compatible value was actually determined and set
85538320bc6fSPatrick Sanan 
855420f4b53cSBarry Smith     Level: advanced
855520f4b53cSBarry Smith 
85568320bc6fSPatrick Sanan     Notes:
8557bb7acecfSBarry Smith     Two `DM`s are deemed compatible if they represent the same parallel decomposition
85583d862458SPatrick Sanan     of the same topology. This implies that the section (field data) on one
85598320bc6fSPatrick Sanan     "makes sense" with respect to the topology and parallel decomposition of the other.
8560bb7acecfSBarry Smith     Loosely speaking, compatible `DM`s represent the same domain and parallel
85613d862458SPatrick Sanan     decomposition, but hold different data.
85628320bc6fSPatrick Sanan 
85638320bc6fSPatrick Sanan     Typically, one would confirm compatibility if intending to simultaneously iterate
8564bb7acecfSBarry Smith     over a pair of vectors obtained from different `DM`s.
85658320bc6fSPatrick Sanan 
8566bb7acecfSBarry Smith     For example, two `DMDA` objects are compatible if they have the same local
85678320bc6fSPatrick Sanan     and global sizes and the same stencil width. They can have different numbers
85688320bc6fSPatrick Sanan     of degrees of freedom per node. Thus, one could use the node numbering from
8569bb7acecfSBarry Smith     either `DM` in bounds for a loop over vectors derived from either `DM`.
85708320bc6fSPatrick Sanan 
8571bb7acecfSBarry Smith     Consider the operation of summing data living on a 2-dof `DMDA` to data living
8572bb7acecfSBarry Smith     on a 1-dof `DMDA`, which should be compatible, as in the following snippet.
85738320bc6fSPatrick Sanan .vb
85748320bc6fSPatrick Sanan   ...
85759566063dSJacob Faibussowitsch   PetscCall(DMGetCompatibility(da1,da2,&compatible,&set));
85768320bc6fSPatrick Sanan   if (set && compatible)  {
85779566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da1,vec1,&arr1));
85789566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da2,vec2,&arr2));
85799566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL));
85808320bc6fSPatrick Sanan     for (j=y; j<y+n; ++j) {
85818320bc6fSPatrick Sanan       for (i=x; i<x+m, ++i) {
85828320bc6fSPatrick Sanan         arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1];
85838320bc6fSPatrick Sanan       }
85848320bc6fSPatrick Sanan     }
85859566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da1,vec1,&arr1));
85869566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da2,vec2,&arr2));
85878320bc6fSPatrick Sanan   } else {
85888320bc6fSPatrick Sanan     SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible");
85898320bc6fSPatrick Sanan   }
85908320bc6fSPatrick Sanan   ...
85918320bc6fSPatrick Sanan .ve
85928320bc6fSPatrick Sanan 
8593bb7acecfSBarry Smith     Checking compatibility might be expensive for a given implementation of `DM`,
85948320bc6fSPatrick Sanan     or might be impossible to unambiguously confirm or deny. For this reason,
85958320bc6fSPatrick Sanan     this function may decline to determine compatibility, and hence users should
85968320bc6fSPatrick Sanan     always check the "set" output parameter.
85978320bc6fSPatrick Sanan 
8598bb7acecfSBarry Smith     A `DM` is always compatible with itself.
85998320bc6fSPatrick Sanan 
8600bb7acecfSBarry Smith     In the current implementation, `DM`s which live on "unequal" communicators
86018320bc6fSPatrick Sanan     (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed
86028320bc6fSPatrick Sanan     incompatible.
86038320bc6fSPatrick Sanan 
86048320bc6fSPatrick Sanan     This function is labeled "Collective," as information about all subdomains
8605bb7acecfSBarry Smith     is required on each rank. However, in `DM` implementations which store all this
86068320bc6fSPatrick Sanan     information locally, this function may be merely "Logically Collective".
86078320bc6fSPatrick Sanan 
8608bb7acecfSBarry Smith     Developer Note:
8609bb7acecfSBarry Smith     Compatibility is assumed to be a symmetric concept; `DM` A is compatible with `DM` B
86103d862458SPatrick Sanan     iff B is compatible with A. Thus, this function checks the implementations
8611a5bc1bf3SBarry Smith     of both dm and dmc (if they are of different types), attempting to determine
8612bb7acecfSBarry Smith     compatibility. It is left to `DM` implementers to ensure that symmetry is
86138320bc6fSPatrick Sanan     preserved. The simplest way to do this is, when implementing type-specific
86143d862458SPatrick Sanan     logic for this function, is to check for existing logic in the implementation
8615bb7acecfSBarry Smith     of other `DM` types and let *set = PETSC_FALSE if found.
86168320bc6fSPatrick Sanan 
8617*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreateCompatibleDMDA()`, `DMStagCreateCompatibleDMStag()`
86188320bc6fSPatrick Sanan @*/
8619d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCompatibility(DM dm1, DM dm2, PetscBool *compatible, PetscBool *set)
8620d71ae5a4SJacob Faibussowitsch {
86218320bc6fSPatrick Sanan   PetscMPIInt compareResult;
86228320bc6fSPatrick Sanan   DMType      type, type2;
86238320bc6fSPatrick Sanan   PetscBool   sameType;
86248320bc6fSPatrick Sanan 
86258320bc6fSPatrick Sanan   PetscFunctionBegin;
8626a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dm1, DM_CLASSID, 1);
86278320bc6fSPatrick Sanan   PetscValidHeaderSpecific(dm2, DM_CLASSID, 2);
86288320bc6fSPatrick Sanan 
86298320bc6fSPatrick Sanan   /* Declare a DM compatible with itself */
8630a5bc1bf3SBarry Smith   if (dm1 == dm2) {
86318320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
86328320bc6fSPatrick Sanan     *compatible = PETSC_TRUE;
86333ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
86348320bc6fSPatrick Sanan   }
86358320bc6fSPatrick Sanan 
86368320bc6fSPatrick Sanan   /* Declare a DM incompatible with a DM that lives on an "unequal"
86378320bc6fSPatrick Sanan      communicator. Note that this does not preclude compatibility with
86388320bc6fSPatrick Sanan      DMs living on "congruent" or "similar" communicators, but this must be
86398320bc6fSPatrick Sanan      determined by the implementation-specific logic */
86409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)dm1), PetscObjectComm((PetscObject)dm2), &compareResult));
86418320bc6fSPatrick Sanan   if (compareResult == MPI_UNEQUAL) {
86428320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
86438320bc6fSPatrick Sanan     *compatible = PETSC_FALSE;
86443ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
86458320bc6fSPatrick Sanan   }
86468320bc6fSPatrick Sanan 
86478320bc6fSPatrick Sanan   /* Pass to the implementation-specific routine, if one exists. */
8648a5bc1bf3SBarry Smith   if (dm1->ops->getcompatibility) {
8649dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm1, getcompatibility, dm2, compatible, set);
86503ba16761SJacob Faibussowitsch     if (*set) PetscFunctionReturn(PETSC_SUCCESS);
86518320bc6fSPatrick Sanan   }
86528320bc6fSPatrick Sanan 
8653a5bc1bf3SBarry Smith   /* If dm1 and dm2 are of different types, then attempt to check compatibility
86548320bc6fSPatrick Sanan      with an implementation of this function from dm2 */
86559566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm1, &type));
86569566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm2, &type2));
86579566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(type, type2, &sameType));
86588320bc6fSPatrick Sanan   if (!sameType && dm2->ops->getcompatibility) {
8659dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm2, getcompatibility, dm1, compatible, set); /* Note argument order */
86608320bc6fSPatrick Sanan   } else {
86618320bc6fSPatrick Sanan     *set = PETSC_FALSE;
86628320bc6fSPatrick Sanan   }
86633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86648320bc6fSPatrick Sanan }
8665c0f0dcc3SMatthew G. Knepley 
8666c0f0dcc3SMatthew G. Knepley /*@C
8667bb7acecfSBarry Smith   DMMonitorSet - Sets an additional monitor function that is to be used after a solve to monitor discretization performance.
8668c0f0dcc3SMatthew G. Knepley 
866920f4b53cSBarry Smith   Logically Collective
8670c0f0dcc3SMatthew G. Knepley 
8671c0f0dcc3SMatthew G. Knepley   Input Parameters:
8672bb7acecfSBarry Smith + DM - the `DM`
8673c0f0dcc3SMatthew G. Knepley . f - the monitor function
867420f4b53cSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
867520f4b53cSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
8676c0f0dcc3SMatthew G. Knepley 
867720f4b53cSBarry Smith   Options Database Key:
8678bb7acecfSBarry Smith - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `DMMonitorSet()`, but
8679c0f0dcc3SMatthew G. Knepley                             does not cancel those set via the options database.
8680c0f0dcc3SMatthew G. Knepley 
86819bdbcad8SBarry Smith   Level: intermediate
86829bdbcad8SBarry Smith 
8683bb7acecfSBarry Smith   Note:
8684c0f0dcc3SMatthew G. Knepley   Several different monitoring routines may be set by calling
8685bb7acecfSBarry Smith   `DMMonitorSet()` multiple times or with `DMMonitorSetFromOptions()`; all will be called in the
8686c0f0dcc3SMatthew G. Knepley   order in which they were set.
8687c0f0dcc3SMatthew G. Knepley 
8688bb7acecfSBarry Smith   Fortran Note:
8689bb7acecfSBarry Smith   Only a single monitor function can be set for each `DM` object
8690bb7acecfSBarry Smith 
8691bb7acecfSBarry Smith   Developer Note:
8692bb7acecfSBarry Smith   This API has a generic name but seems specific to a very particular aspect of the use of `DM`
8693c0f0dcc3SMatthew G. Knepley 
8694*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorCancel()`, `DMMonitorSetFromOptions()`, `DMMonitor()`
8695c0f0dcc3SMatthew G. Knepley @*/
8696d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
8697d71ae5a4SJacob Faibussowitsch {
8698c0f0dcc3SMatthew G. Knepley   PetscInt m;
8699c0f0dcc3SMatthew G. Knepley 
8700c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8701c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8702c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
8703c0f0dcc3SMatthew G. Knepley     PetscBool identical;
8704c0f0dcc3SMatthew G. Knepley 
87059566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical));
87063ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
8707c0f0dcc3SMatthew G. Knepley   }
87087a8be351SBarry Smith   PetscCheck(dm->numbermonitors < MAXDMMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
8709c0f0dcc3SMatthew G. Knepley   dm->monitor[dm->numbermonitors]          = f;
8710c0f0dcc3SMatthew G. Knepley   dm->monitordestroy[dm->numbermonitors]   = monitordestroy;
8711c0f0dcc3SMatthew G. Knepley   dm->monitorcontext[dm->numbermonitors++] = (void *)mctx;
87123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8713c0f0dcc3SMatthew G. Knepley }
8714c0f0dcc3SMatthew G. Knepley 
8715c0f0dcc3SMatthew G. Knepley /*@
8716bb7acecfSBarry Smith   DMMonitorCancel - Clears all the monitor functions for a `DM` object.
8717c0f0dcc3SMatthew G. Knepley 
871820f4b53cSBarry Smith   Logically Collective
8719c0f0dcc3SMatthew G. Knepley 
8720c0f0dcc3SMatthew G. Knepley   Input Parameter:
8721c0f0dcc3SMatthew G. Knepley . dm - the DM
8722c0f0dcc3SMatthew G. Knepley 
8723c0f0dcc3SMatthew G. Knepley   Options Database Key:
8724c0f0dcc3SMatthew G. Knepley . -dm_monitor_cancel - cancels all monitors that have been hardwired
8725bb7acecfSBarry Smith   into a code by calls to `DMonitorSet()`, but does not cancel those
8726c0f0dcc3SMatthew G. Knepley   set via the options database
8727c0f0dcc3SMatthew G. Knepley 
87289bdbcad8SBarry Smith   Level: intermediate
87299bdbcad8SBarry Smith 
8730bb7acecfSBarry Smith   Note:
8731bb7acecfSBarry Smith   There is no way to clear one specific monitor from a `DM` object.
8732c0f0dcc3SMatthew G. Knepley 
8733*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMMonitorSetFromOptions()`, `DMMonitor()`
8734c0f0dcc3SMatthew G. Knepley @*/
8735d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorCancel(DM dm)
8736d71ae5a4SJacob Faibussowitsch {
8737c0f0dcc3SMatthew G. Knepley   PetscInt m;
8738c0f0dcc3SMatthew G. Knepley 
8739c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8740c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8741c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
87429566063dSJacob Faibussowitsch     if (dm->monitordestroy[m]) PetscCall((*dm->monitordestroy[m])(&dm->monitorcontext[m]));
8743c0f0dcc3SMatthew G. Knepley   }
8744c0f0dcc3SMatthew G. Knepley   dm->numbermonitors = 0;
87453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8746c0f0dcc3SMatthew G. Knepley }
8747c0f0dcc3SMatthew G. Knepley 
8748c0f0dcc3SMatthew G. Knepley /*@C
8749c0f0dcc3SMatthew G. Knepley   DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
8750c0f0dcc3SMatthew G. Knepley 
875120f4b53cSBarry Smith   Collective
8752c0f0dcc3SMatthew G. Knepley 
8753c0f0dcc3SMatthew G. Knepley   Input Parameters:
8754bb7acecfSBarry Smith + dm   - `DM` object you wish to monitor
8755c0f0dcc3SMatthew G. Knepley . name - the monitor type one is seeking
8756c0f0dcc3SMatthew G. Knepley . help - message indicating what monitoring is done
8757c0f0dcc3SMatthew G. Knepley . manual - manual page for the monitor
8758c0f0dcc3SMatthew G. Knepley . monitor - the monitor function
8759bb7acecfSBarry Smith - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the `DM` or `PetscViewer` objects
8760c0f0dcc3SMatthew G. Knepley 
8761c0f0dcc3SMatthew G. Knepley   Output Parameter:
8762c0f0dcc3SMatthew G. Knepley . flg - Flag set if the monitor was created
8763c0f0dcc3SMatthew G. Knepley 
8764c0f0dcc3SMatthew G. Knepley   Level: developer
8765c0f0dcc3SMatthew G. Knepley 
8766*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
8767db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
8768db781477SPatrick Sanan           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
8769db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
8770c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
8771db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
8772bb7acecfSBarry Smith           `PetscOptionsFList()`, `PetscOptionsEList()`, `DMMonitor()`, `DMMonitorSet()`
8773c0f0dcc3SMatthew G. Knepley @*/
8774d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg)
8775d71ae5a4SJacob Faibussowitsch {
8776c0f0dcc3SMatthew G. Knepley   PetscViewer       viewer;
8777c0f0dcc3SMatthew G. Knepley   PetscViewerFormat format;
8778c0f0dcc3SMatthew G. Knepley 
8779c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8780c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)dm), ((PetscObject)dm)->options, ((PetscObject)dm)->prefix, name, &viewer, &format, flg));
8782c0f0dcc3SMatthew G. Knepley   if (*flg) {
8783c0f0dcc3SMatthew G. Knepley     PetscViewerAndFormat *vf;
8784c0f0dcc3SMatthew G. Knepley 
87859566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
87869566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)viewer));
87879566063dSJacob Faibussowitsch     if (monitorsetup) PetscCall((*monitorsetup)(dm, vf));
87889566063dSJacob Faibussowitsch     PetscCall(DMMonitorSet(dm, (PetscErrorCode(*)(DM, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
8789c0f0dcc3SMatthew G. Knepley   }
87903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8791c0f0dcc3SMatthew G. Knepley }
8792c0f0dcc3SMatthew G. Knepley 
8793c0f0dcc3SMatthew G. Knepley /*@
8794c0f0dcc3SMatthew G. Knepley    DMMonitor - runs the user provided monitor routines, if they exist
8795c0f0dcc3SMatthew G. Knepley 
879620f4b53cSBarry Smith    Collective
8797c0f0dcc3SMatthew G. Knepley 
87982fe279fdSBarry Smith    Input Parameter:
8799bb7acecfSBarry Smith .  dm - The `DM`
8800c0f0dcc3SMatthew G. Knepley 
8801c0f0dcc3SMatthew G. Knepley    Level: developer
8802c0f0dcc3SMatthew G. Knepley 
8803bb7acecfSBarry Smith    Question:
8804bb7acecfSBarry Smith    Note should indicate when during the life of the `DM` the monitor is run. It appears to be related to the discretization process seems rather specialized
8805bb7acecfSBarry Smith    since some `DM` have no concept of discretization
8806bb7acecfSBarry Smith 
8807*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMMonitorSetFromOptions()`
8808c0f0dcc3SMatthew G. Knepley @*/
8809d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitor(DM dm)
8810d71ae5a4SJacob Faibussowitsch {
8811c0f0dcc3SMatthew G. Knepley   PetscInt m;
8812c0f0dcc3SMatthew G. Knepley 
8813c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
88143ba16761SJacob Faibussowitsch   if (!dm) PetscFunctionReturn(PETSC_SUCCESS);
8815c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
881648a46eb9SPierre Jolivet   for (m = 0; m < dm->numbermonitors; ++m) PetscCall((*dm->monitor[m])(dm, dm->monitorcontext[m]));
88173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8818c0f0dcc3SMatthew G. Knepley }
88192e4af2aeSMatthew G. Knepley 
88202e4af2aeSMatthew G. Knepley /*@
8821bb7acecfSBarry Smith   DMComputeError - Computes the error assuming the user has provided the exact solution functions
88222e4af2aeSMatthew G. Knepley 
882320f4b53cSBarry Smith   Collective
88242e4af2aeSMatthew G. Knepley 
88252e4af2aeSMatthew G. Knepley   Input Parameters:
8826bb7acecfSBarry Smith + dm     - The `DM`
88276b867d5aSJose E. Roman - sol    - The solution vector
88282e4af2aeSMatthew G. Knepley 
88296b867d5aSJose E. Roman   Input/Output Parameter:
883020f4b53cSBarry Smith . errors - An array of length Nf, the number of fields, or `NULL` for no output; on output
88316b867d5aSJose E. Roman            contains the error in each field
88326b867d5aSJose E. Roman 
88336b867d5aSJose E. Roman   Output Parameter:
883420f4b53cSBarry Smith . errorVec - A vector to hold the cellwise error (may be `NULL`)
883520f4b53cSBarry Smith 
883620f4b53cSBarry Smith   Level: developer
88372e4af2aeSMatthew G. Knepley 
8838bb7acecfSBarry Smith   Note:
8839bb7acecfSBarry Smith   The exact solutions come from the `PetscDS` object, and the time comes from `DMGetOutputSequenceNumber()`.
88402e4af2aeSMatthew G. Knepley 
8841*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMGetRegionNumDS()`, `PetscDSGetExactSolution()`, `DMGetOutputSequenceNumber()`
88422e4af2aeSMatthew G. Knepley @*/
8843d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec)
8844d71ae5a4SJacob Faibussowitsch {
88452e4af2aeSMatthew G. Knepley   PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
88462e4af2aeSMatthew G. Knepley   void    **ctxs;
88472e4af2aeSMatthew G. Knepley   PetscReal time;
88482e4af2aeSMatthew G. Knepley   PetscInt  Nf, f, Nds, s;
88492e4af2aeSMatthew G. Knepley 
88502e4af2aeSMatthew G. Knepley   PetscFunctionBegin;
88519566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
88529566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(Nf, &exactSol, Nf, &ctxs));
88539566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
88542e4af2aeSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
88552e4af2aeSMatthew G. Knepley     PetscDS         ds;
88562e4af2aeSMatthew G. Knepley     DMLabel         label;
88572e4af2aeSMatthew G. Knepley     IS              fieldIS;
88582e4af2aeSMatthew G. Knepley     const PetscInt *fields;
88592e4af2aeSMatthew G. Knepley     PetscInt        dsNf;
88602e4af2aeSMatthew G. Knepley 
886107218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds, NULL));
88629566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
88639566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISGetIndices(fieldIS, &fields));
88642e4af2aeSMatthew G. Knepley     for (f = 0; f < dsNf; ++f) {
88652e4af2aeSMatthew G. Knepley       const PetscInt field = fields[f];
88669566063dSJacob Faibussowitsch       PetscCall(PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]));
88672e4af2aeSMatthew G. Knepley     }
88689566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISRestoreIndices(fieldIS, &fields));
88692e4af2aeSMatthew G. Knepley   }
8870ad540459SPierre Jolivet   for (f = 0; f < Nf; ++f) PetscCheck(exactSol[f], PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "DS must contain exact solution functions in order to calculate error, missing for field %" PetscInt_FMT, f);
88719566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
88729566063dSJacob Faibussowitsch   if (errors) PetscCall(DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors));
88732e4af2aeSMatthew G. Knepley   if (errorVec) {
88742e4af2aeSMatthew G. Knepley     DM             edm;
88752e4af2aeSMatthew G. Knepley     DMPolytopeType ct;
88762e4af2aeSMatthew G. Knepley     PetscBool      simplex;
88772e4af2aeSMatthew G. Knepley     PetscInt       dim, cStart, Nf;
88782e4af2aeSMatthew G. Knepley 
88799566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &edm));
88809566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(edm, &dim));
88819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
88829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cStart, &ct));
88832e4af2aeSMatthew G. Knepley     simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
88849566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
88852e4af2aeSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
88862e4af2aeSMatthew G. Knepley       PetscFE         fe, efe;
88872e4af2aeSMatthew G. Knepley       PetscQuadrature q;
88882e4af2aeSMatthew G. Knepley       const char     *name;
88892e4af2aeSMatthew G. Knepley 
88909566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe));
88919566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe));
88929566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)fe, &name));
88939566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)efe, name));
88949566063dSJacob Faibussowitsch       PetscCall(PetscFEGetQuadrature(fe, &q));
88959566063dSJacob Faibussowitsch       PetscCall(PetscFESetQuadrature(efe, q));
88969566063dSJacob Faibussowitsch       PetscCall(DMSetField(edm, f, NULL, (PetscObject)efe));
88979566063dSJacob Faibussowitsch       PetscCall(PetscFEDestroy(&efe));
88982e4af2aeSMatthew G. Knepley     }
88999566063dSJacob Faibussowitsch     PetscCall(DMCreateDS(edm));
89002e4af2aeSMatthew G. Knepley 
89019566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(edm, errorVec));
89029566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*errorVec, "Error"));
89039566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec));
89049566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&edm));
89052e4af2aeSMatthew G. Knepley   }
89069566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exactSol, ctxs));
89073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
89082e4af2aeSMatthew G. Knepley }
89099a2a23afSMatthew G. Knepley 
89109a2a23afSMatthew G. Knepley /*@
8911bb7acecfSBarry Smith   DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this `DM`
89129a2a23afSMatthew G. Knepley 
891320f4b53cSBarry Smith   Not Collective
89149a2a23afSMatthew G. Knepley 
89159a2a23afSMatthew G. Knepley   Input Parameter:
8916bb7acecfSBarry Smith . dm     - The `DM`
89179a2a23afSMatthew G. Knepley 
89189a2a23afSMatthew G. Knepley   Output Parameter:
8919a5b23f4aSJose E. Roman . numAux - The number of auxiliary data vectors
89209a2a23afSMatthew G. Knepley 
89219a2a23afSMatthew G. Knepley   Level: advanced
89229a2a23afSMatthew G. Knepley 
8923*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
89249a2a23afSMatthew G. Knepley @*/
8925d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux)
8926d71ae5a4SJacob Faibussowitsch {
89279a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89289a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89299566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetSize(dm->auxData, numAux));
89303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
89319a2a23afSMatthew G. Knepley }
89329a2a23afSMatthew G. Knepley 
89339a2a23afSMatthew G. Knepley /*@
8934ac17215fSMatthew G. Knepley   DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value, and equation part
89359a2a23afSMatthew G. Knepley 
893620f4b53cSBarry Smith   Not Collective
89379a2a23afSMatthew G. Knepley 
89389a2a23afSMatthew G. Knepley   Input Parameters:
8939bb7acecfSBarry Smith + dm     - The `DM`
8940bb7acecfSBarry Smith . label  - The `DMLabel`
8941ac17215fSMatthew G. Knepley . value  - The label value indicating the region
8942ac17215fSMatthew G. Knepley - part   - The equation part, or 0 if unused
89439a2a23afSMatthew G. Knepley 
89449a2a23afSMatthew G. Knepley   Output Parameter:
8945bb7acecfSBarry Smith . aux    - The `Vec` holding auxiliary field data
89469a2a23afSMatthew G. Knepley 
89479bdbcad8SBarry Smith   Level: advanced
89489bdbcad8SBarry Smith 
8949bb7acecfSBarry Smith   Note:
8950bb7acecfSBarry Smith   If no auxiliary vector is found for this (label, value), (NULL, 0, 0) is checked as well.
895104c51a94SMatthew G. Knepley 
8952*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryLabels()`
89539a2a23afSMatthew G. Knepley @*/
8954d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec *aux)
8955d71ae5a4SJacob Faibussowitsch {
8956ac17215fSMatthew G. Knepley   PetscHashAuxKey key, wild = {NULL, 0, 0};
895704c51a94SMatthew G. Knepley   PetscBool       has;
89589a2a23afSMatthew G. Knepley 
89599a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89609a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89619a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
89629a2a23afSMatthew G. Knepley   key.label = label;
89639a2a23afSMatthew G. Knepley   key.value = value;
8964ac17215fSMatthew G. Knepley   key.part  = part;
89659566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxHas(dm->auxData, key, &has));
89669566063dSJacob Faibussowitsch   if (has) PetscCall(PetscHMapAuxGet(dm->auxData, key, aux));
89679566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxGet(dm->auxData, wild, aux));
89683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
89699a2a23afSMatthew G. Knepley }
89709a2a23afSMatthew G. Knepley 
89719a2a23afSMatthew G. Knepley /*@
8972bb7acecfSBarry Smith   DMSetAuxiliaryVec - Set an auxiliary vector for region specified by the given label and value, and equation part
89739a2a23afSMatthew G. Knepley 
897420f4b53cSBarry Smith   Not Collective because auxiliary vectors are not parallel
89759a2a23afSMatthew G. Knepley 
89769a2a23afSMatthew G. Knepley   Input Parameters:
8977bb7acecfSBarry Smith + dm     - The `DM`
8978bb7acecfSBarry Smith . label  - The `DMLabel`
89799a2a23afSMatthew G. Knepley . value  - The label value indicating the region
8980ac17215fSMatthew G. Knepley . part   - The equation part, or 0 if unused
8981bb7acecfSBarry Smith - aux    - The `Vec` holding auxiliary field data
89829a2a23afSMatthew G. Knepley 
89839a2a23afSMatthew G. Knepley   Level: advanced
89849a2a23afSMatthew G. Knepley 
8985*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMCopyAuxiliaryVec()`
89869a2a23afSMatthew G. Knepley @*/
8987d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec aux)
8988d71ae5a4SJacob Faibussowitsch {
89899a2a23afSMatthew G. Knepley   Vec             old;
89909a2a23afSMatthew G. Knepley   PetscHashAuxKey key;
89919a2a23afSMatthew G. Knepley 
89929a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89939a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89949a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
89959a2a23afSMatthew G. Knepley   key.label = label;
89969a2a23afSMatthew G. Knepley   key.value = value;
8997ac17215fSMatthew G. Knepley   key.part  = part;
89989566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGet(dm->auxData, key, &old));
89999566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)aux));
90009566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)old));
90019566063dSJacob Faibussowitsch   if (!aux) PetscCall(PetscHMapAuxDel(dm->auxData, key));
90029566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxSet(dm->auxData, key, aux));
90033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
90049a2a23afSMatthew G. Knepley }
90059a2a23afSMatthew G. Knepley 
90069a2a23afSMatthew G. Knepley /*@C
9007bb7acecfSBarry Smith   DMGetAuxiliaryLabels - Get the labels, values, and parts for all auxiliary vectors in this `DM`
90089a2a23afSMatthew G. Knepley 
900920f4b53cSBarry Smith   Not Collective
90109a2a23afSMatthew G. Knepley 
90119a2a23afSMatthew G. Knepley   Input Parameter:
9012bb7acecfSBarry Smith . dm      - The `DM`
90139a2a23afSMatthew G. Knepley 
90149a2a23afSMatthew G. Knepley   Output Parameters:
9015bb7acecfSBarry Smith + labels  - The `DMLabel`s for each `Vec`
9016bb7acecfSBarry Smith . values  - The label values for each `Vec`
9017bb7acecfSBarry Smith - parts   - The equation parts for each `Vec`
90189a2a23afSMatthew G. Knepley 
90199bdbcad8SBarry Smith   Level: advanced
90209bdbcad8SBarry Smith 
9021bb7acecfSBarry Smith   Note:
9022bb7acecfSBarry Smith   The arrays passed in must be at least as large as `DMGetNumAuxiliaryVec()`.
90239a2a23afSMatthew G. Knepley 
9024*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMSetAuxiliaryVec()`, DMCopyAuxiliaryVec()`
90259a2a23afSMatthew G. Knepley @*/
9026d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[], PetscInt parts[])
9027d71ae5a4SJacob Faibussowitsch {
90289a2a23afSMatthew G. Knepley   PetscHashAuxKey *keys;
90299a2a23afSMatthew G. Knepley   PetscInt         n, i, off = 0;
90309a2a23afSMatthew G. Knepley 
90319a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90329a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90339a2a23afSMatthew G. Knepley   PetscValidPointer(labels, 2);
9034dadcf809SJacob Faibussowitsch   PetscValidIntPointer(values, 3);
9035dadcf809SJacob Faibussowitsch   PetscValidIntPointer(parts, 4);
90369566063dSJacob Faibussowitsch   PetscCall(DMGetNumAuxiliaryVec(dm, &n));
90379566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &keys));
90389566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetKeys(dm->auxData, &off, keys));
90399371c9d4SSatish Balay   for (i = 0; i < n; ++i) {
90409371c9d4SSatish Balay     labels[i] = keys[i].label;
90419371c9d4SSatish Balay     values[i] = keys[i].value;
90429371c9d4SSatish Balay     parts[i]  = keys[i].part;
90439371c9d4SSatish Balay   }
90449566063dSJacob Faibussowitsch   PetscCall(PetscFree(keys));
90453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
90469a2a23afSMatthew G. Knepley }
90479a2a23afSMatthew G. Knepley 
90489a2a23afSMatthew G. Knepley /*@
9049bb7acecfSBarry Smith   DMCopyAuxiliaryVec - Copy the auxiliary vector data on a `DM` to a new `DM`
90509a2a23afSMatthew G. Knepley 
905120f4b53cSBarry Smith   Not Collective
90529a2a23afSMatthew G. Knepley 
90539a2a23afSMatthew G. Knepley   Input Parameter:
9054bb7acecfSBarry Smith . dm    - The `DM`
90559a2a23afSMatthew G. Knepley 
90569a2a23afSMatthew G. Knepley   Output Parameter:
9057bb7acecfSBarry Smith . dmNew - The new `DM`, now with the same auxiliary data
90589a2a23afSMatthew G. Knepley 
90599a2a23afSMatthew G. Knepley   Level: advanced
90609a2a23afSMatthew G. Knepley 
9061bb7acecfSBarry Smith   Note:
9062bb7acecfSBarry Smith   This is a shallow copy of the auxiliary vectors
9063bb7acecfSBarry Smith 
9064*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
90659a2a23afSMatthew G. Knepley @*/
9066d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew)
9067d71ae5a4SJacob Faibussowitsch {
90689a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90699a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90709566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDestroy(&dmNew->auxData));
90719566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData));
90723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
90739a2a23afSMatthew G. Knepley }
9074b5a892a1SMatthew G. Knepley 
9075b5a892a1SMatthew G. Knepley /*@C
9076bb7acecfSBarry Smith   DMPolytopeMatchOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9077b5a892a1SMatthew G. Knepley 
907820f4b53cSBarry Smith   Not Collective
9079b5a892a1SMatthew G. Knepley 
9080b5a892a1SMatthew G. Knepley   Input Parameters:
9081bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9082b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9083b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9084b5a892a1SMatthew G. Knepley 
9085b5a892a1SMatthew G. Knepley   Output Parameters:
9086bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9087b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9088b5a892a1SMatthew G. Knepley 
9089b5a892a1SMatthew G. Knepley   Level: advanced
9090b5a892a1SMatthew G. Knepley 
9091bb7acecfSBarry Smith   Note:
9092bb7acecfSBarry Smith   An arrangement is a face order combined with an orientation for each face
9093bb7acecfSBarry Smith 
9094bb7acecfSBarry Smith   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangments(ct)`/2 to `DMPolytopeTypeGetNumArrangments(ct)`/2
9095bb7acecfSBarry Smith   that labels each arrangement (face ordering plus orientation for each face).
9096bb7acecfSBarry Smith 
9097bb7acecfSBarry Smith   See `DMPolytopeMatchVertexOrientation()` to find a new vertex orientation that takes the source vertex arrangement to the target vertex arrangement
9098bb7acecfSBarry Smith 
9099*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetVertexOrientation()`
9100b5a892a1SMatthew G. Knepley @*/
9101d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt, PetscBool *found)
9102d71ae5a4SJacob Faibussowitsch {
9103b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetConeSize(ct);
9104b5a892a1SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct) / 2;
9105b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9106b5a892a1SMatthew G. Knepley 
9107b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91089371c9d4SSatish Balay   if (!nO) {
91099371c9d4SSatish Balay     *ornt  = 0;
91109371c9d4SSatish Balay     *found = PETSC_TRUE;
91113ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
91129371c9d4SSatish Balay   }
9113b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
9114b5a892a1SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
9115b5a892a1SMatthew G. Knepley 
91169371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
91179371c9d4SSatish Balay       if (sourceCone[arr[c * 2]] != targetCone[c]) break;
91189371c9d4SSatish Balay     if (c == cS) {
91199371c9d4SSatish Balay       *ornt = o;
91209371c9d4SSatish Balay       break;
91219371c9d4SSatish Balay     }
9122b5a892a1SMatthew G. Knepley   }
9123b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
91243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9125b5a892a1SMatthew G. Knepley }
9126b5a892a1SMatthew G. Knepley 
9127b5a892a1SMatthew G. Knepley /*@C
9128bb7acecfSBarry Smith   DMPolytopeGetOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9129b5a892a1SMatthew G. Knepley 
913020f4b53cSBarry Smith   Not Collective
9131b5a892a1SMatthew G. Knepley 
9132b5a892a1SMatthew G. Knepley   Input Parameters:
9133bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9134b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9135b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9136b5a892a1SMatthew G. Knepley 
91372fe279fdSBarry Smith   Output Parameter:
9138bb7acecfSBarry Smith . ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9139b5a892a1SMatthew G. Knepley 
9140b5a892a1SMatthew G. Knepley   Level: advanced
9141b5a892a1SMatthew G. Knepley 
9142bb7acecfSBarry Smith   Note:
9143bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchOrientation()` except it will generate an error if no suitable orientation can be found.
9144bb7acecfSBarry Smith 
9145bb7acecfSBarry Smith   Developer Note:
9146bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchOrientation()` and error if none is found
9147bb7acecfSBarry Smith 
9148*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeMatchOrientation()`, `DMPolytopeGetVertexOrientation()`, `DMPolytopeMatchVertexOrientation()`
9149b5a892a1SMatthew G. Knepley @*/
9150d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9151d71ae5a4SJacob Faibussowitsch {
9152b5a892a1SMatthew G. Knepley   PetscBool found;
9153b5a892a1SMatthew G. Knepley 
9154b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91559566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchOrientation(ct, sourceCone, targetCone, ornt, &found));
91567a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
91573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9158b5a892a1SMatthew G. Knepley }
9159b5a892a1SMatthew G. Knepley 
9160b5a892a1SMatthew G. Knepley /*@C
9161bb7acecfSBarry Smith   DMPolytopeMatchVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9162b5a892a1SMatthew G. Knepley 
916320f4b53cSBarry Smith   Not Collective
9164b5a892a1SMatthew G. Knepley 
9165b5a892a1SMatthew G. Knepley   Input Parameters:
9166bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9167b5a892a1SMatthew G. Knepley . sourceVert - The source arrangement of vertices
9168b5a892a1SMatthew G. Knepley - targetVert - The target arrangement of vertices
9169b5a892a1SMatthew G. Knepley 
9170b5a892a1SMatthew G. Knepley   Output Parameters:
9171bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9172b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9173b5a892a1SMatthew G. Knepley 
9174b5a892a1SMatthew G. Knepley   Level: advanced
9175b5a892a1SMatthew G. Knepley 
9176bb7acecfSBarry Smith   Note:
9177bb7acecfSBarry Smith   An arrangement is a vertex order
9178bb7acecfSBarry Smith 
9179bb7acecfSBarry Smith   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangments(ct)`/2 to `DMPolytopeTypeGetNumArrangments(ct)`/2
9180bb7acecfSBarry Smith   that labels each arrangement (vertex ordering).
9181bb7acecfSBarry Smith 
9182bb7acecfSBarry Smith   See `DMPolytopeMatchOrientation()` to find a new face orientation that takes the source face arrangement to the target face arrangement
9183bb7acecfSBarry Smith 
9184*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchOrientation()`, `DMPolytopeTypeGetNumVertices()`, `DMPolytopeTypeGetVertexArrangment()`
9185b5a892a1SMatthew G. Knepley @*/
9186d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchVertexOrientation(DMPolytopeType ct, const PetscInt sourceVert[], const PetscInt targetVert[], PetscInt *ornt, PetscBool *found)
9187d71ae5a4SJacob Faibussowitsch {
9188b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetNumVertices(ct);
9189b5a892a1SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct) / 2;
9190b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9191b5a892a1SMatthew G. Knepley 
9192b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91939371c9d4SSatish Balay   if (!nO) {
91949371c9d4SSatish Balay     *ornt  = 0;
91959371c9d4SSatish Balay     *found = PETSC_TRUE;
91963ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
91979371c9d4SSatish Balay   }
9198b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
9199b5a892a1SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetVertexArrangment(ct, o);
9200b5a892a1SMatthew G. Knepley 
92019371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
92029371c9d4SSatish Balay       if (sourceVert[arr[c]] != targetVert[c]) break;
92039371c9d4SSatish Balay     if (c == cS) {
92049371c9d4SSatish Balay       *ornt = o;
92059371c9d4SSatish Balay       break;
92069371c9d4SSatish Balay     }
9207b5a892a1SMatthew G. Knepley   }
9208b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
92093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9210b5a892a1SMatthew G. Knepley }
9211b5a892a1SMatthew G. Knepley 
9212b5a892a1SMatthew G. Knepley /*@C
9213bb7acecfSBarry Smith   DMPolytopeGetVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9214b5a892a1SMatthew G. Knepley 
921520f4b53cSBarry Smith   Not Collective
9216b5a892a1SMatthew G. Knepley 
9217b5a892a1SMatthew G. Knepley   Input Parameters:
9218bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9219b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of vertices
9220b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of vertices
9221b5a892a1SMatthew G. Knepley 
92222fe279fdSBarry Smith   Output Parameter:
9223bb7acecfSBarry Smith . ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9224b5a892a1SMatthew G. Knepley 
9225b5a892a1SMatthew G. Knepley   Level: advanced
9226b5a892a1SMatthew G. Knepley 
9227bb7acecfSBarry Smith   Note:
9228bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchVertexOrientation()` except it errors if not orientation is possible.
9229bb7acecfSBarry Smith 
9230bb7acecfSBarry Smith   Developer Note:
9231bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchVertexOrientation()` and error if none is found
9232bb7acecfSBarry Smith 
9233*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetOrientation()`
9234b5a892a1SMatthew G. Knepley @*/
9235d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetVertexOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9236d71ae5a4SJacob Faibussowitsch {
9237b5a892a1SMatthew G. Knepley   PetscBool found;
9238b5a892a1SMatthew G. Knepley 
9239b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
92409566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchVertexOrientation(ct, sourceCone, targetCone, ornt, &found));
92417a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
92423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9243b5a892a1SMatthew G. Knepley }
9244012bc364SMatthew G. Knepley 
9245012bc364SMatthew G. Knepley /*@C
9246012bc364SMatthew G. Knepley   DMPolytopeInCellTest - Check whether a point lies inside the reference cell of given type
9247012bc364SMatthew G. Knepley 
924820f4b53cSBarry Smith   Not Collective
9249012bc364SMatthew G. Knepley 
9250012bc364SMatthew G. Knepley   Input Parameters:
9251bb7acecfSBarry Smith + ct    - The `DMPolytopeType`
9252012bc364SMatthew G. Knepley - point - Coordinates of the point
9253012bc364SMatthew G. Knepley 
92542fe279fdSBarry Smith   Output Parameter:
9255012bc364SMatthew G. Knepley . inside  - Flag indicating whether the point is inside the reference cell of given type
9256012bc364SMatthew G. Knepley 
9257012bc364SMatthew G. Knepley   Level: advanced
9258012bc364SMatthew G. Knepley 
9259*1cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMLocatePoints()`
9260012bc364SMatthew G. Knepley @*/
9261d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeInCellTest(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
9262d71ae5a4SJacob Faibussowitsch {
9263012bc364SMatthew G. Knepley   PetscReal sum = 0.0;
9264012bc364SMatthew G. Knepley   PetscInt  d;
9265012bc364SMatthew G. Knepley 
9266012bc364SMatthew G. Knepley   PetscFunctionBegin;
9267012bc364SMatthew G. Knepley   *inside = PETSC_TRUE;
9268012bc364SMatthew G. Knepley   switch (ct) {
9269012bc364SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
9270012bc364SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
9271012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
92729371c9d4SSatish Balay       if (point[d] < -1.0) {
92739371c9d4SSatish Balay         *inside = PETSC_FALSE;
92749371c9d4SSatish Balay         break;
92759371c9d4SSatish Balay       }
9276012bc364SMatthew G. Knepley       sum += point[d];
9277012bc364SMatthew G. Knepley     }
92789371c9d4SSatish Balay     if (sum > PETSC_SMALL) {
92799371c9d4SSatish Balay       *inside = PETSC_FALSE;
92809371c9d4SSatish Balay       break;
92819371c9d4SSatish Balay     }
9282012bc364SMatthew G. Knepley     break;
9283012bc364SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
9284012bc364SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
9285012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
92869371c9d4SSatish Balay       if (PetscAbsReal(point[d]) > 1. + PETSC_SMALL) {
92879371c9d4SSatish Balay         *inside = PETSC_FALSE;
9288012bc364SMatthew G. Knepley         break;
92899371c9d4SSatish Balay       }
92909371c9d4SSatish Balay     break;
9291d71ae5a4SJacob Faibussowitsch   default:
9292d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
9293012bc364SMatthew G. Knepley   }
92943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9295012bc364SMatthew G. Knepley }
9296