xref: /petsc/src/dm/interface/dm.c (revision 0462cc06d86a4b04d8da7c4dbbe0d29bc6def07a)
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 
49bb7acecfSBarry Smith .seealso: `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));
959566063dSJacob Faibussowitsch   PetscCall(DMSetRegionDS(v, NULL, NULL, ds));
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 
131bb7acecfSBarry Smith .seealso: `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));
1689566063dSJacob Faibussowitsch       PetscCallMPI(MPI_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 
224bb7acecfSBarry Smith .seealso: `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 
249db781477SPatrick Sanan .seealso: `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 
275bb7acecfSBarry Smith .seealso: `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 
302db781477SPatrick Sanan .seealso: `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 
327db781477SPatrick Sanan .seealso: `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 
354db781477SPatrick Sanan .seealso: `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 
379bb7acecfSBarry Smith .seealso: `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 
403db781477SPatrick Sanan .seealso: `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 
432db781477SPatrick Sanan .seealso: `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 
461db781477SPatrick Sanan .seealso: `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 
48720f4b53cSBarry Smith .seealso: `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 
51620f4b53cSBarry Smith .seealso: `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 
53231697293SDave May    Input Parameters:
533bb7acecfSBarry Smith .  dm - the `DM` context
53431697293SDave May 
53531697293SDave May    Output Parameters:
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 
544bb7acecfSBarry Smith .seealso: `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 
63020f4b53cSBarry Smith .seealso: `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 
817bb7acecfSBarry Smith .seealso: `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 
888bb7acecfSBarry Smith .seealso: `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 
934bb7acecfSBarry Smith .seealso: `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*0462cc06SPierre Jolivet .seealso: `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 
1014bb7acecfSBarry Smith .seealso: `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 
1048bb7acecfSBarry Smith  .seealso: `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 
1087bb7acecfSBarry Smith .seealso: `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 
1175db781477SPatrick Sanan .seealso: `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 
1210bb7acecfSBarry Smith .seealso: `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 
1243bb7acecfSBarry Smith .seealso: `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 
1293bb7acecfSBarry Smith .seealso: `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 
1328bb7acecfSBarry Smith .seealso: `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 
1363bb7acecfSBarry Smith .seealso: `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 
1393bb7acecfSBarry Smith .seealso: `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 
14271bf8429eSBarry Smith .seealso: `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 
1467bb7acecfSBarry Smith .seealso: `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 
1522bb7acecfSBarry Smith .seealso: `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 
1547bb7acecfSBarry Smith .seealso: `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 
1569bb7acecfSBarry Smith .seealso: `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 
1593863027abSJed Brown .seealso: `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 
1608863027abSJed Brown   Input Parameters:
1609863027abSJed Brown . dm - the `DM`
1610863027abSJed Brown 
1611863027abSJed Brown   Output Parameters:
1612863027abSJed Brown . btype - block by topological point or field node
1613863027abSJed Brown 
1614863027abSJed Brown   Level: advanced
1615863027abSJed Brown 
1616863027abSJed Brown .seealso: `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 
1647bb7acecfSBarry Smith .seealso: `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 
1697bb7acecfSBarry Smith .seealso: `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 
1740bb7acecfSBarry Smith .seealso: `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 
1774bb7acecfSBarry Smith .seealso: `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 
1807bb7acecfSBarry Smith .seealso: `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 
1842bb7acecfSBarry Smith .seealso: `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 
1879bb7acecfSBarry Smith .seealso: `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 
2006bb7acecfSBarry Smith .seealso: `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 
2083bb7acecfSBarry Smith .seealso: `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 
2114bb7acecfSBarry Smith .seealso: `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 
2162bb7acecfSBarry Smith .seealso: `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 
2239bb7acecfSBarry Smith .seealso: `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 
2270bb7acecfSBarry Smith .seealso: `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
2306bb7acecfSBarry Smith .  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 
2332bb7acecfSBarry Smith .seealso: `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 
2369bb7acecfSBarry Smith .seealso: `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 
2404bb7acecfSBarry Smith .seealso: `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 
2444bb7acecfSBarry Smith .seealso: `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 
2481bb7acecfSBarry Smith .seealso: `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 
2507bb7acecfSBarry Smith .seealso: `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 
2534bb7acecfSBarry Smith .seealso: `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 
2579bb7acecfSBarry Smith .seealso: `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 
2683bb7acecfSBarry Smith .seealso: `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 
2753bb7acecfSBarry Smith .seealso: `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 
2787bb7acecfSBarry Smith .seealso: `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 
2833bb7acecfSBarry Smith .seealso: `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 
2896bb7acecfSBarry Smith .seealso: `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 
2972bb7acecfSBarry Smith .seealso: `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 
3006bb7acecfSBarry Smith .seealso: `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 
3134bb7acecfSBarry Smith .seealso: `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*0462cc06SPierre Jolivet .seealso: `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 
3235bb7acecfSBarry Smith .seealso: `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 
3261bb7acecfSBarry Smith .seealso: `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 
3327db781477SPatrick Sanan .seealso: `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 
3363db781477SPatrick Sanan .seealso: `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 
3399bb7acecfSBarry Smith .seealso: `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 
3447bb7acecfSBarry Smith .seealso: `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 
3480db781477SPatrick Sanan .seealso: `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 
3512db781477SPatrick Sanan .seealso: `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 
3538bb7acecfSBarry Smith .seealso: `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 
3563bb7acecfSBarry Smith .seealso: `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 
3587bb7acecfSBarry Smith .seealso: `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 
3621bb7acecfSBarry Smith .seealso: `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 
3652bb7acecfSBarry Smith .seealso: `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 
3676bb7acecfSBarry Smith .seealso: `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 
3702bb7acecfSBarry Smith .seealso: `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 
3723bb7acecfSBarry Smith .seealso: `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 
3747bb7acecfSBarry Smith .seealso: `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 
3775bb7acecfSBarry Smith .seealso: `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 
3800bb7acecfSBarry Smith .seealso: `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 
3824bb7acecfSBarry Smith .seealso: `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 
3848bb7acecfSBarry Smith .seealso: `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:
3878*0462cc06SPierre Jolivet   Of the `DM` is constructed by directly calling a function to construct a particular `DM`, for example, `DMDACreate2d()` or `DMPlexCreateBoxMesh()`
3879bb7acecfSBarry Smith 
3880bb7acecfSBarry Smith .seealso: `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 
3916bb7acecfSBarry Smith .seealso: `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 
3947bb7acecfSBarry Smith .seealso: `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 
4068bb7acecfSBarry Smith .seealso: `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 
4098db781477SPatrick Sanan .seealso: `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 
4202db781477SPatrick Sanan .seealso: `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 
4228db781477SPatrick Sanan .seealso: `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 
4277db781477SPatrick Sanan .seealso: `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 
4298bb7acecfSBarry Smith .seealso: `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 
4346db781477SPatrick Sanan .seealso: `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 
4379db781477SPatrick Sanan .seealso: `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 
4425db781477SPatrick Sanan .seealso: `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 
4520db781477SPatrick Sanan .seealso: `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`
45495080bbdbSMatthew G Knepley - 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 
4556db781477SPatrick Sanan .seealso: `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 
4587db781477SPatrick Sanan .seealso: `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 
4626db781477SPatrick Sanan .seealso: `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 
4658db781477SPatrick Sanan .seealso: `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 
4684db781477SPatrick Sanan .seealso: `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 
4706db781477SPatrick Sanan .seealso: `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 
4733db781477SPatrick Sanan .seealso: `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 
4753db781477SPatrick Sanan .seealso: `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 
4812db781477SPatrick Sanan .seealso: `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 
4843db781477SPatrick Sanan .seealso: `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 
4865db781477SPatrick Sanan .seealso: `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 
4899db781477SPatrick Sanan .seealso: `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 
4940db781477SPatrick Sanan .seealso: `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 
4975bb7acecfSBarry Smith .seealso: `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 
5007db781477SPatrick Sanan .seealso: `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 
5031bb7acecfSBarry Smith  .seealso: `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 
5054db781477SPatrick Sanan .seealso: `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 
5100db781477SPatrick Sanan .seealso: `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 
5143db781477SPatrick Sanan .seealso: `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 
5184db781477SPatrick Sanan .seealso: `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 
5222db781477SPatrick Sanan .seealso: `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 
5259799db056SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC));
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 
5269799db056SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC));
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));
5294799db056SMatthew G. Knepley   PetscCallMPI(MPI_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 
5358db781477SPatrick Sanan .seealso: `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 
5379db781477SPatrick Sanan .seealso: `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));
53899566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->probs[s].label));
53909566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[s].fields));
5391e5e52638SMatthew G. Knepley   }
53929566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5393e5e52638SMatthew G. Knepley   dm->probs = NULL;
5394e5e52638SMatthew G. Knepley   dm->Nds   = 0;
53953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5396e5e52638SMatthew G. Knepley }
5397e5e52638SMatthew G. Knepley 
5398e5e52638SMatthew G. Knepley /*@
539920f4b53cSBarry Smith   DMGetDS - Get the default `PetscDS`
5400e5e52638SMatthew G. Knepley 
540120f4b53cSBarry Smith   Not Collective
5402e5e52638SMatthew G. Knepley 
5403e5e52638SMatthew G. Knepley   Input Parameter:
540420f4b53cSBarry Smith . dm    - The `DM`
5405e5e52638SMatthew G. Knepley 
5406e5e52638SMatthew G. Knepley   Output Parameter:
540720f4b53cSBarry Smith . prob - The default `PetscDS`
5408e5e52638SMatthew G. Knepley 
5409e5e52638SMatthew G. Knepley   Level: intermediate
5410e5e52638SMatthew G. Knepley 
5411db781477SPatrick Sanan .seealso: `DMGetCellDS()`, `DMGetRegionDS()`
5412e5e52638SMatthew G. Knepley @*/
5413d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
5414d71ae5a4SJacob Faibussowitsch {
5415e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5416e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5417e5e52638SMatthew G. Knepley   PetscValidPointer(prob, 2);
5418b0143b4dSMatthew G. Knepley   if (dm->Nds <= 0) {
5419b0143b4dSMatthew G. Knepley     PetscDS ds;
5420b0143b4dSMatthew G. Knepley 
54219566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
54229566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, NULL, NULL, ds));
54239566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&ds));
5424b0143b4dSMatthew G. Knepley   }
5425b0143b4dSMatthew G. Knepley   *prob = dm->probs[0].ds;
54263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5427e5e52638SMatthew G. Knepley }
5428e5e52638SMatthew G. Knepley 
5429e5e52638SMatthew G. Knepley /*@
543020f4b53cSBarry Smith   DMGetCellDS - Get the `PetscDS` defined on a given cell
5431e5e52638SMatthew G. Knepley 
543220f4b53cSBarry Smith   Not Collective
5433e5e52638SMatthew G. Knepley 
5434e5e52638SMatthew G. Knepley   Input Parameters:
543520f4b53cSBarry Smith + dm    - The `DM`
543620f4b53cSBarry Smith - point - Cell for the `PetscDS`
5437e5e52638SMatthew G. Knepley 
5438e5e52638SMatthew G. Knepley   Output Parameter:
543920f4b53cSBarry Smith . prob - The `PetscDS` defined on the given cell
5440e5e52638SMatthew G. Knepley 
5441e5e52638SMatthew G. Knepley   Level: developer
5442e5e52638SMatthew G. Knepley 
5443db781477SPatrick Sanan .seealso: `DMGetDS()`, `DMSetRegionDS()`
5444e5e52638SMatthew G. Knepley @*/
5445d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *prob)
5446d71ae5a4SJacob Faibussowitsch {
5447e5e52638SMatthew G. Knepley   PetscDS  probDef = NULL;
5448e5e52638SMatthew G. Knepley   PetscInt s;
5449e5e52638SMatthew G. Knepley 
5450e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5451e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5452e5e52638SMatthew G. Knepley   PetscValidPointer(prob, 3);
545363a3b9bcSJacob Faibussowitsch   PetscCheck(point >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %" PetscInt_FMT, point);
5454e5e52638SMatthew G. Knepley   *prob = NULL;
5455e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5456e5e52638SMatthew G. Knepley     PetscInt val;
5457e5e52638SMatthew G. Knepley 
54589371c9d4SSatish Balay     if (!dm->probs[s].label) {
54599371c9d4SSatish Balay       probDef = dm->probs[s].ds;
54609371c9d4SSatish Balay     } else {
54619566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(dm->probs[s].label, point, &val));
54629371c9d4SSatish Balay       if (val >= 0) {
54639371c9d4SSatish Balay         *prob = dm->probs[s].ds;
54649371c9d4SSatish Balay         break;
54659371c9d4SSatish Balay       }
5466e5e52638SMatthew G. Knepley     }
5467e5e52638SMatthew G. Knepley   }
5468e5e52638SMatthew G. Knepley   if (!*prob) *prob = probDef;
54693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5470e5e52638SMatthew G. Knepley }
5471e5e52638SMatthew G. Knepley 
5472e5e52638SMatthew G. Knepley /*@
547320f4b53cSBarry Smith   DMGetRegionDS - Get the `PetscDS` for a given mesh region, defined by a `DMLabel`
5474e5e52638SMatthew G. Knepley 
547520f4b53cSBarry Smith   Not Collective
5476e5e52638SMatthew G. Knepley 
5477e5e52638SMatthew G. Knepley   Input Parameters:
547820f4b53cSBarry Smith + dm    - The `DM`
547920f4b53cSBarry Smith - label - The `DMLabel` defining the mesh region, or `NULL` for the entire mesh
5480e5e52638SMatthew G. Knepley 
5481b3cf3223SMatthew G. Knepley   Output Parameters:
548220f4b53cSBarry Smith + fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL`
548320f4b53cSBarry Smith - prob - The `PetscDS` defined on 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
549020f4b53cSBarry Smith   fields = `NULL` and prob = `NULL` if there is no `PetscDS` for the full domain.
549120f4b53cSBarry Smith 
5492db781477SPatrick Sanan .seealso: `DMGetRegionNumDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5493e5e52638SMatthew G. Knepley @*/
5494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds)
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   }
5509e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5510154ca461SJed Brown     if (dm->probs[s].label == label || !dm->probs[s].label) {
5511b3cf3223SMatthew G. Knepley       if (fields) *fields = dm->probs[s].fields;
5512b3cf3223SMatthew G. Knepley       if (ds) *ds = dm->probs[s].ds;
55133ba16761SJacob Faibussowitsch       if (dm->probs[s].label) PetscFunctionReturn(PETSC_SUCCESS);
5514b3cf3223SMatthew G. Knepley     }
5515e5e52638SMatthew G. Knepley   }
55163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5517e5e52638SMatthew G. Knepley }
5518e5e52638SMatthew G. Knepley 
5519e5e52638SMatthew G. Knepley /*@
5520bb7acecfSBarry Smith   DMSetRegionDS - Set the `PetscDS` for a given mesh region, defined by a `DMLabel`
5521083401c6SMatthew G. Knepley 
552220f4b53cSBarry Smith   Collective
5523083401c6SMatthew G. Knepley 
5524083401c6SMatthew G. Knepley   Input Parameters:
5525bb7acecfSBarry Smith + dm     - The `DM`
552620f4b53cSBarry Smith . label  - The `DMLabel` defining the mesh region, or `NULL` for the entire mesh
552720f4b53cSBarry Smith . fields - The IS containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL` for all fields
5528bb7acecfSBarry Smith - prob   - The `PetscDS` defined on the given region
5529083401c6SMatthew G. Knepley 
553020f4b53cSBarry Smith   Level: advanced
553120f4b53cSBarry Smith 
5532bb7acecfSBarry Smith   Note:
5533bb7acecfSBarry 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,
5534083401c6SMatthew G. Knepley   the fields argument is ignored.
5535083401c6SMatthew G. Knepley 
5536db781477SPatrick Sanan .seealso: `DMGetRegionDS()`, `DMSetRegionNumDS()`, `DMGetDS()`, `DMGetCellDS()`
5537083401c6SMatthew G. Knepley @*/
5538d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds)
5539d71ae5a4SJacob Faibussowitsch {
5540083401c6SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5541083401c6SMatthew G. Knepley 
5542083401c6SMatthew G. Knepley   PetscFunctionBegin;
5543083401c6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5544083401c6SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
5545064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 4);
5546083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5547083401c6SMatthew G. Knepley     if (dm->probs[s].label == label) {
55489566063dSJacob Faibussowitsch       PetscCall(PetscDSDestroy(&dm->probs[s].ds));
5549083401c6SMatthew G. Knepley       dm->probs[s].ds = ds;
55503ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
5551083401c6SMatthew G. Knepley     }
5552083401c6SMatthew G. Knepley   }
55539566063dSJacob Faibussowitsch   PetscCall(DMDSEnlarge_Static(dm, Nds + 1));
55549566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
55559566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fields));
55569566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ds));
5557083401c6SMatthew G. Knepley   if (!label) {
5558083401c6SMatthew G. Knepley     /* Put the NULL label at the front, so it is returned as the default */
5559083401c6SMatthew G. Knepley     for (s = Nds - 1; s >= 0; --s) dm->probs[s + 1] = dm->probs[s];
5560083401c6SMatthew G. Knepley     Nds = 0;
5561083401c6SMatthew G. Knepley   }
5562083401c6SMatthew G. Knepley   dm->probs[Nds].label  = label;
5563083401c6SMatthew G. Knepley   dm->probs[Nds].fields = fields;
5564083401c6SMatthew G. Knepley   dm->probs[Nds].ds     = ds;
55653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5566083401c6SMatthew G. Knepley }
5567083401c6SMatthew G. Knepley 
5568083401c6SMatthew G. Knepley /*@
556920f4b53cSBarry Smith   DMGetRegionNumDS - Get the `PetscDS` for a given mesh region, defined by the region number
5570e5e52638SMatthew G. Knepley 
557120f4b53cSBarry Smith   Not Collective
5572e5e52638SMatthew G. Knepley 
5573e5e52638SMatthew G. Knepley   Input Parameters:
557420f4b53cSBarry Smith + dm  - The `DM`
5575e5e52638SMatthew G. Knepley - num - The region number, in [0, Nds)
5576e5e52638SMatthew G. Knepley 
5577e5e52638SMatthew G. Knepley   Output Parameters:
557820f4b53cSBarry Smith + label  - The region label, or `NULL`
557920f4b53cSBarry Smith . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL`
558020f4b53cSBarry Smith - ds     - The `PetscDS` defined on the given region, or `NULL`
5581e5e52638SMatthew G. Knepley 
5582e5e52638SMatthew G. Knepley   Level: advanced
5583e5e52638SMatthew G. Knepley 
5584db781477SPatrick Sanan .seealso: `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5585e5e52638SMatthew G. Knepley @*/
5586d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds)
5587d71ae5a4SJacob Faibussowitsch {
5588e5e52638SMatthew G. Knepley   PetscInt Nds;
5589e5e52638SMatthew G. Knepley 
5590e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5591e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
55929566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
559363a3b9bcSJacob 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);
5594e5e52638SMatthew G. Knepley   if (label) {
5595e5e52638SMatthew G. Knepley     PetscValidPointer(label, 3);
5596e5e52638SMatthew G. Knepley     *label = dm->probs[num].label;
5597e5e52638SMatthew G. Knepley   }
5598b3cf3223SMatthew G. Knepley   if (fields) {
5599b3cf3223SMatthew G. Knepley     PetscValidPointer(fields, 4);
5600b3cf3223SMatthew G. Knepley     *fields = dm->probs[num].fields;
5601b3cf3223SMatthew G. Knepley   }
5602e5e52638SMatthew G. Knepley   if (ds) {
5603b3cf3223SMatthew G. Knepley     PetscValidPointer(ds, 5);
5604e5e52638SMatthew G. Knepley     *ds = dm->probs[num].ds;
5605e5e52638SMatthew G. Knepley   }
56063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5607e5e52638SMatthew G. Knepley }
5608e5e52638SMatthew G. Knepley 
5609e5e52638SMatthew G. Knepley /*@
561020f4b53cSBarry Smith   DMSetRegionNumDS - Set the `PetscDS` for a given mesh region, defined by the region number
5611e5e52638SMatthew G. Knepley 
561220f4b53cSBarry Smith   Not Collective
5613e5e52638SMatthew G. Knepley 
5614e5e52638SMatthew G. Knepley   Input Parameters:
561520f4b53cSBarry Smith + dm     - The `DM`
5616083401c6SMatthew G. Knepley . num    - The region number, in [0, Nds)
561720f4b53cSBarry Smith . label  - The region label, or `NULL`
561820f4b53cSBarry Smith . fields - The `IS` containing the `DM` field numbers for the fields in this DS, or `NULL` to prevent setting
561920f4b53cSBarry Smith - ds     - The `PetscDS` defined on the given region, or `NULL` to prevent setting
5620e5e52638SMatthew G. Knepley 
5621e5e52638SMatthew G. Knepley   Level: advanced
5622e5e52638SMatthew G. Knepley 
5623db781477SPatrick Sanan .seealso: `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5624e5e52638SMatthew G. Knepley @*/
5625d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds)
5626d71ae5a4SJacob Faibussowitsch {
5627083401c6SMatthew G. Knepley   PetscInt Nds;
5628e5e52638SMatthew G. Knepley 
5629e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5630e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5631ad540459SPierre Jolivet   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
56329566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
563363a3b9bcSJacob 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);
56349566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
56359566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->probs[num].label));
5636083401c6SMatthew G. Knepley   dm->probs[num].label = label;
5637083401c6SMatthew G. Knepley   if (fields) {
5638083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(fields, IS_CLASSID, 4);
56399566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)fields));
56409566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[num].fields));
5641083401c6SMatthew G. Knepley     dm->probs[num].fields = fields;
5642e5e52638SMatthew G. Knepley   }
5643083401c6SMatthew G. Knepley   if (ds) {
5644083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 5);
56459566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ds));
56469566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[num].ds));
5647083401c6SMatthew G. Knepley     dm->probs[num].ds = ds;
5648083401c6SMatthew G. Knepley   }
56493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5650e5e52638SMatthew G. Knepley }
5651e5e52638SMatthew G. Knepley 
5652e5e52638SMatthew G. Knepley /*@
565320f4b53cSBarry Smith   DMFindRegionNum - Find the region number for a given `PetscDS`, or -1 if it is not found.
56541d3af9e0SMatthew G. Knepley 
565520f4b53cSBarry Smith   Not Collective
56561d3af9e0SMatthew G. Knepley 
56571d3af9e0SMatthew G. Knepley   Input Parameters:
565820f4b53cSBarry Smith + dm  - The `DM`
565920f4b53cSBarry Smith - ds  - The `PetscDS` defined on the given region
56601d3af9e0SMatthew G. Knepley 
56611d3af9e0SMatthew G. Knepley   Output Parameter:
56621d3af9e0SMatthew G. Knepley . num - The region number, in [0, Nds), or -1 if not found
56631d3af9e0SMatthew G. Knepley 
56641d3af9e0SMatthew G. Knepley   Level: advanced
56651d3af9e0SMatthew G. Knepley 
5666db781477SPatrick Sanan .seealso: `DMGetRegionNumDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
56671d3af9e0SMatthew G. Knepley @*/
5668d71ae5a4SJacob Faibussowitsch PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num)
5669d71ae5a4SJacob Faibussowitsch {
56701d3af9e0SMatthew G. Knepley   PetscInt Nds, n;
56711d3af9e0SMatthew G. Knepley 
56721d3af9e0SMatthew G. Knepley   PetscFunctionBegin;
56731d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56741d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 2);
5675dadcf809SJacob Faibussowitsch   PetscValidIntPointer(num, 3);
56769566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
56779371c9d4SSatish Balay   for (n = 0; n < Nds; ++n)
56789371c9d4SSatish Balay     if (ds == dm->probs[n].ds) break;
56791d3af9e0SMatthew G. Knepley   if (n >= Nds) *num = -1;
56801d3af9e0SMatthew G. Knepley   else *num = n;
56813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56821d3af9e0SMatthew G. Knepley }
56831d3af9e0SMatthew G. Knepley 
56842df84da0SMatthew G. Knepley /*@C
5685bb7acecfSBarry Smith   DMCreateFEDefault - Create a `PetscFE` based on the celltype for the mesh
56862df84da0SMatthew G. Knepley 
568720f4b53cSBarry Smith   Not Collective
56882df84da0SMatthew G. Knepley 
5689f1a722f8SMatthew G. Knepley   Input Parameters:
5690bb7acecfSBarry Smith + dm     - The `DM`
56912df84da0SMatthew G. Knepley . Nc     - The number of components for the field
569220f4b53cSBarry Smith . prefix - The options prefix for the output `PetscFE`, or `NULL`
5693bb7acecfSBarry Smith - qorder - The quadrature order or `PETSC_DETERMINE` to use `PetscSpace` polynomial degree
56942df84da0SMatthew G. Knepley 
56952df84da0SMatthew G. Knepley   Output Parameter:
5696bb7acecfSBarry Smith . fem - The `PetscFE`
56972df84da0SMatthew G. Knepley 
569820f4b53cSBarry Smith   Level: intermediate
569920f4b53cSBarry Smith 
5700bb7acecfSBarry Smith   Note:
5701bb7acecfSBarry Smith   This is a convenience method that just calls `PetscFECreateByCell()` underneath.
57022df84da0SMatthew G. Knepley 
5703db781477SPatrick Sanan .seealso: `PetscFECreateByCell()`, `DMAddField()`, `DMCreateDS()`, `DMGetCellDS()`, `DMGetRegionDS()`
57042df84da0SMatthew G. Knepley @*/
5705d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFEDefault(DM dm, PetscInt Nc, const char prefix[], PetscInt qorder, PetscFE *fem)
5706d71ae5a4SJacob Faibussowitsch {
57072df84da0SMatthew G. Knepley   DMPolytopeType ct;
57082df84da0SMatthew G. Knepley   PetscInt       dim, cStart;
57092df84da0SMatthew G. Knepley 
57102df84da0SMatthew G. Knepley   PetscFunctionBegin;
57112df84da0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57122df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 2);
57132df84da0SMatthew G. Knepley   if (prefix) PetscValidCharPointer(prefix, 3);
57142df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, qorder, 4);
57152df84da0SMatthew G. Knepley   PetscValidPointer(fem, 5);
57169566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
57179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
57189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
57199566063dSJacob Faibussowitsch   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, Nc, ct, prefix, qorder, fem));
57203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57212df84da0SMatthew G. Knepley }
57222df84da0SMatthew G. Knepley 
57231d3af9e0SMatthew G. Knepley /*@
5724bb7acecfSBarry Smith   DMCreateDS - Create the discrete systems for the `DM` based upon the fields added to the `DM`
5725e5e52638SMatthew G. Knepley 
572620f4b53cSBarry Smith   Collective
5727e5e52638SMatthew G. Knepley 
5728e5e52638SMatthew G. Knepley   Input Parameter:
5729bb7acecfSBarry Smith . dm - The `DM`
5730e5e52638SMatthew G. Knepley 
573120f4b53cSBarry Smith   Options Database Key:
5732bb7acecfSBarry Smith . -dm_petscds_view - View all the `PetscDS` objects in this `DM`
573345480ffeSMatthew G. Knepley 
573420f4b53cSBarry Smith   Level: intermediate
573520f4b53cSBarry Smith 
5736bb7acecfSBarry Smith   Note:
5737bb7acecfSBarry Smith   If the label has a `PetscDS` defined, it will be replaced. Otherwise, it will be added to the `DM`.
5738e5e52638SMatthew G. Knepley 
5739db781477SPatrick Sanan .seealso: `DMSetField`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
5740e5e52638SMatthew G. Knepley @*/
5741d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDS(DM dm)
5742d71ae5a4SJacob Faibussowitsch {
5743e5e52638SMatthew G. Knepley   MPI_Comm  comm;
5744083401c6SMatthew G. Knepley   PetscDS   dsDef;
5745083401c6SMatthew G. Knepley   DMLabel  *labelSet;
5746f9244615SMatthew G. Knepley   PetscInt  dE, Nf = dm->Nf, f, s, Nl, l, Ndef, k;
5747f9244615SMatthew G. Knepley   PetscBool doSetup = PETSC_TRUE, flg;
5748e5e52638SMatthew G. Knepley 
5749e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5750e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57513ba16761SJacob Faibussowitsch   if (!dm->fields) PetscFunctionReturn(PETSC_SUCCESS);
57529566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
57539566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
5754083401c6SMatthew G. Knepley   /* Determine how many regions we have */
57559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(Nf, &labelSet));
5756083401c6SMatthew G. Knepley   Nl   = 0;
5757083401c6SMatthew G. Knepley   Ndef = 0;
5758083401c6SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5759083401c6SMatthew G. Knepley     DMLabel  label = dm->fields[f].label;
5760083401c6SMatthew G. Knepley     PetscInt l;
5761083401c6SMatthew G. Knepley 
5762f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
5763f918ec44SMatthew G. Knepley     /* Move CEED context to discretizations */
5764f918ec44SMatthew G. Knepley     {
5765f918ec44SMatthew G. Knepley       PetscClassId id;
5766f918ec44SMatthew G. Knepley 
57679566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(dm->fields[f].disc, &id));
5768f918ec44SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
5769f918ec44SMatthew G. Knepley         Ceed ceed;
5770f918ec44SMatthew G. Knepley 
57719566063dSJacob Faibussowitsch         PetscCall(DMGetCeed(dm, &ceed));
57729566063dSJacob Faibussowitsch         PetscCall(PetscFESetCeed((PetscFE)dm->fields[f].disc, ceed));
5773f918ec44SMatthew G. Knepley       }
5774f918ec44SMatthew G. Knepley     }
5775f918ec44SMatthew G. Knepley #endif
57769371c9d4SSatish Balay     if (!label) {
57779371c9d4SSatish Balay       ++Ndef;
57789371c9d4SSatish Balay       continue;
57799371c9d4SSatish Balay     }
57809371c9d4SSatish Balay     for (l = 0; l < Nl; ++l)
57819371c9d4SSatish Balay       if (label == labelSet[l]) break;
5782083401c6SMatthew G. Knepley     if (l < Nl) continue;
5783083401c6SMatthew G. Knepley     labelSet[Nl++] = label;
5784083401c6SMatthew G. Knepley   }
5785083401c6SMatthew G. Knepley   /* Create default DS if there are no labels to intersect with */
57869566063dSJacob Faibussowitsch   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef));
5787083401c6SMatthew G. Knepley   if (!dsDef && Ndef && !Nl) {
5788b3cf3223SMatthew G. Knepley     IS        fields;
5789b3cf3223SMatthew G. Knepley     PetscInt *fld, nf;
5790b3cf3223SMatthew G. Knepley 
57919371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
57929371c9d4SSatish Balay       if (!dm->fields[f].label) ++nf;
57937a8be351SBarry Smith     PetscCheck(nf, comm, PETSC_ERR_PLIB, "All fields have labels, but we are trying to create a default DS");
57949566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
57959371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
57969371c9d4SSatish Balay       if (!dm->fields[f].label) fld[nf++] = f;
57979566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
57989566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
57999566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
58009566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
580188f0c812SMatthew G. Knepley 
58029566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
58039566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, NULL, fields, dsDef));
58049566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
58059566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fields));
58062df9ee95SMatthew G. Knepley   }
58079566063dSJacob Faibussowitsch   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef));
58089566063dSJacob Faibussowitsch   if (dsDef) PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
5809083401c6SMatthew G. Knepley   /* Intersect labels with default fields */
5810083401c6SMatthew G. Knepley   if (Ndef && Nl) {
58110122748bSMatthew G. Knepley     DM              plex;
5812083401c6SMatthew G. Knepley     DMLabel         cellLabel;
5813083401c6SMatthew G. Knepley     IS              fieldIS, allcellIS, defcellIS = NULL;
5814083401c6SMatthew G. Knepley     PetscInt       *fields;
5815083401c6SMatthew G. Knepley     const PetscInt *cells;
5816083401c6SMatthew G. Knepley     PetscInt        depth, nf = 0, n, c;
58170122748bSMatthew G. Knepley 
58189566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
58199566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(plex, &depth));
58209566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(plex, "dim", depth, &allcellIS));
58219566063dSJacob Faibussowitsch     if (!allcellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, &allcellIS));
58225fedec97SMatthew G. Knepley     /* TODO This looks like it only works for one label */
5823083401c6SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
5824083401c6SMatthew G. Knepley       DMLabel label = labelSet[l];
5825083401c6SMatthew G. Knepley       IS      pointIS;
5826083401c6SMatthew G. Knepley 
58279566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&defcellIS));
58289566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(label, 1, &pointIS));
58299566063dSJacob Faibussowitsch       PetscCall(ISDifference(allcellIS, pointIS, &defcellIS));
58309566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pointIS));
5831083401c6SMatthew G. Knepley     }
58329566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&allcellIS));
5833083401c6SMatthew G. Knepley 
58349566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel));
58359566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(defcellIS, &n));
58369566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(defcellIS, &cells));
58379566063dSJacob Faibussowitsch     for (c = 0; c < n; ++c) PetscCall(DMLabelSetValue(cellLabel, cells[c], 1));
58389566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(defcellIS, &cells));
58399566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&defcellIS));
58409566063dSJacob Faibussowitsch     PetscCall(DMPlexLabelComplete(plex, cellLabel));
5841083401c6SMatthew G. Knepley 
58429566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Ndef, &fields));
58439371c9d4SSatish Balay     for (f = 0; f < Nf; ++f)
58449371c9d4SSatish Balay       if (!dm->fields[f].label) fields[nf++] = f;
58459566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fieldIS));
58469566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fieldIS, "dm_fields_"));
58479566063dSJacob Faibussowitsch     PetscCall(ISSetType(fieldIS, ISGENERAL));
58489566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER));
5849083401c6SMatthew G. Knepley 
58509566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
58519566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, cellLabel, fieldIS, dsDef));
58529566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
58539566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&cellLabel));
58549566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
58559566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fieldIS));
58569566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5857083401c6SMatthew G. Knepley   }
5858083401c6SMatthew G. Knepley   /* Create label DSes
5859083401c6SMatthew G. Knepley      - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS
5860083401c6SMatthew G. Knepley   */
5861083401c6SMatthew G. Knepley   /* TODO Should check that labels are disjoint */
5862083401c6SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
5863083401c6SMatthew G. Knepley     DMLabel   label = labelSet[l];
5864083401c6SMatthew G. Knepley     PetscDS   ds;
5865083401c6SMatthew G. Knepley     IS        fields;
5866083401c6SMatthew G. Knepley     PetscInt *fld, nf;
5867083401c6SMatthew G. Knepley 
58689566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
58699371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58709371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) ++nf;
58719566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
58729371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58739371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f;
58749566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
58759566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
58769566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
58779566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
58789566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, label, fields, ds));
58799566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fields));
58809566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(ds, dE));
5881083401c6SMatthew G. Knepley     {
5882083401c6SMatthew G. Knepley       DMPolytopeType ct;
5883083401c6SMatthew G. Knepley       PetscInt       lStart, lEnd;
58845fedec97SMatthew G. Knepley       PetscBool      isCohesiveLocal = PETSC_FALSE, isCohesive;
58850122748bSMatthew G. Knepley 
58869566063dSJacob Faibussowitsch       PetscCall(DMLabelGetBounds(label, &lStart, &lEnd));
5887665f567fSMatthew G. Knepley       if (lStart >= 0) {
58889566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, lStart, &ct));
5889412e9a14SMatthew G. Knepley         switch (ct) {
5890412e9a14SMatthew G. Knepley         case DM_POLYTOPE_POINT_PRISM_TENSOR:
5891412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
5892412e9a14SMatthew G. Knepley         case DM_POLYTOPE_TRI_PRISM_TENSOR:
5893d71ae5a4SJacob Faibussowitsch         case DM_POLYTOPE_QUAD_PRISM_TENSOR:
5894d71ae5a4SJacob Faibussowitsch           isCohesiveLocal = PETSC_TRUE;
5895d71ae5a4SJacob Faibussowitsch           break;
5896d71ae5a4SJacob Faibussowitsch         default:
5897d71ae5a4SJacob Faibussowitsch           break;
5898412e9a14SMatthew G. Knepley         }
5899665f567fSMatthew G. Knepley       }
59009566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allreduce(&isCohesiveLocal, &isCohesive, 1, MPIU_BOOL, MPI_LOR, comm));
59015fedec97SMatthew G. Knepley       for (f = 0, nf = 0; f < Nf; ++f) {
59025fedec97SMatthew G. Knepley         if (label == dm->fields[f].label || !dm->fields[f].label) {
59035fedec97SMatthew G. Knepley           if (label == dm->fields[f].label) {
59049566063dSJacob Faibussowitsch             PetscCall(PetscDSSetDiscretization(ds, nf, NULL));
59059566063dSJacob Faibussowitsch             PetscCall(PetscDSSetCohesive(ds, nf, isCohesive));
59065fedec97SMatthew G. Knepley           }
59075fedec97SMatthew G. Knepley           ++nf;
59085fedec97SMatthew G. Knepley         }
59095fedec97SMatthew G. Knepley       }
5910e5e52638SMatthew G. Knepley     }
59119566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&ds));
5912e5e52638SMatthew G. Knepley   }
59139566063dSJacob Faibussowitsch   PetscCall(PetscFree(labelSet));
5914e5e52638SMatthew G. Knepley   /* Set fields in DSes */
5915083401c6SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5916083401c6SMatthew G. Knepley     PetscDS         ds     = dm->probs[s].ds;
5917083401c6SMatthew G. Knepley     IS              fields = dm->probs[s].fields;
5918083401c6SMatthew G. Knepley     const PetscInt *fld;
59195fedec97SMatthew G. Knepley     PetscInt        nf, dsnf;
59205fedec97SMatthew G. Knepley     PetscBool       isCohesive;
5921e5e52638SMatthew G. Knepley 
59229566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsnf));
59239566063dSJacob Faibussowitsch     PetscCall(PetscDSIsCohesive(ds, &isCohesive));
59249566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(fields, &nf));
59259566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fields, &fld));
5926083401c6SMatthew G. Knepley     for (f = 0; f < nf; ++f) {
5927083401c6SMatthew G. Knepley       PetscObject  disc = dm->fields[fld[f]].disc;
59285fedec97SMatthew G. Knepley       PetscBool    isCohesiveField;
5929e5e52638SMatthew G. Knepley       PetscClassId id;
5930e5e52638SMatthew G. Knepley 
59315fedec97SMatthew G. Knepley       /* Handle DS with no fields */
59329566063dSJacob Faibussowitsch       if (dsnf) PetscCall(PetscDSGetCohesive(ds, f, &isCohesiveField));
59335fedec97SMatthew G. Knepley       /* If this is a cohesive cell, then regular fields need the lower dimensional discretization */
59349566063dSJacob Faibussowitsch       if (isCohesive && !isCohesiveField) PetscCall(PetscFEGetHeightSubspace((PetscFE)disc, 1, (PetscFE *)&disc));
59359566063dSJacob Faibussowitsch       PetscCall(PetscDSSetDiscretization(ds, f, disc));
5936083401c6SMatthew G. Knepley       /* We allow people to have placeholder fields and construct the Section by hand */
59379566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(disc, &id));
5938e5e52638SMatthew G. Knepley       if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE;
5939e5e52638SMatthew G. Knepley     }
59409566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fields, &fld));
5941e5e52638SMatthew G. Knepley   }
5942f9244615SMatthew G. Knepley   /* Allow k-jet tabulation */
59439566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)dm)->prefix, "-dm_ds_jet_degree", &k, &flg));
5944f9244615SMatthew G. Knepley   if (flg) {
59453b4aee56SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
59463b4aee56SMatthew G. Knepley       PetscDS  ds = dm->probs[s].ds;
59473b4aee56SMatthew G. Knepley       PetscInt Nf, f;
59483b4aee56SMatthew G. Knepley 
59499566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(ds, &Nf));
59509566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSSetJetDegree(ds, f, k));
59513b4aee56SMatthew G. Knepley     }
5952f9244615SMatthew G. Knepley   }
5953e5e52638SMatthew G. Knepley   /* Setup DSes */
5954e5e52638SMatthew G. Knepley   if (doSetup) {
59559566063dSJacob Faibussowitsch     for (s = 0; s < dm->Nds; ++s) PetscCall(PetscDSSetUp(dm->probs[s].ds));
5956e5e52638SMatthew G. Knepley   }
59573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5958e5e52638SMatthew G. Knepley }
5959e5e52638SMatthew G. Knepley 
5960e5e52638SMatthew G. Knepley /*@
5961bb7acecfSBarry Smith   DMComputeExactSolution - Compute the exact solution for a given `DM`, using the `PetscDS` information.
59627f96f943SMatthew G. Knepley 
596320f4b53cSBarry Smith   Collective
5964f2cacb80SMatthew G. Knepley 
59657f96f943SMatthew G. Knepley   Input Parameters:
5966bb7acecfSBarry Smith + dm   - The `DM`
59677f96f943SMatthew G. Knepley - time - The time
59687f96f943SMatthew G. Knepley 
59697f96f943SMatthew G. Knepley   Output Parameters:
597020f4b53cSBarry Smith + u    - The vector will be filled with exact solution values, or `NULL`
597120f4b53cSBarry Smith - u_t  - The vector will be filled with the time derivative of exact solution values, or `NULL`
597220f4b53cSBarry Smith 
597320f4b53cSBarry Smith   Level: developer
59747f96f943SMatthew G. Knepley 
5975bb7acecfSBarry Smith   Note:
5976bb7acecfSBarry Smith   The user must call `PetscDSSetExactSolution()` before using this routine
59777f96f943SMatthew G. Knepley 
5978db781477SPatrick Sanan .seealso: `PetscDSSetExactSolution()`
59797f96f943SMatthew G. Knepley @*/
5980d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t)
5981d71ae5a4SJacob Faibussowitsch {
59827f96f943SMatthew G. Knepley   PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
59837f96f943SMatthew G. Knepley   void   **ectxs;
5984f60fa741SMatthew G. Knepley   Vec      locu, locu_t;
59857f96f943SMatthew G. Knepley   PetscInt Nf, Nds, s;
59867f96f943SMatthew G. Knepley 
59877f96f943SMatthew G. Knepley   PetscFunctionBegin;
5988f2cacb80SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5989f60fa741SMatthew G. Knepley   if (u) {
5990f60fa741SMatthew G. Knepley     PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
5991f60fa741SMatthew G. Knepley     PetscCall(DMGetLocalVector(dm, &locu));
5992f60fa741SMatthew G. Knepley     PetscCall(VecSet(locu, 0.));
5993f60fa741SMatthew G. Knepley   }
5994f60fa741SMatthew G. Knepley   if (u_t) {
5995f60fa741SMatthew G. Knepley     PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4);
5996f60fa741SMatthew G. Knepley     PetscCall(DMGetLocalVector(dm, &locu_t));
5997f60fa741SMatthew G. Knepley     PetscCall(VecSet(locu_t, 0.));
5998f60fa741SMatthew G. Knepley   }
59999566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
60009566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(Nf, &exacts, Nf, &ectxs));
60019566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
60027f96f943SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
60037f96f943SMatthew G. Knepley     PetscDS         ds;
60047f96f943SMatthew G. Knepley     DMLabel         label;
60057f96f943SMatthew G. Knepley     IS              fieldIS;
60067f96f943SMatthew G. Knepley     const PetscInt *fields, id = 1;
60077f96f943SMatthew G. Knepley     PetscInt        dsNf, f;
60087f96f943SMatthew G. Knepley 
60099566063dSJacob Faibussowitsch     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds));
60109566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
60119566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fieldIS, &fields));
60129566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(exacts, Nf));
60139566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(ectxs, Nf));
6014f2cacb80SMatthew G. Knepley     if (u) {
6015f60fa741SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) PetscCall(PetscDSGetExactSolution(ds, fields[f], &exacts[fields[f]], &ectxs[fields[f]]));
6016f60fa741SMatthew G. Knepley       if (label) PetscCall(DMProjectFunctionLabelLocal(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, locu));
6017f60fa741SMatthew G. Knepley       else PetscCall(DMProjectFunctionLocal(dm, time, exacts, ectxs, INSERT_ALL_VALUES, locu));
60187f96f943SMatthew G. Knepley     }
6019f2cacb80SMatthew G. Knepley     if (u_t) {
60209566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(exacts, Nf));
60219566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ectxs, Nf));
6022f60fa741SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, fields[f], &exacts[fields[f]], &ectxs[fields[f]]));
6023f60fa741SMatthew G. Knepley       if (label) PetscCall(DMProjectFunctionLabelLocal(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, locu_t));
6024f60fa741SMatthew G. Knepley       else PetscCall(DMProjectFunctionLocal(dm, time, exacts, ectxs, INSERT_ALL_VALUES, locu_t));
6025f2cacb80SMatthew G. Knepley     }
60269566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fieldIS, &fields));
6027f2cacb80SMatthew G. Knepley   }
6028f2cacb80SMatthew G. Knepley   if (u) {
60299566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution"));
60309566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u, "exact_"));
6031f2cacb80SMatthew G. Knepley   }
6032f2cacb80SMatthew G. Knepley   if (u_t) {
60339566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution Time Derivative"));
60349566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u_t, "exact_t_"));
6035f2cacb80SMatthew G. Knepley   }
60369566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exacts, ectxs));
6037f60fa741SMatthew G. Knepley   if (u) {
6038f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(dm, locu, INSERT_ALL_VALUES, u));
6039f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(dm, locu, INSERT_ALL_VALUES, u));
6040f60fa741SMatthew G. Knepley     PetscCall(DMRestoreLocalVector(dm, &locu));
6041f60fa741SMatthew G. Knepley   }
6042f60fa741SMatthew G. Knepley   if (u_t) {
6043f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(dm, locu_t, INSERT_ALL_VALUES, u_t));
6044f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(dm, locu_t, INSERT_ALL_VALUES, u_t));
6045f60fa741SMatthew G. Knepley     PetscCall(DMRestoreLocalVector(dm, &locu_t));
6046f60fa741SMatthew G. Knepley   }
60473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60487f96f943SMatthew G. Knepley }
60497f96f943SMatthew G. Knepley 
6050d71ae5a4SJacob Faibussowitsch PetscErrorCode DMTransferDS_Internal(DM dm, DMLabel label, IS fields, PetscDS ds)
6051d71ae5a4SJacob Faibussowitsch {
605245480ffeSMatthew G. Knepley   PetscDS    dsNew;
605345480ffeSMatthew G. Knepley   DSBoundary b;
60546a02485aSMatthew G. Knepley   PetscInt   cdim, Nf, f, d;
60555fedec97SMatthew G. Knepley   PetscBool  isCohesive;
605645480ffeSMatthew G. Knepley   void      *ctx;
605745480ffeSMatthew G. Knepley 
605845480ffeSMatthew G. Knepley   PetscFunctionBegin;
60599566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)ds), &dsNew));
60609566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyConstants(ds, dsNew));
60619566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyExactSolutions(ds, dsNew));
60629566063dSJacob Faibussowitsch   PetscCall(PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, dsNew));
60639566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyEquations(ds, dsNew));
60649566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
606545480ffeSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
60669566063dSJacob Faibussowitsch     PetscCall(PetscDSGetContext(ds, f, &ctx));
60679566063dSJacob Faibussowitsch     PetscCall(PetscDSSetContext(dsNew, f, ctx));
60689566063dSJacob Faibussowitsch     PetscCall(PetscDSGetCohesive(ds, f, &isCohesive));
60699566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCohesive(dsNew, f, isCohesive));
60706a02485aSMatthew G. Knepley     PetscCall(PetscDSGetJetDegree(ds, f, &d));
60716a02485aSMatthew G. Knepley     PetscCall(PetscDSSetJetDegree(dsNew, f, d));
607245480ffeSMatthew G. Knepley   }
607345480ffeSMatthew G. Knepley   if (Nf) {
60749566063dSJacob Faibussowitsch     PetscCall(PetscDSGetCoordinateDimension(ds, &cdim));
60759566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(dsNew, cdim));
607645480ffeSMatthew G. Knepley   }
60779566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew));
607845480ffeSMatthew G. Knepley   for (b = dsNew->boundary; b; b = b->next) {
60799566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, b->lname, &b->label));
608045480ffeSMatthew G. Knepley     /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */
60817a8be351SBarry Smith     //PetscCheck(b->label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name);
608245480ffeSMatthew G. Knepley   }
608345480ffeSMatthew G. Knepley 
60849566063dSJacob Faibussowitsch   PetscCall(DMSetRegionDS(dm, label, fields, dsNew));
60859566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&dsNew));
60863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
608745480ffeSMatthew G. Knepley }
608845480ffeSMatthew G. Knepley 
60897f96f943SMatthew G. Knepley /*@
6090bb7acecfSBarry Smith   DMCopyDS - Copy the discrete systems for the `DM` into another `DM`
6091e5e52638SMatthew G. Knepley 
609220f4b53cSBarry Smith   Collective
6093e5e52638SMatthew G. Knepley 
6094e5e52638SMatthew G. Knepley   Input Parameter:
6095bb7acecfSBarry Smith . dm - The `DM`
6096e5e52638SMatthew G. Knepley 
6097e5e52638SMatthew G. Knepley   Output Parameter:
6098bb7acecfSBarry Smith . newdm - The `DM`
6099e5e52638SMatthew G. Knepley 
6100e5e52638SMatthew G. Knepley   Level: advanced
6101e5e52638SMatthew G. Knepley 
6102db781477SPatrick Sanan .seealso: `DMCopyFields()`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
6103e5e52638SMatthew G. Knepley @*/
6104d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDS(DM dm, DM newdm)
6105d71ae5a4SJacob Faibussowitsch {
6106e5e52638SMatthew G. Knepley   PetscInt Nds, s;
6107e5e52638SMatthew G. Knepley 
6108e5e52638SMatthew G. Knepley   PetscFunctionBegin;
61093ba16761SJacob Faibussowitsch   if (dm == newdm) PetscFunctionReturn(PETSC_SUCCESS);
61109566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
61119566063dSJacob Faibussowitsch   PetscCall(DMClearDS(newdm));
6112e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
6113e5e52638SMatthew G. Knepley     DMLabel  label;
6114b3cf3223SMatthew G. Knepley     IS       fields;
611545480ffeSMatthew G. Knepley     PetscDS  ds, newds;
6116783e2ec8SMatthew G. Knepley     PetscInt Nbd, bd;
6117e5e52638SMatthew G. Knepley 
61189566063dSJacob Faibussowitsch     PetscCall(DMGetRegionNumDS(dm, s, &label, &fields, &ds));
6119b8025e53SMatthew G. Knepley     /* TODO: We need to change all keys from labels in the old DM to labels in the new DM */
61209566063dSJacob Faibussowitsch     PetscCall(DMTransferDS_Internal(newdm, label, fields, ds));
6121d5b43468SJose E. Roman     /* Complete new labels in the new DS */
61229566063dSJacob Faibussowitsch     PetscCall(DMGetRegionDS(newdm, label, NULL, &newds));
61239566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumBoundary(newds, &Nbd));
6124783e2ec8SMatthew G. Knepley     for (bd = 0; bd < Nbd; ++bd) {
6125b8025e53SMatthew G. Knepley       PetscWeakForm wf;
612645480ffeSMatthew G. Knepley       DMLabel       label;
6127783e2ec8SMatthew G. Knepley       PetscInt      field;
6128783e2ec8SMatthew G. Knepley 
61299566063dSJacob Faibussowitsch       PetscCall(PetscDSGetBoundary(newds, bd, &wf, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
61309566063dSJacob Faibussowitsch       PetscCall(PetscWeakFormReplaceLabel(wf, label));
6131783e2ec8SMatthew G. Knepley     }
6132e5e52638SMatthew G. Knepley   }
6133799db056SMatthew G. Knepley   PetscCall(DMCompleteBCLabels_Internal(newdm));
61343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6135e5e52638SMatthew G. Knepley }
6136e5e52638SMatthew G. Knepley 
6137e5e52638SMatthew G. Knepley /*@
6138bb7acecfSBarry Smith   DMCopyDisc - Copy the fields and discrete systems for the `DM` into another `DM`
6139e5e52638SMatthew G. Knepley 
614020f4b53cSBarry Smith   Collective
6141e5e52638SMatthew G. Knepley 
6142e5e52638SMatthew G. Knepley   Input Parameter:
6143bb7acecfSBarry Smith . dm - The `DM`
6144e5e52638SMatthew G. Knepley 
6145e5e52638SMatthew G. Knepley   Output Parameter:
6146bb7acecfSBarry Smith . newdm - The `DM`
6147e5e52638SMatthew G. Knepley 
6148e5e52638SMatthew G. Knepley   Level: advanced
6149e5e52638SMatthew G. Knepley 
6150bb7acecfSBarry Smith   Developer Note:
6151bb7acecfSBarry Smith   Really ugly name, nothing in PETSc is called a `Disc` plus it is an ugly abbreviation
6152bb7acecfSBarry Smith 
6153db781477SPatrick Sanan .seealso: `DMCopyFields()`, `DMCopyDS()`
6154e5e52638SMatthew G. Knepley @*/
6155d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDisc(DM dm, DM newdm)
6156d71ae5a4SJacob Faibussowitsch {
6157e5e52638SMatthew G. Knepley   PetscFunctionBegin;
61589566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, newdm));
61599566063dSJacob Faibussowitsch   PetscCall(DMCopyDS(dm, newdm));
61603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6161e5e52638SMatthew G. Knepley }
6162e5e52638SMatthew G. Knepley 
6163c73cfb54SMatthew G. Knepley /*@
6164bb7acecfSBarry Smith   DMGetDimension - Return the topological dimension of the `DM`
6165c73cfb54SMatthew G. Knepley 
616620f4b53cSBarry Smith   Not Collective
6167c73cfb54SMatthew G. Knepley 
6168c73cfb54SMatthew G. Knepley   Input Parameter:
6169bb7acecfSBarry Smith . dm - The `DM`
6170c73cfb54SMatthew G. Knepley 
6171c73cfb54SMatthew G. Knepley   Output Parameter:
6172c73cfb54SMatthew G. Knepley . dim - The topological dimension
6173c73cfb54SMatthew G. Knepley 
6174c73cfb54SMatthew G. Knepley   Level: beginner
6175c73cfb54SMatthew G. Knepley 
6176db781477SPatrick Sanan .seealso: `DMSetDimension()`, `DMCreate()`
6177c73cfb54SMatthew G. Knepley @*/
6178d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
6179d71ae5a4SJacob Faibussowitsch {
6180c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6181c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6182534a8f05SLisandro Dalcin   PetscValidIntPointer(dim, 2);
6183c73cfb54SMatthew G. Knepley   *dim = dm->dim;
61843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6185c73cfb54SMatthew G. Knepley }
6186c73cfb54SMatthew G. Knepley 
6187c73cfb54SMatthew G. Knepley /*@
6188bb7acecfSBarry Smith   DMSetDimension - Set the topological dimension of the `DM`
6189c73cfb54SMatthew G. Knepley 
619020f4b53cSBarry Smith   Collective
6191c73cfb54SMatthew G. Knepley 
6192c73cfb54SMatthew G. Knepley   Input Parameters:
6193bb7acecfSBarry Smith + dm - The `DM`
6194c73cfb54SMatthew G. Knepley - dim - The topological dimension
6195c73cfb54SMatthew G. Knepley 
6196c73cfb54SMatthew G. Knepley   Level: beginner
6197c73cfb54SMatthew G. Knepley 
6198db781477SPatrick Sanan .seealso: `DMGetDimension()`, `DMCreate()`
6199c73cfb54SMatthew G. Knepley @*/
6200d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
6201d71ae5a4SJacob Faibussowitsch {
6202e5e52638SMatthew G. Knepley   PetscDS  ds;
620345480ffeSMatthew G. Knepley   PetscInt Nds, n;
6204f17e8794SMatthew G. Knepley 
6205c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6206c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6207c73cfb54SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6208c73cfb54SMatthew G. Knepley   dm->dim = dim;
6209d17bd122SMatthew G. Knepley   if (dm->dim >= 0) {
62109566063dSJacob Faibussowitsch     PetscCall(DMGetNumDS(dm, &Nds));
621145480ffeSMatthew G. Knepley     for (n = 0; n < Nds; ++n) {
62129566063dSJacob Faibussowitsch       PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds));
62139566063dSJacob Faibussowitsch       if (ds->dimEmbed < 0) PetscCall(PetscDSSetCoordinateDimension(ds, dim));
621445480ffeSMatthew G. Knepley     }
6215d17bd122SMatthew G. Knepley   }
62163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6217c73cfb54SMatthew G. Knepley }
6218c73cfb54SMatthew G. Knepley 
6219793f3fe5SMatthew G. Knepley /*@
6220793f3fe5SMatthew G. Knepley   DMGetDimPoints - Get the half-open interval for all points of a given dimension
6221793f3fe5SMatthew G. Knepley 
622220f4b53cSBarry Smith   Collective
6223793f3fe5SMatthew G. Knepley 
6224793f3fe5SMatthew G. Knepley   Input Parameters:
6225bb7acecfSBarry Smith + dm - the `DM`
6226793f3fe5SMatthew G. Knepley - dim - the dimension
6227793f3fe5SMatthew G. Knepley 
6228793f3fe5SMatthew G. Knepley   Output Parameters:
6229793f3fe5SMatthew G. Knepley + pStart - The first point of the given dimension
6230aa049354SPatrick Sanan - pEnd - The first point following points of the given dimension
6231793f3fe5SMatthew G. Knepley 
623220f4b53cSBarry Smith   Level: intermediate
623320f4b53cSBarry Smith 
6234793f3fe5SMatthew G. Knepley   Note:
6235793f3fe5SMatthew G. Knepley   The points are vertices in the Hasse diagram encoding the topology. This is explained in
6236a8d69d7bSBarry Smith   https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme,
6237793f3fe5SMatthew G. Knepley   then the interval is empty.
6238793f3fe5SMatthew G. Knepley 
6239db781477SPatrick Sanan .seealso: `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
6240793f3fe5SMatthew G. Knepley @*/
6241d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
6242d71ae5a4SJacob Faibussowitsch {
6243793f3fe5SMatthew G. Knepley   PetscInt d;
6244793f3fe5SMatthew G. Knepley 
6245793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
6246793f3fe5SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62479566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &d));
62487a8be351SBarry Smith   PetscCheck((dim >= 0) && (dim <= d), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %" PetscInt_FMT, dim);
6249dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getdimpoints, dim, pStart, pEnd);
62503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6251793f3fe5SMatthew G. Knepley }
6252793f3fe5SMatthew G. Knepley 
62536636e97aSMatthew G Knepley /*@
6254bb7acecfSBarry Smith   DMGetOutputDM - Retrieve the `DM` associated with the layout for output
6255f4d763aaSMatthew G. Knepley 
625620f4b53cSBarry Smith   Collective
62578f700142SStefano Zampini 
6258f4d763aaSMatthew G. Knepley   Input Parameter:
6259bb7acecfSBarry Smith . dm - The original `DM`
6260f4d763aaSMatthew G. Knepley 
6261f4d763aaSMatthew G. Knepley   Output Parameter:
6262bb7acecfSBarry Smith . odm - The `DM` which provides the layout for output
6263f4d763aaSMatthew G. Knepley 
6264f4d763aaSMatthew G. Knepley   Level: intermediate
6265f4d763aaSMatthew G. Knepley 
6266bb7acecfSBarry Smith   Note:
6267bb7acecfSBarry Smith   In some situations the vector obtained with `DMCreateGlobalVector()` excludes points for degrees of freedom that are associated with fixed (Dirichelet) boundary
6268bb7acecfSBarry 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
6269bb7acecfSBarry Smith   locations for those dof so that they can be output to a file or other viewer along with the unconstrained dof.
6270bb7acecfSBarry Smith 
6271bb7acecfSBarry Smith .seealso: `VecView()`, `DMGetGlobalSection()`, `DMCreateGlobalVector()`, `PetscSectionHasConstraints()`, `DMSetGlobalSection()`
6272f4d763aaSMatthew G. Knepley @*/
6273d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
6274d71ae5a4SJacob Faibussowitsch {
6275c26acbdeSMatthew G. Knepley   PetscSection section;
62762d4e4a49SMatthew G. Knepley   PetscBool    hasConstraints, ghasConstraints;
627714f150ffSMatthew G. Knepley 
627814f150ffSMatthew G. Knepley   PetscFunctionBegin;
627914f150ffSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
628014f150ffSMatthew G. Knepley   PetscValidPointer(odm, 2);
62819566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
62829566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
62839566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
62842d4e4a49SMatthew G. Knepley   if (!ghasConstraints) {
6285c26acbdeSMatthew G. Knepley     *odm = dm;
62863ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6287c26acbdeSMatthew G. Knepley   }
628814f150ffSMatthew G. Knepley   if (!dm->dmBC) {
6289c26acbdeSMatthew G. Knepley     PetscSection newSection, gsection;
629014f150ffSMatthew G. Knepley     PetscSF      sf;
629114f150ffSMatthew G. Knepley 
62929566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &dm->dmBC));
62939566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dm, dm->dmBC));
62949566063dSJacob Faibussowitsch     PetscCall(PetscSectionClone(section, &newSection));
62959566063dSJacob Faibussowitsch     PetscCall(DMSetLocalSection(dm->dmBC, newSection));
62969566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&newSection));
62979566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm->dmBC, &sf));
62989566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
62999566063dSJacob Faibussowitsch     PetscCall(DMSetGlobalSection(dm->dmBC, gsection));
63009566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&gsection));
630114f150ffSMatthew G. Knepley   }
630214f150ffSMatthew G. Knepley   *odm = dm->dmBC;
63033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
630414f150ffSMatthew G. Knepley }
6305f4d763aaSMatthew G. Knepley 
6306f4d763aaSMatthew G. Knepley /*@
6307cdb7a50dSMatthew G. Knepley   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
6308f4d763aaSMatthew G. Knepley 
6309f4d763aaSMatthew G. Knepley   Input Parameter:
6310bb7acecfSBarry Smith . dm - The original `DM`
6311f4d763aaSMatthew G. Knepley 
6312cdb7a50dSMatthew G. Knepley   Output Parameters:
6313cdb7a50dSMatthew G. Knepley + num - The output sequence number
6314cdb7a50dSMatthew G. Knepley - val - The output sequence value
6315f4d763aaSMatthew G. Knepley 
6316f4d763aaSMatthew G. Knepley   Level: intermediate
6317f4d763aaSMatthew G. Knepley 
6318bb7acecfSBarry Smith   Note:
6319bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6320bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6321bb7acecfSBarry Smith 
6322bb7acecfSBarry Smith   Developer Note:
6323bb7acecfSBarry Smith   The `DM` serves as a convenient place to store the current iteration value. The iteration is not
6324bb7acecfSBarry Smith   not directly related to the `DM`.
6325f4d763aaSMatthew G. Knepley 
6326db781477SPatrick Sanan .seealso: `VecView()`
6327f4d763aaSMatthew G. Knepley @*/
6328d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
6329d71ae5a4SJacob Faibussowitsch {
6330f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6331f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63329371c9d4SSatish Balay   if (num) {
63339371c9d4SSatish Balay     PetscValidIntPointer(num, 2);
63349371c9d4SSatish Balay     *num = dm->outputSequenceNum;
63359371c9d4SSatish Balay   }
63369371c9d4SSatish Balay   if (val) {
63379371c9d4SSatish Balay     PetscValidRealPointer(val, 3);
63389371c9d4SSatish Balay     *val = dm->outputSequenceVal;
63399371c9d4SSatish Balay   }
63403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6341f4d763aaSMatthew G. Knepley }
6342f4d763aaSMatthew G. Knepley 
6343f4d763aaSMatthew G. Knepley /*@
6344cdb7a50dSMatthew G. Knepley   DMSetOutputSequenceNumber - Set the sequence number/value for output
6345f4d763aaSMatthew G. Knepley 
6346f4d763aaSMatthew G. Knepley   Input Parameters:
6347bb7acecfSBarry Smith + dm - The original `DM`
6348cdb7a50dSMatthew G. Knepley . num - The output sequence number
6349cdb7a50dSMatthew G. Knepley - val - The output sequence value
6350f4d763aaSMatthew G. Knepley 
6351f4d763aaSMatthew G. Knepley   Level: intermediate
6352f4d763aaSMatthew G. Knepley 
6353bb7acecfSBarry Smith   Note:
6354bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6355bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6356f4d763aaSMatthew G. Knepley 
6357db781477SPatrick Sanan .seealso: `VecView()`
6358f4d763aaSMatthew G. Knepley @*/
6359d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
6360d71ae5a4SJacob Faibussowitsch {
6361f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6362f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6363f4d763aaSMatthew G. Knepley   dm->outputSequenceNum = num;
6364cdb7a50dSMatthew G. Knepley   dm->outputSequenceVal = val;
63653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6366cdb7a50dSMatthew G. Knepley }
6367cdb7a50dSMatthew G. Knepley 
6368cdb7a50dSMatthew G. Knepley /*@C
6369bb7acecfSBarry Smith  DMOutputSequenceLoad - Retrieve the sequence value from a `PetscViewer`
6370cdb7a50dSMatthew G. Knepley 
6371cdb7a50dSMatthew G. Knepley   Input Parameters:
6372bb7acecfSBarry Smith + dm   - The original `DM`
6373cdb7a50dSMatthew G. Knepley . name - The sequence name
6374cdb7a50dSMatthew G. Knepley - num  - The output sequence number
6375cdb7a50dSMatthew G. Knepley 
6376cdb7a50dSMatthew G. Knepley   Output Parameter:
6377cdb7a50dSMatthew G. Knepley . val  - The output sequence value
6378cdb7a50dSMatthew G. Knepley 
6379cdb7a50dSMatthew G. Knepley   Level: intermediate
6380cdb7a50dSMatthew 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.
6384bb7acecfSBarry Smith 
6385bb7acecfSBarry Smith   Developer Note:
6386bb7acecfSBarry Smith   It is unclear at the user API level why a `DM` is needed as input
6387cdb7a50dSMatthew G. Knepley 
6388db781477SPatrick Sanan .seealso: `DMGetOutputSequenceNumber()`, `DMSetOutputSequenceNumber()`, `VecView()`
6389cdb7a50dSMatthew G. Knepley @*/
6390d71ae5a4SJacob Faibussowitsch PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
6391d71ae5a4SJacob Faibussowitsch {
6392cdb7a50dSMatthew G. Knepley   PetscBool ishdf5;
6393cdb7a50dSMatthew G. Knepley 
6394cdb7a50dSMatthew G. Knepley   PetscFunctionBegin;
6395cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6396cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
6397064a246eSJacob Faibussowitsch   PetscValidRealPointer(val, 5);
63989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6399cdb7a50dSMatthew G. Knepley   if (ishdf5) {
6400cdb7a50dSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6401cdb7a50dSMatthew G. Knepley     PetscScalar value;
6402cdb7a50dSMatthew G. Knepley 
64039566063dSJacob Faibussowitsch     PetscCall(DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer));
64044aeb217fSMatthew G. Knepley     *val = PetscRealPart(value);
6405cdb7a50dSMatthew G. Knepley #endif
6406cdb7a50dSMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
64073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6408f4d763aaSMatthew G. Knepley }
64098e4ac7eaSMatthew G. Knepley 
64108e4ac7eaSMatthew G. Knepley /*@
6411bb7acecfSBarry Smith   DMGetUseNatural - Get the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
64128e4ac7eaSMatthew G. Knepley 
641320f4b53cSBarry Smith   Not Collective
64148e4ac7eaSMatthew G. Knepley 
64158e4ac7eaSMatthew G. Knepley   Input Parameter:
6416bb7acecfSBarry Smith . dm - The `DM`
64178e4ac7eaSMatthew G. Knepley 
64188e4ac7eaSMatthew G. Knepley   Output Parameter:
6419bb7acecfSBarry Smith . useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
64208e4ac7eaSMatthew G. Knepley 
64218e4ac7eaSMatthew G. Knepley   Level: beginner
64228e4ac7eaSMatthew G. Knepley 
6423db781477SPatrick Sanan .seealso: `DMSetUseNatural()`, `DMCreate()`
64248e4ac7eaSMatthew G. Knepley @*/
6425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
6426d71ae5a4SJacob Faibussowitsch {
64278e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
64288e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6429534a8f05SLisandro Dalcin   PetscValidBoolPointer(useNatural, 2);
64308e4ac7eaSMatthew G. Knepley   *useNatural = dm->useNatural;
64313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
64328e4ac7eaSMatthew G. Knepley }
64338e4ac7eaSMatthew G. Knepley 
64348e4ac7eaSMatthew G. Knepley /*@
6435bb7acecfSBarry Smith   DMSetUseNatural - Set the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
64368e4ac7eaSMatthew G. Knepley 
643720f4b53cSBarry Smith   Collective
64388e4ac7eaSMatthew G. Knepley 
64398e4ac7eaSMatthew G. Knepley   Input Parameters:
6440bb7acecfSBarry Smith  + dm - The `DM`
6441bb7acecfSBarry Smith - useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
64428e4ac7eaSMatthew G. Knepley 
6443bb7acecfSBarry Smith   Note:
6444bb7acecfSBarry Smith   This also causes the map to be build after `DMCreateSubDM()` and `DMCreateSuperDM()`
64455d3b26e6SMatthew G. Knepley 
64468e4ac7eaSMatthew G. Knepley   Level: beginner
64478e4ac7eaSMatthew G. Knepley 
6448db781477SPatrick Sanan .seealso: `DMGetUseNatural()`, `DMCreate()`, `DMPlexDistribute()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
64498e4ac7eaSMatthew G. Knepley @*/
6450d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
6451d71ae5a4SJacob Faibussowitsch {
64528e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
64538e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64548833efb5SBlaise Bourdin   PetscValidLogicalCollectiveBool(dm, useNatural, 2);
64558e4ac7eaSMatthew G. Knepley   dm->useNatural = useNatural;
64563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
64578e4ac7eaSMatthew G. Knepley }
6458c58f1c22SToby Isaac 
6459c58f1c22SToby Isaac /*@C
6460bb7acecfSBarry Smith   DMCreateLabel - Create a label of the given name if it does not already exist in the `DM`
6461c58f1c22SToby Isaac 
6462c58f1c22SToby Isaac   Not Collective
6463c58f1c22SToby Isaac 
6464c58f1c22SToby Isaac   Input Parameters:
6465bb7acecfSBarry Smith + dm   - The `DM` object
6466c58f1c22SToby Isaac - name - The label name
6467c58f1c22SToby Isaac 
6468c58f1c22SToby Isaac   Level: intermediate
6469c58f1c22SToby Isaac 
6470db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6471c58f1c22SToby Isaac @*/
6472d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabel(DM dm, const char name[])
6473d71ae5a4SJacob Faibussowitsch {
64745d80c0bfSVaclav Hapla   PetscBool flg;
64755d80c0bfSVaclav Hapla   DMLabel   label;
6476c58f1c22SToby Isaac 
6477c58f1c22SToby Isaac   PetscFunctionBegin;
6478c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6479c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
64809566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
6481c58f1c22SToby Isaac   if (!flg) {
64829566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
64839566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
64849566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
6485c58f1c22SToby Isaac   }
64863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6487c58f1c22SToby Isaac }
6488c58f1c22SToby Isaac 
6489c58f1c22SToby Isaac /*@C
6490bb7acecfSBarry 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.
64910fdc7489SMatthew Knepley 
64920fdc7489SMatthew Knepley   Not Collective
64930fdc7489SMatthew Knepley 
64940fdc7489SMatthew Knepley   Input Parameters:
6495bb7acecfSBarry Smith + dm   - The `DM` object
64960fdc7489SMatthew Knepley . l    - The index for the label
64970fdc7489SMatthew Knepley - name - The label name
64980fdc7489SMatthew Knepley 
64990fdc7489SMatthew Knepley   Level: intermediate
65000fdc7489SMatthew Knepley 
6501db781477SPatrick Sanan .seealso: `DMCreateLabel()`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
65020fdc7489SMatthew Knepley @*/
6503d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[])
6504d71ae5a4SJacob Faibussowitsch {
65050fdc7489SMatthew Knepley   DMLabelLink orig, prev = NULL;
65060fdc7489SMatthew Knepley   DMLabel     label;
65070fdc7489SMatthew Knepley   PetscInt    Nl, m;
65080fdc7489SMatthew Knepley   PetscBool   flg, match;
65090fdc7489SMatthew Knepley   const char *lname;
65100fdc7489SMatthew Knepley 
65110fdc7489SMatthew Knepley   PetscFunctionBegin;
65120fdc7489SMatthew Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6513064a246eSJacob Faibussowitsch   PetscValidCharPointer(name, 3);
65149566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
65150fdc7489SMatthew Knepley   if (!flg) {
65169566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
65179566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
65189566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
65190fdc7489SMatthew Knepley   }
65209566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
652163a3b9bcSJacob Faibussowitsch   PetscCheck(l < Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", l, Nl);
65220fdc7489SMatthew Knepley   for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) {
65239566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)orig->label, &lname));
65249566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &match));
65250fdc7489SMatthew Knepley     if (match) break;
65260fdc7489SMatthew Knepley   }
65273ba16761SJacob Faibussowitsch   if (m == l) PetscFunctionReturn(PETSC_SUCCESS);
65280fdc7489SMatthew Knepley   if (!m) dm->labels = orig->next;
65290fdc7489SMatthew Knepley   else prev->next = orig->next;
65300fdc7489SMatthew Knepley   if (!l) {
65310fdc7489SMatthew Knepley     orig->next = dm->labels;
65320fdc7489SMatthew Knepley     dm->labels = orig;
65330fdc7489SMatthew Knepley   } else {
65349371c9d4SSatish Balay     for (m = 0, prev = dm->labels; m < l - 1; ++m, prev = prev->next)
65359371c9d4SSatish Balay       ;
65360fdc7489SMatthew Knepley     orig->next = prev->next;
65370fdc7489SMatthew Knepley     prev->next = orig;
65380fdc7489SMatthew Knepley   }
65393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65400fdc7489SMatthew Knepley }
65410fdc7489SMatthew Knepley 
65420fdc7489SMatthew Knepley /*@C
6543bb7acecfSBarry Smith   DMGetLabelValue - Get the value in a `DMLabel` for the given point, with -1 as the default
6544c58f1c22SToby Isaac 
6545c58f1c22SToby Isaac   Not Collective
6546c58f1c22SToby Isaac 
6547c58f1c22SToby Isaac   Input Parameters:
6548bb7acecfSBarry Smith + dm   - The `DM` object
6549c58f1c22SToby Isaac . name - The label name
6550c58f1c22SToby Isaac - point - The mesh point
6551c58f1c22SToby Isaac 
6552c58f1c22SToby Isaac   Output Parameter:
6553c58f1c22SToby Isaac . value - The label value for this point, or -1 if the point is not in the label
6554c58f1c22SToby Isaac 
6555c58f1c22SToby Isaac   Level: beginner
6556c58f1c22SToby Isaac 
6557db781477SPatrick Sanan .seealso: `DMLabelGetValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6558c58f1c22SToby Isaac @*/
6559d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
6560d71ae5a4SJacob Faibussowitsch {
6561c58f1c22SToby Isaac   DMLabel label;
6562c58f1c22SToby Isaac 
6563c58f1c22SToby Isaac   PetscFunctionBegin;
6564c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6565c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
65669566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
65677a8be351SBarry Smith   PetscCheck(label, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
65689566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, point, value));
65693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6570c58f1c22SToby Isaac }
6571c58f1c22SToby Isaac 
6572c58f1c22SToby Isaac /*@C
6573bb7acecfSBarry Smith   DMSetLabelValue - Add a point to a `DMLabel` with given value
6574c58f1c22SToby Isaac 
6575c58f1c22SToby Isaac   Not Collective
6576c58f1c22SToby Isaac 
6577c58f1c22SToby Isaac   Input Parameters:
6578bb7acecfSBarry Smith + dm   - The `DM` object
6579c58f1c22SToby Isaac . name - The label name
6580c58f1c22SToby Isaac . point - The mesh point
6581c58f1c22SToby Isaac - value - The label value for this point
6582c58f1c22SToby Isaac 
6583c58f1c22SToby Isaac   Output Parameter:
6584c58f1c22SToby Isaac 
6585c58f1c22SToby Isaac   Level: beginner
6586c58f1c22SToby Isaac 
6587db781477SPatrick Sanan .seealso: `DMLabelSetValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6588c58f1c22SToby Isaac @*/
6589d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6590d71ae5a4SJacob Faibussowitsch {
6591c58f1c22SToby Isaac   DMLabel label;
6592c58f1c22SToby Isaac 
6593c58f1c22SToby Isaac   PetscFunctionBegin;
6594c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6595c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
65969566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6597c58f1c22SToby Isaac   if (!label) {
65989566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
65999566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
6600c58f1c22SToby Isaac   }
66019566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, point, value));
66023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6603c58f1c22SToby Isaac }
6604c58f1c22SToby Isaac 
6605c58f1c22SToby Isaac /*@C
6606bb7acecfSBarry Smith   DMClearLabelValue - Remove a point from a `DMLabel` with given value
6607c58f1c22SToby Isaac 
6608c58f1c22SToby Isaac   Not Collective
6609c58f1c22SToby Isaac 
6610c58f1c22SToby Isaac   Input Parameters:
6611bb7acecfSBarry Smith + dm   - The `DM` object
6612c58f1c22SToby Isaac . name - The label name
6613c58f1c22SToby Isaac . point - The mesh point
6614c58f1c22SToby Isaac - value - The label value for this point
6615c58f1c22SToby Isaac 
6616c58f1c22SToby Isaac   Level: beginner
6617c58f1c22SToby Isaac 
6618db781477SPatrick Sanan .seealso: `DMLabelClearValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6619c58f1c22SToby Isaac @*/
6620d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6621d71ae5a4SJacob Faibussowitsch {
6622c58f1c22SToby Isaac   DMLabel label;
6623c58f1c22SToby Isaac 
6624c58f1c22SToby Isaac   PetscFunctionBegin;
6625c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6626c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
66279566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
66283ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
66299566063dSJacob Faibussowitsch   PetscCall(DMLabelClearValue(label, point, value));
66303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6631c58f1c22SToby Isaac }
6632c58f1c22SToby Isaac 
6633c58f1c22SToby Isaac /*@C
6634bb7acecfSBarry Smith   DMGetLabelSize - Get the value of `DMLabelGetNumValues()` of a `DMLabel` in the `DM`
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 
6642c58f1c22SToby Isaac   Output Parameter:
6643c58f1c22SToby Isaac . size - The number of different integer ids, or 0 if the label does not exist
6644c58f1c22SToby Isaac 
6645c58f1c22SToby Isaac   Level: beginner
6646c58f1c22SToby Isaac 
6647bb7acecfSBarry Smith   Developer Note:
6648bb7acecfSBarry Smith   This should be renamed to something like `DMGetLabelNumValues()` or removed.
6649bb7acecfSBarry Smith 
6650bb7acecfSBarry Smith .seealso: `DMLabelGetNumValues()`, `DMSetLabelValue()`, `DMGetLabel()`
6651c58f1c22SToby Isaac @*/
6652d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
6653d71ae5a4SJacob Faibussowitsch {
6654c58f1c22SToby Isaac   DMLabel label;
6655c58f1c22SToby Isaac 
6656c58f1c22SToby Isaac   PetscFunctionBegin;
6657c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6658c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6659534a8f05SLisandro Dalcin   PetscValidIntPointer(size, 3);
66609566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6661c58f1c22SToby Isaac   *size = 0;
66623ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
66639566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, size));
66643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6665c58f1c22SToby Isaac }
6666c58f1c22SToby Isaac 
6667c58f1c22SToby Isaac /*@C
6668bb7acecfSBarry Smith   DMGetLabelIdIS - Get the `DMLabelGetValueIS()` from a `DMLabel` in the `DM`
6669c58f1c22SToby Isaac 
6670c58f1c22SToby Isaac   Not Collective
6671c58f1c22SToby Isaac 
6672c58f1c22SToby Isaac   Input Parameters:
6673bb7acecfSBarry Smith + mesh - The `DM` object
6674c58f1c22SToby Isaac - name - The label name
6675c58f1c22SToby Isaac 
6676c58f1c22SToby Isaac   Output Parameter:
667720f4b53cSBarry Smith . ids - The integer ids, or `NULL` if the label does not exist
6678c58f1c22SToby Isaac 
6679c58f1c22SToby Isaac   Level: beginner
6680c58f1c22SToby Isaac 
6681db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMGetLabelSize()`
6682c58f1c22SToby Isaac @*/
6683d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
6684d71ae5a4SJacob Faibussowitsch {
6685c58f1c22SToby Isaac   DMLabel label;
6686c58f1c22SToby Isaac 
6687c58f1c22SToby Isaac   PetscFunctionBegin;
6688c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6689c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6690c58f1c22SToby Isaac   PetscValidPointer(ids, 3);
66919566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6692c58f1c22SToby Isaac   *ids = NULL;
6693dab2e251SBlaise Bourdin   if (label) {
66949566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, ids));
6695dab2e251SBlaise Bourdin   } else {
6696dab2e251SBlaise Bourdin     /* returning an empty IS */
66979566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, ids));
6698dab2e251SBlaise Bourdin   }
66993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6700c58f1c22SToby Isaac }
6701c58f1c22SToby Isaac 
6702c58f1c22SToby Isaac /*@C
6703c58f1c22SToby Isaac   DMGetStratumSize - Get the number of points in a label stratum
6704c58f1c22SToby Isaac 
6705c58f1c22SToby Isaac   Not Collective
6706c58f1c22SToby Isaac 
6707c58f1c22SToby Isaac   Input Parameters:
6708bb7acecfSBarry Smith + dm - The `DM` object
6709c58f1c22SToby Isaac . name - The label name
6710c58f1c22SToby Isaac - value - The stratum value
6711c58f1c22SToby Isaac 
6712c58f1c22SToby Isaac   Output Parameter:
6713bb7acecfSBarry Smith . size - The number of points, also called the stratum size
6714c58f1c22SToby Isaac 
6715c58f1c22SToby Isaac   Level: beginner
6716c58f1c22SToby Isaac 
6717db781477SPatrick Sanan .seealso: `DMLabelGetStratumSize()`, `DMGetLabelSize()`, `DMGetLabelIds()`
6718c58f1c22SToby Isaac @*/
6719d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
6720d71ae5a4SJacob Faibussowitsch {
6721c58f1c22SToby Isaac   DMLabel label;
6722c58f1c22SToby Isaac 
6723c58f1c22SToby Isaac   PetscFunctionBegin;
6724c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6725c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6726534a8f05SLisandro Dalcin   PetscValidIntPointer(size, 4);
67279566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6728c58f1c22SToby Isaac   *size = 0;
67293ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
67309566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize(label, value, size));
67313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6732c58f1c22SToby Isaac }
6733c58f1c22SToby Isaac 
6734c58f1c22SToby Isaac /*@C
6735c58f1c22SToby Isaac   DMGetStratumIS - Get the points in a label stratum
6736c58f1c22SToby Isaac 
6737c58f1c22SToby Isaac   Not Collective
6738c58f1c22SToby Isaac 
6739c58f1c22SToby Isaac   Input Parameters:
6740bb7acecfSBarry Smith + dm - The `DM` object
6741c58f1c22SToby Isaac . name - The label name
6742c58f1c22SToby Isaac - value - The stratum value
6743c58f1c22SToby Isaac 
6744c58f1c22SToby Isaac   Output Parameter:
674520f4b53cSBarry Smith . points - The stratum points, or `NULL` if the label does not exist or does not have that value
6746c58f1c22SToby Isaac 
6747c58f1c22SToby Isaac   Level: beginner
6748c58f1c22SToby Isaac 
6749db781477SPatrick Sanan .seealso: `DMLabelGetStratumIS()`, `DMGetStratumSize()`
6750c58f1c22SToby Isaac @*/
6751d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
6752d71ae5a4SJacob Faibussowitsch {
6753c58f1c22SToby Isaac   DMLabel label;
6754c58f1c22SToby Isaac 
6755c58f1c22SToby Isaac   PetscFunctionBegin;
6756c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6757c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6758c58f1c22SToby Isaac   PetscValidPointer(points, 4);
67599566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6760c58f1c22SToby Isaac   *points = NULL;
67613ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
67629566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, points));
67633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6764c58f1c22SToby Isaac }
6765c58f1c22SToby Isaac 
67664de306b1SToby Isaac /*@C
67679044fa66SMatthew G. Knepley   DMSetStratumIS - Set the points in a label stratum
67684de306b1SToby Isaac 
67694de306b1SToby Isaac   Not Collective
67704de306b1SToby Isaac 
67714de306b1SToby Isaac   Input Parameters:
6772bb7acecfSBarry Smith + dm - The `DM` object
67734de306b1SToby Isaac . name - The label name
67744de306b1SToby Isaac . value - The stratum value
67754de306b1SToby Isaac - points - The stratum points
67764de306b1SToby Isaac 
67774de306b1SToby Isaac   Level: beginner
67784de306b1SToby Isaac 
6779bb7acecfSBarry Smith .seealso: `DMLabel`, `DMClearLabelStratum()`, `DMLabelClearStratum()`, `DMLabelSetStratumIS()`, `DMGetStratumSize()`
67804de306b1SToby Isaac @*/
6781d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
6782d71ae5a4SJacob Faibussowitsch {
67834de306b1SToby Isaac   DMLabel label;
67844de306b1SToby Isaac 
67854de306b1SToby Isaac   PetscFunctionBegin;
67864de306b1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67874de306b1SToby Isaac   PetscValidCharPointer(name, 2);
67884de306b1SToby Isaac   PetscValidPointer(points, 4);
67899566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
67903ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
67919566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, points));
67923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67934de306b1SToby Isaac }
67944de306b1SToby Isaac 
6795c58f1c22SToby Isaac /*@C
6796bb7acecfSBarry Smith   DMClearLabelStratum - Remove all points from a stratum from a `DMLabel`
6797c58f1c22SToby Isaac 
6798c58f1c22SToby Isaac   Not Collective
6799c58f1c22SToby Isaac 
6800c58f1c22SToby Isaac   Input Parameters:
6801bb7acecfSBarry Smith + dm   - The `DM` object
6802c58f1c22SToby Isaac . name - The label name
6803c58f1c22SToby Isaac - value - The label value for this point
6804c58f1c22SToby Isaac 
6805c58f1c22SToby Isaac   Output Parameter:
6806c58f1c22SToby Isaac 
6807c58f1c22SToby Isaac   Level: beginner
6808c58f1c22SToby Isaac 
6809bb7acecfSBarry Smith .seealso: `DMLabel`, `DMLabelClearStratum()`, `DMSetLabelValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6810c58f1c22SToby Isaac @*/
6811d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
6812d71ae5a4SJacob Faibussowitsch {
6813c58f1c22SToby Isaac   DMLabel label;
6814c58f1c22SToby Isaac 
6815c58f1c22SToby Isaac   PetscFunctionBegin;
6816c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6817c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
68189566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
68193ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
68209566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
68213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6822c58f1c22SToby Isaac }
6823c58f1c22SToby Isaac 
6824c58f1c22SToby Isaac /*@
6825bb7acecfSBarry Smith   DMGetNumLabels - Return the number of labels defined by on the `DM`
6826c58f1c22SToby Isaac 
6827c58f1c22SToby Isaac   Not Collective
6828c58f1c22SToby Isaac 
6829c58f1c22SToby Isaac   Input Parameter:
6830bb7acecfSBarry Smith . dm   - The `DM` object
6831c58f1c22SToby Isaac 
6832c58f1c22SToby Isaac   Output Parameter:
6833c58f1c22SToby Isaac . numLabels - the number of Labels
6834c58f1c22SToby Isaac 
6835c58f1c22SToby Isaac   Level: intermediate
6836c58f1c22SToby Isaac 
6837bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetLabelByNum()`, `DMGetLabelName()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6838c58f1c22SToby Isaac @*/
6839d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
6840d71ae5a4SJacob Faibussowitsch {
68415d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6842c58f1c22SToby Isaac   PetscInt    n    = 0;
6843c58f1c22SToby Isaac 
6844c58f1c22SToby Isaac   PetscFunctionBegin;
6845c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6846534a8f05SLisandro Dalcin   PetscValidIntPointer(numLabels, 2);
68479371c9d4SSatish Balay   while (next) {
68489371c9d4SSatish Balay     ++n;
68499371c9d4SSatish Balay     next = next->next;
68509371c9d4SSatish Balay   }
6851c58f1c22SToby Isaac   *numLabels = n;
68523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6853c58f1c22SToby Isaac }
6854c58f1c22SToby Isaac 
6855c58f1c22SToby Isaac /*@C
6856c58f1c22SToby Isaac   DMGetLabelName - Return the name of nth label
6857c58f1c22SToby Isaac 
6858c58f1c22SToby Isaac   Not Collective
6859c58f1c22SToby Isaac 
6860c58f1c22SToby Isaac   Input Parameters:
6861bb7acecfSBarry Smith + dm - The `DM` object
6862c58f1c22SToby Isaac - n  - the label number
6863c58f1c22SToby Isaac 
6864c58f1c22SToby Isaac   Output Parameter:
6865c58f1c22SToby Isaac . name - the label name
6866c58f1c22SToby Isaac 
6867c58f1c22SToby Isaac   Level: intermediate
6868c58f1c22SToby Isaac 
6869bb7acecfSBarry Smith   Developer Note:
6870bb7acecfSBarry Smith   Some of the functions that appropriate on labels using their number have the suffix ByNum, others do not.
6871bb7acecfSBarry Smith 
6872bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetLabelByNum()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6873c58f1c22SToby Isaac @*/
6874d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
6875d71ae5a4SJacob Faibussowitsch {
68765d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6877c58f1c22SToby Isaac   PetscInt    l    = 0;
6878c58f1c22SToby Isaac 
6879c58f1c22SToby Isaac   PetscFunctionBegin;
6880c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6881c58f1c22SToby Isaac   PetscValidPointer(name, 3);
6882c58f1c22SToby Isaac   while (next) {
6883c58f1c22SToby Isaac     if (l == n) {
68849566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)next->label, name));
68853ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6886c58f1c22SToby Isaac     }
6887c58f1c22SToby Isaac     ++l;
6888c58f1c22SToby Isaac     next = next->next;
6889c58f1c22SToby Isaac   }
689063a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
6891c58f1c22SToby Isaac }
6892c58f1c22SToby Isaac 
6893c58f1c22SToby Isaac /*@C
6894bb7acecfSBarry Smith   DMHasLabel - Determine whether the `DM` has a label of a given name
6895c58f1c22SToby Isaac 
6896c58f1c22SToby Isaac   Not Collective
6897c58f1c22SToby Isaac 
6898c58f1c22SToby Isaac   Input Parameters:
6899bb7acecfSBarry Smith + dm   - The `DM` object
6900c58f1c22SToby Isaac - name - The label name
6901c58f1c22SToby Isaac 
6902c58f1c22SToby Isaac   Output Parameter:
6903bb7acecfSBarry Smith . hasLabel - `PETSC_TRUE` if the label is present
6904c58f1c22SToby Isaac 
6905c58f1c22SToby Isaac   Level: intermediate
6906c58f1c22SToby Isaac 
6907bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetLabel()`, `DMGetLabelByNum()`, `DMCreateLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6908c58f1c22SToby Isaac @*/
6909d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
6910d71ae5a4SJacob Faibussowitsch {
69115d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6912d67d17b1SMatthew G. Knepley   const char *lname;
6913c58f1c22SToby Isaac 
6914c58f1c22SToby Isaac   PetscFunctionBegin;
6915c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6916c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6917534a8f05SLisandro Dalcin   PetscValidBoolPointer(hasLabel, 3);
6918c58f1c22SToby Isaac   *hasLabel = PETSC_FALSE;
6919c58f1c22SToby Isaac   while (next) {
69209566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
69219566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, hasLabel));
6922c58f1c22SToby Isaac     if (*hasLabel) break;
6923c58f1c22SToby Isaac     next = next->next;
6924c58f1c22SToby Isaac   }
69253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6926c58f1c22SToby Isaac }
6927c58f1c22SToby Isaac 
6928c58f1c22SToby Isaac /*@C
692920f4b53cSBarry Smith   DMGetLabel - Return the label of a given name, or `NULL`, from a `DM`
6930c58f1c22SToby Isaac 
6931c58f1c22SToby Isaac   Not Collective
6932c58f1c22SToby Isaac 
6933c58f1c22SToby Isaac   Input Parameters:
6934bb7acecfSBarry Smith + dm   - The `DM` object
6935c58f1c22SToby Isaac - name - The label name
6936c58f1c22SToby Isaac 
6937c58f1c22SToby Isaac   Output Parameter:
693820f4b53cSBarry Smith . label - The `DMLabel`, or `NULL` if the label is absent
6939c58f1c22SToby Isaac 
6940bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
6941bb7acecfSBarry Smith +   "depth"       - Holds the depth (co-dimension) of each mesh point
6942bb7acecfSBarry Smith .   "celltype"    - Holds the topological type of each cell
6943bb7acecfSBarry Smith .   "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
6944bb7acecfSBarry Smith .   "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
6945bb7acecfSBarry Smith .   "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
6946bb7acecfSBarry Smith -  "Vertex Sets" - Mirrors the vertex sets defined by GMsh
69476d7c9049SMatthew G. Knepley 
6948c58f1c22SToby Isaac   Level: intermediate
6949c58f1c22SToby Isaac 
6950bb7acecfSBarry Smith .seealso: `DMLabel`, `DMHasLabel()`, `DMGetLabelByNum()`, `DMAddLabel()`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
6951c58f1c22SToby Isaac @*/
6952d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
6953d71ae5a4SJacob Faibussowitsch {
69545d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6955c58f1c22SToby Isaac   PetscBool   hasLabel;
6956d67d17b1SMatthew G. Knepley   const char *lname;
6957c58f1c22SToby Isaac 
6958c58f1c22SToby Isaac   PetscFunctionBegin;
6959c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6960c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6961c58f1c22SToby Isaac   PetscValidPointer(label, 3);
6962c58f1c22SToby Isaac   *label = NULL;
6963c58f1c22SToby Isaac   while (next) {
69649566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
69659566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
6966c58f1c22SToby Isaac     if (hasLabel) {
6967c58f1c22SToby Isaac       *label = next->label;
6968c58f1c22SToby Isaac       break;
6969c58f1c22SToby Isaac     }
6970c58f1c22SToby Isaac     next = next->next;
6971c58f1c22SToby Isaac   }
69723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6973c58f1c22SToby Isaac }
6974c58f1c22SToby Isaac 
6975c58f1c22SToby Isaac /*@C
6976bb7acecfSBarry Smith   DMGetLabelByNum - Return the nth label on a `DM`
6977c58f1c22SToby Isaac 
6978c58f1c22SToby Isaac   Not Collective
6979c58f1c22SToby Isaac 
6980c58f1c22SToby Isaac   Input Parameters:
6981bb7acecfSBarry Smith + dm - The `DM` object
6982c58f1c22SToby Isaac - n  - the label number
6983c58f1c22SToby Isaac 
6984c58f1c22SToby Isaac   Output Parameter:
6985c58f1c22SToby Isaac . label - the label
6986c58f1c22SToby Isaac 
6987c58f1c22SToby Isaac   Level: intermediate
6988c58f1c22SToby Isaac 
6989bb7acecfSBarry Smith .seealso: `DMLabel`, `DMAddLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6990c58f1c22SToby Isaac @*/
6991d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
6992d71ae5a4SJacob Faibussowitsch {
69935d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6994c58f1c22SToby Isaac   PetscInt    l    = 0;
6995c58f1c22SToby Isaac 
6996c58f1c22SToby Isaac   PetscFunctionBegin;
6997c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6998c58f1c22SToby Isaac   PetscValidPointer(label, 3);
6999c58f1c22SToby Isaac   while (next) {
7000c58f1c22SToby Isaac     if (l == n) {
7001c58f1c22SToby Isaac       *label = next->label;
70023ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
7003c58f1c22SToby Isaac     }
7004c58f1c22SToby Isaac     ++l;
7005c58f1c22SToby Isaac     next = next->next;
7006c58f1c22SToby Isaac   }
700763a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
7008c58f1c22SToby Isaac }
7009c58f1c22SToby Isaac 
7010c58f1c22SToby Isaac /*@C
7011bb7acecfSBarry Smith   DMAddLabel - Add the label to this `DM`
7012c58f1c22SToby Isaac 
7013c58f1c22SToby Isaac   Not Collective
7014c58f1c22SToby Isaac 
7015c58f1c22SToby Isaac   Input Parameters:
7016bb7acecfSBarry Smith + dm   - The `DM` object
7017bb7acecfSBarry Smith - label - The `DMLabel`
7018c58f1c22SToby Isaac 
7019c58f1c22SToby Isaac   Level: developer
7020c58f1c22SToby Isaac 
7021bb7acecfSBarry Smith .seealso: `DMLabel`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7022c58f1c22SToby Isaac @*/
7023d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddLabel(DM dm, DMLabel label)
7024d71ae5a4SJacob Faibussowitsch {
70255d80c0bfSVaclav Hapla   DMLabelLink l, *p, tmpLabel;
7026c58f1c22SToby Isaac   PetscBool   hasLabel;
7027d67d17b1SMatthew G. Knepley   const char *lname;
70285d80c0bfSVaclav Hapla   PetscBool   flg;
7029c58f1c22SToby Isaac 
7030c58f1c22SToby Isaac   PetscFunctionBegin;
7031c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70329566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
70339566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, lname, &hasLabel));
70347a8be351SBarry Smith   PetscCheck(!hasLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname);
70359566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(1, &tmpLabel));
7036c58f1c22SToby Isaac   tmpLabel->label  = label;
7037c58f1c22SToby Isaac   tmpLabel->output = PETSC_TRUE;
70385d80c0bfSVaclav Hapla   for (p = &dm->labels; (l = *p); p = &l->next) { }
70395d80c0bfSVaclav Hapla   *p = tmpLabel;
70409566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
70419566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "depth", &flg));
70425d80c0bfSVaclav Hapla   if (flg) dm->depthLabel = label;
70439566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "celltype", &flg));
7044ba2698f1SMatthew G. Knepley   if (flg) dm->celltypeLabel = label;
70453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7046c58f1c22SToby Isaac }
7047c58f1c22SToby Isaac 
7048c58f1c22SToby Isaac /*@C
70494a7ee7d0SMatthew G. Knepley   DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present
70504a7ee7d0SMatthew G. Knepley 
70514a7ee7d0SMatthew G. Knepley   Not Collective
70524a7ee7d0SMatthew G. Knepley 
70534a7ee7d0SMatthew G. Knepley   Input Parameters:
7054bb7acecfSBarry Smith + dm    - The `DM` object
7055bb7acecfSBarry Smith - label - The `DMLabel`, having the same name, to substitute
70564a7ee7d0SMatthew G. Knepley 
7057bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
7058bb7acecfSBarry Smith +  "depth"       - Holds the depth (co-dimension) of each mesh point
7059bb7acecfSBarry Smith .  "celltype"    - Holds the topological type of each cell
7060bb7acecfSBarry Smith .  "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
7061bb7acecfSBarry Smith .  "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
7062bb7acecfSBarry Smith .  "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
7063bb7acecfSBarry Smith - "Vertex Sets" - Mirrors the vertex sets defined by GMsh
70644a7ee7d0SMatthew G. Knepley 
70654a7ee7d0SMatthew G. Knepley   Level: intermediate
70664a7ee7d0SMatthew G. Knepley 
7067bb7acecfSBarry Smith .seealso: `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
70684a7ee7d0SMatthew G. Knepley @*/
7069d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabel(DM dm, DMLabel label)
7070d71ae5a4SJacob Faibussowitsch {
70714a7ee7d0SMatthew G. Knepley   DMLabelLink next = dm->labels;
70724a7ee7d0SMatthew G. Knepley   PetscBool   hasLabel, flg;
70734a7ee7d0SMatthew G. Knepley   const char *name, *lname;
70744a7ee7d0SMatthew G. Knepley 
70754a7ee7d0SMatthew G. Knepley   PetscFunctionBegin;
70764a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70774a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
70789566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
70794a7ee7d0SMatthew G. Knepley   while (next) {
70809566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
70819566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
70824a7ee7d0SMatthew G. Knepley     if (hasLabel) {
70839566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)label));
70849566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "depth", &flg));
70854a7ee7d0SMatthew G. Knepley       if (flg) dm->depthLabel = label;
70869566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "celltype", &flg));
70874a7ee7d0SMatthew G. Knepley       if (flg) dm->celltypeLabel = label;
70889566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&next->label));
70894a7ee7d0SMatthew G. Knepley       next->label = label;
70904a7ee7d0SMatthew G. Knepley       break;
70914a7ee7d0SMatthew G. Knepley     }
70924a7ee7d0SMatthew G. Knepley     next = next->next;
70934a7ee7d0SMatthew G. Knepley   }
70943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70954a7ee7d0SMatthew G. Knepley }
70964a7ee7d0SMatthew G. Knepley 
70974a7ee7d0SMatthew G. Knepley /*@C
7098bb7acecfSBarry Smith   DMRemoveLabel - Remove the label given by name from this `DM`
7099c58f1c22SToby Isaac 
7100c58f1c22SToby Isaac   Not Collective
7101c58f1c22SToby Isaac 
7102c58f1c22SToby Isaac   Input Parameters:
7103bb7acecfSBarry Smith + dm   - The `DM` object
7104c58f1c22SToby Isaac - name - The label name
7105c58f1c22SToby Isaac 
7106c58f1c22SToby Isaac   Output Parameter:
710720f4b53cSBarry Smith . label - The `DMLabel`, or `NULL` if the label is absent. Pass in `NULL` to call `DMLabelDestroy()` on the label, otherwise the
7108bb7acecfSBarry Smith           caller is responsible for calling `DMLabelDestroy()`.
7109c58f1c22SToby Isaac 
7110c58f1c22SToby Isaac   Level: developer
7111c58f1c22SToby Isaac 
7112bb7acecfSBarry Smith .seealso: `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabelBySelf()`
7113c58f1c22SToby Isaac @*/
7114d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
7115d71ae5a4SJacob Faibussowitsch {
711695d578d6SVaclav Hapla   DMLabelLink link, *pnext;
7117c58f1c22SToby Isaac   PetscBool   hasLabel;
7118d67d17b1SMatthew G. Knepley   const char *lname;
7119c58f1c22SToby Isaac 
7120c58f1c22SToby Isaac   PetscFunctionBegin;
7121c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7122e5472504SVaclav Hapla   PetscValidCharPointer(name, 2);
7123e5472504SVaclav Hapla   if (label) {
7124e5472504SVaclav Hapla     PetscValidPointer(label, 3);
7125c58f1c22SToby Isaac     *label = NULL;
7126e5472504SVaclav Hapla   }
71275d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
71289566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)link->label, &lname));
71299566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
7130c58f1c22SToby Isaac     if (hasLabel) {
713195d578d6SVaclav Hapla       *pnext = link->next; /* Remove from list */
71329566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &hasLabel));
713395d578d6SVaclav Hapla       if (hasLabel) dm->depthLabel = NULL;
71349566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &hasLabel));
7135ba2698f1SMatthew G. Knepley       if (hasLabel) dm->celltypeLabel = NULL;
713695d578d6SVaclav Hapla       if (label) *label = link->label;
71379566063dSJacob Faibussowitsch       else PetscCall(DMLabelDestroy(&link->label));
71389566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7139c58f1c22SToby Isaac       break;
7140c58f1c22SToby Isaac     }
7141c58f1c22SToby Isaac   }
71423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7143c58f1c22SToby Isaac }
7144c58f1c22SToby Isaac 
7145306894acSVaclav Hapla /*@
7146bb7acecfSBarry Smith   DMRemoveLabelBySelf - Remove the label from this `DM`
7147306894acSVaclav Hapla 
7148306894acSVaclav Hapla   Not Collective
7149306894acSVaclav Hapla 
7150306894acSVaclav Hapla   Input Parameters:
7151bb7acecfSBarry Smith + dm   - The `DM` object
7152bb7acecfSBarry Smith . label - The `DMLabel` to be removed from the `DM`
715320f4b53cSBarry Smith - failNotFound - Should it fail if the label is not found in the `DM`?
7154306894acSVaclav Hapla 
7155306894acSVaclav Hapla   Level: developer
7156306894acSVaclav Hapla 
7157bb7acecfSBarry Smith   Note:
7158306894acSVaclav Hapla   Only exactly the same instance is removed if found, name match is ignored.
7159bb7acecfSBarry Smith   If the `DM` has an exclusive reference to the label, the label gets destroyed and
7160306894acSVaclav Hapla   *label nullified.
7161306894acSVaclav Hapla 
7162bb7acecfSBarry Smith .seealso: `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()` `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabel()`
7163306894acSVaclav Hapla @*/
7164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound)
7165d71ae5a4SJacob Faibussowitsch {
716643e45a93SVaclav Hapla   DMLabelLink link, *pnext;
7167306894acSVaclav Hapla   PetscBool   hasLabel = PETSC_FALSE;
7168306894acSVaclav Hapla 
7169306894acSVaclav Hapla   PetscFunctionBegin;
7170306894acSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7171306894acSVaclav Hapla   PetscValidPointer(label, 2);
71723ba16761SJacob Faibussowitsch   if (!*label && !failNotFound) PetscFunctionReturn(PETSC_SUCCESS);
7173306894acSVaclav Hapla   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2);
7174306894acSVaclav Hapla   PetscValidLogicalCollectiveBool(dm, failNotFound, 3);
71755d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
717643e45a93SVaclav Hapla     if (*label == link->label) {
7177306894acSVaclav Hapla       hasLabel = PETSC_TRUE;
717843e45a93SVaclav Hapla       *pnext   = link->next; /* Remove from list */
7179306894acSVaclav Hapla       if (*label == dm->depthLabel) dm->depthLabel = NULL;
7180ba2698f1SMatthew G. Knepley       if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL;
718143e45a93SVaclav Hapla       if (((PetscObject)link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */
71829566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&link->label));
71839566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7184306894acSVaclav Hapla       break;
7185306894acSVaclav Hapla     }
7186306894acSVaclav Hapla   }
71877a8be351SBarry Smith   PetscCheck(hasLabel || !failNotFound, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM");
71883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7189306894acSVaclav Hapla }
7190306894acSVaclav Hapla 
7191c58f1c22SToby Isaac /*@C
7192c58f1c22SToby Isaac   DMGetLabelOutput - Get the output flag for a given label
7193c58f1c22SToby Isaac 
7194c58f1c22SToby Isaac   Not Collective
7195c58f1c22SToby Isaac 
7196c58f1c22SToby Isaac   Input Parameters:
7197bb7acecfSBarry Smith + dm   - The `DM` object
7198c58f1c22SToby Isaac - name - The label name
7199c58f1c22SToby Isaac 
7200c58f1c22SToby Isaac   Output Parameter:
7201c58f1c22SToby Isaac . output - The flag for output
7202c58f1c22SToby Isaac 
7203c58f1c22SToby Isaac   Level: developer
7204c58f1c22SToby Isaac 
7205bb7acecfSBarry Smith .seealso: `DMLabel`, `DMSetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7206c58f1c22SToby Isaac @*/
7207d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
7208d71ae5a4SJacob Faibussowitsch {
72095d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7210d67d17b1SMatthew G. Knepley   const char *lname;
7211c58f1c22SToby Isaac 
7212c58f1c22SToby Isaac   PetscFunctionBegin;
7213c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7214dadcf809SJacob Faibussowitsch   PetscValidCharPointer(name, 2);
7215dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(output, 3);
7216c58f1c22SToby Isaac   while (next) {
7217c58f1c22SToby Isaac     PetscBool flg;
7218c58f1c22SToby Isaac 
72199566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
72209566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
72219371c9d4SSatish Balay     if (flg) {
72229371c9d4SSatish Balay       *output = next->output;
72233ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
72249371c9d4SSatish Balay     }
7225c58f1c22SToby Isaac     next = next->next;
7226c58f1c22SToby Isaac   }
722798921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7228c58f1c22SToby Isaac }
7229c58f1c22SToby Isaac 
7230c58f1c22SToby Isaac /*@C
7231bb7acecfSBarry Smith   DMSetLabelOutput - Set if a given label should be saved to a `PetscViewer` in calls to `DMView()`
7232c58f1c22SToby Isaac 
7233c58f1c22SToby Isaac   Not Collective
7234c58f1c22SToby Isaac 
7235c58f1c22SToby Isaac   Input Parameters:
7236bb7acecfSBarry Smith + dm     - The `DM` object
7237c58f1c22SToby Isaac . name   - The label name
7238bb7acecfSBarry Smith - output - `PETSC_TRUE` to save the label to the viewer
7239c58f1c22SToby Isaac 
7240c58f1c22SToby Isaac   Level: developer
7241c58f1c22SToby Isaac 
7242bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetOutputFlag()`, `DMGetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7243c58f1c22SToby Isaac @*/
7244d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
7245d71ae5a4SJacob Faibussowitsch {
72465d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7247d67d17b1SMatthew G. Knepley   const char *lname;
7248c58f1c22SToby Isaac 
7249c58f1c22SToby Isaac   PetscFunctionBegin;
7250c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7251534a8f05SLisandro Dalcin   PetscValidCharPointer(name, 2);
7252c58f1c22SToby Isaac   while (next) {
7253c58f1c22SToby Isaac     PetscBool flg;
7254c58f1c22SToby Isaac 
72559566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
72569566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
72579371c9d4SSatish Balay     if (flg) {
72589371c9d4SSatish Balay       next->output = output;
72593ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
72609371c9d4SSatish Balay     }
7261c58f1c22SToby Isaac     next = next->next;
7262c58f1c22SToby Isaac   }
726398921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7264c58f1c22SToby Isaac }
7265c58f1c22SToby Isaac 
7266c58f1c22SToby Isaac /*@
7267bb7acecfSBarry Smith   DMCopyLabels - Copy labels from one `DM` mesh to another `DM` with a superset of the points
7268c58f1c22SToby Isaac 
726920f4b53cSBarry Smith   Collective
7270c58f1c22SToby Isaac 
7271d8d19677SJose E. Roman   Input Parameters:
7272bb7acecfSBarry Smith + dmA - The `DM` object with initial labels
7273bb7acecfSBarry Smith . dmB - The `DM` object to which labels are copied
7274bb7acecfSBarry Smith . mode - Copy labels by pointers (`PETSC_OWN_POINTER`) or duplicate them (`PETSC_COPY_VALUES`)
7275bb7acecfSBarry Smith . all  - Copy all labels including "depth", "dim", and "celltype" (`PETSC_TRUE`) which are otherwise ignored (`PETSC_FALSE`)
7276bb7acecfSBarry Smith - emode - How to behave when a `DMLabel` in the source and destination `DM`s with the same name is encountered (see `DMCopyLabelsMode`)
7277c58f1c22SToby Isaac 
7278c58f1c22SToby Isaac   Level: intermediate
7279c58f1c22SToby Isaac 
7280bb7acecfSBarry Smith   Note:
72812cbb9b06SVaclav Hapla   This is typically used when interpolating or otherwise adding to a mesh, or testing.
7282c58f1c22SToby Isaac 
7283bb7acecfSBarry Smith .seealso: `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`
7284c58f1c22SToby Isaac @*/
7285d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all, DMCopyLabelsMode emode)
7286d71ae5a4SJacob Faibussowitsch {
72872cbb9b06SVaclav Hapla   DMLabel     label, labelNew, labelOld;
7288c58f1c22SToby Isaac   const char *name;
7289c58f1c22SToby Isaac   PetscBool   flg;
72905d80c0bfSVaclav Hapla   DMLabelLink link;
7291c58f1c22SToby Isaac 
72925d80c0bfSVaclav Hapla   PetscFunctionBegin;
72935d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
72945d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
72955d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveEnum(dmA, mode, 3);
72965d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveBool(dmA, all, 4);
72977a8be351SBarry Smith   PetscCheck(mode != PETSC_USE_POINTER, PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects");
72983ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
72995d80c0bfSVaclav Hapla   for (link = dmA->labels; link; link = link->next) {
73005d80c0bfSVaclav Hapla     label = link->label;
73019566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
73025d80c0bfSVaclav Hapla     if (!all) {
73039566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &flg));
7304c58f1c22SToby Isaac       if (flg) continue;
73059566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "dim", &flg));
73067d5acc75SStefano Zampini       if (flg) continue;
73079566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &flg));
7308ba2698f1SMatthew G. Knepley       if (flg) continue;
73095d80c0bfSVaclav Hapla     }
73109566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dmB, name, &labelOld));
73112cbb9b06SVaclav Hapla     if (labelOld) {
73122cbb9b06SVaclav Hapla       switch (emode) {
7313d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_KEEP:
7314d71ae5a4SJacob Faibussowitsch         continue;
7315d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_REPLACE:
7316d71ae5a4SJacob Faibussowitsch         PetscCall(DMRemoveLabelBySelf(dmB, &labelOld, PETSC_TRUE));
7317d71ae5a4SJacob Faibussowitsch         break;
7318d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_FAIL:
7319d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in destination DM", name);
7320d71ae5a4SJacob Faibussowitsch       default:
7321d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Unhandled DMCopyLabelsMode %d", (int)emode);
73222cbb9b06SVaclav Hapla       }
73232cbb9b06SVaclav Hapla     }
73245d80c0bfSVaclav Hapla     if (mode == PETSC_COPY_VALUES) {
73259566063dSJacob Faibussowitsch       PetscCall(DMLabelDuplicate(label, &labelNew));
73265d80c0bfSVaclav Hapla     } else {
73275d80c0bfSVaclav Hapla       labelNew = label;
73285d80c0bfSVaclav Hapla     }
73299566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dmB, labelNew));
73309566063dSJacob Faibussowitsch     if (mode == PETSC_COPY_VALUES) PetscCall(DMLabelDestroy(&labelNew));
7331c58f1c22SToby Isaac   }
73323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7333c58f1c22SToby Isaac }
7334461a15a0SLisandro Dalcin 
7335609dae6eSVaclav Hapla /*@C
7336bb7acecfSBarry Smith   DMCompareLabels - Compare labels of two `DMPLEX` meshes
7337609dae6eSVaclav Hapla 
733820f4b53cSBarry Smith   Collective; No Fortran Support
7339609dae6eSVaclav Hapla 
7340609dae6eSVaclav Hapla   Input Parameters:
7341bb7acecfSBarry Smith + dm0 - First `DM` object
7342bb7acecfSBarry Smith - dm1 - Second `DM` object
7343609dae6eSVaclav Hapla 
7344609dae6eSVaclav Hapla   Output Parameters
73455efe38ccSVaclav Hapla + equal   - (Optional) Flag whether labels of dm0 and dm1 are the same
734620f4b53cSBarry Smith - message - (Optional) Message describing the difference, or `NULL` if there is no difference
7347609dae6eSVaclav Hapla 
7348609dae6eSVaclav Hapla   Level: intermediate
7349609dae6eSVaclav Hapla 
7350609dae6eSVaclav Hapla   Notes:
7351bb7acecfSBarry Smith   The output flag equal will be the same on all processes.
7352bb7acecfSBarry Smith 
735320f4b53cSBarry Smith   If equal is passed as `NULL` and difference is found, an error is thrown on all processes.
7354bb7acecfSBarry Smith 
735520f4b53cSBarry Smith   Make sure to pass equal is `NULL` on all processes or none of them.
7356609dae6eSVaclav Hapla 
73575efe38ccSVaclav Hapla   The output message is set independently on each rank.
7358bb7acecfSBarry Smith 
7359bb7acecfSBarry Smith   message must be freed with `PetscFree()`
7360bb7acecfSBarry Smith 
736120f4b53cSBarry Smith   If message is passed as `NULL` and a difference is found, the difference description is printed to stderr in synchronized manner.
7362bb7acecfSBarry Smith 
736320f4b53cSBarry Smith   Make sure to pass message as `NULL` on all processes or no processes.
7364609dae6eSVaclav Hapla 
7365609dae6eSVaclav Hapla   Labels are matched by name. If the number of labels and their names are equal,
7366bb7acecfSBarry Smith   `DMLabelCompare()` is used to compare each pair of labels with the same name.
7367609dae6eSVaclav Hapla 
7368bb7acecfSBarry Smith .seealso: `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`, `DMLabelCompare()`
7369609dae6eSVaclav Hapla @*/
7370d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompareLabels(DM dm0, DM dm1, PetscBool *equal, char **message)
7371d71ae5a4SJacob Faibussowitsch {
73725efe38ccSVaclav Hapla   PetscInt    n, i;
7373609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
73745efe38ccSVaclav Hapla   PetscBool   eq;
7375609dae6eSVaclav Hapla   MPI_Comm    comm;
73765efe38ccSVaclav Hapla   PetscMPIInt rank;
7377609dae6eSVaclav Hapla 
7378609dae6eSVaclav Hapla   PetscFunctionBegin;
7379609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm0, DM_CLASSID, 1);
7380609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm1, DM_CLASSID, 2);
7381609dae6eSVaclav Hapla   PetscCheckSameComm(dm0, 1, dm1, 2);
73825efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 3);
7383609dae6eSVaclav Hapla   if (message) PetscValidPointer(message, 4);
73849566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm0, &comm));
73859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
73865efe38ccSVaclav Hapla   {
73875efe38ccSVaclav Hapla     PetscInt n1;
73885efe38ccSVaclav Hapla 
73899566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm0, &n));
73909566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm1, &n1));
73915efe38ccSVaclav Hapla     eq = (PetscBool)(n == n1);
739248a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Number of labels in dm0 = %" PetscInt_FMT " != %" PetscInt_FMT " = Number of labels in dm1", n, n1));
73939566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
73945efe38ccSVaclav Hapla     if (!eq) goto finish;
73955efe38ccSVaclav Hapla   }
73965efe38ccSVaclav Hapla   for (i = 0; i < n; i++) {
7397609dae6eSVaclav Hapla     DMLabel     l0, l1;
7398609dae6eSVaclav Hapla     const char *name;
7399609dae6eSVaclav Hapla     char       *msgInner;
7400609dae6eSVaclav Hapla 
7401609dae6eSVaclav Hapla     /* Ignore label order */
74029566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm0, i, &l0));
74039566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)l0, &name));
74049566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm1, name, &l1));
7405609dae6eSVaclav Hapla     if (!l1) {
740663a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Label \"%s\" (#%" PetscInt_FMT " in dm0) not found in dm1", name, i));
74075efe38ccSVaclav Hapla       eq = PETSC_FALSE;
74085efe38ccSVaclav Hapla       break;
7409609dae6eSVaclav Hapla     }
74109566063dSJacob Faibussowitsch     PetscCall(DMLabelCompare(comm, l0, l1, &eq, &msgInner));
74119566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(msg, msgInner, sizeof(msg)));
74129566063dSJacob Faibussowitsch     PetscCall(PetscFree(msgInner));
74135efe38ccSVaclav Hapla     if (!eq) break;
7414609dae6eSVaclav Hapla   }
74159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
7416609dae6eSVaclav Hapla finish:
74175efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
7418609dae6eSVaclav Hapla   if (message) {
7419609dae6eSVaclav Hapla     *message = NULL;
742048a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
74215efe38ccSVaclav Hapla   } else {
742248a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
74239566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
74245efe38ccSVaclav Hapla   }
74255efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
74265efe38ccSVaclav Hapla   if (equal) *equal = eq;
74277a8be351SBarry Smith   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels are not the same in dm0 and dm1");
74283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7429609dae6eSVaclav Hapla }
7430609dae6eSVaclav Hapla 
7431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value)
7432d71ae5a4SJacob Faibussowitsch {
7433461a15a0SLisandro Dalcin   PetscFunctionBegin;
7434461a15a0SLisandro Dalcin   PetscValidPointer(label, 2);
7435461a15a0SLisandro Dalcin   if (!*label) {
74369566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
74379566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, label));
7438461a15a0SLisandro Dalcin   }
74399566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(*label, point, value));
74403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7441461a15a0SLisandro Dalcin }
7442461a15a0SLisandro Dalcin 
74430fdc7489SMatthew Knepley /*
74440fdc7489SMatthew Knepley   Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would
74450fdc7489SMatthew Knepley   like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every
74460fdc7489SMatthew Knepley   (label, id) pair in the DM.
74470fdc7489SMatthew Knepley 
74480fdc7489SMatthew Knepley   However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to
74490fdc7489SMatthew Knepley   each label.
74500fdc7489SMatthew Knepley */
7451d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal)
7452d71ae5a4SJacob Faibussowitsch {
74530fdc7489SMatthew Knepley   DMUniversalLabel ul;
74540fdc7489SMatthew Knepley   PetscBool       *active;
74550fdc7489SMatthew Knepley   PetscInt         pStart, pEnd, p, Nl, l, m;
74560fdc7489SMatthew Knepley 
74570fdc7489SMatthew Knepley   PetscFunctionBegin;
74589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, &ul));
74599566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label));
74609566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
74619566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Nl, &active));
74620fdc7489SMatthew Knepley   ul->Nl = 0;
74630fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
74640fdc7489SMatthew Knepley     PetscBool   isdepth, iscelltype;
74650fdc7489SMatthew Knepley     const char *name;
74660fdc7489SMatthew Knepley 
74679566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
74689566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "depth", 6, &isdepth));
74699566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "celltype", 9, &iscelltype));
74700fdc7489SMatthew Knepley     active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE;
74710fdc7489SMatthew Knepley     if (active[l]) ++ul->Nl;
74720fdc7489SMatthew Knepley   }
74739566063dSJacob 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));
74740fdc7489SMatthew Knepley   ul->Nv = 0;
74750fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
74760fdc7489SMatthew Knepley     DMLabel     label;
74770fdc7489SMatthew Knepley     PetscInt    nv;
74780fdc7489SMatthew Knepley     const char *name;
74790fdc7489SMatthew Knepley 
74800fdc7489SMatthew Knepley     if (!active[l]) continue;
74819566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
74829566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
74839566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
74849566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &ul->names[m]));
74850fdc7489SMatthew Knepley     ul->indices[m] = l;
74860fdc7489SMatthew Knepley     ul->Nv += nv;
74870fdc7489SMatthew Knepley     ul->offsets[m + 1] = nv;
74880fdc7489SMatthew Knepley     ul->bits[m + 1]    = PetscCeilReal(PetscLog2Real(nv + 1));
74890fdc7489SMatthew Knepley     ++m;
74900fdc7489SMatthew Knepley   }
74910fdc7489SMatthew Knepley   for (l = 1; l <= ul->Nl; ++l) {
74920fdc7489SMatthew Knepley     ul->offsets[l] = ul->offsets[l - 1] + ul->offsets[l];
74930fdc7489SMatthew Knepley     ul->bits[l]    = ul->bits[l - 1] + ul->bits[l];
74940fdc7489SMatthew Knepley   }
74950fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
74960fdc7489SMatthew Knepley     PetscInt b;
74970fdc7489SMatthew Knepley 
74980fdc7489SMatthew Knepley     ul->masks[l] = 0;
74990fdc7489SMatthew Knepley     for (b = ul->bits[l]; b < ul->bits[l + 1]; ++b) ul->masks[l] |= 1 << b;
75000fdc7489SMatthew Knepley   }
75019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ul->Nv, &ul->values));
75020fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
75030fdc7489SMatthew Knepley     DMLabel         label;
75040fdc7489SMatthew Knepley     IS              valueIS;
75050fdc7489SMatthew Knepley     const PetscInt *varr;
75060fdc7489SMatthew Knepley     PetscInt        nv, v;
75070fdc7489SMatthew Knepley 
75080fdc7489SMatthew Knepley     if (!active[l]) continue;
75099566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
75109566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
75119566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, &valueIS));
75129566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(valueIS, &varr));
7513ad540459SPierre Jolivet     for (v = 0; v < nv; ++v) ul->values[ul->offsets[m] + v] = varr[v];
75149566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(valueIS, &varr));
75159566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&valueIS));
75169566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(nv, &ul->values[ul->offsets[m]]));
75170fdc7489SMatthew Knepley     ++m;
75180fdc7489SMatthew Knepley   }
75199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
75200fdc7489SMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
75210fdc7489SMatthew Knepley     PetscInt  uval   = 0;
75220fdc7489SMatthew Knepley     PetscBool marked = PETSC_FALSE;
75230fdc7489SMatthew Knepley 
75240fdc7489SMatthew Knepley     for (l = 0, m = 0; l < Nl; ++l) {
75250fdc7489SMatthew Knepley       DMLabel  label;
75260649b39aSStefano Zampini       PetscInt val, defval, loc, nv;
75270fdc7489SMatthew Knepley 
75280fdc7489SMatthew Knepley       if (!active[l]) continue;
75299566063dSJacob Faibussowitsch       PetscCall(DMGetLabelByNum(dm, l, &label));
75309566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, p, &val));
75319566063dSJacob Faibussowitsch       PetscCall(DMLabelGetDefaultValue(label, &defval));
75329371c9d4SSatish Balay       if (val == defval) {
75339371c9d4SSatish Balay         ++m;
75349371c9d4SSatish Balay         continue;
75359371c9d4SSatish Balay       }
75360649b39aSStefano Zampini       nv     = ul->offsets[m + 1] - ul->offsets[m];
75370fdc7489SMatthew Knepley       marked = PETSC_TRUE;
75389566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc));
753963a3b9bcSJacob Faibussowitsch       PetscCheck(loc >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %" PetscInt_FMT " not found in compression array", val);
75400fdc7489SMatthew Knepley       uval += (loc + 1) << ul->bits[m];
75410fdc7489SMatthew Knepley       ++m;
75420fdc7489SMatthew Knepley     }
75439566063dSJacob Faibussowitsch     if (marked) PetscCall(DMLabelSetValue(ul->label, p, uval));
75440fdc7489SMatthew Knepley   }
75459566063dSJacob Faibussowitsch   PetscCall(PetscFree(active));
75460fdc7489SMatthew Knepley   *universal = ul;
75473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75480fdc7489SMatthew Knepley }
75490fdc7489SMatthew Knepley 
7550d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal)
7551d71ae5a4SJacob Faibussowitsch {
75520fdc7489SMatthew Knepley   PetscInt l;
75530fdc7489SMatthew Knepley 
75540fdc7489SMatthew Knepley   PetscFunctionBegin;
75559566063dSJacob Faibussowitsch   for (l = 0; l < (*universal)->Nl; ++l) PetscCall(PetscFree((*universal)->names[l]));
75569566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&(*universal)->label));
75579566063dSJacob Faibussowitsch   PetscCall(PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks));
75589566063dSJacob Faibussowitsch   PetscCall(PetscFree((*universal)->values));
75599566063dSJacob Faibussowitsch   PetscCall(PetscFree(*universal));
75600fdc7489SMatthew Knepley   *universal = NULL;
75613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75620fdc7489SMatthew Knepley }
75630fdc7489SMatthew Knepley 
7564d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel)
7565d71ae5a4SJacob Faibussowitsch {
75660fdc7489SMatthew Knepley   PetscFunctionBegin;
75670fdc7489SMatthew Knepley   PetscValidPointer(ulabel, 2);
75680fdc7489SMatthew Knepley   *ulabel = ul->label;
75693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75700fdc7489SMatthew Knepley }
75710fdc7489SMatthew Knepley 
7572d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm)
7573d71ae5a4SJacob Faibussowitsch {
75740fdc7489SMatthew Knepley   PetscInt Nl = ul->Nl, l;
75750fdc7489SMatthew Knepley 
75760fdc7489SMatthew Knepley   PetscFunctionBegin;
7577064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 3);
75780fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
75799566063dSJacob Faibussowitsch     if (preserveOrder) PetscCall(DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]));
75809566063dSJacob Faibussowitsch     else PetscCall(DMCreateLabel(dm, ul->names[l]));
75810fdc7489SMatthew Knepley   }
75820fdc7489SMatthew Knepley   if (preserveOrder) {
75830fdc7489SMatthew Knepley     for (l = 0; l < ul->Nl; ++l) {
75840fdc7489SMatthew Knepley       const char *name;
75850fdc7489SMatthew Knepley       PetscBool   match;
75860fdc7489SMatthew Knepley 
75879566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, ul->indices[l], &name));
75889566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, ul->names[l], &match));
758963a3b9bcSJacob 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]);
75900fdc7489SMatthew Knepley     }
75910fdc7489SMatthew Knepley   }
75923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75930fdc7489SMatthew Knepley }
75940fdc7489SMatthew Knepley 
7595d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value)
7596d71ae5a4SJacob Faibussowitsch {
75970fdc7489SMatthew Knepley   PetscInt l;
75980fdc7489SMatthew Knepley 
75990fdc7489SMatthew Knepley   PetscFunctionBegin;
76000fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
76010fdc7489SMatthew Knepley     DMLabel  label;
76020fdc7489SMatthew Knepley     PetscInt lval = (value & ul->masks[l]) >> ul->bits[l];
76030fdc7489SMatthew Knepley 
76040fdc7489SMatthew Knepley     if (lval) {
76059566063dSJacob Faibussowitsch       if (useIndex) PetscCall(DMGetLabelByNum(dm, ul->indices[l], &label));
76069566063dSJacob Faibussowitsch       else PetscCall(DMGetLabel(dm, ul->names[l], &label));
76079566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(label, p, ul->values[ul->offsets[l] + lval - 1]));
76080fdc7489SMatthew Knepley     }
76090fdc7489SMatthew Knepley   }
76103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76110fdc7489SMatthew Knepley }
7612a8fb8f29SToby Isaac 
7613a8fb8f29SToby Isaac /*@
7614bb7acecfSBarry Smith   DMGetCoarseDM - Get the coarse `DM`from which this `DM` was obtained by refinement
7615bb7acecfSBarry Smith 
761620f4b53cSBarry Smith   Not Collective
7617a8fb8f29SToby Isaac 
7618a8fb8f29SToby Isaac   Input Parameter:
7619bb7acecfSBarry Smith . dm - The `DM` object
7620a8fb8f29SToby Isaac 
7621a8fb8f29SToby Isaac   Output Parameter:
7622bb7acecfSBarry Smith . cdm - The coarse `DM`
7623a8fb8f29SToby Isaac 
7624a8fb8f29SToby Isaac   Level: intermediate
7625a8fb8f29SToby Isaac 
7626bb7acecfSBarry Smith .seealso: `DMSetCoarseDM()`, `DMCoarsen()`
7627a8fb8f29SToby Isaac @*/
7628d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
7629d71ae5a4SJacob Faibussowitsch {
7630a8fb8f29SToby Isaac   PetscFunctionBegin;
7631a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7632a8fb8f29SToby Isaac   PetscValidPointer(cdm, 2);
7633a8fb8f29SToby Isaac   *cdm = dm->coarseMesh;
76343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7635a8fb8f29SToby Isaac }
7636a8fb8f29SToby Isaac 
7637a8fb8f29SToby Isaac /*@
7638bb7acecfSBarry Smith   DMSetCoarseDM - Set the coarse `DM` from which this `DM` was obtained by refinement
7639a8fb8f29SToby Isaac 
7640a8fb8f29SToby Isaac   Input Parameters:
7641bb7acecfSBarry Smith + dm - The `DM` object
7642bb7acecfSBarry Smith - cdm - The coarse `DM`
7643a8fb8f29SToby Isaac 
7644a8fb8f29SToby Isaac   Level: intermediate
7645a8fb8f29SToby Isaac 
7646bb7acecfSBarry Smith   Note:
7647bb7acecfSBarry Smith   Normally this is set automatically by `DMRefine()`
7648bb7acecfSBarry Smith 
7649bb7acecfSBarry Smith .seealso: `DMGetCoarseDM()`, `DMCoarsen()`, `DMSetRefine()`, `DMSetFineDM()`
7650a8fb8f29SToby Isaac @*/
7651d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
7652d71ae5a4SJacob Faibussowitsch {
7653a8fb8f29SToby Isaac   PetscFunctionBegin;
7654a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7655a8fb8f29SToby Isaac   if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
765689d734beSBarry Smith   if (dm == cdm) cdm = NULL;
76579566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)cdm));
76589566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->coarseMesh));
7659a8fb8f29SToby Isaac   dm->coarseMesh = cdm;
76603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7661a8fb8f29SToby Isaac }
7662a8fb8f29SToby Isaac 
766388bdff64SToby Isaac /*@
7664bb7acecfSBarry Smith   DMGetFineDM - Get the fine mesh from which this `DM` was obtained by coarsening
766588bdff64SToby Isaac 
766688bdff64SToby Isaac   Input Parameter:
7667bb7acecfSBarry Smith . dm - The `DM` object
766888bdff64SToby Isaac 
766988bdff64SToby Isaac   Output Parameter:
7670bb7acecfSBarry Smith . fdm - The fine `DM`
767188bdff64SToby Isaac 
767288bdff64SToby Isaac   Level: intermediate
767388bdff64SToby Isaac 
7674bb7acecfSBarry Smith .seealso: `DMSetFineDM()`, `DMCoarsen()`, `DMRefine()`
767588bdff64SToby Isaac @*/
7676d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
7677d71ae5a4SJacob Faibussowitsch {
767888bdff64SToby Isaac   PetscFunctionBegin;
767988bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
768088bdff64SToby Isaac   PetscValidPointer(fdm, 2);
768188bdff64SToby Isaac   *fdm = dm->fineMesh;
76823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
768388bdff64SToby Isaac }
768488bdff64SToby Isaac 
768588bdff64SToby Isaac /*@
7686bb7acecfSBarry Smith   DMSetFineDM - Set the fine mesh from which this was obtained by coarsening
768788bdff64SToby Isaac 
768888bdff64SToby Isaac   Input Parameters:
7689bb7acecfSBarry Smith + dm - The `DM` object
7690bb7acecfSBarry Smith - fdm - The fine `DM`
769188bdff64SToby Isaac 
7692bb7acecfSBarry Smith   Level: developer
769388bdff64SToby Isaac 
7694bb7acecfSBarry Smith   Note:
7695bb7acecfSBarry Smith   Normally this is set automatically by `DMCoarsen()`
7696bb7acecfSBarry Smith 
7697bb7acecfSBarry Smith .seealso: `DMGetFineDM()`, `DMCoarsen()`, `DMRefine()`
769888bdff64SToby Isaac @*/
7699d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFineDM(DM dm, DM fdm)
7700d71ae5a4SJacob Faibussowitsch {
770188bdff64SToby Isaac   PetscFunctionBegin;
770288bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
770388bdff64SToby Isaac   if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2);
770489d734beSBarry Smith   if (dm == fdm) fdm = NULL;
77059566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fdm));
77069566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->fineMesh));
770788bdff64SToby Isaac   dm->fineMesh = fdm;
77083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
770988bdff64SToby Isaac }
771088bdff64SToby Isaac 
7711a6ba4734SToby Isaac /*@C
7712bb7acecfSBarry Smith   DMAddBoundary - Add a boundary condition to a model represented by a `DM`
7713a6ba4734SToby Isaac 
771420f4b53cSBarry Smith   Collective
7715783e2ec8SMatthew G. Knepley 
7716a6ba4734SToby Isaac   Input Parameters:
7717bb7acecfSBarry Smith + dm       - The `DM`, with a `PetscDS` that matches the problem being constrained
7718bb7acecfSBarry Smith . type     - The type of condition, e.g. `DM_BC_ESSENTIAL_ANALYTIC`, `DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
7719a6ba4734SToby Isaac . name     - The BC name
772045480ffeSMatthew G. Knepley . label    - The label defining constrained points
7721bb7acecfSBarry Smith . Nv       - The number of `DMLabel` values for constrained points
772245480ffeSMatthew G. Knepley . values   - An array of values for constrained points
7723a6ba4734SToby Isaac . field    - The field to constrain
772445480ffeSMatthew G. Knepley . Nc       - The number of constrained field components (0 will constrain all fields)
7725a6ba4734SToby Isaac . comps    - An array of constrained component numbers
7726a6ba4734SToby Isaac . bcFunc   - A pointwise function giving boundary values
772756cf3b9cSMatthew G. Knepley . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL
7728a6ba4734SToby Isaac - ctx      - An optional user context for bcFunc
7729a6ba4734SToby Isaac 
773045480ffeSMatthew G. Knepley   Output Parameter:
773145480ffeSMatthew G. Knepley . bd          - (Optional) Boundary number
773245480ffeSMatthew G. Knepley 
7733a6ba4734SToby Isaac   Options Database Keys:
7734a6ba4734SToby Isaac + -bc_<boundary name> <num> - Overrides the boundary ids
7735a6ba4734SToby Isaac - -bc_<boundary name>_comp <num> - Overrides the boundary components
7736a6ba4734SToby Isaac 
773720f4b53cSBarry Smith   Level: intermediate
773820f4b53cSBarry Smith 
7739bb7acecfSBarry Smith   Notes:
7740bb7acecfSBarry 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:
774156cf3b9cSMatthew G. Knepley 
774220f4b53cSBarry Smith $ void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
774356cf3b9cSMatthew G. Knepley 
7744bb7acecfSBarry Smith   If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is:
774556cf3b9cSMatthew G. Knepley 
774620f4b53cSBarry Smith .vb
774720f4b53cSBarry Smith   void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
774820f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
774920f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
775020f4b53cSBarry Smith               PetscReal time, const PetscReal x[], PetscScalar bcval[])
775120f4b53cSBarry Smith .ve
775256cf3b9cSMatthew G. Knepley + dim - the spatial dimension
775356cf3b9cSMatthew G. Knepley . Nf - the number of fields
775456cf3b9cSMatthew G. Knepley . uOff - the offset into u[] and u_t[] for each field
775556cf3b9cSMatthew G. Knepley . uOff_x - the offset into u_x[] for each field
775656cf3b9cSMatthew G. Knepley . u - each field evaluated at the current point
775756cf3b9cSMatthew G. Knepley . u_t - the time derivative of each field evaluated at the current point
775856cf3b9cSMatthew G. Knepley . u_x - the gradient of each field evaluated at the current point
775956cf3b9cSMatthew G. Knepley . aOff - the offset into a[] and a_t[] for each auxiliary field
776056cf3b9cSMatthew G. Knepley . aOff_x - the offset into a_x[] for each auxiliary field
776156cf3b9cSMatthew G. Knepley . a - each auxiliary field evaluated at the current point
776256cf3b9cSMatthew G. Knepley . a_t - the time derivative of each auxiliary field evaluated at the current point
776356cf3b9cSMatthew G. Knepley . a_x - the gradient of auxiliary each field evaluated at the current point
776456cf3b9cSMatthew G. Knepley . t - current time
776556cf3b9cSMatthew G. Knepley . x - coordinates of the current point
776656cf3b9cSMatthew G. Knepley . numConstants - number of constant parameters
776756cf3b9cSMatthew G. Knepley . constants - constant parameters
776856cf3b9cSMatthew G. Knepley - bcval - output values at the current point
776956cf3b9cSMatthew G. Knepley 
7770db781477SPatrick Sanan .seealso: `DSGetBoundary()`, `PetscDSAddBoundary()`
7771a6ba4734SToby Isaac @*/
7772d71ae5a4SJacob 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)
7773d71ae5a4SJacob Faibussowitsch {
7774e5e52638SMatthew G. Knepley   PetscDS ds;
7775a6ba4734SToby Isaac 
7776a6ba4734SToby Isaac   PetscFunctionBegin;
7777a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7778783e2ec8SMatthew G. Knepley   PetscValidLogicalCollectiveEnum(dm, type, 2);
777945480ffeSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
778045480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nv, 5);
778145480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, field, 7);
778245480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 8);
778301a5d20dSJed Brown   PetscCheck(!dm->localSection, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot add boundary to DM after creating local section");
77849566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
7785799db056SMatthew G. Knepley   /* Complete label */
7786799db056SMatthew G. Knepley   if (label) {
7787799db056SMatthew G. Knepley     PetscObject  obj;
7788799db056SMatthew G. Knepley     PetscClassId id;
7789799db056SMatthew G. Knepley 
7790799db056SMatthew G. Knepley     PetscCall(DMGetField(dm, field, NULL, &obj));
7791799db056SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
7792799db056SMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
7793799db056SMatthew G. Knepley       DM plex;
7794799db056SMatthew G. Knepley 
7795799db056SMatthew G. Knepley       PetscCall(DMConvert(dm, DMPLEX, &plex));
7796799db056SMatthew G. Knepley       if (plex) PetscCall(DMPlexLabelComplete(plex, label));
7797799db056SMatthew G. Knepley       PetscCall(DMDestroy(&plex));
7798799db056SMatthew G. Knepley     }
7799799db056SMatthew G. Knepley   }
78009566063dSJacob Faibussowitsch   PetscCall(PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd));
78013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7802a6ba4734SToby Isaac }
7803a6ba4734SToby Isaac 
780445480ffeSMatthew G. Knepley /* TODO Remove this since now the structures are the same */
7805d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPopulateBoundary(DM dm)
7806d71ae5a4SJacob Faibussowitsch {
7807e5e52638SMatthew G. Knepley   PetscDS     ds;
7808dff059c6SToby Isaac   DMBoundary *lastnext;
7809e6f8dbb6SToby Isaac   DSBoundary  dsbound;
7810e6f8dbb6SToby Isaac 
7811e6f8dbb6SToby Isaac   PetscFunctionBegin;
78129566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
7813e5e52638SMatthew G. Knepley   dsbound = ds->boundary;
781447a1f5adSToby Isaac   if (dm->boundary) {
781547a1f5adSToby Isaac     DMBoundary next = dm->boundary;
781647a1f5adSToby Isaac 
781747a1f5adSToby Isaac     /* quick check to see if the PetscDS has changed */
78183ba16761SJacob Faibussowitsch     if (next->dsboundary == dsbound) PetscFunctionReturn(PETSC_SUCCESS);
781947a1f5adSToby Isaac     /* the PetscDS has changed: tear down and rebuild */
782047a1f5adSToby Isaac     while (next) {
782147a1f5adSToby Isaac       DMBoundary b = next;
782247a1f5adSToby Isaac 
782347a1f5adSToby Isaac       next = b->next;
78249566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
7825a6ba4734SToby Isaac     }
782647a1f5adSToby Isaac     dm->boundary = NULL;
7827a6ba4734SToby Isaac   }
782847a1f5adSToby Isaac 
7829dff059c6SToby Isaac   lastnext = &(dm->boundary);
7830e6f8dbb6SToby Isaac   while (dsbound) {
7831e6f8dbb6SToby Isaac     DMBoundary dmbound;
7832e6f8dbb6SToby Isaac 
78339566063dSJacob Faibussowitsch     PetscCall(PetscNew(&dmbound));
7834e6f8dbb6SToby Isaac     dmbound->dsboundary = dsbound;
783545480ffeSMatthew G. Knepley     dmbound->label      = dsbound->label;
783647a1f5adSToby Isaac     /* push on the back instead of the front so that it is in the same order as in the PetscDS */
7837dff059c6SToby Isaac     *lastnext = dmbound;
7838dff059c6SToby Isaac     lastnext  = &(dmbound->next);
7839dff059c6SToby Isaac     dsbound   = dsbound->next;
7840a6ba4734SToby Isaac   }
78413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7842a6ba4734SToby Isaac }
7843a6ba4734SToby Isaac 
7844bb7acecfSBarry Smith /* TODO: missing manual page */
7845d71ae5a4SJacob Faibussowitsch PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
7846d71ae5a4SJacob Faibussowitsch {
7847b95f2879SToby Isaac   DMBoundary b;
7848a6ba4734SToby Isaac 
7849a6ba4734SToby Isaac   PetscFunctionBegin;
7850a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7851534a8f05SLisandro Dalcin   PetscValidBoolPointer(isBd, 3);
7852a6ba4734SToby Isaac   *isBd = PETSC_FALSE;
78539566063dSJacob Faibussowitsch   PetscCall(DMPopulateBoundary(dm));
7854b95f2879SToby Isaac   b = dm->boundary;
7855a6ba4734SToby Isaac   while (b && !(*isBd)) {
7856e6f8dbb6SToby Isaac     DMLabel    label = b->label;
7857e6f8dbb6SToby Isaac     DSBoundary dsb   = b->dsboundary;
7858a6ba4734SToby Isaac     PetscInt   i;
7859a6ba4734SToby Isaac 
786045480ffeSMatthew G. Knepley     if (label) {
78619566063dSJacob Faibussowitsch       for (i = 0; i < dsb->Nv && !(*isBd); ++i) PetscCall(DMLabelStratumHasPoint(label, dsb->values[i], point, isBd));
7862a6ba4734SToby Isaac     }
7863a6ba4734SToby Isaac     b = b->next;
7864a6ba4734SToby Isaac   }
78653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7866a6ba4734SToby Isaac }
78674d6f44ffSToby Isaac 
78684d6f44ffSToby Isaac /*@C
7869bb7acecfSBarry Smith   DMProjectFunction - This projects the given function into the function space provided by a `DM`, putting the coefficients in a global vector.
7870a6e0b375SMatthew G. Knepley 
787120f4b53cSBarry Smith   Collective
78724d6f44ffSToby Isaac 
78734d6f44ffSToby Isaac   Input Parameters:
7874bb7acecfSBarry Smith + dm      - The `DM`
78750709b2feSToby Isaac . time    - The time
78764d6f44ffSToby Isaac . funcs   - The coordinate functions to evaluate, one per field
78774d6f44ffSToby Isaac . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
78784d6f44ffSToby Isaac - mode    - The insertion mode for values
78794d6f44ffSToby Isaac 
78804d6f44ffSToby Isaac   Output Parameter:
78814d6f44ffSToby Isaac . X - vector
78824d6f44ffSToby Isaac 
788320f4b53cSBarry Smith    Calling sequence of `funcs`:
788420f4b53cSBarry Smith $  PetscErrorCode funcs(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
78854d6f44ffSToby Isaac +  dim - The spatial dimension
78868ec8862eSJed Brown .  time - The time at which to sample
78874d6f44ffSToby Isaac .  x   - The coordinates
788877b739a6SMatthew Knepley .  Nc  - The number of components
78894d6f44ffSToby Isaac .  u   - The output field values
78904d6f44ffSToby Isaac -  ctx - optional user-defined function context
78914d6f44ffSToby Isaac 
78924d6f44ffSToby Isaac   Level: developer
78934d6f44ffSToby Isaac 
7894bb7acecfSBarry Smith   Developer Notes:
7895bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
7896bb7acecfSBarry Smith 
7897bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
7898bb7acecfSBarry Smith 
7899db781477SPatrick Sanan .seealso: `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
79004d6f44ffSToby Isaac @*/
7901d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
7902d71ae5a4SJacob Faibussowitsch {
79034d6f44ffSToby Isaac   Vec localX;
79044d6f44ffSToby Isaac 
79054d6f44ffSToby Isaac   PetscFunctionBegin;
79064d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79079566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
7908f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
79099566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX));
79109566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
79119566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
79129566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
79133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79144d6f44ffSToby Isaac }
79154d6f44ffSToby Isaac 
7916a6e0b375SMatthew G. Knepley /*@C
7917bb7acecfSBarry Smith   DMProjectFunctionLocal - This projects the given function into the function space provided by a `DM`, putting the coefficients in a local vector.
7918a6e0b375SMatthew G. Knepley 
791920f4b53cSBarry Smith   Not Collective
7920a6e0b375SMatthew G. Knepley 
7921a6e0b375SMatthew G. Knepley   Input Parameters:
7922bb7acecfSBarry Smith + dm      - The `DM`
7923a6e0b375SMatthew G. Knepley . time    - The time
7924a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
7925a6e0b375SMatthew G. Knepley . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
7926a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
7927a6e0b375SMatthew G. Knepley 
7928a6e0b375SMatthew G. Knepley   Output Parameter:
7929a6e0b375SMatthew G. Knepley . localX - vector
7930a6e0b375SMatthew G. Knepley 
793120f4b53cSBarry Smith    Calling sequence of `funcs`:
793220f4b53cSBarry Smith $  PetscErrorCode funcs(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
7933a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
7934a6e0b375SMatthew G. Knepley .  x   - The coordinates
793577b739a6SMatthew Knepley .  Nc  - The number of components
7936a6e0b375SMatthew G. Knepley .  u   - The output field values
7937a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
7938a6e0b375SMatthew G. Knepley 
7939a6e0b375SMatthew G. Knepley   Level: developer
7940a6e0b375SMatthew G. Knepley 
7941bb7acecfSBarry Smith   Developer Notes:
7942bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
7943bb7acecfSBarry Smith 
7944bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
7945bb7acecfSBarry Smith 
7946db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
7947a6e0b375SMatthew G. Knepley @*/
7948d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
7949d71ae5a4SJacob Faibussowitsch {
79504d6f44ffSToby Isaac   PetscFunctionBegin;
79514d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7952064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
79539566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfunctionlocal)(dm, time, funcs, ctxs, mode, localX));
79543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79554d6f44ffSToby Isaac }
79564d6f44ffSToby Isaac 
7957a6e0b375SMatthew G. Knepley /*@C
7958bb7acecfSBarry 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.
7959a6e0b375SMatthew G. Knepley 
796020f4b53cSBarry Smith   Collective
7961a6e0b375SMatthew G. Knepley 
7962a6e0b375SMatthew G. Knepley   Input Parameters:
7963bb7acecfSBarry Smith + dm      - The `DM`
7964a6e0b375SMatthew G. Knepley . time    - The time
7965bb7acecfSBarry Smith . label   - The `DMLabel` selecting the portion of the mesh for projection
7966a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
7967bb7acecfSBarry Smith . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs may be null.
7968a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
7969a6e0b375SMatthew G. Knepley 
7970a6e0b375SMatthew G. Knepley   Output Parameter:
7971a6e0b375SMatthew G. Knepley . X - vector
7972a6e0b375SMatthew G. Knepley 
797320f4b53cSBarry Smith    Calling sequence of `funcs`:
797420f4b53cSBarry Smith $  PetscErrorCode funcs(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
7975a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
7976a6e0b375SMatthew G. Knepley .  x   - The coordinates
797777b739a6SMatthew Knepley .  Nc  - The number of components
7978a6e0b375SMatthew G. Knepley .  u   - The output field values
7979a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
7980a6e0b375SMatthew G. Knepley 
7981a6e0b375SMatthew G. Knepley   Level: developer
7982a6e0b375SMatthew G. Knepley 
7983bb7acecfSBarry Smith   Developer Notes:
7984bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
7985bb7acecfSBarry Smith 
7986bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
7987bb7acecfSBarry Smith 
7988db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabelLocal()`, `DMComputeL2Diff()`
7989a6e0b375SMatthew G. Knepley @*/
7990d71ae5a4SJacob 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)
7991d71ae5a4SJacob Faibussowitsch {
79922c53366bSMatthew G. Knepley   Vec localX;
79932c53366bSMatthew G. Knepley 
79942c53366bSMatthew G. Knepley   PetscFunctionBegin;
79952c53366bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79969566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
7997f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
79989566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
79999566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
80009566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
80019566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
80023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80032c53366bSMatthew G. Knepley }
80042c53366bSMatthew G. Knepley 
8005a6e0b375SMatthew G. Knepley /*@C
8006bb7acecfSBarry 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.
8007a6e0b375SMatthew G. Knepley 
800820f4b53cSBarry Smith   Not Collective
8009a6e0b375SMatthew G. Knepley 
8010a6e0b375SMatthew G. Knepley   Input Parameters:
8011bb7acecfSBarry Smith + dm      - The `DM`
8012a6e0b375SMatthew G. Knepley . time    - The time
8013bb7acecfSBarry Smith . label   - The `DMLabel` selecting the portion of the mesh for projection
8014a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
8015a6e0b375SMatthew G. Knepley . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
8016a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8017a6e0b375SMatthew G. Knepley 
8018a6e0b375SMatthew G. Knepley   Output Parameter:
8019a6e0b375SMatthew G. Knepley . localX - vector
8020a6e0b375SMatthew G. Knepley 
802120f4b53cSBarry Smith    Calling sequence of `funcs`:
802220f4b53cSBarry Smith $  PetscErrorCode funcs(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
8023a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
8024a6e0b375SMatthew G. Knepley .  x   - The coordinates
802577b739a6SMatthew Knepley .  Nc  - The number of components
8026a6e0b375SMatthew G. Knepley .  u   - The output field values
8027a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
8028a6e0b375SMatthew G. Knepley 
8029a6e0b375SMatthew G. Knepley   Level: developer
8030a6e0b375SMatthew G. Knepley 
8031bb7acecfSBarry Smith   Developer Notes:
8032bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8033bb7acecfSBarry Smith 
8034bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8035bb7acecfSBarry Smith 
8036db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
8037a6e0b375SMatthew G. Knepley @*/
8038d71ae5a4SJacob 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)
8039d71ae5a4SJacob Faibussowitsch {
80404d6f44ffSToby Isaac   PetscFunctionBegin;
80414d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8042064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
80439566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfunctionlabellocal)(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
80443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80454d6f44ffSToby Isaac }
80462716604bSToby Isaac 
8047a6e0b375SMatthew G. Knepley /*@C
8048bb7acecfSBarry 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.
8049a6e0b375SMatthew G. Knepley 
805020f4b53cSBarry Smith   Not Collective
8051a6e0b375SMatthew G. Knepley 
8052a6e0b375SMatthew G. Knepley   Input Parameters:
8053bb7acecfSBarry Smith + dm      - The `DM`
8054a6e0b375SMatthew G. Knepley . time    - The time
805520f4b53cSBarry Smith . localU  - The input field vector; may be `NULL` if projection is defined purely by coordinates
8056a6e0b375SMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8057a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8058a6e0b375SMatthew G. Knepley 
8059a6e0b375SMatthew G. Knepley   Output Parameter:
8060a6e0b375SMatthew G. Knepley . localX  - The output vector
8061a6e0b375SMatthew G. Knepley 
806220f4b53cSBarry Smith    Calling sequence of `funcs`:
806320f4b53cSBarry Smith .vb
806420f4b53cSBarry Smith    void funcs(PetscInt dim, PetscInt Nf, PetscInt NfAux,
806520f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
806620f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
806720f4b53cSBarry Smith               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
806820f4b53cSBarry Smith .ve
8069a6e0b375SMatthew G. Knepley +  dim          - The spatial dimension
8070a6e0b375SMatthew G. Knepley .  Nf           - The number of input fields
8071a6e0b375SMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8072a6e0b375SMatthew G. Knepley .  uOff         - The offset of each field in u[]
8073a6e0b375SMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8074a6e0b375SMatthew G. Knepley .  u            - The field values at this point in space
8075a6e0b375SMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8076a6e0b375SMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8077a6e0b375SMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8078a6e0b375SMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8079a6e0b375SMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8080a6e0b375SMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8081a6e0b375SMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8082a6e0b375SMatthew G. Knepley .  t            - The current time
8083a6e0b375SMatthew G. Knepley .  x            - The coordinates of this point
8084a6e0b375SMatthew G. Knepley .  numConstants - The number of constants
8085a6e0b375SMatthew G. Knepley .  constants    - The value of each constant
8086a6e0b375SMatthew G. Knepley -  f            - The value of the function at this point in space
8087a6e0b375SMatthew G. Knepley 
8088bb7acecfSBarry Smith   Note:
8089bb7acecfSBarry 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.
8090bb7acecfSBarry 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
8091bb7acecfSBarry 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
8092a6e0b375SMatthew 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.
8093a6e0b375SMatthew G. Knepley 
8094a6e0b375SMatthew G. Knepley   Level: intermediate
8095a6e0b375SMatthew G. Knepley 
8096bb7acecfSBarry Smith   Developer Notes:
8097bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8098bb7acecfSBarry Smith 
8099bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8100bb7acecfSBarry Smith 
8101db781477SPatrick Sanan .seealso: `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8102a6e0b375SMatthew G. Knepley @*/
8103d71ae5a4SJacob 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)
8104d71ae5a4SJacob Faibussowitsch {
81058c6c5593SMatthew G. Knepley   PetscFunctionBegin;
81068c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8107eb8f539aSJed Brown   if (localU) PetscValidHeaderSpecific(localU, VEC_CLASSID, 3);
81088c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
81099566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfieldlocal)(dm, time, localU, funcs, mode, localX));
81103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81118c6c5593SMatthew G. Knepley }
81128c6c5593SMatthew G. Knepley 
8113a6e0b375SMatthew G. Knepley /*@C
8114a6e0b375SMatthew 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.
8115a6e0b375SMatthew G. Knepley 
811620f4b53cSBarry Smith   Not Collective
8117a6e0b375SMatthew G. Knepley 
8118a6e0b375SMatthew G. Knepley   Input Parameters:
8119bb7acecfSBarry Smith + dm      - The `DM`
8120a6e0b375SMatthew G. Knepley . time    - The time
8121bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain to output
8122a6e0b375SMatthew G. Knepley . numIds  - The number of label ids to use
8123a6e0b375SMatthew G. Knepley . ids     - The label ids to use for marking
8124bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
812520f4b53cSBarry Smith . comps   - The components to set in the output, or `NULL` for all components
8126a6e0b375SMatthew G. Knepley . localU  - The input field vector
8127a6e0b375SMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8128a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8129a6e0b375SMatthew G. Knepley 
8130a6e0b375SMatthew G. Knepley   Output Parameter:
8131a6e0b375SMatthew G. Knepley . localX  - The output vector
8132a6e0b375SMatthew G. Knepley 
813320f4b53cSBarry Smith    Calling sequence of `funcs`:
813420f4b53cSBarry Smith .vb
813520f4b53cSBarry Smith    void funcs(PetscInt dim, PetscInt Nf, PetscInt NfAux,
813620f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
813720f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
813820f4b53cSBarry Smith               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
813920f4b53cSBarry Smith .ve
8140a6e0b375SMatthew G. Knepley +  dim          - The spatial dimension
8141a6e0b375SMatthew G. Knepley .  Nf           - The number of input fields
8142a6e0b375SMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8143a6e0b375SMatthew G. Knepley .  uOff         - The offset of each field in u[]
8144a6e0b375SMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8145a6e0b375SMatthew G. Knepley .  u            - The field values at this point in space
8146a6e0b375SMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8147a6e0b375SMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8148a6e0b375SMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8149a6e0b375SMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8150a6e0b375SMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8151a6e0b375SMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8152a6e0b375SMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8153a6e0b375SMatthew G. Knepley .  t            - The current time
8154a6e0b375SMatthew G. Knepley .  x            - The coordinates of this point
8155a6e0b375SMatthew G. Knepley .  numConstants - The number of constants
8156a6e0b375SMatthew G. Knepley .  constants    - The value of each constant
8157a6e0b375SMatthew G. Knepley -  f            - The value of the function at this point in space
8158a6e0b375SMatthew G. Knepley 
8159bb7acecfSBarry Smith   Note:
8160bb7acecfSBarry 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.
8161bb7acecfSBarry 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
8162bb7acecfSBarry 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
8163a6e0b375SMatthew 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.
8164a6e0b375SMatthew G. Knepley 
8165a6e0b375SMatthew G. Knepley   Level: intermediate
8166a6e0b375SMatthew G. Knepley 
8167bb7acecfSBarry Smith   Developer Notes:
8168bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8169bb7acecfSBarry Smith 
8170bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8171bb7acecfSBarry Smith 
8172d29d7c6eSMatthew G. Knepley .seealso: `DMProjectField()`, `DMProjectFieldLabel()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8173a6e0b375SMatthew G. Knepley @*/
8174d71ae5a4SJacob 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)
8175d71ae5a4SJacob Faibussowitsch {
81768c6c5593SMatthew G. Knepley   PetscFunctionBegin;
81778c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8178064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8179064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
81809566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
81813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81828c6c5593SMatthew G. Knepley }
81838c6c5593SMatthew G. Knepley 
81842716604bSToby Isaac /*@C
8185d29d7c6eSMatthew 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.
8186d29d7c6eSMatthew G. Knepley 
818720f4b53cSBarry Smith   Not Collective
8188d29d7c6eSMatthew G. Knepley 
8189d29d7c6eSMatthew G. Knepley   Input Parameters:
8190bb7acecfSBarry Smith + dm      - The `DM`
8191d29d7c6eSMatthew G. Knepley . time    - The time
8192bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain to output
8193d29d7c6eSMatthew G. Knepley . numIds  - The number of label ids to use
8194d29d7c6eSMatthew G. Knepley . ids     - The label ids to use for marking
8195bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
819620f4b53cSBarry Smith . comps   - The components to set in the output, or `NULL` for all components
8197d29d7c6eSMatthew G. Knepley . U       - The input field vector
8198d29d7c6eSMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8199d29d7c6eSMatthew G. Knepley - mode    - The insertion mode for values
8200d29d7c6eSMatthew G. Knepley 
8201d29d7c6eSMatthew G. Knepley   Output Parameter:
8202d29d7c6eSMatthew G. Knepley . X       - The output vector
8203d29d7c6eSMatthew G. Knepley 
820420f4b53cSBarry Smith    Calling sequence of `funcs`:
820520f4b53cSBarry Smith .vb
820620f4b53cSBarry Smith   void func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
820720f4b53cSBarry Smith             const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
820820f4b53cSBarry Smith             const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
820920f4b53cSBarry Smith             PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
821020f4b53cSBarry Smith .ve
8211d29d7c6eSMatthew G. Knepley +  dim          - The spatial dimension
8212d29d7c6eSMatthew G. Knepley .  Nf           - The number of input fields
8213d29d7c6eSMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8214d29d7c6eSMatthew G. Knepley .  uOff         - The offset of each field in u[]
8215d29d7c6eSMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8216d29d7c6eSMatthew G. Knepley .  u            - The field values at this point in space
8217d29d7c6eSMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8218d29d7c6eSMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8219d29d7c6eSMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8220d29d7c6eSMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8221d29d7c6eSMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8222d29d7c6eSMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8223d29d7c6eSMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8224d29d7c6eSMatthew G. Knepley .  t            - The current time
8225d29d7c6eSMatthew G. Knepley .  x            - The coordinates of this point
8226d29d7c6eSMatthew G. Knepley .  numConstants - The number of constants
8227d29d7c6eSMatthew G. Knepley .  constants    - The value of each constant
8228d29d7c6eSMatthew G. Knepley -  f            - The value of the function at this point in space
8229d29d7c6eSMatthew G. Knepley 
8230bb7acecfSBarry Smith   Note:
8231bb7acecfSBarry 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.
8232bb7acecfSBarry 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
8233bb7acecfSBarry 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
8234d29d7c6eSMatthew 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.
8235d29d7c6eSMatthew G. Knepley 
8236d29d7c6eSMatthew G. Knepley   Level: intermediate
8237d29d7c6eSMatthew G. Knepley 
8238bb7acecfSBarry Smith   Developer Notes:
8239bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8240bb7acecfSBarry Smith 
8241bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8242bb7acecfSBarry Smith 
8243d29d7c6eSMatthew G. Knepley .seealso: `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8244d29d7c6eSMatthew G. Knepley @*/
8245d71ae5a4SJacob 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)
8246d71ae5a4SJacob Faibussowitsch {
8247d29d7c6eSMatthew G. Knepley   DM  dmIn;
8248d29d7c6eSMatthew G. Knepley   Vec localU, localX;
8249d29d7c6eSMatthew G. Knepley 
8250d29d7c6eSMatthew G. Knepley   PetscFunctionBegin;
8251d29d7c6eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8252d29d7c6eSMatthew G. Knepley   PetscCall(VecGetDM(U, &dmIn));
8253d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dmIn, &localU));
8254d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dm, &localX));
8255f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
825672fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalBegin(dmIn, U, mode, localU));
825772fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalEnd(dmIn, U, mode, localU));
8258d29d7c6eSMatthew G. Knepley   PetscCall(DMProjectFieldLabelLocal(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
8259d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
8260d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
8261d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dm, &localX));
8262d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dmIn, &localU));
82633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8264d29d7c6eSMatthew G. Knepley }
8265d29d7c6eSMatthew G. Knepley 
8266d29d7c6eSMatthew G. Knepley /*@C
8267ece3a9fcSMatthew 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.
8268ece3a9fcSMatthew G. Knepley 
826920f4b53cSBarry Smith   Not Collective
8270ece3a9fcSMatthew G. Knepley 
8271ece3a9fcSMatthew G. Knepley   Input Parameters:
8272bb7acecfSBarry Smith + dm      - The `DM`
8273ece3a9fcSMatthew G. Knepley . time    - The time
8274bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain boundary to output
8275ece3a9fcSMatthew G. Knepley . numIds  - The number of label ids to use
8276ece3a9fcSMatthew G. Knepley . ids     - The label ids to use for marking
8277bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
827820f4b53cSBarry Smith . comps   - The components to set in the output, or `NULL` for all components
8279ece3a9fcSMatthew G. Knepley . localU  - The input field vector
8280ece3a9fcSMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8281ece3a9fcSMatthew G. Knepley - mode    - The insertion mode for values
8282ece3a9fcSMatthew G. Knepley 
8283ece3a9fcSMatthew G. Knepley   Output Parameter:
8284ece3a9fcSMatthew G. Knepley . localX  - The output vector
8285ece3a9fcSMatthew G. Knepley 
828620f4b53cSBarry Smith    Calling sequence of `funcs`:
828720f4b53cSBarry Smith .vb
828820f4b53cSBarry Smith    void funcs(PetscInt dim, PetscInt Nf, PetscInt NfAux,
828920f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
829020f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
829120f4b53cSBarry Smith               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
829220f4b53cSBarry Smith .ve
8293ece3a9fcSMatthew G. Knepley +  dim          - The spatial dimension
8294ece3a9fcSMatthew G. Knepley .  Nf           - The number of input fields
8295ece3a9fcSMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8296ece3a9fcSMatthew G. Knepley .  uOff         - The offset of each field in u[]
8297ece3a9fcSMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8298ece3a9fcSMatthew G. Knepley .  u            - The field values at this point in space
8299ece3a9fcSMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8300ece3a9fcSMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8301ece3a9fcSMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8302ece3a9fcSMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8303ece3a9fcSMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8304ece3a9fcSMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8305ece3a9fcSMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8306ece3a9fcSMatthew G. Knepley .  t            - The current time
8307ece3a9fcSMatthew G. Knepley .  x            - The coordinates of this point
8308ece3a9fcSMatthew G. Knepley .  n            - The face normal
8309ece3a9fcSMatthew G. Knepley .  numConstants - The number of constants
8310ece3a9fcSMatthew G. Knepley .  constants    - The value of each constant
8311ece3a9fcSMatthew G. Knepley -  f            - The value of the function at this point in space
8312ece3a9fcSMatthew G. Knepley 
8313ece3a9fcSMatthew G. Knepley   Note:
8314bb7acecfSBarry 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.
8315bb7acecfSBarry 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
8316bb7acecfSBarry 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
8317ece3a9fcSMatthew 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.
8318ece3a9fcSMatthew G. Knepley 
8319ece3a9fcSMatthew G. Knepley   Level: intermediate
8320ece3a9fcSMatthew G. Knepley 
8321bb7acecfSBarry Smith   Developer Notes:
8322bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8323bb7acecfSBarry Smith 
8324bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8325bb7acecfSBarry Smith 
8326db781477SPatrick Sanan .seealso: `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8327ece3a9fcSMatthew G. Knepley @*/
8328d71ae5a4SJacob 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)
8329d71ae5a4SJacob Faibussowitsch {
8330ece3a9fcSMatthew G. Knepley   PetscFunctionBegin;
8331ece3a9fcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8332064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8333064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
83349566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
83353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8336ece3a9fcSMatthew G. Knepley }
8337ece3a9fcSMatthew G. Knepley 
8338ece3a9fcSMatthew G. Knepley /*@C
83392716604bSToby Isaac   DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
83402716604bSToby Isaac 
834120f4b53cSBarry Smith   Collective
8342bb7acecfSBarry Smith 
83432716604bSToby Isaac   Input Parameters:
8344bb7acecfSBarry Smith + dm    - The `DM`
83450709b2feSToby Isaac . time  - The time
83462716604bSToby Isaac . funcs - The functions to evaluate for each field component
83472716604bSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8348574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
83492716604bSToby Isaac 
83502716604bSToby Isaac   Output Parameter:
83512716604bSToby Isaac . diff - The diff ||u - u_h||_2
83522716604bSToby Isaac 
83532716604bSToby Isaac   Level: developer
83542716604bSToby Isaac 
8355bb7acecfSBarry Smith   Developer Notes:
8356bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8357bb7acecfSBarry Smith 
8358bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8359bb7acecfSBarry Smith 
8360db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
83612716604bSToby Isaac @*/
8362d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
8363d71ae5a4SJacob Faibussowitsch {
83642716604bSToby Isaac   PetscFunctionBegin;
83652716604bSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8366b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
83679566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2diff)(dm, time, funcs, ctxs, X, diff));
83683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83692716604bSToby Isaac }
8370b698f381SToby Isaac 
8371b698f381SToby Isaac /*@C
8372b698f381SToby Isaac   DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
8373b698f381SToby Isaac 
837420f4b53cSBarry Smith   Collective
8375d083f849SBarry Smith 
8376b698f381SToby Isaac   Input Parameters:
8377bb7acecfSBarry Smith + dm    - The `DM`
8378b698f381SToby Isaac , time  - The time
8379b698f381SToby Isaac . funcs - The gradient functions to evaluate for each field component
8380b698f381SToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8381574a98acSMatthew G. Knepley . X     - The coefficient vector u_h, a global vector
8382b698f381SToby Isaac - n     - The vector to project along
8383b698f381SToby Isaac 
8384b698f381SToby Isaac   Output Parameter:
8385b698f381SToby Isaac . diff - The diff ||(grad u - grad u_h) . n||_2
8386b698f381SToby Isaac 
8387b698f381SToby Isaac   Level: developer
8388b698f381SToby Isaac 
8389bb7acecfSBarry Smith   Developer Notes:
8390bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8391bb7acecfSBarry Smith 
8392bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8393bb7acecfSBarry Smith 
8394bb7acecfSBarry Smith .seealso: `DMProjectFunction()`, `DMComputeL2Diff()`, `DMComputeL2FieldDiff()`
8395b698f381SToby Isaac @*/
8396d71ae5a4SJacob 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)
8397d71ae5a4SJacob Faibussowitsch {
8398b698f381SToby Isaac   PetscFunctionBegin;
8399b698f381SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8400b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
84019566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2gradientdiff)(dm, time, funcs, ctxs, X, n, diff));
84023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8403b698f381SToby Isaac }
8404b698f381SToby Isaac 
84052a16baeaSToby Isaac /*@C
84062a16baeaSToby Isaac   DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
84072a16baeaSToby Isaac 
840820f4b53cSBarry Smith   Collective
8409d083f849SBarry Smith 
84102a16baeaSToby Isaac   Input Parameters:
8411bb7acecfSBarry Smith + dm    - The `DM`
84122a16baeaSToby Isaac . time  - The time
84132a16baeaSToby Isaac . funcs - The functions to evaluate for each field component
84142a16baeaSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8415574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
84162a16baeaSToby Isaac 
84172a16baeaSToby Isaac   Output Parameter:
84182a16baeaSToby Isaac . diff - The array of differences, ||u^f - u^f_h||_2
84192a16baeaSToby Isaac 
84202a16baeaSToby Isaac   Level: developer
84212a16baeaSToby Isaac 
8422bb7acecfSBarry Smith   Developer Notes:
8423bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8424bb7acecfSBarry Smith 
8425bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8426bb7acecfSBarry Smith 
8427db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
84282a16baeaSToby Isaac @*/
8429d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
8430d71ae5a4SJacob Faibussowitsch {
84312a16baeaSToby Isaac   PetscFunctionBegin;
84322a16baeaSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84332a16baeaSToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
84349566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2fielddiff)(dm, time, funcs, ctxs, X, diff));
84353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84362a16baeaSToby Isaac }
84372a16baeaSToby Isaac 
8438df0b854cSToby Isaac /*@C
8439bb7acecfSBarry Smith  DMGetNeighbors - Gets an array containing the MPI ranks of all the processes neighbors
8440502a2867SDave May 
8441502a2867SDave May  Not Collective
8442502a2867SDave May 
8443502a2867SDave May  Input Parameter:
8444bb7acecfSBarry Smith .  dm    - The `DM`
8445502a2867SDave May 
84460a19bb7dSprj-  Output Parameters:
84470a19bb7dSprj- +  nranks - the number of neighbours
84480a19bb7dSprj- -  ranks - the neighbors ranks
8449502a2867SDave May 
8450bb7acecfSBarry Smith  Note:
8451bb7acecfSBarry Smith  Do not free the array, it is freed when the `DM` is destroyed.
8452502a2867SDave May 
8453502a2867SDave May  Level: beginner
8454502a2867SDave May 
8455db781477SPatrick Sanan  .seealso: `DMDAGetNeighbors()`, `PetscSFGetRootRanks()`
8456502a2867SDave May @*/
8457d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNeighbors(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
8458d71ae5a4SJacob Faibussowitsch {
8459502a2867SDave May   PetscFunctionBegin;
8460502a2867SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84619566063dSJacob Faibussowitsch   PetscCall((dm->ops->getneighbors)(dm, nranks, ranks));
84623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8463502a2867SDave May }
8464502a2867SDave May 
8465531c7667SBarry Smith #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
8466531c7667SBarry Smith 
8467531c7667SBarry Smith /*
8468531c7667SBarry Smith     Converts the input vector to a ghosted vector and then calls the standard coloring code.
8469531c7667SBarry Smith     This has be a different function because it requires DM which is not defined in the Mat library
8470531c7667SBarry Smith */
8471d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringApply_AIJDM(Mat J, MatFDColoring coloring, Vec x1, void *sctx)
8472d71ae5a4SJacob Faibussowitsch {
8473531c7667SBarry Smith   PetscFunctionBegin;
8474531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8475531c7667SBarry Smith     Vec x1local;
8476531c7667SBarry Smith     DM  dm;
84779566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
84787a8be351SBarry Smith     PetscCheck(dm, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_INCOMP, "IS_COLORING_LOCAL requires a DM");
84799566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &x1local));
84809566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, x1, INSERT_VALUES, x1local));
84819566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, x1, INSERT_VALUES, x1local));
8482531c7667SBarry Smith     x1 = x1local;
8483531c7667SBarry Smith   }
84849566063dSJacob Faibussowitsch   PetscCall(MatFDColoringApply_AIJ(J, coloring, x1, sctx));
8485531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8486531c7667SBarry Smith     DM dm;
84879566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
84889566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &x1));
8489531c7667SBarry Smith   }
84903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8491531c7667SBarry Smith }
8492531c7667SBarry Smith 
8493531c7667SBarry Smith /*@
8494bb7acecfSBarry Smith     MatFDColoringUseDM - allows a `MatFDColoring` object to use the `DM` associated with the matrix to compute a `IS_COLORING_LOCAL` coloring
8495531c7667SBarry Smith 
8496531c7667SBarry Smith     Input Parameter:
8497bb7acecfSBarry Smith .    coloring - the `MatFDColoring` object
8498531c7667SBarry Smith 
8499bb7acecfSBarry Smith     Developer Note:
8500bb7acecfSBarry Smith     this routine exists because the PETSc `Mat` library does not know about the `DM` objects
8501531c7667SBarry Smith 
85021b266c99SBarry Smith     Level: advanced
85031b266c99SBarry Smith 
8504db781477SPatrick Sanan .seealso: `MatFDColoring`, `MatFDColoringCreate()`, `ISColoringType`
8505531c7667SBarry Smith @*/
8506d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringUseDM(Mat coloring, MatFDColoring fdcoloring)
8507d71ae5a4SJacob Faibussowitsch {
8508531c7667SBarry Smith   PetscFunctionBegin;
8509531c7667SBarry Smith   coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
85103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8511531c7667SBarry Smith }
85128320bc6fSPatrick Sanan 
85138320bc6fSPatrick Sanan /*@
8514bb7acecfSBarry Smith     DMGetCompatibility - determine if two `DM`s are compatible
85158320bc6fSPatrick Sanan 
85168320bc6fSPatrick Sanan     Collective
85178320bc6fSPatrick Sanan 
85188320bc6fSPatrick Sanan     Input Parameters:
8519bb7acecfSBarry Smith +    dm1 - the first `DM`
8520bb7acecfSBarry Smith -    dm2 - the second `DM`
85218320bc6fSPatrick Sanan 
85228320bc6fSPatrick Sanan     Output Parameters:
8523bb7acecfSBarry Smith +    compatible - whether or not the two `DM`s are compatible
8524bb7acecfSBarry Smith -    set - whether or not the compatible value was actually determined and set
85258320bc6fSPatrick Sanan 
852620f4b53cSBarry Smith     Level: advanced
852720f4b53cSBarry Smith 
85288320bc6fSPatrick Sanan     Notes:
8529bb7acecfSBarry Smith     Two `DM`s are deemed compatible if they represent the same parallel decomposition
85303d862458SPatrick Sanan     of the same topology. This implies that the section (field data) on one
85318320bc6fSPatrick Sanan     "makes sense" with respect to the topology and parallel decomposition of the other.
8532bb7acecfSBarry Smith     Loosely speaking, compatible `DM`s represent the same domain and parallel
85333d862458SPatrick Sanan     decomposition, but hold different data.
85348320bc6fSPatrick Sanan 
85358320bc6fSPatrick Sanan     Typically, one would confirm compatibility if intending to simultaneously iterate
8536bb7acecfSBarry Smith     over a pair of vectors obtained from different `DM`s.
85378320bc6fSPatrick Sanan 
8538bb7acecfSBarry Smith     For example, two `DMDA` objects are compatible if they have the same local
85398320bc6fSPatrick Sanan     and global sizes and the same stencil width. They can have different numbers
85408320bc6fSPatrick Sanan     of degrees of freedom per node. Thus, one could use the node numbering from
8541bb7acecfSBarry Smith     either `DM` in bounds for a loop over vectors derived from either `DM`.
85428320bc6fSPatrick Sanan 
8543bb7acecfSBarry Smith     Consider the operation of summing data living on a 2-dof `DMDA` to data living
8544bb7acecfSBarry Smith     on a 1-dof `DMDA`, which should be compatible, as in the following snippet.
85458320bc6fSPatrick Sanan .vb
85468320bc6fSPatrick Sanan   ...
85479566063dSJacob Faibussowitsch   PetscCall(DMGetCompatibility(da1,da2,&compatible,&set));
85488320bc6fSPatrick Sanan   if (set && compatible)  {
85499566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da1,vec1,&arr1));
85509566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da2,vec2,&arr2));
85519566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL));
85528320bc6fSPatrick Sanan     for (j=y; j<y+n; ++j) {
85538320bc6fSPatrick Sanan       for (i=x; i<x+m, ++i) {
85548320bc6fSPatrick Sanan         arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1];
85558320bc6fSPatrick Sanan       }
85568320bc6fSPatrick Sanan     }
85579566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da1,vec1,&arr1));
85589566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da2,vec2,&arr2));
85598320bc6fSPatrick Sanan   } else {
85608320bc6fSPatrick Sanan     SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible");
85618320bc6fSPatrick Sanan   }
85628320bc6fSPatrick Sanan   ...
85638320bc6fSPatrick Sanan .ve
85648320bc6fSPatrick Sanan 
8565bb7acecfSBarry Smith     Checking compatibility might be expensive for a given implementation of `DM`,
85668320bc6fSPatrick Sanan     or might be impossible to unambiguously confirm or deny. For this reason,
85678320bc6fSPatrick Sanan     this function may decline to determine compatibility, and hence users should
85688320bc6fSPatrick Sanan     always check the "set" output parameter.
85698320bc6fSPatrick Sanan 
8570bb7acecfSBarry Smith     A `DM` is always compatible with itself.
85718320bc6fSPatrick Sanan 
8572bb7acecfSBarry Smith     In the current implementation, `DM`s which live on "unequal" communicators
85738320bc6fSPatrick Sanan     (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed
85748320bc6fSPatrick Sanan     incompatible.
85758320bc6fSPatrick Sanan 
85768320bc6fSPatrick Sanan     This function is labeled "Collective," as information about all subdomains
8577bb7acecfSBarry Smith     is required on each rank. However, in `DM` implementations which store all this
85788320bc6fSPatrick Sanan     information locally, this function may be merely "Logically Collective".
85798320bc6fSPatrick Sanan 
8580bb7acecfSBarry Smith     Developer Note:
8581bb7acecfSBarry Smith     Compatibility is assumed to be a symmetric concept; `DM` A is compatible with `DM` B
85823d862458SPatrick Sanan     iff B is compatible with A. Thus, this function checks the implementations
8583a5bc1bf3SBarry Smith     of both dm and dmc (if they are of different types), attempting to determine
8584bb7acecfSBarry Smith     compatibility. It is left to `DM` implementers to ensure that symmetry is
85858320bc6fSPatrick Sanan     preserved. The simplest way to do this is, when implementing type-specific
85863d862458SPatrick Sanan     logic for this function, is to check for existing logic in the implementation
8587bb7acecfSBarry Smith     of other `DM` types and let *set = PETSC_FALSE if found.
85888320bc6fSPatrick Sanan 
8589db781477SPatrick Sanan .seealso: `DM`, `DMDACreateCompatibleDMDA()`, `DMStagCreateCompatibleDMStag()`
85908320bc6fSPatrick Sanan @*/
8591d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCompatibility(DM dm1, DM dm2, PetscBool *compatible, PetscBool *set)
8592d71ae5a4SJacob Faibussowitsch {
85938320bc6fSPatrick Sanan   PetscMPIInt compareResult;
85948320bc6fSPatrick Sanan   DMType      type, type2;
85958320bc6fSPatrick Sanan   PetscBool   sameType;
85968320bc6fSPatrick Sanan 
85978320bc6fSPatrick Sanan   PetscFunctionBegin;
8598a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dm1, DM_CLASSID, 1);
85998320bc6fSPatrick Sanan   PetscValidHeaderSpecific(dm2, DM_CLASSID, 2);
86008320bc6fSPatrick Sanan 
86018320bc6fSPatrick Sanan   /* Declare a DM compatible with itself */
8602a5bc1bf3SBarry Smith   if (dm1 == dm2) {
86038320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
86048320bc6fSPatrick Sanan     *compatible = PETSC_TRUE;
86053ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
86068320bc6fSPatrick Sanan   }
86078320bc6fSPatrick Sanan 
86088320bc6fSPatrick Sanan   /* Declare a DM incompatible with a DM that lives on an "unequal"
86098320bc6fSPatrick Sanan      communicator. Note that this does not preclude compatibility with
86108320bc6fSPatrick Sanan      DMs living on "congruent" or "similar" communicators, but this must be
86118320bc6fSPatrick Sanan      determined by the implementation-specific logic */
86129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)dm1), PetscObjectComm((PetscObject)dm2), &compareResult));
86138320bc6fSPatrick Sanan   if (compareResult == MPI_UNEQUAL) {
86148320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
86158320bc6fSPatrick Sanan     *compatible = PETSC_FALSE;
86163ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
86178320bc6fSPatrick Sanan   }
86188320bc6fSPatrick Sanan 
86198320bc6fSPatrick Sanan   /* Pass to the implementation-specific routine, if one exists. */
8620a5bc1bf3SBarry Smith   if (dm1->ops->getcompatibility) {
8621dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm1, getcompatibility, dm2, compatible, set);
86223ba16761SJacob Faibussowitsch     if (*set) PetscFunctionReturn(PETSC_SUCCESS);
86238320bc6fSPatrick Sanan   }
86248320bc6fSPatrick Sanan 
8625a5bc1bf3SBarry Smith   /* If dm1 and dm2 are of different types, then attempt to check compatibility
86268320bc6fSPatrick Sanan      with an implementation of this function from dm2 */
86279566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm1, &type));
86289566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm2, &type2));
86299566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(type, type2, &sameType));
86308320bc6fSPatrick Sanan   if (!sameType && dm2->ops->getcompatibility) {
8631dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm2, getcompatibility, dm1, compatible, set); /* Note argument order */
86328320bc6fSPatrick Sanan   } else {
86338320bc6fSPatrick Sanan     *set = PETSC_FALSE;
86348320bc6fSPatrick Sanan   }
86353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86368320bc6fSPatrick Sanan }
8637c0f0dcc3SMatthew G. Knepley 
8638c0f0dcc3SMatthew G. Knepley /*@C
8639bb7acecfSBarry Smith   DMMonitorSet - Sets an additional monitor function that is to be used after a solve to monitor discretization performance.
8640c0f0dcc3SMatthew G. Knepley 
864120f4b53cSBarry Smith   Logically Collective
8642c0f0dcc3SMatthew G. Knepley 
8643c0f0dcc3SMatthew G. Knepley   Input Parameters:
8644bb7acecfSBarry Smith + DM - the `DM`
8645c0f0dcc3SMatthew G. Knepley . f - the monitor function
864620f4b53cSBarry Smith . mctx - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
864720f4b53cSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
8648c0f0dcc3SMatthew G. Knepley 
864920f4b53cSBarry Smith   Options Database Key:
8650bb7acecfSBarry Smith - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `DMMonitorSet()`, but
8651c0f0dcc3SMatthew G. Knepley                             does not cancel those set via the options database.
8652c0f0dcc3SMatthew G. Knepley 
8653bb7acecfSBarry Smith   Note:
8654c0f0dcc3SMatthew G. Knepley   Several different monitoring routines may be set by calling
8655bb7acecfSBarry Smith   `DMMonitorSet()` multiple times or with `DMMonitorSetFromOptions()`; all will be called in the
8656c0f0dcc3SMatthew G. Knepley   order in which they were set.
8657c0f0dcc3SMatthew G. Knepley 
8658bb7acecfSBarry Smith   Fortran Note:
8659bb7acecfSBarry Smith   Only a single monitor function can be set for each `DM` object
8660bb7acecfSBarry Smith 
8661bb7acecfSBarry Smith   Developer Note:
8662bb7acecfSBarry Smith   This API has a generic name but seems specific to a very particular aspect of the use of `DM`
8663c0f0dcc3SMatthew G. Knepley 
8664c0f0dcc3SMatthew G. Knepley   Level: intermediate
8665c0f0dcc3SMatthew G. Knepley 
8666bb7acecfSBarry Smith .seealso: `DMMonitorCancel()`, `DMMonitorSetFromOptions()`, `DMMonitor()`
8667c0f0dcc3SMatthew G. Knepley @*/
8668d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
8669d71ae5a4SJacob Faibussowitsch {
8670c0f0dcc3SMatthew G. Knepley   PetscInt m;
8671c0f0dcc3SMatthew G. Knepley 
8672c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8673c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8674c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
8675c0f0dcc3SMatthew G. Knepley     PetscBool identical;
8676c0f0dcc3SMatthew G. Knepley 
86779566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical));
86783ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
8679c0f0dcc3SMatthew G. Knepley   }
86807a8be351SBarry Smith   PetscCheck(dm->numbermonitors < MAXDMMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
8681c0f0dcc3SMatthew G. Knepley   dm->monitor[dm->numbermonitors]          = f;
8682c0f0dcc3SMatthew G. Knepley   dm->monitordestroy[dm->numbermonitors]   = monitordestroy;
8683c0f0dcc3SMatthew G. Knepley   dm->monitorcontext[dm->numbermonitors++] = (void *)mctx;
86843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8685c0f0dcc3SMatthew G. Knepley }
8686c0f0dcc3SMatthew G. Knepley 
8687c0f0dcc3SMatthew G. Knepley /*@
8688bb7acecfSBarry Smith   DMMonitorCancel - Clears all the monitor functions for a `DM` object.
8689c0f0dcc3SMatthew G. Knepley 
869020f4b53cSBarry Smith   Logically Collective
8691c0f0dcc3SMatthew G. Knepley 
8692c0f0dcc3SMatthew G. Knepley   Input Parameter:
8693c0f0dcc3SMatthew G. Knepley . dm - the DM
8694c0f0dcc3SMatthew G. Knepley 
8695c0f0dcc3SMatthew G. Knepley   Options Database Key:
8696c0f0dcc3SMatthew G. Knepley . -dm_monitor_cancel - cancels all monitors that have been hardwired
8697bb7acecfSBarry Smith   into a code by calls to `DMonitorSet()`, but does not cancel those
8698c0f0dcc3SMatthew G. Knepley   set via the options database
8699c0f0dcc3SMatthew G. Knepley 
8700bb7acecfSBarry Smith   Note:
8701bb7acecfSBarry Smith   There is no way to clear one specific monitor from a `DM` object.
8702c0f0dcc3SMatthew G. Knepley 
8703c0f0dcc3SMatthew G. Knepley   Level: intermediate
8704c0f0dcc3SMatthew G. Knepley 
8705bb7acecfSBarry Smith .seealso: `DMMonitorSet()`, `DMMonitorSetFromOptions()`, `DMMonitor()`
8706c0f0dcc3SMatthew G. Knepley @*/
8707d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorCancel(DM dm)
8708d71ae5a4SJacob Faibussowitsch {
8709c0f0dcc3SMatthew G. Knepley   PetscInt m;
8710c0f0dcc3SMatthew G. Knepley 
8711c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8712c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8713c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
87149566063dSJacob Faibussowitsch     if (dm->monitordestroy[m]) PetscCall((*dm->monitordestroy[m])(&dm->monitorcontext[m]));
8715c0f0dcc3SMatthew G. Knepley   }
8716c0f0dcc3SMatthew G. Knepley   dm->numbermonitors = 0;
87173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8718c0f0dcc3SMatthew G. Knepley }
8719c0f0dcc3SMatthew G. Knepley 
8720c0f0dcc3SMatthew G. Knepley /*@C
8721c0f0dcc3SMatthew G. Knepley   DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
8722c0f0dcc3SMatthew G. Knepley 
872320f4b53cSBarry Smith   Collective
8724c0f0dcc3SMatthew G. Knepley 
8725c0f0dcc3SMatthew G. Knepley   Input Parameters:
8726bb7acecfSBarry Smith + dm   - `DM` object you wish to monitor
8727c0f0dcc3SMatthew G. Knepley . name - the monitor type one is seeking
8728c0f0dcc3SMatthew G. Knepley . help - message indicating what monitoring is done
8729c0f0dcc3SMatthew G. Knepley . manual - manual page for the monitor
8730c0f0dcc3SMatthew G. Knepley . monitor - the monitor function
8731bb7acecfSBarry 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
8732c0f0dcc3SMatthew G. Knepley 
8733c0f0dcc3SMatthew G. Knepley   Output Parameter:
8734c0f0dcc3SMatthew G. Knepley . flg - Flag set if the monitor was created
8735c0f0dcc3SMatthew G. Knepley 
8736c0f0dcc3SMatthew G. Knepley   Level: developer
8737c0f0dcc3SMatthew G. Knepley 
8738db781477SPatrick Sanan .seealso: `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
8739db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
8740db781477SPatrick Sanan           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
8741db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
8742c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
8743db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
8744bb7acecfSBarry Smith           `PetscOptionsFList()`, `PetscOptionsEList()`, `DMMonitor()`, `DMMonitorSet()`
8745c0f0dcc3SMatthew G. Knepley @*/
8746d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg)
8747d71ae5a4SJacob Faibussowitsch {
8748c0f0dcc3SMatthew G. Knepley   PetscViewer       viewer;
8749c0f0dcc3SMatthew G. Knepley   PetscViewerFormat format;
8750c0f0dcc3SMatthew G. Knepley 
8751c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8752c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)dm), ((PetscObject)dm)->options, ((PetscObject)dm)->prefix, name, &viewer, &format, flg));
8754c0f0dcc3SMatthew G. Knepley   if (*flg) {
8755c0f0dcc3SMatthew G. Knepley     PetscViewerAndFormat *vf;
8756c0f0dcc3SMatthew G. Knepley 
87579566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
87589566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)viewer));
87599566063dSJacob Faibussowitsch     if (monitorsetup) PetscCall((*monitorsetup)(dm, vf));
87609566063dSJacob Faibussowitsch     PetscCall(DMMonitorSet(dm, (PetscErrorCode(*)(DM, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
8761c0f0dcc3SMatthew G. Knepley   }
87623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8763c0f0dcc3SMatthew G. Knepley }
8764c0f0dcc3SMatthew G. Knepley 
8765c0f0dcc3SMatthew G. Knepley /*@
8766c0f0dcc3SMatthew G. Knepley    DMMonitor - runs the user provided monitor routines, if they exist
8767c0f0dcc3SMatthew G. Knepley 
876820f4b53cSBarry Smith    Collective
8769c0f0dcc3SMatthew G. Knepley 
8770c0f0dcc3SMatthew G. Knepley    Input Parameters:
8771bb7acecfSBarry Smith .  dm - The `DM`
8772c0f0dcc3SMatthew G. Knepley 
8773c0f0dcc3SMatthew G. Knepley    Level: developer
8774c0f0dcc3SMatthew G. Knepley 
8775bb7acecfSBarry Smith    Question:
8776bb7acecfSBarry 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
8777bb7acecfSBarry Smith    since some `DM` have no concept of discretization
8778bb7acecfSBarry Smith 
8779bb7acecfSBarry Smith .seealso: `DMMonitorSet()`, `DMMonitorSetFromOptions()`
8780c0f0dcc3SMatthew G. Knepley @*/
8781d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitor(DM dm)
8782d71ae5a4SJacob Faibussowitsch {
8783c0f0dcc3SMatthew G. Knepley   PetscInt m;
8784c0f0dcc3SMatthew G. Knepley 
8785c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
87863ba16761SJacob Faibussowitsch   if (!dm) PetscFunctionReturn(PETSC_SUCCESS);
8787c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
878848a46eb9SPierre Jolivet   for (m = 0; m < dm->numbermonitors; ++m) PetscCall((*dm->monitor[m])(dm, dm->monitorcontext[m]));
87893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8790c0f0dcc3SMatthew G. Knepley }
87912e4af2aeSMatthew G. Knepley 
87922e4af2aeSMatthew G. Knepley /*@
8793bb7acecfSBarry Smith   DMComputeError - Computes the error assuming the user has provided the exact solution functions
87942e4af2aeSMatthew G. Knepley 
879520f4b53cSBarry Smith   Collective
87962e4af2aeSMatthew G. Knepley 
87972e4af2aeSMatthew G. Knepley   Input Parameters:
8798bb7acecfSBarry Smith + dm     - The `DM`
87996b867d5aSJose E. Roman - sol    - The solution vector
88002e4af2aeSMatthew G. Knepley 
88016b867d5aSJose E. Roman   Input/Output Parameter:
880220f4b53cSBarry Smith . errors - An array of length Nf, the number of fields, or `NULL` for no output; on output
88036b867d5aSJose E. Roman            contains the error in each field
88046b867d5aSJose E. Roman 
88056b867d5aSJose E. Roman   Output Parameter:
880620f4b53cSBarry Smith . errorVec - A vector to hold the cellwise error (may be `NULL`)
880720f4b53cSBarry Smith 
880820f4b53cSBarry Smith   Level: developer
88092e4af2aeSMatthew G. Knepley 
8810bb7acecfSBarry Smith   Note:
8811bb7acecfSBarry Smith   The exact solutions come from the `PetscDS` object, and the time comes from `DMGetOutputSequenceNumber()`.
88122e4af2aeSMatthew G. Knepley 
8813db781477SPatrick Sanan .seealso: `DMMonitorSet()`, `DMGetRegionNumDS()`, `PetscDSGetExactSolution()`, `DMGetOutputSequenceNumber()`
88142e4af2aeSMatthew G. Knepley @*/
8815d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec)
8816d71ae5a4SJacob Faibussowitsch {
88172e4af2aeSMatthew G. Knepley   PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
88182e4af2aeSMatthew G. Knepley   void    **ctxs;
88192e4af2aeSMatthew G. Knepley   PetscReal time;
88202e4af2aeSMatthew G. Knepley   PetscInt  Nf, f, Nds, s;
88212e4af2aeSMatthew G. Knepley 
88222e4af2aeSMatthew G. Knepley   PetscFunctionBegin;
88239566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
88249566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(Nf, &exactSol, Nf, &ctxs));
88259566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
88262e4af2aeSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
88272e4af2aeSMatthew G. Knepley     PetscDS         ds;
88282e4af2aeSMatthew G. Knepley     DMLabel         label;
88292e4af2aeSMatthew G. Knepley     IS              fieldIS;
88302e4af2aeSMatthew G. Knepley     const PetscInt *fields;
88312e4af2aeSMatthew G. Knepley     PetscInt        dsNf;
88322e4af2aeSMatthew G. Knepley 
88339566063dSJacob Faibussowitsch     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds));
88349566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
88359566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISGetIndices(fieldIS, &fields));
88362e4af2aeSMatthew G. Knepley     for (f = 0; f < dsNf; ++f) {
88372e4af2aeSMatthew G. Knepley       const PetscInt field = fields[f];
88389566063dSJacob Faibussowitsch       PetscCall(PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]));
88392e4af2aeSMatthew G. Knepley     }
88409566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISRestoreIndices(fieldIS, &fields));
88412e4af2aeSMatthew G. Knepley   }
8842ad540459SPierre 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);
88439566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
88449566063dSJacob Faibussowitsch   if (errors) PetscCall(DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors));
88452e4af2aeSMatthew G. Knepley   if (errorVec) {
88462e4af2aeSMatthew G. Knepley     DM             edm;
88472e4af2aeSMatthew G. Knepley     DMPolytopeType ct;
88482e4af2aeSMatthew G. Knepley     PetscBool      simplex;
88492e4af2aeSMatthew G. Knepley     PetscInt       dim, cStart, Nf;
88502e4af2aeSMatthew G. Knepley 
88519566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &edm));
88529566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(edm, &dim));
88539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
88549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cStart, &ct));
88552e4af2aeSMatthew G. Knepley     simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
88569566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
88572e4af2aeSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
88582e4af2aeSMatthew G. Knepley       PetscFE         fe, efe;
88592e4af2aeSMatthew G. Knepley       PetscQuadrature q;
88602e4af2aeSMatthew G. Knepley       const char     *name;
88612e4af2aeSMatthew G. Knepley 
88629566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe));
88639566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe));
88649566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)fe, &name));
88659566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)efe, name));
88669566063dSJacob Faibussowitsch       PetscCall(PetscFEGetQuadrature(fe, &q));
88679566063dSJacob Faibussowitsch       PetscCall(PetscFESetQuadrature(efe, q));
88689566063dSJacob Faibussowitsch       PetscCall(DMSetField(edm, f, NULL, (PetscObject)efe));
88699566063dSJacob Faibussowitsch       PetscCall(PetscFEDestroy(&efe));
88702e4af2aeSMatthew G. Knepley     }
88719566063dSJacob Faibussowitsch     PetscCall(DMCreateDS(edm));
88722e4af2aeSMatthew G. Knepley 
88739566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(edm, errorVec));
88749566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*errorVec, "Error"));
88759566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec));
88769566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&edm));
88772e4af2aeSMatthew G. Knepley   }
88789566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exactSol, ctxs));
88793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
88802e4af2aeSMatthew G. Knepley }
88819a2a23afSMatthew G. Knepley 
88829a2a23afSMatthew G. Knepley /*@
8883bb7acecfSBarry Smith   DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this `DM`
88849a2a23afSMatthew G. Knepley 
888520f4b53cSBarry Smith   Not Collective
88869a2a23afSMatthew G. Knepley 
88879a2a23afSMatthew G. Knepley   Input Parameter:
8888bb7acecfSBarry Smith . dm     - The `DM`
88899a2a23afSMatthew G. Knepley 
88909a2a23afSMatthew G. Knepley   Output Parameter:
8891a5b23f4aSJose E. Roman . numAux - The number of auxiliary data vectors
88929a2a23afSMatthew G. Knepley 
88939a2a23afSMatthew G. Knepley   Level: advanced
88949a2a23afSMatthew G. Knepley 
8895bb7acecfSBarry Smith .seealso: `DMSetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
88969a2a23afSMatthew G. Knepley @*/
8897d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux)
8898d71ae5a4SJacob Faibussowitsch {
88999a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89009a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89019566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetSize(dm->auxData, numAux));
89023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
89039a2a23afSMatthew G. Knepley }
89049a2a23afSMatthew G. Knepley 
89059a2a23afSMatthew G. Knepley /*@
8906ac17215fSMatthew G. Knepley   DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value, and equation part
89079a2a23afSMatthew G. Knepley 
890820f4b53cSBarry Smith   Not Collective
89099a2a23afSMatthew G. Knepley 
89109a2a23afSMatthew G. Knepley   Input Parameters:
8911bb7acecfSBarry Smith + dm     - The `DM`
8912bb7acecfSBarry Smith . label  - The `DMLabel`
8913ac17215fSMatthew G. Knepley . value  - The label value indicating the region
8914ac17215fSMatthew G. Knepley - part   - The equation part, or 0 if unused
89159a2a23afSMatthew G. Knepley 
89169a2a23afSMatthew G. Knepley   Output Parameter:
8917bb7acecfSBarry Smith . aux    - The `Vec` holding auxiliary field data
89189a2a23afSMatthew G. Knepley 
8919bb7acecfSBarry Smith   Note:
8920bb7acecfSBarry Smith   If no auxiliary vector is found for this (label, value), (NULL, 0, 0) is checked as well.
892104c51a94SMatthew G. Knepley 
89229a2a23afSMatthew G. Knepley   Level: advanced
89239a2a23afSMatthew G. Knepley 
8924bb7acecfSBarry Smith .seealso: `DMSetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryLabels()`
89259a2a23afSMatthew G. Knepley @*/
8926d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec *aux)
8927d71ae5a4SJacob Faibussowitsch {
8928ac17215fSMatthew G. Knepley   PetscHashAuxKey key, wild = {NULL, 0, 0};
892904c51a94SMatthew G. Knepley   PetscBool       has;
89309a2a23afSMatthew G. Knepley 
89319a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89329a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89339a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
89349a2a23afSMatthew G. Knepley   key.label = label;
89359a2a23afSMatthew G. Knepley   key.value = value;
8936ac17215fSMatthew G. Knepley   key.part  = part;
89379566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxHas(dm->auxData, key, &has));
89389566063dSJacob Faibussowitsch   if (has) PetscCall(PetscHMapAuxGet(dm->auxData, key, aux));
89399566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxGet(dm->auxData, wild, aux));
89403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
89419a2a23afSMatthew G. Knepley }
89429a2a23afSMatthew G. Knepley 
89439a2a23afSMatthew G. Knepley /*@
8944bb7acecfSBarry Smith   DMSetAuxiliaryVec - Set an auxiliary vector for region specified by the given label and value, and equation part
89459a2a23afSMatthew G. Knepley 
894620f4b53cSBarry Smith   Not Collective because auxiliary vectors are not parallel
89479a2a23afSMatthew G. Knepley 
89489a2a23afSMatthew G. Knepley   Input Parameters:
8949bb7acecfSBarry Smith + dm     - The `DM`
8950bb7acecfSBarry Smith . label  - The `DMLabel`
89519a2a23afSMatthew G. Knepley . value  - The label value indicating the region
8952ac17215fSMatthew G. Knepley . part   - The equation part, or 0 if unused
8953bb7acecfSBarry Smith - aux    - The `Vec` holding auxiliary field data
89549a2a23afSMatthew G. Knepley 
89559a2a23afSMatthew G. Knepley   Level: advanced
89569a2a23afSMatthew G. Knepley 
8957bb7acecfSBarry Smith .seealso: `DMGetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMCopyAuxiliaryVec()`
89589a2a23afSMatthew G. Knepley @*/
8959d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec aux)
8960d71ae5a4SJacob Faibussowitsch {
89619a2a23afSMatthew G. Knepley   Vec             old;
89629a2a23afSMatthew G. Knepley   PetscHashAuxKey key;
89639a2a23afSMatthew G. Knepley 
89649a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89659a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89669a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
89679a2a23afSMatthew G. Knepley   key.label = label;
89689a2a23afSMatthew G. Knepley   key.value = value;
8969ac17215fSMatthew G. Knepley   key.part  = part;
89709566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGet(dm->auxData, key, &old));
89719566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)aux));
89729566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)old));
89739566063dSJacob Faibussowitsch   if (!aux) PetscCall(PetscHMapAuxDel(dm->auxData, key));
89749566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxSet(dm->auxData, key, aux));
89753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
89769a2a23afSMatthew G. Knepley }
89779a2a23afSMatthew G. Knepley 
89789a2a23afSMatthew G. Knepley /*@C
8979bb7acecfSBarry Smith   DMGetAuxiliaryLabels - Get the labels, values, and parts for all auxiliary vectors in this `DM`
89809a2a23afSMatthew G. Knepley 
898120f4b53cSBarry Smith   Not Collective
89829a2a23afSMatthew G. Knepley 
89839a2a23afSMatthew G. Knepley   Input Parameter:
8984bb7acecfSBarry Smith . dm      - The `DM`
89859a2a23afSMatthew G. Knepley 
89869a2a23afSMatthew G. Knepley   Output Parameters:
8987bb7acecfSBarry Smith + labels  - The `DMLabel`s for each `Vec`
8988bb7acecfSBarry Smith . values  - The label values for each `Vec`
8989bb7acecfSBarry Smith - parts   - The equation parts for each `Vec`
89909a2a23afSMatthew G. Knepley 
8991bb7acecfSBarry Smith   Note:
8992bb7acecfSBarry Smith   The arrays passed in must be at least as large as `DMGetNumAuxiliaryVec()`.
89939a2a23afSMatthew G. Knepley 
89949a2a23afSMatthew G. Knepley   Level: advanced
89959a2a23afSMatthew G. Knepley 
8996bb7acecfSBarry Smith .seealso: `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMSetAuxiliaryVec()`, DMCopyAuxiliaryVec()`
89979a2a23afSMatthew G. Knepley @*/
8998d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[], PetscInt parts[])
8999d71ae5a4SJacob Faibussowitsch {
90009a2a23afSMatthew G. Knepley   PetscHashAuxKey *keys;
90019a2a23afSMatthew G. Knepley   PetscInt         n, i, off = 0;
90029a2a23afSMatthew G. Knepley 
90039a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90049a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90059a2a23afSMatthew G. Knepley   PetscValidPointer(labels, 2);
9006dadcf809SJacob Faibussowitsch   PetscValidIntPointer(values, 3);
9007dadcf809SJacob Faibussowitsch   PetscValidIntPointer(parts, 4);
90089566063dSJacob Faibussowitsch   PetscCall(DMGetNumAuxiliaryVec(dm, &n));
90099566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &keys));
90109566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetKeys(dm->auxData, &off, keys));
90119371c9d4SSatish Balay   for (i = 0; i < n; ++i) {
90129371c9d4SSatish Balay     labels[i] = keys[i].label;
90139371c9d4SSatish Balay     values[i] = keys[i].value;
90149371c9d4SSatish Balay     parts[i]  = keys[i].part;
90159371c9d4SSatish Balay   }
90169566063dSJacob Faibussowitsch   PetscCall(PetscFree(keys));
90173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
90189a2a23afSMatthew G. Knepley }
90199a2a23afSMatthew G. Knepley 
90209a2a23afSMatthew G. Knepley /*@
9021bb7acecfSBarry Smith   DMCopyAuxiliaryVec - Copy the auxiliary vector data on a `DM` to a new `DM`
90229a2a23afSMatthew G. Knepley 
902320f4b53cSBarry Smith   Not Collective
90249a2a23afSMatthew G. Knepley 
90259a2a23afSMatthew G. Knepley   Input Parameter:
9026bb7acecfSBarry Smith . dm    - The `DM`
90279a2a23afSMatthew G. Knepley 
90289a2a23afSMatthew G. Knepley   Output Parameter:
9029bb7acecfSBarry Smith . dmNew - The new `DM`, now with the same auxiliary data
90309a2a23afSMatthew G. Knepley 
90319a2a23afSMatthew G. Knepley   Level: advanced
90329a2a23afSMatthew G. Knepley 
9033bb7acecfSBarry Smith   Note:
9034bb7acecfSBarry Smith   This is a shallow copy of the auxiliary vectors
9035bb7acecfSBarry Smith 
9036db781477SPatrick Sanan .seealso: `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
90379a2a23afSMatthew G. Knepley @*/
9038d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew)
9039d71ae5a4SJacob Faibussowitsch {
90409a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90419a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90429566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDestroy(&dmNew->auxData));
90439566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData));
90443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
90459a2a23afSMatthew G. Knepley }
9046b5a892a1SMatthew G. Knepley 
9047b5a892a1SMatthew G. Knepley /*@C
9048bb7acecfSBarry Smith   DMPolytopeMatchOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9049b5a892a1SMatthew G. Knepley 
905020f4b53cSBarry Smith   Not Collective
9051b5a892a1SMatthew G. Knepley 
9052b5a892a1SMatthew G. Knepley   Input Parameters:
9053bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9054b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9055b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9056b5a892a1SMatthew G. Knepley 
9057b5a892a1SMatthew G. Knepley   Output Parameters:
9058bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9059b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9060b5a892a1SMatthew G. Knepley 
9061b5a892a1SMatthew G. Knepley   Level: advanced
9062b5a892a1SMatthew G. Knepley 
9063bb7acecfSBarry Smith   Note:
9064bb7acecfSBarry Smith   An arrangement is a face order combined with an orientation for each face
9065bb7acecfSBarry Smith 
9066bb7acecfSBarry Smith   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangments(ct)`/2 to `DMPolytopeTypeGetNumArrangments(ct)`/2
9067bb7acecfSBarry Smith   that labels each arrangement (face ordering plus orientation for each face).
9068bb7acecfSBarry Smith 
9069bb7acecfSBarry Smith   See `DMPolytopeMatchVertexOrientation()` to find a new vertex orientation that takes the source vertex arrangement to the target vertex arrangement
9070bb7acecfSBarry Smith 
9071bb7acecfSBarry Smith .seealso: `DMPolytopeGetOrientation()`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetVertexOrientation()`
9072b5a892a1SMatthew G. Knepley @*/
9073d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt, PetscBool *found)
9074d71ae5a4SJacob Faibussowitsch {
9075b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetConeSize(ct);
9076b5a892a1SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct) / 2;
9077b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9078b5a892a1SMatthew G. Knepley 
9079b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
90809371c9d4SSatish Balay   if (!nO) {
90819371c9d4SSatish Balay     *ornt  = 0;
90829371c9d4SSatish Balay     *found = PETSC_TRUE;
90833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
90849371c9d4SSatish Balay   }
9085b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
9086b5a892a1SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
9087b5a892a1SMatthew G. Knepley 
90889371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
90899371c9d4SSatish Balay       if (sourceCone[arr[c * 2]] != targetCone[c]) break;
90909371c9d4SSatish Balay     if (c == cS) {
90919371c9d4SSatish Balay       *ornt = o;
90929371c9d4SSatish Balay       break;
90939371c9d4SSatish Balay     }
9094b5a892a1SMatthew G. Knepley   }
9095b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
90963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9097b5a892a1SMatthew G. Knepley }
9098b5a892a1SMatthew G. Knepley 
9099b5a892a1SMatthew G. Knepley /*@C
9100bb7acecfSBarry Smith   DMPolytopeGetOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9101b5a892a1SMatthew G. Knepley 
910220f4b53cSBarry Smith   Not Collective
9103b5a892a1SMatthew G. Knepley 
9104b5a892a1SMatthew G. Knepley   Input Parameters:
9105bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9106b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9107b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9108b5a892a1SMatthew G. Knepley 
9109b5a892a1SMatthew G. Knepley   Output Parameters:
9110bb7acecfSBarry Smith . ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9111b5a892a1SMatthew G. Knepley 
9112b5a892a1SMatthew G. Knepley   Level: advanced
9113b5a892a1SMatthew G. Knepley 
9114bb7acecfSBarry Smith   Note:
9115bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchOrientation()` except it will generate an error if no suitable orientation can be found.
9116bb7acecfSBarry Smith 
9117bb7acecfSBarry Smith   Developer Note:
9118bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchOrientation()` and error if none is found
9119bb7acecfSBarry Smith 
9120bb7acecfSBarry Smith .seealso: `DMPolytopeType`, `DMPolytopeMatchOrientation()`, `DMPolytopeGetVertexOrientation()`, `DMPolytopeMatchVertexOrientation()`
9121b5a892a1SMatthew G. Knepley @*/
9122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9123d71ae5a4SJacob Faibussowitsch {
9124b5a892a1SMatthew G. Knepley   PetscBool found;
9125b5a892a1SMatthew G. Knepley 
9126b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91279566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchOrientation(ct, sourceCone, targetCone, ornt, &found));
91287a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
91293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9130b5a892a1SMatthew G. Knepley }
9131b5a892a1SMatthew G. Knepley 
9132b5a892a1SMatthew G. Knepley /*@C
9133bb7acecfSBarry Smith   DMPolytopeMatchVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9134b5a892a1SMatthew G. Knepley 
913520f4b53cSBarry Smith   Not Collective
9136b5a892a1SMatthew G. Knepley 
9137b5a892a1SMatthew G. Knepley   Input Parameters:
9138bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9139b5a892a1SMatthew G. Knepley . sourceVert - The source arrangement of vertices
9140b5a892a1SMatthew G. Knepley - targetVert - The target arrangement of vertices
9141b5a892a1SMatthew G. Knepley 
9142b5a892a1SMatthew G. Knepley   Output Parameters:
9143bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9144b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9145b5a892a1SMatthew G. Knepley 
9146b5a892a1SMatthew G. Knepley   Level: advanced
9147b5a892a1SMatthew G. Knepley 
9148bb7acecfSBarry Smith   Note:
9149bb7acecfSBarry Smith   An arrangement is a vertex order
9150bb7acecfSBarry Smith 
9151bb7acecfSBarry Smith   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangments(ct)`/2 to `DMPolytopeTypeGetNumArrangments(ct)`/2
9152bb7acecfSBarry Smith   that labels each arrangement (vertex ordering).
9153bb7acecfSBarry Smith 
9154bb7acecfSBarry Smith   See `DMPolytopeMatchOrientation()` to find a new face orientation that takes the source face arrangement to the target face arrangement
9155bb7acecfSBarry Smith 
9156bb7acecfSBarry Smith .seealso: `DMPolytopeType`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchOrientation()`, `DMPolytopeTypeGetNumVertices()`, `DMPolytopeTypeGetVertexArrangment()`
9157b5a892a1SMatthew G. Knepley @*/
9158d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchVertexOrientation(DMPolytopeType ct, const PetscInt sourceVert[], const PetscInt targetVert[], PetscInt *ornt, PetscBool *found)
9159d71ae5a4SJacob Faibussowitsch {
9160b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetNumVertices(ct);
9161b5a892a1SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct) / 2;
9162b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9163b5a892a1SMatthew G. Knepley 
9164b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91659371c9d4SSatish Balay   if (!nO) {
91669371c9d4SSatish Balay     *ornt  = 0;
91679371c9d4SSatish Balay     *found = PETSC_TRUE;
91683ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
91699371c9d4SSatish Balay   }
9170b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
9171b5a892a1SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetVertexArrangment(ct, o);
9172b5a892a1SMatthew G. Knepley 
91739371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
91749371c9d4SSatish Balay       if (sourceVert[arr[c]] != targetVert[c]) break;
91759371c9d4SSatish Balay     if (c == cS) {
91769371c9d4SSatish Balay       *ornt = o;
91779371c9d4SSatish Balay       break;
91789371c9d4SSatish Balay     }
9179b5a892a1SMatthew G. Knepley   }
9180b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
91813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9182b5a892a1SMatthew G. Knepley }
9183b5a892a1SMatthew G. Knepley 
9184b5a892a1SMatthew G. Knepley /*@C
9185bb7acecfSBarry Smith   DMPolytopeGetVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9186b5a892a1SMatthew G. Knepley 
918720f4b53cSBarry Smith   Not Collective
9188b5a892a1SMatthew G. Knepley 
9189b5a892a1SMatthew G. Knepley   Input Parameters:
9190bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9191b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of vertices
9192b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of vertices
9193b5a892a1SMatthew G. Knepley 
9194b5a892a1SMatthew G. Knepley   Output Parameters:
9195bb7acecfSBarry Smith . ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9196b5a892a1SMatthew G. Knepley 
9197b5a892a1SMatthew G. Knepley   Level: advanced
9198b5a892a1SMatthew G. Knepley 
9199bb7acecfSBarry Smith   Note:
9200bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchVertexOrientation()` except it errors if not orientation is possible.
9201bb7acecfSBarry Smith 
9202bb7acecfSBarry Smith   Developer Note:
9203bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchVertexOrientation()` and error if none is found
9204bb7acecfSBarry Smith 
9205bb7acecfSBarry Smith .seealso: `DMPolytopeType`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetOrientation()`
9206b5a892a1SMatthew G. Knepley @*/
9207d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetVertexOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9208d71ae5a4SJacob Faibussowitsch {
9209b5a892a1SMatthew G. Knepley   PetscBool found;
9210b5a892a1SMatthew G. Knepley 
9211b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
92129566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchVertexOrientation(ct, sourceCone, targetCone, ornt, &found));
92137a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
92143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9215b5a892a1SMatthew G. Knepley }
9216012bc364SMatthew G. Knepley 
9217012bc364SMatthew G. Knepley /*@C
9218012bc364SMatthew G. Knepley   DMPolytopeInCellTest - Check whether a point lies inside the reference cell of given type
9219012bc364SMatthew G. Knepley 
922020f4b53cSBarry Smith   Not Collective
9221012bc364SMatthew G. Knepley 
9222012bc364SMatthew G. Knepley   Input Parameters:
9223bb7acecfSBarry Smith + ct    - The `DMPolytopeType`
9224012bc364SMatthew G. Knepley - point - Coordinates of the point
9225012bc364SMatthew G. Knepley 
9226012bc364SMatthew G. Knepley   Output Parameters:
9227012bc364SMatthew G. Knepley . inside  - Flag indicating whether the point is inside the reference cell of given type
9228012bc364SMatthew G. Knepley 
9229012bc364SMatthew G. Knepley   Level: advanced
9230012bc364SMatthew G. Knepley 
9231bb7acecfSBarry Smith .seealso: `DM`, `DMPolytopeType`, `DMLocatePoints()`
9232012bc364SMatthew G. Knepley @*/
9233d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeInCellTest(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
9234d71ae5a4SJacob Faibussowitsch {
9235012bc364SMatthew G. Knepley   PetscReal sum = 0.0;
9236012bc364SMatthew G. Knepley   PetscInt  d;
9237012bc364SMatthew G. Knepley 
9238012bc364SMatthew G. Knepley   PetscFunctionBegin;
9239012bc364SMatthew G. Knepley   *inside = PETSC_TRUE;
9240012bc364SMatthew G. Knepley   switch (ct) {
9241012bc364SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
9242012bc364SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
9243012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
92449371c9d4SSatish Balay       if (point[d] < -1.0) {
92459371c9d4SSatish Balay         *inside = PETSC_FALSE;
92469371c9d4SSatish Balay         break;
92479371c9d4SSatish Balay       }
9248012bc364SMatthew G. Knepley       sum += point[d];
9249012bc364SMatthew G. Knepley     }
92509371c9d4SSatish Balay     if (sum > PETSC_SMALL) {
92519371c9d4SSatish Balay       *inside = PETSC_FALSE;
92529371c9d4SSatish Balay       break;
92539371c9d4SSatish Balay     }
9254012bc364SMatthew G. Knepley     break;
9255012bc364SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
9256012bc364SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
9257012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
92589371c9d4SSatish Balay       if (PetscAbsReal(point[d]) > 1. + PETSC_SMALL) {
92599371c9d4SSatish Balay         *inside = PETSC_FALSE;
9260012bc364SMatthew G. Knepley         break;
92619371c9d4SSatish Balay       }
92629371c9d4SSatish Balay     break;
9263d71ae5a4SJacob Faibussowitsch   default:
9264d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
9265012bc364SMatthew G. Knepley   }
92663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9267012bc364SMatthew G. Knepley }
9268