xref: /petsc/src/dm/interface/dm.c (revision d5b43468fb8780a8feea140ccd6fa3e6a50411cc)
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);
32149566063dSJacob Faibussowitsch   PetscCall((*dm->ops->localtolocalbegin)(dm, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l));
3215f089877aSRichard Tran Mills   PetscFunctionReturn(0);
3216f089877aSRichard Tran Mills }
3217f089877aSRichard Tran Mills 
3218f089877aSRichard Tran Mills /*@
3219bb7acecfSBarry Smith    DMLocalToLocalEnd - Maps from a local vector to another local vector where the ghost
3220bb7acecfSBarry Smith    points in the second are set correctly. Must be preceded by `DMLocalToLocalBegin()`.
3221f089877aSRichard Tran Mills 
3222d083f849SBarry Smith    Neighbor-wise Collective on dm
3223f089877aSRichard Tran Mills 
3224f089877aSRichard Tran Mills    Input Parameters:
3225bb7acecfSBarry Smith +  da - the `DM` object
3226bc0a1609SRichard Tran Mills .  g - the original local vector
3227bb7acecfSBarry Smith -  mode - one of `INSERT_VALUES` or `ADD_VALUES`
3228f089877aSRichard Tran Mills 
3229bc0a1609SRichard Tran Mills    Output Parameter:
3230bc0a1609SRichard Tran Mills .  l  - the local vector with correct ghost values
3231f089877aSRichard Tran Mills 
3232f089877aSRichard Tran Mills    Level: intermediate
3233f089877aSRichard Tran Mills 
3234bb7acecfSBarry Smith .seealso: `DMLocalToLocalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMLocalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3235f089877aSRichard Tran Mills 
3236f089877aSRichard Tran Mills @*/
3237d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
3238d71ae5a4SJacob Faibussowitsch {
3239f089877aSRichard Tran Mills   PetscFunctionBegin;
3240f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32419566063dSJacob Faibussowitsch   PetscCall((*dm->ops->localtolocalend)(dm, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l));
3242f089877aSRichard Tran Mills   PetscFunctionReturn(0);
3243f089877aSRichard Tran Mills }
3244f089877aSRichard Tran Mills 
324547c6ae99SBarry Smith /*@
3246bb7acecfSBarry Smith     DMCoarsen - Coarsens a `DM` object using a standard, non-adaptive coarsening of the underlying mesh
324747c6ae99SBarry Smith 
3248d083f849SBarry Smith     Collective on dm
324947c6ae99SBarry Smith 
3250d8d19677SJose E. Roman     Input Parameters:
3251bb7acecfSBarry Smith +   dm - the `DM` object
3252bb7acecfSBarry Smith -   comm - the communicator to contain the new `DM` object (or MPI_COMM_NULL)
325347c6ae99SBarry Smith 
325447c6ae99SBarry Smith     Output Parameter:
3255bb7acecfSBarry Smith .   dmc - the coarsened `DM`
325647c6ae99SBarry Smith 
325747c6ae99SBarry Smith     Level: developer
325847c6ae99SBarry Smith 
3259bb7acecfSBarry Smith .seealso: `DM`, `DMRefine()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
326047c6ae99SBarry Smith 
326147c6ae99SBarry Smith @*/
3262d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
3263d71ae5a4SJacob Faibussowitsch {
3264b17ce1afSJed Brown   DMCoarsenHookLink link;
326547c6ae99SBarry Smith 
326647c6ae99SBarry Smith   PetscFunctionBegin;
3267171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Coarsen, dm, 0, 0, 0));
3269dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, coarsen, comm, dmc);
3270b9d85ea2SLisandro Dalcin   if (*dmc) {
3271a3574896SRichard Tran Mills     (*dmc)->bind_below = dm->bind_below; /* Propagate this from parent DM; otherwise -dm_bind_below will be useless for multigrid cases. */
32729566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dm, *dmc));
327343842a1eSJed Brown     (*dmc)->ops->creatematrix = dm->ops->creatematrix;
32749566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmc));
3275644e2e5bSBarry Smith     (*dmc)->ctx       = dm->ctx;
32760598a293SJed Brown     (*dmc)->levelup   = dm->levelup;
3277656b349aSBarry Smith     (*dmc)->leveldown = dm->leveldown + 1;
32789566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmc, dm->mattype));
3279b17ce1afSJed Brown     for (link = dm->coarsenhook; link; link = link->next) {
32809566063dSJacob Faibussowitsch       if (link->coarsenhook) PetscCall((*link->coarsenhook)(dm, *dmc, link->ctx));
3281b17ce1afSJed Brown     }
3282b9d85ea2SLisandro Dalcin   }
32839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Coarsen, dm, 0, 0, 0));
32847a8be351SBarry Smith   PetscCheck(*dmc, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
3285b17ce1afSJed Brown   PetscFunctionReturn(0);
3286b17ce1afSJed Brown }
3287b17ce1afSJed Brown 
3288bb9467b5SJed Brown /*@C
3289b17ce1afSJed Brown    DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
3290b17ce1afSJed Brown 
3291bb7acecfSBarry Smith    Logically Collective on fine
3292b17ce1afSJed Brown 
32934165533cSJose E. Roman    Input Parameters:
3294bb7acecfSBarry Smith +  fine - `DM` on which to run a hook when restricting to a coarser level
3295b17ce1afSJed Brown .  coarsenhook - function to run when setting up a coarser level
3296bb7acecfSBarry Smith .  restricthook - function to run to update data on coarser levels (called once per `SNESSolve()`)
32970298fd71SBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3298b17ce1afSJed Brown 
3299b17ce1afSJed Brown    Calling sequence of coarsenhook:
3300b17ce1afSJed Brown $    coarsenhook(DM fine,DM coarse,void *ctx);
3301b17ce1afSJed Brown 
3302bb7acecfSBarry Smith +  fine - fine level `DM`
3303bb7acecfSBarry Smith .  coarse - coarse level `DM` to restrict problem to
3304b17ce1afSJed Brown -  ctx - optional user-defined function context
3305b17ce1afSJed Brown 
3306b17ce1afSJed Brown    Calling sequence for restricthook:
3307c833c3b5SJed Brown $    restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx)
3308bb7acecfSBarry Smith $
3309bb7acecfSBarry Smith +  fine - fine level `DM`
3310bb7acecfSBarry Smith .  mrestrict - matrix restricting a fine-level solution to the coarse grid, usually the transpose of the interpolation
3311c833c3b5SJed Brown .  rscale - scaling vector for restriction
3312c833c3b5SJed Brown .  inject - matrix restricting by injection
3313b17ce1afSJed Brown .  coarse - coarse level DM to update
3314b17ce1afSJed Brown -  ctx - optional user-defined function context
3315b17ce1afSJed Brown 
3316b17ce1afSJed Brown    Level: advanced
3317b17ce1afSJed Brown 
3318b17ce1afSJed Brown    Notes:
3319bb7acecfSBarry 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`.
3320b17ce1afSJed Brown 
3321b17ce1afSJed Brown    If this function is called multiple times, the hooks will be run in the order they are added.
3322b17ce1afSJed Brown 
3323b17ce1afSJed Brown    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3324bb7acecfSBarry Smith    extract the finest level information from its context (instead of from the `SNES`).
3325b17ce1afSJed Brown 
3326bb7acecfSBarry Smith    The hooks are automatically called by `DMRestrict()`
3327bb7acecfSBarry Smith 
3328bb7acecfSBarry Smith    Fortran Note:
3329bb7acecfSBarry Smith    This function is not available from Fortran.
3330bb9467b5SJed Brown 
3331db781477SPatrick Sanan .seealso: `DMCoarsenHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3332b17ce1afSJed Brown @*/
3333d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHookAdd(DM fine, PetscErrorCode (*coarsenhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, Mat, Vec, Mat, DM, void *), void *ctx)
3334d71ae5a4SJacob Faibussowitsch {
3335b17ce1afSJed Brown   DMCoarsenHookLink link, *p;
3336b17ce1afSJed Brown 
3337b17ce1afSJed Brown   PetscFunctionBegin;
3338b17ce1afSJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
33391e3d8eccSJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
33401e3d8eccSJed Brown     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0);
33411e3d8eccSJed Brown   }
33429566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
3343b17ce1afSJed Brown   link->coarsenhook  = coarsenhook;
3344b17ce1afSJed Brown   link->restricthook = restricthook;
3345b17ce1afSJed Brown   link->ctx          = ctx;
33460298fd71SBarry Smith   link->next         = NULL;
3347b17ce1afSJed Brown   *p                 = link;
3348b17ce1afSJed Brown   PetscFunctionReturn(0);
3349b17ce1afSJed Brown }
3350b17ce1afSJed Brown 
3351dc822a44SJed Brown /*@C
3352bb7acecfSBarry Smith    DMCoarsenHookRemove - remove a callback set with `DMCoarsenHookAdd()`
3353dc822a44SJed Brown 
3354bb7acecfSBarry Smith    Logically Collective on fine
3355dc822a44SJed Brown 
33564165533cSJose E. Roman    Input Parameters:
3357bb7acecfSBarry Smith +  fine - `DM` on which to run a hook when restricting to a coarser level
3358dc822a44SJed Brown .  coarsenhook - function to run when setting up a coarser level
3359bb7acecfSBarry Smith .  restricthook - function to run to update data on coarser levels
3360dc822a44SJed Brown -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3361dc822a44SJed Brown 
3362dc822a44SJed Brown    Level: advanced
3363dc822a44SJed Brown 
3364bb7acecfSBarry Smith    Note:
3365dc822a44SJed Brown    This function does nothing if the hook is not in the list.
3366dc822a44SJed Brown 
3367bb7acecfSBarry Smith    Fortran Note:
3368bb7acecfSBarry Smith    This function is not available from Fortran.
3369dc822a44SJed Brown 
3370db781477SPatrick Sanan .seealso: `DMCoarsenHookAdd()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3371dc822a44SJed Brown @*/
3372d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHookRemove(DM fine, PetscErrorCode (*coarsenhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, Mat, Vec, Mat, DM, void *), void *ctx)
3373d71ae5a4SJacob Faibussowitsch {
3374dc822a44SJed Brown   DMCoarsenHookLink link, *p;
3375dc822a44SJed Brown 
3376dc822a44SJed Brown   PetscFunctionBegin;
3377dc822a44SJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
3378dc822a44SJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3379dc822a44SJed Brown     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3380dc822a44SJed Brown       link = *p;
3381dc822a44SJed Brown       *p   = link->next;
33829566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3383dc822a44SJed Brown       break;
3384dc822a44SJed Brown     }
3385dc822a44SJed Brown   }
3386dc822a44SJed Brown   PetscFunctionReturn(0);
3387dc822a44SJed Brown }
3388dc822a44SJed Brown 
3389b17ce1afSJed Brown /*@
3390bb7acecfSBarry Smith    DMRestrict - restricts user-defined problem data to a coarser `DM` by running hooks registered by `DMCoarsenHookAdd()`
3391b17ce1afSJed Brown 
3392b17ce1afSJed Brown    Collective if any hooks are
3393b17ce1afSJed Brown 
33944165533cSJose E. Roman    Input Parameters:
3395bb7acecfSBarry Smith +  fine - finer `DM` from which the data is obtained
3396bb7acecfSBarry Smith .  restrct - restriction matrix, apply using `MatRestrict()`, usually the transpose of the interpolation
3397e91eccc2SStefano Zampini .  rscale - scaling vector for restriction
3398bb7acecfSBarry Smith .  inject - injection matrix, also use `MatRestrict()`
3399e91eccc2SStefano Zampini -  coarse - coarser DM to update
3400b17ce1afSJed Brown 
3401b17ce1afSJed Brown    Level: developer
3402b17ce1afSJed Brown 
3403bb7acecfSBarry Smith    Developer Note:
3404bb7acecfSBarry Smith    Though this routine is called `DMRestrict()` the hooks are added with `DMCoarsenHookAdd()`, a consistent terminology would be better
3405bb7acecfSBarry Smith 
3406bb7acecfSBarry Smith .seealso: `DMCoarsenHookAdd()`, `MatRestrict()`, `DMInterpolate()`, `DMRefineHookAdd()`
3407b17ce1afSJed Brown @*/
3408d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestrict(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse)
3409d71ae5a4SJacob Faibussowitsch {
3410b17ce1afSJed Brown   DMCoarsenHookLink link;
3411b17ce1afSJed Brown 
3412b17ce1afSJed Brown   PetscFunctionBegin;
3413b17ce1afSJed Brown   for (link = fine->coarsenhook; link; link = link->next) {
34141baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(fine, restrct, rscale, inject, coarse, link->ctx));
3415b17ce1afSJed Brown   }
341647c6ae99SBarry Smith   PetscFunctionReturn(0);
341747c6ae99SBarry Smith }
341847c6ae99SBarry Smith 
3419bb9467b5SJed Brown /*@C
3420be081cd6SPeter Brune    DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
34215dbd56e3SPeter Brune 
3422d083f849SBarry Smith    Logically Collective on global
34235dbd56e3SPeter Brune 
34244165533cSJose E. Roman    Input Parameters:
3425bb7acecfSBarry Smith +  global - global `DM`
3426bb7acecfSBarry Smith .  ddhook - function to run to pass data to the decomposition `DM` upon its creation
34275dbd56e3SPeter Brune .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
34280298fd71SBarry Smith -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
34295dbd56e3SPeter Brune 
3430ec4806b8SPeter Brune    Calling sequence for ddhook:
3431ec4806b8SPeter Brune $    ddhook(DM global,DM block,void *ctx)
3432ec4806b8SPeter Brune 
3433bb7acecfSBarry Smith +  global - global `DM`
3434bb7acecfSBarry Smith .  block  - block `DM`
3435ec4806b8SPeter Brune -  ctx - optional user-defined function context
3436ec4806b8SPeter Brune 
34375dbd56e3SPeter Brune    Calling sequence for restricthook:
3438ec4806b8SPeter Brune $    restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx)
34395dbd56e3SPeter Brune 
3440bb7acecfSBarry Smith +  global - global `DM`
34415dbd56e3SPeter Brune .  out    - scatter to the outer (with ghost and overlap points) block vector
34425dbd56e3SPeter Brune .  in     - scatter to block vector values only owned locally
3443bb7acecfSBarry Smith .  block  - block `DM`
34445dbd56e3SPeter Brune -  ctx - optional user-defined function context
34455dbd56e3SPeter Brune 
34465dbd56e3SPeter Brune    Level: advanced
34475dbd56e3SPeter Brune 
34485dbd56e3SPeter Brune    Notes:
3449bb7acecfSBarry Smith    This function is only needed if auxiliary data needs to be set up on subdomain `DM`s.
34505dbd56e3SPeter Brune 
34515dbd56e3SPeter Brune    If this function is called multiple times, the hooks will be run in the order they are added.
34525dbd56e3SPeter Brune 
34535dbd56e3SPeter Brune    In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3454bb7acecfSBarry Smith    extract the global information from its context (instead of from the `SNES`).
34555dbd56e3SPeter Brune 
3456bb7acecfSBarry Smith    Fortran Note:
3457bb7acecfSBarry Smith    This function is not available from Fortran.
3458bb9467b5SJed Brown 
3459bb7acecfSBarry Smith .seealso: `DMSubDomainHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
34605dbd56e3SPeter Brune @*/
3461d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainHookAdd(DM global, PetscErrorCode (*ddhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, VecScatter, VecScatter, DM, void *), void *ctx)
3462d71ae5a4SJacob Faibussowitsch {
3463be081cd6SPeter Brune   DMSubDomainHookLink link, *p;
34645dbd56e3SPeter Brune 
34655dbd56e3SPeter Brune   PetscFunctionBegin;
34665dbd56e3SPeter Brune   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3467b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
3468b3a6b972SJed Brown     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0);
3469b3a6b972SJed Brown   }
34709566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
34715dbd56e3SPeter Brune   link->restricthook = restricthook;
3472be081cd6SPeter Brune   link->ddhook       = ddhook;
34735dbd56e3SPeter Brune   link->ctx          = ctx;
34740298fd71SBarry Smith   link->next         = NULL;
34755dbd56e3SPeter Brune   *p                 = link;
34765dbd56e3SPeter Brune   PetscFunctionReturn(0);
34775dbd56e3SPeter Brune }
34785dbd56e3SPeter Brune 
3479b3a6b972SJed Brown /*@C
3480b3a6b972SJed Brown    DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid
3481b3a6b972SJed Brown 
3482bb7acecfSBarry Smith    Logically Collective on global
3483b3a6b972SJed Brown 
34844165533cSJose E. Roman    Input Parameters:
3485bb7acecfSBarry Smith +  global - global `DM`
3486bb7acecfSBarry Smith .  ddhook - function to run to pass data to the decomposition `DM` upon its creation
3487b3a6b972SJed Brown .  restricthook - function to run to update data on block solve (at the beginning of the block solve)
3488b3a6b972SJed Brown -  ctx - [optional] user-defined context for provide data for the hooks (may be NULL)
3489b3a6b972SJed Brown 
3490b3a6b972SJed Brown    Level: advanced
3491b3a6b972SJed Brown 
3492bb7acecfSBarry Smith    Fortran Note:
3493bb7acecfSBarry Smith    This function is not available from Fortran.
3494b3a6b972SJed Brown 
3495db781477SPatrick Sanan .seealso: `DMSubDomainHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3496b3a6b972SJed Brown @*/
3497d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainHookRemove(DM global, PetscErrorCode (*ddhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, VecScatter, VecScatter, DM, void *), void *ctx)
3498d71ae5a4SJacob Faibussowitsch {
3499b3a6b972SJed Brown   DMSubDomainHookLink link, *p;
3500b3a6b972SJed Brown 
3501b3a6b972SJed Brown   PetscFunctionBegin;
3502b3a6b972SJed Brown   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3503b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3504b3a6b972SJed Brown     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3505b3a6b972SJed Brown       link = *p;
3506b3a6b972SJed Brown       *p   = link->next;
35079566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3508b3a6b972SJed Brown       break;
3509b3a6b972SJed Brown     }
3510b3a6b972SJed Brown   }
3511b3a6b972SJed Brown   PetscFunctionReturn(0);
3512b3a6b972SJed Brown }
3513b3a6b972SJed Brown 
35145dbd56e3SPeter Brune /*@
3515bb7acecfSBarry Smith    DMSubDomainRestrict - restricts user-defined problem data to a block `DM` by running hooks registered by `DMSubDomainHookAdd()`
35165dbd56e3SPeter Brune 
35175dbd56e3SPeter Brune    Collective if any hooks are
35185dbd56e3SPeter Brune 
35194165533cSJose E. Roman    Input Parameters:
3520bb7acecfSBarry Smith +  fine - finer `DM` to use as a base
3521be081cd6SPeter Brune .  oscatter - scatter from domain global vector filling subdomain global vector with overlap
3522be081cd6SPeter Brune .  gscatter - scatter from domain global vector filling subdomain local vector with ghosts
3523bb7acecfSBarry Smith -  coarse - coarser `DM` to update
35245dbd56e3SPeter Brune 
35255dbd56e3SPeter Brune    Level: developer
35265dbd56e3SPeter Brune 
3527db781477SPatrick Sanan .seealso: `DMCoarsenHookAdd()`, `MatRestrict()`
35285dbd56e3SPeter Brune @*/
3529d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainRestrict(DM global, VecScatter oscatter, VecScatter gscatter, DM subdm)
3530d71ae5a4SJacob Faibussowitsch {
3531be081cd6SPeter Brune   DMSubDomainHookLink link;
35325dbd56e3SPeter Brune 
35335dbd56e3SPeter Brune   PetscFunctionBegin;
3534be081cd6SPeter Brune   for (link = global->subdomainhook; link; link = link->next) {
35351baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(global, oscatter, gscatter, subdm, link->ctx));
35365dbd56e3SPeter Brune   }
35375dbd56e3SPeter Brune   PetscFunctionReturn(0);
35385dbd56e3SPeter Brune }
35395dbd56e3SPeter Brune 
35405fe1f584SPeter Brune /*@
3541bb7acecfSBarry Smith     DMGetCoarsenLevel - Gets the number of coarsenings that have generated this `DM`.
35425fe1f584SPeter Brune 
35435fe1f584SPeter Brune     Not Collective
35445fe1f584SPeter Brune 
35455fe1f584SPeter Brune     Input Parameter:
3546bb7acecfSBarry Smith .   dm - the `DM` object
35475fe1f584SPeter Brune 
35485fe1f584SPeter Brune     Output Parameter:
35496a7d9d85SPeter Brune .   level - number of coarsenings
35505fe1f584SPeter Brune 
35515fe1f584SPeter Brune     Level: developer
35525fe1f584SPeter Brune 
3553bb7acecfSBarry Smith .seealso: `DMCoarsen()`, `DMSetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
35545fe1f584SPeter Brune 
35555fe1f584SPeter Brune @*/
3556d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarsenLevel(DM dm, PetscInt *level)
3557d71ae5a4SJacob Faibussowitsch {
35585fe1f584SPeter Brune   PetscFunctionBegin;
35595fe1f584SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3560b9d85ea2SLisandro Dalcin   PetscValidIntPointer(level, 2);
35615fe1f584SPeter Brune   *level = dm->leveldown;
35625fe1f584SPeter Brune   PetscFunctionReturn(0);
35635fe1f584SPeter Brune }
35645fe1f584SPeter Brune 
35659a64c4a8SMatthew G. Knepley /*@
3566bb7acecfSBarry Smith     DMSetCoarsenLevel - Sets the number of coarsenings that have generated this `DM`.
35679a64c4a8SMatthew G. Knepley 
3568bb7acecfSBarry Smith     Collective on dm
35699a64c4a8SMatthew G. Knepley 
35709a64c4a8SMatthew G. Knepley     Input Parameters:
3571bb7acecfSBarry Smith +   dm - the `DM` object
35729a64c4a8SMatthew G. Knepley -   level - number of coarsenings
35739a64c4a8SMatthew G. Knepley 
35749a64c4a8SMatthew G. Knepley     Level: developer
35759a64c4a8SMatthew G. Knepley 
3576bb7acecfSBarry Smith     Note:
3577bb7acecfSBarry Smith     This is rarely used directly, the information is automatically set when a `DM` is created with `DMCoarsen()`
3578bb7acecfSBarry Smith 
3579bb7acecfSBarry Smith .seealso: `DMSetCoarsenLevel()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
35809a64c4a8SMatthew G. Knepley @*/
3581d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarsenLevel(DM dm, PetscInt level)
3582d71ae5a4SJacob Faibussowitsch {
35839a64c4a8SMatthew G. Knepley   PetscFunctionBegin;
35849a64c4a8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35859a64c4a8SMatthew G. Knepley   dm->leveldown = level;
35869a64c4a8SMatthew G. Knepley   PetscFunctionReturn(0);
35879a64c4a8SMatthew G. Knepley }
35889a64c4a8SMatthew G. Knepley 
358947c6ae99SBarry Smith /*@C
3590bb7acecfSBarry Smith     DMRefineHierarchy - Refines a `DM` object, all levels at once
359147c6ae99SBarry Smith 
3592d083f849SBarry Smith     Collective on dm
359347c6ae99SBarry Smith 
3594d8d19677SJose E. Roman     Input Parameters:
3595bb7acecfSBarry Smith +   dm - the `DM` object
359647c6ae99SBarry Smith -   nlevels - the number of levels of refinement
359747c6ae99SBarry Smith 
359847c6ae99SBarry Smith     Output Parameter:
3599bb7acecfSBarry Smith .   dmf - the refined `DM` hierarchy
360047c6ae99SBarry Smith 
360147c6ae99SBarry Smith     Level: developer
360247c6ae99SBarry Smith 
3603bb7acecfSBarry Smith .seealso: `DMCoarsen()`, `DMCoarsenHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
360447c6ae99SBarry Smith 
360547c6ae99SBarry Smith @*/
3606d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHierarchy(DM dm, PetscInt nlevels, DM dmf[])
3607d71ae5a4SJacob Faibussowitsch {
360847c6ae99SBarry Smith   PetscFunctionBegin;
3609171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36107a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
361147c6ae99SBarry Smith   if (nlevels == 0) PetscFunctionReturn(0);
3612b9d85ea2SLisandro Dalcin   PetscValidPointer(dmf, 3);
361347c6ae99SBarry Smith   if (dm->ops->refinehierarchy) {
3614dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, refinehierarchy, nlevels, dmf);
361547c6ae99SBarry Smith   } else if (dm->ops->refine) {
361647c6ae99SBarry Smith     PetscInt i;
361747c6ae99SBarry Smith 
36189566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &dmf[0]));
361948a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMRefine(dmf[i - 1], PetscObjectComm((PetscObject)dm), &dmf[i]));
3620ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No RefineHierarchy for this DM yet");
362147c6ae99SBarry Smith   PetscFunctionReturn(0);
362247c6ae99SBarry Smith }
362347c6ae99SBarry Smith 
362447c6ae99SBarry Smith /*@C
3625bb7acecfSBarry Smith     DMCoarsenHierarchy - Coarsens a `DM` object, all levels at once
362647c6ae99SBarry Smith 
3627d083f849SBarry Smith     Collective on dm
362847c6ae99SBarry Smith 
3629d8d19677SJose E. Roman     Input Parameters:
3630bb7acecfSBarry Smith +   dm - the `DM` object
363147c6ae99SBarry Smith -   nlevels - the number of levels of coarsening
363247c6ae99SBarry Smith 
363347c6ae99SBarry Smith     Output Parameter:
3634bb7acecfSBarry Smith .   dmc - the coarsened `DM` hierarchy
363547c6ae99SBarry Smith 
363647c6ae99SBarry Smith     Level: developer
363747c6ae99SBarry Smith 
3638bb7acecfSBarry Smith .seealso: `DMCoarsen()`, `DMRefineHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
363947c6ae99SBarry Smith 
364047c6ae99SBarry Smith @*/
3641d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
3642d71ae5a4SJacob Faibussowitsch {
364347c6ae99SBarry Smith   PetscFunctionBegin;
3644171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36457a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
364647c6ae99SBarry Smith   if (nlevels == 0) PetscFunctionReturn(0);
364747c6ae99SBarry Smith   PetscValidPointer(dmc, 3);
364847c6ae99SBarry Smith   if (dm->ops->coarsenhierarchy) {
3649dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, coarsenhierarchy, nlevels, dmc);
365047c6ae99SBarry Smith   } else if (dm->ops->coarsen) {
365147c6ae99SBarry Smith     PetscInt i;
365247c6ae99SBarry Smith 
36539566063dSJacob Faibussowitsch     PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &dmc[0]));
365448a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMCoarsen(dmc[i - 1], PetscObjectComm((PetscObject)dm), &dmc[i]));
3655ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No CoarsenHierarchy for this DM yet");
365647c6ae99SBarry Smith   PetscFunctionReturn(0);
365747c6ae99SBarry Smith }
365847c6ae99SBarry Smith 
36591a266240SBarry Smith /*@C
3660bb7acecfSBarry Smith     DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the `DM` is destroyed
36611a266240SBarry Smith 
3662bb7acecfSBarry Smith     Logically Collective if the function is collective
36631a266240SBarry Smith 
36641a266240SBarry Smith     Input Parameters:
3665bb7acecfSBarry Smith +   dm - the `DM` object
36661a266240SBarry Smith -   destroy - the destroy function
36671a266240SBarry Smith 
36681a266240SBarry Smith     Level: intermediate
36691a266240SBarry Smith 
3670bb7acecfSBarry Smith .seealso: `DMSetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
36711a266240SBarry Smith 
3672f07f9ceaSJed Brown @*/
3673d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetApplicationContextDestroy(DM dm, PetscErrorCode (*destroy)(void **))
3674d71ae5a4SJacob Faibussowitsch {
36751a266240SBarry Smith   PetscFunctionBegin;
3676171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36771a266240SBarry Smith   dm->ctxdestroy = destroy;
36781a266240SBarry Smith   PetscFunctionReturn(0);
36791a266240SBarry Smith }
36801a266240SBarry Smith 
3681b07ff414SBarry Smith /*@
3682bb7acecfSBarry Smith     DMSetApplicationContext - Set a user context into a `DM` object
368347c6ae99SBarry Smith 
368447c6ae99SBarry Smith     Not Collective
368547c6ae99SBarry Smith 
368647c6ae99SBarry Smith     Input Parameters:
3687bb7acecfSBarry Smith +   dm - the `DM` object
368847c6ae99SBarry Smith -   ctx - the user context
368947c6ae99SBarry Smith 
369047c6ae99SBarry Smith     Level: intermediate
369147c6ae99SBarry Smith 
3692bb7acecfSBarry Smith     Note:
3693bb7acecfSBarry Smith     A user context is a way to pass problem specific information that is accessable whenever the `DM` is available
3694bb7acecfSBarry Smith 
3695bb7acecfSBarry Smith .seealso: `DMGetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
369647c6ae99SBarry Smith 
369747c6ae99SBarry Smith @*/
3698d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetApplicationContext(DM dm, void *ctx)
3699d71ae5a4SJacob Faibussowitsch {
370047c6ae99SBarry Smith   PetscFunctionBegin;
3701171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
370247c6ae99SBarry Smith   dm->ctx = ctx;
370347c6ae99SBarry Smith   PetscFunctionReturn(0);
370447c6ae99SBarry Smith }
370547c6ae99SBarry Smith 
370647c6ae99SBarry Smith /*@
3707bb7acecfSBarry Smith     DMGetApplicationContext - Gets a user context from a `DM` object
370847c6ae99SBarry Smith 
370947c6ae99SBarry Smith     Not Collective
371047c6ae99SBarry Smith 
371147c6ae99SBarry Smith     Input Parameter:
3712bb7acecfSBarry Smith .   dm - the `DM` object
371347c6ae99SBarry Smith 
371447c6ae99SBarry Smith     Output Parameter:
371547c6ae99SBarry Smith .   ctx - the user context
371647c6ae99SBarry Smith 
371747c6ae99SBarry Smith     Level: intermediate
371847c6ae99SBarry Smith 
3719bb7acecfSBarry Smith     Note:
3720bb7acecfSBarry Smith     A user context is a way to pass problem specific information that is accessable whenever the `DM` is available
3721bb7acecfSBarry Smith 
3722bb7acecfSBarry Smith .seealso: `DMGetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
372347c6ae99SBarry Smith 
372447c6ae99SBarry Smith @*/
3725d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetApplicationContext(DM dm, void *ctx)
3726d71ae5a4SJacob Faibussowitsch {
372747c6ae99SBarry Smith   PetscFunctionBegin;
3728171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37291b2093e4SBarry Smith   *(void **)ctx = dm->ctx;
373047c6ae99SBarry Smith   PetscFunctionReturn(0);
373147c6ae99SBarry Smith }
373247c6ae99SBarry Smith 
373308da532bSDmitry Karpeev /*@C
3734bb7acecfSBarry Smith     DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for `SNESVI`.
373508da532bSDmitry Karpeev 
3736d083f849SBarry Smith     Logically Collective on dm
373708da532bSDmitry Karpeev 
3738d8d19677SJose E. Roman     Input Parameters:
373908da532bSDmitry Karpeev +   dm - the DM object
37400298fd71SBarry Smith -   f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set)
374108da532bSDmitry Karpeev 
374208da532bSDmitry Karpeev     Level: intermediate
374308da532bSDmitry Karpeev 
3744bb7acecfSBarry Smith .seealso: `DMComputeVariableBounds()`, `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`,
3745db781477SPatrick Sanan          `DMSetJacobian()`
374608da532bSDmitry Karpeev 
374708da532bSDmitry Karpeev @*/
3748d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetVariableBounds(DM dm, PetscErrorCode (*f)(DM, Vec, Vec))
3749d71ae5a4SJacob Faibussowitsch {
375008da532bSDmitry Karpeev   PetscFunctionBegin;
37515a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
375208da532bSDmitry Karpeev   dm->ops->computevariablebounds = f;
375308da532bSDmitry Karpeev   PetscFunctionReturn(0);
375408da532bSDmitry Karpeev }
375508da532bSDmitry Karpeev 
375608da532bSDmitry Karpeev /*@
3757bb7acecfSBarry Smith     DMHasVariableBounds - does the `DM` object have a variable bounds function?
375808da532bSDmitry Karpeev 
375908da532bSDmitry Karpeev     Not Collective
376008da532bSDmitry Karpeev 
376108da532bSDmitry Karpeev     Input Parameter:
3762bb7acecfSBarry Smith .   dm - the `DM` object to destroy
376308da532bSDmitry Karpeev 
376408da532bSDmitry Karpeev     Output Parameter:
3765bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the variable bounds function exists
376608da532bSDmitry Karpeev 
376708da532bSDmitry Karpeev     Level: developer
376808da532bSDmitry Karpeev 
3769bb7acecfSBarry Smith .seealso: `DMComputeVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
377008da532bSDmitry Karpeev 
377108da532bSDmitry Karpeev @*/
3772d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasVariableBounds(DM dm, PetscBool *flg)
3773d71ae5a4SJacob Faibussowitsch {
377408da532bSDmitry Karpeev   PetscFunctionBegin;
37755a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3776534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
377708da532bSDmitry Karpeev   *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
377808da532bSDmitry Karpeev   PetscFunctionReturn(0);
377908da532bSDmitry Karpeev }
378008da532bSDmitry Karpeev 
378108da532bSDmitry Karpeev /*@C
3782bb7acecfSBarry Smith     DMComputeVariableBounds - compute variable bounds used by `SNESVI`.
378308da532bSDmitry Karpeev 
3784d083f849SBarry Smith     Logically Collective on dm
378508da532bSDmitry Karpeev 
3786f899ff85SJose E. Roman     Input Parameter:
3787bb7acecfSBarry Smith .   dm - the `DM` object
378808da532bSDmitry Karpeev 
378908da532bSDmitry Karpeev     Output parameters:
379008da532bSDmitry Karpeev +   xl - lower bound
379108da532bSDmitry Karpeev -   xu - upper bound
379208da532bSDmitry Karpeev 
3793907376e6SBarry Smith     Level: advanced
3794907376e6SBarry Smith 
379595452b02SPatrick Sanan     Notes:
379695452b02SPatrick Sanan     This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
379708da532bSDmitry Karpeev 
3798bb7acecfSBarry Smith .seealso: `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
379908da532bSDmitry Karpeev 
380008da532bSDmitry Karpeev @*/
3801d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3802d71ae5a4SJacob Faibussowitsch {
380308da532bSDmitry Karpeev   PetscFunctionBegin;
38045a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
380508da532bSDmitry Karpeev   PetscValidHeaderSpecific(xl, VEC_CLASSID, 2);
38065a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(xu, VEC_CLASSID, 3);
3807dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, computevariablebounds, xl, xu);
380808da532bSDmitry Karpeev   PetscFunctionReturn(0);
380908da532bSDmitry Karpeev }
381008da532bSDmitry Karpeev 
3811b0ae01b7SPeter Brune /*@
3812bb7acecfSBarry Smith     DMHasColoring - does the `DM` object have a method of providing a coloring?
3813b0ae01b7SPeter Brune 
3814b0ae01b7SPeter Brune     Not Collective
3815b0ae01b7SPeter Brune 
3816b0ae01b7SPeter Brune     Input Parameter:
3817b0ae01b7SPeter Brune .   dm - the DM object
3818b0ae01b7SPeter Brune 
3819b0ae01b7SPeter Brune     Output Parameter:
3820bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateColoring()`.
3821b0ae01b7SPeter Brune 
3822b0ae01b7SPeter Brune     Level: developer
3823b0ae01b7SPeter Brune 
3824bb7acecfSBarry Smith .seealso: `DMCreateColoring()`
3825b0ae01b7SPeter Brune 
3826b0ae01b7SPeter Brune @*/
3827d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasColoring(DM dm, PetscBool *flg)
3828d71ae5a4SJacob Faibussowitsch {
3829b0ae01b7SPeter Brune   PetscFunctionBegin;
38305a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3831534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
3832b0ae01b7SPeter Brune   *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
3833b0ae01b7SPeter Brune   PetscFunctionReturn(0);
3834b0ae01b7SPeter Brune }
3835b0ae01b7SPeter Brune 
38363ad4599aSBarry Smith /*@
3837bb7acecfSBarry Smith     DMHasCreateRestriction - does the `DM` object have a method of providing a restriction?
38383ad4599aSBarry Smith 
38393ad4599aSBarry Smith     Not Collective
38403ad4599aSBarry Smith 
38413ad4599aSBarry Smith     Input Parameter:
3842bb7acecfSBarry Smith .   dm - the `DM` object
38433ad4599aSBarry Smith 
38443ad4599aSBarry Smith     Output Parameter:
3845bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateRestriction()`.
38463ad4599aSBarry Smith 
38473ad4599aSBarry Smith     Level: developer
38483ad4599aSBarry Smith 
3849bb7acecfSBarry Smith .seealso: `DMCreateRestriction()`, `DMHasCreateInterpolation()`, `DMHasCreateInjection()`
38503ad4599aSBarry Smith 
38513ad4599aSBarry Smith @*/
3852d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateRestriction(DM dm, PetscBool *flg)
3853d71ae5a4SJacob Faibussowitsch {
38543ad4599aSBarry Smith   PetscFunctionBegin;
38555a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3856534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
38573ad4599aSBarry Smith   *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
38583ad4599aSBarry Smith   PetscFunctionReturn(0);
38593ad4599aSBarry Smith }
38603ad4599aSBarry Smith 
3861a7058e45SLawrence Mitchell /*@
3862bb7acecfSBarry Smith     DMHasCreateInjection - does the `DM` object have a method of providing an injection?
3863a7058e45SLawrence Mitchell 
3864a7058e45SLawrence Mitchell     Not Collective
3865a7058e45SLawrence Mitchell 
3866a7058e45SLawrence Mitchell     Input Parameter:
3867bb7acecfSBarry Smith .   dm - the `DM` object
3868a7058e45SLawrence Mitchell 
3869a7058e45SLawrence Mitchell     Output Parameter:
3870bb7acecfSBarry Smith .   flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateInjection()`.
3871a7058e45SLawrence Mitchell 
3872a7058e45SLawrence Mitchell     Level: developer
3873a7058e45SLawrence Mitchell 
3874bb7acecfSBarry Smith .seealso: `DMCreateInjection()`, `DMHasCreateRestriction()`, `DMHasCreateInterpolation()`
3875a7058e45SLawrence Mitchell 
3876a7058e45SLawrence Mitchell @*/
3877d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateInjection(DM dm, PetscBool *flg)
3878d71ae5a4SJacob Faibussowitsch {
3879a7058e45SLawrence Mitchell   PetscFunctionBegin;
38805a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3881534a8f05SLisandro Dalcin   PetscValidBoolPointer(flg, 2);
3882dbbe0bcdSBarry Smith   if (dm->ops->hascreateinjection) PetscUseTypeMethod(dm, hascreateinjection, flg);
3883ad540459SPierre Jolivet   else *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE;
3884a7058e45SLawrence Mitchell   PetscFunctionReturn(0);
3885a7058e45SLawrence Mitchell }
3886a7058e45SLawrence Mitchell 
38870298fd71SBarry Smith PetscFunctionList DMList              = NULL;
3888264ace61SBarry Smith PetscBool         DMRegisterAllCalled = PETSC_FALSE;
3889264ace61SBarry Smith 
3890264ace61SBarry Smith /*@C
3891bb7acecfSBarry Smith   DMSetType - Builds a `DM`, for a particular `DM` implementation.
3892264ace61SBarry Smith 
3893d083f849SBarry Smith   Collective on dm
3894264ace61SBarry Smith 
3895264ace61SBarry Smith   Input Parameters:
3896bb7acecfSBarry Smith + dm     - The `DM` object
3897bb7acecfSBarry Smith - method - The name of the `DMType`, for example `DMDA`, `DMPLEX`
3898264ace61SBarry Smith 
3899264ace61SBarry Smith   Options Database Key:
3900bb7acecfSBarry Smith . -dm_type <type> - Sets the `DM` type; use -help for a list of available types
3901264ace61SBarry Smith 
3902264ace61SBarry Smith   Level: intermediate
3903264ace61SBarry Smith 
3904bb7acecfSBarry Smith   Note:
3905bb7acecfSBarry Smith   Of the `DM` is constructed by directly calling a function to construct a particular `DM`, for example, `DMDACreate2d()` or `DMPLEXCreateBoxMesh()`
3906bb7acecfSBarry Smith 
3907bb7acecfSBarry Smith .seealso: `DMType`, `DMDA`, `DMPLEX`, `DMGetType()`, `DMCreate()`, `DMDACreate2d()`
3908264ace61SBarry Smith @*/
3909d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetType(DM dm, DMType method)
3910d71ae5a4SJacob Faibussowitsch {
3911264ace61SBarry Smith   PetscErrorCode (*r)(DM);
3912264ace61SBarry Smith   PetscBool match;
3913264ace61SBarry Smith 
3914264ace61SBarry Smith   PetscFunctionBegin;
3915264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, method, &match));
3917264ace61SBarry Smith   if (match) PetscFunctionReturn(0);
3918264ace61SBarry Smith 
39199566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
39209566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(DMList, method, &r));
39217a8be351SBarry Smith   PetscCheck(r, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3922264ace61SBarry Smith 
3923dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, destroy);
39249566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(dm->ops, sizeof(*dm->ops)));
39259566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)dm, method));
39269566063dSJacob Faibussowitsch   PetscCall((*r)(dm));
3927264ace61SBarry Smith   PetscFunctionReturn(0);
3928264ace61SBarry Smith }
3929264ace61SBarry Smith 
3930264ace61SBarry Smith /*@C
3931bb7acecfSBarry Smith   DMGetType - Gets the `DM` type name (as a string) from the `DM`.
3932264ace61SBarry Smith 
3933264ace61SBarry Smith   Not Collective
3934264ace61SBarry Smith 
3935264ace61SBarry Smith   Input Parameter:
3936bb7acecfSBarry Smith . dm  - The `DM`
3937264ace61SBarry Smith 
3938264ace61SBarry Smith   Output Parameter:
3939bb7acecfSBarry Smith . type - The `DMType` name
3940264ace61SBarry Smith 
3941264ace61SBarry Smith   Level: intermediate
3942264ace61SBarry Smith 
3943bb7acecfSBarry Smith .seealso: `DMType`, `DMDA`, `DMPLEX`, `DMSetType()`, `DMCreate()`
3944264ace61SBarry Smith @*/
3945d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetType(DM dm, DMType *type)
3946d71ae5a4SJacob Faibussowitsch {
3947264ace61SBarry Smith   PetscFunctionBegin;
3948264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3949c959eef4SJed Brown   PetscValidPointer(type, 2);
39509566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
3951264ace61SBarry Smith   *type = ((PetscObject)dm)->type_name;
3952264ace61SBarry Smith   PetscFunctionReturn(0);
3953264ace61SBarry Smith }
3954264ace61SBarry Smith 
395567a56275SMatthew G Knepley /*@C
3956bb7acecfSBarry Smith   DMConvert - Converts a `DM` to another `DM`, either of the same or different type.
395767a56275SMatthew G Knepley 
3958d083f849SBarry Smith   Collective on dm
395967a56275SMatthew G Knepley 
396067a56275SMatthew G Knepley   Input Parameters:
3961bb7acecfSBarry Smith + dm - the `DM`
3962bb7acecfSBarry Smith - newtype - new `DM` type (use "same" for the same type)
396367a56275SMatthew G Knepley 
396467a56275SMatthew G Knepley   Output Parameter:
3965bb7acecfSBarry Smith . M - pointer to new `DM`
396667a56275SMatthew G Knepley 
396767a56275SMatthew G Knepley   Notes:
3968bb7acecfSBarry Smith   Cannot be used to convert a sequential `DM` to a parallel or a parallel to sequential,
3969bb7acecfSBarry Smith   the MPI communicator of the generated `DM` is always the same as the communicator
3970bb7acecfSBarry Smith   of the input `DM`.
397167a56275SMatthew G Knepley 
397267a56275SMatthew G Knepley   Level: intermediate
397367a56275SMatthew G Knepley 
3974bb7acecfSBarry Smith .seealso: `DM`, `DMSetType()`, `DMCreate()`, `DMClone()`
397567a56275SMatthew G Knepley @*/
3976d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
3977d71ae5a4SJacob Faibussowitsch {
397867a56275SMatthew G Knepley   DM        B;
397967a56275SMatthew G Knepley   char      convname[256];
3980c067b6caSMatthew G. Knepley   PetscBool sametype /*, issame */;
398167a56275SMatthew G Knepley 
398267a56275SMatthew G Knepley   PetscFunctionBegin;
398367a56275SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
398467a56275SMatthew G Knepley   PetscValidType(dm, 1);
398567a56275SMatthew G Knepley   PetscValidPointer(M, 3);
39869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, newtype, &sametype));
39879566063dSJacob Faibussowitsch   /* PetscCall(PetscStrcmp(newtype, "same", &issame)); */
3988c067b6caSMatthew G. Knepley   if (sametype) {
3989c067b6caSMatthew G. Knepley     *M = dm;
39909566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
3991c067b6caSMatthew G. Knepley     PetscFunctionReturn(0);
3992c067b6caSMatthew G. Knepley   } else {
39930298fd71SBarry Smith     PetscErrorCode (*conv)(DM, DMType, DM *) = NULL;
399467a56275SMatthew G Knepley 
399567a56275SMatthew G Knepley     /*
399667a56275SMatthew G Knepley        Order of precedence:
399767a56275SMatthew G Knepley        1) See if a specialized converter is known to the current DM.
399867a56275SMatthew G Knepley        2) See if a specialized converter is known to the desired DM class.
399967a56275SMatthew G Knepley        3) See if a good general converter is registered for the desired class
400067a56275SMatthew G Knepley        4) See if a good general converter is known for the current matrix.
400167a56275SMatthew G Knepley        5) Use a really basic converter.
400267a56275SMatthew G Knepley     */
400367a56275SMatthew G Knepley 
400467a56275SMatthew G Knepley     /* 1) See if a specialized converter is known to the current DM and the desired class */
40059566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
40069566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
40079566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
40089566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
40099566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
40109566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)dm, convname, &conv));
401167a56275SMatthew G Knepley     if (conv) goto foundconv;
401267a56275SMatthew G Knepley 
401367a56275SMatthew G Knepley     /* 2)  See if a specialized converter is known to the desired DM class. */
40149566063dSJacob Faibussowitsch     PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &B));
40159566063dSJacob Faibussowitsch     PetscCall(DMSetType(B, newtype));
40169566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
40179566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
40189566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
40199566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
40209566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
40219566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
402267a56275SMatthew G Knepley     if (conv) {
40239566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&B));
402467a56275SMatthew G Knepley       goto foundconv;
402567a56275SMatthew G Knepley     }
402667a56275SMatthew G Knepley 
402767a56275SMatthew G Knepley #if 0
402867a56275SMatthew G Knepley     /* 3) See if a good general converter is registered for the desired class */
402967a56275SMatthew G Knepley     conv = B->ops->convertfrom;
40309566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&B));
403167a56275SMatthew G Knepley     if (conv) goto foundconv;
403267a56275SMatthew G Knepley 
403367a56275SMatthew G Knepley     /* 4) See if a good general converter is known for the current matrix */
403467a56275SMatthew G Knepley     if (dm->ops->convert) {
403567a56275SMatthew G Knepley       conv = dm->ops->convert;
403667a56275SMatthew G Knepley     }
403767a56275SMatthew G Knepley     if (conv) goto foundconv;
403867a56275SMatthew G Knepley #endif
403967a56275SMatthew G Knepley 
404067a56275SMatthew G Knepley     /* 5) Use a really basic converter. */
404198921bdaSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject)dm)->type_name, newtype);
404267a56275SMatthew G Knepley 
404367a56275SMatthew G Knepley   foundconv:
40449566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(DM_Convert, dm, 0, 0, 0));
40459566063dSJacob Faibussowitsch     PetscCall((*conv)(dm, newtype, M));
404612fa691eSMatthew G. Knepley     /* Things that are independent of DM type: We should consult DMClone() here */
404790b157c4SStefano Zampini     {
40484fb89dddSMatthew G. Knepley       const PetscReal *maxCell, *Lstart, *L;
40496858538eSMatthew G. Knepley 
40504fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
40514fb89dddSMatthew G. Knepley       PetscCall(DMSetPeriodicity(*M, maxCell, Lstart, L));
4052c8a6034eSMark       (*M)->prealloc_only = dm->prealloc_only;
40539566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->vectype));
40549566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*M)->vectype));
40559566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->mattype));
40569566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*M)->mattype));
405712fa691eSMatthew G. Knepley     }
40589566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(DM_Convert, dm, 0, 0, 0));
405967a56275SMatthew G Knepley   }
40609566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
406167a56275SMatthew G Knepley   PetscFunctionReturn(0);
406267a56275SMatthew G Knepley }
4063264ace61SBarry Smith 
4064264ace61SBarry Smith /*--------------------------------------------------------------------------------------------------------------------*/
4065264ace61SBarry Smith 
4066264ace61SBarry Smith /*@C
4067bb7acecfSBarry Smith   DMRegister -  Adds a new `DM` type implementation
40681c84c290SBarry Smith 
40691c84c290SBarry Smith   Not Collective
40701c84c290SBarry Smith 
40711c84c290SBarry Smith   Input Parameters:
40721c84c290SBarry Smith + name        - The name of a new user-defined creation routine
40731c84c290SBarry Smith - create_func - The creation routine itself
40741c84c290SBarry Smith 
40751c84c290SBarry Smith   Notes:
4076bb7acecfSBarry Smith   DMRegister() may be called multiple times to add several user-defined `DM`s
40771c84c290SBarry Smith 
40781c84c290SBarry Smith   Sample usage:
40791c84c290SBarry Smith .vb
4080bdf89e91SBarry Smith     DMRegister("my_da", MyDMCreate);
40811c84c290SBarry Smith .ve
40821c84c290SBarry Smith 
40831c84c290SBarry Smith   Then, your DM type can be chosen with the procedural interface via
40841c84c290SBarry Smith .vb
40851c84c290SBarry Smith     DMCreate(MPI_Comm, DM *);
40861c84c290SBarry Smith     DMSetType(DM,"my_da");
40871c84c290SBarry Smith .ve
40881c84c290SBarry Smith    or at runtime via the option
40891c84c290SBarry Smith .vb
40901c84c290SBarry Smith     -da_type my_da
40911c84c290SBarry Smith .ve
4092264ace61SBarry Smith 
4093264ace61SBarry Smith   Level: advanced
40941c84c290SBarry Smith 
4095bb7acecfSBarry Smith .seealso: `DM`, `DMType`, `DMSetType()`, `DMRegisterAll()`, `DMRegisterDestroy()`
40961c84c290SBarry Smith 
4097264ace61SBarry Smith @*/
4098d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRegister(const char sname[], PetscErrorCode (*function)(DM))
4099d71ae5a4SJacob Faibussowitsch {
4100264ace61SBarry Smith   PetscFunctionBegin;
41019566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
41029566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&DMList, sname, function));
4103264ace61SBarry Smith   PetscFunctionReturn(0);
4104264ace61SBarry Smith }
4105264ace61SBarry Smith 
4106b859378eSBarry Smith /*@C
4107bb7acecfSBarry Smith   DMLoad - Loads a DM that has been stored in binary  with `DMView()`.
4108b859378eSBarry Smith 
4109d083f849SBarry Smith   Collective on viewer
4110b859378eSBarry Smith 
4111b859378eSBarry Smith   Input Parameters:
4112bb7acecfSBarry Smith + newdm - the newly loaded `DM`, this needs to have been created with `DMCreate()` or
4113bb7acecfSBarry Smith            some related function before a call to `DMLoad()`.
4114bb7acecfSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` or
4115bb7acecfSBarry Smith            `PETSCVIEWERHDF5` file viewer, obtained from `PetscViewerHDF5Open()`
4116b859378eSBarry Smith 
4117b859378eSBarry Smith    Level: intermediate
4118b859378eSBarry Smith 
4119b859378eSBarry Smith   Notes:
412055849f57SBarry Smith   The type is determined by the data in the file, any type set into the DM before this call is ignored.
4121b859378eSBarry Smith 
4122bb7acecfSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
4123bb7acecfSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
4124bb7acecfSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
4125cd7e8a5eSksagiyam 
4126b859378eSBarry Smith   Notes for advanced users:
4127b859378eSBarry Smith   Most users should not need to know the details of the binary storage
4128bb7acecfSBarry Smith   format, since `DMLoad()` and `DMView()` completely hide these details.
4129b859378eSBarry Smith   But for anyone who's interested, the standard binary matrix storage
4130b859378eSBarry Smith   format is
4131b859378eSBarry Smith .vb
4132b859378eSBarry Smith      has not yet been determined
4133b859378eSBarry Smith .ve
4134b859378eSBarry Smith 
4135db781477SPatrick Sanan .seealso: `PetscViewerBinaryOpen()`, `DMView()`, `MatLoad()`, `VecLoad()`
4136b859378eSBarry Smith @*/
4137d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
4138d71ae5a4SJacob Faibussowitsch {
41399331c7a4SMatthew G. Knepley   PetscBool isbinary, ishdf5;
4140b859378eSBarry Smith 
4141b859378eSBarry Smith   PetscFunctionBegin;
4142b859378eSBarry Smith   PetscValidHeaderSpecific(newdm, DM_CLASSID, 1);
4143b859378eSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
41449566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckReadable(viewer));
41459566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
41469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
41479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Load, viewer, 0, 0, 0));
41489331c7a4SMatthew G. Knepley   if (isbinary) {
41499331c7a4SMatthew G. Knepley     PetscInt classid;
41509331c7a4SMatthew G. Knepley     char     type[256];
4151b859378eSBarry Smith 
41529566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
41537a8be351SBarry Smith     PetscCheck(classid == DM_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not DM next in file, classid found %d", (int)classid);
41549566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
41559566063dSJacob Faibussowitsch     PetscCall(DMSetType(newdm, type));
4156dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41579331c7a4SMatthew G. Knepley   } else if (ishdf5) {
4158dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41599331c7a4SMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
41609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Load, viewer, 0, 0, 0));
4161b859378eSBarry Smith   PetscFunctionReturn(0);
4162b859378eSBarry Smith }
4163b859378eSBarry Smith 
41647da65231SMatthew G Knepley /******************************** FEM Support **********************************/
41657da65231SMatthew G Knepley 
4166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
4167d71ae5a4SJacob Faibussowitsch {
41681d47ebbbSSatish Balay   PetscInt f;
41691b30c384SMatthew G Knepley 
41707da65231SMatthew G Knepley   PetscFunctionBegin;
417163a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
417248a46eb9SPierre Jolivet   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f])));
41737da65231SMatthew G Knepley   PetscFunctionReturn(0);
41747da65231SMatthew G Knepley }
41757da65231SMatthew G Knepley 
4176d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
4177d71ae5a4SJacob Faibussowitsch {
41781b30c384SMatthew G Knepley   PetscInt f, g;
41797da65231SMatthew G Knepley 
41807da65231SMatthew G Knepley   PetscFunctionBegin;
418163a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
41821d47ebbbSSatish Balay   for (f = 0; f < rows; ++f) {
41839566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  |"));
418448a46eb9SPierre Jolivet     for (g = 0; g < cols; ++g) PetscCall(PetscPrintf(PETSC_COMM_SELF, " % 9.5g", (double)PetscRealPart(A[f * cols + g])));
41859566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, " |\n"));
41867da65231SMatthew G Knepley   }
41877da65231SMatthew G Knepley   PetscFunctionReturn(0);
41887da65231SMatthew G Knepley }
4189e7c4fc90SDmitry Karpeev 
4190d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
4191d71ae5a4SJacob Faibussowitsch {
41920c5b8624SToby Isaac   PetscInt           localSize, bs;
41930c5b8624SToby Isaac   PetscMPIInt        size;
41940c5b8624SToby Isaac   Vec                x, xglob;
41950c5b8624SToby Isaac   const PetscScalar *xarray;
4196e759306cSMatthew G. Knepley 
4197e759306cSMatthew G. Knepley   PetscFunctionBegin;
41989566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
41999566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, &x));
42009566063dSJacob Faibussowitsch   PetscCall(VecCopy(X, x));
42019566063dSJacob Faibussowitsch   PetscCall(VecChop(x, tol));
42029566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "%s:\n", name));
42030c5b8624SToby Isaac   if (size > 1) {
42049566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(x, &localSize));
42059566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xarray));
42069566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(x, &bs));
42079566063dSJacob Faibussowitsch     PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)dm), bs, localSize, PETSC_DETERMINE, xarray, &xglob));
42080c5b8624SToby Isaac   } else {
42090c5b8624SToby Isaac     xglob = x;
42100c5b8624SToby Isaac   }
42119566063dSJacob Faibussowitsch   PetscCall(VecView(xglob, PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)dm))));
42120c5b8624SToby Isaac   if (size > 1) {
42139566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xglob));
42149566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xarray));
42150c5b8624SToby Isaac   }
42169566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
4217e759306cSMatthew G. Knepley   PetscFunctionReturn(0);
4218e759306cSMatthew G. Knepley }
4219e759306cSMatthew G. Knepley 
422088ed4aceSMatthew G Knepley /*@
4221bb7acecfSBarry Smith   DMGetSection - Get the `PetscSection` encoding the local data layout for the `DM`.   This is equivalent to `DMGetLocalSection()`. Deprecated in v3.12
4222061576a5SJed Brown 
4223061576a5SJed Brown   Input Parameter:
4224bb7acecfSBarry Smith . dm - The `DM`
4225061576a5SJed Brown 
4226061576a5SJed Brown   Output Parameter:
4227bb7acecfSBarry Smith . section - The `PetscSection`
4228061576a5SJed Brown 
4229061576a5SJed Brown   Options Database Keys:
4230bb7acecfSBarry Smith . -dm_petscsection_view - View the `PetscSection` created by the `DM`
4231061576a5SJed Brown 
4232061576a5SJed Brown   Level: advanced
4233061576a5SJed Brown 
4234061576a5SJed Brown   Notes:
4235bb7acecfSBarry Smith   Use `DMGetLocalSection()` in new code.
4236061576a5SJed Brown 
4237bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
4238061576a5SJed Brown 
4239db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `DMSetLocalSection()`, `DMGetGlobalSection()`
4240061576a5SJed Brown @*/
4241d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSection(DM dm, PetscSection *section)
4242d71ae5a4SJacob Faibussowitsch {
4243061576a5SJed Brown   PetscFunctionBegin;
42449566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, section));
4245061576a5SJed Brown   PetscFunctionReturn(0);
4246061576a5SJed Brown }
4247061576a5SJed Brown 
4248061576a5SJed Brown /*@
4249bb7acecfSBarry Smith   DMGetLocalSection - Get the `PetscSection` encoding the local data layout for the `DM`.
425088ed4aceSMatthew G Knepley 
425188ed4aceSMatthew G Knepley   Input Parameter:
4252bb7acecfSBarry Smith . dm - The `DM`
425388ed4aceSMatthew G Knepley 
425488ed4aceSMatthew G Knepley   Output Parameter:
4255bb7acecfSBarry Smith . section - The `PetscSection`
425688ed4aceSMatthew G Knepley 
4257e5893cccSMatthew G. Knepley   Options Database Keys:
4258bb7acecfSBarry Smith . -dm_petscsection_view - View the section created by the `DM`
4259e5893cccSMatthew G. Knepley 
426088ed4aceSMatthew G Knepley   Level: intermediate
426188ed4aceSMatthew G Knepley 
4262bb7acecfSBarry Smith   Note:
4263bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
426488ed4aceSMatthew G Knepley 
4265db781477SPatrick Sanan .seealso: `DMSetLocalSection()`, `DMGetGlobalSection()`
426688ed4aceSMatthew G Knepley @*/
4267d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section)
4268d71ae5a4SJacob Faibussowitsch {
426988ed4aceSMatthew G Knepley   PetscFunctionBegin;
427088ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
427188ed4aceSMatthew G Knepley   PetscValidPointer(section, 2);
42721bb6d2a8SBarry Smith   if (!dm->localSection && dm->ops->createlocalsection) {
4273e5e52638SMatthew G. Knepley     PetscInt d;
4274e5e52638SMatthew G. Knepley 
427545480ffeSMatthew G. Knepley     if (dm->setfromoptionscalled) {
427645480ffeSMatthew G. Knepley       PetscObject       obj = (PetscObject)dm;
427745480ffeSMatthew G. Knepley       PetscViewer       viewer;
427845480ffeSMatthew G. Knepley       PetscViewerFormat format;
427945480ffeSMatthew G. Knepley       PetscBool         flg;
428045480ffeSMatthew G. Knepley 
42819566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm(obj), obj->options, obj->prefix, "-dm_petscds_view", &viewer, &format, &flg));
42829566063dSJacob Faibussowitsch       if (flg) PetscCall(PetscViewerPushFormat(viewer, format));
428345480ffeSMatthew G. Knepley       for (d = 0; d < dm->Nds; ++d) {
42849566063dSJacob Faibussowitsch         PetscCall(PetscDSSetFromOptions(dm->probs[d].ds));
42859566063dSJacob Faibussowitsch         if (flg) PetscCall(PetscDSView(dm->probs[d].ds, viewer));
428645480ffeSMatthew G. Knepley       }
428745480ffeSMatthew G. Knepley       if (flg) {
42889566063dSJacob Faibussowitsch         PetscCall(PetscViewerFlush(viewer));
42899566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
42909566063dSJacob Faibussowitsch         PetscCall(PetscViewerDestroy(&viewer));
429145480ffeSMatthew G. Knepley       }
429245480ffeSMatthew G. Knepley     }
4293dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createlocalsection);
42949566063dSJacob Faibussowitsch     if (dm->localSection) PetscCall(PetscObjectViewFromOptions((PetscObject)dm->localSection, NULL, "-dm_petscsection_view"));
42952f0f8703SMatthew G. Knepley   }
42961bb6d2a8SBarry Smith   *section = dm->localSection;
429788ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
429888ed4aceSMatthew G Knepley }
429988ed4aceSMatthew G Knepley 
430088ed4aceSMatthew G Knepley /*@
4301bb7acecfSBarry Smith   DMSetSection - Set the `PetscSection` encoding the local data layout for the `DM`.  This is equivalent to `DMSetLocalSection()`. Deprecated in v3.12
4302061576a5SJed Brown 
4303061576a5SJed Brown   Input Parameters:
4304bb7acecfSBarry Smith + dm - The `DM`
4305bb7acecfSBarry Smith - section - The `PetscSection`
4306061576a5SJed Brown 
4307061576a5SJed Brown   Level: advanced
4308061576a5SJed Brown 
4309061576a5SJed Brown   Notes:
4310bb7acecfSBarry Smith   Use `DMSetLocalSection()` in new code.
4311061576a5SJed Brown 
4312bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4313061576a5SJed Brown 
4314db781477SPatrick Sanan .seealso: `DMSetLocalSection()`, `DMGetLocalSection()`, `DMSetGlobalSection()`
4315061576a5SJed Brown @*/
4316d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSection(DM dm, PetscSection section)
4317d71ae5a4SJacob Faibussowitsch {
4318061576a5SJed Brown   PetscFunctionBegin;
43199566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(dm, section));
4320061576a5SJed Brown   PetscFunctionReturn(0);
4321061576a5SJed Brown }
4322061576a5SJed Brown 
4323061576a5SJed Brown /*@
4324bb7acecfSBarry Smith   DMSetLocalSection - Set the `PetscSection` encoding the local data layout for the `DM`.
432588ed4aceSMatthew G Knepley 
432688ed4aceSMatthew G Knepley   Input Parameters:
4327bb7acecfSBarry Smith + dm - The `DM`
4328bb7acecfSBarry Smith - section - The `PetscSection`
432988ed4aceSMatthew G Knepley 
433088ed4aceSMatthew G Knepley   Level: intermediate
433188ed4aceSMatthew G Knepley 
4332bb7acecfSBarry Smith   Note:
4333bb7acecfSBarry Smith   Any existing Section will be destroyed
433488ed4aceSMatthew G Knepley 
4335bb7acecfSBarry Smith .seealso: `PetscSection`, `DMGetLocalSection()`, `DMSetGlobalSection()`
433688ed4aceSMatthew G Knepley @*/
4337d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLocalSection(DM dm, PetscSection section)
4338d71ae5a4SJacob Faibussowitsch {
4339c473ab19SMatthew G. Knepley   PetscInt numFields = 0;
4340af122d2aSMatthew G Knepley   PetscInt f;
434188ed4aceSMatthew G Knepley 
434288ed4aceSMatthew G Knepley   PetscFunctionBegin;
434388ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4344b9d85ea2SLisandro Dalcin   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
43459566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
43469566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->localSection));
43471bb6d2a8SBarry Smith   dm->localSection = section;
43489566063dSJacob Faibussowitsch   if (section) PetscCall(PetscSectionGetNumFields(dm->localSection, &numFields));
4349af122d2aSMatthew G Knepley   if (numFields) {
43509566063dSJacob Faibussowitsch     PetscCall(DMSetNumFields(dm, numFields));
4351af122d2aSMatthew G Knepley     for (f = 0; f < numFields; ++f) {
43520f21e855SMatthew G. Knepley       PetscObject disc;
4353af122d2aSMatthew G Knepley       const char *name;
4354af122d2aSMatthew G Knepley 
43559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(dm->localSection, f, &name));
43569566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, &disc));
43579566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName(disc, name));
4358af122d2aSMatthew G Knepley     }
4359af122d2aSMatthew G Knepley   }
4360e87a4003SBarry Smith   /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */
43619566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
436288ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
436388ed4aceSMatthew G Knepley }
436488ed4aceSMatthew G Knepley 
43659435951eSToby Isaac /*@
4366bb7acecfSBarry Smith   DMGetDefaultConstraints - Get the `PetscSection` and `Mat` that specify the local constraint interpolation. See `DMSetDefaultConstraints()` for a description of the purpose of constraint interpolation.
43679435951eSToby Isaac 
4368e228b242SToby Isaac   not collective
4369e228b242SToby Isaac 
43709435951eSToby Isaac   Input Parameter:
4371bb7acecfSBarry Smith . dm - The `DM`
43729435951eSToby Isaac 
4373d8d19677SJose E. Roman   Output Parameters:
4374bb7acecfSBarry 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.
4375bb7acecfSBarry 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.
437679769bd5SJed Brown - bias - Vector containing bias to be added to constrained dofs
43779435951eSToby Isaac 
43789435951eSToby Isaac   Level: advanced
43799435951eSToby Isaac 
4380bb7acecfSBarry Smith   Note:
4381bb7acecfSBarry Smith   This gets borrowed references, so the user should not destroy the `PetscSection`, `Mat`, or `Vec`.
43829435951eSToby Isaac 
4383db781477SPatrick Sanan .seealso: `DMSetDefaultConstraints()`
43849435951eSToby Isaac @*/
4385d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat, Vec *bias)
4386d71ae5a4SJacob Faibussowitsch {
43879435951eSToby Isaac   PetscFunctionBegin;
43889435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4389dbbe0bcdSBarry Smith   if (!dm->defaultConstraint.section && !dm->defaultConstraint.mat && dm->ops->createdefaultconstraints) PetscUseTypeMethod(dm, createdefaultconstraints);
43903b8ba7d1SJed Brown   if (section) *section = dm->defaultConstraint.section;
43913b8ba7d1SJed Brown   if (mat) *mat = dm->defaultConstraint.mat;
439279769bd5SJed Brown   if (bias) *bias = dm->defaultConstraint.bias;
43939435951eSToby Isaac   PetscFunctionReturn(0);
43949435951eSToby Isaac }
43959435951eSToby Isaac 
43969435951eSToby Isaac /*@
4397bb7acecfSBarry Smith   DMSetDefaultConstraints - Set the `PetscSection` and `Mat` that specify the local constraint interpolation.
43989435951eSToby Isaac 
4399bb7acecfSBarry 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()`.
44009435951eSToby Isaac 
4401bb7acecfSBarry 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.
44029435951eSToby Isaac 
4403e228b242SToby Isaac   collective on dm
4404e228b242SToby Isaac 
44059435951eSToby Isaac   Input Parameters:
4406bb7acecfSBarry Smith + dm - The `DM`
4407bb7acecfSBarry 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).
4408bb7acecfSBarry 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).
4409bb7acecfSBarry 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).
44109435951eSToby Isaac 
44119435951eSToby Isaac   Level: advanced
44129435951eSToby Isaac 
4413bb7acecfSBarry Smith   Note:
4414bb7acecfSBarry Smith   This increments the references of the `PetscSection`, `Mat`, and `Vec`, so they user can destroy them.
44159435951eSToby Isaac 
4416db781477SPatrick Sanan .seealso: `DMGetDefaultConstraints()`
44179435951eSToby Isaac @*/
4418d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat, Vec bias)
4419d71ae5a4SJacob Faibussowitsch {
4420e228b242SToby Isaac   PetscMPIInt result;
44219435951eSToby Isaac 
44229435951eSToby Isaac   PetscFunctionBegin;
44239435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4424e228b242SToby Isaac   if (section) {
4425e228b242SToby Isaac     PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
44269566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)section), &result));
44277a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint section must have local communicator");
4428e228b242SToby Isaac   }
4429e228b242SToby Isaac   if (mat) {
4430e228b242SToby Isaac     PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
44319566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)mat), &result));
44327a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint matrix must have local communicator");
4433e228b242SToby Isaac   }
443479769bd5SJed Brown   if (bias) {
443579769bd5SJed Brown     PetscValidHeaderSpecific(bias, VEC_CLASSID, 4);
44369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)bias), &result));
443779769bd5SJed Brown     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint bias must have local communicator");
443879769bd5SJed Brown   }
44399566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
44409566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->defaultConstraint.section));
44413b8ba7d1SJed Brown   dm->defaultConstraint.section = section;
44429566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)mat));
44439566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&dm->defaultConstraint.mat));
44443b8ba7d1SJed Brown   dm->defaultConstraint.mat = mat;
44459566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)bias));
44469566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&dm->defaultConstraint.bias));
444779769bd5SJed Brown   dm->defaultConstraint.bias = bias;
44489435951eSToby Isaac   PetscFunctionReturn(0);
44499435951eSToby Isaac }
44509435951eSToby Isaac 
4451497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
4452507e4973SMatthew G. Knepley /*
4453bb7acecfSBarry Smith   DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. Generates and error if they are not consistent.
4454507e4973SMatthew G. Knepley 
4455507e4973SMatthew G. Knepley   Input Parameters:
4456bb7acecfSBarry Smith + dm - The `DM`
4457bb7acecfSBarry Smith . localSection - `PetscSection` describing the local data layout
4458bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
4459507e4973SMatthew G. Knepley 
4460507e4973SMatthew G. Knepley   Level: intermediate
4461507e4973SMatthew G. Knepley 
4462db781477SPatrick Sanan .seealso: `DMGetSectionSF()`, `DMSetSectionSF()`
4463507e4973SMatthew G. Knepley */
4464d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
4465d71ae5a4SJacob Faibussowitsch {
4466507e4973SMatthew G. Knepley   MPI_Comm        comm;
4467507e4973SMatthew G. Knepley   PetscLayout     layout;
4468507e4973SMatthew G. Knepley   const PetscInt *ranges;
4469507e4973SMatthew G. Knepley   PetscInt        pStart, pEnd, p, nroots;
4470507e4973SMatthew G. Knepley   PetscMPIInt     size, rank;
4471507e4973SMatthew G. Knepley   PetscBool       valid = PETSC_TRUE, gvalid;
4472507e4973SMatthew G. Knepley 
4473507e4973SMatthew G. Knepley   PetscFunctionBegin;
44749566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4475507e4973SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44769566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
44779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
44789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(globalSection, &pStart, &pEnd));
44799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(globalSection, &nroots));
44809566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &layout));
44819566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
44829566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, nroots));
44839566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(layout));
44849566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRanges(layout, &ranges));
4485507e4973SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4486f741bcd2SMatthew G. Knepley     PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
4487507e4973SMatthew G. Knepley 
44889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(localSection, p, &dof));
44899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(localSection, p, &off));
44909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(localSection, p, &cdof));
44919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(globalSection, p, &gdof));
44929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(globalSection, p, &gcdof));
44939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &goff));
4494507e4973SMatthew G. Knepley     if (!gdof) continue; /* Censored point */
44959371c9d4SSatish Balay     if ((gdof < 0 ? -(gdof + 1) : gdof) != dof) {
44969371c9d4SSatish 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));
44979371c9d4SSatish Balay       valid = PETSC_FALSE;
44989371c9d4SSatish Balay     }
44999371c9d4SSatish Balay     if (gcdof && (gcdof != cdof)) {
45009371c9d4SSatish 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));
45019371c9d4SSatish Balay       valid = PETSC_FALSE;
45029371c9d4SSatish Balay     }
4503507e4973SMatthew G. Knepley     if (gdof < 0) {
4504507e4973SMatthew G. Knepley       gsize = gdof < 0 ? -(gdof + 1) - gcdof : gdof - gcdof;
4505507e4973SMatthew G. Knepley       for (d = 0; d < gsize; ++d) {
4506507e4973SMatthew G. Knepley         PetscInt offset = -(goff + 1) + d, r;
4507507e4973SMatthew G. Knepley 
45089566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(offset, size + 1, ranges, &r));
4509507e4973SMatthew G. Knepley         if (r < 0) r = -(r + 2);
45109371c9d4SSatish Balay         if ((r < 0) || (r >= size)) {
45119371c9d4SSatish Balay           PetscCall(PetscSynchronizedPrintf(comm, "[%d]Point %" PetscInt_FMT " mapped to invalid process %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, p, r, gdof, goff));
45129371c9d4SSatish Balay           valid = PETSC_FALSE;
45139371c9d4SSatish Balay           break;
45149371c9d4SSatish Balay         }
4515507e4973SMatthew G. Knepley       }
4516507e4973SMatthew G. Knepley     }
4517507e4973SMatthew G. Knepley   }
45189566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
45199566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
45201c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm));
4521507e4973SMatthew G. Knepley   if (!gvalid) {
45229566063dSJacob Faibussowitsch     PetscCall(DMView(dm, NULL));
4523507e4973SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
4524507e4973SMatthew G. Knepley   }
4525507e4973SMatthew G. Knepley   PetscFunctionReturn(0);
4526507e4973SMatthew G. Knepley }
4527f741bcd2SMatthew G. Knepley #endif
4528507e4973SMatthew G. Knepley 
452988ed4aceSMatthew G Knepley /*@
4530bb7acecfSBarry Smith   DMGetGlobalSection - Get the `PetscSection` encoding the global data layout for the `DM`.
453188ed4aceSMatthew G Knepley 
4532d083f849SBarry Smith   Collective on dm
45338b1ab98fSJed Brown 
453488ed4aceSMatthew G Knepley   Input Parameter:
4535bb7acecfSBarry Smith . dm - The `DM`
453688ed4aceSMatthew G Knepley 
453788ed4aceSMatthew G Knepley   Output Parameter:
4538bb7acecfSBarry Smith . section - The `PetscSection`
453988ed4aceSMatthew G Knepley 
454088ed4aceSMatthew G Knepley   Level: intermediate
454188ed4aceSMatthew G Knepley 
4542bb7acecfSBarry Smith   Note:
4543bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
454488ed4aceSMatthew G Knepley 
4545db781477SPatrick Sanan .seealso: `DMSetLocalSection()`, `DMGetLocalSection()`
454688ed4aceSMatthew G Knepley @*/
4547d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section)
4548d71ae5a4SJacob Faibussowitsch {
454988ed4aceSMatthew G Knepley   PetscFunctionBegin;
455088ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
455188ed4aceSMatthew G Knepley   PetscValidPointer(section, 2);
45521bb6d2a8SBarry Smith   if (!dm->globalSection) {
4553fd59a867SMatthew G. Knepley     PetscSection s;
4554fd59a867SMatthew G. Knepley 
45559566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &s));
45567a8be351SBarry Smith     PetscCheck(s, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
45577a8be351SBarry Smith     PetscCheck(dm->sf, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection");
45589566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->globalSection));
45599566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&dm->map));
45609566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map));
45619566063dSJacob Faibussowitsch     PetscCall(PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view"));
456288ed4aceSMatthew G Knepley   }
45631bb6d2a8SBarry Smith   *section = dm->globalSection;
456488ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
456588ed4aceSMatthew G Knepley }
456688ed4aceSMatthew G Knepley 
4567b21d0597SMatthew G Knepley /*@
4568bb7acecfSBarry Smith   DMSetGlobalSection - Set the `PetscSection` encoding the global data layout for the `DM`.
4569b21d0597SMatthew G Knepley 
4570b21d0597SMatthew G Knepley   Input Parameters:
4571bb7acecfSBarry Smith + dm - The `DM`
45725080bbdbSMatthew G Knepley - section - The PetscSection, or NULL
4573b21d0597SMatthew G Knepley 
4574b21d0597SMatthew G Knepley   Level: intermediate
4575b21d0597SMatthew G Knepley 
4576bb7acecfSBarry Smith   Note:
4577bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4578b21d0597SMatthew G Knepley 
4579db781477SPatrick Sanan .seealso: `DMGetGlobalSection()`, `DMSetLocalSection()`
4580b21d0597SMatthew G Knepley @*/
4581d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section)
4582d71ae5a4SJacob Faibussowitsch {
4583b21d0597SMatthew G Knepley   PetscFunctionBegin;
4584b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45855080bbdbSMatthew G Knepley   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
45869566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
45879566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
45881bb6d2a8SBarry Smith   dm->globalSection = section;
4589497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
45909566063dSJacob Faibussowitsch   if (section) PetscCall(DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section));
4591507e4973SMatthew G. Knepley #endif
4592b21d0597SMatthew G Knepley   PetscFunctionReturn(0);
4593b21d0597SMatthew G Knepley }
4594b21d0597SMatthew G Knepley 
459588ed4aceSMatthew G Knepley /*@
4596bb7acecfSBarry Smith   DMGetSectionSF - Get the `PetscSF` encoding the parallel dof overlap for the `DM`. If it has not been set,
4597bb7acecfSBarry Smith   it is created from the default `PetscSection` layouts in the `DM`.
459888ed4aceSMatthew G Knepley 
459988ed4aceSMatthew G Knepley   Input Parameter:
4600bb7acecfSBarry Smith . dm - The `DM`
460188ed4aceSMatthew G Knepley 
460288ed4aceSMatthew G Knepley   Output Parameter:
4603bb7acecfSBarry Smith . sf - The `PetscSF`
460488ed4aceSMatthew G Knepley 
460588ed4aceSMatthew G Knepley   Level: intermediate
460688ed4aceSMatthew G Knepley 
4607bb7acecfSBarry Smith   Note:
4608bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
460988ed4aceSMatthew G Knepley 
4610db781477SPatrick Sanan .seealso: `DMSetSectionSF()`, `DMCreateSectionSF()`
461188ed4aceSMatthew G Knepley @*/
4612d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf)
4613d71ae5a4SJacob Faibussowitsch {
461488ed4aceSMatthew G Knepley   PetscInt nroots;
461588ed4aceSMatthew G Knepley 
461688ed4aceSMatthew G Knepley   PetscFunctionBegin;
461788ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
461888ed4aceSMatthew G Knepley   PetscValidPointer(sf, 2);
461948a46eb9SPierre Jolivet   if (!dm->sectionSF) PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &dm->sectionSF));
46209566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL));
462188ed4aceSMatthew G Knepley   if (nroots < 0) {
462288ed4aceSMatthew G Knepley     PetscSection section, gSection;
462388ed4aceSMatthew G Knepley 
46249566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
462531ea6d37SMatthew G Knepley     if (section) {
46269566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gSection));
46279566063dSJacob Faibussowitsch       PetscCall(DMCreateSectionSF(dm, section, gSection));
462831ea6d37SMatthew G Knepley     } else {
46290298fd71SBarry Smith       *sf = NULL;
463031ea6d37SMatthew G Knepley       PetscFunctionReturn(0);
463131ea6d37SMatthew G Knepley     }
463288ed4aceSMatthew G Knepley   }
46331bb6d2a8SBarry Smith   *sf = dm->sectionSF;
463488ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
463588ed4aceSMatthew G Knepley }
463688ed4aceSMatthew G Knepley 
463788ed4aceSMatthew G Knepley /*@
4638bb7acecfSBarry Smith   DMSetSectionSF - Set the `PetscSF` encoding the parallel dof overlap for the `DM`
463988ed4aceSMatthew G Knepley 
464088ed4aceSMatthew G Knepley   Input Parameters:
4641bb7acecfSBarry Smith + dm - The `DM`
4642bb7acecfSBarry Smith - sf - The `PetscSF`
464388ed4aceSMatthew G Knepley 
464488ed4aceSMatthew G Knepley   Level: intermediate
464588ed4aceSMatthew G Knepley 
4646bb7acecfSBarry Smith   Note:
4647bb7acecfSBarry Smith   Any previous `PetscSF` is destroyed
464888ed4aceSMatthew G Knepley 
4649db781477SPatrick Sanan .seealso: `DMGetSectionSF()`, `DMCreateSectionSF()`
465088ed4aceSMatthew G Knepley @*/
4651d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf)
4652d71ae5a4SJacob Faibussowitsch {
465388ed4aceSMatthew G Knepley   PetscFunctionBegin;
465488ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4655b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
46569566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
46579566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sectionSF));
46581bb6d2a8SBarry Smith   dm->sectionSF = sf;
465988ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
466088ed4aceSMatthew G Knepley }
466188ed4aceSMatthew G Knepley 
466288ed4aceSMatthew G Knepley /*@C
4663bb7acecfSBarry Smith   DMCreateSectionSF - Create the `PetscSF` encoding the parallel dof overlap for the `DM` based upon the `PetscSection`s
466488ed4aceSMatthew G Knepley   describing the data layout.
466588ed4aceSMatthew G Knepley 
466688ed4aceSMatthew G Knepley   Input Parameters:
4667bb7acecfSBarry Smith + dm - The `DM`
4668bb7acecfSBarry Smith . localSection - `PetscSection` describing the local data layout
4669bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
467088ed4aceSMatthew G Knepley 
46711bb6d2a8SBarry Smith   Level: developer
46721bb6d2a8SBarry Smith 
4673bb7acecfSBarry Smith   Note:
4674bb7acecfSBarry Smith   One usually uses `DMGetSectionSF()` to obtain the `PetscSF`
4675bb7acecfSBarry Smith 
4676bb7acecfSBarry Smith   Developer Note:
4677bb7acecfSBarry Smith   Since this routine has for arguments the two sections from the `DM` and puts the resulting `PetscSF`
4678bb7acecfSBarry Smith   directly into the `DM`, perhaps this function should not take the local and global sections as
4679bb7acecfSBarry Smith   input and should just obtain them from the `DM`?
46801bb6d2a8SBarry Smith 
4681db781477SPatrick Sanan .seealso: `DMGetSectionSF()`, `DMSetSectionSF()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
468288ed4aceSMatthew G Knepley @*/
4683d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection)
4684d71ae5a4SJacob Faibussowitsch {
468588ed4aceSMatthew G Knepley   PetscFunctionBegin;
468688ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46879566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphSection(dm->sectionSF, localSection, globalSection));
468888ed4aceSMatthew G Knepley   PetscFunctionReturn(0);
468988ed4aceSMatthew G Knepley }
4690af122d2aSMatthew G Knepley 
4691b21d0597SMatthew G Knepley /*@
4692bb7acecfSBarry Smith   DMGetPointSF - Get the `PetscSF` encoding the parallel section point overlap for the `DM`.
4693bb7acecfSBarry Smith 
4694bb7acecfSBarry Smith   Not collective but the resulting `PetscSF` is collective
4695b21d0597SMatthew G Knepley 
4696b21d0597SMatthew G Knepley   Input Parameter:
4697bb7acecfSBarry Smith . dm - The `DM`
4698b21d0597SMatthew G Knepley 
4699b21d0597SMatthew G Knepley   Output Parameter:
4700bb7acecfSBarry Smith . sf - The `PetscSF`
4701b21d0597SMatthew G Knepley 
4702b21d0597SMatthew G Knepley   Level: intermediate
4703b21d0597SMatthew G Knepley 
4704bb7acecfSBarry Smith   Note:
4705bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
4706b21d0597SMatthew G Knepley 
4707db781477SPatrick Sanan .seealso: `DMSetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4708b21d0597SMatthew G Knepley @*/
4709d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
4710d71ae5a4SJacob Faibussowitsch {
4711b21d0597SMatthew G Knepley   PetscFunctionBegin;
4712b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4713b21d0597SMatthew G Knepley   PetscValidPointer(sf, 2);
4714b21d0597SMatthew G Knepley   *sf = dm->sf;
4715b21d0597SMatthew G Knepley   PetscFunctionReturn(0);
4716b21d0597SMatthew G Knepley }
4717b21d0597SMatthew G Knepley 
4718057b4bcdSMatthew G Knepley /*@
4719bb7acecfSBarry Smith   DMSetPointSF - Set the `PetscSF` encoding the parallel section point overlap for the `DM`.
4720bb7acecfSBarry Smith 
4721bb7acecfSBarry Smith   Collective on dm
4722057b4bcdSMatthew G Knepley 
4723057b4bcdSMatthew G Knepley   Input Parameters:
4724bb7acecfSBarry Smith + dm - The `DM`
4725bb7acecfSBarry Smith - sf - The` PetscSF`
4726057b4bcdSMatthew G Knepley 
4727057b4bcdSMatthew G Knepley   Level: intermediate
4728057b4bcdSMatthew G Knepley 
4729db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4730057b4bcdSMatthew G Knepley @*/
4731d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
4732d71ae5a4SJacob Faibussowitsch {
4733057b4bcdSMatthew G Knepley   PetscFunctionBegin;
4734057b4bcdSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4735b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47379566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sf));
4738057b4bcdSMatthew G Knepley   dm->sf = sf;
4739057b4bcdSMatthew G Knepley   PetscFunctionReturn(0);
4740057b4bcdSMatthew G Knepley }
4741057b4bcdSMatthew G Knepley 
47424f37162bSMatthew G. Knepley /*@
4743bb7acecfSBarry Smith   DMGetNaturalSF - Get the `PetscSF` encoding the map back to the original mesh ordering
47444f37162bSMatthew G. Knepley 
47454f37162bSMatthew G. Knepley   Input Parameter:
4746bb7acecfSBarry Smith . dm - The `DM`
47474f37162bSMatthew G. Knepley 
47484f37162bSMatthew G. Knepley   Output Parameter:
4749bb7acecfSBarry Smith . sf - The `PetscSF`
47504f37162bSMatthew G. Knepley 
47514f37162bSMatthew G. Knepley   Level: intermediate
47524f37162bSMatthew G. Knepley 
4753bb7acecfSBarry Smith   Note:
4754bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
47554f37162bSMatthew G. Knepley 
4756db781477SPatrick Sanan .seealso: `DMSetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
47574f37162bSMatthew G. Knepley @*/
4758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNaturalSF(DM dm, PetscSF *sf)
4759d71ae5a4SJacob Faibussowitsch {
47604f37162bSMatthew G. Knepley   PetscFunctionBegin;
47614f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47624f37162bSMatthew G. Knepley   PetscValidPointer(sf, 2);
47634f37162bSMatthew G. Knepley   *sf = dm->sfNatural;
47644f37162bSMatthew G. Knepley   PetscFunctionReturn(0);
47654f37162bSMatthew G. Knepley }
47664f37162bSMatthew G. Knepley 
47674f37162bSMatthew G. Knepley /*@
47684f37162bSMatthew G. Knepley   DMSetNaturalSF - Set the PetscSF encoding the map back to the original mesh ordering
47694f37162bSMatthew G. Knepley 
47704f37162bSMatthew G. Knepley   Input Parameters:
47714f37162bSMatthew G. Knepley + dm - The DM
47724f37162bSMatthew G. Knepley - sf - The PetscSF
47734f37162bSMatthew G. Knepley 
47744f37162bSMatthew G. Knepley   Level: intermediate
47754f37162bSMatthew G. Knepley 
4776db781477SPatrick Sanan .seealso: `DMGetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
47774f37162bSMatthew G. Knepley @*/
4778d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNaturalSF(DM dm, PetscSF sf)
4779d71ae5a4SJacob Faibussowitsch {
47804f37162bSMatthew G. Knepley   PetscFunctionBegin;
47814f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47824f37162bSMatthew G. Knepley   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47839566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47849566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sfNatural));
47854f37162bSMatthew G. Knepley   dm->sfNatural = sf;
47864f37162bSMatthew G. Knepley   PetscFunctionReturn(0);
47874f37162bSMatthew G. Knepley }
47884f37162bSMatthew G. Knepley 
4789d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc)
4790d71ae5a4SJacob Faibussowitsch {
479134aa8a36SMatthew G. Knepley   PetscClassId id;
479234aa8a36SMatthew G. Knepley 
479334aa8a36SMatthew G. Knepley   PetscFunctionBegin;
47949566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId(disc, &id));
479534aa8a36SMatthew G. Knepley   if (id == PETSCFE_CLASSID) {
47969566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
479734aa8a36SMatthew G. Knepley   } else if (id == PETSCFV_CLASSID) {
47989566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE));
479917c1d62eSMatthew G. Knepley   } else {
48009566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
480134aa8a36SMatthew G. Knepley   }
480234aa8a36SMatthew G. Knepley   PetscFunctionReturn(0);
480334aa8a36SMatthew G. Knepley }
480434aa8a36SMatthew G. Knepley 
4805d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew)
4806d71ae5a4SJacob Faibussowitsch {
480744a7f3ddSMatthew G. Knepley   RegionField *tmpr;
480844a7f3ddSMatthew G. Knepley   PetscInt     Nf = dm->Nf, f;
480944a7f3ddSMatthew G. Knepley 
481044a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
481144a7f3ddSMatthew G. Knepley   if (Nf >= NfNew) PetscFunctionReturn(0);
48129566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NfNew, &tmpr));
481344a7f3ddSMatthew G. Knepley   for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f];
48149371c9d4SSatish Balay   for (f = Nf; f < NfNew; ++f) {
48159371c9d4SSatish Balay     tmpr[f].disc        = NULL;
48169371c9d4SSatish Balay     tmpr[f].label       = NULL;
48179371c9d4SSatish Balay     tmpr[f].avoidTensor = PETSC_FALSE;
48189371c9d4SSatish Balay   }
48199566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
482044a7f3ddSMatthew G. Knepley   dm->Nf     = NfNew;
482144a7f3ddSMatthew G. Knepley   dm->fields = tmpr;
482244a7f3ddSMatthew G. Knepley   PetscFunctionReturn(0);
482344a7f3ddSMatthew G. Knepley }
482444a7f3ddSMatthew G. Knepley 
482544a7f3ddSMatthew G. Knepley /*@
482644a7f3ddSMatthew G. Knepley   DMClearFields - Remove all fields from the DM
482744a7f3ddSMatthew G. Knepley 
4828d083f849SBarry Smith   Logically collective on dm
482944a7f3ddSMatthew G. Knepley 
483044a7f3ddSMatthew G. Knepley   Input Parameter:
483144a7f3ddSMatthew G. Knepley . dm - The DM
483244a7f3ddSMatthew G. Knepley 
483344a7f3ddSMatthew G. Knepley   Level: intermediate
483444a7f3ddSMatthew G. Knepley 
4835db781477SPatrick Sanan .seealso: `DMGetNumFields()`, `DMSetNumFields()`, `DMSetField()`
483644a7f3ddSMatthew G. Knepley @*/
4837d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearFields(DM dm)
4838d71ae5a4SJacob Faibussowitsch {
483944a7f3ddSMatthew G. Knepley   PetscInt f;
484044a7f3ddSMatthew G. Knepley 
484144a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
484244a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
484344a7f3ddSMatthew G. Knepley   for (f = 0; f < dm->Nf; ++f) {
48449566063dSJacob Faibussowitsch     PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
48459566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->fields[f].label));
484644a7f3ddSMatthew G. Knepley   }
48479566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
484844a7f3ddSMatthew G. Knepley   dm->fields = NULL;
484944a7f3ddSMatthew G. Knepley   dm->Nf     = 0;
485044a7f3ddSMatthew G. Knepley   PetscFunctionReturn(0);
485144a7f3ddSMatthew G. Knepley }
485244a7f3ddSMatthew G. Knepley 
4853689b5837SMatthew G. Knepley /*@
4854689b5837SMatthew G. Knepley   DMGetNumFields - Get the number of fields in the DM
4855689b5837SMatthew G. Knepley 
4856689b5837SMatthew G. Knepley   Not collective
4857689b5837SMatthew G. Knepley 
4858689b5837SMatthew G. Knepley   Input Parameter:
4859689b5837SMatthew G. Knepley . dm - The DM
4860689b5837SMatthew G. Knepley 
4861689b5837SMatthew G. Knepley   Output Parameter:
4862689b5837SMatthew G. Knepley . Nf - The number of fields
4863689b5837SMatthew G. Knepley 
4864689b5837SMatthew G. Knepley   Level: intermediate
4865689b5837SMatthew G. Knepley 
4866db781477SPatrick Sanan .seealso: `DMSetNumFields()`, `DMSetField()`
4867689b5837SMatthew G. Knepley @*/
4868d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4869d71ae5a4SJacob Faibussowitsch {
48700f21e855SMatthew G. Knepley   PetscFunctionBegin;
48710f21e855SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4872534a8f05SLisandro Dalcin   PetscValidIntPointer(numFields, 2);
487344a7f3ddSMatthew G. Knepley   *numFields = dm->Nf;
4874af122d2aSMatthew G Knepley   PetscFunctionReturn(0);
4875af122d2aSMatthew G Knepley }
4876af122d2aSMatthew G Knepley 
4877689b5837SMatthew G. Knepley /*@
4878689b5837SMatthew G. Knepley   DMSetNumFields - Set the number of fields in the DM
4879689b5837SMatthew G. Knepley 
4880d083f849SBarry Smith   Logically collective on dm
4881689b5837SMatthew G. Knepley 
4882689b5837SMatthew G. Knepley   Input Parameters:
4883689b5837SMatthew G. Knepley + dm - The DM
4884689b5837SMatthew G. Knepley - Nf - The number of fields
4885689b5837SMatthew G. Knepley 
4886689b5837SMatthew G. Knepley   Level: intermediate
4887689b5837SMatthew G. Knepley 
4888db781477SPatrick Sanan .seealso: `DMGetNumFields()`, `DMSetField()`
4889689b5837SMatthew G. Knepley @*/
4890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4891d71ae5a4SJacob Faibussowitsch {
48920f21e855SMatthew G. Knepley   PetscInt Nf, f;
4893af122d2aSMatthew G Knepley 
4894af122d2aSMatthew G Knepley   PetscFunctionBegin;
4895af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48969566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
48970f21e855SMatthew G. Knepley   for (f = Nf; f < numFields; ++f) {
48980f21e855SMatthew G. Knepley     PetscContainer obj;
48990f21e855SMatthew G. Knepley 
49009566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)dm), &obj));
49019566063dSJacob Faibussowitsch     PetscCall(DMAddField(dm, NULL, (PetscObject)obj));
49029566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&obj));
4903af122d2aSMatthew G Knepley   }
4904af122d2aSMatthew G Knepley   PetscFunctionReturn(0);
4905af122d2aSMatthew G Knepley }
4906af122d2aSMatthew G Knepley 
4907c1929be8SMatthew G. Knepley /*@
4908bb7acecfSBarry Smith   DMGetField - Return the `DMLabel` and discretization object for a given `DM` field
4909c1929be8SMatthew G. Knepley 
4910c1929be8SMatthew G. Knepley   Not collective
4911c1929be8SMatthew G. Knepley 
4912c1929be8SMatthew G. Knepley   Input Parameters:
4913bb7acecfSBarry Smith + dm - The `DM`
4914c1929be8SMatthew G. Knepley - f  - The field number
4915c1929be8SMatthew G. Knepley 
491644a7f3ddSMatthew G. Knepley   Output Parameters:
4917bb7acecfSBarry Smith + label - The label indicating the support of the field, or NULL for the entire mesh (pass in NULL if not needed)
4918bb7acecfSBarry Smith - disc - The discretization object (pass in NULL if not needed)
4919c1929be8SMatthew G. Knepley 
492044a7f3ddSMatthew G. Knepley   Level: intermediate
4921c1929be8SMatthew G. Knepley 
4922db781477SPatrick Sanan .seealso: `DMAddField()`, `DMSetField()`
4923c1929be8SMatthew G. Knepley @*/
4924d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *disc)
4925d71ae5a4SJacob Faibussowitsch {
4926af122d2aSMatthew G Knepley   PetscFunctionBegin;
4927af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4928bb7acecfSBarry Smith   PetscValidPointer(disc, 4);
49297a8be351SBarry 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);
493044a7f3ddSMatthew G. Knepley   if (label) *label = dm->fields[f].label;
4931bb7acecfSBarry Smith   if (disc) *disc = dm->fields[f].disc;
4932decb47aaSMatthew G. Knepley   PetscFunctionReturn(0);
4933decb47aaSMatthew G. Knepley }
4934decb47aaSMatthew G. Knepley 
4935083401c6SMatthew G. Knepley /* Does not clear the DS */
4936d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField_Internal(DM dm, PetscInt f, DMLabel label, PetscObject disc)
4937d71ae5a4SJacob Faibussowitsch {
4938083401c6SMatthew G. Knepley   PetscFunctionBegin;
49399566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, f + 1));
49409566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->fields[f].label));
49419566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
4942083401c6SMatthew G. Knepley   dm->fields[f].label = label;
4943bb7acecfSBarry Smith   dm->fields[f].disc  = disc;
49449566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
4945bb7acecfSBarry Smith   PetscCall(PetscObjectReference((PetscObject)disc));
4946083401c6SMatthew G. Knepley   PetscFunctionReturn(0);
4947083401c6SMatthew G. Knepley }
4948083401c6SMatthew G. Knepley 
4949c1929be8SMatthew G. Knepley /*@
4950bb7acecfSBarry Smith   DMSetField - Set the discretization object for a given `DM` field. Usually one would call `DMAddField()` which automatically handles
4951bb7acecfSBarry Smith   the field numbering.
4952c1929be8SMatthew G. Knepley 
4953d083f849SBarry Smith   Logically collective on dm
4954c1929be8SMatthew G. Knepley 
4955c1929be8SMatthew G. Knepley   Input Parameters:
4956bb7acecfSBarry Smith + dm    - The `DM`
4957c1929be8SMatthew G. Knepley . f     - The field number
495844a7f3ddSMatthew G. Knepley . label - The label indicating the support of the field, or NULL for the entire mesh
4959bb7acecfSBarry Smith - disc - The discretization object
4960c1929be8SMatthew G. Knepley 
496144a7f3ddSMatthew G. Knepley   Level: intermediate
4962c1929be8SMatthew G. Knepley 
4963db781477SPatrick Sanan .seealso: `DMAddField()`, `DMGetField()`
4964c1929be8SMatthew G. Knepley @*/
4965d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject disc)
4966d71ae5a4SJacob Faibussowitsch {
4967decb47aaSMatthew G. Knepley   PetscFunctionBegin;
4968decb47aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4969e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
4970bb7acecfSBarry Smith   PetscValidHeader(disc, 4);
49717a8be351SBarry Smith   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
4972bb7acecfSBarry Smith   PetscCall(DMSetField_Internal(dm, f, label, disc));
4973bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, f, disc));
49749566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
497544a7f3ddSMatthew G. Knepley   PetscFunctionReturn(0);
497644a7f3ddSMatthew G. Knepley }
497744a7f3ddSMatthew G. Knepley 
497844a7f3ddSMatthew G. Knepley /*@
4979bb7acecfSBarry 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)
4980bb7acecfSBarry Smith   and a discretization object that defines the function space associated with those points.
498144a7f3ddSMatthew G. Knepley 
4982d083f849SBarry Smith   Logically collective on dm
498344a7f3ddSMatthew G. Knepley 
498444a7f3ddSMatthew G. Knepley   Input Parameters:
4985bb7acecfSBarry Smith + dm    - The `DM`
498644a7f3ddSMatthew G. Knepley . label - The label indicating the support of the field, or NULL for the entire mesh
4987bb7acecfSBarry Smith - disc - The discretization object
498844a7f3ddSMatthew G. Knepley 
498944a7f3ddSMatthew G. Knepley   Level: intermediate
499044a7f3ddSMatthew G. Knepley 
4991bb7acecfSBarry Smith   Notes:
4992bb7acecfSBarry Smith   The label already exists or will be added to the `DM` with `DMSetLabel()`.
4993bb7acecfSBarry Smith 
4994bb7acecfSBarry Smith   For example, a piecewise continous pressure field can be defined by coefficients at the cell centers of a mesh and piecewise constant functions
4995bb7acecfSBarry 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
4996bb7acecfSBarry Smith   geometry entities, a `DMLabel` indicating a subset of those geometric entities, and a discretization object, such as a `PetscFE`.
4997bb7acecfSBarry Smith 
4998bb7acecfSBarry Smith .seealso: `DMSetLabel()`, `DMSetField()`, `DMGetField()`, `PetscFE`
499944a7f3ddSMatthew G. Knepley @*/
5000d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject disc)
5001d71ae5a4SJacob Faibussowitsch {
500244a7f3ddSMatthew G. Knepley   PetscInt Nf = dm->Nf;
500344a7f3ddSMatthew G. Knepley 
500444a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
500544a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5006064a246eSJacob Faibussowitsch   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
5007bb7acecfSBarry Smith   PetscValidHeader(disc, 3);
50089566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, Nf + 1));
500944a7f3ddSMatthew G. Knepley   dm->fields[Nf].label = label;
5010bb7acecfSBarry Smith   dm->fields[Nf].disc  = disc;
50119566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
5012bb7acecfSBarry Smith   PetscCall(PetscObjectReference((PetscObject)disc));
5013bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, Nf, disc));
50149566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
5015af122d2aSMatthew G Knepley   PetscFunctionReturn(0);
5016af122d2aSMatthew G Knepley }
50176636e97aSMatthew G Knepley 
5018e5e52638SMatthew G. Knepley /*@
5019e0b68406SMatthew Knepley   DMSetFieldAvoidTensor - Set flag to avoid defining the field on tensor cells
5020e0b68406SMatthew Knepley 
5021e0b68406SMatthew Knepley   Logically collective on dm
5022e0b68406SMatthew Knepley 
5023e0b68406SMatthew Knepley   Input Parameters:
5024bb7acecfSBarry Smith + dm          - The `DM`
5025e0b68406SMatthew Knepley . f           - The field index
5026bb7acecfSBarry Smith - avoidTensor - `PETSC_TRUE` to skip defining the field on tensor cells
5027e0b68406SMatthew Knepley 
5028e0b68406SMatthew Knepley   Level: intermediate
5029e0b68406SMatthew Knepley 
5030db781477SPatrick Sanan .seealso: `DMGetFieldAvoidTensor()`, `DMSetField()`, `DMGetField()`
5031e0b68406SMatthew Knepley @*/
5032d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFieldAvoidTensor(DM dm, PetscInt f, PetscBool avoidTensor)
5033d71ae5a4SJacob Faibussowitsch {
5034e0b68406SMatthew Knepley   PetscFunctionBegin;
503563a3b9bcSJacob 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);
5036e0b68406SMatthew Knepley   dm->fields[f].avoidTensor = avoidTensor;
5037e0b68406SMatthew Knepley   PetscFunctionReturn(0);
5038e0b68406SMatthew Knepley }
5039e0b68406SMatthew Knepley 
5040e0b68406SMatthew Knepley /*@
5041e0b68406SMatthew Knepley   DMGetFieldAvoidTensor - Get flag to avoid defining the field on tensor cells
5042e0b68406SMatthew Knepley 
5043bb7acecfSBarry Smith   Not collective
5044e0b68406SMatthew Knepley 
5045e0b68406SMatthew Knepley   Input Parameters:
5046bb7acecfSBarry Smith + dm          - The `DM`
5047e0b68406SMatthew Knepley - f           - The field index
5048e0b68406SMatthew Knepley 
5049e0b68406SMatthew Knepley   Output Parameter:
5050e0b68406SMatthew Knepley . avoidTensor - The flag to avoid defining the field on tensor cells
5051e0b68406SMatthew Knepley 
5052e0b68406SMatthew Knepley   Level: intermediate
5053e0b68406SMatthew Knepley 
5054bb7acecfSBarry Smith  .seealso: `DMAddField()`, `DMSetField()`, `DMGetField()`, `DMSetFieldAvoidTensor()`, `DMSetField()`, `DMGetField()`
5055e0b68406SMatthew Knepley @*/
5056d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFieldAvoidTensor(DM dm, PetscInt f, PetscBool *avoidTensor)
5057d71ae5a4SJacob Faibussowitsch {
5058e0b68406SMatthew Knepley   PetscFunctionBegin;
505963a3b9bcSJacob 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);
5060e0b68406SMatthew Knepley   *avoidTensor = dm->fields[f].avoidTensor;
5061e0b68406SMatthew Knepley   PetscFunctionReturn(0);
5062e0b68406SMatthew Knepley }
5063e0b68406SMatthew Knepley 
5064e0b68406SMatthew Knepley /*@
5065bb7acecfSBarry Smith   DMCopyFields - Copy the discretizations for the `DM` into another `DM`
5066e5e52638SMatthew G. Knepley 
5067d083f849SBarry Smith   Collective on dm
5068e5e52638SMatthew G. Knepley 
5069e5e52638SMatthew G. Knepley   Input Parameter:
5070bb7acecfSBarry Smith . dm - The `DM`
5071e5e52638SMatthew G. Knepley 
5072e5e52638SMatthew G. Knepley   Output Parameter:
5073bb7acecfSBarry Smith . newdm - The `DM`
5074e5e52638SMatthew G. Knepley 
5075e5e52638SMatthew G. Knepley   Level: advanced
5076e5e52638SMatthew G. Knepley 
5077db781477SPatrick Sanan .seealso: `DMGetField()`, `DMSetField()`, `DMAddField()`, `DMCopyDS()`, `DMGetDS()`, `DMGetCellDS()`
5078e5e52638SMatthew G. Knepley @*/
5079d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyFields(DM dm, DM newdm)
5080d71ae5a4SJacob Faibussowitsch {
5081e5e52638SMatthew G. Knepley   PetscInt Nf, f;
5082e5e52638SMatthew G. Knepley 
5083e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5084e5e52638SMatthew G. Knepley   if (dm == newdm) PetscFunctionReturn(0);
50859566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
50869566063dSJacob Faibussowitsch   PetscCall(DMClearFields(newdm));
5087e5e52638SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5088e5e52638SMatthew G. Knepley     DMLabel     label;
5089e5e52638SMatthew G. Knepley     PetscObject field;
509034aa8a36SMatthew G. Knepley     PetscBool   useCone, useClosure;
5091e5e52638SMatthew G. Knepley 
50929566063dSJacob Faibussowitsch     PetscCall(DMGetField(dm, f, &label, &field));
50939566063dSJacob Faibussowitsch     PetscCall(DMSetField(newdm, f, label, field));
50949566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, f, &useCone, &useClosure));
50959566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(newdm, f, useCone, useClosure));
509634aa8a36SMatthew G. Knepley   }
509734aa8a36SMatthew G. Knepley   PetscFunctionReturn(0);
509834aa8a36SMatthew G. Knepley }
509934aa8a36SMatthew G. Knepley 
510034aa8a36SMatthew G. Knepley /*@
510134aa8a36SMatthew G. Knepley   DMGetAdjacency - Returns the flags for determining variable influence
510234aa8a36SMatthew G. Knepley 
510334aa8a36SMatthew G. Knepley   Not collective
510434aa8a36SMatthew G. Knepley 
510534aa8a36SMatthew G. Knepley   Input Parameters:
510634aa8a36SMatthew G. Knepley + dm - The DM object
510734aa8a36SMatthew G. Knepley - f  - The field number, or PETSC_DEFAULT for the default adjacency
510834aa8a36SMatthew G. Knepley 
5109d8d19677SJose E. Roman   Output Parameters:
511034aa8a36SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
511134aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
511234aa8a36SMatthew G. Knepley 
511334aa8a36SMatthew G. Knepley   Notes:
511434aa8a36SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
511534aa8a36SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
511634aa8a36SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
5117979e053dSMatthew G. Knepley   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
511834aa8a36SMatthew G. Knepley 
511934aa8a36SMatthew G. Knepley   Level: developer
512034aa8a36SMatthew G. Knepley 
5121db781477SPatrick Sanan .seealso: `DMSetAdjacency()`, `DMGetField()`, `DMSetField()`
512234aa8a36SMatthew G. Knepley @*/
5123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure)
5124d71ae5a4SJacob Faibussowitsch {
512534aa8a36SMatthew G. Knepley   PetscFunctionBegin;
512634aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5127534a8f05SLisandro Dalcin   if (useCone) PetscValidBoolPointer(useCone, 3);
5128534a8f05SLisandro Dalcin   if (useClosure) PetscValidBoolPointer(useClosure, 4);
512934aa8a36SMatthew G. Knepley   if (f < 0) {
513034aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->adjacency[0];
513134aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->adjacency[1];
513234aa8a36SMatthew G. Knepley   } else {
513334aa8a36SMatthew G. Knepley     PetscInt Nf;
513434aa8a36SMatthew G. Knepley 
51359566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
51367a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
513734aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->fields[f].adjacency[0];
513834aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->fields[f].adjacency[1];
513934aa8a36SMatthew G. Knepley   }
514034aa8a36SMatthew G. Knepley   PetscFunctionReturn(0);
514134aa8a36SMatthew G. Knepley }
514234aa8a36SMatthew G. Knepley 
514334aa8a36SMatthew G. Knepley /*@
514434aa8a36SMatthew G. Knepley   DMSetAdjacency - Set the flags for determining variable influence
514534aa8a36SMatthew G. Knepley 
514634aa8a36SMatthew G. Knepley   Not collective
514734aa8a36SMatthew G. Knepley 
514834aa8a36SMatthew G. Knepley   Input Parameters:
514934aa8a36SMatthew G. Knepley + dm         - The DM object
515034aa8a36SMatthew G. Knepley . f          - The field number
515134aa8a36SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
515234aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
515334aa8a36SMatthew G. Knepley 
515434aa8a36SMatthew G. Knepley   Notes:
515534aa8a36SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
515634aa8a36SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
515734aa8a36SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
5158979e053dSMatthew G. Knepley   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
515934aa8a36SMatthew G. Knepley 
516034aa8a36SMatthew G. Knepley   Level: developer
516134aa8a36SMatthew G. Knepley 
5162db781477SPatrick Sanan .seealso: `DMGetAdjacency()`, `DMGetField()`, `DMSetField()`
516334aa8a36SMatthew G. Knepley @*/
5164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure)
5165d71ae5a4SJacob Faibussowitsch {
516634aa8a36SMatthew G. Knepley   PetscFunctionBegin;
516734aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
516834aa8a36SMatthew G. Knepley   if (f < 0) {
516934aa8a36SMatthew G. Knepley     dm->adjacency[0] = useCone;
517034aa8a36SMatthew G. Knepley     dm->adjacency[1] = useClosure;
517134aa8a36SMatthew G. Knepley   } else {
517234aa8a36SMatthew G. Knepley     PetscInt Nf;
517334aa8a36SMatthew G. Knepley 
51749566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
51757a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
517634aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[0] = useCone;
517734aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[1] = useClosure;
5178e5e52638SMatthew G. Knepley   }
5179e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5180e5e52638SMatthew G. Knepley }
5181e5e52638SMatthew G. Knepley 
5182b0441da4SMatthew G. Knepley /*@
5183b0441da4SMatthew G. Knepley   DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined
5184b0441da4SMatthew G. Knepley 
5185b0441da4SMatthew G. Knepley   Not collective
5186b0441da4SMatthew G. Knepley 
5187f899ff85SJose E. Roman   Input Parameter:
5188b0441da4SMatthew G. Knepley . dm - The DM object
5189b0441da4SMatthew G. Knepley 
5190d8d19677SJose E. Roman   Output Parameters:
5191b0441da4SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
5192b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5193b0441da4SMatthew G. Knepley 
5194b0441da4SMatthew G. Knepley   Notes:
5195b0441da4SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
5196b0441da4SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
5197b0441da4SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
5198b0441da4SMatthew G. Knepley 
5199b0441da4SMatthew G. Knepley   Level: developer
5200b0441da4SMatthew G. Knepley 
5201db781477SPatrick Sanan .seealso: `DMSetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5202b0441da4SMatthew G. Knepley @*/
5203d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure)
5204d71ae5a4SJacob Faibussowitsch {
5205b0441da4SMatthew G. Knepley   PetscInt Nf;
5206b0441da4SMatthew G. Knepley 
5207b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5208b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5209064a246eSJacob Faibussowitsch   if (useCone) PetscValidBoolPointer(useCone, 2);
5210064a246eSJacob Faibussowitsch   if (useClosure) PetscValidBoolPointer(useClosure, 3);
52119566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5212b0441da4SMatthew G. Knepley   if (!Nf) {
52139566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5214b0441da4SMatthew G. Knepley   } else {
52159566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, 0, useCone, useClosure));
5216b0441da4SMatthew G. Knepley   }
5217b0441da4SMatthew G. Knepley   PetscFunctionReturn(0);
5218b0441da4SMatthew G. Knepley }
5219b0441da4SMatthew G. Knepley 
5220b0441da4SMatthew G. Knepley /*@
5221b0441da4SMatthew G. Knepley   DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined
5222b0441da4SMatthew G. Knepley 
5223b0441da4SMatthew G. Knepley   Not collective
5224b0441da4SMatthew G. Knepley 
5225b0441da4SMatthew G. Knepley   Input Parameters:
5226b0441da4SMatthew G. Knepley + dm         - The DM object
5227b0441da4SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
5228b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5229b0441da4SMatthew G. Knepley 
5230b0441da4SMatthew G. Knepley   Notes:
5231b0441da4SMatthew G. Knepley $     FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
5232b0441da4SMatthew G. Knepley $     FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
5233b0441da4SMatthew G. Knepley $     FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
5234b0441da4SMatthew G. Knepley 
5235b0441da4SMatthew G. Knepley   Level: developer
5236b0441da4SMatthew G. Knepley 
5237db781477SPatrick Sanan .seealso: `DMGetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5238b0441da4SMatthew G. Knepley @*/
5239d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure)
5240d71ae5a4SJacob Faibussowitsch {
5241b0441da4SMatthew G. Knepley   PetscInt Nf;
5242b0441da4SMatthew G. Knepley 
5243b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5244b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52459566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5246b0441da4SMatthew G. Knepley   if (!Nf) {
52479566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5248b0441da4SMatthew G. Knepley   } else {
52499566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, 0, useCone, useClosure));
5250e5e52638SMatthew G. Knepley   }
5251e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5252e5e52638SMatthew G. Knepley }
5253e5e52638SMatthew G. Knepley 
5254d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompleteBCLabels_Internal(DM dm)
5255d71ae5a4SJacob Faibussowitsch {
5256799db056SMatthew G. Knepley   DM           plex;
5257799db056SMatthew G. Knepley   DMLabel     *labels, *glabels;
5258799db056SMatthew G. Knepley   const char **names;
5259799db056SMatthew G. Knepley   char        *sendNames, *recvNames;
5260799db056SMatthew G. Knepley   PetscInt     Nds, s, maxLabels = 0, maxLen = 0, gmaxLen, Nl = 0, gNl, l, gl, m;
5261799db056SMatthew G. Knepley   size_t       len;
5262799db056SMatthew G. Knepley   MPI_Comm     comm;
5263799db056SMatthew G. Knepley   PetscMPIInt  rank, size, p, *counts, *displs;
5264783e2ec8SMatthew G. Knepley 
5265783e2ec8SMatthew G. Knepley   PetscFunctionBegin;
5266799db056SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5267799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
5268799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5269799db056SMatthew G. Knepley   PetscCall(DMGetNumDS(dm, &Nds));
5270799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5271799db056SMatthew G. Knepley     PetscDS  dsBC;
5272799db056SMatthew G. Knepley     PetscInt numBd;
5273799db056SMatthew G. Knepley 
5274799db056SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC));
5275799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5276799db056SMatthew G. Knepley     maxLabels += numBd;
5277799db056SMatthew G. Knepley   }
5278799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(maxLabels, &labels));
5279799db056SMatthew G. Knepley   /* Get list of labels to be completed */
5280799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5281799db056SMatthew G. Knepley     PetscDS  dsBC;
5282799db056SMatthew G. Knepley     PetscInt numBd, bd;
5283799db056SMatthew G. Knepley 
5284799db056SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC));
5285799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5286799db056SMatthew G. Knepley     for (bd = 0; bd < numBd; ++bd) {
5287799db056SMatthew G. Knepley       DMLabel      label;
5288799db056SMatthew G. Knepley       PetscInt     field;
5289799db056SMatthew G. Knepley       PetscObject  obj;
5290799db056SMatthew G. Knepley       PetscClassId id;
5291799db056SMatthew G. Knepley 
5292799db056SMatthew G. Knepley       PetscCall(PetscDSGetBoundary(dsBC, bd, NULL, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
52939566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, field, NULL, &obj));
52949566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
5295799db056SMatthew G. Knepley       if (!(id == PETSCFE_CLASSID) || !label) continue;
52969371c9d4SSatish Balay       for (l = 0; l < Nl; ++l)
52979371c9d4SSatish Balay         if (labels[l] == label) break;
5298799db056SMatthew G. Knepley       if (l == Nl) labels[Nl++] = label;
5299783e2ec8SMatthew G. Knepley     }
5300799db056SMatthew G. Knepley   }
5301799db056SMatthew G. Knepley   /* Get label names */
5302799db056SMatthew G. Knepley   PetscCall(PetscMalloc1(Nl, &names));
5303799db056SMatthew G. Knepley   for (l = 0; l < Nl; ++l) PetscCall(PetscObjectGetName((PetscObject)labels[l], &names[l]));
53049371c9d4SSatish Balay   for (l = 0; l < Nl; ++l) {
53059371c9d4SSatish Balay     PetscCall(PetscStrlen(names[l], &len));
53069371c9d4SSatish Balay     maxLen = PetscMax(maxLen, (PetscInt)len + 2);
53079371c9d4SSatish Balay   }
5308799db056SMatthew G. Knepley   PetscCall(PetscFree(labels));
5309799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allreduce(&maxLen, &gmaxLen, 1, MPIU_INT, MPI_MAX, comm));
5310799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(Nl * gmaxLen, &sendNames));
5311799db056SMatthew G. Knepley   for (l = 0; l < Nl; ++l) PetscCall(PetscStrcpy(&sendNames[gmaxLen * l], names[l]));
5312799db056SMatthew G. Knepley   PetscCall(PetscFree(names));
5313799db056SMatthew G. Knepley   /* Put all names on all processes */
5314799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(size, &counts, size + 1, &displs));
5315799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgather(&Nl, 1, MPI_INT, counts, 1, MPI_INT, comm));
5316799db056SMatthew G. Knepley   for (p = 0; p < size; ++p) displs[p + 1] = displs[p] + counts[p];
5317799db056SMatthew G. Knepley   gNl = displs[size];
53189371c9d4SSatish Balay   for (p = 0; p < size; ++p) {
53199371c9d4SSatish Balay     counts[p] *= gmaxLen;
53209371c9d4SSatish Balay     displs[p] *= gmaxLen;
53219371c9d4SSatish Balay   }
5322799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(gNl * gmaxLen, &recvNames, gNl, &glabels));
5323799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgatherv(sendNames, counts[rank], MPI_CHAR, recvNames, counts, displs, MPI_CHAR, comm));
5324799db056SMatthew G. Knepley   PetscCall(PetscFree2(counts, displs));
5325799db056SMatthew G. Knepley   PetscCall(PetscFree(sendNames));
5326799db056SMatthew G. Knepley   for (l = 0, gl = 0; l < gNl; ++l) {
5327799db056SMatthew G. Knepley     PetscCall(DMGetLabel(dm, &recvNames[l * gmaxLen], &glabels[gl]));
5328799db056SMatthew G. Knepley     PetscCheck(glabels[gl], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Label %s missing on rank %d", &recvNames[l * gmaxLen], rank);
53299371c9d4SSatish Balay     for (m = 0; m < gl; ++m)
53309371c9d4SSatish Balay       if (glabels[m] == glabels[gl]) continue;
53319566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
5332799db056SMatthew G. Knepley     PetscCall(DMPlexLabelComplete(plex, glabels[gl]));
53339566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5334799db056SMatthew G. Knepley     ++gl;
5335783e2ec8SMatthew G. Knepley   }
5336799db056SMatthew G. Knepley   PetscCall(PetscFree2(recvNames, glabels));
5337783e2ec8SMatthew G. Knepley   PetscFunctionReturn(0);
5338783e2ec8SMatthew G. Knepley }
5339783e2ec8SMatthew G. Knepley 
5340d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew)
5341d71ae5a4SJacob Faibussowitsch {
5342e5e52638SMatthew G. Knepley   DMSpace *tmpd;
5343e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5344e5e52638SMatthew G. Knepley 
5345e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5346e5e52638SMatthew G. Knepley   if (Nds >= NdsNew) PetscFunctionReturn(0);
53479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NdsNew, &tmpd));
5348e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s];
53499371c9d4SSatish Balay   for (s = Nds; s < NdsNew; ++s) {
53509371c9d4SSatish Balay     tmpd[s].ds     = NULL;
53519371c9d4SSatish Balay     tmpd[s].label  = NULL;
53529371c9d4SSatish Balay     tmpd[s].fields = NULL;
53539371c9d4SSatish Balay   }
53549566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5355e5e52638SMatthew G. Knepley   dm->Nds   = NdsNew;
5356e5e52638SMatthew G. Knepley   dm->probs = tmpd;
5357e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5358e5e52638SMatthew G. Knepley }
5359e5e52638SMatthew G. Knepley 
5360e5e52638SMatthew G. Knepley /*@
5361e5e52638SMatthew G. Knepley   DMGetNumDS - Get the number of discrete systems in the DM
5362e5e52638SMatthew G. Knepley 
5363e5e52638SMatthew G. Knepley   Not collective
5364e5e52638SMatthew G. Knepley 
5365e5e52638SMatthew G. Knepley   Input Parameter:
5366e5e52638SMatthew G. Knepley . dm - The DM
5367e5e52638SMatthew G. Knepley 
5368e5e52638SMatthew G. Knepley   Output Parameter:
5369e5e52638SMatthew G. Knepley . Nds - The number of PetscDS objects
5370e5e52638SMatthew G. Knepley 
5371e5e52638SMatthew G. Knepley   Level: intermediate
5372e5e52638SMatthew G. Knepley 
5373db781477SPatrick Sanan .seealso: `DMGetDS()`, `DMGetCellDS()`
5374e5e52638SMatthew G. Knepley @*/
5375d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds)
5376d71ae5a4SJacob Faibussowitsch {
5377e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5378e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5379534a8f05SLisandro Dalcin   PetscValidIntPointer(Nds, 2);
5380e5e52638SMatthew G. Knepley   *Nds = dm->Nds;
5381e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5382e5e52638SMatthew G. Knepley }
5383e5e52638SMatthew G. Knepley 
5384e5e52638SMatthew G. Knepley /*@
5385e5e52638SMatthew G. Knepley   DMClearDS - Remove all discrete systems from the DM
5386e5e52638SMatthew G. Knepley 
5387d083f849SBarry Smith   Logically collective on dm
5388e5e52638SMatthew G. Knepley 
5389e5e52638SMatthew G. Knepley   Input Parameter:
5390e5e52638SMatthew G. Knepley . dm - The DM
5391e5e52638SMatthew G. Knepley 
5392e5e52638SMatthew G. Knepley   Level: intermediate
5393e5e52638SMatthew G. Knepley 
5394db781477SPatrick Sanan .seealso: `DMGetNumDS()`, `DMGetDS()`, `DMSetField()`
5395e5e52638SMatthew G. Knepley @*/
5396d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearDS(DM dm)
5397d71ae5a4SJacob Faibussowitsch {
5398e5e52638SMatthew G. Knepley   PetscInt s;
5399e5e52638SMatthew G. Knepley 
5400e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5401e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5402e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
54039566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[s].ds));
54049566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->probs[s].label));
54059566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[s].fields));
5406e5e52638SMatthew G. Knepley   }
54079566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5408e5e52638SMatthew G. Knepley   dm->probs = NULL;
5409e5e52638SMatthew G. Knepley   dm->Nds   = 0;
5410e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5411e5e52638SMatthew G. Knepley }
5412e5e52638SMatthew G. Knepley 
5413e5e52638SMatthew G. Knepley /*@
5414e5e52638SMatthew G. Knepley   DMGetDS - Get the default PetscDS
5415e5e52638SMatthew G. Knepley 
5416e5e52638SMatthew G. Knepley   Not collective
5417e5e52638SMatthew G. Knepley 
5418e5e52638SMatthew G. Knepley   Input Parameter:
5419e5e52638SMatthew G. Knepley . dm    - The DM
5420e5e52638SMatthew G. Knepley 
5421e5e52638SMatthew G. Knepley   Output Parameter:
5422e5e52638SMatthew G. Knepley . prob - The default PetscDS
5423e5e52638SMatthew G. Knepley 
5424e5e52638SMatthew G. Knepley   Level: intermediate
5425e5e52638SMatthew G. Knepley 
5426db781477SPatrick Sanan .seealso: `DMGetCellDS()`, `DMGetRegionDS()`
5427e5e52638SMatthew G. Knepley @*/
5428d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDS(DM dm, PetscDS *prob)
5429d71ae5a4SJacob Faibussowitsch {
5430e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5431e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5432e5e52638SMatthew G. Knepley   PetscValidPointer(prob, 2);
5433b0143b4dSMatthew G. Knepley   if (dm->Nds <= 0) {
5434b0143b4dSMatthew G. Knepley     PetscDS ds;
5435b0143b4dSMatthew G. Knepley 
54369566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
54379566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, NULL, NULL, ds));
54389566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&ds));
5439b0143b4dSMatthew G. Knepley   }
5440b0143b4dSMatthew G. Knepley   *prob = dm->probs[0].ds;
5441e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5442e5e52638SMatthew G. Knepley }
5443e5e52638SMatthew G. Knepley 
5444e5e52638SMatthew G. Knepley /*@
5445e5e52638SMatthew G. Knepley   DMGetCellDS - Get the PetscDS defined on a given cell
5446e5e52638SMatthew G. Knepley 
5447e5e52638SMatthew G. Knepley   Not collective
5448e5e52638SMatthew G. Knepley 
5449e5e52638SMatthew G. Knepley   Input Parameters:
5450e5e52638SMatthew G. Knepley + dm    - The DM
5451e5e52638SMatthew G. Knepley - point - Cell for the DS
5452e5e52638SMatthew G. Knepley 
5453e5e52638SMatthew G. Knepley   Output Parameter:
5454e5e52638SMatthew G. Knepley . prob - The PetscDS defined on the given cell
5455e5e52638SMatthew G. Knepley 
5456e5e52638SMatthew G. Knepley   Level: developer
5457e5e52638SMatthew G. Knepley 
5458db781477SPatrick Sanan .seealso: `DMGetDS()`, `DMSetRegionDS()`
5459e5e52638SMatthew G. Knepley @*/
5460d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *prob)
5461d71ae5a4SJacob Faibussowitsch {
5462e5e52638SMatthew G. Knepley   PetscDS  probDef = NULL;
5463e5e52638SMatthew G. Knepley   PetscInt s;
5464e5e52638SMatthew G. Knepley 
5465e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5466e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5467e5e52638SMatthew G. Knepley   PetscValidPointer(prob, 3);
546863a3b9bcSJacob Faibussowitsch   PetscCheck(point >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %" PetscInt_FMT, point);
5469e5e52638SMatthew G. Knepley   *prob = NULL;
5470e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5471e5e52638SMatthew G. Knepley     PetscInt val;
5472e5e52638SMatthew G. Knepley 
54739371c9d4SSatish Balay     if (!dm->probs[s].label) {
54749371c9d4SSatish Balay       probDef = dm->probs[s].ds;
54759371c9d4SSatish Balay     } else {
54769566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(dm->probs[s].label, point, &val));
54779371c9d4SSatish Balay       if (val >= 0) {
54789371c9d4SSatish Balay         *prob = dm->probs[s].ds;
54799371c9d4SSatish Balay         break;
54809371c9d4SSatish Balay       }
5481e5e52638SMatthew G. Knepley     }
5482e5e52638SMatthew G. Knepley   }
5483e5e52638SMatthew G. Knepley   if (!*prob) *prob = probDef;
5484e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5485e5e52638SMatthew G. Knepley }
5486e5e52638SMatthew G. Knepley 
5487e5e52638SMatthew G. Knepley /*@
5488e5e52638SMatthew G. Knepley   DMGetRegionDS - Get the PetscDS for a given mesh region, defined by a DMLabel
5489e5e52638SMatthew G. Knepley 
5490e5e52638SMatthew G. Knepley   Not collective
5491e5e52638SMatthew G. Knepley 
5492e5e52638SMatthew G. Knepley   Input Parameters:
5493e5e52638SMatthew G. Knepley + dm    - The DM
5494e5e52638SMatthew G. Knepley - label - The DMLabel defining the mesh region, or NULL for the entire mesh
5495e5e52638SMatthew G. Knepley 
5496b3cf3223SMatthew G. Knepley   Output Parameters:
5497b3cf3223SMatthew G. Knepley + fields - The IS containing the DM field numbers for the fields in this DS, or NULL
5498b3cf3223SMatthew G. Knepley - prob - The PetscDS defined on the given region, or NULL
5499e5e52638SMatthew G. Knepley 
5500154ca461SJed Brown   Note:
5501154ca461SJed Brown   If a non-NULL label is given, but there is no PetscDS on that specific label,
5502154ca461SJed Brown   the PetscDS for the full domain (if present) is returned. Returns with
5503154ca461SJed Brown   fields=NULL and prob=NULL if there is no PetscDS for the full domain.
5504e5e52638SMatthew G. Knepley 
5505e5e52638SMatthew G. Knepley   Level: advanced
5506e5e52638SMatthew G. Knepley 
5507db781477SPatrick Sanan .seealso: `DMGetRegionNumDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5508e5e52638SMatthew G. Knepley @*/
5509d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds)
5510d71ae5a4SJacob Faibussowitsch {
5511e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5512e5e52638SMatthew G. Knepley 
5513e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5514e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5515e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
55169371c9d4SSatish Balay   if (fields) {
55179371c9d4SSatish Balay     PetscValidPointer(fields, 3);
55189371c9d4SSatish Balay     *fields = NULL;
55199371c9d4SSatish Balay   }
55209371c9d4SSatish Balay   if (ds) {
55219371c9d4SSatish Balay     PetscValidPointer(ds, 4);
55229371c9d4SSatish Balay     *ds = NULL;
55239371c9d4SSatish Balay   }
5524e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5525154ca461SJed Brown     if (dm->probs[s].label == label || !dm->probs[s].label) {
5526b3cf3223SMatthew G. Knepley       if (fields) *fields = dm->probs[s].fields;
5527b3cf3223SMatthew G. Knepley       if (ds) *ds = dm->probs[s].ds;
5528154ca461SJed Brown       if (dm->probs[s].label) PetscFunctionReturn(0);
5529b3cf3223SMatthew G. Knepley     }
5530e5e52638SMatthew G. Knepley   }
55312df9ee95SMatthew G. Knepley   PetscFunctionReturn(0);
5532e5e52638SMatthew G. Knepley }
5533e5e52638SMatthew G. Knepley 
5534e5e52638SMatthew G. Knepley /*@
5535bb7acecfSBarry Smith   DMSetRegionDS - Set the `PetscDS` for a given mesh region, defined by a `DMLabel`
5536083401c6SMatthew G. Knepley 
5537083401c6SMatthew G. Knepley   Collective on dm
5538083401c6SMatthew G. Knepley 
5539083401c6SMatthew G. Knepley   Input Parameters:
5540bb7acecfSBarry Smith + dm     - The `DM`
5541bb7acecfSBarry Smith . label  - The `DMLabel` defining the mesh region, or NULL for the entire mesh
5542bb7acecfSBarry Smith . fields - The IS containing the `DM` field numbers for the fields in this `PetscDS`, or NULL for all fields
5543bb7acecfSBarry Smith - prob   - The `PetscDS` defined on the given region
5544083401c6SMatthew G. Knepley 
5545bb7acecfSBarry Smith   Note:
5546bb7acecfSBarry 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,
5547083401c6SMatthew G. Knepley   the fields argument is ignored.
5548083401c6SMatthew G. Knepley 
5549083401c6SMatthew G. Knepley   Level: advanced
5550083401c6SMatthew G. Knepley 
5551db781477SPatrick Sanan .seealso: `DMGetRegionDS()`, `DMSetRegionNumDS()`, `DMGetDS()`, `DMGetCellDS()`
5552083401c6SMatthew G. Knepley @*/
5553d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds)
5554d71ae5a4SJacob Faibussowitsch {
5555083401c6SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5556083401c6SMatthew G. Knepley 
5557083401c6SMatthew G. Knepley   PetscFunctionBegin;
5558083401c6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5559083401c6SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
5560064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 4);
5561083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5562083401c6SMatthew G. Knepley     if (dm->probs[s].label == label) {
55639566063dSJacob Faibussowitsch       PetscCall(PetscDSDestroy(&dm->probs[s].ds));
5564083401c6SMatthew G. Knepley       dm->probs[s].ds = ds;
5565083401c6SMatthew G. Knepley       PetscFunctionReturn(0);
5566083401c6SMatthew G. Knepley     }
5567083401c6SMatthew G. Knepley   }
55689566063dSJacob Faibussowitsch   PetscCall(DMDSEnlarge_Static(dm, Nds + 1));
55699566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
55709566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fields));
55719566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ds));
5572083401c6SMatthew G. Knepley   if (!label) {
5573083401c6SMatthew G. Knepley     /* Put the NULL label at the front, so it is returned as the default */
5574083401c6SMatthew G. Knepley     for (s = Nds - 1; s >= 0; --s) dm->probs[s + 1] = dm->probs[s];
5575083401c6SMatthew G. Knepley     Nds = 0;
5576083401c6SMatthew G. Knepley   }
5577083401c6SMatthew G. Knepley   dm->probs[Nds].label  = label;
5578083401c6SMatthew G. Knepley   dm->probs[Nds].fields = fields;
5579083401c6SMatthew G. Knepley   dm->probs[Nds].ds     = ds;
5580083401c6SMatthew G. Knepley   PetscFunctionReturn(0);
5581083401c6SMatthew G. Knepley }
5582083401c6SMatthew G. Knepley 
5583083401c6SMatthew G. Knepley /*@
5584e5e52638SMatthew G. Knepley   DMGetRegionNumDS - Get the PetscDS for a given mesh region, defined by the region number
5585e5e52638SMatthew G. Knepley 
5586e5e52638SMatthew G. Knepley   Not collective
5587e5e52638SMatthew G. Knepley 
5588e5e52638SMatthew G. Knepley   Input Parameters:
5589e5e52638SMatthew G. Knepley + dm  - The DM
5590e5e52638SMatthew G. Knepley - num - The region number, in [0, Nds)
5591e5e52638SMatthew G. Knepley 
5592e5e52638SMatthew G. Knepley   Output Parameters:
5593b3cf3223SMatthew G. Knepley + label  - The region label, or NULL
5594b3cf3223SMatthew G. Knepley . fields - The IS containing the DM field numbers for the fields in this DS, or NULL
5595083401c6SMatthew G. Knepley - ds     - The PetscDS defined on the given region, or NULL
5596e5e52638SMatthew G. Knepley 
5597e5e52638SMatthew G. Knepley   Level: advanced
5598e5e52638SMatthew G. Knepley 
5599db781477SPatrick Sanan .seealso: `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5600e5e52638SMatthew G. Knepley @*/
5601d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds)
5602d71ae5a4SJacob Faibussowitsch {
5603e5e52638SMatthew G. Knepley   PetscInt Nds;
5604e5e52638SMatthew G. Knepley 
5605e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5606e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56079566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
560863a3b9bcSJacob 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);
5609e5e52638SMatthew G. Knepley   if (label) {
5610e5e52638SMatthew G. Knepley     PetscValidPointer(label, 3);
5611e5e52638SMatthew G. Knepley     *label = dm->probs[num].label;
5612e5e52638SMatthew G. Knepley   }
5613b3cf3223SMatthew G. Knepley   if (fields) {
5614b3cf3223SMatthew G. Knepley     PetscValidPointer(fields, 4);
5615b3cf3223SMatthew G. Knepley     *fields = dm->probs[num].fields;
5616b3cf3223SMatthew G. Knepley   }
5617e5e52638SMatthew G. Knepley   if (ds) {
5618b3cf3223SMatthew G. Knepley     PetscValidPointer(ds, 5);
5619e5e52638SMatthew G. Knepley     *ds = dm->probs[num].ds;
5620e5e52638SMatthew G. Knepley   }
5621e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5622e5e52638SMatthew G. Knepley }
5623e5e52638SMatthew G. Knepley 
5624e5e52638SMatthew G. Knepley /*@
5625083401c6SMatthew G. Knepley   DMSetRegionNumDS - Set the PetscDS for a given mesh region, defined by the region number
5626e5e52638SMatthew G. Knepley 
5627083401c6SMatthew G. Knepley   Not collective
5628e5e52638SMatthew G. Knepley 
5629e5e52638SMatthew G. Knepley   Input Parameters:
5630e5e52638SMatthew G. Knepley + dm     - The DM
5631083401c6SMatthew G. Knepley . num    - The region number, in [0, Nds)
5632083401c6SMatthew G. Knepley . label  - The region label, or NULL
5633083401c6SMatthew G. Knepley . fields - The IS containing the DM field numbers for the fields in this DS, or NULL to prevent setting
5634083401c6SMatthew G. Knepley - ds     - The PetscDS defined on the given region, or NULL to prevent setting
5635e5e52638SMatthew G. Knepley 
5636e5e52638SMatthew G. Knepley   Level: advanced
5637e5e52638SMatthew G. Knepley 
5638db781477SPatrick Sanan .seealso: `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5639e5e52638SMatthew G. Knepley @*/
5640d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds)
5641d71ae5a4SJacob Faibussowitsch {
5642083401c6SMatthew G. Knepley   PetscInt Nds;
5643e5e52638SMatthew G. Knepley 
5644e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5645e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5646ad540459SPierre Jolivet   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
56479566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
564863a3b9bcSJacob 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);
56499566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
56509566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->probs[num].label));
5651083401c6SMatthew G. Knepley   dm->probs[num].label = label;
5652083401c6SMatthew G. Knepley   if (fields) {
5653083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(fields, IS_CLASSID, 4);
56549566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)fields));
56559566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[num].fields));
5656083401c6SMatthew G. Knepley     dm->probs[num].fields = fields;
5657e5e52638SMatthew G. Knepley   }
5658083401c6SMatthew G. Knepley   if (ds) {
5659083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 5);
56609566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ds));
56619566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[num].ds));
5662083401c6SMatthew G. Knepley     dm->probs[num].ds = ds;
5663083401c6SMatthew G. Knepley   }
5664e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5665e5e52638SMatthew G. Knepley }
5666e5e52638SMatthew G. Knepley 
5667e5e52638SMatthew G. Knepley /*@
56681d3af9e0SMatthew G. Knepley   DMFindRegionNum - Find the region number for a given PetscDS, or -1 if it is not found.
56691d3af9e0SMatthew G. Knepley 
56701d3af9e0SMatthew G. Knepley   Not collective
56711d3af9e0SMatthew G. Knepley 
56721d3af9e0SMatthew G. Knepley   Input Parameters:
56731d3af9e0SMatthew G. Knepley + dm  - The DM
56741d3af9e0SMatthew G. Knepley - ds  - The PetscDS defined on the given region
56751d3af9e0SMatthew G. Knepley 
56761d3af9e0SMatthew G. Knepley   Output Parameter:
56771d3af9e0SMatthew G. Knepley . num - The region number, in [0, Nds), or -1 if not found
56781d3af9e0SMatthew G. Knepley 
56791d3af9e0SMatthew G. Knepley   Level: advanced
56801d3af9e0SMatthew G. Knepley 
5681db781477SPatrick Sanan .seealso: `DMGetRegionNumDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
56821d3af9e0SMatthew G. Knepley @*/
5683d71ae5a4SJacob Faibussowitsch PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num)
5684d71ae5a4SJacob Faibussowitsch {
56851d3af9e0SMatthew G. Knepley   PetscInt Nds, n;
56861d3af9e0SMatthew G. Knepley 
56871d3af9e0SMatthew G. Knepley   PetscFunctionBegin;
56881d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56891d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 2);
5690dadcf809SJacob Faibussowitsch   PetscValidIntPointer(num, 3);
56919566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
56929371c9d4SSatish Balay   for (n = 0; n < Nds; ++n)
56939371c9d4SSatish Balay     if (ds == dm->probs[n].ds) break;
56941d3af9e0SMatthew G. Knepley   if (n >= Nds) *num = -1;
56951d3af9e0SMatthew G. Knepley   else *num = n;
56961d3af9e0SMatthew G. Knepley   PetscFunctionReturn(0);
56971d3af9e0SMatthew G. Knepley }
56981d3af9e0SMatthew G. Knepley 
56992df84da0SMatthew G. Knepley /*@C
5700bb7acecfSBarry Smith   DMCreateFEDefault - Create a `PetscFE` based on the celltype for the mesh
57012df84da0SMatthew G. Knepley 
57022df84da0SMatthew G. Knepley   Not collective
57032df84da0SMatthew G. Knepley 
5704f1a722f8SMatthew G. Knepley   Input Parameters:
5705bb7acecfSBarry Smith + dm     - The `DM`
57062df84da0SMatthew G. Knepley . Nc     - The number of components for the field
5707bb7acecfSBarry Smith . prefix - The options prefix for the output `PetscFE`, or NULL
5708bb7acecfSBarry Smith - qorder - The quadrature order or `PETSC_DETERMINE` to use `PetscSpace` polynomial degree
57092df84da0SMatthew G. Knepley 
57102df84da0SMatthew G. Knepley   Output Parameter:
5711bb7acecfSBarry Smith . fem - The `PetscFE`
57122df84da0SMatthew G. Knepley 
5713bb7acecfSBarry Smith   Note:
5714bb7acecfSBarry Smith   This is a convenience method that just calls `PetscFECreateByCell()` underneath.
57152df84da0SMatthew G. Knepley 
57162df84da0SMatthew G. Knepley   Level: intermediate
57172df84da0SMatthew G. Knepley 
5718db781477SPatrick Sanan .seealso: `PetscFECreateByCell()`, `DMAddField()`, `DMCreateDS()`, `DMGetCellDS()`, `DMGetRegionDS()`
57192df84da0SMatthew G. Knepley @*/
5720d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFEDefault(DM dm, PetscInt Nc, const char prefix[], PetscInt qorder, PetscFE *fem)
5721d71ae5a4SJacob Faibussowitsch {
57222df84da0SMatthew G. Knepley   DMPolytopeType ct;
57232df84da0SMatthew G. Knepley   PetscInt       dim, cStart;
57242df84da0SMatthew G. Knepley 
57252df84da0SMatthew G. Knepley   PetscFunctionBegin;
57262df84da0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57272df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 2);
57282df84da0SMatthew G. Knepley   if (prefix) PetscValidCharPointer(prefix, 3);
57292df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, qorder, 4);
57302df84da0SMatthew G. Knepley   PetscValidPointer(fem, 5);
57319566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
57329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
57339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
57349566063dSJacob Faibussowitsch   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, Nc, ct, prefix, qorder, fem));
57352df84da0SMatthew G. Knepley   PetscFunctionReturn(0);
57362df84da0SMatthew G. Knepley }
57372df84da0SMatthew G. Knepley 
57381d3af9e0SMatthew G. Knepley /*@
5739bb7acecfSBarry Smith   DMCreateDS - Create the discrete systems for the `DM` based upon the fields added to the `DM`
5740e5e52638SMatthew G. Knepley 
5741d083f849SBarry Smith   Collective on dm
5742e5e52638SMatthew G. Knepley 
5743e5e52638SMatthew G. Knepley   Input Parameter:
5744bb7acecfSBarry Smith . dm - The `DM`
5745e5e52638SMatthew G. Knepley 
574645480ffeSMatthew G. Knepley   Options Database Keys:
5747bb7acecfSBarry Smith . -dm_petscds_view - View all the `PetscDS` objects in this `DM`
574845480ffeSMatthew G. Knepley 
5749bb7acecfSBarry Smith   Note:
5750bb7acecfSBarry Smith   If the label has a `PetscDS` defined, it will be replaced. Otherwise, it will be added to the `DM`.
5751e5e52638SMatthew G. Knepley 
5752e5e52638SMatthew G. Knepley   Level: intermediate
5753e5e52638SMatthew G. Knepley 
5754db781477SPatrick Sanan .seealso: `DMSetField`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
5755e5e52638SMatthew G. Knepley @*/
5756d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDS(DM dm)
5757d71ae5a4SJacob Faibussowitsch {
5758e5e52638SMatthew G. Knepley   MPI_Comm  comm;
5759083401c6SMatthew G. Knepley   PetscDS   dsDef;
5760083401c6SMatthew G. Knepley   DMLabel  *labelSet;
5761f9244615SMatthew G. Knepley   PetscInt  dE, Nf = dm->Nf, f, s, Nl, l, Ndef, k;
5762f9244615SMatthew G. Knepley   PetscBool doSetup = PETSC_TRUE, flg;
5763e5e52638SMatthew G. Knepley 
5764e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5765e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5766e5e52638SMatthew G. Knepley   if (!dm->fields) PetscFunctionReturn(0);
57679566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
57689566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
5769083401c6SMatthew G. Knepley   /* Determine how many regions we have */
57709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(Nf, &labelSet));
5771083401c6SMatthew G. Knepley   Nl   = 0;
5772083401c6SMatthew G. Knepley   Ndef = 0;
5773083401c6SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5774083401c6SMatthew G. Knepley     DMLabel  label = dm->fields[f].label;
5775083401c6SMatthew G. Knepley     PetscInt l;
5776083401c6SMatthew G. Knepley 
5777f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
5778f918ec44SMatthew G. Knepley     /* Move CEED context to discretizations */
5779f918ec44SMatthew G. Knepley     {
5780f918ec44SMatthew G. Knepley       PetscClassId id;
5781f918ec44SMatthew G. Knepley 
57829566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(dm->fields[f].disc, &id));
5783f918ec44SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
5784f918ec44SMatthew G. Knepley         Ceed ceed;
5785f918ec44SMatthew G. Knepley 
57869566063dSJacob Faibussowitsch         PetscCall(DMGetCeed(dm, &ceed));
57879566063dSJacob Faibussowitsch         PetscCall(PetscFESetCeed((PetscFE)dm->fields[f].disc, ceed));
5788f918ec44SMatthew G. Knepley       }
5789f918ec44SMatthew G. Knepley     }
5790f918ec44SMatthew G. Knepley #endif
57919371c9d4SSatish Balay     if (!label) {
57929371c9d4SSatish Balay       ++Ndef;
57939371c9d4SSatish Balay       continue;
57949371c9d4SSatish Balay     }
57959371c9d4SSatish Balay     for (l = 0; l < Nl; ++l)
57969371c9d4SSatish Balay       if (label == labelSet[l]) break;
5797083401c6SMatthew G. Knepley     if (l < Nl) continue;
5798083401c6SMatthew G. Knepley     labelSet[Nl++] = label;
5799083401c6SMatthew G. Knepley   }
5800083401c6SMatthew G. Knepley   /* Create default DS if there are no labels to intersect with */
58019566063dSJacob Faibussowitsch   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef));
5802083401c6SMatthew G. Knepley   if (!dsDef && Ndef && !Nl) {
5803b3cf3223SMatthew G. Knepley     IS        fields;
5804b3cf3223SMatthew G. Knepley     PetscInt *fld, nf;
5805b3cf3223SMatthew G. Knepley 
58069371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58079371c9d4SSatish Balay       if (!dm->fields[f].label) ++nf;
58087a8be351SBarry Smith     PetscCheck(nf, comm, PETSC_ERR_PLIB, "All fields have labels, but we are trying to create a default DS");
58099566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
58109371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58119371c9d4SSatish Balay       if (!dm->fields[f].label) fld[nf++] = f;
58129566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
58139566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
58149566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
58159566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
581688f0c812SMatthew G. Knepley 
58179566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
58189566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, NULL, fields, dsDef));
58199566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
58209566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fields));
58212df9ee95SMatthew G. Knepley   }
58229566063dSJacob Faibussowitsch   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef));
58239566063dSJacob Faibussowitsch   if (dsDef) PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
5824083401c6SMatthew G. Knepley   /* Intersect labels with default fields */
5825083401c6SMatthew G. Knepley   if (Ndef && Nl) {
58260122748bSMatthew G. Knepley     DM              plex;
5827083401c6SMatthew G. Knepley     DMLabel         cellLabel;
5828083401c6SMatthew G. Knepley     IS              fieldIS, allcellIS, defcellIS = NULL;
5829083401c6SMatthew G. Knepley     PetscInt       *fields;
5830083401c6SMatthew G. Knepley     const PetscInt *cells;
5831083401c6SMatthew G. Knepley     PetscInt        depth, nf = 0, n, c;
58320122748bSMatthew G. Knepley 
58339566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
58349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(plex, &depth));
58359566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(plex, "dim", depth, &allcellIS));
58369566063dSJacob Faibussowitsch     if (!allcellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, &allcellIS));
58375fedec97SMatthew G. Knepley     /* TODO This looks like it only works for one label */
5838083401c6SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
5839083401c6SMatthew G. Knepley       DMLabel label = labelSet[l];
5840083401c6SMatthew G. Knepley       IS      pointIS;
5841083401c6SMatthew G. Knepley 
58429566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&defcellIS));
58439566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(label, 1, &pointIS));
58449566063dSJacob Faibussowitsch       PetscCall(ISDifference(allcellIS, pointIS, &defcellIS));
58459566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pointIS));
5846083401c6SMatthew G. Knepley     }
58479566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&allcellIS));
5848083401c6SMatthew G. Knepley 
58499566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel));
58509566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(defcellIS, &n));
58519566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(defcellIS, &cells));
58529566063dSJacob Faibussowitsch     for (c = 0; c < n; ++c) PetscCall(DMLabelSetValue(cellLabel, cells[c], 1));
58539566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(defcellIS, &cells));
58549566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&defcellIS));
58559566063dSJacob Faibussowitsch     PetscCall(DMPlexLabelComplete(plex, cellLabel));
5856083401c6SMatthew G. Knepley 
58579566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Ndef, &fields));
58589371c9d4SSatish Balay     for (f = 0; f < Nf; ++f)
58599371c9d4SSatish Balay       if (!dm->fields[f].label) fields[nf++] = f;
58609566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fieldIS));
58619566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fieldIS, "dm_fields_"));
58629566063dSJacob Faibussowitsch     PetscCall(ISSetType(fieldIS, ISGENERAL));
58639566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER));
5864083401c6SMatthew G. Knepley 
58659566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
58669566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, cellLabel, fieldIS, dsDef));
58679566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
58689566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&cellLabel));
58699566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
58709566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fieldIS));
58719566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5872083401c6SMatthew G. Knepley   }
5873083401c6SMatthew G. Knepley   /* Create label DSes
5874083401c6SMatthew G. Knepley      - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS
5875083401c6SMatthew G. Knepley   */
5876083401c6SMatthew G. Knepley   /* TODO Should check that labels are disjoint */
5877083401c6SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
5878083401c6SMatthew G. Knepley     DMLabel   label = labelSet[l];
5879083401c6SMatthew G. Knepley     PetscDS   ds;
5880083401c6SMatthew G. Knepley     IS        fields;
5881083401c6SMatthew G. Knepley     PetscInt *fld, nf;
5882083401c6SMatthew G. Knepley 
58839566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
58849371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58859371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) ++nf;
58869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
58879371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58889371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f;
58899566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
58909566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
58919566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
58929566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
58939566063dSJacob Faibussowitsch     PetscCall(DMSetRegionDS(dm, label, fields, ds));
58949566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fields));
58959566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(ds, dE));
5896083401c6SMatthew G. Knepley     {
5897083401c6SMatthew G. Knepley       DMPolytopeType ct;
5898083401c6SMatthew G. Knepley       PetscInt       lStart, lEnd;
58995fedec97SMatthew G. Knepley       PetscBool      isCohesiveLocal = PETSC_FALSE, isCohesive;
59000122748bSMatthew G. Knepley 
59019566063dSJacob Faibussowitsch       PetscCall(DMLabelGetBounds(label, &lStart, &lEnd));
5902665f567fSMatthew G. Knepley       if (lStart >= 0) {
59039566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, lStart, &ct));
5904412e9a14SMatthew G. Knepley         switch (ct) {
5905412e9a14SMatthew G. Knepley         case DM_POLYTOPE_POINT_PRISM_TENSOR:
5906412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
5907412e9a14SMatthew G. Knepley         case DM_POLYTOPE_TRI_PRISM_TENSOR:
5908d71ae5a4SJacob Faibussowitsch         case DM_POLYTOPE_QUAD_PRISM_TENSOR:
5909d71ae5a4SJacob Faibussowitsch           isCohesiveLocal = PETSC_TRUE;
5910d71ae5a4SJacob Faibussowitsch           break;
5911d71ae5a4SJacob Faibussowitsch         default:
5912d71ae5a4SJacob Faibussowitsch           break;
5913412e9a14SMatthew G. Knepley         }
5914665f567fSMatthew G. Knepley       }
59159566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allreduce(&isCohesiveLocal, &isCohesive, 1, MPIU_BOOL, MPI_LOR, comm));
59165fedec97SMatthew G. Knepley       for (f = 0, nf = 0; f < Nf; ++f) {
59175fedec97SMatthew G. Knepley         if (label == dm->fields[f].label || !dm->fields[f].label) {
59185fedec97SMatthew G. Knepley           if (label == dm->fields[f].label) {
59199566063dSJacob Faibussowitsch             PetscCall(PetscDSSetDiscretization(ds, nf, NULL));
59209566063dSJacob Faibussowitsch             PetscCall(PetscDSSetCohesive(ds, nf, isCohesive));
59215fedec97SMatthew G. Knepley           }
59225fedec97SMatthew G. Knepley           ++nf;
59235fedec97SMatthew G. Knepley         }
59245fedec97SMatthew G. Knepley       }
5925e5e52638SMatthew G. Knepley     }
59269566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&ds));
5927e5e52638SMatthew G. Knepley   }
59289566063dSJacob Faibussowitsch   PetscCall(PetscFree(labelSet));
5929e5e52638SMatthew G. Knepley   /* Set fields in DSes */
5930083401c6SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5931083401c6SMatthew G. Knepley     PetscDS         ds     = dm->probs[s].ds;
5932083401c6SMatthew G. Knepley     IS              fields = dm->probs[s].fields;
5933083401c6SMatthew G. Knepley     const PetscInt *fld;
59345fedec97SMatthew G. Knepley     PetscInt        nf, dsnf;
59355fedec97SMatthew G. Knepley     PetscBool       isCohesive;
5936e5e52638SMatthew G. Knepley 
59379566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsnf));
59389566063dSJacob Faibussowitsch     PetscCall(PetscDSIsCohesive(ds, &isCohesive));
59399566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(fields, &nf));
59409566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fields, &fld));
5941083401c6SMatthew G. Knepley     for (f = 0; f < nf; ++f) {
5942083401c6SMatthew G. Knepley       PetscObject  disc = dm->fields[fld[f]].disc;
59435fedec97SMatthew G. Knepley       PetscBool    isCohesiveField;
5944e5e52638SMatthew G. Knepley       PetscClassId id;
5945e5e52638SMatthew G. Knepley 
59465fedec97SMatthew G. Knepley       /* Handle DS with no fields */
59479566063dSJacob Faibussowitsch       if (dsnf) PetscCall(PetscDSGetCohesive(ds, f, &isCohesiveField));
59485fedec97SMatthew G. Knepley       /* If this is a cohesive cell, then regular fields need the lower dimensional discretization */
59499566063dSJacob Faibussowitsch       if (isCohesive && !isCohesiveField) PetscCall(PetscFEGetHeightSubspace((PetscFE)disc, 1, (PetscFE *)&disc));
59509566063dSJacob Faibussowitsch       PetscCall(PetscDSSetDiscretization(ds, f, disc));
5951083401c6SMatthew G. Knepley       /* We allow people to have placeholder fields and construct the Section by hand */
59529566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(disc, &id));
5953e5e52638SMatthew G. Knepley       if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE;
5954e5e52638SMatthew G. Knepley     }
59559566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fields, &fld));
5956e5e52638SMatthew G. Knepley   }
5957f9244615SMatthew G. Knepley   /* Allow k-jet tabulation */
59589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)dm)->prefix, "-dm_ds_jet_degree", &k, &flg));
5959f9244615SMatthew G. Knepley   if (flg) {
59603b4aee56SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
59613b4aee56SMatthew G. Knepley       PetscDS  ds = dm->probs[s].ds;
59623b4aee56SMatthew G. Knepley       PetscInt Nf, f;
59633b4aee56SMatthew G. Knepley 
59649566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(ds, &Nf));
59659566063dSJacob Faibussowitsch       for (f = 0; f < Nf; ++f) PetscCall(PetscDSSetJetDegree(ds, f, k));
59663b4aee56SMatthew G. Knepley     }
5967f9244615SMatthew G. Knepley   }
5968e5e52638SMatthew G. Knepley   /* Setup DSes */
5969e5e52638SMatthew G. Knepley   if (doSetup) {
59709566063dSJacob Faibussowitsch     for (s = 0; s < dm->Nds; ++s) PetscCall(PetscDSSetUp(dm->probs[s].ds));
5971e5e52638SMatthew G. Knepley   }
5972e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
5973e5e52638SMatthew G. Knepley }
5974e5e52638SMatthew G. Knepley 
5975e5e52638SMatthew G. Knepley /*@
5976bb7acecfSBarry Smith   DMComputeExactSolution - Compute the exact solution for a given `DM`, using the `PetscDS` information.
59777f96f943SMatthew G. Knepley 
5978bb7acecfSBarry Smith   Collective on `DM`
5979f2cacb80SMatthew G. Knepley 
59807f96f943SMatthew G. Knepley   Input Parameters:
5981bb7acecfSBarry Smith + dm   - The `DM`
59827f96f943SMatthew G. Knepley - time - The time
59837f96f943SMatthew G. Knepley 
59847f96f943SMatthew G. Knepley   Output Parameters:
5985f2cacb80SMatthew G. Knepley + u    - The vector will be filled with exact solution values, or NULL
5986f2cacb80SMatthew G. Knepley - u_t  - The vector will be filled with the time derivative of exact solution values, or NULL
59877f96f943SMatthew G. Knepley 
5988bb7acecfSBarry Smith   Note:
5989bb7acecfSBarry Smith   The user must call `PetscDSSetExactSolution()` before using this routine
59907f96f943SMatthew G. Knepley 
59917f96f943SMatthew G. Knepley   Level: developer
59927f96f943SMatthew G. Knepley 
5993db781477SPatrick Sanan .seealso: `PetscDSSetExactSolution()`
59947f96f943SMatthew G. Knepley @*/
5995d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t)
5996d71ae5a4SJacob Faibussowitsch {
59977f96f943SMatthew G. Knepley   PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
59987f96f943SMatthew G. Knepley   void   **ectxs;
59997f96f943SMatthew G. Knepley   PetscInt Nf, Nds, s;
60007f96f943SMatthew G. Knepley 
60017f96f943SMatthew G. Knepley   PetscFunctionBegin;
6002f2cacb80SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6003f2cacb80SMatthew G. Knepley   if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
6004f2cacb80SMatthew G. Knepley   if (u_t) PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4);
60059566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
60069566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(Nf, &exacts, Nf, &ectxs));
60079566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
60087f96f943SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
60097f96f943SMatthew G. Knepley     PetscDS         ds;
60107f96f943SMatthew G. Knepley     DMLabel         label;
60117f96f943SMatthew G. Knepley     IS              fieldIS;
60127f96f943SMatthew G. Knepley     const PetscInt *fields, id = 1;
60137f96f943SMatthew G. Knepley     PetscInt        dsNf, f;
60147f96f943SMatthew G. Knepley 
60159566063dSJacob Faibussowitsch     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds));
60169566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
60179566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fieldIS, &fields));
60189566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(exacts, Nf));
60199566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(ectxs, Nf));
6020f2cacb80SMatthew G. Knepley     if (u) {
60217f96f943SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) {
60227f96f943SMatthew G. Knepley         const PetscInt field = fields[f];
60239566063dSJacob Faibussowitsch         PetscCall(PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]));
60247f96f943SMatthew G. Knepley       }
60259566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(fieldIS, &fields));
60267f96f943SMatthew G. Knepley       if (label) {
60279566063dSJacob Faibussowitsch         PetscCall(DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u));
60287f96f943SMatthew G. Knepley       } else {
60299566063dSJacob Faibussowitsch         PetscCall(DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u));
60307f96f943SMatthew G. Knepley       }
60317f96f943SMatthew G. Knepley     }
6032f2cacb80SMatthew G. Knepley     if (u_t) {
60339566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(exacts, Nf));
60349566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ectxs, Nf));
6035f2cacb80SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) {
6036f2cacb80SMatthew G. Knepley         const PetscInt field = fields[f];
60379566063dSJacob Faibussowitsch         PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, field, &exacts[field], &ectxs[field]));
6038f2cacb80SMatthew G. Knepley       }
60399566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(fieldIS, &fields));
6040f2cacb80SMatthew G. Knepley       if (label) {
60419566063dSJacob Faibussowitsch         PetscCall(DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u_t));
6042f2cacb80SMatthew G. Knepley       } else {
60439566063dSJacob Faibussowitsch         PetscCall(DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u_t));
6044f2cacb80SMatthew G. Knepley       }
6045f2cacb80SMatthew G. Knepley     }
6046f2cacb80SMatthew G. Knepley   }
6047f2cacb80SMatthew G. Knepley   if (u) {
60489566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution"));
60499566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u, "exact_"));
6050f2cacb80SMatthew G. Knepley   }
6051f2cacb80SMatthew G. Knepley   if (u_t) {
60529566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution Time Derivative"));
60539566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u_t, "exact_t_"));
6054f2cacb80SMatthew G. Knepley   }
60559566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exacts, ectxs));
60567f96f943SMatthew G. Knepley   PetscFunctionReturn(0);
60577f96f943SMatthew G. Knepley }
60587f96f943SMatthew G. Knepley 
6059d71ae5a4SJacob Faibussowitsch PetscErrorCode DMTransferDS_Internal(DM dm, DMLabel label, IS fields, PetscDS ds)
6060d71ae5a4SJacob Faibussowitsch {
606145480ffeSMatthew G. Knepley   PetscDS    dsNew;
606245480ffeSMatthew G. Knepley   DSBoundary b;
60636a02485aSMatthew G. Knepley   PetscInt   cdim, Nf, f, d;
60645fedec97SMatthew G. Knepley   PetscBool  isCohesive;
606545480ffeSMatthew G. Knepley   void      *ctx;
606645480ffeSMatthew G. Knepley 
606745480ffeSMatthew G. Knepley   PetscFunctionBegin;
60689566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)ds), &dsNew));
60699566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyConstants(ds, dsNew));
60709566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyExactSolutions(ds, dsNew));
60719566063dSJacob Faibussowitsch   PetscCall(PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, dsNew));
60729566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyEquations(ds, dsNew));
60739566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
607445480ffeSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
60759566063dSJacob Faibussowitsch     PetscCall(PetscDSGetContext(ds, f, &ctx));
60769566063dSJacob Faibussowitsch     PetscCall(PetscDSSetContext(dsNew, f, ctx));
60779566063dSJacob Faibussowitsch     PetscCall(PetscDSGetCohesive(ds, f, &isCohesive));
60789566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCohesive(dsNew, f, isCohesive));
60796a02485aSMatthew G. Knepley     PetscCall(PetscDSGetJetDegree(ds, f, &d));
60806a02485aSMatthew G. Knepley     PetscCall(PetscDSSetJetDegree(dsNew, f, d));
608145480ffeSMatthew G. Knepley   }
608245480ffeSMatthew G. Knepley   if (Nf) {
60839566063dSJacob Faibussowitsch     PetscCall(PetscDSGetCoordinateDimension(ds, &cdim));
60849566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(dsNew, cdim));
608545480ffeSMatthew G. Knepley   }
60869566063dSJacob Faibussowitsch   PetscCall(PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew));
608745480ffeSMatthew G. Knepley   for (b = dsNew->boundary; b; b = b->next) {
60889566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, b->lname, &b->label));
608945480ffeSMatthew G. Knepley     /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */
60907a8be351SBarry Smith     //PetscCheck(b->label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name);
609145480ffeSMatthew G. Knepley   }
609245480ffeSMatthew G. Knepley 
60939566063dSJacob Faibussowitsch   PetscCall(DMSetRegionDS(dm, label, fields, dsNew));
60949566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&dsNew));
609545480ffeSMatthew G. Knepley   PetscFunctionReturn(0);
609645480ffeSMatthew G. Knepley }
609745480ffeSMatthew G. Knepley 
60987f96f943SMatthew G. Knepley /*@
6099bb7acecfSBarry Smith   DMCopyDS - Copy the discrete systems for the `DM` into another `DM`
6100e5e52638SMatthew G. Knepley 
6101d083f849SBarry Smith   Collective on dm
6102e5e52638SMatthew G. Knepley 
6103e5e52638SMatthew G. Knepley   Input Parameter:
6104bb7acecfSBarry Smith . dm - The `DM`
6105e5e52638SMatthew G. Knepley 
6106e5e52638SMatthew G. Knepley   Output Parameter:
6107bb7acecfSBarry Smith . newdm - The `DM`
6108e5e52638SMatthew G. Knepley 
6109e5e52638SMatthew G. Knepley   Level: advanced
6110e5e52638SMatthew G. Knepley 
6111db781477SPatrick Sanan .seealso: `DMCopyFields()`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
6112e5e52638SMatthew G. Knepley @*/
6113d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDS(DM dm, DM newdm)
6114d71ae5a4SJacob Faibussowitsch {
6115e5e52638SMatthew G. Knepley   PetscInt Nds, s;
6116e5e52638SMatthew G. Knepley 
6117e5e52638SMatthew G. Knepley   PetscFunctionBegin;
6118e5e52638SMatthew G. Knepley   if (dm == newdm) PetscFunctionReturn(0);
61199566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
61209566063dSJacob Faibussowitsch   PetscCall(DMClearDS(newdm));
6121e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
6122e5e52638SMatthew G. Knepley     DMLabel  label;
6123b3cf3223SMatthew G. Knepley     IS       fields;
612445480ffeSMatthew G. Knepley     PetscDS  ds, newds;
6125783e2ec8SMatthew G. Knepley     PetscInt Nbd, bd;
6126e5e52638SMatthew G. Knepley 
61279566063dSJacob Faibussowitsch     PetscCall(DMGetRegionNumDS(dm, s, &label, &fields, &ds));
6128b8025e53SMatthew G. Knepley     /* TODO: We need to change all keys from labels in the old DM to labels in the new DM */
61299566063dSJacob Faibussowitsch     PetscCall(DMTransferDS_Internal(newdm, label, fields, ds));
6130*d5b43468SJose E. Roman     /* Complete new labels in the new DS */
61319566063dSJacob Faibussowitsch     PetscCall(DMGetRegionDS(newdm, label, NULL, &newds));
61329566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumBoundary(newds, &Nbd));
6133783e2ec8SMatthew G. Knepley     for (bd = 0; bd < Nbd; ++bd) {
6134b8025e53SMatthew G. Knepley       PetscWeakForm wf;
613545480ffeSMatthew G. Knepley       DMLabel       label;
6136783e2ec8SMatthew G. Knepley       PetscInt      field;
6137783e2ec8SMatthew G. Knepley 
61389566063dSJacob Faibussowitsch       PetscCall(PetscDSGetBoundary(newds, bd, &wf, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
61399566063dSJacob Faibussowitsch       PetscCall(PetscWeakFormReplaceLabel(wf, label));
6140783e2ec8SMatthew G. Knepley     }
6141e5e52638SMatthew G. Knepley   }
6142799db056SMatthew G. Knepley   PetscCall(DMCompleteBCLabels_Internal(newdm));
6143e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
6144e5e52638SMatthew G. Knepley }
6145e5e52638SMatthew G. Knepley 
6146e5e52638SMatthew G. Knepley /*@
6147bb7acecfSBarry Smith   DMCopyDisc - Copy the fields and discrete systems for the `DM` into another `DM`
6148e5e52638SMatthew G. Knepley 
6149d083f849SBarry Smith   Collective on dm
6150e5e52638SMatthew G. Knepley 
6151e5e52638SMatthew G. Knepley   Input Parameter:
6152bb7acecfSBarry Smith . dm - The `DM`
6153e5e52638SMatthew G. Knepley 
6154e5e52638SMatthew G. Knepley   Output Parameter:
6155bb7acecfSBarry Smith . newdm - The `DM`
6156e5e52638SMatthew G. Knepley 
6157e5e52638SMatthew G. Knepley   Level: advanced
6158e5e52638SMatthew G. Knepley 
6159bb7acecfSBarry Smith   Developer Note:
6160bb7acecfSBarry Smith   Really ugly name, nothing in PETSc is called a `Disc` plus it is an ugly abbreviation
6161bb7acecfSBarry Smith 
6162db781477SPatrick Sanan .seealso: `DMCopyFields()`, `DMCopyDS()`
6163e5e52638SMatthew G. Knepley @*/
6164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDisc(DM dm, DM newdm)
6165d71ae5a4SJacob Faibussowitsch {
6166e5e52638SMatthew G. Knepley   PetscFunctionBegin;
61679566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, newdm));
61689566063dSJacob Faibussowitsch   PetscCall(DMCopyDS(dm, newdm));
6169e5e52638SMatthew G. Knepley   PetscFunctionReturn(0);
6170e5e52638SMatthew G. Knepley }
6171e5e52638SMatthew G. Knepley 
6172c73cfb54SMatthew G. Knepley /*@
6173bb7acecfSBarry Smith   DMGetDimension - Return the topological dimension of the `DM`
6174c73cfb54SMatthew G. Knepley 
6175c73cfb54SMatthew G. Knepley   Not collective
6176c73cfb54SMatthew G. Knepley 
6177c73cfb54SMatthew G. Knepley   Input Parameter:
6178bb7acecfSBarry Smith . dm - The `DM`
6179c73cfb54SMatthew G. Knepley 
6180c73cfb54SMatthew G. Knepley   Output Parameter:
6181c73cfb54SMatthew G. Knepley . dim - The topological dimension
6182c73cfb54SMatthew G. Knepley 
6183c73cfb54SMatthew G. Knepley   Level: beginner
6184c73cfb54SMatthew G. Knepley 
6185db781477SPatrick Sanan .seealso: `DMSetDimension()`, `DMCreate()`
6186c73cfb54SMatthew G. Knepley @*/
6187d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
6188d71ae5a4SJacob Faibussowitsch {
6189c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6190c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6191534a8f05SLisandro Dalcin   PetscValidIntPointer(dim, 2);
6192c73cfb54SMatthew G. Knepley   *dim = dm->dim;
6193c73cfb54SMatthew G. Knepley   PetscFunctionReturn(0);
6194c73cfb54SMatthew G. Knepley }
6195c73cfb54SMatthew G. Knepley 
6196c73cfb54SMatthew G. Knepley /*@
6197bb7acecfSBarry Smith   DMSetDimension - Set the topological dimension of the `DM`
6198c73cfb54SMatthew G. Knepley 
6199c73cfb54SMatthew G. Knepley   Collective on dm
6200c73cfb54SMatthew G. Knepley 
6201c73cfb54SMatthew G. Knepley   Input Parameters:
6202bb7acecfSBarry Smith + dm - The `DM`
6203c73cfb54SMatthew G. Knepley - dim - The topological dimension
6204c73cfb54SMatthew G. Knepley 
6205c73cfb54SMatthew G. Knepley   Level: beginner
6206c73cfb54SMatthew G. Knepley 
6207db781477SPatrick Sanan .seealso: `DMGetDimension()`, `DMCreate()`
6208c73cfb54SMatthew G. Knepley @*/
6209d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
6210d71ae5a4SJacob Faibussowitsch {
6211e5e52638SMatthew G. Knepley   PetscDS  ds;
621245480ffeSMatthew G. Knepley   PetscInt Nds, n;
6213f17e8794SMatthew G. Knepley 
6214c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6215c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6216c73cfb54SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6217c73cfb54SMatthew G. Knepley   dm->dim = dim;
6218d17bd122SMatthew G. Knepley   if (dm->dim >= 0) {
62199566063dSJacob Faibussowitsch     PetscCall(DMGetNumDS(dm, &Nds));
622045480ffeSMatthew G. Knepley     for (n = 0; n < Nds; ++n) {
62219566063dSJacob Faibussowitsch       PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds));
62229566063dSJacob Faibussowitsch       if (ds->dimEmbed < 0) PetscCall(PetscDSSetCoordinateDimension(ds, dim));
622345480ffeSMatthew G. Knepley     }
6224d17bd122SMatthew G. Knepley   }
6225c73cfb54SMatthew G. Knepley   PetscFunctionReturn(0);
6226c73cfb54SMatthew G. Knepley }
6227c73cfb54SMatthew G. Knepley 
6228793f3fe5SMatthew G. Knepley /*@
6229793f3fe5SMatthew G. Knepley   DMGetDimPoints - Get the half-open interval for all points of a given dimension
6230793f3fe5SMatthew G. Knepley 
6231d083f849SBarry Smith   Collective on dm
6232793f3fe5SMatthew G. Knepley 
6233793f3fe5SMatthew G. Knepley   Input Parameters:
6234bb7acecfSBarry Smith + dm - the `DM`
6235793f3fe5SMatthew G. Knepley - dim - the dimension
6236793f3fe5SMatthew G. Knepley 
6237793f3fe5SMatthew G. Knepley   Output Parameters:
6238793f3fe5SMatthew G. Knepley + pStart - The first point of the given dimension
6239aa049354SPatrick Sanan - pEnd - The first point following points of the given dimension
6240793f3fe5SMatthew G. Knepley 
6241793f3fe5SMatthew G. Knepley   Note:
6242793f3fe5SMatthew G. Knepley   The points are vertices in the Hasse diagram encoding the topology. This is explained in
6243a8d69d7bSBarry Smith   https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme,
6244793f3fe5SMatthew G. Knepley   then the interval is empty.
6245793f3fe5SMatthew G. Knepley 
6246793f3fe5SMatthew G. Knepley   Level: intermediate
6247793f3fe5SMatthew G. Knepley 
6248db781477SPatrick Sanan .seealso: `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
6249793f3fe5SMatthew G. Knepley @*/
6250d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
6251d71ae5a4SJacob Faibussowitsch {
6252793f3fe5SMatthew G. Knepley   PetscInt d;
6253793f3fe5SMatthew G. Knepley 
6254793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
6255793f3fe5SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62569566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &d));
62577a8be351SBarry Smith   PetscCheck((dim >= 0) && (dim <= d), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %" PetscInt_FMT, dim);
6258dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getdimpoints, dim, pStart, pEnd);
6259793f3fe5SMatthew G. Knepley   PetscFunctionReturn(0);
6260793f3fe5SMatthew G. Knepley }
6261793f3fe5SMatthew G. Knepley 
62626636e97aSMatthew G Knepley /*@
6263bb7acecfSBarry Smith   DMGetOutputDM - Retrieve the `DM` associated with the layout for output
6264f4d763aaSMatthew G. Knepley 
62658f700142SStefano Zampini   Collective on dm
62668f700142SStefano Zampini 
6267f4d763aaSMatthew G. Knepley   Input Parameter:
6268bb7acecfSBarry Smith . dm - The original `DM`
6269f4d763aaSMatthew G. Knepley 
6270f4d763aaSMatthew G. Knepley   Output Parameter:
6271bb7acecfSBarry Smith . odm - The `DM` which provides the layout for output
6272f4d763aaSMatthew G. Knepley 
6273f4d763aaSMatthew G. Knepley   Level: intermediate
6274f4d763aaSMatthew G. Knepley 
6275bb7acecfSBarry Smith   Note:
6276bb7acecfSBarry Smith   In some situations the vector obtained with `DMCreateGlobalVector()` excludes points for degrees of freedom that are associated with fixed (Dirichelet) boundary
6277bb7acecfSBarry 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
6278bb7acecfSBarry Smith   locations for those dof so that they can be output to a file or other viewer along with the unconstrained dof.
6279bb7acecfSBarry Smith 
6280bb7acecfSBarry Smith .seealso: `VecView()`, `DMGetGlobalSection()`, `DMCreateGlobalVector()`, `PetscSectionHasConstraints()`, `DMSetGlobalSection()`
6281f4d763aaSMatthew G. Knepley @*/
6282d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
6283d71ae5a4SJacob Faibussowitsch {
6284c26acbdeSMatthew G. Knepley   PetscSection section;
62852d4e4a49SMatthew G. Knepley   PetscBool    hasConstraints, ghasConstraints;
628614f150ffSMatthew G. Knepley 
628714f150ffSMatthew G. Knepley   PetscFunctionBegin;
628814f150ffSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
628914f150ffSMatthew G. Knepley   PetscValidPointer(odm, 2);
62909566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
62919566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
62929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
62932d4e4a49SMatthew G. Knepley   if (!ghasConstraints) {
6294c26acbdeSMatthew G. Knepley     *odm = dm;
6295c26acbdeSMatthew G. Knepley     PetscFunctionReturn(0);
6296c26acbdeSMatthew G. Knepley   }
629714f150ffSMatthew G. Knepley   if (!dm->dmBC) {
6298c26acbdeSMatthew G. Knepley     PetscSection newSection, gsection;
629914f150ffSMatthew G. Knepley     PetscSF      sf;
630014f150ffSMatthew G. Knepley 
63019566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &dm->dmBC));
63029566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dm, dm->dmBC));
63039566063dSJacob Faibussowitsch     PetscCall(PetscSectionClone(section, &newSection));
63049566063dSJacob Faibussowitsch     PetscCall(DMSetLocalSection(dm->dmBC, newSection));
63059566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&newSection));
63069566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm->dmBC, &sf));
63079566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
63089566063dSJacob Faibussowitsch     PetscCall(DMSetGlobalSection(dm->dmBC, gsection));
63099566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&gsection));
631014f150ffSMatthew G. Knepley   }
631114f150ffSMatthew G. Knepley   *odm = dm->dmBC;
631214f150ffSMatthew G. Knepley   PetscFunctionReturn(0);
631314f150ffSMatthew G. Knepley }
6314f4d763aaSMatthew G. Knepley 
6315f4d763aaSMatthew G. Knepley /*@
6316cdb7a50dSMatthew G. Knepley   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
6317f4d763aaSMatthew G. Knepley 
6318f4d763aaSMatthew G. Knepley   Input Parameter:
6319bb7acecfSBarry Smith . dm - The original `DM`
6320f4d763aaSMatthew G. Knepley 
6321cdb7a50dSMatthew G. Knepley   Output Parameters:
6322cdb7a50dSMatthew G. Knepley + num - The output sequence number
6323cdb7a50dSMatthew G. Knepley - val - The output sequence value
6324f4d763aaSMatthew G. Knepley 
6325f4d763aaSMatthew G. Knepley   Level: intermediate
6326f4d763aaSMatthew G. Knepley 
6327bb7acecfSBarry Smith   Note:
6328bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6329bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6330bb7acecfSBarry Smith 
6331bb7acecfSBarry Smith   Developer Note:
6332bb7acecfSBarry Smith   The `DM` serves as a convenient place to store the current iteration value. The iteration is not
6333bb7acecfSBarry Smith   not directly related to the `DM`.
6334f4d763aaSMatthew G. Knepley 
6335db781477SPatrick Sanan .seealso: `VecView()`
6336f4d763aaSMatthew G. Knepley @*/
6337d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
6338d71ae5a4SJacob Faibussowitsch {
6339f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6340f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63419371c9d4SSatish Balay   if (num) {
63429371c9d4SSatish Balay     PetscValidIntPointer(num, 2);
63439371c9d4SSatish Balay     *num = dm->outputSequenceNum;
63449371c9d4SSatish Balay   }
63459371c9d4SSatish Balay   if (val) {
63469371c9d4SSatish Balay     PetscValidRealPointer(val, 3);
63479371c9d4SSatish Balay     *val = dm->outputSequenceVal;
63489371c9d4SSatish Balay   }
6349f4d763aaSMatthew G. Knepley   PetscFunctionReturn(0);
6350f4d763aaSMatthew G. Knepley }
6351f4d763aaSMatthew G. Knepley 
6352f4d763aaSMatthew G. Knepley /*@
6353cdb7a50dSMatthew G. Knepley   DMSetOutputSequenceNumber - Set the sequence number/value for output
6354f4d763aaSMatthew G. Knepley 
6355f4d763aaSMatthew G. Knepley   Input Parameters:
6356bb7acecfSBarry Smith + dm - The original `DM`
6357cdb7a50dSMatthew G. Knepley . num - The output sequence number
6358cdb7a50dSMatthew G. Knepley - val - The output sequence value
6359f4d763aaSMatthew G. Knepley 
6360f4d763aaSMatthew G. Knepley   Level: intermediate
6361f4d763aaSMatthew G. Knepley 
6362bb7acecfSBarry Smith   Note:
6363bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6364bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6365f4d763aaSMatthew G. Knepley 
6366db781477SPatrick Sanan .seealso: `VecView()`
6367f4d763aaSMatthew G. Knepley @*/
6368d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
6369d71ae5a4SJacob Faibussowitsch {
6370f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6371f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6372f4d763aaSMatthew G. Knepley   dm->outputSequenceNum = num;
6373cdb7a50dSMatthew G. Knepley   dm->outputSequenceVal = val;
6374cdb7a50dSMatthew G. Knepley   PetscFunctionReturn(0);
6375cdb7a50dSMatthew G. Knepley }
6376cdb7a50dSMatthew G. Knepley 
6377cdb7a50dSMatthew G. Knepley /*@C
6378bb7acecfSBarry Smith  DMOutputSequenceLoad - Retrieve the sequence value from a `PetscViewer`
6379cdb7a50dSMatthew G. Knepley 
6380cdb7a50dSMatthew G. Knepley   Input Parameters:
6381bb7acecfSBarry Smith + dm   - The original `DM`
6382cdb7a50dSMatthew G. Knepley . name - The sequence name
6383cdb7a50dSMatthew G. Knepley - num  - The output sequence number
6384cdb7a50dSMatthew G. Knepley 
6385cdb7a50dSMatthew G. Knepley   Output Parameter:
6386cdb7a50dSMatthew G. Knepley . val  - The output sequence value
6387cdb7a50dSMatthew G. Knepley 
6388cdb7a50dSMatthew G. Knepley   Level: intermediate
6389cdb7a50dSMatthew G. Knepley 
6390bb7acecfSBarry Smith   Note:
6391bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6392bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6393bb7acecfSBarry Smith 
6394bb7acecfSBarry Smith   Developer Note:
6395bb7acecfSBarry Smith   It is unclear at the user API level why a `DM` is needed as input
6396cdb7a50dSMatthew G. Knepley 
6397db781477SPatrick Sanan .seealso: `DMGetOutputSequenceNumber()`, `DMSetOutputSequenceNumber()`, `VecView()`
6398cdb7a50dSMatthew G. Knepley @*/
6399d71ae5a4SJacob Faibussowitsch PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
6400d71ae5a4SJacob Faibussowitsch {
6401cdb7a50dSMatthew G. Knepley   PetscBool ishdf5;
6402cdb7a50dSMatthew G. Knepley 
6403cdb7a50dSMatthew G. Knepley   PetscFunctionBegin;
6404cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6405cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
6406064a246eSJacob Faibussowitsch   PetscValidRealPointer(val, 5);
64079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6408cdb7a50dSMatthew G. Knepley   if (ishdf5) {
6409cdb7a50dSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6410cdb7a50dSMatthew G. Knepley     PetscScalar value;
6411cdb7a50dSMatthew G. Knepley 
64129566063dSJacob Faibussowitsch     PetscCall(DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer));
64134aeb217fSMatthew G. Knepley     *val = PetscRealPart(value);
6414cdb7a50dSMatthew G. Knepley #endif
6415cdb7a50dSMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
6416f4d763aaSMatthew G. Knepley   PetscFunctionReturn(0);
6417f4d763aaSMatthew G. Knepley }
64188e4ac7eaSMatthew G. Knepley 
64198e4ac7eaSMatthew G. Knepley /*@
6420bb7acecfSBarry Smith   DMGetUseNatural - Get the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
64218e4ac7eaSMatthew G. Knepley 
64228e4ac7eaSMatthew G. Knepley   Not collective
64238e4ac7eaSMatthew G. Knepley 
64248e4ac7eaSMatthew G. Knepley   Input Parameter:
6425bb7acecfSBarry Smith . dm - The `DM`
64268e4ac7eaSMatthew G. Knepley 
64278e4ac7eaSMatthew G. Knepley   Output Parameter:
6428bb7acecfSBarry Smith . useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
64298e4ac7eaSMatthew G. Knepley 
64308e4ac7eaSMatthew G. Knepley   Level: beginner
64318e4ac7eaSMatthew G. Knepley 
6432db781477SPatrick Sanan .seealso: `DMSetUseNatural()`, `DMCreate()`
64338e4ac7eaSMatthew G. Knepley @*/
6434d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
6435d71ae5a4SJacob Faibussowitsch {
64368e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
64378e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6438534a8f05SLisandro Dalcin   PetscValidBoolPointer(useNatural, 2);
64398e4ac7eaSMatthew G. Knepley   *useNatural = dm->useNatural;
64408e4ac7eaSMatthew G. Knepley   PetscFunctionReturn(0);
64418e4ac7eaSMatthew G. Knepley }
64428e4ac7eaSMatthew G. Knepley 
64438e4ac7eaSMatthew G. Knepley /*@
6444bb7acecfSBarry Smith   DMSetUseNatural - Set the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
64458e4ac7eaSMatthew G. Knepley 
64468e4ac7eaSMatthew G. Knepley   Collective on dm
64478e4ac7eaSMatthew G. Knepley 
64488e4ac7eaSMatthew G. Knepley   Input Parameters:
6449bb7acecfSBarry Smith  + dm - The `DM`
6450bb7acecfSBarry Smith - useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
64518e4ac7eaSMatthew G. Knepley 
6452bb7acecfSBarry Smith   Note:
6453bb7acecfSBarry Smith   This also causes the map to be build after `DMCreateSubDM()` and `DMCreateSuperDM()`
64545d3b26e6SMatthew G. Knepley 
64558e4ac7eaSMatthew G. Knepley   Level: beginner
64568e4ac7eaSMatthew G. Knepley 
6457db781477SPatrick Sanan .seealso: `DMGetUseNatural()`, `DMCreate()`, `DMPlexDistribute()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
64588e4ac7eaSMatthew G. Knepley @*/
6459d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
6460d71ae5a4SJacob Faibussowitsch {
64618e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
64628e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64638833efb5SBlaise Bourdin   PetscValidLogicalCollectiveBool(dm, useNatural, 2);
64648e4ac7eaSMatthew G. Knepley   dm->useNatural = useNatural;
64658e4ac7eaSMatthew G. Knepley   PetscFunctionReturn(0);
64668e4ac7eaSMatthew G. Knepley }
6467c58f1c22SToby Isaac 
6468c58f1c22SToby Isaac /*@C
6469bb7acecfSBarry Smith   DMCreateLabel - Create a label of the given name if it does not already exist in the `DM`
6470c58f1c22SToby Isaac 
6471c58f1c22SToby Isaac   Not Collective
6472c58f1c22SToby Isaac 
6473c58f1c22SToby Isaac   Input Parameters:
6474bb7acecfSBarry Smith + dm   - The `DM` object
6475c58f1c22SToby Isaac - name - The label name
6476c58f1c22SToby Isaac 
6477c58f1c22SToby Isaac   Level: intermediate
6478c58f1c22SToby Isaac 
6479db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6480c58f1c22SToby Isaac @*/
6481d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabel(DM dm, const char name[])
6482d71ae5a4SJacob Faibussowitsch {
64835d80c0bfSVaclav Hapla   PetscBool flg;
64845d80c0bfSVaclav Hapla   DMLabel   label;
6485c58f1c22SToby Isaac 
6486c58f1c22SToby Isaac   PetscFunctionBegin;
6487c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6488c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
64899566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
6490c58f1c22SToby Isaac   if (!flg) {
64919566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
64929566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
64939566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
6494c58f1c22SToby Isaac   }
6495c58f1c22SToby Isaac   PetscFunctionReturn(0);
6496c58f1c22SToby Isaac }
6497c58f1c22SToby Isaac 
6498c58f1c22SToby Isaac /*@C
6499bb7acecfSBarry 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.
65000fdc7489SMatthew Knepley 
65010fdc7489SMatthew Knepley   Not Collective
65020fdc7489SMatthew Knepley 
65030fdc7489SMatthew Knepley   Input Parameters:
6504bb7acecfSBarry Smith + dm   - The `DM` object
65050fdc7489SMatthew Knepley . l    - The index for the label
65060fdc7489SMatthew Knepley - name - The label name
65070fdc7489SMatthew Knepley 
65080fdc7489SMatthew Knepley   Level: intermediate
65090fdc7489SMatthew Knepley 
6510db781477SPatrick Sanan .seealso: `DMCreateLabel()`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
65110fdc7489SMatthew Knepley @*/
6512d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[])
6513d71ae5a4SJacob Faibussowitsch {
65140fdc7489SMatthew Knepley   DMLabelLink orig, prev = NULL;
65150fdc7489SMatthew Knepley   DMLabel     label;
65160fdc7489SMatthew Knepley   PetscInt    Nl, m;
65170fdc7489SMatthew Knepley   PetscBool   flg, match;
65180fdc7489SMatthew Knepley   const char *lname;
65190fdc7489SMatthew Knepley 
65200fdc7489SMatthew Knepley   PetscFunctionBegin;
65210fdc7489SMatthew Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6522064a246eSJacob Faibussowitsch   PetscValidCharPointer(name, 3);
65239566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
65240fdc7489SMatthew Knepley   if (!flg) {
65259566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
65269566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
65279566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
65280fdc7489SMatthew Knepley   }
65299566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
653063a3b9bcSJacob Faibussowitsch   PetscCheck(l < Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", l, Nl);
65310fdc7489SMatthew Knepley   for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) {
65329566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)orig->label, &lname));
65339566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &match));
65340fdc7489SMatthew Knepley     if (match) break;
65350fdc7489SMatthew Knepley   }
65360fdc7489SMatthew Knepley   if (m == l) PetscFunctionReturn(0);
65370fdc7489SMatthew Knepley   if (!m) dm->labels = orig->next;
65380fdc7489SMatthew Knepley   else prev->next = orig->next;
65390fdc7489SMatthew Knepley   if (!l) {
65400fdc7489SMatthew Knepley     orig->next = dm->labels;
65410fdc7489SMatthew Knepley     dm->labels = orig;
65420fdc7489SMatthew Knepley   } else {
65439371c9d4SSatish Balay     for (m = 0, prev = dm->labels; m < l - 1; ++m, prev = prev->next)
65449371c9d4SSatish Balay       ;
65450fdc7489SMatthew Knepley     orig->next = prev->next;
65460fdc7489SMatthew Knepley     prev->next = orig;
65470fdc7489SMatthew Knepley   }
65480fdc7489SMatthew Knepley   PetscFunctionReturn(0);
65490fdc7489SMatthew Knepley }
65500fdc7489SMatthew Knepley 
65510fdc7489SMatthew Knepley /*@C
6552bb7acecfSBarry Smith   DMGetLabelValue - Get the value in a `DMLabel` for the given point, with -1 as the default
6553c58f1c22SToby Isaac 
6554c58f1c22SToby Isaac   Not Collective
6555c58f1c22SToby Isaac 
6556c58f1c22SToby Isaac   Input Parameters:
6557bb7acecfSBarry Smith + dm   - The `DM` object
6558c58f1c22SToby Isaac . name - The label name
6559c58f1c22SToby Isaac - point - The mesh point
6560c58f1c22SToby Isaac 
6561c58f1c22SToby Isaac   Output Parameter:
6562c58f1c22SToby Isaac . value - The label value for this point, or -1 if the point is not in the label
6563c58f1c22SToby Isaac 
6564c58f1c22SToby Isaac   Level: beginner
6565c58f1c22SToby Isaac 
6566db781477SPatrick Sanan .seealso: `DMLabelGetValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6567c58f1c22SToby Isaac @*/
6568d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
6569d71ae5a4SJacob Faibussowitsch {
6570c58f1c22SToby Isaac   DMLabel label;
6571c58f1c22SToby Isaac 
6572c58f1c22SToby Isaac   PetscFunctionBegin;
6573c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6574c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
65759566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
65767a8be351SBarry Smith   PetscCheck(label, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
65779566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, point, value));
6578c58f1c22SToby Isaac   PetscFunctionReturn(0);
6579c58f1c22SToby Isaac }
6580c58f1c22SToby Isaac 
6581c58f1c22SToby Isaac /*@C
6582bb7acecfSBarry Smith   DMSetLabelValue - Add a point to a `DMLabel` with given value
6583c58f1c22SToby Isaac 
6584c58f1c22SToby Isaac   Not Collective
6585c58f1c22SToby Isaac 
6586c58f1c22SToby Isaac   Input Parameters:
6587bb7acecfSBarry Smith + dm   - The `DM` object
6588c58f1c22SToby Isaac . name - The label name
6589c58f1c22SToby Isaac . point - The mesh point
6590c58f1c22SToby Isaac - value - The label value for this point
6591c58f1c22SToby Isaac 
6592c58f1c22SToby Isaac   Output Parameter:
6593c58f1c22SToby Isaac 
6594c58f1c22SToby Isaac   Level: beginner
6595c58f1c22SToby Isaac 
6596db781477SPatrick Sanan .seealso: `DMLabelSetValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6597c58f1c22SToby Isaac @*/
6598d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6599d71ae5a4SJacob Faibussowitsch {
6600c58f1c22SToby Isaac   DMLabel label;
6601c58f1c22SToby Isaac 
6602c58f1c22SToby Isaac   PetscFunctionBegin;
6603c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6604c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
66059566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6606c58f1c22SToby Isaac   if (!label) {
66079566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
66089566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
6609c58f1c22SToby Isaac   }
66109566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, point, value));
6611c58f1c22SToby Isaac   PetscFunctionReturn(0);
6612c58f1c22SToby Isaac }
6613c58f1c22SToby Isaac 
6614c58f1c22SToby Isaac /*@C
6615bb7acecfSBarry Smith   DMClearLabelValue - Remove a point from a `DMLabel` with given value
6616c58f1c22SToby Isaac 
6617c58f1c22SToby Isaac   Not Collective
6618c58f1c22SToby Isaac 
6619c58f1c22SToby Isaac   Input Parameters:
6620bb7acecfSBarry Smith + dm   - The `DM` object
6621c58f1c22SToby Isaac . name - The label name
6622c58f1c22SToby Isaac . point - The mesh point
6623c58f1c22SToby Isaac - value - The label value for this point
6624c58f1c22SToby Isaac 
6625c58f1c22SToby Isaac   Level: beginner
6626c58f1c22SToby Isaac 
6627db781477SPatrick Sanan .seealso: `DMLabelClearValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6628c58f1c22SToby Isaac @*/
6629d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6630d71ae5a4SJacob Faibussowitsch {
6631c58f1c22SToby Isaac   DMLabel label;
6632c58f1c22SToby Isaac 
6633c58f1c22SToby Isaac   PetscFunctionBegin;
6634c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6635c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
66369566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6637c58f1c22SToby Isaac   if (!label) PetscFunctionReturn(0);
66389566063dSJacob Faibussowitsch   PetscCall(DMLabelClearValue(label, point, value));
6639c58f1c22SToby Isaac   PetscFunctionReturn(0);
6640c58f1c22SToby Isaac }
6641c58f1c22SToby Isaac 
6642c58f1c22SToby Isaac /*@C
6643bb7acecfSBarry Smith   DMGetLabelSize - Get the value of `DMLabelGetNumValues()` of a `DMLabel` in the `DM`
6644c58f1c22SToby Isaac 
6645c58f1c22SToby Isaac   Not Collective
6646c58f1c22SToby Isaac 
6647c58f1c22SToby Isaac   Input Parameters:
6648bb7acecfSBarry Smith + dm   - The `DM` object
6649c58f1c22SToby Isaac - name - The label name
6650c58f1c22SToby Isaac 
6651c58f1c22SToby Isaac   Output Parameter:
6652c58f1c22SToby Isaac . size - The number of different integer ids, or 0 if the label does not exist
6653c58f1c22SToby Isaac 
6654c58f1c22SToby Isaac   Level: beginner
6655c58f1c22SToby Isaac 
6656bb7acecfSBarry Smith   Developer Note:
6657bb7acecfSBarry Smith   This should be renamed to something like `DMGetLabelNumValues()` or removed.
6658bb7acecfSBarry Smith 
6659bb7acecfSBarry Smith .seealso: `DMLabelGetNumValues()`, `DMSetLabelValue()`, `DMGetLabel()`
6660c58f1c22SToby Isaac @*/
6661d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
6662d71ae5a4SJacob Faibussowitsch {
6663c58f1c22SToby Isaac   DMLabel label;
6664c58f1c22SToby Isaac 
6665c58f1c22SToby Isaac   PetscFunctionBegin;
6666c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6667c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6668534a8f05SLisandro Dalcin   PetscValidIntPointer(size, 3);
66699566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6670c58f1c22SToby Isaac   *size = 0;
6671c58f1c22SToby Isaac   if (!label) PetscFunctionReturn(0);
66729566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, size));
6673c58f1c22SToby Isaac   PetscFunctionReturn(0);
6674c58f1c22SToby Isaac }
6675c58f1c22SToby Isaac 
6676c58f1c22SToby Isaac /*@C
6677bb7acecfSBarry Smith   DMGetLabelIdIS - Get the `DMLabelGetValueIS()` from a `DMLabel` in the `DM`
6678c58f1c22SToby Isaac 
6679c58f1c22SToby Isaac   Not Collective
6680c58f1c22SToby Isaac 
6681c58f1c22SToby Isaac   Input Parameters:
6682bb7acecfSBarry Smith + mesh - The `DM` object
6683c58f1c22SToby Isaac - name - The label name
6684c58f1c22SToby Isaac 
6685c58f1c22SToby Isaac   Output Parameter:
6686c58f1c22SToby Isaac . ids - The integer ids, or NULL if the label does not exist
6687c58f1c22SToby Isaac 
6688c58f1c22SToby Isaac   Level: beginner
6689c58f1c22SToby Isaac 
6690db781477SPatrick Sanan .seealso: `DMLabelGetValueIS()`, `DMGetLabelSize()`
6691c58f1c22SToby Isaac @*/
6692d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
6693d71ae5a4SJacob Faibussowitsch {
6694c58f1c22SToby Isaac   DMLabel label;
6695c58f1c22SToby Isaac 
6696c58f1c22SToby Isaac   PetscFunctionBegin;
6697c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6698c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6699c58f1c22SToby Isaac   PetscValidPointer(ids, 3);
67009566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6701c58f1c22SToby Isaac   *ids = NULL;
6702dab2e251SBlaise Bourdin   if (label) {
67039566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, ids));
6704dab2e251SBlaise Bourdin   } else {
6705dab2e251SBlaise Bourdin     /* returning an empty IS */
67069566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, ids));
6707dab2e251SBlaise Bourdin   }
6708c58f1c22SToby Isaac   PetscFunctionReturn(0);
6709c58f1c22SToby Isaac }
6710c58f1c22SToby Isaac 
6711c58f1c22SToby Isaac /*@C
6712c58f1c22SToby Isaac   DMGetStratumSize - Get the number of points in a label stratum
6713c58f1c22SToby Isaac 
6714c58f1c22SToby Isaac   Not Collective
6715c58f1c22SToby Isaac 
6716c58f1c22SToby Isaac   Input Parameters:
6717bb7acecfSBarry Smith + dm - The `DM` object
6718c58f1c22SToby Isaac . name - The label name
6719c58f1c22SToby Isaac - value - The stratum value
6720c58f1c22SToby Isaac 
6721c58f1c22SToby Isaac   Output Parameter:
6722bb7acecfSBarry Smith . size - The number of points, also called the stratum size
6723c58f1c22SToby Isaac 
6724c58f1c22SToby Isaac   Level: beginner
6725c58f1c22SToby Isaac 
6726db781477SPatrick Sanan .seealso: `DMLabelGetStratumSize()`, `DMGetLabelSize()`, `DMGetLabelIds()`
6727c58f1c22SToby Isaac @*/
6728d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
6729d71ae5a4SJacob Faibussowitsch {
6730c58f1c22SToby Isaac   DMLabel label;
6731c58f1c22SToby Isaac 
6732c58f1c22SToby Isaac   PetscFunctionBegin;
6733c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6734c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6735534a8f05SLisandro Dalcin   PetscValidIntPointer(size, 4);
67369566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6737c58f1c22SToby Isaac   *size = 0;
6738c58f1c22SToby Isaac   if (!label) PetscFunctionReturn(0);
67399566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize(label, value, size));
6740c58f1c22SToby Isaac   PetscFunctionReturn(0);
6741c58f1c22SToby Isaac }
6742c58f1c22SToby Isaac 
6743c58f1c22SToby Isaac /*@C
6744c58f1c22SToby Isaac   DMGetStratumIS - Get the points in a label stratum
6745c58f1c22SToby Isaac 
6746c58f1c22SToby Isaac   Not Collective
6747c58f1c22SToby Isaac 
6748c58f1c22SToby Isaac   Input Parameters:
6749bb7acecfSBarry Smith + dm - The `DM` object
6750c58f1c22SToby Isaac . name - The label name
6751c58f1c22SToby Isaac - value - The stratum value
6752c58f1c22SToby Isaac 
6753c58f1c22SToby Isaac   Output Parameter:
6754c58f1c22SToby Isaac . points - The stratum points, or NULL if the label does not exist or does not have that value
6755c58f1c22SToby Isaac 
6756c58f1c22SToby Isaac   Level: beginner
6757c58f1c22SToby Isaac 
6758db781477SPatrick Sanan .seealso: `DMLabelGetStratumIS()`, `DMGetStratumSize()`
6759c58f1c22SToby Isaac @*/
6760d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
6761d71ae5a4SJacob Faibussowitsch {
6762c58f1c22SToby Isaac   DMLabel label;
6763c58f1c22SToby Isaac 
6764c58f1c22SToby Isaac   PetscFunctionBegin;
6765c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6766c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6767c58f1c22SToby Isaac   PetscValidPointer(points, 4);
67689566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6769c58f1c22SToby Isaac   *points = NULL;
6770c58f1c22SToby Isaac   if (!label) PetscFunctionReturn(0);
67719566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, points));
6772c58f1c22SToby Isaac   PetscFunctionReturn(0);
6773c58f1c22SToby Isaac }
6774c58f1c22SToby Isaac 
67754de306b1SToby Isaac /*@C
67769044fa66SMatthew G. Knepley   DMSetStratumIS - Set the points in a label stratum
67774de306b1SToby Isaac 
67784de306b1SToby Isaac   Not Collective
67794de306b1SToby Isaac 
67804de306b1SToby Isaac   Input Parameters:
6781bb7acecfSBarry Smith + dm - The `DM` object
67824de306b1SToby Isaac . name - The label name
67834de306b1SToby Isaac . value - The stratum value
67844de306b1SToby Isaac - points - The stratum points
67854de306b1SToby Isaac 
67864de306b1SToby Isaac   Level: beginner
67874de306b1SToby Isaac 
6788bb7acecfSBarry Smith .seealso: `DMLabel`, `DMClearLabelStratum()`, `DMLabelClearStratum()`, `DMLabelSetStratumIS()`, `DMGetStratumSize()`
67894de306b1SToby Isaac @*/
6790d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
6791d71ae5a4SJacob Faibussowitsch {
67924de306b1SToby Isaac   DMLabel label;
67934de306b1SToby Isaac 
67944de306b1SToby Isaac   PetscFunctionBegin;
67954de306b1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67964de306b1SToby Isaac   PetscValidCharPointer(name, 2);
67974de306b1SToby Isaac   PetscValidPointer(points, 4);
67989566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
67994de306b1SToby Isaac   if (!label) PetscFunctionReturn(0);
68009566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, points));
68014de306b1SToby Isaac   PetscFunctionReturn(0);
68024de306b1SToby Isaac }
68034de306b1SToby Isaac 
6804c58f1c22SToby Isaac /*@C
6805bb7acecfSBarry Smith   DMClearLabelStratum - Remove all points from a stratum from a `DMLabel`
6806c58f1c22SToby Isaac 
6807c58f1c22SToby Isaac   Not Collective
6808c58f1c22SToby Isaac 
6809c58f1c22SToby Isaac   Input Parameters:
6810bb7acecfSBarry Smith + dm   - The `DM` object
6811c58f1c22SToby Isaac . name - The label name
6812c58f1c22SToby Isaac - value - The label value for this point
6813c58f1c22SToby Isaac 
6814c58f1c22SToby Isaac   Output Parameter:
6815c58f1c22SToby Isaac 
6816c58f1c22SToby Isaac   Level: beginner
6817c58f1c22SToby Isaac 
6818bb7acecfSBarry Smith .seealso: `DMLabel`, `DMLabelClearStratum()`, `DMSetLabelValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6819c58f1c22SToby Isaac @*/
6820d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
6821d71ae5a4SJacob Faibussowitsch {
6822c58f1c22SToby Isaac   DMLabel label;
6823c58f1c22SToby Isaac 
6824c58f1c22SToby Isaac   PetscFunctionBegin;
6825c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6826c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
68279566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6828c58f1c22SToby Isaac   if (!label) PetscFunctionReturn(0);
68299566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
6830c58f1c22SToby Isaac   PetscFunctionReturn(0);
6831c58f1c22SToby Isaac }
6832c58f1c22SToby Isaac 
6833c58f1c22SToby Isaac /*@
6834bb7acecfSBarry Smith   DMGetNumLabels - Return the number of labels defined by on the `DM`
6835c58f1c22SToby Isaac 
6836c58f1c22SToby Isaac   Not Collective
6837c58f1c22SToby Isaac 
6838c58f1c22SToby Isaac   Input Parameter:
6839bb7acecfSBarry Smith . dm   - The `DM` object
6840c58f1c22SToby Isaac 
6841c58f1c22SToby Isaac   Output Parameter:
6842c58f1c22SToby Isaac . numLabels - the number of Labels
6843c58f1c22SToby Isaac 
6844c58f1c22SToby Isaac   Level: intermediate
6845c58f1c22SToby Isaac 
6846bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetLabelByNum()`, `DMGetLabelName()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6847c58f1c22SToby Isaac @*/
6848d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
6849d71ae5a4SJacob Faibussowitsch {
68505d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6851c58f1c22SToby Isaac   PetscInt    n    = 0;
6852c58f1c22SToby Isaac 
6853c58f1c22SToby Isaac   PetscFunctionBegin;
6854c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6855534a8f05SLisandro Dalcin   PetscValidIntPointer(numLabels, 2);
68569371c9d4SSatish Balay   while (next) {
68579371c9d4SSatish Balay     ++n;
68589371c9d4SSatish Balay     next = next->next;
68599371c9d4SSatish Balay   }
6860c58f1c22SToby Isaac   *numLabels = n;
6861c58f1c22SToby Isaac   PetscFunctionReturn(0);
6862c58f1c22SToby Isaac }
6863c58f1c22SToby Isaac 
6864c58f1c22SToby Isaac /*@C
6865c58f1c22SToby Isaac   DMGetLabelName - Return the name of nth label
6866c58f1c22SToby Isaac 
6867c58f1c22SToby Isaac   Not Collective
6868c58f1c22SToby Isaac 
6869c58f1c22SToby Isaac   Input Parameters:
6870bb7acecfSBarry Smith + dm - The `DM` object
6871c58f1c22SToby Isaac - n  - the label number
6872c58f1c22SToby Isaac 
6873c58f1c22SToby Isaac   Output Parameter:
6874c58f1c22SToby Isaac . name - the label name
6875c58f1c22SToby Isaac 
6876c58f1c22SToby Isaac   Level: intermediate
6877c58f1c22SToby Isaac 
6878bb7acecfSBarry Smith   Developer Note:
6879bb7acecfSBarry Smith   Some of the functions that appropriate on labels using their number have the suffix ByNum, others do not.
6880bb7acecfSBarry Smith 
6881bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetLabelByNum()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6882c58f1c22SToby Isaac @*/
6883d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
6884d71ae5a4SJacob Faibussowitsch {
68855d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6886c58f1c22SToby Isaac   PetscInt    l    = 0;
6887c58f1c22SToby Isaac 
6888c58f1c22SToby Isaac   PetscFunctionBegin;
6889c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6890c58f1c22SToby Isaac   PetscValidPointer(name, 3);
6891c58f1c22SToby Isaac   while (next) {
6892c58f1c22SToby Isaac     if (l == n) {
68939566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)next->label, name));
6894c58f1c22SToby Isaac       PetscFunctionReturn(0);
6895c58f1c22SToby Isaac     }
6896c58f1c22SToby Isaac     ++l;
6897c58f1c22SToby Isaac     next = next->next;
6898c58f1c22SToby Isaac   }
689963a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
6900c58f1c22SToby Isaac }
6901c58f1c22SToby Isaac 
6902c58f1c22SToby Isaac /*@C
6903bb7acecfSBarry Smith   DMHasLabel - Determine whether the `DM` has a label of a given name
6904c58f1c22SToby Isaac 
6905c58f1c22SToby Isaac   Not Collective
6906c58f1c22SToby Isaac 
6907c58f1c22SToby Isaac   Input Parameters:
6908bb7acecfSBarry Smith + dm   - The `DM` object
6909c58f1c22SToby Isaac - name - The label name
6910c58f1c22SToby Isaac 
6911c58f1c22SToby Isaac   Output Parameter:
6912bb7acecfSBarry Smith . hasLabel - `PETSC_TRUE` if the label is present
6913c58f1c22SToby Isaac 
6914c58f1c22SToby Isaac   Level: intermediate
6915c58f1c22SToby Isaac 
6916bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetLabel()`, `DMGetLabelByNum()`, `DMCreateLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6917c58f1c22SToby Isaac @*/
6918d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
6919d71ae5a4SJacob Faibussowitsch {
69205d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6921d67d17b1SMatthew G. Knepley   const char *lname;
6922c58f1c22SToby Isaac 
6923c58f1c22SToby Isaac   PetscFunctionBegin;
6924c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6925c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6926534a8f05SLisandro Dalcin   PetscValidBoolPointer(hasLabel, 3);
6927c58f1c22SToby Isaac   *hasLabel = PETSC_FALSE;
6928c58f1c22SToby Isaac   while (next) {
69299566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
69309566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, hasLabel));
6931c58f1c22SToby Isaac     if (*hasLabel) break;
6932c58f1c22SToby Isaac     next = next->next;
6933c58f1c22SToby Isaac   }
6934c58f1c22SToby Isaac   PetscFunctionReturn(0);
6935c58f1c22SToby Isaac }
6936c58f1c22SToby Isaac 
6937c58f1c22SToby Isaac /*@C
6938bb7acecfSBarry Smith   DMGetLabel - Return the label of a given name, or NULL, from a `DM`
6939c58f1c22SToby Isaac 
6940c58f1c22SToby Isaac   Not Collective
6941c58f1c22SToby Isaac 
6942c58f1c22SToby Isaac   Input Parameters:
6943bb7acecfSBarry Smith + dm   - The `DM` object
6944c58f1c22SToby Isaac - name - The label name
6945c58f1c22SToby Isaac 
6946c58f1c22SToby Isaac   Output Parameter:
6947bb7acecfSBarry Smith . label - The `DMLabel`, or NULL if the label is absent
6948c58f1c22SToby Isaac 
6949bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
6950bb7acecfSBarry Smith +   "depth"       - Holds the depth (co-dimension) of each mesh point
6951bb7acecfSBarry Smith .   "celltype"    - Holds the topological type of each cell
6952bb7acecfSBarry Smith .   "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
6953bb7acecfSBarry Smith .   "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
6954bb7acecfSBarry Smith .   "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
6955bb7acecfSBarry Smith -  "Vertex Sets" - Mirrors the vertex sets defined by GMsh
69566d7c9049SMatthew G. Knepley 
6957c58f1c22SToby Isaac   Level: intermediate
6958c58f1c22SToby Isaac 
6959bb7acecfSBarry Smith .seealso: `DMLabel`, `DMHasLabel()`, `DMGetLabelByNum()`, `DMAddLabel()`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
6960c58f1c22SToby Isaac @*/
6961d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
6962d71ae5a4SJacob Faibussowitsch {
69635d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6964c58f1c22SToby Isaac   PetscBool   hasLabel;
6965d67d17b1SMatthew G. Knepley   const char *lname;
6966c58f1c22SToby Isaac 
6967c58f1c22SToby Isaac   PetscFunctionBegin;
6968c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6969c58f1c22SToby Isaac   PetscValidCharPointer(name, 2);
6970c58f1c22SToby Isaac   PetscValidPointer(label, 3);
6971c58f1c22SToby Isaac   *label = NULL;
6972c58f1c22SToby Isaac   while (next) {
69739566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
69749566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
6975c58f1c22SToby Isaac     if (hasLabel) {
6976c58f1c22SToby Isaac       *label = next->label;
6977c58f1c22SToby Isaac       break;
6978c58f1c22SToby Isaac     }
6979c58f1c22SToby Isaac     next = next->next;
6980c58f1c22SToby Isaac   }
6981c58f1c22SToby Isaac   PetscFunctionReturn(0);
6982c58f1c22SToby Isaac }
6983c58f1c22SToby Isaac 
6984c58f1c22SToby Isaac /*@C
6985bb7acecfSBarry Smith   DMGetLabelByNum - Return the nth label on a `DM`
6986c58f1c22SToby Isaac 
6987c58f1c22SToby Isaac   Not Collective
6988c58f1c22SToby Isaac 
6989c58f1c22SToby Isaac   Input Parameters:
6990bb7acecfSBarry Smith + dm - The `DM` object
6991c58f1c22SToby Isaac - n  - the label number
6992c58f1c22SToby Isaac 
6993c58f1c22SToby Isaac   Output Parameter:
6994c58f1c22SToby Isaac . label - the label
6995c58f1c22SToby Isaac 
6996c58f1c22SToby Isaac   Level: intermediate
6997c58f1c22SToby Isaac 
6998bb7acecfSBarry Smith .seealso: `DMLabel`, `DMAddLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6999c58f1c22SToby Isaac @*/
7000d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
7001d71ae5a4SJacob Faibussowitsch {
70025d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7003c58f1c22SToby Isaac   PetscInt    l    = 0;
7004c58f1c22SToby Isaac 
7005c58f1c22SToby Isaac   PetscFunctionBegin;
7006c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7007c58f1c22SToby Isaac   PetscValidPointer(label, 3);
7008c58f1c22SToby Isaac   while (next) {
7009c58f1c22SToby Isaac     if (l == n) {
7010c58f1c22SToby Isaac       *label = next->label;
7011c58f1c22SToby Isaac       PetscFunctionReturn(0);
7012c58f1c22SToby Isaac     }
7013c58f1c22SToby Isaac     ++l;
7014c58f1c22SToby Isaac     next = next->next;
7015c58f1c22SToby Isaac   }
701663a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
7017c58f1c22SToby Isaac }
7018c58f1c22SToby Isaac 
7019c58f1c22SToby Isaac /*@C
7020bb7acecfSBarry Smith   DMAddLabel - Add the label to this `DM`
7021c58f1c22SToby Isaac 
7022c58f1c22SToby Isaac   Not Collective
7023c58f1c22SToby Isaac 
7024c58f1c22SToby Isaac   Input Parameters:
7025bb7acecfSBarry Smith + dm   - The `DM` object
7026bb7acecfSBarry Smith - label - The `DMLabel`
7027c58f1c22SToby Isaac 
7028c58f1c22SToby Isaac   Level: developer
7029c58f1c22SToby Isaac 
7030bb7acecfSBarry Smith .seealso: `DMLabel`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7031c58f1c22SToby Isaac @*/
7032d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddLabel(DM dm, DMLabel label)
7033d71ae5a4SJacob Faibussowitsch {
70345d80c0bfSVaclav Hapla   DMLabelLink l, *p, tmpLabel;
7035c58f1c22SToby Isaac   PetscBool   hasLabel;
7036d67d17b1SMatthew G. Knepley   const char *lname;
70375d80c0bfSVaclav Hapla   PetscBool   flg;
7038c58f1c22SToby Isaac 
7039c58f1c22SToby Isaac   PetscFunctionBegin;
7040c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70419566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
70429566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, lname, &hasLabel));
70437a8be351SBarry Smith   PetscCheck(!hasLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname);
70449566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(1, &tmpLabel));
7045c58f1c22SToby Isaac   tmpLabel->label  = label;
7046c58f1c22SToby Isaac   tmpLabel->output = PETSC_TRUE;
70475d80c0bfSVaclav Hapla   for (p = &dm->labels; (l = *p); p = &l->next) { }
70485d80c0bfSVaclav Hapla   *p = tmpLabel;
70499566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
70509566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "depth", &flg));
70515d80c0bfSVaclav Hapla   if (flg) dm->depthLabel = label;
70529566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "celltype", &flg));
7053ba2698f1SMatthew G. Knepley   if (flg) dm->celltypeLabel = label;
7054c58f1c22SToby Isaac   PetscFunctionReturn(0);
7055c58f1c22SToby Isaac }
7056c58f1c22SToby Isaac 
7057c58f1c22SToby Isaac /*@C
70584a7ee7d0SMatthew G. Knepley   DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present
70594a7ee7d0SMatthew G. Knepley 
70604a7ee7d0SMatthew G. Knepley   Not Collective
70614a7ee7d0SMatthew G. Knepley 
70624a7ee7d0SMatthew G. Knepley   Input Parameters:
7063bb7acecfSBarry Smith + dm    - The `DM` object
7064bb7acecfSBarry Smith - label - The `DMLabel`, having the same name, to substitute
70654a7ee7d0SMatthew G. Knepley 
7066bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
7067bb7acecfSBarry Smith +  "depth"       - Holds the depth (co-dimension) of each mesh point
7068bb7acecfSBarry Smith .  "celltype"    - Holds the topological type of each cell
7069bb7acecfSBarry Smith .  "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
7070bb7acecfSBarry Smith .  "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
7071bb7acecfSBarry Smith .  "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
7072bb7acecfSBarry Smith - "Vertex Sets" - Mirrors the vertex sets defined by GMsh
70734a7ee7d0SMatthew G. Knepley 
70744a7ee7d0SMatthew G. Knepley   Level: intermediate
70754a7ee7d0SMatthew G. Knepley 
7076bb7acecfSBarry Smith .seealso: `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
70774a7ee7d0SMatthew G. Knepley @*/
7078d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabel(DM dm, DMLabel label)
7079d71ae5a4SJacob Faibussowitsch {
70804a7ee7d0SMatthew G. Knepley   DMLabelLink next = dm->labels;
70814a7ee7d0SMatthew G. Knepley   PetscBool   hasLabel, flg;
70824a7ee7d0SMatthew G. Knepley   const char *name, *lname;
70834a7ee7d0SMatthew G. Knepley 
70844a7ee7d0SMatthew G. Knepley   PetscFunctionBegin;
70854a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70864a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
70879566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
70884a7ee7d0SMatthew G. Knepley   while (next) {
70899566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
70909566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
70914a7ee7d0SMatthew G. Knepley     if (hasLabel) {
70929566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)label));
70939566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "depth", &flg));
70944a7ee7d0SMatthew G. Knepley       if (flg) dm->depthLabel = label;
70959566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "celltype", &flg));
70964a7ee7d0SMatthew G. Knepley       if (flg) dm->celltypeLabel = label;
70979566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&next->label));
70984a7ee7d0SMatthew G. Knepley       next->label = label;
70994a7ee7d0SMatthew G. Knepley       break;
71004a7ee7d0SMatthew G. Knepley     }
71014a7ee7d0SMatthew G. Knepley     next = next->next;
71024a7ee7d0SMatthew G. Knepley   }
71034a7ee7d0SMatthew G. Knepley   PetscFunctionReturn(0);
71044a7ee7d0SMatthew G. Knepley }
71054a7ee7d0SMatthew G. Knepley 
71064a7ee7d0SMatthew G. Knepley /*@C
7107bb7acecfSBarry Smith   DMRemoveLabel - Remove the label given by name from this `DM`
7108c58f1c22SToby Isaac 
7109c58f1c22SToby Isaac   Not Collective
7110c58f1c22SToby Isaac 
7111c58f1c22SToby Isaac   Input Parameters:
7112bb7acecfSBarry Smith + dm   - The `DM` object
7113c58f1c22SToby Isaac - name - The label name
7114c58f1c22SToby Isaac 
7115c58f1c22SToby Isaac   Output Parameter:
7116bb7acecfSBarry Smith . label - The `DMLabel`, or NULL if the label is absent. Pass in NULL to call `DMLabelDestroy()` on the label, otherwise the
7117bb7acecfSBarry Smith           caller is responsible for calling `DMLabelDestroy()`.
7118c58f1c22SToby Isaac 
7119c58f1c22SToby Isaac   Level: developer
7120c58f1c22SToby Isaac 
7121bb7acecfSBarry Smith .seealso: `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabelBySelf()`
7122c58f1c22SToby Isaac @*/
7123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
7124d71ae5a4SJacob Faibussowitsch {
712595d578d6SVaclav Hapla   DMLabelLink link, *pnext;
7126c58f1c22SToby Isaac   PetscBool   hasLabel;
7127d67d17b1SMatthew G. Knepley   const char *lname;
7128c58f1c22SToby Isaac 
7129c58f1c22SToby Isaac   PetscFunctionBegin;
7130c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7131e5472504SVaclav Hapla   PetscValidCharPointer(name, 2);
7132e5472504SVaclav Hapla   if (label) {
7133e5472504SVaclav Hapla     PetscValidPointer(label, 3);
7134c58f1c22SToby Isaac     *label = NULL;
7135e5472504SVaclav Hapla   }
71365d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
71379566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)link->label, &lname));
71389566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
7139c58f1c22SToby Isaac     if (hasLabel) {
714095d578d6SVaclav Hapla       *pnext = link->next; /* Remove from list */
71419566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &hasLabel));
714295d578d6SVaclav Hapla       if (hasLabel) dm->depthLabel = NULL;
71439566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &hasLabel));
7144ba2698f1SMatthew G. Knepley       if (hasLabel) dm->celltypeLabel = NULL;
714595d578d6SVaclav Hapla       if (label) *label = link->label;
71469566063dSJacob Faibussowitsch       else PetscCall(DMLabelDestroy(&link->label));
71479566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7148c58f1c22SToby Isaac       break;
7149c58f1c22SToby Isaac     }
7150c58f1c22SToby Isaac   }
7151c58f1c22SToby Isaac   PetscFunctionReturn(0);
7152c58f1c22SToby Isaac }
7153c58f1c22SToby Isaac 
7154306894acSVaclav Hapla /*@
7155bb7acecfSBarry Smith   DMRemoveLabelBySelf - Remove the label from this `DM`
7156306894acSVaclav Hapla 
7157306894acSVaclav Hapla   Not Collective
7158306894acSVaclav Hapla 
7159306894acSVaclav Hapla   Input Parameters:
7160bb7acecfSBarry Smith + dm   - The `DM` object
7161bb7acecfSBarry Smith . label - The `DMLabel` to be removed from the `DM`
7162306894acSVaclav Hapla - failNotFound - Should it fail if the label is not found in the DM?
7163306894acSVaclav Hapla 
7164306894acSVaclav Hapla   Level: developer
7165306894acSVaclav Hapla 
7166bb7acecfSBarry Smith   Note:
7167306894acSVaclav Hapla   Only exactly the same instance is removed if found, name match is ignored.
7168bb7acecfSBarry Smith   If the `DM` has an exclusive reference to the label, the label gets destroyed and
7169306894acSVaclav Hapla   *label nullified.
7170306894acSVaclav Hapla 
7171bb7acecfSBarry Smith .seealso: `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()` `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabel()`
7172306894acSVaclav Hapla @*/
7173d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound)
7174d71ae5a4SJacob Faibussowitsch {
717543e45a93SVaclav Hapla   DMLabelLink link, *pnext;
7176306894acSVaclav Hapla   PetscBool   hasLabel = PETSC_FALSE;
7177306894acSVaclav Hapla 
7178306894acSVaclav Hapla   PetscFunctionBegin;
7179306894acSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7180306894acSVaclav Hapla   PetscValidPointer(label, 2);
7181f39a9ae0SVaclav Hapla   if (!*label && !failNotFound) PetscFunctionReturn(0);
7182306894acSVaclav Hapla   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2);
7183306894acSVaclav Hapla   PetscValidLogicalCollectiveBool(dm, failNotFound, 3);
71845d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
718543e45a93SVaclav Hapla     if (*label == link->label) {
7186306894acSVaclav Hapla       hasLabel = PETSC_TRUE;
718743e45a93SVaclav Hapla       *pnext   = link->next; /* Remove from list */
7188306894acSVaclav Hapla       if (*label == dm->depthLabel) dm->depthLabel = NULL;
7189ba2698f1SMatthew G. Knepley       if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL;
719043e45a93SVaclav Hapla       if (((PetscObject)link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */
71919566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&link->label));
71929566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7193306894acSVaclav Hapla       break;
7194306894acSVaclav Hapla     }
7195306894acSVaclav Hapla   }
71967a8be351SBarry Smith   PetscCheck(hasLabel || !failNotFound, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM");
7197306894acSVaclav Hapla   PetscFunctionReturn(0);
7198306894acSVaclav Hapla }
7199306894acSVaclav Hapla 
7200c58f1c22SToby Isaac /*@C
7201c58f1c22SToby Isaac   DMGetLabelOutput - Get the output flag for a given label
7202c58f1c22SToby Isaac 
7203c58f1c22SToby Isaac   Not Collective
7204c58f1c22SToby Isaac 
7205c58f1c22SToby Isaac   Input Parameters:
7206bb7acecfSBarry Smith + dm   - The `DM` object
7207c58f1c22SToby Isaac - name - The label name
7208c58f1c22SToby Isaac 
7209c58f1c22SToby Isaac   Output Parameter:
7210c58f1c22SToby Isaac . output - The flag for output
7211c58f1c22SToby Isaac 
7212c58f1c22SToby Isaac   Level: developer
7213c58f1c22SToby Isaac 
7214bb7acecfSBarry Smith .seealso: `DMLabel`, `DMSetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7215c58f1c22SToby Isaac @*/
7216d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
7217d71ae5a4SJacob Faibussowitsch {
72185d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7219d67d17b1SMatthew G. Knepley   const char *lname;
7220c58f1c22SToby Isaac 
7221c58f1c22SToby Isaac   PetscFunctionBegin;
7222c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7223dadcf809SJacob Faibussowitsch   PetscValidCharPointer(name, 2);
7224dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(output, 3);
7225c58f1c22SToby Isaac   while (next) {
7226c58f1c22SToby Isaac     PetscBool flg;
7227c58f1c22SToby Isaac 
72289566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
72299566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
72309371c9d4SSatish Balay     if (flg) {
72319371c9d4SSatish Balay       *output = next->output;
72329371c9d4SSatish Balay       PetscFunctionReturn(0);
72339371c9d4SSatish Balay     }
7234c58f1c22SToby Isaac     next = next->next;
7235c58f1c22SToby Isaac   }
723698921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7237c58f1c22SToby Isaac }
7238c58f1c22SToby Isaac 
7239c58f1c22SToby Isaac /*@C
7240bb7acecfSBarry Smith   DMSetLabelOutput - Set if a given label should be saved to a `PetscViewer` in calls to `DMView()`
7241c58f1c22SToby Isaac 
7242c58f1c22SToby Isaac   Not Collective
7243c58f1c22SToby Isaac 
7244c58f1c22SToby Isaac   Input Parameters:
7245bb7acecfSBarry Smith + dm     - The `DM` object
7246c58f1c22SToby Isaac . name   - The label name
7247bb7acecfSBarry Smith - output - `PETSC_TRUE` to save the label to the viewer
7248c58f1c22SToby Isaac 
7249c58f1c22SToby Isaac   Level: developer
7250c58f1c22SToby Isaac 
7251bb7acecfSBarry Smith .seealso: `DMLabel`, `DMGetOutputFlag()`, `DMGetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7252c58f1c22SToby Isaac @*/
7253d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
7254d71ae5a4SJacob Faibussowitsch {
72555d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7256d67d17b1SMatthew G. Knepley   const char *lname;
7257c58f1c22SToby Isaac 
7258c58f1c22SToby Isaac   PetscFunctionBegin;
7259c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7260534a8f05SLisandro Dalcin   PetscValidCharPointer(name, 2);
7261c58f1c22SToby Isaac   while (next) {
7262c58f1c22SToby Isaac     PetscBool flg;
7263c58f1c22SToby Isaac 
72649566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
72659566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
72669371c9d4SSatish Balay     if (flg) {
72679371c9d4SSatish Balay       next->output = output;
72689371c9d4SSatish Balay       PetscFunctionReturn(0);
72699371c9d4SSatish Balay     }
7270c58f1c22SToby Isaac     next = next->next;
7271c58f1c22SToby Isaac   }
727298921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7273c58f1c22SToby Isaac }
7274c58f1c22SToby Isaac 
7275c58f1c22SToby Isaac /*@
7276bb7acecfSBarry Smith   DMCopyLabels - Copy labels from one `DM` mesh to another `DM` with a superset of the points
7277c58f1c22SToby Isaac 
7278d083f849SBarry Smith   Collective on dmA
7279c58f1c22SToby Isaac 
7280d8d19677SJose E. Roman   Input Parameters:
7281bb7acecfSBarry Smith + dmA - The `DM` object with initial labels
7282bb7acecfSBarry Smith . dmB - The `DM` object to which labels are copied
7283bb7acecfSBarry Smith . mode - Copy labels by pointers (`PETSC_OWN_POINTER`) or duplicate them (`PETSC_COPY_VALUES`)
7284bb7acecfSBarry Smith . all  - Copy all labels including "depth", "dim", and "celltype" (`PETSC_TRUE`) which are otherwise ignored (`PETSC_FALSE`)
7285bb7acecfSBarry Smith - emode - How to behave when a `DMLabel` in the source and destination `DM`s with the same name is encountered (see `DMCopyLabelsMode`)
7286c58f1c22SToby Isaac 
7287c58f1c22SToby Isaac   Level: intermediate
7288c58f1c22SToby Isaac 
7289bb7acecfSBarry Smith   Note:
72902cbb9b06SVaclav Hapla   This is typically used when interpolating or otherwise adding to a mesh, or testing.
7291c58f1c22SToby Isaac 
7292bb7acecfSBarry Smith .seealso: `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`
7293c58f1c22SToby Isaac @*/
7294d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all, DMCopyLabelsMode emode)
7295d71ae5a4SJacob Faibussowitsch {
72962cbb9b06SVaclav Hapla   DMLabel     label, labelNew, labelOld;
7297c58f1c22SToby Isaac   const char *name;
7298c58f1c22SToby Isaac   PetscBool   flg;
72995d80c0bfSVaclav Hapla   DMLabelLink link;
7300c58f1c22SToby Isaac 
73015d80c0bfSVaclav Hapla   PetscFunctionBegin;
73025d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
73035d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
73045d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveEnum(dmA, mode, 3);
73055d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveBool(dmA, all, 4);
73067a8be351SBarry Smith   PetscCheck(mode != PETSC_USE_POINTER, PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects");
73075d80c0bfSVaclav Hapla   if (dmA == dmB) PetscFunctionReturn(0);
73085d80c0bfSVaclav Hapla   for (link = dmA->labels; link; link = link->next) {
73095d80c0bfSVaclav Hapla     label = link->label;
73109566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
73115d80c0bfSVaclav Hapla     if (!all) {
73129566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &flg));
7313c58f1c22SToby Isaac       if (flg) continue;
73149566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "dim", &flg));
73157d5acc75SStefano Zampini       if (flg) continue;
73169566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &flg));
7317ba2698f1SMatthew G. Knepley       if (flg) continue;
73185d80c0bfSVaclav Hapla     }
73199566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dmB, name, &labelOld));
73202cbb9b06SVaclav Hapla     if (labelOld) {
73212cbb9b06SVaclav Hapla       switch (emode) {
7322d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_KEEP:
7323d71ae5a4SJacob Faibussowitsch         continue;
7324d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_REPLACE:
7325d71ae5a4SJacob Faibussowitsch         PetscCall(DMRemoveLabelBySelf(dmB, &labelOld, PETSC_TRUE));
7326d71ae5a4SJacob Faibussowitsch         break;
7327d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_FAIL:
7328d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in destination DM", name);
7329d71ae5a4SJacob Faibussowitsch       default:
7330d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Unhandled DMCopyLabelsMode %d", (int)emode);
73312cbb9b06SVaclav Hapla       }
73322cbb9b06SVaclav Hapla     }
73335d80c0bfSVaclav Hapla     if (mode == PETSC_COPY_VALUES) {
73349566063dSJacob Faibussowitsch       PetscCall(DMLabelDuplicate(label, &labelNew));
73355d80c0bfSVaclav Hapla     } else {
73365d80c0bfSVaclav Hapla       labelNew = label;
73375d80c0bfSVaclav Hapla     }
73389566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dmB, labelNew));
73399566063dSJacob Faibussowitsch     if (mode == PETSC_COPY_VALUES) PetscCall(DMLabelDestroy(&labelNew));
7340c58f1c22SToby Isaac   }
7341c58f1c22SToby Isaac   PetscFunctionReturn(0);
7342c58f1c22SToby Isaac }
7343461a15a0SLisandro Dalcin 
7344609dae6eSVaclav Hapla /*@C
7345bb7acecfSBarry Smith   DMCompareLabels - Compare labels of two `DMPLEX` meshes
7346609dae6eSVaclav Hapla 
73475efe38ccSVaclav Hapla   Collective
7348609dae6eSVaclav Hapla 
7349609dae6eSVaclav Hapla   Input Parameters:
7350bb7acecfSBarry Smith + dm0 - First `DM` object
7351bb7acecfSBarry Smith - dm1 - Second `DM` object
7352609dae6eSVaclav Hapla 
7353609dae6eSVaclav Hapla   Output Parameters
73545efe38ccSVaclav Hapla + equal   - (Optional) Flag whether labels of dm0 and dm1 are the same
7355609dae6eSVaclav Hapla - message - (Optional) Message describing the difference, or NULL if there is no difference
7356609dae6eSVaclav Hapla 
7357609dae6eSVaclav Hapla   Level: intermediate
7358609dae6eSVaclav Hapla 
7359609dae6eSVaclav Hapla   Notes:
7360bb7acecfSBarry Smith   The output flag equal will be the same on all processes.
7361bb7acecfSBarry Smith 
7362bb7acecfSBarry Smith   If equal is passed as NULL and difference is found, an error is thrown on all processes.
7363bb7acecfSBarry Smith 
7364bb7acecfSBarry Smith   Make sure to pass equal is NULL on all processes or none of them.
7365609dae6eSVaclav Hapla 
73665efe38ccSVaclav Hapla   The output message is set independently on each rank.
7367bb7acecfSBarry Smith 
7368bb7acecfSBarry Smith   message must be freed with `PetscFree()`
7369bb7acecfSBarry Smith 
7370bb7acecfSBarry Smith   If message is passed as NULL and a difference is found, the difference description is printed to stderr in synchronized manner.
7371bb7acecfSBarry Smith 
7372bb7acecfSBarry Smith   Make sure to pass message as NULL on all processes or no processes.
7373609dae6eSVaclav Hapla 
7374609dae6eSVaclav Hapla   Labels are matched by name. If the number of labels and their names are equal,
7375bb7acecfSBarry Smith   `DMLabelCompare()` is used to compare each pair of labels with the same name.
7376609dae6eSVaclav Hapla 
7377bb7acecfSBarry Smith   Fortran Note:
7378bb7acecfSBarry Smith   This function is not available from Fortran.
7379609dae6eSVaclav Hapla 
7380bb7acecfSBarry Smith .seealso: `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`, `DMLabelCompare()`
7381609dae6eSVaclav Hapla @*/
7382d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompareLabels(DM dm0, DM dm1, PetscBool *equal, char **message)
7383d71ae5a4SJacob Faibussowitsch {
73845efe38ccSVaclav Hapla   PetscInt    n, i;
7385609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
73865efe38ccSVaclav Hapla   PetscBool   eq;
7387609dae6eSVaclav Hapla   MPI_Comm    comm;
73885efe38ccSVaclav Hapla   PetscMPIInt rank;
7389609dae6eSVaclav Hapla 
7390609dae6eSVaclav Hapla   PetscFunctionBegin;
7391609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm0, DM_CLASSID, 1);
7392609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm1, DM_CLASSID, 2);
7393609dae6eSVaclav Hapla   PetscCheckSameComm(dm0, 1, dm1, 2);
73945efe38ccSVaclav Hapla   if (equal) PetscValidBoolPointer(equal, 3);
7395609dae6eSVaclav Hapla   if (message) PetscValidPointer(message, 4);
73969566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm0, &comm));
73979566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
73985efe38ccSVaclav Hapla   {
73995efe38ccSVaclav Hapla     PetscInt n1;
74005efe38ccSVaclav Hapla 
74019566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm0, &n));
74029566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm1, &n1));
74035efe38ccSVaclav Hapla     eq = (PetscBool)(n == n1);
740448a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Number of labels in dm0 = %" PetscInt_FMT " != %" PetscInt_FMT " = Number of labels in dm1", n, n1));
74059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
74065efe38ccSVaclav Hapla     if (!eq) goto finish;
74075efe38ccSVaclav Hapla   }
74085efe38ccSVaclav Hapla   for (i = 0; i < n; i++) {
7409609dae6eSVaclav Hapla     DMLabel     l0, l1;
7410609dae6eSVaclav Hapla     const char *name;
7411609dae6eSVaclav Hapla     char       *msgInner;
7412609dae6eSVaclav Hapla 
7413609dae6eSVaclav Hapla     /* Ignore label order */
74149566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm0, i, &l0));
74159566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)l0, &name));
74169566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm1, name, &l1));
7417609dae6eSVaclav Hapla     if (!l1) {
741863a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Label \"%s\" (#%" PetscInt_FMT " in dm0) not found in dm1", name, i));
74195efe38ccSVaclav Hapla       eq = PETSC_FALSE;
74205efe38ccSVaclav Hapla       break;
7421609dae6eSVaclav Hapla     }
74229566063dSJacob Faibussowitsch     PetscCall(DMLabelCompare(comm, l0, l1, &eq, &msgInner));
74239566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(msg, msgInner, sizeof(msg)));
74249566063dSJacob Faibussowitsch     PetscCall(PetscFree(msgInner));
74255efe38ccSVaclav Hapla     if (!eq) break;
7426609dae6eSVaclav Hapla   }
74279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
7428609dae6eSVaclav Hapla finish:
74295efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
7430609dae6eSVaclav Hapla   if (message) {
7431609dae6eSVaclav Hapla     *message = NULL;
743248a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
74335efe38ccSVaclav Hapla   } else {
743448a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
74359566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
74365efe38ccSVaclav Hapla   }
74375efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
74385efe38ccSVaclav Hapla   if (equal) *equal = eq;
74397a8be351SBarry Smith   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels are not the same in dm0 and dm1");
7440609dae6eSVaclav Hapla   PetscFunctionReturn(0);
7441609dae6eSVaclav Hapla }
7442609dae6eSVaclav Hapla 
7443d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value)
7444d71ae5a4SJacob Faibussowitsch {
7445461a15a0SLisandro Dalcin   PetscFunctionBegin;
7446461a15a0SLisandro Dalcin   PetscValidPointer(label, 2);
7447461a15a0SLisandro Dalcin   if (!*label) {
74489566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
74499566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, label));
7450461a15a0SLisandro Dalcin   }
74519566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(*label, point, value));
7452461a15a0SLisandro Dalcin   PetscFunctionReturn(0);
7453461a15a0SLisandro Dalcin }
7454461a15a0SLisandro Dalcin 
74550fdc7489SMatthew Knepley /*
74560fdc7489SMatthew Knepley   Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would
74570fdc7489SMatthew Knepley   like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every
74580fdc7489SMatthew Knepley   (label, id) pair in the DM.
74590fdc7489SMatthew Knepley 
74600fdc7489SMatthew Knepley   However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to
74610fdc7489SMatthew Knepley   each label.
74620fdc7489SMatthew Knepley */
7463d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal)
7464d71ae5a4SJacob Faibussowitsch {
74650fdc7489SMatthew Knepley   DMUniversalLabel ul;
74660fdc7489SMatthew Knepley   PetscBool       *active;
74670fdc7489SMatthew Knepley   PetscInt         pStart, pEnd, p, Nl, l, m;
74680fdc7489SMatthew Knepley 
74690fdc7489SMatthew Knepley   PetscFunctionBegin;
74709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, &ul));
74719566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label));
74729566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
74739566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Nl, &active));
74740fdc7489SMatthew Knepley   ul->Nl = 0;
74750fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
74760fdc7489SMatthew Knepley     PetscBool   isdepth, iscelltype;
74770fdc7489SMatthew Knepley     const char *name;
74780fdc7489SMatthew Knepley 
74799566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
74809566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "depth", 6, &isdepth));
74819566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "celltype", 9, &iscelltype));
74820fdc7489SMatthew Knepley     active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE;
74830fdc7489SMatthew Knepley     if (active[l]) ++ul->Nl;
74840fdc7489SMatthew Knepley   }
74859566063dSJacob 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));
74860fdc7489SMatthew Knepley   ul->Nv = 0;
74870fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
74880fdc7489SMatthew Knepley     DMLabel     label;
74890fdc7489SMatthew Knepley     PetscInt    nv;
74900fdc7489SMatthew Knepley     const char *name;
74910fdc7489SMatthew Knepley 
74920fdc7489SMatthew Knepley     if (!active[l]) continue;
74939566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
74949566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
74959566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
74969566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &ul->names[m]));
74970fdc7489SMatthew Knepley     ul->indices[m] = l;
74980fdc7489SMatthew Knepley     ul->Nv += nv;
74990fdc7489SMatthew Knepley     ul->offsets[m + 1] = nv;
75000fdc7489SMatthew Knepley     ul->bits[m + 1]    = PetscCeilReal(PetscLog2Real(nv + 1));
75010fdc7489SMatthew Knepley     ++m;
75020fdc7489SMatthew Knepley   }
75030fdc7489SMatthew Knepley   for (l = 1; l <= ul->Nl; ++l) {
75040fdc7489SMatthew Knepley     ul->offsets[l] = ul->offsets[l - 1] + ul->offsets[l];
75050fdc7489SMatthew Knepley     ul->bits[l]    = ul->bits[l - 1] + ul->bits[l];
75060fdc7489SMatthew Knepley   }
75070fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
75080fdc7489SMatthew Knepley     PetscInt b;
75090fdc7489SMatthew Knepley 
75100fdc7489SMatthew Knepley     ul->masks[l] = 0;
75110fdc7489SMatthew Knepley     for (b = ul->bits[l]; b < ul->bits[l + 1]; ++b) ul->masks[l] |= 1 << b;
75120fdc7489SMatthew Knepley   }
75139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ul->Nv, &ul->values));
75140fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
75150fdc7489SMatthew Knepley     DMLabel         label;
75160fdc7489SMatthew Knepley     IS              valueIS;
75170fdc7489SMatthew Knepley     const PetscInt *varr;
75180fdc7489SMatthew Knepley     PetscInt        nv, v;
75190fdc7489SMatthew Knepley 
75200fdc7489SMatthew Knepley     if (!active[l]) continue;
75219566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
75229566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
75239566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, &valueIS));
75249566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(valueIS, &varr));
7525ad540459SPierre Jolivet     for (v = 0; v < nv; ++v) ul->values[ul->offsets[m] + v] = varr[v];
75269566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(valueIS, &varr));
75279566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&valueIS));
75289566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(nv, &ul->values[ul->offsets[m]]));
75290fdc7489SMatthew Knepley     ++m;
75300fdc7489SMatthew Knepley   }
75319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
75320fdc7489SMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
75330fdc7489SMatthew Knepley     PetscInt  uval   = 0;
75340fdc7489SMatthew Knepley     PetscBool marked = PETSC_FALSE;
75350fdc7489SMatthew Knepley 
75360fdc7489SMatthew Knepley     for (l = 0, m = 0; l < Nl; ++l) {
75370fdc7489SMatthew Knepley       DMLabel  label;
75380649b39aSStefano Zampini       PetscInt val, defval, loc, nv;
75390fdc7489SMatthew Knepley 
75400fdc7489SMatthew Knepley       if (!active[l]) continue;
75419566063dSJacob Faibussowitsch       PetscCall(DMGetLabelByNum(dm, l, &label));
75429566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, p, &val));
75439566063dSJacob Faibussowitsch       PetscCall(DMLabelGetDefaultValue(label, &defval));
75449371c9d4SSatish Balay       if (val == defval) {
75459371c9d4SSatish Balay         ++m;
75469371c9d4SSatish Balay         continue;
75479371c9d4SSatish Balay       }
75480649b39aSStefano Zampini       nv     = ul->offsets[m + 1] - ul->offsets[m];
75490fdc7489SMatthew Knepley       marked = PETSC_TRUE;
75509566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc));
755163a3b9bcSJacob Faibussowitsch       PetscCheck(loc >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %" PetscInt_FMT " not found in compression array", val);
75520fdc7489SMatthew Knepley       uval += (loc + 1) << ul->bits[m];
75530fdc7489SMatthew Knepley       ++m;
75540fdc7489SMatthew Knepley     }
75559566063dSJacob Faibussowitsch     if (marked) PetscCall(DMLabelSetValue(ul->label, p, uval));
75560fdc7489SMatthew Knepley   }
75579566063dSJacob Faibussowitsch   PetscCall(PetscFree(active));
75580fdc7489SMatthew Knepley   *universal = ul;
75590fdc7489SMatthew Knepley   PetscFunctionReturn(0);
75600fdc7489SMatthew Knepley }
75610fdc7489SMatthew Knepley 
7562d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal)
7563d71ae5a4SJacob Faibussowitsch {
75640fdc7489SMatthew Knepley   PetscInt l;
75650fdc7489SMatthew Knepley 
75660fdc7489SMatthew Knepley   PetscFunctionBegin;
75679566063dSJacob Faibussowitsch   for (l = 0; l < (*universal)->Nl; ++l) PetscCall(PetscFree((*universal)->names[l]));
75689566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&(*universal)->label));
75699566063dSJacob Faibussowitsch   PetscCall(PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks));
75709566063dSJacob Faibussowitsch   PetscCall(PetscFree((*universal)->values));
75719566063dSJacob Faibussowitsch   PetscCall(PetscFree(*universal));
75720fdc7489SMatthew Knepley   *universal = NULL;
75730fdc7489SMatthew Knepley   PetscFunctionReturn(0);
75740fdc7489SMatthew Knepley }
75750fdc7489SMatthew Knepley 
7576d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel)
7577d71ae5a4SJacob Faibussowitsch {
75780fdc7489SMatthew Knepley   PetscFunctionBegin;
75790fdc7489SMatthew Knepley   PetscValidPointer(ulabel, 2);
75800fdc7489SMatthew Knepley   *ulabel = ul->label;
75810fdc7489SMatthew Knepley   PetscFunctionReturn(0);
75820fdc7489SMatthew Knepley }
75830fdc7489SMatthew Knepley 
7584d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm)
7585d71ae5a4SJacob Faibussowitsch {
75860fdc7489SMatthew Knepley   PetscInt Nl = ul->Nl, l;
75870fdc7489SMatthew Knepley 
75880fdc7489SMatthew Knepley   PetscFunctionBegin;
7589064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 3);
75900fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
75919566063dSJacob Faibussowitsch     if (preserveOrder) PetscCall(DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]));
75929566063dSJacob Faibussowitsch     else PetscCall(DMCreateLabel(dm, ul->names[l]));
75930fdc7489SMatthew Knepley   }
75940fdc7489SMatthew Knepley   if (preserveOrder) {
75950fdc7489SMatthew Knepley     for (l = 0; l < ul->Nl; ++l) {
75960fdc7489SMatthew Knepley       const char *name;
75970fdc7489SMatthew Knepley       PetscBool   match;
75980fdc7489SMatthew Knepley 
75999566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, ul->indices[l], &name));
76009566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, ul->names[l], &match));
760163a3b9bcSJacob 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]);
76020fdc7489SMatthew Knepley     }
76030fdc7489SMatthew Knepley   }
76040fdc7489SMatthew Knepley   PetscFunctionReturn(0);
76050fdc7489SMatthew Knepley }
76060fdc7489SMatthew Knepley 
7607d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value)
7608d71ae5a4SJacob Faibussowitsch {
76090fdc7489SMatthew Knepley   PetscInt l;
76100fdc7489SMatthew Knepley 
76110fdc7489SMatthew Knepley   PetscFunctionBegin;
76120fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
76130fdc7489SMatthew Knepley     DMLabel  label;
76140fdc7489SMatthew Knepley     PetscInt lval = (value & ul->masks[l]) >> ul->bits[l];
76150fdc7489SMatthew Knepley 
76160fdc7489SMatthew Knepley     if (lval) {
76179566063dSJacob Faibussowitsch       if (useIndex) PetscCall(DMGetLabelByNum(dm, ul->indices[l], &label));
76189566063dSJacob Faibussowitsch       else PetscCall(DMGetLabel(dm, ul->names[l], &label));
76199566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(label, p, ul->values[ul->offsets[l] + lval - 1]));
76200fdc7489SMatthew Knepley     }
76210fdc7489SMatthew Knepley   }
76220fdc7489SMatthew Knepley   PetscFunctionReturn(0);
76230fdc7489SMatthew Knepley }
7624a8fb8f29SToby Isaac 
7625a8fb8f29SToby Isaac /*@
7626bb7acecfSBarry Smith   DMGetCoarseDM - Get the coarse `DM`from which this `DM` was obtained by refinement
7627bb7acecfSBarry Smith 
7628bb7acecfSBarry Smith   Not collective
7629a8fb8f29SToby Isaac 
7630a8fb8f29SToby Isaac   Input Parameter:
7631bb7acecfSBarry Smith . dm - The `DM` object
7632a8fb8f29SToby Isaac 
7633a8fb8f29SToby Isaac   Output Parameter:
7634bb7acecfSBarry Smith . cdm - The coarse `DM`
7635a8fb8f29SToby Isaac 
7636a8fb8f29SToby Isaac   Level: intermediate
7637a8fb8f29SToby Isaac 
7638bb7acecfSBarry Smith .seealso: `DMSetCoarseDM()`, `DMCoarsen()`
7639a8fb8f29SToby Isaac @*/
7640d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
7641d71ae5a4SJacob Faibussowitsch {
7642a8fb8f29SToby Isaac   PetscFunctionBegin;
7643a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7644a8fb8f29SToby Isaac   PetscValidPointer(cdm, 2);
7645a8fb8f29SToby Isaac   *cdm = dm->coarseMesh;
7646a8fb8f29SToby Isaac   PetscFunctionReturn(0);
7647a8fb8f29SToby Isaac }
7648a8fb8f29SToby Isaac 
7649a8fb8f29SToby Isaac /*@
7650bb7acecfSBarry Smith   DMSetCoarseDM - Set the coarse `DM` from which this `DM` was obtained by refinement
7651a8fb8f29SToby Isaac 
7652a8fb8f29SToby Isaac   Input Parameters:
7653bb7acecfSBarry Smith + dm - The `DM` object
7654bb7acecfSBarry Smith - cdm - The coarse `DM`
7655a8fb8f29SToby Isaac 
7656a8fb8f29SToby Isaac   Level: intermediate
7657a8fb8f29SToby Isaac 
7658bb7acecfSBarry Smith   Note:
7659bb7acecfSBarry Smith   Normally this is set automatically by `DMRefine()`
7660bb7acecfSBarry Smith 
7661bb7acecfSBarry Smith .seealso: `DMGetCoarseDM()`, `DMCoarsen()`, `DMSetRefine()`, `DMSetFineDM()`
7662a8fb8f29SToby Isaac @*/
7663d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
7664d71ae5a4SJacob Faibussowitsch {
7665a8fb8f29SToby Isaac   PetscFunctionBegin;
7666a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7667a8fb8f29SToby Isaac   if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
766889d734beSBarry Smith   if (dm == cdm) cdm = NULL;
76699566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)cdm));
76709566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->coarseMesh));
7671a8fb8f29SToby Isaac   dm->coarseMesh = cdm;
7672a8fb8f29SToby Isaac   PetscFunctionReturn(0);
7673a8fb8f29SToby Isaac }
7674a8fb8f29SToby Isaac 
767588bdff64SToby Isaac /*@
7676bb7acecfSBarry Smith   DMGetFineDM - Get the fine mesh from which this `DM` was obtained by coarsening
767788bdff64SToby Isaac 
767888bdff64SToby Isaac   Input Parameter:
7679bb7acecfSBarry Smith . dm - The `DM` object
768088bdff64SToby Isaac 
768188bdff64SToby Isaac   Output Parameter:
7682bb7acecfSBarry Smith . fdm - The fine `DM`
768388bdff64SToby Isaac 
768488bdff64SToby Isaac   Level: intermediate
768588bdff64SToby Isaac 
7686bb7acecfSBarry Smith .seealso: `DMSetFineDM()`, `DMCoarsen()`, `DMRefine()`
768788bdff64SToby Isaac @*/
7688d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
7689d71ae5a4SJacob Faibussowitsch {
769088bdff64SToby Isaac   PetscFunctionBegin;
769188bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
769288bdff64SToby Isaac   PetscValidPointer(fdm, 2);
769388bdff64SToby Isaac   *fdm = dm->fineMesh;
769488bdff64SToby Isaac   PetscFunctionReturn(0);
769588bdff64SToby Isaac }
769688bdff64SToby Isaac 
769788bdff64SToby Isaac /*@
7698bb7acecfSBarry Smith   DMSetFineDM - Set the fine mesh from which this was obtained by coarsening
769988bdff64SToby Isaac 
770088bdff64SToby Isaac   Input Parameters:
7701bb7acecfSBarry Smith + dm - The `DM` object
7702bb7acecfSBarry Smith - fdm - The fine `DM`
770388bdff64SToby Isaac 
7704bb7acecfSBarry Smith   Level: developer
770588bdff64SToby Isaac 
7706bb7acecfSBarry Smith   Note:
7707bb7acecfSBarry Smith   Normally this is set automatically by `DMCoarsen()`
7708bb7acecfSBarry Smith 
7709bb7acecfSBarry Smith .seealso: `DMGetFineDM()`, `DMCoarsen()`, `DMRefine()`
771088bdff64SToby Isaac @*/
7711d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFineDM(DM dm, DM fdm)
7712d71ae5a4SJacob Faibussowitsch {
771388bdff64SToby Isaac   PetscFunctionBegin;
771488bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
771588bdff64SToby Isaac   if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2);
771689d734beSBarry Smith   if (dm == fdm) fdm = NULL;
77179566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fdm));
77189566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->fineMesh));
771988bdff64SToby Isaac   dm->fineMesh = fdm;
772088bdff64SToby Isaac   PetscFunctionReturn(0);
772188bdff64SToby Isaac }
772288bdff64SToby Isaac 
7723a6ba4734SToby Isaac /*@C
7724bb7acecfSBarry Smith   DMAddBoundary - Add a boundary condition to a model represented by a `DM`
7725a6ba4734SToby Isaac 
7726783e2ec8SMatthew G. Knepley   Collective on dm
7727783e2ec8SMatthew G. Knepley 
7728a6ba4734SToby Isaac   Input Parameters:
7729bb7acecfSBarry Smith + dm       - The `DM`, with a `PetscDS` that matches the problem being constrained
7730bb7acecfSBarry Smith . type     - The type of condition, e.g. `DM_BC_ESSENTIAL_ANALYTIC`, `DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
7731a6ba4734SToby Isaac . name     - The BC name
773245480ffeSMatthew G. Knepley . label    - The label defining constrained points
7733bb7acecfSBarry Smith . Nv       - The number of `DMLabel` values for constrained points
773445480ffeSMatthew G. Knepley . values   - An array of values for constrained points
7735a6ba4734SToby Isaac . field    - The field to constrain
773645480ffeSMatthew G. Knepley . Nc       - The number of constrained field components (0 will constrain all fields)
7737a6ba4734SToby Isaac . comps    - An array of constrained component numbers
7738a6ba4734SToby Isaac . bcFunc   - A pointwise function giving boundary values
773956cf3b9cSMatthew G. Knepley . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL
7740a6ba4734SToby Isaac - ctx      - An optional user context for bcFunc
7741a6ba4734SToby Isaac 
774245480ffeSMatthew G. Knepley   Output Parameter:
774345480ffeSMatthew G. Knepley . bd          - (Optional) Boundary number
774445480ffeSMatthew G. Knepley 
7745a6ba4734SToby Isaac   Options Database Keys:
7746a6ba4734SToby Isaac + -bc_<boundary name> <num> - Overrides the boundary ids
7747a6ba4734SToby Isaac - -bc_<boundary name>_comp <num> - Overrides the boundary components
7748a6ba4734SToby Isaac 
7749bb7acecfSBarry Smith   Notes:
7750bb7acecfSBarry 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:
775156cf3b9cSMatthew G. Knepley 
775256cf3b9cSMatthew G. Knepley $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
775356cf3b9cSMatthew G. Knepley 
7754bb7acecfSBarry Smith   If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is:
775556cf3b9cSMatthew G. Knepley 
775656cf3b9cSMatthew G. Knepley $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
775756cf3b9cSMatthew G. Knepley $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
775856cf3b9cSMatthew G. Knepley $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
775956cf3b9cSMatthew G. Knepley $        PetscReal time, const PetscReal x[], PetscScalar bcval[])
776056cf3b9cSMatthew G. Knepley 
776156cf3b9cSMatthew G. Knepley + dim - the spatial dimension
776256cf3b9cSMatthew G. Knepley . Nf - the number of fields
776356cf3b9cSMatthew G. Knepley . uOff - the offset into u[] and u_t[] for each field
776456cf3b9cSMatthew G. Knepley . uOff_x - the offset into u_x[] for each field
776556cf3b9cSMatthew G. Knepley . u - each field evaluated at the current point
776656cf3b9cSMatthew G. Knepley . u_t - the time derivative of each field evaluated at the current point
776756cf3b9cSMatthew G. Knepley . u_x - the gradient of each field evaluated at the current point
776856cf3b9cSMatthew G. Knepley . aOff - the offset into a[] and a_t[] for each auxiliary field
776956cf3b9cSMatthew G. Knepley . aOff_x - the offset into a_x[] for each auxiliary field
777056cf3b9cSMatthew G. Knepley . a - each auxiliary field evaluated at the current point
777156cf3b9cSMatthew G. Knepley . a_t - the time derivative of each auxiliary field evaluated at the current point
777256cf3b9cSMatthew G. Knepley . a_x - the gradient of auxiliary each field evaluated at the current point
777356cf3b9cSMatthew G. Knepley . t - current time
777456cf3b9cSMatthew G. Knepley . x - coordinates of the current point
777556cf3b9cSMatthew G. Knepley . numConstants - number of constant parameters
777656cf3b9cSMatthew G. Knepley . constants - constant parameters
777756cf3b9cSMatthew G. Knepley - bcval - output values at the current point
777856cf3b9cSMatthew G. Knepley 
7779ed808b8fSJed Brown   Level: intermediate
7780a6ba4734SToby Isaac 
7781db781477SPatrick Sanan .seealso: `DSGetBoundary()`, `PetscDSAddBoundary()`
7782a6ba4734SToby Isaac @*/
7783d71ae5a4SJacob 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)
7784d71ae5a4SJacob Faibussowitsch {
7785e5e52638SMatthew G. Knepley   PetscDS ds;
7786a6ba4734SToby Isaac 
7787a6ba4734SToby Isaac   PetscFunctionBegin;
7788a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7789783e2ec8SMatthew G. Knepley   PetscValidLogicalCollectiveEnum(dm, type, 2);
779045480ffeSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
779145480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nv, 5);
779245480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, field, 7);
779345480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 8);
779401a5d20dSJed Brown   PetscCheck(!dm->localSection, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot add boundary to DM after creating local section");
77959566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
7796799db056SMatthew G. Knepley   /* Complete label */
7797799db056SMatthew G. Knepley   if (label) {
7798799db056SMatthew G. Knepley     PetscObject  obj;
7799799db056SMatthew G. Knepley     PetscClassId id;
7800799db056SMatthew G. Knepley 
7801799db056SMatthew G. Knepley     PetscCall(DMGetField(dm, field, NULL, &obj));
7802799db056SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
7803799db056SMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
7804799db056SMatthew G. Knepley       DM plex;
7805799db056SMatthew G. Knepley 
7806799db056SMatthew G. Knepley       PetscCall(DMConvert(dm, DMPLEX, &plex));
7807799db056SMatthew G. Knepley       if (plex) PetscCall(DMPlexLabelComplete(plex, label));
7808799db056SMatthew G. Knepley       PetscCall(DMDestroy(&plex));
7809799db056SMatthew G. Knepley     }
7810799db056SMatthew G. Knepley   }
78119566063dSJacob Faibussowitsch   PetscCall(PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd));
7812a6ba4734SToby Isaac   PetscFunctionReturn(0);
7813a6ba4734SToby Isaac }
7814a6ba4734SToby Isaac 
781545480ffeSMatthew G. Knepley /* TODO Remove this since now the structures are the same */
7816d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPopulateBoundary(DM dm)
7817d71ae5a4SJacob Faibussowitsch {
7818e5e52638SMatthew G. Knepley   PetscDS     ds;
7819dff059c6SToby Isaac   DMBoundary *lastnext;
7820e6f8dbb6SToby Isaac   DSBoundary  dsbound;
7821e6f8dbb6SToby Isaac 
7822e6f8dbb6SToby Isaac   PetscFunctionBegin;
78239566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
7824e5e52638SMatthew G. Knepley   dsbound = ds->boundary;
782547a1f5adSToby Isaac   if (dm->boundary) {
782647a1f5adSToby Isaac     DMBoundary next = dm->boundary;
782747a1f5adSToby Isaac 
782847a1f5adSToby Isaac     /* quick check to see if the PetscDS has changed */
782947a1f5adSToby Isaac     if (next->dsboundary == dsbound) PetscFunctionReturn(0);
783047a1f5adSToby Isaac     /* the PetscDS has changed: tear down and rebuild */
783147a1f5adSToby Isaac     while (next) {
783247a1f5adSToby Isaac       DMBoundary b = next;
783347a1f5adSToby Isaac 
783447a1f5adSToby Isaac       next = b->next;
78359566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
7836a6ba4734SToby Isaac     }
783747a1f5adSToby Isaac     dm->boundary = NULL;
7838a6ba4734SToby Isaac   }
783947a1f5adSToby Isaac 
7840dff059c6SToby Isaac   lastnext = &(dm->boundary);
7841e6f8dbb6SToby Isaac   while (dsbound) {
7842e6f8dbb6SToby Isaac     DMBoundary dmbound;
7843e6f8dbb6SToby Isaac 
78449566063dSJacob Faibussowitsch     PetscCall(PetscNew(&dmbound));
7845e6f8dbb6SToby Isaac     dmbound->dsboundary = dsbound;
784645480ffeSMatthew G. Knepley     dmbound->label      = dsbound->label;
784747a1f5adSToby Isaac     /* push on the back instead of the front so that it is in the same order as in the PetscDS */
7848dff059c6SToby Isaac     *lastnext = dmbound;
7849dff059c6SToby Isaac     lastnext  = &(dmbound->next);
7850dff059c6SToby Isaac     dsbound   = dsbound->next;
7851a6ba4734SToby Isaac   }
7852a6ba4734SToby Isaac   PetscFunctionReturn(0);
7853a6ba4734SToby Isaac }
7854a6ba4734SToby Isaac 
7855bb7acecfSBarry Smith /* TODO: missing manual page */
7856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
7857d71ae5a4SJacob Faibussowitsch {
7858b95f2879SToby Isaac   DMBoundary b;
7859a6ba4734SToby Isaac 
7860a6ba4734SToby Isaac   PetscFunctionBegin;
7861a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7862534a8f05SLisandro Dalcin   PetscValidBoolPointer(isBd, 3);
7863a6ba4734SToby Isaac   *isBd = PETSC_FALSE;
78649566063dSJacob Faibussowitsch   PetscCall(DMPopulateBoundary(dm));
7865b95f2879SToby Isaac   b = dm->boundary;
7866a6ba4734SToby Isaac   while (b && !(*isBd)) {
7867e6f8dbb6SToby Isaac     DMLabel    label = b->label;
7868e6f8dbb6SToby Isaac     DSBoundary dsb   = b->dsboundary;
7869a6ba4734SToby Isaac     PetscInt   i;
7870a6ba4734SToby Isaac 
787145480ffeSMatthew G. Knepley     if (label) {
78729566063dSJacob Faibussowitsch       for (i = 0; i < dsb->Nv && !(*isBd); ++i) PetscCall(DMLabelStratumHasPoint(label, dsb->values[i], point, isBd));
7873a6ba4734SToby Isaac     }
7874a6ba4734SToby Isaac     b = b->next;
7875a6ba4734SToby Isaac   }
7876a6ba4734SToby Isaac   PetscFunctionReturn(0);
7877a6ba4734SToby Isaac }
78784d6f44ffSToby Isaac 
78794d6f44ffSToby Isaac /*@C
7880bb7acecfSBarry Smith   DMProjectFunction - This projects the given function into the function space provided by a `DM`, putting the coefficients in a global vector.
7881a6e0b375SMatthew G. Knepley 
7882bb7acecfSBarry Smith   Collective on dm
78834d6f44ffSToby Isaac 
78844d6f44ffSToby Isaac   Input Parameters:
7885bb7acecfSBarry Smith + dm      - The `DM`
78860709b2feSToby Isaac . time    - The time
78874d6f44ffSToby Isaac . funcs   - The coordinate functions to evaluate, one per field
78884d6f44ffSToby Isaac . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
78894d6f44ffSToby Isaac - mode    - The insertion mode for values
78904d6f44ffSToby Isaac 
78914d6f44ffSToby Isaac   Output Parameter:
78924d6f44ffSToby Isaac . X - vector
78934d6f44ffSToby Isaac 
78944d6f44ffSToby Isaac    Calling sequence of func:
789577b739a6SMatthew Knepley $    func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
78964d6f44ffSToby Isaac 
78974d6f44ffSToby Isaac +  dim - The spatial dimension
78988ec8862eSJed Brown .  time - The time at which to sample
78994d6f44ffSToby Isaac .  x   - The coordinates
790077b739a6SMatthew Knepley .  Nc  - The number of components
79014d6f44ffSToby Isaac .  u   - The output field values
79024d6f44ffSToby Isaac -  ctx - optional user-defined function context
79034d6f44ffSToby Isaac 
79044d6f44ffSToby Isaac   Level: developer
79054d6f44ffSToby Isaac 
7906bb7acecfSBarry Smith   Developer Notes:
7907bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
7908bb7acecfSBarry Smith 
7909bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
7910bb7acecfSBarry Smith 
7911db781477SPatrick Sanan .seealso: `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
79124d6f44ffSToby Isaac @*/
7913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X)
7914d71ae5a4SJacob Faibussowitsch {
79154d6f44ffSToby Isaac   Vec localX;
79164d6f44ffSToby Isaac 
79174d6f44ffSToby Isaac   PetscFunctionBegin;
79184d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79199566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
79209566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX));
79219566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
79229566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
79239566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
79244d6f44ffSToby Isaac   PetscFunctionReturn(0);
79254d6f44ffSToby Isaac }
79264d6f44ffSToby Isaac 
7927a6e0b375SMatthew G. Knepley /*@C
7928bb7acecfSBarry Smith   DMProjectFunctionLocal - This projects the given function into the function space provided by a `DM`, putting the coefficients in a local vector.
7929a6e0b375SMatthew G. Knepley 
7930a6e0b375SMatthew G. Knepley   Not collective
7931a6e0b375SMatthew G. Knepley 
7932a6e0b375SMatthew G. Knepley   Input Parameters:
7933bb7acecfSBarry Smith + dm      - The `DM`
7934a6e0b375SMatthew G. Knepley . time    - The time
7935a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
7936a6e0b375SMatthew G. Knepley . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
7937a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
7938a6e0b375SMatthew G. Knepley 
7939a6e0b375SMatthew G. Knepley   Output Parameter:
7940a6e0b375SMatthew G. Knepley . localX - vector
7941a6e0b375SMatthew G. Knepley 
7942a6e0b375SMatthew G. Knepley    Calling sequence of func:
794377b739a6SMatthew Knepley $    func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
7944a6e0b375SMatthew G. Knepley 
7945a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
7946a6e0b375SMatthew G. Knepley .  x   - The coordinates
794777b739a6SMatthew Knepley .  Nc  - The number of components
7948a6e0b375SMatthew G. Knepley .  u   - The output field values
7949a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
7950a6e0b375SMatthew G. Knepley 
7951a6e0b375SMatthew G. Knepley   Level: developer
7952a6e0b375SMatthew G. Knepley 
7953bb7acecfSBarry Smith   Developer Notes:
7954bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
7955bb7acecfSBarry Smith 
7956bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
7957bb7acecfSBarry Smith 
7958db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
7959a6e0b375SMatthew G. Knepley @*/
7960d71ae5a4SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX)
7961d71ae5a4SJacob Faibussowitsch {
79624d6f44ffSToby Isaac   PetscFunctionBegin;
79634d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7964064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
79659566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfunctionlocal)(dm, time, funcs, ctxs, mode, localX));
79664d6f44ffSToby Isaac   PetscFunctionReturn(0);
79674d6f44ffSToby Isaac }
79684d6f44ffSToby Isaac 
7969a6e0b375SMatthew G. Knepley /*@C
7970bb7acecfSBarry 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.
7971a6e0b375SMatthew G. Knepley 
7972bb7acecfSBarry Smith   Collective on dm
7973a6e0b375SMatthew G. Knepley 
7974a6e0b375SMatthew G. Knepley   Input Parameters:
7975bb7acecfSBarry Smith + dm      - The `DM`
7976a6e0b375SMatthew G. Knepley . time    - The time
7977bb7acecfSBarry Smith . label   - The `DMLabel` selecting the portion of the mesh for projection
7978a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
7979bb7acecfSBarry Smith . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs may be null.
7980a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
7981a6e0b375SMatthew G. Knepley 
7982a6e0b375SMatthew G. Knepley   Output Parameter:
7983a6e0b375SMatthew G. Knepley . X - vector
7984a6e0b375SMatthew G. Knepley 
7985a6e0b375SMatthew G. Knepley    Calling sequence of func:
798677b739a6SMatthew Knepley $    func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
7987a6e0b375SMatthew G. Knepley 
7988a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
7989a6e0b375SMatthew G. Knepley .  x   - The coordinates
799077b739a6SMatthew Knepley .  Nc  - The number of components
7991a6e0b375SMatthew G. Knepley .  u   - The output field values
7992a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
7993a6e0b375SMatthew G. Knepley 
7994a6e0b375SMatthew G. Knepley   Level: developer
7995a6e0b375SMatthew G. Knepley 
7996bb7acecfSBarry Smith   Developer Notes:
7997bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
7998bb7acecfSBarry Smith 
7999bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8000bb7acecfSBarry Smith 
8001db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabelLocal()`, `DMComputeL2Diff()`
8002a6e0b375SMatthew G. Knepley @*/
8003d71ae5a4SJacob 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)
8004d71ae5a4SJacob Faibussowitsch {
80052c53366bSMatthew G. Knepley   Vec localX;
80062c53366bSMatthew G. Knepley 
80072c53366bSMatthew G. Knepley   PetscFunctionBegin;
80082c53366bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80099566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
80109566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
80119566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
80129566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
80139566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
80142c53366bSMatthew G. Knepley   PetscFunctionReturn(0);
80152c53366bSMatthew G. Knepley }
80162c53366bSMatthew G. Knepley 
8017a6e0b375SMatthew G. Knepley /*@C
8018bb7acecfSBarry 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.
8019a6e0b375SMatthew G. Knepley 
8020a6e0b375SMatthew G. Knepley   Not collective
8021a6e0b375SMatthew G. Knepley 
8022a6e0b375SMatthew G. Knepley   Input Parameters:
8023bb7acecfSBarry Smith + dm      - The `DM`
8024a6e0b375SMatthew G. Knepley . time    - The time
8025bb7acecfSBarry Smith . label   - The `DMLabel` selecting the portion of the mesh for projection
8026a6e0b375SMatthew G. Knepley . funcs   - The coordinate functions to evaluate, one per field
8027a6e0b375SMatthew G. Knepley . ctxs    - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
8028a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8029a6e0b375SMatthew G. Knepley 
8030a6e0b375SMatthew G. Knepley   Output Parameter:
8031a6e0b375SMatthew G. Knepley . localX - vector
8032a6e0b375SMatthew G. Knepley 
8033a6e0b375SMatthew G. Knepley    Calling sequence of func:
803477b739a6SMatthew Knepley $    func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx);
8035a6e0b375SMatthew G. Knepley 
8036a6e0b375SMatthew G. Knepley +  dim - The spatial dimension
8037a6e0b375SMatthew G. Knepley .  x   - The coordinates
803877b739a6SMatthew Knepley .  Nc  - The number of components
8039a6e0b375SMatthew G. Knepley .  u   - The output field values
8040a6e0b375SMatthew G. Knepley -  ctx - optional user-defined function context
8041a6e0b375SMatthew G. Knepley 
8042a6e0b375SMatthew G. Knepley   Level: developer
8043a6e0b375SMatthew G. Knepley 
8044bb7acecfSBarry Smith   Developer Notes:
8045bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8046bb7acecfSBarry Smith 
8047bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8048bb7acecfSBarry Smith 
8049db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
8050a6e0b375SMatthew G. Knepley @*/
8051d71ae5a4SJacob 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)
8052d71ae5a4SJacob Faibussowitsch {
80534d6f44ffSToby Isaac   PetscFunctionBegin;
80544d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8055064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
80569566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfunctionlabellocal)(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
80574d6f44ffSToby Isaac   PetscFunctionReturn(0);
80584d6f44ffSToby Isaac }
80592716604bSToby Isaac 
8060a6e0b375SMatthew G. Knepley /*@C
8061bb7acecfSBarry 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.
8062a6e0b375SMatthew G. Knepley 
8063a6e0b375SMatthew G. Knepley   Not collective
8064a6e0b375SMatthew G. Knepley 
8065a6e0b375SMatthew G. Knepley   Input Parameters:
8066bb7acecfSBarry Smith + dm      - The `DM`
8067a6e0b375SMatthew G. Knepley . time    - The time
8068a6e0b375SMatthew G. Knepley . localU  - The input field vector
8069a6e0b375SMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8070a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8071a6e0b375SMatthew G. Knepley 
8072a6e0b375SMatthew G. Knepley   Output Parameter:
8073a6e0b375SMatthew G. Knepley . localX  - The output vector
8074a6e0b375SMatthew G. Knepley 
8075a6e0b375SMatthew G. Knepley    Calling sequence of func:
8076a6e0b375SMatthew G. Knepley $    func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8077a6e0b375SMatthew G. Knepley $         const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8078a6e0b375SMatthew G. Knepley $         const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8079a6e0b375SMatthew G. Knepley $         PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8080a6e0b375SMatthew G. Knepley 
8081a6e0b375SMatthew G. Knepley +  dim          - The spatial dimension
8082a6e0b375SMatthew G. Knepley .  Nf           - The number of input fields
8083a6e0b375SMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8084a6e0b375SMatthew G. Knepley .  uOff         - The offset of each field in u[]
8085a6e0b375SMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8086a6e0b375SMatthew G. Knepley .  u            - The field values at this point in space
8087a6e0b375SMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8088a6e0b375SMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8089a6e0b375SMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8090a6e0b375SMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8091a6e0b375SMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8092a6e0b375SMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8093a6e0b375SMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8094a6e0b375SMatthew G. Knepley .  t            - The current time
8095a6e0b375SMatthew G. Knepley .  x            - The coordinates of this point
8096a6e0b375SMatthew G. Knepley .  numConstants - The number of constants
8097a6e0b375SMatthew G. Knepley .  constants    - The value of each constant
8098a6e0b375SMatthew G. Knepley -  f            - The value of the function at this point in space
8099a6e0b375SMatthew G. Knepley 
8100bb7acecfSBarry Smith   Note:
8101bb7acecfSBarry 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.
8102bb7acecfSBarry 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
8103bb7acecfSBarry 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
8104a6e0b375SMatthew 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.
8105a6e0b375SMatthew G. Knepley 
8106a6e0b375SMatthew G. Knepley   Level: intermediate
8107a6e0b375SMatthew G. Knepley 
8108bb7acecfSBarry Smith   Developer Notes:
8109bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8110bb7acecfSBarry Smith 
8111bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8112bb7acecfSBarry Smith 
8113db781477SPatrick Sanan .seealso: `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8114a6e0b375SMatthew G. Knepley @*/
8115d71ae5a4SJacob 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)
8116d71ae5a4SJacob Faibussowitsch {
81178c6c5593SMatthew G. Knepley   PetscFunctionBegin;
81188c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81198c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(localU, VEC_CLASSID, 3);
81208c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
81219566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfieldlocal)(dm, time, localU, funcs, mode, localX));
81228c6c5593SMatthew G. Knepley   PetscFunctionReturn(0);
81238c6c5593SMatthew G. Knepley }
81248c6c5593SMatthew G. Knepley 
8125a6e0b375SMatthew G. Knepley /*@C
8126a6e0b375SMatthew 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.
8127a6e0b375SMatthew G. Knepley 
8128a6e0b375SMatthew G. Knepley   Not collective
8129a6e0b375SMatthew G. Knepley 
8130a6e0b375SMatthew G. Knepley   Input Parameters:
8131bb7acecfSBarry Smith + dm      - The `DM`
8132a6e0b375SMatthew G. Knepley . time    - The time
8133bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain to output
8134a6e0b375SMatthew G. Knepley . numIds  - The number of label ids to use
8135a6e0b375SMatthew G. Knepley . ids     - The label ids to use for marking
8136bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
8137a6e0b375SMatthew G. Knepley . comps   - The components to set in the output, or NULL for all components
8138a6e0b375SMatthew G. Knepley . localU  - The input field vector
8139a6e0b375SMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8140a6e0b375SMatthew G. Knepley - mode    - The insertion mode for values
8141a6e0b375SMatthew G. Knepley 
8142a6e0b375SMatthew G. Knepley   Output Parameter:
8143a6e0b375SMatthew G. Knepley . localX  - The output vector
8144a6e0b375SMatthew G. Knepley 
8145a6e0b375SMatthew G. Knepley    Calling sequence of func:
8146a6e0b375SMatthew G. Knepley $    func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8147a6e0b375SMatthew G. Knepley $         const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8148a6e0b375SMatthew G. Knepley $         const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8149a6e0b375SMatthew G. Knepley $         PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8150a6e0b375SMatthew G. Knepley 
8151a6e0b375SMatthew G. Knepley +  dim          - The spatial dimension
8152a6e0b375SMatthew G. Knepley .  Nf           - The number of input fields
8153a6e0b375SMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8154a6e0b375SMatthew G. Knepley .  uOff         - The offset of each field in u[]
8155a6e0b375SMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8156a6e0b375SMatthew G. Knepley .  u            - The field values at this point in space
8157a6e0b375SMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8158a6e0b375SMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8159a6e0b375SMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8160a6e0b375SMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8161a6e0b375SMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8162a6e0b375SMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8163a6e0b375SMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8164a6e0b375SMatthew G. Knepley .  t            - The current time
8165a6e0b375SMatthew G. Knepley .  x            - The coordinates of this point
8166a6e0b375SMatthew G. Knepley .  numConstants - The number of constants
8167a6e0b375SMatthew G. Knepley .  constants    - The value of each constant
8168a6e0b375SMatthew G. Knepley -  f            - The value of the function at this point in space
8169a6e0b375SMatthew G. Knepley 
8170bb7acecfSBarry Smith   Note:
8171bb7acecfSBarry 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.
8172bb7acecfSBarry 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
8173bb7acecfSBarry 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
8174a6e0b375SMatthew 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.
8175a6e0b375SMatthew G. Knepley 
8176a6e0b375SMatthew G. Knepley   Level: intermediate
8177a6e0b375SMatthew G. Knepley 
8178bb7acecfSBarry Smith   Developer Notes:
8179bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8180bb7acecfSBarry Smith 
8181bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8182bb7acecfSBarry Smith 
8183d29d7c6eSMatthew G. Knepley .seealso: `DMProjectField()`, `DMProjectFieldLabel()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8184a6e0b375SMatthew G. Knepley @*/
8185d71ae5a4SJacob 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)
8186d71ae5a4SJacob Faibussowitsch {
81878c6c5593SMatthew G. Knepley   PetscFunctionBegin;
81888c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8189064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8190064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
81919566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
81928c6c5593SMatthew G. Knepley   PetscFunctionReturn(0);
81938c6c5593SMatthew G. Knepley }
81948c6c5593SMatthew G. Knepley 
81952716604bSToby Isaac /*@C
8196d29d7c6eSMatthew 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.
8197d29d7c6eSMatthew G. Knepley 
8198d29d7c6eSMatthew G. Knepley   Not collective
8199d29d7c6eSMatthew G. Knepley 
8200d29d7c6eSMatthew G. Knepley   Input Parameters:
8201bb7acecfSBarry Smith + dm      - The `DM`
8202d29d7c6eSMatthew G. Knepley . time    - The time
8203bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain to output
8204d29d7c6eSMatthew G. Knepley . numIds  - The number of label ids to use
8205d29d7c6eSMatthew G. Knepley . ids     - The label ids to use for marking
8206bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
8207d29d7c6eSMatthew G. Knepley . comps   - The components to set in the output, or NULL for all components
8208d29d7c6eSMatthew G. Knepley . U       - The input field vector
8209d29d7c6eSMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8210d29d7c6eSMatthew G. Knepley - mode    - The insertion mode for values
8211d29d7c6eSMatthew G. Knepley 
8212d29d7c6eSMatthew G. Knepley   Output Parameter:
8213d29d7c6eSMatthew G. Knepley . X       - The output vector
8214d29d7c6eSMatthew G. Knepley 
8215d29d7c6eSMatthew G. Knepley    Calling sequence of func:
8216d29d7c6eSMatthew G. Knepley $    func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8217d29d7c6eSMatthew G. Knepley $         const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8218d29d7c6eSMatthew G. Knepley $         const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8219d29d7c6eSMatthew G. Knepley $         PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8220d29d7c6eSMatthew G. Knepley 
8221d29d7c6eSMatthew G. Knepley +  dim          - The spatial dimension
8222d29d7c6eSMatthew G. Knepley .  Nf           - The number of input fields
8223d29d7c6eSMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8224d29d7c6eSMatthew G. Knepley .  uOff         - The offset of each field in u[]
8225d29d7c6eSMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8226d29d7c6eSMatthew G. Knepley .  u            - The field values at this point in space
8227d29d7c6eSMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8228d29d7c6eSMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8229d29d7c6eSMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8230d29d7c6eSMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8231d29d7c6eSMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8232d29d7c6eSMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8233d29d7c6eSMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8234d29d7c6eSMatthew G. Knepley .  t            - The current time
8235d29d7c6eSMatthew G. Knepley .  x            - The coordinates of this point
8236d29d7c6eSMatthew G. Knepley .  numConstants - The number of constants
8237d29d7c6eSMatthew G. Knepley .  constants    - The value of each constant
8238d29d7c6eSMatthew G. Knepley -  f            - The value of the function at this point in space
8239d29d7c6eSMatthew G. Knepley 
8240bb7acecfSBarry Smith   Note:
8241bb7acecfSBarry 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.
8242bb7acecfSBarry 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
8243bb7acecfSBarry 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
8244d29d7c6eSMatthew 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.
8245d29d7c6eSMatthew G. Knepley 
8246d29d7c6eSMatthew G. Knepley   Level: intermediate
8247d29d7c6eSMatthew G. Knepley 
8248bb7acecfSBarry Smith   Developer Notes:
8249bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8250bb7acecfSBarry Smith 
8251bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8252bb7acecfSBarry Smith 
8253d29d7c6eSMatthew G. Knepley .seealso: `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8254d29d7c6eSMatthew G. Knepley @*/
8255d71ae5a4SJacob 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)
8256d71ae5a4SJacob Faibussowitsch {
8257d29d7c6eSMatthew G. Knepley   DM  dmIn;
8258d29d7c6eSMatthew G. Knepley   Vec localU, localX;
8259d29d7c6eSMatthew G. Knepley 
8260d29d7c6eSMatthew G. Knepley   PetscFunctionBegin;
8261d29d7c6eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8262d29d7c6eSMatthew G. Knepley   PetscCall(VecGetDM(U, &dmIn));
8263d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dmIn, &localU));
8264d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dm, &localX));
826572fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalBegin(dmIn, U, mode, localU));
826672fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalEnd(dmIn, U, mode, localU));
8267d29d7c6eSMatthew G. Knepley   PetscCall(DMProjectFieldLabelLocal(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
8268d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
8269d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
8270d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dm, &localX));
8271d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dmIn, &localU));
8272d29d7c6eSMatthew G. Knepley   PetscFunctionReturn(0);
8273d29d7c6eSMatthew G. Knepley }
8274d29d7c6eSMatthew G. Knepley 
8275d29d7c6eSMatthew G. Knepley /*@C
8276ece3a9fcSMatthew 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.
8277ece3a9fcSMatthew G. Knepley 
8278ece3a9fcSMatthew G. Knepley   Not collective
8279ece3a9fcSMatthew G. Knepley 
8280ece3a9fcSMatthew G. Knepley   Input Parameters:
8281bb7acecfSBarry Smith + dm      - The `DM`
8282ece3a9fcSMatthew G. Knepley . time    - The time
8283bb7acecfSBarry Smith . label   - The `DMLabel` marking the portion of the domain boundary to output
8284ece3a9fcSMatthew G. Knepley . numIds  - The number of label ids to use
8285ece3a9fcSMatthew G. Knepley . ids     - The label ids to use for marking
8286bb7acecfSBarry Smith . Nc      - The number of components to set in the output, or `PETSC_DETERMINE` for all components
8287ece3a9fcSMatthew G. Knepley . comps   - The components to set in the output, or NULL for all components
8288ece3a9fcSMatthew G. Knepley . localU  - The input field vector
8289ece3a9fcSMatthew G. Knepley . funcs   - The functions to evaluate, one per field
8290ece3a9fcSMatthew G. Knepley - mode    - The insertion mode for values
8291ece3a9fcSMatthew G. Knepley 
8292ece3a9fcSMatthew G. Knepley   Output Parameter:
8293ece3a9fcSMatthew G. Knepley . localX  - The output vector
8294ece3a9fcSMatthew G. Knepley 
8295ece3a9fcSMatthew G. Knepley    Calling sequence of func:
8296ece3a9fcSMatthew G. Knepley $    func(PetscInt dim, PetscInt Nf, PetscInt NfAux,
8297ece3a9fcSMatthew G. Knepley $         const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
8298ece3a9fcSMatthew G. Knepley $         const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
8299ece3a9fcSMatthew G. Knepley $         PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]);
8300ece3a9fcSMatthew G. Knepley 
8301ece3a9fcSMatthew G. Knepley +  dim          - The spatial dimension
8302ece3a9fcSMatthew G. Knepley .  Nf           - The number of input fields
8303ece3a9fcSMatthew G. Knepley .  NfAux        - The number of input auxiliary fields
8304ece3a9fcSMatthew G. Knepley .  uOff         - The offset of each field in u[]
8305ece3a9fcSMatthew G. Knepley .  uOff_x       - The offset of each field in u_x[]
8306ece3a9fcSMatthew G. Knepley .  u            - The field values at this point in space
8307ece3a9fcSMatthew G. Knepley .  u_t          - The field time derivative at this point in space (or NULL)
8308ece3a9fcSMatthew G. Knepley .  u_x          - The field derivatives at this point in space
8309ece3a9fcSMatthew G. Knepley .  aOff         - The offset of each auxiliary field in u[]
8310ece3a9fcSMatthew G. Knepley .  aOff_x       - The offset of each auxiliary field in u_x[]
8311ece3a9fcSMatthew G. Knepley .  a            - The auxiliary field values at this point in space
8312ece3a9fcSMatthew G. Knepley .  a_t          - The auxiliary field time derivative at this point in space (or NULL)
8313ece3a9fcSMatthew G. Knepley .  a_x          - The auxiliary field derivatives at this point in space
8314ece3a9fcSMatthew G. Knepley .  t            - The current time
8315ece3a9fcSMatthew G. Knepley .  x            - The coordinates of this point
8316ece3a9fcSMatthew G. Knepley .  n            - The face normal
8317ece3a9fcSMatthew G. Knepley .  numConstants - The number of constants
8318ece3a9fcSMatthew G. Knepley .  constants    - The value of each constant
8319ece3a9fcSMatthew G. Knepley -  f            - The value of the function at this point in space
8320ece3a9fcSMatthew G. Knepley 
8321ece3a9fcSMatthew G. Knepley   Note:
8322bb7acecfSBarry 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.
8323bb7acecfSBarry 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
8324bb7acecfSBarry 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
8325ece3a9fcSMatthew 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.
8326ece3a9fcSMatthew G. Knepley 
8327ece3a9fcSMatthew G. Knepley   Level: intermediate
8328ece3a9fcSMatthew G. Knepley 
8329bb7acecfSBarry Smith   Developer Notes:
8330bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8331bb7acecfSBarry Smith 
8332bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8333bb7acecfSBarry Smith 
8334db781477SPatrick Sanan .seealso: `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8335ece3a9fcSMatthew G. Knepley @*/
8336d71ae5a4SJacob 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)
8337d71ae5a4SJacob Faibussowitsch {
8338ece3a9fcSMatthew G. Knepley   PetscFunctionBegin;
8339ece3a9fcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8340064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8341064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
83429566063dSJacob Faibussowitsch   PetscCall((dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
8343ece3a9fcSMatthew G. Knepley   PetscFunctionReturn(0);
8344ece3a9fcSMatthew G. Knepley }
8345ece3a9fcSMatthew G. Knepley 
8346ece3a9fcSMatthew G. Knepley /*@C
83472716604bSToby Isaac   DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
83482716604bSToby Isaac 
8349bb7acecfSBarry Smith   Collective on dm
8350bb7acecfSBarry Smith 
83512716604bSToby Isaac   Input Parameters:
8352bb7acecfSBarry Smith + dm    - The `DM`
83530709b2feSToby Isaac . time  - The time
83542716604bSToby Isaac . funcs - The functions to evaluate for each field component
83552716604bSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8356574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
83572716604bSToby Isaac 
83582716604bSToby Isaac   Output Parameter:
83592716604bSToby Isaac . diff - The diff ||u - u_h||_2
83602716604bSToby Isaac 
83612716604bSToby Isaac   Level: developer
83622716604bSToby Isaac 
8363bb7acecfSBarry Smith   Developer Notes:
8364bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8365bb7acecfSBarry Smith 
8366bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8367bb7acecfSBarry Smith 
8368db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
83692716604bSToby Isaac @*/
8370d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
8371d71ae5a4SJacob Faibussowitsch {
83722716604bSToby Isaac   PetscFunctionBegin;
83732716604bSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8374b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
83759566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2diff)(dm, time, funcs, ctxs, X, diff));
83762716604bSToby Isaac   PetscFunctionReturn(0);
83772716604bSToby Isaac }
8378b698f381SToby Isaac 
8379b698f381SToby Isaac /*@C
8380b698f381SToby Isaac   DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
8381b698f381SToby Isaac 
8382d083f849SBarry Smith   Collective on dm
8383d083f849SBarry Smith 
8384b698f381SToby Isaac   Input Parameters:
8385bb7acecfSBarry Smith + dm    - The `DM`
8386b698f381SToby Isaac , time  - The time
8387b698f381SToby Isaac . funcs - The gradient functions to evaluate for each field component
8388b698f381SToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8389574a98acSMatthew G. Knepley . X     - The coefficient vector u_h, a global vector
8390b698f381SToby Isaac - n     - The vector to project along
8391b698f381SToby Isaac 
8392b698f381SToby Isaac   Output Parameter:
8393b698f381SToby Isaac . diff - The diff ||(grad u - grad u_h) . n||_2
8394b698f381SToby Isaac 
8395b698f381SToby Isaac   Level: developer
8396b698f381SToby Isaac 
8397bb7acecfSBarry Smith   Developer Notes:
8398bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8399bb7acecfSBarry Smith 
8400bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8401bb7acecfSBarry Smith 
8402bb7acecfSBarry Smith .seealso: `DMProjectFunction()`, `DMComputeL2Diff()`, `DMComputeL2FieldDiff()`
8403b698f381SToby Isaac @*/
8404d71ae5a4SJacob 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)
8405d71ae5a4SJacob Faibussowitsch {
8406b698f381SToby Isaac   PetscFunctionBegin;
8407b698f381SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8408b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
84099566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2gradientdiff)(dm, time, funcs, ctxs, X, n, diff));
8410b698f381SToby Isaac   PetscFunctionReturn(0);
8411b698f381SToby Isaac }
8412b698f381SToby Isaac 
84132a16baeaSToby Isaac /*@C
84142a16baeaSToby Isaac   DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
84152a16baeaSToby Isaac 
8416d083f849SBarry Smith   Collective on dm
8417d083f849SBarry Smith 
84182a16baeaSToby Isaac   Input Parameters:
8419bb7acecfSBarry Smith + dm    - The `DM`
84202a16baeaSToby Isaac . time  - The time
84212a16baeaSToby Isaac . funcs - The functions to evaluate for each field component
84222a16baeaSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8423574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
84242a16baeaSToby Isaac 
84252a16baeaSToby Isaac   Output Parameter:
84262a16baeaSToby Isaac . diff - The array of differences, ||u^f - u^f_h||_2
84272a16baeaSToby Isaac 
84282a16baeaSToby Isaac   Level: developer
84292a16baeaSToby Isaac 
8430bb7acecfSBarry Smith   Developer Notes:
8431bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8432bb7acecfSBarry Smith 
8433bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8434bb7acecfSBarry Smith 
8435db781477SPatrick Sanan .seealso: `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
84362a16baeaSToby Isaac @*/
8437d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
8438d71ae5a4SJacob Faibussowitsch {
84392a16baeaSToby Isaac   PetscFunctionBegin;
84402a16baeaSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84412a16baeaSToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
84429566063dSJacob Faibussowitsch   PetscCall((dm->ops->computel2fielddiff)(dm, time, funcs, ctxs, X, diff));
84432a16baeaSToby Isaac   PetscFunctionReturn(0);
84442a16baeaSToby Isaac }
84452a16baeaSToby Isaac 
8446df0b854cSToby Isaac /*@C
8447bb7acecfSBarry Smith  DMGetNeighbors - Gets an array containing the MPI ranks of all the processes neighbors
8448502a2867SDave May 
8449502a2867SDave May  Not Collective
8450502a2867SDave May 
8451502a2867SDave May  Input Parameter:
8452bb7acecfSBarry Smith .  dm    - The `DM`
8453502a2867SDave May 
84540a19bb7dSprj-  Output Parameters:
84550a19bb7dSprj- +  nranks - the number of neighbours
84560a19bb7dSprj- -  ranks - the neighbors ranks
8457502a2867SDave May 
8458bb7acecfSBarry Smith  Note:
8459bb7acecfSBarry Smith  Do not free the array, it is freed when the `DM` is destroyed.
8460502a2867SDave May 
8461502a2867SDave May  Level: beginner
8462502a2867SDave May 
8463db781477SPatrick Sanan  .seealso: `DMDAGetNeighbors()`, `PetscSFGetRootRanks()`
8464502a2867SDave May @*/
8465d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNeighbors(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
8466d71ae5a4SJacob Faibussowitsch {
8467502a2867SDave May   PetscFunctionBegin;
8468502a2867SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84699566063dSJacob Faibussowitsch   PetscCall((dm->ops->getneighbors)(dm, nranks, ranks));
8470502a2867SDave May   PetscFunctionReturn(0);
8471502a2867SDave May }
8472502a2867SDave May 
8473531c7667SBarry Smith #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
8474531c7667SBarry Smith 
8475531c7667SBarry Smith /*
8476531c7667SBarry Smith     Converts the input vector to a ghosted vector and then calls the standard coloring code.
8477531c7667SBarry Smith     This has be a different function because it requires DM which is not defined in the Mat library
8478531c7667SBarry Smith */
8479d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringApply_AIJDM(Mat J, MatFDColoring coloring, Vec x1, void *sctx)
8480d71ae5a4SJacob Faibussowitsch {
8481531c7667SBarry Smith   PetscFunctionBegin;
8482531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8483531c7667SBarry Smith     Vec x1local;
8484531c7667SBarry Smith     DM  dm;
84859566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
84867a8be351SBarry Smith     PetscCheck(dm, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_INCOMP, "IS_COLORING_LOCAL requires a DM");
84879566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &x1local));
84889566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, x1, INSERT_VALUES, x1local));
84899566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, x1, INSERT_VALUES, x1local));
8490531c7667SBarry Smith     x1 = x1local;
8491531c7667SBarry Smith   }
84929566063dSJacob Faibussowitsch   PetscCall(MatFDColoringApply_AIJ(J, coloring, x1, sctx));
8493531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8494531c7667SBarry Smith     DM dm;
84959566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
84969566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &x1));
8497531c7667SBarry Smith   }
8498531c7667SBarry Smith   PetscFunctionReturn(0);
8499531c7667SBarry Smith }
8500531c7667SBarry Smith 
8501531c7667SBarry Smith /*@
8502bb7acecfSBarry Smith     MatFDColoringUseDM - allows a `MatFDColoring` object to use the `DM` associated with the matrix to compute a `IS_COLORING_LOCAL` coloring
8503531c7667SBarry Smith 
8504531c7667SBarry Smith     Input Parameter:
8505bb7acecfSBarry Smith .    coloring - the `MatFDColoring` object
8506531c7667SBarry Smith 
8507bb7acecfSBarry Smith     Developer Note:
8508bb7acecfSBarry Smith     this routine exists because the PETSc `Mat` library does not know about the `DM` objects
8509531c7667SBarry Smith 
85101b266c99SBarry Smith     Level: advanced
85111b266c99SBarry Smith 
8512db781477SPatrick Sanan .seealso: `MatFDColoring`, `MatFDColoringCreate()`, `ISColoringType`
8513531c7667SBarry Smith @*/
8514d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringUseDM(Mat coloring, MatFDColoring fdcoloring)
8515d71ae5a4SJacob Faibussowitsch {
8516531c7667SBarry Smith   PetscFunctionBegin;
8517531c7667SBarry Smith   coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
8518531c7667SBarry Smith   PetscFunctionReturn(0);
8519531c7667SBarry Smith }
85208320bc6fSPatrick Sanan 
85218320bc6fSPatrick Sanan /*@
8522bb7acecfSBarry Smith     DMGetCompatibility - determine if two `DM`s are compatible
85238320bc6fSPatrick Sanan 
85248320bc6fSPatrick Sanan     Collective
85258320bc6fSPatrick Sanan 
85268320bc6fSPatrick Sanan     Input Parameters:
8527bb7acecfSBarry Smith +    dm1 - the first `DM`
8528bb7acecfSBarry Smith -    dm2 - the second `DM`
85298320bc6fSPatrick Sanan 
85308320bc6fSPatrick Sanan     Output Parameters:
8531bb7acecfSBarry Smith +    compatible - whether or not the two `DM`s are compatible
8532bb7acecfSBarry Smith -    set - whether or not the compatible value was actually determined and set
85338320bc6fSPatrick Sanan 
85348320bc6fSPatrick Sanan     Notes:
8535bb7acecfSBarry Smith     Two `DM`s are deemed compatible if they represent the same parallel decomposition
85363d862458SPatrick Sanan     of the same topology. This implies that the section (field data) on one
85378320bc6fSPatrick Sanan     "makes sense" with respect to the topology and parallel decomposition of the other.
8538bb7acecfSBarry Smith     Loosely speaking, compatible `DM`s represent the same domain and parallel
85393d862458SPatrick Sanan     decomposition, but hold different data.
85408320bc6fSPatrick Sanan 
85418320bc6fSPatrick Sanan     Typically, one would confirm compatibility if intending to simultaneously iterate
8542bb7acecfSBarry Smith     over a pair of vectors obtained from different `DM`s.
85438320bc6fSPatrick Sanan 
8544bb7acecfSBarry Smith     For example, two `DMDA` objects are compatible if they have the same local
85458320bc6fSPatrick Sanan     and global sizes and the same stencil width. They can have different numbers
85468320bc6fSPatrick Sanan     of degrees of freedom per node. Thus, one could use the node numbering from
8547bb7acecfSBarry Smith     either `DM` in bounds for a loop over vectors derived from either `DM`.
85488320bc6fSPatrick Sanan 
8549bb7acecfSBarry Smith     Consider the operation of summing data living on a 2-dof `DMDA` to data living
8550bb7acecfSBarry Smith     on a 1-dof `DMDA`, which should be compatible, as in the following snippet.
85518320bc6fSPatrick Sanan .vb
85528320bc6fSPatrick Sanan   ...
85539566063dSJacob Faibussowitsch   PetscCall(DMGetCompatibility(da1,da2,&compatible,&set));
85548320bc6fSPatrick Sanan   if (set && compatible)  {
85559566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da1,vec1,&arr1));
85569566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da2,vec2,&arr2));
85579566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL));
85588320bc6fSPatrick Sanan     for (j=y; j<y+n; ++j) {
85598320bc6fSPatrick Sanan       for (i=x; i<x+m, ++i) {
85608320bc6fSPatrick Sanan         arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1];
85618320bc6fSPatrick Sanan       }
85628320bc6fSPatrick Sanan     }
85639566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da1,vec1,&arr1));
85649566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da2,vec2,&arr2));
85658320bc6fSPatrick Sanan   } else {
85668320bc6fSPatrick Sanan     SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible");
85678320bc6fSPatrick Sanan   }
85688320bc6fSPatrick Sanan   ...
85698320bc6fSPatrick Sanan .ve
85708320bc6fSPatrick Sanan 
8571bb7acecfSBarry Smith     Checking compatibility might be expensive for a given implementation of `DM`,
85728320bc6fSPatrick Sanan     or might be impossible to unambiguously confirm or deny. For this reason,
85738320bc6fSPatrick Sanan     this function may decline to determine compatibility, and hence users should
85748320bc6fSPatrick Sanan     always check the "set" output parameter.
85758320bc6fSPatrick Sanan 
8576bb7acecfSBarry Smith     A `DM` is always compatible with itself.
85778320bc6fSPatrick Sanan 
8578bb7acecfSBarry Smith     In the current implementation, `DM`s which live on "unequal" communicators
85798320bc6fSPatrick Sanan     (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed
85808320bc6fSPatrick Sanan     incompatible.
85818320bc6fSPatrick Sanan 
85828320bc6fSPatrick Sanan     This function is labeled "Collective," as information about all subdomains
8583bb7acecfSBarry Smith     is required on each rank. However, in `DM` implementations which store all this
85848320bc6fSPatrick Sanan     information locally, this function may be merely "Logically Collective".
85858320bc6fSPatrick Sanan 
8586bb7acecfSBarry Smith     Developer Note:
8587bb7acecfSBarry Smith     Compatibility is assumed to be a symmetric concept; `DM` A is compatible with `DM` B
85883d862458SPatrick Sanan     iff B is compatible with A. Thus, this function checks the implementations
8589a5bc1bf3SBarry Smith     of both dm and dmc (if they are of different types), attempting to determine
8590bb7acecfSBarry Smith     compatibility. It is left to `DM` implementers to ensure that symmetry is
85918320bc6fSPatrick Sanan     preserved. The simplest way to do this is, when implementing type-specific
85923d862458SPatrick Sanan     logic for this function, is to check for existing logic in the implementation
8593bb7acecfSBarry Smith     of other `DM` types and let *set = PETSC_FALSE if found.
85948320bc6fSPatrick Sanan 
85958320bc6fSPatrick Sanan     Level: advanced
85968320bc6fSPatrick Sanan 
8597db781477SPatrick Sanan .seealso: `DM`, `DMDACreateCompatibleDMDA()`, `DMStagCreateCompatibleDMStag()`
85988320bc6fSPatrick Sanan @*/
8599d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCompatibility(DM dm1, DM dm2, PetscBool *compatible, PetscBool *set)
8600d71ae5a4SJacob Faibussowitsch {
86018320bc6fSPatrick Sanan   PetscMPIInt compareResult;
86028320bc6fSPatrick Sanan   DMType      type, type2;
86038320bc6fSPatrick Sanan   PetscBool   sameType;
86048320bc6fSPatrick Sanan 
86058320bc6fSPatrick Sanan   PetscFunctionBegin;
8606a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dm1, DM_CLASSID, 1);
86078320bc6fSPatrick Sanan   PetscValidHeaderSpecific(dm2, DM_CLASSID, 2);
86088320bc6fSPatrick Sanan 
86098320bc6fSPatrick Sanan   /* Declare a DM compatible with itself */
8610a5bc1bf3SBarry Smith   if (dm1 == dm2) {
86118320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
86128320bc6fSPatrick Sanan     *compatible = PETSC_TRUE;
86138320bc6fSPatrick Sanan     PetscFunctionReturn(0);
86148320bc6fSPatrick Sanan   }
86158320bc6fSPatrick Sanan 
86168320bc6fSPatrick Sanan   /* Declare a DM incompatible with a DM that lives on an "unequal"
86178320bc6fSPatrick Sanan      communicator. Note that this does not preclude compatibility with
86188320bc6fSPatrick Sanan      DMs living on "congruent" or "similar" communicators, but this must be
86198320bc6fSPatrick Sanan      determined by the implementation-specific logic */
86209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)dm1), PetscObjectComm((PetscObject)dm2), &compareResult));
86218320bc6fSPatrick Sanan   if (compareResult == MPI_UNEQUAL) {
86228320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
86238320bc6fSPatrick Sanan     *compatible = PETSC_FALSE;
86248320bc6fSPatrick Sanan     PetscFunctionReturn(0);
86258320bc6fSPatrick Sanan   }
86268320bc6fSPatrick Sanan 
86278320bc6fSPatrick Sanan   /* Pass to the implementation-specific routine, if one exists. */
8628a5bc1bf3SBarry Smith   if (dm1->ops->getcompatibility) {
8629dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm1, getcompatibility, dm2, compatible, set);
8630b9d85ea2SLisandro Dalcin     if (*set) PetscFunctionReturn(0);
86318320bc6fSPatrick Sanan   }
86328320bc6fSPatrick Sanan 
8633a5bc1bf3SBarry Smith   /* If dm1 and dm2 are of different types, then attempt to check compatibility
86348320bc6fSPatrick Sanan      with an implementation of this function from dm2 */
86359566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm1, &type));
86369566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm2, &type2));
86379566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(type, type2, &sameType));
86388320bc6fSPatrick Sanan   if (!sameType && dm2->ops->getcompatibility) {
8639dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm2, getcompatibility, dm1, compatible, set); /* Note argument order */
86408320bc6fSPatrick Sanan   } else {
86418320bc6fSPatrick Sanan     *set = PETSC_FALSE;
86428320bc6fSPatrick Sanan   }
86438320bc6fSPatrick Sanan   PetscFunctionReturn(0);
86448320bc6fSPatrick Sanan }
8645c0f0dcc3SMatthew G. Knepley 
8646c0f0dcc3SMatthew G. Knepley /*@C
8647bb7acecfSBarry Smith   DMMonitorSet - Sets an additional monitor function that is to be used after a solve to monitor discretization performance.
8648c0f0dcc3SMatthew G. Knepley 
8649bb7acecfSBarry Smith   Logically Collective on dm
8650c0f0dcc3SMatthew G. Knepley 
8651c0f0dcc3SMatthew G. Knepley   Input Parameters:
8652bb7acecfSBarry Smith + DM - the `DM`
8653c0f0dcc3SMatthew G. Knepley . f - the monitor function
8654c0f0dcc3SMatthew G. Knepley . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired)
8655c0f0dcc3SMatthew G. Knepley - monitordestroy - [optional] routine that frees monitor context (may be NULL)
8656c0f0dcc3SMatthew G. Knepley 
8657c0f0dcc3SMatthew G. Knepley   Options Database Keys:
8658bb7acecfSBarry Smith - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `DMMonitorSet()`, but
8659c0f0dcc3SMatthew G. Knepley                             does not cancel those set via the options database.
8660c0f0dcc3SMatthew G. Knepley 
8661bb7acecfSBarry Smith   Note:
8662c0f0dcc3SMatthew G. Knepley   Several different monitoring routines may be set by calling
8663bb7acecfSBarry Smith   `DMMonitorSet()` multiple times or with `DMMonitorSetFromOptions()`; all will be called in the
8664c0f0dcc3SMatthew G. Knepley   order in which they were set.
8665c0f0dcc3SMatthew G. Knepley 
8666bb7acecfSBarry Smith   Fortran Note:
8667bb7acecfSBarry Smith   Only a single monitor function can be set for each `DM` object
8668bb7acecfSBarry Smith 
8669bb7acecfSBarry Smith   Developer Note:
8670bb7acecfSBarry Smith   This API has a generic name but seems specific to a very particular aspect of the use of `DM`
8671c0f0dcc3SMatthew G. Knepley 
8672c0f0dcc3SMatthew G. Knepley   Level: intermediate
8673c0f0dcc3SMatthew G. Knepley 
8674bb7acecfSBarry Smith .seealso: `DMMonitorCancel()`, `DMMonitorSetFromOptions()`, `DMMonitor()`
8675c0f0dcc3SMatthew G. Knepley @*/
8676d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
8677d71ae5a4SJacob Faibussowitsch {
8678c0f0dcc3SMatthew G. Knepley   PetscInt m;
8679c0f0dcc3SMatthew G. Knepley 
8680c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8681c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8682c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
8683c0f0dcc3SMatthew G. Knepley     PetscBool identical;
8684c0f0dcc3SMatthew G. Knepley 
86859566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical));
8686c0f0dcc3SMatthew G. Knepley     if (identical) PetscFunctionReturn(0);
8687c0f0dcc3SMatthew G. Knepley   }
86887a8be351SBarry Smith   PetscCheck(dm->numbermonitors < MAXDMMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
8689c0f0dcc3SMatthew G. Knepley   dm->monitor[dm->numbermonitors]          = f;
8690c0f0dcc3SMatthew G. Knepley   dm->monitordestroy[dm->numbermonitors]   = monitordestroy;
8691c0f0dcc3SMatthew G. Knepley   dm->monitorcontext[dm->numbermonitors++] = (void *)mctx;
8692c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
8693c0f0dcc3SMatthew G. Knepley }
8694c0f0dcc3SMatthew G. Knepley 
8695c0f0dcc3SMatthew G. Knepley /*@
8696bb7acecfSBarry Smith   DMMonitorCancel - Clears all the monitor functions for a `DM` object.
8697c0f0dcc3SMatthew G. Knepley 
8698bb7acecfSBarry Smith   Logically Collective on dm
8699c0f0dcc3SMatthew G. Knepley 
8700c0f0dcc3SMatthew G. Knepley   Input Parameter:
8701c0f0dcc3SMatthew G. Knepley . dm - the DM
8702c0f0dcc3SMatthew G. Knepley 
8703c0f0dcc3SMatthew G. Knepley   Options Database Key:
8704c0f0dcc3SMatthew G. Knepley . -dm_monitor_cancel - cancels all monitors that have been hardwired
8705bb7acecfSBarry Smith   into a code by calls to `DMonitorSet()`, but does not cancel those
8706c0f0dcc3SMatthew G. Knepley   set via the options database
8707c0f0dcc3SMatthew G. Knepley 
8708bb7acecfSBarry Smith   Note:
8709bb7acecfSBarry Smith   There is no way to clear one specific monitor from a `DM` object.
8710c0f0dcc3SMatthew G. Knepley 
8711c0f0dcc3SMatthew G. Knepley   Level: intermediate
8712c0f0dcc3SMatthew G. Knepley 
8713bb7acecfSBarry Smith .seealso: `DMMonitorSet()`, `DMMonitorSetFromOptions()`, `DMMonitor()`
8714c0f0dcc3SMatthew G. Knepley @*/
8715d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorCancel(DM dm)
8716d71ae5a4SJacob Faibussowitsch {
8717c0f0dcc3SMatthew G. Knepley   PetscInt m;
8718c0f0dcc3SMatthew G. Knepley 
8719c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8720c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8721c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
87229566063dSJacob Faibussowitsch     if (dm->monitordestroy[m]) PetscCall((*dm->monitordestroy[m])(&dm->monitorcontext[m]));
8723c0f0dcc3SMatthew G. Knepley   }
8724c0f0dcc3SMatthew G. Knepley   dm->numbermonitors = 0;
8725c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
8726c0f0dcc3SMatthew G. Knepley }
8727c0f0dcc3SMatthew G. Knepley 
8728c0f0dcc3SMatthew G. Knepley /*@C
8729c0f0dcc3SMatthew G. Knepley   DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
8730c0f0dcc3SMatthew G. Knepley 
8731bb7acecfSBarry Smith   Collective on dm
8732c0f0dcc3SMatthew G. Knepley 
8733c0f0dcc3SMatthew G. Knepley   Input Parameters:
8734bb7acecfSBarry Smith + dm   - `DM` object you wish to monitor
8735c0f0dcc3SMatthew G. Knepley . name - the monitor type one is seeking
8736c0f0dcc3SMatthew G. Knepley . help - message indicating what monitoring is done
8737c0f0dcc3SMatthew G. Knepley . manual - manual page for the monitor
8738c0f0dcc3SMatthew G. Knepley . monitor - the monitor function
8739bb7acecfSBarry 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
8740c0f0dcc3SMatthew G. Knepley 
8741c0f0dcc3SMatthew G. Knepley   Output Parameter:
8742c0f0dcc3SMatthew G. Knepley . flg - Flag set if the monitor was created
8743c0f0dcc3SMatthew G. Knepley 
8744c0f0dcc3SMatthew G. Knepley   Level: developer
8745c0f0dcc3SMatthew G. Knepley 
8746db781477SPatrick Sanan .seealso: `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
8747db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
8748db781477SPatrick Sanan           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
8749db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
8750c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
8751db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
8752bb7acecfSBarry Smith           `PetscOptionsFList()`, `PetscOptionsEList()`, `DMMonitor()`, `DMMonitorSet()`
8753c0f0dcc3SMatthew G. Knepley @*/
8754d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg)
8755d71ae5a4SJacob Faibussowitsch {
8756c0f0dcc3SMatthew G. Knepley   PetscViewer       viewer;
8757c0f0dcc3SMatthew G. Knepley   PetscViewerFormat format;
8758c0f0dcc3SMatthew G. Knepley 
8759c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8760c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)dm), ((PetscObject)dm)->options, ((PetscObject)dm)->prefix, name, &viewer, &format, flg));
8762c0f0dcc3SMatthew G. Knepley   if (*flg) {
8763c0f0dcc3SMatthew G. Knepley     PetscViewerAndFormat *vf;
8764c0f0dcc3SMatthew G. Knepley 
87659566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
87669566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)viewer));
87679566063dSJacob Faibussowitsch     if (monitorsetup) PetscCall((*monitorsetup)(dm, vf));
87689566063dSJacob Faibussowitsch     PetscCall(DMMonitorSet(dm, (PetscErrorCode(*)(DM, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
8769c0f0dcc3SMatthew G. Knepley   }
8770c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
8771c0f0dcc3SMatthew G. Knepley }
8772c0f0dcc3SMatthew G. Knepley 
8773c0f0dcc3SMatthew G. Knepley /*@
8774c0f0dcc3SMatthew G. Knepley    DMMonitor - runs the user provided monitor routines, if they exist
8775c0f0dcc3SMatthew G. Knepley 
8776bb7acecfSBarry Smith    Collective on dm
8777c0f0dcc3SMatthew G. Knepley 
8778c0f0dcc3SMatthew G. Knepley    Input Parameters:
8779bb7acecfSBarry Smith .  dm - The `DM`
8780c0f0dcc3SMatthew G. Knepley 
8781c0f0dcc3SMatthew G. Knepley    Level: developer
8782c0f0dcc3SMatthew G. Knepley 
8783bb7acecfSBarry Smith    Question:
8784bb7acecfSBarry 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
8785bb7acecfSBarry Smith    since some `DM` have no concept of discretization
8786bb7acecfSBarry Smith 
8787bb7acecfSBarry Smith .seealso: `DMMonitorSet()`, `DMMonitorSetFromOptions()`
8788c0f0dcc3SMatthew G. Knepley @*/
8789d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitor(DM dm)
8790d71ae5a4SJacob Faibussowitsch {
8791c0f0dcc3SMatthew G. Knepley   PetscInt m;
8792c0f0dcc3SMatthew G. Knepley 
8793c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8794c0f0dcc3SMatthew G. Knepley   if (!dm) PetscFunctionReturn(0);
8795c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
879648a46eb9SPierre Jolivet   for (m = 0; m < dm->numbermonitors; ++m) PetscCall((*dm->monitor[m])(dm, dm->monitorcontext[m]));
8797c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
8798c0f0dcc3SMatthew G. Knepley }
87992e4af2aeSMatthew G. Knepley 
88002e4af2aeSMatthew G. Knepley /*@
8801bb7acecfSBarry Smith   DMComputeError - Computes the error assuming the user has provided the exact solution functions
88022e4af2aeSMatthew G. Knepley 
8803bb7acecfSBarry Smith   Collective on dm
88042e4af2aeSMatthew G. Knepley 
88052e4af2aeSMatthew G. Knepley   Input Parameters:
8806bb7acecfSBarry Smith + dm     - The `DM`
88076b867d5aSJose E. Roman - sol    - The solution vector
88082e4af2aeSMatthew G. Knepley 
88096b867d5aSJose E. Roman   Input/Output Parameter:
88106b867d5aSJose E. Roman . errors - An array of length Nf, the number of fields, or NULL for no output; on output
88116b867d5aSJose E. Roman            contains the error in each field
88126b867d5aSJose E. Roman 
88136b867d5aSJose E. Roman   Output Parameter:
88146b867d5aSJose E. Roman . errorVec - A vector to hold the cellwise error (may be NULL)
88152e4af2aeSMatthew G. Knepley 
8816bb7acecfSBarry Smith   Note:
8817bb7acecfSBarry Smith   The exact solutions come from the `PetscDS` object, and the time comes from `DMGetOutputSequenceNumber()`.
88182e4af2aeSMatthew G. Knepley 
88192e4af2aeSMatthew G. Knepley   Level: developer
88202e4af2aeSMatthew G. Knepley 
8821db781477SPatrick Sanan .seealso: `DMMonitorSet()`, `DMGetRegionNumDS()`, `PetscDSGetExactSolution()`, `DMGetOutputSequenceNumber()`
88222e4af2aeSMatthew G. Knepley @*/
8823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec)
8824d71ae5a4SJacob Faibussowitsch {
88252e4af2aeSMatthew G. Knepley   PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
88262e4af2aeSMatthew G. Knepley   void    **ctxs;
88272e4af2aeSMatthew G. Knepley   PetscReal time;
88282e4af2aeSMatthew G. Knepley   PetscInt  Nf, f, Nds, s;
88292e4af2aeSMatthew G. Knepley 
88302e4af2aeSMatthew G. Knepley   PetscFunctionBegin;
88319566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
88329566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(Nf, &exactSol, Nf, &ctxs));
88339566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
88342e4af2aeSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
88352e4af2aeSMatthew G. Knepley     PetscDS         ds;
88362e4af2aeSMatthew G. Knepley     DMLabel         label;
88372e4af2aeSMatthew G. Knepley     IS              fieldIS;
88382e4af2aeSMatthew G. Knepley     const PetscInt *fields;
88392e4af2aeSMatthew G. Knepley     PetscInt        dsNf;
88402e4af2aeSMatthew G. Knepley 
88419566063dSJacob Faibussowitsch     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds));
88429566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
88439566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISGetIndices(fieldIS, &fields));
88442e4af2aeSMatthew G. Knepley     for (f = 0; f < dsNf; ++f) {
88452e4af2aeSMatthew G. Knepley       const PetscInt field = fields[f];
88469566063dSJacob Faibussowitsch       PetscCall(PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]));
88472e4af2aeSMatthew G. Knepley     }
88489566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISRestoreIndices(fieldIS, &fields));
88492e4af2aeSMatthew G. Knepley   }
8850ad540459SPierre 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);
88519566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
88529566063dSJacob Faibussowitsch   if (errors) PetscCall(DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors));
88532e4af2aeSMatthew G. Knepley   if (errorVec) {
88542e4af2aeSMatthew G. Knepley     DM             edm;
88552e4af2aeSMatthew G. Knepley     DMPolytopeType ct;
88562e4af2aeSMatthew G. Knepley     PetscBool      simplex;
88572e4af2aeSMatthew G. Knepley     PetscInt       dim, cStart, Nf;
88582e4af2aeSMatthew G. Knepley 
88599566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &edm));
88609566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(edm, &dim));
88619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
88629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cStart, &ct));
88632e4af2aeSMatthew G. Knepley     simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
88649566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
88652e4af2aeSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
88662e4af2aeSMatthew G. Knepley       PetscFE         fe, efe;
88672e4af2aeSMatthew G. Knepley       PetscQuadrature q;
88682e4af2aeSMatthew G. Knepley       const char     *name;
88692e4af2aeSMatthew G. Knepley 
88709566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe));
88719566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe));
88729566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)fe, &name));
88739566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)efe, name));
88749566063dSJacob Faibussowitsch       PetscCall(PetscFEGetQuadrature(fe, &q));
88759566063dSJacob Faibussowitsch       PetscCall(PetscFESetQuadrature(efe, q));
88769566063dSJacob Faibussowitsch       PetscCall(DMSetField(edm, f, NULL, (PetscObject)efe));
88779566063dSJacob Faibussowitsch       PetscCall(PetscFEDestroy(&efe));
88782e4af2aeSMatthew G. Knepley     }
88799566063dSJacob Faibussowitsch     PetscCall(DMCreateDS(edm));
88802e4af2aeSMatthew G. Knepley 
88819566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(edm, errorVec));
88829566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*errorVec, "Error"));
88839566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec));
88849566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&edm));
88852e4af2aeSMatthew G. Knepley   }
88869566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exactSol, ctxs));
88872e4af2aeSMatthew G. Knepley   PetscFunctionReturn(0);
88882e4af2aeSMatthew G. Knepley }
88899a2a23afSMatthew G. Knepley 
88909a2a23afSMatthew G. Knepley /*@
8891bb7acecfSBarry Smith   DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this `DM`
88929a2a23afSMatthew G. Knepley 
88939a2a23afSMatthew G. Knepley   Not collective
88949a2a23afSMatthew G. Knepley 
88959a2a23afSMatthew G. Knepley   Input Parameter:
8896bb7acecfSBarry Smith . dm     - The `DM`
88979a2a23afSMatthew G. Knepley 
88989a2a23afSMatthew G. Knepley   Output Parameter:
8899a5b23f4aSJose E. Roman . numAux - The number of auxiliary data vectors
89009a2a23afSMatthew G. Knepley 
89019a2a23afSMatthew G. Knepley   Level: advanced
89029a2a23afSMatthew G. Knepley 
8903bb7acecfSBarry Smith .seealso: `DMSetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
89049a2a23afSMatthew G. Knepley @*/
8905d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux)
8906d71ae5a4SJacob Faibussowitsch {
89079a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89089a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89099566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetSize(dm->auxData, numAux));
89109a2a23afSMatthew G. Knepley   PetscFunctionReturn(0);
89119a2a23afSMatthew G. Knepley }
89129a2a23afSMatthew G. Knepley 
89139a2a23afSMatthew G. Knepley /*@
8914ac17215fSMatthew G. Knepley   DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value, and equation part
89159a2a23afSMatthew G. Knepley 
89169a2a23afSMatthew G. Knepley   Not collective
89179a2a23afSMatthew G. Knepley 
89189a2a23afSMatthew G. Knepley   Input Parameters:
8919bb7acecfSBarry Smith + dm     - The `DM`
8920bb7acecfSBarry Smith . label  - The `DMLabel`
8921ac17215fSMatthew G. Knepley . value  - The label value indicating the region
8922ac17215fSMatthew G. Knepley - part   - The equation part, or 0 if unused
89239a2a23afSMatthew G. Knepley 
89249a2a23afSMatthew G. Knepley   Output Parameter:
8925bb7acecfSBarry Smith . aux    - The `Vec` holding auxiliary field data
89269a2a23afSMatthew G. Knepley 
8927bb7acecfSBarry Smith   Note:
8928bb7acecfSBarry Smith   If no auxiliary vector is found for this (label, value), (NULL, 0, 0) is checked as well.
892904c51a94SMatthew G. Knepley 
89309a2a23afSMatthew G. Knepley   Level: advanced
89319a2a23afSMatthew G. Knepley 
8932bb7acecfSBarry Smith .seealso: `DMSetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryLabels()`
89339a2a23afSMatthew G. Knepley @*/
8934d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec *aux)
8935d71ae5a4SJacob Faibussowitsch {
8936ac17215fSMatthew G. Knepley   PetscHashAuxKey key, wild = {NULL, 0, 0};
893704c51a94SMatthew G. Knepley   PetscBool       has;
89389a2a23afSMatthew G. Knepley 
89399a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89409a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89419a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
89429a2a23afSMatthew G. Knepley   key.label = label;
89439a2a23afSMatthew G. Knepley   key.value = value;
8944ac17215fSMatthew G. Knepley   key.part  = part;
89459566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxHas(dm->auxData, key, &has));
89469566063dSJacob Faibussowitsch   if (has) PetscCall(PetscHMapAuxGet(dm->auxData, key, aux));
89479566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxGet(dm->auxData, wild, aux));
89489a2a23afSMatthew G. Knepley   PetscFunctionReturn(0);
89499a2a23afSMatthew G. Knepley }
89509a2a23afSMatthew G. Knepley 
89519a2a23afSMatthew G. Knepley /*@
8952bb7acecfSBarry Smith   DMSetAuxiliaryVec - Set an auxiliary vector for region specified by the given label and value, and equation part
89539a2a23afSMatthew G. Knepley 
8954bb7acecfSBarry Smith   Not collective because auxilary vectors are not parallel
89559a2a23afSMatthew G. Knepley 
89569a2a23afSMatthew G. Knepley   Input Parameters:
8957bb7acecfSBarry Smith + dm     - The `DM`
8958bb7acecfSBarry Smith . label  - The `DMLabel`
89599a2a23afSMatthew G. Knepley . value  - The label value indicating the region
8960ac17215fSMatthew G. Knepley . part   - The equation part, or 0 if unused
8961bb7acecfSBarry Smith - aux    - The `Vec` holding auxiliary field data
89629a2a23afSMatthew G. Knepley 
89639a2a23afSMatthew G. Knepley   Level: advanced
89649a2a23afSMatthew G. Knepley 
8965bb7acecfSBarry Smith .seealso: `DMGetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMCopyAuxiliaryVec()`
89669a2a23afSMatthew G. Knepley @*/
8967d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec aux)
8968d71ae5a4SJacob Faibussowitsch {
89699a2a23afSMatthew G. Knepley   Vec             old;
89709a2a23afSMatthew G. Knepley   PetscHashAuxKey key;
89719a2a23afSMatthew G. Knepley 
89729a2a23afSMatthew G. Knepley   PetscFunctionBegin;
89739a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89749a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
89759a2a23afSMatthew G. Knepley   key.label = label;
89769a2a23afSMatthew G. Knepley   key.value = value;
8977ac17215fSMatthew G. Knepley   key.part  = part;
89789566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGet(dm->auxData, key, &old));
89799566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)aux));
89809566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)old));
89819566063dSJacob Faibussowitsch   if (!aux) PetscCall(PetscHMapAuxDel(dm->auxData, key));
89829566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxSet(dm->auxData, key, aux));
89839a2a23afSMatthew G. Knepley   PetscFunctionReturn(0);
89849a2a23afSMatthew G. Knepley }
89859a2a23afSMatthew G. Knepley 
89869a2a23afSMatthew G. Knepley /*@C
8987bb7acecfSBarry Smith   DMGetAuxiliaryLabels - Get the labels, values, and parts for all auxiliary vectors in this `DM`
89889a2a23afSMatthew G. Knepley 
89899a2a23afSMatthew G. Knepley   Not collective
89909a2a23afSMatthew G. Knepley 
89919a2a23afSMatthew G. Knepley   Input Parameter:
8992bb7acecfSBarry Smith . dm      - The `DM`
89939a2a23afSMatthew G. Knepley 
89949a2a23afSMatthew G. Knepley   Output Parameters:
8995bb7acecfSBarry Smith + labels  - The `DMLabel`s for each `Vec`
8996bb7acecfSBarry Smith . values  - The label values for each `Vec`
8997bb7acecfSBarry Smith - parts   - The equation parts for each `Vec`
89989a2a23afSMatthew G. Knepley 
8999bb7acecfSBarry Smith   Note:
9000bb7acecfSBarry Smith   The arrays passed in must be at least as large as `DMGetNumAuxiliaryVec()`.
90019a2a23afSMatthew G. Knepley 
90029a2a23afSMatthew G. Knepley   Level: advanced
90039a2a23afSMatthew G. Knepley 
9004bb7acecfSBarry Smith .seealso: `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMSetAuxiliaryVec()`, DMCopyAuxiliaryVec()`
90059a2a23afSMatthew G. Knepley @*/
9006d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[], PetscInt parts[])
9007d71ae5a4SJacob Faibussowitsch {
90089a2a23afSMatthew G. Knepley   PetscHashAuxKey *keys;
90099a2a23afSMatthew G. Knepley   PetscInt         n, i, off = 0;
90109a2a23afSMatthew G. Knepley 
90119a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90129a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90139a2a23afSMatthew G. Knepley   PetscValidPointer(labels, 2);
9014dadcf809SJacob Faibussowitsch   PetscValidIntPointer(values, 3);
9015dadcf809SJacob Faibussowitsch   PetscValidIntPointer(parts, 4);
90169566063dSJacob Faibussowitsch   PetscCall(DMGetNumAuxiliaryVec(dm, &n));
90179566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &keys));
90189566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetKeys(dm->auxData, &off, keys));
90199371c9d4SSatish Balay   for (i = 0; i < n; ++i) {
90209371c9d4SSatish Balay     labels[i] = keys[i].label;
90219371c9d4SSatish Balay     values[i] = keys[i].value;
90229371c9d4SSatish Balay     parts[i]  = keys[i].part;
90239371c9d4SSatish Balay   }
90249566063dSJacob Faibussowitsch   PetscCall(PetscFree(keys));
90259a2a23afSMatthew G. Knepley   PetscFunctionReturn(0);
90269a2a23afSMatthew G. Knepley }
90279a2a23afSMatthew G. Knepley 
90289a2a23afSMatthew G. Knepley /*@
9029bb7acecfSBarry Smith   DMCopyAuxiliaryVec - Copy the auxiliary vector data on a `DM` to a new `DM`
90309a2a23afSMatthew G. Knepley 
90319a2a23afSMatthew G. Knepley   Not collective
90329a2a23afSMatthew G. Knepley 
90339a2a23afSMatthew G. Knepley   Input Parameter:
9034bb7acecfSBarry Smith . dm    - The `DM`
90359a2a23afSMatthew G. Knepley 
90369a2a23afSMatthew G. Knepley   Output Parameter:
9037bb7acecfSBarry Smith . dmNew - The new `DM`, now with the same auxiliary data
90389a2a23afSMatthew G. Knepley 
90399a2a23afSMatthew G. Knepley   Level: advanced
90409a2a23afSMatthew G. Knepley 
9041bb7acecfSBarry Smith   Note:
9042bb7acecfSBarry Smith   This is a shallow copy of the auxiliary vectors
9043bb7acecfSBarry Smith 
9044db781477SPatrick Sanan .seealso: `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
90459a2a23afSMatthew G. Knepley @*/
9046d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew)
9047d71ae5a4SJacob Faibussowitsch {
90489a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90499a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90509566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDestroy(&dmNew->auxData));
90519566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData));
90529a2a23afSMatthew G. Knepley   PetscFunctionReturn(0);
90539a2a23afSMatthew G. Knepley }
9054b5a892a1SMatthew G. Knepley 
9055b5a892a1SMatthew G. Knepley /*@C
9056bb7acecfSBarry Smith   DMPolytopeMatchOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9057b5a892a1SMatthew G. Knepley 
9058b5a892a1SMatthew G. Knepley   Not collective
9059b5a892a1SMatthew G. Knepley 
9060b5a892a1SMatthew G. Knepley   Input Parameters:
9061bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9062b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9063b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9064b5a892a1SMatthew G. Knepley 
9065b5a892a1SMatthew G. Knepley   Output Parameters:
9066bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9067b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9068b5a892a1SMatthew G. Knepley 
9069b5a892a1SMatthew G. Knepley   Level: advanced
9070b5a892a1SMatthew G. Knepley 
9071bb7acecfSBarry Smith   Note:
9072bb7acecfSBarry Smith   An arrangement is a face order combined with an orientation for each face
9073bb7acecfSBarry Smith 
9074bb7acecfSBarry Smith   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangments(ct)`/2 to `DMPolytopeTypeGetNumArrangments(ct)`/2
9075bb7acecfSBarry Smith   that labels each arrangement (face ordering plus orientation for each face).
9076bb7acecfSBarry Smith 
9077bb7acecfSBarry Smith   See `DMPolytopeMatchVertexOrientation()` to find a new vertex orientation that takes the source vertex arrangement to the target vertex arrangement
9078bb7acecfSBarry Smith 
9079bb7acecfSBarry Smith .seealso: `DMPolytopeGetOrientation()`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetVertexOrientation()`
9080b5a892a1SMatthew G. Knepley @*/
9081d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt, PetscBool *found)
9082d71ae5a4SJacob Faibussowitsch {
9083b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetConeSize(ct);
9084b5a892a1SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct) / 2;
9085b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9086b5a892a1SMatthew G. Knepley 
9087b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
90889371c9d4SSatish Balay   if (!nO) {
90899371c9d4SSatish Balay     *ornt  = 0;
90909371c9d4SSatish Balay     *found = PETSC_TRUE;
90919371c9d4SSatish Balay     PetscFunctionReturn(0);
90929371c9d4SSatish Balay   }
9093b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
9094b5a892a1SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
9095b5a892a1SMatthew G. Knepley 
90969371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
90979371c9d4SSatish Balay       if (sourceCone[arr[c * 2]] != targetCone[c]) break;
90989371c9d4SSatish Balay     if (c == cS) {
90999371c9d4SSatish Balay       *ornt = o;
91009371c9d4SSatish Balay       break;
91019371c9d4SSatish Balay     }
9102b5a892a1SMatthew G. Knepley   }
9103b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
9104b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
9105b5a892a1SMatthew G. Knepley }
9106b5a892a1SMatthew G. Knepley 
9107b5a892a1SMatthew G. Knepley /*@C
9108bb7acecfSBarry Smith   DMPolytopeGetOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9109b5a892a1SMatthew G. Knepley 
9110b5a892a1SMatthew G. Knepley   Not collective
9111b5a892a1SMatthew G. Knepley 
9112b5a892a1SMatthew G. Knepley   Input Parameters:
9113bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9114b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9115b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9116b5a892a1SMatthew G. Knepley 
9117b5a892a1SMatthew G. Knepley   Output Parameters:
9118bb7acecfSBarry Smith . ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9119b5a892a1SMatthew G. Knepley 
9120b5a892a1SMatthew G. Knepley   Level: advanced
9121b5a892a1SMatthew G. Knepley 
9122bb7acecfSBarry Smith   Note:
9123bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchOrientation()` except it will generate an error if no suitable orientation can be found.
9124bb7acecfSBarry Smith 
9125bb7acecfSBarry Smith   Developer Note:
9126bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchOrientation()` and error if none is found
9127bb7acecfSBarry Smith 
9128bb7acecfSBarry Smith .seealso: `DMPolytopeType`, `DMPolytopeMatchOrientation()`, `DMPolytopeGetVertexOrientation()`, `DMPolytopeMatchVertexOrientation()`
9129b5a892a1SMatthew G. Knepley @*/
9130d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9131d71ae5a4SJacob Faibussowitsch {
9132b5a892a1SMatthew G. Knepley   PetscBool found;
9133b5a892a1SMatthew G. Knepley 
9134b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91359566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchOrientation(ct, sourceCone, targetCone, ornt, &found));
91367a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
9137b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
9138b5a892a1SMatthew G. Knepley }
9139b5a892a1SMatthew G. Knepley 
9140b5a892a1SMatthew G. Knepley /*@C
9141bb7acecfSBarry Smith   DMPolytopeMatchVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9142b5a892a1SMatthew G. Knepley 
9143b5a892a1SMatthew G. Knepley   Not collective
9144b5a892a1SMatthew G. Knepley 
9145b5a892a1SMatthew G. Knepley   Input Parameters:
9146bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9147b5a892a1SMatthew G. Knepley . sourceVert - The source arrangement of vertices
9148b5a892a1SMatthew G. Knepley - targetVert - The target arrangement of vertices
9149b5a892a1SMatthew G. Knepley 
9150b5a892a1SMatthew G. Knepley   Output Parameters:
9151bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9152b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9153b5a892a1SMatthew G. Knepley 
9154b5a892a1SMatthew G. Knepley   Level: advanced
9155b5a892a1SMatthew G. Knepley 
9156bb7acecfSBarry Smith   Note:
9157bb7acecfSBarry Smith   An arrangement is a vertex order
9158bb7acecfSBarry Smith 
9159bb7acecfSBarry Smith   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangments(ct)`/2 to `DMPolytopeTypeGetNumArrangments(ct)`/2
9160bb7acecfSBarry Smith   that labels each arrangement (vertex ordering).
9161bb7acecfSBarry Smith 
9162bb7acecfSBarry Smith   See `DMPolytopeMatchOrientation()` to find a new face orientation that takes the source face arrangement to the target face arrangement
9163bb7acecfSBarry Smith 
9164bb7acecfSBarry Smith .seealso: `DMPolytopeType`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchOrientation()`, `DMPolytopeTypeGetNumVertices()`, `DMPolytopeTypeGetVertexArrangment()`
9165b5a892a1SMatthew G. Knepley @*/
9166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchVertexOrientation(DMPolytopeType ct, const PetscInt sourceVert[], const PetscInt targetVert[], PetscInt *ornt, PetscBool *found)
9167d71ae5a4SJacob Faibussowitsch {
9168b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetNumVertices(ct);
9169b5a892a1SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct) / 2;
9170b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9171b5a892a1SMatthew G. Knepley 
9172b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91739371c9d4SSatish Balay   if (!nO) {
91749371c9d4SSatish Balay     *ornt  = 0;
91759371c9d4SSatish Balay     *found = PETSC_TRUE;
91769371c9d4SSatish Balay     PetscFunctionReturn(0);
91779371c9d4SSatish Balay   }
9178b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
9179b5a892a1SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetVertexArrangment(ct, o);
9180b5a892a1SMatthew G. Knepley 
91819371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
91829371c9d4SSatish Balay       if (sourceVert[arr[c]] != targetVert[c]) break;
91839371c9d4SSatish Balay     if (c == cS) {
91849371c9d4SSatish Balay       *ornt = o;
91859371c9d4SSatish Balay       break;
91869371c9d4SSatish Balay     }
9187b5a892a1SMatthew G. Knepley   }
9188b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
9189b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
9190b5a892a1SMatthew G. Knepley }
9191b5a892a1SMatthew G. Knepley 
9192b5a892a1SMatthew G. Knepley /*@C
9193bb7acecfSBarry Smith   DMPolytopeGetVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9194b5a892a1SMatthew G. Knepley 
9195b5a892a1SMatthew G. Knepley   Not collective
9196b5a892a1SMatthew G. Knepley 
9197b5a892a1SMatthew G. Knepley   Input Parameters:
9198bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9199b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of vertices
9200b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of vertices
9201b5a892a1SMatthew G. Knepley 
9202b5a892a1SMatthew G. Knepley   Output Parameters:
9203bb7acecfSBarry Smith . ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9204b5a892a1SMatthew G. Knepley 
9205b5a892a1SMatthew G. Knepley   Level: advanced
9206b5a892a1SMatthew G. Knepley 
9207bb7acecfSBarry Smith   Note:
9208bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchVertexOrientation()` except it errors if not orientation is possible.
9209bb7acecfSBarry Smith 
9210bb7acecfSBarry Smith   Developer Note:
9211bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchVertexOrientation()` and error if none is found
9212bb7acecfSBarry Smith 
9213bb7acecfSBarry Smith .seealso: `DMPolytopeType`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetOrientation()`
9214b5a892a1SMatthew G. Knepley @*/
9215d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetVertexOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9216d71ae5a4SJacob Faibussowitsch {
9217b5a892a1SMatthew G. Knepley   PetscBool found;
9218b5a892a1SMatthew G. Knepley 
9219b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
92209566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchVertexOrientation(ct, sourceCone, targetCone, ornt, &found));
92217a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
9222b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
9223b5a892a1SMatthew G. Knepley }
9224012bc364SMatthew G. Knepley 
9225012bc364SMatthew G. Knepley /*@C
9226012bc364SMatthew G. Knepley   DMPolytopeInCellTest - Check whether a point lies inside the reference cell of given type
9227012bc364SMatthew G. Knepley 
9228012bc364SMatthew G. Knepley   Not collective
9229012bc364SMatthew G. Knepley 
9230012bc364SMatthew G. Knepley   Input Parameters:
9231bb7acecfSBarry Smith + ct    - The `DMPolytopeType`
9232012bc364SMatthew G. Knepley - point - Coordinates of the point
9233012bc364SMatthew G. Knepley 
9234012bc364SMatthew G. Knepley   Output Parameters:
9235012bc364SMatthew G. Knepley . inside  - Flag indicating whether the point is inside the reference cell of given type
9236012bc364SMatthew G. Knepley 
9237012bc364SMatthew G. Knepley   Level: advanced
9238012bc364SMatthew G. Knepley 
9239bb7acecfSBarry Smith .seealso: `DM`, `DMPolytopeType`, `DMLocatePoints()`
9240012bc364SMatthew G. Knepley @*/
9241d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeInCellTest(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
9242d71ae5a4SJacob Faibussowitsch {
9243012bc364SMatthew G. Knepley   PetscReal sum = 0.0;
9244012bc364SMatthew G. Knepley   PetscInt  d;
9245012bc364SMatthew G. Knepley 
9246012bc364SMatthew G. Knepley   PetscFunctionBegin;
9247012bc364SMatthew G. Knepley   *inside = PETSC_TRUE;
9248012bc364SMatthew G. Knepley   switch (ct) {
9249012bc364SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
9250012bc364SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
9251012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
92529371c9d4SSatish Balay       if (point[d] < -1.0) {
92539371c9d4SSatish Balay         *inside = PETSC_FALSE;
92549371c9d4SSatish Balay         break;
92559371c9d4SSatish Balay       }
9256012bc364SMatthew G. Knepley       sum += point[d];
9257012bc364SMatthew G. Knepley     }
92589371c9d4SSatish Balay     if (sum > PETSC_SMALL) {
92599371c9d4SSatish Balay       *inside = PETSC_FALSE;
92609371c9d4SSatish Balay       break;
92619371c9d4SSatish Balay     }
9262012bc364SMatthew G. Knepley     break;
9263012bc364SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
9264012bc364SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
9265012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
92669371c9d4SSatish Balay       if (PetscAbsReal(point[d]) > 1. + PETSC_SMALL) {
92679371c9d4SSatish Balay         *inside = PETSC_FALSE;
9268012bc364SMatthew G. Knepley         break;
92699371c9d4SSatish Balay       }
92709371c9d4SSatish Balay     break;
9271d71ae5a4SJacob Faibussowitsch   default:
9272d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
9273012bc364SMatthew G. Knepley   }
9274012bc364SMatthew G. Knepley   PetscFunctionReturn(0);
9275012bc364SMatthew G. Knepley }
9276