xref: /petsc/src/dm/interface/dm.c (revision 9f4ada1598380228c679a94df7f1b051b1b79bf6)
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};
249371c9d4SSatish Balay const char *const DMPolytopeTypes[]   = {"vertex",  "segment",       "tensor_segment",      "triangle", "quadrilateral", "tensor_quad",    "tetrahedron",  "hexahedron", "triangular_prism", "tensor_triangular_prism", "tensor_quadrilateral_prism",
259371c9d4SSatish Balay                                          "pyramid", "FV_ghost_cell", "interior_ghost_cell", "unknown",  "invalid",       "DMPolytopeType", "DM_POLYTOPE_", NULL};
262cbb9b06SVaclav Hapla const char *const DMCopyLabelsModes[] = {"replace", "keep", "fail", "DMCopyLabelsMode", "DM_COPY_LABELS_", NULL};
2760c22052SBarry Smith 
28a4121054SBarry Smith /*@
29bb7acecfSBarry Smith   DMCreate - Creates an empty `DM` object. `DM`s are the abstract objects in PETSc that mediate between meshes and discretizations and the
30bb7acecfSBarry Smith   algebraic solvers, time integrators, and optimization algorithms.
31a4121054SBarry Smith 
32d083f849SBarry Smith   Collective
33a4121054SBarry Smith 
34a4121054SBarry Smith   Input Parameter:
35bb7acecfSBarry Smith . comm - The communicator for the `DM` object
36a4121054SBarry Smith 
37a4121054SBarry Smith   Output Parameter:
38bb7acecfSBarry Smith . dm - The `DM` object
39a4121054SBarry Smith 
40a4121054SBarry Smith   Level: beginner
41a4121054SBarry Smith 
42bb7acecfSBarry Smith   Notes:
43bb7acecfSBarry Smith   See `DMType` for a brief summary of available `DM`.
44bb7acecfSBarry Smith 
45bb7acecfSBarry Smith   The type must then be set with `DMSetType()`. If you never call `DMSetType()` it will generate an
46bb7acecfSBarry Smith   error when you try to use the dm.
47bb7acecfSBarry Smith 
48bb7acecfSBarry Smith .seealso: `DMSetType()`, `DMType`, `DMDACreate()`, `DMDA`, `DMSLICED`, `DMCOMPOSITE`, `DMPLEX`, `DMMOAB`, `DMNETWORK`
49a4121054SBarry Smith @*/
50d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreate(MPI_Comm comm, DM *dm)
51d71ae5a4SJacob Faibussowitsch {
52a4121054SBarry Smith   DM      v;
53e5e52638SMatthew G. Knepley   PetscDS ds;
54a4121054SBarry Smith 
55a4121054SBarry Smith   PetscFunctionBegin;
561411c6eeSJed Brown   PetscValidPointer(dm, 2);
570298fd71SBarry Smith   *dm = NULL;
589566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
59a4121054SBarry Smith 
609566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView));
61e7c4fc90SDmitry Karpeev 
6262e5d2d2SJDBetteridge   ((PetscObject)v)->non_cyclic_references = &DMCountNonCyclicReferences;
6362e5d2d2SJDBetteridge 
6449be4549SMatthew G. Knepley   v->setupcalled          = PETSC_FALSE;
6549be4549SMatthew G. Knepley   v->setfromoptionscalled = PETSC_FALSE;
660298fd71SBarry Smith   v->ltogmap              = NULL;
67a4ea9b21SRichard Tran Mills   v->bind_below           = 0;
681411c6eeSJed Brown   v->bs                   = 1;
69171400e9SBarry Smith   v->coloringtype         = IS_COLORING_GLOBAL;
709566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &v->sf));
719566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &v->sectionSF));
72c58f1c22SToby Isaac   v->labels                    = NULL;
7334aa8a36SMatthew G. Knepley   v->adjacency[0]              = PETSC_FALSE;
7434aa8a36SMatthew G. Knepley   v->adjacency[1]              = PETSC_TRUE;
75c58f1c22SToby Isaac   v->depthLabel                = NULL;
76ba2698f1SMatthew G. Knepley   v->celltypeLabel             = NULL;
771bb6d2a8SBarry Smith   v->localSection              = NULL;
781bb6d2a8SBarry Smith   v->globalSection             = NULL;
793b8ba7d1SJed Brown   v->defaultConstraint.section = NULL;
803b8ba7d1SJed Brown   v->defaultConstraint.mat     = NULL;
8179769bd5SJed Brown   v->defaultConstraint.bias    = NULL;
826858538eSMatthew G. Knepley   v->coordinates[0].dim        = PETSC_DEFAULT;
836858538eSMatthew G. Knepley   v->coordinates[1].dim        = PETSC_DEFAULT;
846858538eSMatthew G. Knepley   v->sparseLocalize            = PETSC_TRUE;
8596173672SStefano Zampini   v->dim                       = PETSC_DETERMINE;
86435a35e8SMatthew G Knepley   {
87435a35e8SMatthew G Knepley     PetscInt i;
88435a35e8SMatthew G Knepley     for (i = 0; i < 10; ++i) {
890298fd71SBarry Smith       v->nullspaceConstructors[i]     = NULL;
90f9d4088aSMatthew G. Knepley       v->nearnullspaceConstructors[i] = NULL;
91435a35e8SMatthew G Knepley     }
92435a35e8SMatthew G Knepley   }
939566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
949566063dSJacob Faibussowitsch   PetscCall(DMSetRegionDS(v, NULL, NULL, ds));
959566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&ds));
969566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxCreate(&v->auxData));
9714f150ffSMatthew G. Knepley   v->dmBC              = NULL;
98a8fb8f29SToby Isaac   v->coarseMesh        = NULL;
99f4d763aaSMatthew G. Knepley   v->outputSequenceNum = -1;
100cdb7a50dSMatthew G. Knepley   v->outputSequenceVal = 0.0;
1019566063dSJacob Faibussowitsch   PetscCall(DMSetVecType(v, VECSTANDARD));
1029566063dSJacob Faibussowitsch   PetscCall(DMSetMatType(v, MATAIJ));
1034a7a4c06SLawrence Mitchell 
1041411c6eeSJed Brown   *dm = v;
105a4121054SBarry Smith   PetscFunctionReturn(0);
106a4121054SBarry Smith }
107a4121054SBarry Smith 
10838221697SMatthew G. Knepley /*@
109bb7acecfSBarry Smith   DMClone - Creates a `DM` object with the same topology as the original.
11038221697SMatthew G. Knepley 
111d083f849SBarry Smith   Collective
11238221697SMatthew G. Knepley 
11338221697SMatthew G. Knepley   Input Parameter:
114bb7acecfSBarry Smith . dm - The original `DM` object
11538221697SMatthew G. Knepley 
11638221697SMatthew G. Knepley   Output Parameter:
117bb7acecfSBarry Smith . newdm  - The new `DM` object
11838221697SMatthew G. Knepley 
11938221697SMatthew G. Knepley   Level: beginner
12038221697SMatthew G. Knepley 
1211cb8cacdSPatrick Sanan   Notes:
122bb7acecfSBarry Smith   For some `DM` implementations this is a shallow clone, the result of which may share (reference counted) information with its parent. For example,
123bb7acecfSBarry Smith   `DMClone()` applied to a `DMPLEX` object will result in a new `DMPLEX` that shares the topology with the original `DMPLEX`. It does not
124bb7acecfSBarry Smith   share the `PetscSection` of the original `DM`.
1251bb6d2a8SBarry Smith 
126bb7acecfSBarry Smith   The clone is considered set up if the original has been set up.
12789706ed2SPatrick Sanan 
128bb7acecfSBarry Smith   Use `DMConvert()` for a general way to create new `DM` from a given `DM`
129bb7acecfSBarry Smith 
130bb7acecfSBarry Smith .seealso: `DMDestroy()`, `DMCreate()`, `DMSetType()`, `DMSetLocalSection()`, `DMSetGlobalSection()`, `DMPLEX`, `DMSetType()`, `DMConvert()`
1311bb6d2a8SBarry Smith 
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   }
20738221697SMatthew G. Knepley   PetscFunctionReturn(0);
20838221697SMatthew G. Knepley }
20938221697SMatthew G. Knepley 
2109a42bb27SBarry Smith /*@C
211bb7acecfSBarry Smith        DMSetVecType - Sets the type of vector created with `DMCreateLocalVector()` and `DMCreateGlobalVector()`
2129a42bb27SBarry Smith 
213d083f849SBarry Smith    Logically Collective on da
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 
2199a42bb27SBarry Smith    Options Database:
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));
2339a42bb27SBarry Smith   PetscFunctionReturn(0);
2349a42bb27SBarry Smith }
2359a42bb27SBarry Smith 
236c0dedaeaSBarry Smith /*@C
237bb7acecfSBarry Smith        DMGetVecType - Gets the type of vector created with `DMCreateLocalVector()` and `DMCreateGlobalVector()`
238c0dedaeaSBarry Smith 
239d083f849SBarry Smith    Logically Collective on da
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;
256c0dedaeaSBarry Smith   PetscFunctionReturn(0);
257c0dedaeaSBarry Smith }
258c0dedaeaSBarry Smith 
2595f1ad066SMatthew G Knepley /*@
260bb7acecfSBarry Smith   VecGetDM - Gets the `DM` defining the data layout of the vector
2615f1ad066SMatthew G Knepley 
2625f1ad066SMatthew G Knepley   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));
2835f1ad066SMatthew G Knepley   PetscFunctionReturn(0);
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 
2895f1ad066SMatthew G Knepley   Not collective
2905f1ad066SMatthew G Knepley 
2915f1ad066SMatthew G Knepley   Input Parameters:
292bb7acecfSBarry Smith + v - The `Vec`
293bb7acecfSBarry Smith - dm - The `DM`
2945f1ad066SMatthew G Knepley 
295bb7acecfSBarry Smith   Note:
296bb7acecfSBarry Smith   This is rarely used, generally one uses `DMGetLocalVector()` or  `DMGetGlobalVector()` to create a vector associated with a given `DM`
297d9805387SMatthew G. Knepley 
298bb7acecfSBarry 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.
299bb7acecfSBarry Smith 
300bb7acecfSBarry Smith   Level: developer
3015f1ad066SMatthew G Knepley 
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));
3105f1ad066SMatthew G Knepley   PetscFunctionReturn(0);
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 
316d083f849SBarry Smith    Logically Collective on dm
3178f1509bcSBarry Smith 
3188f1509bcSBarry Smith    Input Parameters:
319bb7acecfSBarry Smith +  dm - the `DM` context
3208f1509bcSBarry Smith -  ctype - the matrix type
3218f1509bcSBarry Smith 
3228f1509bcSBarry Smith    Options Database:
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;
3358f1509bcSBarry Smith   PetscFunctionReturn(0);
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 
341d083f849SBarry Smith    Logically Collective on dm
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 
3498f1509bcSBarry Smith    Options Database:
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;
3628f1509bcSBarry Smith   PetscFunctionReturn(0);
3638f1509bcSBarry Smith }
3648f1509bcSBarry Smith 
3658f1509bcSBarry Smith /*@C
366bb7acecfSBarry Smith        DMSetMatType - Sets the type of matrix created with `DMCreateMatrix()`
3678f1509bcSBarry Smith 
368d083f849SBarry Smith    Logically Collective on dm
3698f1509bcSBarry Smith 
3708f1509bcSBarry Smith    Input Parameters:
371bb7acecfSBarry Smith +  dm - the `DM` context
372bb7acecfSBarry Smith -  ctype - the matrix type, for example `MATMPIAIJ`
373521d9a4cSLisandro Dalcin 
374521d9a4cSLisandro Dalcin    Options Database:
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));
387521d9a4cSLisandro Dalcin   PetscFunctionReturn(0);
388521d9a4cSLisandro Dalcin }
389521d9a4cSLisandro Dalcin 
390c0dedaeaSBarry Smith /*@C
391bb7acecfSBarry Smith        DMGetMatType - Gets the type of matrix created with `DMCreateMatrix()`
392c0dedaeaSBarry Smith 
393d083f849SBarry Smith    Logically Collective on dm
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;
410c0dedaeaSBarry Smith   PetscFunctionReturn(0);
411c0dedaeaSBarry Smith }
412c0dedaeaSBarry Smith 
413c688c046SMatthew G Knepley /*@
414bb7acecfSBarry Smith   MatGetDM - Gets the `DM` defining the data layout of the matrix
415c688c046SMatthew G Knepley 
416c688c046SMatthew G Knepley   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));
440c688c046SMatthew G Knepley   PetscFunctionReturn(0);
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 
446c688c046SMatthew G Knepley   Not collective
447c688c046SMatthew G Knepley 
448c688c046SMatthew G Knepley   Input Parameters:
449c688c046SMatthew G Knepley + A - The Mat
450c688c046SMatthew G Knepley - 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));
469c688c046SMatthew G Knepley   PetscFunctionReturn(0);
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 
475d083f849SBarry Smith    Logically Collective on dm
4769a42bb27SBarry Smith 
477d8d19677SJose E. Roman    Input Parameters:
478bb7acecfSBarry Smith +  da - the `DM` context
479bb7acecfSBarry Smith -  prefix - the prefix to prepend
4809a42bb27SBarry Smith 
4819a42bb27SBarry Smith    Notes:
4829a42bb27SBarry Smith    A hyphen (-) must NOT be given at the beginning of the prefix name.
4839a42bb27SBarry Smith    The first character of all runtime options is AUTOMATICALLY the hyphen.
4849a42bb27SBarry Smith 
4859a42bb27SBarry Smith    Level: advanced
4869a42bb27SBarry Smith 
487bb7acecfSBarry Smith .seealso: `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));
4969a42bb27SBarry Smith   PetscFunctionReturn(0);
4979a42bb27SBarry Smith }
4989a42bb27SBarry Smith 
49931697293SDave May /*@C
500bb7acecfSBarry Smith    DMAppendOptionsPrefix - Appends an additional string to an already exising prefix used for searching for
501bb7acecfSBarry Smith    `DM` options in the options database.
50231697293SDave May 
503d083f849SBarry Smith    Logically Collective on dm
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 
50931697293SDave May    Notes:
510bb7acecfSBarry 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.
51131697293SDave May    A hyphen (-) must NOT be given at the beginning of the prefix name.
51231697293SDave May    The first character of all runtime options is AUTOMATICALLY the hyphen.
51331697293SDave May 
51431697293SDave May    Level: advanced
51531697293SDave May 
516bb7acecfSBarry Smith .seealso: `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));
52331697293SDave May   PetscFunctionReturn(0);
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 
538bb7acecfSBarry Smith    Fortran Note:
53995452b02SPatrick Sanan     On the fortran side, the user should pass in a string 'prefix' of
54031697293SDave May    sufficient length to hold the prefix.
54131697293SDave May 
54231697293SDave May    Level: advanced
54331697293SDave May 
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));
55131697293SDave May   PetscFunctionReturn(0);
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;
57988bdff64SToby Isaac   PetscFunctionReturn(0);
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));
58762e5d2d2SJDBetteridge   PetscFunctionReturn(0);
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;
606354557abSToby Isaac   PetscFunctionReturn(0);
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));
6176858538eSMatthew G. Knepley   PetscFunctionReturn(0);
6186858538eSMatthew G. Knepley }
6196858538eSMatthew G. Knepley 
6201fb7b255SJunchao Zhang /*@C
621bb7acecfSBarry Smith     DMDestroy - Destroys a `DM`.
62247c6ae99SBarry Smith 
623d083f849SBarry Smith     Collective on dm
62447c6ae99SBarry Smith 
62547c6ae99SBarry Smith     Input Parameter:
626bb7acecfSBarry Smith .   dm - the `DM` object to destroy
62747c6ae99SBarry Smith 
62847c6ae99SBarry Smith     Level: developer
62947c6ae99SBarry Smith 
630bb7acecfSBarry Smith .seealso: `DMCreate()`, `DMType`, `DMSetType()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
63147c6ae99SBarry Smith 
63247c6ae99SBarry Smith @*/
633d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy(DM *dm)
634d71ae5a4SJacob Faibussowitsch {
6356eb26441SStefano Zampini   PetscInt       cnt;
636dfe15315SJed Brown   DMNamedVecLink nlink, nnext;
63747c6ae99SBarry Smith 
63847c6ae99SBarry Smith   PetscFunctionBegin;
6396bf464f9SBarry Smith   if (!*dm) PetscFunctionReturn(0);
6406bf464f9SBarry Smith   PetscValidHeaderSpecific((*dm), DM_CLASSID, 1);
64187e657c6SBarry Smith 
64288bdff64SToby Isaac   /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
64362e5d2d2SJDBetteridge   PetscCall(DMCountNonCyclicReferences_Internal(*dm, PETSC_TRUE, PETSC_TRUE, &cnt));
64488bdff64SToby Isaac   --((PetscObject)(*dm))->refct;
6459371c9d4SSatish Balay   if (--cnt > 0) {
6469371c9d4SSatish Balay     *dm = NULL;
6479371c9d4SSatish Balay     PetscFunctionReturn(0);
6489371c9d4SSatish Balay   }
6496bf464f9SBarry Smith   if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0);
6506bf464f9SBarry Smith   ((PetscObject)(*dm))->refct = 0;
6516eb26441SStefano Zampini 
6529566063dSJacob Faibussowitsch   PetscCall(DMClearGlobalVectors(*dm));
6539566063dSJacob Faibussowitsch   PetscCall(DMClearLocalVectors(*dm));
6546eb26441SStefano Zampini 
655f490541aSPeter Brune   nnext              = (*dm)->namedglobal;
6560298fd71SBarry Smith   (*dm)->namedglobal = NULL;
657f490541aSPeter Brune   for (nlink = nnext; nlink; nlink = nnext) { /* Destroy the named vectors */
6582348bcf4SPeter Brune     nnext = nlink->next;
6597a8be351SBarry Smith     PetscCheck(nlink->status == DMVEC_STATUS_IN, ((PetscObject)*dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "DM still has Vec named '%s' checked out", nlink->name);
6609566063dSJacob Faibussowitsch     PetscCall(PetscFree(nlink->name));
6619566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nlink->X));
6629566063dSJacob Faibussowitsch     PetscCall(PetscFree(nlink));
6632348bcf4SPeter Brune   }
664f490541aSPeter Brune   nnext             = (*dm)->namedlocal;
6650298fd71SBarry Smith   (*dm)->namedlocal = NULL;
666f490541aSPeter Brune   for (nlink = nnext; nlink; nlink = nnext) { /* Destroy the named local vectors */
667f490541aSPeter Brune     nnext = nlink->next;
6687a8be351SBarry Smith     PetscCheck(nlink->status == DMVEC_STATUS_IN, ((PetscObject)*dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "DM still has Vec named '%s' checked out", nlink->name);
6699566063dSJacob Faibussowitsch     PetscCall(PetscFree(nlink->name));
6709566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&nlink->X));
6719566063dSJacob Faibussowitsch     PetscCall(PetscFree(nlink));
672f490541aSPeter Brune   }
6732348bcf4SPeter Brune 
674b17ce1afSJed Brown   /* Destroy the list of hooks */
675c833c3b5SJed Brown   {
676c833c3b5SJed Brown     DMCoarsenHookLink link, next;
677b17ce1afSJed Brown     for (link = (*dm)->coarsenhook; link; link = next) {
678b17ce1afSJed Brown       next = link->next;
6799566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
680b17ce1afSJed Brown     }
6810298fd71SBarry Smith     (*dm)->coarsenhook = NULL;
682c833c3b5SJed Brown   }
683c833c3b5SJed Brown   {
684c833c3b5SJed Brown     DMRefineHookLink link, next;
685c833c3b5SJed Brown     for (link = (*dm)->refinehook; link; link = next) {
686c833c3b5SJed Brown       next = link->next;
6879566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
688c833c3b5SJed Brown     }
6890298fd71SBarry Smith     (*dm)->refinehook = NULL;
690c833c3b5SJed Brown   }
691be081cd6SPeter Brune   {
692be081cd6SPeter Brune     DMSubDomainHookLink link, next;
693be081cd6SPeter Brune     for (link = (*dm)->subdomainhook; link; link = next) {
694be081cd6SPeter Brune       next = link->next;
6959566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
696be081cd6SPeter Brune     }
6970298fd71SBarry Smith     (*dm)->subdomainhook = NULL;
698be081cd6SPeter Brune   }
699baf369e7SPeter Brune   {
700baf369e7SPeter Brune     DMGlobalToLocalHookLink link, next;
701baf369e7SPeter Brune     for (link = (*dm)->gtolhook; link; link = next) {
702baf369e7SPeter Brune       next = link->next;
7039566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
704baf369e7SPeter Brune     }
7050298fd71SBarry Smith     (*dm)->gtolhook = NULL;
706baf369e7SPeter Brune   }
707d4d07f1eSToby Isaac   {
708d4d07f1eSToby Isaac     DMLocalToGlobalHookLink link, next;
709d4d07f1eSToby Isaac     for (link = (*dm)->ltoghook; link; link = next) {
710d4d07f1eSToby Isaac       next = link->next;
7119566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
712d4d07f1eSToby Isaac     }
713d4d07f1eSToby Isaac     (*dm)->ltoghook = NULL;
714d4d07f1eSToby Isaac   }
715aa1993deSMatthew G Knepley   /* Destroy the work arrays */
716aa1993deSMatthew G Knepley   {
717aa1993deSMatthew G Knepley     DMWorkLink link, next;
7187a8be351SBarry Smith     PetscCheck(!(*dm)->workout, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Work array still checked out");
719aa1993deSMatthew G Knepley     for (link = (*dm)->workin; link; link = next) {
720aa1993deSMatthew G Knepley       next = link->next;
7219566063dSJacob Faibussowitsch       PetscCall(PetscFree(link->mem));
7229566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
723aa1993deSMatthew G Knepley     }
7240298fd71SBarry Smith     (*dm)->workin = NULL;
725aa1993deSMatthew G Knepley   }
726c58f1c22SToby Isaac   /* destroy the labels */
7279566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(*dm));
728f4cdcedcSVaclav Hapla   /* destroy the fields */
7299566063dSJacob Faibussowitsch   PetscCall(DMClearFields(*dm));
730f4cdcedcSVaclav Hapla   /* destroy the boundaries */
731e6f8dbb6SToby Isaac   {
732e6f8dbb6SToby Isaac     DMBoundary next = (*dm)->boundary;
733e6f8dbb6SToby Isaac     while (next) {
734e6f8dbb6SToby Isaac       DMBoundary b = next;
735e6f8dbb6SToby Isaac 
736e6f8dbb6SToby Isaac       next = b->next;
7379566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
738e6f8dbb6SToby Isaac     }
739e6f8dbb6SToby Isaac   }
740b17ce1afSJed Brown 
7419566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmksp));
7429566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmsnes));
7439566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmts));
74452536dc3SBarry Smith 
74548a46eb9SPierre Jolivet   if ((*dm)->ctx && (*dm)->ctxdestroy) PetscCall((*(*dm)->ctxdestroy)(&(*dm)->ctx));
7469566063dSJacob Faibussowitsch   PetscCall(MatFDColoringDestroy(&(*dm)->fd));
7479566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap));
7489566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->vectype));
7499566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->mattype));
75088ed4aceSMatthew G Knepley 
7519566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->localSection));
7529566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->globalSection));
7539566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&(*dm)->map));
7549566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->defaultConstraint.section));
7559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&(*dm)->defaultConstraint.mat));
7569566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&(*dm)->sf));
7579566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&(*dm)->sectionSF));
758736995cdSBlaise Bourdin   if ((*dm)->useNatural) {
75948a46eb9SPierre Jolivet     if ((*dm)->sfNatural) PetscCall(PetscSFDestroy(&(*dm)->sfNatural));
7609566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)(*dm)->sfMigration));
761736995cdSBlaise Bourdin   }
7629a2a23afSMatthew G. Knepley   {
7639a2a23afSMatthew G. Knepley     Vec     *auxData;
7649a2a23afSMatthew G. Knepley     PetscInt n, i, off = 0;
7659a2a23afSMatthew G. Knepley 
7669566063dSJacob Faibussowitsch     PetscCall(PetscHMapAuxGetSize((*dm)->auxData, &n));
7679566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &auxData));
7689566063dSJacob Faibussowitsch     PetscCall(PetscHMapAuxGetVals((*dm)->auxData, &off, auxData));
7699566063dSJacob Faibussowitsch     for (i = 0; i < n; ++i) PetscCall(VecDestroy(&auxData[i]));
7709566063dSJacob Faibussowitsch     PetscCall(PetscFree(auxData));
7719566063dSJacob Faibussowitsch     PetscCall(PetscHMapAuxDestroy(&(*dm)->auxData));
7729a2a23afSMatthew G. Knepley   }
77348a46eb9SPierre Jolivet   if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) PetscCall(DMSetFineDM((*dm)->coarseMesh, NULL));
7746eb26441SStefano Zampini 
7759566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->coarseMesh));
77648a46eb9SPierre Jolivet   if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) PetscCall(DMSetCoarseDM((*dm)->fineMesh, NULL));
7779566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->fineMesh));
7784fb89dddSMatthew G. Knepley   PetscCall(PetscFree((*dm)->Lstart));
7799566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->L));
7809566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->maxCell));
7816858538eSMatthew G. Knepley   PetscCall(DMDestroyCoordinates_Private(&(*dm)->coordinates[0]));
7826858538eSMatthew G. Knepley   PetscCall(DMDestroyCoordinates_Private(&(*dm)->coordinates[1]));
7839566063dSJacob Faibussowitsch   if ((*dm)->transformDestroy) PetscCall((*(*dm)->transformDestroy)(*dm, (*dm)->transformCtx));
7849566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->transformDM));
7859566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&(*dm)->transform));
7866636e97aSMatthew G Knepley 
7879566063dSJacob Faibussowitsch   PetscCall(DMClearDS(*dm));
7889566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->dmBC));
789e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
7909566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*dm));
791732e2eb9SMatthew G Knepley 
79248a46eb9SPierre Jolivet   if ((*dm)->ops->destroy) PetscCall((*(*dm)->ops->destroy)(*dm));
7939566063dSJacob Faibussowitsch   PetscCall(DMMonitorCancel(*dm));
794f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
7959566063dSJacob Faibussowitsch   PetscCallCEED(CeedElemRestrictionDestroy(&(*dm)->ceedERestrict));
7969566063dSJacob Faibussowitsch   PetscCallCEED(CeedDestroy(&(*dm)->ceed));
797f918ec44SMatthew G. Knepley #endif
798435a35e8SMatthew G Knepley   /* We do not destroy (*dm)->data here so that we can reference count backend objects */
7999566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(dm));
80047c6ae99SBarry Smith   PetscFunctionReturn(0);
80147c6ae99SBarry Smith }
80247c6ae99SBarry Smith 
803d7bf68aeSBarry Smith /*@
804bb7acecfSBarry Smith     DMSetUp - sets up the data structures inside a `DM` object
805d7bf68aeSBarry Smith 
806d083f849SBarry Smith     Collective on dm
807d7bf68aeSBarry Smith 
808d7bf68aeSBarry Smith     Input Parameter:
809bb7acecfSBarry Smith .   dm - the `DM` object to setup
810d7bf68aeSBarry Smith 
811bb7acecfSBarry Smith     Level: intermediate
812d7bf68aeSBarry Smith 
813bb7acecfSBarry Smith     Note:
814bb7acecfSBarry Smith     This is usually called after various parameter setting operations and `DMSetFromOptions()` are called on the `DM`
815bb7acecfSBarry Smith 
816bb7acecfSBarry Smith .seealso: `DM`, `DMCreate()`, `DMSetType()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
817d7bf68aeSBarry Smith 
818d7bf68aeSBarry Smith @*/
819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp(DM dm)
820d71ae5a4SJacob Faibussowitsch {
821d7bf68aeSBarry Smith   PetscFunctionBegin;
822171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8238387afaaSJed Brown   if (dm->setupcalled) PetscFunctionReturn(0);
824dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, setup);
8258387afaaSJed Brown   dm->setupcalled = PETSC_TRUE;
826d7bf68aeSBarry Smith   PetscFunctionReturn(0);
827d7bf68aeSBarry Smith }
828d7bf68aeSBarry Smith 
829d7bf68aeSBarry Smith /*@
830bb7acecfSBarry Smith     DMSetFromOptions - sets parameters in a `DM` from the options database
831d7bf68aeSBarry Smith 
832d083f849SBarry Smith     Collective on dm
833d7bf68aeSBarry Smith 
834d7bf68aeSBarry Smith     Input Parameter:
835bb7acecfSBarry Smith .   dm - the `DM` object to set options for
836d7bf68aeSBarry Smith 
837732e2eb9SMatthew G Knepley     Options Database:
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>
842bb7acecfSBarry 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`
843732e2eb9SMatthew G Knepley 
8449318fe57SMatthew G. Knepley     DMPLEX Specific creation options
8459318fe57SMatthew G. Knepley + -dm_plex_filename <str>           - File containing a mesh
8469318fe57SMatthew G. Knepley . -dm_plex_boundary_filename <str>  - File containing a mesh boundary
847cd7e8a5eSksagiyam . -dm_plex_name <str>               - Name of the mesh in the file
848bb7acecfSBarry Smith . -dm_plex_shape <shape>            - The domain shape, such as `DM_SHAPE_BOX`, `DM_SHAPE_SPHERE`, etc.
8499318fe57SMatthew G. Knepley . -dm_plex_cell <ct>                - Cell shape
8509318fe57SMatthew G. Knepley . -dm_plex_reference_cell_domain <bool> - Use a reference cell domain
8519318fe57SMatthew G. Knepley . -dm_plex_dim <dim>                - Set the topological dimension
852bb7acecfSBarry Smith . -dm_plex_simplex <bool>           - `PETSC_TRUE` for simplex elements, `PETSC_FALSE` for tensor elements
853bb7acecfSBarry Smith . -dm_plex_interpolate <bool>       - `PETSC_TRUE` turns on topological interpolation (creating edges and faces)
8549318fe57SMatthew G. Knepley . -dm_plex_scale <sc>               - Scale factor for mesh coordinates
8559318fe57SMatthew G. Knepley . -dm_plex_box_faces <m,n,p>        - Number of faces along each dimension
8569318fe57SMatthew G. Knepley . -dm_plex_box_lower <x,y,z>        - Specify lower-left-bottom coordinates for the box
8579318fe57SMatthew G. Knepley . -dm_plex_box_upper <x,y,z>        - Specify upper-right-top coordinates for the box
858bb7acecfSBarry Smith . -dm_plex_box_bd <bx,by,bz>        - Specify the `DMBoundaryType `for each direction
8599318fe57SMatthew G. Knepley . -dm_plex_sphere_radius <r>        - The sphere radius
8609318fe57SMatthew G. Knepley . -dm_plex_ball_radius <r>          - Radius of the ball
8619318fe57SMatthew G. Knepley . -dm_plex_cylinder_bd <bz>         - Boundary type in the z direction
8629318fe57SMatthew G. Knepley . -dm_plex_cylinder_num_wedges <n>  - Number of wedges around the cylinder
863bdf63967SMatthew G. Knepley . -dm_plex_reorder <order>          - Reorder the mesh using the specified algorithm
8649318fe57SMatthew G. Knepley . -dm_refine_pre <n>                - The number of refinements before distribution
8659318fe57SMatthew G. Knepley . -dm_refine_uniform_pre <bool>     - Flag for uniform refinement before distribution
8669318fe57SMatthew G. Knepley . -dm_refine_volume_limit_pre <v>   - The maximum cell volume after refinement before distribution
8679318fe57SMatthew G. Knepley . -dm_refine <n>                    - The number of refinements after distribution
868bdf63967SMatthew G. Knepley . -dm_extrude <l>                   - Activate extrusion and specify the number of layers to extrude
869d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_thickness <t>           - The total thickness of extruded layers
870d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_use_tensor <bool>       - Use tensor cells when extruding
871d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_symmetric <bool>        - Extrude layers symmetrically about the surface
872d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_normal <n0,...,nd>      - Specify the extrusion direction
873d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_thicknesses <t0,...,tl> - Specify thickness of each layer
874909dfd52SMatthew G. Knepley . -dm_plex_create_fv_ghost_cells    - Flag to create finite volume ghost cells on the boundary
875909dfd52SMatthew G. Knepley . -dm_plex_fv_ghost_cells_label <name> - Label name for ghost cells boundary
8769318fe57SMatthew G. Knepley . -dm_distribute <bool>             - Flag to redistribute a mesh among processes
8779318fe57SMatthew G. Knepley . -dm_distribute_overlap <n>        - The size of the overlap halo
8789318fe57SMatthew G. Knepley . -dm_plex_adj_cone <bool>          - Set adjacency direction
8799318fe57SMatthew G. Knepley - -dm_plex_adj_closure <bool>       - Set adjacency size
8809318fe57SMatthew G. Knepley 
881384a6580SVaclav Hapla     DMPLEX Specific Checks
882bb7acecfSBarry Smith +   -dm_plex_check_symmetry        - Check that the adjacency information in the mesh is symmetric - `DMPlexCheckSymmetry()`
883bb7acecfSBarry Smith .   -dm_plex_check_skeleton        - Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes) - `DMPlexCheckSkeleton()`
884bb7acecfSBarry 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()`
885bb7acecfSBarry Smith .   -dm_plex_check_geometry        - Check that cells have positive volume - `DMPlexCheckGeometry()`
886bb7acecfSBarry Smith .   -dm_plex_check_pointsf         - Check some necessary conditions for `PointSF` - `DMPlexCheckPointSF()`
887bb7acecfSBarry Smith .   -dm_plex_check_interface_cones - Check points on inter-partition interfaces have conforming order of cone points - `DMPlexCheckInterfaceCones()`
888384a6580SVaclav Hapla -   -dm_plex_check_all             - Perform all the checks above
889d7bf68aeSBarry Smith 
89095eb5ee5SVaclav Hapla     Level: intermediate
89195eb5ee5SVaclav Hapla 
892bb7acecfSBarry Smith .seealso: `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
893bb7acecfSBarry Smith          `DMPlexCheckSymmetry()`, `DMPlexCheckSkeleton()`, `DMPlexCheckFaces()`, `DMPlexCheckGeometry()`, `DMPlexCheckPointSF()`, `DMPlexCheckInterfaceCones()`,
894bb7acecfSBarry Smith          `DMSetOptionsPrefix()`, `DM`, `DMType`, `DMPLEX`, `DMDA`
895d7bf68aeSBarry Smith 
896d7bf68aeSBarry Smith @*/
897d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions(DM dm)
898d71ae5a4SJacob Faibussowitsch {
8997781c08eSBarry Smith   char      typeName[256];
900ca266f36SBarry Smith   PetscBool flg;
901d7bf68aeSBarry Smith 
902d7bf68aeSBarry Smith   PetscFunctionBegin;
903171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90449be4549SMatthew G. Knepley   dm->setfromoptionscalled = PETSC_TRUE;
9059566063dSJacob Faibussowitsch   if (dm->sf) PetscCall(PetscSFSetFromOptions(dm->sf));
9069566063dSJacob Faibussowitsch   if (dm->sectionSF) PetscCall(PetscSFSetFromOptions(dm->sectionSF));
907d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)dm);
9089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_preallocate_only", "only preallocate matrix, but do not set column indices", "DMSetMatrixPreallocateOnly", dm->prealloc_only, &dm->prealloc_only, NULL));
9099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_vec_type", "Vector type used for created vectors", "DMSetVecType", VecList, dm->vectype, typeName, 256, &flg));
9101baa6e33SBarry Smith   if (flg) PetscCall(DMSetVecType(dm, typeName));
9119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_mat_type", "Matrix type used for created matrices", "DMSetMatType", MatList, dm->mattype ? dm->mattype : typeName, typeName, sizeof(typeName), &flg));
9121baa6e33SBarry Smith   if (flg) PetscCall(DMSetMatType(dm, typeName));
9139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_is_coloring_type", "Global or local coloring of Jacobian", "DMSetISColoringType", ISColoringTypes, (PetscEnum)dm->coloringtype, (PetscEnum *)&dm->coloringtype, NULL));
9149566063dSJacob 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));
915dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, setfromoptions, PetscOptionsObject);
916f9ba7244SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
917dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)dm, PetscOptionsObject));
918d0609cedSBarry Smith   PetscOptionsEnd();
919d7bf68aeSBarry Smith   PetscFunctionReturn(0);
920d7bf68aeSBarry Smith }
921d7bf68aeSBarry Smith 
922fc9bc008SSatish Balay /*@C
923bb7acecfSBarry Smith    DMViewFromOptions - View a `DM` in a particular way based on a request in the options database
924fe2efc57SMark 
925bb7acecfSBarry Smith    Collective on dm
926fe2efc57SMark 
927fe2efc57SMark    Input Parameters:
928bb7acecfSBarry Smith +  dm - the `DM` object
929bb7acecfSBarry Smith .  obj - optional object that provides the prefix for the options database (if NULL then the prefix in obj is used)
930bb7acecfSBarry Smith -  optionname - option string that is used to activate viewing
931fe2efc57SMark 
932fe2efc57SMark    Level: intermediate
933bb7acecfSBarry Smith 
934bb7acecfSBarry Smith    Note:
935bb7acecfSBarry Smith    See `PetscObjectViewFromOptions()` for a list of values that can be provided in the options database to determine how the `DM` is viewed
936bb7acecfSBarry Smith 
937bb7acecfSBarry Smith .seealso: `DM`, `DMView()`, `PetscObjectViewFromOptions()`, `DMCreate()`, `PetscObjectViewFromOptions()`
938fe2efc57SMark @*/
939d71ae5a4SJacob Faibussowitsch PetscErrorCode DMViewFromOptions(DM dm, PetscObject obj, const char name[])
940d71ae5a4SJacob Faibussowitsch {
941fe2efc57SMark   PetscFunctionBegin;
942fe2efc57SMark   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9439566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, obj, name));
944fe2efc57SMark   PetscFunctionReturn(0);
945fe2efc57SMark }
946fe2efc57SMark 
947fe2efc57SMark /*@C
948bb7acecfSBarry 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
949bb7acecfSBarry Smith     save the `DM` in a binary file to be loaded later or create a visualization of the `DM`
95047c6ae99SBarry Smith 
951d083f849SBarry Smith     Collective on dm
95247c6ae99SBarry Smith 
953d8d19677SJose E. Roman     Input Parameters:
954bb7acecfSBarry Smith +   dm - the `DM` object to view
95547c6ae99SBarry Smith -   v - the viewer
95647c6ae99SBarry Smith 
957cd7e8a5eSksagiyam     Notes:
958bb7acecfSBarry Smith     Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` as the `PetscViewerFormat` one can save multiple `DMPLEX`
959bb7acecfSBarry Smith     meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
960bb7acecfSBarry Smith     before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
961cd7e8a5eSksagiyam 
962224748a4SBarry Smith     Level: beginner
96347c6ae99SBarry Smith 
964bb7acecfSBarry Smith .seealso: `PetscViewer`, `PetscViewerFormat`, `PetscViewerSetFormat`(), `DMDestroy()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMLoad()`, `PetscObjectSetName()`
96547c6ae99SBarry Smith 
96647c6ae99SBarry Smith @*/
967d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView(DM dm, PetscViewer v)
968d71ae5a4SJacob Faibussowitsch {
96932c0f0efSBarry Smith   PetscBool         isbinary;
97076a8abe0SBarry Smith   PetscMPIInt       size;
97176a8abe0SBarry Smith   PetscViewerFormat format;
97247c6ae99SBarry Smith 
97347c6ae99SBarry Smith   PetscFunctionBegin;
974171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97548a46eb9SPierre Jolivet   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &v));
976b1b135c8SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);
97774903a4fSStefano Zampini   /* Ideally, we would like to have this test on.
97874903a4fSStefano Zampini      However, it currently breaks socket viz via GLVis.
97974903a4fSStefano Zampini      During DMView(parallel_mesh,glvis_viewer), each
98074903a4fSStefano Zampini      process opens a sequential ASCII socket to visualize
98174903a4fSStefano Zampini      the local mesh, and PetscObjectView(dm,local_socket)
98274903a4fSStefano Zampini      is internally called inside VecView_GLVis, incurring
98374903a4fSStefano Zampini      in an error here */
98474903a4fSStefano Zampini   /* PetscCheckSameComm(dm,1,v,2); */
9859566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckWritable(v));
986b1b135c8SBarry Smith 
9879566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(v, &format));
9889566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
98976a8abe0SBarry Smith   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
9909566063dSJacob Faibussowitsch   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)dm, v));
9919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERBINARY, &isbinary));
99232c0f0efSBarry Smith   if (isbinary) {
99355849f57SBarry Smith     PetscInt classid = DM_FILE_CLASSID;
99432c0f0efSBarry Smith     char     type[256];
99532c0f0efSBarry Smith 
9969566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWrite(v, &classid, 1, PETSC_INT));
9979566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(type, ((PetscObject)dm)->type_name, 256));
9989566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWrite(v, type, 256, PETSC_CHAR));
99932c0f0efSBarry Smith   }
1000dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, view, v);
100147c6ae99SBarry Smith   PetscFunctionReturn(0);
100247c6ae99SBarry Smith }
100347c6ae99SBarry Smith 
100447c6ae99SBarry Smith /*@
1005bb7acecfSBarry 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,
1006bb7acecfSBarry Smith     that is it has no ghost locations.
100747c6ae99SBarry Smith 
1008d083f849SBarry Smith     Collective on dm
100947c6ae99SBarry Smith 
101047c6ae99SBarry Smith     Input Parameter:
1011bb7acecfSBarry Smith .   dm - the `DM` object
101247c6ae99SBarry Smith 
101347c6ae99SBarry Smith     Output Parameter:
101447c6ae99SBarry Smith .   vec - the global vector
101547c6ae99SBarry Smith 
1016073dac72SJed Brown     Level: beginner
101747c6ae99SBarry Smith 
1018bb7acecfSBarry Smith .seealso: `Vec`, `DMCreateLocalVector()`, `DMGetGlobalVector()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
1019bb7acecfSBarry Smith          `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`
102047c6ae99SBarry Smith 
102147c6ae99SBarry Smith @*/
1022d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateGlobalVector(DM dm, Vec *vec)
1023d71ae5a4SJacob Faibussowitsch {
102447c6ae99SBarry Smith   PetscFunctionBegin;
1025171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1026b9d85ea2SLisandro Dalcin   PetscValidPointer(vec, 2);
1027dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createglobalvector, vec);
102876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1029c6b011d8SStefano Zampini     DM vdm;
1030c6b011d8SStefano Zampini 
10319566063dSJacob Faibussowitsch     PetscCall(VecGetDM(*vec, &vdm));
10327a8be351SBarry Smith     PetscCheck(vdm, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DM type '%s' did not attach the DM to the vector", ((PetscObject)dm)->type_name);
1033c6b011d8SStefano Zampini   }
103447c6ae99SBarry Smith   PetscFunctionReturn(0);
103547c6ae99SBarry Smith }
103647c6ae99SBarry Smith 
103747c6ae99SBarry Smith /*@
1038bb7acecfSBarry Smith     DMCreateLocalVector - Creates a local vector from a `DM` object.
103947c6ae99SBarry Smith 
104047c6ae99SBarry Smith     Not Collective
104147c6ae99SBarry Smith 
104247c6ae99SBarry Smith     Input Parameter:
1043bb7acecfSBarry Smith .   dm - the `DM` object
104447c6ae99SBarry Smith 
104547c6ae99SBarry Smith     Output Parameter:
104647c6ae99SBarry Smith .   vec - the local vector
104747c6ae99SBarry Smith 
1048073dac72SJed Brown     Level: beginner
104947c6ae99SBarry Smith 
1050bb7acecfSBarry Smith     Notes:
1051bb7acecfSBarry 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.
1052bb7acecfSBarry Smith 
1053bb7acecfSBarry Smith  .seealso: `Vec`, `DMCreateGlobalVector()`, `DMGetLocalVector()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
1054bb7acecfSBarry Smith          `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`
105547c6ae99SBarry Smith 
105647c6ae99SBarry Smith @*/
1057d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLocalVector(DM dm, Vec *vec)
1058d71ae5a4SJacob Faibussowitsch {
105947c6ae99SBarry Smith   PetscFunctionBegin;
1060171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1061b9d85ea2SLisandro Dalcin   PetscValidPointer(vec, 2);
1062dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createlocalvector, vec);
106376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1064c6b011d8SStefano Zampini     DM vdm;
1065c6b011d8SStefano Zampini 
10669566063dSJacob Faibussowitsch     PetscCall(VecGetDM(*vec, &vdm));
10677a8be351SBarry Smith     PetscCheck(vdm, PETSC_COMM_SELF, PETSC_ERR_LIB, "DM type '%s' did not attach the DM to the vector", ((PetscObject)dm)->type_name);
1068c6b011d8SStefano Zampini   }
106947c6ae99SBarry Smith   PetscFunctionReturn(0);
107047c6ae99SBarry Smith }
107147c6ae99SBarry Smith 
10721411c6eeSJed Brown /*@
1073bb7acecfSBarry Smith    DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a `DM`.
10741411c6eeSJed Brown 
1075d083f849SBarry Smith    Collective on dm
10761411c6eeSJed Brown 
10771411c6eeSJed Brown    Input Parameter:
1078bb7acecfSBarry Smith .  dm - the `DM` that provides the mapping
10791411c6eeSJed Brown 
10801411c6eeSJed Brown    Output Parameter:
10811411c6eeSJed Brown .  ltog - the mapping
10821411c6eeSJed Brown 
1083bb7acecfSBarry Smith    Level: advanced
10841411c6eeSJed Brown 
10851411c6eeSJed Brown    Notes:
1086bb7acecfSBarry Smith    The global to local mapping allows one to set values into the global vector or matrix using `VecSetValuesLocal()` and `MatSetValuesLocal()`
10871411c6eeSJed Brown 
1088bb7acecfSBarry Smith    Vectors obtained with  `DMCreateGlobalVector()` and matrices obtained with `DMCreateMatrix()` already contain the global mapping so you do
1089bb7acecfSBarry Smith    need to use this function with those objects.
1090bb7acecfSBarry Smith 
1091bb7acecfSBarry Smith    This mapping can then be used by `VecSetLocalToGlobalMapping()` or `MatSetLocalToGlobalMapping()`.
1092bb7acecfSBarry Smith 
1093bb7acecfSBarry Smith .seealso: `DMCreateLocalVector()`,  `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `VecSetLocalToGlobalMapping()`, `MatSetLocalToGlobalMapping()`,
1094bb7acecfSBarry Smith           `DMCreateMatrix()`
10951411c6eeSJed Brown @*/
1096d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalToGlobalMapping(DM dm, ISLocalToGlobalMapping *ltog)
1097d71ae5a4SJacob Faibussowitsch {
10980be3e97aSMatthew G. Knepley   PetscInt bs = -1, bsLocal[2], bsMinMax[2];
10991411c6eeSJed Brown 
11001411c6eeSJed Brown   PetscFunctionBegin;
11011411c6eeSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11021411c6eeSJed Brown   PetscValidPointer(ltog, 2);
11031411c6eeSJed Brown   if (!dm->ltogmap) {
110437d0c07bSMatthew G Knepley     PetscSection section, sectionGlobal;
110537d0c07bSMatthew G Knepley 
11069566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
110737d0c07bSMatthew G Knepley     if (section) {
1108a974ec88SMatthew G. Knepley       const PetscInt *cdofs;
110937d0c07bSMatthew G Knepley       PetscInt       *ltog;
1110ccf3bd66SMatthew G. Knepley       PetscInt        pStart, pEnd, n, p, k, l;
111137d0c07bSMatthew G Knepley 
11129566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
11139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
11149566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetStorageSize(section, &n));
11159566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n, &ltog)); /* We want the local+overlap size */
111637d0c07bSMatthew G Knepley       for (p = pStart, l = 0; p < pEnd; ++p) {
1117e6befd46SJed Brown         PetscInt bdof, cdof, dof, off, c, cind;
111837d0c07bSMatthew G Knepley 
111937d0c07bSMatthew G Knepley         /* Should probably use constrained dofs */
11209566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, p, &dof));
11219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
11229566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, p, &cdofs));
11239566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &off));
11241a7dc684SMatthew G. Knepley         /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
11251a7dc684SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
1126ad540459SPierre Jolivet         if (dof) bs = bs < 0 ? bdof : PetscGCD(bs, bdof);
11275227eafbSStefano Zampini 
1128e6befd46SJed Brown         for (c = 0, cind = 0; c < dof; ++c, ++l) {
11295227eafbSStefano Zampini           if (cind < cdof && c == cdofs[cind]) {
1130e6befd46SJed Brown             ltog[l] = off < 0 ? off - c : -(off + c + 1);
1131e6befd46SJed Brown             cind++;
1132e6befd46SJed Brown           } else {
11335227eafbSStefano Zampini             ltog[l] = (off < 0 ? -(off + 1) : off) + c - cind;
1134e6befd46SJed Brown           }
113537d0c07bSMatthew G Knepley         }
113637d0c07bSMatthew G Knepley       }
1137bff27382SMatthew G. Knepley       /* Must have same blocksize on all procs (some might have no points) */
11389371c9d4SSatish Balay       bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
11399371c9d4SSatish Balay       bsLocal[1] = bs;
11409566063dSJacob Faibussowitsch       PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
11419371c9d4SSatish Balay       if (bsMinMax[0] != bsMinMax[1]) {
11429371c9d4SSatish Balay         bs = 1;
11439371c9d4SSatish Balay       } else {
11449371c9d4SSatish Balay         bs = bsMinMax[0];
11459371c9d4SSatish Balay       }
11467591dbb2SMatthew G. Knepley       bs = bs < 0 ? 1 : bs;
11477591dbb2SMatthew G. Knepley       /* Must reduce indices by blocksize */
1148ccf3bd66SMatthew G. Knepley       if (bs > 1) {
1149ca469d19SJed Brown         for (l = 0, k = 0; l < n; l += bs, ++k) {
1150ca469d19SJed Brown           // Integer division of negative values truncates toward zero(!), not toward negative infinity
1151ca469d19SJed Brown           ltog[k] = ltog[l] >= 0 ? ltog[l] / bs : -(-(ltog[l] + 1) / bs + 1);
1152ca469d19SJed Brown         }
1153ccf3bd66SMatthew G. Knepley         n /= bs;
1154ccf3bd66SMatthew G. Knepley       }
11559566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap));
1156dbbe0bcdSBarry Smith     } else PetscUseTypeMethod(dm, getlocaltoglobalmapping);
115737d0c07bSMatthew G Knepley   }
11581411c6eeSJed Brown   *ltog = dm->ltogmap;
11591411c6eeSJed Brown   PetscFunctionReturn(0);
11601411c6eeSJed Brown }
11611411c6eeSJed Brown 
11621411c6eeSJed Brown /*@
1163bb7acecfSBarry Smith    DMGetBlockSize - Gets the inherent block size associated with a `DM`
11641411c6eeSJed Brown 
11651411c6eeSJed Brown    Not Collective
11661411c6eeSJed Brown 
11671411c6eeSJed Brown    Input Parameter:
1168bb7acecfSBarry Smith .  dm - the `DM` with block structure
11691411c6eeSJed Brown 
11701411c6eeSJed Brown    Output Parameter:
11711411c6eeSJed Brown .  bs - the block size, 1 implies no exploitable block structure
11721411c6eeSJed Brown 
11731411c6eeSJed Brown    Level: intermediate
11741411c6eeSJed Brown 
1175bb7acecfSBarry Smith    Note:
1176bb7acecfSBarry Smith    This might be the number of degrees of freedom at each grid point for a structured grid.
1177bb7acecfSBarry Smith 
1178bb7acecfSBarry Smith    Complex `DM` that represent multiphysics or staggered grids or mixed-methods do not generally have a single inherent block size, but
1179bb7acecfSBarry Smith    rather different locations in the vectors may have a different block size.
1180bb7acecfSBarry Smith 
1181db781477SPatrick Sanan .seealso: `ISCreateBlock()`, `VecSetBlockSize()`, `MatSetBlockSize()`, `DMGetLocalToGlobalMapping()`
11821411c6eeSJed Brown @*/
1183d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBlockSize(DM dm, PetscInt *bs)
1184d71ae5a4SJacob Faibussowitsch {
11851411c6eeSJed Brown   PetscFunctionBegin;
11861411c6eeSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1187534a8f05SLisandro Dalcin   PetscValidIntPointer(bs, 2);
11887a8be351SBarry Smith   PetscCheck(dm->bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM does not have enough information to provide a block size yet");
11891411c6eeSJed Brown   *bs = dm->bs;
11901411c6eeSJed Brown   PetscFunctionReturn(0);
11911411c6eeSJed Brown }
11921411c6eeSJed Brown 
119348eeb7c8SBarry Smith /*@C
1194bb7acecfSBarry Smith     DMCreateInterpolation - Gets the interpolation matrix between two `DM` objects. The resulting matrix map degrees of freedom in the vector obtained by
1195bb7acecfSBarry Smith     `DMCreateGlobalVector()` on the coarse `DM` to similar vectors on the fine grid `DM`.
119647c6ae99SBarry Smith 
1197a5bc1bf3SBarry Smith     Collective on dmc
119847c6ae99SBarry Smith 
1199d8d19677SJose E. Roman     Input Parameters:
1200bb7acecfSBarry Smith +   dmc - the `DM` object
1201bb7acecfSBarry Smith -   dmf - the second, finer `DM` object
120247c6ae99SBarry Smith 
1203d8d19677SJose E. Roman     Output Parameters:
120447c6ae99SBarry Smith +  mat - the interpolation
1205bb7acecfSBarry Smith -  vec - the scaling (optional), see `DMCreateInterpolationScale()`
120647c6ae99SBarry Smith 
120747c6ae99SBarry Smith     Level: developer
120847c6ae99SBarry Smith 
120995452b02SPatrick Sanan     Notes:
1210bb7acecfSBarry 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
1211bb7acecfSBarry Smith     DMCoarsen(). The coordinates set into the `DMDA` are completely ignored in computing the interpolation.
1212d52bd9f3SBarry Smith 
1213bb7acecfSBarry Smith     For `DMDA` objects you can use this interpolation (more precisely the interpolation from the `DMGetCoordinateDM()`) to interpolate the mesh coordinate
1214bb7acecfSBarry Smith     vectors EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
121585afcc9aSBarry Smith 
1216bb7acecfSBarry Smith .seealso: `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolationScale()`
121747c6ae99SBarry Smith 
121847c6ae99SBarry Smith @*/
1219d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation(DM dmc, DM dmf, Mat *mat, Vec *vec)
1220d71ae5a4SJacob Faibussowitsch {
122147c6ae99SBarry Smith   PetscFunctionBegin;
1222a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1223a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
1224c7d20fa0SStefano Zampini   PetscValidPointer(mat, 3);
12259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateInterpolation, dmc, dmf, 0, 0));
1226dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createinterpolation, dmf, mat, vec);
12279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateInterpolation, dmc, dmf, 0, 0));
122847c6ae99SBarry Smith   PetscFunctionReturn(0);
122947c6ae99SBarry Smith }
123047c6ae99SBarry Smith 
12313ad4599aSBarry Smith /*@
1232bb7acecfSBarry 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`.
1233bb7acecfSBarry Smith     xcoarse = diag(L)*R*xfine preserves scale and is thus suitable for state (versus residual) restriction. In other words xcoarse is the coarse
1234bb7acecfSBarry Smith     representation of xfine.
12352ed6491fSPatrick Sanan 
12362ed6491fSPatrick Sanan   Input Parameters:
1237bb7acecfSBarry Smith +      dac - `DM` that defines a coarse mesh
1238bb7acecfSBarry Smith .      daf - `DM` that defines a fine mesh
12392ed6491fSPatrick Sanan -      mat - the restriction (or interpolation operator) from fine to coarse
12402ed6491fSPatrick Sanan 
12412ed6491fSPatrick Sanan   Output Parameter:
12422ed6491fSPatrick Sanan .    scale - the scaled vector
12432ed6491fSPatrick Sanan 
1244bb7acecfSBarry Smith   Level: advanced
12452ed6491fSPatrick Sanan 
1246e9c74fd6SRichard Tran Mills   Developer Notes:
1247bb7acecfSBarry Smith   If the fine-scale `DMDA` has the -dm_bind_below option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
1248e9c74fd6SRichard Tran Mills   on the restriction/interpolation operator to set the bindingpropagates flag to true.
1249e9c74fd6SRichard Tran Mills 
1250bb7acecfSBarry Smith .seealso: `MatRestrict()`, `MatInterpolate()`, `DMCreateInterpolation()`, DMCreateRestriction()`, `DMCreateGlobalVector()`
12512ed6491fSPatrick Sanan 
12522ed6491fSPatrick Sanan @*/
1253d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolationScale(DM dac, DM daf, Mat mat, Vec *scale)
1254d71ae5a4SJacob Faibussowitsch {
12552ed6491fSPatrick Sanan   Vec         fine;
12562ed6491fSPatrick Sanan   PetscScalar one = 1.0;
12579704db99SRichard Tran Mills #if defined(PETSC_HAVE_CUDA)
1258e9c74fd6SRichard Tran Mills   PetscBool bindingpropagates, isbound;
12599704db99SRichard Tran Mills #endif
12602ed6491fSPatrick Sanan 
12612ed6491fSPatrick Sanan   PetscFunctionBegin;
12629566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(daf, &fine));
12639566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dac, scale));
12649566063dSJacob Faibussowitsch   PetscCall(VecSet(fine, one));
12659704db99SRichard Tran Mills #if defined(PETSC_HAVE_CUDA)
12669704db99SRichard Tran Mills   /* If the 'fine' Vec is bound to the CPU, it makes sense to bind 'mat' as well.
12679704db99SRichard Tran Mills    * Note that we only do this for the CUDA case, right now, but if we add support for MatMultTranspose() via ViennaCL,
12689704db99SRichard Tran Mills    * we'll need to do it for that case, too.*/
12699566063dSJacob Faibussowitsch   PetscCall(VecGetBindingPropagates(fine, &bindingpropagates));
1270e9c74fd6SRichard Tran Mills   if (bindingpropagates) {
12719566063dSJacob Faibussowitsch     PetscCall(MatSetBindingPropagates(mat, PETSC_TRUE));
12729566063dSJacob Faibussowitsch     PetscCall(VecBoundToCPU(fine, &isbound));
12739566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(mat, isbound));
127483aa49f4SRichard Tran Mills   }
12759704db99SRichard Tran Mills #endif
12769566063dSJacob Faibussowitsch   PetscCall(MatRestrict(mat, fine, *scale));
12779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fine));
12789566063dSJacob Faibussowitsch   PetscCall(VecReciprocal(*scale));
12792ed6491fSPatrick Sanan   PetscFunctionReturn(0);
12802ed6491fSPatrick Sanan }
12812ed6491fSPatrick Sanan 
12822ed6491fSPatrick Sanan /*@
1283bb7acecfSBarry Smith     DMCreateRestriction - Gets restriction matrix between two `DM` objects. The resulting matrix map degrees of freedom in the vector obtained by
1284bb7acecfSBarry Smith     `DMCreateGlobalVector()` on the fine `DM` to similar vectors on the coarse grid `DM`.
12853ad4599aSBarry Smith 
1286a5bc1bf3SBarry Smith     Collective on dmc
12873ad4599aSBarry Smith 
1288d8d19677SJose E. Roman     Input Parameters:
1289bb7acecfSBarry Smith +   dmc - the `DM` object
1290bb7acecfSBarry Smith -   dmf - the second, finer `DM` object
12913ad4599aSBarry Smith 
12923ad4599aSBarry Smith     Output Parameter:
12933ad4599aSBarry Smith .  mat - the restriction
12943ad4599aSBarry Smith 
12953ad4599aSBarry Smith     Level: developer
12963ad4599aSBarry Smith 
1297bb7acecfSBarry Smith     Note:
1298bb7acecfSBarry Smith     This only works for `DMSTAG`. For many situations either the transpose of the operator obtained with `DMCreateInterpolation()` or that
1299bb7acecfSBarry Smith     matrix multiplied by the vector obtained with `DMCreateInterpolationScale()` provides the desired object.
13003ad4599aSBarry Smith 
1301bb7acecfSBarry Smith .seealso: `DMRestrict()`, `DMInterpolate()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateInterpolation()`
13023ad4599aSBarry Smith 
13033ad4599aSBarry Smith @*/
1304d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateRestriction(DM dmc, DM dmf, Mat *mat)
1305d71ae5a4SJacob Faibussowitsch {
13063ad4599aSBarry Smith   PetscFunctionBegin;
1307a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1308a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
13095a84ad33SLisandro Dalcin   PetscValidPointer(mat, 3);
13109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateRestriction, dmc, dmf, 0, 0));
1311dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createrestriction, dmf, mat);
13129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateRestriction, dmc, dmf, 0, 0));
13133ad4599aSBarry Smith   PetscFunctionReturn(0);
13143ad4599aSBarry Smith }
13153ad4599aSBarry Smith 
131647c6ae99SBarry Smith /*@
1317bb7acecfSBarry Smith     DMCreateInjection - Gets injection matrix between two `DM` objects. This is an operator that applied to a vector obtained with
1318bb7acecfSBarry Smith     `DMCreateGlobalVector()` on the fine grid maps the values to a vector on the vector on the coarse `DM` by simply selecting the values
1319bb7acecfSBarry Smith     on the coarse grid points. This compares to the operator obtained by `DMCreateRestriction()` or the transpose of the operator obtained
1320bb7acecfSBarry Smith     by `DMCreateInterpolation()` that uses a "local weighted average" of the values around the coarse grid point as the coarse grid value.
132147c6ae99SBarry Smith 
1322a5bc1bf3SBarry Smith     Collective on dac
132347c6ae99SBarry Smith 
1324d8d19677SJose E. Roman     Input Parameters:
1325bb7acecfSBarry Smith +   dac - the `DM` object
1326bb7acecfSBarry Smith -   daf - the second, finer `DM` object
132747c6ae99SBarry Smith 
132847c6ae99SBarry Smith     Output Parameter:
13296dbf9973SLawrence Mitchell .   mat - the injection
133047c6ae99SBarry Smith 
133147c6ae99SBarry Smith     Level: developer
133247c6ae99SBarry Smith 
1333bb7acecfSBarry Smith    Note:
1334bb7acecfSBarry 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
1335bb7acecfSBarry Smith         `DMCoarsen()`. The coordinates set into the `DMDA` are completely ignored in computing the injection.
133685afcc9aSBarry Smith 
1337bb7acecfSBarry Smith .seealso: `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateInterpolation()`,
1338bb7acecfSBarry Smith           `DMCreateRestriction()`, `MatRestrict()`, `MatInterpolate()`
133947c6ae99SBarry Smith 
134047c6ae99SBarry Smith @*/
1341d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection(DM dac, DM daf, Mat *mat)
1342d71ae5a4SJacob Faibussowitsch {
134347c6ae99SBarry Smith   PetscFunctionBegin;
1344a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dac, DM_CLASSID, 1);
1345a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(daf, DM_CLASSID, 2);
13465a84ad33SLisandro Dalcin   PetscValidPointer(mat, 3);
13479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateInjection, dac, daf, 0, 0));
1348dbbe0bcdSBarry Smith   PetscUseTypeMethod(dac, createinjection, daf, mat);
13499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateInjection, dac, daf, 0, 0));
135047c6ae99SBarry Smith   PetscFunctionReturn(0);
135147c6ae99SBarry Smith }
135247c6ae99SBarry Smith 
1353b412c318SBarry Smith /*@
1354bb7acecfSBarry 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
1355bb7acecfSBarry Smith   a Galerkin finite element model on the `DM`
1356bd041c0cSMatthew G. Knepley 
1357a5bc1bf3SBarry Smith   Collective on dac
1358bd041c0cSMatthew G. Knepley 
1359d8d19677SJose E. Roman   Input Parameters:
1360bb7acecfSBarry Smith + dmc - the target `DM` object
1361bb7acecfSBarry Smith - dmf - the source `DM` object
1362bd041c0cSMatthew G. Knepley 
1363bd041c0cSMatthew G. Knepley   Output Parameter:
1364b4937a87SMatthew G. Knepley . mat - the mass matrix
1365bd041c0cSMatthew G. Knepley 
1366bd041c0cSMatthew G. Knepley   Level: developer
1367bd041c0cSMatthew G. Knepley 
1368bb7acecfSBarry Smith   Notes:
1369bb7acecfSBarry Smith   For `DMPLEX` the finite element model for the `DM` must have been already provided.
1370bb7acecfSBarry Smith 
1371bb7acecfSBarry 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()`
1372bb7acecfSBarry Smith 
1373bb7acecfSBarry Smith .seealso: `DMCreateMassMatrixLumped()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolation()`, `DMCreateInjection()`
1374bd041c0cSMatthew G. Knepley @*/
1375d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix(DM dmc, DM dmf, Mat *mat)
1376d71ae5a4SJacob Faibussowitsch {
1377bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
1378b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1379b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
13805a84ad33SLisandro Dalcin   PetscValidPointer(mat, 3);
13815b8ffe73SMark Adams   PetscCall(PetscLogEventBegin(DM_CreateMassMatrix, 0, 0, 0, 0));
1382dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createmassmatrix, dmf, mat);
13835b8ffe73SMark Adams   PetscCall(PetscLogEventEnd(DM_CreateMassMatrix, 0, 0, 0, 0));
1384b4937a87SMatthew G. Knepley   PetscFunctionReturn(0);
1385b4937a87SMatthew G. Knepley }
1386b4937a87SMatthew G. Knepley 
1387b4937a87SMatthew G. Knepley /*@
1388bb7acecfSBarry Smith   DMCreateMassMatrixLumped - Gets the lumped mass matrix for a given `DM`
1389b4937a87SMatthew G. Knepley 
1390b4937a87SMatthew G. Knepley   Collective on dm
1391b4937a87SMatthew G. Knepley 
1392b4937a87SMatthew G. Knepley   Input Parameter:
1393bb7acecfSBarry Smith . dm - the `DM` object
1394b4937a87SMatthew G. Knepley 
1395b4937a87SMatthew G. Knepley   Output Parameter:
1396bb7acecfSBarry Smith . lm - the lumped mass matrix, which is a diagonal matrix, represented as a vector
1397b4937a87SMatthew G. Knepley 
1398b4937a87SMatthew G. Knepley   Level: developer
1399b4937a87SMatthew G. Knepley 
1400bb7acecfSBarry Smith   Note:
1401bb7acecfSBarry Smith   See `DMCreateMassMatrix()` for how to create the non-lumped version of the mass matrix.
1402bb7acecfSBarry Smith 
1403bb7acecfSBarry Smith .seealso: `DMCreateMassMatrix()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolation()`, `DMCreateInjection()`
1404b4937a87SMatthew G. Knepley @*/
1405d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped(DM dm, Vec *lm)
1406d71ae5a4SJacob Faibussowitsch {
1407b4937a87SMatthew G. Knepley   PetscFunctionBegin;
1408b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1409b4937a87SMatthew G. Knepley   PetscValidPointer(lm, 2);
1410dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createmassmatrixlumped, lm);
1411bd041c0cSMatthew G. Knepley   PetscFunctionReturn(0);
1412bd041c0cSMatthew G. Knepley }
1413bd041c0cSMatthew G. Knepley 
1414bd041c0cSMatthew G. Knepley /*@
1415bb7acecfSBarry Smith     DMCreateColoring - Gets coloring of a graph associated with the `DM`. Often the graph represents the operator matrix associated with the discretization
1416bb7acecfSBarry Smith     of a PDE on the `DM`.
141747c6ae99SBarry Smith 
1418d083f849SBarry Smith     Collective on dm
141947c6ae99SBarry Smith 
1420d8d19677SJose E. Roman     Input Parameters:
1421bb7acecfSBarry Smith +   dm - the `DM` object
1422bb7acecfSBarry Smith -   ctype - `IS_COLORING_LOCAL` or `IS_COLORING_GLOBAL`
142347c6ae99SBarry Smith 
142447c6ae99SBarry Smith     Output Parameter:
142547c6ae99SBarry Smith .   coloring - the coloring
142647c6ae99SBarry Smith 
1427ec5066bdSBarry Smith     Notes:
1428bb7acecfSBarry 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
1429bb7acecfSBarry Smith     matrix comes from (what this function provides). In general using the mesh produces a more optimal coloring (fewer colors).
1430ec5066bdSBarry Smith 
1431bb7acecfSBarry Smith     This produces a coloring with the distance of 2, see `MatSetColoringDistance()` which can be used for efficiently computing Jacobians with `MatFDColoringCreate()`
1432ec5066bdSBarry Smith 
143347c6ae99SBarry Smith     Level: developer
143447c6ae99SBarry Smith 
1435bb7acecfSBarry Smith .seealso: `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatType()`, `MatColoring`, `MatFDColoringCreate()`
143647c6ae99SBarry Smith 
1437aab9d709SJed Brown @*/
1438d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring(DM dm, ISColoringType ctype, ISColoring *coloring)
1439d71ae5a4SJacob Faibussowitsch {
144047c6ae99SBarry Smith   PetscFunctionBegin;
1441171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14425a84ad33SLisandro Dalcin   PetscValidPointer(coloring, 3);
1443dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getcoloring, ctype, coloring);
144447c6ae99SBarry Smith   PetscFunctionReturn(0);
144547c6ae99SBarry Smith }
144647c6ae99SBarry Smith 
1447b412c318SBarry Smith /*@
1448bb7acecfSBarry Smith     DMCreateMatrix - Gets an empty matrix for a `DM` that is most commonly used to store the Jacobian of a discrete PDE operator.
144947c6ae99SBarry Smith 
1450d083f849SBarry Smith     Collective on dm
145147c6ae99SBarry Smith 
145247c6ae99SBarry Smith     Input Parameter:
1453bb7acecfSBarry Smith .   dm - the `DM` object
145447c6ae99SBarry Smith 
145547c6ae99SBarry Smith     Output Parameter:
145647c6ae99SBarry Smith .   mat - the empty Jacobian
145747c6ae99SBarry Smith 
1458073dac72SJed Brown     Level: beginner
145947c6ae99SBarry Smith 
1460f27dd7c6SMatthew G. Knepley     Options Database Keys:
1461bb7acecfSBarry Smith . -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()` and `DMCreateMassMatrix()`, but do not fill it with zeros
1462f27dd7c6SMatthew G. Knepley 
146395452b02SPatrick Sanan     Notes:
146495452b02SPatrick Sanan     This properly preallocates the number of nonzeros in the sparse matrix so you
146594013140SBarry Smith     do not need to do it yourself.
146694013140SBarry Smith 
146794013140SBarry Smith     By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1468bb7acecfSBarry Smith     the nonzero pattern call `DMSetMatrixPreallocateOnly()`
146994013140SBarry Smith 
1470bb7acecfSBarry Smith     For `DMDA`, when you call `MatView()` on this matrix it is displayed using the global natural ordering, NOT in the ordering used
147194013140SBarry Smith     internally by PETSc.
147294013140SBarry Smith 
1473bb7acecfSBarry Smith     For `DMDA`, in general it is easiest to use `MatSetValuesStencil()` or `MatSetValuesLocal()` to put values into the matrix because
1474bb7acecfSBarry Smith     `MatSetValues()` requires the indices for the global numbering for the `DMDA` which is complic`ated to compute
147594013140SBarry Smith 
1476bb7acecfSBarry Smith .seealso: `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMSetMatType()`, `DMCreateMassMatrix()`
147747c6ae99SBarry Smith 
1478aab9d709SJed Brown @*/
1479d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix(DM dm, Mat *mat)
1480d71ae5a4SJacob Faibussowitsch {
148147c6ae99SBarry Smith   PetscFunctionBegin;
1482171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1483064a246eSJacob Faibussowitsch   PetscValidPointer(mat, 2);
14849566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
14859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateMatrix, 0, 0, 0, 0));
1486dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, creatematrix, mat);
148776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1488c6b011d8SStefano Zampini     DM mdm;
1489c6b011d8SStefano Zampini 
14909566063dSJacob Faibussowitsch     PetscCall(MatGetDM(*mat, &mdm));
14917a8be351SBarry Smith     PetscCheck(mdm, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DM type '%s' did not attach the DM to the matrix", ((PetscObject)dm)->type_name);
1492c6b011d8SStefano Zampini   }
1493e571a35bSMatthew G. Knepley   /* Handle nullspace and near nullspace */
1494e5e52638SMatthew G. Knepley   if (dm->Nf) {
1495e571a35bSMatthew G. Knepley     MatNullSpace nullSpace;
1496649ef022SMatthew Knepley     PetscInt     Nf, f;
1497e571a35bSMatthew G. Knepley 
14989566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
1499649ef022SMatthew Knepley     for (f = 0; f < Nf; ++f) {
1500649ef022SMatthew Knepley       if (dm->nullspaceConstructors[f]) {
15019566063dSJacob Faibussowitsch         PetscCall((*dm->nullspaceConstructors[f])(dm, f, f, &nullSpace));
15029566063dSJacob Faibussowitsch         PetscCall(MatSetNullSpace(*mat, nullSpace));
15039566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nullSpace));
1504649ef022SMatthew Knepley         break;
1505e571a35bSMatthew G. Knepley       }
1506649ef022SMatthew Knepley     }
1507649ef022SMatthew Knepley     for (f = 0; f < Nf; ++f) {
1508649ef022SMatthew Knepley       if (dm->nearnullspaceConstructors[f]) {
15099566063dSJacob Faibussowitsch         PetscCall((*dm->nearnullspaceConstructors[f])(dm, f, f, &nullSpace));
15109566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(*mat, nullSpace));
15119566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nullSpace));
1512e571a35bSMatthew G. Knepley       }
1513e571a35bSMatthew G. Knepley     }
1514e571a35bSMatthew G. Knepley   }
15159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateMatrix, 0, 0, 0, 0));
151647c6ae99SBarry Smith   PetscFunctionReturn(0);
151747c6ae99SBarry Smith }
151847c6ae99SBarry Smith 
1519732e2eb9SMatthew G Knepley /*@
1520bb7acecfSBarry Smith   DMSetMatrixPreallocateSkip - When `DMCreateMatrix()` is called the matrix sizes and `ISLocalToGlobalMapping` will be
1521bb7acecfSBarry 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
1522bb7acecfSBarry Smith   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` will be used.
1523aa0f6e3cSJed Brown 
1524aa0f6e3cSJed Brown   Logically Collective on dm
1525aa0f6e3cSJed Brown 
1526aa0f6e3cSJed Brown   Input Parameters:
1527bb7acecfSBarry Smith + dm - the `DM`
1528bb7acecfSBarry Smith - skip - `PETSC_TRUE` to skip preallocation
1529aa0f6e3cSJed Brown 
1530aa0f6e3cSJed Brown   Level: developer
1531aa0f6e3cSJed Brown 
1532bb7acecfSBarry Smith .seealso: `DMCreateMatrix()`, `DMSetMatrixStructureOnly()`, `DMSetMatrixPreallocateOnly()`
1533aa0f6e3cSJed Brown @*/
1534d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixPreallocateSkip(DM dm, PetscBool skip)
1535d71ae5a4SJacob Faibussowitsch {
1536aa0f6e3cSJed Brown   PetscFunctionBegin;
1537aa0f6e3cSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1538aa0f6e3cSJed Brown   dm->prealloc_skip = skip;
1539aa0f6e3cSJed Brown   PetscFunctionReturn(0);
1540aa0f6e3cSJed Brown }
1541aa0f6e3cSJed Brown 
1542aa0f6e3cSJed Brown /*@
1543bb7acecfSBarry Smith   DMSetMatrixPreallocateOnly - When `DMCreateMatrix()` is called the matrix will be properly
1544732e2eb9SMatthew G Knepley     preallocated but the nonzero structure and zero values will not be set.
1545732e2eb9SMatthew G Knepley 
1546d083f849SBarry Smith   Logically Collective on dm
1547732e2eb9SMatthew G Knepley 
1548d8d19677SJose E. Roman   Input Parameters:
1549bb7acecfSBarry Smith + dm - the `DM`
1550bb7acecfSBarry Smith - only - `PETSC_TRUE` if only want preallocation
1551732e2eb9SMatthew G Knepley 
1552732e2eb9SMatthew G Knepley   Level: developer
1553f27dd7c6SMatthew G. Knepley 
1554f27dd7c6SMatthew G. Knepley   Options Database Keys:
1555bb7acecfSBarry Smith . -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()`, `DMCreateMassMatrix()`, but do not fill it with zeros
1556f27dd7c6SMatthew G. Knepley 
1557bb7acecfSBarry Smith .seealso: `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixStructureOnly()`, `DMSetMatrixPreallocateSkip()`
1558732e2eb9SMatthew G Knepley @*/
1559d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1560d71ae5a4SJacob Faibussowitsch {
1561732e2eb9SMatthew G Knepley   PetscFunctionBegin;
1562732e2eb9SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1563732e2eb9SMatthew G Knepley   dm->prealloc_only = only;
1564732e2eb9SMatthew G Knepley   PetscFunctionReturn(0);
1565732e2eb9SMatthew G Knepley }
1566732e2eb9SMatthew G Knepley 
1567b06ff27eSHong Zhang /*@
1568bb7acecfSBarry Smith   DMSetMatrixStructureOnly - When `DMCreateMatrix()` is called, the matrix structure will be created
1569bb7acecfSBarry Smith     but the array for numerical values will not be allocated.
1570b06ff27eSHong Zhang 
1571d083f849SBarry Smith   Logically Collective on dm
1572b06ff27eSHong Zhang 
1573d8d19677SJose E. Roman   Input Parameters:
1574bb7acecfSBarry Smith + dm - the `DM`
1575bb7acecfSBarry Smith - only - `PETSC_TRUE` if you only want matrix stucture
1576b06ff27eSHong Zhang 
1577b06ff27eSHong Zhang   Level: developer
1578bb7acecfSBarry Smith 
1579bb7acecfSBarry Smith .seealso: `DMCreateMatrix()`, `DMSetMatrixPreallocateOnly()`, `DMSetMatrixPreallocateSkip()`
1580b06ff27eSHong Zhang @*/
1581d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1582d71ae5a4SJacob Faibussowitsch {
1583b06ff27eSHong Zhang   PetscFunctionBegin;
1584b06ff27eSHong Zhang   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1585b06ff27eSHong Zhang   dm->structure_only = only;
1586b06ff27eSHong Zhang   PetscFunctionReturn(0);
1587b06ff27eSHong Zhang }
1588b06ff27eSHong Zhang 
1589a89ea682SMatthew G Knepley /*@C
1590bb7acecfSBarry Smith   DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with `DMRestoreWorkArray()`
1591a89ea682SMatthew G Knepley 
1592a89ea682SMatthew G Knepley   Not Collective
1593a89ea682SMatthew G Knepley 
1594a89ea682SMatthew G Knepley   Input Parameters:
1595bb7acecfSBarry Smith + dm - the `DM` object
1596a5b23f4aSJose E. Roman . count - The minimum size
1597bb7acecfSBarry Smith - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, or MPIU_INT)
1598a89ea682SMatthew G Knepley 
1599a89ea682SMatthew G Knepley   Output Parameter:
1600a89ea682SMatthew G Knepley . array - the work array
1601a89ea682SMatthew G Knepley 
1602a89ea682SMatthew G Knepley   Level: developer
1603a89ea682SMatthew G Knepley 
1604bb7acecfSBarry Smith   Note:
1605bb7acecfSBarry Smith   A `DM` may stash the array between instantations so using this routine may be more efficient than calling `PetscMalloc()`
1606bb7acecfSBarry Smith 
1607bb7acecfSBarry Smith   The array may contain nonzero values
1608bb7acecfSBarry Smith 
1609bb7acecfSBarry Smith .seealso: `DMDestroy()`, `DMCreate()`, `DMRestoreWorkArray()`, `PetscMalloc()`
1610a89ea682SMatthew G Knepley @*/
1611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetWorkArray(DM dm, PetscInt count, MPI_Datatype dtype, void *mem)
1612d71ae5a4SJacob Faibussowitsch {
1613aa1993deSMatthew G Knepley   DMWorkLink  link;
161469291d52SBarry Smith   PetscMPIInt dsize;
1615a89ea682SMatthew G Knepley 
1616a89ea682SMatthew G Knepley   PetscFunctionBegin;
1617a89ea682SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1618aa1993deSMatthew G Knepley   PetscValidPointer(mem, 4);
1619aa1993deSMatthew G Knepley   if (dm->workin) {
1620aa1993deSMatthew G Knepley     link       = dm->workin;
1621aa1993deSMatthew G Knepley     dm->workin = dm->workin->next;
1622aa1993deSMatthew G Knepley   } else {
16234dfa11a4SJacob Faibussowitsch     PetscCall(PetscNew(&link));
1624a89ea682SMatthew G Knepley   }
16259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_size(dtype, &dsize));
16265056fcd2SBarry Smith   if (((size_t)dsize * count) > link->bytes) {
16279566063dSJacob Faibussowitsch     PetscCall(PetscFree(link->mem));
16289566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(dsize * count, &link->mem));
1629854ce69bSBarry Smith     link->bytes = dsize * count;
1630aa1993deSMatthew G Knepley   }
1631aa1993deSMatthew G Knepley   link->next  = dm->workout;
1632aa1993deSMatthew G Knepley   dm->workout = link;
1633cea3dcb8SSatish Balay #if defined(__MEMCHECK_H) && (defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) || defined(PLAT_amd64_darwin))
163400d952a4SJed Brown   VALGRIND_MAKE_MEM_NOACCESS((char *)link->mem + (size_t)dsize * count, link->bytes - (size_t)dsize * count);
163500d952a4SJed Brown   VALGRIND_MAKE_MEM_UNDEFINED(link->mem, (size_t)dsize * count);
163600d952a4SJed Brown #endif
1637aa1993deSMatthew G Knepley   *(void **)mem = link->mem;
1638a89ea682SMatthew G Knepley   PetscFunctionReturn(0);
1639a89ea682SMatthew G Knepley }
1640a89ea682SMatthew G Knepley 
1641aa1993deSMatthew G Knepley /*@C
1642bb7acecfSBarry Smith   DMRestoreWorkArray - Restores a work array obtained with `DMCreateWorkArray()`
1643aa1993deSMatthew G Knepley 
1644aa1993deSMatthew G Knepley   Not Collective
1645aa1993deSMatthew G Knepley 
1646aa1993deSMatthew G Knepley   Input Parameters:
1647bb7acecfSBarry Smith + dm - the `DM` object
1648a5b23f4aSJose E. Roman . count - The minimum size
164969291d52SBarry Smith - dtype - MPI data type, often MPIU_REAL, MPIU_SCALAR, MPIU_INT
1650aa1993deSMatthew G Knepley 
1651aa1993deSMatthew G Knepley   Output Parameter:
1652aa1993deSMatthew G Knepley . array - the work array
1653aa1993deSMatthew G Knepley 
1654aa1993deSMatthew G Knepley   Level: developer
1655aa1993deSMatthew G Knepley 
165695452b02SPatrick Sanan   Developer Notes:
1657bb7acecfSBarry Smith   count and dtype are ignored, they are only needed for `DMGetWorkArray()`
1658147403d9SBarry Smith 
1659bb7acecfSBarry Smith .seealso: `DMDestroy()`, `DMCreate()`, `DMGetWorkArray()`
1660aa1993deSMatthew G Knepley @*/
1661d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestoreWorkArray(DM dm, PetscInt count, MPI_Datatype dtype, void *mem)
1662d71ae5a4SJacob Faibussowitsch {
1663aa1993deSMatthew G Knepley   DMWorkLink *p, link;
1664aa1993deSMatthew G Knepley 
1665aa1993deSMatthew G Knepley   PetscFunctionBegin;
1666aa1993deSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1667aa1993deSMatthew G Knepley   PetscValidPointer(mem, 4);
1668aa1993deSMatthew G Knepley   for (p = &dm->workout; (link = *p); p = &link->next) {
1669aa1993deSMatthew G Knepley     if (link->mem == *(void **)mem) {
1670aa1993deSMatthew G Knepley       *p            = link->next;
1671aa1993deSMatthew G Knepley       link->next    = dm->workin;
1672aa1993deSMatthew G Knepley       dm->workin    = link;
16730298fd71SBarry Smith       *(void **)mem = NULL;
1674aa1993deSMatthew G Knepley       PetscFunctionReturn(0);
1675aa1993deSMatthew G Knepley     }
1676aa1993deSMatthew G Knepley   }
1677aa1993deSMatthew G Knepley   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Array was not checked out");
1678aa1993deSMatthew G Knepley }
1679e7c4fc90SDmitry Karpeev 
16808cda7954SMatthew G. Knepley /*@C
1681bb7acecfSBarry Smith   DMSetNullSpaceConstructor - Provide a callback function which constructs the nullspace for a given field, defined with `DMAddField()`, when function spaces
1682bb7acecfSBarry Smith   are joined or split, such as in `DMCreateSubDM()`
16838cda7954SMatthew G. Knepley 
1684bb7acecfSBarry Smith   Logically collective on dm
16858cda7954SMatthew G. Knepley 
16868cda7954SMatthew G. Knepley   Input Parameters:
1687bb7acecfSBarry Smith + dm     - The `DM`
16888cda7954SMatthew G. Knepley . field  - The field number for the nullspace
16898cda7954SMatthew G. Knepley - nullsp - A callback to create the nullspace
16908cda7954SMatthew G. Knepley 
1691147403d9SBarry Smith   Calling sequence of nullsp:
1692147403d9SBarry Smith .vb
1693147403d9SBarry Smith     PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1694147403d9SBarry Smith .ve
1695bb7acecfSBarry Smith +  dm        - The present `DM`
1696bb7acecfSBarry Smith .  origField - The field number given above, in the original `DM`
1697147403d9SBarry Smith .  field     - The field number in dm
1698147403d9SBarry Smith -  nullSpace - The nullspace for the given field
16998cda7954SMatthew G. Knepley 
170049762cbcSSatish Balay   Level: intermediate
170149762cbcSSatish Balay 
1702bb7acecfSBarry Smith   Fortran Notes:
1703bb7acecfSBarry Smith   This function is not available from Fortran.
1704bb7acecfSBarry Smith 
1705bb7acecfSBarry Smith .seealso: `DMAddField()`, `DMGetNullSpaceConstructor()`, `DMSetNearNullSpaceConstructor()`, `DMGetNearNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
1706147403d9SBarry Smith @*/
1707d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM, PetscInt, PetscInt, MatNullSpace *))
1708d71ae5a4SJacob Faibussowitsch {
1709435a35e8SMatthew G Knepley   PetscFunctionBegin;
1710435a35e8SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17117a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1712435a35e8SMatthew G Knepley   dm->nullspaceConstructors[field] = nullsp;
1713435a35e8SMatthew G Knepley   PetscFunctionReturn(0);
1714435a35e8SMatthew G Knepley }
1715435a35e8SMatthew G Knepley 
17168cda7954SMatthew G. Knepley /*@C
1717bb7acecfSBarry Smith   DMGetNullSpaceConstructor - Return the callback function which constructs the nullspace for a given field, defined with `DMAddField()`
17188cda7954SMatthew G. Knepley 
17198cda7954SMatthew G. Knepley   Not collective
17208cda7954SMatthew G. Knepley 
17218cda7954SMatthew G. Knepley   Input Parameters:
1722bb7acecfSBarry Smith + dm     - The `DM`
17238cda7954SMatthew G. Knepley - field  - The field number for the nullspace
17248cda7954SMatthew G. Knepley 
17258cda7954SMatthew G. Knepley   Output Parameter:
17268cda7954SMatthew G. Knepley . nullsp - A callback to create the nullspace
17278cda7954SMatthew G. Knepley 
1728147403d9SBarry Smith   Calling sequence of nullsp:
1729147403d9SBarry Smith .vb
1730147403d9SBarry Smith     PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1731147403d9SBarry Smith .ve
1732147403d9SBarry Smith +  dm        - The present DM
1733147403d9SBarry Smith .  origField - The field number given above, in the original DM
1734147403d9SBarry Smith .  field     - The field number in dm
1735147403d9SBarry Smith -  nullSpace - The nullspace for the given field
17368cda7954SMatthew G. Knepley 
1737bb7acecfSBarry Smith   Fortran Note:
1738bb7acecfSBarry Smith   This function is not available from Fortran.
17398cda7954SMatthew G. Knepley 
174049762cbcSSatish Balay    Level: intermediate
174149762cbcSSatish Balay 
1742bb7acecfSBarry Smith .seealso: `DMAddField()`, `DMGetField()`, `DMSetNullSpaceConstructor()`, `DMSetNearNullSpaceConstructor()`, `DMGetNearNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
1743147403d9SBarry Smith @*/
1744d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM, PetscInt, PetscInt, MatNullSpace *))
1745d71ae5a4SJacob Faibussowitsch {
17460a50eb56SMatthew G. Knepley   PetscFunctionBegin;
17470a50eb56SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1748f9d4088aSMatthew G. Knepley   PetscValidPointer(nullsp, 3);
17497a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
17500a50eb56SMatthew G. Knepley   *nullsp = dm->nullspaceConstructors[field];
17510a50eb56SMatthew G. Knepley   PetscFunctionReturn(0);
17520a50eb56SMatthew G. Knepley }
17530a50eb56SMatthew G. Knepley 
17548cda7954SMatthew G. Knepley /*@C
1755bb7acecfSBarry Smith   DMSetNearNullSpaceConstructor - Provide a callback function which constructs the near-nullspace for a given field, defined with `DMAddField()`
17568cda7954SMatthew G. Knepley 
1757bb7acecfSBarry Smith   Logically collective on dm
17588cda7954SMatthew G. Knepley 
17598cda7954SMatthew G. Knepley   Input Parameters:
1760bb7acecfSBarry Smith + dm     - The `DM`
17618cda7954SMatthew G. Knepley . field  - The field number for the nullspace
17628cda7954SMatthew G. Knepley - nullsp - A callback to create the near-nullspace
17638cda7954SMatthew G. Knepley 
1764147403d9SBarry Smith   Calling sequence of nullsp:
1765147403d9SBarry Smith .vb
1766147403d9SBarry Smith     PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1767147403d9SBarry Smith .ve
1768bb7acecfSBarry Smith +  dm        - The present `DM`
1769bb7acecfSBarry Smith .  origField - The field number given above, in the original `DM`
1770147403d9SBarry Smith .  field     - The field number in dm
1771147403d9SBarry Smith -  nullSpace - The nullspace for the given field
17728cda7954SMatthew G. Knepley 
1773bb7acecfSBarry Smith   Fortran Note:
1774bb7acecfSBarry Smith   This function is not available from Fortran.
17758cda7954SMatthew G. Knepley 
177649762cbcSSatish Balay    Level: intermediate
177749762cbcSSatish Balay 
1778bb7acecfSBarry Smith .seealso: `DMAddField()`, `DMGetNearNullSpaceConstructor()`, `DMSetNullSpaceConstructor()`, `DMGetNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`,
1779bb7acecfSBarry Smith           `MatNullSpace`
1780147403d9SBarry Smith @*/
1781d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM, PetscInt, PetscInt, MatNullSpace *))
1782d71ae5a4SJacob Faibussowitsch {
1783f9d4088aSMatthew G. Knepley   PetscFunctionBegin;
1784f9d4088aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17857a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1786f9d4088aSMatthew G. Knepley   dm->nearnullspaceConstructors[field] = nullsp;
1787f9d4088aSMatthew G. Knepley   PetscFunctionReturn(0);
1788f9d4088aSMatthew G. Knepley }
1789f9d4088aSMatthew G. Knepley 
17908cda7954SMatthew G. Knepley /*@C
1791bb7acecfSBarry Smith   DMGetNearNullSpaceConstructor - Return the callback function which constructs the near-nullspace for a given field, defined with `DMAddField()`
17928cda7954SMatthew G. Knepley 
17938cda7954SMatthew G. Knepley   Not collective
17948cda7954SMatthew G. Knepley 
17958cda7954SMatthew G. Knepley   Input Parameters:
1796bb7acecfSBarry Smith + dm     - The `DM`
17978cda7954SMatthew G. Knepley - field  - The field number for the nullspace
17988cda7954SMatthew G. Knepley 
17998cda7954SMatthew G. Knepley   Output Parameter:
18008cda7954SMatthew G. Knepley . nullsp - A callback to create the near-nullspace
18018cda7954SMatthew G. Knepley 
1802147403d9SBarry Smith   Calling sequence of nullsp:
1803147403d9SBarry Smith .vb
1804147403d9SBarry Smith     PetscErrorCode nullsp(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace)
1805147403d9SBarry Smith .ve
1806bb7acecfSBarry Smith +  dm        - The present `DM`
1807bb7acecfSBarry Smith .  origField - The field number given above, in the original `DM`
1808147403d9SBarry Smith .  field     - The field number in dm
1809147403d9SBarry Smith -  nullSpace - The nullspace for the given field
18108cda7954SMatthew G. Knepley 
1811bb7acecfSBarry Smith   Fortran Note:
1812bb7acecfSBarry Smith   This function is not available from Fortran.
18138cda7954SMatthew G. Knepley 
181449762cbcSSatish Balay    Level: intermediate
181549762cbcSSatish Balay 
1816bb7acecfSBarry Smith .seealso: `DMAddField()`, `DMGetField()`, `DMSetNearNullSpaceConstructor()`, `DMSetNullSpaceConstructor()`, `DMGetNullSpaceConstructor()`, `DMCreateSubDM()`,
1817bb7acecfSBarry Smith           `MatNullSpace`, `DMCreateSuperDM()`
1818147403d9SBarry Smith @*/
1819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM, PetscInt, PetscInt, MatNullSpace *))
1820d71ae5a4SJacob Faibussowitsch {
1821f9d4088aSMatthew G. Knepley   PetscFunctionBegin;
1822f9d4088aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1823f9d4088aSMatthew G. Knepley   PetscValidPointer(nullsp, 3);
18247a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1825f9d4088aSMatthew G. Knepley   *nullsp = dm->nearnullspaceConstructors[field];
1826f9d4088aSMatthew G. Knepley   PetscFunctionReturn(0);
1827f9d4088aSMatthew G. Knepley }
1828f9d4088aSMatthew G. Knepley 
18294f3b5142SJed Brown /*@C
1830bb7acecfSBarry Smith   DMCreateFieldIS - Creates a set of `IS` objects with the global indices of dofs for each field defined with `DMAddField()`
18314d343eeaSMatthew G Knepley 
18324d343eeaSMatthew G Knepley   Not collective
18334d343eeaSMatthew G Knepley 
18344d343eeaSMatthew G Knepley   Input Parameter:
1835bb7acecfSBarry Smith . dm - the `DM` object
18364d343eeaSMatthew G Knepley 
18374d343eeaSMatthew G Knepley   Output Parameters:
18380298fd71SBarry Smith + numFields  - The number of fields (or NULL if not requested)
1839bb7acecfSBarry Smith . fieldNames - The number of each field (or NULL if not requested)
18400298fd71SBarry Smith - fields     - The global indices for each field (or NULL if not requested)
18414d343eeaSMatthew G Knepley 
18424d343eeaSMatthew G Knepley   Level: intermediate
18434d343eeaSMatthew G Knepley 
1844bb7acecfSBarry Smith   Note:
184521c9b008SJed Brown   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1846bb7acecfSBarry Smith   `PetscFree()`, every entry of fields should be destroyed with `ISDestroy()`, and both arrays should be freed with
1847bb7acecfSBarry Smith   `PetscFree()`.
184821c9b008SJed Brown 
1849bb7acecfSBarry Smith   Fortran Note:
1850bb7acecfSBarry Smith   Not available in Fortran.
1851bb7acecfSBarry Smith 
1852bb7acecfSBarry Smith   Developer Note:
1853bb7acecfSBarry Smith   It is not clear why both this function and `DMCreateFieldDecomposition()` exist. Having two seems redundant and confusing. This function should
1854bb7acecfSBarry Smith   likely be removed.
1855bb7acecfSBarry Smith 
1856bb7acecfSBarry Smith .seealso: `DMAddField()`, `DMGetField()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
1857bb7acecfSBarry Smith           `DMCreateFieldDecomposition()`
18584d343eeaSMatthew G Knepley @*/
1859d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1860d71ae5a4SJacob Faibussowitsch {
186137d0c07bSMatthew G Knepley   PetscSection section, sectionGlobal;
18624d343eeaSMatthew G Knepley 
18634d343eeaSMatthew G Knepley   PetscFunctionBegin;
18644d343eeaSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
186569ca1f37SDmitry Karpeev   if (numFields) {
1866534a8f05SLisandro Dalcin     PetscValidIntPointer(numFields, 2);
186769ca1f37SDmitry Karpeev     *numFields = 0;
186869ca1f37SDmitry Karpeev   }
186937d0c07bSMatthew G Knepley   if (fieldNames) {
187037d0c07bSMatthew G Knepley     PetscValidPointer(fieldNames, 3);
18710298fd71SBarry Smith     *fieldNames = NULL;
187269ca1f37SDmitry Karpeev   }
187369ca1f37SDmitry Karpeev   if (fields) {
187469ca1f37SDmitry Karpeev     PetscValidPointer(fields, 4);
18750298fd71SBarry Smith     *fields = NULL;
187669ca1f37SDmitry Karpeev   }
18779566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
187837d0c07bSMatthew G Knepley   if (section) {
18793a544194SStefano Zampini     PetscInt *fieldSizes, *fieldNc, **fieldIndices;
188037d0c07bSMatthew G Knepley     PetscInt  nF, f, pStart, pEnd, p;
188137d0c07bSMatthew G Knepley 
18829566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
18839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &nF));
18849566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(nF, &fieldSizes, nF, &fieldNc, nF, &fieldIndices));
18859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
188637d0c07bSMatthew G Knepley     for (f = 0; f < nF; ++f) {
188737d0c07bSMatthew G Knepley       fieldSizes[f] = 0;
18889566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &fieldNc[f]));
188937d0c07bSMatthew G Knepley     }
189037d0c07bSMatthew G Knepley     for (p = pStart; p < pEnd; ++p) {
189137d0c07bSMatthew G Knepley       PetscInt gdof;
189237d0c07bSMatthew G Knepley 
18939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
189437d0c07bSMatthew G Knepley       if (gdof > 0) {
189537d0c07bSMatthew G Knepley         for (f = 0; f < nF; ++f) {
18963a544194SStefano Zampini           PetscInt fdof, fcdof, fpdof;
189737d0c07bSMatthew G Knepley 
18989566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
18999566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
19003a544194SStefano Zampini           fpdof = fdof - fcdof;
19013a544194SStefano Zampini           if (fpdof && fpdof != fieldNc[f]) {
19023a544194SStefano Zampini             /* Layout does not admit a pointwise block size */
19033a544194SStefano Zampini             fieldNc[f] = 1;
19043a544194SStefano Zampini           }
19053a544194SStefano Zampini           fieldSizes[f] += fpdof;
190637d0c07bSMatthew G Knepley         }
190737d0c07bSMatthew G Knepley       }
190837d0c07bSMatthew G Knepley     }
190937d0c07bSMatthew G Knepley     for (f = 0; f < nF; ++f) {
19109566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(fieldSizes[f], &fieldIndices[f]));
191137d0c07bSMatthew G Knepley       fieldSizes[f] = 0;
191237d0c07bSMatthew G Knepley     }
191337d0c07bSMatthew G Knepley     for (p = pStart; p < pEnd; ++p) {
191437d0c07bSMatthew G Knepley       PetscInt gdof, goff;
191537d0c07bSMatthew G Knepley 
19169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
191737d0c07bSMatthew G Knepley       if (gdof > 0) {
19189566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff));
191937d0c07bSMatthew G Knepley         for (f = 0; f < nF; ++f) {
192037d0c07bSMatthew G Knepley           PetscInt fdof, fcdof, fc;
192137d0c07bSMatthew G Knepley 
19229566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
19239566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
1924ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++fieldSizes[f]) fieldIndices[f][fieldSizes[f]] = goff++;
192537d0c07bSMatthew G Knepley         }
192637d0c07bSMatthew G Knepley       }
192737d0c07bSMatthew G Knepley     }
19288865f1eaSKarl Rupp     if (numFields) *numFields = nF;
192937d0c07bSMatthew G Knepley     if (fieldNames) {
19309566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nF, fieldNames));
193137d0c07bSMatthew G Knepley       for (f = 0; f < nF; ++f) {
193237d0c07bSMatthew G Knepley         const char *fieldName;
193337d0c07bSMatthew G Knepley 
19349566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
19359566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(fieldName, (char **)&(*fieldNames)[f]));
193637d0c07bSMatthew G Knepley       }
193737d0c07bSMatthew G Knepley     }
193837d0c07bSMatthew G Knepley     if (fields) {
19399566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nF, fields));
194037d0c07bSMatthew G Knepley       for (f = 0; f < nF; ++f) {
19413a544194SStefano Zampini         PetscInt bs, in[2], out[2];
19423a544194SStefano Zampini 
19439566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]));
19443a544194SStefano Zampini         in[0] = -fieldNc[f];
19453a544194SStefano Zampini         in[1] = fieldNc[f];
19461c2dc1cbSBarry Smith         PetscCall(MPIU_Allreduce(in, out, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
19473a544194SStefano Zampini         bs = (-out[0] == out[1]) ? out[1] : 1;
19489566063dSJacob Faibussowitsch         PetscCall(ISSetBlockSize((*fields)[f], bs));
194937d0c07bSMatthew G Knepley       }
195037d0c07bSMatthew G Knepley     }
19519566063dSJacob Faibussowitsch     PetscCall(PetscFree3(fieldSizes, fieldNc, fieldIndices));
1952dbbe0bcdSBarry Smith   } else PetscTryTypeMethod(dm, createfieldis, numFields, fieldNames, fields);
19534d343eeaSMatthew G Knepley   PetscFunctionReturn(0);
19544d343eeaSMatthew G Knepley }
19554d343eeaSMatthew G Knepley 
195616621825SDmitry Karpeev /*@C
1957bb7acecfSBarry Smith   DMCreateFieldDecomposition - Returns a list of `IS` objects defining a decomposition of a problem into subproblems
1958bb7acecfSBarry Smith                           corresponding to different fields: each `IS` contains the global indices of the dofs of the
1959bb7acecfSBarry Smith                           corresponding field, defined by `DMAddField()`. The optional list of `DM`s define the `DM` for each subproblem.
1960bb7acecfSBarry Smith                           The same as `DMCreateFieldIS()` but also returns a `DM` for each field.
1961e7c4fc90SDmitry Karpeev 
1962e7c4fc90SDmitry Karpeev   Not collective
1963e7c4fc90SDmitry Karpeev 
1964e7c4fc90SDmitry Karpeev   Input Parameter:
1965bb7acecfSBarry Smith . dm - the `DM` object
1966e7c4fc90SDmitry Karpeev 
1967e7c4fc90SDmitry Karpeev   Output Parameters:
1968bb7acecfSBarry Smith + len       - The number of fields (or NULL if not requested)
19690298fd71SBarry Smith . namelist  - The name for each field (or NULL if not requested)
19700298fd71SBarry Smith . islist    - The global indices for each field (or NULL if not requested)
1971bb7acecfSBarry Smith - dmlist    - The `DM`s for each field subproblem (or NULL, if not requested; if NULL is returned, no `DM`s are defined)
1972e7c4fc90SDmitry Karpeev 
1973e7c4fc90SDmitry Karpeev   Level: intermediate
1974e7c4fc90SDmitry Karpeev 
1975bb7acecfSBarry Smith   Note:
1976e7c4fc90SDmitry Karpeev   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1977bb7acecfSBarry Smith   `PetscFree()`, every entry of is should be destroyed with `ISDestroy()`, every entry of dm should be destroyed with `DMDestroy()`,
1978bb7acecfSBarry Smith   and all of the arrays should be freed with `PetscFree()`.
1979e7c4fc90SDmitry Karpeev 
1980bb7acecfSBarry Smith   Fortran Note:
1981bb7acecfSBarry Smith   Not available in Fortran.
1982bb7acecfSBarry Smith 
1983bb7acecfSBarry Smith   Developer Note:
1984bb7acecfSBarry Smith   It is not clear why this function and `DMCreateFieldIS()` exist. Having two seems redundant and confusing.
1985bb7acecfSBarry Smith 
1986bb7acecfSBarry Smith .seealso: `DMAddField()`, `DMCreateFieldIS()`, `DMCreateSubDM()`, `DMCreateDomainDecomposition()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
1987e7c4fc90SDmitry Karpeev @*/
1988d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1989d71ae5a4SJacob Faibussowitsch {
1990e7c4fc90SDmitry Karpeev   PetscFunctionBegin;
1991e7c4fc90SDmitry Karpeev   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19928865f1eaSKarl Rupp   if (len) {
1993534a8f05SLisandro Dalcin     PetscValidIntPointer(len, 2);
19948865f1eaSKarl Rupp     *len = 0;
19958865f1eaSKarl Rupp   }
19968865f1eaSKarl Rupp   if (namelist) {
19978865f1eaSKarl Rupp     PetscValidPointer(namelist, 3);
1998ea78f98cSLisandro Dalcin     *namelist = NULL;
19998865f1eaSKarl Rupp   }
20008865f1eaSKarl Rupp   if (islist) {
20018865f1eaSKarl Rupp     PetscValidPointer(islist, 4);
2002ea78f98cSLisandro Dalcin     *islist = NULL;
20038865f1eaSKarl Rupp   }
20048865f1eaSKarl Rupp   if (dmlist) {
20058865f1eaSKarl Rupp     PetscValidPointer(dmlist, 5);
2006ea78f98cSLisandro Dalcin     *dmlist = NULL;
20078865f1eaSKarl Rupp   }
2008f3f0edfdSDmitry Karpeev   /*
2009f3f0edfdSDmitry Karpeev    Is it a good idea to apply the following check across all impls?
2010f3f0edfdSDmitry Karpeev    Perhaps some impls can have a well-defined decomposition before DMSetUp?
2011f3f0edfdSDmitry Karpeev    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
2012f3f0edfdSDmitry Karpeev    */
20137a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
201416621825SDmitry Karpeev   if (!dm->ops->createfielddecomposition) {
2015435a35e8SMatthew G Knepley     PetscSection section;
2016435a35e8SMatthew G Knepley     PetscInt     numFields, f;
2017435a35e8SMatthew G Knepley 
20189566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
20199566063dSJacob Faibussowitsch     if (section) PetscCall(PetscSectionGetNumFields(section, &numFields));
2020435a35e8SMatthew G Knepley     if (section && numFields && dm->ops->createsubdm) {
2021f25d98f1SMatthew G. Knepley       if (len) *len = numFields;
20229566063dSJacob Faibussowitsch       if (namelist) PetscCall(PetscMalloc1(numFields, namelist));
20239566063dSJacob Faibussowitsch       if (islist) PetscCall(PetscMalloc1(numFields, islist));
20249566063dSJacob Faibussowitsch       if (dmlist) PetscCall(PetscMalloc1(numFields, dmlist));
2025435a35e8SMatthew G Knepley       for (f = 0; f < numFields; ++f) {
2026435a35e8SMatthew G Knepley         const char *fieldName;
2027435a35e8SMatthew G Knepley 
20289566063dSJacob Faibussowitsch         PetscCall(DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL));
202903dc3394SMatthew G. Knepley         if (namelist) {
20309566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
20319566063dSJacob Faibussowitsch           PetscCall(PetscStrallocpy(fieldName, (char **)&(*namelist)[f]));
2032435a35e8SMatthew G Knepley         }
203303dc3394SMatthew G. Knepley       }
2034435a35e8SMatthew G Knepley     } else {
20359566063dSJacob Faibussowitsch       PetscCall(DMCreateFieldIS(dm, len, namelist, islist));
2036e7c4fc90SDmitry Karpeev       /* By default there are no DMs associated with subproblems. */
20370298fd71SBarry Smith       if (dmlist) *dmlist = NULL;
2038e7c4fc90SDmitry Karpeev     }
2039dbbe0bcdSBarry Smith   } else PetscUseTypeMethod(dm, createfielddecomposition, len, namelist, islist, dmlist);
204016621825SDmitry Karpeev   PetscFunctionReturn(0);
204116621825SDmitry Karpeev }
204216621825SDmitry Karpeev 
2043412a4547SAlexis Marboeuf /*@C
2044412a4547SAlexis Marboeuf   DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in.
2045412a4547SAlexis Marboeuf                   The fields are defined by DMCreateFieldIS().
2046435a35e8SMatthew G Knepley 
2047435a35e8SMatthew G Knepley   Not collective
2048435a35e8SMatthew G Knepley 
2049435a35e8SMatthew G Knepley   Input Parameters:
2050bb7acecfSBarry Smith + dm        - The `DM `object
2051bb7acecfSBarry Smith . numFields - The number of fields to select
20522adcc780SMatthew G. Knepley - fields    - The field numbers of the selected fields
2053435a35e8SMatthew G Knepley 
2054435a35e8SMatthew G Knepley   Output Parameters:
2055bb7acecfSBarry Smith + is - The global indices for all the degrees of freedom in the new sub `DM`
2056bb7acecfSBarry Smith - subdm - The `DM` for the subproblem
2057435a35e8SMatthew G Knepley 
2058bb7acecfSBarry Smith   Note:
2059bb7acecfSBarry Smith   You need to call `DMPlexSetMigrationSF()` on the original `DM` if you want the Global-To-Natural map to be automatically constructed
20605d3b26e6SMatthew G. Knepley 
2061435a35e8SMatthew G Knepley   Level: intermediate
2062435a35e8SMatthew G Knepley 
2063bb7acecfSBarry Smith .seealso: `DMCreateFieldIS()`, `DMCreateFieldDecomposition()`, `DMAddField()`, `DMCreateSuperDM()`, `DM`, `IS`, `DMPlexSetMigrationSF()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
2064435a35e8SMatthew G Knepley @*/
2065d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
2066d71ae5a4SJacob Faibussowitsch {
2067435a35e8SMatthew G Knepley   PetscFunctionBegin;
2068435a35e8SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2069dadcf809SJacob Faibussowitsch   PetscValidIntPointer(fields, 3);
20708865f1eaSKarl Rupp   if (is) PetscValidPointer(is, 4);
20718865f1eaSKarl Rupp   if (subdm) PetscValidPointer(subdm, 5);
2072dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createsubdm, numFields, fields, is, subdm);
2073435a35e8SMatthew G Knepley   PetscFunctionReturn(0);
2074435a35e8SMatthew G Knepley }
2075435a35e8SMatthew G Knepley 
20762adcc780SMatthew G. Knepley /*@C
2077bb7acecfSBarry Smith   DMCreateSuperDM - Returns an arrays of `IS` and `DM` encapsulating a superproblem defined by multiple `DM`s passed in.
20782adcc780SMatthew G. Knepley 
20792adcc780SMatthew G. Knepley   Not collective
20802adcc780SMatthew G. Knepley 
2081d8d19677SJose E. Roman   Input Parameters:
2082bb7acecfSBarry Smith + dms - The `DM` objects
2083bb7acecfSBarry Smith - n - The number of `DM`s
20842adcc780SMatthew G. Knepley 
20852adcc780SMatthew G. Knepley   Output Parameters:
2086bb7acecfSBarry Smith + is - The global indices for each of subproblem within the super `DM`, or NULL
2087bb7acecfSBarry Smith - superdm - The `DM` for the superproblem
20882adcc780SMatthew G. Knepley 
2089bb7acecfSBarry Smith   Note:
2090bb7acecfSBarry Smith   You need to call `DMPlexSetMigrationSF()` on the original `DM` if you want the Global-To-Natural map to be automatically constructed
20915d3b26e6SMatthew G. Knepley 
20922adcc780SMatthew G. Knepley   Level: intermediate
20932adcc780SMatthew G. Knepley 
2094bb7acecfSBarry Smith .seealso: `DM`, `DMCreateSubDM()`, `DMPlexSetMigrationSF()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
20952adcc780SMatthew G. Knepley @*/
2096d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt n, IS **is, DM *superdm)
2097d71ae5a4SJacob Faibussowitsch {
20982adcc780SMatthew G. Knepley   PetscInt i;
20992adcc780SMatthew G. Knepley 
21002adcc780SMatthew G. Knepley   PetscFunctionBegin;
21012adcc780SMatthew G. Knepley   PetscValidPointer(dms, 1);
2102ad540459SPierre Jolivet   for (i = 0; i < n; ++i) PetscValidHeaderSpecific(dms[i], DM_CLASSID, 1);
21032adcc780SMatthew G. Knepley   if (is) PetscValidPointer(is, 3);
2104a42bd24dSMatthew G. Knepley   PetscValidPointer(superdm, 4);
2105bb7acecfSBarry Smith   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %" PetscInt_FMT, n);
2106bb7acecfSBarry Smith   if (n) {
2107b9d85ea2SLisandro Dalcin     DM dm = dms[0];
2108dbbe0bcdSBarry Smith     PetscCall((*dm->ops->createsuperdm)(dms, n, is, superdm));
21092adcc780SMatthew G. Knepley   }
21102adcc780SMatthew G. Knepley   PetscFunctionReturn(0);
21112adcc780SMatthew G. Knepley }
21122adcc780SMatthew G. Knepley 
211316621825SDmitry Karpeev /*@C
2114bb7acecfSBarry Smith   DMCreateDomainDecomposition - Returns lists of `IS` objects defining a decomposition of a problem into subproblems
2115bb7acecfSBarry Smith                           corresponding to restrictions to pairs of nested subdomains: each `IS` contains the global
2116bb7acecfSBarry Smith                           indices of the dofs of the corresponding subdomains with in the dofs of the original `DM`.
2117bb7acecfSBarry Smith                           The inner subdomains conceptually define a nonoverlapping covering, while outer subdomains can overlap.
2118bb7acecfSBarry Smith                           The optional list of `DM`s define a `DM` for each subproblem.
211916621825SDmitry Karpeev 
212016621825SDmitry Karpeev   Not collective
212116621825SDmitry Karpeev 
212216621825SDmitry Karpeev   Input Parameter:
2123bb7acecfSBarry Smith . dm - the `DM` object
212416621825SDmitry Karpeev 
212516621825SDmitry Karpeev   Output Parameters:
2126bb7acecfSBarry Smith + n            - The number of subproblems in the domain decomposition (or NULL if not requested)
21270298fd71SBarry Smith . namelist    - The name for each subdomain (or NULL if not requested)
21280298fd71SBarry Smith . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
21290298fd71SBarry Smith . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
2130bb7acecfSBarry Smith - dmlist      - The `DM`s for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no `DM`s are defined)
213116621825SDmitry Karpeev 
213216621825SDmitry Karpeev   Level: intermediate
213316621825SDmitry Karpeev 
2134bb7acecfSBarry Smith   Note:
213516621825SDmitry Karpeev   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
2136bb7acecfSBarry Smith   `PetscFree()`, every entry of is should be destroyed with `ISDestroy()`, every entry of dm should be destroyed with `DMDestroy()`,
2137bb7acecfSBarry Smith   and all of the arrays should be freed with `PetscFree()`.
213816621825SDmitry Karpeev 
2139bb7acecfSBarry Smith   Questions:
2140bb7acecfSBarry Smith   The dmlist is for the inner subdomains or the outer subdomains or all subdomains?
2141bb7acecfSBarry Smith 
2142bb7acecfSBarry Smith .seealso: `DMCreateFieldDecomposition()`, `DMDestroy()`, `DMCreateDomainDecompositionScatters()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldDecomposition()`
214316621825SDmitry Karpeev @*/
2144d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *n, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
2145d71ae5a4SJacob Faibussowitsch {
2146be081cd6SPeter Brune   DMSubDomainHookLink link;
2147be081cd6SPeter Brune   PetscInt            i, l;
214816621825SDmitry Karpeev 
214916621825SDmitry Karpeev   PetscFunctionBegin;
215016621825SDmitry Karpeev   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21519371c9d4SSatish Balay   if (n) {
21529371c9d4SSatish Balay     PetscValidIntPointer(n, 2);
21539371c9d4SSatish Balay     *n = 0;
21549371c9d4SSatish Balay   }
21559371c9d4SSatish Balay   if (namelist) {
21569371c9d4SSatish Balay     PetscValidPointer(namelist, 3);
21579371c9d4SSatish Balay     *namelist = NULL;
21589371c9d4SSatish Balay   }
21599371c9d4SSatish Balay   if (innerislist) {
21609371c9d4SSatish Balay     PetscValidPointer(innerislist, 4);
21619371c9d4SSatish Balay     *innerislist = NULL;
21629371c9d4SSatish Balay   }
21639371c9d4SSatish Balay   if (outerislist) {
21649371c9d4SSatish Balay     PetscValidPointer(outerislist, 5);
21659371c9d4SSatish Balay     *outerislist = NULL;
21669371c9d4SSatish Balay   }
21679371c9d4SSatish Balay   if (dmlist) {
21689371c9d4SSatish Balay     PetscValidPointer(dmlist, 6);
21699371c9d4SSatish Balay     *dmlist = NULL;
21709371c9d4SSatish Balay   }
2171f3f0edfdSDmitry Karpeev   /*
2172f3f0edfdSDmitry Karpeev    Is it a good idea to apply the following check across all impls?
2173f3f0edfdSDmitry Karpeev    Perhaps some impls can have a well-defined decomposition before DMSetUp?
2174f3f0edfdSDmitry Karpeev    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
2175f3f0edfdSDmitry Karpeev    */
21767a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
217716621825SDmitry Karpeev   if (dm->ops->createdomaindecomposition) {
2178dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createdomaindecomposition, &l, namelist, innerislist, outerislist, dmlist);
217914a18fd3SPeter Brune     /* copy subdomain hooks and context over to the subdomain DMs */
2180f891f5b9SPatrick Sanan     if (dmlist && *dmlist) {
2181be081cd6SPeter Brune       for (i = 0; i < l; i++) {
2182be081cd6SPeter Brune         for (link = dm->subdomainhook; link; link = link->next) {
21839566063dSJacob Faibussowitsch           if (link->ddhook) PetscCall((*link->ddhook)(dm, (*dmlist)[i], link->ctx));
2184be081cd6SPeter Brune         }
2185648262bbSPatrick Sanan         if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
2186e7c4fc90SDmitry Karpeev       }
218714a18fd3SPeter Brune     }
2188bb7acecfSBarry Smith     if (n) *n = l;
218914a18fd3SPeter Brune   }
2190e30e807fSPeter Brune   PetscFunctionReturn(0);
2191e30e807fSPeter Brune }
2192e30e807fSPeter Brune 
2193e30e807fSPeter Brune /*@C
2194e30e807fSPeter Brune   DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
2195e30e807fSPeter Brune 
2196e30e807fSPeter Brune   Not collective
2197e30e807fSPeter Brune 
2198e30e807fSPeter Brune   Input Parameters:
2199bb7acecfSBarry Smith + dm - the `DM` object
2200e30e807fSPeter Brune . n  - the number of subdomain scatters
2201e30e807fSPeter Brune - subdms - the local subdomains
2202e30e807fSPeter Brune 
2203e30e807fSPeter Brune   Output Parameters:
22046b867d5aSJose E. Roman + iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
2205e30e807fSPeter Brune . oscat - scatter from global vector to overlapping global vector entries on subdomain
2206e30e807fSPeter Brune - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
2207e30e807fSPeter Brune 
2208bb7acecfSBarry Smith   Note:
2209bb7acecfSBarry Smith     This is an alternative to the iis and ois arguments in `DMCreateDomainDecomposition()` that allow for the solution
2210e30e807fSPeter Brune   of general nonlinear problems with overlapping subdomain methods.  While merely having index sets that enable subsets
2211e30e807fSPeter Brune   of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
2212e30e807fSPeter Brune   solution and residual data.
2213e30e807fSPeter Brune 
2214bb7acecfSBarry Smith   Questions:
2215bb7acecfSBarry Smith   Can the subdms input be anything or are they exactly the `DM` obtained from `DMCreateDomainDecomposition()`?
2216bb7acecfSBarry Smith 
2217e30e807fSPeter Brune   Level: developer
2218e30e807fSPeter Brune 
2219bb7acecfSBarry Smith .seealso: `DM`, `DMCreateDomainDecomposition()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
2220e30e807fSPeter Brune @*/
2221d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDomainDecompositionScatters(DM dm, PetscInt n, DM *subdms, VecScatter **iscat, VecScatter **oscat, VecScatter **gscat)
2222d71ae5a4SJacob Faibussowitsch {
2223e30e807fSPeter Brune   PetscFunctionBegin;
2224e30e807fSPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2225e30e807fSPeter Brune   PetscValidPointer(subdms, 3);
2226dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createddscatters, n, subdms, iscat, oscat, gscat);
2227e7c4fc90SDmitry Karpeev   PetscFunctionReturn(0);
2228e7c4fc90SDmitry Karpeev }
2229e7c4fc90SDmitry Karpeev 
223047c6ae99SBarry Smith /*@
2231bb7acecfSBarry Smith   DMRefine - Refines a `DM` object using a standard nonadaptive refinement of the underlying mesh
223247c6ae99SBarry Smith 
2233d083f849SBarry Smith   Collective on dm
223447c6ae99SBarry Smith 
2235d8d19677SJose E. Roman   Input Parameters:
2236bb7acecfSBarry Smith + dm   - the `DM` object
2237bb7acecfSBarry Smith - comm - the communicator to contain the new `DM` object (or `MPI_COMM_NULL`)
223847c6ae99SBarry Smith 
223947c6ae99SBarry Smith   Output Parameter:
2240bb7acecfSBarry Smith . dmf - the refined `D`M, or NULL
2241ae0a1c52SMatthew G Knepley 
2242f27dd7c6SMatthew G. Knepley   Options Database Keys:
2243412e9a14SMatthew G. Knepley . -dm_plex_cell_refiner <strategy> - chooses the refinement strategy, e.g. regular, tohex
2244412e9a14SMatthew G. Knepley 
2245bb7acecfSBarry Smith   Note:
2246bb7acecfSBarry Smith   If no refinement was done, the return value is NULL
224747c6ae99SBarry Smith 
224847c6ae99SBarry Smith   Level: developer
224947c6ae99SBarry Smith 
2250bb7acecfSBarry Smith .seealso: `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
225147c6ae99SBarry Smith @*/
2252d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefine(DM dm, MPI_Comm comm, DM *dmf)
2253d71ae5a4SJacob Faibussowitsch {
2254c833c3b5SJed Brown   DMRefineHookLink link;
225547c6ae99SBarry Smith 
225647c6ae99SBarry Smith   PetscFunctionBegin;
2257732e2eb9SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Refine, dm, 0, 0, 0));
2259dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, refine, comm, dmf);
22604057135bSMatthew G Knepley   if (*dmf) {
226143842a1eSJed Brown     (*dmf)->ops->creatematrix = dm->ops->creatematrix;
22628865f1eaSKarl Rupp 
22639566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmf));
22648865f1eaSKarl Rupp 
2265644e2e5bSBarry Smith     (*dmf)->ctx       = dm->ctx;
22660598a293SJed Brown     (*dmf)->leveldown = dm->leveldown;
2267656b349aSBarry Smith     (*dmf)->levelup   = dm->levelup + 1;
22688865f1eaSKarl Rupp 
22699566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmf, dm->mattype));
2270c833c3b5SJed Brown     for (link = dm->refinehook; link; link = link->next) {
22711baa6e33SBarry Smith       if (link->refinehook) PetscCall((*link->refinehook)(dm, *dmf, link->ctx));
2272c833c3b5SJed Brown     }
2273c833c3b5SJed Brown   }
22749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Refine, dm, 0, 0, 0));
2275c833c3b5SJed Brown   PetscFunctionReturn(0);
2276c833c3b5SJed Brown }
2277c833c3b5SJed Brown 
2278bb9467b5SJed Brown /*@C
2279c833c3b5SJed Brown    DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
2280c833c3b5SJed Brown 
2281bb7acecfSBarry Smith    Logically Collective on coarse
2282c833c3b5SJed Brown 
22834165533cSJose E. Roman    Input Parameters:
2284bb7acecfSBarry Smith +  coarse - `DM` on which to run a hook when interpolating to a finer level
2285bb7acecfSBarry Smith .  refinehook - function to run when setting up the finer level
2286bb7acecfSBarry Smith .  interphook - function to run to update data on finer levels (once per `SNESSolve`())
22870298fd71SBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2288c833c3b5SJed Brown 
2289c833c3b5SJed Brown    Calling sequence of refinehook:
2290c833c3b5SJed Brown $    refinehook(DM coarse,DM fine,void *ctx);
2291c833c3b5SJed Brown 
2292bb7acecfSBarry Smith +  coarse - coarse level `DM`
2293bb7acecfSBarry Smith .  fine - fine level `DM` to interpolate problem to
2294c833c3b5SJed Brown -  ctx - optional user-defined function context
2295c833c3b5SJed Brown 
2296c833c3b5SJed Brown    Calling sequence for interphook:
2297c833c3b5SJed Brown $    interphook(DM coarse,Mat interp,DM fine,void *ctx)
2298c833c3b5SJed Brown 
2299bb7acecfSBarry Smith +  coarse - coarse level `DM`
2300c833c3b5SJed Brown .  interp - matrix interpolating a coarse-level solution to the finer grid
2301bb7acecfSBarry Smith .  fine - fine level `DM` to update
2302c833c3b5SJed Brown -  ctx - optional user-defined function context
2303c833c3b5SJed Brown 
2304c833c3b5SJed Brown    Level: advanced
2305c833c3b5SJed Brown 
2306c833c3b5SJed Brown    Notes:
2307bb7acecfSBarry Smith    This function is only needed if auxiliary data that is attached to the `DM`s via, for example, `PetscObjectCompose()`, needs to be
2308bb7acecfSBarry Smith    passed to fine grids while grid sequencing.
2309bb7acecfSBarry Smith 
2310bb7acecfSBarry Smith    The actual interpolation is done when `DMInterpolate()` is called.
2311c833c3b5SJed Brown 
2312c833c3b5SJed Brown    If this function is called multiple times, the hooks will be run in the order they are added.
2313c833c3b5SJed Brown 
2314bb7acecfSBarry Smith    Fortran Note:
2315bb7acecfSBarry Smith    This function is not available from Fortran.
2316bb9467b5SJed Brown 
2317bb7acecfSBarry Smith .seealso: `DM`, `DMCoarsenHookAdd()`, `DMInterpolate()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2318c833c3b5SJed Brown @*/
2319d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHookAdd(DM coarse, PetscErrorCode (*refinehook)(DM, DM, void *), PetscErrorCode (*interphook)(DM, Mat, DM, void *), void *ctx)
2320d71ae5a4SJacob Faibussowitsch {
2321c833c3b5SJed Brown   DMRefineHookLink link, *p;
2322c833c3b5SJed Brown 
2323c833c3b5SJed Brown   PetscFunctionBegin;
2324c833c3b5SJed Brown   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
23253d8e3701SJed Brown   for (p = &coarse->refinehook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
23263d8e3701SJed Brown     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) PetscFunctionReturn(0);
23273d8e3701SJed Brown   }
23289566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2329c833c3b5SJed Brown   link->refinehook = refinehook;
2330c833c3b5SJed Brown   link->interphook = interphook;
2331c833c3b5SJed Brown   link->ctx        = ctx;
23320298fd71SBarry Smith   link->next       = NULL;
2333c833c3b5SJed Brown   *p               = link;
2334c833c3b5SJed Brown   PetscFunctionReturn(0);
2335c833c3b5SJed Brown }
2336c833c3b5SJed Brown 
23373d8e3701SJed Brown /*@C
2338bb7acecfSBarry Smith    DMRefineHookRemove - remove a callback from the list of hooks, that have been set with `DMRefineHookAdd()`, to be run when interpolating
2339bb7acecfSBarry Smith     a nonlinear problem to a finer grid
23403d8e3701SJed Brown 
2341bb7acecfSBarry Smith    Logically Collective on coarse
23423d8e3701SJed Brown 
23434165533cSJose E. Roman    Input Parameters:
2344bb7acecfSBarry Smith +  coarse - the `DM` on which to run a hook when restricting to a coarser level
2345bb7acecfSBarry Smith .  refinehook - function to run when setting up a finer level
2346bb7acecfSBarry Smith .  interphook - function to run to update data on finer levels
23473d8e3701SJed Brown -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
23483d8e3701SJed Brown 
23493d8e3701SJed Brown    Level: advanced
23503d8e3701SJed Brown 
2351bb7acecfSBarry Smith    Note:
23523d8e3701SJed Brown    This function does nothing if the hook is not in the list.
23533d8e3701SJed Brown 
2354bb7acecfSBarry Smith    Fortran Note:
2355bb7acecfSBarry Smith    This function is not available from Fortran.
23563d8e3701SJed Brown 
2357bb7acecfSBarry Smith .seealso: `DMRefineHookAdd()`, `DMCoarsenHookRemove()`, `DMInterpolate()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
23583d8e3701SJed Brown @*/
2359d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHookRemove(DM coarse, PetscErrorCode (*refinehook)(DM, DM, void *), PetscErrorCode (*interphook)(DM, Mat, DM, void *), void *ctx)
2360d71ae5a4SJacob Faibussowitsch {
23613d8e3701SJed Brown   DMRefineHookLink link, *p;
23623d8e3701SJed Brown 
23633d8e3701SJed Brown   PetscFunctionBegin;
23643d8e3701SJed Brown   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
23653d8e3701SJed Brown   for (p = &coarse->refinehook; *p; p = &(*p)->next) { /* Search the list of current hooks */
23663d8e3701SJed Brown     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
23673d8e3701SJed Brown       link = *p;
23683d8e3701SJed Brown       *p   = link->next;
23699566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
23703d8e3701SJed Brown       break;
23713d8e3701SJed Brown     }
23723d8e3701SJed Brown   }
23733d8e3701SJed Brown   PetscFunctionReturn(0);
23743d8e3701SJed Brown }
23753d8e3701SJed Brown 
2376c833c3b5SJed Brown /*@
2377bb7acecfSBarry Smith    DMInterpolate - interpolates user-defined problem data attached to a `DM` to a finer `DM` by running hooks registered by `DMRefineHookAdd()`
2378c833c3b5SJed Brown 
2379c833c3b5SJed Brown    Collective if any hooks are
2380c833c3b5SJed Brown 
23814165533cSJose E. Roman    Input Parameters:
2382bb7acecfSBarry Smith +  coarse - coarser `DM` to use as a base
2383bb7acecfSBarry Smith .  interp - interpolation matrix, apply using `MatInterpolate()`
2384bb7acecfSBarry Smith -  fine - finer `DM` to update
2385c833c3b5SJed Brown 
2386c833c3b5SJed Brown    Level: developer
2387c833c3b5SJed Brown 
2388bb7acecfSBarry Smith    Developer Note:
2389bb7acecfSBarry Smith    This routine is called `DMInterpolate()` while the hook is called `DMRefineHookAdd()`. It would be better to have an
2390bb7acecfSBarry Smith    an API with consistent terminology.
2391bb7acecfSBarry Smith 
2392bb7acecfSBarry Smith .seealso: `DM`, `DMRefineHookAdd()`, `MatInterpolate()`
2393c833c3b5SJed Brown @*/
2394d71ae5a4SJacob Faibussowitsch PetscErrorCode DMInterpolate(DM coarse, Mat interp, DM fine)
2395d71ae5a4SJacob Faibussowitsch {
2396c833c3b5SJed Brown   DMRefineHookLink link;
2397c833c3b5SJed Brown 
2398c833c3b5SJed Brown   PetscFunctionBegin;
2399c833c3b5SJed Brown   for (link = fine->refinehook; link; link = link->next) {
24001baa6e33SBarry Smith     if (link->interphook) PetscCall((*link->interphook)(coarse, interp, fine, link->ctx));
24014057135bSMatthew G Knepley   }
240247c6ae99SBarry Smith   PetscFunctionReturn(0);
240347c6ae99SBarry Smith }
240447c6ae99SBarry Smith 
2405eb3f98d2SBarry Smith /*@
24061f3379b2SToby Isaac    DMInterpolateSolution - Interpolates a solution from a coarse mesh to a fine mesh.
24071f3379b2SToby Isaac 
2408bb7acecfSBarry Smith    Collective on dm
24091f3379b2SToby Isaac 
24104165533cSJose E. Roman    Input Parameters:
2411bb7acecfSBarry Smith +  coarse - coarse `DM`
2412bb7acecfSBarry Smith .  fine   - fine `DM`
2413bb7acecfSBarry Smith .  interp - (optional) the matrix computed by `DMCreateInterpolation()`.  Implementations may not need this, but if it
2414bb7acecfSBarry Smith             is available it can avoid some recomputation.  If it is provided, `MatInterpolate()` will be used if
2415bb7acecfSBarry Smith             the coarse `DM` does not have a specialized implementation.
24161f3379b2SToby Isaac -  coarseSol - solution on the coarse mesh
24171f3379b2SToby Isaac 
24184165533cSJose E. Roman    Output Parameter:
24191f3379b2SToby Isaac .  fineSol - the interpolation of coarseSol to the fine mesh
24201f3379b2SToby Isaac 
24211f3379b2SToby Isaac    Level: developer
24221f3379b2SToby Isaac 
2423bb7acecfSBarry Smith    Note:
2424bb7acecfSBarry Smith    This function exists because the interpolation of a solution vector between meshes is not always a linear
24251f3379b2SToby Isaac    map.  For example, if a boundary value problem has an inhomogeneous Dirichlet boundary condition that is compressed
24261f3379b2SToby Isaac    out of the solution vector.  Or if interpolation is inherently a nonlinear operation, such as a method using
24271f3379b2SToby Isaac    slope-limiting reconstruction.
24281f3379b2SToby Isaac 
2429bb7acecfSBarry Smith    Developer Note:
2430bb7acecfSBarry Smith    This doesn't just interpolate "solutions" so its API name is questionable.
2431bb7acecfSBarry Smith 
2432bb7acecfSBarry Smith .seealso: `DMInterpolate()`, `DMCreateInterpolation()`
24331f3379b2SToby Isaac @*/
2434d71ae5a4SJacob Faibussowitsch PetscErrorCode DMInterpolateSolution(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
2435d71ae5a4SJacob Faibussowitsch {
24361f3379b2SToby Isaac   PetscErrorCode (*interpsol)(DM, DM, Mat, Vec, Vec) = NULL;
24371f3379b2SToby Isaac 
24381f3379b2SToby Isaac   PetscFunctionBegin;
24391f3379b2SToby Isaac   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
24401f3379b2SToby Isaac   if (interp) PetscValidHeaderSpecific(interp, MAT_CLASSID, 3);
24411f3379b2SToby Isaac   PetscValidHeaderSpecific(coarseSol, VEC_CLASSID, 4);
24421f3379b2SToby Isaac   PetscValidHeaderSpecific(fineSol, VEC_CLASSID, 5);
24431f3379b2SToby Isaac 
24449566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)coarse, "DMInterpolateSolution_C", &interpsol));
24451f3379b2SToby Isaac   if (interpsol) {
24469566063dSJacob Faibussowitsch     PetscCall((*interpsol)(coarse, fine, interp, coarseSol, fineSol));
24471f3379b2SToby Isaac   } else if (interp) {
24489566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(interp, coarseSol, fineSol));
244998921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)coarse), PETSC_ERR_SUP, "DM %s does not implement DMInterpolateSolution()", ((PetscObject)coarse)->type_name);
24501f3379b2SToby Isaac   PetscFunctionReturn(0);
24511f3379b2SToby Isaac }
24521f3379b2SToby Isaac 
24531f3379b2SToby Isaac /*@
2454bb7acecfSBarry Smith     DMGetRefineLevel - Gets the number of refinements that have generated this `DM` from some initial `DM`.
2455eb3f98d2SBarry Smith 
2456eb3f98d2SBarry Smith     Not Collective
2457eb3f98d2SBarry Smith 
2458eb3f98d2SBarry Smith     Input Parameter:
2459bb7acecfSBarry Smith .   dm - the `DM` object
2460eb3f98d2SBarry Smith 
2461eb3f98d2SBarry Smith     Output Parameter:
2462eb3f98d2SBarry Smith .   level - number of refinements
2463eb3f98d2SBarry Smith 
2464eb3f98d2SBarry Smith     Level: developer
2465eb3f98d2SBarry Smith 
2466bb7acecfSBarry Smith     Note:
2467bb7acecfSBarry Smith     This can be used, by example, to set the number of coarser levels associated with this `DM` for a multigrid solver.
2468bb7acecfSBarry Smith 
2469bb7acecfSBarry Smith .seealso: `DMRefine()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
2470eb3f98d2SBarry Smith 
2471eb3f98d2SBarry Smith @*/
2472d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRefineLevel(DM dm, PetscInt *level)
2473d71ae5a4SJacob Faibussowitsch {
2474eb3f98d2SBarry Smith   PetscFunctionBegin;
2475eb3f98d2SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2476eb3f98d2SBarry Smith   *level = dm->levelup;
2477eb3f98d2SBarry Smith   PetscFunctionReturn(0);
2478eb3f98d2SBarry Smith }
2479eb3f98d2SBarry Smith 
2480fef3a512SBarry Smith /*@
2481bb7acecfSBarry Smith     DMSetRefineLevel - Sets the number of refinements that have generated this `DM`.
2482fef3a512SBarry Smith 
2483fef3a512SBarry Smith     Not Collective
2484fef3a512SBarry Smith 
2485d8d19677SJose E. Roman     Input Parameters:
2486bb7acecfSBarry Smith +   dm - the `DM` object
2487fef3a512SBarry Smith -   level - number of refinements
2488fef3a512SBarry Smith 
2489fef3a512SBarry Smith     Level: advanced
2490fef3a512SBarry Smith 
249195452b02SPatrick Sanan     Notes:
2492bb7acecfSBarry Smith     This value is used by `PCMG` to determine how many multigrid levels to use
2493fef3a512SBarry Smith 
2494bb7acecfSBarry Smith     The values are usually set automatically by the process that is causing the refinements of an initial `DM` by calling this routine.
2495bb7acecfSBarry Smith 
2496bb7acecfSBarry Smith .seealso: `DMGetRefineLevel()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
2497fef3a512SBarry Smith 
2498fef3a512SBarry Smith @*/
2499d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRefineLevel(DM dm, PetscInt level)
2500d71ae5a4SJacob Faibussowitsch {
2501fef3a512SBarry Smith   PetscFunctionBegin;
2502fef3a512SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2503fef3a512SBarry Smith   dm->levelup = level;
2504fef3a512SBarry Smith   PetscFunctionReturn(0);
2505fef3a512SBarry Smith }
2506fef3a512SBarry Smith 
2507d410b0cfSMatthew G. Knepley /*@
2508bb7acecfSBarry Smith   DMExtrude - Extrude a `DM` object from a surface
2509d410b0cfSMatthew G. Knepley 
2510d410b0cfSMatthew G. Knepley   Collective on dm
2511d410b0cfSMatthew G. Knepley 
2512f1a722f8SMatthew G. Knepley   Input Parameters:
2513bb7acecfSBarry Smith + dm     - the `DM` object
2514d410b0cfSMatthew G. Knepley - layers - the number of extruded cell layers
2515d410b0cfSMatthew G. Knepley 
2516d410b0cfSMatthew G. Knepley   Output Parameter:
2517bb7acecfSBarry Smith . dme - the extruded `DM`, or NULL
2518d410b0cfSMatthew G. Knepley 
2519bb7acecfSBarry Smith   Note:
2520bb7acecfSBarry Smith   If no extrusion was done, the return value is NULL
2521d410b0cfSMatthew G. Knepley 
2522d410b0cfSMatthew G. Knepley   Level: developer
2523d410b0cfSMatthew G. Knepley 
2524bb7acecfSBarry Smith .seealso: `DMRefine()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`
2525d410b0cfSMatthew G. Knepley @*/
2526d71ae5a4SJacob Faibussowitsch PetscErrorCode DMExtrude(DM dm, PetscInt layers, DM *dme)
2527d71ae5a4SJacob Faibussowitsch {
2528d410b0cfSMatthew G. Knepley   PetscFunctionBegin;
2529d410b0cfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2530dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, extrude, layers, dme);
2531d410b0cfSMatthew G. Knepley   if (*dme) {
2532d410b0cfSMatthew G. Knepley     (*dme)->ops->creatematrix = dm->ops->creatematrix;
25339566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dme));
2534d410b0cfSMatthew G. Knepley     (*dme)->ctx = dm->ctx;
25359566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dme, dm->mattype));
2536d410b0cfSMatthew G. Knepley   }
2537d410b0cfSMatthew G. Knepley   PetscFunctionReturn(0);
2538d410b0cfSMatthew G. Knepley }
2539d410b0cfSMatthew G. Knepley 
2540d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasisTransformDM_Internal(DM dm, DM *tdm)
2541d71ae5a4SJacob Faibussowitsch {
2542ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2543ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2544ca3d3a14SMatthew G. Knepley   PetscValidPointer(tdm, 2);
2545ca3d3a14SMatthew G. Knepley   *tdm = dm->transformDM;
2546ca3d3a14SMatthew G. Knepley   PetscFunctionReturn(0);
2547ca3d3a14SMatthew G. Knepley }
2548ca3d3a14SMatthew G. Knepley 
2549d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasisTransformVec_Internal(DM dm, Vec *tv)
2550d71ae5a4SJacob Faibussowitsch {
2551ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2552ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2553ca3d3a14SMatthew G. Knepley   PetscValidPointer(tv, 2);
2554ca3d3a14SMatthew G. Knepley   *tv = dm->transform;
2555ca3d3a14SMatthew G. Knepley   PetscFunctionReturn(0);
2556ca3d3a14SMatthew G. Knepley }
2557ca3d3a14SMatthew G. Knepley 
2558ca3d3a14SMatthew G. Knepley /*@
2559bb7acecfSBarry Smith   DMHasBasisTransform - Whether the `DM` employs a basis transformation from functions in global vectors to functions in local vectors
2560ca3d3a14SMatthew G. Knepley 
2561ca3d3a14SMatthew G. Knepley   Input Parameter:
2562ca3d3a14SMatthew G. Knepley . dm - The DM
2563ca3d3a14SMatthew G. Knepley 
2564ca3d3a14SMatthew G. Knepley   Output Parameter:
2565ca3d3a14SMatthew G. Knepley . flg - PETSC_TRUE if a basis transformation should be done
2566ca3d3a14SMatthew G. Knepley 
2567ca3d3a14SMatthew G. Knepley   Level: developer
2568ca3d3a14SMatthew G. Knepley 
2569bb7acecfSBarry Smith .seealso: `DM`, `DMPlexGlobalToLocalBasis()`, `DMPlexLocalToGlobalBasis()`, `DMPlexCreateBasisRotation()`
2570ca3d3a14SMatthew G. Knepley @*/
2571d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasBasisTransform(DM dm, PetscBool *flg)
2572d71ae5a4SJacob Faibussowitsch {
2573ca3d3a14SMatthew G. Knepley   Vec tv;
2574ca3d3a14SMatthew G. Knepley 
2575ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2576ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2577534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
25789566063dSJacob Faibussowitsch   PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
2579ca3d3a14SMatthew G. Knepley   *flg = tv ? PETSC_TRUE : PETSC_FALSE;
2580ca3d3a14SMatthew G. Knepley   PetscFunctionReturn(0);
2581ca3d3a14SMatthew G. Knepley }
2582ca3d3a14SMatthew G. Knepley 
2583d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConstructBasisTransform_Internal(DM dm)
2584d71ae5a4SJacob Faibussowitsch {
2585ca3d3a14SMatthew G. Knepley   PetscSection s, ts;
2586ca3d3a14SMatthew G. Knepley   PetscScalar *ta;
2587ca3d3a14SMatthew G. Knepley   PetscInt     cdim, pStart, pEnd, p, Nf, f, Nc, dof;
2588ca3d3a14SMatthew G. Knepley 
2589ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
25909566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
25919566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
25929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
25939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
25949566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dm->transformDM));
25959566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm->transformDM, &ts));
25969566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(ts, Nf));
25979566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(ts, pStart, pEnd));
2598ca3d3a14SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
25999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
2600ca3d3a14SMatthew G. Knepley     /* We could start to label fields by their transformation properties */
2601ca3d3a14SMatthew G. Knepley     if (Nc != cdim) continue;
2602ca3d3a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
26039566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, f, &dof));
2604ca3d3a14SMatthew G. Knepley       if (!dof) continue;
26059566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(ts, p, f, PetscSqr(cdim)));
26069566063dSJacob Faibussowitsch       PetscCall(PetscSectionAddDof(ts, p, PetscSqr(cdim)));
2607ca3d3a14SMatthew G. Knepley     }
2608ca3d3a14SMatthew G. Knepley   }
26099566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(ts));
26109566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm->transformDM, &dm->transform));
26119566063dSJacob Faibussowitsch   PetscCall(VecGetArray(dm->transform, &ta));
2612ca3d3a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
2613ca3d3a14SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
26149566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(ts, p, f, &dof));
2615ca3d3a14SMatthew G. Knepley       if (dof) {
2616ca3d3a14SMatthew G. Knepley         PetscReal          x[3] = {0.0, 0.0, 0.0};
2617ca3d3a14SMatthew G. Knepley         PetscScalar       *tva;
2618ca3d3a14SMatthew G. Knepley         const PetscScalar *A;
2619ca3d3a14SMatthew G. Knepley 
2620ca3d3a14SMatthew G. Knepley         /* TODO Get quadrature point for this dual basis vector for coordinate */
26219566063dSJacob Faibussowitsch         PetscCall((*dm->transformGetMatrix)(dm, x, PETSC_TRUE, &A, dm->transformCtx));
26229566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalFieldRef(dm->transformDM, p, f, ta, (void *)&tva));
26239566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(tva, A, PetscSqr(cdim)));
2624ca3d3a14SMatthew G. Knepley       }
2625ca3d3a14SMatthew G. Knepley     }
2626ca3d3a14SMatthew G. Knepley   }
26279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(dm->transform, &ta));
2628ca3d3a14SMatthew G. Knepley   PetscFunctionReturn(0);
2629ca3d3a14SMatthew G. Knepley }
2630ca3d3a14SMatthew G. Knepley 
2631d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyTransform(DM dm, DM newdm)
2632d71ae5a4SJacob Faibussowitsch {
2633ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2634ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2635ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(newdm, DM_CLASSID, 2);
2636ca3d3a14SMatthew G. Knepley   newdm->transformCtx       = dm->transformCtx;
2637ca3d3a14SMatthew G. Knepley   newdm->transformSetUp     = dm->transformSetUp;
2638ca3d3a14SMatthew G. Knepley   newdm->transformDestroy   = NULL;
2639ca3d3a14SMatthew G. Knepley   newdm->transformGetMatrix = dm->transformGetMatrix;
26409566063dSJacob Faibussowitsch   if (newdm->transformSetUp) PetscCall(DMConstructBasisTransform_Internal(newdm));
2641ca3d3a14SMatthew G. Knepley   PetscFunctionReturn(0);
2642ca3d3a14SMatthew G. Knepley }
2643ca3d3a14SMatthew G. Knepley 
2644bb9467b5SJed Brown /*@C
2645bb7acecfSBarry Smith    DMGlobalToLocalHookAdd - adds a callback to be run when `DMGlobalToLocal()` is called
2646baf369e7SPeter Brune 
2647bb7acecfSBarry Smith    Logically Collective on dm
2648baf369e7SPeter Brune 
26494165533cSJose E. Roman    Input Parameters:
2650bb7acecfSBarry Smith +  dm - the `DM`
2651bb7acecfSBarry Smith .  beginhook - function to run at the beginning of `DMGlobalToLocalBegin()`
2652bb7acecfSBarry Smith .  endhook - function to run after `DMGlobalToLocalEnd()` has completed
26530298fd71SBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2654baf369e7SPeter Brune 
2655baf369e7SPeter Brune    Calling sequence for beginhook:
2656baf369e7SPeter Brune $    beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
2657baf369e7SPeter Brune 
2658baf369e7SPeter Brune +  dm - global DM
2659baf369e7SPeter Brune .  g - global vector
2660baf369e7SPeter Brune .  mode - mode
2661baf369e7SPeter Brune .  l - local vector
2662baf369e7SPeter Brune -  ctx - optional user-defined function context
2663baf369e7SPeter Brune 
2664baf369e7SPeter Brune    Calling sequence for endhook:
2665ec4806b8SPeter Brune $    endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx)
2666baf369e7SPeter Brune 
2667baf369e7SPeter Brune +  global - global DM
2668baf369e7SPeter Brune -  ctx - optional user-defined function context
2669baf369e7SPeter Brune 
2670baf369e7SPeter Brune    Level: advanced
2671baf369e7SPeter Brune 
2672bb7acecfSBarry Smith    Note:
2673bb7acecfSBarry 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.
2674bb7acecfSBarry Smith 
2675bb7acecfSBarry Smith .seealso: `DM`, `DMGlobalToLocal()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2676baf369e7SPeter Brune @*/
2677d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalHookAdd(DM dm, PetscErrorCode (*beginhook)(DM, Vec, InsertMode, Vec, void *), PetscErrorCode (*endhook)(DM, Vec, InsertMode, Vec, void *), void *ctx)
2678d71ae5a4SJacob Faibussowitsch {
2679baf369e7SPeter Brune   DMGlobalToLocalHookLink link, *p;
2680baf369e7SPeter Brune 
2681baf369e7SPeter Brune   PetscFunctionBegin;
2682baf369e7SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2683baf369e7SPeter Brune   for (p = &dm->gtolhook; *p; p = &(*p)->next) { } /* Scan to the end of the current list of hooks */
26849566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2685baf369e7SPeter Brune   link->beginhook = beginhook;
2686baf369e7SPeter Brune   link->endhook   = endhook;
2687baf369e7SPeter Brune   link->ctx       = ctx;
26880298fd71SBarry Smith   link->next      = NULL;
2689baf369e7SPeter Brune   *p              = link;
2690baf369e7SPeter Brune   PetscFunctionReturn(0);
2691baf369e7SPeter Brune }
2692baf369e7SPeter Brune 
2693d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
2694d71ae5a4SJacob Faibussowitsch {
26954c274da1SToby Isaac   Mat          cMat;
269679769bd5SJed Brown   Vec          cVec, cBias;
26974c274da1SToby Isaac   PetscSection section, cSec;
26984c274da1SToby Isaac   PetscInt     pStart, pEnd, p, dof;
26994c274da1SToby Isaac 
27004c274da1SToby Isaac   PetscFunctionBegin;
27014c274da1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27029566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, &cBias));
27034c274da1SToby Isaac   if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
27045db9a05bSToby Isaac     PetscInt nRows;
27055db9a05bSToby Isaac 
27069566063dSJacob Faibussowitsch     PetscCall(MatGetSize(cMat, &nRows, NULL));
27075db9a05bSToby Isaac     if (nRows <= 0) PetscFunctionReturn(0);
27089566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
27099566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(cMat, NULL, &cVec));
27109566063dSJacob Faibussowitsch     PetscCall(MatMult(cMat, l, cVec));
27119566063dSJacob Faibussowitsch     if (cBias) PetscCall(VecAXPY(cVec, 1., cBias));
27129566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
27134c274da1SToby Isaac     for (p = pStart; p < pEnd; p++) {
27149566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
27154c274da1SToby Isaac       if (dof) {
27164c274da1SToby Isaac         PetscScalar *vals;
27179566063dSJacob Faibussowitsch         PetscCall(VecGetValuesSection(cVec, cSec, p, &vals));
27189566063dSJacob Faibussowitsch         PetscCall(VecSetValuesSection(l, section, p, vals, INSERT_ALL_VALUES));
27194c274da1SToby Isaac       }
27204c274da1SToby Isaac     }
27219566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cVec));
27224c274da1SToby Isaac   }
27234c274da1SToby Isaac   PetscFunctionReturn(0);
27244c274da1SToby Isaac }
27254c274da1SToby Isaac 
272647c6ae99SBarry Smith /*@
272701729b5cSPatrick Sanan     DMGlobalToLocal - update local vectors from global vector
272801729b5cSPatrick Sanan 
2729d083f849SBarry Smith     Neighbor-wise Collective on dm
273001729b5cSPatrick Sanan 
273101729b5cSPatrick Sanan     Input Parameters:
2732bb7acecfSBarry Smith +   dm - the `DM` object
273301729b5cSPatrick Sanan .   g - the global vector
2734bb7acecfSBarry Smith .   mode - `INSERT_VALUES` or `ADD_VALUES`
273501729b5cSPatrick Sanan -   l - the local vector
273601729b5cSPatrick Sanan 
273701729b5cSPatrick Sanan     Notes:
2738bb7acecfSBarry Smith     The communication involved in this update can be overlapped with computation by instead using
2739bb7acecfSBarry Smith     `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()`.
2740bb7acecfSBarry Smith 
2741bb7acecfSBarry Smith     `DMGlobalToLocalHookAdd()` may be used to provide additional operations that are performed during the update process.
274201729b5cSPatrick Sanan 
274301729b5cSPatrick Sanan     Level: beginner
274401729b5cSPatrick Sanan 
2745bb7acecfSBarry Smith .seealso: `DM`, `DMGlobalToLocalHookAdd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`,
2746bb7acecfSBarry Smith           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`,
2747bb7acecfSBarry Smith           `DMGlobalToLocalBegin()` `DMGlobalToLocalEnd()`
274801729b5cSPatrick Sanan 
274901729b5cSPatrick Sanan @*/
2750d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocal(DM dm, Vec g, InsertMode mode, Vec l)
2751d71ae5a4SJacob Faibussowitsch {
275201729b5cSPatrick Sanan   PetscFunctionBegin;
27539566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dm, g, mode, l));
27549566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dm, g, mode, l));
275501729b5cSPatrick Sanan   PetscFunctionReturn(0);
275601729b5cSPatrick Sanan }
275701729b5cSPatrick Sanan 
275801729b5cSPatrick Sanan /*@
275947c6ae99SBarry Smith     DMGlobalToLocalBegin - Begins updating local vectors from global vector
276047c6ae99SBarry Smith 
2761d083f849SBarry Smith     Neighbor-wise Collective on dm
276247c6ae99SBarry Smith 
276347c6ae99SBarry Smith     Input Parameters:
2764bb7acecfSBarry Smith +   dm - the `DM` object
276547c6ae99SBarry Smith .   g - the global vector
2766bb7acecfSBarry Smith .   mode - `INSERT_VALUES` or `ADD_VALUES`
276747c6ae99SBarry Smith -   l - the local vector
276847c6ae99SBarry Smith 
276901729b5cSPatrick Sanan     Level: intermediate
277047c6ae99SBarry Smith 
2771bb7acecfSBarry Smith     Notes:
2772bb7acecfSBarry Smith     The operation is completed with `DMGlobalToLocalEnd()`
2773bb7acecfSBarry Smith 
2774bb7acecfSBarry Smith     One can perform local computations between the `DMGlobalToLocalBegin()` and  `DMGlobalToLocalEnd()` to overlap communication and computation
2775bb7acecfSBarry Smith 
2776bb7acecfSBarry Smith     `DMGlobalToLocal()` is a short form of  `DMGlobalToLocalBegin()` and  `DMGlobalToLocalEnd()`
2777bb7acecfSBarry Smith 
2778bb7acecfSBarry Smith     `DMGlobalToLocalHookAdd()` may be used to provide additional operations that are performed during the update process.
2779bb7acecfSBarry Smith 
2780bb7acecfSBarry Smith .seealso: `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`
278147c6ae99SBarry Smith 
278247c6ae99SBarry Smith @*/
2783d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalBegin(DM dm, Vec g, InsertMode mode, Vec l)
2784d71ae5a4SJacob Faibussowitsch {
27857128ae9fSMatthew G Knepley   PetscSF                 sf;
2786baf369e7SPeter Brune   DMGlobalToLocalHookLink link;
278747c6ae99SBarry Smith 
278847c6ae99SBarry Smith   PetscFunctionBegin;
2789171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2790baf369e7SPeter Brune   for (link = dm->gtolhook; link; link = link->next) {
27911baa6e33SBarry Smith     if (link->beginhook) PetscCall((*link->beginhook)(dm, g, mode, l, link->ctx));
2792baf369e7SPeter Brune   }
27939566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
27947128ae9fSMatthew G Knepley   if (sf) {
2795ae5cfb4aSMatthew G. Knepley     const PetscScalar *gArray;
2796ae5cfb4aSMatthew G. Knepley     PetscScalar       *lArray;
2797d0295fc0SJunchao Zhang     PetscMemType       lmtype, gmtype;
27987128ae9fSMatthew G Knepley 
27997a8be351SBarry Smith     PetscCheck(mode != ADD_VALUES, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", (int)mode);
28009566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(l, &lArray, &lmtype));
28019566063dSJacob Faibussowitsch     PetscCall(VecGetArrayReadAndMemType(g, &gArray, &gmtype));
28029566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastWithMemTypeBegin(sf, MPIU_SCALAR, gmtype, gArray, lmtype, lArray, MPI_REPLACE));
28039566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(l, &lArray));
28049566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayReadAndMemType(g, &gArray));
28057128ae9fSMatthew G Knepley   } else {
28069566063dSJacob Faibussowitsch     PetscCall((*dm->ops->globaltolocalbegin)(dm, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l));
28077128ae9fSMatthew G Knepley   }
280847c6ae99SBarry Smith   PetscFunctionReturn(0);
280947c6ae99SBarry Smith }
281047c6ae99SBarry Smith 
281147c6ae99SBarry Smith /*@
281247c6ae99SBarry Smith     DMGlobalToLocalEnd - Ends updating local vectors from global vector
281347c6ae99SBarry Smith 
2814d083f849SBarry Smith     Neighbor-wise Collective on dm
281547c6ae99SBarry Smith 
281647c6ae99SBarry Smith     Input Parameters:
2817bb7acecfSBarry Smith +   dm - the `DM` object
281847c6ae99SBarry Smith .   g - the global vector
2819bb7acecfSBarry Smith .   mode - `INSERT_VALUES` or `ADD_VALUES`
282047c6ae99SBarry Smith -   l - the local vector
282147c6ae99SBarry Smith 
282201729b5cSPatrick Sanan     Level: intermediate
282347c6ae99SBarry Smith 
2824bb7acecfSBarry Smith     Note:
2825bb7acecfSBarry Smith     See `DMGlobalToLocalBegin()` for details.
2826bb7acecfSBarry Smith 
2827bb7acecfSBarry Smith .seealso: `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`
282847c6ae99SBarry Smith 
282947c6ae99SBarry Smith @*/
2830d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
2831d71ae5a4SJacob Faibussowitsch {
28327128ae9fSMatthew G Knepley   PetscSF                 sf;
2833ae5cfb4aSMatthew G. Knepley   const PetscScalar      *gArray;
2834ae5cfb4aSMatthew G. Knepley   PetscScalar            *lArray;
2835ca3d3a14SMatthew G. Knepley   PetscBool               transform;
2836baf369e7SPeter Brune   DMGlobalToLocalHookLink link;
2837d0295fc0SJunchao Zhang   PetscMemType            lmtype, gmtype;
283847c6ae99SBarry Smith 
283947c6ae99SBarry Smith   PetscFunctionBegin;
2840171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28419566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
28429566063dSJacob Faibussowitsch   PetscCall(DMHasBasisTransform(dm, &transform));
28437128ae9fSMatthew G Knepley   if (sf) {
28447a8be351SBarry Smith     PetscCheck(mode != ADD_VALUES, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", (int)mode);
28457128ae9fSMatthew G Knepley 
28469566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(l, &lArray, &lmtype));
28479566063dSJacob Faibussowitsch     PetscCall(VecGetArrayReadAndMemType(g, &gArray, &gmtype));
28489566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray, MPI_REPLACE));
28499566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(l, &lArray));
28509566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayReadAndMemType(g, &gArray));
28519566063dSJacob Faibussowitsch     if (transform) PetscCall(DMPlexGlobalToLocalBasis(dm, l));
28527128ae9fSMatthew G Knepley   } else {
28539566063dSJacob Faibussowitsch     PetscCall((*dm->ops->globaltolocalend)(dm, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l));
28547128ae9fSMatthew G Knepley   }
28559566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalHook_Constraints(dm, g, mode, l, NULL));
2856baf369e7SPeter Brune   for (link = dm->gtolhook; link; link = link->next) {
28579566063dSJacob Faibussowitsch     if (link->endhook) PetscCall((*link->endhook)(dm, g, mode, l, link->ctx));
2858baf369e7SPeter Brune   }
285947c6ae99SBarry Smith   PetscFunctionReturn(0);
286047c6ae99SBarry Smith }
286147c6ae99SBarry Smith 
2862d4d07f1eSToby Isaac /*@C
2863d4d07f1eSToby Isaac    DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
2864d4d07f1eSToby Isaac 
2865bb7acecfSBarry Smith    Logically Collective on dm
2866d4d07f1eSToby Isaac 
28674165533cSJose E. Roman    Input Parameters:
2868bb7acecfSBarry Smith +  dm - the `DM`
2869bb7acecfSBarry Smith .  beginhook - function to run at the beginning of `DMLocalToGlobalBegin()`
2870bb7acecfSBarry Smith .  endhook - function to run after `DMLocalToGlobalEnd()` has completed
2871d4d07f1eSToby Isaac -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
2872d4d07f1eSToby Isaac 
2873d4d07f1eSToby Isaac    Calling sequence for beginhook:
2874d4d07f1eSToby Isaac $    beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2875d4d07f1eSToby Isaac 
2876bb7acecfSBarry Smith +  dm - global `DM`
2877d4d07f1eSToby Isaac .  l - local vector
2878d4d07f1eSToby Isaac .  mode - mode
2879d4d07f1eSToby Isaac .  g - global vector
2880d4d07f1eSToby Isaac -  ctx - optional user-defined function context
2881d4d07f1eSToby Isaac 
2882d4d07f1eSToby Isaac    Calling sequence for endhook:
2883d4d07f1eSToby Isaac $    endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx)
2884d4d07f1eSToby Isaac 
2885bb7acecfSBarry Smith +  global - global `DM`
2886d4d07f1eSToby Isaac .  l - local vector
2887d4d07f1eSToby Isaac .  mode - mode
2888d4d07f1eSToby Isaac .  g - global vector
2889d4d07f1eSToby Isaac -  ctx - optional user-defined function context
2890d4d07f1eSToby Isaac 
2891d4d07f1eSToby Isaac    Level: advanced
2892d4d07f1eSToby Isaac 
2893bb7acecfSBarry Smith .seealso: `DMLocalToGlobal()`, `DMRefineHookAdd()`, `DMGlobalToLocalHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2894d4d07f1eSToby Isaac @*/
2895d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalHookAdd(DM dm, PetscErrorCode (*beginhook)(DM, Vec, InsertMode, Vec, void *), PetscErrorCode (*endhook)(DM, Vec, InsertMode, Vec, void *), void *ctx)
2896d71ae5a4SJacob Faibussowitsch {
2897d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link, *p;
2898d4d07f1eSToby Isaac 
2899d4d07f1eSToby Isaac   PetscFunctionBegin;
2900d4d07f1eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2901d4d07f1eSToby Isaac   for (p = &dm->ltoghook; *p; p = &(*p)->next) { } /* Scan to the end of the current list of hooks */
29029566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2903d4d07f1eSToby Isaac   link->beginhook = beginhook;
2904d4d07f1eSToby Isaac   link->endhook   = endhook;
2905d4d07f1eSToby Isaac   link->ctx       = ctx;
2906d4d07f1eSToby Isaac   link->next      = NULL;
2907d4d07f1eSToby Isaac   *p              = link;
2908d4d07f1eSToby Isaac   PetscFunctionReturn(0);
2909d4d07f1eSToby Isaac }
2910d4d07f1eSToby Isaac 
2911d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2912d71ae5a4SJacob Faibussowitsch {
29134c274da1SToby Isaac   Mat          cMat;
29144c274da1SToby Isaac   Vec          cVec;
29154c274da1SToby Isaac   PetscSection section, cSec;
29164c274da1SToby Isaac   PetscInt     pStart, pEnd, p, dof;
29174c274da1SToby Isaac 
29184c274da1SToby Isaac   PetscFunctionBegin;
29194c274da1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29209566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
29214c274da1SToby Isaac   if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
29225db9a05bSToby Isaac     PetscInt nRows;
29235db9a05bSToby Isaac 
29249566063dSJacob Faibussowitsch     PetscCall(MatGetSize(cMat, &nRows, NULL));
29255db9a05bSToby Isaac     if (nRows <= 0) PetscFunctionReturn(0);
29269566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
29279566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(cMat, NULL, &cVec));
29289566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
29294c274da1SToby Isaac     for (p = pStart; p < pEnd; p++) {
29309566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
29314c274da1SToby Isaac       if (dof) {
29324c274da1SToby Isaac         PetscInt     d;
29334c274da1SToby Isaac         PetscScalar *vals;
29349566063dSJacob Faibussowitsch         PetscCall(VecGetValuesSection(l, section, p, &vals));
29359566063dSJacob Faibussowitsch         PetscCall(VecSetValuesSection(cVec, cSec, p, vals, mode));
29364c274da1SToby Isaac         /* for this to be the true transpose, we have to zero the values that
29374c274da1SToby Isaac          * we just extracted */
2938ad540459SPierre Jolivet         for (d = 0; d < dof; d++) vals[d] = 0.;
29394c274da1SToby Isaac       }
29404c274da1SToby Isaac     }
29419566063dSJacob Faibussowitsch     PetscCall(MatMultTransposeAdd(cMat, cVec, l, l));
29429566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cVec));
29434c274da1SToby Isaac   }
29444c274da1SToby Isaac   PetscFunctionReturn(0);
29454c274da1SToby Isaac }
294601729b5cSPatrick Sanan /*@
294701729b5cSPatrick Sanan     DMLocalToGlobal - updates global vectors from local vectors
294801729b5cSPatrick Sanan 
2949d083f849SBarry Smith     Neighbor-wise Collective on dm
295001729b5cSPatrick Sanan 
295101729b5cSPatrick Sanan     Input Parameters:
2952bb7acecfSBarry Smith +   dm - the `DM` object
295301729b5cSPatrick Sanan .   l - the local vector
2954bb7acecfSBarry 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.
295501729b5cSPatrick Sanan -   g - the global vector
295601729b5cSPatrick Sanan 
295701729b5cSPatrick Sanan     Notes:
295801729b5cSPatrick Sanan     The communication involved in this update can be overlapped with computation by using
2959bb7acecfSBarry Smith     `DMLocalToGlobalBegin()` and `DMLocalToGlobalEnd()`.
296001729b5cSPatrick Sanan 
2961bb7acecfSBarry Smith     In the `ADD_VALUES` case you normally would zero the receiving vector before beginning this operation.
2962bb7acecfSBarry Smith 
2963bb7acecfSBarry 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.
2964bb7acecfSBarry Smith 
2965bb7acecfSBarry Smith     Use `DMLocalToGlobalHookAdd()` to add additional operations that are performed on the data during the update process
296601729b5cSPatrick Sanan 
296701729b5cSPatrick Sanan     Level: beginner
296801729b5cSPatrick Sanan 
2969bb7acecfSBarry Smith .seealso: `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalBegin()`,  `DMLocalToGlobalHookAdd()`,  `DMGlobaToLocallHookAdd()`
297001729b5cSPatrick Sanan 
297101729b5cSPatrick Sanan @*/
2972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobal(DM dm, Vec l, InsertMode mode, Vec g)
2973d71ae5a4SJacob Faibussowitsch {
297401729b5cSPatrick Sanan   PetscFunctionBegin;
29759566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, l, mode, g));
29769566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, l, mode, g));
297701729b5cSPatrick Sanan   PetscFunctionReturn(0);
297801729b5cSPatrick Sanan }
29794c274da1SToby Isaac 
298047c6ae99SBarry Smith /*@
298101729b5cSPatrick Sanan     DMLocalToGlobalBegin - begins updating global vectors from local vectors
29829a42bb27SBarry Smith 
2983d083f849SBarry Smith     Neighbor-wise Collective on dm
29849a42bb27SBarry Smith 
29859a42bb27SBarry Smith     Input Parameters:
2986bb7acecfSBarry Smith +   dm - the `DM` object
2987f6813fd5SJed Brown .   l - the local vector
2988bb7acecfSBarry 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.
29891eb28f2eSBarry Smith -   g - the global vector
29909a42bb27SBarry Smith 
299195452b02SPatrick Sanan     Notes:
2992bb7acecfSBarry Smith     In the `ADD_VALUES` case you normally would zero the receiving vector before beginning this operation.
2993bb7acecfSBarry Smith 
2994bb7acecfSBarry 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.
2995bb7acecfSBarry Smith 
2996bb7acecfSBarry Smith     Use `DMLocalToGlobalEnd()` to complete the communication process.
2997bb7acecfSBarry Smith 
2998bb7acecfSBarry Smith     `DMLocalToGlobal()` is a short form of  `DMLocalToGlobalBegin()` and  `DMLocalToGlobalEnd()`
2999bb7acecfSBarry Smith 
3000bb7acecfSBarry Smith     `DMLocalToGlobalHookAdd()` may be used to provide additional operations that are performed during the update process.
30019a42bb27SBarry Smith 
300201729b5cSPatrick Sanan     Level: intermediate
30039a42bb27SBarry Smith 
3004bb7acecfSBarry Smith .seealso: `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalBegin()`
30059a42bb27SBarry Smith 
30069a42bb27SBarry Smith @*/
3007d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalBegin(DM dm, Vec l, InsertMode mode, Vec g)
3008d71ae5a4SJacob Faibussowitsch {
30097128ae9fSMatthew G Knepley   PetscSF                 sf;
301084330215SMatthew G. Knepley   PetscSection            s, gs;
3011d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link;
3012ca3d3a14SMatthew G. Knepley   Vec                     tmpl;
3013ae5cfb4aSMatthew G. Knepley   const PetscScalar      *lArray;
3014ae5cfb4aSMatthew G. Knepley   PetscScalar            *gArray;
3015fa88e482SJed Brown   PetscBool               isInsert, transform, l_inplace = PETSC_FALSE, g_inplace = PETSC_FALSE;
3016d0295fc0SJunchao Zhang   PetscMemType            lmtype = PETSC_MEMTYPE_HOST, gmtype = PETSC_MEMTYPE_HOST;
30179a42bb27SBarry Smith 
30189a42bb27SBarry Smith   PetscFunctionBegin;
3019171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3020d4d07f1eSToby Isaac   for (link = dm->ltoghook; link; link = link->next) {
30211baa6e33SBarry Smith     if (link->beginhook) PetscCall((*link->beginhook)(dm, l, mode, g, link->ctx));
3022d4d07f1eSToby Isaac   }
30239566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalHook_Constraints(dm, l, mode, g, NULL));
30249566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
30259566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
30267128ae9fSMatthew G Knepley   switch (mode) {
30277128ae9fSMatthew G Knepley   case INSERT_VALUES:
30287128ae9fSMatthew G Knepley   case INSERT_ALL_VALUES:
3029d71ae5a4SJacob Faibussowitsch   case INSERT_BC_VALUES:
3030d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_TRUE;
3031d71ae5a4SJacob Faibussowitsch     break;
30327128ae9fSMatthew G Knepley   case ADD_VALUES:
30337128ae9fSMatthew G Knepley   case ADD_ALL_VALUES:
3034d71ae5a4SJacob Faibussowitsch   case ADD_BC_VALUES:
3035d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_FALSE;
3036d71ae5a4SJacob Faibussowitsch     break;
3037d71ae5a4SJacob Faibussowitsch   default:
3038d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", mode);
30397128ae9fSMatthew G Knepley   }
3040ca3d3a14SMatthew G. Knepley   if ((sf && !isInsert) || (s && isInsert)) {
30419566063dSJacob Faibussowitsch     PetscCall(DMHasBasisTransform(dm, &transform));
3042ca3d3a14SMatthew G. Knepley     if (transform) {
30439566063dSJacob Faibussowitsch       PetscCall(DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
30449566063dSJacob Faibussowitsch       PetscCall(VecCopy(l, tmpl));
30459566063dSJacob Faibussowitsch       PetscCall(DMPlexLocalToGlobalBasis(dm, tmpl));
30469566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tmpl, &lArray));
3047fa88e482SJed Brown     } else if (isInsert) {
30489566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(l, &lArray));
3049fa88e482SJed Brown     } else {
30509566063dSJacob Faibussowitsch       PetscCall(VecGetArrayReadAndMemType(l, &lArray, &lmtype));
3051fa88e482SJed Brown       l_inplace = PETSC_TRUE;
3052ca3d3a14SMatthew G. Knepley     }
3053fa88e482SJed Brown     if (s && isInsert) {
30549566063dSJacob Faibussowitsch       PetscCall(VecGetArray(g, &gArray));
3055fa88e482SJed Brown     } else {
30569566063dSJacob Faibussowitsch       PetscCall(VecGetArrayAndMemType(g, &gArray, &gmtype));
3057fa88e482SJed Brown       g_inplace = PETSC_TRUE;
3058fa88e482SJed Brown     }
3059ca3d3a14SMatthew G. Knepley     if (sf && !isInsert) {
30609566063dSJacob Faibussowitsch       PetscCall(PetscSFReduceWithMemTypeBegin(sf, MPIU_SCALAR, lmtype, lArray, gmtype, gArray, MPIU_SUM));
306184330215SMatthew G. Knepley     } else if (s && isInsert) {
306284330215SMatthew G. Knepley       PetscInt gStart, pStart, pEnd, p;
306384330215SMatthew G. Knepley 
30649566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gs));
30659566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
30669566063dSJacob Faibussowitsch       PetscCall(VecGetOwnershipRange(g, &gStart, NULL));
306784330215SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
3068b3b16f48SMatthew G. Knepley         PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
306984330215SMatthew G. Knepley 
30709566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(s, p, &dof));
30719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(gs, p, &gdof));
30729566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
30739566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(gs, p, &gcdof));
30749566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(s, p, &off));
30759566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(gs, p, &goff));
3076b3b16f48SMatthew G. Knepley         /* Ignore off-process data and points with no global data */
307703442857SMatthew G. Knepley         if (!gdof || goff < 0) continue;
30787a8be351SBarry 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);
3079b3b16f48SMatthew G. Knepley         /* If no constraints are enforced in the global vector */
3080b3b16f48SMatthew G. Knepley         if (!gcdof) {
308184330215SMatthew G. Knepley           for (d = 0; d < dof; ++d) gArray[goff - gStart + d] = lArray[off + d];
3082b3b16f48SMatthew G. Knepley           /* If constraints are enforced in the global vector */
3083b3b16f48SMatthew G. Knepley         } else if (cdof == gcdof) {
308484330215SMatthew G. Knepley           const PetscInt *cdofs;
308584330215SMatthew G. Knepley           PetscInt        cind = 0;
308684330215SMatthew G. Knepley 
30879566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetConstraintIndices(s, p, &cdofs));
3088b3b16f48SMatthew G. Knepley           for (d = 0, e = 0; d < dof; ++d) {
30899371c9d4SSatish Balay             if ((cind < cdof) && (d == cdofs[cind])) {
30909371c9d4SSatish Balay               ++cind;
30919371c9d4SSatish Balay               continue;
30929371c9d4SSatish Balay             }
3093b3b16f48SMatthew G. Knepley             gArray[goff - gStart + e++] = lArray[off + d];
309484330215SMatthew G. Knepley           }
30957a8be351SBarry 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);
309684330215SMatthew G. Knepley       }
3097ca3d3a14SMatthew G. Knepley     }
3098fa88e482SJed Brown     if (g_inplace) {
30999566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayAndMemType(g, &gArray));
3100fa88e482SJed Brown     } else {
31019566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(g, &gArray));
3102fa88e482SJed Brown     }
3103ca3d3a14SMatthew G. Knepley     if (transform) {
31049566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tmpl, &lArray));
31059566063dSJacob Faibussowitsch       PetscCall(DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
3106fa88e482SJed Brown     } else if (l_inplace) {
31079566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayReadAndMemType(l, &lArray));
3108ca3d3a14SMatthew G. Knepley     } else {
31099566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(l, &lArray));
3110ca3d3a14SMatthew G. Knepley     }
31117128ae9fSMatthew G Knepley   } else {
31129566063dSJacob Faibussowitsch     PetscCall((*dm->ops->localtoglobalbegin)(dm, l, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), g));
31137128ae9fSMatthew G Knepley   }
31149a42bb27SBarry Smith   PetscFunctionReturn(0);
31159a42bb27SBarry Smith }
31169a42bb27SBarry Smith 
31179a42bb27SBarry Smith /*@
31189a42bb27SBarry Smith     DMLocalToGlobalEnd - updates global vectors from local vectors
311947c6ae99SBarry Smith 
3120d083f849SBarry Smith     Neighbor-wise Collective on dm
312147c6ae99SBarry Smith 
312247c6ae99SBarry Smith     Input Parameters:
3123bb7acecfSBarry Smith +   dm - the `DM` object
3124f6813fd5SJed Brown .   l - the local vector
3125bb7acecfSBarry Smith .   mode - `INSERT_VALUES` or `ADD_VALUES`
3126f6813fd5SJed Brown -   g - the global vector
312747c6ae99SBarry Smith 
312801729b5cSPatrick Sanan     Level: intermediate
312947c6ae99SBarry Smith 
3130bb7acecfSBarry Smith     Note:
3131bb7acecfSBarry Smith     See `DMLocalToGlobalBegin()` for full details
3132bb7acecfSBarry Smith 
3133bb7acecfSBarry Smith .seealso: `DMLocalToGlobalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalEnd()`
313447c6ae99SBarry Smith 
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   }
318747c6ae99SBarry Smith   PetscFunctionReturn(0);
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 
3195d083f849SBarry Smith    Neighbor-wise Collective on dm
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 
3207bb7acecfSBarry Smith .seealso: `DMLocalToLocalEnd(), `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMLocalToLocalEnd()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3208f089877aSRichard Tran Mills 
3209f089877aSRichard Tran Mills @*/
3210d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalBegin(DM dm, Vec g, InsertMode mode, Vec l)
3211d71ae5a4SJacob Faibussowitsch {
3212f089877aSRichard Tran Mills   PetscFunctionBegin;
3213f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3214*9f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
3215*9f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(l, VEC_CLASSID, 4);
3216*9f4ada15SMatthew G. Knepley   PetscUseTypeMethod(dm, localtolocalbegin, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
3217f089877aSRichard Tran Mills   PetscFunctionReturn(0);
3218f089877aSRichard Tran Mills }
3219f089877aSRichard Tran Mills 
3220f089877aSRichard Tran Mills /*@
3221bb7acecfSBarry Smith    DMLocalToLocalEnd - Maps from a local vector to another local vector where the ghost
3222bb7acecfSBarry Smith    points in the second are set correctly. Must be preceded by `DMLocalToLocalBegin()`.
3223f089877aSRichard Tran Mills 
3224d083f849SBarry Smith    Neighbor-wise Collective on dm
3225f089877aSRichard Tran Mills 
3226f089877aSRichard Tran Mills    Input Parameters:
3227bb7acecfSBarry Smith +  da - the `DM` object
3228bc0a1609SRichard Tran Mills .  g - the original local vector
3229bb7acecfSBarry Smith -  mode - one of `INSERT_VALUES` or `ADD_VALUES`
3230f089877aSRichard Tran Mills 
3231bc0a1609SRichard Tran Mills    Output Parameter:
3232bc0a1609SRichard Tran Mills .  l  - the local vector with correct ghost values
3233f089877aSRichard Tran Mills 
3234f089877aSRichard Tran Mills    Level: intermediate
3235f089877aSRichard Tran Mills 
3236bb7acecfSBarry Smith .seealso: `DMLocalToLocalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMLocalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3237f089877aSRichard Tran Mills 
3238f089877aSRichard Tran Mills @*/
3239d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
3240d71ae5a4SJacob Faibussowitsch {
3241f089877aSRichard Tran Mills   PetscFunctionBegin;
3242f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3243*9f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
3244*9f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(l, VEC_CLASSID, 4);
3245*9f4ada15SMatthew G. Knepley   PetscUseTypeMethod(dm, localtolocalend, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
3246f089877aSRichard Tran Mills   PetscFunctionReturn(0);
3247f089877aSRichard Tran Mills }
3248f089877aSRichard Tran Mills 
324947c6ae99SBarry Smith /*@
3250bb7acecfSBarry Smith     DMCoarsen - Coarsens a `DM` object using a standard, non-adaptive coarsening of the underlying mesh
325147c6ae99SBarry Smith 
3252d083f849SBarry Smith     Collective on dm
325347c6ae99SBarry Smith 
3254d8d19677SJose E. Roman     Input Parameters:
3255bb7acecfSBarry Smith +   dm - the `DM` object
3256bb7acecfSBarry Smith -   comm - the communicator to contain the new `DM` object (or MPI_COMM_NULL)
325747c6ae99SBarry Smith 
325847c6ae99SBarry Smith     Output Parameter:
3259bb7acecfSBarry Smith .   dmc - the coarsened `DM`
326047c6ae99SBarry Smith 
326147c6ae99SBarry Smith     Level: developer
326247c6ae99SBarry Smith 
3263bb7acecfSBarry Smith .seealso: `DM`, `DMRefine()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
326447c6ae99SBarry Smith 
326547c6ae99SBarry Smith @*/
3266d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
3267d71ae5a4SJacob Faibussowitsch {
3268b17ce1afSJed Brown   DMCoarsenHookLink link;
326947c6ae99SBarry Smith 
327047c6ae99SBarry Smith   PetscFunctionBegin;
3271171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Coarsen, dm, 0, 0, 0));
3273dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, coarsen, comm, dmc);
3274b9d85ea2SLisandro Dalcin   if (*dmc) {
3275a3574896SRichard Tran Mills     (*dmc)->bind_below = dm->bind_below; /* Propagate this from parent DM; otherwise -dm_bind_below will be useless for multigrid cases. */
32769566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dm, *dmc));
327743842a1eSJed Brown     (*dmc)->ops->creatematrix = dm->ops->creatematrix;
32789566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmc));
3279644e2e5bSBarry Smith     (*dmc)->ctx       = dm->ctx;
32800598a293SJed Brown     (*dmc)->levelup   = dm->levelup;
3281656b349aSBarry Smith     (*dmc)->leveldown = dm->leveldown + 1;
32829566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmc, dm->mattype));
3283b17ce1afSJed Brown     for (link = dm->coarsenhook; link; link = link->next) {
32849566063dSJacob Faibussowitsch       if (link->coarsenhook) PetscCall((*link->coarsenhook)(dm, *dmc, link->ctx));
3285b17ce1afSJed Brown     }
3286b9d85ea2SLisandro Dalcin   }
32879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Coarsen, dm, 0, 0, 0));
32887a8be351SBarry Smith   PetscCheck(*dmc, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
3289b17ce1afSJed Brown   PetscFunctionReturn(0);
3290b17ce1afSJed Brown }
3291b17ce1afSJed Brown 
3292bb9467b5SJed Brown /*@C
3293b17ce1afSJed Brown    DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
3294b17ce1afSJed Brown 
3295bb7acecfSBarry Smith    Logically Collective on fine
3296b17ce1afSJed Brown 
32974165533cSJose E. Roman    Input Parameters:
3298bb7acecfSBarry Smith +  fine - `DM` on which to run a hook when restricting to a coarser level
3299b17ce1afSJed Brown .  coarsenhook - function to run when setting up a coarser level
3300bb7acecfSBarry Smith .  restricthook - function to run to update data on coarser levels (called once per `SNESSolve()`)
33010298fd71SBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3302b17ce1afSJed Brown 
3303b17ce1afSJed Brown    Calling sequence of coarsenhook:
3304b17ce1afSJed Brown $    coarsenhook(DM fine,DM coarse,void *ctx);
3305b17ce1afSJed Brown 
3306bb7acecfSBarry Smith +  fine - fine level `DM`
3307bb7acecfSBarry Smith .  coarse - coarse level `DM` to restrict problem to
3308b17ce1afSJed Brown -  ctx - optional user-defined function context
3309b17ce1afSJed Brown 
3310b17ce1afSJed Brown    Calling sequence for restricthook:
3311c833c3b5SJed Brown $    restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
3312bb7acecfSBarry Smith $
3313bb7acecfSBarry Smith +  fine - fine level `DM`
3314bb7acecfSBarry Smith .  mrestrict - matrix restricting a fine-level solution to the coarse grid, usually the transpose of the interpolation
3315c833c3b5SJed Brown .  rscale - scaling vector for restriction
3316c833c3b5SJed Brown .  inject - matrix restricting by injection
3317b17ce1afSJed Brown .  coarse - coarse level DM to update
3318b17ce1afSJed Brown -  ctx - optional user-defined function context
3319b17ce1afSJed Brown 
3320b17ce1afSJed Brown    Level: advanced
3321b17ce1afSJed Brown 
3322b17ce1afSJed Brown    Notes:
3323bb7acecfSBarry 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`.
3324b17ce1afSJed Brown 
3325b17ce1afSJed Brown    If this function is called multiple times, the hooks will be run in the order they are added.
3326b17ce1afSJed Brown 
3327b17ce1afSJed Brown    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3328bb7acecfSBarry Smith    extract the finest level information from its context (instead of from the `SNES`).
3329b17ce1afSJed Brown 
3330bb7acecfSBarry Smith    The hooks are automatically called by `DMRestrict()`
3331bb7acecfSBarry Smith 
3332bb7acecfSBarry Smith    Fortran Note:
3333bb7acecfSBarry Smith    This function is not available from Fortran.
3334bb9467b5SJed Brown 
3335db781477SPatrick Sanan .seealso: `DMCoarsenHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3336b17ce1afSJed Brown @*/
3337d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHookAdd(DM fine, PetscErrorCode (*coarsenhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, Mat, Vec, Mat, DM, void *), void *ctx)
3338d71ae5a4SJacob Faibussowitsch {
3339b17ce1afSJed Brown   DMCoarsenHookLink link, *p;
3340b17ce1afSJed Brown 
3341b17ce1afSJed Brown   PetscFunctionBegin;
3342b17ce1afSJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
33431e3d8eccSJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
33441e3d8eccSJed Brown     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0);
33451e3d8eccSJed Brown   }
33469566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
3347b17ce1afSJed Brown   link->coarsenhook  = coarsenhook;
3348b17ce1afSJed Brown   link->restricthook = restricthook;
3349b17ce1afSJed Brown   link->ctx          = ctx;
33500298fd71SBarry Smith   link->next         = NULL;
3351b17ce1afSJed Brown   *p                 = link;
3352b17ce1afSJed Brown   PetscFunctionReturn(0);
3353b17ce1afSJed Brown }
3354b17ce1afSJed Brown 
3355dc822a44SJed Brown /*@C
3356bb7acecfSBarry Smith    DMCoarsenHookRemove - remove a callback set with `DMCoarsenHookAdd()`
3357dc822a44SJed Brown 
3358bb7acecfSBarry Smith    Logically Collective on fine
3359dc822a44SJed Brown 
33604165533cSJose E. Roman    Input Parameters:
3361bb7acecfSBarry Smith +  fine - `DM` on which to run a hook when restricting to a coarser level
3362dc822a44SJed Brown .  coarsenhook - function to run when setting up a coarser level
3363bb7acecfSBarry Smith .  restricthook - function to run to update data on coarser levels
3364dc822a44SJed Brown -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3365dc822a44SJed Brown 
3366dc822a44SJed Brown    Level: advanced
3367dc822a44SJed Brown 
3368bb7acecfSBarry Smith    Note:
3369dc822a44SJed Brown    This function does nothing if the hook is not in the list.
3370dc822a44SJed Brown 
3371bb7acecfSBarry Smith    Fortran Note:
3372bb7acecfSBarry Smith    This function is not available from Fortran.
3373dc822a44SJed Brown 
3374db781477SPatrick Sanan .seealso: `DMCoarsenHookAdd()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3375dc822a44SJed Brown @*/
3376d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHookRemove(DM fine, PetscErrorCode (*coarsenhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, Mat, Vec, Mat, DM, void *), void *ctx)
3377d71ae5a4SJacob Faibussowitsch {
3378dc822a44SJed Brown   DMCoarsenHookLink link, *p;
3379dc822a44SJed Brown 
3380dc822a44SJed Brown   PetscFunctionBegin;
3381dc822a44SJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
3382dc822a44SJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3383dc822a44SJed Brown     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3384dc822a44SJed Brown       link = *p;
3385dc822a44SJed Brown       *p   = link->next;
33869566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3387dc822a44SJed Brown       break;
3388dc822a44SJed Brown     }
3389dc822a44SJed Brown   }
3390dc822a44SJed Brown   PetscFunctionReturn(0);
3391dc822a44SJed Brown }
3392dc822a44SJed Brown 
3393b17ce1afSJed Brown /*@
3394bb7acecfSBarry Smith    DMRestrict - restricts user-defined problem data to a coarser `DM` by running hooks registered by `DMCoarsenHookAdd()`
3395b17ce1afSJed Brown 
3396b17ce1afSJed Brown    Collective if any hooks are
3397b17ce1afSJed Brown 
33984165533cSJose E. Roman    Input Parameters:
3399bb7acecfSBarry Smith +  fine - finer `DM` from which the data is obtained
3400bb7acecfSBarry Smith .  restrct - restriction matrix, apply using `MatRestrict()`, usually the transpose of the interpolation
3401e91eccc2SStefano Zampini .  rscale - scaling vector for restriction
3402bb7acecfSBarry Smith .  inject - injection matrix, also use `MatRestrict()`
3403e91eccc2SStefano Zampini -  coarse - coarser DM to update
3404b17ce1afSJed Brown 
3405b17ce1afSJed Brown    Level: developer
3406b17ce1afSJed Brown 
3407bb7acecfSBarry Smith    Developer Note:
3408bb7acecfSBarry Smith    Though this routine is called `DMRestrict()` the hooks are added with `DMCoarsenHookAdd()`, a consistent terminology would be better
3409bb7acecfSBarry Smith 
3410bb7acecfSBarry Smith .seealso: `DMCoarsenHookAdd()`, `MatRestrict()`, `DMInterpolate()`, `DMRefineHookAdd()`
3411b17ce1afSJed Brown @*/
3412d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestrict(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse)
3413d71ae5a4SJacob Faibussowitsch {
3414b17ce1afSJed Brown   DMCoarsenHookLink link;
3415b17ce1afSJed Brown 
3416b17ce1afSJed Brown   PetscFunctionBegin;
3417b17ce1afSJed Brown   for (link = fine->coarsenhook; link; link = link->next) {
34181baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(fine, restrct, rscale, inject, coarse, link->ctx));
3419b17ce1afSJed Brown   }
342047c6ae99SBarry Smith   PetscFunctionReturn(0);
342147c6ae99SBarry Smith }
342247c6ae99SBarry Smith 
3423bb9467b5SJed Brown /*@C
3424be081cd6SPeter Brune    DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
34255dbd56e3SPeter Brune 
3426d083f849SBarry Smith    Logically Collective on global
34275dbd56e3SPeter Brune 
34284165533cSJose E. Roman    Input Parameters:
3429bb7acecfSBarry Smith +  global - global `DM`
3430bb7acecfSBarry Smith .  ddhook - function to run to pass data to the decomposition `DM` upon its creation
34315dbd56e3SPeter Brune .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
34320298fd71SBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
34335dbd56e3SPeter Brune 
3434ec4806b8SPeter Brune    Calling sequence for ddhook:
3435ec4806b8SPeter Brune $    ddhook(DM global,DM block,void *ctx)
3436ec4806b8SPeter Brune 
3437bb7acecfSBarry Smith +  global - global `DM`
3438bb7acecfSBarry Smith .  block  - block `DM`
3439ec4806b8SPeter Brune -  ctx - optional user-defined function context
3440ec4806b8SPeter Brune 
34415dbd56e3SPeter Brune    Calling sequence for restricthook:
3442ec4806b8SPeter Brune $    restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
34435dbd56e3SPeter Brune 
3444bb7acecfSBarry Smith +  global - global `DM`
34455dbd56e3SPeter Brune .  out    - scatter to the outer (with ghost and overlap points) block vector
34465dbd56e3SPeter Brune .  in     - scatter to block vector values only owned locally
3447bb7acecfSBarry Smith .  block  - block `DM`
34485dbd56e3SPeter Brune -  ctx - optional user-defined function context
34495dbd56e3SPeter Brune 
34505dbd56e3SPeter Brune    Level: advanced
34515dbd56e3SPeter Brune 
34525dbd56e3SPeter Brune    Notes:
3453bb7acecfSBarry Smith    This function is only needed if auxiliary data needs to be set up on subdomain `DM`s.
34545dbd56e3SPeter Brune 
34555dbd56e3SPeter Brune    If this function is called multiple times, the hooks will be run in the order they are added.
34565dbd56e3SPeter Brune 
34575dbd56e3SPeter Brune    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3458bb7acecfSBarry Smith    extract the global information from its context (instead of from the `SNES`).
34595dbd56e3SPeter Brune 
3460bb7acecfSBarry Smith    Fortran Note:
3461bb7acecfSBarry Smith    This function is not available from Fortran.
3462bb9467b5SJed Brown 
3463bb7acecfSBarry Smith .seealso: `DMSubDomainHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
34645dbd56e3SPeter Brune @*/
3465d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainHookAdd(DM global, PetscErrorCode (*ddhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, VecScatter, VecScatter, DM, void *), void *ctx)
3466d71ae5a4SJacob Faibussowitsch {
3467be081cd6SPeter Brune   DMSubDomainHookLink link, *p;
34685dbd56e3SPeter Brune 
34695dbd56e3SPeter Brune   PetscFunctionBegin;
34705dbd56e3SPeter Brune   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3471b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
3472b3a6b972SJed Brown     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0);
3473b3a6b972SJed Brown   }
34749566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
34755dbd56e3SPeter Brune   link->restricthook = restricthook;
3476be081cd6SPeter Brune   link->ddhook       = ddhook;
34775dbd56e3SPeter Brune   link->ctx          = ctx;
34780298fd71SBarry Smith   link->next         = NULL;
34795dbd56e3SPeter Brune   *p                 = link;
34805dbd56e3SPeter Brune   PetscFunctionReturn(0);
34815dbd56e3SPeter Brune }
34825dbd56e3SPeter Brune 
3483b3a6b972SJed Brown /*@C
3484b3a6b972SJed Brown    DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid
3485b3a6b972SJed Brown 
3486bb7acecfSBarry Smith    Logically Collective on global
3487b3a6b972SJed Brown 
34884165533cSJose E. Roman    Input Parameters:
3489bb7acecfSBarry Smith +  global - global `DM`
3490bb7acecfSBarry Smith .  ddhook - function to run to pass data to the decomposition `DM` upon its creation
3491b3a6b972SJed Brown .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
3492b3a6b972SJed Brown -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3493b3a6b972SJed Brown 
3494b3a6b972SJed Brown    Level: advanced
3495b3a6b972SJed Brown 
3496bb7acecfSBarry Smith    Fortran Note:
3497bb7acecfSBarry Smith    This function is not available from Fortran.
3498b3a6b972SJed Brown 
3499db781477SPatrick Sanan .seealso: `DMSubDomainHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3500b3a6b972SJed Brown @*/
3501d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainHookRemove(DM global, PetscErrorCode (*ddhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, VecScatter, VecScatter, DM, void *), void *ctx)
3502d71ae5a4SJacob Faibussowitsch {
3503b3a6b972SJed Brown   DMSubDomainHookLink link, *p;
3504b3a6b972SJed Brown 
3505b3a6b972SJed Brown   PetscFunctionBegin;
3506b3a6b972SJed Brown   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3507b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3508b3a6b972SJed Brown     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3509b3a6b972SJed Brown       link = *p;
3510b3a6b972SJed Brown       *p   = link->next;
35119566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3512b3a6b972SJed Brown       break;
3513b3a6b972SJed Brown     }
3514b3a6b972SJed Brown   }
3515b3a6b972SJed Brown   PetscFunctionReturn(0);
3516b3a6b972SJed Brown }
3517b3a6b972SJed Brown 
35185dbd56e3SPeter Brune /*@
3519bb7acecfSBarry Smith    DMSubDomainRestrict - restricts user-defined problem data to a block `DM` by running hooks registered by `DMSubDomainHookAdd()`
35205dbd56e3SPeter Brune 
35215dbd56e3SPeter Brune    Collective if any hooks are
35225dbd56e3SPeter Brune 
35234165533cSJose E. Roman    Input Parameters:
3524bb7acecfSBarry Smith +  fine - finer `DM` to use as a base
3525be081cd6SPeter Brune .  oscatter - scatter from domain global vector filling subdomain global vector with overlap
3526be081cd6SPeter Brune .  gscatter - scatter from domain global vector filling subdomain local vector with ghosts
3527bb7acecfSBarry Smith -  coarse - coarser `DM` to update
35285dbd56e3SPeter Brune 
35295dbd56e3SPeter Brune    Level: developer
35305dbd56e3SPeter Brune 
3531db781477SPatrick Sanan .seealso: `DMCoarsenHookAdd()`, `MatRestrict()`
35325dbd56e3SPeter Brune @*/
3533d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainRestrict(DM global, VecScatter oscatter, VecScatter gscatter, DM subdm)
3534d71ae5a4SJacob Faibussowitsch {
3535be081cd6SPeter Brune   DMSubDomainHookLink link;
35365dbd56e3SPeter Brune 
35375dbd56e3SPeter Brune   PetscFunctionBegin;
3538be081cd6SPeter Brune   for (link = global->subdomainhook; link; link = link->next) {
35391baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(global, oscatter, gscatter, subdm, link->ctx));
35405dbd56e3SPeter Brune   }
35415dbd56e3SPeter Brune   PetscFunctionReturn(0);
35425dbd56e3SPeter Brune }
35435dbd56e3SPeter Brune 
35445fe1f584SPeter Brune /*@
3545bb7acecfSBarry Smith     DMGetCoarsenLevel - Gets the number of coarsenings that have generated this `DM`.
35465fe1f584SPeter Brune 
35475fe1f584SPeter Brune     Not Collective
35485fe1f584SPeter Brune 
35495fe1f584SPeter Brune     Input Parameter:
3550bb7acecfSBarry Smith .   dm - the `DM` object
35515fe1f584SPeter Brune 
35525fe1f584SPeter Brune     Output Parameter:
35536a7d9d85SPeter Brune .   level - number of coarsenings
35545fe1f584SPeter Brune 
35555fe1f584SPeter Brune     Level: developer
35565fe1f584SPeter Brune 
3557bb7acecfSBarry Smith .seealso: `DMCoarsen()`, `DMSetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
35585fe1f584SPeter Brune 
35595fe1f584SPeter Brune @*/
3560d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarsenLevel(DM dm, PetscInt *level)
3561d71ae5a4SJacob Faibussowitsch {
35625fe1f584SPeter Brune   PetscFunctionBegin;
35635fe1f584SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3564b9d85ea2SLisandro Dalcin   PetscValidIntPointer(level, 2);
35655fe1f584SPeter Brune   *level = dm->leveldown;
35665fe1f584SPeter Brune   PetscFunctionReturn(0);
35675fe1f584SPeter Brune }
35685fe1f584SPeter Brune 
35699a64c4a8SMatthew G. Knepley /*@
3570bb7acecfSBarry Smith     DMSetCoarsenLevel - Sets the number of coarsenings that have generated this `DM`.
35719a64c4a8SMatthew G. Knepley 
3572bb7acecfSBarry Smith     Collective on dm
35739a64c4a8SMatthew G. Knepley 
35749a64c4a8SMatthew G. Knepley     Input Parameters:
3575bb7acecfSBarry Smith +   dm - the `DM` object
35769a64c4a8SMatthew G. Knepley -   level - number of coarsenings
35779a64c4a8SMatthew G. Knepley 
35789a64c4a8SMatthew G. Knepley     Level: developer
35799a64c4a8SMatthew G. Knepley 
3580bb7acecfSBarry Smith     Note:
3581bb7acecfSBarry Smith     This is rarely used directly, the information is automatically set when a `DM` is created with `DMCoarsen()`
3582bb7acecfSBarry Smith 
3583bb7acecfSBarry Smith .seealso: `DMSetCoarsenLevel()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
35849a64c4a8SMatthew G. Knepley @*/
3585d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarsenLevel(DM dm, PetscInt level)
3586d71ae5a4SJacob Faibussowitsch {
35879a64c4a8SMatthew G. Knepley   PetscFunctionBegin;
35889a64c4a8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35899a64c4a8SMatthew G. Knepley   dm->leveldown = level;
35909a64c4a8SMatthew G. Knepley   PetscFunctionReturn(0);
35919a64c4a8SMatthew G. Knepley }
35929a64c4a8SMatthew G. Knepley 
359347c6ae99SBarry Smith /*@C
3594bb7acecfSBarry Smith     DMRefineHierarchy - Refines a `DM` object, all levels at once
359547c6ae99SBarry Smith 
3596d083f849SBarry Smith     Collective on dm
359747c6ae99SBarry Smith 
3598d8d19677SJose E. Roman     Input Parameters:
3599bb7acecfSBarry Smith +   dm - the `DM` object
360047c6ae99SBarry Smith -   nlevels - the number of levels of refinement
360147c6ae99SBarry Smith 
360247c6ae99SBarry Smith     Output Parameter:
3603bb7acecfSBarry Smith .   dmf - the refined `DM` hierarchy
360447c6ae99SBarry Smith 
360547c6ae99SBarry Smith     Level: developer
360647c6ae99SBarry Smith 
3607bb7acecfSBarry Smith .seealso: `DMCoarsen()`, `DMCoarsenHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
360847c6ae99SBarry Smith 
360947c6ae99SBarry Smith @*/
3610d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHierarchy(DM dm, PetscInt nlevels, DM dmf[])
3611d71ae5a4SJacob Faibussowitsch {
361247c6ae99SBarry Smith   PetscFunctionBegin;
3613171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36147a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
361547c6ae99SBarry Smith   if (nlevels == 0) PetscFunctionReturn(0);
3616b9d85ea2SLisandro Dalcin   PetscValidPointer(dmf, 3);
361747c6ae99SBarry Smith   if (dm->ops->refinehierarchy) {
3618dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, refinehierarchy, nlevels, dmf);
361947c6ae99SBarry Smith   } else if (dm->ops->refine) {
362047c6ae99SBarry Smith     PetscInt i;
362147c6ae99SBarry Smith 
36229566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &dmf[0]));
362348a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMRefine(dmf[i - 1], PetscObjectComm((PetscObject)dm), &dmf[i]));
3624ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No RefineHierarchy for this DM yet");
362547c6ae99SBarry Smith   PetscFunctionReturn(0);
362647c6ae99SBarry Smith }
362747c6ae99SBarry Smith 
362847c6ae99SBarry Smith /*@C
3629bb7acecfSBarry Smith     DMCoarsenHierarchy - Coarsens a `DM` object, all levels at once
363047c6ae99SBarry Smith 
3631d083f849SBarry Smith     Collective on dm
363247c6ae99SBarry Smith 
3633d8d19677SJose E. Roman     Input Parameters:
3634bb7acecfSBarry Smith +   dm - the `DM` object
363547c6ae99SBarry Smith -   nlevels - the number of levels of coarsening
363647c6ae99SBarry Smith 
363747c6ae99SBarry Smith     Output Parameter:
3638bb7acecfSBarry Smith .   dmc - the coarsened `DM` hierarchy
363947c6ae99SBarry Smith 
364047c6ae99SBarry Smith     Level: developer
364147c6ae99SBarry Smith 
3642bb7acecfSBarry Smith .seealso: `DMCoarsen()`, `DMRefineHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
364347c6ae99SBarry Smith 
364447c6ae99SBarry Smith @*/
3645d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
3646d71ae5a4SJacob Faibussowitsch {
364747c6ae99SBarry Smith   PetscFunctionBegin;
3648171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36497a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
365047c6ae99SBarry Smith   if (nlevels == 0) PetscFunctionReturn(0);
365147c6ae99SBarry Smith   PetscValidPointer(dmc, 3);
365247c6ae99SBarry Smith   if (dm->ops->coarsenhierarchy) {
3653dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, coarsenhierarchy, nlevels, dmc);
365447c6ae99SBarry Smith   } else if (dm->ops->coarsen) {
365547c6ae99SBarry Smith     PetscInt i;
365647c6ae99SBarry Smith 
36579566063dSJacob Faibussowitsch     PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &dmc[0]));
365848a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMCoarsen(dmc[i - 1], PetscObjectComm((PetscObject)dm), &dmc[i]));
3659ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No CoarsenHierarchy for this DM yet");
366047c6ae99SBarry Smith   PetscFunctionReturn(0);
366147c6ae99SBarry Smith }
366247c6ae99SBarry Smith 
36631a266240SBarry Smith /*@C
3664bb7acecfSBarry Smith     DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the `DM` is destroyed
36651a266240SBarry Smith 
3666bb7acecfSBarry Smith     Logically Collective if the function is collective
36671a266240SBarry Smith 
36681a266240SBarry Smith     Input Parameters:
3669bb7acecfSBarry Smith +   dm - the `DM` object
36701a266240SBarry Smith -   destroy - the destroy function
36711a266240SBarry Smith 
36721a266240SBarry Smith     Level: intermediate
36731a266240SBarry Smith 
3674bb7acecfSBarry Smith .seealso: `DMSetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
36751a266240SBarry Smith 
3676f07f9ceaSJed Brown @*/
3677d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetApplicationContextDestroy(DM dm, PetscErrorCode (*destroy)(void **))
3678d71ae5a4SJacob Faibussowitsch {
36791a266240SBarry Smith   PetscFunctionBegin;
3680171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36811a266240SBarry Smith   dm->ctxdestroy = destroy;
36821a266240SBarry Smith   PetscFunctionReturn(0);
36831a266240SBarry Smith }
36841a266240SBarry Smith 
3685b07ff414SBarry Smith /*@
3686bb7acecfSBarry Smith     DMSetApplicationContext - Set a user context into a `DM` object
368747c6ae99SBarry Smith 
368847c6ae99SBarry Smith     Not Collective
368947c6ae99SBarry Smith 
369047c6ae99SBarry Smith     Input Parameters:
3691bb7acecfSBarry Smith +   dm - the `DM` object
369247c6ae99SBarry Smith -   ctx - the user context
369347c6ae99SBarry Smith 
369447c6ae99SBarry Smith     Level: intermediate
369547c6ae99SBarry Smith 
3696bb7acecfSBarry Smith     Note:
3697bb7acecfSBarry Smith     A user context is a way to pass problem specific information that is accessable whenever the `DM` is available
3698bb7acecfSBarry Smith 
3699bb7acecfSBarry Smith .seealso: `DMGetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
370047c6ae99SBarry Smith 
370147c6ae99SBarry Smith @*/
3702d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetApplicationContext(DM dm, void *ctx)
3703d71ae5a4SJacob Faibussowitsch {
370447c6ae99SBarry Smith   PetscFunctionBegin;
3705171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
370647c6ae99SBarry Smith   dm->ctx = ctx;
370747c6ae99SBarry Smith   PetscFunctionReturn(0);
370847c6ae99SBarry Smith }
370947c6ae99SBarry Smith 
371047c6ae99SBarry Smith /*@
3711bb7acecfSBarry Smith     DMGetApplicationContext - Gets a user context from a `DM` object
371247c6ae99SBarry Smith 
371347c6ae99SBarry Smith     Not Collective
371447c6ae99SBarry Smith 
371547c6ae99SBarry Smith     Input Parameter:
3716bb7acecfSBarry Smith .   dm - the `DM` object
371747c6ae99SBarry Smith 
371847c6ae99SBarry Smith     Output Parameter:
371947c6ae99SBarry Smith .   ctx - the user context
372047c6ae99SBarry Smith 
372147c6ae99SBarry Smith     Level: intermediate
372247c6ae99SBarry Smith 
3723bb7acecfSBarry Smith     Note:
3724bb7acecfSBarry Smith     A user context is a way to pass problem specific information that is accessable whenever the `DM` is available
3725bb7acecfSBarry Smith 
3726bb7acecfSBarry Smith .seealso: `DMGetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
372747c6ae99SBarry Smith 
372847c6ae99SBarry Smith @*/
3729d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetApplicationContext(DM dm, void *ctx)
3730d71ae5a4SJacob Faibussowitsch {
373147c6ae99SBarry Smith   PetscFunctionBegin;
3732171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37331b2093e4SBarry Smith   *(void **)ctx = dm->ctx;
373447c6ae99SBarry Smith   PetscFunctionReturn(0);
373547c6ae99SBarry Smith }
373647c6ae99SBarry Smith 
373708da532bSDmitry Karpeev /*@C
3738bb7acecfSBarry Smith     DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for `SNESVI`.
373908da532bSDmitry Karpeev 
3740d083f849SBarry Smith     Logically Collective on dm
374108da532bSDmitry Karpeev 
3742d8d19677SJose E. Roman     Input Parameters:
374308da532bSDmitry Karpeev +   dm - the DM object
37440298fd71SBarry Smith -   f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
374508da532bSDmitry Karpeev 
374608da532bSDmitry Karpeev     Level: intermediate
374708da532bSDmitry Karpeev 
3748bb7acecfSBarry Smith .seealso: `DMComputeVariableBounds()`, `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`,
3749db781477SPatrick Sanan          `DMSetJacobian()`
375008da532bSDmitry Karpeev 
375108da532bSDmitry Karpeev @*/
3752d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetVariableBounds(DM dm, PetscErrorCode (*f)(DM, Vec, Vec))
3753d71ae5a4SJacob Faibussowitsch {
375408da532bSDmitry Karpeev   PetscFunctionBegin;
37555a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
375608da532bSDmitry Karpeev   dm->ops->computevariablebounds = f;
375708da532bSDmitry Karpeev   PetscFunctionReturn(0);
375808da532bSDmitry Karpeev }
375908da532bSDmitry Karpeev 
376008da532bSDmitry Karpeev /*@
3761bb7acecfSBarry Smith     DMHasVariableBounds - does the `DM` object have a variable bounds function?
376208da532bSDmitry Karpeev 
376308da532bSDmitry Karpeev     Not Collective
376408da532bSDmitry Karpeev 
376508da532bSDmitry Karpeev     Input Parameter:
3766bb7acecfSBarry Smith .   dm - the `DM` object to destroy
376708da532bSDmitry Karpeev 
376808da532bSDmitry Karpeev     Output Parameter:
3769bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the variable bounds function exists
377008da532bSDmitry Karpeev 
377108da532bSDmitry Karpeev     Level: developer
377208da532bSDmitry Karpeev 
3773bb7acecfSBarry Smith .seealso: `DMComputeVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
377408da532bSDmitry Karpeev 
377508da532bSDmitry Karpeev @*/
3776d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasVariableBounds(DM dm, PetscBool *flg)
3777d71ae5a4SJacob Faibussowitsch {
377808da532bSDmitry Karpeev   PetscFunctionBegin;
37795a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3780534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
378108da532bSDmitry Karpeev   *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
378208da532bSDmitry Karpeev   PetscFunctionReturn(0);
378308da532bSDmitry Karpeev }
378408da532bSDmitry Karpeev 
378508da532bSDmitry Karpeev /*@C
3786bb7acecfSBarry Smith     DMComputeVariableBounds - compute variable bounds used by `SNESVI`.
378708da532bSDmitry Karpeev 
3788d083f849SBarry Smith     Logically Collective on dm
378908da532bSDmitry Karpeev 
3790f899ff85SJose E. Roman     Input Parameter:
3791bb7acecfSBarry Smith .   dm - the `DM` object
379208da532bSDmitry Karpeev 
379308da532bSDmitry Karpeev     Output parameters:
379408da532bSDmitry Karpeev +   xl - lower bound
379508da532bSDmitry Karpeev -   xu - upper bound
379608da532bSDmitry Karpeev 
3797907376e6SBarry Smith     Level: advanced
3798907376e6SBarry Smith 
379995452b02SPatrick Sanan     Notes:
380095452b02SPatrick Sanan     This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
380108da532bSDmitry Karpeev 
3802bb7acecfSBarry Smith .seealso: `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
380308da532bSDmitry Karpeev 
380408da532bSDmitry Karpeev @*/
3805d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3806d71ae5a4SJacob Faibussowitsch {
380708da532bSDmitry Karpeev   PetscFunctionBegin;
38085a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
380908da532bSDmitry Karpeev   PetscValidHeaderSpecific(xl, VEC_CLASSID, 2);
38105a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(xu, VEC_CLASSID, 3);
3811dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, computevariablebounds, xl, xu);
381208da532bSDmitry Karpeev   PetscFunctionReturn(0);
381308da532bSDmitry Karpeev }
381408da532bSDmitry Karpeev 
3815b0ae01b7SPeter Brune /*@
3816bb7acecfSBarry Smith     DMHasColoring - does the `DM` object have a method of providing a coloring?
3817b0ae01b7SPeter Brune 
3818b0ae01b7SPeter Brune     Not Collective
3819b0ae01b7SPeter Brune 
3820b0ae01b7SPeter Brune     Input Parameter:
3821b0ae01b7SPeter Brune .   dm - the DM object
3822b0ae01b7SPeter Brune 
3823b0ae01b7SPeter Brune     Output Parameter:
3824bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateColoring()`.
3825b0ae01b7SPeter Brune 
3826b0ae01b7SPeter Brune     Level: developer
3827b0ae01b7SPeter Brune 
3828bb7acecfSBarry Smith .seealso: `DMCreateColoring()`
3829b0ae01b7SPeter Brune 
3830b0ae01b7SPeter Brune @*/
3831d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasColoring(DM dm, PetscBool *flg)
3832d71ae5a4SJacob Faibussowitsch {
3833b0ae01b7SPeter Brune   PetscFunctionBegin;
38345a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3835534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
3836b0ae01b7SPeter Brune   *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
3837b0ae01b7SPeter Brune   PetscFunctionReturn(0);
3838b0ae01b7SPeter Brune }
3839b0ae01b7SPeter Brune 
38403ad4599aSBarry Smith /*@
3841bb7acecfSBarry Smith     DMHasCreateRestriction - does the `DM` object have a method of providing a restriction?
38423ad4599aSBarry Smith 
38433ad4599aSBarry Smith     Not Collective
38443ad4599aSBarry Smith 
38453ad4599aSBarry Smith     Input Parameter:
3846bb7acecfSBarry Smith .   dm - the `DM` object
38473ad4599aSBarry Smith 
38483ad4599aSBarry Smith     Output Parameter:
3849bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateRestriction()`.
38503ad4599aSBarry Smith 
38513ad4599aSBarry Smith     Level: developer
38523ad4599aSBarry Smith 
3853bb7acecfSBarry Smith .seealso: `DMCreateRestriction()`, `DMHasCreateInterpolation()`, `DMHasCreateInjection()`
38543ad4599aSBarry Smith 
38553ad4599aSBarry Smith @*/
3856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateRestriction(DM dm, PetscBool *flg)
3857d71ae5a4SJacob Faibussowitsch {
38583ad4599aSBarry Smith   PetscFunctionBegin;
38595a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3860534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
38613ad4599aSBarry Smith   *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
38623ad4599aSBarry Smith   PetscFunctionReturn(0);
38633ad4599aSBarry Smith }
38643ad4599aSBarry Smith 
3865a7058e45SLawrence Mitchell /*@
3866bb7acecfSBarry Smith     DMHasCreateInjection - does the `DM` object have a method of providing an injection?
3867a7058e45SLawrence Mitchell 
3868a7058e45SLawrence Mitchell     Not Collective
3869a7058e45SLawrence Mitchell 
3870a7058e45SLawrence Mitchell     Input Parameter:
3871bb7acecfSBarry Smith .   dm - the `DM` object
3872a7058e45SLawrence Mitchell 
3873a7058e45SLawrence Mitchell     Output Parameter:
3874bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateInjection()`.
3875a7058e45SLawrence Mitchell 
3876a7058e45SLawrence Mitchell     Level: developer
3877a7058e45SLawrence Mitchell 
3878bb7acecfSBarry Smith .seealso: `DMCreateInjection()`, `DMHasCreateRestriction()`, `DMHasCreateInterpolation()`
3879a7058e45SLawrence Mitchell 
3880a7058e45SLawrence Mitchell @*/
3881d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateInjection(DM dm, PetscBool *flg)
3882d71ae5a4SJacob Faibussowitsch {
3883a7058e45SLawrence Mitchell   PetscFunctionBegin;
38845a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3885534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
3886dbbe0bcdSBarry Smith   if (dm->ops->hascreateinjection) PetscUseTypeMethod(dm, hascreateinjection, flg);
3887ad540459SPierre Jolivet   else *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE;
3888a7058e45SLawrence Mitchell   PetscFunctionReturn(0);
3889a7058e45SLawrence Mitchell }
3890a7058e45SLawrence Mitchell 
38910298fd71SBarry Smith PetscFunctionList DMList              = NULL;
3892264ace61SBarry Smith PetscBool         DMRegisterAllCalled = PETSC_FALSE;
3893264ace61SBarry Smith 
3894264ace61SBarry Smith /*@C
3895bb7acecfSBarry Smith   DMSetType - Builds a `DM`, for a particular `DM` implementation.
3896264ace61SBarry Smith 
3897d083f849SBarry Smith   Collective on dm
3898264ace61SBarry Smith 
3899264ace61SBarry Smith   Input Parameters:
3900bb7acecfSBarry Smith + dm     - The `DM` object
3901bb7acecfSBarry Smith - method - The name of the `DMType`, for example `DMDA`, `DMPLEX`
3902264ace61SBarry Smith 
3903264ace61SBarry Smith   Options Database Key:
3904bb7acecfSBarry Smith . -dm_type <type> - Sets the `DM` type; use -help for a list of available types
3905264ace61SBarry Smith 
3906264ace61SBarry Smith   Level: intermediate
3907264ace61SBarry Smith 
3908bb7acecfSBarry Smith   Note:
3909bb7acecfSBarry Smith   Of the `DM` is constructed by directly calling a function to construct a particular `DM`, for example, `DMDACreate2d()` or `DMPLEXCreateBoxMesh()`
3910bb7acecfSBarry Smith 
3911bb7acecfSBarry Smith .seealso: `DMType`, `DMDA`, `DMPLEX`, `DMGetType()`, `DMCreate()`, `DMDACreate2d()`
3912264ace61SBarry Smith @*/
3913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetType(DM dm, DMType method)
3914d71ae5a4SJacob Faibussowitsch {
3915264ace61SBarry Smith   PetscErrorCode (*r)(DM);
3916264ace61SBarry Smith   PetscBool match;
3917264ace61SBarry Smith 
3918264ace61SBarry Smith   PetscFunctionBegin;
3919264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, method, &match));
3921264ace61SBarry Smith   if (match) PetscFunctionReturn(0);
3922264ace61SBarry Smith 
39239566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
39249566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(DMList, method, &r));
39257a8be351SBarry Smith   PetscCheck(r, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3926264ace61SBarry Smith 
3927dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, destroy);
39289566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(dm->ops, sizeof(*dm->ops)));
39299566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)dm, method));
39309566063dSJacob Faibussowitsch   PetscCall((*r)(dm));
3931264ace61SBarry Smith   PetscFunctionReturn(0);
3932264ace61SBarry Smith }
3933264ace61SBarry Smith 
3934264ace61SBarry Smith /*@C
3935bb7acecfSBarry Smith   DMGetType - Gets the `DM` type name (as a string) from the `DM`.
3936264ace61SBarry Smith 
3937264ace61SBarry Smith   Not Collective
3938264ace61SBarry Smith 
3939264ace61SBarry Smith   Input Parameter:
3940bb7acecfSBarry Smith . dm  - The `DM`
3941264ace61SBarry Smith 
3942264ace61SBarry Smith   Output Parameter:
3943bb7acecfSBarry Smith . type - The `DMType` name
3944264ace61SBarry Smith 
3945264ace61SBarry Smith   Level: intermediate
3946264ace61SBarry Smith 
3947bb7acecfSBarry Smith .seealso: `DMType`, `DMDA`, `DMPLEX`, `DMSetType()`, `DMCreate()`
3948264ace61SBarry Smith @*/
3949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetType(DM dm, DMType *type)
3950d71ae5a4SJacob Faibussowitsch {
3951264ace61SBarry Smith   PetscFunctionBegin;
3952264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3953c959eef4SJed Brown   PetscValidPointer(type, 2);
39549566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
3955264ace61SBarry Smith   *type = ((PetscObject)dm)->type_name;
3956264ace61SBarry Smith   PetscFunctionReturn(0);
3957264ace61SBarry Smith }
3958264ace61SBarry Smith 
395967a56275SMatthew G Knepley /*@C
3960bb7acecfSBarry Smith   DMConvert - Converts a `DM` to another `DM`, either of the same or different type.
396167a56275SMatthew G Knepley 
3962d083f849SBarry Smith   Collective on dm
396367a56275SMatthew G Knepley 
396467a56275SMatthew G Knepley   Input Parameters:
3965bb7acecfSBarry Smith + dm - the `DM`
3966bb7acecfSBarry Smith - newtype - new `DM` type (use "same" for the same type)
396767a56275SMatthew G Knepley 
396867a56275SMatthew G Knepley   Output Parameter:
3969bb7acecfSBarry Smith . M - pointer to new `DM`
397067a56275SMatthew G Knepley 
397167a56275SMatthew G Knepley   Notes:
3972bb7acecfSBarry Smith   Cannot be used to convert a sequential `DM` to a parallel or a parallel to sequential,
3973bb7acecfSBarry Smith   the MPI communicator of the generated `DM` is always the same as the communicator
3974bb7acecfSBarry Smith   of the input `DM`.
397567a56275SMatthew G Knepley 
397667a56275SMatthew G Knepley   Level: intermediate
397767a56275SMatthew G Knepley 
3978bb7acecfSBarry Smith .seealso: `DM`, `DMSetType()`, `DMCreate()`, `DMClone()`
397967a56275SMatthew G Knepley @*/
3980d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
3981d71ae5a4SJacob Faibussowitsch {
398267a56275SMatthew G Knepley   DM        B;
398367a56275SMatthew G Knepley   char      convname[256];
3984c067b6caSMatthew G. Knepley   PetscBool sametype /*, issame */;
398567a56275SMatthew G Knepley 
398667a56275SMatthew G Knepley   PetscFunctionBegin;
398767a56275SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
398867a56275SMatthew G Knepley   PetscValidType(dm, 1);
398967a56275SMatthew G Knepley   PetscValidPointer(M, 3);
39909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, newtype, &sametype));
39919566063dSJacob Faibussowitsch   /* PetscCall(PetscStrcmp(newtype, "same", &issame)); */
3992c067b6caSMatthew G. Knepley   if (sametype) {
3993c067b6caSMatthew G. Knepley     *M = dm;
39949566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
3995c067b6caSMatthew G. Knepley     PetscFunctionReturn(0);
3996c067b6caSMatthew G. Knepley   } else {
39970298fd71SBarry Smith     PetscErrorCode (*conv)(DM, DMType, DM *) = NULL;
399867a56275SMatthew G Knepley 
399967a56275SMatthew G Knepley     /*
400067a56275SMatthew G Knepley        Order of precedence:
400167a56275SMatthew G Knepley        1) See if a specialized converter is known to the current DM.
400267a56275SMatthew G Knepley        2) See if a specialized converter is known to the desired DM class.
400367a56275SMatthew G Knepley        3) See if a good general converter is registered for the desired class
400467a56275SMatthew G Knepley        4) See if a good general converter is known for the current matrix.
400567a56275SMatthew G Knepley        5) Use a really basic converter.
400667a56275SMatthew G Knepley     */
400767a56275SMatthew G Knepley 
400867a56275SMatthew G Knepley     /* 1) See if a specialized converter is known to the current DM and the desired class */
40099566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
40109566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
40119566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
40129566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
40139566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
40149566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)dm, convname, &conv));
401567a56275SMatthew G Knepley     if (conv) goto foundconv;
401667a56275SMatthew G Knepley 
401767a56275SMatthew G Knepley     /* 2)  See if a specialized converter is known to the desired DM class. */
40189566063dSJacob Faibussowitsch     PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &B));
40199566063dSJacob Faibussowitsch     PetscCall(DMSetType(B, newtype));
40209566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
40219566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
40229566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
40239566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
40249566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
40259566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
402667a56275SMatthew G Knepley     if (conv) {
40279566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&B));
402867a56275SMatthew G Knepley       goto foundconv;
402967a56275SMatthew G Knepley     }
403067a56275SMatthew G Knepley 
403167a56275SMatthew G Knepley #if 0
403267a56275SMatthew G Knepley     /* 3) See if a good general converter is registered for the desired class */
403367a56275SMatthew G Knepley     conv = B->ops->convertfrom;
40349566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&B));
403567a56275SMatthew G Knepley     if (conv) goto foundconv;
403667a56275SMatthew G Knepley 
403767a56275SMatthew G Knepley     /* 4) See if a good general converter is known for the current matrix */
403867a56275SMatthew G Knepley     if (dm->ops->convert) {
403967a56275SMatthew G Knepley       conv = dm->ops->convert;
404067a56275SMatthew G Knepley     }
404167a56275SMatthew G Knepley     if (conv) goto foundconv;
404267a56275SMatthew G Knepley #endif
404367a56275SMatthew G Knepley 
404467a56275SMatthew G Knepley     /* 5) Use a really basic converter. */
404598921bdaSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject)dm)->type_name, newtype);
404667a56275SMatthew G Knepley 
404767a56275SMatthew G Knepley   foundconv:
40489566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(DM_Convert, dm, 0, 0, 0));
40499566063dSJacob Faibussowitsch     PetscCall((*conv)(dm, newtype, M));
405012fa691eSMatthew G. Knepley     /* Things that are independent of DM type: We should consult DMClone() here */
405190b157c4SStefano Zampini     {
40524fb89dddSMatthew G. Knepley       const PetscReal *maxCell, *Lstart, *L;
40536858538eSMatthew G. Knepley 
40544fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
40554fb89dddSMatthew G. Knepley       PetscCall(DMSetPeriodicity(*M, maxCell, Lstart, L));
4056c8a6034eSMark       (*M)->prealloc_only = dm->prealloc_only;
40579566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->vectype));
40589566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*M)->vectype));
40599566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->mattype));
40609566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*M)->mattype));
406112fa691eSMatthew G. Knepley     }
40629566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(DM_Convert, dm, 0, 0, 0));
406367a56275SMatthew G Knepley   }
40649566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
406567a56275SMatthew G Knepley   PetscFunctionReturn(0);
406667a56275SMatthew G Knepley }
4067264ace61SBarry Smith 
4068264ace61SBarry Smith /*--------------------------------------------------------------------------------------------------------------------*/
4069264ace61SBarry Smith 
4070264ace61SBarry Smith /*@C
4071bb7acecfSBarry Smith   DMRegister -  Adds a new `DM` type implementation
40721c84c290SBarry Smith 
40731c84c290SBarry Smith   Not Collective
40741c84c290SBarry Smith 
40751c84c290SBarry Smith   Input Parameters:
40761c84c290SBarry Smith + name        - The name of a new user-defined creation routine
40771c84c290SBarry Smith - create_func - The creation routine itself
40781c84c290SBarry Smith 
40791c84c290SBarry Smith   Notes:
4080bb7acecfSBarry Smith   DMRegister() may be called multiple times to add several user-defined `DM`s
40811c84c290SBarry Smith 
40821c84c290SBarry Smith   Sample usage:
40831c84c290SBarry Smith .vb
4084bdf89e91SBarry Smith     DMRegister("my_da", MyDMCreate);
40851c84c290SBarry Smith .ve
40861c84c290SBarry Smith 
40871c84c290SBarry Smith   Then, your DM type can be chosen with the procedural interface via
40881c84c290SBarry Smith .vb
40891c84c290SBarry Smith     DMCreate(MPI_Comm, DM *);
40901c84c290SBarry Smith     DMSetType(DM,"my_da");
40911c84c290SBarry Smith .ve
40921c84c290SBarry Smith    or at runtime via the option
40931c84c290SBarry Smith .vb
40941c84c290SBarry Smith     -da_type my_da
40951c84c290SBarry Smith .ve
4096264ace61SBarry Smith 
4097264ace61SBarry Smith   Level: advanced
40981c84c290SBarry Smith 
4099bb7acecfSBarry Smith .seealso: `DM`, `DMType`, `DMSetType()`, `DMRegisterAll()`, `DMRegisterDestroy()`
41001c84c290SBarry Smith 
4101264ace61SBarry Smith @*/
4102d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRegister(const char sname[], PetscErrorCode (*function)(DM))
4103d71ae5a4SJacob Faibussowitsch {
4104264ace61SBarry Smith   PetscFunctionBegin;
41059566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
41069566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&DMList, sname, function));
4107264ace61SBarry Smith   PetscFunctionReturn(0);
4108264ace61SBarry Smith }
4109264ace61SBarry Smith 
4110b859378eSBarry Smith /*@C
4111bb7acecfSBarry Smith   DMLoad - Loads a DM that has been stored in binary  with `DMView()`.
4112b859378eSBarry Smith 
4113d083f849SBarry Smith   Collective on viewer
4114b859378eSBarry Smith 
4115b859378eSBarry Smith   Input Parameters:
4116bb7acecfSBarry Smith + newdm - the newly loaded `DM`, this needs to have been created with `DMCreate()` or
4117bb7acecfSBarry Smith            some related function before a call to `DMLoad()`.
4118bb7acecfSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` or
4119bb7acecfSBarry Smith            `PETSCVIEWERHDF5` file viewer, obtained from `PetscViewerHDF5Open()`
4120b859378eSBarry Smith 
4121b859378eSBarry Smith    Level: intermediate
4122b859378eSBarry Smith 
4123b859378eSBarry Smith   Notes:
412455849f57SBarry Smith   The type is determined by the data in the file, any type set into the DM before this call is ignored.
4125b859378eSBarry Smith 
4126bb7acecfSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
4127bb7acecfSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
4128bb7acecfSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
4129cd7e8a5eSksagiyam 
4130b859378eSBarry Smith   Notes for advanced users:
4131b859378eSBarry Smith   Most users should not need to know the details of the binary storage
4132bb7acecfSBarry Smith   format, since `DMLoad()` and `DMView()` completely hide these details.
4133b859378eSBarry Smith   But for anyone who's interested, the standard binary matrix storage
4134b859378eSBarry Smith   format is
4135b859378eSBarry Smith .vb
4136b859378eSBarry Smith      has not yet been determined
4137b859378eSBarry Smith .ve
4138b859378eSBarry Smith 
4139db781477SPatrick Sanan .seealso: `PetscViewerBinaryOpen()`, `DMView()`, `MatLoad()`, `VecLoad()`
4140b859378eSBarry Smith @*/
4141d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
4142d71ae5a4SJacob Faibussowitsch {
41439331c7a4SMatthew G. Knepley   PetscBool isbinary, ishdf5;
4144b859378eSBarry Smith 
4145b859378eSBarry Smith   PetscFunctionBegin;
4146b859378eSBarry Smith   PetscValidHeaderSpecific(newdm, DM_CLASSID, 1);
4147b859378eSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
41489566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckReadable(viewer));
41499566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
41509566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
41519566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Load, viewer, 0, 0, 0));
41529331c7a4SMatthew G. Knepley   if (isbinary) {
41539331c7a4SMatthew G. Knepley     PetscInt classid;
41549331c7a4SMatthew G. Knepley     char     type[256];
4155b859378eSBarry Smith 
41569566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
41577a8be351SBarry Smith     PetscCheck(classid == DM_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not DM next in file, classid found %d", (int)classid);
41589566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
41599566063dSJacob Faibussowitsch     PetscCall(DMSetType(newdm, type));
4160dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41619331c7a4SMatthew G. Knepley   } else if (ishdf5) {
4162dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41639331c7a4SMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
41649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Load, viewer, 0, 0, 0));
4165b859378eSBarry Smith   PetscFunctionReturn(0);
4166b859378eSBarry Smith }
4167b859378eSBarry Smith 
41687da65231SMatthew G Knepley /******************************** FEM Support **********************************/
41697da65231SMatthew G Knepley 
4170d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
4171d71ae5a4SJacob Faibussowitsch {
41721d47ebbbSSatish Balay   PetscInt f;
41731b30c384SMatthew G Knepley 
41747da65231SMatthew G Knepley   PetscFunctionBegin;
417563a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
417648a46eb9SPierre Jolivet   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f])));
41777da65231SMatthew G Knepley   PetscFunctionReturn(0);
41787da65231SMatthew G Knepley }
41797da65231SMatthew G Knepley 
4180d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
4181d71ae5a4SJacob Faibussowitsch {
41821b30c384SMatthew G Knepley   PetscInt f, g;
41837da65231SMatthew G Knepley 
41847da65231SMatthew G Knepley   PetscFunctionBegin;
418563a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
41861d47ebbbSSatish Balay   for (f = 0; f < rows; ++f) {
41879566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  |"));
418848a46eb9SPierre Jolivet     for (g = 0; g < cols; ++g) PetscCall(PetscPrintf(PETSC_COMM_SELF, " % 9.5g", (double)PetscRealPart(A[f * cols + g])));
41899566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, " |\n"));
41907da65231SMatthew G Knepley   }
41917da65231SMatthew G Knepley   PetscFunctionReturn(0);
41927da65231SMatthew G Knepley }
4193e7c4fc90SDmitry Karpeev 
4194d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
4195d71ae5a4SJacob Faibussowitsch {
41960c5b8624SToby Isaac   PetscInt           localSize, bs;
41970c5b8624SToby Isaac   PetscMPIInt        size;
41980c5b8624SToby Isaac   Vec                x, xglob;
41990c5b8624SToby Isaac   const PetscScalar *xarray;
4200e759306cSMatthew G. Knepley 
4201e759306cSMatthew G. Knepley   PetscFunctionBegin;
42029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
42039566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, &x));
42049566063dSJacob Faibussowitsch   PetscCall(VecCopy(X, x));
42059566063dSJacob Faibussowitsch   PetscCall(VecChop(x, tol));
42069566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "%s:\n", name));
42070c5b8624SToby Isaac   if (size > 1) {
42089566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(x, &localSize));
42099566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xarray));
42109566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(x, &bs));
42119566063dSJacob Faibussowitsch     PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)dm), bs, localSize, PETSC_DETERMINE, xarray, &xglob));
42120c5b8624SToby Isaac   } else {
42130c5b8624SToby Isaac     xglob = x;
42140c5b8624SToby Isaac   }
42159566063dSJacob Faibussowitsch   PetscCall(VecView(xglob, PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)dm))));
42160c5b8624SToby Isaac   if (size > 1) {
42179566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xglob));
42189566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xarray));
42190c5b8624SToby Isaac   }
42209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
4221e759306cSMatthew G. Knepley   PetscFunctionReturn(0);
4222e759306cSMatthew G. Knepley }
4223e759306cSMatthew G. Knepley 
422488ed4aceSMatthew G Knepley /*@
4225bb7acecfSBarry Smith   DMGetSection - Get the `PetscSection` encoding the local data layout for the `DM`.   This is equivalent to `DMGetLocalSection()`. Deprecated in v3.12
4226061576a5SJed Brown 
4227061576a5SJed Brown   Input Parameter:
4228bb7acecfSBarry Smith . dm - The `DM`
4229061576a5SJed Brown 
4230061576a5SJed Brown   Output Parameter:
4231bb7acecfSBarry Smith . section - The `PetscSection`
4232061576a5SJed Brown 
4233061576a5SJed Brown   Options Database Keys:
4234bb7acecfSBarry Smith . -dm_petscsection_view - View the `PetscSection` created by the `DM`
4235061576a5SJed Brown 
4236061576a5SJed Brown   Level: advanced
4237061576a5SJed Brown 
4238061576a5SJed Brown   Notes:
4239bb7acecfSBarry Smith   Use `DMGetLocalSection()` in new code.
4240061576a5SJed Brown 
4241bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
4242061576a5SJed Brown 
4243db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `DMSetLocalSection()`, `DMGetGlobalSection()`
4244061576a5SJed Brown @*/
4245d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSection(DM dm, PetscSection *section)
4246d71ae5a4SJacob Faibussowitsch {
4247061576a5SJed Brown   PetscFunctionBegin;
42489566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, section));
4249061576a5SJed Brown   PetscFunctionReturn(0);
4250061576a5SJed Brown }
4251061576a5SJed Brown 
4252061576a5SJed Brown /*@
4253bb7acecfSBarry Smith   DMGetLocalSection - Get the `PetscSection` encoding the local data layout for the `DM`.
425488ed4aceSMatthew G Knepley 
425588ed4aceSMatthew G Knepley   Input Parameter:
4256bb7acecfSBarry Smith . dm - The `DM`
425788ed4aceSMatthew G Knepley 
425888ed4aceSMatthew G Knepley   Output Parameter:
4259bb7acecfSBarry Smith . section - The `PetscSection`
426088ed4aceSMatthew G Knepley 
4261e5893cccSMatthew G. Knepley   Options Database Keys:
4262bb7acecfSBarry Smith . -dm_petscsection_view - View the section created by the `DM`
4263e5893cccSMatthew G. Knepley 
426488ed4aceSMatthew G Knepley   Level: intermediate
426588ed4aceSMatthew G Knepley 
4266bb7acecfSBarry Smith   Note:
4267bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
426888ed4aceSMatthew G Knepley 
4269db781477SPatrick Sanan .seealso: `DMSetLocalSection()`, `DMGetGlobalSection()`
427088ed4aceSMatthew G Knepley @*/
4271d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section)
4272d71ae5a4SJacob Faibussowitsch {
427388ed4aceSMatthew G Knepley   PetscFunctionBegin;
427488ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
427588ed4aceSMatthew G Knepley   PetscValidPointer(section, 2);
42761bb6d2a8SBarry Smith   if (!dm->localSection && dm->ops->createlocalsection) {
4277e5e52638SMatthew G. Knepley     PetscInt d;
4278e5e52638SMatthew G. Knepley 
427945480ffeSMatthew G. Knepley     if (dm->setfromoptionscalled) {
428045480ffeSMatthew G. Knepley       PetscObject       obj = (PetscObject)dm;
428145480ffeSMatthew G. Knepley       PetscViewer       viewer;
428245480ffeSMatthew G. Knepley       PetscViewerFormat format;
428345480ffeSMatthew G. Knepley       PetscBool         flg;
428445480ffeSMatthew G. Knepley 
42859566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm(obj), obj->options, obj->prefix, "-dm_petscds_view", &viewer, &format, &flg));
42869566063dSJacob Faibussowitsch       if (flg) PetscCall(PetscViewerPushFormat(viewer, format));
428745480ffeSMatthew G. Knepley       for (d = 0; d < dm->Nds; ++d) {
42889566063dSJacob Faibussowitsch         PetscCall(PetscDSSetFromOptions(dm->probs[d].ds));
42899566063dSJacob Faibussowitsch         if (flg) PetscCall(PetscDSView(dm->probs[d].ds, viewer));
429045480ffeSMatthew G. Knepley       }
429145480ffeSMatthew G. Knepley       if (flg) {
42929566063dSJacob Faibussowitsch         PetscCall(PetscViewerFlush(viewer));
42939566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
42949566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&viewer));
429545480ffeSMatthew G. Knepley       }
429645480ffeSMatthew G. Knepley     }
4297dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createlocalsection);
42989566063dSJacob Faibussowitsch     if (dm->localSection) PetscCall(PetscObjectViewFromOptions((PetscObject)dm->localSection, NULL, "-dm_petscsection_view"));
42992f0f8703SMatthew G. Knepley   }
43001bb6d2a8SBarry Smith   *section = dm->localSection;
430188ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
430288ed4aceSMatthew G Knepley }
430388ed4aceSMatthew G Knepley 
430488ed4aceSMatthew G Knepley /*@
4305bb7acecfSBarry Smith   DMSetSection - Set the `PetscSection` encoding the local data layout for the `DM`.  This is equivalent to `DMSetLocalSection()`. Deprecated in v3.12
4306061576a5SJed Brown 
4307061576a5SJed Brown   Input Parameters:
4308bb7acecfSBarry Smith + dm - The `DM`
4309bb7acecfSBarry Smith - section - The `PetscSection`
4310061576a5SJed Brown 
4311061576a5SJed Brown   Level: advanced
4312061576a5SJed Brown 
4313061576a5SJed Brown   Notes:
4314bb7acecfSBarry Smith   Use `DMSetLocalSection()` in new code.
4315061576a5SJed Brown 
4316bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4317061576a5SJed Brown 
4318db781477SPatrick Sanan .seealso: `DMSetLocalSection()`, `DMGetLocalSection()`, `DMSetGlobalSection()`
4319061576a5SJed Brown @*/
4320d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSection(DM dm, PetscSection section)
4321d71ae5a4SJacob Faibussowitsch {
4322061576a5SJed Brown   PetscFunctionBegin;
43239566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(dm, section));
4324061576a5SJed Brown   PetscFunctionReturn(0);
4325061576a5SJed Brown }
4326061576a5SJed Brown 
4327061576a5SJed Brown /*@
4328bb7acecfSBarry Smith   DMSetLocalSection - Set the `PetscSection` encoding the local data layout for the `DM`.
432988ed4aceSMatthew G Knepley 
433088ed4aceSMatthew G Knepley   Input Parameters:
4331bb7acecfSBarry Smith + dm - The `DM`
4332bb7acecfSBarry Smith - section - The `PetscSection`
433388ed4aceSMatthew G Knepley 
433488ed4aceSMatthew G Knepley   Level: intermediate
433588ed4aceSMatthew G Knepley 
4336bb7acecfSBarry Smith   Note:
4337bb7acecfSBarry Smith   Any existing Section will be destroyed
433888ed4aceSMatthew G Knepley 
4339bb7acecfSBarry Smith .seealso: `PetscSection`, `DMGetLocalSection()`, `DMSetGlobalSection()`
434088ed4aceSMatthew G Knepley @*/
4341d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLocalSection(DM dm, PetscSection section)
4342d71ae5a4SJacob Faibussowitsch {
4343c473ab19SMatthew G. Knepley   PetscInt numFields = 0;
4344af122d2aSMatthew G Knepley   PetscInt f;
434588ed4aceSMatthew G Knepley 
434688ed4aceSMatthew G Knepley   PetscFunctionBegin;
434788ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4348b9d85ea2SLisandro Dalcin   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
43499566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
43509566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->localSection));
43511bb6d2a8SBarry Smith   dm->localSection = section;
43529566063dSJacob Faibussowitsch   if (section) PetscCall(PetscSectionGetNumFields(dm->localSection, &numFields));
4353af122d2aSMatthew G Knepley   if (numFields) {
43549566063dSJacob Faibussowitsch     PetscCall(DMSetNumFields(dm, numFields));
4355af122d2aSMatthew G Knepley     for (f = 0; f < numFields; ++f) {
43560f21e855SMatthew G. Knepley       PetscObject disc;
4357af122d2aSMatthew G Knepley       const char *name;
4358af122d2aSMatthew G Knepley 
43599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(dm->localSection, f, &name));
43609566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, &disc));
43619566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName(disc, name));
4362af122d2aSMatthew G Knepley     }
4363af122d2aSMatthew G Knepley   }
4364e87a4003SBarry Smith   /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */
43659566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
436688ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
436788ed4aceSMatthew G Knepley }
436888ed4aceSMatthew G Knepley 
43699435951eSToby Isaac /*@
4370bb7acecfSBarry Smith   DMGetDefaultConstraints - Get the `PetscSection` and `Mat` that specify the local constraint interpolation. See `DMSetDefaultConstraints()` for a description of the purpose of constraint interpolation.
43719435951eSToby Isaac 
4372e228b242SToby Isaac   not collective
4373e228b242SToby Isaac 
43749435951eSToby Isaac   Input Parameter:
4375bb7acecfSBarry Smith . dm - The `DM`
43769435951eSToby Isaac 
4377d8d19677SJose E. Roman   Output Parameters:
4378bb7acecfSBarry 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.
4379bb7acecfSBarry 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.
438079769bd5SJed Brown - bias - Vector containing bias to be added to constrained dofs
43819435951eSToby Isaac 
43829435951eSToby Isaac   Level: advanced
43839435951eSToby Isaac 
4384bb7acecfSBarry Smith   Note:
4385bb7acecfSBarry Smith   This gets borrowed references, so the user should not destroy the `PetscSection`, `Mat`, or `Vec`.
43869435951eSToby Isaac 
4387db781477SPatrick Sanan .seealso: `DMSetDefaultConstraints()`
43889435951eSToby Isaac @*/
4389d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat, Vec *bias)
4390d71ae5a4SJacob Faibussowitsch {
43919435951eSToby Isaac   PetscFunctionBegin;
43929435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4393dbbe0bcdSBarry Smith   if (!dm->defaultConstraint.section && !dm->defaultConstraint.mat && dm->ops->createdefaultconstraints) PetscUseTypeMethod(dm, createdefaultconstraints);
43943b8ba7d1SJed Brown   if (section) *section = dm->defaultConstraint.section;
43953b8ba7d1SJed Brown   if (mat) *mat = dm->defaultConstraint.mat;
439679769bd5SJed Brown   if (bias) *bias = dm->defaultConstraint.bias;
43979435951eSToby Isaac   PetscFunctionReturn(0);
43989435951eSToby Isaac }
43999435951eSToby Isaac 
44009435951eSToby Isaac /*@
4401bb7acecfSBarry Smith   DMSetDefaultConstraints - Set the `PetscSection` and `Mat` that specify the local constraint interpolation.
44029435951eSToby Isaac 
4403bb7acecfSBarry 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()`.
44049435951eSToby Isaac 
4405bb7acecfSBarry 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.
44069435951eSToby Isaac 
4407e228b242SToby Isaac   collective on dm
4408e228b242SToby Isaac 
44099435951eSToby Isaac   Input Parameters:
4410bb7acecfSBarry Smith + dm - The `DM`
4411bb7acecfSBarry 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).
4412bb7acecfSBarry 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).
4413bb7acecfSBarry 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).
44149435951eSToby Isaac 
44159435951eSToby Isaac   Level: advanced
44169435951eSToby Isaac 
4417bb7acecfSBarry Smith   Note:
4418bb7acecfSBarry Smith   This increments the references of the `PetscSection`, `Mat`, and `Vec`, so they user can destroy them.
44199435951eSToby Isaac 
4420db781477SPatrick Sanan .seealso: `DMGetDefaultConstraints()`
44219435951eSToby Isaac @*/
4422d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat, Vec bias)
4423d71ae5a4SJacob Faibussowitsch {
4424e228b242SToby Isaac   PetscMPIInt result;
44259435951eSToby Isaac 
44269435951eSToby Isaac   PetscFunctionBegin;
44279435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4428e228b242SToby Isaac   if (section) {
4429e228b242SToby Isaac     PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
44309566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)section), &result));
44317a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint section must have local communicator");
4432e228b242SToby Isaac   }
4433e228b242SToby Isaac   if (mat) {
4434e228b242SToby Isaac     PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
44359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)mat), &result));
44367a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint matrix must have local communicator");
4437e228b242SToby Isaac   }
443879769bd5SJed Brown   if (bias) {
443979769bd5SJed Brown     PetscValidHeaderSpecific(bias, VEC_CLASSID, 4);
44409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)bias), &result));
444179769bd5SJed Brown     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint bias must have local communicator");
444279769bd5SJed Brown   }
44439566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
44449566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->defaultConstraint.section));
44453b8ba7d1SJed Brown   dm->defaultConstraint.section = section;
44469566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)mat));
44479566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&dm->defaultConstraint.mat));
44483b8ba7d1SJed Brown   dm->defaultConstraint.mat = mat;
44499566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)bias));
44509566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&dm->defaultConstraint.bias));
445179769bd5SJed Brown   dm->defaultConstraint.bias = bias;
44529435951eSToby Isaac   PetscFunctionReturn(0);
44539435951eSToby Isaac }
44549435951eSToby Isaac 
4455497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
4456507e4973SMatthew G. Knepley /*
4457bb7acecfSBarry Smith   DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. Generates and error if they are not consistent.
4458507e4973SMatthew G. Knepley 
4459507e4973SMatthew G. Knepley   Input Parameters:
4460bb7acecfSBarry Smith + dm - The `DM`
4461bb7acecfSBarry Smith . localSection - `PetscSection` describing the local data layout
4462bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
4463507e4973SMatthew G. Knepley 
4464507e4973SMatthew G. Knepley   Level: intermediate
4465507e4973SMatthew G. Knepley 
4466db781477SPatrick Sanan .seealso: `DMGetSectionSF()`, `DMSetSectionSF()`
4467507e4973SMatthew G. Knepley */
4468d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
4469d71ae5a4SJacob Faibussowitsch {
4470507e4973SMatthew G. Knepley   MPI_Comm        comm;
4471507e4973SMatthew G. Knepley   PetscLayout     layout;
4472507e4973SMatthew G. Knepley   const PetscInt *ranges;
4473507e4973SMatthew G. Knepley   PetscInt        pStart, pEnd, p, nroots;
4474507e4973SMatthew G. Knepley   PetscMPIInt     size, rank;
4475507e4973SMatthew G. Knepley   PetscBool       valid = PETSC_TRUE, gvalid;
4476507e4973SMatthew G. Knepley 
4477507e4973SMatthew G. Knepley   PetscFunctionBegin;
44789566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4479507e4973SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44809566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
44819566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
44829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(globalSection, &pStart, &pEnd));
44839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(globalSection, &nroots));
44849566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &layout));
44859566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
44869566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, nroots));
44879566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(layout));
44889566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRanges(layout, &ranges));
4489507e4973SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4490f741bcd2SMatthew G. Knepley     PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
4491507e4973SMatthew G. Knepley 
44929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(localSection, p, &dof));
44939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(localSection, p, &off));
44949566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(localSection, p, &cdof));
44959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(globalSection, p, &gdof));
44969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(globalSection, p, &gcdof));
44979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &goff));
4498507e4973SMatthew G. Knepley     if (!gdof) continue; /* Censored point */
44999371c9d4SSatish Balay     if ((gdof < 0 ? -(gdof + 1) : gdof) != dof) {
45009371c9d4SSatish 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));
45019371c9d4SSatish Balay       valid = PETSC_FALSE;
45029371c9d4SSatish Balay     }
45039371c9d4SSatish Balay     if (gcdof && (gcdof != cdof)) {
45049371c9d4SSatish 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));
45059371c9d4SSatish Balay       valid = PETSC_FALSE;
45069371c9d4SSatish Balay     }
4507507e4973SMatthew G. Knepley     if (gdof < 0) {
4508507e4973SMatthew G. Knepley       gsize = gdof < 0 ? -(gdof + 1) - gcdof : gdof - gcdof;
4509507e4973SMatthew G. Knepley       for (d = 0; d < gsize; ++d) {
4510507e4973SMatthew G. Knepley         PetscInt offset = -(goff + 1) + d, r;
4511507e4973SMatthew G. Knepley 
45129566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(offset, size + 1, ranges, &r));
4513507e4973SMatthew G. Knepley         if (r < 0) r = -(r + 2);
45149371c9d4SSatish Balay         if ((r < 0) || (r >= size)) {
45159371c9d4SSatish Balay           PetscCall(PetscSynchronizedPrintf(comm, "[%d]Point %" PetscInt_FMT " mapped to invalid process %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, p, r, gdof, goff));
45169371c9d4SSatish Balay           valid = PETSC_FALSE;
45179371c9d4SSatish Balay           break;
45189371c9d4SSatish Balay         }
4519507e4973SMatthew G. Knepley       }
4520507e4973SMatthew G. Knepley     }
4521507e4973SMatthew G. Knepley   }
45229566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
45239566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
45241c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm));
4525507e4973SMatthew G. Knepley   if (!gvalid) {
45269566063dSJacob Faibussowitsch     PetscCall(DMView(dm, NULL));
4527507e4973SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
4528507e4973SMatthew G. Knepley   }
4529507e4973SMatthew G. Knepley   PetscFunctionReturn(0);
4530507e4973SMatthew G. Knepley }
4531f741bcd2SMatthew G. Knepley #endif
4532507e4973SMatthew G. Knepley 
453388ed4aceSMatthew G Knepley /*@
4534bb7acecfSBarry Smith   DMGetGlobalSection - Get the `PetscSection` encoding the global data layout for the `DM`.
453588ed4aceSMatthew G Knepley 
4536d083f849SBarry Smith   Collective on dm
45378b1ab98fSJed Brown 
453888ed4aceSMatthew G Knepley   Input Parameter:
4539bb7acecfSBarry Smith . dm - The `DM`
454088ed4aceSMatthew G Knepley 
454188ed4aceSMatthew G Knepley   Output Parameter:
4542bb7acecfSBarry Smith . section - The `PetscSection`
454388ed4aceSMatthew G Knepley 
454488ed4aceSMatthew G Knepley   Level: intermediate
454588ed4aceSMatthew G Knepley 
4546bb7acecfSBarry Smith   Note:
4547bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
454888ed4aceSMatthew G Knepley 
4549db781477SPatrick Sanan .seealso: `DMSetLocalSection()`, `DMGetLocalSection()`
455088ed4aceSMatthew G Knepley @*/
4551d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section)
4552d71ae5a4SJacob Faibussowitsch {
455388ed4aceSMatthew G Knepley   PetscFunctionBegin;
455488ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
455588ed4aceSMatthew G Knepley   PetscValidPointer(section, 2);
45561bb6d2a8SBarry Smith   if (!dm->globalSection) {
4557fd59a867SMatthew G. Knepley     PetscSection s;
4558fd59a867SMatthew G. Knepley 
45599566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &s));
45607a8be351SBarry Smith     PetscCheck(s, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
45617a8be351SBarry Smith     PetscCheck(dm->sf, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection");
45629566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->globalSection));
45639566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&dm->map));
45649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map));
45659566063dSJacob Faibussowitsch     PetscCall(PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view"));
456688ed4aceSMatthew G Knepley   }
45671bb6d2a8SBarry Smith   *section = dm->globalSection;
456888ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
456988ed4aceSMatthew G Knepley }
457088ed4aceSMatthew G Knepley 
4571b21d0597SMatthew G Knepley /*@
4572bb7acecfSBarry Smith   DMSetGlobalSection - Set the `PetscSection` encoding the global data layout for the `DM`.
4573b21d0597SMatthew G Knepley 
4574b21d0597SMatthew G Knepley   Input Parameters:
4575bb7acecfSBarry Smith + dm - The `DM`
45765080bbdbSMatthew G Knepley - section - The PetscSection, or NULL
4577b21d0597SMatthew G Knepley 
4578b21d0597SMatthew G Knepley   Level: intermediate
4579b21d0597SMatthew G Knepley 
4580bb7acecfSBarry Smith   Note:
4581bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4582b21d0597SMatthew G Knepley 
4583db781477SPatrick Sanan .seealso: `DMGetGlobalSection()`, `DMSetLocalSection()`
4584b21d0597SMatthew G Knepley @*/
4585d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section)
4586d71ae5a4SJacob Faibussowitsch {
4587b21d0597SMatthew G Knepley   PetscFunctionBegin;
4588b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45895080bbdbSMatthew G Knepley   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
45909566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
45919566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
45921bb6d2a8SBarry Smith   dm->globalSection = section;
4593497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
45949566063dSJacob Faibussowitsch   if (section) PetscCall(DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section));
4595507e4973SMatthew G. Knepley #endif
4596b21d0597SMatthew G Knepley   PetscFunctionReturn(0);
4597b21d0597SMatthew G Knepley }
4598b21d0597SMatthew G Knepley 
459988ed4aceSMatthew G Knepley /*@
4600bb7acecfSBarry Smith   DMGetSectionSF - Get the `PetscSF` encoding the parallel dof overlap for the `DM`. If it has not been set,
4601bb7acecfSBarry Smith   it is created from the default `PetscSection` layouts in the `DM`.
460288ed4aceSMatthew G Knepley 
460388ed4aceSMatthew G Knepley   Input Parameter:
4604bb7acecfSBarry Smith . dm - The `DM`
460588ed4aceSMatthew G Knepley 
460688ed4aceSMatthew G Knepley   Output Parameter:
4607bb7acecfSBarry Smith . sf - The `PetscSF`
460888ed4aceSMatthew G Knepley 
460988ed4aceSMatthew G Knepley   Level: intermediate
461088ed4aceSMatthew G Knepley 
4611bb7acecfSBarry Smith   Note:
4612bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
461388ed4aceSMatthew G Knepley 
4614db781477SPatrick Sanan .seealso: `DMSetSectionSF()`, `DMCreateSectionSF()`
461588ed4aceSMatthew G Knepley @*/
4616d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf)
4617d71ae5a4SJacob Faibussowitsch {
461888ed4aceSMatthew G Knepley   PetscInt nroots;
461988ed4aceSMatthew G Knepley 
462088ed4aceSMatthew G Knepley   PetscFunctionBegin;
462188ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
462288ed4aceSMatthew G Knepley   PetscValidPointer(sf, 2);
462348a46eb9SPierre Jolivet   if (!dm->sectionSF) PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &dm->sectionSF));
46249566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL));
462588ed4aceSMatthew G Knepley   if (nroots < 0) {
462688ed4aceSMatthew G Knepley     PetscSection section, gSection;
462788ed4aceSMatthew G Knepley 
46289566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
462931ea6d37SMatthew G Knepley     if (section) {
46309566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gSection));
46319566063dSJacob Faibussowitsch       PetscCall(DMCreateSectionSF(dm, section, gSection));
463231ea6d37SMatthew G Knepley     } else {
46330298fd71SBarry Smith       *sf = NULL;
463431ea6d37SMatthew G Knepley       PetscFunctionReturn(0);
463531ea6d37SMatthew G Knepley     }
463688ed4aceSMatthew G Knepley   }
46371bb6d2a8SBarry Smith   *sf = dm->sectionSF;
463888ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
463988ed4aceSMatthew G Knepley }
464088ed4aceSMatthew G Knepley 
464188ed4aceSMatthew G Knepley /*@
4642bb7acecfSBarry Smith   DMSetSectionSF - Set the `PetscSF` encoding the parallel dof overlap for the `DM`
464388ed4aceSMatthew G Knepley 
464488ed4aceSMatthew G Knepley   Input Parameters:
4645bb7acecfSBarry Smith + dm - The `DM`
4646bb7acecfSBarry Smith - sf - The `PetscSF`
464788ed4aceSMatthew G Knepley 
464888ed4aceSMatthew G Knepley   Level: intermediate
464988ed4aceSMatthew G Knepley 
4650bb7acecfSBarry Smith   Note:
4651bb7acecfSBarry Smith   Any previous `PetscSF` is destroyed
465288ed4aceSMatthew G Knepley 
4653db781477SPatrick Sanan .seealso: `DMGetSectionSF()`, `DMCreateSectionSF()`
465488ed4aceSMatthew G Knepley @*/
4655d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf)
4656d71ae5a4SJacob Faibussowitsch {
465788ed4aceSMatthew G Knepley   PetscFunctionBegin;
465888ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4659b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
46609566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
46619566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sectionSF));
46621bb6d2a8SBarry Smith   dm->sectionSF = sf;
466388ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
466488ed4aceSMatthew G Knepley }
466588ed4aceSMatthew G Knepley 
466688ed4aceSMatthew G Knepley /*@C
4667bb7acecfSBarry Smith   DMCreateSectionSF - Create the `PetscSF` encoding the parallel dof overlap for the `DM` based upon the `PetscSection`s
466888ed4aceSMatthew G Knepley   describing the data layout.
466988ed4aceSMatthew G Knepley 
467088ed4aceSMatthew G Knepley   Input Parameters:
4671bb7acecfSBarry Smith + dm - The `DM`
4672bb7acecfSBarry Smith . localSection - `PetscSection` describing the local data layout
4673bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
467488ed4aceSMatthew G Knepley 
46751bb6d2a8SBarry Smith   Level: developer
46761bb6d2a8SBarry Smith 
4677bb7acecfSBarry Smith   Note:
4678bb7acecfSBarry Smith   One usually uses `DMGetSectionSF()` to obtain the `PetscSF`
4679bb7acecfSBarry Smith 
4680bb7acecfSBarry Smith   Developer Note:
4681bb7acecfSBarry Smith   Since this routine has for arguments the two sections from the `DM` and puts the resulting `PetscSF`
4682bb7acecfSBarry Smith   directly into the `DM`, perhaps this function should not take the local and global sections as
4683bb7acecfSBarry Smith   input and should just obtain them from the `DM`?
46841bb6d2a8SBarry Smith 
4685db781477SPatrick Sanan .seealso: `DMGetSectionSF()`, `DMSetSectionSF()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
468688ed4aceSMatthew G Knepley @*/
4687d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection)
4688d71ae5a4SJacob Faibussowitsch {
468988ed4aceSMatthew G Knepley   PetscFunctionBegin;
469088ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46919566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphSection(dm->sectionSF, localSection, globalSection));
469288ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
469388ed4aceSMatthew G Knepley }
4694af122d2aSMatthew G Knepley 
4695b21d0597SMatthew G Knepley /*@
4696bb7acecfSBarry Smith   DMGetPointSF - Get the `PetscSF` encoding the parallel section point overlap for the `DM`.
4697bb7acecfSBarry Smith 
4698bb7acecfSBarry Smith   Not collective but the resulting `PetscSF` is collective
4699b21d0597SMatthew G Knepley 
4700b21d0597SMatthew G Knepley   Input Parameter:
4701bb7acecfSBarry Smith . dm - The `DM`
4702b21d0597SMatthew G Knepley 
4703b21d0597SMatthew G Knepley   Output Parameter:
4704bb7acecfSBarry Smith . sf - The `PetscSF`
4705b21d0597SMatthew G Knepley 
4706b21d0597SMatthew G Knepley   Level: intermediate
4707b21d0597SMatthew G Knepley 
4708bb7acecfSBarry Smith   Note:
4709bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
4710b21d0597SMatthew G Knepley 
4711db781477SPatrick Sanan .seealso: `DMSetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4712b21d0597SMatthew G Knepley @*/
4713d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
4714d71ae5a4SJacob Faibussowitsch {
4715b21d0597SMatthew G Knepley   PetscFunctionBegin;
4716b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4717b21d0597SMatthew G Knepley   PetscValidPointer(sf, 2);
4718b21d0597SMatthew G Knepley   *sf = dm->sf;
4719b21d0597SMatthew G Knepley   PetscFunctionReturn(0);
4720b21d0597SMatthew G Knepley }
4721b21d0597SMatthew G Knepley 
4722057b4bcdSMatthew G Knepley /*@
4723bb7acecfSBarry Smith   DMSetPointSF - Set the `PetscSF` encoding the parallel section point overlap for the `DM`.
4724bb7acecfSBarry Smith 
4725bb7acecfSBarry Smith   Collective on dm
4726057b4bcdSMatthew G Knepley 
4727057b4bcdSMatthew G Knepley   Input Parameters:
4728bb7acecfSBarry Smith + dm - The `DM`
4729bb7acecfSBarry Smith - sf - The` PetscSF`
4730057b4bcdSMatthew G Knepley 
4731057b4bcdSMatthew G Knepley   Level: intermediate
4732057b4bcdSMatthew G Knepley 
4733db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4734057b4bcdSMatthew G Knepley @*/
4735d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
4736d71ae5a4SJacob Faibussowitsch {
4737057b4bcdSMatthew G Knepley   PetscFunctionBegin;
4738057b4bcdSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4739b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47409566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47419566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sf));
4742057b4bcdSMatthew G Knepley   dm->sf = sf;
4743057b4bcdSMatthew G Knepley   PetscFunctionReturn(0);
4744057b4bcdSMatthew G Knepley }
4745057b4bcdSMatthew G Knepley 
47464f37162bSMatthew G. Knepley /*@
4747bb7acecfSBarry Smith   DMGetNaturalSF - Get the `PetscSF` encoding the map back to the original mesh ordering
47484f37162bSMatthew G. Knepley 
47494f37162bSMatthew G. Knepley   Input Parameter:
4750bb7acecfSBarry Smith . dm - The `DM`
47514f37162bSMatthew G. Knepley 
47524f37162bSMatthew G. Knepley   Output Parameter:
4753bb7acecfSBarry Smith . sf - The `PetscSF`
47544f37162bSMatthew G. Knepley 
47554f37162bSMatthew G. Knepley   Level: intermediate
47564f37162bSMatthew G. Knepley 
4757bb7acecfSBarry Smith   Note:
4758bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
47594f37162bSMatthew G. Knepley 
4760db781477SPatrick Sanan .seealso: `DMSetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
47614f37162bSMatthew G. Knepley @*/
4762d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNaturalSF(DM dm, PetscSF *sf)
4763d71ae5a4SJacob Faibussowitsch {
47644f37162bSMatthew G. Knepley   PetscFunctionBegin;
47654f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47664f37162bSMatthew G. Knepley   PetscValidPointer(sf, 2);
47674f37162bSMatthew G. Knepley   *sf = dm->sfNatural;
47684f37162bSMatthew G. Knepley   PetscFunctionReturn(0);
47694f37162bSMatthew G. Knepley }
47704f37162bSMatthew G. Knepley 
47714f37162bSMatthew G. Knepley /*@
47724f37162bSMatthew G. Knepley   DMSetNaturalSF - Set the PetscSF encoding the map back to the original mesh ordering
47734f37162bSMatthew G. Knepley 
47744f37162bSMatthew G. Knepley   Input Parameters:
47754f37162bSMatthew G. Knepley + dm - The DM
47764f37162bSMatthew G. Knepley - sf - The PetscSF
47774f37162bSMatthew G. Knepley 
47784f37162bSMatthew G. Knepley   Level: intermediate
47794f37162bSMatthew G. Knepley 
4780db781477SPatrick Sanan .seealso: `DMGetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
47814f37162bSMatthew G. Knepley @*/
4782d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNaturalSF(DM dm, PetscSF sf)
4783d71ae5a4SJacob Faibussowitsch {
47844f37162bSMatthew G. Knepley   PetscFunctionBegin;
47854f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47864f37162bSMatthew G. Knepley   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47879566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47889566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sfNatural));
47894f37162bSMatthew G. Knepley   dm->sfNatural = sf;
47904f37162bSMatthew G. Knepley   PetscFunctionReturn(0);
47914f37162bSMatthew G. Knepley }
47924f37162bSMatthew G. Knepley 
4793d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc)
4794d71ae5a4SJacob Faibussowitsch {
479534aa8a36SMatthew G. Knepley   PetscClassId id;
479634aa8a36SMatthew G. Knepley 
479734aa8a36SMatthew G. Knepley   PetscFunctionBegin;
47989566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId(disc, &id));
479934aa8a36SMatthew G. Knepley   if (id == PETSCFE_CLASSID) {
48009566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
480134aa8a36SMatthew G. Knepley   } else if (id == PETSCFV_CLASSID) {
48029566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE));
480317c1d62eSMatthew G. Knepley   } else {
48049566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
480534aa8a36SMatthew G. Knepley   }
480634aa8a36SMatthew G. Knepley   PetscFunctionReturn(0);
480734aa8a36SMatthew G. Knepley }
480834aa8a36SMatthew G. Knepley 
4809d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew)
4810d71ae5a4SJacob Faibussowitsch {
481144a7f3ddSMatthew G. Knepley   RegionField *tmpr;
481244a7f3ddSMatthew G. Knepley   PetscInt     Nf = dm->Nf, f;
481344a7f3ddSMatthew G. Knepley 
481444a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
481544a7f3ddSMatthew G. Knepley   if (Nf >= NfNew) PetscFunctionReturn(0);
48169566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NfNew, &tmpr));
481744a7f3ddSMatthew G. Knepley   for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f];
48189371c9d4SSatish Balay   for (f = Nf; f < NfNew; ++f) {
48199371c9d4SSatish Balay     tmpr[f].disc        = NULL;
48209371c9d4SSatish Balay     tmpr[f].label       = NULL;
48219371c9d4SSatish Balay     tmpr[f].avoidTensor = PETSC_FALSE;
48229371c9d4SSatish Balay   }
48239566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
482444a7f3ddSMatthew G. Knepley   dm->Nf     = NfNew;
482544a7f3ddSMatthew G. Knepley   dm->fields = tmpr;
482644a7f3ddSMatthew G. Knepley   PetscFunctionReturn(0);
482744a7f3ddSMatthew G. Knepley }
482844a7f3ddSMatthew G. Knepley 
482944a7f3ddSMatthew G. Knepley /*@
483044a7f3ddSMatthew G. Knepley   DMClearFields - Remove all fields from the DM
483144a7f3ddSMatthew G. Knepley 
4832d083f849SBarry Smith   Logically collective on dm
483344a7f3ddSMatthew G. Knepley 
483444a7f3ddSMatthew G. Knepley   Input Parameter:
483544a7f3ddSMatthew G. Knepley . dm - The DM
483644a7f3ddSMatthew G. Knepley 
483744a7f3ddSMatthew G. Knepley   Level: intermediate
483844a7f3ddSMatthew G. Knepley 
4839db781477SPatrick Sanan .seealso: `DMGetNumFields()`, `DMSetNumFields()`, `DMSetField()`
484044a7f3ddSMatthew G. Knepley @*/
4841d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearFields(DM dm)
4842d71ae5a4SJacob Faibussowitsch {
484344a7f3ddSMatthew G. Knepley   PetscInt f;
484444a7f3ddSMatthew G. Knepley 
484544a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
484644a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
484744a7f3ddSMatthew G. Knepley   for (f = 0; f < dm->Nf; ++f) {
48489566063dSJacob Faibussowitsch     PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
48499566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->fields[f].label));
485044a7f3ddSMatthew G. Knepley   }
48519566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
485244a7f3ddSMatthew G. Knepley   dm->fields = NULL;
485344a7f3ddSMatthew G. Knepley   dm->Nf     = 0;
485444a7f3ddSMatthew G. Knepley   PetscFunctionReturn(0);
485544a7f3ddSMatthew G. Knepley }
485644a7f3ddSMatthew G. Knepley 
4857689b5837SMatthew G. Knepley /*@
4858689b5837SMatthew G. Knepley   DMGetNumFields - Get the number of fields in the DM
4859689b5837SMatthew G. Knepley 
4860689b5837SMatthew G. Knepley   Not collective
4861689b5837SMatthew G. Knepley 
4862689b5837SMatthew G. Knepley   Input Parameter:
4863689b5837SMatthew G. Knepley . dm - The DM
4864689b5837SMatthew G. Knepley 
4865689b5837SMatthew G. Knepley   Output Parameter:
4866689b5837SMatthew G. Knepley . Nf - The number of fields
4867689b5837SMatthew G. Knepley 
4868689b5837SMatthew G. Knepley   Level: intermediate
4869689b5837SMatthew G. Knepley 
4870db781477SPatrick Sanan .seealso: `DMSetNumFields()`, `DMSetField()`
4871689b5837SMatthew G. Knepley @*/
4872d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4873d71ae5a4SJacob Faibussowitsch {
48740f21e855SMatthew G. Knepley   PetscFunctionBegin;
48750f21e855SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4876534a8f05SLisandro Dalcin   PetscValidIntPointer(numFields, 2);
487744a7f3ddSMatthew G. Knepley   *numFields = dm->Nf;
4878af122d2aSMatthew G Knepley   PetscFunctionReturn(0);
4879af122d2aSMatthew G Knepley }
4880af122d2aSMatthew G Knepley 
4881689b5837SMatthew G. Knepley /*@
4882689b5837SMatthew G. Knepley   DMSetNumFields - Set the number of fields in the DM
4883689b5837SMatthew G. Knepley 
4884d083f849SBarry Smith   Logically collective on dm
4885689b5837SMatthew G. Knepley 
4886689b5837SMatthew G. Knepley   Input Parameters:
4887689b5837SMatthew G. Knepley + dm - The DM
4888689b5837SMatthew G. Knepley - Nf - The number of fields
4889689b5837SMatthew G. Knepley 
4890689b5837SMatthew G. Knepley   Level: intermediate
4891689b5837SMatthew G. Knepley 
4892db781477SPatrick Sanan .seealso: `DMGetNumFields()`, `DMSetField()`
4893689b5837SMatthew G. Knepley @*/
4894d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4895d71ae5a4SJacob Faibussowitsch {
48960f21e855SMatthew G. Knepley   PetscInt Nf, f;
4897af122d2aSMatthew G Knepley 
4898af122d2aSMatthew G Knepley   PetscFunctionBegin;
4899af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49009566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
49010f21e855SMatthew G. Knepley   for (f = Nf; f < numFields; ++f) {
49020f21e855SMatthew G. Knepley     PetscContainer obj;
49030f21e855SMatthew G. Knepley 
49049566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)dm), &obj));
49059566063dSJacob Faibussowitsch     PetscCall(DMAddField(dm, NULL, (PetscObject)obj));
49069566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&obj));
4907af122d2aSMatthew G Knepley   }
4908af122d2aSMatthew G Knepley   PetscFunctionReturn(0);
4909af122d2aSMatthew G Knepley }
4910af122d2aSMatthew G Knepley 
4911c1929be8SMatthew G. Knepley /*@
4912bb7acecfSBarry Smith   DMGetField - Return the `DMLabel` and discretization object for a given `DM` field
4913c1929be8SMatthew G. Knepley 
4914c1929be8SMatthew G. Knepley   Not collective
4915c1929be8SMatthew G. Knepley 
4916c1929be8SMatthew G. Knepley   Input Parameters:
4917bb7acecfSBarry Smith + dm - The `DM`
4918c1929be8SMatthew G. Knepley - f  - The field number
4919c1929be8SMatthew G. Knepley 
492044a7f3ddSMatthew G. Knepley   Output Parameters:
4921bb7acecfSBarry Smith + label - The label indicating the support of the field, or NULL for the entire mesh (pass in NULL if not needed)
4922bb7acecfSBarry Smith - disc - The discretization object (pass in NULL if not needed)
4923c1929be8SMatthew G. Knepley 
492444a7f3ddSMatthew G. Knepley   Level: intermediate
4925c1929be8SMatthew G. Knepley 
4926db781477SPatrick Sanan .seealso: `DMAddField()`, `DMSetField()`
4927c1929be8SMatthew G. Knepley @*/
4928d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *disc)
4929d71ae5a4SJacob Faibussowitsch {
4930af122d2aSMatthew G Knepley   PetscFunctionBegin;
4931af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4932bb7acecfSBarry Smith   PetscValidPointer(disc, 4);
49337a8be351SBarry 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);
493444a7f3ddSMatthew G. Knepley   if (label) *label = dm->fields[f].label;
4935bb7acecfSBarry Smith   if (disc) *disc = dm->fields[f].disc;
4936decb47aaSMatthew G. Knepley   PetscFunctionReturn(0);
4937decb47aaSMatthew G. Knepley }
4938decb47aaSMatthew G. Knepley 
4939083401c6SMatthew G. Knepley /* Does not clear the DS */
4940d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField_Internal(DM dm, PetscInt f, DMLabel label, PetscObject disc)
4941d71ae5a4SJacob Faibussowitsch {
4942083401c6SMatthew G. Knepley   PetscFunctionBegin;
49439566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, f + 1));
49449566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->fields[f].label));
49459566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
4946083401c6SMatthew G. Knepley   dm->fields[f].label = label;
4947bb7acecfSBarry Smith   dm->fields[f].disc  = disc;
49489566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
4949bb7acecfSBarry Smith   PetscCall(PetscObjectReference((PetscObject)disc));
4950083401c6SMatthew G. Knepley   PetscFunctionReturn(0);
4951083401c6SMatthew G. Knepley }
4952083401c6SMatthew G. Knepley 
4953c1929be8SMatthew G. Knepley /*@
4954bb7acecfSBarry Smith   DMSetField - Set the discretization object for a given `DM` field. Usually one would call `DMAddField()` which automatically handles
4955bb7acecfSBarry Smith   the field numbering.
4956c1929be8SMatthew G. Knepley 
4957d083f849SBarry Smith   Logically collective on dm
4958c1929be8SMatthew G. Knepley 
4959c1929be8SMatthew G. Knepley   Input Parameters:
4960bb7acecfSBarry Smith + dm    - The `DM`
4961c1929be8SMatthew G. Knepley . f     - The field number
496244a7f3ddSMatthew G. Knepley . label - The label indicating the support of the field, or NULL for the entire mesh
4963bb7acecfSBarry Smith - disc - The discretization object
4964c1929be8SMatthew G. Knepley 
496544a7f3ddSMatthew G. Knepley   Level: intermediate
4966c1929be8SMatthew G. Knepley 
4967db781477SPatrick Sanan .seealso: `DMAddField()`, `DMGetField()`
4968c1929be8SMatthew G. Knepley @*/
4969d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject disc)
4970d71ae5a4SJacob Faibussowitsch {
4971decb47aaSMatthew G. Knepley   PetscFunctionBegin;
4972decb47aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4973e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
4974bb7acecfSBarry Smith   PetscValidHeader(disc, 4);
49757a8be351SBarry Smith   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
4976bb7acecfSBarry Smith   PetscCall(DMSetField_Internal(dm, f, label, disc));
4977bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, f, disc));
49789566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
497944a7f3ddSMatthew G. Knepley   PetscFunctionReturn(0);
498044a7f3ddSMatthew G. Knepley }
498144a7f3ddSMatthew G. Knepley 
498244a7f3ddSMatthew G. Knepley /*@
4983bb7acecfSBarry 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)
4984bb7acecfSBarry Smith   and a discretization object that defines the function space associated with those points.
498544a7f3ddSMatthew G. Knepley 
4986d083f849SBarry Smith   Logically collective on dm
498744a7f3ddSMatthew G. Knepley 
498844a7f3ddSMatthew G. Knepley   Input Parameters:
4989bb7acecfSBarry Smith + dm    - The `DM`
499044a7f3ddSMatthew G. Knepley . label - The label indicating the support of the field, or NULL for the entire mesh
4991bb7acecfSBarry Smith - disc - The discretization object
499244a7f3ddSMatthew G. Knepley 
499344a7f3ddSMatthew G. Knepley   Level: intermediate
499444a7f3ddSMatthew G. Knepley 
4995bb7acecfSBarry Smith   Notes:
4996bb7acecfSBarry Smith   The label already exists or will be added to the `DM` with `DMSetLabel()`.
4997bb7acecfSBarry Smith 
4998bb7acecfSBarry Smith   For example, a piecewise continous pressure field can be defined by coefficients at the cell centers of a mesh and piecewise constant functions
4999bb7acecfSBarry 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
5000bb7acecfSBarry Smith   geometry entities, a `DMLabel` indicating a subset of those geometric entities, and a discretization object, such as a `PetscFE`.
5001bb7acecfSBarry Smith 
5002bb7acecfSBarry Smith .seealso: `DMSetLabel()`, `DMSetField()`, `DMGetField()`, `PetscFE`
500344a7f3ddSMatthew G. Knepley @*/
5004d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject disc)
5005d71ae5a4SJacob Faibussowitsch {
500644a7f3ddSMatthew G. Knepley   PetscInt Nf = dm->Nf;
500744a7f3ddSMatthew G. Knepley 
500844a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
500944a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5010064a246eSJacob Faibussowitsch   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
5011bb7acecfSBarry Smith   PetscValidHeader(disc, 3);
50129566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, Nf + 1));
501344a7f3ddSMatthew G. Knepley   dm->fields[Nf].label = label;
5014bb7acecfSBarry Smith   dm->fields[Nf].disc  = disc;
50159566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
5016bb7acecfSBarry Smith   PetscCall(PetscObjectReference((PetscObject)disc));
5017bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, Nf, disc));
50189566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
5019af122d2aSMatthew G Knepley   PetscFunctionReturn(0);
5020af122d2aSMatthew G Knepley }
50216636e97aSMatthew G Knepley 
5022e5e52638SMatthew G. Knepley /*@
5023e0b68406SMatthew Knepley   DMSetFieldAvoidTensor - Set flag to avoid defining the field on tensor cells
5024e0b68406SMatthew Knepley 
5025e0b68406SMatthew Knepley   Logically collective on dm
5026e0b68406SMatthew Knepley 
5027e0b68406SMatthew Knepley   Input Parameters:
5028bb7acecfSBarry Smith + dm          - The `DM`
5029e0b68406SMatthew Knepley . f           - The field index
5030bb7acecfSBarry Smith - avoidTensor - `PETSC_TRUE` to skip defining the field on tensor cells
5031e0b68406SMatthew Knepley 
5032e0b68406SMatthew Knepley   Level: intermediate
5033e0b68406SMatthew Knepley 
5034db781477SPatrick Sanan .seealso: `DMGetFieldAvoidTensor()`, `DMSetField()`, `DMGetField()`
5035e0b68406SMatthew Knepley @*/
5036d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFieldAvoidTensor(DM dm, PetscInt f, PetscBool avoidTensor)
5037d71ae5a4SJacob Faibussowitsch {
5038e0b68406SMatthew Knepley   PetscFunctionBegin;
503963a3b9bcSJacob 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);
5040e0b68406SMatthew Knepley   dm->fields[f].avoidTensor = avoidTensor;
5041e0b68406SMatthew Knepley   PetscFunctionReturn(0);
5042e0b68406SMatthew Knepley }
5043e0b68406SMatthew Knepley 
5044e0b68406SMatthew Knepley /*@
5045e0b68406SMatthew Knepley   DMGetFieldAvoidTensor - Get flag to avoid defining the field on tensor cells
5046e0b68406SMatthew Knepley 
5047bb7acecfSBarry Smith   Not collective
5048e0b68406SMatthew Knepley 
5049e0b68406SMatthew Knepley   Input Parameters:
5050bb7acecfSBarry Smith + dm          - The `DM`
5051e0b68406SMatthew Knepley - f           - The field index
5052e0b68406SMatthew Knepley 
5053e0b68406SMatthew Knepley   Output Parameter:
5054e0b68406SMatthew Knepley . avoidTensor - The flag to avoid defining the field on tensor cells
5055e0b68406SMatthew Knepley 
5056e0b68406SMatthew Knepley   Level: intermediate
5057e0b68406SMatthew Knepley 
5058bb7acecfSBarry Smith  .seealso: `DMAddField()`, `DMSetField()`, `DMGetField()`, `DMSetFieldAvoidTensor()`, `DMSetField()`, `DMGetField()`
5059e0b68406SMatthew Knepley @*/
5060d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFieldAvoidTensor(DM dm, PetscInt f, PetscBool *avoidTensor)
5061d71ae5a4SJacob Faibussowitsch {
5062e0b68406SMatthew Knepley   PetscFunctionBegin;
506363a3b9bcSJacob 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);
5064e0b68406SMatthew Knepley   *avoidTensor = dm->fields[f].avoidTensor;
5065e0b68406SMatthew Knepley   PetscFunctionReturn(0);
5066e0b68406SMatthew Knepley }
5067e0b68406SMatthew Knepley 
5068e0b68406SMatthew Knepley /*@
5069bb7acecfSBarry Smith   DMCopyFields - Copy the discretizations for the `DM` into another `DM`
5070e5e52638SMatthew G. Knepley 
5071d083f849SBarry Smith   Collective on dm
5072e5e52638SMatthew G. Knepley 
5073e5e52638SMatthew G. Knepley   Input Parameter:
5074bb7acecfSBarry Smith . dm - The `DM`
5075e5e52638SMatthew G. Knepley 
5076e5e52638SMatthew G. Knepley   Output Parameter:
5077bb7acecfSBarry Smith . newdm - The `DM`
5078e5e52638SMatthew G. Knepley 
5079e5e52638SMatthew G. Knepley   Level: advanced
5080e5e52638SMatthew G. Knepley 
5081db781477SPatrick Sanan .seealso: `DMGetField()`, `DMSetField()`, `DMAddField()`, `DMCopyDS()`, `DMGetDS()`, `DMGetCellDS()`
5082e5e52638SMatthew G. Knepley @*/
5083d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyFields(DM dm, DM newdm)
5084d71ae5a4SJacob Faibussowitsch {
5085e5e52638SMatthew G. Knepley   PetscInt Nf, f;
5086e5e52638SMatthew G. Knepley 
5087e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5088e5e52638SMatthew G. Knepley   if (dm == newdm) PetscFunctionReturn(0);
50899566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
50909566063dSJacob Faibussowitsch   PetscCall(DMClearFields(newdm));
5091e5e52638SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5092e5e52638SMatthew G. Knepley     DMLabel     label;
5093e5e52638SMatthew G. Knepley     PetscObject field;
509434aa8a36SMatthew G. Knepley     PetscBool   useCone, useClosure;
5095e5e52638SMatthew G. Knepley 
50969566063dSJacob Faibussowitsch     PetscCall(DMGetField(dm, f, &label, &field));
50979566063dSJacob Faibussowitsch     PetscCall(DMSetField(newdm, f, label, field));
50989566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, f, &useCone, &useClosure));
50999566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(newdm, f, useCone, useClosure));
510034aa8a36SMatthew G. Knepley   }
510134aa8a36SMatthew G. Knepley   PetscFunctionReturn(0);
510234aa8a36SMatthew G. Knepley }
510334aa8a36SMatthew G. Knepley 
510434aa8a36SMatthew G. Knepley /*@
510534aa8a36SMatthew G. Knepley   DMGetAdjacency - Returns the flags for determining variable influence
510634aa8a36SMatthew G. Knepley 
510734aa8a36SMatthew G. Knepley   Not collective
510834aa8a36SMatthew G. Knepley 
510934aa8a36SMatthew G. Knepley   Input Parameters:
511034aa8a36SMatthew G. Knepley + dm - The DM object
511134aa8a36SMatthew G. Knepley - f  - The field number, or PETSC_DEFAULT for the default adjacency
511234aa8a36SMatthew G. Knepley 
5113d8d19677SJose E. Roman   Output Parameters:
511434aa8a36SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
511534aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
511634aa8a36SMatthew G. Knepley 
511734aa8a36SMatthew G. Knepley   Notes:
511834aa8a36SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
511934aa8a36SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
512034aa8a36SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
5121979e053dSMatthew G. Knepley   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
512234aa8a36SMatthew G. Knepley 
512334aa8a36SMatthew G. Knepley   Level: developer
512434aa8a36SMatthew G. Knepley 
5125db781477SPatrick Sanan .seealso: `DMSetAdjacency()`, `DMGetField()`, `DMSetField()`
512634aa8a36SMatthew G. Knepley @*/
5127d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure)
5128d71ae5a4SJacob Faibussowitsch {
512934aa8a36SMatthew G. Knepley   PetscFunctionBegin;
513034aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5131534a8f05SLisandro Dalcin   if (useCone) PetscValidBoolPointer(useCone, 3);
5132534a8f05SLisandro Dalcin   if (useClosure) PetscValidBoolPointer(useClosure, 4);
513334aa8a36SMatthew G. Knepley   if (f < 0) {
513434aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->adjacency[0];
513534aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->adjacency[1];
513634aa8a36SMatthew G. Knepley   } else {
513734aa8a36SMatthew G. Knepley     PetscInt Nf;
513834aa8a36SMatthew G. Knepley 
51399566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
51407a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
514134aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->fields[f].adjacency[0];
514234aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->fields[f].adjacency[1];
514334aa8a36SMatthew G. Knepley   }
514434aa8a36SMatthew G. Knepley   PetscFunctionReturn(0);
514534aa8a36SMatthew G. Knepley }
514634aa8a36SMatthew G. Knepley 
514734aa8a36SMatthew G. Knepley /*@
514834aa8a36SMatthew G. Knepley   DMSetAdjacency - Set the flags for determining variable influence
514934aa8a36SMatthew G. Knepley 
515034aa8a36SMatthew G. Knepley   Not collective
515134aa8a36SMatthew G. Knepley 
515234aa8a36SMatthew G. Knepley   Input Parameters:
515334aa8a36SMatthew G. Knepley + dm         - The DM object
515434aa8a36SMatthew G. Knepley . f          - The field number
515534aa8a36SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
515634aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
515734aa8a36SMatthew G. Knepley 
515834aa8a36SMatthew G. Knepley   Notes:
515934aa8a36SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
516034aa8a36SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
516134aa8a36SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
5162979e053dSMatthew G. Knepley   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
516334aa8a36SMatthew G. Knepley 
516434aa8a36SMatthew G. Knepley   Level: developer
516534aa8a36SMatthew G. Knepley 
5166db781477SPatrick Sanan .seealso: `DMGetAdjacency()`, `DMGetField()`, `DMSetField()`
516734aa8a36SMatthew G. Knepley @*/
5168d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure)
5169d71ae5a4SJacob Faibussowitsch {
517034aa8a36SMatthew G. Knepley   PetscFunctionBegin;
517134aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
517234aa8a36SMatthew G. Knepley   if (f < 0) {
517334aa8a36SMatthew G. Knepley     dm->adjacency[0] = useCone;
517434aa8a36SMatthew G. Knepley     dm->adjacency[1] = useClosure;
517534aa8a36SMatthew G. Knepley   } else {
517634aa8a36SMatthew G. Knepley     PetscInt Nf;
517734aa8a36SMatthew G. Knepley 
51789566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
51797a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
518034aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[0] = useCone;
518134aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[1] = useClosure;
5182e5e52638SMatthew G. Knepley   }
5183e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5184e5e52638SMatthew G. Knepley }
5185e5e52638SMatthew G. Knepley 
5186b0441da4SMatthew G. Knepley /*@
5187b0441da4SMatthew G. Knepley   DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined
5188b0441da4SMatthew G. Knepley 
5189b0441da4SMatthew G. Knepley   Not collective
5190b0441da4SMatthew G. Knepley 
5191f899ff85SJose E. Roman   Input Parameter:
5192b0441da4SMatthew G. Knepley . dm - The DM object
5193b0441da4SMatthew G. Knepley 
5194d8d19677SJose E. Roman   Output Parameters:
5195b0441da4SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
5196b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5197b0441da4SMatthew G. Knepley 
5198b0441da4SMatthew G. Knepley   Notes:
5199b0441da4SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
5200b0441da4SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
5201b0441da4SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
5202b0441da4SMatthew G. Knepley 
5203b0441da4SMatthew G. Knepley   Level: developer
5204b0441da4SMatthew G. Knepley 
5205db781477SPatrick Sanan .seealso: `DMSetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5206b0441da4SMatthew G. Knepley @*/
5207d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure)
5208d71ae5a4SJacob Faibussowitsch {
5209b0441da4SMatthew G. Knepley   PetscInt Nf;
5210b0441da4SMatthew G. Knepley 
5211b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5212b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5213064a246eSJacob Faibussowitsch   if (useCone) PetscValidBoolPointer(useCone, 2);
5214064a246eSJacob Faibussowitsch   if (useClosure) PetscValidBoolPointer(useClosure, 3);
52159566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5216b0441da4SMatthew G. Knepley   if (!Nf) {
52179566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5218b0441da4SMatthew G. Knepley   } else {
52199566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, 0, useCone, useClosure));
5220b0441da4SMatthew G. Knepley   }
5221b0441da4SMatthew G. Knepley   PetscFunctionReturn(0);
5222b0441da4SMatthew G. Knepley }
5223b0441da4SMatthew G. Knepley 
5224b0441da4SMatthew G. Knepley /*@
5225b0441da4SMatthew G. Knepley   DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined
5226b0441da4SMatthew G. Knepley 
5227b0441da4SMatthew G. Knepley   Not collective
5228b0441da4SMatthew G. Knepley 
5229b0441da4SMatthew G. Knepley   Input Parameters:
5230b0441da4SMatthew G. Knepley + dm         - The DM object
5231b0441da4SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
5232b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5233b0441da4SMatthew G. Knepley 
5234b0441da4SMatthew G. Knepley   Notes:
5235b0441da4SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
5236b0441da4SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
5237b0441da4SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
5238b0441da4SMatthew G. Knepley 
5239b0441da4SMatthew G. Knepley   Level: developer
5240b0441da4SMatthew G. Knepley 
5241db781477SPatrick Sanan .seealso: `DMGetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5242b0441da4SMatthew G. Knepley @*/
5243d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure)
5244d71ae5a4SJacob Faibussowitsch {
5245b0441da4SMatthew G. Knepley   PetscInt Nf;
5246b0441da4SMatthew G. Knepley 
5247b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5248b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52499566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5250b0441da4SMatthew G. Knepley   if (!Nf) {
52519566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5252b0441da4SMatthew G. Knepley   } else {
52539566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, 0, useCone, useClosure));
5254e5e52638SMatthew G. Knepley   }
5255e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5256e5e52638SMatthew G. Knepley }
5257e5e52638SMatthew G. Knepley 
5258d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompleteBCLabels_Internal(DM dm)
5259d71ae5a4SJacob Faibussowitsch {
5260799db056SMatthew G. Knepley   DM           plex;
5261799db056SMatthew G. Knepley   DMLabel     *labels, *glabels;
5262799db056SMatthew G. Knepley   const char **names;
5263799db056SMatthew G. Knepley   char        *sendNames, *recvNames;
5264799db056SMatthew G. Knepley   PetscInt     Nds, s, maxLabels = 0, maxLen = 0, gmaxLen, Nl = 0, gNl, l, gl, m;
5265799db056SMatthew G. Knepley   size_t       len;
5266799db056SMatthew G. Knepley   MPI_Comm     comm;
5267799db056SMatthew G. Knepley   PetscMPIInt  rank, size, p, *counts, *displs;
5268783e2ec8SMatthew G. Knepley 
5269783e2ec8SMatthew G. Knepley   PetscFunctionBegin;
5270799db056SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5271799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
5272799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5273799db056SMatthew G. Knepley   PetscCall(DMGetNumDS(dm, &Nds));
5274799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5275799db056SMatthew G. Knepley     PetscDS  dsBC;
5276799db056SMatthew G. Knepley     PetscInt numBd;
5277799db056SMatthew G. Knepley 
5278799db056SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC));
5279799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5280799db056SMatthew G. Knepley     maxLabels += numBd;
5281799db056SMatthew G. Knepley   }
5282799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(maxLabels, &labels));
5283799db056SMatthew G. Knepley   /* Get list of labels to be completed */
5284799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5285799db056SMatthew G. Knepley     PetscDS  dsBC;
5286799db056SMatthew G. Knepley     PetscInt numBd, bd;
5287799db056SMatthew G. Knepley 
5288799db056SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC));
5289799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5290799db056SMatthew G. Knepley     for (bd = 0; bd < numBd; ++bd) {
5291799db056SMatthew G. Knepley       DMLabel      label;
5292799db056SMatthew G. Knepley       PetscInt     field;
5293799db056SMatthew G. Knepley       PetscObject  obj;
5294799db056SMatthew G. Knepley       PetscClassId id;
5295799db056SMatthew G. Knepley 
5296799db056SMatthew G. Knepley       PetscCall(PetscDSGetBoundary(dsBC, bd, NULL, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
52979566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, field, NULL, &obj));
52989566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
5299799db056SMatthew G. Knepley       if (!(id == PETSCFE_CLASSID) || !label) continue;
53009371c9d4SSatish Balay       for (l = 0; l < Nl; ++l)
53019371c9d4SSatish Balay         if (labels[l] == label) break;
5302799db056SMatthew G. Knepley       if (l == Nl) labels[Nl++] = label;
5303783e2ec8SMatthew G. Knepley     }
5304799db056SMatthew G. Knepley   }
5305799db056SMatthew G. Knepley   /* Get label names */
5306799db056SMatthew G. Knepley   PetscCall(PetscMalloc1(Nl, &names));
5307799db056SMatthew G. Knepley   for (l = 0; l < Nl; ++l) PetscCall(PetscObjectGetName((PetscObject)labels[l], &names[l]));
53089371c9d4SSatish Balay   for (l = 0; l < Nl; ++l) {
53099371c9d4SSatish Balay     PetscCall(PetscStrlen(names[l], &len));
53109371c9d4SSatish Balay     maxLen = PetscMax(maxLen, (PetscInt)len + 2);
53119371c9d4SSatish Balay   }
5312799db056SMatthew G. Knepley   PetscCall(PetscFree(labels));
5313799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allreduce(&maxLen, &gmaxLen, 1, MPIU_INT, MPI_MAX, comm));
5314799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(Nl * gmaxLen, &sendNames));
5315799db056SMatthew G. Knepley   for (l = 0; l < Nl; ++l) PetscCall(PetscStrcpy(&sendNames[gmaxLen * l], names[l]));
5316799db056SMatthew G. Knepley   PetscCall(PetscFree(names));
5317799db056SMatthew G. Knepley   /* Put all names on all processes */
5318799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(size, &counts, size + 1, &displs));
5319799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgather(&Nl, 1, MPI_INT, counts, 1, MPI_INT, comm));
5320799db056SMatthew G. Knepley   for (p = 0; p < size; ++p) displs[p + 1] = displs[p] + counts[p];
5321799db056SMatthew G. Knepley   gNl = displs[size];
53229371c9d4SSatish Balay   for (p = 0; p < size; ++p) {
53239371c9d4SSatish Balay     counts[p] *= gmaxLen;
53249371c9d4SSatish Balay     displs[p] *= gmaxLen;
53259371c9d4SSatish Balay   }
5326799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(gNl * gmaxLen, &recvNames, gNl, &glabels));
5327799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgatherv(sendNames, counts[rank], MPI_CHAR, recvNames, counts, displs, MPI_CHAR, comm));
5328799db056SMatthew G. Knepley   PetscCall(PetscFree2(counts, displs));
5329799db056SMatthew G. Knepley   PetscCall(PetscFree(sendNames));
5330799db056SMatthew G. Knepley   for (l = 0, gl = 0; l < gNl; ++l) {
5331799db056SMatthew G. Knepley     PetscCall(DMGetLabel(dm, &recvNames[l * gmaxLen], &glabels[gl]));
5332799db056SMatthew G. Knepley     PetscCheck(glabels[gl], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Label %s missing on rank %d", &recvNames[l * gmaxLen], rank);
53339371c9d4SSatish Balay     for (m = 0; m < gl; ++m)
53349371c9d4SSatish Balay       if (glabels[m] == glabels[gl]) continue;
53359566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
5336799db056SMatthew G. Knepley     PetscCall(DMPlexLabelComplete(plex, glabels[gl]));
53379566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5338799db056SMatthew G. Knepley     ++gl;
5339783e2ec8SMatthew G. Knepley   }
5340799db056SMatthew G. Knepley   PetscCall(PetscFree2(recvNames, glabels));
5341783e2ec8SMatthew G. Knepley   PetscFunctionReturn(0);
5342783e2ec8SMatthew G. Knepley }
5343783e2ec8SMatthew G. Knepley 
5344d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew)
5345d71ae5a4SJacob Faibussowitsch {
5346e5e52638SMatthew G. Knepley   DMSpace *tmpd;
5347e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5348e5e52638SMatthew G. Knepley 
5349e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5350e5e52638SMatthew G. Knepley   if (Nds >= NdsNew) PetscFunctionReturn(0);
53519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NdsNew, &tmpd));
5352e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s];
53539371c9d4SSatish Balay   for (s = Nds; s < NdsNew; ++s) {
53549371c9d4SSatish Balay     tmpd[s].ds     = NULL;
53559371c9d4SSatish Balay     tmpd[s].label  = NULL;
53569371c9d4SSatish Balay     tmpd[s].fields = NULL;
53579371c9d4SSatish Balay   }
53589566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5359e5e52638SMatthew G. Knepley   dm->Nds   = NdsNew;
5360e5e52638SMatthew G. Knepley   dm->probs = tmpd;
5361e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5362e5e52638SMatthew G. Knepley }
5363e5e52638SMatthew G. Knepley 
5364e5e52638SMatthew G. Knepley /*@
5365e5e52638SMatthew G. Knepley   DMGetNumDS - Get the number of discrete systems in the DM
5366e5e52638SMatthew G. Knepley 
5367e5e52638SMatthew G. Knepley   Not collective
5368e5e52638SMatthew G. Knepley 
5369e5e52638SMatthew G. Knepley   Input Parameter:
5370e5e52638SMatthew G. Knepley . dm - The DM
5371e5e52638SMatthew G. Knepley 
5372e5e52638SMatthew G. Knepley   Output Parameter:
5373e5e52638SMatthew G. Knepley . Nds - The number of PetscDS objects
5374e5e52638SMatthew G. Knepley 
5375e5e52638SMatthew G. Knepley   Level: intermediate
5376e5e52638SMatthew G. Knepley 
5377db781477SPatrick Sanan .seealso: `DMGetDS()`, `DMGetCellDS()`
5378e5e52638SMatthew G. Knepley @*/
5379d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds)
5380d71ae5a4SJacob Faibussowitsch {
5381e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5382e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5383534a8f05SLisandro Dalcin   PetscValidIntPointer(Nds, 2);
5384e5e52638SMatthew G. Knepley   *Nds = dm->Nds;
5385e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5386e5e52638SMatthew G. Knepley }
5387e5e52638SMatthew G. Knepley 
5388e5e52638SMatthew G. Knepley /*@
5389e5e52638SMatthew G. Knepley   DMClearDS - Remove all discrete systems from the DM
5390e5e52638SMatthew G. Knepley 
5391d083f849SBarry Smith   Logically collective on dm
5392e5e52638SMatthew G. Knepley 
5393e5e52638SMatthew G. Knepley   Input Parameter:
5394e5e52638SMatthew G. Knepley . dm - The DM
5395e5e52638SMatthew G. Knepley 
5396e5e52638SMatthew G. Knepley   Level: intermediate
5397e5e52638SMatthew G. Knepley 
5398db781477SPatrick Sanan .seealso: `DMGetNumDS()`, `DMGetDS()`, `DMSetField()`
5399e5e52638SMatthew G. Knepley @*/
5400d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearDS(DM dm)
5401d71ae5a4SJacob Faibussowitsch {
5402e5e52638SMatthew G. Knepley   PetscInt s;
5403e5e52638SMatthew G. Knepley 
5404e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5405e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5406e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
54079566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[s].ds));
54089566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->probs[s].label));
54099566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[s].fields));
5410e5e52638SMatthew G. Knepley   }
54119566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5412e5e52638SMatthew G. Knepley   dm->probs = NULL;
5413e5e52638SMatthew G. Knepley   dm->Nds   = 0;
5414e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5415e5e52638SMatthew G. Knepley }
5416e5e52638SMatthew G. Knepley 
5417e5e52638SMatthew G. Knepley /*@
5418e5e52638SMatthew G. Knepley   DMGetDS - Get the default PetscDS
5419e5e52638SMatthew G. Knepley 
5420e5e52638SMatthew G. Knepley   Not collective
5421e5e52638SMatthew G. Knepley 
5422e5e52638SMatthew G. Knepley   Input Parameter:
5423e5e52638SMatthew G. Knepley . dm    - The DM
5424e5e52638SMatthew G. Knepley 
5425e5e52638SMatthew G. Knepley   Output Parameter:
5426e5e52638SMatthew G. Knepley . prob - The default PetscDS
5427e5e52638SMatthew G. Knepley 
5428e5e52638SMatthew G. Knepley   Level: intermediate
5429e5e52638SMatthew G. Knepley 
5430db781477SPatrick Sanan .seealso: `DMGetCellDS()`, `DMGetRegionDS()`
5431e5e52638SMatthew G. Knepley @*/
5432d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
5433d71ae5a4SJacob Faibussowitsch {
5434e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5435e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5436e5e52638SMatthew G. Knepley   PetscValidPointer(prob, 2);
5437b0143b4dSMatthew G. Knepley   if (dm->Nds <= 0) {
5438b0143b4dSMatthew G. Knepley     PetscDS ds;
5439b0143b4dSMatthew G. Knepley 
54409566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
54419566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, NULL, NULL, ds));
54429566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&ds));
5443b0143b4dSMatthew G. Knepley   }
5444b0143b4dSMatthew G. Knepley   *prob = dm->probs[0].ds;
5445e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5446e5e52638SMatthew G. Knepley }
5447e5e52638SMatthew G. Knepley 
5448e5e52638SMatthew G. Knepley /*@
5449e5e52638SMatthew G. Knepley   DMGetCellDS - Get the PetscDS defined on a given cell
5450e5e52638SMatthew G. Knepley 
5451e5e52638SMatthew G. Knepley   Not collective
5452e5e52638SMatthew G. Knepley 
5453e5e52638SMatthew G. Knepley   Input Parameters:
5454e5e52638SMatthew G. Knepley + dm    - The DM
5455e5e52638SMatthew G. Knepley - point - Cell for the DS
5456e5e52638SMatthew G. Knepley 
5457e5e52638SMatthew G. Knepley   Output Parameter:
5458e5e52638SMatthew G. Knepley . prob - The PetscDS defined on the given cell
5459e5e52638SMatthew G. Knepley 
5460e5e52638SMatthew G. Knepley   Level: developer
5461e5e52638SMatthew G. Knepley 
5462db781477SPatrick Sanan .seealso: `DMGetDS()`, `DMSetRegionDS()`
5463e5e52638SMatthew G. Knepley @*/
5464d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *prob)
5465d71ae5a4SJacob Faibussowitsch {
5466e5e52638SMatthew G. Knepley   PetscDS  probDef = NULL;
5467e5e52638SMatthew G. Knepley   PetscInt s;
5468e5e52638SMatthew G. Knepley 
5469e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5470e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5471e5e52638SMatthew G. Knepley   PetscValidPointer(prob, 3);
547263a3b9bcSJacob Faibussowitsch   PetscCheck(point >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %" PetscInt_FMT, point);
5473e5e52638SMatthew G. Knepley   *prob = NULL;
5474e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5475e5e52638SMatthew G. Knepley     PetscInt val;
5476e5e52638SMatthew G. Knepley 
54779371c9d4SSatish Balay     if (!dm->probs[s].label) {
54789371c9d4SSatish Balay       probDef = dm->probs[s].ds;
54799371c9d4SSatish Balay     } else {
54809566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(dm->probs[s].label, point, &val));
54819371c9d4SSatish Balay       if (val >= 0) {
54829371c9d4SSatish Balay         *prob = dm->probs[s].ds;
54839371c9d4SSatish Balay         break;
54849371c9d4SSatish Balay       }
5485e5e52638SMatthew G. Knepley     }
5486e5e52638SMatthew G. Knepley   }
5487e5e52638SMatthew G. Knepley   if (!*prob) *prob = probDef;
5488e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5489e5e52638SMatthew G. Knepley }
5490e5e52638SMatthew G. Knepley 
5491e5e52638SMatthew G. Knepley /*@
5492e5e52638SMatthew G. Knepley   DMGetRegionDS - Get the PetscDS for a given mesh region, defined by a DMLabel
5493e5e52638SMatthew G. Knepley 
5494e5e52638SMatthew G. Knepley   Not collective
5495e5e52638SMatthew G. Knepley 
5496e5e52638SMatthew G. Knepley   Input Parameters:
5497e5e52638SMatthew G. Knepley + dm    - The DM
5498e5e52638SMatthew G. Knepley - label - The DMLabel defining the mesh region, or NULL for the entire mesh
5499e5e52638SMatthew G. Knepley 
5500b3cf3223SMatthew G. Knepley   Output Parameters:
5501b3cf3223SMatthew G. Knepley + fields - The IS containing the DM field numbers for the fields in this DS, or NULL
5502b3cf3223SMatthew G. Knepley - prob - The PetscDS defined on the given region, or NULL
5503e5e52638SMatthew G. Knepley 
5504154ca461SJed Brown   Note:
5505154ca461SJed Brown   If a non-NULL label is given, but there is no PetscDS on that specific label,
5506154ca461SJed Brown   the PetscDS for the full domain (if present) is returned. Returns with
5507154ca461SJed Brown   fields=NULL and prob=NULL if there is no PetscDS for the full domain.
5508e5e52638SMatthew G. Knepley 
5509e5e52638SMatthew G. Knepley   Level: advanced
5510e5e52638SMatthew G. Knepley 
5511db781477SPatrick Sanan .seealso: `DMGetRegionNumDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5512e5e52638SMatthew G. Knepley @*/
5513d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds)
5514d71ae5a4SJacob Faibussowitsch {
5515e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5516e5e52638SMatthew G. Knepley 
5517e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5518e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5519e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
55209371c9d4SSatish Balay   if (fields) {
55219371c9d4SSatish Balay     PetscValidPointer(fields, 3);
55229371c9d4SSatish Balay     *fields = NULL;
55239371c9d4SSatish Balay   }
55249371c9d4SSatish Balay   if (ds) {
55259371c9d4SSatish Balay     PetscValidPointer(ds, 4);
55269371c9d4SSatish Balay     *ds = NULL;
55279371c9d4SSatish Balay   }
5528e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5529154ca461SJed Brown     if (dm->probs[s].label == label || !dm->probs[s].label) {
5530b3cf3223SMatthew G. Knepley       if (fields) *fields = dm->probs[s].fields;
5531b3cf3223SMatthew G. Knepley       if (ds) *ds = dm->probs[s].ds;
5532154ca461SJed Brown       if (dm->probs[s].label) PetscFunctionReturn(0);
5533b3cf3223SMatthew G. Knepley     }
5534e5e52638SMatthew G. Knepley   }
55352df9ee95SMatthew G. Knepley   PetscFunctionReturn(0);
5536e5e52638SMatthew G. Knepley }
5537e5e52638SMatthew G. Knepley 
5538e5e52638SMatthew G. Knepley /*@
5539bb7acecfSBarry Smith   DMSetRegionDS - Set the `PetscDS` for a given mesh region, defined by a `DMLabel`
5540083401c6SMatthew G. Knepley 
5541083401c6SMatthew G. Knepley   Collective on dm
5542083401c6SMatthew G. Knepley 
5543083401c6SMatthew G. Knepley   Input Parameters:
5544bb7acecfSBarry Smith + dm     - The `DM`
5545bb7acecfSBarry Smith . label  - The `DMLabel` defining the mesh region, or NULL for the entire mesh
5546bb7acecfSBarry Smith . fields - The IS containing the `DM` field numbers for the fields in this `PetscDS`, or NULL for all fields
5547bb7acecfSBarry Smith - prob   - The `PetscDS` defined on the given region
5548083401c6SMatthew G. Knepley 
5549bb7acecfSBarry Smith   Note:
5550bb7acecfSBarry 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,
5551083401c6SMatthew G. Knepley   the fields argument is ignored.
5552083401c6SMatthew G. Knepley 
5553083401c6SMatthew G. Knepley   Level: advanced
5554083401c6SMatthew G. Knepley 
5555db781477SPatrick Sanan .seealso: `DMGetRegionDS()`, `DMSetRegionNumDS()`, `DMGetDS()`, `DMGetCellDS()`
5556083401c6SMatthew G. Knepley @*/
5557d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds)
5558d71ae5a4SJacob Faibussowitsch {
5559083401c6SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5560083401c6SMatthew G. Knepley 
5561083401c6SMatthew G. Knepley   PetscFunctionBegin;
5562083401c6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5563083401c6SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
5564064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 4);
5565083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5566083401c6SMatthew G. Knepley     if (dm->probs[s].label == label) {
55679566063dSJacob Faibussowitsch       PetscCall(PetscDSDestroy(&dm->probs[s].ds));
5568083401c6SMatthew G. Knepley       dm->probs[s].ds = ds;
5569083401c6SMatthew G. Knepley       PetscFunctionReturn(0);
5570083401c6SMatthew G. Knepley     }
5571083401c6SMatthew G. Knepley   }
55729566063dSJacob Faibussowitsch   PetscCall(DMDSEnlarge_Static(dm, Nds + 1));
55739566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
55749566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fields));
55759566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ds));
5576083401c6SMatthew G. Knepley   if (!label) {
5577083401c6SMatthew G. Knepley     /* Put the NULL label at the front, so it is returned as the default */
5578083401c6SMatthew G. Knepley     for (s = Nds - 1; s >= 0; --s) dm->probs[s + 1] = dm->probs[s];
5579083401c6SMatthew G. Knepley     Nds = 0;
5580083401c6SMatthew G. Knepley   }
5581083401c6SMatthew G. Knepley   dm->probs[Nds].label  = label;
5582083401c6SMatthew G. Knepley   dm->probs[Nds].fields = fields;
5583083401c6SMatthew G. Knepley   dm->probs[Nds].ds     = ds;
5584083401c6SMatthew G. Knepley   PetscFunctionReturn(0);
5585083401c6SMatthew G. Knepley }
5586083401c6SMatthew G. Knepley 
5587083401c6SMatthew G. Knepley /*@
5588e5e52638SMatthew G. Knepley   DMGetRegionNumDS - Get the PetscDS for a given mesh region, defined by the region number
5589e5e52638SMatthew G. Knepley 
5590e5e52638SMatthew G. Knepley   Not collective
5591e5e52638SMatthew G. Knepley 
5592e5e52638SMatthew G. Knepley   Input Parameters:
5593e5e52638SMatthew G. Knepley + dm  - The DM
5594e5e52638SMatthew G. Knepley - num - The region number, in [0, Nds)
5595e5e52638SMatthew G. Knepley 
5596e5e52638SMatthew G. Knepley   Output Parameters:
5597b3cf3223SMatthew G. Knepley + label  - The region label, or NULL
5598b3cf3223SMatthew G. Knepley . fields - The IS containing the DM field numbers for the fields in this DS, or NULL
5599083401c6SMatthew G. Knepley - ds     - The PetscDS defined on the given region, or NULL
5600e5e52638SMatthew G. Knepley 
5601e5e52638SMatthew G. Knepley   Level: advanced
5602e5e52638SMatthew G. Knepley 
5603db781477SPatrick Sanan .seealso: `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5604e5e52638SMatthew G. Knepley @*/
5605d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds)
5606d71ae5a4SJacob Faibussowitsch {
5607e5e52638SMatthew G. Knepley   PetscInt Nds;
5608e5e52638SMatthew G. Knepley 
5609e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5610e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56119566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
561263a3b9bcSJacob 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);
5613e5e52638SMatthew G. Knepley   if (label) {
5614e5e52638SMatthew G. Knepley     PetscValidPointer(label, 3);
5615e5e52638SMatthew G. Knepley     *label = dm->probs[num].label;
5616e5e52638SMatthew G. Knepley   }
5617b3cf3223SMatthew G. Knepley   if (fields) {
5618b3cf3223SMatthew G. Knepley     PetscValidPointer(fields, 4);
5619b3cf3223SMatthew G. Knepley     *fields = dm->probs[num].fields;
5620b3cf3223SMatthew G. Knepley   }
5621e5e52638SMatthew G. Knepley   if (ds) {
5622b3cf3223SMatthew G. Knepley     PetscValidPointer(ds, 5);
5623e5e52638SMatthew G. Knepley     *ds = dm->probs[num].ds;
5624e5e52638SMatthew G. Knepley   }
5625e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5626e5e52638SMatthew G. Knepley }
5627e5e52638SMatthew G. Knepley 
5628e5e52638SMatthew G. Knepley /*@
5629083401c6SMatthew G. Knepley   DMSetRegionNumDS - Set the PetscDS for a given mesh region, defined by the region number
5630e5e52638SMatthew G. Knepley 
5631083401c6SMatthew G. Knepley   Not collective
5632e5e52638SMatthew G. Knepley 
5633e5e52638SMatthew G. Knepley   Input Parameters:
5634e5e52638SMatthew G. Knepley + dm     - The DM
5635083401c6SMatthew G. Knepley . num    - The region number, in [0, Nds)
5636083401c6SMatthew G. Knepley . label  - The region label, or NULL
5637083401c6SMatthew G. Knepley . fields - The IS containing the DM field numbers for the fields in this DS, or NULL to prevent setting
5638083401c6SMatthew G. Knepley - ds     - The PetscDS defined on the given region, or NULL to prevent setting
5639e5e52638SMatthew G. Knepley 
5640e5e52638SMatthew G. Knepley   Level: advanced
5641e5e52638SMatthew G. Knepley 
5642db781477SPatrick Sanan .seealso: `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5643e5e52638SMatthew G. Knepley @*/
5644d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds)
5645d71ae5a4SJacob Faibussowitsch {
5646083401c6SMatthew G. Knepley   PetscInt Nds;
5647e5e52638SMatthew G. Knepley 
5648e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5649e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5650ad540459SPierre Jolivet   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
56519566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
565263a3b9bcSJacob 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);
56539566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
56549566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->probs[num].label));
5655083401c6SMatthew G. Knepley   dm->probs[num].label = label;
5656083401c6SMatthew G. Knepley   if (fields) {
5657083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(fields, IS_CLASSID, 4);
56589566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)fields));
56599566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[num].fields));
5660083401c6SMatthew G. Knepley     dm->probs[num].fields = fields;
5661e5e52638SMatthew G. Knepley   }
5662083401c6SMatthew G. Knepley   if (ds) {
5663083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 5);
56649566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ds));
56659566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[num].ds));
5666083401c6SMatthew G. Knepley     dm->probs[num].ds = ds;
5667083401c6SMatthew G. Knepley   }
5668e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5669e5e52638SMatthew G. Knepley }
5670e5e52638SMatthew G. Knepley 
5671e5e52638SMatthew G. Knepley /*@
56721d3af9e0SMatthew G. Knepley   DMFindRegionNum - Find the region number for a given PetscDS, or -1 if it is not found.
56731d3af9e0SMatthew G. Knepley 
56741d3af9e0SMatthew G. Knepley   Not collective
56751d3af9e0SMatthew G. Knepley 
56761d3af9e0SMatthew G. Knepley   Input Parameters:
56771d3af9e0SMatthew G. Knepley + dm  - The DM
56781d3af9e0SMatthew G. Knepley - ds  - The PetscDS defined on the given region
56791d3af9e0SMatthew G. Knepley 
56801d3af9e0SMatthew G. Knepley   Output Parameter:
56811d3af9e0SMatthew G. Knepley . num - The region number, in [0, Nds), or -1 if not found
56821d3af9e0SMatthew G. Knepley 
56831d3af9e0SMatthew G. Knepley   Level: advanced
56841d3af9e0SMatthew G. Knepley 
5685db781477SPatrick Sanan .seealso: `DMGetRegionNumDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
56861d3af9e0SMatthew G. Knepley @*/
5687d71ae5a4SJacob Faibussowitsch PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num)
5688d71ae5a4SJacob Faibussowitsch {
56891d3af9e0SMatthew G. Knepley   PetscInt Nds, n;
56901d3af9e0SMatthew G. Knepley 
56911d3af9e0SMatthew G. Knepley   PetscFunctionBegin;
56921d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56931d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 2);
5694dadcf809SJacob Faibussowitsch   PetscValidIntPointer(num, 3);
56959566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
56969371c9d4SSatish Balay   for (n = 0; n < Nds; ++n)
56979371c9d4SSatish Balay     if (ds == dm->probs[n].ds) break;
56981d3af9e0SMatthew G. Knepley   if (n >= Nds) *num = -1;
56991d3af9e0SMatthew G. Knepley   else *num = n;
57001d3af9e0SMatthew G. Knepley   PetscFunctionReturn(0);
57011d3af9e0SMatthew G. Knepley }
57021d3af9e0SMatthew G. Knepley 
57032df84da0SMatthew G. Knepley /*@C
5704bb7acecfSBarry Smith   DMCreateFEDefault - Create a `PetscFE` based on the celltype for the mesh
57052df84da0SMatthew G. Knepley 
57062df84da0SMatthew G. Knepley   Not collective
57072df84da0SMatthew G. Knepley 
5708f1a722f8SMatthew G. Knepley   Input Parameters:
5709bb7acecfSBarry Smith + dm     - The `DM`
57102df84da0SMatthew G. Knepley . Nc     - The number of components for the field
5711bb7acecfSBarry Smith . prefix - The options prefix for the output `PetscFE`, or NULL
5712bb7acecfSBarry Smith - qorder - The quadrature order or `PETSC_DETERMINE` to use `PetscSpace` polynomial degree
57132df84da0SMatthew G. Knepley 
57142df84da0SMatthew G. Knepley   Output Parameter:
5715bb7acecfSBarry Smith . fem - The `PetscFE`
57162df84da0SMatthew G. Knepley 
5717bb7acecfSBarry Smith   Note:
5718bb7acecfSBarry Smith   This is a convenience method that just calls `PetscFECreateByCell()` underneath.
57192df84da0SMatthew G. Knepley 
57202df84da0SMatthew G. Knepley   Level: intermediate
57212df84da0SMatthew G. Knepley 
5722db781477SPatrick Sanan .seealso: `PetscFECreateByCell()`, `DMAddField()`, `DMCreateDS()`, `DMGetCellDS()`, `DMGetRegionDS()`
57232df84da0SMatthew G. Knepley @*/
5724d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFEDefault(DM dm, PetscInt Nc, const char prefix[], PetscInt qorder, PetscFE *fem)
5725d71ae5a4SJacob Faibussowitsch {
57262df84da0SMatthew G. Knepley   DMPolytopeType ct;
57272df84da0SMatthew G. Knepley   PetscInt       dim, cStart;
57282df84da0SMatthew G. Knepley 
57292df84da0SMatthew G. Knepley   PetscFunctionBegin;
57302df84da0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57312df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 2);
57322df84da0SMatthew G. Knepley   if (prefix) PetscValidCharPointer(prefix, 3);
57332df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, qorder, 4);
57342df84da0SMatthew G. Knepley   PetscValidPointer(fem, 5);
57359566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
57369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
57379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
57389566063dSJacob Faibussowitsch   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, Nc, ct, prefix, qorder, fem));
57392df84da0SMatthew G. Knepley   PetscFunctionReturn(0);
57402df84da0SMatthew G. Knepley }
57412df84da0SMatthew G. Knepley 
57421d3af9e0SMatthew G. Knepley /*@
5743bb7acecfSBarry Smith   DMCreateDS - Create the discrete systems for the `DM` based upon the fields added to the `DM`
5744e5e52638SMatthew G. Knepley 
5745d083f849SBarry Smith   Collective on dm
5746e5e52638SMatthew G. Knepley 
5747e5e52638SMatthew G. Knepley   Input Parameter:
5748bb7acecfSBarry Smith . dm - The `DM`
5749e5e52638SMatthew G. Knepley 
575045480ffeSMatthew G. Knepley   Options Database Keys:
5751bb7acecfSBarry Smith . -dm_petscds_view - View all the `PetscDS` objects in this `DM`
575245480ffeSMatthew G. Knepley 
5753bb7acecfSBarry Smith   Note:
5754bb7acecfSBarry Smith   If the label has a `PetscDS` defined, it will be replaced. Otherwise, it will be added to the `DM`.
5755e5e52638SMatthew G. Knepley 
5756e5e52638SMatthew G. Knepley   Level: intermediate
5757e5e52638SMatthew G. Knepley 
5758db781477SPatrick Sanan .seealso: `DMSetField`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
5759e5e52638SMatthew G. Knepley @*/
5760d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDS(DM dm)
5761d71ae5a4SJacob Faibussowitsch {
5762e5e52638SMatthew G. Knepley   MPI_Comm  comm;
5763083401c6SMatthew G. Knepley   PetscDS   dsDef;
5764083401c6SMatthew G. Knepley   DMLabel  *labelSet;
5765f9244615SMatthew G. Knepley   PetscInt  dE, Nf = dm->Nf, f, s, Nl, l, Ndef, k;
5766f9244615SMatthew G. Knepley   PetscBool doSetup = PETSC_TRUE, flg;
5767e5e52638SMatthew G. Knepley 
5768e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5769e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5770e5e52638SMatthew G. Knepley   if (!dm->fields) PetscFunctionReturn(0);
57719566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
57729566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
5773083401c6SMatthew G. Knepley   /* Determine how many regions we have */
57749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(Nf, &labelSet));
5775083401c6SMatthew G. Knepley   Nl   = 0;
5776083401c6SMatthew G. Knepley   Ndef = 0;
5777083401c6SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5778083401c6SMatthew G. Knepley     DMLabel  label = dm->fields[f].label;
5779083401c6SMatthew G. Knepley     PetscInt l;
5780083401c6SMatthew G. Knepley 
5781f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
5782f918ec44SMatthew G. Knepley     /* Move CEED context to discretizations */
5783f918ec44SMatthew G. Knepley     {
5784f918ec44SMatthew G. Knepley       PetscClassId id;
5785f918ec44SMatthew G. Knepley 
57869566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(dm->fields[f].disc, &id));
5787f918ec44SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
5788f918ec44SMatthew G. Knepley         Ceed ceed;
5789f918ec44SMatthew G. Knepley 
57909566063dSJacob Faibussowitsch         PetscCall(DMGetCeed(dm, &ceed));
57919566063dSJacob Faibussowitsch         PetscCall(PetscFESetCeed((PetscFE)dm->fields[f].disc, ceed));
5792f918ec44SMatthew G. Knepley       }
5793f918ec44SMatthew G. Knepley     }
5794f918ec44SMatthew G. Knepley #endif
57959371c9d4SSatish Balay     if (!label) {
57969371c9d4SSatish Balay       ++Ndef;
57979371c9d4SSatish Balay       continue;
57989371c9d4SSatish Balay     }
57999371c9d4SSatish Balay     for (l = 0; l < Nl; ++l)
58009371c9d4SSatish Balay       if (label == labelSet[l]) break;
5801083401c6SMatthew G. Knepley     if (l < Nl) continue;
5802083401c6SMatthew G. Knepley     labelSet[Nl++] = label;
5803083401c6SMatthew G. Knepley   }
5804083401c6SMatthew G. Knepley   /* Create default DS if there are no labels to intersect with */
58059566063dSJacob Faibussowitsch   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef));
5806083401c6SMatthew G. Knepley   if (!dsDef && Ndef && !Nl) {
5807b3cf3223SMatthew G. Knepley     IS        fields;
5808b3cf3223SMatthew G. Knepley     PetscInt *fld, nf;
5809b3cf3223SMatthew G. Knepley 
58109371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58119371c9d4SSatish Balay       if (!dm->fields[f].label) ++nf;
58127a8be351SBarry Smith     PetscCheck(nf, comm, PETSC_ERR_PLIB, "All fields have labels, but we are trying to create a default DS");
58139566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
58149371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58159371c9d4SSatish Balay       if (!dm->fields[f].label) fld[nf++] = f;
58169566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
58179566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
58189566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
58199566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
582088f0c812SMatthew G. Knepley 
58219566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
58229566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, NULL, fields, dsDef));
58239566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
58249566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fields));
58252df9ee95SMatthew G. Knepley   }
58269566063dSJacob Faibussowitsch   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef));
58279566063dSJacob Faibussowitsch   if (dsDef) PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
5828083401c6SMatthew G. Knepley   /* Intersect labels with default fields */
5829083401c6SMatthew G. Knepley   if (Ndef && Nl) {
58300122748bSMatthew G. Knepley     DM              plex;
5831083401c6SMatthew G. Knepley     DMLabel         cellLabel;
5832083401c6SMatthew G. Knepley     IS              fieldIS, allcellIS, defcellIS = NULL;
5833083401c6SMatthew G. Knepley     PetscInt       *fields;
5834083401c6SMatthew G. Knepley     const PetscInt *cells;
5835083401c6SMatthew G. Knepley     PetscInt        depth, nf = 0, n, c;
58360122748bSMatthew G. Knepley 
58379566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
58389566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(plex, &depth));
58399566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(plex, "dim", depth, &allcellIS));
58409566063dSJacob Faibussowitsch     if (!allcellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, &allcellIS));
58415fedec97SMatthew G. Knepley     /* TODO This looks like it only works for one label */
5842083401c6SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
5843083401c6SMatthew G. Knepley       DMLabel label = labelSet[l];
5844083401c6SMatthew G. Knepley       IS      pointIS;
5845083401c6SMatthew G. Knepley 
58469566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&defcellIS));
58479566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(label, 1, &pointIS));
58489566063dSJacob Faibussowitsch       PetscCall(ISDifference(allcellIS, pointIS, &defcellIS));
58499566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pointIS));
5850083401c6SMatthew G. Knepley     }
58519566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&allcellIS));
5852083401c6SMatthew G. Knepley 
58539566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel));
58549566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(defcellIS, &n));
58559566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(defcellIS, &cells));
58569566063dSJacob Faibussowitsch     for (c = 0; c < n; ++c) PetscCall(DMLabelSetValue(cellLabel, cells[c], 1));
58579566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(defcellIS, &cells));
58589566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&defcellIS));
58599566063dSJacob Faibussowitsch     PetscCall(DMPlexLabelComplete(plex, cellLabel));
5860083401c6SMatthew G. Knepley 
58619566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Ndef, &fields));
58629371c9d4SSatish Balay     for (f = 0; f < Nf; ++f)
58639371c9d4SSatish Balay       if (!dm->fields[f].label) fields[nf++] = f;
58649566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fieldIS));
58659566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fieldIS, "dm_fields_"));
58669566063dSJacob Faibussowitsch     PetscCall(ISSetType(fieldIS, ISGENERAL));
58679566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER));
5868083401c6SMatthew G. Knepley 
58699566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
58709566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, cellLabel, fieldIS, dsDef));
58719566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
58729566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&cellLabel));
58739566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
58749566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fieldIS));
58759566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5876083401c6SMatthew G. Knepley   }
5877083401c6SMatthew G. Knepley   /* Create label DSes
5878083401c6SMatthew G. Knepley      - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS
5879083401c6SMatthew G. Knepley   */
5880083401c6SMatthew G. Knepley   /* TODO Should check that labels are disjoint */
5881083401c6SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
5882083401c6SMatthew G. Knepley     DMLabel   label = labelSet[l];
5883083401c6SMatthew G. Knepley     PetscDS   ds;
5884083401c6SMatthew G. Knepley     IS        fields;
5885083401c6SMatthew G. Knepley     PetscInt *fld, nf;
5886083401c6SMatthew G. Knepley 
58879566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
58889371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58899371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) ++nf;
58909566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
58919371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58929371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f;
58939566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
58949566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
58959566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
58969566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
58979566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, label, fields, ds));
58989566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fields));
58999566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(ds, dE));
5900083401c6SMatthew G. Knepley     {
5901083401c6SMatthew G. Knepley       DMPolytopeType ct;
5902083401c6SMatthew G. Knepley       PetscInt       lStart, lEnd;
59035fedec97SMatthew G. Knepley       PetscBool      isCohesiveLocal = PETSC_FALSE, isCohesive;
59040122748bSMatthew G. Knepley 
59059566063dSJacob Faibussowitsch       PetscCall(DMLabelGetBounds(label, &lStart, &lEnd));
5906665f567fSMatthew G. Knepley       if (lStart >= 0) {
59079566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, lStart, &ct));
5908412e9a14SMatthew G. Knepley         switch (ct) {
5909412e9a14SMatthew G. Knepley         case DM_POLYTOPE_POINT_PRISM_TENSOR:
5910412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
5911412e9a14SMatthew G. Knepley         case DM_POLYTOPE_TRI_PRISM_TENSOR:
5912d71ae5a4SJacob Faibussowitsch         case DM_POLYTOPE_QUAD_PRISM_TENSOR:
5913d71ae5a4SJacob Faibussowitsch           isCohesiveLocal = PETSC_TRUE;
5914d71ae5a4SJacob Faibussowitsch           break;
5915d71ae5a4SJacob Faibussowitsch         default:
5916d71ae5a4SJacob Faibussowitsch           break;
5917412e9a14SMatthew G. Knepley         }
5918665f567fSMatthew G. Knepley       }
59199566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allreduce(&isCohesiveLocal, &isCohesive, 1, MPIU_BOOL, MPI_LOR, comm));
59205fedec97SMatthew G. Knepley       for (f = 0, nf = 0; f < Nf; ++f) {
59215fedec97SMatthew G. Knepley         if (label == dm->fields[f].label || !dm->fields[f].label) {
59225fedec97SMatthew G. Knepley           if (label == dm->fields[f].label) {
59239566063dSJacob Faibussowitsch             PetscCall(PetscDSSetDiscretization(ds, nf, NULL));
59249566063dSJacob Faibussowitsch             PetscCall(PetscDSSetCohesive(ds, nf, isCohesive));
59255fedec97SMatthew G. Knepley           }
59265fedec97SMatthew G. Knepley           ++nf;
59275fedec97SMatthew G. Knepley         }
59285fedec97SMatthew G. Knepley       }
5929e5e52638SMatthew G. Knepley     }
59309566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&ds));
5931e5e52638SMatthew G. Knepley   }
59329566063dSJacob Faibussowitsch   PetscCall(PetscFree(labelSet));
5933e5e52638SMatthew G. Knepley   /* Set fields in DSes */
5934083401c6SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5935083401c6SMatthew G. Knepley     PetscDS         ds     = dm->probs[s].ds;
5936083401c6SMatthew G. Knepley     IS              fields = dm->probs[s].fields;
5937083401c6SMatthew G. Knepley     const PetscInt *fld;
59385fedec97SMatthew G. Knepley     PetscInt        nf, dsnf;
59395fedec97SMatthew G. Knepley     PetscBool       isCohesive;
5940e5e52638SMatthew G. Knepley 
59419566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsnf));
59429566063dSJacob Faibussowitsch     PetscCall(PetscDSIsCohesive(ds, &isCohesive));
59439566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(fields, &nf));
59449566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fields, &fld));
5945083401c6SMatthew G. Knepley     for (f = 0; f < nf; ++f) {
5946083401c6SMatthew G. Knepley       PetscObject  disc = dm->fields[fld[f]].disc;
59475fedec97SMatthew G. Knepley       PetscBool    isCohesiveField;
5948e5e52638SMatthew G. Knepley       PetscClassId id;
5949e5e52638SMatthew G. Knepley 
59505fedec97SMatthew G. Knepley       /* Handle DS with no fields */
59519566063dSJacob Faibussowitsch       if (dsnf) PetscCall(PetscDSGetCohesive(ds, f, &isCohesiveField));
59525fedec97SMatthew G. Knepley       /* If this is a cohesive cell, then regular fields need the lower dimensional discretization */
59539566063dSJacob Faibussowitsch       if (isCohesive && !isCohesiveField) PetscCall(PetscFEGetHeightSubspace((PetscFE)disc, 1, (PetscFE *)&disc));
59549566063dSJacob Faibussowitsch       PetscCall(PetscDSSetDiscretization(ds, f, disc));
5955083401c6SMatthew G. Knepley       /* We allow people to have placeholder fields and construct the Section by hand */
59569566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(disc, &id));
5957e5e52638SMatthew G. Knepley       if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE;
5958e5e52638SMatthew G. Knepley     }
59599566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fields, &fld));
5960e5e52638SMatthew G. Knepley   }
5961f9244615SMatthew G. Knepley   /* Allow k-jet tabulation */
59629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)dm)->prefix, "-dm_ds_jet_degree", &k, &flg));
5963f9244615SMatthew G. Knepley   if (flg) {
59643b4aee56SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
59653b4aee56SMatthew G. Knepley       PetscDS  ds = dm->probs[s].ds;
59663b4aee56SMatthew G. Knepley       PetscInt Nf, f;
59673b4aee56SMatthew G. Knepley 
59689566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(ds, &Nf));
59699566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSSetJetDegree(ds, f, k));
59703b4aee56SMatthew G. Knepley     }
5971f9244615SMatthew G. Knepley   }
5972e5e52638SMatthew G. Knepley   /* Setup DSes */
5973e5e52638SMatthew G. Knepley   if (doSetup) {
59749566063dSJacob Faibussowitsch     for (s = 0; s < dm->Nds; ++s) PetscCall(PetscDSSetUp(dm->probs[s].ds));
5975e5e52638SMatthew G. Knepley   }
5976e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5977e5e52638SMatthew G. Knepley }
5978e5e52638SMatthew G. Knepley 
5979e5e52638SMatthew G. Knepley /*@
5980bb7acecfSBarry Smith   DMComputeExactSolution - Compute the exact solution for a given `DM`, using the `PetscDS` information.
59817f96f943SMatthew G. Knepley 
5982bb7acecfSBarry Smith   Collective on `DM`
5983f2cacb80SMatthew G. Knepley 
59847f96f943SMatthew G. Knepley   Input Parameters:
5985bb7acecfSBarry Smith + dm   - The `DM`
59867f96f943SMatthew G. Knepley - time - The time
59877f96f943SMatthew G. Knepley 
59887f96f943SMatthew G. Knepley   Output Parameters:
5989f2cacb80SMatthew G. Knepley + u    - The vector will be filled with exact solution values, or NULL
5990f2cacb80SMatthew G. Knepley - u_t  - The vector will be filled with the time derivative of exact solution values, or NULL
59917f96f943SMatthew G. Knepley 
5992bb7acecfSBarry Smith   Note:
5993bb7acecfSBarry Smith   The user must call `PetscDSSetExactSolution()` before using this routine
59947f96f943SMatthew G. Knepley 
59957f96f943SMatthew G. Knepley   Level: developer
59967f96f943SMatthew G. Knepley 
5997db781477SPatrick Sanan .seealso: `PetscDSSetExactSolution()`
59987f96f943SMatthew G. Knepley @*/
5999d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t)
6000d71ae5a4SJacob Faibussowitsch {
60017f96f943SMatthew G. Knepley   PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
60027f96f943SMatthew G. Knepley   void   **ectxs;
60037f96f943SMatthew G. Knepley   PetscInt Nf, Nds, s;
60047f96f943SMatthew G. Knepley 
60057f96f943SMatthew G. Knepley   PetscFunctionBegin;
6006f2cacb80SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6007f2cacb80SMatthew G. Knepley   if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
6008f2cacb80SMatthew G. Knepley   if (u_t) PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4);
60099566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
60109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(Nf, &exacts, Nf, &ectxs));
60119566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
60127f96f943SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
60137f96f943SMatthew G. Knepley     PetscDS         ds;
60147f96f943SMatthew G. Knepley     DMLabel         label;
60157f96f943SMatthew G. Knepley     IS              fieldIS;
60167f96f943SMatthew G. Knepley     const PetscInt *fields, id = 1;
60177f96f943SMatthew G. Knepley     PetscInt        dsNf, f;
60187f96f943SMatthew G. Knepley 
60199566063dSJacob Faibussowitsch     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds));
60209566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
60219566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fieldIS, &fields));
60229566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(exacts, Nf));
60239566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(ectxs, Nf));
6024f2cacb80SMatthew G. Knepley     if (u) {
60257f96f943SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) {
60267f96f943SMatthew G. Knepley         const PetscInt field = fields[f];
60279566063dSJacob Faibussowitsch         PetscCall(PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]));
60287f96f943SMatthew G. Knepley       }
60299566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(fieldIS, &fields));
60307f96f943SMatthew G. Knepley       if (label) {
60319566063dSJacob Faibussowitsch         PetscCall(DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u));
60327f96f943SMatthew G. Knepley       } else {
60339566063dSJacob Faibussowitsch         PetscCall(DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u));
60347f96f943SMatthew G. Knepley       }
60357f96f943SMatthew G. Knepley     }
6036f2cacb80SMatthew G. Knepley     if (u_t) {
60379566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(exacts, Nf));
60389566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ectxs, Nf));
6039f2cacb80SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) {
6040f2cacb80SMatthew G. Knepley         const PetscInt field = fields[f];
60419566063dSJacob Faibussowitsch         PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, field, &exacts[field], &ectxs[field]));
6042f2cacb80SMatthew G. Knepley       }
60439566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(fieldIS, &fields));
6044f2cacb80SMatthew G. Knepley       if (label) {
60459566063dSJacob Faibussowitsch         PetscCall(DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u_t));
6046f2cacb80SMatthew G. Knepley       } else {
60479566063dSJacob Faibussowitsch         PetscCall(DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u_t));
6048f2cacb80SMatthew G. Knepley       }
6049f2cacb80SMatthew G. Knepley     }
6050f2cacb80SMatthew G. Knepley   }
6051f2cacb80SMatthew G. Knepley   if (u) {
60529566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution"));
60539566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u, "exact_"));
6054f2cacb80SMatthew G. Knepley   }
6055f2cacb80SMatthew G. Knepley   if (u_t) {
60569566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution Time Derivative"));
60579566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u_t, "exact_t_"));
6058f2cacb80SMatthew G. Knepley   }
60599566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exacts, ectxs));
60607f96f943SMatthew G. Knepley   PetscFunctionReturn(0);
60617f96f943SMatthew G. Knepley }
60627f96f943SMatthew G. Knepley 
6063d71ae5a4SJacob Faibussowitsch PetscErrorCode DMTransferDS_Internal(DM dm, DMLabel label, IS fields, PetscDS ds)
6064d71ae5a4SJacob Faibussowitsch {
606545480ffeSMatthew G. Knepley   PetscDS    dsNew;
606645480ffeSMatthew G. Knepley   DSBoundary b;
60676a02485aSMatthew G. Knepley   PetscInt   cdim, Nf, f, d;
60685fedec97SMatthew G. Knepley   PetscBool  isCohesive;
606945480ffeSMatthew G. Knepley   void      *ctx;
607045480ffeSMatthew G. Knepley 
607145480ffeSMatthew G. Knepley   PetscFunctionBegin;
60729566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)ds), &dsNew));
60739566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyConstants(ds, dsNew));
60749566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyExactSolutions(ds, dsNew));
60759566063dSJacob Faibussowitsch   PetscCall(PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, dsNew));
60769566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyEquations(ds, dsNew));
60779566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
607845480ffeSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
60799566063dSJacob Faibussowitsch     PetscCall(PetscDSGetContext(ds, f, &ctx));
60809566063dSJacob Faibussowitsch     PetscCall(PetscDSSetContext(dsNew, f, ctx));
60819566063dSJacob Faibussowitsch     PetscCall(PetscDSGetCohesive(ds, f, &isCohesive));
60829566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCohesive(dsNew, f, isCohesive));
60836a02485aSMatthew G. Knepley     PetscCall(PetscDSGetJetDegree(ds, f, &d));
60846a02485aSMatthew G. Knepley     PetscCall(PetscDSSetJetDegree(dsNew, f, d));
608545480ffeSMatthew G. Knepley   }
608645480ffeSMatthew G. Knepley   if (Nf) {
60879566063dSJacob Faibussowitsch     PetscCall(PetscDSGetCoordinateDimension(ds, &cdim));
60889566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(dsNew, cdim));
608945480ffeSMatthew G. Knepley   }
60909566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew));
609145480ffeSMatthew G. Knepley   for (b = dsNew->boundary; b; b = b->next) {
60929566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, b->lname, &b->label));
609345480ffeSMatthew G. Knepley     /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */
60947a8be351SBarry Smith     //PetscCheck(b->label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name);
609545480ffeSMatthew G. Knepley   }
609645480ffeSMatthew G. Knepley 
60979566063dSJacob Faibussowitsch   PetscCall(DMSetRegionDS(dm, label, fields, dsNew));
60989566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&dsNew));
609945480ffeSMatthew G. Knepley   PetscFunctionReturn(0);
610045480ffeSMatthew G. Knepley }
610145480ffeSMatthew G. Knepley 
61027f96f943SMatthew G. Knepley /*@
6103bb7acecfSBarry Smith   DMCopyDS - Copy the discrete systems for the `DM` into another `DM`
6104e5e52638SMatthew G. Knepley 
6105d083f849SBarry Smith   Collective on dm
6106e5e52638SMatthew G. Knepley 
6107e5e52638SMatthew G. Knepley   Input Parameter:
6108bb7acecfSBarry Smith . dm - The `DM`
6109e5e52638SMatthew G. Knepley 
6110e5e52638SMatthew G. Knepley   Output Parameter:
6111bb7acecfSBarry Smith . newdm - The `DM`
6112e5e52638SMatthew G. Knepley 
6113e5e52638SMatthew G. Knepley   Level: advanced
6114e5e52638SMatthew G. Knepley 
6115db781477SPatrick Sanan .seealso: `DMCopyFields()`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
6116e5e52638SMatthew G. Knepley @*/
6117d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDS(DM dm, DM newdm)
6118d71ae5a4SJacob Faibussowitsch {
6119e5e52638SMatthew G. Knepley   PetscInt Nds, s;
6120e5e52638SMatthew G. Knepley 
6121e5e52638SMatthew G. Knepley   PetscFunctionBegin;
6122e5e52638SMatthew G. Knepley   if (dm == newdm) PetscFunctionReturn(0);
61239566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
61249566063dSJacob Faibussowitsch   PetscCall(DMClearDS(newdm));
6125e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
6126e5e52638SMatthew G. Knepley     DMLabel  label;
6127b3cf3223SMatthew G. Knepley     IS       fields;
612845480ffeSMatthew G. Knepley     PetscDS  ds, newds;
6129783e2ec8SMatthew G. Knepley     PetscInt Nbd, bd;
6130e5e52638SMatthew G. Knepley 
61319566063dSJacob Faibussowitsch     PetscCall(DMGetRegionNumDS(dm, s, &label, &fields, &ds));
6132b8025e53SMatthew G. Knepley     /* TODO: We need to change all keys from labels in the old DM to labels in the new DM */
61339566063dSJacob Faibussowitsch     PetscCall(DMTransferDS_Internal(newdm, label, fields, ds));
613445480ffeSMatthew G. Knepley     /* Commplete new labels in the new DS */
61359566063dSJacob Faibussowitsch     PetscCall(DMGetRegionDS(newdm, label, NULL, &newds));
61369566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumBoundary(newds, &Nbd));
6137783e2ec8SMatthew G. Knepley     for (bd = 0; bd < Nbd; ++bd) {
6138b8025e53SMatthew G. Knepley       PetscWeakForm wf;
613945480ffeSMatthew G. Knepley       DMLabel       label;
6140783e2ec8SMatthew G. Knepley       PetscInt      field;
6141783e2ec8SMatthew G. Knepley 
61429566063dSJacob Faibussowitsch       PetscCall(PetscDSGetBoundary(newds, bd, &wf, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
61439566063dSJacob Faibussowitsch       PetscCall(PetscWeakFormReplaceLabel(wf, label));
6144783e2ec8SMatthew G. Knepley     }
6145e5e52638SMatthew G. Knepley   }
6146799db056SMatthew G. Knepley   PetscCall(DMCompleteBCLabels_Internal(newdm));
6147e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
6148e5e52638SMatthew G. Knepley }
6149e5e52638SMatthew G. Knepley 
6150e5e52638SMatthew G. Knepley /*@
6151bb7acecfSBarry Smith   DMCopyDisc - Copy the fields and discrete systems for the `DM` into another `DM`
6152e5e52638SMatthew G. Knepley 
6153d083f849SBarry Smith   Collective on dm
6154e5e52638SMatthew G. Knepley 
6155e5e52638SMatthew G. Knepley   Input Parameter:
6156bb7acecfSBarry Smith . dm - The `DM`
6157e5e52638SMatthew G. Knepley 
6158e5e52638SMatthew G. Knepley   Output Parameter:
6159bb7acecfSBarry Smith . newdm - The `DM`
6160e5e52638SMatthew G. Knepley 
6161e5e52638SMatthew G. Knepley   Level: advanced
6162e5e52638SMatthew G. Knepley 
6163bb7acecfSBarry Smith   Developer Note:
6164bb7acecfSBarry Smith   Really ugly name, nothing in PETSc is called a `Disc` plus it is an ugly abbreviation
6165bb7acecfSBarry Smith 
6166db781477SPatrick Sanan .seealso: `DMCopyFields()`, `DMCopyDS()`
6167e5e52638SMatthew G. Knepley @*/
6168d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDisc(DM dm, DM newdm)
6169d71ae5a4SJacob Faibussowitsch {
6170e5e52638SMatthew G. Knepley   PetscFunctionBegin;
61719566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, newdm));
61729566063dSJacob Faibussowitsch   PetscCall(DMCopyDS(dm, newdm));
6173e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
6174e5e52638SMatthew G. Knepley }
6175e5e52638SMatthew G. Knepley 
6176c73cfb54SMatthew G. Knepley /*@
6177bb7acecfSBarry Smith   DMGetDimension - Return the topological dimension of the `DM`
6178c73cfb54SMatthew G. Knepley 
6179c73cfb54SMatthew G. Knepley   Not collective
6180c73cfb54SMatthew G. Knepley 
6181c73cfb54SMatthew G. Knepley   Input Parameter:
6182bb7acecfSBarry Smith . dm - The `DM`
6183c73cfb54SMatthew G. Knepley 
6184c73cfb54SMatthew G. Knepley   Output Parameter:
6185c73cfb54SMatthew G. Knepley . dim - The topological dimension
6186c73cfb54SMatthew G. Knepley 
6187c73cfb54SMatthew G. Knepley   Level: beginner
6188c73cfb54SMatthew G. Knepley 
6189db781477SPatrick Sanan .seealso: `DMSetDimension()`, `DMCreate()`
6190c73cfb54SMatthew G. Knepley @*/
6191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
6192d71ae5a4SJacob Faibussowitsch {
6193c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6194c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6195534a8f05SLisandro Dalcin   PetscValidIntPointer(dim, 2);
6196c73cfb54SMatthew G. Knepley   *dim = dm->dim;
6197c73cfb54SMatthew G. Knepley   PetscFunctionReturn(0);
6198c73cfb54SMatthew G. Knepley }
6199c73cfb54SMatthew G. Knepley 
6200c73cfb54SMatthew G. Knepley /*@
6201bb7acecfSBarry Smith   DMSetDimension - Set the topological dimension of the `DM`
6202c73cfb54SMatthew G. Knepley 
6203c73cfb54SMatthew G. Knepley   Collective on dm
6204c73cfb54SMatthew G. Knepley 
6205c73cfb54SMatthew G. Knepley   Input Parameters:
6206bb7acecfSBarry Smith + dm - The `DM`
6207c73cfb54SMatthew G. Knepley - dim - The topological dimension
6208c73cfb54SMatthew G. Knepley 
6209c73cfb54SMatthew G. Knepley   Level: beginner
6210c73cfb54SMatthew G. Knepley 
6211db781477SPatrick Sanan .seealso: `DMGetDimension()`, `DMCreate()`
6212c73cfb54SMatthew G. Knepley @*/
6213d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
6214d71ae5a4SJacob Faibussowitsch {
6215e5e52638SMatthew G. Knepley   PetscDS  ds;
621645480ffeSMatthew G. Knepley   PetscInt Nds, n;
6217f17e8794SMatthew G. Knepley 
6218c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6219c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6220c73cfb54SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6221c73cfb54SMatthew G. Knepley   dm->dim = dim;
6222d17bd122SMatthew G. Knepley   if (dm->dim >= 0) {
62239566063dSJacob Faibussowitsch     PetscCall(DMGetNumDS(dm, &Nds));
622445480ffeSMatthew G. Knepley     for (n = 0; n < Nds; ++n) {
62259566063dSJacob Faibussowitsch       PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds));
62269566063dSJacob Faibussowitsch       if (ds->dimEmbed < 0) PetscCall(PetscDSSetCoordinateDimension(ds, dim));
622745480ffeSMatthew G. Knepley     }
6228d17bd122SMatthew G. Knepley   }
6229c73cfb54SMatthew G. Knepley   PetscFunctionReturn(0);
6230c73cfb54SMatthew G. Knepley }
6231c73cfb54SMatthew G. Knepley 
6232793f3fe5SMatthew G. Knepley /*@
6233793f3fe5SMatthew G. Knepley   DMGetDimPoints - Get the half-open interval for all points of a given dimension
6234793f3fe5SMatthew G. Knepley 
6235d083f849SBarry Smith   Collective on dm
6236793f3fe5SMatthew G. Knepley 
6237793f3fe5SMatthew G. Knepley   Input Parameters:
6238bb7acecfSBarry Smith + dm - the `DM`
6239793f3fe5SMatthew G. Knepley - dim - the dimension
6240793f3fe5SMatthew G. Knepley 
6241793f3fe5SMatthew G. Knepley   Output Parameters:
6242793f3fe5SMatthew G. Knepley + pStart - The first point of the given dimension
6243aa049354SPatrick Sanan - pEnd - The first point following points of the given dimension
6244793f3fe5SMatthew G. Knepley 
6245793f3fe5SMatthew G. Knepley   Note:
6246793f3fe5SMatthew G. Knepley   The points are vertices in the Hasse diagram encoding the topology. This is explained in
6247a8d69d7bSBarry Smith   https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme,
6248793f3fe5SMatthew G. Knepley   then the interval is empty.
6249793f3fe5SMatthew G. Knepley 
6250793f3fe5SMatthew G. Knepley   Level: intermediate
6251793f3fe5SMatthew G. Knepley 
6252db781477SPatrick Sanan .seealso: `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
6253793f3fe5SMatthew G. Knepley @*/
6254d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
6255d71ae5a4SJacob Faibussowitsch {
6256793f3fe5SMatthew G. Knepley   PetscInt d;
6257793f3fe5SMatthew G. Knepley 
6258793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
6259793f3fe5SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62609566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &d));
62617a8be351SBarry Smith   PetscCheck((dim >= 0) && (dim <= d), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %" PetscInt_FMT, dim);
6262dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getdimpoints, dim, pStart, pEnd);
6263793f3fe5SMatthew G. Knepley   PetscFunctionReturn(0);
6264793f3fe5SMatthew G. Knepley }
6265793f3fe5SMatthew G. Knepley 
62666636e97aSMatthew G Knepley /*@
6267bb7acecfSBarry Smith   DMGetOutputDM - Retrieve the `DM` associated with the layout for output
6268f4d763aaSMatthew G. Knepley 
62698f700142SStefano Zampini   Collective on dm
62708f700142SStefano Zampini 
6271f4d763aaSMatthew G. Knepley   Input Parameter:
6272bb7acecfSBarry Smith . dm - The original `DM`
6273f4d763aaSMatthew G. Knepley 
6274f4d763aaSMatthew G. Knepley   Output Parameter:
6275bb7acecfSBarry Smith . odm - The `DM` which provides the layout for output
6276f4d763aaSMatthew G. Knepley 
6277f4d763aaSMatthew G. Knepley   Level: intermediate
6278f4d763aaSMatthew G. Knepley 
6279bb7acecfSBarry Smith   Note:
6280bb7acecfSBarry Smith   In some situations the vector obtained with `DMCreateGlobalVector()` excludes points for degrees of freedom that are associated with fixed (Dirichelet) boundary
6281bb7acecfSBarry 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
6282bb7acecfSBarry Smith   locations for those dof so that they can be output to a file or other viewer along with the unconstrained dof.
6283bb7acecfSBarry Smith 
6284bb7acecfSBarry Smith .seealso: `VecView()`, `DMGetGlobalSection()`, `DMCreateGlobalVector()`, `PetscSectionHasConstraints()`, `DMSetGlobalSection()`
6285f4d763aaSMatthew G. Knepley @*/
6286d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
6287d71ae5a4SJacob Faibussowitsch {
6288c26acbdeSMatthew G. Knepley   PetscSection section;
62892d4e4a49SMatthew G. Knepley   PetscBool    hasConstraints, ghasConstraints;
629014f150ffSMatthew G. Knepley 
629114f150ffSMatthew G. Knepley   PetscFunctionBegin;
629214f150ffSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
629314f150ffSMatthew G. Knepley   PetscValidPointer(odm, 2);
62949566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
62959566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
62969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
62972d4e4a49SMatthew G. Knepley   if (!ghasConstraints) {
6298c26acbdeSMatthew G. Knepley     *odm = dm;
6299c26acbdeSMatthew G. Knepley     PetscFunctionReturn(0);
6300c26acbdeSMatthew G. Knepley   }
630114f150ffSMatthew G. Knepley   if (!dm->dmBC) {
6302c26acbdeSMatthew G. Knepley     PetscSection newSection, gsection;
630314f150ffSMatthew G. Knepley     PetscSF      sf;
630414f150ffSMatthew G. Knepley 
63059566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &dm->dmBC));
63069566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dm, dm->dmBC));
63079566063dSJacob Faibussowitsch     PetscCall(PetscSectionClone(section, &newSection));
63089566063dSJacob Faibussowitsch     PetscCall(DMSetLocalSection(dm->dmBC, newSection));
63099566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&newSection));
63109566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm->dmBC, &sf));
63119566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
63129566063dSJacob Faibussowitsch     PetscCall(DMSetGlobalSection(dm->dmBC, gsection));
63139566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&gsection));
631414f150ffSMatthew G. Knepley   }
631514f150ffSMatthew G. Knepley   *odm = dm->dmBC;
631614f150ffSMatthew G. Knepley   PetscFunctionReturn(0);
631714f150ffSMatthew G. Knepley }
6318f4d763aaSMatthew G. Knepley 
6319f4d763aaSMatthew G. Knepley /*@
6320cdb7a50dSMatthew G. Knepley   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
6321f4d763aaSMatthew G. Knepley 
6322f4d763aaSMatthew G. Knepley   Input Parameter:
6323bb7acecfSBarry Smith . dm - The original `DM`
6324f4d763aaSMatthew G. Knepley 
6325cdb7a50dSMatthew G. Knepley   Output Parameters:
6326cdb7a50dSMatthew G. Knepley + num - The output sequence number
6327cdb7a50dSMatthew G. Knepley - val - The output sequence value
6328f4d763aaSMatthew G. Knepley 
6329f4d763aaSMatthew G. Knepley   Level: intermediate
6330f4d763aaSMatthew G. Knepley 
6331bb7acecfSBarry Smith   Note:
6332bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6333bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6334bb7acecfSBarry Smith 
6335bb7acecfSBarry Smith   Developer Note:
6336bb7acecfSBarry Smith   The `DM` serves as a convenient place to store the current iteration value. The iteration is not
6337bb7acecfSBarry Smith   not directly related to the `DM`.
6338f4d763aaSMatthew G. Knepley 
6339db781477SPatrick Sanan .seealso: `VecView()`
6340f4d763aaSMatthew G. Knepley @*/
6341d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
6342d71ae5a4SJacob Faibussowitsch {
6343f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6344f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63459371c9d4SSatish Balay   if (num) {
63469371c9d4SSatish Balay     PetscValidIntPointer(num, 2);
63479371c9d4SSatish Balay     *num = dm->outputSequenceNum;
63489371c9d4SSatish Balay   }
63499371c9d4SSatish Balay   if (val) {
63509371c9d4SSatish Balay     PetscValidRealPointer(val, 3);
63519371c9d4SSatish Balay     *val = dm->outputSequenceVal;
63529371c9d4SSatish Balay   }
6353f4d763aaSMatthew G. Knepley   PetscFunctionReturn(0);
6354f4d763aaSMatthew G. Knepley }
6355f4d763aaSMatthew G. Knepley 
6356f4d763aaSMatthew G. Knepley /*@
6357cdb7a50dSMatthew G. Knepley   DMSetOutputSequenceNumber - Set the sequence number/value for output
6358f4d763aaSMatthew G. Knepley 
6359f4d763aaSMatthew G. Knepley   Input Parameters:
6360bb7acecfSBarry Smith + dm - The original `DM`
6361cdb7a50dSMatthew G. Knepley . num - The output sequence number
6362cdb7a50dSMatthew G. Knepley - val - The output sequence value
6363f4d763aaSMatthew G. Knepley 
6364f4d763aaSMatthew G. Knepley   Level: intermediate
6365f4d763aaSMatthew G. Knepley 
6366bb7acecfSBarry Smith   Note:
6367bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6368bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6369f4d763aaSMatthew G. Knepley 
6370db781477SPatrick Sanan .seealso: `VecView()`
6371f4d763aaSMatthew G. Knepley @*/
6372d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
6373d71ae5a4SJacob Faibussowitsch {
6374f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6375f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6376f4d763aaSMatthew G. Knepley   dm->outputSequenceNum = num;
6377cdb7a50dSMatthew G. Knepley   dm->outputSequenceVal = val;
6378cdb7a50dSMatthew G. Knepley   PetscFunctionReturn(0);
6379cdb7a50dSMatthew G. Knepley }
6380cdb7a50dSMatthew G. Knepley 
6381cdb7a50dSMatthew G. Knepley /*@C
6382bb7acecfSBarry Smith  DMOutputSequenceLoad - Retrieve the sequence value from a `PetscViewer`
6383cdb7a50dSMatthew G. Knepley 
6384cdb7a50dSMatthew G. Knepley   Input Parameters:
6385bb7acecfSBarry Smith + dm   - The original `DM`
6386cdb7a50dSMatthew G. Knepley . name - The sequence name
6387cdb7a50dSMatthew G. Knepley - num  - The output sequence number
6388cdb7a50dSMatthew G. Knepley 
6389cdb7a50dSMatthew G. Knepley   Output Parameter:
6390cdb7a50dSMatthew G. Knepley . val  - The output sequence value
6391cdb7a50dSMatthew G. Knepley 
6392cdb7a50dSMatthew G. Knepley   Level: intermediate
6393cdb7a50dSMatthew G. Knepley 
6394bb7acecfSBarry Smith   Note:
6395bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6396bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6397bb7acecfSBarry Smith 
6398bb7acecfSBarry Smith   Developer Note:
6399bb7acecfSBarry Smith   It is unclear at the user API level why a `DM` is needed as input
6400cdb7a50dSMatthew G. Knepley 
6401db781477SPatrick Sanan .seealso: `DMGetOutputSequenceNumber()`, `DMSetOutputSequenceNumber()`, `VecView()`
6402cdb7a50dSMatthew G. Knepley @*/
6403d71ae5a4SJacob Faibussowitsch PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
6404d71ae5a4SJacob Faibussowitsch {
6405cdb7a50dSMatthew G. Knepley   PetscBool ishdf5;
6406cdb7a50dSMatthew G. Knepley 
6407cdb7a50dSMatthew G. Knepley   PetscFunctionBegin;
6408cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6409cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
6410064a246eSJacob Faibussowitsch   PetscValidRealPointer(val, 5);
64119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6412cdb7a50dSMatthew G. Knepley   if (ishdf5) {
6413cdb7a50dSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6414cdb7a50dSMatthew G. Knepley     PetscScalar value;
6415cdb7a50dSMatthew G. Knepley 
64169566063dSJacob Faibussowitsch     PetscCall(DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer));
64174aeb217fSMatthew G. Knepley     *val = PetscRealPart(value);
6418cdb7a50dSMatthew G. Knepley #endif
6419cdb7a50dSMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
6420f4d763aaSMatthew G. Knepley   PetscFunctionReturn(0);
6421f4d763aaSMatthew G. Knepley }
64228e4ac7eaSMatthew G. Knepley 
64238e4ac7eaSMatthew G. Knepley /*@
6424bb7acecfSBarry Smith   DMGetUseNatural - Get the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
64258e4ac7eaSMatthew G. Knepley 
64268e4ac7eaSMatthew G. Knepley   Not collective
64278e4ac7eaSMatthew G. Knepley 
64288e4ac7eaSMatthew G. Knepley   Input Parameter:
6429bb7acecfSBarry Smith . dm - The `DM`
64308e4ac7eaSMatthew G. Knepley 
64318e4ac7eaSMatthew G. Knepley   Output Parameter:
6432bb7acecfSBarry Smith . useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
64338e4ac7eaSMatthew G. Knepley 
64348e4ac7eaSMatthew G. Knepley   Level: beginner
64358e4ac7eaSMatthew G. Knepley 
6436db781477SPatrick Sanan .seealso: `DMSetUseNatural()`, `DMCreate()`
64378e4ac7eaSMatthew G. Knepley @*/
6438d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
6439d71ae5a4SJacob Faibussowitsch {
64408e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
64418e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6442534a8f05SLisandro Dalcin   PetscValidBoolPointer(useNatural, 2);
64438e4ac7eaSMatthew G. Knepley   *useNatural = dm->useNatural;
64448e4ac7eaSMatthew G. Knepley   PetscFunctionReturn(0);
64458e4ac7eaSMatthew G. Knepley }
64468e4ac7eaSMatthew G. Knepley 
64478e4ac7eaSMatthew G. Knepley /*@
6448bb7acecfSBarry Smith   DMSetUseNatural - Set the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
64498e4ac7eaSMatthew G. Knepley 
64508e4ac7eaSMatthew G. Knepley   Collective on dm
64518e4ac7eaSMatthew G. Knepley 
64528e4ac7eaSMatthew G. Knepley   Input Parameters:
6453bb7acecfSBarry Smith  + dm - The `DM`
6454bb7acecfSBarry Smith - useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
64558e4ac7eaSMatthew G. Knepley 
6456bb7acecfSBarry Smith   Note:
6457bb7acecfSBarry Smith   This also causes the map to be build after `DMCreateSubDM()` and `DMCreateSuperDM()`
64585d3b26e6SMatthew G. Knepley 
64598e4ac7eaSMatthew G. Knepley   Level: beginner
64608e4ac7eaSMatthew G. Knepley 
6461db781477SPatrick Sanan .seealso: `DMGetUseNatural()`, `DMCreate()`, `DMPlexDistribute()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
64628e4ac7eaSMatthew G. Knepley @*/
6463d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
6464d71ae5a4SJacob Faibussowitsch {
64658e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
64668e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64678833efb5SBlaise Bourdin   PetscValidLogicalCollectiveBool(dm, useNatural, 2);
64688e4ac7eaSMatthew G. Knepley   dm->useNatural = useNatural;
64698e4ac7eaSMatthew G. Knepley   PetscFunctionReturn(0);
64708e4ac7eaSMatthew G. Knepley }
6471c58f1c22SToby Isaac 
6472c58f1c22SToby Isaac /*@C
6473bb7acecfSBarry Smith   DMCreateLabel - Create a label of the given name if it does not already exist in the `DM`
6474c58f1c22SToby Isaac 
6475c58f1c22SToby Isaac   Not Collective
6476c58f1c22SToby Isaac 
6477c58f1c22SToby Isaac   Input Parameters:
6478bb7acecfSBarry Smith + dm   - The `DM` object
6479c58f1c22SToby Isaac - name - The label name
6480c58f1c22SToby Isaac 
6481c58f1c22SToby Isaac   Level: intermediate
6482c58f1c22SToby Isaac 
6483db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6484c58f1c22SToby Isaac @*/
6485d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabel(DM dm, const char name[])
6486d71ae5a4SJacob Faibussowitsch {
64875d80c0bfSVaclav Hapla   PetscBool flg;
64885d80c0bfSVaclav Hapla   DMLabel   label;
6489c58f1c22SToby Isaac 
6490c58f1c22SToby Isaac   PetscFunctionBegin;
6491c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6492c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
64939566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
6494c58f1c22SToby Isaac   if (!flg) {
64959566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
64969566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
64979566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
6498c58f1c22SToby Isaac   }
6499c58f1c22SToby Isaac   PetscFunctionReturn(0);
6500c58f1c22SToby Isaac }
6501c58f1c22SToby Isaac 
6502c58f1c22SToby Isaac /*@C
6503bb7acecfSBarry 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.
65040fdc7489SMatthew Knepley 
65050fdc7489SMatthew Knepley   Not Collective
65060fdc7489SMatthew Knepley 
65070fdc7489SMatthew Knepley   Input Parameters:
6508bb7acecfSBarry Smith + dm   - The `DM` object
65090fdc7489SMatthew Knepley . l    - The index for the label
65100fdc7489SMatthew Knepley - name - The label name
65110fdc7489SMatthew Knepley 
65120fdc7489SMatthew Knepley   Level: intermediate
65130fdc7489SMatthew Knepley 
6514db781477SPatrick Sanan .seealso: `DMCreateLabel()`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
65150fdc7489SMatthew Knepley @*/
6516d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[])
6517d71ae5a4SJacob Faibussowitsch {
65180fdc7489SMatthew Knepley   DMLabelLink orig, prev = NULL;
65190fdc7489SMatthew Knepley   DMLabel     label;
65200fdc7489SMatthew Knepley   PetscInt    Nl, m;
65210fdc7489SMatthew Knepley   PetscBool   flg, match;
65220fdc7489SMatthew Knepley   const char *lname;
65230fdc7489SMatthew Knepley 
65240fdc7489SMatthew Knepley   PetscFunctionBegin;
65250fdc7489SMatthew Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6526064a246eSJacob Faibussowitsch   PetscValidCharPointer(name, 3);
65279566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
65280fdc7489SMatthew Knepley   if (!flg) {
65299566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
65309566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
65319566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
65320fdc7489SMatthew Knepley   }
65339566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
653463a3b9bcSJacob Faibussowitsch   PetscCheck(l < Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", l, Nl);
65350fdc7489SMatthew Knepley   for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) {
65369566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)orig->label, &lname));
65379566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &match));
65380fdc7489SMatthew Knepley     if (match) break;
65390fdc7489SMatthew Knepley   }
65400fdc7489SMatthew Knepley   if (m == l) PetscFunctionReturn(0);
65410fdc7489SMatthew Knepley   if (!m) dm->labels = orig->next;
65420fdc7489SMatthew Knepley   else prev->next = orig->next;
65430fdc7489SMatthew Knepley   if (!l) {
65440fdc7489SMatthew Knepley     orig->next = dm->labels;
65450fdc7489SMatthew Knepley     dm->labels = orig;
65460fdc7489SMatthew Knepley   } else {
65479371c9d4SSatish Balay     for (m = 0, prev = dm->labels; m < l - 1; ++m, prev = prev->next)
65489371c9d4SSatish Balay       ;
65490fdc7489SMatthew Knepley     orig->next = prev->next;
65500fdc7489SMatthew Knepley     prev->next = orig;
65510fdc7489SMatthew Knepley   }
65520fdc7489SMatthew Knepley   PetscFunctionReturn(0);
65530fdc7489SMatthew Knepley }
65540fdc7489SMatthew Knepley 
65550fdc7489SMatthew Knepley /*@C
6556bb7acecfSBarry Smith   DMGetLabelValue - Get the value in a `DMLabel` for the given point, with -1 as the default
6557c58f1c22SToby Isaac 
6558c58f1c22SToby Isaac   Not Collective
6559c58f1c22SToby Isaac 
6560c58f1c22SToby Isaac   Input Parameters:
6561bb7acecfSBarry Smith + dm   - The `DM` object
6562c58f1c22SToby Isaac . name - The label name
6563c58f1c22SToby Isaac - point - The mesh point
6564c58f1c22SToby Isaac 
6565c58f1c22SToby Isaac   Output Parameter:
6566c58f1c22SToby Isaac . value - The label value for this point, or -1 if the point is not in the label
6567c58f1c22SToby Isaac 
6568c58f1c22SToby Isaac   Level: beginner
6569c58f1c22SToby Isaac 
6570db781477SPatrick Sanan .seealso: `DMLabelGetValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6571c58f1c22SToby Isaac @*/
6572d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
6573d71ae5a4SJacob Faibussowitsch {
6574c58f1c22SToby Isaac   DMLabel label;
6575c58f1c22SToby Isaac 
6576c58f1c22SToby Isaac   PetscFunctionBegin;
6577c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6578c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
65799566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
65807a8be351SBarry Smith   PetscCheck(label, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
65819566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, point, value));
6582c58f1c22SToby Isaac   PetscFunctionReturn(0);
6583c58f1c22SToby Isaac }
6584c58f1c22SToby Isaac 
6585c58f1c22SToby Isaac /*@C
6586bb7acecfSBarry Smith   DMSetLabelValue - Add a point to a `DMLabel` with given value
6587c58f1c22SToby Isaac 
6588c58f1c22SToby Isaac   Not Collective
6589c58f1c22SToby Isaac 
6590c58f1c22SToby Isaac   Input Parameters:
6591bb7acecfSBarry Smith + dm   - The `DM` object
6592c58f1c22SToby Isaac . name - The label name
6593c58f1c22SToby Isaac . point - The mesh point
6594c58f1c22SToby Isaac - value - The label value for this point
6595c58f1c22SToby Isaac 
6596c58f1c22SToby Isaac   Output Parameter:
6597c58f1c22SToby Isaac 
6598c58f1c22SToby Isaac   Level: beginner
6599c58f1c22SToby Isaac 
6600db781477SPatrick Sanan .seealso: `DMLabelSetValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6601c58f1c22SToby Isaac @*/
6602d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6603d71ae5a4SJacob Faibussowitsch {
6604c58f1c22SToby Isaac   DMLabel label;
6605c58f1c22SToby Isaac 
6606c58f1c22SToby Isaac   PetscFunctionBegin;
6607c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6608c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
66099566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6610c58f1c22SToby Isaac   if (!label) {
66119566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
66129566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
6613c58f1c22SToby Isaac   }
66149566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, point, value));
6615c58f1c22SToby Isaac   PetscFunctionReturn(0);
6616c58f1c22SToby Isaac }
6617c58f1c22SToby Isaac 
6618c58f1c22SToby Isaac /*@C
6619bb7acecfSBarry Smith   DMClearLabelValue - Remove a point from a `DMLabel` with given value
6620c58f1c22SToby Isaac 
6621c58f1c22SToby Isaac   Not Collective
6622c58f1c22SToby Isaac 
6623c58f1c22SToby Isaac   Input Parameters:
6624bb7acecfSBarry Smith + dm   - The `DM` object
6625c58f1c22SToby Isaac . name - The label name
6626c58f1c22SToby Isaac . point - The mesh point
6627c58f1c22SToby Isaac - value - The label value for this point
6628c58f1c22SToby Isaac 
6629c58f1c22SToby Isaac   Level: beginner
6630c58f1c22SToby Isaac 
6631db781477SPatrick Sanan .seealso: `DMLabelClearValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6632c58f1c22SToby Isaac @*/
6633d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6634d71ae5a4SJacob Faibussowitsch {
6635c58f1c22SToby Isaac   DMLabel label;
6636c58f1c22SToby Isaac 
6637c58f1c22SToby Isaac   PetscFunctionBegin;
6638c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6639c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
66409566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6641c58f1c22SToby Isaac   if (!label) PetscFunctionReturn(0);
66429566063dSJacob Faibussowitsch   PetscCall(DMLabelClearValue(label, point, value));
6643c58f1c22SToby Isaac   PetscFunctionReturn(0);
6644c58f1c22SToby Isaac }
6645c58f1c22SToby Isaac 
6646c58f1c22SToby Isaac /*@C
6647bb7acecfSBarry Smith   DMGetLabelSize - Get the value of `DMLabelGetNumValues()` of a `DMLabel` in the `DM`
6648c58f1c22SToby Isaac 
6649c58f1c22SToby Isaac   Not Collective
6650c58f1c22SToby Isaac 
6651c58f1c22SToby Isaac   Input Parameters:
6652bb7acecfSBarry Smith + dm   - The `DM` object
6653c58f1c22SToby Isaac - name - The label name
6654c58f1c22SToby Isaac 
6655c58f1c22SToby Isaac   Output Parameter:
6656c58f1c22SToby Isaac . size - The number of different integer ids, or 0 if the label does not exist
6657c58f1c22SToby Isaac 
6658c58f1c22SToby Isaac   Level: beginner
6659c58f1c22SToby Isaac 
6660bb7acecfSBarry Smith   Developer Note:
6661bb7acecfSBarry Smith   This should be renamed to something like `DMGetLabelNumValues()` or removed.
6662bb7acecfSBarry Smith 
6663bb7acecfSBarry Smith .seealso: `DMLabelGetNumValues()`, `DMSetLabelValue()`, `DMGetLabel()`
6664c58f1c22SToby Isaac @*/
6665d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
6666d71ae5a4SJacob Faibussowitsch {
6667c58f1c22SToby Isaac   DMLabel label;
6668c58f1c22SToby Isaac 
6669c58f1c22SToby Isaac   PetscFunctionBegin;
6670c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6671c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6672534a8f05SLisandro Dalcin   PetscValidIntPointer(size, 3);
66739566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6674c58f1c22SToby Isaac   *size = 0;
6675c58f1c22SToby Isaac   if (!label) PetscFunctionReturn(0);
66769566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, size));
6677c58f1c22SToby Isaac   PetscFunctionReturn(0);
6678c58f1c22SToby Isaac }
6679c58f1c22SToby Isaac 
6680c58f1c22SToby Isaac /*@C
6681bb7acecfSBarry Smith   DMGetLabelIdIS - Get the `DMLabelGetValueIS()` from a `DMLabel` in the `DM`
6682c58f1c22SToby Isaac 
6683c58f1c22SToby Isaac   Not Collective
6684c58f1c22SToby Isaac 
6685c58f1c22SToby Isaac   Input Parameters:
6686bb7acecfSBarry Smith + mesh - The `DM` object
6687c58f1c22SToby Isaac - name - The label name
6688c58f1c22SToby Isaac 
6689c58f1c22SToby Isaac   Output Parameter:
6690c58f1c22SToby Isaac . ids - The integer ids, or NULL if the label does not exist
6691c58f1c22SToby Isaac 
6692c58f1c22SToby Isaac   Level: beginner
6693c58f1c22SToby Isaac 
6694db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMGetLabelSize()`
6695c58f1c22SToby Isaac @*/
6696d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
6697d71ae5a4SJacob Faibussowitsch {
6698c58f1c22SToby Isaac   DMLabel label;
6699c58f1c22SToby Isaac 
6700c58f1c22SToby Isaac   PetscFunctionBegin;
6701c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6702c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6703c58f1c22SToby Isaac   PetscValidPointer(ids, 3);
67049566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6705c58f1c22SToby Isaac   *ids = NULL;
6706dab2e251SBlaise Bourdin   if (label) {
67079566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, ids));
6708dab2e251SBlaise Bourdin   } else {
6709dab2e251SBlaise Bourdin     /* returning an empty IS */
67109566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, ids));
6711dab2e251SBlaise Bourdin   }
6712c58f1c22SToby Isaac   PetscFunctionReturn(0);
6713c58f1c22SToby Isaac }
6714c58f1c22SToby Isaac 
6715c58f1c22SToby Isaac /*@C
6716c58f1c22SToby Isaac   DMGetStratumSize - Get the number of points in a label stratum
6717c58f1c22SToby Isaac 
6718c58f1c22SToby Isaac   Not Collective
6719c58f1c22SToby Isaac 
6720c58f1c22SToby Isaac   Input Parameters:
6721bb7acecfSBarry Smith + dm - The `DM` object
6722c58f1c22SToby Isaac . name - The label name
6723c58f1c22SToby Isaac - value - The stratum value
6724c58f1c22SToby Isaac 
6725c58f1c22SToby Isaac   Output Parameter:
6726bb7acecfSBarry Smith . size - The number of points, also called the stratum size
6727c58f1c22SToby Isaac 
6728c58f1c22SToby Isaac   Level: beginner
6729c58f1c22SToby Isaac 
6730db781477SPatrick Sanan .seealso: `DMLabelGetStratumSize()`, `DMGetLabelSize()`, `DMGetLabelIds()`
6731c58f1c22SToby Isaac @*/
6732d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
6733d71ae5a4SJacob Faibussowitsch {
6734c58f1c22SToby Isaac   DMLabel label;
6735c58f1c22SToby Isaac 
6736c58f1c22SToby Isaac   PetscFunctionBegin;
6737c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6738c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6739534a8f05SLisandro Dalcin   PetscValidIntPointer(size, 4);
67409566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6741c58f1c22SToby Isaac   *size = 0;
6742c58f1c22SToby Isaac   if (!label) PetscFunctionReturn(0);
67439566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize(label, value, size));
6744c58f1c22SToby Isaac   PetscFunctionReturn(0);
6745c58f1c22SToby Isaac }
6746c58f1c22SToby Isaac 
6747c58f1c22SToby Isaac /*@C
6748c58f1c22SToby Isaac   DMGetStratumIS - Get the points in a label stratum
6749c58f1c22SToby Isaac 
6750c58f1c22SToby Isaac   Not Collective
6751c58f1c22SToby Isaac 
6752c58f1c22SToby Isaac   Input Parameters:
6753bb7acecfSBarry Smith + dm - The `DM` object
6754c58f1c22SToby Isaac . name - The label name
6755c58f1c22SToby Isaac - value - The stratum value
6756c58f1c22SToby Isaac 
6757c58f1c22SToby Isaac   Output Parameter:
6758c58f1c22SToby Isaac . points - The stratum points, or NULL if the label does not exist or does not have that value
6759c58f1c22SToby Isaac 
6760c58f1c22SToby Isaac   Level: beginner
6761c58f1c22SToby Isaac 
6762db781477SPatrick Sanan .seealso: `DMLabelGetStratumIS()`, `DMGetStratumSize()`
6763c58f1c22SToby Isaac @*/
6764d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
6765d71ae5a4SJacob Faibussowitsch {
6766c58f1c22SToby Isaac   DMLabel label;
6767c58f1c22SToby Isaac 
6768c58f1c22SToby Isaac   PetscFunctionBegin;
6769c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6770c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6771c58f1c22SToby Isaac   PetscValidPointer(points, 4);
67729566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6773c58f1c22SToby Isaac   *points = NULL;
6774c58f1c22SToby Isaac   if (!label) PetscFunctionReturn(0);
67759566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, points));
6776c58f1c22SToby Isaac   PetscFunctionReturn(0);
6777c58f1c22SToby Isaac }
6778c58f1c22SToby Isaac 
67794de306b1SToby Isaac /*@C
67809044fa66SMatthew G. Knepley   DMSetStratumIS - Set the points in a label stratum
67814de306b1SToby Isaac 
67824de306b1SToby Isaac   Not Collective
67834de306b1SToby Isaac 
67844de306b1SToby Isaac   Input Parameters:
6785bb7acecfSBarry Smith + dm - The `DM` object
67864de306b1SToby Isaac . name - The label name
67874de306b1SToby Isaac . value - The stratum value
67884de306b1SToby Isaac - points - The stratum points
67894de306b1SToby Isaac 
67904de306b1SToby Isaac   Level: beginner
67914de306b1SToby Isaac 
6792bb7acecfSBarry Smith .seealso: `DMLabel`, `DMClearLabelStratum()`, `DMLabelClearStratum()`, `DMLabelSetStratumIS()`, `DMGetStratumSize()`
67934de306b1SToby Isaac @*/
6794d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
6795d71ae5a4SJacob Faibussowitsch {
67964de306b1SToby Isaac   DMLabel label;
67974de306b1SToby Isaac 
67984de306b1SToby Isaac   PetscFunctionBegin;
67994de306b1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68004de306b1SToby Isaac   PetscValidCharPointer(name, 2);
68014de306b1SToby Isaac   PetscValidPointer(points, 4);
68029566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
68034de306b1SToby Isaac   if (!label) PetscFunctionReturn(0);
68049566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, points));
68054de306b1SToby Isaac   PetscFunctionReturn(0);
68064de306b1SToby Isaac }
68074de306b1SToby Isaac 
6808c58f1c22SToby Isaac /*@C
6809bb7acecfSBarry Smith   DMClearLabelStratum - Remove all points from a stratum from a `DMLabel`
6810c58f1c22SToby Isaac 
6811c58f1c22SToby Isaac   Not Collective
6812c58f1c22SToby Isaac 
6813c58f1c22SToby Isaac   Input Parameters:
6814bb7acecfSBarry Smith + dm   - The `DM` object
6815c58f1c22SToby Isaac . name - The label name
6816c58f1c22SToby Isaac - value - The label value for this point
6817c58f1c22SToby Isaac 
6818c58f1c22SToby Isaac   Output Parameter:
6819c58f1c22SToby Isaac 
6820c58f1c22SToby Isaac   Level: beginner
6821c58f1c22SToby Isaac 
6822bb7acecfSBarry Smith .seealso: `DMLabel`, `DMLabelClearStratum()`, `DMSetLabelValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6823c58f1c22SToby Isaac @*/
6824d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
6825d71ae5a4SJacob Faibussowitsch {
6826c58f1c22SToby Isaac   DMLabel label;
6827c58f1c22SToby Isaac 
6828c58f1c22SToby Isaac   PetscFunctionBegin;
6829c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6830c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
68319566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6832c58f1c22SToby Isaac   if (!label) PetscFunctionReturn(0);
68339566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
6834c58f1c22SToby Isaac   PetscFunctionReturn(0);
6835c58f1c22SToby Isaac }
6836c58f1c22SToby Isaac 
6837c58f1c22SToby Isaac /*@
6838bb7acecfSBarry Smith   DMGetNumLabels - Return the number of labels defined by on the `DM`
6839c58f1c22SToby Isaac 
6840c58f1c22SToby Isaac   Not Collective
6841c58f1c22SToby Isaac 
6842c58f1c22SToby Isaac   Input Parameter:
6843bb7acecfSBarry Smith . dm   - The `DM` object
6844c58f1c22SToby Isaac 
6845c58f1c22SToby Isaac   Output Parameter:
6846c58f1c22SToby Isaac . numLabels - the number of Labels
6847c58f1c22SToby Isaac 
6848c58f1c22SToby Isaac   Level: intermediate
6849c58f1c22SToby Isaac 
6850bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetLabelByNum()`, `DMGetLabelName()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6851c58f1c22SToby Isaac @*/
6852d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
6853d71ae5a4SJacob Faibussowitsch {
68545d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6855c58f1c22SToby Isaac   PetscInt    n    = 0;
6856c58f1c22SToby Isaac 
6857c58f1c22SToby Isaac   PetscFunctionBegin;
6858c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6859534a8f05SLisandro Dalcin   PetscValidIntPointer(numLabels, 2);
68609371c9d4SSatish Balay   while (next) {
68619371c9d4SSatish Balay     ++n;
68629371c9d4SSatish Balay     next = next->next;
68639371c9d4SSatish Balay   }
6864c58f1c22SToby Isaac   *numLabels = n;
6865c58f1c22SToby Isaac   PetscFunctionReturn(0);
6866c58f1c22SToby Isaac }
6867c58f1c22SToby Isaac 
6868c58f1c22SToby Isaac /*@C
6869c58f1c22SToby Isaac   DMGetLabelName - Return the name of nth label
6870c58f1c22SToby Isaac 
6871c58f1c22SToby Isaac   Not Collective
6872c58f1c22SToby Isaac 
6873c58f1c22SToby Isaac   Input Parameters:
6874bb7acecfSBarry Smith + dm - The `DM` object
6875c58f1c22SToby Isaac - n  - the label number
6876c58f1c22SToby Isaac 
6877c58f1c22SToby Isaac   Output Parameter:
6878c58f1c22SToby Isaac . name - the label name
6879c58f1c22SToby Isaac 
6880c58f1c22SToby Isaac   Level: intermediate
6881c58f1c22SToby Isaac 
6882bb7acecfSBarry Smith   Developer Note:
6883bb7acecfSBarry Smith   Some of the functions that appropriate on labels using their number have the suffix ByNum, others do not.
6884bb7acecfSBarry Smith 
6885bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetLabelByNum()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6886c58f1c22SToby Isaac @*/
6887d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
6888d71ae5a4SJacob Faibussowitsch {
68895d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6890c58f1c22SToby Isaac   PetscInt    l    = 0;
6891c58f1c22SToby Isaac 
6892c58f1c22SToby Isaac   PetscFunctionBegin;
6893c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6894c58f1c22SToby Isaac   PetscValidPointer(name, 3);
6895c58f1c22SToby Isaac   while (next) {
6896c58f1c22SToby Isaac     if (l == n) {
68979566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)next->label, name));
6898c58f1c22SToby Isaac       PetscFunctionReturn(0);
6899c58f1c22SToby Isaac     }
6900c58f1c22SToby Isaac     ++l;
6901c58f1c22SToby Isaac     next = next->next;
6902c58f1c22SToby Isaac   }
690363a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
6904c58f1c22SToby Isaac }
6905c58f1c22SToby Isaac 
6906c58f1c22SToby Isaac /*@C
6907bb7acecfSBarry Smith   DMHasLabel - Determine whether the `DM` has a label of a given name
6908c58f1c22SToby Isaac 
6909c58f1c22SToby Isaac   Not Collective
6910c58f1c22SToby Isaac 
6911c58f1c22SToby Isaac   Input Parameters:
6912bb7acecfSBarry Smith + dm   - The `DM` object
6913c58f1c22SToby Isaac - name - The label name
6914c58f1c22SToby Isaac 
6915c58f1c22SToby Isaac   Output Parameter:
6916bb7acecfSBarry Smith . hasLabel - `PETSC_TRUE` if the label is present
6917c58f1c22SToby Isaac 
6918c58f1c22SToby Isaac   Level: intermediate
6919c58f1c22SToby Isaac 
6920bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetLabel()`, `DMGetLabelByNum()`, `DMCreateLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6921c58f1c22SToby Isaac @*/
6922d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
6923d71ae5a4SJacob Faibussowitsch {
69245d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6925d67d17b1SMatthew G. Knepley   const char *lname;
6926c58f1c22SToby Isaac 
6927c58f1c22SToby Isaac   PetscFunctionBegin;
6928c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6929c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6930534a8f05SLisandro Dalcin   PetscValidBoolPointer(hasLabel, 3);
6931c58f1c22SToby Isaac   *hasLabel = PETSC_FALSE;
6932c58f1c22SToby Isaac   while (next) {
69339566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
69349566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, hasLabel));
6935c58f1c22SToby Isaac     if (*hasLabel) break;
6936c58f1c22SToby Isaac     next = next->next;
6937c58f1c22SToby Isaac   }
6938c58f1c22SToby Isaac   PetscFunctionReturn(0);
6939c58f1c22SToby Isaac }
6940c58f1c22SToby Isaac 
6941c58f1c22SToby Isaac /*@C
6942bb7acecfSBarry Smith   DMGetLabel - Return the label of a given name, or NULL, from a `DM`
6943c58f1c22SToby Isaac 
6944c58f1c22SToby Isaac   Not Collective
6945c58f1c22SToby Isaac 
6946c58f1c22SToby Isaac   Input Parameters:
6947bb7acecfSBarry Smith + dm   - The `DM` object
6948c58f1c22SToby Isaac - name - The label name
6949c58f1c22SToby Isaac 
6950c58f1c22SToby Isaac   Output Parameter:
6951bb7acecfSBarry Smith . label - The `DMLabel`, or NULL if the label is absent
6952c58f1c22SToby Isaac 
6953bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
6954bb7acecfSBarry Smith +   "depth"       - Holds the depth (co-dimension) of each mesh point
6955bb7acecfSBarry Smith .   "celltype"    - Holds the topological type of each cell
6956bb7acecfSBarry Smith .   "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
6957bb7acecfSBarry Smith .   "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
6958bb7acecfSBarry Smith .   "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
6959bb7acecfSBarry Smith -  "Vertex Sets" - Mirrors the vertex sets defined by GMsh
69606d7c9049SMatthew G. Knepley 
6961c58f1c22SToby Isaac   Level: intermediate
6962c58f1c22SToby Isaac 
6963bb7acecfSBarry Smith .seealso: `DMLabel`, `DMHasLabel()`, `DMGetLabelByNum()`, `DMAddLabel()`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
6964c58f1c22SToby Isaac @*/
6965d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
6966d71ae5a4SJacob Faibussowitsch {
69675d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6968c58f1c22SToby Isaac   PetscBool   hasLabel;
6969d67d17b1SMatthew G. Knepley   const char *lname;
6970c58f1c22SToby Isaac 
6971c58f1c22SToby Isaac   PetscFunctionBegin;
6972c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6973c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6974c58f1c22SToby Isaac   PetscValidPointer(label, 3);
6975c58f1c22SToby Isaac   *label = NULL;
6976c58f1c22SToby Isaac   while (next) {
69779566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
69789566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
6979c58f1c22SToby Isaac     if (hasLabel) {
6980c58f1c22SToby Isaac       *label = next->label;
6981c58f1c22SToby Isaac       break;
6982c58f1c22SToby Isaac     }
6983c58f1c22SToby Isaac     next = next->next;
6984c58f1c22SToby Isaac   }
6985c58f1c22SToby Isaac   PetscFunctionReturn(0);
6986c58f1c22SToby Isaac }
6987c58f1c22SToby Isaac 
6988c58f1c22SToby Isaac /*@C
6989bb7acecfSBarry Smith   DMGetLabelByNum - Return the nth label on a `DM`
6990c58f1c22SToby Isaac 
6991c58f1c22SToby Isaac   Not Collective
6992c58f1c22SToby Isaac 
6993c58f1c22SToby Isaac   Input Parameters:
6994bb7acecfSBarry Smith + dm - The `DM` object
6995c58f1c22SToby Isaac - n  - the label number
6996c58f1c22SToby Isaac 
6997c58f1c22SToby Isaac   Output Parameter:
6998c58f1c22SToby Isaac . label - the label
6999c58f1c22SToby Isaac 
7000c58f1c22SToby Isaac   Level: intermediate
7001c58f1c22SToby Isaac 
7002bb7acecfSBarry Smith .seealso: `DMLabel`, `DMAddLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7003c58f1c22SToby Isaac @*/
7004d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
7005d71ae5a4SJacob Faibussowitsch {
70065d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7007c58f1c22SToby Isaac   PetscInt    l    = 0;
7008c58f1c22SToby Isaac 
7009c58f1c22SToby Isaac   PetscFunctionBegin;
7010c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7011c58f1c22SToby Isaac   PetscValidPointer(label, 3);
7012c58f1c22SToby Isaac   while (next) {
7013c58f1c22SToby Isaac     if (l == n) {
7014c58f1c22SToby Isaac       *label = next->label;
7015c58f1c22SToby Isaac       PetscFunctionReturn(0);
7016c58f1c22SToby Isaac     }
7017c58f1c22SToby Isaac     ++l;
7018c58f1c22SToby Isaac     next = next->next;
7019c58f1c22SToby Isaac   }
702063a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
7021c58f1c22SToby Isaac }
7022c58f1c22SToby Isaac 
7023c58f1c22SToby Isaac /*@C
7024bb7acecfSBarry Smith   DMAddLabel - Add the label to this `DM`
7025c58f1c22SToby Isaac 
7026c58f1c22SToby Isaac   Not Collective
7027c58f1c22SToby Isaac 
7028c58f1c22SToby Isaac   Input Parameters:
7029bb7acecfSBarry Smith + dm   - The `DM` object
7030bb7acecfSBarry Smith - label - The `DMLabel`
7031c58f1c22SToby Isaac 
7032c58f1c22SToby Isaac   Level: developer
7033c58f1c22SToby Isaac 
7034bb7acecfSBarry Smith .seealso: `DMLabel`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7035c58f1c22SToby Isaac @*/
7036d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddLabel(DM dm, DMLabel label)
7037d71ae5a4SJacob Faibussowitsch {
70385d80c0bfSVaclav Hapla   DMLabelLink l, *p, tmpLabel;
7039c58f1c22SToby Isaac   PetscBool   hasLabel;
7040d67d17b1SMatthew G. Knepley   const char *lname;
70415d80c0bfSVaclav Hapla   PetscBool   flg;
7042c58f1c22SToby Isaac 
7043c58f1c22SToby Isaac   PetscFunctionBegin;
7044c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70459566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
70469566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, lname, &hasLabel));
70477a8be351SBarry Smith   PetscCheck(!hasLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname);
70489566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(1, &tmpLabel));
7049c58f1c22SToby Isaac   tmpLabel->label  = label;
7050c58f1c22SToby Isaac   tmpLabel->output = PETSC_TRUE;
70515d80c0bfSVaclav Hapla   for (p = &dm->labels; (l = *p); p = &l->next) { }
70525d80c0bfSVaclav Hapla   *p = tmpLabel;
70539566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
70549566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "depth", &flg));
70555d80c0bfSVaclav Hapla   if (flg) dm->depthLabel = label;
70569566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "celltype", &flg));
7057ba2698f1SMatthew G. Knepley   if (flg) dm->celltypeLabel = label;
7058c58f1c22SToby Isaac   PetscFunctionReturn(0);
7059c58f1c22SToby Isaac }
7060c58f1c22SToby Isaac 
7061c58f1c22SToby Isaac /*@C
70624a7ee7d0SMatthew G. Knepley   DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present
70634a7ee7d0SMatthew G. Knepley 
70644a7ee7d0SMatthew G. Knepley   Not Collective
70654a7ee7d0SMatthew G. Knepley 
70664a7ee7d0SMatthew G. Knepley   Input Parameters:
7067bb7acecfSBarry Smith + dm    - The `DM` object
7068bb7acecfSBarry Smith - label - The `DMLabel`, having the same name, to substitute
70694a7ee7d0SMatthew G. Knepley 
7070bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
7071bb7acecfSBarry Smith +  "depth"       - Holds the depth (co-dimension) of each mesh point
7072bb7acecfSBarry Smith .  "celltype"    - Holds the topological type of each cell
7073bb7acecfSBarry Smith .  "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
7074bb7acecfSBarry Smith .  "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
7075bb7acecfSBarry Smith .  "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
7076bb7acecfSBarry Smith - "Vertex Sets" - Mirrors the vertex sets defined by GMsh
70774a7ee7d0SMatthew G. Knepley 
70784a7ee7d0SMatthew G. Knepley   Level: intermediate
70794a7ee7d0SMatthew G. Knepley 
7080bb7acecfSBarry Smith .seealso: `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
70814a7ee7d0SMatthew G. Knepley @*/
7082d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabel(DM dm, DMLabel label)
7083d71ae5a4SJacob Faibussowitsch {
70844a7ee7d0SMatthew G. Knepley   DMLabelLink next = dm->labels;
70854a7ee7d0SMatthew G. Knepley   PetscBool   hasLabel, flg;
70864a7ee7d0SMatthew G. Knepley   const char *name, *lname;
70874a7ee7d0SMatthew G. Knepley 
70884a7ee7d0SMatthew G. Knepley   PetscFunctionBegin;
70894a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70904a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
70919566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
70924a7ee7d0SMatthew G. Knepley   while (next) {
70939566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
70949566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
70954a7ee7d0SMatthew G. Knepley     if (hasLabel) {
70969566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)label));
70979566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "depth", &flg));
70984a7ee7d0SMatthew G. Knepley       if (flg) dm->depthLabel = label;
70999566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "celltype", &flg));
71004a7ee7d0SMatthew G. Knepley       if (flg) dm->celltypeLabel = label;
71019566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&next->label));
71024a7ee7d0SMatthew G. Knepley       next->label = label;
71034a7ee7d0SMatthew G. Knepley       break;
71044a7ee7d0SMatthew G. Knepley     }
71054a7ee7d0SMatthew G. Knepley     next = next->next;
71064a7ee7d0SMatthew G. Knepley   }
71074a7ee7d0SMatthew G. Knepley   PetscFunctionReturn(0);
71084a7ee7d0SMatthew G. Knepley }
71094a7ee7d0SMatthew G. Knepley 
71104a7ee7d0SMatthew G. Knepley /*@C
7111bb7acecfSBarry Smith   DMRemoveLabel - Remove the label given by name from this `DM`
7112c58f1c22SToby Isaac 
7113c58f1c22SToby Isaac   Not Collective
7114c58f1c22SToby Isaac 
7115c58f1c22SToby Isaac   Input Parameters:
7116bb7acecfSBarry Smith + dm   - The `DM` object
7117c58f1c22SToby Isaac - name - The label name
7118c58f1c22SToby Isaac 
7119c58f1c22SToby Isaac   Output Parameter:
7120bb7acecfSBarry Smith . label - The `DMLabel`, or NULL if the label is absent. Pass in NULL to call `DMLabelDestroy()` on the label, otherwise the
7121bb7acecfSBarry Smith           caller is responsible for calling `DMLabelDestroy()`.
7122c58f1c22SToby Isaac 
7123c58f1c22SToby Isaac   Level: developer
7124c58f1c22SToby Isaac 
7125bb7acecfSBarry Smith .seealso: `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabelBySelf()`
7126c58f1c22SToby Isaac @*/
7127d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
7128d71ae5a4SJacob Faibussowitsch {
712995d578d6SVaclav Hapla   DMLabelLink link, *pnext;
7130c58f1c22SToby Isaac   PetscBool   hasLabel;
7131d67d17b1SMatthew G. Knepley   const char *lname;
7132c58f1c22SToby Isaac 
7133c58f1c22SToby Isaac   PetscFunctionBegin;
7134c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7135e5472504SVaclav Hapla   PetscValidCharPointer(name, 2);
7136e5472504SVaclav Hapla   if (label) {
7137e5472504SVaclav Hapla     PetscValidPointer(label, 3);
7138c58f1c22SToby Isaac     *label = NULL;
7139e5472504SVaclav Hapla   }
71405d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
71419566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)link->label, &lname));
71429566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
7143c58f1c22SToby Isaac     if (hasLabel) {
714495d578d6SVaclav Hapla       *pnext = link->next; /* Remove from list */
71459566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &hasLabel));
714695d578d6SVaclav Hapla       if (hasLabel) dm->depthLabel = NULL;
71479566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &hasLabel));
7148ba2698f1SMatthew G. Knepley       if (hasLabel) dm->celltypeLabel = NULL;
714995d578d6SVaclav Hapla       if (label) *label = link->label;
71509566063dSJacob Faibussowitsch       else PetscCall(DMLabelDestroy(&link->label));
71519566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7152c58f1c22SToby Isaac       break;
7153c58f1c22SToby Isaac     }
7154c58f1c22SToby Isaac   }
7155c58f1c22SToby Isaac   PetscFunctionReturn(0);
7156c58f1c22SToby Isaac }
7157c58f1c22SToby Isaac 
7158306894acSVaclav Hapla /*@
7159bb7acecfSBarry Smith   DMRemoveLabelBySelf - Remove the label from this `DM`
7160306894acSVaclav Hapla 
7161306894acSVaclav Hapla   Not Collective
7162306894acSVaclav Hapla 
7163306894acSVaclav Hapla   Input Parameters:
7164bb7acecfSBarry Smith + dm   - The `DM` object
7165bb7acecfSBarry Smith . label - The `DMLabel` to be removed from the `DM`
7166306894acSVaclav Hapla - failNotFound - Should it fail if the label is not found in the DM?
7167306894acSVaclav Hapla 
7168306894acSVaclav Hapla   Level: developer
7169306894acSVaclav Hapla 
7170bb7acecfSBarry Smith   Note:
7171306894acSVaclav Hapla   Only exactly the same instance is removed if found, name match is ignored.
7172bb7acecfSBarry Smith   If the `DM` has an exclusive reference to the label, the label gets destroyed and
7173306894acSVaclav Hapla   *label nullified.
7174306894acSVaclav Hapla 
7175bb7acecfSBarry Smith .seealso: `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()` `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabel()`
7176306894acSVaclav Hapla @*/
7177d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound)
7178d71ae5a4SJacob Faibussowitsch {
717943e45a93SVaclav Hapla   DMLabelLink link, *pnext;
7180306894acSVaclav Hapla   PetscBool   hasLabel = PETSC_FALSE;
7181306894acSVaclav Hapla 
7182306894acSVaclav Hapla   PetscFunctionBegin;
7183306894acSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7184306894acSVaclav Hapla   PetscValidPointer(label, 2);
7185f39a9ae0SVaclav Hapla   if (!*label && !failNotFound) PetscFunctionReturn(0);
7186306894acSVaclav Hapla   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2);
7187306894acSVaclav Hapla   PetscValidLogicalCollectiveBool(dm, failNotFound, 3);
71885d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
718943e45a93SVaclav Hapla     if (*label == link->label) {
7190306894acSVaclav Hapla       hasLabel = PETSC_TRUE;
719143e45a93SVaclav Hapla       *pnext   = link->next; /* Remove from list */
7192306894acSVaclav Hapla       if (*label == dm->depthLabel) dm->depthLabel = NULL;
7193ba2698f1SMatthew G. Knepley       if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL;
719443e45a93SVaclav Hapla       if (((PetscObject)link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */
71959566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&link->label));
71969566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7197306894acSVaclav Hapla       break;
7198306894acSVaclav Hapla     }
7199306894acSVaclav Hapla   }
72007a8be351SBarry Smith   PetscCheck(hasLabel || !failNotFound, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM");
7201306894acSVaclav Hapla   PetscFunctionReturn(0);
7202306894acSVaclav Hapla }
7203306894acSVaclav Hapla 
7204c58f1c22SToby Isaac /*@C
7205c58f1c22SToby Isaac   DMGetLabelOutput - Get the output flag for a given label
7206c58f1c22SToby Isaac 
7207c58f1c22SToby Isaac   Not Collective
7208c58f1c22SToby Isaac 
7209c58f1c22SToby Isaac   Input Parameters:
7210bb7acecfSBarry Smith + dm   - The `DM` object
7211c58f1c22SToby Isaac - name - The label name
7212c58f1c22SToby Isaac 
7213c58f1c22SToby Isaac   Output Parameter:
7214c58f1c22SToby Isaac . output - The flag for output
7215c58f1c22SToby Isaac 
7216c58f1c22SToby Isaac   Level: developer
7217c58f1c22SToby Isaac 
7218bb7acecfSBarry Smith .seealso: `DMLabel`, `DMSetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7219c58f1c22SToby Isaac @*/
7220d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
7221d71ae5a4SJacob Faibussowitsch {
72225d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7223d67d17b1SMatthew G. Knepley   const char *lname;
7224c58f1c22SToby Isaac 
7225c58f1c22SToby Isaac   PetscFunctionBegin;
7226c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7227dadcf809SJacob Faibussowitsch   PetscValidCharPointer(name, 2);
7228dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(output, 3);
7229c58f1c22SToby Isaac   while (next) {
7230c58f1c22SToby Isaac     PetscBool flg;
7231c58f1c22SToby Isaac 
72329566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
72339566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
72349371c9d4SSatish Balay     if (flg) {
72359371c9d4SSatish Balay       *output = next->output;
72369371c9d4SSatish Balay       PetscFunctionReturn(0);
72379371c9d4SSatish Balay     }
7238c58f1c22SToby Isaac     next = next->next;
7239c58f1c22SToby Isaac   }
724098921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7241c58f1c22SToby Isaac }
7242c58f1c22SToby Isaac 
7243c58f1c22SToby Isaac /*@C
7244bb7acecfSBarry Smith   DMSetLabelOutput - Set if a given label should be saved to a `PetscViewer` in calls to `DMView()`
7245c58f1c22SToby Isaac 
7246c58f1c22SToby Isaac   Not Collective
7247c58f1c22SToby Isaac 
7248c58f1c22SToby Isaac   Input Parameters:
7249bb7acecfSBarry Smith + dm     - The `DM` object
7250c58f1c22SToby Isaac . name   - The label name
7251bb7acecfSBarry Smith - output - `PETSC_TRUE` to save the label to the viewer
7252c58f1c22SToby Isaac 
7253c58f1c22SToby Isaac   Level: developer
7254c58f1c22SToby Isaac 
7255bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetOutputFlag()`, `DMGetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7256c58f1c22SToby Isaac @*/
7257d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
7258d71ae5a4SJacob Faibussowitsch {
72595d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7260d67d17b1SMatthew G. Knepley   const char *lname;
7261c58f1c22SToby Isaac 
7262c58f1c22SToby Isaac   PetscFunctionBegin;
7263c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7264534a8f05SLisandro Dalcin   PetscValidCharPointer(name, 2);
7265c58f1c22SToby Isaac   while (next) {
7266c58f1c22SToby Isaac     PetscBool flg;
7267c58f1c22SToby Isaac 
72689566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
72699566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
72709371c9d4SSatish Balay     if (flg) {
72719371c9d4SSatish Balay       next->output = output;
72729371c9d4SSatish Balay       PetscFunctionReturn(0);
72739371c9d4SSatish Balay     }
7274c58f1c22SToby Isaac     next = next->next;
7275c58f1c22SToby Isaac   }
727698921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7277c58f1c22SToby Isaac }
7278c58f1c22SToby Isaac 
7279c58f1c22SToby Isaac /*@
7280bb7acecfSBarry Smith   DMCopyLabels - Copy labels from one `DM` mesh to another `DM` with a superset of the points
7281c58f1c22SToby Isaac 
7282d083f849SBarry Smith   Collective on dmA
7283c58f1c22SToby Isaac 
7284d8d19677SJose E. Roman   Input Parameters:
7285bb7acecfSBarry Smith + dmA - The `DM` object with initial labels
7286bb7acecfSBarry Smith . dmB - The `DM` object to which labels are copied
7287bb7acecfSBarry Smith . mode - Copy labels by pointers (`PETSC_OWN_POINTER`) or duplicate them (`PETSC_COPY_VALUES`)
7288bb7acecfSBarry Smith . all  - Copy all labels including "depth", "dim", and "celltype" (`PETSC_TRUE`) which are otherwise ignored (`PETSC_FALSE`)
7289bb7acecfSBarry Smith - emode - How to behave when a `DMLabel` in the source and destination `DM`s with the same name is encountered (see `DMCopyLabelsMode`)
7290c58f1c22SToby Isaac 
7291c58f1c22SToby Isaac   Level: intermediate
7292c58f1c22SToby Isaac 
7293bb7acecfSBarry Smith   Note:
72942cbb9b06SVaclav Hapla   This is typically used when interpolating or otherwise adding to a mesh, or testing.
7295c58f1c22SToby Isaac 
7296bb7acecfSBarry Smith .seealso: `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`
7297c58f1c22SToby Isaac @*/
7298d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all, DMCopyLabelsMode emode)
7299d71ae5a4SJacob Faibussowitsch {
73002cbb9b06SVaclav Hapla   DMLabel     label, labelNew, labelOld;
7301c58f1c22SToby Isaac   const char *name;
7302c58f1c22SToby Isaac   PetscBool   flg;
73035d80c0bfSVaclav Hapla   DMLabelLink link;
7304c58f1c22SToby Isaac 
73055d80c0bfSVaclav Hapla   PetscFunctionBegin;
73065d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
73075d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
73085d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveEnum(dmA, mode, 3);
73095d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveBool(dmA, all, 4);
73107a8be351SBarry Smith   PetscCheck(mode != PETSC_USE_POINTER, PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects");
73115d80c0bfSVaclav Hapla   if (dmA == dmB) PetscFunctionReturn(0);
73125d80c0bfSVaclav Hapla   for (link = dmA->labels; link; link = link->next) {
73135d80c0bfSVaclav Hapla     label = link->label;
73149566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
73155d80c0bfSVaclav Hapla     if (!all) {
73169566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &flg));
7317c58f1c22SToby Isaac       if (flg) continue;
73189566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "dim", &flg));
73197d5acc75SStefano Zampini       if (flg) continue;
73209566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &flg));
7321ba2698f1SMatthew G. Knepley       if (flg) continue;
73225d80c0bfSVaclav Hapla     }
73239566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dmB, name, &labelOld));
73242cbb9b06SVaclav Hapla     if (labelOld) {
73252cbb9b06SVaclav Hapla       switch (emode) {
7326d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_KEEP:
7327d71ae5a4SJacob Faibussowitsch         continue;
7328d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_REPLACE:
7329d71ae5a4SJacob Faibussowitsch         PetscCall(DMRemoveLabelBySelf(dmB, &labelOld, PETSC_TRUE));
7330d71ae5a4SJacob Faibussowitsch         break;
7331d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_FAIL:
7332d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in destination DM", name);
7333d71ae5a4SJacob Faibussowitsch       default:
7334d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Unhandled DMCopyLabelsMode %d", (int)emode);
73352cbb9b06SVaclav Hapla       }
73362cbb9b06SVaclav Hapla     }
73375d80c0bfSVaclav Hapla     if (mode == PETSC_COPY_VALUES) {
73389566063dSJacob Faibussowitsch       PetscCall(DMLabelDuplicate(label, &labelNew));
73395d80c0bfSVaclav Hapla     } else {
73405d80c0bfSVaclav Hapla       labelNew = label;
73415d80c0bfSVaclav Hapla     }
73429566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dmB, labelNew));
73439566063dSJacob Faibussowitsch     if (mode == PETSC_COPY_VALUES) PetscCall(DMLabelDestroy(&labelNew));
7344c58f1c22SToby Isaac   }
7345c58f1c22SToby Isaac   PetscFunctionReturn(0);
7346c58f1c22SToby Isaac }
7347461a15a0SLisandro Dalcin 
7348609dae6eSVaclav Hapla /*@C
7349bb7acecfSBarry Smith   DMCompareLabels - Compare labels of two `DMPLEX` meshes
7350609dae6eSVaclav Hapla 
73515efe38ccSVaclav Hapla   Collective
7352609dae6eSVaclav Hapla 
7353609dae6eSVaclav Hapla   Input Parameters:
7354bb7acecfSBarry Smith + dm0 - First `DM` object
7355bb7acecfSBarry Smith - dm1 - Second `DM` object
7356609dae6eSVaclav Hapla 
7357609dae6eSVaclav Hapla   Output Parameters
73585efe38ccSVaclav Hapla + equal   - (Optional) Flag whether labels of dm0 and dm1 are the same
7359609dae6eSVaclav Hapla - message - (Optional) Message describing the difference, or NULL if there is no difference
7360609dae6eSVaclav Hapla 
7361609dae6eSVaclav Hapla   Level: intermediate
7362609dae6eSVaclav Hapla 
7363609dae6eSVaclav Hapla   Notes:
7364bb7acecfSBarry Smith   The output flag equal will be the same on all processes.
7365bb7acecfSBarry Smith 
7366bb7acecfSBarry Smith   If equal is passed as NULL and difference is found, an error is thrown on all processes.
7367bb7acecfSBarry Smith 
7368bb7acecfSBarry Smith   Make sure to pass equal is NULL on all processes or none of them.
7369609dae6eSVaclav Hapla 
73705efe38ccSVaclav Hapla   The output message is set independently on each rank.
7371bb7acecfSBarry Smith 
7372bb7acecfSBarry Smith   message must be freed with `PetscFree()`
7373bb7acecfSBarry Smith 
7374bb7acecfSBarry Smith   If message is passed as NULL and a difference is found, the difference description is printed to stderr in synchronized manner.
7375bb7acecfSBarry Smith 
7376bb7acecfSBarry Smith   Make sure to pass message as NULL on all processes or no processes.
7377609dae6eSVaclav Hapla 
7378609dae6eSVaclav Hapla   Labels are matched by name. If the number of labels and their names are equal,
7379bb7acecfSBarry Smith   `DMLabelCompare()` is used to compare each pair of labels with the same name.
7380609dae6eSVaclav Hapla 
7381bb7acecfSBarry Smith   Fortran Note:
7382bb7acecfSBarry Smith   This function is not available from Fortran.
7383609dae6eSVaclav Hapla 
7384bb7acecfSBarry Smith .seealso: `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`, `DMLabelCompare()`
7385609dae6eSVaclav Hapla @*/
7386d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompareLabels(DM dm0, DM dm1, PetscBool *equal, char **message)
7387d71ae5a4SJacob Faibussowitsch {
73885efe38ccSVaclav Hapla   PetscInt    n, i;
7389609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
73905efe38ccSVaclav Hapla   PetscBool   eq;
7391609dae6eSVaclav Hapla   MPI_Comm    comm;
73925efe38ccSVaclav Hapla   PetscMPIInt rank;
7393609dae6eSVaclav Hapla 
7394609dae6eSVaclav Hapla   PetscFunctionBegin;
7395609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm0, DM_CLASSID, 1);
7396609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm1, DM_CLASSID, 2);
7397609dae6eSVaclav Hapla   PetscCheckSameComm(dm0, 1, dm1, 2);
73985efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 3);
7399609dae6eSVaclav Hapla   if (message) PetscValidPointer(message, 4);
74009566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm0, &comm));
74019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
74025efe38ccSVaclav Hapla   {
74035efe38ccSVaclav Hapla     PetscInt n1;
74045efe38ccSVaclav Hapla 
74059566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm0, &n));
74069566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm1, &n1));
74075efe38ccSVaclav Hapla     eq = (PetscBool)(n == n1);
740848a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Number of labels in dm0 = %" PetscInt_FMT " != %" PetscInt_FMT " = Number of labels in dm1", n, n1));
74099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
74105efe38ccSVaclav Hapla     if (!eq) goto finish;
74115efe38ccSVaclav Hapla   }
74125efe38ccSVaclav Hapla   for (i = 0; i < n; i++) {
7413609dae6eSVaclav Hapla     DMLabel     l0, l1;
7414609dae6eSVaclav Hapla     const char *name;
7415609dae6eSVaclav Hapla     char       *msgInner;
7416609dae6eSVaclav Hapla 
7417609dae6eSVaclav Hapla     /* Ignore label order */
74189566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm0, i, &l0));
74199566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)l0, &name));
74209566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm1, name, &l1));
7421609dae6eSVaclav Hapla     if (!l1) {
742263a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Label \"%s\" (#%" PetscInt_FMT " in dm0) not found in dm1", name, i));
74235efe38ccSVaclav Hapla       eq = PETSC_FALSE;
74245efe38ccSVaclav Hapla       break;
7425609dae6eSVaclav Hapla     }
74269566063dSJacob Faibussowitsch     PetscCall(DMLabelCompare(comm, l0, l1, &eq, &msgInner));
74279566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(msg, msgInner, sizeof(msg)));
74289566063dSJacob Faibussowitsch     PetscCall(PetscFree(msgInner));
74295efe38ccSVaclav Hapla     if (!eq) break;
7430609dae6eSVaclav Hapla   }
74319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
7432609dae6eSVaclav Hapla finish:
74335efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
7434609dae6eSVaclav Hapla   if (message) {
7435609dae6eSVaclav Hapla     *message = NULL;
743648a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
74375efe38ccSVaclav Hapla   } else {
743848a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
74399566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
74405efe38ccSVaclav Hapla   }
74415efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
74425efe38ccSVaclav Hapla   if (equal) *equal = eq;
74437a8be351SBarry Smith   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels are not the same in dm0 and dm1");
7444609dae6eSVaclav Hapla   PetscFunctionReturn(0);
7445609dae6eSVaclav Hapla }
7446609dae6eSVaclav Hapla 
7447d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value)
7448d71ae5a4SJacob Faibussowitsch {
7449461a15a0SLisandro Dalcin   PetscFunctionBegin;
7450461a15a0SLisandro Dalcin   PetscValidPointer(label, 2);
7451461a15a0SLisandro Dalcin   if (!*label) {
74529566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
74539566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, label));
7454461a15a0SLisandro Dalcin   }
74559566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(*label, point, value));
7456461a15a0SLisandro Dalcin   PetscFunctionReturn(0);
7457461a15a0SLisandro Dalcin }
7458461a15a0SLisandro Dalcin 
74590fdc7489SMatthew Knepley /*
74600fdc7489SMatthew Knepley   Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would
74610fdc7489SMatthew Knepley   like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every
74620fdc7489SMatthew Knepley   (label, id) pair in the DM.
74630fdc7489SMatthew Knepley 
74640fdc7489SMatthew Knepley   However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to
74650fdc7489SMatthew Knepley   each label.
74660fdc7489SMatthew Knepley */
7467d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal)
7468d71ae5a4SJacob Faibussowitsch {
74690fdc7489SMatthew Knepley   DMUniversalLabel ul;
74700fdc7489SMatthew Knepley   PetscBool       *active;
74710fdc7489SMatthew Knepley   PetscInt         pStart, pEnd, p, Nl, l, m;
74720fdc7489SMatthew Knepley 
74730fdc7489SMatthew Knepley   PetscFunctionBegin;
74749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, &ul));
74759566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label));
74769566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
74779566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Nl, &active));
74780fdc7489SMatthew Knepley   ul->Nl = 0;
74790fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
74800fdc7489SMatthew Knepley     PetscBool   isdepth, iscelltype;
74810fdc7489SMatthew Knepley     const char *name;
74820fdc7489SMatthew Knepley 
74839566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
74849566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "depth", 6, &isdepth));
74859566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "celltype", 9, &iscelltype));
74860fdc7489SMatthew Knepley     active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE;
74870fdc7489SMatthew Knepley     if (active[l]) ++ul->Nl;
74880fdc7489SMatthew Knepley   }
74899566063dSJacob 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));
74900fdc7489SMatthew Knepley   ul->Nv = 0;
74910fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
74920fdc7489SMatthew Knepley     DMLabel     label;
74930fdc7489SMatthew Knepley     PetscInt    nv;
74940fdc7489SMatthew Knepley     const char *name;
74950fdc7489SMatthew Knepley 
74960fdc7489SMatthew Knepley     if (!active[l]) continue;
74979566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
74989566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
74999566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
75009566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &ul->names[m]));
75010fdc7489SMatthew Knepley     ul->indices[m] = l;
75020fdc7489SMatthew Knepley     ul->Nv += nv;
75030fdc7489SMatthew Knepley     ul->offsets[m + 1] = nv;
75040fdc7489SMatthew Knepley     ul->bits[m + 1]    = PetscCeilReal(PetscLog2Real(nv + 1));
75050fdc7489SMatthew Knepley     ++m;
75060fdc7489SMatthew Knepley   }
75070fdc7489SMatthew Knepley   for (l = 1; l <= ul->Nl; ++l) {
75080fdc7489SMatthew Knepley     ul->offsets[l] = ul->offsets[l - 1] + ul->offsets[l];
75090fdc7489SMatthew Knepley     ul->bits[l]    = ul->bits[l - 1] + ul->bits[l];
75100fdc7489SMatthew Knepley   }
75110fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
75120fdc7489SMatthew Knepley     PetscInt b;
75130fdc7489SMatthew Knepley 
75140fdc7489SMatthew Knepley     ul->masks[l] = 0;
75150fdc7489SMatthew Knepley     for (b = ul->bits[l]; b < ul->bits[l + 1]; ++b) ul->masks[l] |= 1 << b;
75160fdc7489SMatthew Knepley   }
75179566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ul->Nv, &ul->values));
75180fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
75190fdc7489SMatthew Knepley     DMLabel         label;
75200fdc7489SMatthew Knepley     IS              valueIS;
75210fdc7489SMatthew Knepley     const PetscInt *varr;
75220fdc7489SMatthew Knepley     PetscInt        nv, v;
75230fdc7489SMatthew Knepley 
75240fdc7489SMatthew Knepley     if (!active[l]) continue;
75259566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
75269566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
75279566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, &valueIS));
75289566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(valueIS, &varr));
7529ad540459SPierre Jolivet     for (v = 0; v < nv; ++v) ul->values[ul->offsets[m] + v] = varr[v];
75309566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(valueIS, &varr));
75319566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&valueIS));
75329566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(nv, &ul->values[ul->offsets[m]]));
75330fdc7489SMatthew Knepley     ++m;
75340fdc7489SMatthew Knepley   }
75359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
75360fdc7489SMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
75370fdc7489SMatthew Knepley     PetscInt  uval   = 0;
75380fdc7489SMatthew Knepley     PetscBool marked = PETSC_FALSE;
75390fdc7489SMatthew Knepley 
75400fdc7489SMatthew Knepley     for (l = 0, m = 0; l < Nl; ++l) {
75410fdc7489SMatthew Knepley       DMLabel  label;
75420649b39aSStefano Zampini       PetscInt val, defval, loc, nv;
75430fdc7489SMatthew Knepley 
75440fdc7489SMatthew Knepley       if (!active[l]) continue;
75459566063dSJacob Faibussowitsch       PetscCall(DMGetLabelByNum(dm, l, &label));
75469566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, p, &val));
75479566063dSJacob Faibussowitsch       PetscCall(DMLabelGetDefaultValue(label, &defval));
75489371c9d4SSatish Balay       if (val == defval) {
75499371c9d4SSatish Balay         ++m;
75509371c9d4SSatish Balay         continue;
75519371c9d4SSatish Balay       }
75520649b39aSStefano Zampini       nv     = ul->offsets[m + 1] - ul->offsets[m];
75530fdc7489SMatthew Knepley       marked = PETSC_TRUE;
75549566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc));
755563a3b9bcSJacob Faibussowitsch       PetscCheck(loc >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %" PetscInt_FMT " not found in compression array", val);
75560fdc7489SMatthew Knepley       uval += (loc + 1) << ul->bits[m];
75570fdc7489SMatthew Knepley       ++m;
75580fdc7489SMatthew Knepley     }
75599566063dSJacob Faibussowitsch     if (marked) PetscCall(DMLabelSetValue(ul->label, p, uval));
75600fdc7489SMatthew Knepley   }
75619566063dSJacob Faibussowitsch   PetscCall(PetscFree(active));
75620fdc7489SMatthew Knepley   *universal = ul;
75630fdc7489SMatthew Knepley   PetscFunctionReturn(0);
75640fdc7489SMatthew Knepley }
75650fdc7489SMatthew Knepley 
7566d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal)
7567d71ae5a4SJacob Faibussowitsch {
75680fdc7489SMatthew Knepley   PetscInt l;
75690fdc7489SMatthew Knepley 
75700fdc7489SMatthew Knepley   PetscFunctionBegin;
75719566063dSJacob Faibussowitsch   for (l = 0; l < (*universal)->Nl; ++l) PetscCall(PetscFree((*universal)->names[l]));
75729566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&(*universal)->label));
75739566063dSJacob Faibussowitsch   PetscCall(PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks));
75749566063dSJacob Faibussowitsch   PetscCall(PetscFree((*universal)->values));
75759566063dSJacob Faibussowitsch   PetscCall(PetscFree(*universal));
75760fdc7489SMatthew Knepley   *universal = NULL;
75770fdc7489SMatthew Knepley   PetscFunctionReturn(0);
75780fdc7489SMatthew Knepley }
75790fdc7489SMatthew Knepley 
7580d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel)
7581d71ae5a4SJacob Faibussowitsch {
75820fdc7489SMatthew Knepley   PetscFunctionBegin;
75830fdc7489SMatthew Knepley   PetscValidPointer(ulabel, 2);
75840fdc7489SMatthew Knepley   *ulabel = ul->label;
75850fdc7489SMatthew Knepley   PetscFunctionReturn(0);
75860fdc7489SMatthew Knepley }
75870fdc7489SMatthew Knepley 
7588d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm)
7589d71ae5a4SJacob Faibussowitsch {
75900fdc7489SMatthew Knepley   PetscInt Nl = ul->Nl, l;
75910fdc7489SMatthew Knepley 
75920fdc7489SMatthew Knepley   PetscFunctionBegin;
7593064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 3);
75940fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
75959566063dSJacob Faibussowitsch     if (preserveOrder) PetscCall(DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]));
75969566063dSJacob Faibussowitsch     else PetscCall(DMCreateLabel(dm, ul->names[l]));
75970fdc7489SMatthew Knepley   }
75980fdc7489SMatthew Knepley   if (preserveOrder) {
75990fdc7489SMatthew Knepley     for (l = 0; l < ul->Nl; ++l) {
76000fdc7489SMatthew Knepley       const char *name;
76010fdc7489SMatthew Knepley       PetscBool   match;
76020fdc7489SMatthew Knepley 
76039566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, ul->indices[l], &name));
76049566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, ul->names[l], &match));
760563a3b9bcSJacob 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]);
76060fdc7489SMatthew Knepley     }
76070fdc7489SMatthew Knepley   }
76080fdc7489SMatthew Knepley   PetscFunctionReturn(0);
76090fdc7489SMatthew Knepley }
76100fdc7489SMatthew Knepley 
7611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value)
7612d71ae5a4SJacob Faibussowitsch {
76130fdc7489SMatthew Knepley   PetscInt l;
76140fdc7489SMatthew Knepley 
76150fdc7489SMatthew Knepley   PetscFunctionBegin;
76160fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
76170fdc7489SMatthew Knepley     DMLabel  label;
76180fdc7489SMatthew Knepley     PetscInt lval = (value & ul->masks[l]) >> ul->bits[l];
76190fdc7489SMatthew Knepley 
76200fdc7489SMatthew Knepley     if (lval) {
76219566063dSJacob Faibussowitsch       if (useIndex) PetscCall(DMGetLabelByNum(dm, ul->indices[l], &label));
76229566063dSJacob Faibussowitsch       else PetscCall(DMGetLabel(dm, ul->names[l], &label));
76239566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(label, p, ul->values[ul->offsets[l] + lval - 1]));
76240fdc7489SMatthew Knepley     }
76250fdc7489SMatthew Knepley   }
76260fdc7489SMatthew Knepley   PetscFunctionReturn(0);
76270fdc7489SMatthew Knepley }
7628a8fb8f29SToby Isaac 
7629a8fb8f29SToby Isaac /*@
7630bb7acecfSBarry Smith   DMGetCoarseDM - Get the coarse `DM`from which this `DM` was obtained by refinement
7631bb7acecfSBarry Smith 
7632bb7acecfSBarry Smith   Not collective
7633a8fb8f29SToby Isaac 
7634a8fb8f29SToby Isaac   Input Parameter:
7635bb7acecfSBarry Smith . dm - The `DM` object
7636a8fb8f29SToby Isaac 
7637a8fb8f29SToby Isaac   Output Parameter:
7638bb7acecfSBarry Smith . cdm - The coarse `DM`
7639a8fb8f29SToby Isaac 
7640a8fb8f29SToby Isaac   Level: intermediate
7641a8fb8f29SToby Isaac 
7642bb7acecfSBarry Smith .seealso: `DMSetCoarseDM()`, `DMCoarsen()`
7643a8fb8f29SToby Isaac @*/
7644d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
7645d71ae5a4SJacob Faibussowitsch {
7646a8fb8f29SToby Isaac   PetscFunctionBegin;
7647a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7648a8fb8f29SToby Isaac   PetscValidPointer(cdm, 2);
7649a8fb8f29SToby Isaac   *cdm = dm->coarseMesh;
7650a8fb8f29SToby Isaac   PetscFunctionReturn(0);
7651a8fb8f29SToby Isaac }
7652a8fb8f29SToby Isaac 
7653a8fb8f29SToby Isaac /*@
7654bb7acecfSBarry Smith   DMSetCoarseDM - Set the coarse `DM` from which this `DM` was obtained by refinement
7655a8fb8f29SToby Isaac 
7656a8fb8f29SToby Isaac   Input Parameters:
7657bb7acecfSBarry Smith + dm - The `DM` object
7658bb7acecfSBarry Smith - cdm - The coarse `DM`
7659a8fb8f29SToby Isaac 
7660a8fb8f29SToby Isaac   Level: intermediate
7661a8fb8f29SToby Isaac 
7662bb7acecfSBarry Smith   Note:
7663bb7acecfSBarry Smith   Normally this is set automatically by `DMRefine()`
7664bb7acecfSBarry Smith 
7665bb7acecfSBarry Smith .seealso: `DMGetCoarseDM()`, `DMCoarsen()`, `DMSetRefine()`, `DMSetFineDM()`
7666a8fb8f29SToby Isaac @*/
7667d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
7668d71ae5a4SJacob Faibussowitsch {
7669a8fb8f29SToby Isaac   PetscFunctionBegin;
7670a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7671a8fb8f29SToby Isaac   if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
767289d734beSBarry Smith   if (dm == cdm) cdm = NULL;
76739566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)cdm));
76749566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->coarseMesh));
7675a8fb8f29SToby Isaac   dm->coarseMesh = cdm;
7676a8fb8f29SToby Isaac   PetscFunctionReturn(0);
7677a8fb8f29SToby Isaac }
7678a8fb8f29SToby Isaac 
767988bdff64SToby Isaac /*@
7680bb7acecfSBarry Smith   DMGetFineDM - Get the fine mesh from which this `DM` was obtained by coarsening
768188bdff64SToby Isaac 
768288bdff64SToby Isaac   Input Parameter:
7683bb7acecfSBarry Smith . dm - The `DM` object
768488bdff64SToby Isaac 
768588bdff64SToby Isaac   Output Parameter:
7686bb7acecfSBarry Smith . fdm - The fine `DM`
768788bdff64SToby Isaac 
768888bdff64SToby Isaac   Level: intermediate
768988bdff64SToby Isaac 
7690bb7acecfSBarry Smith .seealso: `DMSetFineDM()`, `DMCoarsen()`, `DMRefine()`
769188bdff64SToby Isaac @*/
7692d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
7693d71ae5a4SJacob Faibussowitsch {
769488bdff64SToby Isaac   PetscFunctionBegin;
769588bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
769688bdff64SToby Isaac   PetscValidPointer(fdm, 2);
769788bdff64SToby Isaac   *fdm = dm->fineMesh;
769888bdff64SToby Isaac   PetscFunctionReturn(0);
769988bdff64SToby Isaac }
770088bdff64SToby Isaac 
770188bdff64SToby Isaac /*@
7702bb7acecfSBarry Smith   DMSetFineDM - Set the fine mesh from which this was obtained by coarsening
770388bdff64SToby Isaac 
770488bdff64SToby Isaac   Input Parameters:
7705bb7acecfSBarry Smith + dm - The `DM` object
7706bb7acecfSBarry Smith - fdm - The fine `DM`
770788bdff64SToby Isaac 
7708bb7acecfSBarry Smith   Level: developer
770988bdff64SToby Isaac 
7710bb7acecfSBarry Smith   Note:
7711bb7acecfSBarry Smith   Normally this is set automatically by `DMCoarsen()`
7712bb7acecfSBarry Smith 
7713bb7acecfSBarry Smith .seealso: `DMGetFineDM()`, `DMCoarsen()`, `DMRefine()`
771488bdff64SToby Isaac @*/
7715d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFineDM(DM dm, DM fdm)
7716d71ae5a4SJacob Faibussowitsch {
771788bdff64SToby Isaac   PetscFunctionBegin;
771888bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
771988bdff64SToby Isaac   if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2);
772089d734beSBarry Smith   if (dm == fdm) fdm = NULL;
77219566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fdm));
77229566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->fineMesh));
772388bdff64SToby Isaac   dm->fineMesh = fdm;
772488bdff64SToby Isaac   PetscFunctionReturn(0);
772588bdff64SToby Isaac }
772688bdff64SToby Isaac 
7727a6ba4734SToby Isaac /*@C
7728bb7acecfSBarry Smith   DMAddBoundary - Add a boundary condition to a model represented by a `DM`
7729a6ba4734SToby Isaac 
7730783e2ec8SMatthew G. Knepley   Collective on dm
7731783e2ec8SMatthew G. Knepley 
7732a6ba4734SToby Isaac   Input Parameters:
7733bb7acecfSBarry Smith + dm       - The `DM`, with a `PetscDS` that matches the problem being constrained
7734bb7acecfSBarry Smith . type     - The type of condition, e.g. `DM_BC_ESSENTIAL_ANALYTIC`, `DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
7735a6ba4734SToby Isaac . name     - The BC name
773645480ffeSMatthew G. Knepley . label    - The label defining constrained points
7737bb7acecfSBarry Smith . Nv       - The number of `DMLabel` values for constrained points
773845480ffeSMatthew G. Knepley . values   - An array of values for constrained points
7739a6ba4734SToby Isaac . field    - The field to constrain
774045480ffeSMatthew G. Knepley . Nc       - The number of constrained field components (0 will constrain all fields)
7741a6ba4734SToby Isaac . comps    - An array of constrained component numbers
7742a6ba4734SToby Isaac . bcFunc   - A pointwise function giving boundary values
774356cf3b9cSMatthew G. Knepley . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL
7744a6ba4734SToby Isaac - ctx      - An optional user context for bcFunc
7745a6ba4734SToby Isaac 
774645480ffeSMatthew G. Knepley   Output Parameter:
774745480ffeSMatthew G. Knepley . bd          - (Optional) Boundary number
774845480ffeSMatthew G. Knepley 
7749a6ba4734SToby Isaac   Options Database Keys:
7750a6ba4734SToby Isaac + -bc_<boundary name> <num> - Overrides the boundary ids
7751a6ba4734SToby Isaac - -bc_<boundary name>_comp <num> - Overrides the boundary components
7752a6ba4734SToby Isaac 
7753bb7acecfSBarry Smith   Notes:
7754bb7acecfSBarry 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:
775556cf3b9cSMatthew G. Knepley 
775656cf3b9cSMatthew G. Knepley $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
775756cf3b9cSMatthew G. Knepley 
7758bb7acecfSBarry Smith   If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is:
775956cf3b9cSMatthew G. Knepley 
776056cf3b9cSMatthew G. Knepley $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
776156cf3b9cSMatthew G. Knepley $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
776256cf3b9cSMatthew G. Knepley $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
776356cf3b9cSMatthew G. Knepley $        PetscReal time, const PetscReal x[], PetscScalar bcval[])
776456cf3b9cSMatthew G. Knepley 
776556cf3b9cSMatthew G. Knepley + dim - the spatial dimension
776656cf3b9cSMatthew G. Knepley . Nf - the number of fields
776756cf3b9cSMatthew G. Knepley . uOff - the offset into u[] and u_t[] for each field
776856cf3b9cSMatthew G. Knepley . uOff_x - the offset into u_x[] for each field
776956cf3b9cSMatthew G. Knepley . u - each field evaluated at the current point
777056cf3b9cSMatthew G. Knepley . u_t - the time derivative of each field evaluated at the current point
777156cf3b9cSMatthew G. Knepley . u_x - the gradient of each field evaluated at the current point
777256cf3b9cSMatthew G. Knepley . aOff - the offset into a[] and a_t[] for each auxiliary field
777356cf3b9cSMatthew G. Knepley . aOff_x - the offset into a_x[] for each auxiliary field
777456cf3b9cSMatthew G. Knepley . a - each auxiliary field evaluated at the current point
777556cf3b9cSMatthew G. Knepley . a_t - the time derivative of each auxiliary field evaluated at the current point
777656cf3b9cSMatthew G. Knepley . a_x - the gradient of auxiliary each field evaluated at the current point
777756cf3b9cSMatthew G. Knepley . t - current time
777856cf3b9cSMatthew G. Knepley . x - coordinates of the current point
777956cf3b9cSMatthew G. Knepley . numConstants - number of constant parameters
778056cf3b9cSMatthew G. Knepley . constants - constant parameters
778156cf3b9cSMatthew G. Knepley - bcval - output values at the current point
778256cf3b9cSMatthew G. Knepley 
7783ed808b8fSJed Brown   Level: intermediate
7784a6ba4734SToby Isaac 
7785db781477SPatrick Sanan .seealso: `DSGetBoundary()`, `PetscDSAddBoundary()`
7786a6ba4734SToby Isaac @*/
7787d71ae5a4SJacob 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)
7788d71ae5a4SJacob Faibussowitsch {
7789e5e52638SMatthew G. Knepley   PetscDS ds;
7790a6ba4734SToby Isaac 
7791a6ba4734SToby Isaac   PetscFunctionBegin;
7792a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7793783e2ec8SMatthew G. Knepley   PetscValidLogicalCollectiveEnum(dm, type, 2);
779445480ffeSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
779545480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nv, 5);
779645480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, field, 7);
779745480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 8);
779801a5d20dSJed Brown   PetscCheck(!dm->localSection, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot add boundary to DM after creating local section");
77999566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
7800799db056SMatthew G. Knepley   /* Complete label */
7801799db056SMatthew G. Knepley   if (label) {
7802799db056SMatthew G. Knepley     PetscObject  obj;
7803799db056SMatthew G. Knepley     PetscClassId id;
7804799db056SMatthew G. Knepley 
7805799db056SMatthew G. Knepley     PetscCall(DMGetField(dm, field, NULL, &obj));
7806799db056SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
7807799db056SMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
7808799db056SMatthew G. Knepley       DM plex;
7809799db056SMatthew G. Knepley 
7810799db056SMatthew G. Knepley       PetscCall(DMConvert(dm, DMPLEX, &plex));
7811799db056SMatthew G. Knepley       if (plex) PetscCall(DMPlexLabelComplete(plex, label));
7812799db056SMatthew G. Knepley       PetscCall(DMDestroy(&plex));
7813799db056SMatthew G. Knepley     }
7814799db056SMatthew G. Knepley   }
78159566063dSJacob Faibussowitsch   PetscCall(PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd));
7816a6ba4734SToby Isaac   PetscFunctionReturn(0);
7817a6ba4734SToby Isaac }
7818a6ba4734SToby Isaac 
781945480ffeSMatthew G. Knepley /* TODO Remove this since now the structures are the same */
7820d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPopulateBoundary(DM dm)
7821d71ae5a4SJacob Faibussowitsch {
7822e5e52638SMatthew G. Knepley   PetscDS     ds;
7823dff059c6SToby Isaac   DMBoundary *lastnext;
7824e6f8dbb6SToby Isaac   DSBoundary  dsbound;
7825e6f8dbb6SToby Isaac 
7826e6f8dbb6SToby Isaac   PetscFunctionBegin;
78279566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
7828e5e52638SMatthew G. Knepley   dsbound = ds->boundary;
782947a1f5adSToby Isaac   if (dm->boundary) {
783047a1f5adSToby Isaac     DMBoundary next = dm->boundary;
783147a1f5adSToby Isaac 
783247a1f5adSToby Isaac     /* quick check to see if the PetscDS has changed */
783347a1f5adSToby Isaac     if (next->dsboundary == dsbound) PetscFunctionReturn(0);
783447a1f5adSToby Isaac     /* the PetscDS has changed: tear down and rebuild */
783547a1f5adSToby Isaac     while (next) {
783647a1f5adSToby Isaac       DMBoundary b = next;
783747a1f5adSToby Isaac 
783847a1f5adSToby Isaac       next = b->next;
78399566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
7840a6ba4734SToby Isaac     }
784147a1f5adSToby Isaac     dm->boundary = NULL;
7842a6ba4734SToby Isaac   }
784347a1f5adSToby Isaac 
7844dff059c6SToby Isaac   lastnext = &(dm->boundary);
7845e6f8dbb6SToby Isaac   while (dsbound) {
7846e6f8dbb6SToby Isaac     DMBoundary dmbound;
7847e6f8dbb6SToby Isaac 
78489566063dSJacob Faibussowitsch     PetscCall(PetscNew(&dmbound));
7849e6f8dbb6SToby Isaac     dmbound->dsboundary = dsbound;
785045480ffeSMatthew G. Knepley     dmbound->label      = dsbound->label;
785147a1f5adSToby Isaac     /* push on the back instead of the front so that it is in the same order as in the PetscDS */
7852dff059c6SToby Isaac     *lastnext = dmbound;
7853dff059c6SToby Isaac     lastnext  = &(dmbound->next);
7854dff059c6SToby Isaac     dsbound   = dsbound->next;
7855a6ba4734SToby Isaac   }
7856a6ba4734SToby Isaac   PetscFunctionReturn(0);
7857a6ba4734SToby Isaac }
7858a6ba4734SToby Isaac 
7859bb7acecfSBarry Smith /* TODO: missing manual page */
7860d71ae5a4SJacob Faibussowitsch PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
7861d71ae5a4SJacob Faibussowitsch {
7862b95f2879SToby Isaac   DMBoundary b;
7863a6ba4734SToby Isaac 
7864a6ba4734SToby Isaac   PetscFunctionBegin;
7865a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7866534a8f05SLisandro Dalcin   PetscValidBoolPointer(isBd, 3);
7867a6ba4734SToby Isaac   *isBd = PETSC_FALSE;
78689566063dSJacob Faibussowitsch   PetscCall(DMPopulateBoundary(dm));
7869b95f2879SToby Isaac   b = dm->boundary;
7870a6ba4734SToby Isaac   while (b && !(*isBd)) {
7871e6f8dbb6SToby Isaac     DMLabel    label = b->label;
7872e6f8dbb6SToby Isaac     DSBoundary dsb   = b->dsboundary;
7873a6ba4734SToby Isaac     PetscInt   i;
7874a6ba4734SToby Isaac 
787545480ffeSMatthew G. Knepley     if (label) {
78769566063dSJacob Faibussowitsch       for (i = 0; i < dsb->Nv && !(*isBd); ++i) PetscCall(DMLabelStratumHasPoint(label, dsb->values[i], point, isBd));
7877a6ba4734SToby Isaac     }
7878a6ba4734SToby Isaac     b = b->next;
7879a6ba4734SToby Isaac   }
7880a6ba4734SToby Isaac   PetscFunctionReturn(0);
7881a6ba4734SToby Isaac }
78824d6f44ffSToby Isaac 
78834d6f44ffSToby Isaac /*@C
7884bb7acecfSBarry Smith   DMProjectFunction - This projects the given function into the function space provided by a `DM`, putting the coefficients in a global vector.
7885a6e0b375SMatthew G. Knepley 
7886bb7acecfSBarry Smith   Collective on dm
78874d6f44ffSToby Isaac 
78884d6f44ffSToby Isaac   Input Parameters:
7889bb7acecfSBarry Smith + dm      - The `DM`
78900709b2feSToby Isaac . time    - The time
78914d6f44ffSToby Isaac . funcs   - The coordinate functions to evaluate, one per field
78924d6f44ffSToby Isaac . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
78934d6f44ffSToby Isaac - mode    - The insertion mode for values
78944d6f44ffSToby Isaac 
78954d6f44ffSToby Isaac   Output Parameter:
78964d6f44ffSToby Isaac . X - vector
78974d6f44ffSToby Isaac 
78984d6f44ffSToby Isaac    Calling sequence of func:
789977b739a6SMatthew Knepley $    func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
79004d6f44ffSToby Isaac 
79014d6f44ffSToby Isaac +  dim - The spatial dimension
79028ec8862eSJed Brown .  time - The time at which to sample
79034d6f44ffSToby Isaac .  x   - The coordinates
790477b739a6SMatthew Knepley .  Nc  - The number of components
79054d6f44ffSToby Isaac .  u   - The output field values
79064d6f44ffSToby Isaac -  ctx - optional user-defined function context
79074d6f44ffSToby Isaac 
79084d6f44ffSToby Isaac   Level: developer
79094d6f44ffSToby Isaac 
7910bb7acecfSBarry Smith   Developer Notes:
7911bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
7912bb7acecfSBarry Smith 
7913bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
7914bb7acecfSBarry Smith 
7915db781477SPatrick Sanan .seealso: `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
79164d6f44ffSToby Isaac @*/
7917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
7918d71ae5a4SJacob Faibussowitsch {
79194d6f44ffSToby Isaac   Vec localX;
79204d6f44ffSToby Isaac 
79214d6f44ffSToby Isaac   PetscFunctionBegin;
79224d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79239566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
79249566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX));
79259566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
79269566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
79279566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
79284d6f44ffSToby Isaac   PetscFunctionReturn(0);
79294d6f44ffSToby Isaac }
79304d6f44ffSToby Isaac 
7931a6e0b375SMatthew G. Knepley /*@C
7932bb7acecfSBarry Smith   DMProjectFunctionLocal - This projects the given function into the function space provided by a `DM`, putting the coefficients in a local vector.
7933a6e0b375SMatthew G. Knepley 
7934a6e0b375SMatthew G. Knepley   Not collective
7935a6e0b375SMatthew G. Knepley 
7936a6e0b375SMatthew G. Knepley   Input Parameters:
7937bb7acecfSBarry Smith + dm      - The `DM`
7938a6e0b375SMatthew G. Knepley . time    - The time
7939a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
7940a6e0b375SMatthew G. Knepley . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
7941a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
7942a6e0b375SMatthew G. Knepley 
7943a6e0b375SMatthew G. Knepley   Output Parameter:
7944a6e0b375SMatthew G. Knepley . localX - vector
7945a6e0b375SMatthew G. Knepley 
7946a6e0b375SMatthew G. Knepley    Calling sequence of func:
794777b739a6SMatthew Knepley $    func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
7948a6e0b375SMatthew G. Knepley 
7949a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
7950a6e0b375SMatthew G. Knepley .  x   - The coordinates
795177b739a6SMatthew Knepley .  Nc  - The number of components
7952a6e0b375SMatthew G. Knepley .  u   - The output field values
7953a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
7954a6e0b375SMatthew G. Knepley 
7955a6e0b375SMatthew G. Knepley   Level: developer
7956a6e0b375SMatthew G. Knepley 
7957bb7acecfSBarry Smith   Developer Notes:
7958bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
7959bb7acecfSBarry Smith 
7960bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
7961bb7acecfSBarry Smith 
7962db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
7963a6e0b375SMatthew G. Knepley @*/
7964d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
7965d71ae5a4SJacob Faibussowitsch {
79664d6f44ffSToby Isaac   PetscFunctionBegin;
79674d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7968064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
79699566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfunctionlocal)(dm, time, funcs, ctxs, mode, localX));
79704d6f44ffSToby Isaac   PetscFunctionReturn(0);
79714d6f44ffSToby Isaac }
79724d6f44ffSToby Isaac 
7973a6e0b375SMatthew G. Knepley /*@C
7974bb7acecfSBarry 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.
7975a6e0b375SMatthew G. Knepley 
7976bb7acecfSBarry Smith   Collective on dm
7977a6e0b375SMatthew G. Knepley 
7978a6e0b375SMatthew G. Knepley   Input Parameters:
7979bb7acecfSBarry Smith + dm      - The `DM`
7980a6e0b375SMatthew G. Knepley . time    - The time
7981bb7acecfSBarry Smith . label   - The `DMLabel` selecting the portion of the mesh for projection
7982a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
7983bb7acecfSBarry Smith . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs may be null.
7984a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
7985a6e0b375SMatthew G. Knepley 
7986a6e0b375SMatthew G. Knepley   Output Parameter:
7987a6e0b375SMatthew G. Knepley . X - vector
7988a6e0b375SMatthew G. Knepley 
7989a6e0b375SMatthew G. Knepley    Calling sequence of func:
799077b739a6SMatthew Knepley $    func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
7991a6e0b375SMatthew G. Knepley 
7992a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
7993a6e0b375SMatthew G. Knepley .  x   - The coordinates
799477b739a6SMatthew Knepley .  Nc  - The number of components
7995a6e0b375SMatthew G. Knepley .  u   - The output field values
7996a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
7997a6e0b375SMatthew G. Knepley 
7998a6e0b375SMatthew G. Knepley   Level: developer
7999a6e0b375SMatthew G. Knepley 
8000bb7acecfSBarry Smith   Developer Notes:
8001bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8002bb7acecfSBarry Smith 
8003bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8004bb7acecfSBarry Smith 
8005db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabelLocal()`, `DMComputeL2Diff()`
8006a6e0b375SMatthew G. Knepley @*/
8007d71ae5a4SJacob 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)
8008d71ae5a4SJacob Faibussowitsch {
80092c53366bSMatthew G. Knepley   Vec localX;
80102c53366bSMatthew G. Knepley 
80112c53366bSMatthew G. Knepley   PetscFunctionBegin;
80122c53366bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80139566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
80149566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
80159566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
80169566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
80179566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
80182c53366bSMatthew G. Knepley   PetscFunctionReturn(0);
80192c53366bSMatthew G. Knepley }
80202c53366bSMatthew G. Knepley 
8021a6e0b375SMatthew G. Knepley /*@C
8022bb7acecfSBarry 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.
8023a6e0b375SMatthew G. Knepley 
8024a6e0b375SMatthew G. Knepley   Not collective
8025a6e0b375SMatthew G. Knepley 
8026a6e0b375SMatthew G. Knepley   Input Parameters:
8027bb7acecfSBarry Smith + dm      - The `DM`
8028a6e0b375SMatthew G. Knepley . time    - The time
8029bb7acecfSBarry Smith . label   - The `DMLabel` selecting the portion of the mesh for projection
8030a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
8031a6e0b375SMatthew G. Knepley . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
8032a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8033a6e0b375SMatthew G. Knepley 
8034a6e0b375SMatthew G. Knepley   Output Parameter:
8035a6e0b375SMatthew G. Knepley . localX - vector
8036a6e0b375SMatthew G. Knepley 
8037a6e0b375SMatthew G. Knepley    Calling sequence of func:
803877b739a6SMatthew Knepley $    func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
8039a6e0b375SMatthew G. Knepley 
8040a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
8041a6e0b375SMatthew G. Knepley .  x   - The coordinates
804277b739a6SMatthew Knepley .  Nc  - The number of components
8043a6e0b375SMatthew G. Knepley .  u   - The output field values
8044a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
8045a6e0b375SMatthew G. Knepley 
8046a6e0b375SMatthew G. Knepley   Level: developer
8047a6e0b375SMatthew G. Knepley 
8048bb7acecfSBarry Smith   Developer Notes:
8049bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8050bb7acecfSBarry Smith 
8051bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8052bb7acecfSBarry Smith 
8053db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
8054a6e0b375SMatthew G. Knepley @*/
8055d71ae5a4SJacob 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)
8056d71ae5a4SJacob Faibussowitsch {
80574d6f44ffSToby Isaac   PetscFunctionBegin;
80584d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8059064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
80609566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfunctionlabellocal)(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
80614d6f44ffSToby Isaac   PetscFunctionReturn(0);
80624d6f44ffSToby Isaac }
80632716604bSToby Isaac 
8064a6e0b375SMatthew G. Knepley /*@C
8065bb7acecfSBarry 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.
8066a6e0b375SMatthew G. Knepley 
8067a6e0b375SMatthew G. Knepley   Not collective
8068a6e0b375SMatthew G. Knepley 
8069a6e0b375SMatthew G. Knepley   Input Parameters:
8070bb7acecfSBarry Smith + dm      - The `DM`
8071a6e0b375SMatthew G. Knepley . time    - The time
8072a6e0b375SMatthew G. Knepley . localU  - The input field vector
8073a6e0b375SMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8074a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8075a6e0b375SMatthew G. Knepley 
8076a6e0b375SMatthew G. Knepley   Output Parameter:
8077a6e0b375SMatthew G. Knepley . localX  - The output vector
8078a6e0b375SMatthew G. Knepley 
8079a6e0b375SMatthew G. Knepley    Calling sequence of func:
8080a6e0b375SMatthew G. Knepley $    func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8081a6e0b375SMatthew G. Knepley $         const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8082a6e0b375SMatthew G. Knepley $         const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8083a6e0b375SMatthew G. Knepley $         PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8084a6e0b375SMatthew G. Knepley 
8085a6e0b375SMatthew G. Knepley +  dim          - The spatial dimension
8086a6e0b375SMatthew G. Knepley .  Nf           - The number of input fields
8087a6e0b375SMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8088a6e0b375SMatthew G. Knepley .  uOff         - The offset of each field in u[]
8089a6e0b375SMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8090a6e0b375SMatthew G. Knepley .  u            - The field values at this point in space
8091a6e0b375SMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8092a6e0b375SMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8093a6e0b375SMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8094a6e0b375SMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8095a6e0b375SMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8096a6e0b375SMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8097a6e0b375SMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8098a6e0b375SMatthew G. Knepley .  t            - The current time
8099a6e0b375SMatthew G. Knepley .  x            - The coordinates of this point
8100a6e0b375SMatthew G. Knepley .  numConstants - The number of constants
8101a6e0b375SMatthew G. Knepley .  constants    - The value of each constant
8102a6e0b375SMatthew G. Knepley -  f            - The value of the function at this point in space
8103a6e0b375SMatthew G. Knepley 
8104bb7acecfSBarry Smith   Note:
8105bb7acecfSBarry 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.
8106bb7acecfSBarry 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
8107bb7acecfSBarry 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
8108a6e0b375SMatthew 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.
8109a6e0b375SMatthew G. Knepley 
8110a6e0b375SMatthew G. Knepley   Level: intermediate
8111a6e0b375SMatthew G. Knepley 
8112bb7acecfSBarry Smith   Developer Notes:
8113bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8114bb7acecfSBarry Smith 
8115bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8116bb7acecfSBarry Smith 
8117db781477SPatrick Sanan .seealso: `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8118a6e0b375SMatthew G. Knepley @*/
8119d71ae5a4SJacob 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)
8120d71ae5a4SJacob Faibussowitsch {
81218c6c5593SMatthew G. Knepley   PetscFunctionBegin;
81228c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81238c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(localU, VEC_CLASSID, 3);
81248c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
81259566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfieldlocal)(dm, time, localU, funcs, mode, localX));
81268c6c5593SMatthew G. Knepley   PetscFunctionReturn(0);
81278c6c5593SMatthew G. Knepley }
81288c6c5593SMatthew G. Knepley 
8129a6e0b375SMatthew G. Knepley /*@C
8130a6e0b375SMatthew 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.
8131a6e0b375SMatthew G. Knepley 
8132a6e0b375SMatthew G. Knepley   Not collective
8133a6e0b375SMatthew G. Knepley 
8134a6e0b375SMatthew G. Knepley   Input Parameters:
8135bb7acecfSBarry Smith + dm      - The `DM`
8136a6e0b375SMatthew G. Knepley . time    - The time
8137bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain to output
8138a6e0b375SMatthew G. Knepley . numIds  - The number of label ids to use
8139a6e0b375SMatthew G. Knepley . ids     - The label ids to use for marking
8140bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
8141a6e0b375SMatthew G. Knepley . comps   - The components to set in the output, or NULL for all components
8142a6e0b375SMatthew G. Knepley . localU  - The input field vector
8143a6e0b375SMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8144a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8145a6e0b375SMatthew G. Knepley 
8146a6e0b375SMatthew G. Knepley   Output Parameter:
8147a6e0b375SMatthew G. Knepley . localX  - The output vector
8148a6e0b375SMatthew G. Knepley 
8149a6e0b375SMatthew G. Knepley    Calling sequence of func:
8150a6e0b375SMatthew G. Knepley $    func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8151a6e0b375SMatthew G. Knepley $         const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8152a6e0b375SMatthew G. Knepley $         const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8153a6e0b375SMatthew G. Knepley $         PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8154a6e0b375SMatthew G. Knepley 
8155a6e0b375SMatthew G. Knepley +  dim          - The spatial dimension
8156a6e0b375SMatthew G. Knepley .  Nf           - The number of input fields
8157a6e0b375SMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8158a6e0b375SMatthew G. Knepley .  uOff         - The offset of each field in u[]
8159a6e0b375SMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8160a6e0b375SMatthew G. Knepley .  u            - The field values at this point in space
8161a6e0b375SMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8162a6e0b375SMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8163a6e0b375SMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8164a6e0b375SMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8165a6e0b375SMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8166a6e0b375SMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8167a6e0b375SMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8168a6e0b375SMatthew G. Knepley .  t            - The current time
8169a6e0b375SMatthew G. Knepley .  x            - The coordinates of this point
8170a6e0b375SMatthew G. Knepley .  numConstants - The number of constants
8171a6e0b375SMatthew G. Knepley .  constants    - The value of each constant
8172a6e0b375SMatthew G. Knepley -  f            - The value of the function at this point in space
8173a6e0b375SMatthew G. Knepley 
8174bb7acecfSBarry Smith   Note:
8175bb7acecfSBarry 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.
8176bb7acecfSBarry 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
8177bb7acecfSBarry 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
8178a6e0b375SMatthew 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.
8179a6e0b375SMatthew G. Knepley 
8180a6e0b375SMatthew G. Knepley   Level: intermediate
8181a6e0b375SMatthew G. Knepley 
8182bb7acecfSBarry Smith   Developer Notes:
8183bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8184bb7acecfSBarry Smith 
8185bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8186bb7acecfSBarry Smith 
8187d29d7c6eSMatthew G. Knepley .seealso: `DMProjectField()`, `DMProjectFieldLabel()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8188a6e0b375SMatthew G. Knepley @*/
8189d71ae5a4SJacob 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)
8190d71ae5a4SJacob Faibussowitsch {
81918c6c5593SMatthew G. Knepley   PetscFunctionBegin;
81928c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8193064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8194064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
81959566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
81968c6c5593SMatthew G. Knepley   PetscFunctionReturn(0);
81978c6c5593SMatthew G. Knepley }
81988c6c5593SMatthew G. Knepley 
81992716604bSToby Isaac /*@C
8200d29d7c6eSMatthew 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.
8201d29d7c6eSMatthew G. Knepley 
8202d29d7c6eSMatthew G. Knepley   Not collective
8203d29d7c6eSMatthew G. Knepley 
8204d29d7c6eSMatthew G. Knepley   Input Parameters:
8205bb7acecfSBarry Smith + dm      - The `DM`
8206d29d7c6eSMatthew G. Knepley . time    - The time
8207bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain to output
8208d29d7c6eSMatthew G. Knepley . numIds  - The number of label ids to use
8209d29d7c6eSMatthew G. Knepley . ids     - The label ids to use for marking
8210bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
8211d29d7c6eSMatthew G. Knepley . comps   - The components to set in the output, or NULL for all components
8212d29d7c6eSMatthew G. Knepley . U       - The input field vector
8213d29d7c6eSMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8214d29d7c6eSMatthew G. Knepley - mode    - The insertion mode for values
8215d29d7c6eSMatthew G. Knepley 
8216d29d7c6eSMatthew G. Knepley   Output Parameter:
8217d29d7c6eSMatthew G. Knepley . X       - The output vector
8218d29d7c6eSMatthew G. Knepley 
8219d29d7c6eSMatthew G. Knepley    Calling sequence of func:
8220d29d7c6eSMatthew G. Knepley $    func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8221d29d7c6eSMatthew G. Knepley $         const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8222d29d7c6eSMatthew G. Knepley $         const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8223d29d7c6eSMatthew G. Knepley $         PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8224d29d7c6eSMatthew G. Knepley 
8225d29d7c6eSMatthew G. Knepley +  dim          - The spatial dimension
8226d29d7c6eSMatthew G. Knepley .  Nf           - The number of input fields
8227d29d7c6eSMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8228d29d7c6eSMatthew G. Knepley .  uOff         - The offset of each field in u[]
8229d29d7c6eSMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8230d29d7c6eSMatthew G. Knepley .  u            - The field values at this point in space
8231d29d7c6eSMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8232d29d7c6eSMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8233d29d7c6eSMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8234d29d7c6eSMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8235d29d7c6eSMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8236d29d7c6eSMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8237d29d7c6eSMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8238d29d7c6eSMatthew G. Knepley .  t            - The current time
8239d29d7c6eSMatthew G. Knepley .  x            - The coordinates of this point
8240d29d7c6eSMatthew G. Knepley .  numConstants - The number of constants
8241d29d7c6eSMatthew G. Knepley .  constants    - The value of each constant
8242d29d7c6eSMatthew G. Knepley -  f            - The value of the function at this point in space
8243d29d7c6eSMatthew G. Knepley 
8244bb7acecfSBarry Smith   Note:
8245bb7acecfSBarry 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.
8246bb7acecfSBarry 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
8247bb7acecfSBarry 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
8248d29d7c6eSMatthew 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.
8249d29d7c6eSMatthew G. Knepley 
8250d29d7c6eSMatthew G. Knepley   Level: intermediate
8251d29d7c6eSMatthew G. Knepley 
8252bb7acecfSBarry Smith   Developer Notes:
8253bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8254bb7acecfSBarry Smith 
8255bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8256bb7acecfSBarry Smith 
8257d29d7c6eSMatthew G. Knepley .seealso: `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8258d29d7c6eSMatthew G. Knepley @*/
8259d71ae5a4SJacob 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)
8260d71ae5a4SJacob Faibussowitsch {
8261d29d7c6eSMatthew G. Knepley   DM  dmIn;
8262d29d7c6eSMatthew G. Knepley   Vec localU, localX;
8263d29d7c6eSMatthew G. Knepley 
8264d29d7c6eSMatthew G. Knepley   PetscFunctionBegin;
8265d29d7c6eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8266d29d7c6eSMatthew G. Knepley   PetscCall(VecGetDM(U, &dmIn));
8267d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dmIn, &localU));
8268d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dm, &localX));
826972fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalBegin(dmIn, U, mode, localU));
827072fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalEnd(dmIn, U, mode, localU));
8271d29d7c6eSMatthew G. Knepley   PetscCall(DMProjectFieldLabelLocal(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
8272d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
8273d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
8274d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dm, &localX));
8275d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dmIn, &localU));
8276d29d7c6eSMatthew G. Knepley   PetscFunctionReturn(0);
8277d29d7c6eSMatthew G. Knepley }
8278d29d7c6eSMatthew G. Knepley 
8279d29d7c6eSMatthew G. Knepley /*@C
8280ece3a9fcSMatthew 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.
8281ece3a9fcSMatthew G. Knepley 
8282ece3a9fcSMatthew G. Knepley   Not collective
8283ece3a9fcSMatthew G. Knepley 
8284ece3a9fcSMatthew G. Knepley   Input Parameters:
8285bb7acecfSBarry Smith + dm      - The `DM`
8286ece3a9fcSMatthew G. Knepley . time    - The time
8287bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain boundary to output
8288ece3a9fcSMatthew G. Knepley . numIds  - The number of label ids to use
8289ece3a9fcSMatthew G. Knepley . ids     - The label ids to use for marking
8290bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
8291ece3a9fcSMatthew G. Knepley . comps   - The components to set in the output, or NULL for all components
8292ece3a9fcSMatthew G. Knepley . localU  - The input field vector
8293ece3a9fcSMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8294ece3a9fcSMatthew G. Knepley - mode    - The insertion mode for values
8295ece3a9fcSMatthew G. Knepley 
8296ece3a9fcSMatthew G. Knepley   Output Parameter:
8297ece3a9fcSMatthew G. Knepley . localX  - The output vector
8298ece3a9fcSMatthew G. Knepley 
8299ece3a9fcSMatthew G. Knepley    Calling sequence of func:
8300ece3a9fcSMatthew G. Knepley $    func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8301ece3a9fcSMatthew G. Knepley $         const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8302ece3a9fcSMatthew G. Knepley $         const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8303ece3a9fcSMatthew G. Knepley $         PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8304ece3a9fcSMatthew G. Knepley 
8305ece3a9fcSMatthew G. Knepley +  dim          - The spatial dimension
8306ece3a9fcSMatthew G. Knepley .  Nf           - The number of input fields
8307ece3a9fcSMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8308ece3a9fcSMatthew G. Knepley .  uOff         - The offset of each field in u[]
8309ece3a9fcSMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8310ece3a9fcSMatthew G. Knepley .  u            - The field values at this point in space
8311ece3a9fcSMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8312ece3a9fcSMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8313ece3a9fcSMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8314ece3a9fcSMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8315ece3a9fcSMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8316ece3a9fcSMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8317ece3a9fcSMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8318ece3a9fcSMatthew G. Knepley .  t            - The current time
8319ece3a9fcSMatthew G. Knepley .  x            - The coordinates of this point
8320ece3a9fcSMatthew G. Knepley .  n            - The face normal
8321ece3a9fcSMatthew G. Knepley .  numConstants - The number of constants
8322ece3a9fcSMatthew G. Knepley .  constants    - The value of each constant
8323ece3a9fcSMatthew G. Knepley -  f            - The value of the function at this point in space
8324ece3a9fcSMatthew G. Knepley 
8325ece3a9fcSMatthew G. Knepley   Note:
8326bb7acecfSBarry 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.
8327bb7acecfSBarry 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
8328bb7acecfSBarry 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
8329ece3a9fcSMatthew 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.
8330ece3a9fcSMatthew G. Knepley 
8331ece3a9fcSMatthew G. Knepley   Level: intermediate
8332ece3a9fcSMatthew G. Knepley 
8333bb7acecfSBarry Smith   Developer Notes:
8334bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8335bb7acecfSBarry Smith 
8336bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8337bb7acecfSBarry Smith 
8338db781477SPatrick Sanan .seealso: `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8339ece3a9fcSMatthew G. Knepley @*/
8340d71ae5a4SJacob 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)
8341d71ae5a4SJacob Faibussowitsch {
8342ece3a9fcSMatthew G. Knepley   PetscFunctionBegin;
8343ece3a9fcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8344064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8345064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
83469566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
8347ece3a9fcSMatthew G. Knepley   PetscFunctionReturn(0);
8348ece3a9fcSMatthew G. Knepley }
8349ece3a9fcSMatthew G. Knepley 
8350ece3a9fcSMatthew G. Knepley /*@C
83512716604bSToby Isaac   DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
83522716604bSToby Isaac 
8353bb7acecfSBarry Smith   Collective on dm
8354bb7acecfSBarry Smith 
83552716604bSToby Isaac   Input Parameters:
8356bb7acecfSBarry Smith + dm    - The `DM`
83570709b2feSToby Isaac . time  - The time
83582716604bSToby Isaac . funcs - The functions to evaluate for each field component
83592716604bSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8360574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
83612716604bSToby Isaac 
83622716604bSToby Isaac   Output Parameter:
83632716604bSToby Isaac . diff - The diff ||u - u_h||_2
83642716604bSToby Isaac 
83652716604bSToby Isaac   Level: developer
83662716604bSToby Isaac 
8367bb7acecfSBarry Smith   Developer Notes:
8368bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8369bb7acecfSBarry Smith 
8370bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8371bb7acecfSBarry Smith 
8372db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
83732716604bSToby Isaac @*/
8374d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
8375d71ae5a4SJacob Faibussowitsch {
83762716604bSToby Isaac   PetscFunctionBegin;
83772716604bSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8378b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
83799566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2diff)(dm, time, funcs, ctxs, X, diff));
83802716604bSToby Isaac   PetscFunctionReturn(0);
83812716604bSToby Isaac }
8382b698f381SToby Isaac 
8383b698f381SToby Isaac /*@C
8384b698f381SToby Isaac   DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
8385b698f381SToby Isaac 
8386d083f849SBarry Smith   Collective on dm
8387d083f849SBarry Smith 
8388b698f381SToby Isaac   Input Parameters:
8389bb7acecfSBarry Smith + dm    - The `DM`
8390b698f381SToby Isaac , time  - The time
8391b698f381SToby Isaac . funcs - The gradient functions to evaluate for each field component
8392b698f381SToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8393574a98acSMatthew G. Knepley . X     - The coefficient vector u_h, a global vector
8394b698f381SToby Isaac - n     - The vector to project along
8395b698f381SToby Isaac 
8396b698f381SToby Isaac   Output Parameter:
8397b698f381SToby Isaac . diff - The diff ||(grad u - grad u_h) . n||_2
8398b698f381SToby Isaac 
8399b698f381SToby Isaac   Level: developer
8400b698f381SToby Isaac 
8401bb7acecfSBarry Smith   Developer Notes:
8402bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8403bb7acecfSBarry Smith 
8404bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8405bb7acecfSBarry Smith 
8406bb7acecfSBarry Smith .seealso: `DMProjectFunction()`, `DMComputeL2Diff()`, `DMComputeL2FieldDiff()`
8407b698f381SToby Isaac @*/
8408d71ae5a4SJacob 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)
8409d71ae5a4SJacob Faibussowitsch {
8410b698f381SToby Isaac   PetscFunctionBegin;
8411b698f381SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8412b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
84139566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2gradientdiff)(dm, time, funcs, ctxs, X, n, diff));
8414b698f381SToby Isaac   PetscFunctionReturn(0);
8415b698f381SToby Isaac }
8416b698f381SToby Isaac 
84172a16baeaSToby Isaac /*@C
84182a16baeaSToby Isaac   DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
84192a16baeaSToby Isaac 
8420d083f849SBarry Smith   Collective on dm
8421d083f849SBarry Smith 
84222a16baeaSToby Isaac   Input Parameters:
8423bb7acecfSBarry Smith + dm    - The `DM`
84242a16baeaSToby Isaac . time  - The time
84252a16baeaSToby Isaac . funcs - The functions to evaluate for each field component
84262a16baeaSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8427574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
84282a16baeaSToby Isaac 
84292a16baeaSToby Isaac   Output Parameter:
84302a16baeaSToby Isaac . diff - The array of differences, ||u^f - u^f_h||_2
84312a16baeaSToby Isaac 
84322a16baeaSToby Isaac   Level: developer
84332a16baeaSToby Isaac 
8434bb7acecfSBarry Smith   Developer Notes:
8435bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8436bb7acecfSBarry Smith 
8437bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8438bb7acecfSBarry Smith 
8439db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
84402a16baeaSToby Isaac @*/
8441d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
8442d71ae5a4SJacob Faibussowitsch {
84432a16baeaSToby Isaac   PetscFunctionBegin;
84442a16baeaSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84452a16baeaSToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
84469566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2fielddiff)(dm, time, funcs, ctxs, X, diff));
84472a16baeaSToby Isaac   PetscFunctionReturn(0);
84482a16baeaSToby Isaac }
84492a16baeaSToby Isaac 
8450df0b854cSToby Isaac /*@C
8451bb7acecfSBarry Smith  DMGetNeighbors - Gets an array containing the MPI ranks of all the processes neighbors
8452502a2867SDave May 
8453502a2867SDave May  Not Collective
8454502a2867SDave May 
8455502a2867SDave May  Input Parameter:
8456bb7acecfSBarry Smith .  dm    - The `DM`
8457502a2867SDave May 
84580a19bb7dSprj-  Output Parameters:
84590a19bb7dSprj- +  nranks - the number of neighbours
84600a19bb7dSprj- -  ranks - the neighbors ranks
8461502a2867SDave May 
8462bb7acecfSBarry Smith  Note:
8463bb7acecfSBarry Smith  Do not free the array, it is freed when the `DM` is destroyed.
8464502a2867SDave May 
8465502a2867SDave May  Level: beginner
8466502a2867SDave May 
8467db781477SPatrick Sanan  .seealso: `DMDAGetNeighbors()`, `PetscSFGetRootRanks()`
8468502a2867SDave May @*/
8469d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNeighbors(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
8470d71ae5a4SJacob Faibussowitsch {
8471502a2867SDave May   PetscFunctionBegin;
8472502a2867SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84739566063dSJacob Faibussowitsch   PetscCall((dm->ops->getneighbors)(dm, nranks, ranks));
8474502a2867SDave May   PetscFunctionReturn(0);
8475502a2867SDave May }
8476502a2867SDave May 
8477531c7667SBarry Smith #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
8478531c7667SBarry Smith 
8479531c7667SBarry Smith /*
8480531c7667SBarry Smith     Converts the input vector to a ghosted vector and then calls the standard coloring code.
8481531c7667SBarry Smith     This has be a different function because it requires DM which is not defined in the Mat library
8482531c7667SBarry Smith */
8483d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringApply_AIJDM(Mat J, MatFDColoring coloring, Vec x1, void *sctx)
8484d71ae5a4SJacob Faibussowitsch {
8485531c7667SBarry Smith   PetscFunctionBegin;
8486531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8487531c7667SBarry Smith     Vec x1local;
8488531c7667SBarry Smith     DM  dm;
84899566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
84907a8be351SBarry Smith     PetscCheck(dm, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_INCOMP, "IS_COLORING_LOCAL requires a DM");
84919566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &x1local));
84929566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, x1, INSERT_VALUES, x1local));
84939566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, x1, INSERT_VALUES, x1local));
8494531c7667SBarry Smith     x1 = x1local;
8495531c7667SBarry Smith   }
84969566063dSJacob Faibussowitsch   PetscCall(MatFDColoringApply_AIJ(J, coloring, x1, sctx));
8497531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8498531c7667SBarry Smith     DM dm;
84999566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
85009566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &x1));
8501531c7667SBarry Smith   }
8502531c7667SBarry Smith   PetscFunctionReturn(0);
8503531c7667SBarry Smith }
8504531c7667SBarry Smith 
8505531c7667SBarry Smith /*@
8506bb7acecfSBarry Smith     MatFDColoringUseDM - allows a `MatFDColoring` object to use the `DM` associated with the matrix to compute a `IS_COLORING_LOCAL` coloring
8507531c7667SBarry Smith 
8508531c7667SBarry Smith     Input Parameter:
8509bb7acecfSBarry Smith .    coloring - the `MatFDColoring` object
8510531c7667SBarry Smith 
8511bb7acecfSBarry Smith     Developer Note:
8512bb7acecfSBarry Smith     this routine exists because the PETSc `Mat` library does not know about the `DM` objects
8513531c7667SBarry Smith 
85141b266c99SBarry Smith     Level: advanced
85151b266c99SBarry Smith 
8516db781477SPatrick Sanan .seealso: `MatFDColoring`, `MatFDColoringCreate()`, `ISColoringType`
8517531c7667SBarry Smith @*/
8518d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringUseDM(Mat coloring, MatFDColoring fdcoloring)
8519d71ae5a4SJacob Faibussowitsch {
8520531c7667SBarry Smith   PetscFunctionBegin;
8521531c7667SBarry Smith   coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
8522531c7667SBarry Smith   PetscFunctionReturn(0);
8523531c7667SBarry Smith }
85248320bc6fSPatrick Sanan 
85258320bc6fSPatrick Sanan /*@
8526bb7acecfSBarry Smith     DMGetCompatibility - determine if two `DM`s are compatible
85278320bc6fSPatrick Sanan 
85288320bc6fSPatrick Sanan     Collective
85298320bc6fSPatrick Sanan 
85308320bc6fSPatrick Sanan     Input Parameters:
8531bb7acecfSBarry Smith +    dm1 - the first `DM`
8532bb7acecfSBarry Smith -    dm2 - the second `DM`
85338320bc6fSPatrick Sanan 
85348320bc6fSPatrick Sanan     Output Parameters:
8535bb7acecfSBarry Smith +    compatible - whether or not the two `DM`s are compatible
8536bb7acecfSBarry Smith -    set - whether or not the compatible value was actually determined and set
85378320bc6fSPatrick Sanan 
85388320bc6fSPatrick Sanan     Notes:
8539bb7acecfSBarry Smith     Two `DM`s are deemed compatible if they represent the same parallel decomposition
85403d862458SPatrick Sanan     of the same topology. This implies that the section (field data) on one
85418320bc6fSPatrick Sanan     "makes sense" with respect to the topology and parallel decomposition of the other.
8542bb7acecfSBarry Smith     Loosely speaking, compatible `DM`s represent the same domain and parallel
85433d862458SPatrick Sanan     decomposition, but hold different data.
85448320bc6fSPatrick Sanan 
85458320bc6fSPatrick Sanan     Typically, one would confirm compatibility if intending to simultaneously iterate
8546bb7acecfSBarry Smith     over a pair of vectors obtained from different `DM`s.
85478320bc6fSPatrick Sanan 
8548bb7acecfSBarry Smith     For example, two `DMDA` objects are compatible if they have the same local
85498320bc6fSPatrick Sanan     and global sizes and the same stencil width. They can have different numbers
85508320bc6fSPatrick Sanan     of degrees of freedom per node. Thus, one could use the node numbering from
8551bb7acecfSBarry Smith     either `DM` in bounds for a loop over vectors derived from either `DM`.
85528320bc6fSPatrick Sanan 
8553bb7acecfSBarry Smith     Consider the operation of summing data living on a 2-dof `DMDA` to data living
8554bb7acecfSBarry Smith     on a 1-dof `DMDA`, which should be compatible, as in the following snippet.
85558320bc6fSPatrick Sanan .vb
85568320bc6fSPatrick Sanan   ...
85579566063dSJacob Faibussowitsch   PetscCall(DMGetCompatibility(da1,da2,&compatible,&set));
85588320bc6fSPatrick Sanan   if (set && compatible)  {
85599566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da1,vec1,&arr1));
85609566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da2,vec2,&arr2));
85619566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL));
85628320bc6fSPatrick Sanan     for (j=y; j<y+n; ++j) {
85638320bc6fSPatrick Sanan       for (i=x; i<x+m, ++i) {
85648320bc6fSPatrick Sanan         arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1];
85658320bc6fSPatrick Sanan       }
85668320bc6fSPatrick Sanan     }
85679566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da1,vec1,&arr1));
85689566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da2,vec2,&arr2));
85698320bc6fSPatrick Sanan   } else {
85708320bc6fSPatrick Sanan     SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible");
85718320bc6fSPatrick Sanan   }
85728320bc6fSPatrick Sanan   ...
85738320bc6fSPatrick Sanan .ve
85748320bc6fSPatrick Sanan 
8575bb7acecfSBarry Smith     Checking compatibility might be expensive for a given implementation of `DM`,
85768320bc6fSPatrick Sanan     or might be impossible to unambiguously confirm or deny. For this reason,
85778320bc6fSPatrick Sanan     this function may decline to determine compatibility, and hence users should
85788320bc6fSPatrick Sanan     always check the "set" output parameter.
85798320bc6fSPatrick Sanan 
8580bb7acecfSBarry Smith     A `DM` is always compatible with itself.
85818320bc6fSPatrick Sanan 
8582bb7acecfSBarry Smith     In the current implementation, `DM`s which live on "unequal" communicators
85838320bc6fSPatrick Sanan     (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed
85848320bc6fSPatrick Sanan     incompatible.
85858320bc6fSPatrick Sanan 
85868320bc6fSPatrick Sanan     This function is labeled "Collective," as information about all subdomains
8587bb7acecfSBarry Smith     is required on each rank. However, in `DM` implementations which store all this
85888320bc6fSPatrick Sanan     information locally, this function may be merely "Logically Collective".
85898320bc6fSPatrick Sanan 
8590bb7acecfSBarry Smith     Developer Note:
8591bb7acecfSBarry Smith     Compatibility is assumed to be a symmetric concept; `DM` A is compatible with `DM` B
85923d862458SPatrick Sanan     iff B is compatible with A. Thus, this function checks the implementations
8593a5bc1bf3SBarry Smith     of both dm and dmc (if they are of different types), attempting to determine
8594bb7acecfSBarry Smith     compatibility. It is left to `DM` implementers to ensure that symmetry is
85958320bc6fSPatrick Sanan     preserved. The simplest way to do this is, when implementing type-specific
85963d862458SPatrick Sanan     logic for this function, is to check for existing logic in the implementation
8597bb7acecfSBarry Smith     of other `DM` types and let *set = PETSC_FALSE if found.
85988320bc6fSPatrick Sanan 
85998320bc6fSPatrick Sanan     Level: advanced
86008320bc6fSPatrick Sanan 
8601db781477SPatrick Sanan .seealso: `DM`, `DMDACreateCompatibleDMDA()`, `DMStagCreateCompatibleDMStag()`
86028320bc6fSPatrick Sanan @*/
8603d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCompatibility(DM dm1, DM dm2, PetscBool *compatible, PetscBool *set)
8604d71ae5a4SJacob Faibussowitsch {
86058320bc6fSPatrick Sanan   PetscMPIInt compareResult;
86068320bc6fSPatrick Sanan   DMType      type, type2;
86078320bc6fSPatrick Sanan   PetscBool   sameType;
86088320bc6fSPatrick Sanan 
86098320bc6fSPatrick Sanan   PetscFunctionBegin;
8610a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dm1, DM_CLASSID, 1);
86118320bc6fSPatrick Sanan   PetscValidHeaderSpecific(dm2, DM_CLASSID, 2);
86128320bc6fSPatrick Sanan 
86138320bc6fSPatrick Sanan   /* Declare a DM compatible with itself */
8614a5bc1bf3SBarry Smith   if (dm1 == dm2) {
86158320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
86168320bc6fSPatrick Sanan     *compatible = PETSC_TRUE;
86178320bc6fSPatrick Sanan     PetscFunctionReturn(0);
86188320bc6fSPatrick Sanan   }
86198320bc6fSPatrick Sanan 
86208320bc6fSPatrick Sanan   /* Declare a DM incompatible with a DM that lives on an "unequal"
86218320bc6fSPatrick Sanan      communicator. Note that this does not preclude compatibility with
86228320bc6fSPatrick Sanan      DMs living on "congruent" or "similar" communicators, but this must be
86238320bc6fSPatrick Sanan      determined by the implementation-specific logic */
86249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)dm1), PetscObjectComm((PetscObject)dm2), &compareResult));
86258320bc6fSPatrick Sanan   if (compareResult == MPI_UNEQUAL) {
86268320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
86278320bc6fSPatrick Sanan     *compatible = PETSC_FALSE;
86288320bc6fSPatrick Sanan     PetscFunctionReturn(0);
86298320bc6fSPatrick Sanan   }
86308320bc6fSPatrick Sanan 
86318320bc6fSPatrick Sanan   /* Pass to the implementation-specific routine, if one exists. */
8632a5bc1bf3SBarry Smith   if (dm1->ops->getcompatibility) {
8633dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm1, getcompatibility, dm2, compatible, set);
8634b9d85ea2SLisandro Dalcin     if (*set) PetscFunctionReturn(0);
86358320bc6fSPatrick Sanan   }
86368320bc6fSPatrick Sanan 
8637a5bc1bf3SBarry Smith   /* If dm1 and dm2 are of different types, then attempt to check compatibility
86388320bc6fSPatrick Sanan      with an implementation of this function from dm2 */
86399566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm1, &type));
86409566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm2, &type2));
86419566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(type, type2, &sameType));
86428320bc6fSPatrick Sanan   if (!sameType && dm2->ops->getcompatibility) {
8643dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm2, getcompatibility, dm1, compatible, set); /* Note argument order */
86448320bc6fSPatrick Sanan   } else {
86458320bc6fSPatrick Sanan     *set = PETSC_FALSE;
86468320bc6fSPatrick Sanan   }
86478320bc6fSPatrick Sanan   PetscFunctionReturn(0);
86488320bc6fSPatrick Sanan }
8649c0f0dcc3SMatthew G. Knepley 
8650c0f0dcc3SMatthew G. Knepley /*@C
8651bb7acecfSBarry Smith   DMMonitorSet - Sets an additional monitor function that is to be used after a solve to monitor discretization performance.
8652c0f0dcc3SMatthew G. Knepley 
8653bb7acecfSBarry Smith   Logically Collective on dm
8654c0f0dcc3SMatthew G. Knepley 
8655c0f0dcc3SMatthew G. Knepley   Input Parameters:
8656bb7acecfSBarry Smith + DM - the `DM`
8657c0f0dcc3SMatthew G. Knepley . f - the monitor function
8658c0f0dcc3SMatthew G. Knepley . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired)
8659c0f0dcc3SMatthew G. Knepley - monitordestroy - [optional] routine that frees monitor context (may be NULL)
8660c0f0dcc3SMatthew G. Knepley 
8661c0f0dcc3SMatthew G. Knepley   Options Database Keys:
8662bb7acecfSBarry Smith - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `DMMonitorSet()`, but
8663c0f0dcc3SMatthew G. Knepley                             does not cancel those set via the options database.
8664c0f0dcc3SMatthew G. Knepley 
8665bb7acecfSBarry Smith   Note:
8666c0f0dcc3SMatthew G. Knepley   Several different monitoring routines may be set by calling
8667bb7acecfSBarry Smith   `DMMonitorSet()` multiple times or with `DMMonitorSetFromOptions()`; all will be called in the
8668c0f0dcc3SMatthew G. Knepley   order in which they were set.
8669c0f0dcc3SMatthew G. Knepley 
8670bb7acecfSBarry Smith   Fortran Note:
8671bb7acecfSBarry Smith   Only a single monitor function can be set for each `DM` object
8672bb7acecfSBarry Smith 
8673bb7acecfSBarry Smith   Developer Note:
8674bb7acecfSBarry Smith   This API has a generic name but seems specific to a very particular aspect of the use of `DM`
8675c0f0dcc3SMatthew G. Knepley 
8676c0f0dcc3SMatthew G. Knepley   Level: intermediate
8677c0f0dcc3SMatthew G. Knepley 
8678bb7acecfSBarry Smith .seealso: `DMMonitorCancel()`,`DMMonitorSetFromOptions()`, `DMMonitor()`
8679c0f0dcc3SMatthew G. Knepley @*/
8680d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
8681d71ae5a4SJacob Faibussowitsch {
8682c0f0dcc3SMatthew G. Knepley   PetscInt m;
8683c0f0dcc3SMatthew G. Knepley 
8684c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8685c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8686c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
8687c0f0dcc3SMatthew G. Knepley     PetscBool identical;
8688c0f0dcc3SMatthew G. Knepley 
86899566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical));
8690c0f0dcc3SMatthew G. Knepley     if (identical) PetscFunctionReturn(0);
8691c0f0dcc3SMatthew G. Knepley   }
86927a8be351SBarry Smith   PetscCheck(dm->numbermonitors < MAXDMMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
8693c0f0dcc3SMatthew G. Knepley   dm->monitor[dm->numbermonitors]          = f;
8694c0f0dcc3SMatthew G. Knepley   dm->monitordestroy[dm->numbermonitors]   = monitordestroy;
8695c0f0dcc3SMatthew G. Knepley   dm->monitorcontext[dm->numbermonitors++] = (void *)mctx;
8696c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
8697c0f0dcc3SMatthew G. Knepley }
8698c0f0dcc3SMatthew G. Knepley 
8699c0f0dcc3SMatthew G. Knepley /*@
8700bb7acecfSBarry Smith   DMMonitorCancel - Clears all the monitor functions for a `DM` object.
8701c0f0dcc3SMatthew G. Knepley 
8702bb7acecfSBarry Smith   Logically Collective on dm
8703c0f0dcc3SMatthew G. Knepley 
8704c0f0dcc3SMatthew G. Knepley   Input Parameter:
8705c0f0dcc3SMatthew G. Knepley . dm - the DM
8706c0f0dcc3SMatthew G. Knepley 
8707c0f0dcc3SMatthew G. Knepley   Options Database Key:
8708c0f0dcc3SMatthew G. Knepley . -dm_monitor_cancel - cancels all monitors that have been hardwired
8709bb7acecfSBarry Smith   into a code by calls to `DMonitorSet()`, but does not cancel those
8710c0f0dcc3SMatthew G. Knepley   set via the options database
8711c0f0dcc3SMatthew G. Knepley 
8712bb7acecfSBarry Smith   Note:
8713bb7acecfSBarry Smith   There is no way to clear one specific monitor from a `DM` object.
8714c0f0dcc3SMatthew G. Knepley 
8715c0f0dcc3SMatthew G. Knepley   Level: intermediate
8716c0f0dcc3SMatthew G. Knepley 
8717bb7acecfSBarry Smith .seealso: `DMMonitorSet()`, `DMMonitorSetFromOptions()`,  `DMMonitor()`
8718c0f0dcc3SMatthew G. Knepley @*/
8719d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorCancel(DM dm)
8720d71ae5a4SJacob Faibussowitsch {
8721c0f0dcc3SMatthew G. Knepley   PetscInt m;
8722c0f0dcc3SMatthew G. Knepley 
8723c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8724c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8725c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
87269566063dSJacob Faibussowitsch     if (dm->monitordestroy[m]) PetscCall((*dm->monitordestroy[m])(&dm->monitorcontext[m]));
8727c0f0dcc3SMatthew G. Knepley   }
8728c0f0dcc3SMatthew G. Knepley   dm->numbermonitors = 0;
8729c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
8730c0f0dcc3SMatthew G. Knepley }
8731c0f0dcc3SMatthew G. Knepley 
8732c0f0dcc3SMatthew G. Knepley /*@C
8733c0f0dcc3SMatthew G. Knepley   DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
8734c0f0dcc3SMatthew G. Knepley 
8735bb7acecfSBarry Smith   Collective on dm
8736c0f0dcc3SMatthew G. Knepley 
8737c0f0dcc3SMatthew G. Knepley   Input Parameters:
8738bb7acecfSBarry Smith + dm   - `DM` object you wish to monitor
8739c0f0dcc3SMatthew G. Knepley . name - the monitor type one is seeking
8740c0f0dcc3SMatthew G. Knepley . help - message indicating what monitoring is done
8741c0f0dcc3SMatthew G. Knepley . manual - manual page for the monitor
8742c0f0dcc3SMatthew G. Knepley . monitor - the monitor function
8743bb7acecfSBarry 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
8744c0f0dcc3SMatthew G. Knepley 
8745c0f0dcc3SMatthew G. Knepley   Output Parameter:
8746c0f0dcc3SMatthew G. Knepley . flg - Flag set if the monitor was created
8747c0f0dcc3SMatthew G. Knepley 
8748c0f0dcc3SMatthew G. Knepley   Level: developer
8749c0f0dcc3SMatthew G. Knepley 
8750db781477SPatrick Sanan .seealso: `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
8751db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
8752db781477SPatrick Sanan           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
8753db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
8754c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
8755db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
8756bb7acecfSBarry Smith           `PetscOptionsFList()`, `PetscOptionsEList()`, `DMMonitor()`, `DMMonitorSet()`
8757c0f0dcc3SMatthew G. Knepley @*/
8758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg)
8759d71ae5a4SJacob Faibussowitsch {
8760c0f0dcc3SMatthew G. Knepley   PetscViewer       viewer;
8761c0f0dcc3SMatthew G. Knepley   PetscViewerFormat format;
8762c0f0dcc3SMatthew G. Knepley 
8763c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8764c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)dm), ((PetscObject)dm)->options, ((PetscObject)dm)->prefix, name, &viewer, &format, flg));
8766c0f0dcc3SMatthew G. Knepley   if (*flg) {
8767c0f0dcc3SMatthew G. Knepley     PetscViewerAndFormat *vf;
8768c0f0dcc3SMatthew G. Knepley 
87699566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
87709566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)viewer));
87719566063dSJacob Faibussowitsch     if (monitorsetup) PetscCall((*monitorsetup)(dm, vf));
87729566063dSJacob Faibussowitsch     PetscCall(DMMonitorSet(dm, (PetscErrorCode(*)(DM, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
8773c0f0dcc3SMatthew G. Knepley   }
8774c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
8775c0f0dcc3SMatthew G. Knepley }
8776c0f0dcc3SMatthew G. Knepley 
8777c0f0dcc3SMatthew G. Knepley /*@
8778c0f0dcc3SMatthew G. Knepley    DMMonitor - runs the user provided monitor routines, if they exist
8779c0f0dcc3SMatthew G. Knepley 
8780bb7acecfSBarry Smith    Collective on dm
8781c0f0dcc3SMatthew G. Knepley 
8782c0f0dcc3SMatthew G. Knepley    Input Parameters:
8783bb7acecfSBarry Smith .  dm - The `DM`
8784c0f0dcc3SMatthew G. Knepley 
8785c0f0dcc3SMatthew G. Knepley    Level: developer
8786c0f0dcc3SMatthew G. Knepley 
8787bb7acecfSBarry Smith    Question:
8788bb7acecfSBarry 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
8789bb7acecfSBarry Smith    since some `DM` have no concept of discretization
8790bb7acecfSBarry Smith 
8791bb7acecfSBarry Smith .seealso: `DMMonitorSet()`, `DMMonitorSetFromOptions()`
8792c0f0dcc3SMatthew G. Knepley @*/
8793d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitor(DM dm)
8794d71ae5a4SJacob Faibussowitsch {
8795c0f0dcc3SMatthew G. Knepley   PetscInt m;
8796c0f0dcc3SMatthew G. Knepley 
8797c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8798c0f0dcc3SMatthew G. Knepley   if (!dm) PetscFunctionReturn(0);
8799c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
880048a46eb9SPierre Jolivet   for (m = 0; m < dm->numbermonitors; ++m) PetscCall((*dm->monitor[m])(dm, dm->monitorcontext[m]));
8801c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
8802c0f0dcc3SMatthew G. Knepley }
88032e4af2aeSMatthew G. Knepley 
88042e4af2aeSMatthew G. Knepley /*@
8805bb7acecfSBarry Smith   DMComputeError - Computes the error assuming the user has provided the exact solution functions
88062e4af2aeSMatthew G. Knepley 
8807bb7acecfSBarry Smith   Collective on dm
88082e4af2aeSMatthew G. Knepley 
88092e4af2aeSMatthew G. Knepley   Input Parameters:
8810bb7acecfSBarry Smith + dm     - The `DM`
88116b867d5aSJose E. Roman - sol    - The solution vector
88122e4af2aeSMatthew G. Knepley 
88136b867d5aSJose E. Roman   Input/Output Parameter:
88146b867d5aSJose E. Roman . errors - An array of length Nf, the number of fields, or NULL for no output; on output
88156b867d5aSJose E. Roman            contains the error in each field
88166b867d5aSJose E. Roman 
88176b867d5aSJose E. Roman   Output Parameter:
88186b867d5aSJose E. Roman . errorVec - A vector to hold the cellwise error (may be NULL)
88192e4af2aeSMatthew G. Knepley 
8820bb7acecfSBarry Smith   Note:
8821bb7acecfSBarry Smith   The exact solutions come from the `PetscDS` object, and the time comes from `DMGetOutputSequenceNumber()`.
88222e4af2aeSMatthew G. Knepley 
88232e4af2aeSMatthew G. Knepley   Level: developer
88242e4af2aeSMatthew G. Knepley 
8825db781477SPatrick Sanan .seealso: `DMMonitorSet()`, `DMGetRegionNumDS()`, `PetscDSGetExactSolution()`, `DMGetOutputSequenceNumber()`
88262e4af2aeSMatthew G. Knepley @*/
8827d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec)
8828d71ae5a4SJacob Faibussowitsch {
88292e4af2aeSMatthew G. Knepley   PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
88302e4af2aeSMatthew G. Knepley   void    **ctxs;
88312e4af2aeSMatthew G. Knepley   PetscReal time;
88322e4af2aeSMatthew G. Knepley   PetscInt  Nf, f, Nds, s;
88332e4af2aeSMatthew G. Knepley 
88342e4af2aeSMatthew G. Knepley   PetscFunctionBegin;
88359566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
88369566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(Nf, &exactSol, Nf, &ctxs));
88379566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
88382e4af2aeSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
88392e4af2aeSMatthew G. Knepley     PetscDS         ds;
88402e4af2aeSMatthew G. Knepley     DMLabel         label;
88412e4af2aeSMatthew G. Knepley     IS              fieldIS;
88422e4af2aeSMatthew G. Knepley     const PetscInt *fields;
88432e4af2aeSMatthew G. Knepley     PetscInt        dsNf;
88442e4af2aeSMatthew G. Knepley 
88459566063dSJacob Faibussowitsch     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds));
88469566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
88479566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISGetIndices(fieldIS, &fields));
88482e4af2aeSMatthew G. Knepley     for (f = 0; f < dsNf; ++f) {
88492e4af2aeSMatthew G. Knepley       const PetscInt field = fields[f];
88509566063dSJacob Faibussowitsch       PetscCall(PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]));
88512e4af2aeSMatthew G. Knepley     }
88529566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISRestoreIndices(fieldIS, &fields));
88532e4af2aeSMatthew G. Knepley   }
8854ad540459SPierre 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);
88559566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
88569566063dSJacob Faibussowitsch   if (errors) PetscCall(DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors));
88572e4af2aeSMatthew G. Knepley   if (errorVec) {
88582e4af2aeSMatthew G. Knepley     DM             edm;
88592e4af2aeSMatthew G. Knepley     DMPolytopeType ct;
88602e4af2aeSMatthew G. Knepley     PetscBool      simplex;
88612e4af2aeSMatthew G. Knepley     PetscInt       dim, cStart, Nf;
88622e4af2aeSMatthew G. Knepley 
88639566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &edm));
88649566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(edm, &dim));
88659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
88669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cStart, &ct));
88672e4af2aeSMatthew G. Knepley     simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
88689566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
88692e4af2aeSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
88702e4af2aeSMatthew G. Knepley       PetscFE         fe, efe;
88712e4af2aeSMatthew G. Knepley       PetscQuadrature q;
88722e4af2aeSMatthew G. Knepley       const char     *name;
88732e4af2aeSMatthew G. Knepley 
88749566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe));
88759566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe));
88769566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)fe, &name));
88779566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)efe, name));
88789566063dSJacob Faibussowitsch       PetscCall(PetscFEGetQuadrature(fe, &q));
88799566063dSJacob Faibussowitsch       PetscCall(PetscFESetQuadrature(efe, q));
88809566063dSJacob Faibussowitsch       PetscCall(DMSetField(edm, f, NULL, (PetscObject)efe));
88819566063dSJacob Faibussowitsch       PetscCall(PetscFEDestroy(&efe));
88822e4af2aeSMatthew G. Knepley     }
88839566063dSJacob Faibussowitsch     PetscCall(DMCreateDS(edm));
88842e4af2aeSMatthew G. Knepley 
88859566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(edm, errorVec));
88869566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*errorVec, "Error"));
88879566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec));
88889566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&edm));
88892e4af2aeSMatthew G. Knepley   }
88909566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exactSol, ctxs));
88912e4af2aeSMatthew G. Knepley   PetscFunctionReturn(0);
88922e4af2aeSMatthew G. Knepley }
88939a2a23afSMatthew G. Knepley 
88949a2a23afSMatthew G. Knepley /*@
8895bb7acecfSBarry Smith   DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this `DM`
88969a2a23afSMatthew G. Knepley 
88979a2a23afSMatthew G. Knepley   Not collective
88989a2a23afSMatthew G. Knepley 
88999a2a23afSMatthew G. Knepley   Input Parameter:
8900bb7acecfSBarry Smith . dm     - The `DM`
89019a2a23afSMatthew G. Knepley 
89029a2a23afSMatthew G. Knepley   Output Parameter:
8903a5b23f4aSJose E. Roman . numAux - The number of auxiliary data vectors
89049a2a23afSMatthew G. Knepley 
89059a2a23afSMatthew G. Knepley   Level: advanced
89069a2a23afSMatthew G. Knepley 
8907bb7acecfSBarry Smith .seealso: `DMSetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
89089a2a23afSMatthew G. Knepley @*/
8909d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux)
8910d71ae5a4SJacob Faibussowitsch {
89119a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89129a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89139566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetSize(dm->auxData, numAux));
89149a2a23afSMatthew G. Knepley   PetscFunctionReturn(0);
89159a2a23afSMatthew G. Knepley }
89169a2a23afSMatthew G. Knepley 
89179a2a23afSMatthew G. Knepley /*@
8918ac17215fSMatthew G. Knepley   DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value, and equation part
89199a2a23afSMatthew G. Knepley 
89209a2a23afSMatthew G. Knepley   Not collective
89219a2a23afSMatthew G. Knepley 
89229a2a23afSMatthew G. Knepley   Input Parameters:
8923bb7acecfSBarry Smith + dm     - The `DM`
8924bb7acecfSBarry Smith . label  - The `DMLabel`
8925ac17215fSMatthew G. Knepley . value  - The label value indicating the region
8926ac17215fSMatthew G. Knepley - part   - The equation part, or 0 if unused
89279a2a23afSMatthew G. Knepley 
89289a2a23afSMatthew G. Knepley   Output Parameter:
8929bb7acecfSBarry Smith . aux    - The `Vec` holding auxiliary field data
89309a2a23afSMatthew G. Knepley 
8931bb7acecfSBarry Smith   Note:
8932bb7acecfSBarry Smith   If no auxiliary vector is found for this (label, value), (NULL, 0, 0) is checked as well.
893304c51a94SMatthew G. Knepley 
89349a2a23afSMatthew G. Knepley   Level: advanced
89359a2a23afSMatthew G. Knepley 
8936bb7acecfSBarry Smith .seealso: `DMSetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryLabels()`
89379a2a23afSMatthew G. Knepley @*/
8938d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec *aux)
8939d71ae5a4SJacob Faibussowitsch {
8940ac17215fSMatthew G. Knepley   PetscHashAuxKey key, wild = {NULL, 0, 0};
894104c51a94SMatthew G. Knepley   PetscBool       has;
89429a2a23afSMatthew G. Knepley 
89439a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89449a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89459a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
89469a2a23afSMatthew G. Knepley   key.label = label;
89479a2a23afSMatthew G. Knepley   key.value = value;
8948ac17215fSMatthew G. Knepley   key.part  = part;
89499566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxHas(dm->auxData, key, &has));
89509566063dSJacob Faibussowitsch   if (has) PetscCall(PetscHMapAuxGet(dm->auxData, key, aux));
89519566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxGet(dm->auxData, wild, aux));
89529a2a23afSMatthew G. Knepley   PetscFunctionReturn(0);
89539a2a23afSMatthew G. Knepley }
89549a2a23afSMatthew G. Knepley 
89559a2a23afSMatthew G. Knepley /*@
8956bb7acecfSBarry Smith   DMSetAuxiliaryVec - Set an auxiliary vector for region specified by the given label and value, and equation part
89579a2a23afSMatthew G. Knepley 
8958bb7acecfSBarry Smith   Not collective because auxilary vectors are not parallel
89599a2a23afSMatthew G. Knepley 
89609a2a23afSMatthew G. Knepley   Input Parameters:
8961bb7acecfSBarry Smith + dm     - The `DM`
8962bb7acecfSBarry Smith . label  - The `DMLabel`
89639a2a23afSMatthew G. Knepley . value  - The label value indicating the region
8964ac17215fSMatthew G. Knepley . part   - The equation part, or 0 if unused
8965bb7acecfSBarry Smith - aux    - The `Vec` holding auxiliary field data
89669a2a23afSMatthew G. Knepley 
89679a2a23afSMatthew G. Knepley   Level: advanced
89689a2a23afSMatthew G. Knepley 
8969bb7acecfSBarry Smith .seealso: `DMGetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMCopyAuxiliaryVec()`
89709a2a23afSMatthew G. Knepley @*/
8971d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec aux)
8972d71ae5a4SJacob Faibussowitsch {
89739a2a23afSMatthew G. Knepley   Vec             old;
89749a2a23afSMatthew G. Knepley   PetscHashAuxKey key;
89759a2a23afSMatthew G. Knepley 
89769a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89779a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89789a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
89799a2a23afSMatthew G. Knepley   key.label = label;
89809a2a23afSMatthew G. Knepley   key.value = value;
8981ac17215fSMatthew G. Knepley   key.part  = part;
89829566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGet(dm->auxData, key, &old));
89839566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)aux));
89849566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)old));
89859566063dSJacob Faibussowitsch   if (!aux) PetscCall(PetscHMapAuxDel(dm->auxData, key));
89869566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxSet(dm->auxData, key, aux));
89879a2a23afSMatthew G. Knepley   PetscFunctionReturn(0);
89889a2a23afSMatthew G. Knepley }
89899a2a23afSMatthew G. Knepley 
89909a2a23afSMatthew G. Knepley /*@C
8991bb7acecfSBarry Smith   DMGetAuxiliaryLabels - Get the labels, values, and parts for all auxiliary vectors in this `DM`
89929a2a23afSMatthew G. Knepley 
89939a2a23afSMatthew G. Knepley   Not collective
89949a2a23afSMatthew G. Knepley 
89959a2a23afSMatthew G. Knepley   Input Parameter:
8996bb7acecfSBarry Smith . dm      - The `DM`
89979a2a23afSMatthew G. Knepley 
89989a2a23afSMatthew G. Knepley   Output Parameters:
8999bb7acecfSBarry Smith + labels  - The `DMLabel`s for each `Vec`
9000bb7acecfSBarry Smith . values  - The label values for each `Vec`
9001bb7acecfSBarry Smith - parts   - The equation parts for each `Vec`
90029a2a23afSMatthew G. Knepley 
9003bb7acecfSBarry Smith   Note:
9004bb7acecfSBarry Smith   The arrays passed in must be at least as large as `DMGetNumAuxiliaryVec()`.
90059a2a23afSMatthew G. Knepley 
90069a2a23afSMatthew G. Knepley   Level: advanced
90079a2a23afSMatthew G. Knepley 
9008bb7acecfSBarry Smith .seealso: `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMSetAuxiliaryVec()`, DMCopyAuxiliaryVec()`
90099a2a23afSMatthew G. Knepley @*/
9010d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[], PetscInt parts[])
9011d71ae5a4SJacob Faibussowitsch {
90129a2a23afSMatthew G. Knepley   PetscHashAuxKey *keys;
90139a2a23afSMatthew G. Knepley   PetscInt         n, i, off = 0;
90149a2a23afSMatthew G. Knepley 
90159a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90169a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90179a2a23afSMatthew G. Knepley   PetscValidPointer(labels, 2);
9018dadcf809SJacob Faibussowitsch   PetscValidIntPointer(values, 3);
9019dadcf809SJacob Faibussowitsch   PetscValidIntPointer(parts, 4);
90209566063dSJacob Faibussowitsch   PetscCall(DMGetNumAuxiliaryVec(dm, &n));
90219566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &keys));
90229566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetKeys(dm->auxData, &off, keys));
90239371c9d4SSatish Balay   for (i = 0; i < n; ++i) {
90249371c9d4SSatish Balay     labels[i] = keys[i].label;
90259371c9d4SSatish Balay     values[i] = keys[i].value;
90269371c9d4SSatish Balay     parts[i]  = keys[i].part;
90279371c9d4SSatish Balay   }
90289566063dSJacob Faibussowitsch   PetscCall(PetscFree(keys));
90299a2a23afSMatthew G. Knepley   PetscFunctionReturn(0);
90309a2a23afSMatthew G. Knepley }
90319a2a23afSMatthew G. Knepley 
90329a2a23afSMatthew G. Knepley /*@
9033bb7acecfSBarry Smith   DMCopyAuxiliaryVec - Copy the auxiliary vector data on a `DM` to a new `DM`
90349a2a23afSMatthew G. Knepley 
90359a2a23afSMatthew G. Knepley   Not collective
90369a2a23afSMatthew G. Knepley 
90379a2a23afSMatthew G. Knepley   Input Parameter:
9038bb7acecfSBarry Smith . dm    - The `DM`
90399a2a23afSMatthew G. Knepley 
90409a2a23afSMatthew G. Knepley   Output Parameter:
9041bb7acecfSBarry Smith . dmNew - The new `DM`, now with the same auxiliary data
90429a2a23afSMatthew G. Knepley 
90439a2a23afSMatthew G. Knepley   Level: advanced
90449a2a23afSMatthew G. Knepley 
9045bb7acecfSBarry Smith   Note:
9046bb7acecfSBarry Smith   This is a shallow copy of the auxiliary vectors
9047bb7acecfSBarry Smith 
9048db781477SPatrick Sanan .seealso: `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
90499a2a23afSMatthew G. Knepley @*/
9050d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew)
9051d71ae5a4SJacob Faibussowitsch {
90529a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90539a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90549566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDestroy(&dmNew->auxData));
90559566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData));
90569a2a23afSMatthew G. Knepley   PetscFunctionReturn(0);
90579a2a23afSMatthew G. Knepley }
9058b5a892a1SMatthew G. Knepley 
9059b5a892a1SMatthew G. Knepley /*@C
9060bb7acecfSBarry Smith   DMPolytopeMatchOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9061b5a892a1SMatthew G. Knepley 
9062b5a892a1SMatthew G. Knepley   Not collective
9063b5a892a1SMatthew G. Knepley 
9064b5a892a1SMatthew G. Knepley   Input Parameters:
9065bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9066b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9067b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9068b5a892a1SMatthew G. Knepley 
9069b5a892a1SMatthew G. Knepley   Output Parameters:
9070bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9071b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9072b5a892a1SMatthew G. Knepley 
9073b5a892a1SMatthew G. Knepley   Level: advanced
9074b5a892a1SMatthew G. Knepley 
9075bb7acecfSBarry Smith   Note:
9076bb7acecfSBarry Smith   An arrangement is a face order combined with an orientation for each face
9077bb7acecfSBarry Smith 
9078bb7acecfSBarry Smith   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangments(ct)`/2 to `DMPolytopeTypeGetNumArrangments(ct)`/2
9079bb7acecfSBarry Smith   that labels each arrangement (face ordering plus orientation for each face).
9080bb7acecfSBarry Smith 
9081bb7acecfSBarry Smith   See `DMPolytopeMatchVertexOrientation()` to find a new vertex orientation that takes the source vertex arrangement to the target vertex arrangement
9082bb7acecfSBarry Smith 
9083bb7acecfSBarry Smith .seealso: `DMPolytopeGetOrientation()`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetVertexOrientation()`
9084b5a892a1SMatthew G. Knepley @*/
9085d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt, PetscBool *found)
9086d71ae5a4SJacob Faibussowitsch {
9087b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetConeSize(ct);
9088b5a892a1SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct) / 2;
9089b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9090b5a892a1SMatthew G. Knepley 
9091b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
90929371c9d4SSatish Balay   if (!nO) {
90939371c9d4SSatish Balay     *ornt  = 0;
90949371c9d4SSatish Balay     *found = PETSC_TRUE;
90959371c9d4SSatish Balay     PetscFunctionReturn(0);
90969371c9d4SSatish Balay   }
9097b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
9098b5a892a1SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
9099b5a892a1SMatthew G. Knepley 
91009371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
91019371c9d4SSatish Balay       if (sourceCone[arr[c * 2]] != targetCone[c]) break;
91029371c9d4SSatish Balay     if (c == cS) {
91039371c9d4SSatish Balay       *ornt = o;
91049371c9d4SSatish Balay       break;
91059371c9d4SSatish Balay     }
9106b5a892a1SMatthew G. Knepley   }
9107b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
9108b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
9109b5a892a1SMatthew G. Knepley }
9110b5a892a1SMatthew G. Knepley 
9111b5a892a1SMatthew G. Knepley /*@C
9112bb7acecfSBarry Smith   DMPolytopeGetOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9113b5a892a1SMatthew G. Knepley 
9114b5a892a1SMatthew G. Knepley   Not collective
9115b5a892a1SMatthew G. Knepley 
9116b5a892a1SMatthew G. Knepley   Input Parameters:
9117bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9118b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9119b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9120b5a892a1SMatthew G. Knepley 
9121b5a892a1SMatthew G. Knepley   Output Parameters:
9122bb7acecfSBarry Smith . ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9123b5a892a1SMatthew G. Knepley 
9124b5a892a1SMatthew G. Knepley   Level: advanced
9125b5a892a1SMatthew G. Knepley 
9126bb7acecfSBarry Smith   Note:
9127bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchOrientation()` except it will generate an error if no suitable orientation can be found.
9128bb7acecfSBarry Smith 
9129bb7acecfSBarry Smith   Developer Note:
9130bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchOrientation()` and error if none is found
9131bb7acecfSBarry Smith 
9132bb7acecfSBarry Smith .seealso: `DMPolytopeType`, `DMPolytopeMatchOrientation()`, `DMPolytopeGetVertexOrientation()`, `DMPolytopeMatchVertexOrientation()`
9133b5a892a1SMatthew G. Knepley @*/
9134d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9135d71ae5a4SJacob Faibussowitsch {
9136b5a892a1SMatthew G. Knepley   PetscBool found;
9137b5a892a1SMatthew G. Knepley 
9138b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91399566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchOrientation(ct, sourceCone, targetCone, ornt, &found));
91407a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
9141b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
9142b5a892a1SMatthew G. Knepley }
9143b5a892a1SMatthew G. Knepley 
9144b5a892a1SMatthew G. Knepley /*@C
9145bb7acecfSBarry Smith   DMPolytopeMatchVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9146b5a892a1SMatthew G. Knepley 
9147b5a892a1SMatthew G. Knepley   Not collective
9148b5a892a1SMatthew G. Knepley 
9149b5a892a1SMatthew G. Knepley   Input Parameters:
9150bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9151b5a892a1SMatthew G. Knepley . sourceVert - The source arrangement of vertices
9152b5a892a1SMatthew G. Knepley - targetVert - The target arrangement of vertices
9153b5a892a1SMatthew G. Knepley 
9154b5a892a1SMatthew G. Knepley   Output Parameters:
9155bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9156b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9157b5a892a1SMatthew G. Knepley 
9158b5a892a1SMatthew G. Knepley   Level: advanced
9159b5a892a1SMatthew G. Knepley 
9160bb7acecfSBarry Smith   Note:
9161bb7acecfSBarry Smith   An arrangement is a vertex order
9162bb7acecfSBarry Smith 
9163bb7acecfSBarry Smith   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangments(ct)`/2 to `DMPolytopeTypeGetNumArrangments(ct)`/2
9164bb7acecfSBarry Smith   that labels each arrangement (vertex ordering).
9165bb7acecfSBarry Smith 
9166bb7acecfSBarry Smith   See `DMPolytopeMatchOrientation()` to find a new face orientation that takes the source face arrangement to the target face arrangement
9167bb7acecfSBarry Smith 
9168bb7acecfSBarry Smith .seealso: `DMPolytopeType`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchOrientation()`, `DMPolytopeTypeGetNumVertices()`, `DMPolytopeTypeGetVertexArrangment()`
9169b5a892a1SMatthew G. Knepley @*/
9170d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchVertexOrientation(DMPolytopeType ct, const PetscInt sourceVert[], const PetscInt targetVert[], PetscInt *ornt, PetscBool *found)
9171d71ae5a4SJacob Faibussowitsch {
9172b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetNumVertices(ct);
9173b5a892a1SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct) / 2;
9174b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9175b5a892a1SMatthew G. Knepley 
9176b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91779371c9d4SSatish Balay   if (!nO) {
91789371c9d4SSatish Balay     *ornt  = 0;
91799371c9d4SSatish Balay     *found = PETSC_TRUE;
91809371c9d4SSatish Balay     PetscFunctionReturn(0);
91819371c9d4SSatish Balay   }
9182b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
9183b5a892a1SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetVertexArrangment(ct, o);
9184b5a892a1SMatthew G. Knepley 
91859371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
91869371c9d4SSatish Balay       if (sourceVert[arr[c]] != targetVert[c]) break;
91879371c9d4SSatish Balay     if (c == cS) {
91889371c9d4SSatish Balay       *ornt = o;
91899371c9d4SSatish Balay       break;
91909371c9d4SSatish Balay     }
9191b5a892a1SMatthew G. Knepley   }
9192b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
9193b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
9194b5a892a1SMatthew G. Knepley }
9195b5a892a1SMatthew G. Knepley 
9196b5a892a1SMatthew G. Knepley /*@C
9197bb7acecfSBarry Smith   DMPolytopeGetVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9198b5a892a1SMatthew G. Knepley 
9199b5a892a1SMatthew G. Knepley   Not collective
9200b5a892a1SMatthew G. Knepley 
9201b5a892a1SMatthew G. Knepley   Input Parameters:
9202bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9203b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of vertices
9204b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of vertices
9205b5a892a1SMatthew G. Knepley 
9206b5a892a1SMatthew G. Knepley   Output Parameters:
9207bb7acecfSBarry Smith . ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9208b5a892a1SMatthew G. Knepley 
9209b5a892a1SMatthew G. Knepley   Level: advanced
9210b5a892a1SMatthew G. Knepley 
9211bb7acecfSBarry Smith   Note:
9212bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchVertexOrientation()` except it errors if not orientation is possible.
9213bb7acecfSBarry Smith 
9214bb7acecfSBarry Smith   Developer Note:
9215bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchVertexOrientation()` and error if none is found
9216bb7acecfSBarry Smith 
9217bb7acecfSBarry Smith .seealso: `DMPolytopeType`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetOrientation()`
9218b5a892a1SMatthew G. Knepley @*/
9219d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetVertexOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9220d71ae5a4SJacob Faibussowitsch {
9221b5a892a1SMatthew G. Knepley   PetscBool found;
9222b5a892a1SMatthew G. Knepley 
9223b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
92249566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchVertexOrientation(ct, sourceCone, targetCone, ornt, &found));
92257a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
9226b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
9227b5a892a1SMatthew G. Knepley }
9228012bc364SMatthew G. Knepley 
9229012bc364SMatthew G. Knepley /*@C
9230012bc364SMatthew G. Knepley   DMPolytopeInCellTest - Check whether a point lies inside the reference cell of given type
9231012bc364SMatthew G. Knepley 
9232012bc364SMatthew G. Knepley   Not collective
9233012bc364SMatthew G. Knepley 
9234012bc364SMatthew G. Knepley   Input Parameters:
9235bb7acecfSBarry Smith + ct    - The `DMPolytopeType`
9236012bc364SMatthew G. Knepley - point - Coordinates of the point
9237012bc364SMatthew G. Knepley 
9238012bc364SMatthew G. Knepley   Output Parameters:
9239012bc364SMatthew G. Knepley . inside  - Flag indicating whether the point is inside the reference cell of given type
9240012bc364SMatthew G. Knepley 
9241012bc364SMatthew G. Knepley   Level: advanced
9242012bc364SMatthew G. Knepley 
9243bb7acecfSBarry Smith .seealso: `DM`, `DMPolytopeType`, `DMLocatePoints()`
9244012bc364SMatthew G. Knepley @*/
9245d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeInCellTest(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
9246d71ae5a4SJacob Faibussowitsch {
9247012bc364SMatthew G. Knepley   PetscReal sum = 0.0;
9248012bc364SMatthew G. Knepley   PetscInt  d;
9249012bc364SMatthew G. Knepley 
9250012bc364SMatthew G. Knepley   PetscFunctionBegin;
9251012bc364SMatthew G. Knepley   *inside = PETSC_TRUE;
9252012bc364SMatthew G. Knepley   switch (ct) {
9253012bc364SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
9254012bc364SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
9255012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
92569371c9d4SSatish Balay       if (point[d] < -1.0) {
92579371c9d4SSatish Balay         *inside = PETSC_FALSE;
92589371c9d4SSatish Balay         break;
92599371c9d4SSatish Balay       }
9260012bc364SMatthew G. Knepley       sum += point[d];
9261012bc364SMatthew G. Knepley     }
92629371c9d4SSatish Balay     if (sum > PETSC_SMALL) {
92639371c9d4SSatish Balay       *inside = PETSC_FALSE;
92649371c9d4SSatish Balay       break;
92659371c9d4SSatish Balay     }
9266012bc364SMatthew G. Knepley     break;
9267012bc364SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
9268012bc364SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
9269012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
92709371c9d4SSatish Balay       if (PetscAbsReal(point[d]) > 1. + PETSC_SMALL) {
92719371c9d4SSatish Balay         *inside = PETSC_FALSE;
9272012bc364SMatthew G. Knepley         break;
92739371c9d4SSatish Balay       }
92749371c9d4SSatish Balay     break;
9275d71ae5a4SJacob Faibussowitsch   default:
9276d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
9277012bc364SMatthew G. Knepley   }
9278012bc364SMatthew G. Knepley   PetscFunctionReturn(0);
9279012bc364SMatthew G. Knepley }
9280