xref: /petsc/src/dm/interface/dm.c (revision c8a418c4ab7d8b9bd837a28b8b94b8bd2f756001)
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>
6d2b2dc1eSMatthew G. Knepley #include <petscdmceed.h>
7f19dbd58SToby Isaac #include <petscdmfield.h>
80c312b8eSJed Brown #include <petscsf.h>
92764a2aaSMatthew G. Knepley #include <petscds.h>
1047c6ae99SBarry Smith 
11f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
12f918ec44SMatthew G. Knepley   #include <petscfeceed.h>
13f918ec44SMatthew G. Knepley #endif
14f918ec44SMatthew G. Knepley 
15732e2eb9SMatthew G Knepley PetscClassId DM_CLASSID;
16d67d17b1SMatthew G. Knepley PetscClassId DMLABEL_CLASSID;
1742d0c57aSJames Wright 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_View, DM_AdaptInterpolator, DM_ProjectFunction;
1867a56275SMatthew G Knepley 
19ea78f98cSLisandro Dalcin const char *const DMBoundaryTypes[]          = {"NONE", "GHOSTED", "MIRROR", "PERIODIC", "TWIST", "DMBoundaryType", "DM_BOUNDARY_", NULL};
20d1b3049bSMatthew 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};
210e762ea3SJed Brown const char *const DMBlockingTypes[]          = {"TOPOLOGICAL_POINT", "FIELD_NODE", "DMBlockingType", "DM_BLOCKING_", NULL};
22476787b7SMatthew G. Knepley const char *const DMPolytopeTypes[] =
23476787b7SMatthew G. Knepley   {"vertex",  "segment",      "tensor_segment", "triangle", "quadrilateral",  "tensor_quad",  "tetrahedron", "hexahedron", "triangular_prism", "tensor_triangular_prism", "tensor_quadrilateral_prism", "pyramid", "FV_ghost_cell", "interior_ghost_cell",
24476787b7SMatthew G. Knepley    "unknown", "unknown_cell", "unknown_face",   "invalid",  "DMPolytopeType", "DM_POLYTOPE_", NULL};
252cbb9b06SVaclav Hapla const char *const DMCopyLabelsModes[] = {"replace", "keep", "fail", "DMCopyLabelsMode", "DM_COPY_LABELS_", NULL};
2660c22052SBarry Smith 
27a4121054SBarry Smith /*@
28bb7acecfSBarry Smith   DMCreate - Creates an empty `DM` object. `DM`s are the abstract objects in PETSc that mediate between meshes and discretizations and the
290b4b7b1cSBarry Smith   algebraic solvers, time integrators, and optimization algorithms in PETSc.
30a4121054SBarry Smith 
31d083f849SBarry Smith   Collective
32a4121054SBarry Smith 
33a4121054SBarry Smith   Input Parameter:
34bb7acecfSBarry Smith . comm - The communicator for the `DM` object
35a4121054SBarry Smith 
36a4121054SBarry Smith   Output Parameter:
37bb7acecfSBarry Smith . dm - The `DM` object
38a4121054SBarry Smith 
39a4121054SBarry Smith   Level: beginner
40a4121054SBarry Smith 
41bb7acecfSBarry Smith   Notes:
42bb7acecfSBarry Smith   See `DMType` for a brief summary of available `DM`.
43bb7acecfSBarry Smith 
44bb7acecfSBarry Smith   The type must then be set with `DMSetType()`. If you never call `DMSetType()` it will generate an
450b4b7b1cSBarry Smith   error when you try to use the `dm`.
460b4b7b1cSBarry Smith 
470b4b7b1cSBarry Smith   `DM` is an orphan initialism or orphan acronym, the letters have no meaning and never did.
48bb7acecfSBarry Smith 
491cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetType()`, `DMType`, `DMDACreate()`, `DMDA`, `DMSLICED`, `DMCOMPOSITE`, `DMPLEX`, `DMMOAB`, `DMNETWORK`
50a4121054SBarry Smith @*/
51d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreate(MPI_Comm comm, DM *dm)
52d71ae5a4SJacob Faibussowitsch {
53a4121054SBarry Smith   DM      v;
54e5e52638SMatthew G. Knepley   PetscDS ds;
55a4121054SBarry Smith 
56a4121054SBarry Smith   PetscFunctionBegin;
574f572ea9SToby Isaac   PetscAssertPointer(dm, 2);
58377f809aSBarry Smith 
599566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
609566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView));
6162e5d2d2SJDBetteridge   ((PetscObject)v)->non_cyclic_references = &DMCountNonCyclicReferences;
6249be4549SMatthew G. Knepley   v->setupcalled                          = PETSC_FALSE;
6349be4549SMatthew G. Knepley   v->setfromoptionscalled                 = PETSC_FALSE;
640298fd71SBarry Smith   v->ltogmap                              = NULL;
65a4ea9b21SRichard Tran Mills   v->bind_below                           = 0;
661411c6eeSJed Brown   v->bs                                   = 1;
67171400e9SBarry Smith   v->coloringtype                         = IS_COLORING_GLOBAL;
689566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &v->sf));
699566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &v->sectionSF));
70c58f1c22SToby Isaac   v->labels                    = NULL;
7134aa8a36SMatthew G. Knepley   v->adjacency[0]              = PETSC_FALSE;
7234aa8a36SMatthew G. Knepley   v->adjacency[1]              = PETSC_TRUE;
73c58f1c22SToby Isaac   v->depthLabel                = NULL;
74ba2698f1SMatthew G. Knepley   v->celltypeLabel             = NULL;
751bb6d2a8SBarry Smith   v->localSection              = NULL;
761bb6d2a8SBarry Smith   v->globalSection             = NULL;
773b8ba7d1SJed Brown   v->defaultConstraint.section = NULL;
783b8ba7d1SJed Brown   v->defaultConstraint.mat     = NULL;
7979769bd5SJed Brown   v->defaultConstraint.bias    = NULL;
806858538eSMatthew G. Knepley   v->coordinates[0].dim        = PETSC_DEFAULT;
816858538eSMatthew G. Knepley   v->coordinates[1].dim        = PETSC_DEFAULT;
826858538eSMatthew G. Knepley   v->sparseLocalize            = PETSC_TRUE;
8396173672SStefano Zampini   v->dim                       = PETSC_DETERMINE;
84435a35e8SMatthew G Knepley   {
85435a35e8SMatthew G Knepley     PetscInt i;
86435a35e8SMatthew G Knepley     for (i = 0; i < 10; ++i) {
870298fd71SBarry Smith       v->nullspaceConstructors[i]     = NULL;
88f9d4088aSMatthew G. Knepley       v->nearnullspaceConstructors[i] = NULL;
89435a35e8SMatthew G Knepley     }
90435a35e8SMatthew G Knepley   }
919566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
9207218a29SMatthew G. Knepley   PetscCall(DMSetRegionDS(v, NULL, NULL, ds, NULL));
939566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&ds));
949566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxCreate(&v->auxData));
9514f150ffSMatthew G. Knepley   v->dmBC              = NULL;
96a8fb8f29SToby Isaac   v->coarseMesh        = NULL;
97f4d763aaSMatthew G. Knepley   v->outputSequenceNum = -1;
98cdb7a50dSMatthew G. Knepley   v->outputSequenceVal = 0.0;
999566063dSJacob Faibussowitsch   PetscCall(DMSetVecType(v, VECSTANDARD));
1009566063dSJacob Faibussowitsch   PetscCall(DMSetMatType(v, MATAIJ));
1014a7a4c06SLawrence Mitchell 
1021411c6eeSJed Brown   *dm = v;
1033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
104a4121054SBarry Smith }
105a4121054SBarry Smith 
10638221697SMatthew G. Knepley /*@
107bb7acecfSBarry Smith   DMClone - Creates a `DM` object with the same topology as the original.
10838221697SMatthew G. Knepley 
109d083f849SBarry Smith   Collective
11038221697SMatthew G. Knepley 
11138221697SMatthew G. Knepley   Input Parameter:
112bb7acecfSBarry Smith . dm - The original `DM` object
11338221697SMatthew G. Knepley 
11438221697SMatthew G. Knepley   Output Parameter:
115bb7acecfSBarry Smith . newdm - The new `DM` object
11638221697SMatthew G. Knepley 
11738221697SMatthew G. Knepley   Level: beginner
11838221697SMatthew G. Knepley 
1191cb8cacdSPatrick Sanan   Notes:
120bb7acecfSBarry Smith   For some `DM` implementations this is a shallow clone, the result of which may share (reference counted) information with its parent. For example,
121bb7acecfSBarry Smith   `DMClone()` applied to a `DMPLEX` object will result in a new `DMPLEX` that shares the topology with the original `DMPLEX`. It does not
122bb7acecfSBarry Smith   share the `PetscSection` of the original `DM`.
1231bb6d2a8SBarry Smith 
124bb7acecfSBarry Smith   The clone is considered set up if the original has been set up.
12589706ed2SPatrick Sanan 
126bb7acecfSBarry Smith   Use `DMConvert()` for a general way to create new `DM` from a given `DM`
127bb7acecfSBarry Smith 
12860225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMSetType()`, `DMSetLocalSection()`, `DMSetGlobalSection()`, `DMPLEX`, `DMConvert()`
12938221697SMatthew G. Knepley @*/
130d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClone(DM dm, DM *newdm)
131d71ae5a4SJacob Faibussowitsch {
13238221697SMatthew G. Knepley   PetscSF              sf;
13338221697SMatthew G. Knepley   Vec                  coords;
13438221697SMatthew G. Knepley   void                *ctx;
135ec196627SMatthew G. Knepley   MatOrderingType      otype;
136ec196627SMatthew G. Knepley   DMReorderDefaultFlag flg;
1376858538eSMatthew G. Knepley   PetscInt             dim, cdim, i;
13838221697SMatthew G. Knepley 
13938221697SMatthew G. Knepley   PetscFunctionBegin;
14038221697SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1414f572ea9SToby Isaac   PetscAssertPointer(newdm, 2);
1429566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), newdm));
1439566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dm, *newdm, PETSC_COPY_VALUES, PETSC_TRUE, DM_COPY_LABELS_FAIL));
144ddf8437dSMatthew G. Knepley   (*newdm)->leveldown     = dm->leveldown;
145ddf8437dSMatthew G. Knepley   (*newdm)->levelup       = dm->levelup;
146c8a6034eSMark   (*newdm)->prealloc_only = dm->prealloc_only;
147fc214432SJed Brown   (*newdm)->prealloc_skip = dm->prealloc_skip;
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));
160ec196627SMatthew G. Knepley   PetscCall(DMReorderSectionGetDefault(dm, &flg));
161ec196627SMatthew G. Knepley   PetscCall(DMReorderSectionSetDefault(*newdm, flg));
162ec196627SMatthew G. Knepley   PetscCall(DMReorderSectionGetType(dm, &otype));
163ec196627SMatthew G. Knepley   PetscCall(DMReorderSectionSetType(*newdm, otype));
1646858538eSMatthew G. Knepley   for (i = 0; i < 2; ++i) {
1656858538eSMatthew G. Knepley     if (dm->coordinates[i].dm) {
166be4c1c3eSMatthew G. Knepley       DM           ncdm;
167be4c1c3eSMatthew G. Knepley       PetscSection cs;
1685a0206caSToby Isaac       PetscInt     pEnd = -1, pEndMax = -1;
169be4c1c3eSMatthew G. Knepley 
1706858538eSMatthew G. Knepley       PetscCall(DMGetLocalSection(dm->coordinates[i].dm, &cs));
1719566063dSJacob Faibussowitsch       if (cs) PetscCall(PetscSectionGetChart(cs, NULL, &pEnd));
172462c564dSBarry Smith       PetscCallMPI(MPIU_Allreduce(&pEnd, &pEndMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1735a0206caSToby Isaac       if (pEndMax >= 0) {
1746858538eSMatthew G. Knepley         PetscCall(DMClone(dm->coordinates[i].dm, &ncdm));
1756858538eSMatthew G. Knepley         PetscCall(DMCopyDisc(dm->coordinates[i].dm, ncdm));
1769566063dSJacob Faibussowitsch         PetscCall(DMSetLocalSection(ncdm, cs));
1775e50ca95SJames Wright         if (dm->coordinates[i].dm->periodic.setup) {
1785e50ca95SJames Wright           ncdm->periodic.setup = dm->coordinates[i].dm->periodic.setup;
1795e50ca95SJames Wright           PetscCall(ncdm->periodic.setup(ncdm));
1805e50ca95SJames Wright         }
1816858538eSMatthew G. Knepley         if (i) PetscCall(DMSetCellCoordinateDM(*newdm, ncdm));
1826858538eSMatthew G. Knepley         else PetscCall(DMSetCoordinateDM(*newdm, ncdm));
1839566063dSJacob Faibussowitsch         PetscCall(DMDestroy(&ncdm));
184be4c1c3eSMatthew G. Knepley       }
185be4c1c3eSMatthew G. Knepley     }
1866858538eSMatthew G. Knepley   }
1879566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1889566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*newdm, cdim));
1899566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coords));
19038221697SMatthew G. Knepley   if (coords) {
1919566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(*newdm, coords));
19238221697SMatthew G. Knepley   } else {
1939566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinates(dm, &coords));
1949566063dSJacob Faibussowitsch     if (coords) PetscCall(DMSetCoordinates(*newdm, coords));
19538221697SMatthew G. Knepley   }
1966858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &coords));
1976858538eSMatthew G. Knepley   if (coords) {
1986858538eSMatthew G. Knepley     PetscCall(DMSetCellCoordinatesLocal(*newdm, coords));
1996858538eSMatthew G. Knepley   } else {
2006858538eSMatthew G. Knepley     PetscCall(DMGetCellCoordinates(dm, &coords));
2016858538eSMatthew G. Knepley     if (coords) PetscCall(DMSetCellCoordinates(*newdm, coords));
2026858538eSMatthew G. Knepley   }
20390b157c4SStefano Zampini   {
2044fb89dddSMatthew G. Knepley     const PetscReal *maxCell, *Lstart, *L;
2056858538eSMatthew G. Knepley 
2064fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
2074fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(*newdm, maxCell, Lstart, L));
208c6b900c6SMatthew G. Knepley   }
20934aa8a36SMatthew G. Knepley   {
21034aa8a36SMatthew G. Knepley     PetscBool useCone, useClosure;
21134aa8a36SMatthew G. Knepley 
2129566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, PETSC_DEFAULT, &useCone, &useClosure));
2139566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(*newdm, PETSC_DEFAULT, useCone, useClosure));
21434aa8a36SMatthew G. Knepley   }
2153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21638221697SMatthew G. Knepley }
21738221697SMatthew G. Knepley 
2185d83a8b1SBarry Smith /*@
2195d83a8b1SBarry Smith   DMSetVecType - Sets the type of vector to be created with `DMCreateLocalVector()` and `DMCreateGlobalVector()`
2209a42bb27SBarry Smith 
22120f4b53cSBarry Smith   Logically Collective
2229a42bb27SBarry Smith 
223147403d9SBarry Smith   Input Parameters:
22432546409SMatthew G. Knepley + dm    - initial distributed array
225bb7acecfSBarry Smith - ctype - the vector type, for example `VECSTANDARD`, `VECCUDA`, or `VECVIENNACL`
2269a42bb27SBarry Smith 
22720f4b53cSBarry Smith   Options Database Key:
228147403d9SBarry Smith . -dm_vec_type ctype - the type of vector to create
2299a42bb27SBarry Smith 
2309a42bb27SBarry Smith   Level: intermediate
2319a42bb27SBarry Smith 
23260225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMDestroy()`, `DMDAInterpolationType`, `VecType`, `DMGetVecType()`, `DMSetMatType()`, `DMGetMatType()`,
233bb7acecfSBarry Smith           `VECSTANDARD`, `VECCUDA`, `VECVIENNACL`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`
2349a42bb27SBarry Smith @*/
23532546409SMatthew G. Knepley PetscErrorCode DMSetVecType(DM dm, VecType ctype)
236d71ae5a4SJacob Faibussowitsch {
23732546409SMatthew G. Knepley   char *tmp;
23832546409SMatthew G. Knepley 
2399a42bb27SBarry Smith   PetscFunctionBegin;
24032546409SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24132546409SMatthew G. Knepley   PetscAssertPointer(ctype, 2);
24232546409SMatthew G. Knepley   tmp = (char *)dm->vectype;
24332546409SMatthew G. Knepley   PetscCall(PetscStrallocpy(ctype, (char **)&dm->vectype));
24432546409SMatthew G. Knepley   PetscCall(PetscFree(tmp));
2453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2469a42bb27SBarry Smith }
2479a42bb27SBarry Smith 
2485d83a8b1SBarry Smith /*@
249bb7acecfSBarry Smith   DMGetVecType - Gets the type of vector created with `DMCreateLocalVector()` and `DMCreateGlobalVector()`
250c0dedaeaSBarry Smith 
25120f4b53cSBarry Smith   Logically Collective
252c0dedaeaSBarry Smith 
253c0dedaeaSBarry Smith   Input Parameter:
254c0dedaeaSBarry Smith . da - initial distributed array
255c0dedaeaSBarry Smith 
256c0dedaeaSBarry Smith   Output Parameter:
257c0dedaeaSBarry Smith . ctype - the vector type
258c0dedaeaSBarry Smith 
259c0dedaeaSBarry Smith   Level: intermediate
260c0dedaeaSBarry Smith 
26160225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMDestroy()`, `DMDAInterpolationType`, `VecType`, `DMSetMatType()`, `DMGetMatType()`, `DMSetVecType()`
262c0dedaeaSBarry Smith @*/
263d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetVecType(DM da, VecType *ctype)
264d71ae5a4SJacob Faibussowitsch {
265c0dedaeaSBarry Smith   PetscFunctionBegin;
266c0dedaeaSBarry Smith   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
267c0dedaeaSBarry Smith   *ctype = da->vectype;
2683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
269c0dedaeaSBarry Smith }
270c0dedaeaSBarry Smith 
2715f1ad066SMatthew G Knepley /*@
272bb7acecfSBarry Smith   VecGetDM - Gets the `DM` defining the data layout of the vector
2735f1ad066SMatthew G Knepley 
27420f4b53cSBarry Smith   Not Collective
2755f1ad066SMatthew G Knepley 
2765f1ad066SMatthew G Knepley   Input Parameter:
277bb7acecfSBarry Smith . v - The `Vec`
2785f1ad066SMatthew G Knepley 
2795f1ad066SMatthew G Knepley   Output Parameter:
280bb7acecfSBarry Smith . dm - The `DM`
2815f1ad066SMatthew G Knepley 
2825f1ad066SMatthew G Knepley   Level: intermediate
2835f1ad066SMatthew G Knepley 
284bb7acecfSBarry Smith   Note:
285bb7acecfSBarry Smith   A `Vec` may not have a `DM` associated with it.
286bb7acecfSBarry Smith 
2871cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecSetDM()`, `DMGetLocalVector()`, `DMGetGlobalVector()`, `DMSetVecType()`
2885f1ad066SMatthew G Knepley @*/
289d71ae5a4SJacob Faibussowitsch PetscErrorCode VecGetDM(Vec v, DM *dm)
290d71ae5a4SJacob Faibussowitsch {
2915f1ad066SMatthew G Knepley   PetscFunctionBegin;
2925f1ad066SMatthew G Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
2934f572ea9SToby Isaac   PetscAssertPointer(dm, 2);
2949566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)v, "__PETSc_dm", (PetscObject *)dm));
2953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2965f1ad066SMatthew G Knepley }
2975f1ad066SMatthew G Knepley 
2985f1ad066SMatthew G Knepley /*@
299bb7acecfSBarry Smith   VecSetDM - Sets the `DM` defining the data layout of the vector.
3005f1ad066SMatthew G Knepley 
30120f4b53cSBarry Smith   Not Collective
3025f1ad066SMatthew G Knepley 
3035f1ad066SMatthew G Knepley   Input Parameters:
304bb7acecfSBarry Smith + v  - The `Vec`
305bb7acecfSBarry Smith - dm - The `DM`
3065f1ad066SMatthew G Knepley 
30720f4b53cSBarry Smith   Level: developer
30820f4b53cSBarry Smith 
30973ff1848SBarry Smith   Notes:
310bb7acecfSBarry Smith   This is rarely used, generally one uses `DMGetLocalVector()` or  `DMGetGlobalVector()` to create a vector associated with a given `DM`
311d9805387SMatthew G. Knepley 
312bb7acecfSBarry 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.
313bb7acecfSBarry Smith 
3141cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecGetDM()`, `DMGetLocalVector()`, `DMGetGlobalVector()`, `DMSetVecType()`
3155f1ad066SMatthew G Knepley @*/
316d71ae5a4SJacob Faibussowitsch PetscErrorCode VecSetDM(Vec v, DM dm)
317d71ae5a4SJacob Faibussowitsch {
3185f1ad066SMatthew G Knepley   PetscFunctionBegin;
3195f1ad066SMatthew G Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
320d7f50e27SLisandro Dalcin   if (dm) PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
3219566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)v, "__PETSc_dm", (PetscObject)dm));
3223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3235f1ad066SMatthew G Knepley }
3245f1ad066SMatthew G Knepley 
325cc4c1da9SBarry Smith /*@
326bb7acecfSBarry Smith   DMSetISColoringType - Sets the type of coloring, `IS_COLORING_GLOBAL` or `IS_COLORING_LOCAL` that is created by the `DM`
3278f1509bcSBarry Smith 
32820f4b53cSBarry Smith   Logically Collective
3298f1509bcSBarry Smith 
3308f1509bcSBarry Smith   Input Parameters:
331bb7acecfSBarry Smith + dm    - the `DM` context
3328f1509bcSBarry Smith - ctype - the matrix type
3338f1509bcSBarry Smith 
33420f4b53cSBarry Smith   Options Database Key:
3358f1509bcSBarry Smith . -dm_is_coloring_type - global or local
3368f1509bcSBarry Smith 
3378f1509bcSBarry Smith   Level: intermediate
3388f1509bcSBarry Smith 
3391cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMGetMatType()`,
340bb7acecfSBarry Smith           `DMGetISColoringType()`, `ISColoringType`, `IS_COLORING_GLOBAL`, `IS_COLORING_LOCAL`
3418f1509bcSBarry Smith @*/
342d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetISColoringType(DM dm, ISColoringType ctype)
343d71ae5a4SJacob Faibussowitsch {
3448f1509bcSBarry Smith   PetscFunctionBegin;
3458f1509bcSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3468f1509bcSBarry Smith   dm->coloringtype = ctype;
3473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3488f1509bcSBarry Smith }
3498f1509bcSBarry Smith 
350cc4c1da9SBarry Smith /*@
351bb7acecfSBarry Smith   DMGetISColoringType - Gets the type of coloring, `IS_COLORING_GLOBAL` or `IS_COLORING_LOCAL` that is created by the `DM`
352521d9a4cSLisandro Dalcin 
35320f4b53cSBarry Smith   Logically Collective
354521d9a4cSLisandro Dalcin 
355521d9a4cSLisandro Dalcin   Input Parameter:
356bb7acecfSBarry Smith . dm - the `DM` context
3578f1509bcSBarry Smith 
3588f1509bcSBarry Smith   Output Parameter:
3598f1509bcSBarry Smith . ctype - the matrix type
3608f1509bcSBarry Smith 
36120f4b53cSBarry Smith   Options Database Key:
3628f1509bcSBarry Smith . -dm_is_coloring_type - global or local
3638f1509bcSBarry Smith 
3648f1509bcSBarry Smith   Level: intermediate
3658f1509bcSBarry Smith 
3661cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMGetMatType()`,
36742747ad1SJacob Faibussowitsch           `ISColoringType`, `IS_COLORING_GLOBAL`, `IS_COLORING_LOCAL`
3688f1509bcSBarry Smith @*/
369d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetISColoringType(DM dm, ISColoringType *ctype)
370d71ae5a4SJacob Faibussowitsch {
3718f1509bcSBarry Smith   PetscFunctionBegin;
3728f1509bcSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3738f1509bcSBarry Smith   *ctype = dm->coloringtype;
3743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3758f1509bcSBarry Smith }
3768f1509bcSBarry Smith 
377cc4c1da9SBarry Smith /*@
378bb7acecfSBarry Smith   DMSetMatType - Sets the type of matrix created with `DMCreateMatrix()`
3798f1509bcSBarry Smith 
38020f4b53cSBarry Smith   Logically Collective
3818f1509bcSBarry Smith 
3828f1509bcSBarry Smith   Input Parameters:
383bb7acecfSBarry Smith + dm    - the `DM` context
384bb7acecfSBarry Smith - ctype - the matrix type, for example `MATMPIAIJ`
385521d9a4cSLisandro Dalcin 
38620f4b53cSBarry Smith   Options Database Key:
387bb7acecfSBarry Smith . -dm_mat_type ctype - the type of the matrix to create, for example mpiaij
388521d9a4cSLisandro Dalcin 
389521d9a4cSLisandro Dalcin   Level: intermediate
390521d9a4cSLisandro Dalcin 
39142747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `MatType`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `DMGetMatType()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
392521d9a4cSLisandro Dalcin @*/
393d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatType(DM dm, MatType ctype)
394d71ae5a4SJacob Faibussowitsch {
39532546409SMatthew G. Knepley   char *tmp;
39632546409SMatthew G. Knepley 
397521d9a4cSLisandro Dalcin   PetscFunctionBegin;
398521d9a4cSLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39932546409SMatthew G. Knepley   PetscAssertPointer(ctype, 2);
40032546409SMatthew G. Knepley   tmp = (char *)dm->mattype;
4019566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ctype, (char **)&dm->mattype));
40232546409SMatthew G. Knepley   PetscCall(PetscFree(tmp));
4033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
404521d9a4cSLisandro Dalcin }
405521d9a4cSLisandro Dalcin 
406cc4c1da9SBarry Smith /*@
40720f4b53cSBarry Smith   DMGetMatType - Gets the type of matrix that would be created with `DMCreateMatrix()`
408c0dedaeaSBarry Smith 
40920f4b53cSBarry Smith   Logically Collective
410c0dedaeaSBarry Smith 
411c0dedaeaSBarry Smith   Input Parameter:
412bb7acecfSBarry Smith . dm - the `DM` context
413c0dedaeaSBarry Smith 
414c0dedaeaSBarry Smith   Output Parameter:
415c0dedaeaSBarry Smith . ctype - the matrix type
416c0dedaeaSBarry Smith 
417c0dedaeaSBarry Smith   Level: intermediate
418c0dedaeaSBarry Smith 
41942747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMSetMatType()`
420c0dedaeaSBarry Smith @*/
421d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetMatType(DM dm, MatType *ctype)
422d71ae5a4SJacob Faibussowitsch {
423c0dedaeaSBarry Smith   PetscFunctionBegin;
424c0dedaeaSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
425c0dedaeaSBarry Smith   *ctype = dm->mattype;
4263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
427c0dedaeaSBarry Smith }
428c0dedaeaSBarry Smith 
429c688c046SMatthew G Knepley /*@
430bb7acecfSBarry Smith   MatGetDM - Gets the `DM` defining the data layout of the matrix
431c688c046SMatthew G Knepley 
43220f4b53cSBarry Smith   Not Collective
433c688c046SMatthew G Knepley 
434c688c046SMatthew G Knepley   Input Parameter:
435bb7acecfSBarry Smith . A - The `Mat`
436c688c046SMatthew G Knepley 
437c688c046SMatthew G Knepley   Output Parameter:
438bb7acecfSBarry Smith . dm - The `DM`
439c688c046SMatthew G Knepley 
440c688c046SMatthew G Knepley   Level: intermediate
441c688c046SMatthew G Knepley 
442bb7acecfSBarry Smith   Note:
443bb7acecfSBarry Smith   A matrix may not have a `DM` associated with it
444bb7acecfSBarry Smith 
44573ff1848SBarry Smith   Developer Note:
446bb7acecfSBarry Smith   Since the `Mat` class doesn't know about the `DM` class the `DM` object is associated with the `Mat` through a `PetscObjectCompose()` operation
4478f1509bcSBarry Smith 
4481cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatSetDM()`, `DMCreateMatrix()`, `DMSetMatType()`
449c688c046SMatthew G Knepley @*/
450d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDM(Mat A, DM *dm)
451d71ae5a4SJacob Faibussowitsch {
452c688c046SMatthew G Knepley   PetscFunctionBegin;
453c688c046SMatthew G Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4544f572ea9SToby Isaac   PetscAssertPointer(dm, 2);
4559566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_dm", (PetscObject *)dm));
4563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
457c688c046SMatthew G Knepley }
458c688c046SMatthew G Knepley 
459c688c046SMatthew G Knepley /*@
460bb7acecfSBarry Smith   MatSetDM - Sets the `DM` defining the data layout of the matrix
461c688c046SMatthew G Knepley 
46220f4b53cSBarry Smith   Not Collective
463c688c046SMatthew G Knepley 
464c688c046SMatthew G Knepley   Input Parameters:
46520f4b53cSBarry Smith + A  - The `Mat`
46620f4b53cSBarry Smith - dm - The `DM`
467c688c046SMatthew G Knepley 
468bb7acecfSBarry Smith   Level: developer
469c688c046SMatthew G Knepley 
470bb7acecfSBarry Smith   Note:
471bb7acecfSBarry Smith   This is rarely used in practice, rather `DMCreateMatrix()` is used to create a matrix associated with a particular `DM`
472bb7acecfSBarry Smith 
47373ff1848SBarry Smith   Developer Note:
474bb7acecfSBarry Smith   Since the `Mat` class doesn't know about the `DM` class the `DM` object is associated with
475bb7acecfSBarry Smith   the `Mat` through a `PetscObjectCompose()` operation
4768f1509bcSBarry Smith 
4771cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatGetDM()`, `DMCreateMatrix()`, `DMSetMatType()`
478c688c046SMatthew G Knepley @*/
479d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetDM(Mat A, DM dm)
480d71ae5a4SJacob Faibussowitsch {
481c688c046SMatthew G Knepley   PetscFunctionBegin;
482c688c046SMatthew G Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4838865f1eaSKarl Rupp   if (dm) PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
4849566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_dm", (PetscObject)dm));
4853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
486c688c046SMatthew G Knepley }
487c688c046SMatthew G Knepley 
488cc4c1da9SBarry Smith /*@
489bb7acecfSBarry Smith   DMSetOptionsPrefix - Sets the prefix prepended to all option names when searching through the options database
4909a42bb27SBarry Smith 
49120f4b53cSBarry Smith   Logically Collective
4929a42bb27SBarry Smith 
493d8d19677SJose E. Roman   Input Parameters:
49460225df5SJacob Faibussowitsch + dm     - the `DM` context
495bb7acecfSBarry Smith - prefix - the prefix to prepend
4969a42bb27SBarry Smith 
49720f4b53cSBarry Smith   Level: advanced
49820f4b53cSBarry Smith 
49920f4b53cSBarry Smith   Note:
5009a42bb27SBarry Smith   A hyphen (-) must NOT be given at the beginning of the prefix name.
5019a42bb27SBarry Smith   The first character of all runtime options is AUTOMATICALLY the hyphen.
5029a42bb27SBarry Smith 
5031cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscObjectSetOptionsPrefix()`, `DMSetFromOptions()`
5049a42bb27SBarry Smith @*/
505d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOptionsPrefix(DM dm, const char prefix[])
506d71ae5a4SJacob Faibussowitsch {
5079a42bb27SBarry Smith   PetscFunctionBegin;
5089a42bb27SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5099566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
5101baa6e33SBarry Smith   if (dm->sf) PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm->sf, prefix));
5111baa6e33SBarry Smith   if (dm->sectionSF) PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm->sectionSF, prefix));
5123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5139a42bb27SBarry Smith }
5149a42bb27SBarry Smith 
515cc4c1da9SBarry Smith /*@
516da81f932SPierre Jolivet   DMAppendOptionsPrefix - Appends an additional string to an already existing prefix used for searching for
517bb7acecfSBarry Smith   `DM` options in the options database.
51831697293SDave May 
51920f4b53cSBarry Smith   Logically Collective
52031697293SDave May 
52131697293SDave May   Input Parameters:
522bb7acecfSBarry Smith + dm     - the `DM` context
523bb7acecfSBarry Smith - prefix - the string to append to the current prefix
52431697293SDave May 
52520f4b53cSBarry Smith   Level: advanced
52620f4b53cSBarry Smith 
52720f4b53cSBarry Smith   Note:
528bb7acecfSBarry 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.
52931697293SDave May   A hyphen (-) must NOT be given at the beginning of the prefix name.
53031697293SDave May   The first character of all runtime options is AUTOMATICALLY the hyphen.
53131697293SDave May 
5321cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetOptionsPrefix()`, `DMGetOptionsPrefix()`, `PetscObjectAppendOptionsPrefix()`, `DMSetFromOptions()`
53331697293SDave May @*/
534d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAppendOptionsPrefix(DM dm, const char prefix[])
535d71ae5a4SJacob Faibussowitsch {
53631697293SDave May   PetscFunctionBegin;
53731697293SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5389566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, prefix));
5393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54031697293SDave May }
54131697293SDave May 
542cc4c1da9SBarry Smith /*@
54331697293SDave May   DMGetOptionsPrefix - Gets the prefix used for searching for all
544bb7acecfSBarry Smith   DM options in the options database.
54531697293SDave May 
54631697293SDave May   Not Collective
54731697293SDave May 
5482fe279fdSBarry Smith   Input Parameter:
549bb7acecfSBarry Smith . dm - the `DM` context
55031697293SDave May 
5512fe279fdSBarry Smith   Output Parameter:
55231697293SDave May . prefix - pointer to the prefix string used is returned
55331697293SDave May 
55431697293SDave May   Level: advanced
55531697293SDave May 
55673ff1848SBarry Smith   Fortran Note:
55720f4b53cSBarry Smith   Pass in a string 'prefix' of
55820f4b53cSBarry Smith   sufficient length to hold the prefix.
55920f4b53cSBarry Smith 
5601cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetOptionsPrefix()`, `DMAppendOptionsPrefix()`, `DMSetFromOptions()`
56131697293SDave May @*/
562d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOptionsPrefix(DM dm, const char *prefix[])
563d71ae5a4SJacob Faibussowitsch {
56431697293SDave May   PetscFunctionBegin;
56531697293SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5669566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, prefix));
5673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56831697293SDave May }
56931697293SDave May 
57062e5d2d2SJDBetteridge static PetscErrorCode DMCountNonCyclicReferences_Internal(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
571d71ae5a4SJacob Faibussowitsch {
5726eb26441SStefano Zampini   PetscInt refct = ((PetscObject)dm)->refct;
57388bdff64SToby Isaac 
57488bdff64SToby Isaac   PetscFunctionBegin;
575aab5bcd8SJed Brown   *ncrefct = 0;
57688bdff64SToby Isaac   if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
57788bdff64SToby Isaac     refct--;
57888bdff64SToby Isaac     if (recurseCoarse) {
57988bdff64SToby Isaac       PetscInt coarseCount;
58088bdff64SToby Isaac 
58162e5d2d2SJDBetteridge       PetscCall(DMCountNonCyclicReferences_Internal(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE, &coarseCount));
58288bdff64SToby Isaac       refct += coarseCount;
58388bdff64SToby Isaac     }
58488bdff64SToby Isaac   }
58588bdff64SToby Isaac   if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
58688bdff64SToby Isaac     refct--;
58788bdff64SToby Isaac     if (recurseFine) {
58888bdff64SToby Isaac       PetscInt fineCount;
58988bdff64SToby Isaac 
59062e5d2d2SJDBetteridge       PetscCall(DMCountNonCyclicReferences_Internal(dm->fineMesh, PETSC_FALSE, PETSC_TRUE, &fineCount));
59188bdff64SToby Isaac       refct += fineCount;
59288bdff64SToby Isaac     }
59388bdff64SToby Isaac   }
59488bdff64SToby Isaac   *ncrefct = refct;
5953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59688bdff64SToby Isaac }
59788bdff64SToby Isaac 
59862e5d2d2SJDBetteridge /* Generic wrapper for DMCountNonCyclicReferences_Internal() */
59962e5d2d2SJDBetteridge PetscErrorCode DMCountNonCyclicReferences(PetscObject dm, PetscInt *ncrefct)
60062e5d2d2SJDBetteridge {
60162e5d2d2SJDBetteridge   PetscFunctionBegin;
60262e5d2d2SJDBetteridge   PetscCall(DMCountNonCyclicReferences_Internal((DM)dm, PETSC_TRUE, PETSC_TRUE, ncrefct));
6033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60462e5d2d2SJDBetteridge }
60562e5d2d2SJDBetteridge 
606d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroyLabelLinkList_Internal(DM dm)
607d71ae5a4SJacob Faibussowitsch {
6085d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
609354557abSToby Isaac 
610354557abSToby Isaac   PetscFunctionBegin;
611354557abSToby Isaac   /* destroy the labels */
612354557abSToby Isaac   while (next) {
613354557abSToby Isaac     DMLabelLink tmp = next->next;
614354557abSToby Isaac 
6155d80c0bfSVaclav Hapla     if (next->label == dm->depthLabel) dm->depthLabel = NULL;
616ba2698f1SMatthew G. Knepley     if (next->label == dm->celltypeLabel) dm->celltypeLabel = NULL;
6179566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&next->label));
6189566063dSJacob Faibussowitsch     PetscCall(PetscFree(next));
619354557abSToby Isaac     next = tmp;
620354557abSToby Isaac   }
6215d80c0bfSVaclav Hapla   dm->labels = NULL;
6223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
623354557abSToby Isaac }
624354557abSToby Isaac 
62566976f2fSJacob Faibussowitsch static PetscErrorCode DMDestroyCoordinates_Private(DMCoordinates *c)
626d71ae5a4SJacob Faibussowitsch {
6276858538eSMatthew G. Knepley   PetscFunctionBegin;
6286858538eSMatthew G. Knepley   c->dim = PETSC_DEFAULT;
6296858538eSMatthew G. Knepley   PetscCall(DMDestroy(&c->dm));
6306858538eSMatthew G. Knepley   PetscCall(VecDestroy(&c->x));
6316858538eSMatthew G. Knepley   PetscCall(VecDestroy(&c->xl));
6326858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&c->field));
6333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6346858538eSMatthew G. Knepley }
6356858538eSMatthew G. Knepley 
6360764c050SBarry Smith /*@
637bb7acecfSBarry Smith   DMDestroy - Destroys a `DM`.
63847c6ae99SBarry Smith 
63920f4b53cSBarry Smith   Collective
64047c6ae99SBarry Smith 
64147c6ae99SBarry Smith   Input Parameter:
642bb7acecfSBarry Smith . dm - the `DM` object to destroy
64347c6ae99SBarry Smith 
64447c6ae99SBarry Smith   Level: developer
64547c6ae99SBarry Smith 
6461cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMType`, `DMSetType()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
64747c6ae99SBarry Smith @*/
648d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy(DM *dm)
649d71ae5a4SJacob Faibussowitsch {
6506eb26441SStefano Zampini   PetscInt cnt;
65147c6ae99SBarry Smith 
65247c6ae99SBarry Smith   PetscFunctionBegin;
6533ba16761SJacob Faibussowitsch   if (!*dm) PetscFunctionReturn(PETSC_SUCCESS);
654f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*dm, DM_CLASSID, 1);
65587e657c6SBarry Smith 
65688bdff64SToby Isaac   /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
65762e5d2d2SJDBetteridge   PetscCall(DMCountNonCyclicReferences_Internal(*dm, PETSC_TRUE, PETSC_TRUE, &cnt));
658f4f49eeaSPierre Jolivet   --((PetscObject)*dm)->refct;
6599371c9d4SSatish Balay   if (--cnt > 0) {
6609371c9d4SSatish Balay     *dm = NULL;
6613ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6629371c9d4SSatish Balay   }
663f4f49eeaSPierre Jolivet   if (((PetscObject)*dm)->refct < 0) PetscFunctionReturn(PETSC_SUCCESS);
664f4f49eeaSPierre Jolivet   ((PetscObject)*dm)->refct = 0;
6656eb26441SStefano Zampini 
6669566063dSJacob Faibussowitsch   PetscCall(DMClearGlobalVectors(*dm));
6679566063dSJacob Faibussowitsch   PetscCall(DMClearLocalVectors(*dm));
668974ca4ecSStefano Zampini   PetscCall(DMClearNamedGlobalVectors(*dm));
669974ca4ecSStefano Zampini   PetscCall(DMClearNamedLocalVectors(*dm));
6702348bcf4SPeter Brune 
671b17ce1afSJed Brown   /* Destroy the list of hooks */
672c833c3b5SJed Brown   {
673c833c3b5SJed Brown     DMCoarsenHookLink link, next;
674b17ce1afSJed Brown     for (link = (*dm)->coarsenhook; link; link = next) {
675b17ce1afSJed Brown       next = link->next;
6769566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
677b17ce1afSJed Brown     }
6780298fd71SBarry Smith     (*dm)->coarsenhook = NULL;
679c833c3b5SJed Brown   }
680c833c3b5SJed Brown   {
681c833c3b5SJed Brown     DMRefineHookLink link, next;
682c833c3b5SJed Brown     for (link = (*dm)->refinehook; link; link = next) {
683c833c3b5SJed Brown       next = link->next;
6849566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
685c833c3b5SJed Brown     }
6860298fd71SBarry Smith     (*dm)->refinehook = NULL;
687c833c3b5SJed Brown   }
688be081cd6SPeter Brune   {
689be081cd6SPeter Brune     DMSubDomainHookLink link, next;
690be081cd6SPeter Brune     for (link = (*dm)->subdomainhook; link; link = next) {
691be081cd6SPeter Brune       next = link->next;
6929566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
693be081cd6SPeter Brune     }
6940298fd71SBarry Smith     (*dm)->subdomainhook = NULL;
695be081cd6SPeter Brune   }
696baf369e7SPeter Brune   {
697baf369e7SPeter Brune     DMGlobalToLocalHookLink link, next;
698baf369e7SPeter Brune     for (link = (*dm)->gtolhook; link; link = next) {
699baf369e7SPeter Brune       next = link->next;
7009566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
701baf369e7SPeter Brune     }
7020298fd71SBarry Smith     (*dm)->gtolhook = NULL;
703baf369e7SPeter Brune   }
704d4d07f1eSToby Isaac   {
705d4d07f1eSToby Isaac     DMLocalToGlobalHookLink link, next;
706d4d07f1eSToby Isaac     for (link = (*dm)->ltoghook; link; link = next) {
707d4d07f1eSToby Isaac       next = link->next;
7089566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
709d4d07f1eSToby Isaac     }
710d4d07f1eSToby Isaac     (*dm)->ltoghook = NULL;
711d4d07f1eSToby Isaac   }
712aa1993deSMatthew G Knepley   /* Destroy the work arrays */
713aa1993deSMatthew G Knepley   {
714aa1993deSMatthew G Knepley     DMWorkLink link, next;
715835f2295SStefano Zampini     PetscCheck(!(*dm)->workout, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Work array still checked out %p %p", (void *)(*dm)->workout, (*dm)->workout->mem);
716aa1993deSMatthew G Knepley     for (link = (*dm)->workin; link; link = next) {
717aa1993deSMatthew G Knepley       next = link->next;
7189566063dSJacob Faibussowitsch       PetscCall(PetscFree(link->mem));
7199566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
720aa1993deSMatthew G Knepley     }
7210298fd71SBarry Smith     (*dm)->workin = NULL;
722aa1993deSMatthew G Knepley   }
723c58f1c22SToby Isaac   /* destroy the labels */
7249566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(*dm));
725f4cdcedcSVaclav Hapla   /* destroy the fields */
7269566063dSJacob Faibussowitsch   PetscCall(DMClearFields(*dm));
727f4cdcedcSVaclav Hapla   /* destroy the boundaries */
728e6f8dbb6SToby Isaac   {
729e6f8dbb6SToby Isaac     DMBoundary next = (*dm)->boundary;
730e6f8dbb6SToby Isaac     while (next) {
731e6f8dbb6SToby Isaac       DMBoundary b = next;
732e6f8dbb6SToby Isaac 
733e6f8dbb6SToby Isaac       next = b->next;
7349566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
735e6f8dbb6SToby Isaac     }
736e6f8dbb6SToby Isaac   }
737b17ce1afSJed Brown 
7389566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmksp));
7399566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmsnes));
7409566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmts));
74152536dc3SBarry Smith 
74248a46eb9SPierre Jolivet   if ((*dm)->ctx && (*dm)->ctxdestroy) PetscCall((*(*dm)->ctxdestroy)(&(*dm)->ctx));
7439566063dSJacob Faibussowitsch   PetscCall(MatFDColoringDestroy(&(*dm)->fd));
7449566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap));
7459566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->vectype));
7469566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->mattype));
74788ed4aceSMatthew G Knepley 
7489566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->localSection));
7499566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->globalSection));
750adc21957SMatthew G. Knepley   PetscCall(PetscFree((*dm)->reorderSectionType));
7519566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&(*dm)->map));
7529566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->defaultConstraint.section));
7539566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&(*dm)->defaultConstraint.mat));
7549566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&(*dm)->sf));
7559566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&(*dm)->sectionSF));
75648a46eb9SPierre Jolivet   if ((*dm)->sfNatural) PetscCall(PetscSFDestroy(&(*dm)->sfNatural));
7579566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)(*dm)->sfMigration));
758e4d5475eSStefano Zampini   PetscCall(DMClearAuxiliaryVec(*dm));
7599566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDestroy(&(*dm)->auxData));
76048a46eb9SPierre Jolivet   if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) PetscCall(DMSetFineDM((*dm)->coarseMesh, NULL));
7616eb26441SStefano Zampini 
7629566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->coarseMesh));
76348a46eb9SPierre Jolivet   if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) PetscCall(DMSetCoarseDM((*dm)->fineMesh, NULL));
7649566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->fineMesh));
7654fb89dddSMatthew G. Knepley   PetscCall(PetscFree((*dm)->Lstart));
7669566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->L));
7679566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->maxCell));
7686858538eSMatthew G. Knepley   PetscCall(DMDestroyCoordinates_Private(&(*dm)->coordinates[0]));
7696858538eSMatthew G. Knepley   PetscCall(DMDestroyCoordinates_Private(&(*dm)->coordinates[1]));
7709566063dSJacob Faibussowitsch   if ((*dm)->transformDestroy) PetscCall((*(*dm)->transformDestroy)(*dm, (*dm)->transformCtx));
7719566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->transformDM));
7729566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&(*dm)->transform));
773ddedc8f6SJames Wright   for (PetscInt i = 0; i < (*dm)->periodic.num_affines; i++) {
774ddedc8f6SJames Wright     PetscCall(VecScatterDestroy(&(*dm)->periodic.affine_to_local[i]));
775ddedc8f6SJames Wright     PetscCall(VecDestroy(&(*dm)->periodic.affine[i]));
776ddedc8f6SJames Wright   }
777ddedc8f6SJames Wright   if ((*dm)->periodic.num_affines > 0) PetscCall(PetscFree2((*dm)->periodic.affine_to_local, (*dm)->periodic.affine));
7786636e97aSMatthew G Knepley 
7799566063dSJacob Faibussowitsch   PetscCall(DMClearDS(*dm));
7809566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->dmBC));
781e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
7829566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*dm));
783732e2eb9SMatthew G Knepley 
784213acdd3SPierre Jolivet   PetscTryTypeMethod(*dm, destroy);
7859566063dSJacob Faibussowitsch   PetscCall(DMMonitorCancel(*dm));
786d2b2dc1eSMatthew G. Knepley   PetscCall(DMCeedDestroy(&(*dm)->dmceed));
787f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
7889566063dSJacob Faibussowitsch   PetscCallCEED(CeedElemRestrictionDestroy(&(*dm)->ceedERestrict));
7899566063dSJacob Faibussowitsch   PetscCallCEED(CeedDestroy(&(*dm)->ceed));
790f918ec44SMatthew G. Knepley #endif
791435a35e8SMatthew G Knepley   /* We do not destroy (*dm)->data here so that we can reference count backend objects */
7929566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(dm));
7933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79447c6ae99SBarry Smith }
79547c6ae99SBarry Smith 
796d7bf68aeSBarry Smith /*@
797bb7acecfSBarry Smith   DMSetUp - sets up the data structures inside a `DM` object
798d7bf68aeSBarry Smith 
79920f4b53cSBarry Smith   Collective
800d7bf68aeSBarry Smith 
801d7bf68aeSBarry Smith   Input Parameter:
802bb7acecfSBarry Smith . dm - the `DM` object to setup
803d7bf68aeSBarry Smith 
804bb7acecfSBarry Smith   Level: intermediate
805d7bf68aeSBarry Smith 
806bb7acecfSBarry Smith   Note:
807bb7acecfSBarry Smith   This is usually called after various parameter setting operations and `DMSetFromOptions()` are called on the `DM`
808bb7acecfSBarry Smith 
8091cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMSetType()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
810d7bf68aeSBarry Smith @*/
811d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp(DM dm)
812d71ae5a4SJacob Faibussowitsch {
813d7bf68aeSBarry Smith   PetscFunctionBegin;
814171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8153ba16761SJacob Faibussowitsch   if (dm->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
816dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, setup);
8178387afaaSJed Brown   dm->setupcalled = PETSC_TRUE;
8183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
819d7bf68aeSBarry Smith }
820d7bf68aeSBarry Smith 
821d7bf68aeSBarry Smith /*@
822bb7acecfSBarry Smith   DMSetFromOptions - sets parameters in a `DM` from the options database
823d7bf68aeSBarry Smith 
82420f4b53cSBarry Smith   Collective
825d7bf68aeSBarry Smith 
826d7bf68aeSBarry Smith   Input Parameter:
827bb7acecfSBarry Smith . dm - the `DM` object to set options for
828d7bf68aeSBarry Smith 
82920f4b53cSBarry Smith   Options Database Keys:
830bb7acecfSBarry Smith + -dm_preallocate_only                               - Only preallocate the matrix for `DMCreateMatrix()` and `DMCreateMassMatrix()`, but do not fill it with zeros
831bb7acecfSBarry Smith . -dm_vec_type <type>                                - type of vector to create inside `DM`
832bb7acecfSBarry Smith . -dm_mat_type <type>                                - type of matrix to create inside `DM`
833a4ea9b21SRichard Tran Mills . -dm_is_coloring_type                               - <global or local>
83420f4b53cSBarry 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`
83522d6dc08SStefano Zampini . -dm_plex_option_phases <ph0_, ph1_, ...>           - List of prefixes for option processing phases
83620f4b53cSBarry Smith . -dm_plex_filename <str>                            - File containing a mesh
8379318fe57SMatthew G. Knepley . -dm_plex_boundary_filename <str>                   - File containing a mesh boundary
838cd7e8a5eSksagiyam . -dm_plex_name <str>                                - Name of the mesh in the file
8395dca41c3SJed Brown . -dm_plex_shape <shape>                             - The domain shape, such as `BOX`, `SPHERE`, etc.
8409318fe57SMatthew G. Knepley . -dm_plex_cell <ct>                                 - Cell shape
8419318fe57SMatthew G. Knepley . -dm_plex_reference_cell_domain <bool>              - Use a reference cell domain
8429318fe57SMatthew G. Knepley . -dm_plex_dim <dim>                                 - Set the topological dimension
843bb7acecfSBarry Smith . -dm_plex_simplex <bool>                            - `PETSC_TRUE` for simplex elements, `PETSC_FALSE` for tensor elements
844bb7acecfSBarry Smith . -dm_plex_interpolate <bool>                        - `PETSC_TRUE` turns on topological interpolation (creating edges and faces)
845b9da1bb3SMatthew G. Knepley . -dm_plex_orient <bool>                             - `PETSC_TRUE` turns on topological orientation (flipping edges and faces)
8469318fe57SMatthew G. Knepley . -dm_plex_scale <sc>                                - Scale factor for mesh coordinates
847be664eb1SMatthew G. Knepley . -dm_coord_remap <bool>                             - Map coordinates using a function
848ac9d17c7SMatthew G. Knepley . -dm_plex_coordinate_dim <dim>                      - Change the coordinate dimension of a mesh (usually given with cdm_ prefix)
849be664eb1SMatthew G. Knepley . -dm_coord_map <mapname>                            - Select a builtin coordinate map
850be664eb1SMatthew G. Knepley . -dm_coord_map_params <p0,p1,p2,...>                - Set coordinate mapping parameters
8519318fe57SMatthew G. Knepley . -dm_plex_box_faces <m,n,p>                         - Number of faces along each dimension
8529318fe57SMatthew G. Knepley . -dm_plex_box_lower <x,y,z>                         - Specify lower-left-bottom coordinates for the box
8539318fe57SMatthew G. Knepley . -dm_plex_box_upper <x,y,z>                         - Specify upper-right-top coordinates for the box
854bb7acecfSBarry Smith . -dm_plex_box_bd <bx,by,bz>                         - Specify the `DMBoundaryType` for each direction
8559318fe57SMatthew G. Knepley . -dm_plex_sphere_radius <r>                         - The sphere radius
8569318fe57SMatthew G. Knepley . -dm_plex_ball_radius <r>                           - Radius of the ball
8579318fe57SMatthew G. Knepley . -dm_plex_cylinder_bd <bz>                          - Boundary type in the z direction
8589318fe57SMatthew G. Knepley . -dm_plex_cylinder_num_wedges <n>                   - Number of wedges around the cylinder
859bdf63967SMatthew G. Knepley . -dm_plex_reorder <order>                           - Reorder the mesh using the specified algorithm
8609318fe57SMatthew G. Knepley . -dm_refine_pre <n>                                 - The number of refinements before distribution
8619318fe57SMatthew G. Knepley . -dm_refine_uniform_pre <bool>                      - Flag for uniform refinement before distribution
8629318fe57SMatthew G. Knepley . -dm_refine_volume_limit_pre <v>                    - The maximum cell volume after refinement before distribution
8639318fe57SMatthew G. Knepley . -dm_refine <n>                                     - The number of refinements after distribution
864bdf63967SMatthew G. Knepley . -dm_extrude <l>                                    - Activate extrusion and specify the number of layers to extrude
865d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_thickness <t>           - The total thickness of extruded layers
866d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_use_tensor <bool>       - Use tensor cells when extruding
867d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_symmetric <bool>        - Extrude layers symmetrically about the surface
868d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_normal <n0,...,nd>      - Specify the extrusion direction
869d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_thicknesses <t0,...,tl> - Specify thickness of each layer
870909dfd52SMatthew G. Knepley . -dm_plex_create_fv_ghost_cells                     - Flag to create finite volume ghost cells on the boundary
871909dfd52SMatthew G. Knepley . -dm_plex_fv_ghost_cells_label <name>               - Label name for ghost cells boundary
8729318fe57SMatthew G. Knepley . -dm_distribute <bool>                              - Flag to redistribute a mesh among processes
8739318fe57SMatthew G. Knepley . -dm_distribute_overlap <n>                         - The size of the overlap halo
8749318fe57SMatthew G. Knepley . -dm_plex_adj_cone <bool>                           - Set adjacency direction
87520f4b53cSBarry Smith . -dm_plex_adj_closure <bool>                        - Set adjacency size
876d2b2dc1eSMatthew G. Knepley . -dm_plex_use_ceed <bool>                           - Use LibCEED as the FEM backend
87720f4b53cSBarry Smith . -dm_plex_check_symmetry                            - Check that the adjacency information in the mesh is symmetric - `DMPlexCheckSymmetry()`
878bb7acecfSBarry Smith . -dm_plex_check_skeleton                            - Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes) - `DMPlexCheckSkeleton()`
879bb7acecfSBarry 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()`
880bb7acecfSBarry Smith . -dm_plex_check_geometry                            - Check that cells have positive volume - `DMPlexCheckGeometry()`
881bb7acecfSBarry Smith . -dm_plex_check_pointsf                             - Check some necessary conditions for `PointSF` - `DMPlexCheckPointSF()`
882bb7acecfSBarry Smith . -dm_plex_check_interface_cones                     - Check points on inter-partition interfaces have conforming order of cone points - `DMPlexCheckInterfaceCones()`
883384a6580SVaclav Hapla - -dm_plex_check_all                                 - Perform all the checks above
884d7bf68aeSBarry Smith 
88595eb5ee5SVaclav Hapla   Level: intermediate
88695eb5ee5SVaclav Hapla 
8878e704042SBarry Smith   Note:
8888e704042SBarry Smith   For some `DMType` such as `DMDA` this cannot be called after `DMSetUp()` has been called.
8898e704042SBarry Smith 
8901cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
891bb7acecfSBarry Smith          `DMPlexCheckSymmetry()`, `DMPlexCheckSkeleton()`, `DMPlexCheckFaces()`, `DMPlexCheckGeometry()`, `DMPlexCheckPointSF()`, `DMPlexCheckInterfaceCones()`,
8928e704042SBarry Smith          `DMSetOptionsPrefix()`, `DMType`, `DMPLEX`, `DMDA`, `DMSetUp()`
893d7bf68aeSBarry Smith @*/
894d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions(DM dm)
895d71ae5a4SJacob Faibussowitsch {
8967781c08eSBarry Smith   char      typeName[256];
897ca266f36SBarry Smith   PetscBool flg;
898d7bf68aeSBarry Smith 
899d7bf68aeSBarry Smith   PetscFunctionBegin;
900171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90149be4549SMatthew G. Knepley   dm->setfromoptionscalled = PETSC_TRUE;
9029566063dSJacob Faibussowitsch   if (dm->sf) PetscCall(PetscSFSetFromOptions(dm->sf));
9039566063dSJacob Faibussowitsch   if (dm->sectionSF) PetscCall(PetscSFSetFromOptions(dm->sectionSF));
904dd4c3f67SMatthew G. Knepley   if (dm->coordinates[0].dm) PetscCall(DMSetFromOptions(dm->coordinates[0].dm));
905d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)dm);
9069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_preallocate_only", "only preallocate matrix, but do not set column indices", "DMSetMatrixPreallocateOnly", dm->prealloc_only, &dm->prealloc_only, NULL));
9079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_vec_type", "Vector type used for created vectors", "DMSetVecType", VecList, dm->vectype, typeName, 256, &flg));
9081baa6e33SBarry Smith   if (flg) PetscCall(DMSetVecType(dm, typeName));
9099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_mat_type", "Matrix type used for created matrices", "DMSetMatType", MatList, dm->mattype ? dm->mattype : typeName, typeName, sizeof(typeName), &flg));
9101baa6e33SBarry Smith   if (flg) PetscCall(DMSetMatType(dm, typeName));
911863027abSJed Brown   PetscCall(PetscOptionsEnum("-dm_blocking_type", "Topological point or field node blocking", "DMSetBlockingType", DMBlockingTypes, (PetscEnum)dm->blocking_type, (PetscEnum *)&dm->blocking_type, NULL));
9129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_is_coloring_type", "Global or local coloring of Jacobian", "DMSetISColoringType", ISColoringTypes, (PetscEnum)dm->coloringtype, (PetscEnum *)&dm->coloringtype, NULL));
9139566063dSJacob 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));
914eb9d3e4dSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_ignore_perm_output", "Ignore the local section permutation on output", "DMGetOutputDM", dm->ignorePermOutput, &dm->ignorePermOutput, NULL));
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();
9193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
920d7bf68aeSBarry Smith }
921d7bf68aeSBarry Smith 
922ffeef943SBarry Smith /*@
923bb7acecfSBarry Smith   DMViewFromOptions - View a `DM` in a particular way based on a request in the options database
924fe2efc57SMark 
92520f4b53cSBarry Smith   Collective
926fe2efc57SMark 
927fe2efc57SMark   Input Parameters:
928bb7acecfSBarry Smith + dm   - the `DM` object
92920f4b53cSBarry Smith . obj  - optional object that provides the prefix for the options database (if `NULL` then the prefix in obj is used)
93060225df5SJacob Faibussowitsch - name - 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 
93760225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMView()`, `PetscObjectViewFromOptions()`, `DMCreate()`
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));
9443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
945fe2efc57SMark }
946fe2efc57SMark 
947ffeef943SBarry Smith /*@
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 
95120f4b53cSBarry Smith   Collective
95247c6ae99SBarry Smith 
953d8d19677SJose E. Roman   Input Parameters:
954bb7acecfSBarry Smith + dm - the `DM` object to view
95547c6ae99SBarry Smith - v  - the viewer
95647c6ae99SBarry Smith 
957*c8a418c4SMatthew G. Knepley   Options Database Keys:
958*c8a418c4SMatthew G. Knepley + -view_pyvista_warp <f>                 - Warps the mesh by the active scalar with factor f
959*c8a418c4SMatthew G. Knepley - -view_pyvista_clip <xl,xu,yl,yu,zl,zu> - Defines the clipping box
960*c8a418c4SMatthew G. Knepley 
96120f4b53cSBarry Smith   Level: beginner
96220f4b53cSBarry Smith 
96349c89c76SBlaise Bourdin   Notes:
96449c89c76SBlaise Bourdin 
96549c89c76SBlaise Bourdin   `PetscViewer` = `PETSCVIEWERHDF5` i.e. HDF5 format can be used with `PETSC_VIEWER_HDF5_PETSC` as the `PetscViewerFormat` to save multiple `DMPLEX`
966bb7acecfSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
967bb7acecfSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
968cd7e8a5eSksagiyam 
96949c89c76SBlaise Bourdin   `PetscViewer` = `PETSCVIEWEREXODUSII` i.e. ExodusII format assumes that element blocks (mapped to "Cell sets" labels)
97049c89c76SBlaise Bourdin   consists of sequentially numbered cells.
97149c89c76SBlaise Bourdin 
97249c89c76SBlaise Bourdin   If `dm` has been distributed, only the part of the `DM` on MPI rank 0 (including "ghost" cells and vertices) will be written.
97349c89c76SBlaise Bourdin 
974*c8a418c4SMatthew G. Knepley   Only TRI, TET, QUAD, and HEX cells are supported in ExodusII.
97549c89c76SBlaise Bourdin 
97649c89c76SBlaise Bourdin   `DMPLEX` only represents geometry while most post-processing software expect that a mesh also provides information on the discretization space. This function assumes that the file represents Lagrange finite elements of order 1 or 2.
97749c89c76SBlaise Bourdin   The order of the mesh shall be set using `PetscViewerExodusIISetOrder()`
97849c89c76SBlaise Bourdin 
979d7c1f440SPierre Jolivet   Variable names can be set and queried using `PetscViewerExodusII[Set/Get][Nodal/Zonal]VariableNames[s]`.
98049c89c76SBlaise Bourdin 
9811cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscViewer`, `PetscViewerFormat`, `PetscViewerSetFormat()`, `DMDestroy()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMLoad()`, `PetscObjectSetName()`
98247c6ae99SBarry Smith @*/
983d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView(DM dm, PetscViewer v)
984d71ae5a4SJacob Faibussowitsch {
98532c0f0efSBarry Smith   PetscBool         isbinary;
98676a8abe0SBarry Smith   PetscMPIInt       size;
98776a8abe0SBarry Smith   PetscViewerFormat format;
98847c6ae99SBarry Smith 
98947c6ae99SBarry Smith   PetscFunctionBegin;
990171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
99148a46eb9SPierre Jolivet   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &v));
992b1b135c8SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);
99374903a4fSStefano Zampini   /* Ideally, we would like to have this test on.
99474903a4fSStefano Zampini      However, it currently breaks socket viz via GLVis.
99574903a4fSStefano Zampini      During DMView(parallel_mesh,glvis_viewer), each
99674903a4fSStefano Zampini      process opens a sequential ASCII socket to visualize
99774903a4fSStefano Zampini      the local mesh, and PetscObjectView(dm,local_socket)
99874903a4fSStefano Zampini      is internally called inside VecView_GLVis, incurring
99974903a4fSStefano Zampini      in an error here */
100074903a4fSStefano Zampini   /* PetscCheckSameComm(dm,1,v,2); */
10019566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckWritable(v));
1002b1b135c8SBarry Smith 
100342d0c57aSJames Wright   PetscCall(PetscLogEventBegin(DM_View, v, 0, 0, 0));
10049566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(v, &format));
10059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
10063ba16761SJacob Faibussowitsch   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
10079566063dSJacob Faibussowitsch   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)dm, v));
10089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERBINARY, &isbinary));
100932c0f0efSBarry Smith   if (isbinary) {
101055849f57SBarry Smith     PetscInt classid = DM_FILE_CLASSID;
101132c0f0efSBarry Smith     char     type[256];
101232c0f0efSBarry Smith 
10139566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWrite(v, &classid, 1, PETSC_INT));
1014c6a7a370SJeremy L Thompson     PetscCall(PetscStrncpy(type, ((PetscObject)dm)->type_name, sizeof(type)));
10159566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWrite(v, type, 256, PETSC_CHAR));
101632c0f0efSBarry Smith   }
1017dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, view, v);
101842d0c57aSJames Wright   PetscCall(PetscLogEventEnd(DM_View, v, 0, 0, 0));
10193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
102047c6ae99SBarry Smith }
102147c6ae99SBarry Smith 
102247c6ae99SBarry Smith /*@
1023bb7acecfSBarry 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,
1024bb7acecfSBarry Smith   that is it has no ghost locations.
102547c6ae99SBarry Smith 
102620f4b53cSBarry Smith   Collective
102747c6ae99SBarry Smith 
102847c6ae99SBarry Smith   Input Parameter:
1029bb7acecfSBarry Smith . dm - the `DM` object
103047c6ae99SBarry Smith 
103147c6ae99SBarry Smith   Output Parameter:
103247c6ae99SBarry Smith . vec - the global vector
103347c6ae99SBarry Smith 
1034073dac72SJed Brown   Level: beginner
103547c6ae99SBarry Smith 
10361cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `Vec`, `DMCreateLocalVector()`, `DMGetGlobalVector()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
1037bb7acecfSBarry Smith          `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`
103847c6ae99SBarry Smith @*/
1039d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateGlobalVector(DM dm, Vec *vec)
1040d71ae5a4SJacob Faibussowitsch {
104147c6ae99SBarry Smith   PetscFunctionBegin;
1042171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10434f572ea9SToby Isaac   PetscAssertPointer(vec, 2);
1044dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createglobalvector, vec);
104576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1046c6b011d8SStefano Zampini     DM vdm;
1047c6b011d8SStefano Zampini 
10489566063dSJacob Faibussowitsch     PetscCall(VecGetDM(*vec, &vdm));
10497a8be351SBarry Smith     PetscCheck(vdm, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DM type '%s' did not attach the DM to the vector", ((PetscObject)dm)->type_name);
1050c6b011d8SStefano Zampini   }
10513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
105247c6ae99SBarry Smith }
105347c6ae99SBarry Smith 
105447c6ae99SBarry Smith /*@
1055bb7acecfSBarry Smith   DMCreateLocalVector - Creates a local vector from a `DM` object.
105647c6ae99SBarry Smith 
105747c6ae99SBarry Smith   Not Collective
105847c6ae99SBarry Smith 
105947c6ae99SBarry Smith   Input Parameter:
1060bb7acecfSBarry Smith . dm - the `DM` object
106147c6ae99SBarry Smith 
106247c6ae99SBarry Smith   Output Parameter:
106347c6ae99SBarry Smith . vec - the local vector
106447c6ae99SBarry Smith 
1065073dac72SJed Brown   Level: beginner
106647c6ae99SBarry Smith 
106720f4b53cSBarry Smith   Note:
1068bb7acecfSBarry 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.
1069bb7acecfSBarry Smith 
10701cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `Vec`, `DMCreateGlobalVector()`, `DMGetLocalVector()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
1071bb7acecfSBarry Smith          `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`
107247c6ae99SBarry Smith @*/
1073d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLocalVector(DM dm, Vec *vec)
1074d71ae5a4SJacob Faibussowitsch {
107547c6ae99SBarry Smith   PetscFunctionBegin;
1076171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10774f572ea9SToby Isaac   PetscAssertPointer(vec, 2);
1078dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createlocalvector, vec);
107976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1080c6b011d8SStefano Zampini     DM vdm;
1081c6b011d8SStefano Zampini 
10829566063dSJacob Faibussowitsch     PetscCall(VecGetDM(*vec, &vdm));
10837a8be351SBarry Smith     PetscCheck(vdm, PETSC_COMM_SELF, PETSC_ERR_LIB, "DM type '%s' did not attach the DM to the vector", ((PetscObject)dm)->type_name);
1084c6b011d8SStefano Zampini   }
10853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
108647c6ae99SBarry Smith }
108747c6ae99SBarry Smith 
10881411c6eeSJed Brown /*@
1089bb7acecfSBarry Smith   DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a `DM`.
10901411c6eeSJed Brown 
109120f4b53cSBarry Smith   Collective
10921411c6eeSJed Brown 
10931411c6eeSJed Brown   Input Parameter:
1094bb7acecfSBarry Smith . dm - the `DM` that provides the mapping
10951411c6eeSJed Brown 
10961411c6eeSJed Brown   Output Parameter:
10971411c6eeSJed Brown . ltog - the mapping
10981411c6eeSJed Brown 
1099bb7acecfSBarry Smith   Level: advanced
11001411c6eeSJed Brown 
11011411c6eeSJed Brown   Notes:
1102bb7acecfSBarry Smith   The global to local mapping allows one to set values into the global vector or matrix using `VecSetValuesLocal()` and `MatSetValuesLocal()`
11031411c6eeSJed Brown 
1104bb7acecfSBarry Smith   Vectors obtained with  `DMCreateGlobalVector()` and matrices obtained with `DMCreateMatrix()` already contain the global mapping so you do
1105bb7acecfSBarry Smith   need to use this function with those objects.
1106bb7acecfSBarry Smith 
1107bb7acecfSBarry Smith   This mapping can then be used by `VecSetLocalToGlobalMapping()` or `MatSetLocalToGlobalMapping()`.
1108bb7acecfSBarry Smith 
110960225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `VecSetLocalToGlobalMapping()`, `MatSetLocalToGlobalMapping()`,
1110bb7acecfSBarry Smith           `DMCreateMatrix()`
11111411c6eeSJed Brown @*/
1112d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalToGlobalMapping(DM dm, ISLocalToGlobalMapping *ltog)
1113d71ae5a4SJacob Faibussowitsch {
11140be3e97aSMatthew G. Knepley   PetscInt bs = -1, bsLocal[2], bsMinMax[2];
11151411c6eeSJed Brown 
11161411c6eeSJed Brown   PetscFunctionBegin;
11171411c6eeSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11184f572ea9SToby Isaac   PetscAssertPointer(ltog, 2);
11191411c6eeSJed Brown   if (!dm->ltogmap) {
112037d0c07bSMatthew G Knepley     PetscSection section, sectionGlobal;
112137d0c07bSMatthew G Knepley 
11229566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
112337d0c07bSMatthew G Knepley     if (section) {
1124a974ec88SMatthew G. Knepley       const PetscInt *cdofs;
112537d0c07bSMatthew G Knepley       PetscInt       *ltog;
1126ccf3bd66SMatthew G. Knepley       PetscInt        pStart, pEnd, n, p, k, l;
112737d0c07bSMatthew G Knepley 
11289566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
11299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
11309566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetStorageSize(section, &n));
11319566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n, &ltog)); /* We want the local+overlap size */
113237d0c07bSMatthew G Knepley       for (p = pStart, l = 0; p < pEnd; ++p) {
1133e6befd46SJed Brown         PetscInt bdof, cdof, dof, off, c, cind;
113437d0c07bSMatthew G Knepley 
113537d0c07bSMatthew G Knepley         /* Should probably use constrained dofs */
11369566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, p, &dof));
11379566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
11389566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, p, &cdofs));
11399566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &off));
11401a7dc684SMatthew G. Knepley         /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
11411a7dc684SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
1142ad540459SPierre Jolivet         if (dof) bs = bs < 0 ? bdof : PetscGCD(bs, bdof);
11435227eafbSStefano Zampini 
1144e6befd46SJed Brown         for (c = 0, cind = 0; c < dof; ++c, ++l) {
11455227eafbSStefano Zampini           if (cind < cdof && c == cdofs[cind]) {
1146e6befd46SJed Brown             ltog[l] = off < 0 ? off - c : -(off + c + 1);
1147e6befd46SJed Brown             cind++;
1148e6befd46SJed Brown           } else {
11495227eafbSStefano Zampini             ltog[l] = (off < 0 ? -(off + 1) : off) + c - cind;
1150e6befd46SJed Brown           }
115137d0c07bSMatthew G Knepley         }
115237d0c07bSMatthew G Knepley       }
1153bff27382SMatthew G. Knepley       /* Must have same blocksize on all procs (some might have no points) */
11541690c2aeSBarry Smith       bsLocal[0] = bs < 0 ? PETSC_INT_MAX : bs;
11559371c9d4SSatish Balay       bsLocal[1] = bs;
11569566063dSJacob Faibussowitsch       PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
11579371c9d4SSatish Balay       if (bsMinMax[0] != bsMinMax[1]) {
11589371c9d4SSatish Balay         bs = 1;
11599371c9d4SSatish Balay       } else {
11609371c9d4SSatish Balay         bs = bsMinMax[0];
11619371c9d4SSatish Balay       }
11627591dbb2SMatthew G. Knepley       bs = bs < 0 ? 1 : bs;
11637591dbb2SMatthew G. Knepley       /* Must reduce indices by blocksize */
1164ccf3bd66SMatthew G. Knepley       if (bs > 1) {
1165ca469d19SJed Brown         for (l = 0, k = 0; l < n; l += bs, ++k) {
1166ca469d19SJed Brown           // Integer division of negative values truncates toward zero(!), not toward negative infinity
1167ca469d19SJed Brown           ltog[k] = ltog[l] >= 0 ? ltog[l] / bs : -(-(ltog[l] + 1) / bs + 1);
1168ca469d19SJed Brown         }
1169ccf3bd66SMatthew G. Knepley         n /= bs;
1170ccf3bd66SMatthew G. Knepley       }
11719566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap));
1172dbbe0bcdSBarry Smith     } else PetscUseTypeMethod(dm, getlocaltoglobalmapping);
117337d0c07bSMatthew G Knepley   }
11741411c6eeSJed Brown   *ltog = dm->ltogmap;
11753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11761411c6eeSJed Brown }
11771411c6eeSJed Brown 
11781411c6eeSJed Brown /*@
1179bb7acecfSBarry Smith   DMGetBlockSize - Gets the inherent block size associated with a `DM`
11801411c6eeSJed Brown 
11811411c6eeSJed Brown   Not Collective
11821411c6eeSJed Brown 
11831411c6eeSJed Brown   Input Parameter:
1184bb7acecfSBarry Smith . dm - the `DM` with block structure
11851411c6eeSJed Brown 
11861411c6eeSJed Brown   Output Parameter:
11871411c6eeSJed Brown . bs - the block size, 1 implies no exploitable block structure
11881411c6eeSJed Brown 
11891411c6eeSJed Brown   Level: intermediate
11901411c6eeSJed Brown 
119173ff1848SBarry Smith   Notes:
1192bb7acecfSBarry Smith   This might be the number of degrees of freedom at each grid point for a structured grid.
1193bb7acecfSBarry Smith 
1194bb7acecfSBarry Smith   Complex `DM` that represent multiphysics or staggered grids or mixed-methods do not generally have a single inherent block size, but
1195bb7acecfSBarry Smith   rather different locations in the vectors may have a different block size.
1196bb7acecfSBarry Smith 
11971cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `ISCreateBlock()`, `VecSetBlockSize()`, `MatSetBlockSize()`, `DMGetLocalToGlobalMapping()`
11981411c6eeSJed Brown @*/
1199d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBlockSize(DM dm, PetscInt *bs)
1200d71ae5a4SJacob Faibussowitsch {
12011411c6eeSJed Brown   PetscFunctionBegin;
12021411c6eeSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
12034f572ea9SToby Isaac   PetscAssertPointer(bs, 2);
12047a8be351SBarry Smith   PetscCheck(dm->bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM does not have enough information to provide a block size yet");
12051411c6eeSJed Brown   *bs = dm->bs;
12063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12071411c6eeSJed Brown }
12081411c6eeSJed Brown 
1209ffeef943SBarry Smith /*@
1210bb7acecfSBarry Smith   DMCreateInterpolation - Gets the interpolation matrix between two `DM` objects. The resulting matrix map degrees of freedom in the vector obtained by
1211bb7acecfSBarry Smith   `DMCreateGlobalVector()` on the coarse `DM` to similar vectors on the fine grid `DM`.
121247c6ae99SBarry Smith 
121320f4b53cSBarry Smith   Collective
121447c6ae99SBarry Smith 
1215d8d19677SJose E. Roman   Input Parameters:
1216bb7acecfSBarry Smith + dmc - the `DM` object
1217bb7acecfSBarry Smith - dmf - the second, finer `DM` object
121847c6ae99SBarry Smith 
1219d8d19677SJose E. Roman   Output Parameters:
122047c6ae99SBarry Smith + mat - the interpolation
1221b6971eaeSBarry Smith - vec - the scaling (optional, pass `NULL` if not needed), see `DMCreateInterpolationScale()`
122247c6ae99SBarry Smith 
122347c6ae99SBarry Smith   Level: developer
122447c6ae99SBarry Smith 
122595452b02SPatrick Sanan   Notes:
1226bb7acecfSBarry 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
1227bb7acecfSBarry Smith   DMCoarsen(). The coordinates set into the `DMDA` are completely ignored in computing the interpolation.
1228d52bd9f3SBarry Smith 
1229bb7acecfSBarry Smith   For `DMDA` objects you can use this interpolation (more precisely the interpolation from the `DMGetCoordinateDM()`) to interpolate the mesh coordinate
1230bb7acecfSBarry Smith   vectors EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
123185afcc9aSBarry Smith 
12321cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolationScale()`
123347c6ae99SBarry Smith @*/
1234d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation(DM dmc, DM dmf, Mat *mat, Vec *vec)
1235d71ae5a4SJacob Faibussowitsch {
123647c6ae99SBarry Smith   PetscFunctionBegin;
1237a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1238a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
12394f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
12409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateInterpolation, dmc, dmf, 0, 0));
1241dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createinterpolation, dmf, mat, vec);
12429566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateInterpolation, dmc, dmf, 0, 0));
12433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
124447c6ae99SBarry Smith }
124547c6ae99SBarry Smith 
12463ad4599aSBarry Smith /*@
1247a4e35b19SJacob Faibussowitsch   DMCreateInterpolationScale - Forms L = 1/(R*1) where 1 is the vector of all ones, and R is
1248a4e35b19SJacob Faibussowitsch   the transpose of the interpolation between the `DM`.
12492ed6491fSPatrick Sanan 
12502ed6491fSPatrick Sanan   Input Parameters:
1251bb7acecfSBarry Smith + dac - `DM` that defines a coarse mesh
1252bb7acecfSBarry Smith . daf - `DM` that defines a fine mesh
12532ed6491fSPatrick Sanan - mat - the restriction (or interpolation operator) from fine to coarse
12542ed6491fSPatrick Sanan 
12552ed6491fSPatrick Sanan   Output Parameter:
12562ed6491fSPatrick Sanan . scale - the scaled vector
12572ed6491fSPatrick Sanan 
1258bb7acecfSBarry Smith   Level: advanced
12592ed6491fSPatrick Sanan 
126073ff1848SBarry Smith   Note:
1261a4e35b19SJacob Faibussowitsch   xcoarse = diag(L)*R*xfine preserves scale and is thus suitable for state (versus residual)
1262a4e35b19SJacob Faibussowitsch   restriction. In other words xcoarse is the coarse representation of xfine.
1263a4e35b19SJacob Faibussowitsch 
126473ff1848SBarry Smith   Developer Note:
1265bb7acecfSBarry Smith   If the fine-scale `DMDA` has the -dm_bind_below option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
1266e9c74fd6SRichard Tran Mills   on the restriction/interpolation operator to set the bindingpropagates flag to true.
1267e9c74fd6SRichard Tran Mills 
126860225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `MatRestrict()`, `MatInterpolate()`, `DMCreateInterpolation()`, `DMCreateRestriction()`, `DMCreateGlobalVector()`
12692ed6491fSPatrick Sanan @*/
1270d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolationScale(DM dac, DM daf, Mat mat, Vec *scale)
1271d71ae5a4SJacob Faibussowitsch {
12722ed6491fSPatrick Sanan   Vec         fine;
12732ed6491fSPatrick Sanan   PetscScalar one = 1.0;
12749704db99SRichard Tran Mills #if defined(PETSC_HAVE_CUDA)
1275e9c74fd6SRichard Tran Mills   PetscBool bindingpropagates, isbound;
12769704db99SRichard Tran Mills #endif
12772ed6491fSPatrick Sanan 
12782ed6491fSPatrick Sanan   PetscFunctionBegin;
12799566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(daf, &fine));
12809566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dac, scale));
12819566063dSJacob Faibussowitsch   PetscCall(VecSet(fine, one));
12829704db99SRichard Tran Mills #if defined(PETSC_HAVE_CUDA)
12839704db99SRichard Tran Mills   /* If the 'fine' Vec is bound to the CPU, it makes sense to bind 'mat' as well.
12849704db99SRichard Tran Mills    * Note that we only do this for the CUDA case, right now, but if we add support for MatMultTranspose() via ViennaCL,
12859704db99SRichard Tran Mills    * we'll need to do it for that case, too.*/
12869566063dSJacob Faibussowitsch   PetscCall(VecGetBindingPropagates(fine, &bindingpropagates));
1287e9c74fd6SRichard Tran Mills   if (bindingpropagates) {
12889566063dSJacob Faibussowitsch     PetscCall(MatSetBindingPropagates(mat, PETSC_TRUE));
12899566063dSJacob Faibussowitsch     PetscCall(VecBoundToCPU(fine, &isbound));
12909566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(mat, isbound));
129183aa49f4SRichard Tran Mills   }
12929704db99SRichard Tran Mills #endif
12939566063dSJacob Faibussowitsch   PetscCall(MatRestrict(mat, fine, *scale));
12949566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fine));
12959566063dSJacob Faibussowitsch   PetscCall(VecReciprocal(*scale));
12963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12972ed6491fSPatrick Sanan }
12982ed6491fSPatrick Sanan 
12992ed6491fSPatrick Sanan /*@
1300bb7acecfSBarry Smith   DMCreateRestriction - Gets restriction matrix between two `DM` objects. The resulting matrix map degrees of freedom in the vector obtained by
1301bb7acecfSBarry Smith   `DMCreateGlobalVector()` on the fine `DM` to similar vectors on the coarse grid `DM`.
13023ad4599aSBarry Smith 
130320f4b53cSBarry Smith   Collective
13043ad4599aSBarry Smith 
1305d8d19677SJose E. Roman   Input Parameters:
1306bb7acecfSBarry Smith + dmc - the `DM` object
1307bb7acecfSBarry Smith - dmf - the second, finer `DM` object
13083ad4599aSBarry Smith 
13093ad4599aSBarry Smith   Output Parameter:
13103ad4599aSBarry Smith . mat - the restriction
13113ad4599aSBarry Smith 
13123ad4599aSBarry Smith   Level: developer
13133ad4599aSBarry Smith 
1314bb7acecfSBarry Smith   Note:
1315bb7acecfSBarry Smith   This only works for `DMSTAG`. For many situations either the transpose of the operator obtained with `DMCreateInterpolation()` or that
1316bb7acecfSBarry Smith   matrix multiplied by the vector obtained with `DMCreateInterpolationScale()` provides the desired object.
13173ad4599aSBarry Smith 
13181cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRestrict()`, `DMInterpolate()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateInterpolation()`
13193ad4599aSBarry Smith @*/
1320d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateRestriction(DM dmc, DM dmf, Mat *mat)
1321d71ae5a4SJacob Faibussowitsch {
13223ad4599aSBarry Smith   PetscFunctionBegin;
1323a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1324a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
13254f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
13269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateRestriction, dmc, dmf, 0, 0));
1327dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createrestriction, dmf, mat);
13289566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateRestriction, dmc, dmf, 0, 0));
13293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13303ad4599aSBarry Smith }
13313ad4599aSBarry Smith 
133247c6ae99SBarry Smith /*@
1333a4e35b19SJacob Faibussowitsch   DMCreateInjection - Gets injection matrix between two `DM` objects.
133447c6ae99SBarry Smith 
133520f4b53cSBarry Smith   Collective
133647c6ae99SBarry Smith 
1337d8d19677SJose E. Roman   Input Parameters:
1338bb7acecfSBarry Smith + dac - the `DM` object
1339bb7acecfSBarry Smith - daf - the second, finer `DM` object
134047c6ae99SBarry Smith 
134147c6ae99SBarry Smith   Output Parameter:
13426dbf9973SLawrence Mitchell . mat - the injection
134347c6ae99SBarry Smith 
134447c6ae99SBarry Smith   Level: developer
134547c6ae99SBarry Smith 
1346a4e35b19SJacob Faibussowitsch   Notes:
1347a4e35b19SJacob Faibussowitsch   This is an operator that applied to a vector obtained with `DMCreateGlobalVector()` on the
1348a4e35b19SJacob Faibussowitsch   fine grid maps the values to a vector on the vector on the coarse `DM` by simply selecting
1349a4e35b19SJacob Faibussowitsch   the values on the coarse grid points. This compares to the operator obtained by
1350a4e35b19SJacob Faibussowitsch   `DMCreateRestriction()` or the transpose of the operator obtained by
1351a4e35b19SJacob Faibussowitsch   `DMCreateInterpolation()` that uses a "local weighted average" of the values around the
1352a4e35b19SJacob Faibussowitsch   coarse grid point as the coarse grid value.
1353a4e35b19SJacob Faibussowitsch 
1354bb7acecfSBarry 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
1355bb7acecfSBarry Smith   `DMCoarsen()`. The coordinates set into the `DMDA` are completely ignored in computing the injection.
135685afcc9aSBarry Smith 
13571cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateInterpolation()`,
1358bb7acecfSBarry Smith           `DMCreateRestriction()`, `MatRestrict()`, `MatInterpolate()`
135947c6ae99SBarry Smith @*/
1360d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection(DM dac, DM daf, Mat *mat)
1361d71ae5a4SJacob Faibussowitsch {
136247c6ae99SBarry Smith   PetscFunctionBegin;
1363a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dac, DM_CLASSID, 1);
1364a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(daf, DM_CLASSID, 2);
13654f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
13669566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateInjection, dac, daf, 0, 0));
1367dbbe0bcdSBarry Smith   PetscUseTypeMethod(dac, createinjection, daf, mat);
13689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateInjection, dac, daf, 0, 0));
13693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
137047c6ae99SBarry Smith }
137147c6ae99SBarry Smith 
1372b412c318SBarry Smith /*@
1373bb7acecfSBarry 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
1374bb7acecfSBarry Smith   a Galerkin finite element model on the `DM`
1375bd041c0cSMatthew G. Knepley 
137620f4b53cSBarry Smith   Collective
1377bd041c0cSMatthew G. Knepley 
1378d8d19677SJose E. Roman   Input Parameters:
1379bb7acecfSBarry Smith + dmc - the target `DM` object
13808c1c0954SStefano Zampini - dmf - the source `DM` object, can be `NULL`
1381bd041c0cSMatthew G. Knepley 
1382bd041c0cSMatthew G. Knepley   Output Parameter:
1383b4937a87SMatthew G. Knepley . mat - the mass matrix
1384bd041c0cSMatthew G. Knepley 
1385bd041c0cSMatthew G. Knepley   Level: developer
1386bd041c0cSMatthew G. Knepley 
1387bb7acecfSBarry Smith   Notes:
1388bb7acecfSBarry Smith   For `DMPLEX` the finite element model for the `DM` must have been already provided.
1389bb7acecfSBarry Smith 
13908c1c0954SStefano Zampini   if `dmc` is `dmf` or `NULL`, then x^t M x is an approximation to the L2 norm of the vector x which is obtained by `DMCreateGlobalVector()`
1391bb7acecfSBarry Smith 
139242747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateMassMatrixLumped()`, `DMCreateMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolation()`, `DMCreateInjection()`
1393bd041c0cSMatthew G. Knepley @*/
1394d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix(DM dmc, DM dmf, Mat *mat)
1395d71ae5a4SJacob Faibussowitsch {
1396bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
1397b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
13988c1c0954SStefano Zampini   if (!dmf) dmf = dmc;
1399b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
14004f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
14018c1c0954SStefano Zampini   PetscCall(PetscLogEventBegin(DM_CreateMassMatrix, dmc, dmf, 0, 0));
1402dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createmassmatrix, dmf, mat);
14038c1c0954SStefano Zampini   PetscCall(PetscLogEventEnd(DM_CreateMassMatrix, dmc, dmf, 0, 0));
14043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1405b4937a87SMatthew G. Knepley }
1406b4937a87SMatthew G. Knepley 
1407b4937a87SMatthew G. Knepley /*@
1408bb7acecfSBarry Smith   DMCreateMassMatrixLumped - Gets the lumped mass matrix for a given `DM`
1409b4937a87SMatthew G. Knepley 
141020f4b53cSBarry Smith   Collective
1411b4937a87SMatthew G. Knepley 
1412b4937a87SMatthew G. Knepley   Input Parameter:
1413bb7acecfSBarry Smith . dm - the `DM` object
1414b4937a87SMatthew G. Knepley 
14157dcfde4dSJose E. Roman   Output Parameters:
14168e9849d2SStefano Zampini + llm - the local lumped mass matrix, which is a diagonal matrix, represented as a vector
14178e9849d2SStefano Zampini - lm  - the global lumped mass matrix, which is a diagonal matrix, represented as a vector
1418b4937a87SMatthew G. Knepley 
1419b4937a87SMatthew G. Knepley   Level: developer
1420b4937a87SMatthew G. Knepley 
1421bb7acecfSBarry Smith   Note:
1422bb7acecfSBarry Smith   See `DMCreateMassMatrix()` for how to create the non-lumped version of the mass matrix.
1423bb7acecfSBarry Smith 
142460225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateMassMatrix()`, `DMCreateMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolation()`, `DMCreateInjection()`
1425b4937a87SMatthew G. Knepley @*/
14268e9849d2SStefano Zampini PetscErrorCode DMCreateMassMatrixLumped(DM dm, Vec *llm, Vec *lm)
1427d71ae5a4SJacob Faibussowitsch {
1428b4937a87SMatthew G. Knepley   PetscFunctionBegin;
1429b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14308e9849d2SStefano Zampini   if (llm) PetscAssertPointer(llm, 2);
14318e9849d2SStefano Zampini   if (lm) PetscAssertPointer(lm, 3);
14328e9849d2SStefano Zampini   if (llm || lm) PetscUseTypeMethod(dm, createmassmatrixlumped, llm, lm);
14333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1434bd041c0cSMatthew G. Knepley }
1435bd041c0cSMatthew G. Knepley 
1436bd041c0cSMatthew G. Knepley /*@
1437bb7acecfSBarry Smith   DMCreateColoring - Gets coloring of a graph associated with the `DM`. Often the graph represents the operator matrix associated with the discretization
1438bb7acecfSBarry Smith   of a PDE on the `DM`.
143947c6ae99SBarry Smith 
144020f4b53cSBarry Smith   Collective
144147c6ae99SBarry Smith 
1442d8d19677SJose E. Roman   Input Parameters:
1443bb7acecfSBarry Smith + dm    - the `DM` object
1444bb7acecfSBarry Smith - ctype - `IS_COLORING_LOCAL` or `IS_COLORING_GLOBAL`
144547c6ae99SBarry Smith 
144647c6ae99SBarry Smith   Output Parameter:
144747c6ae99SBarry Smith . coloring - the coloring
144847c6ae99SBarry Smith 
14491bf8429eSBarry Smith   Level: developer
14501bf8429eSBarry Smith 
1451ec5066bdSBarry Smith   Notes:
1452bb7acecfSBarry 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
1453bb7acecfSBarry Smith   matrix comes from (what this function provides). In general using the mesh produces a more optimal coloring (fewer colors).
1454ec5066bdSBarry Smith 
1455bb7acecfSBarry Smith   This produces a coloring with the distance of 2, see `MatSetColoringDistance()` which can be used for efficiently computing Jacobians with `MatFDColoringCreate()`
14561bf8429eSBarry Smith   For `DMDA` in three dimensions with periodic boundary conditions the number of grid points in each dimension must be divisible by 2*stencil_width + 1,
14571bf8429eSBarry Smith   otherwise an error will be generated.
1458ec5066bdSBarry Smith 
14591cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `ISColoring`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatType()`, `MatColoring`, `MatFDColoringCreate()`
1460aab9d709SJed Brown @*/
1461d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring(DM dm, ISColoringType ctype, ISColoring *coloring)
1462d71ae5a4SJacob Faibussowitsch {
146347c6ae99SBarry Smith   PetscFunctionBegin;
1464171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14654f572ea9SToby Isaac   PetscAssertPointer(coloring, 3);
1466dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getcoloring, ctype, coloring);
14673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
146847c6ae99SBarry Smith }
146947c6ae99SBarry Smith 
1470b412c318SBarry Smith /*@
1471bb7acecfSBarry Smith   DMCreateMatrix - Gets an empty matrix for a `DM` that is most commonly used to store the Jacobian of a discrete PDE operator.
147247c6ae99SBarry Smith 
147320f4b53cSBarry Smith   Collective
147447c6ae99SBarry Smith 
147547c6ae99SBarry Smith   Input Parameter:
1476bb7acecfSBarry Smith . dm - the `DM` object
147747c6ae99SBarry Smith 
147847c6ae99SBarry Smith   Output Parameter:
147947c6ae99SBarry Smith . mat - the empty Jacobian
148047c6ae99SBarry Smith 
148120f4b53cSBarry Smith   Options Database Key:
1482bb7acecfSBarry Smith . -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()` and `DMCreateMassMatrix()`, but do not fill it with zeros
1483f27dd7c6SMatthew G. Knepley 
148420f4b53cSBarry Smith   Level: beginner
148520f4b53cSBarry Smith 
148695452b02SPatrick Sanan   Notes:
148795452b02SPatrick Sanan   This properly preallocates the number of nonzeros in the sparse matrix so you
148894013140SBarry Smith   do not need to do it yourself.
148994013140SBarry Smith 
149094013140SBarry Smith   By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1491bb7acecfSBarry Smith   the nonzero pattern call `DMSetMatrixPreallocateOnly()`
149294013140SBarry Smith 
1493bb7acecfSBarry Smith   For `DMDA`, when you call `MatView()` on this matrix it is displayed using the global natural ordering, NOT in the ordering used
149494013140SBarry Smith   internally by PETSc.
149594013140SBarry Smith 
1496bb7acecfSBarry Smith   For `DMDA`, in general it is easiest to use `MatSetValuesStencil()` or `MatSetValuesLocal()` to put values into the matrix because
1497bb7acecfSBarry Smith   `MatSetValues()` requires the indices for the global numbering for the `DMDA` which is complic`ated to compute
149894013140SBarry Smith 
14991cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMSetMatType()`, `DMCreateMassMatrix()`
1500aab9d709SJed Brown @*/
1501d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix(DM dm, Mat *mat)
1502d71ae5a4SJacob Faibussowitsch {
150347c6ae99SBarry Smith   PetscFunctionBegin;
1504171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
15054f572ea9SToby Isaac   PetscAssertPointer(mat, 2);
15069566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
15079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateMatrix, 0, 0, 0, 0));
1508dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, creatematrix, mat);
150976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1510c6b011d8SStefano Zampini     DM mdm;
1511c6b011d8SStefano Zampini 
15129566063dSJacob Faibussowitsch     PetscCall(MatGetDM(*mat, &mdm));
15137a8be351SBarry Smith     PetscCheck(mdm, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DM type '%s' did not attach the DM to the matrix", ((PetscObject)dm)->type_name);
1514c6b011d8SStefano Zampini   }
1515e571a35bSMatthew G. Knepley   /* Handle nullspace and near nullspace */
1516e5e52638SMatthew G. Knepley   if (dm->Nf) {
1517e571a35bSMatthew G. Knepley     MatNullSpace nullSpace;
1518649ef022SMatthew Knepley     PetscInt     Nf, f;
1519e571a35bSMatthew G. Knepley 
15209566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
1521649ef022SMatthew Knepley     for (f = 0; f < Nf; ++f) {
1522649ef022SMatthew Knepley       if (dm->nullspaceConstructors[f]) {
15239566063dSJacob Faibussowitsch         PetscCall((*dm->nullspaceConstructors[f])(dm, f, f, &nullSpace));
15249566063dSJacob Faibussowitsch         PetscCall(MatSetNullSpace(*mat, nullSpace));
15259566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nullSpace));
1526649ef022SMatthew Knepley         break;
1527e571a35bSMatthew G. Knepley       }
1528649ef022SMatthew Knepley     }
1529649ef022SMatthew Knepley     for (f = 0; f < Nf; ++f) {
1530649ef022SMatthew Knepley       if (dm->nearnullspaceConstructors[f]) {
15319566063dSJacob Faibussowitsch         PetscCall((*dm->nearnullspaceConstructors[f])(dm, f, f, &nullSpace));
15329566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(*mat, nullSpace));
15339566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nullSpace));
1534e571a35bSMatthew G. Knepley       }
1535e571a35bSMatthew G. Knepley     }
1536e571a35bSMatthew G. Knepley   }
15379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateMatrix, 0, 0, 0, 0));
15383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
153947c6ae99SBarry Smith }
154047c6ae99SBarry Smith 
1541732e2eb9SMatthew G Knepley /*@
1542a4e35b19SJacob Faibussowitsch   DMSetMatrixPreallocateSkip - When `DMCreateMatrix()` is called the matrix sizes and
1543a4e35b19SJacob Faibussowitsch   `ISLocalToGlobalMapping` will be properly set, but the data structures to store values in the
1544a4e35b19SJacob Faibussowitsch   matrices will not be preallocated.
1545aa0f6e3cSJed Brown 
154620f4b53cSBarry Smith   Logically Collective
1547aa0f6e3cSJed Brown 
1548aa0f6e3cSJed Brown   Input Parameters:
1549bb7acecfSBarry Smith + dm   - the `DM`
1550bb7acecfSBarry Smith - skip - `PETSC_TRUE` to skip preallocation
1551aa0f6e3cSJed Brown 
1552aa0f6e3cSJed Brown   Level: developer
1553aa0f6e3cSJed Brown 
155473ff1848SBarry Smith   Note:
1555a4e35b19SJacob Faibussowitsch   This is most useful to reduce initialization costs when `MatSetPreallocationCOO()` and
1556a4e35b19SJacob Faibussowitsch   `MatSetValuesCOO()` will be used.
1557a4e35b19SJacob Faibussowitsch 
15581cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMSetMatrixStructureOnly()`, `DMSetMatrixPreallocateOnly()`
1559aa0f6e3cSJed Brown @*/
1560d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixPreallocateSkip(DM dm, PetscBool skip)
1561d71ae5a4SJacob Faibussowitsch {
1562aa0f6e3cSJed Brown   PetscFunctionBegin;
1563aa0f6e3cSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1564aa0f6e3cSJed Brown   dm->prealloc_skip = skip;
15653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1566aa0f6e3cSJed Brown }
1567aa0f6e3cSJed Brown 
1568aa0f6e3cSJed Brown /*@
1569bb7acecfSBarry Smith   DMSetMatrixPreallocateOnly - When `DMCreateMatrix()` is called the matrix will be properly
1570732e2eb9SMatthew G Knepley   preallocated but the nonzero structure and zero values will not be set.
1571732e2eb9SMatthew G Knepley 
157220f4b53cSBarry Smith   Logically Collective
1573732e2eb9SMatthew G Knepley 
1574d8d19677SJose E. Roman   Input Parameters:
1575bb7acecfSBarry Smith + dm   - the `DM`
1576bb7acecfSBarry Smith - only - `PETSC_TRUE` if only want preallocation
1577732e2eb9SMatthew G Knepley 
157820f4b53cSBarry Smith   Options Database Key:
1579bb7acecfSBarry Smith . -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()`, `DMCreateMassMatrix()`, but do not fill it with zeros
1580f27dd7c6SMatthew G. Knepley 
158120f4b53cSBarry Smith   Level: developer
158220f4b53cSBarry Smith 
15831cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixStructureOnly()`, `DMSetMatrixPreallocateSkip()`
1584732e2eb9SMatthew G Knepley @*/
1585d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1586d71ae5a4SJacob Faibussowitsch {
1587732e2eb9SMatthew G Knepley   PetscFunctionBegin;
1588732e2eb9SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1589732e2eb9SMatthew G Knepley   dm->prealloc_only = only;
15903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1591732e2eb9SMatthew G Knepley }
1592732e2eb9SMatthew G Knepley 
1593b06ff27eSHong Zhang /*@
15940b4b7b1cSBarry Smith   DMSetMatrixStructureOnly - When `DMCreateMatrix()` is called, the matrix nonzero structure will be created
1595bb7acecfSBarry Smith   but the array for numerical values will not be allocated.
1596b06ff27eSHong Zhang 
159720f4b53cSBarry Smith   Logically Collective
1598b06ff27eSHong Zhang 
1599d8d19677SJose E. Roman   Input Parameters:
1600bb7acecfSBarry Smith + dm   - the `DM`
16010b4b7b1cSBarry Smith - only - `PETSC_TRUE` if you only want matrix nonzero structure
1602b06ff27eSHong Zhang 
1603b06ff27eSHong Zhang   Level: developer
1604bb7acecfSBarry Smith 
16051cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMSetMatrixPreallocateOnly()`, `DMSetMatrixPreallocateSkip()`
1606b06ff27eSHong Zhang @*/
1607d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1608d71ae5a4SJacob Faibussowitsch {
1609b06ff27eSHong Zhang   PetscFunctionBegin;
1610b06ff27eSHong Zhang   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1611b06ff27eSHong Zhang   dm->structure_only = only;
16123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1613b06ff27eSHong Zhang }
1614b06ff27eSHong Zhang 
1615863027abSJed Brown /*@
1616863027abSJed Brown   DMSetBlockingType - set the blocking granularity to be used for variable block size `DMCreateMatrix()` is called
1617863027abSJed Brown 
161820f4b53cSBarry Smith   Logically Collective
1619863027abSJed Brown 
1620863027abSJed Brown   Input Parameters:
1621863027abSJed Brown + dm    - the `DM`
1622863027abSJed Brown - btype - block by topological point or field node
1623863027abSJed Brown 
162420f4b53cSBarry Smith   Options Database Key:
16250e762ea3SJed Brown . -dm_blocking_type [topological_point, field_node] - use topological point blocking or field node blocking
1626863027abSJed Brown 
162720f4b53cSBarry Smith   Level: advanced
162820f4b53cSBarry Smith 
16291cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `MatSetVariableBlockSizes()`
1630863027abSJed Brown @*/
1631863027abSJed Brown PetscErrorCode DMSetBlockingType(DM dm, DMBlockingType btype)
1632863027abSJed Brown {
1633863027abSJed Brown   PetscFunctionBegin;
1634863027abSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1635863027abSJed Brown   dm->blocking_type = btype;
16363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1637863027abSJed Brown }
1638863027abSJed Brown 
1639863027abSJed Brown /*@
1640863027abSJed Brown   DMGetBlockingType - get the blocking granularity to be used for variable block size `DMCreateMatrix()` is called
1641863027abSJed Brown 
1642863027abSJed Brown   Not Collective
1643863027abSJed Brown 
16442fe279fdSBarry Smith   Input Parameter:
1645863027abSJed Brown . dm - the `DM`
1646863027abSJed Brown 
16472fe279fdSBarry Smith   Output Parameter:
1648863027abSJed Brown . btype - block by topological point or field node
1649863027abSJed Brown 
1650863027abSJed Brown   Level: advanced
1651863027abSJed Brown 
16521cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `MatSetVariableBlockSizes()`
1653863027abSJed Brown @*/
1654863027abSJed Brown PetscErrorCode DMGetBlockingType(DM dm, DMBlockingType *btype)
1655863027abSJed Brown {
1656863027abSJed Brown   PetscFunctionBegin;
1657863027abSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
16584f572ea9SToby Isaac   PetscAssertPointer(btype, 2);
1659863027abSJed Brown   *btype = dm->blocking_type;
16603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1661863027abSJed Brown }
1662863027abSJed Brown 
1663a89ea682SMatthew G Knepley /*@C
1664bb7acecfSBarry Smith   DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with `DMRestoreWorkArray()`
1665a89ea682SMatthew G Knepley 
1666a89ea682SMatthew G Knepley   Not Collective
1667a89ea682SMatthew G Knepley 
1668a89ea682SMatthew G Knepley   Input Parameters:
1669bb7acecfSBarry Smith + dm    - the `DM` object
1670a5b23f4aSJose E. Roman . count - The minimum size
167120f4b53cSBarry Smith - dtype - MPI data type, often `MPIU_REAL`, `MPIU_SCALAR`, or `MPIU_INT`)
1672a89ea682SMatthew G Knepley 
1673a89ea682SMatthew G Knepley   Output Parameter:
167460225df5SJacob Faibussowitsch . mem - the work array
1675a89ea682SMatthew G Knepley 
1676a89ea682SMatthew G Knepley   Level: developer
1677a89ea682SMatthew G Knepley 
167873ff1848SBarry Smith   Notes:
1679da81f932SPierre Jolivet   A `DM` may stash the array between instantiations so using this routine may be more efficient than calling `PetscMalloc()`
1680bb7acecfSBarry Smith 
1681bb7acecfSBarry Smith   The array may contain nonzero values
1682bb7acecfSBarry Smith 
16831cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMRestoreWorkArray()`, `PetscMalloc()`
1684a89ea682SMatthew G Knepley @*/
1685d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetWorkArray(DM dm, PetscInt count, MPI_Datatype dtype, void *mem)
1686d71ae5a4SJacob Faibussowitsch {
1687aa1993deSMatthew G Knepley   DMWorkLink  link;
168869291d52SBarry Smith   PetscMPIInt dsize;
1689a89ea682SMatthew G Knepley 
1690a89ea682SMatthew G Knepley   PetscFunctionBegin;
1691a89ea682SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
16924f572ea9SToby Isaac   PetscAssertPointer(mem, 4);
1693442f3b32SStefano Zampini   if (!count) {
1694442f3b32SStefano Zampini     *(void **)mem = NULL;
1695442f3b32SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
1696442f3b32SStefano Zampini   }
1697aa1993deSMatthew G Knepley   if (dm->workin) {
1698aa1993deSMatthew G Knepley     link       = dm->workin;
1699aa1993deSMatthew G Knepley     dm->workin = dm->workin->next;
1700aa1993deSMatthew G Knepley   } else {
17014dfa11a4SJacob Faibussowitsch     PetscCall(PetscNew(&link));
1702a89ea682SMatthew G Knepley   }
1703b77fa653SStefano Zampini   /* Avoid MPI_Type_size for most used datatypes
1704b77fa653SStefano Zampini      Get size directly */
1705b77fa653SStefano Zampini   if (dtype == MPIU_INT) dsize = sizeof(PetscInt);
1706b77fa653SStefano Zampini   else if (dtype == MPIU_REAL) dsize = sizeof(PetscReal);
1707b77fa653SStefano Zampini #if defined(PETSC_USE_64BIT_INDICES)
1708b77fa653SStefano Zampini   else if (dtype == MPI_INT) dsize = sizeof(int);
1709b77fa653SStefano Zampini #endif
1710b77fa653SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1711b77fa653SStefano Zampini   else if (dtype == MPIU_SCALAR) dsize = sizeof(PetscScalar);
1712b77fa653SStefano Zampini #endif
1713b77fa653SStefano Zampini   else PetscCallMPI(MPI_Type_size(dtype, &dsize));
1714b77fa653SStefano Zampini 
17155056fcd2SBarry Smith   if (((size_t)dsize * count) > link->bytes) {
17169566063dSJacob Faibussowitsch     PetscCall(PetscFree(link->mem));
17179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(dsize * count, &link->mem));
1718854ce69bSBarry Smith     link->bytes = dsize * count;
1719aa1993deSMatthew G Knepley   }
1720aa1993deSMatthew G Knepley   link->next    = dm->workout;
1721aa1993deSMatthew G Knepley   dm->workout   = link;
1722aa1993deSMatthew G Knepley   *(void **)mem = link->mem;
17233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1724a89ea682SMatthew G Knepley }
1725a89ea682SMatthew G Knepley 
1726aa1993deSMatthew G Knepley /*@C
1727bb7acecfSBarry Smith   DMRestoreWorkArray - Restores a work array obtained with `DMCreateWorkArray()`
1728aa1993deSMatthew G Knepley 
1729aa1993deSMatthew G Knepley   Not Collective
1730aa1993deSMatthew G Knepley 
1731aa1993deSMatthew G Knepley   Input Parameters:
1732bb7acecfSBarry Smith + dm    - the `DM` object
1733a5b23f4aSJose E. Roman . count - The minimum size
173420f4b53cSBarry Smith - dtype - MPI data type, often `MPIU_REAL`, `MPIU_SCALAR`, `MPIU_INT`
1735aa1993deSMatthew G Knepley 
1736aa1993deSMatthew G Knepley   Output Parameter:
173760225df5SJacob Faibussowitsch . mem - the work array
1738aa1993deSMatthew G Knepley 
1739aa1993deSMatthew G Knepley   Level: developer
1740aa1993deSMatthew G Knepley 
174173ff1848SBarry Smith   Developer Note:
1742bb7acecfSBarry Smith   count and dtype are ignored, they are only needed for `DMGetWorkArray()`
1743147403d9SBarry Smith 
17441cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMGetWorkArray()`
1745aa1993deSMatthew G Knepley @*/
1746d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestoreWorkArray(DM dm, PetscInt count, MPI_Datatype dtype, void *mem)
1747d71ae5a4SJacob Faibussowitsch {
1748aa1993deSMatthew G Knepley   DMWorkLink *p, link;
1749aa1993deSMatthew G Knepley 
1750aa1993deSMatthew G Knepley   PetscFunctionBegin;
1751aa1993deSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17524f572ea9SToby Isaac   PetscAssertPointer(mem, 4);
1753a4e35b19SJacob Faibussowitsch   (void)count;
1754a4e35b19SJacob Faibussowitsch   (void)dtype;
1755442f3b32SStefano Zampini   if (!*(void **)mem) PetscFunctionReturn(PETSC_SUCCESS);
1756aa1993deSMatthew G Knepley   for (p = &dm->workout; (link = *p); p = &link->next) {
1757aa1993deSMatthew G Knepley     if (link->mem == *(void **)mem) {
1758aa1993deSMatthew G Knepley       *p            = link->next;
1759aa1993deSMatthew G Knepley       link->next    = dm->workin;
1760aa1993deSMatthew G Knepley       dm->workin    = link;
17610298fd71SBarry Smith       *(void **)mem = NULL;
17623ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
1763aa1993deSMatthew G Knepley     }
1764aa1993deSMatthew G Knepley   }
1765aa1993deSMatthew G Knepley   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Array was not checked out");
1766aa1993deSMatthew G Knepley }
1767e7c4fc90SDmitry Karpeev 
17688cda7954SMatthew G. Knepley /*@C
1769bb7acecfSBarry Smith   DMSetNullSpaceConstructor - Provide a callback function which constructs the nullspace for a given field, defined with `DMAddField()`, when function spaces
1770bb7acecfSBarry Smith   are joined or split, such as in `DMCreateSubDM()`
17718cda7954SMatthew G. Knepley 
177220f4b53cSBarry Smith   Logically Collective; No Fortran Support
17738cda7954SMatthew G. Knepley 
17748cda7954SMatthew G. Knepley   Input Parameters:
1775bb7acecfSBarry Smith + dm     - The `DM`
17768cda7954SMatthew G. Knepley . field  - The field number for the nullspace
17778cda7954SMatthew G. Knepley - nullsp - A callback to create the nullspace
17788cda7954SMatthew G. Knepley 
177920f4b53cSBarry Smith   Calling sequence of `nullsp`:
1780bb7acecfSBarry Smith + dm        - The present `DM`
1781bb7acecfSBarry Smith . origField - The field number given above, in the original `DM`
1782147403d9SBarry Smith . field     - The field number in dm
1783147403d9SBarry Smith - nullSpace - The nullspace for the given field
17848cda7954SMatthew G. Knepley 
178549762cbcSSatish Balay   Level: intermediate
178649762cbcSSatish Balay 
17871cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetNullSpaceConstructor()`, `DMSetNearNullSpaceConstructor()`, `DMGetNearNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
1788147403d9SBarry Smith @*/
1789a4e35b19SJacob Faibussowitsch PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1790d71ae5a4SJacob Faibussowitsch {
1791435a35e8SMatthew G Knepley   PetscFunctionBegin;
1792435a35e8SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17937a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1794435a35e8SMatthew G Knepley   dm->nullspaceConstructors[field] = nullsp;
17953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1796435a35e8SMatthew G Knepley }
1797435a35e8SMatthew G Knepley 
17988cda7954SMatthew G. Knepley /*@C
1799bb7acecfSBarry Smith   DMGetNullSpaceConstructor - Return the callback function which constructs the nullspace for a given field, defined with `DMAddField()`
18008cda7954SMatthew G. Knepley 
180120f4b53cSBarry Smith   Not Collective; No Fortran Support
18028cda7954SMatthew G. Knepley 
18038cda7954SMatthew G. Knepley   Input Parameters:
1804bb7acecfSBarry Smith + dm    - The `DM`
18058cda7954SMatthew G. Knepley - field - The field number for the nullspace
18068cda7954SMatthew G. Knepley 
18078cda7954SMatthew G. Knepley   Output Parameter:
18088cda7954SMatthew G. Knepley . nullsp - A callback to create the nullspace
18098cda7954SMatthew G. Knepley 
181020f4b53cSBarry Smith   Calling sequence of `nullsp`:
1811147403d9SBarry Smith + dm        - The present DM
1812147403d9SBarry Smith . origField - The field number given above, in the original DM
1813147403d9SBarry Smith . field     - The field number in dm
1814147403d9SBarry Smith - nullSpace - The nullspace for the given field
18158cda7954SMatthew G. Knepley 
181649762cbcSSatish Balay   Level: intermediate
181749762cbcSSatish Balay 
18181cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMSetNullSpaceConstructor()`, `DMSetNearNullSpaceConstructor()`, `DMGetNearNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
1819147403d9SBarry Smith @*/
1820a4e35b19SJacob Faibussowitsch PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1821d71ae5a4SJacob Faibussowitsch {
18220a50eb56SMatthew G. Knepley   PetscFunctionBegin;
18230a50eb56SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18244f572ea9SToby Isaac   PetscAssertPointer(nullsp, 3);
18257a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
18260a50eb56SMatthew G. Knepley   *nullsp = dm->nullspaceConstructors[field];
18273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18280a50eb56SMatthew G. Knepley }
18290a50eb56SMatthew G. Knepley 
18308cda7954SMatthew G. Knepley /*@C
1831bb7acecfSBarry Smith   DMSetNearNullSpaceConstructor - Provide a callback function which constructs the near-nullspace for a given field, defined with `DMAddField()`
18328cda7954SMatthew G. Knepley 
183320f4b53cSBarry Smith   Logically Collective; No Fortran Support
18348cda7954SMatthew G. Knepley 
18358cda7954SMatthew G. Knepley   Input Parameters:
1836bb7acecfSBarry Smith + dm     - The `DM`
18378cda7954SMatthew G. Knepley . field  - The field number for the nullspace
18388cda7954SMatthew G. Knepley - nullsp - A callback to create the near-nullspace
18398cda7954SMatthew G. Knepley 
184020f4b53cSBarry Smith   Calling sequence of `nullsp`:
1841bb7acecfSBarry Smith + dm        - The present `DM`
1842bb7acecfSBarry Smith . origField - The field number given above, in the original `DM`
1843147403d9SBarry Smith . field     - The field number in dm
1844147403d9SBarry Smith - nullSpace - The nullspace for the given field
18458cda7954SMatthew G. Knepley 
184649762cbcSSatish Balay   Level: intermediate
184749762cbcSSatish Balay 
18481cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetNearNullSpaceConstructor()`, `DMSetNullSpaceConstructor()`, `DMGetNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`,
1849bb7acecfSBarry Smith           `MatNullSpace`
1850147403d9SBarry Smith @*/
1851a4e35b19SJacob Faibussowitsch PetscErrorCode DMSetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1852d71ae5a4SJacob Faibussowitsch {
1853f9d4088aSMatthew G. Knepley   PetscFunctionBegin;
1854f9d4088aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18557a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1856f9d4088aSMatthew G. Knepley   dm->nearnullspaceConstructors[field] = nullsp;
18573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1858f9d4088aSMatthew G. Knepley }
1859f9d4088aSMatthew G. Knepley 
18608cda7954SMatthew G. Knepley /*@C
1861bb7acecfSBarry Smith   DMGetNearNullSpaceConstructor - Return the callback function which constructs the near-nullspace for a given field, defined with `DMAddField()`
18628cda7954SMatthew G. Knepley 
186320f4b53cSBarry Smith   Not Collective; No Fortran Support
18648cda7954SMatthew G. Knepley 
18658cda7954SMatthew G. Knepley   Input Parameters:
1866bb7acecfSBarry Smith + dm    - The `DM`
18678cda7954SMatthew G. Knepley - field - The field number for the nullspace
18688cda7954SMatthew G. Knepley 
18698cda7954SMatthew G. Knepley   Output Parameter:
18708cda7954SMatthew G. Knepley . nullsp - A callback to create the near-nullspace
18718cda7954SMatthew G. Knepley 
187220f4b53cSBarry Smith   Calling sequence of `nullsp`:
1873bb7acecfSBarry Smith + dm        - The present `DM`
1874bb7acecfSBarry Smith . origField - The field number given above, in the original `DM`
1875147403d9SBarry Smith . field     - The field number in dm
1876147403d9SBarry Smith - nullSpace - The nullspace for the given field
18778cda7954SMatthew G. Knepley 
187849762cbcSSatish Balay   Level: intermediate
187949762cbcSSatish Balay 
18801cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMSetNearNullSpaceConstructor()`, `DMSetNullSpaceConstructor()`, `DMGetNullSpaceConstructor()`, `DMCreateSubDM()`,
1881bb7acecfSBarry Smith           `MatNullSpace`, `DMCreateSuperDM()`
1882147403d9SBarry Smith @*/
1883a4e35b19SJacob Faibussowitsch PetscErrorCode DMGetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1884d71ae5a4SJacob Faibussowitsch {
1885f9d4088aSMatthew G. Knepley   PetscFunctionBegin;
1886f9d4088aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18874f572ea9SToby Isaac   PetscAssertPointer(nullsp, 3);
18887a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1889f9d4088aSMatthew G. Knepley   *nullsp = dm->nearnullspaceConstructors[field];
18903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1891f9d4088aSMatthew G. Knepley }
1892f9d4088aSMatthew G. Knepley 
18934f3b5142SJed Brown /*@C
1894bb7acecfSBarry Smith   DMCreateFieldIS - Creates a set of `IS` objects with the global indices of dofs for each field defined with `DMAddField()`
18954d343eeaSMatthew G Knepley 
189620f4b53cSBarry Smith   Not Collective; No Fortran Support
18974d343eeaSMatthew G Knepley 
18984d343eeaSMatthew G Knepley   Input Parameter:
1899bb7acecfSBarry Smith . dm - the `DM` object
19004d343eeaSMatthew G Knepley 
19014d343eeaSMatthew G Knepley   Output Parameters:
190220f4b53cSBarry Smith + numFields  - The number of fields (or `NULL` if not requested)
190320f4b53cSBarry Smith . fieldNames - The number of each field (or `NULL` if not requested)
190420f4b53cSBarry Smith - fields     - The global indices for each field (or `NULL` if not requested)
19054d343eeaSMatthew G Knepley 
19064d343eeaSMatthew G Knepley   Level: intermediate
19074d343eeaSMatthew G Knepley 
1908bb7acecfSBarry Smith   Note:
190973ff1848SBarry Smith   The user is responsible for freeing all requested arrays. In particular, every entry of `fieldNames` should be freed with
191073ff1848SBarry Smith   `PetscFree()`, every entry of `fields` should be destroyed with `ISDestroy()`, and both arrays should be freed with
1911bb7acecfSBarry Smith   `PetscFree()`.
191221c9b008SJed Brown 
191373ff1848SBarry Smith   Developer Note:
1914bb7acecfSBarry Smith   It is not clear why both this function and `DMCreateFieldDecomposition()` exist. Having two seems redundant and confusing. This function should
1915bb7acecfSBarry Smith   likely be removed.
1916bb7acecfSBarry Smith 
19171cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
1918bb7acecfSBarry Smith           `DMCreateFieldDecomposition()`
19194d343eeaSMatthew G Knepley @*/
1920d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1921d71ae5a4SJacob Faibussowitsch {
192237d0c07bSMatthew G Knepley   PetscSection section, sectionGlobal;
19234d343eeaSMatthew G Knepley 
19244d343eeaSMatthew G Knepley   PetscFunctionBegin;
19254d343eeaSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
192669ca1f37SDmitry Karpeev   if (numFields) {
19274f572ea9SToby Isaac     PetscAssertPointer(numFields, 2);
192869ca1f37SDmitry Karpeev     *numFields = 0;
192969ca1f37SDmitry Karpeev   }
193037d0c07bSMatthew G Knepley   if (fieldNames) {
19314f572ea9SToby Isaac     PetscAssertPointer(fieldNames, 3);
19320298fd71SBarry Smith     *fieldNames = NULL;
193369ca1f37SDmitry Karpeev   }
193469ca1f37SDmitry Karpeev   if (fields) {
19354f572ea9SToby Isaac     PetscAssertPointer(fields, 4);
19360298fd71SBarry Smith     *fields = NULL;
193769ca1f37SDmitry Karpeev   }
19389566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
193937d0c07bSMatthew G Knepley   if (section) {
19403a544194SStefano Zampini     PetscInt *fieldSizes, *fieldNc, **fieldIndices;
194137d0c07bSMatthew G Knepley     PetscInt  nF, f, pStart, pEnd, p;
194237d0c07bSMatthew G Knepley 
19439566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
19449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &nF));
19459566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(nF, &fieldSizes, nF, &fieldNc, nF, &fieldIndices));
19469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
194737d0c07bSMatthew G Knepley     for (f = 0; f < nF; ++f) {
194837d0c07bSMatthew G Knepley       fieldSizes[f] = 0;
19499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &fieldNc[f]));
195037d0c07bSMatthew G Knepley     }
195137d0c07bSMatthew G Knepley     for (p = pStart; p < pEnd; ++p) {
195237d0c07bSMatthew G Knepley       PetscInt gdof;
195337d0c07bSMatthew G Knepley 
19549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
195537d0c07bSMatthew G Knepley       if (gdof > 0) {
195637d0c07bSMatthew G Knepley         for (f = 0; f < nF; ++f) {
19573a544194SStefano Zampini           PetscInt fdof, fcdof, fpdof;
195837d0c07bSMatthew G Knepley 
19599566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
19609566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
19613a544194SStefano Zampini           fpdof = fdof - fcdof;
19623a544194SStefano Zampini           if (fpdof && fpdof != fieldNc[f]) {
19633a544194SStefano Zampini             /* Layout does not admit a pointwise block size */
19643a544194SStefano Zampini             fieldNc[f] = 1;
19653a544194SStefano Zampini           }
19663a544194SStefano Zampini           fieldSizes[f] += fpdof;
196737d0c07bSMatthew G Knepley         }
196837d0c07bSMatthew G Knepley       }
196937d0c07bSMatthew G Knepley     }
197037d0c07bSMatthew G Knepley     for (f = 0; f < nF; ++f) {
19719566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(fieldSizes[f], &fieldIndices[f]));
197237d0c07bSMatthew G Knepley       fieldSizes[f] = 0;
197337d0c07bSMatthew G Knepley     }
197437d0c07bSMatthew G Knepley     for (p = pStart; p < pEnd; ++p) {
197537d0c07bSMatthew G Knepley       PetscInt gdof, goff;
197637d0c07bSMatthew G Knepley 
19779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
197837d0c07bSMatthew G Knepley       if (gdof > 0) {
19799566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff));
198037d0c07bSMatthew G Knepley         for (f = 0; f < nF; ++f) {
198137d0c07bSMatthew G Knepley           PetscInt fdof, fcdof, fc;
198237d0c07bSMatthew G Knepley 
19839566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
19849566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
1985ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++fieldSizes[f]) fieldIndices[f][fieldSizes[f]] = goff++;
198637d0c07bSMatthew G Knepley         }
198737d0c07bSMatthew G Knepley       }
198837d0c07bSMatthew G Knepley     }
19898865f1eaSKarl Rupp     if (numFields) *numFields = nF;
199037d0c07bSMatthew G Knepley     if (fieldNames) {
19919566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nF, fieldNames));
199237d0c07bSMatthew G Knepley       for (f = 0; f < nF; ++f) {
199337d0c07bSMatthew G Knepley         const char *fieldName;
199437d0c07bSMatthew G Knepley 
19959566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
1996835f2295SStefano Zampini         PetscCall(PetscStrallocpy(fieldName, &(*fieldNames)[f]));
199737d0c07bSMatthew G Knepley       }
199837d0c07bSMatthew G Knepley     }
199937d0c07bSMatthew G Knepley     if (fields) {
20009566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nF, fields));
200137d0c07bSMatthew G Knepley       for (f = 0; f < nF; ++f) {
20023a544194SStefano Zampini         PetscInt bs, in[2], out[2];
20033a544194SStefano Zampini 
20049566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]));
20053a544194SStefano Zampini         in[0] = -fieldNc[f];
20063a544194SStefano Zampini         in[1] = fieldNc[f];
2007462c564dSBarry Smith         PetscCallMPI(MPIU_Allreduce(in, out, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
20083a544194SStefano Zampini         bs = (-out[0] == out[1]) ? out[1] : 1;
20099566063dSJacob Faibussowitsch         PetscCall(ISSetBlockSize((*fields)[f], bs));
201037d0c07bSMatthew G Knepley       }
201137d0c07bSMatthew G Knepley     }
20129566063dSJacob Faibussowitsch     PetscCall(PetscFree3(fieldSizes, fieldNc, fieldIndices));
2013dbbe0bcdSBarry Smith   } else PetscTryTypeMethod(dm, createfieldis, numFields, fieldNames, fields);
20143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20154d343eeaSMatthew G Knepley }
20164d343eeaSMatthew G Knepley 
201716621825SDmitry Karpeev /*@C
2018bb7acecfSBarry Smith   DMCreateFieldDecomposition - Returns a list of `IS` objects defining a decomposition of a problem into subproblems
2019a4e35b19SJacob Faibussowitsch   corresponding to different fields.
2020e7c4fc90SDmitry Karpeev 
202120f4b53cSBarry Smith   Not Collective; No Fortran Support
2022e7c4fc90SDmitry Karpeev 
2023e7c4fc90SDmitry Karpeev   Input Parameter:
2024bb7acecfSBarry Smith . dm - the `DM` object
2025e7c4fc90SDmitry Karpeev 
2026e7c4fc90SDmitry Karpeev   Output Parameters:
202720f4b53cSBarry Smith + len      - The number of fields (or `NULL` if not requested)
202820f4b53cSBarry Smith . namelist - The name for each field (or `NULL` if not requested)
202920f4b53cSBarry Smith . islist   - The global indices for each field (or `NULL` if not requested)
203020f4b53cSBarry Smith - dmlist   - The `DM`s for each field subproblem (or `NULL`, if not requested; if `NULL` is returned, no `DM`s are defined)
2031e7c4fc90SDmitry Karpeev 
2032e7c4fc90SDmitry Karpeev   Level: intermediate
2033e7c4fc90SDmitry Karpeev 
2034a4e35b19SJacob Faibussowitsch   Notes:
2035a4e35b19SJacob Faibussowitsch   Each `IS` contains the global indices of the dofs of the corresponding field, defined by
2036a4e35b19SJacob Faibussowitsch   `DMAddField()`. The optional list of `DM`s define the `DM` for each subproblem.
2037a4e35b19SJacob Faibussowitsch 
2038a4e35b19SJacob Faibussowitsch   The same as `DMCreateFieldIS()` but also returns a `DM` for each field.
2039a4e35b19SJacob Faibussowitsch 
204073ff1848SBarry Smith   The user is responsible for freeing all requested arrays. In particular, every entry of `namelist` should be freed with
204173ff1848SBarry Smith   `PetscFree()`, every entry of `islist` should be destroyed with `ISDestroy()`, every entry of `dmlist` should be destroyed with `DMDestroy()`,
2042bb7acecfSBarry Smith   and all of the arrays should be freed with `PetscFree()`.
2043e7c4fc90SDmitry Karpeev 
204460225df5SJacob Faibussowitsch   Developer Notes:
2045bb7acecfSBarry Smith   It is not clear why this function and `DMCreateFieldIS()` exist. Having two seems redundant and confusing.
2046bb7acecfSBarry Smith 
204773ff1848SBarry Smith   Unlike  `DMRefine()`, `DMCoarsen()`, and `DMCreateDomainDecomposition()` this provides no mechanism to provide hooks that are called after the
204873ff1848SBarry Smith   decomposition is computed.
204973ff1848SBarry Smith 
205073ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMCreateFieldIS()`, `DMCreateSubDM()`, `DMCreateDomainDecomposition()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`
2051e7c4fc90SDmitry Karpeev @*/
2052d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
2053d71ae5a4SJacob Faibussowitsch {
2054e7c4fc90SDmitry Karpeev   PetscFunctionBegin;
2055e7c4fc90SDmitry Karpeev   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20568865f1eaSKarl Rupp   if (len) {
20574f572ea9SToby Isaac     PetscAssertPointer(len, 2);
20588865f1eaSKarl Rupp     *len = 0;
20598865f1eaSKarl Rupp   }
20608865f1eaSKarl Rupp   if (namelist) {
20614f572ea9SToby Isaac     PetscAssertPointer(namelist, 3);
2062ea78f98cSLisandro Dalcin     *namelist = NULL;
20638865f1eaSKarl Rupp   }
20648865f1eaSKarl Rupp   if (islist) {
20654f572ea9SToby Isaac     PetscAssertPointer(islist, 4);
2066ea78f98cSLisandro Dalcin     *islist = NULL;
20678865f1eaSKarl Rupp   }
20688865f1eaSKarl Rupp   if (dmlist) {
20694f572ea9SToby Isaac     PetscAssertPointer(dmlist, 5);
2070ea78f98cSLisandro Dalcin     *dmlist = NULL;
20718865f1eaSKarl Rupp   }
2072f3f0edfdSDmitry Karpeev   /*
2073f3f0edfdSDmitry Karpeev    Is it a good idea to apply the following check across all impls?
2074f3f0edfdSDmitry Karpeev    Perhaps some impls can have a well-defined decomposition before DMSetUp?
2075f3f0edfdSDmitry Karpeev    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
2076f3f0edfdSDmitry Karpeev    */
20777a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
207816621825SDmitry Karpeev   if (!dm->ops->createfielddecomposition) {
2079435a35e8SMatthew G Knepley     PetscSection section;
2080435a35e8SMatthew G Knepley     PetscInt     numFields, f;
2081435a35e8SMatthew G Knepley 
20829566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
20839566063dSJacob Faibussowitsch     if (section) PetscCall(PetscSectionGetNumFields(section, &numFields));
2084435a35e8SMatthew G Knepley     if (section && numFields && dm->ops->createsubdm) {
2085f25d98f1SMatthew G. Knepley       if (len) *len = numFields;
20869566063dSJacob Faibussowitsch       if (namelist) PetscCall(PetscMalloc1(numFields, namelist));
20879566063dSJacob Faibussowitsch       if (islist) PetscCall(PetscMalloc1(numFields, islist));
20889566063dSJacob Faibussowitsch       if (dmlist) PetscCall(PetscMalloc1(numFields, dmlist));
2089435a35e8SMatthew G Knepley       for (f = 0; f < numFields; ++f) {
2090435a35e8SMatthew G Knepley         const char *fieldName;
2091435a35e8SMatthew G Knepley 
20929566063dSJacob Faibussowitsch         PetscCall(DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL));
209303dc3394SMatthew G. Knepley         if (namelist) {
20949566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
2095835f2295SStefano Zampini           PetscCall(PetscStrallocpy(fieldName, &(*namelist)[f]));
2096435a35e8SMatthew G Knepley         }
209703dc3394SMatthew G. Knepley       }
2098435a35e8SMatthew G Knepley     } else {
20999566063dSJacob Faibussowitsch       PetscCall(DMCreateFieldIS(dm, len, namelist, islist));
2100e7c4fc90SDmitry Karpeev       /* By default there are no DMs associated with subproblems. */
21010298fd71SBarry Smith       if (dmlist) *dmlist = NULL;
2102e7c4fc90SDmitry Karpeev     }
2103dbbe0bcdSBarry Smith   } else PetscUseTypeMethod(dm, createfielddecomposition, len, namelist, islist, dmlist);
21043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
210516621825SDmitry Karpeev }
210616621825SDmitry Karpeev 
21075d83a8b1SBarry Smith /*@
210820f4b53cSBarry Smith   DMCreateSubDM - Returns an `IS` and `DM` encapsulating a subproblem defined by the fields passed in.
210920f4b53cSBarry Smith   The fields are defined by `DMCreateFieldIS()`.
2110435a35e8SMatthew G Knepley 
2111435a35e8SMatthew G Knepley   Not collective
2112435a35e8SMatthew G Knepley 
2113435a35e8SMatthew G Knepley   Input Parameters:
2114bb7acecfSBarry Smith + dm        - The `DM` object
2115bb7acecfSBarry Smith . numFields - The number of fields to select
21162adcc780SMatthew G. Knepley - fields    - The field numbers of the selected fields
2117435a35e8SMatthew G Knepley 
2118435a35e8SMatthew G Knepley   Output Parameters:
2119b6971eaeSBarry Smith + is    - The global indices for all the degrees of freedom in the new sub `DM`, use `NULL` if not needed
2120b6971eaeSBarry Smith - subdm - The `DM` for the subproblem, use `NULL` if not needed
2121435a35e8SMatthew G Knepley 
212220f4b53cSBarry Smith   Level: intermediate
212320f4b53cSBarry Smith 
2124bb7acecfSBarry Smith   Note:
2125bb7acecfSBarry Smith   You need to call `DMPlexSetMigrationSF()` on the original `DM` if you want the Global-To-Natural map to be automatically constructed
21265d3b26e6SMatthew G. Knepley 
212760225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateFieldIS()`, `DMCreateFieldDecomposition()`, `DMAddField()`, `DMCreateSuperDM()`, `IS`, `DMPlexSetMigrationSF()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
2128435a35e8SMatthew G Knepley @*/
2129d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
2130d71ae5a4SJacob Faibussowitsch {
2131435a35e8SMatthew G Knepley   PetscFunctionBegin;
2132435a35e8SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21334f572ea9SToby Isaac   PetscAssertPointer(fields, 3);
21344f572ea9SToby Isaac   if (is) PetscAssertPointer(is, 4);
21354f572ea9SToby Isaac   if (subdm) PetscAssertPointer(subdm, 5);
2136dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createsubdm, numFields, fields, is, subdm);
21373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2138435a35e8SMatthew G Knepley }
2139435a35e8SMatthew G Knepley 
21402adcc780SMatthew G. Knepley /*@C
2141bb7acecfSBarry Smith   DMCreateSuperDM - Returns an arrays of `IS` and `DM` encapsulating a superproblem defined by multiple `DM`s passed in.
21422adcc780SMatthew G. Knepley 
21432adcc780SMatthew G. Knepley   Not collective
21442adcc780SMatthew G. Knepley 
2145d8d19677SJose E. Roman   Input Parameters:
2146bb7acecfSBarry Smith + dms - The `DM` objects
2147bb7acecfSBarry Smith - n   - The number of `DM`s
21482adcc780SMatthew G. Knepley 
21492adcc780SMatthew G. Knepley   Output Parameters:
2150bb7acecfSBarry Smith + is      - The global indices for each of subproblem within the super `DM`, or NULL
2151bb7acecfSBarry Smith - superdm - The `DM` for the superproblem
21522adcc780SMatthew G. Knepley 
215320f4b53cSBarry Smith   Level: intermediate
215420f4b53cSBarry Smith 
2155bb7acecfSBarry Smith   Note:
2156bb7acecfSBarry Smith   You need to call `DMPlexSetMigrationSF()` on the original `DM` if you want the Global-To-Natural map to be automatically constructed
21575d3b26e6SMatthew G. Knepley 
215873ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateSubDM()`, `DMPlexSetMigrationSF()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`, `DMCreateDomainDecomposition()`
21592adcc780SMatthew G. Knepley @*/
21605d83a8b1SBarry Smith PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt n, IS *is[], DM *superdm)
2161d71ae5a4SJacob Faibussowitsch {
21622adcc780SMatthew G. Knepley   PetscInt i;
21632adcc780SMatthew G. Knepley 
21642adcc780SMatthew G. Knepley   PetscFunctionBegin;
21654f572ea9SToby Isaac   PetscAssertPointer(dms, 1);
2166ad540459SPierre Jolivet   for (i = 0; i < n; ++i) PetscValidHeaderSpecific(dms[i], DM_CLASSID, 1);
21674f572ea9SToby Isaac   if (is) PetscAssertPointer(is, 3);
21684f572ea9SToby Isaac   PetscAssertPointer(superdm, 4);
2169bb7acecfSBarry Smith   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %" PetscInt_FMT, n);
2170bb7acecfSBarry Smith   if (n) {
2171b9d85ea2SLisandro Dalcin     DM dm = dms[0];
217200045ab3SPierre Jolivet     PetscCheck(dm->ops->createsuperdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No method createsuperdm for DM of type %s", ((PetscObject)dm)->type_name);
2173dbbe0bcdSBarry Smith     PetscCall((*dm->ops->createsuperdm)(dms, n, is, superdm));
21742adcc780SMatthew G. Knepley   }
21753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21762adcc780SMatthew G. Knepley }
21772adcc780SMatthew G. Knepley 
217816621825SDmitry Karpeev /*@C
2179a4e35b19SJacob Faibussowitsch   DMCreateDomainDecomposition - Returns lists of `IS` objects defining a decomposition of a
2180a4e35b19SJacob Faibussowitsch   problem into subproblems corresponding to restrictions to pairs of nested subdomains.
218116621825SDmitry Karpeev 
218220f4b53cSBarry Smith   Not Collective
218316621825SDmitry Karpeev 
218416621825SDmitry Karpeev   Input Parameter:
2185bb7acecfSBarry Smith . dm - the `DM` object
218616621825SDmitry Karpeev 
218716621825SDmitry Karpeev   Output Parameters:
218820f4b53cSBarry Smith + n           - The number of subproblems in the domain decomposition (or `NULL` if not requested)
218920f4b53cSBarry Smith . namelist    - The name for each subdomain (or `NULL` if not requested)
219073ff1848SBarry Smith . innerislist - The global indices for each inner subdomain (or `NULL`, if not requested)
219173ff1848SBarry Smith . outerislist - The global indices for each outer subdomain (or `NULL`, if not requested)
219273ff1848SBarry Smith - dmlist      - The `DM`s for each subdomain subproblem (or `NULL`, if not requested; if `NULL` is returned, no `DM`s are defined)
219316621825SDmitry Karpeev 
219416621825SDmitry Karpeev   Level: intermediate
219516621825SDmitry Karpeev 
219673ff1848SBarry Smith   Notes:
2197a4e35b19SJacob Faibussowitsch   Each `IS` contains the global indices of the dofs of the corresponding subdomains with in the
2198a4e35b19SJacob Faibussowitsch   dofs of the original `DM`. The inner subdomains conceptually define a nonoverlapping
2199a4e35b19SJacob Faibussowitsch   covering, while outer subdomains can overlap.
2200a4e35b19SJacob Faibussowitsch 
2201a4e35b19SJacob Faibussowitsch   The optional list of `DM`s define a `DM` for each subproblem.
2202a4e35b19SJacob Faibussowitsch 
220373ff1848SBarry Smith   The user is responsible for freeing all requested arrays. In particular, every entry of `namelist` should be freed with
220473ff1848SBarry Smith   `PetscFree()`, every entry of `innerislist` and `outerislist` should be destroyed with `ISDestroy()`, every entry of `dmlist` should be destroyed with `DMDestroy()`,
2205bb7acecfSBarry Smith   and all of the arrays should be freed with `PetscFree()`.
220616621825SDmitry Karpeev 
2207a4e35b19SJacob Faibussowitsch   Developer Notes:
220820f4b53cSBarry Smith   The `dmlist` is for the inner subdomains or the outer subdomains or all subdomains?
2209bb7acecfSBarry Smith 
221073ff1848SBarry Smith   The names are inconsistent, the hooks use `DMSubDomainHook` which is nothing like `DMCreateDomainDecomposition()` while `DMRefineHook` is used for `DMRefine()`.
221173ff1848SBarry Smith 
221273ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateFieldDecomposition()`, `DMDestroy()`, `DMCreateDomainDecompositionScatters()`, `DMView()`, `DMCreateInterpolation()`,
221373ff1848SBarry Smith           `DMSubDomainHookAdd()`, `DMSubDomainHookRemove()`,`DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`
221416621825SDmitry Karpeev @*/
2215d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *n, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
2216d71ae5a4SJacob Faibussowitsch {
2217be081cd6SPeter Brune   DMSubDomainHookLink link;
2218be081cd6SPeter Brune   PetscInt            i, l;
221916621825SDmitry Karpeev 
222016621825SDmitry Karpeev   PetscFunctionBegin;
222116621825SDmitry Karpeev   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22229371c9d4SSatish Balay   if (n) {
22234f572ea9SToby Isaac     PetscAssertPointer(n, 2);
22249371c9d4SSatish Balay     *n = 0;
22259371c9d4SSatish Balay   }
22269371c9d4SSatish Balay   if (namelist) {
22274f572ea9SToby Isaac     PetscAssertPointer(namelist, 3);
22289371c9d4SSatish Balay     *namelist = NULL;
22299371c9d4SSatish Balay   }
22309371c9d4SSatish Balay   if (innerislist) {
22314f572ea9SToby Isaac     PetscAssertPointer(innerislist, 4);
22329371c9d4SSatish Balay     *innerislist = NULL;
22339371c9d4SSatish Balay   }
22349371c9d4SSatish Balay   if (outerislist) {
22354f572ea9SToby Isaac     PetscAssertPointer(outerislist, 5);
22369371c9d4SSatish Balay     *outerislist = NULL;
22379371c9d4SSatish Balay   }
22389371c9d4SSatish Balay   if (dmlist) {
22394f572ea9SToby Isaac     PetscAssertPointer(dmlist, 6);
22409371c9d4SSatish Balay     *dmlist = NULL;
22419371c9d4SSatish Balay   }
2242f3f0edfdSDmitry Karpeev   /*
2243f3f0edfdSDmitry Karpeev    Is it a good idea to apply the following check across all impls?
2244f3f0edfdSDmitry Karpeev    Perhaps some impls can have a well-defined decomposition before DMSetUp?
2245f3f0edfdSDmitry Karpeev    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
2246f3f0edfdSDmitry Karpeev    */
22477a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
224816621825SDmitry Karpeev   if (dm->ops->createdomaindecomposition) {
2249dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createdomaindecomposition, &l, namelist, innerislist, outerislist, dmlist);
225014a18fd3SPeter Brune     /* copy subdomain hooks and context over to the subdomain DMs */
2251f891f5b9SPatrick Sanan     if (dmlist && *dmlist) {
2252be081cd6SPeter Brune       for (i = 0; i < l; i++) {
2253be081cd6SPeter Brune         for (link = dm->subdomainhook; link; link = link->next) {
22549566063dSJacob Faibussowitsch           if (link->ddhook) PetscCall((*link->ddhook)(dm, (*dmlist)[i], link->ctx));
2255be081cd6SPeter Brune         }
2256648262bbSPatrick Sanan         if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
2257e7c4fc90SDmitry Karpeev       }
225814a18fd3SPeter Brune     }
2259bb7acecfSBarry Smith     if (n) *n = l;
226014a18fd3SPeter Brune   }
22613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2262e30e807fSPeter Brune }
2263e30e807fSPeter Brune 
2264e30e807fSPeter Brune /*@C
226573ff1848SBarry Smith   DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector for subdomains created with
226673ff1848SBarry Smith   `DMCreateDomainDecomposition()`
2267e30e807fSPeter Brune 
226820f4b53cSBarry Smith   Not Collective
2269e30e807fSPeter Brune 
2270e30e807fSPeter Brune   Input Parameters:
2271bb7acecfSBarry Smith + dm     - the `DM` object
227273ff1848SBarry Smith . n      - the number of subdomains
2273e30e807fSPeter Brune - subdms - the local subdomains
2274e30e807fSPeter Brune 
2275e30e807fSPeter Brune   Output Parameters:
22766b867d5aSJose E. Roman + iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
2277e30e807fSPeter Brune . oscat - scatter from global vector to overlapping global vector entries on subdomain
2278e30e807fSPeter Brune - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
2279e30e807fSPeter Brune 
228020f4b53cSBarry Smith   Level: developer
228120f4b53cSBarry Smith 
2282bb7acecfSBarry Smith   Note:
2283bb7acecfSBarry Smith   This is an alternative to the iis and ois arguments in `DMCreateDomainDecomposition()` that allow for the solution
2284e30e807fSPeter Brune   of general nonlinear problems with overlapping subdomain methods.  While merely having index sets that enable subsets
2285e30e807fSPeter Brune   of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
2286e30e807fSPeter Brune   solution and residual data.
2287e30e807fSPeter Brune 
228873ff1848SBarry Smith   Developer Note:
2289a4e35b19SJacob Faibussowitsch   Can the subdms input be anything or are they exactly the `DM` obtained from
2290a4e35b19SJacob Faibussowitsch   `DMCreateDomainDecomposition()`?
2291bb7acecfSBarry Smith 
22921cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateDomainDecomposition()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
2293e30e807fSPeter Brune @*/
22945d83a8b1SBarry Smith PetscErrorCode DMCreateDomainDecompositionScatters(DM dm, PetscInt n, DM *subdms, VecScatter *iscat[], VecScatter *oscat[], VecScatter *gscat[])
2295d71ae5a4SJacob Faibussowitsch {
2296e30e807fSPeter Brune   PetscFunctionBegin;
2297e30e807fSPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22984f572ea9SToby Isaac   PetscAssertPointer(subdms, 3);
2299dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createddscatters, n, subdms, iscat, oscat, gscat);
23003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2301e7c4fc90SDmitry Karpeev }
2302e7c4fc90SDmitry Karpeev 
230347c6ae99SBarry Smith /*@
2304bb7acecfSBarry Smith   DMRefine - Refines a `DM` object using a standard nonadaptive refinement of the underlying mesh
230547c6ae99SBarry Smith 
230620f4b53cSBarry Smith   Collective
230747c6ae99SBarry Smith 
2308d8d19677SJose E. Roman   Input Parameters:
2309bb7acecfSBarry Smith + dm   - the `DM` object
2310bb7acecfSBarry Smith - comm - the communicator to contain the new `DM` object (or `MPI_COMM_NULL`)
231147c6ae99SBarry Smith 
231247c6ae99SBarry Smith   Output Parameter:
231320f4b53cSBarry Smith . dmf - the refined `DM`, or `NULL`
2314ae0a1c52SMatthew G Knepley 
231520f4b53cSBarry Smith   Options Database Key:
2316412e9a14SMatthew G. Knepley . -dm_plex_cell_refiner <strategy> - chooses the refinement strategy, e.g. regular, tohex
2317412e9a14SMatthew G. Knepley 
231847c6ae99SBarry Smith   Level: developer
231947c6ae99SBarry Smith 
232020f4b53cSBarry Smith   Note:
232120f4b53cSBarry Smith   If no refinement was done, the return value is `NULL`
232220f4b53cSBarry Smith 
232373ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateDomainDecomposition()`,
232473ff1848SBarry Smith           `DMRefineHookAdd()`, `DMRefineHookRemove()`
232547c6ae99SBarry Smith @*/
2326d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefine(DM dm, MPI_Comm comm, DM *dmf)
2327d71ae5a4SJacob Faibussowitsch {
2328c833c3b5SJed Brown   DMRefineHookLink link;
232947c6ae99SBarry Smith 
233047c6ae99SBarry Smith   PetscFunctionBegin;
2331732e2eb9SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23329566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Refine, dm, 0, 0, 0));
2333dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, refine, comm, dmf);
23344057135bSMatthew G Knepley   if (*dmf) {
233543842a1eSJed Brown     (*dmf)->ops->creatematrix = dm->ops->creatematrix;
23368865f1eaSKarl Rupp 
23379566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmf));
23388865f1eaSKarl Rupp 
2339644e2e5bSBarry Smith     (*dmf)->ctx       = dm->ctx;
23400598a293SJed Brown     (*dmf)->leveldown = dm->leveldown;
2341656b349aSBarry Smith     (*dmf)->levelup   = dm->levelup + 1;
23428865f1eaSKarl Rupp 
23439566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmf, dm->mattype));
2344c833c3b5SJed Brown     for (link = dm->refinehook; link; link = link->next) {
23451baa6e33SBarry Smith       if (link->refinehook) PetscCall((*link->refinehook)(dm, *dmf, link->ctx));
2346c833c3b5SJed Brown     }
2347c833c3b5SJed Brown   }
23489566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Refine, dm, 0, 0, 0));
23493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2350c833c3b5SJed Brown }
2351c833c3b5SJed Brown 
2352bb9467b5SJed Brown /*@C
2353c833c3b5SJed Brown   DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
2354c833c3b5SJed Brown 
235520f4b53cSBarry Smith   Logically Collective; No Fortran Support
2356c833c3b5SJed Brown 
23574165533cSJose E. Roman   Input Parameters:
2358bb7acecfSBarry Smith + coarse     - `DM` on which to run a hook when interpolating to a finer level
2359bb7acecfSBarry Smith . refinehook - function to run when setting up the finer level
2360f826b5fcSPierre Jolivet . interphook - function to run to update data on finer levels (once per `SNESSolve()`)
236120f4b53cSBarry Smith - ctx        - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2362c833c3b5SJed Brown 
236320f4b53cSBarry Smith   Calling sequence of `refinehook`:
2364bb7acecfSBarry Smith + coarse - coarse level `DM`
2365bb7acecfSBarry Smith . fine   - fine level `DM` to interpolate problem to
2366c833c3b5SJed Brown - ctx    - optional user-defined function context
2367c833c3b5SJed Brown 
236820f4b53cSBarry Smith   Calling sequence of `interphook`:
2369bb7acecfSBarry Smith + coarse - coarse level `DM`
2370c833c3b5SJed Brown . interp - matrix interpolating a coarse-level solution to the finer grid
2371bb7acecfSBarry Smith . fine   - fine level `DM` to update
2372c833c3b5SJed Brown - ctx    - optional user-defined function context
2373c833c3b5SJed Brown 
2374c833c3b5SJed Brown   Level: advanced
2375c833c3b5SJed Brown 
2376c833c3b5SJed Brown   Notes:
2377bb7acecfSBarry Smith   This function is only needed if auxiliary data that is attached to the `DM`s via, for example, `PetscObjectCompose()`, needs to be
2378bb7acecfSBarry Smith   passed to fine grids while grid sequencing.
2379bb7acecfSBarry Smith 
2380bb7acecfSBarry Smith   The actual interpolation is done when `DMInterpolate()` is called.
2381c833c3b5SJed Brown 
2382c833c3b5SJed Brown   If this function is called multiple times, the hooks will be run in the order they are added.
2383c833c3b5SJed Brown 
23841cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `DMInterpolate()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2385c833c3b5SJed Brown @*/
2386a4e35b19SJacob Faibussowitsch PetscErrorCode DMRefineHookAdd(DM coarse, PetscErrorCode (*refinehook)(DM coarse, DM fine, void *ctx), PetscErrorCode (*interphook)(DM coarse, Mat interp, DM fine, void *ctx), void *ctx)
2387d71ae5a4SJacob Faibussowitsch {
2388c833c3b5SJed Brown   DMRefineHookLink link, *p;
2389c833c3b5SJed Brown 
2390c833c3b5SJed Brown   PetscFunctionBegin;
2391c833c3b5SJed Brown   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
23923d8e3701SJed Brown   for (p = &coarse->refinehook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
23933ba16761SJacob Faibussowitsch     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
23943d8e3701SJed Brown   }
23959566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2396c833c3b5SJed Brown   link->refinehook = refinehook;
2397c833c3b5SJed Brown   link->interphook = interphook;
2398c833c3b5SJed Brown   link->ctx        = ctx;
23990298fd71SBarry Smith   link->next       = NULL;
2400c833c3b5SJed Brown   *p               = link;
24013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2402c833c3b5SJed Brown }
2403c833c3b5SJed Brown 
24043d8e3701SJed Brown /*@C
2405bb7acecfSBarry Smith   DMRefineHookRemove - remove a callback from the list of hooks, that have been set with `DMRefineHookAdd()`, to be run when interpolating
2406bb7acecfSBarry Smith   a nonlinear problem to a finer grid
24073d8e3701SJed Brown 
240820f4b53cSBarry Smith   Logically Collective; No Fortran Support
24093d8e3701SJed Brown 
24104165533cSJose E. Roman   Input Parameters:
2411bb7acecfSBarry Smith + coarse     - the `DM` on which to run a hook when restricting to a coarser level
2412bb7acecfSBarry Smith . refinehook - function to run when setting up a finer level
2413bb7acecfSBarry Smith . interphook - function to run to update data on finer levels
241420f4b53cSBarry Smith - ctx        - [optional] user-defined context for provide data for the hooks (may be `NULL`)
24153d8e3701SJed Brown 
24163d8e3701SJed Brown   Level: advanced
24173d8e3701SJed Brown 
2418bb7acecfSBarry Smith   Note:
24193d8e3701SJed Brown   This function does nothing if the hook is not in the list.
24203d8e3701SJed Brown 
24211cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefineHookAdd()`, `DMCoarsenHookRemove()`, `DMInterpolate()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
24223d8e3701SJed Brown @*/
2423d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHookRemove(DM coarse, PetscErrorCode (*refinehook)(DM, DM, void *), PetscErrorCode (*interphook)(DM, Mat, DM, void *), void *ctx)
2424d71ae5a4SJacob Faibussowitsch {
24253d8e3701SJed Brown   DMRefineHookLink link, *p;
24263d8e3701SJed Brown 
24273d8e3701SJed Brown   PetscFunctionBegin;
24283d8e3701SJed Brown   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
24293d8e3701SJed Brown   for (p = &coarse->refinehook; *p; p = &(*p)->next) { /* Search the list of current hooks */
24303d8e3701SJed Brown     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
24313d8e3701SJed Brown       link = *p;
24323d8e3701SJed Brown       *p   = link->next;
24339566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
24343d8e3701SJed Brown       break;
24353d8e3701SJed Brown     }
24363d8e3701SJed Brown   }
24373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24383d8e3701SJed Brown }
24393d8e3701SJed Brown 
2440c833c3b5SJed Brown /*@
2441bb7acecfSBarry Smith   DMInterpolate - interpolates user-defined problem data attached to a `DM` to a finer `DM` by running hooks registered by `DMRefineHookAdd()`
2442c833c3b5SJed Brown 
2443c833c3b5SJed Brown   Collective if any hooks are
2444c833c3b5SJed Brown 
24454165533cSJose E. Roman   Input Parameters:
2446bb7acecfSBarry Smith + coarse - coarser `DM` to use as a base
2447bb7acecfSBarry Smith . interp - interpolation matrix, apply using `MatInterpolate()`
2448bb7acecfSBarry Smith - fine   - finer `DM` to update
2449c833c3b5SJed Brown 
2450c833c3b5SJed Brown   Level: developer
2451c833c3b5SJed Brown 
245273ff1848SBarry Smith   Developer Note:
2453bb7acecfSBarry Smith   This routine is called `DMInterpolate()` while the hook is called `DMRefineHookAdd()`. It would be better to have an
2454bb7acecfSBarry Smith   an API with consistent terminology.
2455bb7acecfSBarry Smith 
24561cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefineHookAdd()`, `MatInterpolate()`
2457c833c3b5SJed Brown @*/
2458d71ae5a4SJacob Faibussowitsch PetscErrorCode DMInterpolate(DM coarse, Mat interp, DM fine)
2459d71ae5a4SJacob Faibussowitsch {
2460c833c3b5SJed Brown   DMRefineHookLink link;
2461c833c3b5SJed Brown 
2462c833c3b5SJed Brown   PetscFunctionBegin;
2463c833c3b5SJed Brown   for (link = fine->refinehook; link; link = link->next) {
24641baa6e33SBarry Smith     if (link->interphook) PetscCall((*link->interphook)(coarse, interp, fine, link->ctx));
24654057135bSMatthew G Knepley   }
24663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
246747c6ae99SBarry Smith }
246847c6ae99SBarry Smith 
2469eb3f98d2SBarry Smith /*@
24701f3379b2SToby Isaac   DMInterpolateSolution - Interpolates a solution from a coarse mesh to a fine mesh.
24711f3379b2SToby Isaac 
247220f4b53cSBarry Smith   Collective
24731f3379b2SToby Isaac 
24744165533cSJose E. Roman   Input Parameters:
2475bb7acecfSBarry Smith + coarse    - coarse `DM`
2476bb7acecfSBarry Smith . fine      - fine `DM`
2477bb7acecfSBarry Smith . interp    - (optional) the matrix computed by `DMCreateInterpolation()`.  Implementations may not need this, but if it
2478bb7acecfSBarry Smith             is available it can avoid some recomputation.  If it is provided, `MatInterpolate()` will be used if
2479bb7acecfSBarry Smith             the coarse `DM` does not have a specialized implementation.
24801f3379b2SToby Isaac - coarseSol - solution on the coarse mesh
24811f3379b2SToby Isaac 
24824165533cSJose E. Roman   Output Parameter:
24831f3379b2SToby Isaac . fineSol - the interpolation of coarseSol to the fine mesh
24841f3379b2SToby Isaac 
24851f3379b2SToby Isaac   Level: developer
24861f3379b2SToby Isaac 
2487bb7acecfSBarry Smith   Note:
2488bb7acecfSBarry Smith   This function exists because the interpolation of a solution vector between meshes is not always a linear
24891f3379b2SToby Isaac   map.  For example, if a boundary value problem has an inhomogeneous Dirichlet boundary condition that is compressed
24901f3379b2SToby Isaac   out of the solution vector.  Or if interpolation is inherently a nonlinear operation, such as a method using
24911f3379b2SToby Isaac   slope-limiting reconstruction.
24921f3379b2SToby Isaac 
249373ff1848SBarry Smith   Developer Note:
2494bb7acecfSBarry Smith   This doesn't just interpolate "solutions" so its API name is questionable.
2495bb7acecfSBarry Smith 
24961cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMInterpolate()`, `DMCreateInterpolation()`
24971f3379b2SToby Isaac @*/
2498d71ae5a4SJacob Faibussowitsch PetscErrorCode DMInterpolateSolution(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
2499d71ae5a4SJacob Faibussowitsch {
25001f3379b2SToby Isaac   PetscErrorCode (*interpsol)(DM, DM, Mat, Vec, Vec) = NULL;
25011f3379b2SToby Isaac 
25021f3379b2SToby Isaac   PetscFunctionBegin;
25031f3379b2SToby Isaac   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
25041f3379b2SToby Isaac   if (interp) PetscValidHeaderSpecific(interp, MAT_CLASSID, 3);
25051f3379b2SToby Isaac   PetscValidHeaderSpecific(coarseSol, VEC_CLASSID, 4);
25061f3379b2SToby Isaac   PetscValidHeaderSpecific(fineSol, VEC_CLASSID, 5);
25071f3379b2SToby Isaac 
25089566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)coarse, "DMInterpolateSolution_C", &interpsol));
25091f3379b2SToby Isaac   if (interpsol) {
25109566063dSJacob Faibussowitsch     PetscCall((*interpsol)(coarse, fine, interp, coarseSol, fineSol));
25111f3379b2SToby Isaac   } else if (interp) {
25129566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(interp, coarseSol, fineSol));
251398921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)coarse), PETSC_ERR_SUP, "DM %s does not implement DMInterpolateSolution()", ((PetscObject)coarse)->type_name);
25143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25151f3379b2SToby Isaac }
25161f3379b2SToby Isaac 
25171f3379b2SToby Isaac /*@
2518bb7acecfSBarry Smith   DMGetRefineLevel - Gets the number of refinements that have generated this `DM` from some initial `DM`.
2519eb3f98d2SBarry Smith 
2520eb3f98d2SBarry Smith   Not Collective
2521eb3f98d2SBarry Smith 
2522eb3f98d2SBarry Smith   Input Parameter:
2523bb7acecfSBarry Smith . dm - the `DM` object
2524eb3f98d2SBarry Smith 
2525eb3f98d2SBarry Smith   Output Parameter:
2526eb3f98d2SBarry Smith . level - number of refinements
2527eb3f98d2SBarry Smith 
2528eb3f98d2SBarry Smith   Level: developer
2529eb3f98d2SBarry Smith 
2530bb7acecfSBarry Smith   Note:
2531bb7acecfSBarry Smith   This can be used, by example, to set the number of coarser levels associated with this `DM` for a multigrid solver.
2532bb7acecfSBarry Smith 
25331cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
2534eb3f98d2SBarry Smith @*/
2535d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRefineLevel(DM dm, PetscInt *level)
2536d71ae5a4SJacob Faibussowitsch {
2537eb3f98d2SBarry Smith   PetscFunctionBegin;
2538eb3f98d2SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2539eb3f98d2SBarry Smith   *level = dm->levelup;
25403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2541eb3f98d2SBarry Smith }
2542eb3f98d2SBarry Smith 
2543fef3a512SBarry Smith /*@
2544bb7acecfSBarry Smith   DMSetRefineLevel - Sets the number of refinements that have generated this `DM`.
2545fef3a512SBarry Smith 
2546fef3a512SBarry Smith   Not Collective
2547fef3a512SBarry Smith 
2548d8d19677SJose E. Roman   Input Parameters:
2549bb7acecfSBarry Smith + dm    - the `DM` object
2550fef3a512SBarry Smith - level - number of refinements
2551fef3a512SBarry Smith 
2552fef3a512SBarry Smith   Level: advanced
2553fef3a512SBarry Smith 
255495452b02SPatrick Sanan   Notes:
2555bb7acecfSBarry Smith   This value is used by `PCMG` to determine how many multigrid levels to use
2556fef3a512SBarry Smith 
2557bb7acecfSBarry Smith   The values are usually set automatically by the process that is causing the refinements of an initial `DM` by calling this routine.
2558bb7acecfSBarry Smith 
25591cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRefineLevel()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
2560fef3a512SBarry Smith @*/
2561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRefineLevel(DM dm, PetscInt level)
2562d71ae5a4SJacob Faibussowitsch {
2563fef3a512SBarry Smith   PetscFunctionBegin;
2564fef3a512SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2565fef3a512SBarry Smith   dm->levelup = level;
25663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2567fef3a512SBarry Smith }
2568fef3a512SBarry Smith 
2569d410b0cfSMatthew G. Knepley /*@
2570bb7acecfSBarry Smith   DMExtrude - Extrude a `DM` object from a surface
2571d410b0cfSMatthew G. Knepley 
257220f4b53cSBarry Smith   Collective
2573d410b0cfSMatthew G. Knepley 
2574f1a722f8SMatthew G. Knepley   Input Parameters:
2575bb7acecfSBarry Smith + dm     - the `DM` object
2576d410b0cfSMatthew G. Knepley - layers - the number of extruded cell layers
2577d410b0cfSMatthew G. Knepley 
2578d410b0cfSMatthew G. Knepley   Output Parameter:
257920f4b53cSBarry Smith . dme - the extruded `DM`, or `NULL`
2580d410b0cfSMatthew G. Knepley 
2581d410b0cfSMatthew G. Knepley   Level: developer
2582d410b0cfSMatthew G. Knepley 
258320f4b53cSBarry Smith   Note:
258420f4b53cSBarry Smith   If no extrusion was done, the return value is `NULL`
258520f4b53cSBarry Smith 
25861cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`
2587d410b0cfSMatthew G. Knepley @*/
2588d71ae5a4SJacob Faibussowitsch PetscErrorCode DMExtrude(DM dm, PetscInt layers, DM *dme)
2589d71ae5a4SJacob Faibussowitsch {
2590d410b0cfSMatthew G. Knepley   PetscFunctionBegin;
2591d410b0cfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2592dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, extrude, layers, dme);
2593d410b0cfSMatthew G. Knepley   if (*dme) {
2594d410b0cfSMatthew G. Knepley     (*dme)->ops->creatematrix = dm->ops->creatematrix;
25959566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dme));
2596d410b0cfSMatthew G. Knepley     (*dme)->ctx = dm->ctx;
25979566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dme, dm->mattype));
2598d410b0cfSMatthew G. Knepley   }
25993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2600d410b0cfSMatthew G. Knepley }
2601d410b0cfSMatthew G. Knepley 
2602d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasisTransformDM_Internal(DM dm, DM *tdm)
2603d71ae5a4SJacob Faibussowitsch {
2604ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2605ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26064f572ea9SToby Isaac   PetscAssertPointer(tdm, 2);
2607ca3d3a14SMatthew G. Knepley   *tdm = dm->transformDM;
26083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2609ca3d3a14SMatthew G. Knepley }
2610ca3d3a14SMatthew G. Knepley 
2611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasisTransformVec_Internal(DM dm, Vec *tv)
2612d71ae5a4SJacob Faibussowitsch {
2613ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2614ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26154f572ea9SToby Isaac   PetscAssertPointer(tv, 2);
2616ca3d3a14SMatthew G. Knepley   *tv = dm->transform;
26173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2618ca3d3a14SMatthew G. Knepley }
2619ca3d3a14SMatthew G. Knepley 
2620ca3d3a14SMatthew G. Knepley /*@
2621bb7acecfSBarry Smith   DMHasBasisTransform - Whether the `DM` employs a basis transformation from functions in global vectors to functions in local vectors
2622ca3d3a14SMatthew G. Knepley 
2623ca3d3a14SMatthew G. Knepley   Input Parameter:
262420f4b53cSBarry Smith . dm - The `DM`
2625ca3d3a14SMatthew G. Knepley 
2626ca3d3a14SMatthew G. Knepley   Output Parameter:
262720f4b53cSBarry Smith . flg - `PETSC_TRUE` if a basis transformation should be done
2628ca3d3a14SMatthew G. Knepley 
2629ca3d3a14SMatthew G. Knepley   Level: developer
2630ca3d3a14SMatthew G. Knepley 
26311cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPlexGlobalToLocalBasis()`, `DMPlexLocalToGlobalBasis()`, `DMPlexCreateBasisRotation()`
2632ca3d3a14SMatthew G. Knepley @*/
2633d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasBasisTransform(DM dm, PetscBool *flg)
2634d71ae5a4SJacob Faibussowitsch {
2635ca3d3a14SMatthew G. Knepley   Vec tv;
2636ca3d3a14SMatthew G. Knepley 
2637ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2638ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26394f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
26409566063dSJacob Faibussowitsch   PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
2641ca3d3a14SMatthew G. Knepley   *flg = tv ? PETSC_TRUE : PETSC_FALSE;
26423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2643ca3d3a14SMatthew G. Knepley }
2644ca3d3a14SMatthew G. Knepley 
2645d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConstructBasisTransform_Internal(DM dm)
2646d71ae5a4SJacob Faibussowitsch {
2647ca3d3a14SMatthew G. Knepley   PetscSection s, ts;
2648ca3d3a14SMatthew G. Knepley   PetscScalar *ta;
2649ca3d3a14SMatthew G. Knepley   PetscInt     cdim, pStart, pEnd, p, Nf, f, Nc, dof;
2650ca3d3a14SMatthew G. Knepley 
2651ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
26529566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
26539566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
26549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
26559566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
26569566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dm->transformDM));
26579566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm->transformDM, &ts));
26589566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(ts, Nf));
26599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(ts, pStart, pEnd));
2660ca3d3a14SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
26619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
2662ca3d3a14SMatthew G. Knepley     /* We could start to label fields by their transformation properties */
2663ca3d3a14SMatthew G. Knepley     if (Nc != cdim) continue;
2664ca3d3a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
26659566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, f, &dof));
2666ca3d3a14SMatthew G. Knepley       if (!dof) continue;
26679566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(ts, p, f, PetscSqr(cdim)));
26689566063dSJacob Faibussowitsch       PetscCall(PetscSectionAddDof(ts, p, PetscSqr(cdim)));
2669ca3d3a14SMatthew G. Knepley     }
2670ca3d3a14SMatthew G. Knepley   }
26719566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(ts));
26729566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm->transformDM, &dm->transform));
26739566063dSJacob Faibussowitsch   PetscCall(VecGetArray(dm->transform, &ta));
2674ca3d3a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
2675ca3d3a14SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
26769566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(ts, p, f, &dof));
2677ca3d3a14SMatthew G. Knepley       if (dof) {
2678ca3d3a14SMatthew G. Knepley         PetscReal          x[3] = {0.0, 0.0, 0.0};
2679ca3d3a14SMatthew G. Knepley         PetscScalar       *tva;
2680ca3d3a14SMatthew G. Knepley         const PetscScalar *A;
2681ca3d3a14SMatthew G. Knepley 
2682ca3d3a14SMatthew G. Knepley         /* TODO Get quadrature point for this dual basis vector for coordinate */
26839566063dSJacob Faibussowitsch         PetscCall((*dm->transformGetMatrix)(dm, x, PETSC_TRUE, &A, dm->transformCtx));
26849566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalFieldRef(dm->transformDM, p, f, ta, (void *)&tva));
26859566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(tva, A, PetscSqr(cdim)));
2686ca3d3a14SMatthew G. Knepley       }
2687ca3d3a14SMatthew G. Knepley     }
2688ca3d3a14SMatthew G. Knepley   }
26899566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(dm->transform, &ta));
26903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2691ca3d3a14SMatthew G. Knepley }
2692ca3d3a14SMatthew G. Knepley 
2693d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyTransform(DM dm, DM newdm)
2694d71ae5a4SJacob Faibussowitsch {
2695ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2696ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2697ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(newdm, DM_CLASSID, 2);
2698ca3d3a14SMatthew G. Knepley   newdm->transformCtx       = dm->transformCtx;
2699ca3d3a14SMatthew G. Knepley   newdm->transformSetUp     = dm->transformSetUp;
2700ca3d3a14SMatthew G. Knepley   newdm->transformDestroy   = NULL;
2701ca3d3a14SMatthew G. Knepley   newdm->transformGetMatrix = dm->transformGetMatrix;
27029566063dSJacob Faibussowitsch   if (newdm->transformSetUp) PetscCall(DMConstructBasisTransform_Internal(newdm));
27033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2704ca3d3a14SMatthew G. Knepley }
2705ca3d3a14SMatthew G. Knepley 
2706bb9467b5SJed Brown /*@C
2707bb7acecfSBarry Smith   DMGlobalToLocalHookAdd - adds a callback to be run when `DMGlobalToLocal()` is called
2708baf369e7SPeter Brune 
270920f4b53cSBarry Smith   Logically Collective
2710baf369e7SPeter Brune 
27114165533cSJose E. Roman   Input Parameters:
2712bb7acecfSBarry Smith + dm        - the `DM`
2713bb7acecfSBarry Smith . beginhook - function to run at the beginning of `DMGlobalToLocalBegin()`
2714bb7acecfSBarry Smith . endhook   - function to run after `DMGlobalToLocalEnd()` has completed
271520f4b53cSBarry Smith - ctx       - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2716baf369e7SPeter Brune 
271720f4b53cSBarry Smith   Calling sequence of `beginhook`:
2718a4e35b19SJacob Faibussowitsch + dm   - global `DM`
2719baf369e7SPeter Brune . g    - global vector
2720baf369e7SPeter Brune . mode - mode
2721baf369e7SPeter Brune . l    - local vector
2722baf369e7SPeter Brune - ctx  - optional user-defined function context
2723baf369e7SPeter Brune 
272420f4b53cSBarry Smith   Calling sequence of `endhook`:
2725a4e35b19SJacob Faibussowitsch + dm   - global `DM`
2726a4e35b19SJacob Faibussowitsch . g    - global vector
2727a4e35b19SJacob Faibussowitsch . mode - mode
2728a4e35b19SJacob Faibussowitsch . l    - local vector
2729baf369e7SPeter Brune - ctx  - optional user-defined function context
2730baf369e7SPeter Brune 
2731baf369e7SPeter Brune   Level: advanced
2732baf369e7SPeter Brune 
2733bb7acecfSBarry Smith   Note:
2734bb7acecfSBarry 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.
2735bb7acecfSBarry Smith 
27361cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGlobalToLocal()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2737baf369e7SPeter Brune @*/
2738a4e35b19SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalHookAdd(DM dm, PetscErrorCode (*beginhook)(DM dm, Vec g, InsertMode mode, Vec l, void *ctx), PetscErrorCode (*endhook)(DM dm, Vec g, InsertMode mode, Vec l, void *ctx), void *ctx)
2739d71ae5a4SJacob Faibussowitsch {
2740baf369e7SPeter Brune   DMGlobalToLocalHookLink link, *p;
2741baf369e7SPeter Brune 
2742baf369e7SPeter Brune   PetscFunctionBegin;
2743baf369e7SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2744baf369e7SPeter Brune   for (p = &dm->gtolhook; *p; p = &(*p)->next) { } /* Scan to the end of the current list of hooks */
27459566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2746baf369e7SPeter Brune   link->beginhook = beginhook;
2747baf369e7SPeter Brune   link->endhook   = endhook;
2748baf369e7SPeter Brune   link->ctx       = ctx;
27490298fd71SBarry Smith   link->next      = NULL;
2750baf369e7SPeter Brune   *p              = link;
27513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2752baf369e7SPeter Brune }
2753baf369e7SPeter Brune 
2754d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
2755d71ae5a4SJacob Faibussowitsch {
27564c274da1SToby Isaac   Mat          cMat;
275779769bd5SJed Brown   Vec          cVec, cBias;
27584c274da1SToby Isaac   PetscSection section, cSec;
27594c274da1SToby Isaac   PetscInt     pStart, pEnd, p, dof;
27604c274da1SToby Isaac 
27614c274da1SToby Isaac   PetscFunctionBegin;
2762a4e35b19SJacob Faibussowitsch   (void)g;
2763a4e35b19SJacob Faibussowitsch   (void)ctx;
27644c274da1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27659566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, &cBias));
27664c274da1SToby Isaac   if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
27675db9a05bSToby Isaac     PetscInt nRows;
27685db9a05bSToby Isaac 
27699566063dSJacob Faibussowitsch     PetscCall(MatGetSize(cMat, &nRows, NULL));
27703ba16761SJacob Faibussowitsch     if (nRows <= 0) PetscFunctionReturn(PETSC_SUCCESS);
27719566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
27729566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(cMat, NULL, &cVec));
27739566063dSJacob Faibussowitsch     PetscCall(MatMult(cMat, l, cVec));
27749566063dSJacob Faibussowitsch     if (cBias) PetscCall(VecAXPY(cVec, 1., cBias));
27759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
27764c274da1SToby Isaac     for (p = pStart; p < pEnd; p++) {
27779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
27784c274da1SToby Isaac       if (dof) {
27794c274da1SToby Isaac         PetscScalar *vals;
27809566063dSJacob Faibussowitsch         PetscCall(VecGetValuesSection(cVec, cSec, p, &vals));
27819566063dSJacob Faibussowitsch         PetscCall(VecSetValuesSection(l, section, p, vals, INSERT_ALL_VALUES));
27824c274da1SToby Isaac       }
27834c274da1SToby Isaac     }
27849566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cVec));
27854c274da1SToby Isaac   }
27863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27874c274da1SToby Isaac }
27884c274da1SToby Isaac 
278947c6ae99SBarry Smith /*@
279001729b5cSPatrick Sanan   DMGlobalToLocal - update local vectors from global vector
279101729b5cSPatrick Sanan 
279220f4b53cSBarry Smith   Neighbor-wise Collective
279301729b5cSPatrick Sanan 
279401729b5cSPatrick Sanan   Input Parameters:
2795bb7acecfSBarry Smith + dm   - the `DM` object
279601729b5cSPatrick Sanan . g    - the global vector
2797bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
279801729b5cSPatrick Sanan - l    - the local vector
279901729b5cSPatrick Sanan 
280020f4b53cSBarry Smith   Level: beginner
280120f4b53cSBarry Smith 
280201729b5cSPatrick Sanan   Notes:
2803bb7acecfSBarry Smith   The communication involved in this update can be overlapped with computation by instead using
2804bb7acecfSBarry Smith   `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()`.
2805bb7acecfSBarry Smith 
2806bb7acecfSBarry Smith   `DMGlobalToLocalHookAdd()` may be used to provide additional operations that are performed during the update process.
280701729b5cSPatrick Sanan 
28081cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGlobalToLocalHookAdd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`,
280960225df5SJacob Faibussowitsch           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`,
2810bb7acecfSBarry Smith           `DMGlobalToLocalBegin()` `DMGlobalToLocalEnd()`
281101729b5cSPatrick Sanan @*/
2812d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocal(DM dm, Vec g, InsertMode mode, Vec l)
2813d71ae5a4SJacob Faibussowitsch {
281401729b5cSPatrick Sanan   PetscFunctionBegin;
28159566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dm, g, mode, l));
28169566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dm, g, mode, l));
28173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
281801729b5cSPatrick Sanan }
281901729b5cSPatrick Sanan 
282001729b5cSPatrick Sanan /*@
282147c6ae99SBarry Smith   DMGlobalToLocalBegin - Begins updating local vectors from global vector
282247c6ae99SBarry Smith 
282320f4b53cSBarry Smith   Neighbor-wise Collective
282447c6ae99SBarry Smith 
282547c6ae99SBarry Smith   Input Parameters:
2826bb7acecfSBarry Smith + dm   - the `DM` object
282747c6ae99SBarry Smith . g    - the global vector
2828bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
282947c6ae99SBarry Smith - l    - the local vector
283047c6ae99SBarry Smith 
283101729b5cSPatrick Sanan   Level: intermediate
283247c6ae99SBarry Smith 
2833bb7acecfSBarry Smith   Notes:
2834bb7acecfSBarry Smith   The operation is completed with `DMGlobalToLocalEnd()`
2835bb7acecfSBarry Smith 
2836bb7acecfSBarry Smith   One can perform local computations between the `DMGlobalToLocalBegin()` and  `DMGlobalToLocalEnd()` to overlap communication and computation
2837bb7acecfSBarry Smith 
2838bb7acecfSBarry Smith   `DMGlobalToLocal()` is a short form of  `DMGlobalToLocalBegin()` and  `DMGlobalToLocalEnd()`
2839bb7acecfSBarry Smith 
2840bb7acecfSBarry Smith   `DMGlobalToLocalHookAdd()` may be used to provide additional operations that are performed during the update process.
2841bb7acecfSBarry Smith 
284260225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`
284347c6ae99SBarry Smith @*/
2844d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalBegin(DM dm, Vec g, InsertMode mode, Vec l)
2845d71ae5a4SJacob Faibussowitsch {
28467128ae9fSMatthew G Knepley   PetscSF                 sf;
2847baf369e7SPeter Brune   DMGlobalToLocalHookLink link;
284847c6ae99SBarry Smith 
284947c6ae99SBarry Smith   PetscFunctionBegin;
2850171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2851baf369e7SPeter Brune   for (link = dm->gtolhook; link; link = link->next) {
28521baa6e33SBarry Smith     if (link->beginhook) PetscCall((*link->beginhook)(dm, g, mode, l, link->ctx));
2853baf369e7SPeter Brune   }
28549566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
28557128ae9fSMatthew G Knepley   if (sf) {
2856ae5cfb4aSMatthew G. Knepley     const PetscScalar *gArray;
2857ae5cfb4aSMatthew G. Knepley     PetscScalar       *lArray;
2858d0295fc0SJunchao Zhang     PetscMemType       lmtype, gmtype;
28597128ae9fSMatthew G Knepley 
28607a8be351SBarry Smith     PetscCheck(mode != ADD_VALUES, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", (int)mode);
28619566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(l, &lArray, &lmtype));
28629566063dSJacob Faibussowitsch     PetscCall(VecGetArrayReadAndMemType(g, &gArray, &gmtype));
28639566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastWithMemTypeBegin(sf, MPIU_SCALAR, gmtype, gArray, lmtype, lArray, MPI_REPLACE));
28649566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(l, &lArray));
28659566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayReadAndMemType(g, &gArray));
28667128ae9fSMatthew G Knepley   } else {
2867fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, globaltolocalbegin, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
28687128ae9fSMatthew G Knepley   }
28693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
287047c6ae99SBarry Smith }
287147c6ae99SBarry Smith 
287247c6ae99SBarry Smith /*@
287347c6ae99SBarry Smith   DMGlobalToLocalEnd - Ends updating local vectors from global vector
287447c6ae99SBarry Smith 
287520f4b53cSBarry Smith   Neighbor-wise Collective
287647c6ae99SBarry Smith 
287747c6ae99SBarry Smith   Input Parameters:
2878bb7acecfSBarry Smith + dm   - the `DM` object
287947c6ae99SBarry Smith . g    - the global vector
2880bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
288147c6ae99SBarry Smith - l    - the local vector
288247c6ae99SBarry Smith 
288301729b5cSPatrick Sanan   Level: intermediate
288447c6ae99SBarry Smith 
2885bb7acecfSBarry Smith   Note:
2886bb7acecfSBarry Smith   See `DMGlobalToLocalBegin()` for details.
2887bb7acecfSBarry Smith 
288860225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`
288947c6ae99SBarry Smith @*/
2890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
2891d71ae5a4SJacob Faibussowitsch {
28927128ae9fSMatthew G Knepley   PetscSF                 sf;
2893ae5cfb4aSMatthew G. Knepley   const PetscScalar      *gArray;
2894ae5cfb4aSMatthew G. Knepley   PetscScalar            *lArray;
2895ca3d3a14SMatthew G. Knepley   PetscBool               transform;
2896baf369e7SPeter Brune   DMGlobalToLocalHookLink link;
2897d0295fc0SJunchao Zhang   PetscMemType            lmtype, gmtype;
289847c6ae99SBarry Smith 
289947c6ae99SBarry Smith   PetscFunctionBegin;
2900171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29019566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
29029566063dSJacob Faibussowitsch   PetscCall(DMHasBasisTransform(dm, &transform));
29037128ae9fSMatthew G Knepley   if (sf) {
29047a8be351SBarry Smith     PetscCheck(mode != ADD_VALUES, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", (int)mode);
29057128ae9fSMatthew G Knepley 
29069566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(l, &lArray, &lmtype));
29079566063dSJacob Faibussowitsch     PetscCall(VecGetArrayReadAndMemType(g, &gArray, &gmtype));
29089566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray, MPI_REPLACE));
29099566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(l, &lArray));
29109566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayReadAndMemType(g, &gArray));
29119566063dSJacob Faibussowitsch     if (transform) PetscCall(DMPlexGlobalToLocalBasis(dm, l));
29127128ae9fSMatthew G Knepley   } else {
2913fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, globaltolocalend, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
29147128ae9fSMatthew G Knepley   }
29159566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalHook_Constraints(dm, g, mode, l, NULL));
2916baf369e7SPeter Brune   for (link = dm->gtolhook; link; link = link->next) {
29179566063dSJacob Faibussowitsch     if (link->endhook) PetscCall((*link->endhook)(dm, g, mode, l, link->ctx));
2918baf369e7SPeter Brune   }
29193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
292047c6ae99SBarry Smith }
292147c6ae99SBarry Smith 
2922d4d07f1eSToby Isaac /*@C
2923d4d07f1eSToby Isaac   DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
2924d4d07f1eSToby Isaac 
292520f4b53cSBarry Smith   Logically Collective
2926d4d07f1eSToby Isaac 
29274165533cSJose E. Roman   Input Parameters:
2928bb7acecfSBarry Smith + dm        - the `DM`
2929bb7acecfSBarry Smith . beginhook - function to run at the beginning of `DMLocalToGlobalBegin()`
2930bb7acecfSBarry Smith . endhook   - function to run after `DMLocalToGlobalEnd()` has completed
293120f4b53cSBarry Smith - ctx       - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2932d4d07f1eSToby Isaac 
293320f4b53cSBarry Smith   Calling sequence of `beginhook`:
2934a4e35b19SJacob Faibussowitsch + global - global `DM`
2935d4d07f1eSToby Isaac . l      - local vector
2936d4d07f1eSToby Isaac . mode   - mode
2937d4d07f1eSToby Isaac . g      - global vector
2938d4d07f1eSToby Isaac - ctx    - optional user-defined function context
2939d4d07f1eSToby Isaac 
294020f4b53cSBarry Smith   Calling sequence of `endhook`:
2941bb7acecfSBarry Smith + global - global `DM`
2942d4d07f1eSToby Isaac . l      - local vector
2943d4d07f1eSToby Isaac . mode   - mode
2944d4d07f1eSToby Isaac . g      - global vector
2945d4d07f1eSToby Isaac - ctx    - optional user-defined function context
2946d4d07f1eSToby Isaac 
2947d4d07f1eSToby Isaac   Level: advanced
2948d4d07f1eSToby Isaac 
29491cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobal()`, `DMRefineHookAdd()`, `DMGlobalToLocalHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2950d4d07f1eSToby Isaac @*/
2951a4e35b19SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalHookAdd(DM dm, PetscErrorCode (*beginhook)(DM global, Vec l, InsertMode mode, Vec g, void *ctx), PetscErrorCode (*endhook)(DM global, Vec l, InsertMode mode, Vec g, void *ctx), void *ctx)
2952d71ae5a4SJacob Faibussowitsch {
2953d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link, *p;
2954d4d07f1eSToby Isaac 
2955d4d07f1eSToby Isaac   PetscFunctionBegin;
2956d4d07f1eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2957d4d07f1eSToby Isaac   for (p = &dm->ltoghook; *p; p = &(*p)->next) { } /* Scan to the end of the current list of hooks */
29589566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2959d4d07f1eSToby Isaac   link->beginhook = beginhook;
2960d4d07f1eSToby Isaac   link->endhook   = endhook;
2961d4d07f1eSToby Isaac   link->ctx       = ctx;
2962d4d07f1eSToby Isaac   link->next      = NULL;
2963d4d07f1eSToby Isaac   *p              = link;
29643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2965d4d07f1eSToby Isaac }
2966d4d07f1eSToby Isaac 
2967d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2968d71ae5a4SJacob Faibussowitsch {
29694c274da1SToby Isaac   PetscFunctionBegin;
2970a4e35b19SJacob Faibussowitsch   (void)g;
2971a4e35b19SJacob Faibussowitsch   (void)ctx;
29724c274da1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29732b6b7d09SToby Isaac   if (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES) {
29742b6b7d09SToby Isaac     Mat          cMat;
29752b6b7d09SToby Isaac     Vec          cVec;
29765db9a05bSToby Isaac     PetscInt     nRows;
29772b6b7d09SToby Isaac     PetscSection section, cSec;
29782b6b7d09SToby Isaac     PetscInt     pStart, pEnd, p, dof;
29792b6b7d09SToby Isaac 
29802b6b7d09SToby Isaac     PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
29812b6b7d09SToby Isaac     if (!cMat) PetscFunctionReturn(PETSC_SUCCESS);
29825db9a05bSToby Isaac 
29839566063dSJacob Faibussowitsch     PetscCall(MatGetSize(cMat, &nRows, NULL));
29843ba16761SJacob Faibussowitsch     if (nRows <= 0) PetscFunctionReturn(PETSC_SUCCESS);
29859566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
29869566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(cMat, NULL, &cVec));
29879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
29884c274da1SToby Isaac     for (p = pStart; p < pEnd; p++) {
29899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
29904c274da1SToby Isaac       if (dof) {
29914c274da1SToby Isaac         PetscInt     d;
29924c274da1SToby Isaac         PetscScalar *vals;
29939566063dSJacob Faibussowitsch         PetscCall(VecGetValuesSection(l, section, p, &vals));
29949566063dSJacob Faibussowitsch         PetscCall(VecSetValuesSection(cVec, cSec, p, vals, mode));
29954c274da1SToby Isaac         /* for this to be the true transpose, we have to zero the values that
29964c274da1SToby Isaac          * we just extracted */
2997ad540459SPierre Jolivet         for (d = 0; d < dof; d++) vals[d] = 0.;
29984c274da1SToby Isaac       }
29994c274da1SToby Isaac     }
30009566063dSJacob Faibussowitsch     PetscCall(MatMultTransposeAdd(cMat, cVec, l, l));
30019566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cVec));
30024c274da1SToby Isaac   }
30033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30044c274da1SToby Isaac }
300501729b5cSPatrick Sanan /*@
300601729b5cSPatrick Sanan   DMLocalToGlobal - updates global vectors from local vectors
300701729b5cSPatrick Sanan 
300820f4b53cSBarry Smith   Neighbor-wise Collective
300901729b5cSPatrick Sanan 
301001729b5cSPatrick Sanan   Input Parameters:
3011bb7acecfSBarry Smith + dm   - the `DM` object
301201729b5cSPatrick Sanan . l    - the local vector
3013bb7acecfSBarry 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.
301401729b5cSPatrick Sanan - g    - the global vector
301501729b5cSPatrick Sanan 
301620f4b53cSBarry Smith   Level: beginner
301720f4b53cSBarry Smith 
301801729b5cSPatrick Sanan   Notes:
301901729b5cSPatrick Sanan   The communication involved in this update can be overlapped with computation by using
3020bb7acecfSBarry Smith   `DMLocalToGlobalBegin()` and `DMLocalToGlobalEnd()`.
302101729b5cSPatrick Sanan 
3022bb7acecfSBarry Smith   In the `ADD_VALUES` case you normally would zero the receiving vector before beginning this operation.
3023bb7acecfSBarry Smith 
3024bb7acecfSBarry 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.
3025bb7acecfSBarry Smith 
3026bb7acecfSBarry Smith   Use `DMLocalToGlobalHookAdd()` to add additional operations that are performed on the data during the update process
302701729b5cSPatrick Sanan 
30281cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalBegin()`, `DMLocalToGlobalHookAdd()`, `DMGlobaToLocallHookAdd()`
302901729b5cSPatrick Sanan @*/
3030d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobal(DM dm, Vec l, InsertMode mode, Vec g)
3031d71ae5a4SJacob Faibussowitsch {
303201729b5cSPatrick Sanan   PetscFunctionBegin;
30339566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, l, mode, g));
30349566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, l, mode, g));
30353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
303601729b5cSPatrick Sanan }
30374c274da1SToby Isaac 
303847c6ae99SBarry Smith /*@
303901729b5cSPatrick Sanan   DMLocalToGlobalBegin - begins updating global vectors from local vectors
30409a42bb27SBarry Smith 
304120f4b53cSBarry Smith   Neighbor-wise Collective
30429a42bb27SBarry Smith 
30439a42bb27SBarry Smith   Input Parameters:
3044bb7acecfSBarry Smith + dm   - the `DM` object
3045f6813fd5SJed Brown . l    - the local vector
3046aa624791SPierre Jolivet . mode - if `INSERT_VALUES` then no parallel communication is used, if `ADD_VALUES` then all ghost points from the same base point accumulate into that base point.
30471eb28f2eSBarry Smith - g    - the global vector
30489a42bb27SBarry Smith 
304920f4b53cSBarry Smith   Level: intermediate
305020f4b53cSBarry Smith 
305195452b02SPatrick Sanan   Notes:
3052bb7acecfSBarry Smith   In the `ADD_VALUES` case you normally would zero the receiving vector before beginning this operation.
3053bb7acecfSBarry Smith 
3054bb7acecfSBarry 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.
3055bb7acecfSBarry Smith 
3056bb7acecfSBarry Smith   Use `DMLocalToGlobalEnd()` to complete the communication process.
3057bb7acecfSBarry Smith 
3058bb7acecfSBarry Smith   `DMLocalToGlobal()` is a short form of  `DMLocalToGlobalBegin()` and  `DMLocalToGlobalEnd()`
3059bb7acecfSBarry Smith 
3060bb7acecfSBarry Smith   `DMLocalToGlobalHookAdd()` may be used to provide additional operations that are performed during the update process.
30619a42bb27SBarry Smith 
30621cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalBegin()`
30639a42bb27SBarry Smith @*/
3064d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalBegin(DM dm, Vec l, InsertMode mode, Vec g)
3065d71ae5a4SJacob Faibussowitsch {
30667128ae9fSMatthew G Knepley   PetscSF                 sf;
306784330215SMatthew G. Knepley   PetscSection            s, gs;
3068d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link;
3069ca3d3a14SMatthew G. Knepley   Vec                     tmpl;
3070ae5cfb4aSMatthew G. Knepley   const PetscScalar      *lArray;
3071ae5cfb4aSMatthew G. Knepley   PetscScalar            *gArray;
3072fa88e482SJed Brown   PetscBool               isInsert, transform, l_inplace = PETSC_FALSE, g_inplace = PETSC_FALSE;
3073d0295fc0SJunchao Zhang   PetscMemType            lmtype = PETSC_MEMTYPE_HOST, gmtype = PETSC_MEMTYPE_HOST;
30749a42bb27SBarry Smith 
30759a42bb27SBarry Smith   PetscFunctionBegin;
3076171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3077d4d07f1eSToby Isaac   for (link = dm->ltoghook; link; link = link->next) {
30781baa6e33SBarry Smith     if (link->beginhook) PetscCall((*link->beginhook)(dm, l, mode, g, link->ctx));
3079d4d07f1eSToby Isaac   }
30809566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalHook_Constraints(dm, l, mode, g, NULL));
30819566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
30829566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
30837128ae9fSMatthew G Knepley   switch (mode) {
30847128ae9fSMatthew G Knepley   case INSERT_VALUES:
30857128ae9fSMatthew G Knepley   case INSERT_ALL_VALUES:
3086d71ae5a4SJacob Faibussowitsch   case INSERT_BC_VALUES:
3087d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_TRUE;
3088d71ae5a4SJacob Faibussowitsch     break;
30897128ae9fSMatthew G Knepley   case ADD_VALUES:
30907128ae9fSMatthew G Knepley   case ADD_ALL_VALUES:
3091d71ae5a4SJacob Faibussowitsch   case ADD_BC_VALUES:
3092d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_FALSE;
3093d71ae5a4SJacob Faibussowitsch     break;
3094d71ae5a4SJacob Faibussowitsch   default:
3095d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", mode);
30967128ae9fSMatthew G Knepley   }
3097ca3d3a14SMatthew G. Knepley   if ((sf && !isInsert) || (s && isInsert)) {
30989566063dSJacob Faibussowitsch     PetscCall(DMHasBasisTransform(dm, &transform));
3099ca3d3a14SMatthew G. Knepley     if (transform) {
31009566063dSJacob Faibussowitsch       PetscCall(DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
31019566063dSJacob Faibussowitsch       PetscCall(VecCopy(l, tmpl));
31029566063dSJacob Faibussowitsch       PetscCall(DMPlexLocalToGlobalBasis(dm, tmpl));
31039566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tmpl, &lArray));
3104fa88e482SJed Brown     } else if (isInsert) {
31059566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(l, &lArray));
3106fa88e482SJed Brown     } else {
31079566063dSJacob Faibussowitsch       PetscCall(VecGetArrayReadAndMemType(l, &lArray, &lmtype));
3108fa88e482SJed Brown       l_inplace = PETSC_TRUE;
3109ca3d3a14SMatthew G. Knepley     }
3110fa88e482SJed Brown     if (s && isInsert) {
31119566063dSJacob Faibussowitsch       PetscCall(VecGetArray(g, &gArray));
3112fa88e482SJed Brown     } else {
31139566063dSJacob Faibussowitsch       PetscCall(VecGetArrayAndMemType(g, &gArray, &gmtype));
3114fa88e482SJed Brown       g_inplace = PETSC_TRUE;
3115fa88e482SJed Brown     }
3116ca3d3a14SMatthew G. Knepley     if (sf && !isInsert) {
31179566063dSJacob Faibussowitsch       PetscCall(PetscSFReduceWithMemTypeBegin(sf, MPIU_SCALAR, lmtype, lArray, gmtype, gArray, MPIU_SUM));
311884330215SMatthew G. Knepley     } else if (s && isInsert) {
311984330215SMatthew G. Knepley       PetscInt gStart, pStart, pEnd, p;
312084330215SMatthew G. Knepley 
31219566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gs));
31229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
31239566063dSJacob Faibussowitsch       PetscCall(VecGetOwnershipRange(g, &gStart, NULL));
312484330215SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
3125b3b16f48SMatthew G. Knepley         PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
312684330215SMatthew G. Knepley 
31279566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(s, p, &dof));
31289566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(gs, p, &gdof));
31299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
31309566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(gs, p, &gcdof));
31319566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(s, p, &off));
31329566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(gs, p, &goff));
3133b3b16f48SMatthew G. Knepley         /* Ignore off-process data and points with no global data */
313403442857SMatthew G. Knepley         if (!gdof || goff < 0) continue;
31357a8be351SBarry 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);
3136b3b16f48SMatthew G. Knepley         /* If no constraints are enforced in the global vector */
3137b3b16f48SMatthew G. Knepley         if (!gcdof) {
313884330215SMatthew G. Knepley           for (d = 0; d < dof; ++d) gArray[goff - gStart + d] = lArray[off + d];
3139b3b16f48SMatthew G. Knepley           /* If constraints are enforced in the global vector */
3140b3b16f48SMatthew G. Knepley         } else if (cdof == gcdof) {
314184330215SMatthew G. Knepley           const PetscInt *cdofs;
314284330215SMatthew G. Knepley           PetscInt        cind = 0;
314384330215SMatthew G. Knepley 
31449566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetConstraintIndices(s, p, &cdofs));
3145b3b16f48SMatthew G. Knepley           for (d = 0, e = 0; d < dof; ++d) {
31469371c9d4SSatish Balay             if ((cind < cdof) && (d == cdofs[cind])) {
31479371c9d4SSatish Balay               ++cind;
31489371c9d4SSatish Balay               continue;
31499371c9d4SSatish Balay             }
3150b3b16f48SMatthew G. Knepley             gArray[goff - gStart + e++] = lArray[off + d];
315184330215SMatthew G. Knepley           }
31527a8be351SBarry 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);
315384330215SMatthew G. Knepley       }
3154ca3d3a14SMatthew G. Knepley     }
3155fa88e482SJed Brown     if (g_inplace) {
31569566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayAndMemType(g, &gArray));
3157fa88e482SJed Brown     } else {
31589566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(g, &gArray));
3159fa88e482SJed Brown     }
3160ca3d3a14SMatthew G. Knepley     if (transform) {
31619566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tmpl, &lArray));
31629566063dSJacob Faibussowitsch       PetscCall(DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
3163fa88e482SJed Brown     } else if (l_inplace) {
31649566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayReadAndMemType(l, &lArray));
3165ca3d3a14SMatthew G. Knepley     } else {
31669566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(l, &lArray));
3167ca3d3a14SMatthew G. Knepley     }
31687128ae9fSMatthew G Knepley   } else {
3169fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, localtoglobalbegin, l, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), g);
31707128ae9fSMatthew G Knepley   }
31713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31729a42bb27SBarry Smith }
31739a42bb27SBarry Smith 
31749a42bb27SBarry Smith /*@
31759a42bb27SBarry Smith   DMLocalToGlobalEnd - updates global vectors from local vectors
317647c6ae99SBarry Smith 
317720f4b53cSBarry Smith   Neighbor-wise Collective
317847c6ae99SBarry Smith 
317947c6ae99SBarry Smith   Input Parameters:
3180bb7acecfSBarry Smith + dm   - the `DM` object
3181f6813fd5SJed Brown . l    - the local vector
3182bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
3183f6813fd5SJed Brown - g    - the global vector
318447c6ae99SBarry Smith 
318501729b5cSPatrick Sanan   Level: intermediate
318647c6ae99SBarry Smith 
3187bb7acecfSBarry Smith   Note:
3188bb7acecfSBarry Smith   See `DMLocalToGlobalBegin()` for full details
3189bb7acecfSBarry Smith 
319060225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`
319147c6ae99SBarry Smith @*/
3192d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalEnd(DM dm, Vec l, InsertMode mode, Vec g)
3193d71ae5a4SJacob Faibussowitsch {
31947128ae9fSMatthew G Knepley   PetscSF                 sf;
319584330215SMatthew G. Knepley   PetscSection            s;
3196d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link;
3197ca3d3a14SMatthew G. Knepley   PetscBool               isInsert, transform;
319847c6ae99SBarry Smith 
319947c6ae99SBarry Smith   PetscFunctionBegin;
3200171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32019566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
32029566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
32037128ae9fSMatthew G Knepley   switch (mode) {
32047128ae9fSMatthew G Knepley   case INSERT_VALUES:
3205d71ae5a4SJacob Faibussowitsch   case INSERT_ALL_VALUES:
3206d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_TRUE;
3207d71ae5a4SJacob Faibussowitsch     break;
32087128ae9fSMatthew G Knepley   case ADD_VALUES:
3209d71ae5a4SJacob Faibussowitsch   case ADD_ALL_VALUES:
3210d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_FALSE;
3211d71ae5a4SJacob Faibussowitsch     break;
3212d71ae5a4SJacob Faibussowitsch   default:
3213d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", mode);
32147128ae9fSMatthew G Knepley   }
321584330215SMatthew G. Knepley   if (sf && !isInsert) {
3216ae5cfb4aSMatthew G. Knepley     const PetscScalar *lArray;
3217ae5cfb4aSMatthew G. Knepley     PetscScalar       *gArray;
3218ca3d3a14SMatthew G. Knepley     Vec                tmpl;
321984330215SMatthew G. Knepley 
32209566063dSJacob Faibussowitsch     PetscCall(DMHasBasisTransform(dm, &transform));
3221ca3d3a14SMatthew G. Knepley     if (transform) {
32229566063dSJacob Faibussowitsch       PetscCall(DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
32239566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tmpl, &lArray));
3224ca3d3a14SMatthew G. Knepley     } else {
32259566063dSJacob Faibussowitsch       PetscCall(VecGetArrayReadAndMemType(l, &lArray, NULL));
3226ca3d3a14SMatthew G. Knepley     }
32279566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(g, &gArray, NULL));
32289566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM));
3229ca3d3a14SMatthew G. Knepley     if (transform) {
32309566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tmpl, &lArray));
32319566063dSJacob Faibussowitsch       PetscCall(DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
3232ca3d3a14SMatthew G. Knepley     } else {
32339566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayReadAndMemType(l, &lArray));
3234ca3d3a14SMatthew G. Knepley     }
32359566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(g, &gArray));
323684330215SMatthew G. Knepley   } else if (s && isInsert) {
32377128ae9fSMatthew G Knepley   } else {
3238fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, localtoglobalend, l, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), g);
32397128ae9fSMatthew G Knepley   }
3240d4d07f1eSToby Isaac   for (link = dm->ltoghook; link; link = link->next) {
32419566063dSJacob Faibussowitsch     if (link->endhook) PetscCall((*link->endhook)(dm, g, mode, l, link->ctx));
3242d4d07f1eSToby Isaac   }
32433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
324447c6ae99SBarry Smith }
324547c6ae99SBarry Smith 
3246f089877aSRichard Tran Mills /*@
3247a4e35b19SJacob Faibussowitsch   DMLocalToLocalBegin - Begins the process of mapping values from a local vector (that include
3248a4e35b19SJacob Faibussowitsch   ghost points that contain irrelevant values) to another local vector where the ghost points
3249a4e35b19SJacob Faibussowitsch   in the second are set correctly from values on other MPI ranks.
3250f089877aSRichard Tran Mills 
325120f4b53cSBarry Smith   Neighbor-wise Collective
3252f089877aSRichard Tran Mills 
3253f089877aSRichard Tran Mills   Input Parameters:
3254bb7acecfSBarry Smith + dm   - the `DM` object
3255bc0a1609SRichard Tran Mills . g    - the original local vector
3256bb7acecfSBarry Smith - mode - one of `INSERT_VALUES` or `ADD_VALUES`
3257f089877aSRichard Tran Mills 
3258bc0a1609SRichard Tran Mills   Output Parameter:
3259bc0a1609SRichard Tran Mills . l - the local vector with correct ghost values
3260f089877aSRichard Tran Mills 
3261f089877aSRichard Tran Mills   Level: intermediate
3262f089877aSRichard Tran Mills 
326373ff1848SBarry Smith   Note:
3264a4e35b19SJacob Faibussowitsch   Must be followed by `DMLocalToLocalEnd()`.
3265a4e35b19SJacob Faibussowitsch 
326660225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLocalToLocalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3267f089877aSRichard Tran Mills @*/
3268d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalBegin(DM dm, Vec g, InsertMode mode, Vec l)
3269d71ae5a4SJacob Faibussowitsch {
3270f089877aSRichard Tran Mills   PetscFunctionBegin;
3271f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32729f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
32739f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(l, VEC_CLASSID, 4);
32749f4ada15SMatthew G. Knepley   PetscUseTypeMethod(dm, localtolocalbegin, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
32753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3276f089877aSRichard Tran Mills }
3277f089877aSRichard Tran Mills 
3278f089877aSRichard Tran Mills /*@
3279bb7acecfSBarry Smith   DMLocalToLocalEnd - Maps from a local vector to another local vector where the ghost
3280bb7acecfSBarry Smith   points in the second are set correctly. Must be preceded by `DMLocalToLocalBegin()`.
3281f089877aSRichard Tran Mills 
328220f4b53cSBarry Smith   Neighbor-wise Collective
3283f089877aSRichard Tran Mills 
3284f089877aSRichard Tran Mills   Input Parameters:
328560225df5SJacob Faibussowitsch + dm   - the `DM` object
3286bc0a1609SRichard Tran Mills . g    - the original local vector
3287bb7acecfSBarry Smith - mode - one of `INSERT_VALUES` or `ADD_VALUES`
3288f089877aSRichard Tran Mills 
3289bc0a1609SRichard Tran Mills   Output Parameter:
3290bc0a1609SRichard Tran Mills . l - the local vector with correct ghost values
3291f089877aSRichard Tran Mills 
3292f089877aSRichard Tran Mills   Level: intermediate
3293f089877aSRichard Tran Mills 
329460225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLocalToLocalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3295f089877aSRichard Tran Mills @*/
3296d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
3297d71ae5a4SJacob Faibussowitsch {
3298f089877aSRichard Tran Mills   PetscFunctionBegin;
3299f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33009f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
33019f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(l, VEC_CLASSID, 4);
33029f4ada15SMatthew G. Knepley   PetscUseTypeMethod(dm, localtolocalend, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
33033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3304f089877aSRichard Tran Mills }
3305f089877aSRichard Tran Mills 
330647c6ae99SBarry Smith /*@
3307bb7acecfSBarry Smith   DMCoarsen - Coarsens a `DM` object using a standard, non-adaptive coarsening of the underlying mesh
330847c6ae99SBarry Smith 
330920f4b53cSBarry Smith   Collective
331047c6ae99SBarry Smith 
3311d8d19677SJose E. Roman   Input Parameters:
3312bb7acecfSBarry Smith + dm   - the `DM` object
331320f4b53cSBarry Smith - comm - the communicator to contain the new `DM` object (or `MPI_COMM_NULL`)
331447c6ae99SBarry Smith 
331547c6ae99SBarry Smith   Output Parameter:
3316bb7acecfSBarry Smith . dmc - the coarsened `DM`
331747c6ae99SBarry Smith 
331847c6ae99SBarry Smith   Level: developer
331947c6ae99SBarry Smith 
332073ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateDomainDecomposition()`,
332173ff1848SBarry Smith           `DMCoarsenHookAdd()`, `DMCoarsenHookRemove()`
332247c6ae99SBarry Smith @*/
3323d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
3324d71ae5a4SJacob Faibussowitsch {
3325b17ce1afSJed Brown   DMCoarsenHookLink link;
332647c6ae99SBarry Smith 
332747c6ae99SBarry Smith   PetscFunctionBegin;
3328171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Coarsen, dm, 0, 0, 0));
3330dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, coarsen, comm, dmc);
3331b9d85ea2SLisandro Dalcin   if (*dmc) {
3332a3574896SRichard Tran Mills     (*dmc)->bind_below = dm->bind_below; /* Propagate this from parent DM; otherwise -dm_bind_below will be useless for multigrid cases. */
33339566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dm, *dmc));
333443842a1eSJed Brown     (*dmc)->ops->creatematrix = dm->ops->creatematrix;
33359566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmc));
3336644e2e5bSBarry Smith     (*dmc)->ctx       = dm->ctx;
33370598a293SJed Brown     (*dmc)->levelup   = dm->levelup;
3338656b349aSBarry Smith     (*dmc)->leveldown = dm->leveldown + 1;
33399566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmc, dm->mattype));
3340b17ce1afSJed Brown     for (link = dm->coarsenhook; link; link = link->next) {
33419566063dSJacob Faibussowitsch       if (link->coarsenhook) PetscCall((*link->coarsenhook)(dm, *dmc, link->ctx));
3342b17ce1afSJed Brown     }
3343b9d85ea2SLisandro Dalcin   }
33449566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Coarsen, dm, 0, 0, 0));
33457a8be351SBarry Smith   PetscCheck(*dmc, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
33463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3347b17ce1afSJed Brown }
3348b17ce1afSJed Brown 
3349bb9467b5SJed Brown /*@C
3350b17ce1afSJed Brown   DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
3351b17ce1afSJed Brown 
335220f4b53cSBarry Smith   Logically Collective; No Fortran Support
3353b17ce1afSJed Brown 
33544165533cSJose E. Roman   Input Parameters:
3355bb7acecfSBarry Smith + fine         - `DM` on which to run a hook when restricting to a coarser level
3356b17ce1afSJed Brown . coarsenhook  - function to run when setting up a coarser level
3357bb7acecfSBarry Smith . restricthook - function to run to update data on coarser levels (called once per `SNESSolve()`)
335820f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3359b17ce1afSJed Brown 
336020f4b53cSBarry Smith   Calling sequence of `coarsenhook`:
3361bb7acecfSBarry Smith + fine   - fine level `DM`
3362bb7acecfSBarry Smith . coarse - coarse level `DM` to restrict problem to
3363b17ce1afSJed Brown - ctx    - optional user-defined function context
3364b17ce1afSJed Brown 
336520f4b53cSBarry Smith   Calling sequence of `restricthook`:
3366bb7acecfSBarry Smith + fine      - fine level `DM`
3367bb7acecfSBarry Smith . mrestrict - matrix restricting a fine-level solution to the coarse grid, usually the transpose of the interpolation
3368c833c3b5SJed Brown . rscale    - scaling vector for restriction
3369c833c3b5SJed Brown . inject    - matrix restricting by injection
3370b17ce1afSJed Brown . coarse    - coarse level DM to update
3371b17ce1afSJed Brown - ctx       - optional user-defined function context
3372b17ce1afSJed Brown 
3373b17ce1afSJed Brown   Level: advanced
3374b17ce1afSJed Brown 
3375b17ce1afSJed Brown   Notes:
3376bb7acecfSBarry 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`.
3377b17ce1afSJed Brown 
3378b17ce1afSJed Brown   If this function is called multiple times, the hooks will be run in the order they are added.
3379b17ce1afSJed Brown 
3380b17ce1afSJed Brown   In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3381bb7acecfSBarry Smith   extract the finest level information from its context (instead of from the `SNES`).
3382b17ce1afSJed Brown 
3383bb7acecfSBarry Smith   The hooks are automatically called by `DMRestrict()`
3384bb7acecfSBarry Smith 
33851cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3386b17ce1afSJed Brown @*/
3387a4e35b19SJacob Faibussowitsch PetscErrorCode DMCoarsenHookAdd(DM fine, PetscErrorCode (*coarsenhook)(DM fine, DM coarse, void *ctx), PetscErrorCode (*restricthook)(DM fine, Mat mrestrict, Vec rscale, Mat inject, DM coarse, void *ctx), void *ctx)
3388d71ae5a4SJacob Faibussowitsch {
3389b17ce1afSJed Brown   DMCoarsenHookLink link, *p;
3390b17ce1afSJed Brown 
3391b17ce1afSJed Brown   PetscFunctionBegin;
3392b17ce1afSJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
33931e3d8eccSJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
33943ba16761SJacob Faibussowitsch     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
33951e3d8eccSJed Brown   }
33969566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
3397b17ce1afSJed Brown   link->coarsenhook  = coarsenhook;
3398b17ce1afSJed Brown   link->restricthook = restricthook;
3399b17ce1afSJed Brown   link->ctx          = ctx;
34000298fd71SBarry Smith   link->next         = NULL;
3401b17ce1afSJed Brown   *p                 = link;
34023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3403b17ce1afSJed Brown }
3404b17ce1afSJed Brown 
3405dc822a44SJed Brown /*@C
3406bb7acecfSBarry Smith   DMCoarsenHookRemove - remove a callback set with `DMCoarsenHookAdd()`
3407dc822a44SJed Brown 
340820f4b53cSBarry Smith   Logically Collective; No Fortran Support
3409dc822a44SJed Brown 
34104165533cSJose E. Roman   Input Parameters:
3411bb7acecfSBarry Smith + fine         - `DM` on which to run a hook when restricting to a coarser level
3412dc822a44SJed Brown . coarsenhook  - function to run when setting up a coarser level
3413bb7acecfSBarry Smith . restricthook - function to run to update data on coarser levels
341420f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3415dc822a44SJed Brown 
3416dc822a44SJed Brown   Level: advanced
3417dc822a44SJed Brown 
341873ff1848SBarry Smith   Notes:
341973ff1848SBarry Smith   This function does nothing if the `coarsenhook` is not in the list.
342073ff1848SBarry Smith 
342173ff1848SBarry Smith   See `DMCoarsenHookAdd()` for the calling sequence of `coarsenhook` and `restricthook`
3422dc822a44SJed Brown 
34231cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3424dc822a44SJed Brown @*/
3425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHookRemove(DM fine, PetscErrorCode (*coarsenhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, Mat, Vec, Mat, DM, void *), void *ctx)
3426d71ae5a4SJacob Faibussowitsch {
3427dc822a44SJed Brown   DMCoarsenHookLink link, *p;
3428dc822a44SJed Brown 
3429dc822a44SJed Brown   PetscFunctionBegin;
3430dc822a44SJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
3431dc822a44SJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3432dc822a44SJed Brown     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3433dc822a44SJed Brown       link = *p;
3434dc822a44SJed Brown       *p   = link->next;
34359566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3436dc822a44SJed Brown       break;
3437dc822a44SJed Brown     }
3438dc822a44SJed Brown   }
34393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3440dc822a44SJed Brown }
3441dc822a44SJed Brown 
3442b17ce1afSJed Brown /*@
3443bb7acecfSBarry Smith   DMRestrict - restricts user-defined problem data to a coarser `DM` by running hooks registered by `DMCoarsenHookAdd()`
3444b17ce1afSJed Brown 
3445b17ce1afSJed Brown   Collective if any hooks are
3446b17ce1afSJed Brown 
34474165533cSJose E. Roman   Input Parameters:
3448bb7acecfSBarry Smith + fine    - finer `DM` from which the data is obtained
3449bb7acecfSBarry Smith . restrct - restriction matrix, apply using `MatRestrict()`, usually the transpose of the interpolation
3450e91eccc2SStefano Zampini . rscale  - scaling vector for restriction
3451bb7acecfSBarry Smith . inject  - injection matrix, also use `MatRestrict()`
345220f4b53cSBarry Smith - coarse  - coarser `DM` to update
3453b17ce1afSJed Brown 
3454b17ce1afSJed Brown   Level: developer
3455b17ce1afSJed Brown 
345673ff1848SBarry Smith   Developer Note:
3457bb7acecfSBarry Smith   Though this routine is called `DMRestrict()` the hooks are added with `DMCoarsenHookAdd()`, a consistent terminology would be better
3458bb7acecfSBarry Smith 
34591cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `MatRestrict()`, `DMInterpolate()`, `DMRefineHookAdd()`
3460b17ce1afSJed Brown @*/
3461d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestrict(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse)
3462d71ae5a4SJacob Faibussowitsch {
3463b17ce1afSJed Brown   DMCoarsenHookLink link;
3464b17ce1afSJed Brown 
3465b17ce1afSJed Brown   PetscFunctionBegin;
3466b17ce1afSJed Brown   for (link = fine->coarsenhook; link; link = link->next) {
34671baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(fine, restrct, rscale, inject, coarse, link->ctx));
3468b17ce1afSJed Brown   }
34693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
347047c6ae99SBarry Smith }
347147c6ae99SBarry Smith 
3472bb9467b5SJed Brown /*@C
347373ff1848SBarry Smith   DMSubDomainHookAdd - adds a callback to be run when restricting a problem to subdomain `DM`s with `DMCreateDomainDecomposition()`
34745dbd56e3SPeter Brune 
347520f4b53cSBarry Smith   Logically Collective; No Fortran Support
34765dbd56e3SPeter Brune 
34774165533cSJose E. Roman   Input Parameters:
3478bb7acecfSBarry Smith + global       - global `DM`
3479bb7acecfSBarry Smith . ddhook       - function to run to pass data to the decomposition `DM` upon its creation
34805dbd56e3SPeter Brune . restricthook - function to run to update data on block solve (at the beginning of the block solve)
348120f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
34825dbd56e3SPeter Brune 
348320f4b53cSBarry Smith   Calling sequence of `ddhook`:
3484bb7acecfSBarry Smith + global - global `DM`
348573ff1848SBarry Smith . block  - subdomain `DM`
3486ec4806b8SPeter Brune - ctx    - optional user-defined function context
3487ec4806b8SPeter Brune 
348820f4b53cSBarry Smith   Calling sequence of `restricthook`:
3489bb7acecfSBarry Smith + global - global `DM`
349073ff1848SBarry Smith . out    - scatter to the outer (with ghost and overlap points) sub vector
349173ff1848SBarry Smith . in     - scatter to sub vector values only owned locally
349273ff1848SBarry Smith . block  - subdomain `DM`
34935dbd56e3SPeter Brune - ctx    - optional user-defined function context
34945dbd56e3SPeter Brune 
34955dbd56e3SPeter Brune   Level: advanced
34965dbd56e3SPeter Brune 
34975dbd56e3SPeter Brune   Notes:
349873ff1848SBarry Smith   This function can be used if auxiliary data needs to be set up on subdomain `DM`s.
34995dbd56e3SPeter Brune 
35005dbd56e3SPeter Brune   If this function is called multiple times, the hooks will be run in the order they are added.
35015dbd56e3SPeter Brune 
35025dbd56e3SPeter Brune   In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3503bb7acecfSBarry Smith   extract the global information from its context (instead of from the `SNES`).
35045dbd56e3SPeter Brune 
350573ff1848SBarry Smith   Developer Note:
350673ff1848SBarry Smith   It is unclear what "block solve" means within the definition of `restricthook`
350773ff1848SBarry Smith 
350873ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSubDomainHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`, `DMCreateDomainDecomposition()`
35095dbd56e3SPeter Brune @*/
3510a4e35b19SJacob Faibussowitsch PetscErrorCode DMSubDomainHookAdd(DM global, PetscErrorCode (*ddhook)(DM global, DM block, void *ctx), PetscErrorCode (*restricthook)(DM global, VecScatter out, VecScatter in, DM block, void *ctx), void *ctx)
3511d71ae5a4SJacob Faibussowitsch {
3512be081cd6SPeter Brune   DMSubDomainHookLink link, *p;
35135dbd56e3SPeter Brune 
35145dbd56e3SPeter Brune   PetscFunctionBegin;
35155dbd56e3SPeter Brune   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3516b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
35173ba16761SJacob Faibussowitsch     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
3518b3a6b972SJed Brown   }
35199566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
35205dbd56e3SPeter Brune   link->restricthook = restricthook;
3521be081cd6SPeter Brune   link->ddhook       = ddhook;
35225dbd56e3SPeter Brune   link->ctx          = ctx;
35230298fd71SBarry Smith   link->next         = NULL;
35245dbd56e3SPeter Brune   *p                 = link;
35253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35265dbd56e3SPeter Brune }
35275dbd56e3SPeter Brune 
3528b3a6b972SJed Brown /*@C
352973ff1848SBarry Smith   DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to subdomain `DM`s with `DMCreateDomainDecomposition()`
3530b3a6b972SJed Brown 
353120f4b53cSBarry Smith   Logically Collective; No Fortran Support
3532b3a6b972SJed Brown 
35334165533cSJose E. Roman   Input Parameters:
3534bb7acecfSBarry Smith + global       - global `DM`
3535bb7acecfSBarry Smith . ddhook       - function to run to pass data to the decomposition `DM` upon its creation
3536b3a6b972SJed Brown . restricthook - function to run to update data on block solve (at the beginning of the block solve)
353720f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3538b3a6b972SJed Brown 
3539b3a6b972SJed Brown   Level: advanced
3540b3a6b972SJed Brown 
354173ff1848SBarry Smith   Note:
354273ff1848SBarry Smith   See `DMSubDomainHookAdd()` for the calling sequences of `ddhook` and `restricthook`
354373ff1848SBarry Smith 
354473ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSubDomainHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`,
354573ff1848SBarry Smith           `DMCreateDomainDecomposition()`
3546b3a6b972SJed Brown @*/
3547d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainHookRemove(DM global, PetscErrorCode (*ddhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, VecScatter, VecScatter, DM, void *), void *ctx)
3548d71ae5a4SJacob Faibussowitsch {
3549b3a6b972SJed Brown   DMSubDomainHookLink link, *p;
3550b3a6b972SJed Brown 
3551b3a6b972SJed Brown   PetscFunctionBegin;
3552b3a6b972SJed Brown   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3553b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3554b3a6b972SJed Brown     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3555b3a6b972SJed Brown       link = *p;
3556b3a6b972SJed Brown       *p   = link->next;
35579566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3558b3a6b972SJed Brown       break;
3559b3a6b972SJed Brown     }
3560b3a6b972SJed Brown   }
35613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3562b3a6b972SJed Brown }
3563b3a6b972SJed Brown 
35645dbd56e3SPeter Brune /*@
356573ff1848SBarry Smith   DMSubDomainRestrict - restricts user-defined problem data to a subdomain `DM` by running hooks registered by `DMSubDomainHookAdd()`
35665dbd56e3SPeter Brune 
35675dbd56e3SPeter Brune   Collective if any hooks are
35685dbd56e3SPeter Brune 
35694165533cSJose E. Roman   Input Parameters:
3570a4e35b19SJacob Faibussowitsch + global   - The global `DM` to use as a base
3571a4e35b19SJacob Faibussowitsch . oscatter - The scatter from domain global vector filling subdomain global vector with overlap
3572a4e35b19SJacob Faibussowitsch . gscatter - The scatter from domain global vector filling subdomain local vector with ghosts
3573a4e35b19SJacob Faibussowitsch - subdm    - The subdomain `DM` to update
35745dbd56e3SPeter Brune 
35755dbd56e3SPeter Brune   Level: developer
35765dbd56e3SPeter Brune 
357773ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `MatRestrict()`, `DMCreateDomainDecomposition()`
35785dbd56e3SPeter Brune @*/
3579d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainRestrict(DM global, VecScatter oscatter, VecScatter gscatter, DM subdm)
3580d71ae5a4SJacob Faibussowitsch {
3581be081cd6SPeter Brune   DMSubDomainHookLink link;
35825dbd56e3SPeter Brune 
35835dbd56e3SPeter Brune   PetscFunctionBegin;
3584be081cd6SPeter Brune   for (link = global->subdomainhook; link; link = link->next) {
35851baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(global, oscatter, gscatter, subdm, link->ctx));
35865dbd56e3SPeter Brune   }
35873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35885dbd56e3SPeter Brune }
35895dbd56e3SPeter Brune 
35905fe1f584SPeter Brune /*@
3591bb7acecfSBarry Smith   DMGetCoarsenLevel - Gets the number of coarsenings that have generated this `DM`.
35925fe1f584SPeter Brune 
35935fe1f584SPeter Brune   Not Collective
35945fe1f584SPeter Brune 
35955fe1f584SPeter Brune   Input Parameter:
3596bb7acecfSBarry Smith . dm - the `DM` object
35975fe1f584SPeter Brune 
35985fe1f584SPeter Brune   Output Parameter:
35996a7d9d85SPeter Brune . level - number of coarsenings
36005fe1f584SPeter Brune 
36015fe1f584SPeter Brune   Level: developer
36025fe1f584SPeter Brune 
36031cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMSetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
36045fe1f584SPeter Brune @*/
3605d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarsenLevel(DM dm, PetscInt *level)
3606d71ae5a4SJacob Faibussowitsch {
36075fe1f584SPeter Brune   PetscFunctionBegin;
36085fe1f584SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36094f572ea9SToby Isaac   PetscAssertPointer(level, 2);
36105fe1f584SPeter Brune   *level = dm->leveldown;
36113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36125fe1f584SPeter Brune }
36135fe1f584SPeter Brune 
36149a64c4a8SMatthew G. Knepley /*@
3615bb7acecfSBarry Smith   DMSetCoarsenLevel - Sets the number of coarsenings that have generated this `DM`.
36169a64c4a8SMatthew G. Knepley 
361720f4b53cSBarry Smith   Collective
36189a64c4a8SMatthew G. Knepley 
36199a64c4a8SMatthew G. Knepley   Input Parameters:
3620bb7acecfSBarry Smith + dm    - the `DM` object
36219a64c4a8SMatthew G. Knepley - level - number of coarsenings
36229a64c4a8SMatthew G. Knepley 
36239a64c4a8SMatthew G. Knepley   Level: developer
36249a64c4a8SMatthew G. Knepley 
3625bb7acecfSBarry Smith   Note:
3626bb7acecfSBarry Smith   This is rarely used directly, the information is automatically set when a `DM` is created with `DMCoarsen()`
3627bb7acecfSBarry Smith 
362842747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
36299a64c4a8SMatthew G. Knepley @*/
3630d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarsenLevel(DM dm, PetscInt level)
3631d71ae5a4SJacob Faibussowitsch {
36329a64c4a8SMatthew G. Knepley   PetscFunctionBegin;
36339a64c4a8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36349a64c4a8SMatthew G. Knepley   dm->leveldown = level;
36353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36369a64c4a8SMatthew G. Knepley }
36379a64c4a8SMatthew G. Knepley 
3638cc4c1da9SBarry Smith /*@
3639bb7acecfSBarry Smith   DMRefineHierarchy - Refines a `DM` object, all levels at once
364047c6ae99SBarry Smith 
364120f4b53cSBarry Smith   Collective
364247c6ae99SBarry Smith 
3643d8d19677SJose E. Roman   Input Parameters:
3644bb7acecfSBarry Smith + dm      - the `DM` object
364547c6ae99SBarry Smith - nlevels - the number of levels of refinement
364647c6ae99SBarry Smith 
364747c6ae99SBarry Smith   Output Parameter:
3648bb7acecfSBarry Smith . dmf - the refined `DM` hierarchy
364947c6ae99SBarry Smith 
365047c6ae99SBarry Smith   Level: developer
365147c6ae99SBarry Smith 
36521cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMCoarsenHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
365347c6ae99SBarry Smith @*/
3654d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHierarchy(DM dm, PetscInt nlevels, DM dmf[])
3655d71ae5a4SJacob Faibussowitsch {
365647c6ae99SBarry Smith   PetscFunctionBegin;
3657171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36587a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
36593ba16761SJacob Faibussowitsch   if (nlevels == 0) PetscFunctionReturn(PETSC_SUCCESS);
36604f572ea9SToby Isaac   PetscAssertPointer(dmf, 3);
3661213acdd3SPierre Jolivet   if (dm->ops->refine && !dm->ops->refinehierarchy) {
366247c6ae99SBarry Smith     PetscInt i;
366347c6ae99SBarry Smith 
36649566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &dmf[0]));
366548a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMRefine(dmf[i - 1], PetscObjectComm((PetscObject)dm), &dmf[i]));
3666213acdd3SPierre Jolivet   } else PetscUseTypeMethod(dm, refinehierarchy, nlevels, dmf);
36673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
366847c6ae99SBarry Smith }
366947c6ae99SBarry Smith 
3670cc4c1da9SBarry Smith /*@
3671bb7acecfSBarry Smith   DMCoarsenHierarchy - Coarsens a `DM` object, all levels at once
367247c6ae99SBarry Smith 
367320f4b53cSBarry Smith   Collective
367447c6ae99SBarry Smith 
3675d8d19677SJose E. Roman   Input Parameters:
3676bb7acecfSBarry Smith + dm      - the `DM` object
367747c6ae99SBarry Smith - nlevels - the number of levels of coarsening
367847c6ae99SBarry Smith 
367947c6ae99SBarry Smith   Output Parameter:
3680bb7acecfSBarry Smith . dmc - the coarsened `DM` hierarchy
368147c6ae99SBarry Smith 
368247c6ae99SBarry Smith   Level: developer
368347c6ae99SBarry Smith 
36841cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMRefineHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
368547c6ae99SBarry Smith @*/
3686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
3687d71ae5a4SJacob Faibussowitsch {
368847c6ae99SBarry Smith   PetscFunctionBegin;
3689171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36907a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
36913ba16761SJacob Faibussowitsch   if (nlevels == 0) PetscFunctionReturn(PETSC_SUCCESS);
36924f572ea9SToby Isaac   PetscAssertPointer(dmc, 3);
3693213acdd3SPierre Jolivet   if (dm->ops->coarsen && !dm->ops->coarsenhierarchy) {
369447c6ae99SBarry Smith     PetscInt i;
369547c6ae99SBarry Smith 
36969566063dSJacob Faibussowitsch     PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &dmc[0]));
369748a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMCoarsen(dmc[i - 1], PetscObjectComm((PetscObject)dm), &dmc[i]));
3698213acdd3SPierre Jolivet   } else PetscUseTypeMethod(dm, coarsenhierarchy, nlevels, dmc);
36993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
370047c6ae99SBarry Smith }
370147c6ae99SBarry Smith 
37021a266240SBarry Smith /*@C
3703bb7acecfSBarry Smith   DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the `DM` is destroyed
37041a266240SBarry Smith 
3705bb7acecfSBarry Smith   Logically Collective if the function is collective
37061a266240SBarry Smith 
37071a266240SBarry Smith   Input Parameters:
3708bb7acecfSBarry Smith + dm      - the `DM` object
370949abdd8aSBarry Smith - destroy - the destroy function, see `PetscCtxDestroyFn` for the calling sequence
37101a266240SBarry Smith 
37111a266240SBarry Smith   Level: intermediate
37121a266240SBarry Smith 
371349abdd8aSBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`,
371449abdd8aSBarry Smith           `DMGetApplicationContext()`, `PetscCtxDestroyFn`
3715f07f9ceaSJed Brown @*/
371649abdd8aSBarry Smith PetscErrorCode DMSetApplicationContextDestroy(DM dm, PetscCtxDestroyFn *destroy)
3717d71ae5a4SJacob Faibussowitsch {
37181a266240SBarry Smith   PetscFunctionBegin;
3719171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37201a266240SBarry Smith   dm->ctxdestroy = destroy;
37213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37221a266240SBarry Smith }
37231a266240SBarry Smith 
3724b07ff414SBarry Smith /*@
3725bb7acecfSBarry Smith   DMSetApplicationContext - Set a user context into a `DM` object
372647c6ae99SBarry Smith 
372747c6ae99SBarry Smith   Not Collective
372847c6ae99SBarry Smith 
372947c6ae99SBarry Smith   Input Parameters:
3730bb7acecfSBarry Smith + dm  - the `DM` object
373147c6ae99SBarry Smith - ctx - the user context
373247c6ae99SBarry Smith 
373347c6ae99SBarry Smith   Level: intermediate
373447c6ae99SBarry Smith 
3735e33b3f0fSStefano Zampini   Notes:
373635cb6cd3SPierre Jolivet   A user context is a way to pass problem specific information that is accessible whenever the `DM` is available
3737e33b3f0fSStefano Zampini   In a multilevel solver, the user context is shared by all the `DM` in the hierarchy; it is thus not advisable
3738e33b3f0fSStefano Zampini   to store objects that represent discretized quantities inside the context.
3739bb7acecfSBarry Smith 
374060225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMGetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
374147c6ae99SBarry Smith @*/
3742d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetApplicationContext(DM dm, void *ctx)
3743d71ae5a4SJacob Faibussowitsch {
374447c6ae99SBarry Smith   PetscFunctionBegin;
3745171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
374647c6ae99SBarry Smith   dm->ctx = ctx;
37473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
374847c6ae99SBarry Smith }
374947c6ae99SBarry Smith 
375047c6ae99SBarry Smith /*@
3751bb7acecfSBarry Smith   DMGetApplicationContext - Gets a user context from a `DM` object
375247c6ae99SBarry Smith 
375347c6ae99SBarry Smith   Not Collective
375447c6ae99SBarry Smith 
375547c6ae99SBarry Smith   Input Parameter:
3756bb7acecfSBarry Smith . dm - the `DM` object
375747c6ae99SBarry Smith 
375847c6ae99SBarry Smith   Output Parameter:
375947c6ae99SBarry Smith . ctx - the user context
376047c6ae99SBarry Smith 
376147c6ae99SBarry Smith   Level: intermediate
376247c6ae99SBarry Smith 
3763bb7acecfSBarry Smith   Note:
376435cb6cd3SPierre Jolivet   A user context is a way to pass problem specific information that is accessible whenever the `DM` is available
3765bb7acecfSBarry Smith 
376642747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
376747c6ae99SBarry Smith @*/
3768d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetApplicationContext(DM dm, void *ctx)
3769d71ae5a4SJacob Faibussowitsch {
377047c6ae99SBarry Smith   PetscFunctionBegin;
3771171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37721b2093e4SBarry Smith   *(void **)ctx = dm->ctx;
37733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
377447c6ae99SBarry Smith }
377547c6ae99SBarry Smith 
377608da532bSDmitry Karpeev /*@C
3777bb7acecfSBarry Smith   DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for `SNESVI`.
377808da532bSDmitry Karpeev 
377920f4b53cSBarry Smith   Logically Collective
378008da532bSDmitry Karpeev 
3781d8d19677SJose E. Roman   Input Parameters:
378208da532bSDmitry Karpeev + dm - the DM object
378320f4b53cSBarry Smith - f  - the function that computes variable bounds used by SNESVI (use `NULL` to cancel a previous function that was set)
378408da532bSDmitry Karpeev 
378508da532bSDmitry Karpeev   Level: intermediate
378608da532bSDmitry Karpeev 
37871cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMComputeVariableBounds()`, `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`,
3788db781477SPatrick Sanan          `DMSetJacobian()`
378908da532bSDmitry Karpeev @*/
3790d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetVariableBounds(DM dm, PetscErrorCode (*f)(DM, Vec, Vec))
3791d71ae5a4SJacob Faibussowitsch {
379208da532bSDmitry Karpeev   PetscFunctionBegin;
37935a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
379408da532bSDmitry Karpeev   dm->ops->computevariablebounds = f;
37953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
379608da532bSDmitry Karpeev }
379708da532bSDmitry Karpeev 
379808da532bSDmitry Karpeev /*@
3799bb7acecfSBarry Smith   DMHasVariableBounds - does the `DM` object have a variable bounds function?
380008da532bSDmitry Karpeev 
380108da532bSDmitry Karpeev   Not Collective
380208da532bSDmitry Karpeev 
380308da532bSDmitry Karpeev   Input Parameter:
3804bb7acecfSBarry Smith . dm - the `DM` object to destroy
380508da532bSDmitry Karpeev 
380608da532bSDmitry Karpeev   Output Parameter:
3807bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the variable bounds function exists
380808da532bSDmitry Karpeev 
380908da532bSDmitry Karpeev   Level: developer
381008da532bSDmitry Karpeev 
38111cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMComputeVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
381208da532bSDmitry Karpeev @*/
3813d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasVariableBounds(DM dm, PetscBool *flg)
3814d71ae5a4SJacob Faibussowitsch {
381508da532bSDmitry Karpeev   PetscFunctionBegin;
38165a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38174f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
381808da532bSDmitry Karpeev   *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
38193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
382008da532bSDmitry Karpeev }
382108da532bSDmitry Karpeev 
3822cc4c1da9SBarry Smith /*@
3823bb7acecfSBarry Smith   DMComputeVariableBounds - compute variable bounds used by `SNESVI`.
382408da532bSDmitry Karpeev 
382520f4b53cSBarry Smith   Logically Collective
382608da532bSDmitry Karpeev 
3827f899ff85SJose E. Roman   Input Parameter:
3828bb7acecfSBarry Smith . dm - the `DM` object
382908da532bSDmitry Karpeev 
383060225df5SJacob Faibussowitsch   Output Parameters:
383108da532bSDmitry Karpeev + xl - lower bound
383208da532bSDmitry Karpeev - xu - upper bound
383308da532bSDmitry Karpeev 
3834907376e6SBarry Smith   Level: advanced
3835907376e6SBarry Smith 
383620f4b53cSBarry Smith   Note:
383795452b02SPatrick Sanan   This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
383808da532bSDmitry Karpeev 
38391cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
384008da532bSDmitry Karpeev @*/
3841d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3842d71ae5a4SJacob Faibussowitsch {
384308da532bSDmitry Karpeev   PetscFunctionBegin;
38445a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
384508da532bSDmitry Karpeev   PetscValidHeaderSpecific(xl, VEC_CLASSID, 2);
38465a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(xu, VEC_CLASSID, 3);
3847dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, computevariablebounds, xl, xu);
38483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
384908da532bSDmitry Karpeev }
385008da532bSDmitry Karpeev 
3851b0ae01b7SPeter Brune /*@
3852bb7acecfSBarry Smith   DMHasColoring - does the `DM` object have a method of providing a coloring?
3853b0ae01b7SPeter Brune 
3854b0ae01b7SPeter Brune   Not Collective
3855b0ae01b7SPeter Brune 
3856b0ae01b7SPeter Brune   Input Parameter:
3857b0ae01b7SPeter Brune . dm - the DM object
3858b0ae01b7SPeter Brune 
3859b0ae01b7SPeter Brune   Output Parameter:
3860bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateColoring()`.
3861b0ae01b7SPeter Brune 
3862b0ae01b7SPeter Brune   Level: developer
3863b0ae01b7SPeter Brune 
38641cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateColoring()`
3865b0ae01b7SPeter Brune @*/
3866d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasColoring(DM dm, PetscBool *flg)
3867d71ae5a4SJacob Faibussowitsch {
3868b0ae01b7SPeter Brune   PetscFunctionBegin;
38695a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38704f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
3871b0ae01b7SPeter Brune   *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
38723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3873b0ae01b7SPeter Brune }
3874b0ae01b7SPeter Brune 
38753ad4599aSBarry Smith /*@
3876bb7acecfSBarry Smith   DMHasCreateRestriction - does the `DM` object have a method of providing a restriction?
38773ad4599aSBarry Smith 
38783ad4599aSBarry Smith   Not Collective
38793ad4599aSBarry Smith 
38803ad4599aSBarry Smith   Input Parameter:
3881bb7acecfSBarry Smith . dm - the `DM` object
38823ad4599aSBarry Smith 
38833ad4599aSBarry Smith   Output Parameter:
3884bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateRestriction()`.
38853ad4599aSBarry Smith 
38863ad4599aSBarry Smith   Level: developer
38873ad4599aSBarry Smith 
38881cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateRestriction()`, `DMHasCreateInterpolation()`, `DMHasCreateInjection()`
38893ad4599aSBarry Smith @*/
3890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateRestriction(DM dm, PetscBool *flg)
3891d71ae5a4SJacob Faibussowitsch {
38923ad4599aSBarry Smith   PetscFunctionBegin;
38935a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38944f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
38953ad4599aSBarry Smith   *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
38963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38973ad4599aSBarry Smith }
38983ad4599aSBarry Smith 
3899a7058e45SLawrence Mitchell /*@
3900bb7acecfSBarry Smith   DMHasCreateInjection - does the `DM` object have a method of providing an injection?
3901a7058e45SLawrence Mitchell 
3902a7058e45SLawrence Mitchell   Not Collective
3903a7058e45SLawrence Mitchell 
3904a7058e45SLawrence Mitchell   Input Parameter:
3905bb7acecfSBarry Smith . dm - the `DM` object
3906a7058e45SLawrence Mitchell 
3907a7058e45SLawrence Mitchell   Output Parameter:
3908bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateInjection()`.
3909a7058e45SLawrence Mitchell 
3910a7058e45SLawrence Mitchell   Level: developer
3911a7058e45SLawrence Mitchell 
39121cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateInjection()`, `DMHasCreateRestriction()`, `DMHasCreateInterpolation()`
3913a7058e45SLawrence Mitchell @*/
3914d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateInjection(DM dm, PetscBool *flg)
3915d71ae5a4SJacob Faibussowitsch {
3916a7058e45SLawrence Mitchell   PetscFunctionBegin;
39175a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39184f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
3919dbbe0bcdSBarry Smith   if (dm->ops->hascreateinjection) PetscUseTypeMethod(dm, hascreateinjection, flg);
3920ad540459SPierre Jolivet   else *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE;
39213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3922a7058e45SLawrence Mitchell }
3923a7058e45SLawrence Mitchell 
39240298fd71SBarry Smith PetscFunctionList DMList              = NULL;
3925264ace61SBarry Smith PetscBool         DMRegisterAllCalled = PETSC_FALSE;
3926264ace61SBarry Smith 
3927cc4c1da9SBarry Smith /*@
3928bb7acecfSBarry Smith   DMSetType - Builds a `DM`, for a particular `DM` implementation.
3929264ace61SBarry Smith 
393020f4b53cSBarry Smith   Collective
3931264ace61SBarry Smith 
3932264ace61SBarry Smith   Input Parameters:
3933bb7acecfSBarry Smith + dm     - The `DM` object
3934bb7acecfSBarry Smith - method - The name of the `DMType`, for example `DMDA`, `DMPLEX`
3935264ace61SBarry Smith 
3936264ace61SBarry Smith   Options Database Key:
3937bb7acecfSBarry Smith . -dm_type <type> - Sets the `DM` type; use -help for a list of available types
3938264ace61SBarry Smith 
3939264ace61SBarry Smith   Level: intermediate
3940264ace61SBarry Smith 
3941bb7acecfSBarry Smith   Note:
39420462cc06SPierre Jolivet   Of the `DM` is constructed by directly calling a function to construct a particular `DM`, for example, `DMDACreate2d()` or `DMPlexCreateBoxMesh()`
3943bb7acecfSBarry Smith 
39441cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMDA`, `DMPLEX`, `DMGetType()`, `DMCreate()`, `DMDACreate2d()`
3945264ace61SBarry Smith @*/
3946d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetType(DM dm, DMType method)
3947d71ae5a4SJacob Faibussowitsch {
3948264ace61SBarry Smith   PetscErrorCode (*r)(DM);
3949264ace61SBarry Smith   PetscBool match;
3950264ace61SBarry Smith 
3951264ace61SBarry Smith   PetscFunctionBegin;
3952264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39539566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, method, &match));
39543ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
3955264ace61SBarry Smith 
39569566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
39579566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(DMList, method, &r));
39587a8be351SBarry Smith   PetscCheck(r, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3959264ace61SBarry Smith 
3960dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, destroy);
39619566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(dm->ops, sizeof(*dm->ops)));
39629566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)dm, method));
39639566063dSJacob Faibussowitsch   PetscCall((*r)(dm));
39643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3965264ace61SBarry Smith }
3966264ace61SBarry Smith 
3967cc4c1da9SBarry Smith /*@
3968bb7acecfSBarry Smith   DMGetType - Gets the `DM` type name (as a string) from the `DM`.
3969264ace61SBarry Smith 
3970264ace61SBarry Smith   Not Collective
3971264ace61SBarry Smith 
3972264ace61SBarry Smith   Input Parameter:
3973bb7acecfSBarry Smith . dm - The `DM`
3974264ace61SBarry Smith 
3975264ace61SBarry Smith   Output Parameter:
3976bb7acecfSBarry Smith . type - The `DMType` name
3977264ace61SBarry Smith 
3978264ace61SBarry Smith   Level: intermediate
3979264ace61SBarry Smith 
39801cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMDA`, `DMPLEX`, `DMSetType()`, `DMCreate()`
3981264ace61SBarry Smith @*/
3982d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetType(DM dm, DMType *type)
3983d71ae5a4SJacob Faibussowitsch {
3984264ace61SBarry Smith   PetscFunctionBegin;
3985264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39864f572ea9SToby Isaac   PetscAssertPointer(type, 2);
39879566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
3988264ace61SBarry Smith   *type = ((PetscObject)dm)->type_name;
39893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3990264ace61SBarry Smith }
3991264ace61SBarry Smith 
39925d83a8b1SBarry Smith /*@
3993bb7acecfSBarry Smith   DMConvert - Converts a `DM` to another `DM`, either of the same or different type.
399467a56275SMatthew G Knepley 
399520f4b53cSBarry Smith   Collective
399667a56275SMatthew G Knepley 
399767a56275SMatthew G Knepley   Input Parameters:
3998bb7acecfSBarry Smith + dm      - the `DM`
3999bb7acecfSBarry Smith - newtype - new `DM` type (use "same" for the same type)
400067a56275SMatthew G Knepley 
400167a56275SMatthew G Knepley   Output Parameter:
4002bb7acecfSBarry Smith . M - pointer to new `DM`
400367a56275SMatthew G Knepley 
400420f4b53cSBarry Smith   Level: intermediate
400520f4b53cSBarry Smith 
400673ff1848SBarry Smith   Note:
4007bb7acecfSBarry Smith   Cannot be used to convert a sequential `DM` to a parallel or a parallel to sequential,
4008bb7acecfSBarry Smith   the MPI communicator of the generated `DM` is always the same as the communicator
4009bb7acecfSBarry Smith   of the input `DM`.
401067a56275SMatthew G Knepley 
40111cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetType()`, `DMCreate()`, `DMClone()`
401267a56275SMatthew G Knepley @*/
4013d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
4014d71ae5a4SJacob Faibussowitsch {
401567a56275SMatthew G Knepley   DM        B;
401667a56275SMatthew G Knepley   char      convname[256];
4017c067b6caSMatthew G. Knepley   PetscBool sametype /*, issame */;
401867a56275SMatthew G Knepley 
401967a56275SMatthew G Knepley   PetscFunctionBegin;
402067a56275SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
402167a56275SMatthew G Knepley   PetscValidType(dm, 1);
40224f572ea9SToby Isaac   PetscAssertPointer(M, 3);
40239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, newtype, &sametype));
40249566063dSJacob Faibussowitsch   /* PetscCall(PetscStrcmp(newtype, "same", &issame)); */
4025c067b6caSMatthew G. Knepley   if (sametype) {
4026c067b6caSMatthew G. Knepley     *M = dm;
40279566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
40283ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
4029c067b6caSMatthew G. Knepley   } else {
40300298fd71SBarry Smith     PetscErrorCode (*conv)(DM, DMType, DM *) = NULL;
403167a56275SMatthew G Knepley 
403267a56275SMatthew G Knepley     /*
403367a56275SMatthew G Knepley        Order of precedence:
403467a56275SMatthew G Knepley        1) See if a specialized converter is known to the current DM.
403567a56275SMatthew G Knepley        2) See if a specialized converter is known to the desired DM class.
403667a56275SMatthew G Knepley        3) See if a good general converter is registered for the desired class
403767a56275SMatthew G Knepley        4) See if a good general converter is known for the current matrix.
403867a56275SMatthew G Knepley        5) Use a really basic converter.
403967a56275SMatthew G Knepley     */
404067a56275SMatthew G Knepley 
404167a56275SMatthew G Knepley     /* 1) See if a specialized converter is known to the current DM and the desired class */
40429566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
40439566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
40449566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
40459566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
40469566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
40479566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)dm, convname, &conv));
404867a56275SMatthew G Knepley     if (conv) goto foundconv;
404967a56275SMatthew G Knepley 
405067a56275SMatthew G Knepley     /* 2)  See if a specialized converter is known to the desired DM class. */
40519566063dSJacob Faibussowitsch     PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &B));
40529566063dSJacob Faibussowitsch     PetscCall(DMSetType(B, newtype));
40539566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
40549566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
40559566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
40569566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
40579566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
40589566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
405967a56275SMatthew G Knepley     if (conv) {
40609566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&B));
406167a56275SMatthew G Knepley       goto foundconv;
406267a56275SMatthew G Knepley     }
406367a56275SMatthew G Knepley 
406467a56275SMatthew G Knepley #if 0
406567a56275SMatthew G Knepley     /* 3) See if a good general converter is registered for the desired class */
406667a56275SMatthew G Knepley     conv = B->ops->convertfrom;
40679566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&B));
406867a56275SMatthew G Knepley     if (conv) goto foundconv;
406967a56275SMatthew G Knepley 
407067a56275SMatthew G Knepley     /* 4) See if a good general converter is known for the current matrix */
407167a56275SMatthew G Knepley     if (dm->ops->convert) {
407267a56275SMatthew G Knepley       conv = dm->ops->convert;
407367a56275SMatthew G Knepley     }
407467a56275SMatthew G Knepley     if (conv) goto foundconv;
407567a56275SMatthew G Knepley #endif
407667a56275SMatthew G Knepley 
407767a56275SMatthew G Knepley     /* 5) Use a really basic converter. */
407898921bdaSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject)dm)->type_name, newtype);
407967a56275SMatthew G Knepley 
408067a56275SMatthew G Knepley   foundconv:
40819566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(DM_Convert, dm, 0, 0, 0));
40829566063dSJacob Faibussowitsch     PetscCall((*conv)(dm, newtype, M));
408312fa691eSMatthew G. Knepley     /* Things that are independent of DM type: We should consult DMClone() here */
408490b157c4SStefano Zampini     {
40854fb89dddSMatthew G. Knepley       const PetscReal *maxCell, *Lstart, *L;
40866858538eSMatthew G. Knepley 
40874fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
40884fb89dddSMatthew G. Knepley       PetscCall(DMSetPeriodicity(*M, maxCell, Lstart, L));
4089c8a6034eSMark       (*M)->prealloc_only = dm->prealloc_only;
40909566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->vectype));
40919566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*M)->vectype));
40929566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->mattype));
40939566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*M)->mattype));
409412fa691eSMatthew G. Knepley     }
40959566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(DM_Convert, dm, 0, 0, 0));
409667a56275SMatthew G Knepley   }
40979566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
40983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
409967a56275SMatthew G Knepley }
4100264ace61SBarry Smith 
4101264ace61SBarry Smith /*--------------------------------------------------------------------------------------------------------------------*/
4102264ace61SBarry Smith 
4103264ace61SBarry Smith /*@C
4104bb7acecfSBarry Smith   DMRegister -  Adds a new `DM` type implementation
41051c84c290SBarry Smith 
4106cc4c1da9SBarry Smith   Not Collective, No Fortran Support
41071c84c290SBarry Smith 
41081c84c290SBarry Smith   Input Parameters:
410920f4b53cSBarry Smith + sname    - The name of a new user-defined creation routine
411020f4b53cSBarry Smith - function - The creation routine itself
411120f4b53cSBarry Smith 
411220f4b53cSBarry Smith   Level: advanced
41131c84c290SBarry Smith 
411473ff1848SBarry Smith   Note:
411520f4b53cSBarry Smith   `DMRegister()` may be called multiple times to add several user-defined `DM`s
41161c84c290SBarry Smith 
411760225df5SJacob Faibussowitsch   Example Usage:
41181c84c290SBarry Smith .vb
4119bdf89e91SBarry Smith     DMRegister("my_da", MyDMCreate);
41201c84c290SBarry Smith .ve
41211c84c290SBarry Smith 
412220f4b53cSBarry Smith   Then, your `DM` type can be chosen with the procedural interface via
41231c84c290SBarry Smith .vb
41241c84c290SBarry Smith     DMCreate(MPI_Comm, DM *);
41251c84c290SBarry Smith     DMSetType(DM,"my_da");
41261c84c290SBarry Smith .ve
41271c84c290SBarry Smith   or at runtime via the option
41281c84c290SBarry Smith .vb
41291c84c290SBarry Smith     -da_type my_da
41301c84c290SBarry Smith .ve
4131264ace61SBarry Smith 
41321cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMSetType()`, `DMRegisterAll()`, `DMRegisterDestroy()`
4133264ace61SBarry Smith @*/
4134d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRegister(const char sname[], PetscErrorCode (*function)(DM))
4135d71ae5a4SJacob Faibussowitsch {
4136264ace61SBarry Smith   PetscFunctionBegin;
41379566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
41389566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&DMList, sname, function));
41393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4140264ace61SBarry Smith }
4141264ace61SBarry Smith 
4142ffeef943SBarry Smith /*@
4143bb7acecfSBarry Smith   DMLoad - Loads a DM that has been stored in binary  with `DMView()`.
4144b859378eSBarry Smith 
414520f4b53cSBarry Smith   Collective
4146b859378eSBarry Smith 
4147b859378eSBarry Smith   Input Parameters:
4148bb7acecfSBarry Smith + newdm  - the newly loaded `DM`, this needs to have been created with `DMCreate()` or
4149bb7acecfSBarry Smith            some related function before a call to `DMLoad()`.
4150bb7acecfSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` or
4151bb7acecfSBarry Smith            `PETSCVIEWERHDF5` file viewer, obtained from `PetscViewerHDF5Open()`
4152b859378eSBarry Smith 
4153b859378eSBarry Smith   Level: intermediate
4154b859378eSBarry Smith 
4155b859378eSBarry Smith   Notes:
415655849f57SBarry Smith   The type is determined by the data in the file, any type set into the DM before this call is ignored.
4157b859378eSBarry Smith 
4158bb7acecfSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
4159bb7acecfSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
4160bb7acecfSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
4161cd7e8a5eSksagiyam 
41621cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscViewerBinaryOpen()`, `DMView()`, `MatLoad()`, `VecLoad()`
4163b859378eSBarry Smith @*/
4164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
4165d71ae5a4SJacob Faibussowitsch {
41669331c7a4SMatthew G. Knepley   PetscBool isbinary, ishdf5;
4167b859378eSBarry Smith 
4168b859378eSBarry Smith   PetscFunctionBegin;
4169b859378eSBarry Smith   PetscValidHeaderSpecific(newdm, DM_CLASSID, 1);
4170b859378eSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
41719566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckReadable(viewer));
41729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
41739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
41749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Load, viewer, 0, 0, 0));
41759331c7a4SMatthew G. Knepley   if (isbinary) {
41769331c7a4SMatthew G. Knepley     PetscInt classid;
41779331c7a4SMatthew G. Knepley     char     type[256];
4178b859378eSBarry Smith 
41799566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
4180835f2295SStefano Zampini     PetscCheck(classid == DM_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not DM next in file, classid found %" PetscInt_FMT, classid);
41819566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
41829566063dSJacob Faibussowitsch     PetscCall(DMSetType(newdm, type));
4183dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41849331c7a4SMatthew G. Knepley   } else if (ishdf5) {
4185dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41869331c7a4SMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
41879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Load, viewer, 0, 0, 0));
41883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4189b859378eSBarry Smith }
4190b859378eSBarry Smith 
41914ee01570SBarry Smith /* FEM Support */
41927da65231SMatthew G Knepley 
41932ecf6ec3SMatthew G. Knepley PetscErrorCode DMPrintCellIndices(PetscInt c, const char name[], PetscInt len, const PetscInt x[])
41942ecf6ec3SMatthew G. Knepley {
41952ecf6ec3SMatthew G. Knepley   PetscInt f;
41962ecf6ec3SMatthew G. Knepley 
41972ecf6ec3SMatthew G. Knepley   PetscFunctionBegin;
41982ecf6ec3SMatthew G. Knepley   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
41992ecf6ec3SMatthew G. Knepley   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %" PetscInt_FMT " |\n", x[f]));
42002ecf6ec3SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
42012ecf6ec3SMatthew G. Knepley }
42022ecf6ec3SMatthew G. Knepley 
4203d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
4204d71ae5a4SJacob Faibussowitsch {
42051d47ebbbSSatish Balay   PetscInt f;
42061b30c384SMatthew G Knepley 
42077da65231SMatthew G Knepley   PetscFunctionBegin;
420863a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
420948a46eb9SPierre Jolivet   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f])));
42103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42117da65231SMatthew G Knepley }
42127da65231SMatthew G Knepley 
42135962854dSMatthew G. Knepley PetscErrorCode DMPrintCellVectorReal(PetscInt c, const char name[], PetscInt len, const PetscReal x[])
42145962854dSMatthew G. Knepley {
42155962854dSMatthew G. Knepley   PetscInt f;
42165962854dSMatthew G. Knepley 
42175962854dSMatthew G. Knepley   PetscFunctionBegin;
42185962854dSMatthew G. Knepley   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
42195962854dSMatthew G. Knepley   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)x[f]));
42205962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
42215962854dSMatthew G. Knepley }
42225962854dSMatthew G. Knepley 
4223d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
4224d71ae5a4SJacob Faibussowitsch {
42251b30c384SMatthew G Knepley   PetscInt f, g;
42267da65231SMatthew G Knepley 
42277da65231SMatthew G Knepley   PetscFunctionBegin;
422863a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
42291d47ebbbSSatish Balay   for (f = 0; f < rows; ++f) {
42309566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  |"));
423148a46eb9SPierre Jolivet     for (g = 0; g < cols; ++g) PetscCall(PetscPrintf(PETSC_COMM_SELF, " % 9.5g", (double)PetscRealPart(A[f * cols + g])));
42329566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, " |\n"));
42337da65231SMatthew G Knepley   }
42343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42357da65231SMatthew G Knepley }
4236e7c4fc90SDmitry Karpeev 
4237d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
4238d71ae5a4SJacob Faibussowitsch {
42390c5b8624SToby Isaac   PetscInt           localSize, bs;
42400c5b8624SToby Isaac   PetscMPIInt        size;
42410c5b8624SToby Isaac   Vec                x, xglob;
42420c5b8624SToby Isaac   const PetscScalar *xarray;
4243e759306cSMatthew G. Knepley 
4244e759306cSMatthew G. Knepley   PetscFunctionBegin;
42459566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
42469566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, &x));
42479566063dSJacob Faibussowitsch   PetscCall(VecCopy(X, x));
424893ec0da9SPierre Jolivet   PetscCall(VecFilter(x, tol));
42499566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "%s:\n", name));
42500c5b8624SToby Isaac   if (size > 1) {
42519566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(x, &localSize));
42529566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xarray));
42539566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(x, &bs));
42549566063dSJacob Faibussowitsch     PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)dm), bs, localSize, PETSC_DETERMINE, xarray, &xglob));
42550c5b8624SToby Isaac   } else {
42560c5b8624SToby Isaac     xglob = x;
42570c5b8624SToby Isaac   }
42589566063dSJacob Faibussowitsch   PetscCall(VecView(xglob, PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)dm))));
42590c5b8624SToby Isaac   if (size > 1) {
42609566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xglob));
42619566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xarray));
42620c5b8624SToby Isaac   }
42639566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
42643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4265e759306cSMatthew G. Knepley }
4266e759306cSMatthew G. Knepley 
426788ed4aceSMatthew G Knepley /*@
4268bb7acecfSBarry Smith   DMGetLocalSection - Get the `PetscSection` encoding the local data layout for the `DM`.
426988ed4aceSMatthew G Knepley 
427088ed4aceSMatthew G Knepley   Input Parameter:
4271bb7acecfSBarry Smith . dm - The `DM`
427288ed4aceSMatthew G Knepley 
427388ed4aceSMatthew G Knepley   Output Parameter:
4274bb7acecfSBarry Smith . section - The `PetscSection`
427588ed4aceSMatthew G Knepley 
427620f4b53cSBarry Smith   Options Database Key:
4277bb7acecfSBarry Smith . -dm_petscsection_view - View the section created by the `DM`
4278e5893cccSMatthew G. Knepley 
427988ed4aceSMatthew G Knepley   Level: intermediate
428088ed4aceSMatthew G Knepley 
4281bb7acecfSBarry Smith   Note:
4282bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
428388ed4aceSMatthew G Knepley 
42841cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetGlobalSection()`
428588ed4aceSMatthew G Knepley @*/
4286d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section)
4287d71ae5a4SJacob Faibussowitsch {
428888ed4aceSMatthew G Knepley   PetscFunctionBegin;
428988ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
42904f572ea9SToby Isaac   PetscAssertPointer(section, 2);
42911bb6d2a8SBarry Smith   if (!dm->localSection && dm->ops->createlocalsection) {
4292e5e52638SMatthew G. Knepley     PetscInt d;
4293e5e52638SMatthew G. Knepley 
429445480ffeSMatthew G. Knepley     if (dm->setfromoptionscalled) {
429545480ffeSMatthew G. Knepley       PetscObject       obj = (PetscObject)dm;
429645480ffeSMatthew G. Knepley       PetscViewer       viewer;
429745480ffeSMatthew G. Knepley       PetscViewerFormat format;
429845480ffeSMatthew G. Knepley       PetscBool         flg;
429945480ffeSMatthew G. Knepley 
4300648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm(obj), obj->options, obj->prefix, "-dm_petscds_view", &viewer, &format, &flg));
43019566063dSJacob Faibussowitsch       if (flg) PetscCall(PetscViewerPushFormat(viewer, format));
430245480ffeSMatthew G. Knepley       for (d = 0; d < dm->Nds; ++d) {
43039566063dSJacob Faibussowitsch         PetscCall(PetscDSSetFromOptions(dm->probs[d].ds));
43049566063dSJacob Faibussowitsch         if (flg) PetscCall(PetscDSView(dm->probs[d].ds, viewer));
430545480ffeSMatthew G. Knepley       }
430645480ffeSMatthew G. Knepley       if (flg) {
43079566063dSJacob Faibussowitsch         PetscCall(PetscViewerFlush(viewer));
43089566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4309648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
431045480ffeSMatthew G. Knepley       }
431145480ffeSMatthew G. Knepley     }
4312dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createlocalsection);
43139566063dSJacob Faibussowitsch     if (dm->localSection) PetscCall(PetscObjectViewFromOptions((PetscObject)dm->localSection, NULL, "-dm_petscsection_view"));
43142f0f8703SMatthew G. Knepley   }
43151bb6d2a8SBarry Smith   *section = dm->localSection;
43163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
431788ed4aceSMatthew G Knepley }
431888ed4aceSMatthew G Knepley 
431988ed4aceSMatthew G Knepley /*@
4320bb7acecfSBarry Smith   DMSetLocalSection - Set the `PetscSection` encoding the local data layout for the `DM`.
432188ed4aceSMatthew G Knepley 
432288ed4aceSMatthew G Knepley   Input Parameters:
4323bb7acecfSBarry Smith + dm      - The `DM`
4324bb7acecfSBarry Smith - section - The `PetscSection`
432588ed4aceSMatthew G Knepley 
432688ed4aceSMatthew G Knepley   Level: intermediate
432788ed4aceSMatthew G Knepley 
4328bb7acecfSBarry Smith   Note:
4329bb7acecfSBarry Smith   Any existing Section will be destroyed
433088ed4aceSMatthew G Knepley 
43311cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscSection`, `DMGetLocalSection()`, `DMSetGlobalSection()`
433288ed4aceSMatthew G Knepley @*/
4333d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLocalSection(DM dm, PetscSection section)
4334d71ae5a4SJacob Faibussowitsch {
4335c473ab19SMatthew G. Knepley   PetscInt numFields = 0;
4336af122d2aSMatthew G Knepley   PetscInt f;
433788ed4aceSMatthew G Knepley 
433888ed4aceSMatthew G Knepley   PetscFunctionBegin;
433988ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4340b9d85ea2SLisandro Dalcin   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
43419566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
43429566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->localSection));
43431bb6d2a8SBarry Smith   dm->localSection = section;
43449566063dSJacob Faibussowitsch   if (section) PetscCall(PetscSectionGetNumFields(dm->localSection, &numFields));
4345af122d2aSMatthew G Knepley   if (numFields) {
43469566063dSJacob Faibussowitsch     PetscCall(DMSetNumFields(dm, numFields));
4347af122d2aSMatthew G Knepley     for (f = 0; f < numFields; ++f) {
43480f21e855SMatthew G. Knepley       PetscObject disc;
4349af122d2aSMatthew G Knepley       const char *name;
4350af122d2aSMatthew G Knepley 
43519566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(dm->localSection, f, &name));
43529566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, &disc));
43539566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName(disc, name));
4354af122d2aSMatthew G Knepley     }
4355af122d2aSMatthew G Knepley   }
435650350c8eSStefano Zampini   /* The global section and the SectionSF will be rebuilt
435750350c8eSStefano Zampini      in the next call to DMGetGlobalSection() and DMGetSectionSF(). */
43589566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
435950350c8eSStefano Zampini   PetscCall(PetscSFDestroy(&dm->sectionSF));
436052947b74SStefano Zampini   PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &dm->sectionSF));
436150350c8eSStefano Zampini 
436250350c8eSStefano Zampini   /* Clear scratch vectors */
436350350c8eSStefano Zampini   PetscCall(DMClearGlobalVectors(dm));
436450350c8eSStefano Zampini   PetscCall(DMClearLocalVectors(dm));
436550350c8eSStefano Zampini   PetscCall(DMClearNamedGlobalVectors(dm));
436650350c8eSStefano Zampini   PetscCall(DMClearNamedLocalVectors(dm));
43673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
436888ed4aceSMatthew G Knepley }
436988ed4aceSMatthew G Knepley 
4370adc21957SMatthew G. Knepley /*@C
4371d8b4a066SPierre Jolivet   DMCreateSectionPermutation - Create a permutation of the `PetscSection` chart and optionally a block structure.
4372adc21957SMatthew G. Knepley 
4373adc21957SMatthew G. Knepley   Input Parameter:
4374adc21957SMatthew G. Knepley . dm - The `DM`
4375adc21957SMatthew G. Knepley 
43769cde84edSJose E. Roman   Output Parameters:
4377adc21957SMatthew G. Knepley + perm        - A permutation of the mesh points in the chart
4378b6971eaeSBarry Smith - blockStarts - A high bit is set for the point that begins every block, or `NULL` for default blocking
4379adc21957SMatthew G. Knepley 
4380adc21957SMatthew G. Knepley   Level: developer
4381adc21957SMatthew G. Knepley 
4382adc21957SMatthew G. Knepley .seealso: [](ch_dmbase), `DM`, `PetscSection`, `DMGetLocalSection()`, `DMGetGlobalSection()`
4383adc21957SMatthew G. Knepley @*/
4384adc21957SMatthew G. Knepley PetscErrorCode DMCreateSectionPermutation(DM dm, IS *perm, PetscBT *blockStarts)
4385adc21957SMatthew G. Knepley {
4386adc21957SMatthew G. Knepley   PetscFunctionBegin;
4387adc21957SMatthew G. Knepley   *perm        = NULL;
4388adc21957SMatthew G. Knepley   *blockStarts = NULL;
4389adc21957SMatthew G. Knepley   PetscTryTypeMethod(dm, createsectionpermutation, perm, blockStarts);
4390adc21957SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
4391adc21957SMatthew G. Knepley }
4392adc21957SMatthew G. Knepley 
43939435951eSToby Isaac /*@
4394bb7acecfSBarry Smith   DMGetDefaultConstraints - Get the `PetscSection` and `Mat` that specify the local constraint interpolation. See `DMSetDefaultConstraints()` for a description of the purpose of constraint interpolation.
43959435951eSToby Isaac 
439620f4b53cSBarry Smith   not Collective
4397e228b242SToby Isaac 
43989435951eSToby Isaac   Input Parameter:
4399bb7acecfSBarry Smith . dm - The `DM`
44009435951eSToby Isaac 
4401d8d19677SJose E. Roman   Output Parameters:
440220f4b53cSBarry 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.
440320f4b53cSBarry 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.
440479769bd5SJed Brown - bias    - Vector containing bias to be added to constrained dofs
44059435951eSToby Isaac 
44069435951eSToby Isaac   Level: advanced
44079435951eSToby Isaac 
4408bb7acecfSBarry Smith   Note:
4409bb7acecfSBarry Smith   This gets borrowed references, so the user should not destroy the `PetscSection`, `Mat`, or `Vec`.
44109435951eSToby Isaac 
44111cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetDefaultConstraints()`
44129435951eSToby Isaac @*/
4413d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat, Vec *bias)
4414d71ae5a4SJacob Faibussowitsch {
44159435951eSToby Isaac   PetscFunctionBegin;
44169435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4417dbbe0bcdSBarry Smith   if (!dm->defaultConstraint.section && !dm->defaultConstraint.mat && dm->ops->createdefaultconstraints) PetscUseTypeMethod(dm, createdefaultconstraints);
44183b8ba7d1SJed Brown   if (section) *section = dm->defaultConstraint.section;
44193b8ba7d1SJed Brown   if (mat) *mat = dm->defaultConstraint.mat;
442079769bd5SJed Brown   if (bias) *bias = dm->defaultConstraint.bias;
44213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44229435951eSToby Isaac }
44239435951eSToby Isaac 
44249435951eSToby Isaac /*@
4425bb7acecfSBarry Smith   DMSetDefaultConstraints - Set the `PetscSection` and `Mat` that specify the local constraint interpolation.
44269435951eSToby Isaac 
442720f4b53cSBarry Smith   Collective
4428e228b242SToby Isaac 
44299435951eSToby Isaac   Input Parameters:
4430bb7acecfSBarry Smith + dm      - The `DM`
4431bb7acecfSBarry 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).
443220f4b53cSBarry 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).
443320f4b53cSBarry 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).
44349435951eSToby Isaac 
44359435951eSToby Isaac   Level: advanced
44369435951eSToby Isaac 
443720f4b53cSBarry Smith   Notes:
443820f4b53cSBarry 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()`.
443920f4b53cSBarry Smith 
444020f4b53cSBarry 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.
444120f4b53cSBarry Smith 
4442bb7acecfSBarry Smith   This increments the references of the `PetscSection`, `Mat`, and `Vec`, so they user can destroy them.
44439435951eSToby Isaac 
44441cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDefaultConstraints()`
44459435951eSToby Isaac @*/
4446d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat, Vec bias)
4447d71ae5a4SJacob Faibussowitsch {
4448e228b242SToby Isaac   PetscMPIInt result;
44499435951eSToby Isaac 
44509435951eSToby Isaac   PetscFunctionBegin;
44519435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4452e228b242SToby Isaac   if (section) {
4453e228b242SToby Isaac     PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
44549566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)section), &result));
44557a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint section must have local communicator");
4456e228b242SToby Isaac   }
4457e228b242SToby Isaac   if (mat) {
4458e228b242SToby Isaac     PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
44599566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)mat), &result));
44607a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint matrix must have local communicator");
4461e228b242SToby Isaac   }
446279769bd5SJed Brown   if (bias) {
446379769bd5SJed Brown     PetscValidHeaderSpecific(bias, VEC_CLASSID, 4);
44649566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)bias), &result));
446579769bd5SJed Brown     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint bias must have local communicator");
446679769bd5SJed Brown   }
44679566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
44689566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->defaultConstraint.section));
44693b8ba7d1SJed Brown   dm->defaultConstraint.section = section;
44709566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)mat));
44719566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&dm->defaultConstraint.mat));
44723b8ba7d1SJed Brown   dm->defaultConstraint.mat = mat;
44739566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)bias));
44749566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&dm->defaultConstraint.bias));
447579769bd5SJed Brown   dm->defaultConstraint.bias = bias;
44763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44779435951eSToby Isaac }
44789435951eSToby Isaac 
4479497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
4480507e4973SMatthew G. Knepley /*
4481bb7acecfSBarry Smith   DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. Generates and error if they are not consistent.
4482507e4973SMatthew G. Knepley 
4483507e4973SMatthew G. Knepley   Input Parameters:
4484bb7acecfSBarry Smith + dm - The `DM`
4485bb7acecfSBarry Smith . localSection - `PetscSection` describing the local data layout
4486bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
4487507e4973SMatthew G. Knepley 
4488507e4973SMatthew G. Knepley   Level: intermediate
4489507e4973SMatthew G. Knepley 
44901cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMSetSectionSF()`
4491507e4973SMatthew G. Knepley */
4492d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
4493d71ae5a4SJacob Faibussowitsch {
4494507e4973SMatthew G. Knepley   MPI_Comm        comm;
4495507e4973SMatthew G. Knepley   PetscLayout     layout;
4496507e4973SMatthew G. Knepley   const PetscInt *ranges;
4497507e4973SMatthew G. Knepley   PetscInt        pStart, pEnd, p, nroots;
4498507e4973SMatthew G. Knepley   PetscMPIInt     size, rank;
4499507e4973SMatthew G. Knepley   PetscBool       valid = PETSC_TRUE, gvalid;
4500507e4973SMatthew G. Knepley 
4501507e4973SMatthew G. Knepley   PetscFunctionBegin;
45029566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4503507e4973SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45049566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
45059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
45069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(globalSection, &pStart, &pEnd));
45079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(globalSection, &nroots));
45089566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &layout));
45099566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
45109566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, nroots));
45119566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(layout));
45129566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRanges(layout, &ranges));
4513507e4973SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4514f741bcd2SMatthew G. Knepley     PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
4515507e4973SMatthew G. Knepley 
45169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(localSection, p, &dof));
45179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(localSection, p, &off));
45189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(localSection, p, &cdof));
45199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(globalSection, p, &gdof));
45209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(globalSection, p, &gcdof));
45219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &goff));
4522507e4973SMatthew G. Knepley     if (!gdof) continue; /* Censored point */
45239371c9d4SSatish Balay     if ((gdof < 0 ? -(gdof + 1) : gdof) != dof) {
45249371c9d4SSatish 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));
45259371c9d4SSatish Balay       valid = PETSC_FALSE;
45269371c9d4SSatish Balay     }
45279371c9d4SSatish Balay     if (gcdof && (gcdof != cdof)) {
45289371c9d4SSatish 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));
45299371c9d4SSatish Balay       valid = PETSC_FALSE;
45309371c9d4SSatish Balay     }
4531507e4973SMatthew G. Knepley     if (gdof < 0) {
4532507e4973SMatthew G. Knepley       gsize = gdof < 0 ? -(gdof + 1) - gcdof : gdof - gcdof;
4533507e4973SMatthew G. Knepley       for (d = 0; d < gsize; ++d) {
4534507e4973SMatthew G. Knepley         PetscInt offset = -(goff + 1) + d, r;
4535507e4973SMatthew G. Knepley 
45369566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(offset, size + 1, ranges, &r));
4537507e4973SMatthew G. Knepley         if (r < 0) r = -(r + 2);
45389371c9d4SSatish Balay         if ((r < 0) || (r >= size)) {
45399371c9d4SSatish Balay           PetscCall(PetscSynchronizedPrintf(comm, "[%d]Point %" PetscInt_FMT " mapped to invalid process %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, p, r, gdof, goff));
45409371c9d4SSatish Balay           valid = PETSC_FALSE;
45419371c9d4SSatish Balay           break;
45429371c9d4SSatish Balay         }
4543507e4973SMatthew G. Knepley       }
4544507e4973SMatthew G. Knepley     }
4545507e4973SMatthew G. Knepley   }
45469566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
45479566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
4548462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm));
4549507e4973SMatthew G. Knepley   if (!gvalid) {
45509566063dSJacob Faibussowitsch     PetscCall(DMView(dm, NULL));
4551507e4973SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
4552507e4973SMatthew G. Knepley   }
45533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4554507e4973SMatthew G. Knepley }
4555f741bcd2SMatthew G. Knepley #endif
4556507e4973SMatthew G. Knepley 
455790df3356SJames Wright PetscErrorCode DMGetIsoperiodicPointSF_Internal(DM dm, PetscSF *sf)
45586725e60dSJed Brown {
45596725e60dSJed Brown   PetscErrorCode (*f)(DM, PetscSF *);
45604d86920dSPierre Jolivet 
45616725e60dSJed Brown   PetscFunctionBegin;
45626725e60dSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45634f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
45645f06a3ddSJed Brown   PetscCall(PetscObjectQueryFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", &f));
45656725e60dSJed Brown   if (f) PetscCall(f(dm, sf));
45666725e60dSJed Brown   else *sf = dm->sf;
45673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45686725e60dSJed Brown }
45696725e60dSJed Brown 
457088ed4aceSMatthew G Knepley /*@
4571bb7acecfSBarry Smith   DMGetGlobalSection - Get the `PetscSection` encoding the global data layout for the `DM`.
457288ed4aceSMatthew G Knepley 
457320f4b53cSBarry Smith   Collective
45748b1ab98fSJed Brown 
457588ed4aceSMatthew G Knepley   Input Parameter:
4576bb7acecfSBarry Smith . dm - The `DM`
457788ed4aceSMatthew G Knepley 
457888ed4aceSMatthew G Knepley   Output Parameter:
4579bb7acecfSBarry Smith . section - The `PetscSection`
458088ed4aceSMatthew G Knepley 
458188ed4aceSMatthew G Knepley   Level: intermediate
458288ed4aceSMatthew G Knepley 
4583bb7acecfSBarry Smith   Note:
4584bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
458588ed4aceSMatthew G Knepley 
45861cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetLocalSection()`
458788ed4aceSMatthew G Knepley @*/
4588d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section)
4589d71ae5a4SJacob Faibussowitsch {
459088ed4aceSMatthew G Knepley   PetscFunctionBegin;
459188ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45924f572ea9SToby Isaac   PetscAssertPointer(section, 2);
45931bb6d2a8SBarry Smith   if (!dm->globalSection) {
4594fd59a867SMatthew G. Knepley     PetscSection s;
45956725e60dSJed Brown     PetscSF      sf;
4596fd59a867SMatthew G. Knepley 
45979566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &s));
45987a8be351SBarry Smith     PetscCheck(s, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
45997a8be351SBarry Smith     PetscCheck(dm->sf, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection");
46005f06a3ddSJed Brown     PetscCall(DMGetIsoperiodicPointSF_Internal(dm, &sf));
4601eb9d3e4dSMatthew G. Knepley     PetscCall(PetscSectionCreateGlobalSection(s, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &dm->globalSection));
46029566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&dm->map));
46039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map));
46049566063dSJacob Faibussowitsch     PetscCall(PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view"));
460588ed4aceSMatthew G Knepley   }
46061bb6d2a8SBarry Smith   *section = dm->globalSection;
46073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
460888ed4aceSMatthew G Knepley }
460988ed4aceSMatthew G Knepley 
4610b21d0597SMatthew G Knepley /*@
4611bb7acecfSBarry Smith   DMSetGlobalSection - Set the `PetscSection` encoding the global data layout for the `DM`.
4612b21d0597SMatthew G Knepley 
4613b21d0597SMatthew G Knepley   Input Parameters:
4614bb7acecfSBarry Smith + dm      - The `DM`
46152fe279fdSBarry Smith - section - The PetscSection, or `NULL`
4616b21d0597SMatthew G Knepley 
4617b21d0597SMatthew G Knepley   Level: intermediate
4618b21d0597SMatthew G Knepley 
4619bb7acecfSBarry Smith   Note:
4620bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4621b21d0597SMatthew G Knepley 
46221cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetGlobalSection()`, `DMSetLocalSection()`
4623b21d0597SMatthew G Knepley @*/
4624d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section)
4625d71ae5a4SJacob Faibussowitsch {
4626b21d0597SMatthew G Knepley   PetscFunctionBegin;
4627b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46285080bbdbSMatthew G Knepley   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
46299566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
46309566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
46311bb6d2a8SBarry Smith   dm->globalSection = section;
4632497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
46339566063dSJacob Faibussowitsch   if (section) PetscCall(DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section));
4634507e4973SMatthew G. Knepley #endif
463550350c8eSStefano Zampini   /* Clear global scratch vectors and sectionSF */
463650350c8eSStefano Zampini   PetscCall(PetscSFDestroy(&dm->sectionSF));
463752947b74SStefano Zampini   PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &dm->sectionSF));
463850350c8eSStefano Zampini   PetscCall(DMClearGlobalVectors(dm));
463950350c8eSStefano Zampini   PetscCall(DMClearNamedGlobalVectors(dm));
46403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4641b21d0597SMatthew G Knepley }
4642b21d0597SMatthew G Knepley 
464388ed4aceSMatthew G Knepley /*@
4644bb7acecfSBarry Smith   DMGetSectionSF - Get the `PetscSF` encoding the parallel dof overlap for the `DM`. If it has not been set,
4645bb7acecfSBarry Smith   it is created from the default `PetscSection` layouts in the `DM`.
464688ed4aceSMatthew G Knepley 
464788ed4aceSMatthew G Knepley   Input Parameter:
4648bb7acecfSBarry Smith . dm - The `DM`
464988ed4aceSMatthew G Knepley 
465088ed4aceSMatthew G Knepley   Output Parameter:
4651bb7acecfSBarry Smith . sf - The `PetscSF`
465288ed4aceSMatthew G Knepley 
465388ed4aceSMatthew G Knepley   Level: intermediate
465488ed4aceSMatthew G Knepley 
4655bb7acecfSBarry Smith   Note:
4656bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
465788ed4aceSMatthew G Knepley 
46581cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetSectionSF()`, `DMCreateSectionSF()`
465988ed4aceSMatthew G Knepley @*/
4660d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf)
4661d71ae5a4SJacob Faibussowitsch {
466288ed4aceSMatthew G Knepley   PetscInt nroots;
466388ed4aceSMatthew G Knepley 
466488ed4aceSMatthew G Knepley   PetscFunctionBegin;
466588ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46664f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
466748a46eb9SPierre Jolivet   if (!dm->sectionSF) PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &dm->sectionSF));
46689566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL));
466988ed4aceSMatthew G Knepley   if (nroots < 0) {
467088ed4aceSMatthew G Knepley     PetscSection section, gSection;
467188ed4aceSMatthew G Knepley 
46729566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
467331ea6d37SMatthew G Knepley     if (section) {
46749566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gSection));
46759566063dSJacob Faibussowitsch       PetscCall(DMCreateSectionSF(dm, section, gSection));
467631ea6d37SMatthew G Knepley     } else {
46770298fd71SBarry Smith       *sf = NULL;
46783ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
467931ea6d37SMatthew G Knepley     }
468088ed4aceSMatthew G Knepley   }
46811bb6d2a8SBarry Smith   *sf = dm->sectionSF;
46823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
468388ed4aceSMatthew G Knepley }
468488ed4aceSMatthew G Knepley 
468588ed4aceSMatthew G Knepley /*@
4686bb7acecfSBarry Smith   DMSetSectionSF - Set the `PetscSF` encoding the parallel dof overlap for the `DM`
468788ed4aceSMatthew G Knepley 
468888ed4aceSMatthew G Knepley   Input Parameters:
4689bb7acecfSBarry Smith + dm - The `DM`
4690bb7acecfSBarry Smith - sf - The `PetscSF`
469188ed4aceSMatthew G Knepley 
469288ed4aceSMatthew G Knepley   Level: intermediate
469388ed4aceSMatthew G Knepley 
4694bb7acecfSBarry Smith   Note:
4695bb7acecfSBarry Smith   Any previous `PetscSF` is destroyed
469688ed4aceSMatthew G Knepley 
46971cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMCreateSectionSF()`
469888ed4aceSMatthew G Knepley @*/
4699d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf)
4700d71ae5a4SJacob Faibussowitsch {
470188ed4aceSMatthew G Knepley   PetscFunctionBegin;
470288ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4703b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47049566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47059566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sectionSF));
47061bb6d2a8SBarry Smith   dm->sectionSF = sf;
47073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
470888ed4aceSMatthew G Knepley }
470988ed4aceSMatthew G Knepley 
4710cc4c1da9SBarry Smith /*@
4711bb7acecfSBarry Smith   DMCreateSectionSF - Create the `PetscSF` encoding the parallel dof overlap for the `DM` based upon the `PetscSection`s
471288ed4aceSMatthew G Knepley   describing the data layout.
471388ed4aceSMatthew G Knepley 
471488ed4aceSMatthew G Knepley   Input Parameters:
4715bb7acecfSBarry Smith + dm            - The `DM`
4716bb7acecfSBarry Smith . localSection  - `PetscSection` describing the local data layout
4717bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
471888ed4aceSMatthew G Knepley 
47191bb6d2a8SBarry Smith   Level: developer
47201bb6d2a8SBarry Smith 
4721bb7acecfSBarry Smith   Note:
4722bb7acecfSBarry Smith   One usually uses `DMGetSectionSF()` to obtain the `PetscSF`
4723bb7acecfSBarry Smith 
472473ff1848SBarry Smith   Developer Note:
4725bb7acecfSBarry Smith   Since this routine has for arguments the two sections from the `DM` and puts the resulting `PetscSF`
4726bb7acecfSBarry Smith   directly into the `DM`, perhaps this function should not take the local and global sections as
4727b6971eaeSBarry Smith   input and should just obtain them from the `DM`? Plus PETSc creation functions return the thing
4728b6971eaeSBarry Smith   they create, this returns nothing
47291bb6d2a8SBarry Smith 
47301cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
473188ed4aceSMatthew G Knepley @*/
4732d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection)
4733d71ae5a4SJacob Faibussowitsch {
473488ed4aceSMatthew G Knepley   PetscFunctionBegin;
473588ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47369566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphSection(dm->sectionSF, localSection, globalSection));
47373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
473888ed4aceSMatthew G Knepley }
4739af122d2aSMatthew G Knepley 
4740b21d0597SMatthew G Knepley /*@
4741bb7acecfSBarry Smith   DMGetPointSF - Get the `PetscSF` encoding the parallel section point overlap for the `DM`.
4742bb7acecfSBarry Smith 
4743bb7acecfSBarry Smith   Not collective but the resulting `PetscSF` is collective
4744b21d0597SMatthew G Knepley 
4745b21d0597SMatthew G Knepley   Input Parameter:
4746bb7acecfSBarry Smith . dm - The `DM`
4747b21d0597SMatthew G Knepley 
4748b21d0597SMatthew G Knepley   Output Parameter:
4749bb7acecfSBarry Smith . sf - The `PetscSF`
4750b21d0597SMatthew G Knepley 
4751b21d0597SMatthew G Knepley   Level: intermediate
4752b21d0597SMatthew G Knepley 
4753bb7acecfSBarry Smith   Note:
4754bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
4755b21d0597SMatthew G Knepley 
47561cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4757b21d0597SMatthew G Knepley @*/
4758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
4759d71ae5a4SJacob Faibussowitsch {
4760b21d0597SMatthew G Knepley   PetscFunctionBegin;
4761b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47624f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
4763b21d0597SMatthew G Knepley   *sf = dm->sf;
47643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4765b21d0597SMatthew G Knepley }
4766b21d0597SMatthew G Knepley 
4767057b4bcdSMatthew G Knepley /*@
4768bb7acecfSBarry Smith   DMSetPointSF - Set the `PetscSF` encoding the parallel section point overlap for the `DM`.
4769bb7acecfSBarry Smith 
477020f4b53cSBarry Smith   Collective
4771057b4bcdSMatthew G Knepley 
4772057b4bcdSMatthew G Knepley   Input Parameters:
4773bb7acecfSBarry Smith + dm - The `DM`
4774bb7acecfSBarry Smith - sf - The `PetscSF`
4775057b4bcdSMatthew G Knepley 
4776057b4bcdSMatthew G Knepley   Level: intermediate
4777057b4bcdSMatthew G Knepley 
47781cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4779057b4bcdSMatthew G Knepley @*/
4780d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
4781d71ae5a4SJacob Faibussowitsch {
4782057b4bcdSMatthew G Knepley   PetscFunctionBegin;
4783057b4bcdSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4784b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47859566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47869566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sf));
4787057b4bcdSMatthew G Knepley   dm->sf = sf;
47883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4789057b4bcdSMatthew G Knepley }
4790057b4bcdSMatthew G Knepley 
47914f37162bSMatthew G. Knepley /*@
4792bb7acecfSBarry Smith   DMGetNaturalSF - Get the `PetscSF` encoding the map back to the original mesh ordering
47934f37162bSMatthew G. Knepley 
47944f37162bSMatthew G. Knepley   Input Parameter:
4795bb7acecfSBarry Smith . dm - The `DM`
47964f37162bSMatthew G. Knepley 
47974f37162bSMatthew G. Knepley   Output Parameter:
4798bb7acecfSBarry Smith . sf - The `PetscSF`
47994f37162bSMatthew G. Knepley 
48004f37162bSMatthew G. Knepley   Level: intermediate
48014f37162bSMatthew G. Knepley 
4802bb7acecfSBarry Smith   Note:
4803bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
48044f37162bSMatthew G. Knepley 
48051cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
48064f37162bSMatthew G. Knepley @*/
4807d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNaturalSF(DM dm, PetscSF *sf)
4808d71ae5a4SJacob Faibussowitsch {
48094f37162bSMatthew G. Knepley   PetscFunctionBegin;
48104f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48114f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
48124f37162bSMatthew G. Knepley   *sf = dm->sfNatural;
48133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48144f37162bSMatthew G. Knepley }
48154f37162bSMatthew G. Knepley 
48164f37162bSMatthew G. Knepley /*@
48174f37162bSMatthew G. Knepley   DMSetNaturalSF - Set the PetscSF encoding the map back to the original mesh ordering
48184f37162bSMatthew G. Knepley 
48194f37162bSMatthew G. Knepley   Input Parameters:
48204f37162bSMatthew G. Knepley + dm - The DM
48214f37162bSMatthew G. Knepley - sf - The PetscSF
48224f37162bSMatthew G. Knepley 
48234f37162bSMatthew G. Knepley   Level: intermediate
48244f37162bSMatthew G. Knepley 
48251cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
48264f37162bSMatthew G. Knepley @*/
4827d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNaturalSF(DM dm, PetscSF sf)
4828d71ae5a4SJacob Faibussowitsch {
48294f37162bSMatthew G. Knepley   PetscFunctionBegin;
48304f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48314f37162bSMatthew G. Knepley   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
48329566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
48339566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sfNatural));
48344f37162bSMatthew G. Knepley   dm->sfNatural = sf;
48353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48364f37162bSMatthew G. Knepley }
48374f37162bSMatthew G. Knepley 
4838d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc)
4839d71ae5a4SJacob Faibussowitsch {
484034aa8a36SMatthew G. Knepley   PetscClassId id;
484134aa8a36SMatthew G. Knepley 
484234aa8a36SMatthew G. Knepley   PetscFunctionBegin;
48439566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId(disc, &id));
484434aa8a36SMatthew G. Knepley   if (id == PETSCFE_CLASSID) {
48459566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
484634aa8a36SMatthew G. Knepley   } else if (id == PETSCFV_CLASSID) {
48479566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE));
484817c1d62eSMatthew G. Knepley   } else {
48499566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
485034aa8a36SMatthew G. Knepley   }
48513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
485234aa8a36SMatthew G. Knepley }
485334aa8a36SMatthew G. Knepley 
4854d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew)
4855d71ae5a4SJacob Faibussowitsch {
485644a7f3ddSMatthew G. Knepley   RegionField *tmpr;
485744a7f3ddSMatthew G. Knepley   PetscInt     Nf = dm->Nf, f;
485844a7f3ddSMatthew G. Knepley 
485944a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
48603ba16761SJacob Faibussowitsch   if (Nf >= NfNew) PetscFunctionReturn(PETSC_SUCCESS);
48619566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NfNew, &tmpr));
486244a7f3ddSMatthew G. Knepley   for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f];
48639371c9d4SSatish Balay   for (f = Nf; f < NfNew; ++f) {
48649371c9d4SSatish Balay     tmpr[f].disc        = NULL;
48659371c9d4SSatish Balay     tmpr[f].label       = NULL;
48669371c9d4SSatish Balay     tmpr[f].avoidTensor = PETSC_FALSE;
48679371c9d4SSatish Balay   }
48689566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
486944a7f3ddSMatthew G. Knepley   dm->Nf     = NfNew;
487044a7f3ddSMatthew G. Knepley   dm->fields = tmpr;
48713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
487244a7f3ddSMatthew G. Knepley }
487344a7f3ddSMatthew G. Knepley 
487444a7f3ddSMatthew G. Knepley /*@
487520f4b53cSBarry Smith   DMClearFields - Remove all fields from the `DM`
487644a7f3ddSMatthew G. Knepley 
487720f4b53cSBarry Smith   Logically Collective
487844a7f3ddSMatthew G. Knepley 
487944a7f3ddSMatthew G. Knepley   Input Parameter:
488020f4b53cSBarry Smith . dm - The `DM`
488144a7f3ddSMatthew G. Knepley 
488244a7f3ddSMatthew G. Knepley   Level: intermediate
488344a7f3ddSMatthew G. Knepley 
48841cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumFields()`, `DMSetNumFields()`, `DMSetField()`
488544a7f3ddSMatthew G. Knepley @*/
4886d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearFields(DM dm)
4887d71ae5a4SJacob Faibussowitsch {
488844a7f3ddSMatthew G. Knepley   PetscInt f;
488944a7f3ddSMatthew G. Knepley 
489044a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
489144a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
489244a7f3ddSMatthew G. Knepley   for (f = 0; f < dm->Nf; ++f) {
48939566063dSJacob Faibussowitsch     PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
48949566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->fields[f].label));
489544a7f3ddSMatthew G. Knepley   }
48969566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
489744a7f3ddSMatthew G. Knepley   dm->fields = NULL;
489844a7f3ddSMatthew G. Knepley   dm->Nf     = 0;
48993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
490044a7f3ddSMatthew G. Knepley }
490144a7f3ddSMatthew G. Knepley 
4902689b5837SMatthew G. Knepley /*@
490320f4b53cSBarry Smith   DMGetNumFields - Get the number of fields in the `DM`
4904689b5837SMatthew G. Knepley 
490520f4b53cSBarry Smith   Not Collective
4906689b5837SMatthew G. Knepley 
4907689b5837SMatthew G. Knepley   Input Parameter:
490820f4b53cSBarry Smith . dm - The `DM`
4909689b5837SMatthew G. Knepley 
4910689b5837SMatthew G. Knepley   Output Parameter:
491160225df5SJacob Faibussowitsch . numFields - The number of fields
4912689b5837SMatthew G. Knepley 
4913689b5837SMatthew G. Knepley   Level: intermediate
4914689b5837SMatthew G. Knepley 
49151cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetNumFields()`, `DMSetField()`
4916689b5837SMatthew G. Knepley @*/
4917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4918d71ae5a4SJacob Faibussowitsch {
49190f21e855SMatthew G. Knepley   PetscFunctionBegin;
49200f21e855SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49214f572ea9SToby Isaac   PetscAssertPointer(numFields, 2);
492244a7f3ddSMatthew G. Knepley   *numFields = dm->Nf;
49233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4924af122d2aSMatthew G Knepley }
4925af122d2aSMatthew G Knepley 
4926689b5837SMatthew G. Knepley /*@
492720f4b53cSBarry Smith   DMSetNumFields - Set the number of fields in the `DM`
4928689b5837SMatthew G. Knepley 
492920f4b53cSBarry Smith   Logically Collective
4930689b5837SMatthew G. Knepley 
4931689b5837SMatthew G. Knepley   Input Parameters:
493220f4b53cSBarry Smith + dm        - The `DM`
493360225df5SJacob Faibussowitsch - numFields - The number of fields
4934689b5837SMatthew G. Knepley 
4935689b5837SMatthew G. Knepley   Level: intermediate
4936689b5837SMatthew G. Knepley 
49371cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumFields()`, `DMSetField()`
4938689b5837SMatthew G. Knepley @*/
4939d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4940d71ae5a4SJacob Faibussowitsch {
49410f21e855SMatthew G. Knepley   PetscInt Nf, f;
4942af122d2aSMatthew G Knepley 
4943af122d2aSMatthew G Knepley   PetscFunctionBegin;
4944af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49459566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
49460f21e855SMatthew G. Knepley   for (f = Nf; f < numFields; ++f) {
49470f21e855SMatthew G. Knepley     PetscContainer obj;
49480f21e855SMatthew G. Knepley 
49499566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)dm), &obj));
49509566063dSJacob Faibussowitsch     PetscCall(DMAddField(dm, NULL, (PetscObject)obj));
49519566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&obj));
4952af122d2aSMatthew G Knepley   }
49533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4954af122d2aSMatthew G Knepley }
4955af122d2aSMatthew G Knepley 
4956c1929be8SMatthew G. Knepley /*@
4957bb7acecfSBarry Smith   DMGetField - Return the `DMLabel` and discretization object for a given `DM` field
4958c1929be8SMatthew G. Knepley 
495920f4b53cSBarry Smith   Not Collective
4960c1929be8SMatthew G. Knepley 
4961c1929be8SMatthew G. Knepley   Input Parameters:
4962bb7acecfSBarry Smith + dm - The `DM`
4963c1929be8SMatthew G. Knepley - f  - The field number
4964c1929be8SMatthew G. Knepley 
496544a7f3ddSMatthew G. Knepley   Output Parameters:
496620f4b53cSBarry Smith + label - The label indicating the support of the field, or `NULL` for the entire mesh (pass in `NULL` if not needed)
496720f4b53cSBarry Smith - disc  - The discretization object (pass in `NULL` if not needed)
4968c1929be8SMatthew G. Knepley 
496944a7f3ddSMatthew G. Knepley   Level: intermediate
4970c1929be8SMatthew G. Knepley 
49711cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMSetField()`
4972c1929be8SMatthew G. Knepley @*/
4973d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *disc)
4974d71ae5a4SJacob Faibussowitsch {
4975af122d2aSMatthew G Knepley   PetscFunctionBegin;
4976af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49774f572ea9SToby Isaac   PetscAssertPointer(disc, 4);
49787a8be351SBarry 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);
497944a7f3ddSMatthew G. Knepley   if (label) *label = dm->fields[f].label;
4980bb7acecfSBarry Smith   if (disc) *disc = dm->fields[f].disc;
49813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4982decb47aaSMatthew G. Knepley }
4983decb47aaSMatthew G. Knepley 
4984083401c6SMatthew G. Knepley /* Does not clear the DS */
4985d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField_Internal(DM dm, PetscInt f, DMLabel label, PetscObject disc)
4986d71ae5a4SJacob Faibussowitsch {
4987083401c6SMatthew G. Knepley   PetscFunctionBegin;
49889566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, f + 1));
49899566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->fields[f].label));
49909566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
4991083401c6SMatthew G. Knepley   dm->fields[f].label = label;
4992bb7acecfSBarry Smith   dm->fields[f].disc  = disc;
49939566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
4994835f2295SStefano Zampini   PetscCall(PetscObjectReference(disc));
49953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4996083401c6SMatthew G. Knepley }
4997083401c6SMatthew G. Knepley 
4998ffeef943SBarry Smith /*@
4999bb7acecfSBarry Smith   DMSetField - Set the discretization object for a given `DM` field. Usually one would call `DMAddField()` which automatically handles
5000bb7acecfSBarry Smith   the field numbering.
5001c1929be8SMatthew G. Knepley 
500220f4b53cSBarry Smith   Logically Collective
5003c1929be8SMatthew G. Knepley 
5004c1929be8SMatthew G. Knepley   Input Parameters:
5005bb7acecfSBarry Smith + dm    - The `DM`
5006c1929be8SMatthew G. Knepley . f     - The field number
500720f4b53cSBarry Smith . label - The label indicating the support of the field, or `NULL` for the entire mesh
5008bb7acecfSBarry Smith - disc  - The discretization object
5009c1929be8SMatthew G. Knepley 
501044a7f3ddSMatthew G. Knepley   Level: intermediate
5011c1929be8SMatthew G. Knepley 
50121cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`
5013c1929be8SMatthew G. Knepley @*/
5014d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject disc)
5015d71ae5a4SJacob Faibussowitsch {
5016decb47aaSMatthew G. Knepley   PetscFunctionBegin;
5017decb47aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5018e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
5019bb7acecfSBarry Smith   PetscValidHeader(disc, 4);
50207a8be351SBarry Smith   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
5021bb7acecfSBarry Smith   PetscCall(DMSetField_Internal(dm, f, label, disc));
5022bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, f, disc));
50239566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
50243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
502544a7f3ddSMatthew G. Knepley }
502644a7f3ddSMatthew G. Knepley 
5027ffeef943SBarry Smith /*@
5028bb7acecfSBarry 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)
5029bb7acecfSBarry Smith   and a discretization object that defines the function space associated with those points.
503044a7f3ddSMatthew G. Knepley 
503120f4b53cSBarry Smith   Logically Collective
503244a7f3ddSMatthew G. Knepley 
503344a7f3ddSMatthew G. Knepley   Input Parameters:
5034bb7acecfSBarry Smith + dm    - The `DM`
503520f4b53cSBarry Smith . label - The label indicating the support of the field, or `NULL` for the entire mesh
5036bb7acecfSBarry Smith - disc  - The discretization object
503744a7f3ddSMatthew G. Knepley 
503844a7f3ddSMatthew G. Knepley   Level: intermediate
503944a7f3ddSMatthew G. Knepley 
5040bb7acecfSBarry Smith   Notes:
5041bb7acecfSBarry Smith   The label already exists or will be added to the `DM` with `DMSetLabel()`.
5042bb7acecfSBarry Smith 
5043da81f932SPierre Jolivet   For example, a piecewise continuous pressure field can be defined by coefficients at the cell centers of a mesh and piecewise constant functions
5044bb7acecfSBarry 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
5045bb7acecfSBarry Smith   geometry entities, a `DMLabel` indicating a subset of those geometric entities, and a discretization object, such as a `PetscFE`.
5046bb7acecfSBarry Smith 
50471cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLabel()`, `DMSetField()`, `DMGetField()`, `PetscFE`
504844a7f3ddSMatthew G. Knepley @*/
5049d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject disc)
5050d71ae5a4SJacob Faibussowitsch {
505144a7f3ddSMatthew G. Knepley   PetscInt Nf = dm->Nf;
505244a7f3ddSMatthew G. Knepley 
505344a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
505444a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5055064a246eSJacob Faibussowitsch   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
5056bb7acecfSBarry Smith   PetscValidHeader(disc, 3);
50579566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, Nf + 1));
505844a7f3ddSMatthew G. Knepley   dm->fields[Nf].label = label;
5059bb7acecfSBarry Smith   dm->fields[Nf].disc  = disc;
50609566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
5061835f2295SStefano Zampini   PetscCall(PetscObjectReference(disc));
5062bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, Nf, disc));
50639566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
50643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5065af122d2aSMatthew G Knepley }
50666636e97aSMatthew G Knepley 
5067e5e52638SMatthew G. Knepley /*@
5068e0b68406SMatthew Knepley   DMSetFieldAvoidTensor - Set flag to avoid defining the field on tensor cells
5069e0b68406SMatthew Knepley 
507020f4b53cSBarry Smith   Logically Collective
5071e0b68406SMatthew Knepley 
5072e0b68406SMatthew Knepley   Input Parameters:
5073bb7acecfSBarry Smith + dm          - The `DM`
5074e0b68406SMatthew Knepley . f           - The field index
5075bb7acecfSBarry Smith - avoidTensor - `PETSC_TRUE` to skip defining the field on tensor cells
5076e0b68406SMatthew Knepley 
5077e0b68406SMatthew Knepley   Level: intermediate
5078e0b68406SMatthew Knepley 
50791cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetFieldAvoidTensor()`, `DMSetField()`, `DMGetField()`
5080e0b68406SMatthew Knepley @*/
5081d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFieldAvoidTensor(DM dm, PetscInt f, PetscBool avoidTensor)
5082d71ae5a4SJacob Faibussowitsch {
5083e0b68406SMatthew Knepley   PetscFunctionBegin;
508463a3b9bcSJacob 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);
5085e0b68406SMatthew Knepley   dm->fields[f].avoidTensor = avoidTensor;
50863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5087e0b68406SMatthew Knepley }
5088e0b68406SMatthew Knepley 
5089e0b68406SMatthew Knepley /*@
5090e0b68406SMatthew Knepley   DMGetFieldAvoidTensor - Get flag to avoid defining the field on tensor cells
5091e0b68406SMatthew Knepley 
509220f4b53cSBarry Smith   Not Collective
5093e0b68406SMatthew Knepley 
5094e0b68406SMatthew Knepley   Input Parameters:
5095bb7acecfSBarry Smith + dm - The `DM`
5096e0b68406SMatthew Knepley - f  - The field index
5097e0b68406SMatthew Knepley 
5098e0b68406SMatthew Knepley   Output Parameter:
5099e0b68406SMatthew Knepley . avoidTensor - The flag to avoid defining the field on tensor cells
5100e0b68406SMatthew Knepley 
5101e0b68406SMatthew Knepley   Level: intermediate
5102e0b68406SMatthew Knepley 
510360225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMSetField()`, `DMGetField()`, `DMSetFieldAvoidTensor()`
5104e0b68406SMatthew Knepley @*/
5105d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFieldAvoidTensor(DM dm, PetscInt f, PetscBool *avoidTensor)
5106d71ae5a4SJacob Faibussowitsch {
5107e0b68406SMatthew Knepley   PetscFunctionBegin;
510863a3b9bcSJacob 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);
5109e0b68406SMatthew Knepley   *avoidTensor = dm->fields[f].avoidTensor;
51103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5111e0b68406SMatthew Knepley }
5112e0b68406SMatthew Knepley 
5113e0b68406SMatthew Knepley /*@
5114bb7acecfSBarry Smith   DMCopyFields - Copy the discretizations for the `DM` into another `DM`
5115e5e52638SMatthew G. Knepley 
511620f4b53cSBarry Smith   Collective
5117e5e52638SMatthew G. Knepley 
5118bb4b53efSMatthew G. Knepley   Input Parameters:
5119bb4b53efSMatthew G. Knepley + dm        - The `DM`
5120bb4b53efSMatthew G. Knepley . minDegree - Minimum degree for a discretization, or `PETSC_DETERMINE` for no limit
5121bb4b53efSMatthew G. Knepley - maxDegree - Maximum degree for a discretization, or `PETSC_DETERMINE` for no limit
5122e5e52638SMatthew G. Knepley 
5123e5e52638SMatthew G. Knepley   Output Parameter:
5124bb7acecfSBarry Smith . newdm - The `DM`
5125e5e52638SMatthew G. Knepley 
5126e5e52638SMatthew G. Knepley   Level: advanced
5127e5e52638SMatthew G. Knepley 
51281cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetField()`, `DMSetField()`, `DMAddField()`, `DMCopyDS()`, `DMGetDS()`, `DMGetCellDS()`
5129e5e52638SMatthew G. Knepley @*/
5130bb4b53efSMatthew G. Knepley PetscErrorCode DMCopyFields(DM dm, PetscInt minDegree, PetscInt maxDegree, DM newdm)
5131d71ae5a4SJacob Faibussowitsch {
5132e5e52638SMatthew G. Knepley   PetscInt Nf, f;
5133e5e52638SMatthew G. Knepley 
5134e5e52638SMatthew G. Knepley   PetscFunctionBegin;
51353ba16761SJacob Faibussowitsch   if (dm == newdm) PetscFunctionReturn(PETSC_SUCCESS);
51369566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
51379566063dSJacob Faibussowitsch   PetscCall(DMClearFields(newdm));
5138e5e52638SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5139e5e52638SMatthew G. Knepley     DMLabel      label;
5140e5e52638SMatthew G. Knepley     PetscObject  field;
5141bb4b53efSMatthew G. Knepley     PetscClassId id;
514234aa8a36SMatthew G. Knepley     PetscBool    useCone, useClosure;
5143e5e52638SMatthew G. Knepley 
51449566063dSJacob Faibussowitsch     PetscCall(DMGetField(dm, f, &label, &field));
5145bb4b53efSMatthew G. Knepley     PetscCall(PetscObjectGetClassId(field, &id));
5146bb4b53efSMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
5147bb4b53efSMatthew G. Knepley       PetscFE newfe;
5148bb4b53efSMatthew G. Knepley 
5149bb4b53efSMatthew G. Knepley       PetscCall(PetscFELimitDegree((PetscFE)field, minDegree, maxDegree, &newfe));
5150bb4b53efSMatthew G. Knepley       PetscCall(DMSetField(newdm, f, label, (PetscObject)newfe));
5151bb4b53efSMatthew G. Knepley       PetscCall(PetscFEDestroy(&newfe));
5152bb4b53efSMatthew G. Knepley     } else {
51539566063dSJacob Faibussowitsch       PetscCall(DMSetField(newdm, f, label, field));
5154bb4b53efSMatthew G. Knepley     }
51559566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, f, &useCone, &useClosure));
51569566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(newdm, f, useCone, useClosure));
515734aa8a36SMatthew G. Knepley   }
51583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
515934aa8a36SMatthew G. Knepley }
516034aa8a36SMatthew G. Knepley 
516134aa8a36SMatthew G. Knepley /*@
516234aa8a36SMatthew G. Knepley   DMGetAdjacency - Returns the flags for determining variable influence
516334aa8a36SMatthew G. Knepley 
516420f4b53cSBarry Smith   Not Collective
516534aa8a36SMatthew G. Knepley 
516634aa8a36SMatthew G. Knepley   Input Parameters:
516720f4b53cSBarry Smith + dm - The `DM` object
516820f4b53cSBarry Smith - f  - The field number, or `PETSC_DEFAULT` for the default adjacency
516934aa8a36SMatthew G. Knepley 
5170d8d19677SJose E. Roman   Output Parameters:
517134aa8a36SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
517234aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
517334aa8a36SMatthew G. Knepley 
517434aa8a36SMatthew G. Knepley   Level: developer
517534aa8a36SMatthew G. Knepley 
517620f4b53cSBarry Smith   Notes:
517720f4b53cSBarry Smith .vb
517820f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
517920f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
518020f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
518120f4b53cSBarry Smith .ve
518220f4b53cSBarry Smith   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
518320f4b53cSBarry Smith 
51841cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetAdjacency()`, `DMGetField()`, `DMSetField()`
518534aa8a36SMatthew G. Knepley @*/
5186d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure)
5187d71ae5a4SJacob Faibussowitsch {
518834aa8a36SMatthew G. Knepley   PetscFunctionBegin;
518934aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51904f572ea9SToby Isaac   if (useCone) PetscAssertPointer(useCone, 3);
51914f572ea9SToby Isaac   if (useClosure) PetscAssertPointer(useClosure, 4);
519234aa8a36SMatthew G. Knepley   if (f < 0) {
519334aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->adjacency[0];
519434aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->adjacency[1];
519534aa8a36SMatthew G. Knepley   } else {
519634aa8a36SMatthew G. Knepley     PetscInt Nf;
519734aa8a36SMatthew G. Knepley 
51989566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
51997a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
520034aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->fields[f].adjacency[0];
520134aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->fields[f].adjacency[1];
520234aa8a36SMatthew G. Knepley   }
52033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
520434aa8a36SMatthew G. Knepley }
520534aa8a36SMatthew G. Knepley 
520634aa8a36SMatthew G. Knepley /*@
520734aa8a36SMatthew G. Knepley   DMSetAdjacency - Set the flags for determining variable influence
520834aa8a36SMatthew G. Knepley 
520920f4b53cSBarry Smith   Not Collective
521034aa8a36SMatthew G. Knepley 
521134aa8a36SMatthew G. Knepley   Input Parameters:
521220f4b53cSBarry Smith + dm         - The `DM` object
521334aa8a36SMatthew G. Knepley . f          - The field number
521434aa8a36SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
521534aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
521634aa8a36SMatthew G. Knepley 
521734aa8a36SMatthew G. Knepley   Level: developer
521834aa8a36SMatthew G. Knepley 
521920f4b53cSBarry Smith   Notes:
522020f4b53cSBarry Smith .vb
522120f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
522220f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
522320f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
522420f4b53cSBarry Smith .ve
522520f4b53cSBarry Smith   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
522620f4b53cSBarry Smith 
52271cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetAdjacency()`, `DMGetField()`, `DMSetField()`
522834aa8a36SMatthew G. Knepley @*/
5229d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure)
5230d71ae5a4SJacob Faibussowitsch {
523134aa8a36SMatthew G. Knepley   PetscFunctionBegin;
523234aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
523334aa8a36SMatthew G. Knepley   if (f < 0) {
523434aa8a36SMatthew G. Knepley     dm->adjacency[0] = useCone;
523534aa8a36SMatthew G. Knepley     dm->adjacency[1] = useClosure;
523634aa8a36SMatthew G. Knepley   } else {
523734aa8a36SMatthew G. Knepley     PetscInt Nf;
523834aa8a36SMatthew G. Knepley 
52399566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
52407a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
524134aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[0] = useCone;
524234aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[1] = useClosure;
5243e5e52638SMatthew G. Knepley   }
52443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5245e5e52638SMatthew G. Knepley }
5246e5e52638SMatthew G. Knepley 
5247b0441da4SMatthew G. Knepley /*@
5248b0441da4SMatthew G. Knepley   DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined
5249b0441da4SMatthew G. Knepley 
5250b0441da4SMatthew G. Knepley   Not collective
5251b0441da4SMatthew G. Knepley 
5252f899ff85SJose E. Roman   Input Parameter:
525320f4b53cSBarry Smith . dm - The `DM` object
5254b0441da4SMatthew G. Knepley 
5255d8d19677SJose E. Roman   Output Parameters:
5256b0441da4SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
5257b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5258b0441da4SMatthew G. Knepley 
5259b0441da4SMatthew G. Knepley   Level: developer
5260b0441da4SMatthew G. Knepley 
526120f4b53cSBarry Smith   Notes:
526220f4b53cSBarry Smith .vb
526320f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
526420f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
526520f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
526620f4b53cSBarry Smith .ve
526720f4b53cSBarry Smith 
52681cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5269b0441da4SMatthew G. Knepley @*/
5270d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure)
5271d71ae5a4SJacob Faibussowitsch {
5272b0441da4SMatthew G. Knepley   PetscInt Nf;
5273b0441da4SMatthew G. Knepley 
5274b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5275b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52764f572ea9SToby Isaac   if (useCone) PetscAssertPointer(useCone, 2);
52774f572ea9SToby Isaac   if (useClosure) PetscAssertPointer(useClosure, 3);
52789566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5279b0441da4SMatthew G. Knepley   if (!Nf) {
52809566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5281b0441da4SMatthew G. Knepley   } else {
52829566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, 0, useCone, useClosure));
5283b0441da4SMatthew G. Knepley   }
52843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5285b0441da4SMatthew G. Knepley }
5286b0441da4SMatthew G. Knepley 
5287b0441da4SMatthew G. Knepley /*@
5288b0441da4SMatthew G. Knepley   DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined
5289b0441da4SMatthew G. Knepley 
529020f4b53cSBarry Smith   Not Collective
5291b0441da4SMatthew G. Knepley 
5292b0441da4SMatthew G. Knepley   Input Parameters:
529320f4b53cSBarry Smith + dm         - The `DM` object
5294b0441da4SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
5295b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5296b0441da4SMatthew G. Knepley 
5297b0441da4SMatthew G. Knepley   Level: developer
5298b0441da4SMatthew G. Knepley 
529920f4b53cSBarry Smith   Notes:
530020f4b53cSBarry Smith .vb
530120f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
530220f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
530320f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
530420f4b53cSBarry Smith .ve
530520f4b53cSBarry Smith 
53061cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5307b0441da4SMatthew G. Knepley @*/
5308d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure)
5309d71ae5a4SJacob Faibussowitsch {
5310b0441da4SMatthew G. Knepley   PetscInt Nf;
5311b0441da4SMatthew G. Knepley 
5312b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5313b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53149566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5315b0441da4SMatthew G. Knepley   if (!Nf) {
53169566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5317b0441da4SMatthew G. Knepley   } else {
53189566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, 0, useCone, useClosure));
5319e5e52638SMatthew G. Knepley   }
53203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5321e5e52638SMatthew G. Knepley }
5322e5e52638SMatthew G. Knepley 
5323d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompleteBCLabels_Internal(DM dm)
5324d71ae5a4SJacob Faibussowitsch {
5325799db056SMatthew G. Knepley   DM           plex;
5326799db056SMatthew G. Knepley   DMLabel     *labels, *glabels;
5327799db056SMatthew G. Knepley   const char **names;
5328799db056SMatthew G. Knepley   char        *sendNames, *recvNames;
5329799db056SMatthew G. Knepley   PetscInt     Nds, s, maxLabels = 0, maxLen = 0, gmaxLen, Nl = 0, gNl, l, gl, m;
5330799db056SMatthew G. Knepley   size_t       len;
5331799db056SMatthew G. Knepley   MPI_Comm     comm;
5332799db056SMatthew G. Knepley   PetscMPIInt  rank, size, p, *counts, *displs;
5333783e2ec8SMatthew G. Knepley 
5334783e2ec8SMatthew G. Knepley   PetscFunctionBegin;
5335799db056SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5336799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
5337799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5338799db056SMatthew G. Knepley   PetscCall(DMGetNumDS(dm, &Nds));
5339799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5340799db056SMatthew G. Knepley     PetscDS  dsBC;
5341799db056SMatthew G. Knepley     PetscInt numBd;
5342799db056SMatthew G. Knepley 
534307218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC, NULL));
5344799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5345799db056SMatthew G. Knepley     maxLabels += numBd;
5346799db056SMatthew G. Knepley   }
5347799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(maxLabels, &labels));
5348799db056SMatthew G. Knepley   /* Get list of labels to be completed */
5349799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5350799db056SMatthew G. Knepley     PetscDS  dsBC;
5351799db056SMatthew G. Knepley     PetscInt numBd, bd;
5352799db056SMatthew G. Knepley 
535307218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC, NULL));
5354799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5355799db056SMatthew G. Knepley     for (bd = 0; bd < numBd; ++bd) {
5356799db056SMatthew G. Knepley       DMLabel      label;
5357799db056SMatthew G. Knepley       PetscInt     field;
5358799db056SMatthew G. Knepley       PetscObject  obj;
5359799db056SMatthew G. Knepley       PetscClassId id;
5360799db056SMatthew G. Knepley 
5361799db056SMatthew G. Knepley       PetscCall(PetscDSGetBoundary(dsBC, bd, NULL, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
53629566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, field, NULL, &obj));
53639566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
5364fa74d514SMatthew G. Knepley       if (id != PETSCFE_CLASSID || !label) continue;
53659371c9d4SSatish Balay       for (l = 0; l < Nl; ++l)
53669371c9d4SSatish Balay         if (labels[l] == label) break;
5367799db056SMatthew G. Knepley       if (l == Nl) labels[Nl++] = label;
5368783e2ec8SMatthew G. Knepley     }
5369799db056SMatthew G. Knepley   }
5370799db056SMatthew G. Knepley   /* Get label names */
5371799db056SMatthew G. Knepley   PetscCall(PetscMalloc1(Nl, &names));
5372799db056SMatthew G. Knepley   for (l = 0; l < Nl; ++l) PetscCall(PetscObjectGetName((PetscObject)labels[l], &names[l]));
53739371c9d4SSatish Balay   for (l = 0; l < Nl; ++l) {
53749371c9d4SSatish Balay     PetscCall(PetscStrlen(names[l], &len));
53759371c9d4SSatish Balay     maxLen = PetscMax(maxLen, (PetscInt)len + 2);
53769371c9d4SSatish Balay   }
5377799db056SMatthew G. Knepley   PetscCall(PetscFree(labels));
5378462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&maxLen, &gmaxLen, 1, MPIU_INT, MPI_MAX, comm));
5379799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(Nl * gmaxLen, &sendNames));
5380c6a7a370SJeremy L Thompson   for (l = 0; l < Nl; ++l) PetscCall(PetscStrncpy(&sendNames[gmaxLen * l], names[l], gmaxLen));
5381799db056SMatthew G. Knepley   PetscCall(PetscFree(names));
5382799db056SMatthew G. Knepley   /* Put all names on all processes */
5383799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(size, &counts, size + 1, &displs));
5384799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgather(&Nl, 1, MPI_INT, counts, 1, MPI_INT, comm));
5385799db056SMatthew G. Knepley   for (p = 0; p < size; ++p) displs[p + 1] = displs[p] + counts[p];
5386799db056SMatthew G. Knepley   gNl = displs[size];
53879371c9d4SSatish Balay   for (p = 0; p < size; ++p) {
53889371c9d4SSatish Balay     counts[p] *= gmaxLen;
53899371c9d4SSatish Balay     displs[p] *= gmaxLen;
53909371c9d4SSatish Balay   }
5391799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(gNl * gmaxLen, &recvNames, gNl, &glabels));
5392799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgatherv(sendNames, counts[rank], MPI_CHAR, recvNames, counts, displs, MPI_CHAR, comm));
5393799db056SMatthew G. Knepley   PetscCall(PetscFree2(counts, displs));
5394799db056SMatthew G. Knepley   PetscCall(PetscFree(sendNames));
5395799db056SMatthew G. Knepley   for (l = 0, gl = 0; l < gNl; ++l) {
5396799db056SMatthew G. Knepley     PetscCall(DMGetLabel(dm, &recvNames[l * gmaxLen], &glabels[gl]));
5397799db056SMatthew G. Knepley     PetscCheck(glabels[gl], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Label %s missing on rank %d", &recvNames[l * gmaxLen], rank);
53989371c9d4SSatish Balay     for (m = 0; m < gl; ++m)
53995d6b2bfcSJames Wright       if (glabels[m] == glabels[gl]) goto next_label;
54009566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
5401799db056SMatthew G. Knepley     PetscCall(DMPlexLabelComplete(plex, glabels[gl]));
54029566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5403799db056SMatthew G. Knepley     ++gl;
54045d6b2bfcSJames Wright   next_label:
54055d6b2bfcSJames Wright     continue;
5406783e2ec8SMatthew G. Knepley   }
5407799db056SMatthew G. Knepley   PetscCall(PetscFree2(recvNames, glabels));
54083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5409783e2ec8SMatthew G. Knepley }
5410783e2ec8SMatthew G. Knepley 
5411d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew)
5412d71ae5a4SJacob Faibussowitsch {
5413e5e52638SMatthew G. Knepley   DMSpace *tmpd;
5414e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5415e5e52638SMatthew G. Knepley 
5416e5e52638SMatthew G. Knepley   PetscFunctionBegin;
54173ba16761SJacob Faibussowitsch   if (Nds >= NdsNew) PetscFunctionReturn(PETSC_SUCCESS);
54189566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NdsNew, &tmpd));
5419e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s];
54209371c9d4SSatish Balay   for (s = Nds; s < NdsNew; ++s) {
54219371c9d4SSatish Balay     tmpd[s].ds     = NULL;
54229371c9d4SSatish Balay     tmpd[s].label  = NULL;
54239371c9d4SSatish Balay     tmpd[s].fields = NULL;
54249371c9d4SSatish Balay   }
54259566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5426e5e52638SMatthew G. Knepley   dm->Nds   = NdsNew;
5427e5e52638SMatthew G. Knepley   dm->probs = tmpd;
54283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5429e5e52638SMatthew G. Knepley }
5430e5e52638SMatthew G. Knepley 
5431e5e52638SMatthew G. Knepley /*@
543220f4b53cSBarry Smith   DMGetNumDS - Get the number of discrete systems in the `DM`
5433e5e52638SMatthew G. Knepley 
543420f4b53cSBarry Smith   Not Collective
5435e5e52638SMatthew G. Knepley 
5436e5e52638SMatthew G. Knepley   Input Parameter:
543720f4b53cSBarry Smith . dm - The `DM`
5438e5e52638SMatthew G. Knepley 
5439e5e52638SMatthew G. Knepley   Output Parameter:
544020f4b53cSBarry Smith . Nds - The number of `PetscDS` objects
5441e5e52638SMatthew G. Knepley 
5442e5e52638SMatthew G. Knepley   Level: intermediate
5443e5e52638SMatthew G. Knepley 
54441cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDS()`, `DMGetCellDS()`
5445e5e52638SMatthew G. Knepley @*/
5446d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds)
5447d71ae5a4SJacob Faibussowitsch {
5448e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5449e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54504f572ea9SToby Isaac   PetscAssertPointer(Nds, 2);
5451e5e52638SMatthew G. Knepley   *Nds = dm->Nds;
54523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5453e5e52638SMatthew G. Knepley }
5454e5e52638SMatthew G. Knepley 
5455e5e52638SMatthew G. Knepley /*@
545620f4b53cSBarry Smith   DMClearDS - Remove all discrete systems from the `DM`
5457e5e52638SMatthew G. Knepley 
545820f4b53cSBarry Smith   Logically Collective
5459e5e52638SMatthew G. Knepley 
5460e5e52638SMatthew G. Knepley   Input Parameter:
546120f4b53cSBarry Smith . dm - The `DM`
5462e5e52638SMatthew G. Knepley 
5463e5e52638SMatthew G. Knepley   Level: intermediate
5464e5e52638SMatthew G. Knepley 
54651cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumDS()`, `DMGetDS()`, `DMSetField()`
5466e5e52638SMatthew G. Knepley @*/
5467d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearDS(DM dm)
5468d71ae5a4SJacob Faibussowitsch {
5469e5e52638SMatthew G. Knepley   PetscInt s;
5470e5e52638SMatthew G. Knepley 
5471e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5472e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5473e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
54749566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[s].ds));
547507218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dm->probs[s].dsIn));
54769566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->probs[s].label));
54779566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[s].fields));
5478e5e52638SMatthew G. Knepley   }
54799566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5480e5e52638SMatthew G. Knepley   dm->probs = NULL;
5481e5e52638SMatthew G. Knepley   dm->Nds   = 0;
54823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5483e5e52638SMatthew G. Knepley }
5484e5e52638SMatthew G. Knepley 
5485e5e52638SMatthew G. Knepley /*@
548620f4b53cSBarry Smith   DMGetDS - Get the default `PetscDS`
5487e5e52638SMatthew G. Knepley 
548820f4b53cSBarry Smith   Not Collective
5489e5e52638SMatthew G. Knepley 
5490e5e52638SMatthew G. Knepley   Input Parameter:
549120f4b53cSBarry Smith . dm - The `DM`
5492e5e52638SMatthew G. Knepley 
5493e5e52638SMatthew G. Knepley   Output Parameter:
549407218a29SMatthew G. Knepley . ds - The default `PetscDS`
5495e5e52638SMatthew G. Knepley 
5496e5e52638SMatthew G. Knepley   Level: intermediate
5497e5e52638SMatthew G. Knepley 
54981cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetCellDS()`, `DMGetRegionDS()`
5499e5e52638SMatthew G. Knepley @*/
550007218a29SMatthew G. Knepley PetscErrorCode DMGetDS(DM dm, PetscDS *ds)
5501d71ae5a4SJacob Faibussowitsch {
5502e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5503e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
55044f572ea9SToby Isaac   PetscAssertPointer(ds, 2);
550507218a29SMatthew G. Knepley   PetscCheck(dm->Nds > 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Need to call DMCreateDS() before calling DMGetDS()");
550607218a29SMatthew G. Knepley   *ds = dm->probs[0].ds;
55073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5508e5e52638SMatthew G. Knepley }
5509e5e52638SMatthew G. Knepley 
5510e5e52638SMatthew G. Knepley /*@
551120f4b53cSBarry Smith   DMGetCellDS - Get the `PetscDS` defined on a given cell
5512e5e52638SMatthew G. Knepley 
551320f4b53cSBarry Smith   Not Collective
5514e5e52638SMatthew G. Knepley 
5515e5e52638SMatthew G. Knepley   Input Parameters:
551620f4b53cSBarry Smith + dm    - The `DM`
551720f4b53cSBarry Smith - point - Cell for the `PetscDS`
5518e5e52638SMatthew G. Knepley 
551907218a29SMatthew G. Knepley   Output Parameters:
552007218a29SMatthew G. Knepley + ds   - The `PetscDS` defined on the given cell
552107218a29SMatthew G. Knepley - dsIn - The `PetscDS` for input on the given cell, or NULL if the same ds
5522e5e52638SMatthew G. Knepley 
5523e5e52638SMatthew G. Knepley   Level: developer
5524e5e52638SMatthew G. Knepley 
55251cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDS()`, `DMSetRegionDS()`
5526e5e52638SMatthew G. Knepley @*/
552707218a29SMatthew G. Knepley PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *ds, PetscDS *dsIn)
5528d71ae5a4SJacob Faibussowitsch {
552907218a29SMatthew G. Knepley   PetscDS  dsDef = NULL;
5530e5e52638SMatthew G. Knepley   PetscInt s;
5531e5e52638SMatthew G. Knepley 
5532e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5533e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
55344f572ea9SToby Isaac   if (ds) PetscAssertPointer(ds, 3);
55354f572ea9SToby Isaac   if (dsIn) PetscAssertPointer(dsIn, 4);
553663a3b9bcSJacob Faibussowitsch   PetscCheck(point >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %" PetscInt_FMT, point);
553707218a29SMatthew G. Knepley   if (ds) *ds = NULL;
553807218a29SMatthew G. Knepley   if (dsIn) *dsIn = NULL;
5539e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5540e5e52638SMatthew G. Knepley     PetscInt val;
5541e5e52638SMatthew G. Knepley 
55429371c9d4SSatish Balay     if (!dm->probs[s].label) {
554307218a29SMatthew G. Knepley       dsDef = dm->probs[s].ds;
55449371c9d4SSatish Balay     } else {
55459566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(dm->probs[s].label, point, &val));
55469371c9d4SSatish Balay       if (val >= 0) {
554707218a29SMatthew G. Knepley         if (ds) *ds = dm->probs[s].ds;
554807218a29SMatthew G. Knepley         if (dsIn) *dsIn = dm->probs[s].dsIn;
55499371c9d4SSatish Balay         break;
55509371c9d4SSatish Balay       }
5551e5e52638SMatthew G. Knepley     }
5552e5e52638SMatthew G. Knepley   }
555307218a29SMatthew G. Knepley   if (ds && !*ds) *ds = dsDef;
55543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5555e5e52638SMatthew G. Knepley }
5556e5e52638SMatthew G. Knepley 
5557e5e52638SMatthew G. Knepley /*@
555820f4b53cSBarry Smith   DMGetRegionDS - Get the `PetscDS` for a given mesh region, defined by a `DMLabel`
5559e5e52638SMatthew G. Knepley 
556020f4b53cSBarry Smith   Not Collective
5561e5e52638SMatthew G. Knepley 
5562e5e52638SMatthew G. Knepley   Input Parameters:
556320f4b53cSBarry Smith + dm    - The `DM`
556420f4b53cSBarry Smith - label - The `DMLabel` defining the mesh region, or `NULL` for the entire mesh
5565e5e52638SMatthew G. Knepley 
5566b3cf3223SMatthew G. Knepley   Output Parameters:
556720f4b53cSBarry Smith + fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL`
556807218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL`
556907218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input in the given region, or `NULL`
5570e5e52638SMatthew G. Knepley 
5571e5e52638SMatthew G. Knepley   Level: advanced
5572e5e52638SMatthew G. Knepley 
557320f4b53cSBarry Smith   Note:
557420f4b53cSBarry Smith   If a non-`NULL` label is given, but there is no `PetscDS` on that specific label,
557520f4b53cSBarry Smith   the `PetscDS` for the full domain (if present) is returned. Returns with
557607218a29SMatthew G. Knepley   fields = `NULL` and ds = `NULL` if there is no `PetscDS` for the full domain.
557720f4b53cSBarry Smith 
55781cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionNumDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5579e5e52638SMatthew G. Knepley @*/
558007218a29SMatthew G. Knepley PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds, PetscDS *dsIn)
5581d71ae5a4SJacob Faibussowitsch {
5582e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5583e5e52638SMatthew G. Knepley 
5584e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5585e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5586e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
55879371c9d4SSatish Balay   if (fields) {
55884f572ea9SToby Isaac     PetscAssertPointer(fields, 3);
55899371c9d4SSatish Balay     *fields = NULL;
55909371c9d4SSatish Balay   }
55919371c9d4SSatish Balay   if (ds) {
55924f572ea9SToby Isaac     PetscAssertPointer(ds, 4);
55939371c9d4SSatish Balay     *ds = NULL;
55949371c9d4SSatish Balay   }
559507218a29SMatthew G. Knepley   if (dsIn) {
55964f572ea9SToby Isaac     PetscAssertPointer(dsIn, 5);
559707218a29SMatthew G. Knepley     *dsIn = NULL;
559807218a29SMatthew G. Knepley   }
5599e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5600154ca461SJed Brown     if (dm->probs[s].label == label || !dm->probs[s].label) {
5601b3cf3223SMatthew G. Knepley       if (fields) *fields = dm->probs[s].fields;
5602b3cf3223SMatthew G. Knepley       if (ds) *ds = dm->probs[s].ds;
560307218a29SMatthew G. Knepley       if (dsIn) *dsIn = dm->probs[s].dsIn;
56043ba16761SJacob Faibussowitsch       if (dm->probs[s].label) PetscFunctionReturn(PETSC_SUCCESS);
5605b3cf3223SMatthew G. Knepley     }
5606e5e52638SMatthew G. Knepley   }
56073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5608e5e52638SMatthew G. Knepley }
5609e5e52638SMatthew G. Knepley 
5610e5e52638SMatthew G. Knepley /*@
5611bb7acecfSBarry Smith   DMSetRegionDS - Set the `PetscDS` for a given mesh region, defined by a `DMLabel`
5612083401c6SMatthew G. Knepley 
561320f4b53cSBarry Smith   Collective
5614083401c6SMatthew G. Knepley 
5615083401c6SMatthew G. Knepley   Input Parameters:
5616bb7acecfSBarry Smith + dm     - The `DM`
561720f4b53cSBarry Smith . label  - The `DMLabel` defining the mesh region, or `NULL` for the entire mesh
561807218a29SMatthew G. Knepley . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL` for all fields
561907218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region
562007218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input on the given cell, or `NULL` if it is the same `PetscDS`
5621083401c6SMatthew G. Knepley 
562220f4b53cSBarry Smith   Level: advanced
562320f4b53cSBarry Smith 
5624bb7acecfSBarry Smith   Note:
5625bb7acecfSBarry 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,
5626083401c6SMatthew G. Knepley   the fields argument is ignored.
5627083401c6SMatthew G. Knepley 
56281cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionNumDS()`, `DMGetDS()`, `DMGetCellDS()`
5629083401c6SMatthew G. Knepley @*/
563007218a29SMatthew G. Knepley PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds, PetscDS dsIn)
5631d71ae5a4SJacob Faibussowitsch {
5632083401c6SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5633083401c6SMatthew G. Knepley 
5634083401c6SMatthew G. Knepley   PetscFunctionBegin;
5635083401c6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5636083401c6SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
563707218a29SMatthew G. Knepley   if (fields) PetscValidHeaderSpecific(fields, IS_CLASSID, 3);
5638064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 4);
563907218a29SMatthew G. Knepley   if (dsIn) PetscValidHeaderSpecific(dsIn, PETSCDS_CLASSID, 5);
5640083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5641083401c6SMatthew G. Knepley     if (dm->probs[s].label == label) {
56429566063dSJacob Faibussowitsch       PetscCall(PetscDSDestroy(&dm->probs[s].ds));
564307218a29SMatthew G. Knepley       PetscCall(PetscDSDestroy(&dm->probs[s].dsIn));
5644083401c6SMatthew G. Knepley       dm->probs[s].ds   = ds;
564507218a29SMatthew G. Knepley       dm->probs[s].dsIn = dsIn;
56463ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
5647083401c6SMatthew G. Knepley     }
5648083401c6SMatthew G. Knepley   }
56499566063dSJacob Faibussowitsch   PetscCall(DMDSEnlarge_Static(dm, Nds + 1));
56509566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
56519566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fields));
56529566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ds));
565307218a29SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)dsIn));
5654083401c6SMatthew G. Knepley   if (!label) {
5655083401c6SMatthew G. Knepley     /* Put the NULL label at the front, so it is returned as the default */
5656083401c6SMatthew G. Knepley     for (s = Nds - 1; s >= 0; --s) dm->probs[s + 1] = dm->probs[s];
5657083401c6SMatthew G. Knepley     Nds = 0;
5658083401c6SMatthew G. Knepley   }
5659083401c6SMatthew G. Knepley   dm->probs[Nds].label  = label;
5660083401c6SMatthew G. Knepley   dm->probs[Nds].fields = fields;
5661083401c6SMatthew G. Knepley   dm->probs[Nds].ds     = ds;
566207218a29SMatthew G. Knepley   dm->probs[Nds].dsIn   = dsIn;
56633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5664083401c6SMatthew G. Knepley }
5665083401c6SMatthew G. Knepley 
5666083401c6SMatthew G. Knepley /*@
566720f4b53cSBarry Smith   DMGetRegionNumDS - Get the `PetscDS` for a given mesh region, defined by the region number
5668e5e52638SMatthew G. Knepley 
566920f4b53cSBarry Smith   Not Collective
5670e5e52638SMatthew G. Knepley 
5671e5e52638SMatthew G. Knepley   Input Parameters:
567220f4b53cSBarry Smith + dm  - The `DM`
5673e5e52638SMatthew G. Knepley - num - The region number, in [0, Nds)
5674e5e52638SMatthew G. Knepley 
5675e5e52638SMatthew G. Knepley   Output Parameters:
567620f4b53cSBarry Smith + label  - The region label, or `NULL`
567720f4b53cSBarry Smith . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL`
567807218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL`
567907218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input in the given region, or `NULL`
5680e5e52638SMatthew G. Knepley 
5681e5e52638SMatthew G. Knepley   Level: advanced
5682e5e52638SMatthew G. Knepley 
56831cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5684e5e52638SMatthew G. Knepley @*/
568507218a29SMatthew G. Knepley PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds, PetscDS *dsIn)
5686d71ae5a4SJacob Faibussowitsch {
5687e5e52638SMatthew G. Knepley   PetscInt Nds;
5688e5e52638SMatthew G. Knepley 
5689e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5690e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56919566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
569263a3b9bcSJacob 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);
5693e5e52638SMatthew G. Knepley   if (label) {
56944f572ea9SToby Isaac     PetscAssertPointer(label, 3);
5695e5e52638SMatthew G. Knepley     *label = dm->probs[num].label;
5696e5e52638SMatthew G. Knepley   }
5697b3cf3223SMatthew G. Knepley   if (fields) {
56984f572ea9SToby Isaac     PetscAssertPointer(fields, 4);
5699b3cf3223SMatthew G. Knepley     *fields = dm->probs[num].fields;
5700b3cf3223SMatthew G. Knepley   }
5701e5e52638SMatthew G. Knepley   if (ds) {
57024f572ea9SToby Isaac     PetscAssertPointer(ds, 5);
5703e5e52638SMatthew G. Knepley     *ds = dm->probs[num].ds;
5704e5e52638SMatthew G. Knepley   }
570507218a29SMatthew G. Knepley   if (dsIn) {
57064f572ea9SToby Isaac     PetscAssertPointer(dsIn, 6);
570707218a29SMatthew G. Knepley     *dsIn = dm->probs[num].dsIn;
570807218a29SMatthew G. Knepley   }
57093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5710e5e52638SMatthew G. Knepley }
5711e5e52638SMatthew G. Knepley 
5712e5e52638SMatthew G. Knepley /*@
571320f4b53cSBarry Smith   DMSetRegionNumDS - Set the `PetscDS` for a given mesh region, defined by the region number
5714e5e52638SMatthew G. Knepley 
571520f4b53cSBarry Smith   Not Collective
5716e5e52638SMatthew G. Knepley 
5717e5e52638SMatthew G. Knepley   Input Parameters:
571820f4b53cSBarry Smith + dm     - The `DM`
5719083401c6SMatthew G. Knepley . num    - The region number, in [0, Nds)
572020f4b53cSBarry Smith . label  - The region label, or `NULL`
572107218a29SMatthew G. Knepley . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL` to prevent setting
572207218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL` to prevent setting
572307218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input on the given cell, or `NULL` if it is the same `PetscDS`
5724e5e52638SMatthew G. Knepley 
5725e5e52638SMatthew G. Knepley   Level: advanced
5726e5e52638SMatthew G. Knepley 
57271cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5728e5e52638SMatthew G. Knepley @*/
572907218a29SMatthew G. Knepley PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds, PetscDS dsIn)
5730d71ae5a4SJacob Faibussowitsch {
5731083401c6SMatthew G. Knepley   PetscInt Nds;
5732e5e52638SMatthew G. Knepley 
5733e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5734e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5735ad540459SPierre Jolivet   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
57369566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
573763a3b9bcSJacob 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);
57389566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
57399566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->probs[num].label));
5740083401c6SMatthew G. Knepley   dm->probs[num].label = label;
5741083401c6SMatthew G. Knepley   if (fields) {
5742083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(fields, IS_CLASSID, 4);
57439566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)fields));
57449566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[num].fields));
5745083401c6SMatthew G. Knepley     dm->probs[num].fields = fields;
5746e5e52638SMatthew G. Knepley   }
5747083401c6SMatthew G. Knepley   if (ds) {
5748083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 5);
57499566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ds));
57509566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[num].ds));
5751083401c6SMatthew G. Knepley     dm->probs[num].ds = ds;
5752083401c6SMatthew G. Knepley   }
575307218a29SMatthew G. Knepley   if (dsIn) {
575407218a29SMatthew G. Knepley     PetscValidHeaderSpecific(dsIn, PETSCDS_CLASSID, 6);
575507218a29SMatthew G. Knepley     PetscCall(PetscObjectReference((PetscObject)dsIn));
575607218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dm->probs[num].dsIn));
575707218a29SMatthew G. Knepley     dm->probs[num].dsIn = dsIn;
575807218a29SMatthew G. Knepley   }
57593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5760e5e52638SMatthew G. Knepley }
5761e5e52638SMatthew G. Knepley 
5762e5e52638SMatthew G. Knepley /*@
576320f4b53cSBarry Smith   DMFindRegionNum - Find the region number for a given `PetscDS`, or -1 if it is not found.
57641d3af9e0SMatthew G. Knepley 
576520f4b53cSBarry Smith   Not Collective
57661d3af9e0SMatthew G. Knepley 
57671d3af9e0SMatthew G. Knepley   Input Parameters:
576820f4b53cSBarry Smith + dm - The `DM`
576920f4b53cSBarry Smith - ds - The `PetscDS` defined on the given region
57701d3af9e0SMatthew G. Knepley 
57711d3af9e0SMatthew G. Knepley   Output Parameter:
57721d3af9e0SMatthew G. Knepley . num - The region number, in [0, Nds), or -1 if not found
57731d3af9e0SMatthew G. Knepley 
57741d3af9e0SMatthew G. Knepley   Level: advanced
57751d3af9e0SMatthew G. Knepley 
57761cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionNumDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
57771d3af9e0SMatthew G. Knepley @*/
5778d71ae5a4SJacob Faibussowitsch PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num)
5779d71ae5a4SJacob Faibussowitsch {
57801d3af9e0SMatthew G. Knepley   PetscInt Nds, n;
57811d3af9e0SMatthew G. Knepley 
57821d3af9e0SMatthew G. Knepley   PetscFunctionBegin;
57831d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57841d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 2);
57854f572ea9SToby Isaac   PetscAssertPointer(num, 3);
57869566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
57879371c9d4SSatish Balay   for (n = 0; n < Nds; ++n)
57889371c9d4SSatish Balay     if (ds == dm->probs[n].ds) break;
57891d3af9e0SMatthew G. Knepley   if (n >= Nds) *num = -1;
57901d3af9e0SMatthew G. Knepley   else *num = n;
57913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57921d3af9e0SMatthew G. Knepley }
57931d3af9e0SMatthew G. Knepley 
5794cc4c1da9SBarry Smith /*@
5795bb7acecfSBarry Smith   DMCreateFEDefault - Create a `PetscFE` based on the celltype for the mesh
57962df84da0SMatthew G. Knepley 
579720f4b53cSBarry Smith   Not Collective
57982df84da0SMatthew G. Knepley 
5799f1a722f8SMatthew G. Knepley   Input Parameters:
5800bb7acecfSBarry Smith + dm     - The `DM`
58012df84da0SMatthew G. Knepley . Nc     - The number of components for the field
580220f4b53cSBarry Smith . prefix - The options prefix for the output `PetscFE`, or `NULL`
5803bb7acecfSBarry Smith - qorder - The quadrature order or `PETSC_DETERMINE` to use `PetscSpace` polynomial degree
58042df84da0SMatthew G. Knepley 
58052df84da0SMatthew G. Knepley   Output Parameter:
5806bb7acecfSBarry Smith . fem - The `PetscFE`
58072df84da0SMatthew G. Knepley 
580820f4b53cSBarry Smith   Level: intermediate
580920f4b53cSBarry Smith 
5810bb7acecfSBarry Smith   Note:
5811bb7acecfSBarry Smith   This is a convenience method that just calls `PetscFECreateByCell()` underneath.
58122df84da0SMatthew G. Knepley 
58131cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscFECreateByCell()`, `DMAddField()`, `DMCreateDS()`, `DMGetCellDS()`, `DMGetRegionDS()`
58142df84da0SMatthew G. Knepley @*/
5815d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFEDefault(DM dm, PetscInt Nc, const char prefix[], PetscInt qorder, PetscFE *fem)
5816d71ae5a4SJacob Faibussowitsch {
58172df84da0SMatthew G. Knepley   DMPolytopeType ct;
58182df84da0SMatthew G. Knepley   PetscInt       dim, cStart;
58192df84da0SMatthew G. Knepley 
58202df84da0SMatthew G. Knepley   PetscFunctionBegin;
58212df84da0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58222df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 2);
58234f572ea9SToby Isaac   if (prefix) PetscAssertPointer(prefix, 3);
58242df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, qorder, 4);
58254f572ea9SToby Isaac   PetscAssertPointer(fem, 5);
58269566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
58279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
58289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
58299566063dSJacob Faibussowitsch   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, Nc, ct, prefix, qorder, fem));
58303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58312df84da0SMatthew G. Knepley }
58322df84da0SMatthew G. Knepley 
58331d3af9e0SMatthew G. Knepley /*@
5834bb7acecfSBarry Smith   DMCreateDS - Create the discrete systems for the `DM` based upon the fields added to the `DM`
5835e5e52638SMatthew G. Knepley 
583620f4b53cSBarry Smith   Collective
5837e5e52638SMatthew G. Knepley 
5838e5e52638SMatthew G. Knepley   Input Parameter:
5839bb7acecfSBarry Smith . dm - The `DM`
5840e5e52638SMatthew G. Knepley 
584120f4b53cSBarry Smith   Options Database Key:
5842bb7acecfSBarry Smith . -dm_petscds_view - View all the `PetscDS` objects in this `DM`
584345480ffeSMatthew G. Knepley 
584420f4b53cSBarry Smith   Level: intermediate
584520f4b53cSBarry Smith 
58461cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetField`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
5847e5e52638SMatthew G. Knepley @*/
5848d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDS(DM dm)
5849d71ae5a4SJacob Faibussowitsch {
5850e5e52638SMatthew G. Knepley   MPI_Comm  comm;
5851083401c6SMatthew G. Knepley   PetscDS   dsDef;
5852083401c6SMatthew G. Knepley   DMLabel  *labelSet;
5853f9244615SMatthew G. Knepley   PetscInt  dE, Nf = dm->Nf, f, s, Nl, l, Ndef, k;
5854f9244615SMatthew G. Knepley   PetscBool doSetup = PETSC_TRUE, flg;
5855e5e52638SMatthew G. Knepley 
5856e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5857e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58583ba16761SJacob Faibussowitsch   if (!dm->fields) PetscFunctionReturn(PETSC_SUCCESS);
58599566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
58609566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
5861083401c6SMatthew G. Knepley   /* Determine how many regions we have */
58629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(Nf, &labelSet));
5863083401c6SMatthew G. Knepley   Nl   = 0;
5864083401c6SMatthew G. Knepley   Ndef = 0;
5865083401c6SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5866083401c6SMatthew G. Knepley     DMLabel  label = dm->fields[f].label;
5867083401c6SMatthew G. Knepley     PetscInt l;
5868083401c6SMatthew G. Knepley 
5869f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
5870f918ec44SMatthew G. Knepley     /* Move CEED context to discretizations */
5871f918ec44SMatthew G. Knepley     {
5872f918ec44SMatthew G. Knepley       PetscClassId id;
5873f918ec44SMatthew G. Knepley 
58749566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(dm->fields[f].disc, &id));
5875f918ec44SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
5876f918ec44SMatthew G. Knepley         Ceed ceed;
5877f918ec44SMatthew G. Knepley 
58789566063dSJacob Faibussowitsch         PetscCall(DMGetCeed(dm, &ceed));
58799566063dSJacob Faibussowitsch         PetscCall(PetscFESetCeed((PetscFE)dm->fields[f].disc, ceed));
5880f918ec44SMatthew G. Knepley       }
5881f918ec44SMatthew G. Knepley     }
5882f918ec44SMatthew G. Knepley #endif
58839371c9d4SSatish Balay     if (!label) {
58849371c9d4SSatish Balay       ++Ndef;
58859371c9d4SSatish Balay       continue;
58869371c9d4SSatish Balay     }
58879371c9d4SSatish Balay     for (l = 0; l < Nl; ++l)
58889371c9d4SSatish Balay       if (label == labelSet[l]) break;
5889083401c6SMatthew G. Knepley     if (l < Nl) continue;
5890083401c6SMatthew G. Knepley     labelSet[Nl++] = label;
5891083401c6SMatthew G. Knepley   }
5892083401c6SMatthew G. Knepley   /* Create default DS if there are no labels to intersect with */
589307218a29SMatthew G. Knepley   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef, NULL));
5894083401c6SMatthew G. Knepley   if (!dsDef && Ndef && !Nl) {
5895b3cf3223SMatthew G. Knepley     IS        fields;
5896b3cf3223SMatthew G. Knepley     PetscInt *fld, nf;
5897b3cf3223SMatthew G. Knepley 
58989371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58999371c9d4SSatish Balay       if (!dm->fields[f].label) ++nf;
59007a8be351SBarry Smith     PetscCheck(nf, comm, PETSC_ERR_PLIB, "All fields have labels, but we are trying to create a default DS");
59019566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
59029371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
59039371c9d4SSatish Balay       if (!dm->fields[f].label) fld[nf++] = f;
59049566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
59059566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
59069566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
59079566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
590888f0c812SMatthew G. Knepley 
59099566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
591007218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, NULL, fields, dsDef, NULL));
59119566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
59129566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fields));
59132df9ee95SMatthew G. Knepley   }
591407218a29SMatthew G. Knepley   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef, NULL));
59159566063dSJacob Faibussowitsch   if (dsDef) PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
5916083401c6SMatthew G. Knepley   /* Intersect labels with default fields */
5917083401c6SMatthew G. Knepley   if (Ndef && Nl) {
59180122748bSMatthew G. Knepley     DM              plex;
5919083401c6SMatthew G. Knepley     DMLabel         cellLabel;
5920083401c6SMatthew G. Knepley     IS              fieldIS, allcellIS, defcellIS = NULL;
5921083401c6SMatthew G. Knepley     PetscInt       *fields;
5922083401c6SMatthew G. Knepley     const PetscInt *cells;
5923083401c6SMatthew G. Knepley     PetscInt        depth, nf = 0, n, c;
59240122748bSMatthew G. Knepley 
59259566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
59269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(plex, &depth));
59279566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(plex, "dim", depth, &allcellIS));
59289566063dSJacob Faibussowitsch     if (!allcellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, &allcellIS));
59295fedec97SMatthew G. Knepley     /* TODO This looks like it only works for one label */
5930083401c6SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
5931083401c6SMatthew G. Knepley       DMLabel label = labelSet[l];
5932083401c6SMatthew G. Knepley       IS      pointIS;
5933083401c6SMatthew G. Knepley 
59349566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&defcellIS));
59359566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(label, 1, &pointIS));
59369566063dSJacob Faibussowitsch       PetscCall(ISDifference(allcellIS, pointIS, &defcellIS));
59379566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pointIS));
5938083401c6SMatthew G. Knepley     }
59399566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&allcellIS));
5940083401c6SMatthew G. Knepley 
59419566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel));
59429566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(defcellIS, &n));
59439566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(defcellIS, &cells));
59449566063dSJacob Faibussowitsch     for (c = 0; c < n; ++c) PetscCall(DMLabelSetValue(cellLabel, cells[c], 1));
59459566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(defcellIS, &cells));
59469566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&defcellIS));
59479566063dSJacob Faibussowitsch     PetscCall(DMPlexLabelComplete(plex, cellLabel));
5948083401c6SMatthew G. Knepley 
59499566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Ndef, &fields));
59509371c9d4SSatish Balay     for (f = 0; f < Nf; ++f)
59519371c9d4SSatish Balay       if (!dm->fields[f].label) fields[nf++] = f;
59529566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fieldIS));
59539566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fieldIS, "dm_fields_"));
59549566063dSJacob Faibussowitsch     PetscCall(ISSetType(fieldIS, ISGENERAL));
59559566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER));
5956083401c6SMatthew G. Knepley 
59579566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
595807218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, cellLabel, fieldIS, dsDef, NULL));
59599566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
59609566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&cellLabel));
59619566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
59629566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fieldIS));
59639566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5964083401c6SMatthew G. Knepley   }
5965083401c6SMatthew G. Knepley   /* Create label DSes
5966083401c6SMatthew G. Knepley      - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS
5967083401c6SMatthew G. Knepley   */
5968083401c6SMatthew G. Knepley   /* TODO Should check that labels are disjoint */
5969083401c6SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
5970083401c6SMatthew G. Knepley     DMLabel   label = labelSet[l];
597107218a29SMatthew G. Knepley     PetscDS   ds, dsIn = NULL;
5972083401c6SMatthew G. Knepley     IS        fields;
5973083401c6SMatthew G. Knepley     PetscInt *fld, nf;
5974083401c6SMatthew G. Knepley 
59759566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
59769371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
59779371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) ++nf;
59789566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
59799371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
59809371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f;
59819566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
59829566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
59839566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
59849566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
59859566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(ds, dE));
5986083401c6SMatthew G. Knepley     {
5987083401c6SMatthew G. Knepley       DMPolytopeType ct;
5988083401c6SMatthew G. Knepley       PetscInt       lStart, lEnd;
59895fedec97SMatthew G. Knepley       PetscBool      isCohesiveLocal = PETSC_FALSE, isCohesive;
59900122748bSMatthew G. Knepley 
59919566063dSJacob Faibussowitsch       PetscCall(DMLabelGetBounds(label, &lStart, &lEnd));
5992665f567fSMatthew G. Knepley       if (lStart >= 0) {
59939566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, lStart, &ct));
5994412e9a14SMatthew G. Knepley         switch (ct) {
5995412e9a14SMatthew G. Knepley         case DM_POLYTOPE_POINT_PRISM_TENSOR:
5996412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
5997412e9a14SMatthew G. Knepley         case DM_POLYTOPE_TRI_PRISM_TENSOR:
5998d71ae5a4SJacob Faibussowitsch         case DM_POLYTOPE_QUAD_PRISM_TENSOR:
5999d71ae5a4SJacob Faibussowitsch           isCohesiveLocal = PETSC_TRUE;
6000d71ae5a4SJacob Faibussowitsch           break;
6001d71ae5a4SJacob Faibussowitsch         default:
6002d71ae5a4SJacob Faibussowitsch           break;
6003412e9a14SMatthew G. Knepley         }
6004665f567fSMatthew G. Knepley       }
6005462c564dSBarry Smith       PetscCallMPI(MPIU_Allreduce(&isCohesiveLocal, &isCohesive, 1, MPIU_BOOL, MPI_LOR, comm));
600607218a29SMatthew G. Knepley       if (isCohesive) {
600707218a29SMatthew G. Knepley         PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsIn));
600807218a29SMatthew G. Knepley         PetscCall(PetscDSSetCoordinateDimension(dsIn, dE));
600907218a29SMatthew G. Knepley       }
60105fedec97SMatthew G. Knepley       for (f = 0, nf = 0; f < Nf; ++f) {
60115fedec97SMatthew G. Knepley         if (label == dm->fields[f].label || !dm->fields[f].label) {
60125fedec97SMatthew G. Knepley           if (label == dm->fields[f].label) {
60139566063dSJacob Faibussowitsch             PetscCall(PetscDSSetDiscretization(ds, nf, NULL));
60149566063dSJacob Faibussowitsch             PetscCall(PetscDSSetCohesive(ds, nf, isCohesive));
601507218a29SMatthew G. Knepley             if (dsIn) {
601607218a29SMatthew G. Knepley               PetscCall(PetscDSSetDiscretization(dsIn, nf, NULL));
601707218a29SMatthew G. Knepley               PetscCall(PetscDSSetCohesive(dsIn, nf, isCohesive));
601807218a29SMatthew G. Knepley             }
60195fedec97SMatthew G. Knepley           }
60205fedec97SMatthew G. Knepley           ++nf;
60215fedec97SMatthew G. Knepley         }
60225fedec97SMatthew G. Knepley       }
6023e5e52638SMatthew G. Knepley     }
602407218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, label, fields, ds, dsIn));
602507218a29SMatthew G. Knepley     PetscCall(ISDestroy(&fields));
60269566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&ds));
602707218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dsIn));
6028e5e52638SMatthew G. Knepley   }
60299566063dSJacob Faibussowitsch   PetscCall(PetscFree(labelSet));
6030e5e52638SMatthew G. Knepley   /* Set fields in DSes */
6031083401c6SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
6032083401c6SMatthew G. Knepley     PetscDS         ds     = dm->probs[s].ds;
603307218a29SMatthew G. Knepley     PetscDS         dsIn   = dm->probs[s].dsIn;
6034083401c6SMatthew G. Knepley     IS              fields = dm->probs[s].fields;
6035083401c6SMatthew G. Knepley     const PetscInt *fld;
60365fedec97SMatthew G. Knepley     PetscInt        nf, dsnf;
60375fedec97SMatthew G. Knepley     PetscBool       isCohesive;
6038e5e52638SMatthew G. Knepley 
60399566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsnf));
60409566063dSJacob Faibussowitsch     PetscCall(PetscDSIsCohesive(ds, &isCohesive));
60419566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(fields, &nf));
60429566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fields, &fld));
6043083401c6SMatthew G. Knepley     for (f = 0; f < nf; ++f) {
6044083401c6SMatthew G. Knepley       PetscObject  disc = dm->fields[fld[f]].disc;
60455fedec97SMatthew G. Knepley       PetscBool    isCohesiveField;
6046e5e52638SMatthew G. Knepley       PetscClassId id;
6047e5e52638SMatthew G. Knepley 
60485fedec97SMatthew G. Knepley       /* Handle DS with no fields */
60499566063dSJacob Faibussowitsch       if (dsnf) PetscCall(PetscDSGetCohesive(ds, f, &isCohesiveField));
60505fedec97SMatthew G. Knepley       /* If this is a cohesive cell, then regular fields need the lower dimensional discretization */
605107218a29SMatthew G. Knepley       if (isCohesive) {
605207218a29SMatthew G. Knepley         if (!isCohesiveField) {
605307218a29SMatthew G. Knepley           PetscObject bdDisc;
605407218a29SMatthew G. Knepley 
605507218a29SMatthew G. Knepley           PetscCall(PetscFEGetHeightSubspace((PetscFE)disc, 1, (PetscFE *)&bdDisc));
605607218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(ds, f, bdDisc));
605707218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(dsIn, f, disc));
605807218a29SMatthew G. Knepley         } else {
60599566063dSJacob Faibussowitsch           PetscCall(PetscDSSetDiscretization(ds, f, disc));
606007218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(dsIn, f, disc));
606107218a29SMatthew G. Knepley         }
606207218a29SMatthew G. Knepley       } else {
606307218a29SMatthew G. Knepley         PetscCall(PetscDSSetDiscretization(ds, f, disc));
606407218a29SMatthew G. Knepley       }
6065083401c6SMatthew G. Knepley       /* We allow people to have placeholder fields and construct the Section by hand */
60669566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(disc, &id));
6067e5e52638SMatthew G. Knepley       if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE;
6068e5e52638SMatthew G. Knepley     }
60699566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fields, &fld));
6070e5e52638SMatthew G. Knepley   }
6071f9244615SMatthew G. Knepley   /* Allow k-jet tabulation */
60729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)dm)->prefix, "-dm_ds_jet_degree", &k, &flg));
6073f9244615SMatthew G. Knepley   if (flg) {
60743b4aee56SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
60753b4aee56SMatthew G. Knepley       PetscDS  ds   = dm->probs[s].ds;
607607218a29SMatthew G. Knepley       PetscDS  dsIn = dm->probs[s].dsIn;
60773b4aee56SMatthew G. Knepley       PetscInt Nf, f;
60783b4aee56SMatthew G. Knepley 
60799566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(ds, &Nf));
608007218a29SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
608107218a29SMatthew G. Knepley         PetscCall(PetscDSSetJetDegree(ds, f, k));
608207218a29SMatthew G. Knepley         if (dsIn) PetscCall(PetscDSSetJetDegree(dsIn, f, k));
608307218a29SMatthew G. Knepley       }
60843b4aee56SMatthew G. Knepley     }
6085f9244615SMatthew G. Knepley   }
6086e5e52638SMatthew G. Knepley   /* Setup DSes */
6087e5e52638SMatthew G. Knepley   if (doSetup) {
608807218a29SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
6089cf1363e4SMatthew G. Knepley       if (dm->setfromoptionscalled) {
6090cf1363e4SMatthew G. Knepley         PetscCall(PetscDSSetFromOptions(dm->probs[s].ds));
6091cf1363e4SMatthew G. Knepley         if (dm->probs[s].dsIn) PetscCall(PetscDSSetFromOptions(dm->probs[s].dsIn));
6092cf1363e4SMatthew G. Knepley       }
609307218a29SMatthew G. Knepley       PetscCall(PetscDSSetUp(dm->probs[s].ds));
609407218a29SMatthew G. Knepley       if (dm->probs[s].dsIn) PetscCall(PetscDSSetUp(dm->probs[s].dsIn));
609507218a29SMatthew G. Knepley     }
6096e5e52638SMatthew G. Knepley   }
60973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6098e5e52638SMatthew G. Knepley }
6099e5e52638SMatthew G. Knepley 
6100e5e52638SMatthew G. Knepley /*@
6101d2b2dc1eSMatthew G. Knepley   DMUseTensorOrder - Use a tensor product closure ordering for the default section
6102d2b2dc1eSMatthew G. Knepley 
6103d2b2dc1eSMatthew G. Knepley   Input Parameters:
6104d2b2dc1eSMatthew G. Knepley + dm     - The DM
6105d2b2dc1eSMatthew G. Knepley - tensor - Flag for tensor order
6106d2b2dc1eSMatthew G. Knepley 
6107d2b2dc1eSMatthew G. Knepley   Level: developer
6108d2b2dc1eSMatthew G. Knepley 
6109d2b2dc1eSMatthew G. Knepley .seealso: `DMPlexSetClosurePermutationTensor()`, `PetscSectionResetClosurePermutation()`
6110d2b2dc1eSMatthew G. Knepley @*/
6111d2b2dc1eSMatthew G. Knepley PetscErrorCode DMUseTensorOrder(DM dm, PetscBool tensor)
6112d2b2dc1eSMatthew G. Knepley {
6113d2b2dc1eSMatthew G. Knepley   PetscInt  Nf;
6114d2b2dc1eSMatthew G. Knepley   PetscBool reorder = PETSC_TRUE, isPlex;
6115d2b2dc1eSMatthew G. Knepley 
6116d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
6117d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isPlex));
6118d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetNumFields(dm, &Nf));
6119d2b2dc1eSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
6120d2b2dc1eSMatthew G. Knepley     PetscObject  obj;
6121d2b2dc1eSMatthew G. Knepley     PetscClassId id;
6122d2b2dc1eSMatthew G. Knepley 
6123d2b2dc1eSMatthew G. Knepley     PetscCall(DMGetField(dm, f, NULL, &obj));
6124d2b2dc1eSMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
6125d2b2dc1eSMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
6126d2b2dc1eSMatthew G. Knepley       PetscSpace sp;
6127d2b2dc1eSMatthew G. Knepley       PetscBool  tensor;
6128d2b2dc1eSMatthew G. Knepley 
6129d2b2dc1eSMatthew G. Knepley       PetscCall(PetscFEGetBasisSpace((PetscFE)obj, &sp));
6130d2b2dc1eSMatthew G. Knepley       PetscCall(PetscSpacePolynomialGetTensor(sp, &tensor));
6131d2b2dc1eSMatthew G. Knepley       reorder = reorder && tensor ? PETSC_TRUE : PETSC_FALSE;
6132d2b2dc1eSMatthew G. Knepley     } else reorder = PETSC_FALSE;
6133d2b2dc1eSMatthew G. Knepley   }
6134d2b2dc1eSMatthew G. Knepley   if (tensor) {
6135d2b2dc1eSMatthew G. Knepley     if (reorder && isPlex) PetscCall(DMPlexSetClosurePermutationTensor(dm, PETSC_DETERMINE, NULL));
6136d2b2dc1eSMatthew G. Knepley   } else {
6137d2b2dc1eSMatthew G. Knepley     PetscSection s;
6138d2b2dc1eSMatthew G. Knepley 
6139d2b2dc1eSMatthew G. Knepley     PetscCall(DMGetLocalSection(dm, &s));
6140d2b2dc1eSMatthew G. Knepley     if (s) PetscCall(PetscSectionResetClosurePermutation(s));
6141d2b2dc1eSMatthew G. Knepley   }
6142d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6143d2b2dc1eSMatthew G. Knepley }
6144d2b2dc1eSMatthew G. Knepley 
6145d2b2dc1eSMatthew G. Knepley /*@
6146bb7acecfSBarry Smith   DMComputeExactSolution - Compute the exact solution for a given `DM`, using the `PetscDS` information.
61477f96f943SMatthew G. Knepley 
614820f4b53cSBarry Smith   Collective
6149f2cacb80SMatthew G. Knepley 
61507f96f943SMatthew G. Knepley   Input Parameters:
6151bb7acecfSBarry Smith + dm   - The `DM`
61527f96f943SMatthew G. Knepley - time - The time
61537f96f943SMatthew G. Knepley 
61547f96f943SMatthew G. Knepley   Output Parameters:
615520f4b53cSBarry Smith + u   - The vector will be filled with exact solution values, or `NULL`
615620f4b53cSBarry Smith - u_t - The vector will be filled with the time derivative of exact solution values, or `NULL`
615720f4b53cSBarry Smith 
615820f4b53cSBarry Smith   Level: developer
61597f96f943SMatthew G. Knepley 
6160bb7acecfSBarry Smith   Note:
6161bb7acecfSBarry Smith   The user must call `PetscDSSetExactSolution()` before using this routine
61627f96f943SMatthew G. Knepley 
61631cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscDSSetExactSolution()`
61647f96f943SMatthew G. Knepley @*/
6165d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t)
6166d71ae5a4SJacob Faibussowitsch {
61677f96f943SMatthew G. Knepley   PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
61687f96f943SMatthew G. Knepley   void   **ectxs;
6169f60fa741SMatthew G. Knepley   Vec      locu, locu_t;
61707f96f943SMatthew G. Knepley   PetscInt Nf, Nds, s;
61717f96f943SMatthew G. Knepley 
61727f96f943SMatthew G. Knepley   PetscFunctionBegin;
6173f2cacb80SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6174f60fa741SMatthew G. Knepley   if (u) {
6175f60fa741SMatthew G. Knepley     PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
6176f60fa741SMatthew G. Knepley     PetscCall(DMGetLocalVector(dm, &locu));
6177f60fa741SMatthew G. Knepley     PetscCall(VecSet(locu, 0.));
6178f60fa741SMatthew G. Knepley   }
6179f60fa741SMatthew G. Knepley   if (u_t) {
6180f60fa741SMatthew G. Knepley     PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4);
6181f60fa741SMatthew G. Knepley     PetscCall(DMGetLocalVector(dm, &locu_t));
6182f60fa741SMatthew G. Knepley     PetscCall(VecSet(locu_t, 0.));
6183f60fa741SMatthew G. Knepley   }
61849566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
61859566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(Nf, &exacts, Nf, &ectxs));
61869566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
61877f96f943SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
61887f96f943SMatthew G. Knepley     PetscDS         ds;
61897f96f943SMatthew G. Knepley     DMLabel         label;
61907f96f943SMatthew G. Knepley     IS              fieldIS;
61917f96f943SMatthew G. Knepley     const PetscInt *fields, id = 1;
61927f96f943SMatthew G. Knepley     PetscInt        dsNf, f;
61937f96f943SMatthew G. Knepley 
619407218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds, NULL));
61959566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
61969566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fieldIS, &fields));
61979566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(exacts, Nf));
61989566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(ectxs, Nf));
6199f2cacb80SMatthew G. Knepley     if (u) {
6200f60fa741SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) PetscCall(PetscDSGetExactSolution(ds, fields[f], &exacts[fields[f]], &ectxs[fields[f]]));
6201f60fa741SMatthew G. Knepley       if (label) PetscCall(DMProjectFunctionLabelLocal(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, locu));
6202f60fa741SMatthew G. Knepley       else PetscCall(DMProjectFunctionLocal(dm, time, exacts, ectxs, INSERT_ALL_VALUES, locu));
62037f96f943SMatthew G. Knepley     }
6204f2cacb80SMatthew G. Knepley     if (u_t) {
62059566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(exacts, Nf));
62069566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ectxs, Nf));
6207f60fa741SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, fields[f], &exacts[fields[f]], &ectxs[fields[f]]));
6208f60fa741SMatthew G. Knepley       if (label) PetscCall(DMProjectFunctionLabelLocal(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, locu_t));
6209f60fa741SMatthew G. Knepley       else PetscCall(DMProjectFunctionLocal(dm, time, exacts, ectxs, INSERT_ALL_VALUES, locu_t));
6210f2cacb80SMatthew G. Knepley     }
62119566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fieldIS, &fields));
6212f2cacb80SMatthew G. Knepley   }
6213f2cacb80SMatthew G. Knepley   if (u) {
62149566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution"));
62159566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u, "exact_"));
6216f2cacb80SMatthew G. Knepley   }
6217f2cacb80SMatthew G. Knepley   if (u_t) {
62189566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution Time Derivative"));
62199566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u_t, "exact_t_"));
6220f2cacb80SMatthew G. Knepley   }
62219566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exacts, ectxs));
6222f60fa741SMatthew G. Knepley   if (u) {
6223f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(dm, locu, INSERT_ALL_VALUES, u));
6224f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(dm, locu, INSERT_ALL_VALUES, u));
6225f60fa741SMatthew G. Knepley     PetscCall(DMRestoreLocalVector(dm, &locu));
6226f60fa741SMatthew G. Knepley   }
6227f60fa741SMatthew G. Knepley   if (u_t) {
6228f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(dm, locu_t, INSERT_ALL_VALUES, u_t));
6229f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(dm, locu_t, INSERT_ALL_VALUES, u_t));
6230f60fa741SMatthew G. Knepley     PetscCall(DMRestoreLocalVector(dm, &locu_t));
6231f60fa741SMatthew G. Knepley   }
62323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
62337f96f943SMatthew G. Knepley }
62347f96f943SMatthew G. Knepley 
6235bb4b53efSMatthew G. Knepley static PetscErrorCode DMTransferDS_Internal(DM dm, DMLabel label, IS fields, PetscInt minDegree, PetscInt maxDegree, PetscDS ds, PetscDS dsIn)
6236d71ae5a4SJacob Faibussowitsch {
623707218a29SMatthew G. Knepley   PetscDS dsNew, dsInNew = NULL;
623845480ffeSMatthew G. Knepley 
623945480ffeSMatthew G. Knepley   PetscFunctionBegin;
62409566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)ds), &dsNew));
6241bb4b53efSMatthew G. Knepley   PetscCall(PetscDSCopy(ds, minDegree, maxDegree, dm, dsNew));
624207218a29SMatthew G. Knepley   if (dsIn) {
624307218a29SMatthew G. Knepley     PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)dsIn), &dsInNew));
6244bb4b53efSMatthew G. Knepley     PetscCall(PetscDSCopy(dsIn, minDegree, maxDegree, dm, dsInNew));
624545480ffeSMatthew G. Knepley   }
624607218a29SMatthew G. Knepley   PetscCall(DMSetRegionDS(dm, label, fields, dsNew, dsInNew));
62479566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&dsNew));
624807218a29SMatthew G. Knepley   PetscCall(PetscDSDestroy(&dsInNew));
62493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
625045480ffeSMatthew G. Knepley }
625145480ffeSMatthew G. Knepley 
62527f96f943SMatthew G. Knepley /*@
6253bb7acecfSBarry Smith   DMCopyDS - Copy the discrete systems for the `DM` into another `DM`
6254e5e52638SMatthew G. Knepley 
625520f4b53cSBarry Smith   Collective
6256e5e52638SMatthew G. Knepley 
6257bb4b53efSMatthew G. Knepley   Input Parameters:
6258bb4b53efSMatthew G. Knepley + dm        - The `DM`
6259bb4b53efSMatthew G. Knepley . minDegree - Minimum degree for a discretization, or `PETSC_DETERMINE` for no limit
6260bb4b53efSMatthew G. Knepley - maxDegree - Maximum degree for a discretization, or `PETSC_DETERMINE` for no limit
6261e5e52638SMatthew G. Knepley 
6262e5e52638SMatthew G. Knepley   Output Parameter:
6263bb7acecfSBarry Smith . newdm - The `DM`
6264e5e52638SMatthew G. Knepley 
6265e5e52638SMatthew G. Knepley   Level: advanced
6266e5e52638SMatthew G. Knepley 
62671cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCopyFields()`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
6268e5e52638SMatthew G. Knepley @*/
6269bb4b53efSMatthew G. Knepley PetscErrorCode DMCopyDS(DM dm, PetscInt minDegree, PetscInt maxDegree, DM newdm)
6270d71ae5a4SJacob Faibussowitsch {
6271e5e52638SMatthew G. Knepley   PetscInt Nds, s;
6272e5e52638SMatthew G. Knepley 
6273e5e52638SMatthew G. Knepley   PetscFunctionBegin;
62743ba16761SJacob Faibussowitsch   if (dm == newdm) PetscFunctionReturn(PETSC_SUCCESS);
62759566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
62769566063dSJacob Faibussowitsch   PetscCall(DMClearDS(newdm));
6277e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
6278e5e52638SMatthew G. Knepley     DMLabel  label;
6279b3cf3223SMatthew G. Knepley     IS       fields;
628007218a29SMatthew G. Knepley     PetscDS  ds, dsIn, newds;
6281783e2ec8SMatthew G. Knepley     PetscInt Nbd, bd;
6282e5e52638SMatthew G. Knepley 
628307218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fields, &ds, &dsIn));
6284b8025e53SMatthew G. Knepley     /* TODO: We need to change all keys from labels in the old DM to labels in the new DM */
6285bb4b53efSMatthew G. Knepley     PetscCall(DMTransferDS_Internal(newdm, label, fields, minDegree, maxDegree, ds, dsIn));
6286d5b43468SJose E. Roman     /* Complete new labels in the new DS */
628707218a29SMatthew G. Knepley     PetscCall(DMGetRegionDS(newdm, label, NULL, &newds, NULL));
62889566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumBoundary(newds, &Nbd));
6289783e2ec8SMatthew G. Knepley     for (bd = 0; bd < Nbd; ++bd) {
6290b8025e53SMatthew G. Knepley       PetscWeakForm wf;
629145480ffeSMatthew G. Knepley       DMLabel       label;
6292783e2ec8SMatthew G. Knepley       PetscInt      field;
6293783e2ec8SMatthew G. Knepley 
62949566063dSJacob Faibussowitsch       PetscCall(PetscDSGetBoundary(newds, bd, &wf, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
62959566063dSJacob Faibussowitsch       PetscCall(PetscWeakFormReplaceLabel(wf, label));
6296783e2ec8SMatthew G. Knepley     }
6297e5e52638SMatthew G. Knepley   }
6298799db056SMatthew G. Knepley   PetscCall(DMCompleteBCLabels_Internal(newdm));
62993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6300e5e52638SMatthew G. Knepley }
6301e5e52638SMatthew G. Knepley 
6302e5e52638SMatthew G. Knepley /*@
6303bb7acecfSBarry Smith   DMCopyDisc - Copy the fields and discrete systems for the `DM` into another `DM`
6304e5e52638SMatthew G. Knepley 
630520f4b53cSBarry Smith   Collective
6306e5e52638SMatthew G. Knepley 
6307e5e52638SMatthew G. Knepley   Input Parameter:
6308bb7acecfSBarry Smith . dm - The `DM`
6309e5e52638SMatthew G. Knepley 
6310e5e52638SMatthew G. Knepley   Output Parameter:
6311bb7acecfSBarry Smith . newdm - The `DM`
6312e5e52638SMatthew G. Knepley 
6313e5e52638SMatthew G. Knepley   Level: advanced
6314e5e52638SMatthew G. Knepley 
631573ff1848SBarry Smith   Developer Note:
6316bb7acecfSBarry Smith   Really ugly name, nothing in PETSc is called a `Disc` plus it is an ugly abbreviation
6317bb7acecfSBarry Smith 
63181cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCopyFields()`, `DMCopyDS()`
6319e5e52638SMatthew G. Knepley @*/
6320d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDisc(DM dm, DM newdm)
6321d71ae5a4SJacob Faibussowitsch {
6322e5e52638SMatthew G. Knepley   PetscFunctionBegin;
6323bb4b53efSMatthew G. Knepley   PetscCall(DMCopyFields(dm, PETSC_DETERMINE, PETSC_DETERMINE, newdm));
6324bb4b53efSMatthew G. Knepley   PetscCall(DMCopyDS(dm, PETSC_DETERMINE, PETSC_DETERMINE, newdm));
63253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6326e5e52638SMatthew G. Knepley }
6327e5e52638SMatthew G. Knepley 
6328c73cfb54SMatthew G. Knepley /*@
6329bb7acecfSBarry Smith   DMGetDimension - Return the topological dimension of the `DM`
6330c73cfb54SMatthew G. Knepley 
633120f4b53cSBarry Smith   Not Collective
6332c73cfb54SMatthew G. Knepley 
6333c73cfb54SMatthew G. Knepley   Input Parameter:
6334bb7acecfSBarry Smith . dm - The `DM`
6335c73cfb54SMatthew G. Knepley 
6336c73cfb54SMatthew G. Knepley   Output Parameter:
6337c73cfb54SMatthew G. Knepley . dim - The topological dimension
6338c73cfb54SMatthew G. Knepley 
6339c73cfb54SMatthew G. Knepley   Level: beginner
6340c73cfb54SMatthew G. Knepley 
63411cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetDimension()`, `DMCreate()`
6342c73cfb54SMatthew G. Knepley @*/
6343d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
6344d71ae5a4SJacob Faibussowitsch {
6345c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6346c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63474f572ea9SToby Isaac   PetscAssertPointer(dim, 2);
6348c73cfb54SMatthew G. Knepley   *dim = dm->dim;
63493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6350c73cfb54SMatthew G. Knepley }
6351c73cfb54SMatthew G. Knepley 
6352c73cfb54SMatthew G. Knepley /*@
6353bb7acecfSBarry Smith   DMSetDimension - Set the topological dimension of the `DM`
6354c73cfb54SMatthew G. Knepley 
635520f4b53cSBarry Smith   Collective
6356c73cfb54SMatthew G. Knepley 
6357c73cfb54SMatthew G. Knepley   Input Parameters:
6358bb7acecfSBarry Smith + dm  - The `DM`
6359c73cfb54SMatthew G. Knepley - dim - The topological dimension
6360c73cfb54SMatthew G. Knepley 
6361c73cfb54SMatthew G. Knepley   Level: beginner
6362c73cfb54SMatthew G. Knepley 
63631cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDimension()`, `DMCreate()`
6364c73cfb54SMatthew G. Knepley @*/
6365d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
6366d71ae5a4SJacob Faibussowitsch {
6367e5e52638SMatthew G. Knepley   PetscDS  ds;
636845480ffeSMatthew G. Knepley   PetscInt Nds, n;
6369f17e8794SMatthew G. Knepley 
6370c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6371c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6372c73cfb54SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6373c73cfb54SMatthew G. Knepley   dm->dim = dim;
6374d17bd122SMatthew G. Knepley   if (dm->dim >= 0) {
63759566063dSJacob Faibussowitsch     PetscCall(DMGetNumDS(dm, &Nds));
637645480ffeSMatthew G. Knepley     for (n = 0; n < Nds; ++n) {
637707218a29SMatthew G. Knepley       PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds, NULL));
63789566063dSJacob Faibussowitsch       if (ds->dimEmbed < 0) PetscCall(PetscDSSetCoordinateDimension(ds, dim));
637945480ffeSMatthew G. Knepley     }
6380d17bd122SMatthew G. Knepley   }
63813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6382c73cfb54SMatthew G. Knepley }
6383c73cfb54SMatthew G. Knepley 
6384793f3fe5SMatthew G. Knepley /*@
6385793f3fe5SMatthew G. Knepley   DMGetDimPoints - Get the half-open interval for all points of a given dimension
6386793f3fe5SMatthew G. Knepley 
638720f4b53cSBarry Smith   Collective
6388793f3fe5SMatthew G. Knepley 
6389793f3fe5SMatthew G. Knepley   Input Parameters:
6390bb7acecfSBarry Smith + dm  - the `DM`
6391793f3fe5SMatthew G. Knepley - dim - the dimension
6392793f3fe5SMatthew G. Knepley 
6393793f3fe5SMatthew G. Knepley   Output Parameters:
6394793f3fe5SMatthew G. Knepley + pStart - The first point of the given dimension
6395aa049354SPatrick Sanan - pEnd   - The first point following points of the given dimension
6396793f3fe5SMatthew G. Knepley 
639720f4b53cSBarry Smith   Level: intermediate
639820f4b53cSBarry Smith 
6399793f3fe5SMatthew G. Knepley   Note:
6400793f3fe5SMatthew G. Knepley   The points are vertices in the Hasse diagram encoding the topology. This is explained in
6401a8d69d7bSBarry Smith   https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme,
6402793f3fe5SMatthew G. Knepley   then the interval is empty.
6403793f3fe5SMatthew G. Knepley 
64041cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
6405793f3fe5SMatthew G. Knepley @*/
6406d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
6407d71ae5a4SJacob Faibussowitsch {
6408793f3fe5SMatthew G. Knepley   PetscInt d;
6409793f3fe5SMatthew G. Knepley 
6410793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
6411793f3fe5SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64129566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &d));
64137a8be351SBarry Smith   PetscCheck((dim >= 0) && (dim <= d), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %" PetscInt_FMT, dim);
6414dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getdimpoints, dim, pStart, pEnd);
64153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6416793f3fe5SMatthew G. Knepley }
6417793f3fe5SMatthew G. Knepley 
64186636e97aSMatthew G Knepley /*@
6419bb7acecfSBarry Smith   DMGetOutputDM - Retrieve the `DM` associated with the layout for output
6420f4d763aaSMatthew G. Knepley 
642120f4b53cSBarry Smith   Collective
64228f700142SStefano Zampini 
6423f4d763aaSMatthew G. Knepley   Input Parameter:
6424bb7acecfSBarry Smith . dm - The original `DM`
6425f4d763aaSMatthew G. Knepley 
6426f4d763aaSMatthew G. Knepley   Output Parameter:
6427bb7acecfSBarry Smith . odm - The `DM` which provides the layout for output
6428f4d763aaSMatthew G. Knepley 
6429f4d763aaSMatthew G. Knepley   Level: intermediate
6430f4d763aaSMatthew G. Knepley 
6431bb7acecfSBarry Smith   Note:
6432bb7acecfSBarry Smith   In some situations the vector obtained with `DMCreateGlobalVector()` excludes points for degrees of freedom that are associated with fixed (Dirichelet) boundary
6433bb7acecfSBarry 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
6434bb7acecfSBarry Smith   locations for those dof so that they can be output to a file or other viewer along with the unconstrained dof.
6435bb7acecfSBarry Smith 
64361cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`, `DMGetGlobalSection()`, `DMCreateGlobalVector()`, `PetscSectionHasConstraints()`, `DMSetGlobalSection()`
6437f4d763aaSMatthew G. Knepley @*/
6438d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
6439d71ae5a4SJacob Faibussowitsch {
6440c26acbdeSMatthew G. Knepley   PetscSection section;
6441eb9d3e4dSMatthew G. Knepley   IS           perm;
6442eb9d3e4dSMatthew G. Knepley   PetscBool    hasConstraints, newDM, gnewDM;
644392a26154SJames Wright   PetscInt     num_face_sfs = 0;
644414f150ffSMatthew G. Knepley 
644514f150ffSMatthew G. Knepley   PetscFunctionBegin;
644614f150ffSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64474f572ea9SToby Isaac   PetscAssertPointer(odm, 2);
64489566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
64499566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
6450eb9d3e4dSMatthew G. Knepley   PetscCall(PetscSectionGetPermutation(section, &perm));
645192a26154SJames Wright   PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, NULL));
645292a26154SJames Wright   newDM = hasConstraints || perm || (num_face_sfs > 0) ? PETSC_TRUE : PETSC_FALSE;
6453462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&newDM, &gnewDM, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
6454eb9d3e4dSMatthew G. Knepley   if (!gnewDM) {
6455c26acbdeSMatthew G. Knepley     *odm = dm;
64563ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6457c26acbdeSMatthew G. Knepley   }
645814f150ffSMatthew G. Knepley   if (!dm->dmBC) {
6459c26acbdeSMatthew G. Knepley     PetscSection newSection, gsection;
646092a26154SJames Wright     PetscSF      sf, sfNatural;
6461eb9d3e4dSMatthew G. Knepley     PetscBool    usePerm = dm->ignorePermOutput ? PETSC_FALSE : PETSC_TRUE;
646214f150ffSMatthew G. Knepley 
64639566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &dm->dmBC));
64649566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dm, dm->dmBC));
64659566063dSJacob Faibussowitsch     PetscCall(PetscSectionClone(section, &newSection));
64669566063dSJacob Faibussowitsch     PetscCall(DMSetLocalSection(dm->dmBC, newSection));
64679566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&newSection));
646892a26154SJames Wright     PetscCall(DMGetNaturalSF(dm, &sfNatural));
646992a26154SJames Wright     PetscCall(DMSetNaturalSF(dm->dmBC, sfNatural));
64709566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm->dmBC, &sf));
6471eb9d3e4dSMatthew G. Knepley     PetscCall(PetscSectionCreateGlobalSection(section, sf, usePerm, PETSC_TRUE, PETSC_FALSE, &gsection));
64729566063dSJacob Faibussowitsch     PetscCall(DMSetGlobalSection(dm->dmBC, gsection));
64739566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&gsection));
647414f150ffSMatthew G. Knepley   }
647514f150ffSMatthew G. Knepley   *odm = dm->dmBC;
64763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
647714f150ffSMatthew G. Knepley }
6478f4d763aaSMatthew G. Knepley 
6479f4d763aaSMatthew G. Knepley /*@
6480cdb7a50dSMatthew G. Knepley   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
6481f4d763aaSMatthew G. Knepley 
6482f4d763aaSMatthew G. Knepley   Input Parameter:
6483bb7acecfSBarry Smith . dm - The original `DM`
6484f4d763aaSMatthew G. Knepley 
6485cdb7a50dSMatthew G. Knepley   Output Parameters:
6486cdb7a50dSMatthew G. Knepley + num - The output sequence number
6487cdb7a50dSMatthew G. Knepley - val - The output sequence value
6488f4d763aaSMatthew G. Knepley 
6489f4d763aaSMatthew G. Knepley   Level: intermediate
6490f4d763aaSMatthew G. Knepley 
6491bb7acecfSBarry Smith   Note:
6492bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6493bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6494bb7acecfSBarry Smith 
649573ff1848SBarry Smith   Developer Note:
6496bb7acecfSBarry Smith   The `DM` serves as a convenient place to store the current iteration value. The iteration is not
6497bb7acecfSBarry Smith   not directly related to the `DM`.
6498f4d763aaSMatthew G. Knepley 
64991cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`
6500f4d763aaSMatthew G. Knepley @*/
6501d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
6502d71ae5a4SJacob Faibussowitsch {
6503f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6504f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65059371c9d4SSatish Balay   if (num) {
65064f572ea9SToby Isaac     PetscAssertPointer(num, 2);
65079371c9d4SSatish Balay     *num = dm->outputSequenceNum;
65089371c9d4SSatish Balay   }
65099371c9d4SSatish Balay   if (val) {
65104f572ea9SToby Isaac     PetscAssertPointer(val, 3);
65119371c9d4SSatish Balay     *val = dm->outputSequenceVal;
65129371c9d4SSatish Balay   }
65133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6514f4d763aaSMatthew G. Knepley }
6515f4d763aaSMatthew G. Knepley 
6516f4d763aaSMatthew G. Knepley /*@
6517cdb7a50dSMatthew G. Knepley   DMSetOutputSequenceNumber - Set the sequence number/value for output
6518f4d763aaSMatthew G. Knepley 
6519f4d763aaSMatthew G. Knepley   Input Parameters:
6520bb7acecfSBarry Smith + dm  - The original `DM`
6521cdb7a50dSMatthew G. Knepley . num - The output sequence number
6522cdb7a50dSMatthew G. Knepley - val - The output sequence value
6523f4d763aaSMatthew G. Knepley 
6524f4d763aaSMatthew G. Knepley   Level: intermediate
6525f4d763aaSMatthew G. Knepley 
6526bb7acecfSBarry Smith   Note:
6527bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6528bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6529f4d763aaSMatthew G. Knepley 
65301cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`
6531f4d763aaSMatthew G. Knepley @*/
6532d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
6533d71ae5a4SJacob Faibussowitsch {
6534f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6535f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6536f4d763aaSMatthew G. Knepley   dm->outputSequenceNum = num;
6537cdb7a50dSMatthew G. Knepley   dm->outputSequenceVal = val;
65383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6539cdb7a50dSMatthew G. Knepley }
6540cdb7a50dSMatthew G. Knepley 
65415d83a8b1SBarry Smith /*@
6542bb7acecfSBarry Smith   DMOutputSequenceLoad - Retrieve the sequence value from a `PetscViewer`
6543cdb7a50dSMatthew G. Knepley 
6544cdb7a50dSMatthew G. Knepley   Input Parameters:
6545bb7acecfSBarry Smith + dm     - The original `DM`
6546b2033f5dSMatthew G. Knepley . viewer - The `PetscViewer` to get it from
6547cdb7a50dSMatthew G. Knepley . name   - The sequence name
6548cdb7a50dSMatthew G. Knepley - num    - The output sequence number
6549cdb7a50dSMatthew G. Knepley 
6550cdb7a50dSMatthew G. Knepley   Output Parameter:
6551cdb7a50dSMatthew G. Knepley . val - The output sequence value
6552cdb7a50dSMatthew G. Knepley 
6553cdb7a50dSMatthew G. Knepley   Level: intermediate
6554cdb7a50dSMatthew G. Knepley 
6555bb7acecfSBarry Smith   Note:
6556bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6557bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6558bb7acecfSBarry Smith 
655973ff1848SBarry Smith   Developer Note:
6560bb7acecfSBarry Smith   It is unclear at the user API level why a `DM` is needed as input
6561cdb7a50dSMatthew G. Knepley 
65621cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetOutputSequenceNumber()`, `DMSetOutputSequenceNumber()`, `VecView()`
6563cdb7a50dSMatthew G. Knepley @*/
6564b2033f5dSMatthew G. Knepley PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char name[], PetscInt num, PetscReal *val)
6565d71ae5a4SJacob Faibussowitsch {
6566cdb7a50dSMatthew G. Knepley   PetscBool ishdf5;
6567cdb7a50dSMatthew G. Knepley 
6568cdb7a50dSMatthew G. Knepley   PetscFunctionBegin;
6569cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6570cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
6571b2033f5dSMatthew G. Knepley   PetscAssertPointer(name, 3);
65724f572ea9SToby Isaac   PetscAssertPointer(val, 5);
65739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6574cdb7a50dSMatthew G. Knepley   if (ishdf5) {
6575cdb7a50dSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6576cdb7a50dSMatthew G. Knepley     PetscScalar value;
6577cdb7a50dSMatthew G. Knepley 
65789566063dSJacob Faibussowitsch     PetscCall(DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer));
65794aeb217fSMatthew G. Knepley     *val = PetscRealPart(value);
6580cdb7a50dSMatthew G. Knepley #endif
6581cdb7a50dSMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
65823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6583f4d763aaSMatthew G. Knepley }
65848e4ac7eaSMatthew G. Knepley 
65858e4ac7eaSMatthew G. Knepley /*@
6586b2033f5dSMatthew G. Knepley   DMGetOutputSequenceLength - Retrieve the number of sequence values from a `PetscViewer`
6587b2033f5dSMatthew G. Knepley 
6588b2033f5dSMatthew G. Knepley   Input Parameters:
6589b2033f5dSMatthew G. Knepley + dm     - The original `DM`
6590b2033f5dSMatthew G. Knepley . viewer - The `PetscViewer` to get it from
6591b2033f5dSMatthew G. Knepley - name   - The sequence name
6592b2033f5dSMatthew G. Knepley 
6593b2033f5dSMatthew G. Knepley   Output Parameter:
6594b2033f5dSMatthew G. Knepley . len - The length of the output sequence
6595b2033f5dSMatthew G. Knepley 
6596b2033f5dSMatthew G. Knepley   Level: intermediate
6597b2033f5dSMatthew G. Knepley 
6598b2033f5dSMatthew G. Knepley   Note:
6599b2033f5dSMatthew G. Knepley   This is intended for output that should appear in sequence, for instance
6600b2033f5dSMatthew G. Knepley   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6601b2033f5dSMatthew G. Knepley 
6602b2033f5dSMatthew G. Knepley   Developer Note:
6603b2033f5dSMatthew G. Knepley   It is unclear at the user API level why a `DM` is needed as input
6604b2033f5dSMatthew G. Knepley 
6605b2033f5dSMatthew G. Knepley .seealso: [](ch_dmbase), `DM`, `DMGetOutputSequenceNumber()`, `DMSetOutputSequenceNumber()`, `VecView()`
6606b2033f5dSMatthew G. Knepley @*/
6607b2033f5dSMatthew G. Knepley PetscErrorCode DMGetOutputSequenceLength(DM dm, PetscViewer viewer, const char name[], PetscInt *len)
6608b2033f5dSMatthew G. Knepley {
6609b2033f5dSMatthew G. Knepley   PetscBool ishdf5;
6610b2033f5dSMatthew G. Knepley 
6611b2033f5dSMatthew G. Knepley   PetscFunctionBegin;
6612b2033f5dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6613b2033f5dSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
6614b2033f5dSMatthew G. Knepley   PetscAssertPointer(name, 3);
6615b2033f5dSMatthew G. Knepley   PetscAssertPointer(len, 4);
6616b2033f5dSMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6617b2033f5dSMatthew G. Knepley   if (ishdf5) {
6618b2033f5dSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6619b2033f5dSMatthew G. Knepley     PetscCall(DMSequenceGetLength_HDF5_Internal(dm, name, len, viewer));
6620b2033f5dSMatthew G. Knepley #endif
6621b2033f5dSMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
6622b2033f5dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6623b2033f5dSMatthew G. Knepley }
6624b2033f5dSMatthew G. Knepley 
6625b2033f5dSMatthew G. Knepley /*@
6626bb7acecfSBarry Smith   DMGetUseNatural - Get the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
66278e4ac7eaSMatthew G. Knepley 
662820f4b53cSBarry Smith   Not Collective
66298e4ac7eaSMatthew G. Knepley 
66308e4ac7eaSMatthew G. Knepley   Input Parameter:
6631bb7acecfSBarry Smith . dm - The `DM`
66328e4ac7eaSMatthew G. Knepley 
66338e4ac7eaSMatthew G. Knepley   Output Parameter:
6634bb7acecfSBarry Smith . useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
66358e4ac7eaSMatthew G. Knepley 
66368e4ac7eaSMatthew G. Knepley   Level: beginner
66378e4ac7eaSMatthew G. Knepley 
66381cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetUseNatural()`, `DMCreate()`
66398e4ac7eaSMatthew G. Knepley @*/
6640d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
6641d71ae5a4SJacob Faibussowitsch {
66428e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
66438e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
66444f572ea9SToby Isaac   PetscAssertPointer(useNatural, 2);
66458e4ac7eaSMatthew G. Knepley   *useNatural = dm->useNatural;
66463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66478e4ac7eaSMatthew G. Knepley }
66488e4ac7eaSMatthew G. Knepley 
66498e4ac7eaSMatthew G. Knepley /*@
6650bb7acecfSBarry Smith   DMSetUseNatural - Set the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
66518e4ac7eaSMatthew G. Knepley 
665220f4b53cSBarry Smith   Collective
66538e4ac7eaSMatthew G. Knepley 
66548e4ac7eaSMatthew G. Knepley   Input Parameters:
6655bb7acecfSBarry Smith + dm         - The `DM`
6656bb7acecfSBarry Smith - useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
66578e4ac7eaSMatthew G. Knepley 
665873ff1848SBarry Smith   Level: beginner
665973ff1848SBarry Smith 
6660bb7acecfSBarry Smith   Note:
6661bb7acecfSBarry Smith   This also causes the map to be build after `DMCreateSubDM()` and `DMCreateSuperDM()`
66625d3b26e6SMatthew G. Knepley 
66631cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetUseNatural()`, `DMCreate()`, `DMPlexDistribute()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
66648e4ac7eaSMatthew G. Knepley @*/
6665d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
6666d71ae5a4SJacob Faibussowitsch {
66678e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
66688e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
66698833efb5SBlaise Bourdin   PetscValidLogicalCollectiveBool(dm, useNatural, 2);
66708e4ac7eaSMatthew G. Knepley   dm->useNatural = useNatural;
66713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66728e4ac7eaSMatthew G. Knepley }
6673c58f1c22SToby Isaac 
6674cc4c1da9SBarry Smith /*@
6675bb7acecfSBarry Smith   DMCreateLabel - Create a label of the given name if it does not already exist in the `DM`
6676c58f1c22SToby Isaac 
6677c58f1c22SToby Isaac   Not Collective
6678c58f1c22SToby Isaac 
6679c58f1c22SToby Isaac   Input Parameters:
6680bb7acecfSBarry Smith + dm   - The `DM` object
6681c58f1c22SToby Isaac - name - The label name
6682c58f1c22SToby Isaac 
6683c58f1c22SToby Isaac   Level: intermediate
6684c58f1c22SToby Isaac 
66851cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6686c58f1c22SToby Isaac @*/
6687d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabel(DM dm, const char name[])
6688d71ae5a4SJacob Faibussowitsch {
66895d80c0bfSVaclav Hapla   PetscBool flg;
66905d80c0bfSVaclav Hapla   DMLabel   label;
6691c58f1c22SToby Isaac 
6692c58f1c22SToby Isaac   PetscFunctionBegin;
6693c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
66944f572ea9SToby Isaac   PetscAssertPointer(name, 2);
66959566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
6696c58f1c22SToby Isaac   if (!flg) {
66979566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
66989566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
66999566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
6700c58f1c22SToby Isaac   }
67013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6702c58f1c22SToby Isaac }
6703c58f1c22SToby Isaac 
6704cc4c1da9SBarry Smith /*@
6705bb7acecfSBarry 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.
67060fdc7489SMatthew Knepley 
67070fdc7489SMatthew Knepley   Not Collective
67080fdc7489SMatthew Knepley 
67090fdc7489SMatthew Knepley   Input Parameters:
6710bb7acecfSBarry Smith + dm   - The `DM` object
67110fdc7489SMatthew Knepley . l    - The index for the label
67120fdc7489SMatthew Knepley - name - The label name
67130fdc7489SMatthew Knepley 
67140fdc7489SMatthew Knepley   Level: intermediate
67150fdc7489SMatthew Knepley 
67161cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateLabel()`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
67170fdc7489SMatthew Knepley @*/
6718d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[])
6719d71ae5a4SJacob Faibussowitsch {
67200fdc7489SMatthew Knepley   DMLabelLink orig, prev = NULL;
67210fdc7489SMatthew Knepley   DMLabel     label;
67220fdc7489SMatthew Knepley   PetscInt    Nl, m;
67230fdc7489SMatthew Knepley   PetscBool   flg, match;
67240fdc7489SMatthew Knepley   const char *lname;
67250fdc7489SMatthew Knepley 
67260fdc7489SMatthew Knepley   PetscFunctionBegin;
67270fdc7489SMatthew Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67284f572ea9SToby Isaac   PetscAssertPointer(name, 3);
67299566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
67300fdc7489SMatthew Knepley   if (!flg) {
67319566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
67329566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
67339566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
67340fdc7489SMatthew Knepley   }
67359566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
673663a3b9bcSJacob Faibussowitsch   PetscCheck(l < Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", l, Nl);
67370fdc7489SMatthew Knepley   for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) {
67389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)orig->label, &lname));
67399566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &match));
67400fdc7489SMatthew Knepley     if (match) break;
67410fdc7489SMatthew Knepley   }
67423ba16761SJacob Faibussowitsch   if (m == l) PetscFunctionReturn(PETSC_SUCCESS);
67430fdc7489SMatthew Knepley   if (!m) dm->labels = orig->next;
67440fdc7489SMatthew Knepley   else prev->next = orig->next;
67450fdc7489SMatthew Knepley   if (!l) {
67460fdc7489SMatthew Knepley     orig->next = dm->labels;
67470fdc7489SMatthew Knepley     dm->labels = orig;
67480fdc7489SMatthew Knepley   } else {
6749fbccb6d4SPierre Jolivet     for (m = 0, prev = dm->labels; m < l - 1; ++m, prev = prev->next);
67500fdc7489SMatthew Knepley     orig->next = prev->next;
67510fdc7489SMatthew Knepley     prev->next = orig;
67520fdc7489SMatthew Knepley   }
67533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67540fdc7489SMatthew Knepley }
67550fdc7489SMatthew Knepley 
6756cc4c1da9SBarry Smith /*@
6757bb7acecfSBarry Smith   DMGetLabelValue - Get the value in a `DMLabel` for the given point, with -1 as the default
6758c58f1c22SToby Isaac 
6759c58f1c22SToby Isaac   Not Collective
6760c58f1c22SToby Isaac 
6761c58f1c22SToby Isaac   Input Parameters:
6762bb7acecfSBarry Smith + dm    - The `DM` object
6763c58f1c22SToby Isaac . name  - The label name
6764c58f1c22SToby Isaac - point - The mesh point
6765c58f1c22SToby Isaac 
6766c58f1c22SToby Isaac   Output Parameter:
6767c58f1c22SToby Isaac . value - The label value for this point, or -1 if the point is not in the label
6768c58f1c22SToby Isaac 
6769c58f1c22SToby Isaac   Level: beginner
6770c58f1c22SToby Isaac 
67711cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6772c58f1c22SToby Isaac @*/
6773d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
6774d71ae5a4SJacob Faibussowitsch {
6775c58f1c22SToby Isaac   DMLabel label;
6776c58f1c22SToby Isaac 
6777c58f1c22SToby Isaac   PetscFunctionBegin;
6778c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67794f572ea9SToby Isaac   PetscAssertPointer(name, 2);
67809566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
67817a8be351SBarry Smith   PetscCheck(label, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
67829566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, point, value));
67833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6784c58f1c22SToby Isaac }
6785c58f1c22SToby Isaac 
6786cc4c1da9SBarry Smith /*@
6787bb7acecfSBarry Smith   DMSetLabelValue - Add a point to a `DMLabel` with given value
6788c58f1c22SToby Isaac 
6789c58f1c22SToby Isaac   Not Collective
6790c58f1c22SToby Isaac 
6791c58f1c22SToby Isaac   Input Parameters:
6792bb7acecfSBarry Smith + dm    - The `DM` object
6793c58f1c22SToby Isaac . name  - The label name
6794c58f1c22SToby Isaac . point - The mesh point
6795c58f1c22SToby Isaac - value - The label value for this point
6796c58f1c22SToby Isaac 
6797c58f1c22SToby Isaac   Output Parameter:
6798c58f1c22SToby Isaac 
6799c58f1c22SToby Isaac   Level: beginner
6800c58f1c22SToby Isaac 
68011cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelSetValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6802c58f1c22SToby Isaac @*/
6803d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6804d71ae5a4SJacob Faibussowitsch {
6805c58f1c22SToby Isaac   DMLabel label;
6806c58f1c22SToby Isaac 
6807c58f1c22SToby Isaac   PetscFunctionBegin;
6808c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68094f572ea9SToby Isaac   PetscAssertPointer(name, 2);
68109566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6811c58f1c22SToby Isaac   if (!label) {
68129566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
68139566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
6814c58f1c22SToby Isaac   }
68159566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, point, value));
68163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6817c58f1c22SToby Isaac }
6818c58f1c22SToby Isaac 
6819cc4c1da9SBarry Smith /*@
6820bb7acecfSBarry Smith   DMClearLabelValue - Remove a point from a `DMLabel` with given value
6821c58f1c22SToby Isaac 
6822c58f1c22SToby Isaac   Not Collective
6823c58f1c22SToby Isaac 
6824c58f1c22SToby Isaac   Input Parameters:
6825bb7acecfSBarry Smith + dm    - The `DM` object
6826c58f1c22SToby Isaac . name  - The label name
6827c58f1c22SToby Isaac . point - The mesh point
6828c58f1c22SToby Isaac - value - The label value for this point
6829c58f1c22SToby Isaac 
6830c58f1c22SToby Isaac   Level: beginner
6831c58f1c22SToby Isaac 
68321cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelClearValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6833c58f1c22SToby Isaac @*/
6834d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6835d71ae5a4SJacob Faibussowitsch {
6836c58f1c22SToby Isaac   DMLabel label;
6837c58f1c22SToby Isaac 
6838c58f1c22SToby Isaac   PetscFunctionBegin;
6839c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68404f572ea9SToby Isaac   PetscAssertPointer(name, 2);
68419566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
68423ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
68439566063dSJacob Faibussowitsch   PetscCall(DMLabelClearValue(label, point, value));
68443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6845c58f1c22SToby Isaac }
6846c58f1c22SToby Isaac 
6847cc4c1da9SBarry Smith /*@
6848bb7acecfSBarry Smith   DMGetLabelSize - Get the value of `DMLabelGetNumValues()` of a `DMLabel` in the `DM`
6849c58f1c22SToby Isaac 
6850c58f1c22SToby Isaac   Not Collective
6851c58f1c22SToby Isaac 
6852c58f1c22SToby Isaac   Input Parameters:
6853bb7acecfSBarry Smith + dm   - The `DM` object
6854c58f1c22SToby Isaac - name - The label name
6855c58f1c22SToby Isaac 
6856c58f1c22SToby Isaac   Output Parameter:
6857c58f1c22SToby Isaac . size - The number of different integer ids, or 0 if the label does not exist
6858c58f1c22SToby Isaac 
6859c58f1c22SToby Isaac   Level: beginner
6860c58f1c22SToby Isaac 
686173ff1848SBarry Smith   Developer Note:
6862bb7acecfSBarry Smith   This should be renamed to something like `DMGetLabelNumValues()` or removed.
6863bb7acecfSBarry Smith 
68641cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetNumValues()`, `DMSetLabelValue()`, `DMGetLabel()`
6865c58f1c22SToby Isaac @*/
6866d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
6867d71ae5a4SJacob Faibussowitsch {
6868c58f1c22SToby Isaac   DMLabel label;
6869c58f1c22SToby Isaac 
6870c58f1c22SToby Isaac   PetscFunctionBegin;
6871c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68724f572ea9SToby Isaac   PetscAssertPointer(name, 2);
68734f572ea9SToby Isaac   PetscAssertPointer(size, 3);
68749566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6875c58f1c22SToby Isaac   *size = 0;
68763ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
68779566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, size));
68783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6879c58f1c22SToby Isaac }
6880c58f1c22SToby Isaac 
6881cc4c1da9SBarry Smith /*@
6882bb7acecfSBarry Smith   DMGetLabelIdIS - Get the `DMLabelGetValueIS()` from a `DMLabel` in the `DM`
6883c58f1c22SToby Isaac 
6884c58f1c22SToby Isaac   Not Collective
6885c58f1c22SToby Isaac 
6886c58f1c22SToby Isaac   Input Parameters:
688760225df5SJacob Faibussowitsch + dm   - The `DM` object
6888c58f1c22SToby Isaac - name - The label name
6889c58f1c22SToby Isaac 
6890c58f1c22SToby Isaac   Output Parameter:
689120f4b53cSBarry Smith . ids - The integer ids, or `NULL` if the label does not exist
6892c58f1c22SToby Isaac 
6893c58f1c22SToby Isaac   Level: beginner
6894c58f1c22SToby Isaac 
68951cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetValueIS()`, `DMGetLabelSize()`
6896c58f1c22SToby Isaac @*/
6897d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
6898d71ae5a4SJacob Faibussowitsch {
6899c58f1c22SToby Isaac   DMLabel label;
6900c58f1c22SToby Isaac 
6901c58f1c22SToby Isaac   PetscFunctionBegin;
6902c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69034f572ea9SToby Isaac   PetscAssertPointer(name, 2);
69044f572ea9SToby Isaac   PetscAssertPointer(ids, 3);
69059566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6906c58f1c22SToby Isaac   *ids = NULL;
6907dab2e251SBlaise Bourdin   if (label) {
69089566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, ids));
6909dab2e251SBlaise Bourdin   } else {
6910dab2e251SBlaise Bourdin     /* returning an empty IS */
69119566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, ids));
6912dab2e251SBlaise Bourdin   }
69133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6914c58f1c22SToby Isaac }
6915c58f1c22SToby Isaac 
6916cc4c1da9SBarry Smith /*@
6917c58f1c22SToby Isaac   DMGetStratumSize - Get the number of points in a label stratum
6918c58f1c22SToby Isaac 
6919c58f1c22SToby Isaac   Not Collective
6920c58f1c22SToby Isaac 
6921c58f1c22SToby Isaac   Input Parameters:
6922bb7acecfSBarry Smith + dm    - The `DM` object
6923b6971eaeSBarry Smith . name  - The label name of the stratum
6924c58f1c22SToby Isaac - value - The stratum value
6925c58f1c22SToby Isaac 
6926c58f1c22SToby Isaac   Output Parameter:
6927bb7acecfSBarry Smith . size - The number of points, also called the stratum size
6928c58f1c22SToby Isaac 
6929c58f1c22SToby Isaac   Level: beginner
6930c58f1c22SToby Isaac 
69311cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetStratumSize()`, `DMGetLabelSize()`, `DMGetLabelIds()`
6932c58f1c22SToby Isaac @*/
6933d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
6934d71ae5a4SJacob Faibussowitsch {
6935c58f1c22SToby Isaac   DMLabel label;
6936c58f1c22SToby Isaac 
6937c58f1c22SToby Isaac   PetscFunctionBegin;
6938c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69394f572ea9SToby Isaac   PetscAssertPointer(name, 2);
69404f572ea9SToby Isaac   PetscAssertPointer(size, 4);
69419566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6942c58f1c22SToby Isaac   *size = 0;
69433ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
69449566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize(label, value, size));
69453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6946c58f1c22SToby Isaac }
6947c58f1c22SToby Isaac 
6948cc4c1da9SBarry Smith /*@
6949c58f1c22SToby Isaac   DMGetStratumIS - Get the points in a label stratum
6950c58f1c22SToby Isaac 
6951c58f1c22SToby Isaac   Not Collective
6952c58f1c22SToby Isaac 
6953c58f1c22SToby Isaac   Input Parameters:
6954bb7acecfSBarry Smith + dm    - The `DM` object
6955c58f1c22SToby Isaac . name  - The label name
6956c58f1c22SToby Isaac - value - The stratum value
6957c58f1c22SToby Isaac 
6958c58f1c22SToby Isaac   Output Parameter:
695920f4b53cSBarry Smith . points - The stratum points, or `NULL` if the label does not exist or does not have that value
6960c58f1c22SToby Isaac 
6961c58f1c22SToby Isaac   Level: beginner
6962c58f1c22SToby Isaac 
69631cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetStratumIS()`, `DMGetStratumSize()`
6964c58f1c22SToby Isaac @*/
6965d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
6966d71ae5a4SJacob Faibussowitsch {
6967c58f1c22SToby Isaac   DMLabel label;
6968c58f1c22SToby Isaac 
6969c58f1c22SToby Isaac   PetscFunctionBegin;
6970c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69714f572ea9SToby Isaac   PetscAssertPointer(name, 2);
69724f572ea9SToby Isaac   PetscAssertPointer(points, 4);
69739566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6974c58f1c22SToby Isaac   *points = NULL;
69753ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
69769566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, points));
69773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6978c58f1c22SToby Isaac }
6979c58f1c22SToby Isaac 
6980cc4c1da9SBarry Smith /*@
69819044fa66SMatthew G. Knepley   DMSetStratumIS - Set the points in a label stratum
69824de306b1SToby Isaac 
69834de306b1SToby Isaac   Not Collective
69844de306b1SToby Isaac 
69854de306b1SToby Isaac   Input Parameters:
6986bb7acecfSBarry Smith + dm     - The `DM` object
69874de306b1SToby Isaac . name   - The label name
69884de306b1SToby Isaac . value  - The stratum value
69894de306b1SToby Isaac - points - The stratum points
69904de306b1SToby Isaac 
69914de306b1SToby Isaac   Level: beginner
69924de306b1SToby Isaac 
69931cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMClearLabelStratum()`, `DMLabelClearStratum()`, `DMLabelSetStratumIS()`, `DMGetStratumSize()`
69944de306b1SToby Isaac @*/
6995d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
6996d71ae5a4SJacob Faibussowitsch {
69974de306b1SToby Isaac   DMLabel label;
69984de306b1SToby Isaac 
69994de306b1SToby Isaac   PetscFunctionBegin;
70004de306b1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70014f572ea9SToby Isaac   PetscAssertPointer(name, 2);
7002292bffcbSToby Isaac   PetscValidHeaderSpecific(points, IS_CLASSID, 4);
70039566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
70043ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
70059566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, points));
70063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70074de306b1SToby Isaac }
70084de306b1SToby Isaac 
7009cc4c1da9SBarry Smith /*@
7010bb7acecfSBarry Smith   DMClearLabelStratum - Remove all points from a stratum from a `DMLabel`
7011c58f1c22SToby Isaac 
7012c58f1c22SToby Isaac   Not Collective
7013c58f1c22SToby Isaac 
7014c58f1c22SToby Isaac   Input Parameters:
7015bb7acecfSBarry Smith + dm    - The `DM` object
7016c58f1c22SToby Isaac . name  - The label name
7017c58f1c22SToby Isaac - value - The label value for this point
7018c58f1c22SToby Isaac 
7019c58f1c22SToby Isaac   Output Parameter:
7020c58f1c22SToby Isaac 
7021c58f1c22SToby Isaac   Level: beginner
7022c58f1c22SToby Isaac 
70231cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMLabelClearStratum()`, `DMSetLabelValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
7024c58f1c22SToby Isaac @*/
7025d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
7026d71ae5a4SJacob Faibussowitsch {
7027c58f1c22SToby Isaac   DMLabel label;
7028c58f1c22SToby Isaac 
7029c58f1c22SToby Isaac   PetscFunctionBegin;
7030c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70314f572ea9SToby Isaac   PetscAssertPointer(name, 2);
70329566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
70333ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
70349566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
70353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7036c58f1c22SToby Isaac }
7037c58f1c22SToby Isaac 
7038c58f1c22SToby Isaac /*@
7039bb7acecfSBarry Smith   DMGetNumLabels - Return the number of labels defined by on the `DM`
7040c58f1c22SToby Isaac 
7041c58f1c22SToby Isaac   Not Collective
7042c58f1c22SToby Isaac 
7043c58f1c22SToby Isaac   Input Parameter:
7044bb7acecfSBarry Smith . dm - The `DM` object
7045c58f1c22SToby Isaac 
7046c58f1c22SToby Isaac   Output Parameter:
7047c58f1c22SToby Isaac . numLabels - the number of Labels
7048c58f1c22SToby Isaac 
7049c58f1c22SToby Isaac   Level: intermediate
7050c58f1c22SToby Isaac 
70511cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabelByNum()`, `DMGetLabelName()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7052c58f1c22SToby Isaac @*/
7053d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
7054d71ae5a4SJacob Faibussowitsch {
70555d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7056c58f1c22SToby Isaac   PetscInt    n    = 0;
7057c58f1c22SToby Isaac 
7058c58f1c22SToby Isaac   PetscFunctionBegin;
7059c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70604f572ea9SToby Isaac   PetscAssertPointer(numLabels, 2);
70619371c9d4SSatish Balay   while (next) {
70629371c9d4SSatish Balay     ++n;
70639371c9d4SSatish Balay     next = next->next;
70649371c9d4SSatish Balay   }
7065c58f1c22SToby Isaac   *numLabels = n;
70663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7067c58f1c22SToby Isaac }
7068c58f1c22SToby Isaac 
7069cc4c1da9SBarry Smith /*@
7070c58f1c22SToby Isaac   DMGetLabelName - Return the name of nth label
7071c58f1c22SToby Isaac 
7072c58f1c22SToby Isaac   Not Collective
7073c58f1c22SToby Isaac 
7074c58f1c22SToby Isaac   Input Parameters:
7075bb7acecfSBarry Smith + dm - The `DM` object
7076c58f1c22SToby Isaac - n  - the label number
7077c58f1c22SToby Isaac 
7078c58f1c22SToby Isaac   Output Parameter:
7079c58f1c22SToby Isaac . name - the label name
7080c58f1c22SToby Isaac 
7081c58f1c22SToby Isaac   Level: intermediate
7082c58f1c22SToby Isaac 
708373ff1848SBarry Smith   Developer Note:
7084bb7acecfSBarry Smith   Some of the functions that appropriate on labels using their number have the suffix ByNum, others do not.
7085bb7acecfSBarry Smith 
70861cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabelByNum()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7087c58f1c22SToby Isaac @*/
7088cc4c1da9SBarry Smith PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char *name[])
7089d71ae5a4SJacob Faibussowitsch {
70905d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7091c58f1c22SToby Isaac   PetscInt    l    = 0;
7092c58f1c22SToby Isaac 
7093c58f1c22SToby Isaac   PetscFunctionBegin;
7094c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70954f572ea9SToby Isaac   PetscAssertPointer(name, 3);
7096c58f1c22SToby Isaac   while (next) {
7097c58f1c22SToby Isaac     if (l == n) {
70989566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)next->label, name));
70993ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
7100c58f1c22SToby Isaac     }
7101c58f1c22SToby Isaac     ++l;
7102c58f1c22SToby Isaac     next = next->next;
7103c58f1c22SToby Isaac   }
710463a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
7105c58f1c22SToby Isaac }
7106c58f1c22SToby Isaac 
7107cc4c1da9SBarry Smith /*@
7108bb7acecfSBarry Smith   DMHasLabel - Determine whether the `DM` has a label of a given name
7109c58f1c22SToby Isaac 
7110c58f1c22SToby Isaac   Not Collective
7111c58f1c22SToby Isaac 
7112c58f1c22SToby Isaac   Input Parameters:
7113bb7acecfSBarry Smith + dm   - The `DM` object
7114c58f1c22SToby Isaac - name - The label name
7115c58f1c22SToby Isaac 
7116c58f1c22SToby Isaac   Output Parameter:
7117bb7acecfSBarry Smith . hasLabel - `PETSC_TRUE` if the label is present
7118c58f1c22SToby Isaac 
7119c58f1c22SToby Isaac   Level: intermediate
7120c58f1c22SToby Isaac 
71211cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabel()`, `DMGetLabelByNum()`, `DMCreateLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7122c58f1c22SToby Isaac @*/
7123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
7124d71ae5a4SJacob Faibussowitsch {
71255d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7126d67d17b1SMatthew G. Knepley   const char *lname;
7127c58f1c22SToby Isaac 
7128c58f1c22SToby Isaac   PetscFunctionBegin;
7129c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71304f572ea9SToby Isaac   PetscAssertPointer(name, 2);
71314f572ea9SToby Isaac   PetscAssertPointer(hasLabel, 3);
7132c58f1c22SToby Isaac   *hasLabel = PETSC_FALSE;
7133c58f1c22SToby Isaac   while (next) {
71349566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
71359566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, hasLabel));
7136c58f1c22SToby Isaac     if (*hasLabel) break;
7137c58f1c22SToby Isaac     next = next->next;
7138c58f1c22SToby Isaac   }
71393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7140c58f1c22SToby Isaac }
7141c58f1c22SToby Isaac 
7142a4e35b19SJacob Faibussowitsch // PetscClangLinter pragma ignore: -fdoc-section-header-unknown
7143cc4c1da9SBarry Smith /*@
714420f4b53cSBarry Smith   DMGetLabel - Return the label of a given name, or `NULL`, from a `DM`
7145c58f1c22SToby Isaac 
7146c58f1c22SToby Isaac   Not Collective
7147c58f1c22SToby Isaac 
7148c58f1c22SToby Isaac   Input Parameters:
7149bb7acecfSBarry Smith + dm   - The `DM` object
7150c58f1c22SToby Isaac - name - The label name
7151c58f1c22SToby Isaac 
7152c58f1c22SToby Isaac   Output Parameter:
715320f4b53cSBarry Smith . label - The `DMLabel`, or `NULL` if the label is absent
7154c58f1c22SToby Isaac 
7155bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
7156bb7acecfSBarry Smith + "depth"       - Holds the depth (co-dimension) of each mesh point
7157bb7acecfSBarry Smith . "celltype"    - Holds the topological type of each cell
7158bb7acecfSBarry Smith . "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
7159bb7acecfSBarry Smith . "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
7160bb7acecfSBarry Smith . "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
7161bb7acecfSBarry Smith - "Vertex Sets" - Mirrors the vertex sets defined by GMsh
71626d7c9049SMatthew G. Knepley 
7163c58f1c22SToby Isaac   Level: intermediate
7164c58f1c22SToby Isaac 
716560225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMHasLabel()`, `DMGetLabelByNum()`, `DMAddLabel()`, `DMCreateLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
7166c58f1c22SToby Isaac @*/
7167d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
7168d71ae5a4SJacob Faibussowitsch {
71695d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7170c58f1c22SToby Isaac   PetscBool   hasLabel;
7171d67d17b1SMatthew G. Knepley   const char *lname;
7172c58f1c22SToby Isaac 
7173c58f1c22SToby Isaac   PetscFunctionBegin;
7174c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71754f572ea9SToby Isaac   PetscAssertPointer(name, 2);
71764f572ea9SToby Isaac   PetscAssertPointer(label, 3);
7177c58f1c22SToby Isaac   *label = NULL;
7178c58f1c22SToby Isaac   while (next) {
71799566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
71809566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
7181c58f1c22SToby Isaac     if (hasLabel) {
7182c58f1c22SToby Isaac       *label = next->label;
7183c58f1c22SToby Isaac       break;
7184c58f1c22SToby Isaac     }
7185c58f1c22SToby Isaac     next = next->next;
7186c58f1c22SToby Isaac   }
71873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7188c58f1c22SToby Isaac }
7189c58f1c22SToby Isaac 
7190cc4c1da9SBarry Smith /*@
7191bb7acecfSBarry Smith   DMGetLabelByNum - Return the nth label on a `DM`
7192c58f1c22SToby Isaac 
7193c58f1c22SToby Isaac   Not Collective
7194c58f1c22SToby Isaac 
7195c58f1c22SToby Isaac   Input Parameters:
7196bb7acecfSBarry Smith + dm - The `DM` object
7197c58f1c22SToby Isaac - n  - the label number
7198c58f1c22SToby Isaac 
7199c58f1c22SToby Isaac   Output Parameter:
7200c58f1c22SToby Isaac . label - the label
7201c58f1c22SToby Isaac 
7202c58f1c22SToby Isaac   Level: intermediate
7203c58f1c22SToby Isaac 
72041cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7205c58f1c22SToby Isaac @*/
7206d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
7207d71ae5a4SJacob Faibussowitsch {
72085d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7209c58f1c22SToby Isaac   PetscInt    l    = 0;
7210c58f1c22SToby Isaac 
7211c58f1c22SToby Isaac   PetscFunctionBegin;
7212c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72134f572ea9SToby Isaac   PetscAssertPointer(label, 3);
7214c58f1c22SToby Isaac   while (next) {
7215c58f1c22SToby Isaac     if (l == n) {
7216c58f1c22SToby Isaac       *label = next->label;
72173ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
7218c58f1c22SToby Isaac     }
7219c58f1c22SToby Isaac     ++l;
7220c58f1c22SToby Isaac     next = next->next;
7221c58f1c22SToby Isaac   }
722263a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
7223c58f1c22SToby Isaac }
7224c58f1c22SToby Isaac 
7225cc4c1da9SBarry Smith /*@
7226bb7acecfSBarry Smith   DMAddLabel - Add the label to this `DM`
7227c58f1c22SToby Isaac 
7228c58f1c22SToby Isaac   Not Collective
7229c58f1c22SToby Isaac 
7230c58f1c22SToby Isaac   Input Parameters:
7231bb7acecfSBarry Smith + dm    - The `DM` object
7232bb7acecfSBarry Smith - label - The `DMLabel`
7233c58f1c22SToby Isaac 
7234c58f1c22SToby Isaac   Level: developer
7235c58f1c22SToby Isaac 
723660225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7237c58f1c22SToby Isaac @*/
7238d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddLabel(DM dm, DMLabel label)
7239d71ae5a4SJacob Faibussowitsch {
72405d80c0bfSVaclav Hapla   DMLabelLink l, *p, tmpLabel;
7241c58f1c22SToby Isaac   PetscBool   hasLabel;
7242d67d17b1SMatthew G. Knepley   const char *lname;
72435d80c0bfSVaclav Hapla   PetscBool   flg;
7244c58f1c22SToby Isaac 
7245c58f1c22SToby Isaac   PetscFunctionBegin;
7246c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72479566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
72489566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, lname, &hasLabel));
72497a8be351SBarry Smith   PetscCheck(!hasLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname);
72509566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(1, &tmpLabel));
7251c58f1c22SToby Isaac   tmpLabel->label  = label;
7252c58f1c22SToby Isaac   tmpLabel->output = PETSC_TRUE;
72535d80c0bfSVaclav Hapla   for (p = &dm->labels; (l = *p); p = &l->next) { }
72545d80c0bfSVaclav Hapla   *p = tmpLabel;
72559566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
72569566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "depth", &flg));
72575d80c0bfSVaclav Hapla   if (flg) dm->depthLabel = label;
72589566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "celltype", &flg));
7259ba2698f1SMatthew G. Knepley   if (flg) dm->celltypeLabel = label;
72603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7261c58f1c22SToby Isaac }
7262c58f1c22SToby Isaac 
7263a4e35b19SJacob Faibussowitsch // PetscClangLinter pragma ignore: -fdoc-section-header-unknown
7264cc4c1da9SBarry Smith /*@
72654a7ee7d0SMatthew G. Knepley   DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present
72664a7ee7d0SMatthew G. Knepley 
72674a7ee7d0SMatthew G. Knepley   Not Collective
72684a7ee7d0SMatthew G. Knepley 
72694a7ee7d0SMatthew G. Knepley   Input Parameters:
7270bb7acecfSBarry Smith + dm    - The `DM` object
7271bb7acecfSBarry Smith - label - The `DMLabel`, having the same name, to substitute
72724a7ee7d0SMatthew G. Knepley 
7273bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
7274bb7acecfSBarry Smith + "depth"       - Holds the depth (co-dimension) of each mesh point
7275bb7acecfSBarry Smith . "celltype"    - Holds the topological type of each cell
7276bb7acecfSBarry Smith . "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
7277bb7acecfSBarry Smith . "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
7278bb7acecfSBarry Smith . "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
7279bb7acecfSBarry Smith - "Vertex Sets" - Mirrors the vertex sets defined by GMsh
72804a7ee7d0SMatthew G. Knepley 
72814a7ee7d0SMatthew G. Knepley   Level: intermediate
72824a7ee7d0SMatthew G. Knepley 
72831cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
72844a7ee7d0SMatthew G. Knepley @*/
7285d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabel(DM dm, DMLabel label)
7286d71ae5a4SJacob Faibussowitsch {
72874a7ee7d0SMatthew G. Knepley   DMLabelLink next = dm->labels;
72884a7ee7d0SMatthew G. Knepley   PetscBool   hasLabel, flg;
72894a7ee7d0SMatthew G. Knepley   const char *name, *lname;
72904a7ee7d0SMatthew G. Knepley 
72914a7ee7d0SMatthew G. Knepley   PetscFunctionBegin;
72924a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72934a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
72949566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
72954a7ee7d0SMatthew G. Knepley   while (next) {
72969566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
72979566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
72984a7ee7d0SMatthew G. Knepley     if (hasLabel) {
72999566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)label));
73009566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "depth", &flg));
73014a7ee7d0SMatthew G. Knepley       if (flg) dm->depthLabel = label;
73029566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "celltype", &flg));
73034a7ee7d0SMatthew G. Knepley       if (flg) dm->celltypeLabel = label;
73049566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&next->label));
73054a7ee7d0SMatthew G. Knepley       next->label = label;
73064a7ee7d0SMatthew G. Knepley       break;
73074a7ee7d0SMatthew G. Knepley     }
73084a7ee7d0SMatthew G. Knepley     next = next->next;
73094a7ee7d0SMatthew G. Knepley   }
73103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
73114a7ee7d0SMatthew G. Knepley }
73124a7ee7d0SMatthew G. Knepley 
7313cc4c1da9SBarry Smith /*@
7314bb7acecfSBarry Smith   DMRemoveLabel - Remove the label given by name from this `DM`
7315c58f1c22SToby Isaac 
7316c58f1c22SToby Isaac   Not Collective
7317c58f1c22SToby Isaac 
7318c58f1c22SToby Isaac   Input Parameters:
7319bb7acecfSBarry Smith + dm   - The `DM` object
7320c58f1c22SToby Isaac - name - The label name
7321c58f1c22SToby Isaac 
7322c58f1c22SToby Isaac   Output Parameter:
732320f4b53cSBarry Smith . label - The `DMLabel`, or `NULL` if the label is absent. Pass in `NULL` to call `DMLabelDestroy()` on the label, otherwise the
7324bb7acecfSBarry Smith           caller is responsible for calling `DMLabelDestroy()`.
7325c58f1c22SToby Isaac 
7326c58f1c22SToby Isaac   Level: developer
7327c58f1c22SToby Isaac 
73281cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabelBySelf()`
7329c58f1c22SToby Isaac @*/
7330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
7331d71ae5a4SJacob Faibussowitsch {
733295d578d6SVaclav Hapla   DMLabelLink link, *pnext;
7333c58f1c22SToby Isaac   PetscBool   hasLabel;
7334d67d17b1SMatthew G. Knepley   const char *lname;
7335c58f1c22SToby Isaac 
7336c58f1c22SToby Isaac   PetscFunctionBegin;
7337c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73384f572ea9SToby Isaac   PetscAssertPointer(name, 2);
7339e5472504SVaclav Hapla   if (label) {
73404f572ea9SToby Isaac     PetscAssertPointer(label, 3);
7341c58f1c22SToby Isaac     *label = NULL;
7342e5472504SVaclav Hapla   }
73435d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
73449566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)link->label, &lname));
73459566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
7346c58f1c22SToby Isaac     if (hasLabel) {
734795d578d6SVaclav Hapla       *pnext = link->next; /* Remove from list */
73489566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &hasLabel));
734995d578d6SVaclav Hapla       if (hasLabel) dm->depthLabel = NULL;
73509566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &hasLabel));
7351ba2698f1SMatthew G. Knepley       if (hasLabel) dm->celltypeLabel = NULL;
735295d578d6SVaclav Hapla       if (label) *label = link->label;
73539566063dSJacob Faibussowitsch       else PetscCall(DMLabelDestroy(&link->label));
73549566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7355c58f1c22SToby Isaac       break;
7356c58f1c22SToby Isaac     }
7357c58f1c22SToby Isaac   }
73583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7359c58f1c22SToby Isaac }
7360c58f1c22SToby Isaac 
7361306894acSVaclav Hapla /*@
7362bb7acecfSBarry Smith   DMRemoveLabelBySelf - Remove the label from this `DM`
7363306894acSVaclav Hapla 
7364306894acSVaclav Hapla   Not Collective
7365306894acSVaclav Hapla 
7366306894acSVaclav Hapla   Input Parameters:
7367bb7acecfSBarry Smith + dm           - The `DM` object
7368bb7acecfSBarry Smith . label        - The `DMLabel` to be removed from the `DM`
736920f4b53cSBarry Smith - failNotFound - Should it fail if the label is not found in the `DM`?
7370306894acSVaclav Hapla 
7371306894acSVaclav Hapla   Level: developer
7372306894acSVaclav Hapla 
7373bb7acecfSBarry Smith   Note:
7374306894acSVaclav Hapla   Only exactly the same instance is removed if found, name match is ignored.
7375bb7acecfSBarry Smith   If the `DM` has an exclusive reference to the label, the label gets destroyed and
7376306894acSVaclav Hapla   *label nullified.
7377306894acSVaclav Hapla 
73781cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()` `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabel()`
7379306894acSVaclav Hapla @*/
7380d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound)
7381d71ae5a4SJacob Faibussowitsch {
738243e45a93SVaclav Hapla   DMLabelLink link, *pnext;
7383306894acSVaclav Hapla   PetscBool   hasLabel = PETSC_FALSE;
7384306894acSVaclav Hapla 
7385306894acSVaclav Hapla   PetscFunctionBegin;
7386306894acSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73874f572ea9SToby Isaac   PetscAssertPointer(label, 2);
73883ba16761SJacob Faibussowitsch   if (!*label && !failNotFound) PetscFunctionReturn(PETSC_SUCCESS);
7389306894acSVaclav Hapla   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2);
7390306894acSVaclav Hapla   PetscValidLogicalCollectiveBool(dm, failNotFound, 3);
73915d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
739243e45a93SVaclav Hapla     if (*label == link->label) {
7393306894acSVaclav Hapla       hasLabel = PETSC_TRUE;
739443e45a93SVaclav Hapla       *pnext   = link->next; /* Remove from list */
7395306894acSVaclav Hapla       if (*label == dm->depthLabel) dm->depthLabel = NULL;
7396ba2698f1SMatthew G. Knepley       if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL;
739743e45a93SVaclav Hapla       if (((PetscObject)link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */
73989566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&link->label));
73999566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7400306894acSVaclav Hapla       break;
7401306894acSVaclav Hapla     }
7402306894acSVaclav Hapla   }
74037a8be351SBarry Smith   PetscCheck(hasLabel || !failNotFound, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM");
74043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7405306894acSVaclav Hapla }
7406306894acSVaclav Hapla 
7407cc4c1da9SBarry Smith /*@
7408c58f1c22SToby Isaac   DMGetLabelOutput - Get the output flag for a given label
7409c58f1c22SToby Isaac 
7410c58f1c22SToby Isaac   Not Collective
7411c58f1c22SToby Isaac 
7412c58f1c22SToby Isaac   Input Parameters:
7413bb7acecfSBarry Smith + dm   - The `DM` object
7414c58f1c22SToby Isaac - name - The label name
7415c58f1c22SToby Isaac 
7416c58f1c22SToby Isaac   Output Parameter:
7417c58f1c22SToby Isaac . output - The flag for output
7418c58f1c22SToby Isaac 
7419c58f1c22SToby Isaac   Level: developer
7420c58f1c22SToby Isaac 
74211cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMSetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7422c58f1c22SToby Isaac @*/
7423d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
7424d71ae5a4SJacob Faibussowitsch {
74255d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7426d67d17b1SMatthew G. Knepley   const char *lname;
7427c58f1c22SToby Isaac 
7428c58f1c22SToby Isaac   PetscFunctionBegin;
7429c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
74304f572ea9SToby Isaac   PetscAssertPointer(name, 2);
74314f572ea9SToby Isaac   PetscAssertPointer(output, 3);
7432c58f1c22SToby Isaac   while (next) {
7433c58f1c22SToby Isaac     PetscBool flg;
7434c58f1c22SToby Isaac 
74359566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
74369566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
74379371c9d4SSatish Balay     if (flg) {
74389371c9d4SSatish Balay       *output = next->output;
74393ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
74409371c9d4SSatish Balay     }
7441c58f1c22SToby Isaac     next = next->next;
7442c58f1c22SToby Isaac   }
744398921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7444c58f1c22SToby Isaac }
7445c58f1c22SToby Isaac 
7446cc4c1da9SBarry Smith /*@
7447bb7acecfSBarry Smith   DMSetLabelOutput - Set if a given label should be saved to a `PetscViewer` in calls to `DMView()`
7448c58f1c22SToby Isaac 
7449c58f1c22SToby Isaac   Not Collective
7450c58f1c22SToby Isaac 
7451c58f1c22SToby Isaac   Input Parameters:
7452bb7acecfSBarry Smith + dm     - The `DM` object
7453c58f1c22SToby Isaac . name   - The label name
7454bb7acecfSBarry Smith - output - `PETSC_TRUE` to save the label to the viewer
7455c58f1c22SToby Isaac 
7456c58f1c22SToby Isaac   Level: developer
7457c58f1c22SToby Isaac 
74581cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetOutputFlag()`, `DMGetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7459c58f1c22SToby Isaac @*/
7460d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
7461d71ae5a4SJacob Faibussowitsch {
74625d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7463d67d17b1SMatthew G. Knepley   const char *lname;
7464c58f1c22SToby Isaac 
7465c58f1c22SToby Isaac   PetscFunctionBegin;
7466c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
74674f572ea9SToby Isaac   PetscAssertPointer(name, 2);
7468c58f1c22SToby Isaac   while (next) {
7469c58f1c22SToby Isaac     PetscBool flg;
7470c58f1c22SToby Isaac 
74719566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
74729566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
74739371c9d4SSatish Balay     if (flg) {
74749371c9d4SSatish Balay       next->output = output;
74753ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
74769371c9d4SSatish Balay     }
7477c58f1c22SToby Isaac     next = next->next;
7478c58f1c22SToby Isaac   }
747998921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7480c58f1c22SToby Isaac }
7481c58f1c22SToby Isaac 
7482c58f1c22SToby Isaac /*@
7483bb7acecfSBarry Smith   DMCopyLabels - Copy labels from one `DM` mesh to another `DM` with a superset of the points
7484c58f1c22SToby Isaac 
748520f4b53cSBarry Smith   Collective
7486c58f1c22SToby Isaac 
7487d8d19677SJose E. Roman   Input Parameters:
7488bb7acecfSBarry Smith + dmA   - The `DM` object with initial labels
7489bb7acecfSBarry Smith . dmB   - The `DM` object to which labels are copied
7490bb7acecfSBarry Smith . mode  - Copy labels by pointers (`PETSC_OWN_POINTER`) or duplicate them (`PETSC_COPY_VALUES`)
7491bb7acecfSBarry Smith . all   - Copy all labels including "depth", "dim", and "celltype" (`PETSC_TRUE`) which are otherwise ignored (`PETSC_FALSE`)
7492bb7acecfSBarry Smith - emode - How to behave when a `DMLabel` in the source and destination `DM`s with the same name is encountered (see `DMCopyLabelsMode`)
7493c58f1c22SToby Isaac 
7494c58f1c22SToby Isaac   Level: intermediate
7495c58f1c22SToby Isaac 
7496bb7acecfSBarry Smith   Note:
74972cbb9b06SVaclav Hapla   This is typically used when interpolating or otherwise adding to a mesh, or testing.
7498c58f1c22SToby Isaac 
74991cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`
7500c58f1c22SToby Isaac @*/
7501d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all, DMCopyLabelsMode emode)
7502d71ae5a4SJacob Faibussowitsch {
75032cbb9b06SVaclav Hapla   DMLabel     label, labelNew, labelOld;
7504c58f1c22SToby Isaac   const char *name;
7505c58f1c22SToby Isaac   PetscBool   flg;
75065d80c0bfSVaclav Hapla   DMLabelLink link;
7507c58f1c22SToby Isaac 
75085d80c0bfSVaclav Hapla   PetscFunctionBegin;
75095d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
75105d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
75115d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveEnum(dmA, mode, 3);
75125d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveBool(dmA, all, 4);
75137a8be351SBarry Smith   PetscCheck(mode != PETSC_USE_POINTER, PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects");
75143ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
75155d80c0bfSVaclav Hapla   for (link = dmA->labels; link; link = link->next) {
75165d80c0bfSVaclav Hapla     label = link->label;
75179566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
75185d80c0bfSVaclav Hapla     if (!all) {
75199566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &flg));
7520c58f1c22SToby Isaac       if (flg) continue;
75219566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "dim", &flg));
75227d5acc75SStefano Zampini       if (flg) continue;
75239566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &flg));
7524ba2698f1SMatthew G. Knepley       if (flg) continue;
75255d80c0bfSVaclav Hapla     }
75269566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dmB, name, &labelOld));
75272cbb9b06SVaclav Hapla     if (labelOld) {
75282cbb9b06SVaclav Hapla       switch (emode) {
7529d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_KEEP:
7530d71ae5a4SJacob Faibussowitsch         continue;
7531d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_REPLACE:
7532d71ae5a4SJacob Faibussowitsch         PetscCall(DMRemoveLabelBySelf(dmB, &labelOld, PETSC_TRUE));
7533d71ae5a4SJacob Faibussowitsch         break;
7534d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_FAIL:
7535d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in destination DM", name);
7536d71ae5a4SJacob Faibussowitsch       default:
7537d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Unhandled DMCopyLabelsMode %d", (int)emode);
75382cbb9b06SVaclav Hapla       }
75392cbb9b06SVaclav Hapla     }
75405d80c0bfSVaclav Hapla     if (mode == PETSC_COPY_VALUES) {
75419566063dSJacob Faibussowitsch       PetscCall(DMLabelDuplicate(label, &labelNew));
75425d80c0bfSVaclav Hapla     } else {
75435d80c0bfSVaclav Hapla       labelNew = label;
75445d80c0bfSVaclav Hapla     }
75459566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dmB, labelNew));
75469566063dSJacob Faibussowitsch     if (mode == PETSC_COPY_VALUES) PetscCall(DMLabelDestroy(&labelNew));
7547c58f1c22SToby Isaac   }
75483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7549c58f1c22SToby Isaac }
7550461a15a0SLisandro Dalcin 
7551609dae6eSVaclav Hapla /*@C
7552b4028c23SStefano Zampini   DMCompareLabels - Compare labels between two `DM` objects
7553609dae6eSVaclav Hapla 
755420f4b53cSBarry Smith   Collective; No Fortran Support
7555609dae6eSVaclav Hapla 
7556609dae6eSVaclav Hapla   Input Parameters:
7557bb7acecfSBarry Smith + dm0 - First `DM` object
7558bb7acecfSBarry Smith - dm1 - Second `DM` object
7559609dae6eSVaclav Hapla 
7560a4e35b19SJacob Faibussowitsch   Output Parameters:
75615efe38ccSVaclav Hapla + equal   - (Optional) Flag whether labels of dm0 and dm1 are the same
756220f4b53cSBarry Smith - message - (Optional) Message describing the difference, or `NULL` if there is no difference
7563609dae6eSVaclav Hapla 
7564609dae6eSVaclav Hapla   Level: intermediate
7565609dae6eSVaclav Hapla 
7566609dae6eSVaclav Hapla   Notes:
7567bb7acecfSBarry Smith   The output flag equal will be the same on all processes.
7568bb7acecfSBarry Smith 
756920f4b53cSBarry Smith   If equal is passed as `NULL` and difference is found, an error is thrown on all processes.
7570bb7acecfSBarry Smith 
757120f4b53cSBarry Smith   Make sure to pass equal is `NULL` on all processes or none of them.
7572609dae6eSVaclav Hapla 
75735efe38ccSVaclav Hapla   The output message is set independently on each rank.
7574bb7acecfSBarry Smith 
7575bb7acecfSBarry Smith   message must be freed with `PetscFree()`
7576bb7acecfSBarry Smith 
757720f4b53cSBarry Smith   If message is passed as `NULL` and a difference is found, the difference description is printed to stderr in synchronized manner.
7578bb7acecfSBarry Smith 
757920f4b53cSBarry Smith   Make sure to pass message as `NULL` on all processes or no processes.
7580609dae6eSVaclav Hapla 
7581609dae6eSVaclav Hapla   Labels are matched by name. If the number of labels and their names are equal,
7582bb7acecfSBarry Smith   `DMLabelCompare()` is used to compare each pair of labels with the same name.
7583609dae6eSVaclav Hapla 
7584cc4c1da9SBarry Smith   Developer Note:
7585cc4c1da9SBarry Smith   Can automatically generate the Fortran stub because `message` must be freed with `PetscFree()`
7586cc4c1da9SBarry Smith 
75871cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`, `DMLabelCompare()`
7588609dae6eSVaclav Hapla @*/
7589d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompareLabels(DM dm0, DM dm1, PetscBool *equal, char **message)
7590d71ae5a4SJacob Faibussowitsch {
75915efe38ccSVaclav Hapla   PetscInt    n, i;
7592609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
75935efe38ccSVaclav Hapla   PetscBool   eq;
7594609dae6eSVaclav Hapla   MPI_Comm    comm;
75955efe38ccSVaclav Hapla   PetscMPIInt rank;
7596609dae6eSVaclav Hapla 
7597609dae6eSVaclav Hapla   PetscFunctionBegin;
7598609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm0, DM_CLASSID, 1);
7599609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm1, DM_CLASSID, 2);
7600609dae6eSVaclav Hapla   PetscCheckSameComm(dm0, 1, dm1, 2);
76014f572ea9SToby Isaac   if (equal) PetscAssertPointer(equal, 3);
76024f572ea9SToby Isaac   if (message) PetscAssertPointer(message, 4);
76039566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm0, &comm));
76049566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
76055efe38ccSVaclav Hapla   {
76065efe38ccSVaclav Hapla     PetscInt n1;
76075efe38ccSVaclav Hapla 
76089566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm0, &n));
76099566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm1, &n1));
76105efe38ccSVaclav Hapla     eq = (PetscBool)(n == n1);
761148a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Number of labels in dm0 = %" PetscInt_FMT " != %" PetscInt_FMT " = Number of labels in dm1", n, n1));
7612462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
76135efe38ccSVaclav Hapla     if (!eq) goto finish;
76145efe38ccSVaclav Hapla   }
76155efe38ccSVaclav Hapla   for (i = 0; i < n; i++) {
7616609dae6eSVaclav Hapla     DMLabel     l0, l1;
7617609dae6eSVaclav Hapla     const char *name;
7618609dae6eSVaclav Hapla     char       *msgInner;
7619609dae6eSVaclav Hapla 
7620609dae6eSVaclav Hapla     /* Ignore label order */
76219566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm0, i, &l0));
76229566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)l0, &name));
76239566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm1, name, &l1));
7624609dae6eSVaclav Hapla     if (!l1) {
762563a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Label \"%s\" (#%" PetscInt_FMT " in dm0) not found in dm1", name, i));
76265efe38ccSVaclav Hapla       eq = PETSC_FALSE;
76275efe38ccSVaclav Hapla       break;
7628609dae6eSVaclav Hapla     }
76299566063dSJacob Faibussowitsch     PetscCall(DMLabelCompare(comm, l0, l1, &eq, &msgInner));
76309566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(msg, msgInner, sizeof(msg)));
76319566063dSJacob Faibussowitsch     PetscCall(PetscFree(msgInner));
76325efe38ccSVaclav Hapla     if (!eq) break;
7633609dae6eSVaclav Hapla   }
7634462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
7635609dae6eSVaclav Hapla finish:
76365efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
7637609dae6eSVaclav Hapla   if (message) {
7638609dae6eSVaclav Hapla     *message = NULL;
763948a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
76405efe38ccSVaclav Hapla   } else {
764148a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
76429566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
76435efe38ccSVaclav Hapla   }
76445efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
76455efe38ccSVaclav Hapla   if (equal) *equal = eq;
76467a8be351SBarry Smith   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels are not the same in dm0 and dm1");
76473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7648609dae6eSVaclav Hapla }
7649609dae6eSVaclav Hapla 
7650d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value)
7651d71ae5a4SJacob Faibussowitsch {
7652461a15a0SLisandro Dalcin   PetscFunctionBegin;
76534f572ea9SToby Isaac   PetscAssertPointer(label, 2);
7654461a15a0SLisandro Dalcin   if (!*label) {
76559566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
76569566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, label));
7657461a15a0SLisandro Dalcin   }
76589566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(*label, point, value));
76593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7660461a15a0SLisandro Dalcin }
7661461a15a0SLisandro Dalcin 
76620fdc7489SMatthew Knepley /*
76630fdc7489SMatthew Knepley   Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would
76640fdc7489SMatthew Knepley   like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every
76650fdc7489SMatthew Knepley   (label, id) pair in the DM.
76660fdc7489SMatthew Knepley 
76670fdc7489SMatthew Knepley   However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to
76680fdc7489SMatthew Knepley   each label.
76690fdc7489SMatthew Knepley */
7670d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal)
7671d71ae5a4SJacob Faibussowitsch {
76720fdc7489SMatthew Knepley   DMUniversalLabel ul;
76730fdc7489SMatthew Knepley   PetscBool       *active;
76740fdc7489SMatthew Knepley   PetscInt         pStart, pEnd, p, Nl, l, m;
76750fdc7489SMatthew Knepley 
76760fdc7489SMatthew Knepley   PetscFunctionBegin;
76779566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, &ul));
76789566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label));
76799566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
76809566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Nl, &active));
76810fdc7489SMatthew Knepley   ul->Nl = 0;
76820fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
76830fdc7489SMatthew Knepley     PetscBool   isdepth, iscelltype;
76840fdc7489SMatthew Knepley     const char *name;
76850fdc7489SMatthew Knepley 
76869566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
76879566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "depth", 6, &isdepth));
76889566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "celltype", 9, &iscelltype));
76890fdc7489SMatthew Knepley     active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE;
76900fdc7489SMatthew Knepley     if (active[l]) ++ul->Nl;
76910fdc7489SMatthew Knepley   }
76929566063dSJacob 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));
76930fdc7489SMatthew Knepley   ul->Nv = 0;
76940fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
76950fdc7489SMatthew Knepley     DMLabel     label;
76960fdc7489SMatthew Knepley     PetscInt    nv;
76970fdc7489SMatthew Knepley     const char *name;
76980fdc7489SMatthew Knepley 
76990fdc7489SMatthew Knepley     if (!active[l]) continue;
77009566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
77019566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
77029566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
77039566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &ul->names[m]));
77040fdc7489SMatthew Knepley     ul->indices[m] = l;
77050fdc7489SMatthew Knepley     ul->Nv += nv;
77060fdc7489SMatthew Knepley     ul->offsets[m + 1] = nv;
77070fdc7489SMatthew Knepley     ul->bits[m + 1]    = PetscCeilReal(PetscLog2Real(nv + 1));
77080fdc7489SMatthew Knepley     ++m;
77090fdc7489SMatthew Knepley   }
77100fdc7489SMatthew Knepley   for (l = 1; l <= ul->Nl; ++l) {
77110fdc7489SMatthew Knepley     ul->offsets[l] = ul->offsets[l - 1] + ul->offsets[l];
77120fdc7489SMatthew Knepley     ul->bits[l]    = ul->bits[l - 1] + ul->bits[l];
77130fdc7489SMatthew Knepley   }
77140fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
77150fdc7489SMatthew Knepley     PetscInt b;
77160fdc7489SMatthew Knepley 
77170fdc7489SMatthew Knepley     ul->masks[l] = 0;
77180fdc7489SMatthew Knepley     for (b = ul->bits[l]; b < ul->bits[l + 1]; ++b) ul->masks[l] |= 1 << b;
77190fdc7489SMatthew Knepley   }
77209566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ul->Nv, &ul->values));
77210fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
77220fdc7489SMatthew Knepley     DMLabel         label;
77230fdc7489SMatthew Knepley     IS              valueIS;
77240fdc7489SMatthew Knepley     const PetscInt *varr;
77250fdc7489SMatthew Knepley     PetscInt        nv, v;
77260fdc7489SMatthew Knepley 
77270fdc7489SMatthew Knepley     if (!active[l]) continue;
77289566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
77299566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
77309566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, &valueIS));
77319566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(valueIS, &varr));
7732ad540459SPierre Jolivet     for (v = 0; v < nv; ++v) ul->values[ul->offsets[m] + v] = varr[v];
77339566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(valueIS, &varr));
77349566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&valueIS));
77359566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(nv, &ul->values[ul->offsets[m]]));
77360fdc7489SMatthew Knepley     ++m;
77370fdc7489SMatthew Knepley   }
77389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
77390fdc7489SMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
77400fdc7489SMatthew Knepley     PetscInt  uval   = 0;
77410fdc7489SMatthew Knepley     PetscBool marked = PETSC_FALSE;
77420fdc7489SMatthew Knepley 
77430fdc7489SMatthew Knepley     for (l = 0, m = 0; l < Nl; ++l) {
77440fdc7489SMatthew Knepley       DMLabel  label;
77450649b39aSStefano Zampini       PetscInt val, defval, loc, nv;
77460fdc7489SMatthew Knepley 
77470fdc7489SMatthew Knepley       if (!active[l]) continue;
77489566063dSJacob Faibussowitsch       PetscCall(DMGetLabelByNum(dm, l, &label));
77499566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, p, &val));
77509566063dSJacob Faibussowitsch       PetscCall(DMLabelGetDefaultValue(label, &defval));
77519371c9d4SSatish Balay       if (val == defval) {
77529371c9d4SSatish Balay         ++m;
77539371c9d4SSatish Balay         continue;
77549371c9d4SSatish Balay       }
77550649b39aSStefano Zampini       nv     = ul->offsets[m + 1] - ul->offsets[m];
77560fdc7489SMatthew Knepley       marked = PETSC_TRUE;
77579566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc));
775863a3b9bcSJacob Faibussowitsch       PetscCheck(loc >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %" PetscInt_FMT " not found in compression array", val);
77590fdc7489SMatthew Knepley       uval += (loc + 1) << ul->bits[m];
77600fdc7489SMatthew Knepley       ++m;
77610fdc7489SMatthew Knepley     }
77629566063dSJacob Faibussowitsch     if (marked) PetscCall(DMLabelSetValue(ul->label, p, uval));
77630fdc7489SMatthew Knepley   }
77649566063dSJacob Faibussowitsch   PetscCall(PetscFree(active));
77650fdc7489SMatthew Knepley   *universal = ul;
77663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77670fdc7489SMatthew Knepley }
77680fdc7489SMatthew Knepley 
7769d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal)
7770d71ae5a4SJacob Faibussowitsch {
77710fdc7489SMatthew Knepley   PetscInt l;
77720fdc7489SMatthew Knepley 
77730fdc7489SMatthew Knepley   PetscFunctionBegin;
77749566063dSJacob Faibussowitsch   for (l = 0; l < (*universal)->Nl; ++l) PetscCall(PetscFree((*universal)->names[l]));
77759566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&(*universal)->label));
77769566063dSJacob Faibussowitsch   PetscCall(PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks));
77779566063dSJacob Faibussowitsch   PetscCall(PetscFree((*universal)->values));
77789566063dSJacob Faibussowitsch   PetscCall(PetscFree(*universal));
77790fdc7489SMatthew Knepley   *universal = NULL;
77803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77810fdc7489SMatthew Knepley }
77820fdc7489SMatthew Knepley 
7783d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel)
7784d71ae5a4SJacob Faibussowitsch {
77850fdc7489SMatthew Knepley   PetscFunctionBegin;
77864f572ea9SToby Isaac   PetscAssertPointer(ulabel, 2);
77870fdc7489SMatthew Knepley   *ulabel = ul->label;
77883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77890fdc7489SMatthew Knepley }
77900fdc7489SMatthew Knepley 
7791d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm)
7792d71ae5a4SJacob Faibussowitsch {
77930fdc7489SMatthew Knepley   PetscInt Nl = ul->Nl, l;
77940fdc7489SMatthew Knepley 
77950fdc7489SMatthew Knepley   PetscFunctionBegin;
7796064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 3);
77970fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
77989566063dSJacob Faibussowitsch     if (preserveOrder) PetscCall(DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]));
77999566063dSJacob Faibussowitsch     else PetscCall(DMCreateLabel(dm, ul->names[l]));
78000fdc7489SMatthew Knepley   }
78010fdc7489SMatthew Knepley   if (preserveOrder) {
78020fdc7489SMatthew Knepley     for (l = 0; l < ul->Nl; ++l) {
78030fdc7489SMatthew Knepley       const char *name;
78040fdc7489SMatthew Knepley       PetscBool   match;
78050fdc7489SMatthew Knepley 
78069566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, ul->indices[l], &name));
78079566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, ul->names[l], &match));
780863a3b9bcSJacob 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]);
78090fdc7489SMatthew Knepley     }
78100fdc7489SMatthew Knepley   }
78113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78120fdc7489SMatthew Knepley }
78130fdc7489SMatthew Knepley 
7814d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value)
7815d71ae5a4SJacob Faibussowitsch {
78160fdc7489SMatthew Knepley   PetscInt l;
78170fdc7489SMatthew Knepley 
78180fdc7489SMatthew Knepley   PetscFunctionBegin;
78190fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
78200fdc7489SMatthew Knepley     DMLabel  label;
78210fdc7489SMatthew Knepley     PetscInt lval = (value & ul->masks[l]) >> ul->bits[l];
78220fdc7489SMatthew Knepley 
78230fdc7489SMatthew Knepley     if (lval) {
78249566063dSJacob Faibussowitsch       if (useIndex) PetscCall(DMGetLabelByNum(dm, ul->indices[l], &label));
78259566063dSJacob Faibussowitsch       else PetscCall(DMGetLabel(dm, ul->names[l], &label));
78269566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(label, p, ul->values[ul->offsets[l] + lval - 1]));
78270fdc7489SMatthew Knepley     }
78280fdc7489SMatthew Knepley   }
78293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78300fdc7489SMatthew Knepley }
7831a8fb8f29SToby Isaac 
7832a8fb8f29SToby Isaac /*@
7833bb7acecfSBarry Smith   DMGetCoarseDM - Get the coarse `DM`from which this `DM` was obtained by refinement
7834bb7acecfSBarry Smith 
783520f4b53cSBarry Smith   Not Collective
7836a8fb8f29SToby Isaac 
7837a8fb8f29SToby Isaac   Input Parameter:
7838bb7acecfSBarry Smith . dm - The `DM` object
7839a8fb8f29SToby Isaac 
7840a8fb8f29SToby Isaac   Output Parameter:
7841bb7acecfSBarry Smith . cdm - The coarse `DM`
7842a8fb8f29SToby Isaac 
7843a8fb8f29SToby Isaac   Level: intermediate
7844a8fb8f29SToby Isaac 
78451cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetCoarseDM()`, `DMCoarsen()`
7846a8fb8f29SToby Isaac @*/
7847d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
7848d71ae5a4SJacob Faibussowitsch {
7849a8fb8f29SToby Isaac   PetscFunctionBegin;
7850a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78514f572ea9SToby Isaac   PetscAssertPointer(cdm, 2);
7852a8fb8f29SToby Isaac   *cdm = dm->coarseMesh;
78533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7854a8fb8f29SToby Isaac }
7855a8fb8f29SToby Isaac 
7856a8fb8f29SToby Isaac /*@
7857bb7acecfSBarry Smith   DMSetCoarseDM - Set the coarse `DM` from which this `DM` was obtained by refinement
7858a8fb8f29SToby Isaac 
7859a8fb8f29SToby Isaac   Input Parameters:
7860bb7acecfSBarry Smith + dm  - The `DM` object
7861bb7acecfSBarry Smith - cdm - The coarse `DM`
7862a8fb8f29SToby Isaac 
7863a8fb8f29SToby Isaac   Level: intermediate
7864a8fb8f29SToby Isaac 
7865bb7acecfSBarry Smith   Note:
7866bb7acecfSBarry Smith   Normally this is set automatically by `DMRefine()`
7867bb7acecfSBarry Smith 
78681cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetCoarseDM()`, `DMCoarsen()`, `DMSetRefine()`, `DMSetFineDM()`
7869a8fb8f29SToby Isaac @*/
7870d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
7871d71ae5a4SJacob Faibussowitsch {
7872a8fb8f29SToby Isaac   PetscFunctionBegin;
7873a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7874a8fb8f29SToby Isaac   if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
787589d734beSBarry Smith   if (dm == cdm) cdm = NULL;
78769566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)cdm));
78779566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->coarseMesh));
7878a8fb8f29SToby Isaac   dm->coarseMesh = cdm;
78793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7880a8fb8f29SToby Isaac }
7881a8fb8f29SToby Isaac 
788288bdff64SToby Isaac /*@
7883bb7acecfSBarry Smith   DMGetFineDM - Get the fine mesh from which this `DM` was obtained by coarsening
788488bdff64SToby Isaac 
788588bdff64SToby Isaac   Input Parameter:
7886bb7acecfSBarry Smith . dm - The `DM` object
788788bdff64SToby Isaac 
788888bdff64SToby Isaac   Output Parameter:
7889bb7acecfSBarry Smith . fdm - The fine `DM`
789088bdff64SToby Isaac 
789188bdff64SToby Isaac   Level: intermediate
789288bdff64SToby Isaac 
78931cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetFineDM()`, `DMCoarsen()`, `DMRefine()`
789488bdff64SToby Isaac @*/
7895d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
7896d71ae5a4SJacob Faibussowitsch {
789788bdff64SToby Isaac   PetscFunctionBegin;
789888bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78994f572ea9SToby Isaac   PetscAssertPointer(fdm, 2);
790088bdff64SToby Isaac   *fdm = dm->fineMesh;
79013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
790288bdff64SToby Isaac }
790388bdff64SToby Isaac 
790488bdff64SToby Isaac /*@
7905bb7acecfSBarry Smith   DMSetFineDM - Set the fine mesh from which this was obtained by coarsening
790688bdff64SToby Isaac 
790788bdff64SToby Isaac   Input Parameters:
7908bb7acecfSBarry Smith + dm  - The `DM` object
7909bb7acecfSBarry Smith - fdm - The fine `DM`
791088bdff64SToby Isaac 
7911bb7acecfSBarry Smith   Level: developer
791288bdff64SToby Isaac 
7913bb7acecfSBarry Smith   Note:
7914bb7acecfSBarry Smith   Normally this is set automatically by `DMCoarsen()`
7915bb7acecfSBarry Smith 
79161cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetFineDM()`, `DMCoarsen()`, `DMRefine()`
791788bdff64SToby Isaac @*/
7918d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFineDM(DM dm, DM fdm)
7919d71ae5a4SJacob Faibussowitsch {
792088bdff64SToby Isaac   PetscFunctionBegin;
792188bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
792288bdff64SToby Isaac   if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2);
792389d734beSBarry Smith   if (dm == fdm) fdm = NULL;
79249566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fdm));
79259566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->fineMesh));
792688bdff64SToby Isaac   dm->fineMesh = fdm;
79273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
792888bdff64SToby Isaac }
792988bdff64SToby Isaac 
7930a6ba4734SToby Isaac /*@C
7931bb7acecfSBarry Smith   DMAddBoundary - Add a boundary condition to a model represented by a `DM`
7932a6ba4734SToby Isaac 
793320f4b53cSBarry Smith   Collective
7934783e2ec8SMatthew G. Knepley 
7935a6ba4734SToby Isaac   Input Parameters:
7936bb7acecfSBarry Smith + dm       - The `DM`, with a `PetscDS` that matches the problem being constrained
7937bb7acecfSBarry Smith . type     - The type of condition, e.g. `DM_BC_ESSENTIAL_ANALYTIC`, `DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
7938a6ba4734SToby Isaac . name     - The BC name
793945480ffeSMatthew G. Knepley . label    - The label defining constrained points
7940bb7acecfSBarry Smith . Nv       - The number of `DMLabel` values for constrained points
794145480ffeSMatthew G. Knepley . values   - An array of values for constrained points
7942a6ba4734SToby Isaac . field    - The field to constrain
794345480ffeSMatthew G. Knepley . Nc       - The number of constrained field components (0 will constrain all fields)
7944a6ba4734SToby Isaac . comps    - An array of constrained component numbers
7945a6ba4734SToby Isaac . bcFunc   - A pointwise function giving boundary values
794656cf3b9cSMatthew G. Knepley . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL
7947a6ba4734SToby Isaac - ctx      - An optional user context for bcFunc
7948a6ba4734SToby Isaac 
794945480ffeSMatthew G. Knepley   Output Parameter:
795045480ffeSMatthew G. Knepley . bd - (Optional) Boundary number
795145480ffeSMatthew G. Knepley 
7952a6ba4734SToby Isaac   Options Database Keys:
7953a6ba4734SToby Isaac + -bc_<boundary name> <num>      - Overrides the boundary ids
7954a6ba4734SToby Isaac - -bc_<boundary name>_comp <num> - Overrides the boundary components
7955a6ba4734SToby Isaac 
795620f4b53cSBarry Smith   Level: intermediate
795720f4b53cSBarry Smith 
7958bb7acecfSBarry Smith   Notes:
7959fa74d514SMatthew G. Knepley   If the `DM` is of type `DMPLEX` and the field is of type `PetscFE`, then this function completes the label using `DMPlexLabelComplete()`.
7960fa74d514SMatthew G. Knepley 
7961aeebefc2SPierre Jolivet   Both bcFunc and bcFunc_t will depend on the boundary condition type. If the type if `DM_BC_ESSENTIAL`, then the calling sequence is\:
796273ff1848SBarry Smith .vb
796373ff1848SBarry Smith  void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
796473ff1848SBarry Smith .ve
796556cf3b9cSMatthew G. Knepley 
7966a4e35b19SJacob Faibussowitsch   If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is\:
796756cf3b9cSMatthew G. Knepley 
796820f4b53cSBarry Smith .vb
796920f4b53cSBarry Smith   void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
797020f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
797120f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
797220f4b53cSBarry Smith               PetscReal time, const PetscReal x[], PetscScalar bcval[])
797320f4b53cSBarry Smith .ve
797456cf3b9cSMatthew G. Knepley + dim - the spatial dimension
797556cf3b9cSMatthew G. Knepley . Nf - the number of fields
797656cf3b9cSMatthew G. Knepley . uOff - the offset into u[] and u_t[] for each field
797756cf3b9cSMatthew G. Knepley . uOff_x - the offset into u_x[] for each field
797856cf3b9cSMatthew G. Knepley . u - each field evaluated at the current point
797956cf3b9cSMatthew G. Knepley . u_t - the time derivative of each field evaluated at the current point
798056cf3b9cSMatthew G. Knepley . u_x - the gradient of each field evaluated at the current point
798156cf3b9cSMatthew G. Knepley . aOff - the offset into a[] and a_t[] for each auxiliary field
798256cf3b9cSMatthew G. Knepley . aOff_x - the offset into a_x[] for each auxiliary field
798356cf3b9cSMatthew G. Knepley . a - each auxiliary field evaluated at the current point
798456cf3b9cSMatthew G. Knepley . a_t - the time derivative of each auxiliary field evaluated at the current point
798556cf3b9cSMatthew G. Knepley . a_x - the gradient of auxiliary each field evaluated at the current point
798656cf3b9cSMatthew G. Knepley . t - current time
798756cf3b9cSMatthew G. Knepley . x - coordinates of the current point
798856cf3b9cSMatthew G. Knepley . numConstants - number of constant parameters
798956cf3b9cSMatthew G. Knepley . constants - constant parameters
799056cf3b9cSMatthew G. Knepley - bcval - output values at the current point
799156cf3b9cSMatthew G. Knepley 
79921cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DSGetBoundary()`, `PetscDSAddBoundary()`
7993a6ba4734SToby Isaac @*/
7994d71ae5a4SJacob 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)
7995d71ae5a4SJacob Faibussowitsch {
7996e5e52638SMatthew G. Knepley   PetscDS ds;
7997a6ba4734SToby Isaac 
7998a6ba4734SToby Isaac   PetscFunctionBegin;
7999a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8000783e2ec8SMatthew G. Knepley   PetscValidLogicalCollectiveEnum(dm, type, 2);
800145480ffeSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
800245480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nv, 5);
800345480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, field, 7);
800445480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 8);
800501a5d20dSJed Brown   PetscCheck(!dm->localSection, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot add boundary to DM after creating local section");
80069566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
8007799db056SMatthew G. Knepley   /* Complete label */
8008799db056SMatthew G. Knepley   if (label) {
8009799db056SMatthew G. Knepley     PetscObject  obj;
8010799db056SMatthew G. Knepley     PetscClassId id;
8011799db056SMatthew G. Knepley 
8012799db056SMatthew G. Knepley     PetscCall(DMGetField(dm, field, NULL, &obj));
8013799db056SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
8014799db056SMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
8015799db056SMatthew G. Knepley       DM plex;
8016799db056SMatthew G. Knepley 
8017799db056SMatthew G. Knepley       PetscCall(DMConvert(dm, DMPLEX, &plex));
8018799db056SMatthew G. Knepley       if (plex) PetscCall(DMPlexLabelComplete(plex, label));
8019799db056SMatthew G. Knepley       PetscCall(DMDestroy(&plex));
8020799db056SMatthew G. Knepley     }
8021799db056SMatthew G. Knepley   }
80229566063dSJacob Faibussowitsch   PetscCall(PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd));
80233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8024a6ba4734SToby Isaac }
8025a6ba4734SToby Isaac 
802645480ffeSMatthew G. Knepley /* TODO Remove this since now the structures are the same */
8027d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPopulateBoundary(DM dm)
8028d71ae5a4SJacob Faibussowitsch {
8029e5e52638SMatthew G. Knepley   PetscDS     ds;
8030dff059c6SToby Isaac   DMBoundary *lastnext;
8031e6f8dbb6SToby Isaac   DSBoundary  dsbound;
8032e6f8dbb6SToby Isaac 
8033e6f8dbb6SToby Isaac   PetscFunctionBegin;
80349566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
8035e5e52638SMatthew G. Knepley   dsbound = ds->boundary;
803647a1f5adSToby Isaac   if (dm->boundary) {
803747a1f5adSToby Isaac     DMBoundary next = dm->boundary;
803847a1f5adSToby Isaac 
803947a1f5adSToby Isaac     /* quick check to see if the PetscDS has changed */
80403ba16761SJacob Faibussowitsch     if (next->dsboundary == dsbound) PetscFunctionReturn(PETSC_SUCCESS);
804147a1f5adSToby Isaac     /* the PetscDS has changed: tear down and rebuild */
804247a1f5adSToby Isaac     while (next) {
804347a1f5adSToby Isaac       DMBoundary b = next;
804447a1f5adSToby Isaac 
804547a1f5adSToby Isaac       next = b->next;
80469566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
8047a6ba4734SToby Isaac     }
804847a1f5adSToby Isaac     dm->boundary = NULL;
8049a6ba4734SToby Isaac   }
805047a1f5adSToby Isaac 
8051f4f49eeaSPierre Jolivet   lastnext = &dm->boundary;
8052e6f8dbb6SToby Isaac   while (dsbound) {
8053e6f8dbb6SToby Isaac     DMBoundary dmbound;
8054e6f8dbb6SToby Isaac 
80559566063dSJacob Faibussowitsch     PetscCall(PetscNew(&dmbound));
8056e6f8dbb6SToby Isaac     dmbound->dsboundary = dsbound;
805745480ffeSMatthew G. Knepley     dmbound->label      = dsbound->label;
805847a1f5adSToby Isaac     /* push on the back instead of the front so that it is in the same order as in the PetscDS */
8059dff059c6SToby Isaac     *lastnext = dmbound;
8060f4f49eeaSPierre Jolivet     lastnext  = &dmbound->next;
8061dff059c6SToby Isaac     dsbound   = dsbound->next;
8062a6ba4734SToby Isaac   }
80633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8064a6ba4734SToby Isaac }
8065a6ba4734SToby Isaac 
8066bb7acecfSBarry Smith /* TODO: missing manual page */
8067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
8068d71ae5a4SJacob Faibussowitsch {
8069b95f2879SToby Isaac   DMBoundary b;
8070a6ba4734SToby Isaac 
8071a6ba4734SToby Isaac   PetscFunctionBegin;
8072a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80734f572ea9SToby Isaac   PetscAssertPointer(isBd, 3);
8074a6ba4734SToby Isaac   *isBd = PETSC_FALSE;
80759566063dSJacob Faibussowitsch   PetscCall(DMPopulateBoundary(dm));
8076b95f2879SToby Isaac   b = dm->boundary;
807757508eceSPierre Jolivet   while (b && !*isBd) {
8078e6f8dbb6SToby Isaac     DMLabel    label = b->label;
8079e6f8dbb6SToby Isaac     DSBoundary dsb   = b->dsboundary;
8080a6ba4734SToby Isaac     PetscInt   i;
8081a6ba4734SToby Isaac 
808245480ffeSMatthew G. Knepley     if (label) {
808357508eceSPierre Jolivet       for (i = 0; i < dsb->Nv && !*isBd; ++i) PetscCall(DMLabelStratumHasPoint(label, dsb->values[i], point, isBd));
8084a6ba4734SToby Isaac     }
8085a6ba4734SToby Isaac     b = b->next;
8086a6ba4734SToby Isaac   }
80873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8088a6ba4734SToby Isaac }
80894d6f44ffSToby Isaac 
80904d6f44ffSToby Isaac /*@C
8091bb7acecfSBarry Smith   DMProjectFunction - This projects the given function into the function space provided by a `DM`, putting the coefficients in a global vector.
8092a6e0b375SMatthew G. Knepley 
809320f4b53cSBarry Smith   Collective
80944d6f44ffSToby Isaac 
80954d6f44ffSToby Isaac   Input Parameters:
8096bb7acecfSBarry Smith + dm    - The `DM`
80970709b2feSToby Isaac . time  - The time
80984d6f44ffSToby Isaac . funcs - The coordinate functions to evaluate, one per field
80994d6f44ffSToby Isaac . ctxs  - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
81004d6f44ffSToby Isaac - mode  - The insertion mode for values
81014d6f44ffSToby Isaac 
81024d6f44ffSToby Isaac   Output Parameter:
81034d6f44ffSToby Isaac . X - vector
81044d6f44ffSToby Isaac 
810520f4b53cSBarry Smith   Calling sequence of `funcs`:
81064d6f44ffSToby Isaac + dim  - The spatial dimension
81078ec8862eSJed Brown . time - The time at which to sample
81084d6f44ffSToby Isaac . x    - The coordinates
810977b739a6SMatthew Knepley . Nc   - The number of components
81104d6f44ffSToby Isaac . u    - The output field values
81114d6f44ffSToby Isaac - ctx  - optional user-defined function context
81124d6f44ffSToby Isaac 
81134d6f44ffSToby Isaac   Level: developer
81144d6f44ffSToby Isaac 
8115bb7acecfSBarry Smith   Developer Notes:
8116bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8117bb7acecfSBarry Smith 
8118bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8119bb7acecfSBarry Smith 
81201cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
81214d6f44ffSToby Isaac @*/
8122a4e35b19SJacob Faibussowitsch PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx), void **ctxs, InsertMode mode, Vec X)
8123d71ae5a4SJacob Faibussowitsch {
81244d6f44ffSToby Isaac   Vec localX;
81254d6f44ffSToby Isaac 
81264d6f44ffSToby Isaac   PetscFunctionBegin;
81274d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8128708be2fdSJed Brown   PetscCall(PetscLogEventBegin(DM_ProjectFunction, dm, X, 0, 0));
81299566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
8130f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
81319566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX));
81329566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
81339566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
81349566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
8135708be2fdSJed Brown   PetscCall(PetscLogEventEnd(DM_ProjectFunction, dm, X, 0, 0));
81363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81374d6f44ffSToby Isaac }
81384d6f44ffSToby Isaac 
8139a6e0b375SMatthew G. Knepley /*@C
8140bb7acecfSBarry Smith   DMProjectFunctionLocal - This projects the given function into the function space provided by a `DM`, putting the coefficients in a local vector.
8141a6e0b375SMatthew G. Knepley 
814220f4b53cSBarry Smith   Not Collective
8143a6e0b375SMatthew G. Knepley 
8144a6e0b375SMatthew G. Knepley   Input Parameters:
8145bb7acecfSBarry Smith + dm    - The `DM`
8146a6e0b375SMatthew G. Knepley . time  - The time
8147a6e0b375SMatthew G. Knepley . funcs - The coordinate functions to evaluate, one per field
8148a6e0b375SMatthew G. Knepley . ctxs  - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
8149a6e0b375SMatthew G. Knepley - mode  - The insertion mode for values
8150a6e0b375SMatthew G. Knepley 
8151a6e0b375SMatthew G. Knepley   Output Parameter:
8152a6e0b375SMatthew G. Knepley . localX - vector
8153a6e0b375SMatthew G. Knepley 
815420f4b53cSBarry Smith   Calling sequence of `funcs`:
8155a6e0b375SMatthew G. Knepley + dim  - The spatial dimension
8156a4e35b19SJacob Faibussowitsch . time - The current timestep
8157a6e0b375SMatthew G. Knepley . x    - The coordinates
815877b739a6SMatthew Knepley . Nc   - The number of components
8159a6e0b375SMatthew G. Knepley . u    - The output field values
8160a6e0b375SMatthew G. Knepley - ctx  - optional user-defined function context
8161a6e0b375SMatthew G. Knepley 
8162a6e0b375SMatthew G. Knepley   Level: developer
8163a6e0b375SMatthew G. Knepley 
8164bb7acecfSBarry Smith   Developer Notes:
8165bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8166bb7acecfSBarry Smith 
8167bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8168bb7acecfSBarry Smith 
81691cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
8170a6e0b375SMatthew G. Knepley @*/
8171a4e35b19SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx), void **ctxs, InsertMode mode, Vec localX)
8172d71ae5a4SJacob Faibussowitsch {
81734d6f44ffSToby Isaac   PetscFunctionBegin;
81744d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8175064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
8176fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfunctionlocal, time, funcs, ctxs, mode, localX);
81773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81784d6f44ffSToby Isaac }
81794d6f44ffSToby Isaac 
8180a6e0b375SMatthew G. Knepley /*@C
8181bb7acecfSBarry 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.
8182a6e0b375SMatthew G. Knepley 
818320f4b53cSBarry Smith   Collective
8184a6e0b375SMatthew G. Knepley 
8185a6e0b375SMatthew G. Knepley   Input Parameters:
8186bb7acecfSBarry Smith + dm     - The `DM`
8187a6e0b375SMatthew G. Knepley . time   - The time
8188a4e35b19SJacob Faibussowitsch . numIds - The number of ids
8189a4e35b19SJacob Faibussowitsch . ids    - The ids
8190a4e35b19SJacob Faibussowitsch . Nc     - The number of components
8191a4e35b19SJacob Faibussowitsch . comps  - The components
8192bb7acecfSBarry Smith . label  - The `DMLabel` selecting the portion of the mesh for projection
8193a6e0b375SMatthew G. Knepley . funcs  - The coordinate functions to evaluate, one per field
8194bb7acecfSBarry Smith . ctxs   - Optional array of contexts to pass to each coordinate function.  ctxs may be null.
8195a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8196a6e0b375SMatthew G. Knepley 
8197a6e0b375SMatthew G. Knepley   Output Parameter:
8198a6e0b375SMatthew G. Knepley . X - vector
8199a6e0b375SMatthew G. Knepley 
820020f4b53cSBarry Smith   Calling sequence of `funcs`:
8201a6e0b375SMatthew G. Knepley + dim  - The spatial dimension
8202a4e35b19SJacob Faibussowitsch . time - The current timestep
8203a6e0b375SMatthew G. Knepley . x    - The coordinates
820477b739a6SMatthew Knepley . Nc   - The number of components
8205a6e0b375SMatthew G. Knepley . u    - The output field values
8206a6e0b375SMatthew G. Knepley - ctx  - optional user-defined function context
8207a6e0b375SMatthew G. Knepley 
8208a6e0b375SMatthew G. Knepley   Level: developer
8209a6e0b375SMatthew G. Knepley 
8210bb7acecfSBarry Smith   Developer Notes:
8211bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8212bb7acecfSBarry Smith 
8213bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8214bb7acecfSBarry Smith 
82151cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabelLocal()`, `DMComputeL2Diff()`
8216a6e0b375SMatthew G. Knepley @*/
8217a4e35b19SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLabel(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx), void **ctxs, InsertMode mode, Vec X)
8218d71ae5a4SJacob Faibussowitsch {
82192c53366bSMatthew G. Knepley   Vec localX;
82202c53366bSMatthew G. Knepley 
82212c53366bSMatthew G. Knepley   PetscFunctionBegin;
82222c53366bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
82239566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
8224f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
82259566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
82269566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
82279566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
82289566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
82293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82302c53366bSMatthew G. Knepley }
82312c53366bSMatthew G. Knepley 
8232a6e0b375SMatthew G. Knepley /*@C
8233bb7acecfSBarry 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.
8234a6e0b375SMatthew G. Knepley 
823520f4b53cSBarry Smith   Not Collective
8236a6e0b375SMatthew G. Knepley 
8237a6e0b375SMatthew G. Knepley   Input Parameters:
8238bb7acecfSBarry Smith + dm     - The `DM`
8239a6e0b375SMatthew G. Knepley . time   - The time
8240bb7acecfSBarry Smith . label  - The `DMLabel` selecting the portion of the mesh for projection
8241a4e35b19SJacob Faibussowitsch . numIds - The number of ids
8242a4e35b19SJacob Faibussowitsch . ids    - The ids
8243a4e35b19SJacob Faibussowitsch . Nc     - The number of components
8244a4e35b19SJacob Faibussowitsch . comps  - The components
8245a6e0b375SMatthew G. Knepley . funcs  - The coordinate functions to evaluate, one per field
8246a6e0b375SMatthew G. Knepley . ctxs   - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
8247a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8248a6e0b375SMatthew G. Knepley 
8249a6e0b375SMatthew G. Knepley   Output Parameter:
8250a6e0b375SMatthew G. Knepley . localX - vector
8251a6e0b375SMatthew G. Knepley 
825220f4b53cSBarry Smith   Calling sequence of `funcs`:
8253a6e0b375SMatthew G. Knepley + dim  - The spatial dimension
8254a4e35b19SJacob Faibussowitsch . time - The current time
8255a6e0b375SMatthew G. Knepley . x    - The coordinates
825677b739a6SMatthew Knepley . Nc   - The number of components
8257a6e0b375SMatthew G. Knepley . u    - The output field values
8258a6e0b375SMatthew G. Knepley - ctx  - optional user-defined function context
8259a6e0b375SMatthew G. Knepley 
8260a6e0b375SMatthew G. Knepley   Level: developer
8261a6e0b375SMatthew G. Knepley 
8262bb7acecfSBarry Smith   Developer Notes:
8263bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8264bb7acecfSBarry Smith 
8265bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8266bb7acecfSBarry Smith 
82671cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
8268a6e0b375SMatthew G. Knepley @*/
8269a4e35b19SJacob Faibussowitsch PetscErrorCode DMProjectFunctionLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx), void **ctxs, InsertMode mode, Vec localX)
8270d71ae5a4SJacob Faibussowitsch {
82714d6f44ffSToby Isaac   PetscFunctionBegin;
82724d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8273064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
8274fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfunctionlabellocal, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
82753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82764d6f44ffSToby Isaac }
82772716604bSToby Isaac 
8278a6e0b375SMatthew G. Knepley /*@C
8279bb7acecfSBarry 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.
8280a6e0b375SMatthew G. Knepley 
828120f4b53cSBarry Smith   Not Collective
8282a6e0b375SMatthew G. Knepley 
8283a6e0b375SMatthew G. Knepley   Input Parameters:
8284bb7acecfSBarry Smith + dm     - The `DM`
8285a6e0b375SMatthew G. Knepley . time   - The time
828620f4b53cSBarry Smith . localU - The input field vector; may be `NULL` if projection is defined purely by coordinates
8287a6e0b375SMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8288a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8289a6e0b375SMatthew G. Knepley 
8290a6e0b375SMatthew G. Knepley   Output Parameter:
8291a6e0b375SMatthew G. Knepley . localX - The output vector
8292a6e0b375SMatthew G. Knepley 
829320f4b53cSBarry Smith   Calling sequence of `funcs`:
8294a6e0b375SMatthew G. Knepley + dim          - The spatial dimension
8295a6e0b375SMatthew G. Knepley . Nf           - The number of input fields
8296a6e0b375SMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8297a6e0b375SMatthew G. Knepley . uOff         - The offset of each field in u[]
8298a6e0b375SMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8299a6e0b375SMatthew G. Knepley . u            - The field values at this point in space
8300a6e0b375SMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8301a6e0b375SMatthew G. Knepley . u_x          - The field derivatives at this point in space
8302a6e0b375SMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8303a6e0b375SMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8304a6e0b375SMatthew G. Knepley . a            - The auxiliary field values at this point in space
8305a6e0b375SMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8306a6e0b375SMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8307a6e0b375SMatthew G. Knepley . t            - The current time
8308a6e0b375SMatthew G. Knepley . x            - The coordinates of this point
8309a6e0b375SMatthew G. Knepley . numConstants - The number of constants
8310a6e0b375SMatthew G. Knepley . constants    - The value of each constant
8311a6e0b375SMatthew G. Knepley - f            - The value of the function at this point in space
8312a6e0b375SMatthew G. Knepley 
831373ff1848SBarry Smith   Level: intermediate
831473ff1848SBarry Smith 
8315bb7acecfSBarry Smith   Note:
8316bb7acecfSBarry 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.
8317bb7acecfSBarry 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
8318bb7acecfSBarry 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
8319a6e0b375SMatthew 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.
8320a6e0b375SMatthew G. Knepley 
8321bb7acecfSBarry Smith   Developer Notes:
8322bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8323bb7acecfSBarry Smith 
8324bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8325bb7acecfSBarry Smith 
8326a4e35b19SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`,
8327a4e35b19SJacob Faibussowitsch `DMProjectFunction()`, `DMComputeL2Diff()`
8328a6e0b375SMatthew G. Knepley @*/
8329a4e35b19SJacob Faibussowitsch PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, void (**funcs)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]), InsertMode mode, Vec localX)
8330d71ae5a4SJacob Faibussowitsch {
83318c6c5593SMatthew G. Knepley   PetscFunctionBegin;
83328c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8333eb8f539aSJed Brown   if (localU) PetscValidHeaderSpecific(localU, VEC_CLASSID, 3);
83348c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
8335fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfieldlocal, time, localU, funcs, mode, localX);
83363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83378c6c5593SMatthew G. Knepley }
83388c6c5593SMatthew G. Knepley 
8339a6e0b375SMatthew G. Knepley /*@C
8340a6e0b375SMatthew 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.
8341a6e0b375SMatthew G. Knepley 
834220f4b53cSBarry Smith   Not Collective
8343a6e0b375SMatthew G. Knepley 
8344a6e0b375SMatthew G. Knepley   Input Parameters:
8345bb7acecfSBarry Smith + dm     - The `DM`
8346a6e0b375SMatthew G. Knepley . time   - The time
8347bb7acecfSBarry Smith . label  - The `DMLabel` marking the portion of the domain to output
8348a6e0b375SMatthew G. Knepley . numIds - The number of label ids to use
8349a6e0b375SMatthew G. Knepley . ids    - The label ids to use for marking
8350bb7acecfSBarry Smith . Nc     - The number of components to set in the output, or `PETSC_DETERMINE` for all components
835120f4b53cSBarry Smith . comps  - The components to set in the output, or `NULL` for all components
8352a6e0b375SMatthew G. Knepley . localU - The input field vector
8353a6e0b375SMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8354a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8355a6e0b375SMatthew G. Knepley 
8356a6e0b375SMatthew G. Knepley   Output Parameter:
8357a6e0b375SMatthew G. Knepley . localX - The output vector
8358a6e0b375SMatthew G. Knepley 
835920f4b53cSBarry Smith   Calling sequence of `funcs`:
8360a6e0b375SMatthew G. Knepley + dim          - The spatial dimension
8361a6e0b375SMatthew G. Knepley . Nf           - The number of input fields
8362a6e0b375SMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8363a6e0b375SMatthew G. Knepley . uOff         - The offset of each field in u[]
8364a6e0b375SMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8365a6e0b375SMatthew G. Knepley . u            - The field values at this point in space
8366a6e0b375SMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8367a6e0b375SMatthew G. Knepley . u_x          - The field derivatives at this point in space
8368a6e0b375SMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8369a6e0b375SMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8370a6e0b375SMatthew G. Knepley . a            - The auxiliary field values at this point in space
8371a6e0b375SMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8372a6e0b375SMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8373a6e0b375SMatthew G. Knepley . t            - The current time
8374a6e0b375SMatthew G. Knepley . x            - The coordinates of this point
8375a6e0b375SMatthew G. Knepley . numConstants - The number of constants
8376a6e0b375SMatthew G. Knepley . constants    - The value of each constant
8377a6e0b375SMatthew G. Knepley - f            - The value of the function at this point in space
8378a6e0b375SMatthew G. Knepley 
837973ff1848SBarry Smith   Level: intermediate
838073ff1848SBarry Smith 
8381bb7acecfSBarry Smith   Note:
8382bb7acecfSBarry 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.
8383bb7acecfSBarry 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
8384bb7acecfSBarry 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
8385a6e0b375SMatthew 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.
8386a6e0b375SMatthew G. Knepley 
8387bb7acecfSBarry Smith   Developer Notes:
8388bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8389bb7acecfSBarry Smith 
8390bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8391bb7acecfSBarry Smith 
83921cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabel()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8393a6e0b375SMatthew G. Knepley @*/
8394a4e35b19SJacob Faibussowitsch PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, void (**funcs)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]), InsertMode mode, Vec localX)
8395d71ae5a4SJacob Faibussowitsch {
83968c6c5593SMatthew G. Knepley   PetscFunctionBegin;
83978c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8398064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8399064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
8400fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfieldlabellocal, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
84013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84028c6c5593SMatthew G. Knepley }
84038c6c5593SMatthew G. Knepley 
84042716604bSToby Isaac /*@C
8405d29d7c6eSMatthew 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.
8406d29d7c6eSMatthew G. Knepley 
840720f4b53cSBarry Smith   Not Collective
8408d29d7c6eSMatthew G. Knepley 
8409d29d7c6eSMatthew G. Knepley   Input Parameters:
8410bb7acecfSBarry Smith + dm     - The `DM`
8411d29d7c6eSMatthew G. Knepley . time   - The time
8412bb7acecfSBarry Smith . label  - The `DMLabel` marking the portion of the domain to output
8413d29d7c6eSMatthew G. Knepley . numIds - The number of label ids to use
8414d29d7c6eSMatthew G. Knepley . ids    - The label ids to use for marking
8415bb7acecfSBarry Smith . Nc     - The number of components to set in the output, or `PETSC_DETERMINE` for all components
841620f4b53cSBarry Smith . comps  - The components to set in the output, or `NULL` for all components
8417d29d7c6eSMatthew G. Knepley . U      - The input field vector
8418d29d7c6eSMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8419d29d7c6eSMatthew G. Knepley - mode   - The insertion mode for values
8420d29d7c6eSMatthew G. Knepley 
8421d29d7c6eSMatthew G. Knepley   Output Parameter:
8422d29d7c6eSMatthew G. Knepley . X - The output vector
8423d29d7c6eSMatthew G. Knepley 
842420f4b53cSBarry Smith   Calling sequence of `funcs`:
8425d29d7c6eSMatthew G. Knepley + dim          - The spatial dimension
8426d29d7c6eSMatthew G. Knepley . Nf           - The number of input fields
8427d29d7c6eSMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8428d29d7c6eSMatthew G. Knepley . uOff         - The offset of each field in u[]
8429d29d7c6eSMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8430d29d7c6eSMatthew G. Knepley . u            - The field values at this point in space
8431d29d7c6eSMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8432d29d7c6eSMatthew G. Knepley . u_x          - The field derivatives at this point in space
8433d29d7c6eSMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8434d29d7c6eSMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8435d29d7c6eSMatthew G. Knepley . a            - The auxiliary field values at this point in space
8436d29d7c6eSMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8437d29d7c6eSMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8438d29d7c6eSMatthew G. Knepley . t            - The current time
8439d29d7c6eSMatthew G. Knepley . x            - The coordinates of this point
8440d29d7c6eSMatthew G. Knepley . numConstants - The number of constants
8441d29d7c6eSMatthew G. Knepley . constants    - The value of each constant
8442d29d7c6eSMatthew G. Knepley - f            - The value of the function at this point in space
8443d29d7c6eSMatthew G. Knepley 
844473ff1848SBarry Smith   Level: intermediate
844573ff1848SBarry Smith 
8446bb7acecfSBarry Smith   Note:
8447bb7acecfSBarry 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.
8448bb7acecfSBarry 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
8449bb7acecfSBarry 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
8450d29d7c6eSMatthew 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.
8451d29d7c6eSMatthew G. Knepley 
8452bb7acecfSBarry Smith   Developer Notes:
8453bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8454bb7acecfSBarry Smith 
8455bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8456bb7acecfSBarry Smith 
84571cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8458d29d7c6eSMatthew G. Knepley @*/
8459a4e35b19SJacob Faibussowitsch PetscErrorCode DMProjectFieldLabel(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec U, void (**funcs)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]), InsertMode mode, Vec X)
8460d71ae5a4SJacob Faibussowitsch {
8461d29d7c6eSMatthew G. Knepley   DM  dmIn;
8462d29d7c6eSMatthew G. Knepley   Vec localU, localX;
8463d29d7c6eSMatthew G. Knepley 
8464d29d7c6eSMatthew G. Knepley   PetscFunctionBegin;
8465d29d7c6eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8466d29d7c6eSMatthew G. Knepley   PetscCall(VecGetDM(U, &dmIn));
8467d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dmIn, &localU));
8468d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dm, &localX));
8469f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
847072fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalBegin(dmIn, U, mode, localU));
847172fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalEnd(dmIn, U, mode, localU));
8472d29d7c6eSMatthew G. Knepley   PetscCall(DMProjectFieldLabelLocal(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
8473d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
8474d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
8475d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dm, &localX));
8476d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dmIn, &localU));
84773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8478d29d7c6eSMatthew G. Knepley }
8479d29d7c6eSMatthew G. Knepley 
8480d29d7c6eSMatthew G. Knepley /*@C
8481ece3a9fcSMatthew 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.
8482ece3a9fcSMatthew G. Knepley 
848320f4b53cSBarry Smith   Not Collective
8484ece3a9fcSMatthew G. Knepley 
8485ece3a9fcSMatthew G. Knepley   Input Parameters:
8486bb7acecfSBarry Smith + dm     - The `DM`
8487ece3a9fcSMatthew G. Knepley . time   - The time
8488bb7acecfSBarry Smith . label  - The `DMLabel` marking the portion of the domain boundary to output
8489ece3a9fcSMatthew G. Knepley . numIds - The number of label ids to use
8490ece3a9fcSMatthew G. Knepley . ids    - The label ids to use for marking
8491bb7acecfSBarry Smith . Nc     - The number of components to set in the output, or `PETSC_DETERMINE` for all components
849220f4b53cSBarry Smith . comps  - The components to set in the output, or `NULL` for all components
8493ece3a9fcSMatthew G. Knepley . localU - The input field vector
8494ece3a9fcSMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8495ece3a9fcSMatthew G. Knepley - mode   - The insertion mode for values
8496ece3a9fcSMatthew G. Knepley 
8497ece3a9fcSMatthew G. Knepley   Output Parameter:
8498ece3a9fcSMatthew G. Knepley . localX - The output vector
8499ece3a9fcSMatthew G. Knepley 
850020f4b53cSBarry Smith   Calling sequence of `funcs`:
8501ece3a9fcSMatthew G. Knepley + dim          - The spatial dimension
8502ece3a9fcSMatthew G. Knepley . Nf           - The number of input fields
8503ece3a9fcSMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8504ece3a9fcSMatthew G. Knepley . uOff         - The offset of each field in u[]
8505ece3a9fcSMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8506ece3a9fcSMatthew G. Knepley . u            - The field values at this point in space
8507ece3a9fcSMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8508ece3a9fcSMatthew G. Knepley . u_x          - The field derivatives at this point in space
8509ece3a9fcSMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8510ece3a9fcSMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8511ece3a9fcSMatthew G. Knepley . a            - The auxiliary field values at this point in space
8512ece3a9fcSMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8513ece3a9fcSMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8514ece3a9fcSMatthew G. Knepley . t            - The current time
8515ece3a9fcSMatthew G. Knepley . x            - The coordinates of this point
8516ece3a9fcSMatthew G. Knepley . n            - The face normal
8517ece3a9fcSMatthew G. Knepley . numConstants - The number of constants
8518ece3a9fcSMatthew G. Knepley . constants    - The value of each constant
8519ece3a9fcSMatthew G. Knepley - f            - The value of the function at this point in space
8520ece3a9fcSMatthew G. Knepley 
852173ff1848SBarry Smith   Level: intermediate
852273ff1848SBarry Smith 
8523ece3a9fcSMatthew G. Knepley   Note:
8524bb7acecfSBarry 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.
8525bb7acecfSBarry 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
8526bb7acecfSBarry 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
8527ece3a9fcSMatthew 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.
8528ece3a9fcSMatthew G. Knepley 
8529bb7acecfSBarry Smith   Developer Notes:
8530bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8531bb7acecfSBarry Smith 
8532bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8533bb7acecfSBarry Smith 
85341cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8535ece3a9fcSMatthew G. Knepley @*/
8536a4e35b19SJacob Faibussowitsch PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, void (**funcs)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]), InsertMode mode, Vec localX)
8537d71ae5a4SJacob Faibussowitsch {
8538ece3a9fcSMatthew G. Knepley   PetscFunctionBegin;
8539ece3a9fcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8540064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8541064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
8542fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectbdfieldlabellocal, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
85433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8544ece3a9fcSMatthew G. Knepley }
8545ece3a9fcSMatthew G. Knepley 
8546ece3a9fcSMatthew G. Knepley /*@C
85472716604bSToby Isaac   DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
85482716604bSToby Isaac 
854920f4b53cSBarry Smith   Collective
8550bb7acecfSBarry Smith 
85512716604bSToby Isaac   Input Parameters:
8552bb7acecfSBarry Smith + dm    - The `DM`
85530709b2feSToby Isaac . time  - The time
85542716604bSToby Isaac . funcs - The functions to evaluate for each field component
85552716604bSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8556574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
85572716604bSToby Isaac 
85582716604bSToby Isaac   Output Parameter:
85592716604bSToby Isaac . diff - The diff ||u - u_h||_2
85602716604bSToby Isaac 
85612716604bSToby Isaac   Level: developer
85622716604bSToby Isaac 
8563bb7acecfSBarry Smith   Developer Notes:
8564bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8565bb7acecfSBarry Smith 
8566bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8567bb7acecfSBarry Smith 
85681cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
85692716604bSToby Isaac @*/
8570d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
8571d71ae5a4SJacob Faibussowitsch {
85722716604bSToby Isaac   PetscFunctionBegin;
85732716604bSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8574b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
8575fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, computel2diff, time, funcs, ctxs, X, diff);
85763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
85772716604bSToby Isaac }
8578b698f381SToby Isaac 
8579b698f381SToby Isaac /*@C
8580b698f381SToby Isaac   DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
8581b698f381SToby Isaac 
858220f4b53cSBarry Smith   Collective
8583d083f849SBarry Smith 
8584b698f381SToby Isaac   Input Parameters:
8585bb7acecfSBarry Smith + dm    - The `DM`
8586a4e35b19SJacob Faibussowitsch . time  - The time
8587b698f381SToby Isaac . funcs - The gradient functions to evaluate for each field component
8588b698f381SToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8589574a98acSMatthew G. Knepley . X     - The coefficient vector u_h, a global vector
8590b698f381SToby Isaac - n     - The vector to project along
8591b698f381SToby Isaac 
8592b698f381SToby Isaac   Output Parameter:
8593b698f381SToby Isaac . diff - The diff ||(grad u - grad u_h) . n||_2
8594b698f381SToby Isaac 
8595b698f381SToby Isaac   Level: developer
8596b698f381SToby Isaac 
8597bb7acecfSBarry Smith   Developer Notes:
8598bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8599bb7acecfSBarry Smith 
8600bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8601bb7acecfSBarry Smith 
86021cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2Diff()`, `DMComputeL2FieldDiff()`
8603b698f381SToby Isaac @*/
8604d71ae5a4SJacob 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)
8605d71ae5a4SJacob Faibussowitsch {
8606b698f381SToby Isaac   PetscFunctionBegin;
8607b698f381SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8608b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
8609fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, computel2gradientdiff, time, funcs, ctxs, X, n, diff);
86103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8611b698f381SToby Isaac }
8612b698f381SToby Isaac 
86132a16baeaSToby Isaac /*@C
86142a16baeaSToby Isaac   DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
86152a16baeaSToby Isaac 
861620f4b53cSBarry Smith   Collective
8617d083f849SBarry Smith 
86182a16baeaSToby Isaac   Input Parameters:
8619bb7acecfSBarry Smith + dm    - The `DM`
86202a16baeaSToby Isaac . time  - The time
86212a16baeaSToby Isaac . funcs - The functions to evaluate for each field component
86222a16baeaSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8623574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
86242a16baeaSToby Isaac 
86252a16baeaSToby Isaac   Output Parameter:
86262a16baeaSToby Isaac . diff - The array of differences, ||u^f - u^f_h||_2
86272a16baeaSToby Isaac 
86282a16baeaSToby Isaac   Level: developer
86292a16baeaSToby Isaac 
8630bb7acecfSBarry Smith   Developer Notes:
8631bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8632bb7acecfSBarry Smith 
8633bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8634bb7acecfSBarry Smith 
863542747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2GradientDiff()`
86362a16baeaSToby Isaac @*/
8637d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
8638d71ae5a4SJacob Faibussowitsch {
86392a16baeaSToby Isaac   PetscFunctionBegin;
86402a16baeaSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86412a16baeaSToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
8642fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, computel2fielddiff, time, funcs, ctxs, X, diff);
86433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86442a16baeaSToby Isaac }
86452a16baeaSToby Isaac 
8646df0b854cSToby Isaac /*@C
8647bb7acecfSBarry Smith   DMGetNeighbors - Gets an array containing the MPI ranks of all the processes neighbors
8648502a2867SDave May 
8649502a2867SDave May   Not Collective
8650502a2867SDave May 
8651502a2867SDave May   Input Parameter:
8652bb7acecfSBarry Smith . dm - The `DM`
8653502a2867SDave May 
86540a19bb7dSprj-   Output Parameters:
86550a19bb7dSprj- + nranks - the number of neighbours
86560a19bb7dSprj- - ranks  - the neighbors ranks
8657502a2867SDave May 
86589bdbcad8SBarry Smith   Level: beginner
86599bdbcad8SBarry Smith 
8660bb7acecfSBarry Smith   Note:
8661bb7acecfSBarry Smith   Do not free the array, it is freed when the `DM` is destroyed.
8662502a2867SDave May 
86631cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDAGetNeighbors()`, `PetscSFGetRootRanks()`
8664502a2867SDave May @*/
8665d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNeighbors(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
8666d71ae5a4SJacob Faibussowitsch {
8667502a2867SDave May   PetscFunctionBegin;
8668502a2867SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8669fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, getneighbors, nranks, ranks);
86703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8671502a2867SDave May }
8672502a2867SDave May 
8673531c7667SBarry Smith #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
8674531c7667SBarry Smith 
8675531c7667SBarry Smith /*
8676531c7667SBarry Smith     Converts the input vector to a ghosted vector and then calls the standard coloring code.
86772b6f951bSStefano Zampini     This must be a different function because it requires DM which is not defined in the Mat library
8678531c7667SBarry Smith */
867966976f2fSJacob Faibussowitsch static PetscErrorCode MatFDColoringApply_AIJDM(Mat J, MatFDColoring coloring, Vec x1, void *sctx)
8680d71ae5a4SJacob Faibussowitsch {
8681531c7667SBarry Smith   PetscFunctionBegin;
8682531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8683531c7667SBarry Smith     Vec x1local;
8684531c7667SBarry Smith     DM  dm;
86859566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
86867a8be351SBarry Smith     PetscCheck(dm, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_INCOMP, "IS_COLORING_LOCAL requires a DM");
86879566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &x1local));
86889566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, x1, INSERT_VALUES, x1local));
86899566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, x1, INSERT_VALUES, x1local));
8690531c7667SBarry Smith     x1 = x1local;
8691531c7667SBarry Smith   }
86929566063dSJacob Faibussowitsch   PetscCall(MatFDColoringApply_AIJ(J, coloring, x1, sctx));
8693531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8694531c7667SBarry Smith     DM dm;
86959566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
86969566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &x1));
8697531c7667SBarry Smith   }
86983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8699531c7667SBarry Smith }
8700531c7667SBarry Smith 
8701531c7667SBarry Smith /*@
8702bb7acecfSBarry Smith   MatFDColoringUseDM - allows a `MatFDColoring` object to use the `DM` associated with the matrix to compute a `IS_COLORING_LOCAL` coloring
8703531c7667SBarry Smith 
8704a4e35b19SJacob Faibussowitsch   Input Parameters:
8705a4e35b19SJacob Faibussowitsch + coloring   - The matrix to get the `DM` from
8706a4e35b19SJacob Faibussowitsch - fdcoloring - the `MatFDColoring` object
8707531c7667SBarry Smith 
87089bdbcad8SBarry Smith   Level: advanced
87099bdbcad8SBarry Smith 
871073ff1848SBarry Smith   Developer Note:
871173ff1848SBarry Smith   This routine exists because the PETSc `Mat` library does not know about the `DM` objects
8712531c7667SBarry Smith 
87131cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatFDColoring`, `MatFDColoringCreate()`, `ISColoringType`
8714531c7667SBarry Smith @*/
8715d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringUseDM(Mat coloring, MatFDColoring fdcoloring)
8716d71ae5a4SJacob Faibussowitsch {
8717531c7667SBarry Smith   PetscFunctionBegin;
8718531c7667SBarry Smith   coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
87193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8720531c7667SBarry Smith }
87218320bc6fSPatrick Sanan 
87228320bc6fSPatrick Sanan /*@
8723bb7acecfSBarry Smith   DMGetCompatibility - determine if two `DM`s are compatible
87248320bc6fSPatrick Sanan 
87258320bc6fSPatrick Sanan   Collective
87268320bc6fSPatrick Sanan 
87278320bc6fSPatrick Sanan   Input Parameters:
8728bb7acecfSBarry Smith + dm1 - the first `DM`
8729bb7acecfSBarry Smith - dm2 - the second `DM`
87308320bc6fSPatrick Sanan 
87318320bc6fSPatrick Sanan   Output Parameters:
8732bb7acecfSBarry Smith + compatible - whether or not the two `DM`s are compatible
8733bb7acecfSBarry Smith - set        - whether or not the compatible value was actually determined and set
87348320bc6fSPatrick Sanan 
873520f4b53cSBarry Smith   Level: advanced
873620f4b53cSBarry Smith 
87378320bc6fSPatrick Sanan   Notes:
8738bb7acecfSBarry Smith   Two `DM`s are deemed compatible if they represent the same parallel decomposition
87393d862458SPatrick Sanan   of the same topology. This implies that the section (field data) on one
87408320bc6fSPatrick Sanan   "makes sense" with respect to the topology and parallel decomposition of the other.
8741bb7acecfSBarry Smith   Loosely speaking, compatible `DM`s represent the same domain and parallel
87423d862458SPatrick Sanan   decomposition, but hold different data.
87438320bc6fSPatrick Sanan 
87448320bc6fSPatrick Sanan   Typically, one would confirm compatibility if intending to simultaneously iterate
8745bb7acecfSBarry Smith   over a pair of vectors obtained from different `DM`s.
87468320bc6fSPatrick Sanan 
8747bb7acecfSBarry Smith   For example, two `DMDA` objects are compatible if they have the same local
87488320bc6fSPatrick Sanan   and global sizes and the same stencil width. They can have different numbers
87498320bc6fSPatrick Sanan   of degrees of freedom per node. Thus, one could use the node numbering from
8750bb7acecfSBarry Smith   either `DM` in bounds for a loop over vectors derived from either `DM`.
87518320bc6fSPatrick Sanan 
8752bb7acecfSBarry Smith   Consider the operation of summing data living on a 2-dof `DMDA` to data living
8753bb7acecfSBarry Smith   on a 1-dof `DMDA`, which should be compatible, as in the following snippet.
87548320bc6fSPatrick Sanan .vb
87558320bc6fSPatrick Sanan   ...
87569566063dSJacob Faibussowitsch   PetscCall(DMGetCompatibility(da1,da2,&compatible,&set));
87578320bc6fSPatrick Sanan   if (set && compatible)  {
87589566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da1,vec1,&arr1));
87599566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da2,vec2,&arr2));
87609566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL));
87618320bc6fSPatrick Sanan     for (j=y; j<y+n; ++j) {
87628320bc6fSPatrick Sanan       for (i=x; i<x+m, ++i) {
87638320bc6fSPatrick Sanan         arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1];
87648320bc6fSPatrick Sanan       }
87658320bc6fSPatrick Sanan     }
87669566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da1,vec1,&arr1));
87679566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da2,vec2,&arr2));
87688320bc6fSPatrick Sanan   } else {
87698320bc6fSPatrick Sanan     SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible");
87708320bc6fSPatrick Sanan   }
87718320bc6fSPatrick Sanan   ...
87728320bc6fSPatrick Sanan .ve
87738320bc6fSPatrick Sanan 
8774bb7acecfSBarry Smith   Checking compatibility might be expensive for a given implementation of `DM`,
87758320bc6fSPatrick Sanan   or might be impossible to unambiguously confirm or deny. For this reason,
87768320bc6fSPatrick Sanan   this function may decline to determine compatibility, and hence users should
87778320bc6fSPatrick Sanan   always check the "set" output parameter.
87788320bc6fSPatrick Sanan 
8779bb7acecfSBarry Smith   A `DM` is always compatible with itself.
87808320bc6fSPatrick Sanan 
8781bb7acecfSBarry Smith   In the current implementation, `DM`s which live on "unequal" communicators
87828320bc6fSPatrick Sanan   (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed
87838320bc6fSPatrick Sanan   incompatible.
87848320bc6fSPatrick Sanan 
87858320bc6fSPatrick Sanan   This function is labeled "Collective," as information about all subdomains
8786bb7acecfSBarry Smith   is required on each rank. However, in `DM` implementations which store all this
87878320bc6fSPatrick Sanan   information locally, this function may be merely "Logically Collective".
87888320bc6fSPatrick Sanan 
878973ff1848SBarry Smith   Developer Note:
8790bb7acecfSBarry Smith   Compatibility is assumed to be a symmetric concept; `DM` A is compatible with `DM` B
87913d862458SPatrick Sanan   iff B is compatible with A. Thus, this function checks the implementations
8792a5bc1bf3SBarry Smith   of both dm and dmc (if they are of different types), attempting to determine
8793bb7acecfSBarry Smith   compatibility. It is left to `DM` implementers to ensure that symmetry is
87948320bc6fSPatrick Sanan   preserved. The simplest way to do this is, when implementing type-specific
87953d862458SPatrick Sanan   logic for this function, is to check for existing logic in the implementation
8796bb7acecfSBarry Smith   of other `DM` types and let *set = PETSC_FALSE if found.
87978320bc6fSPatrick Sanan 
87981cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreateCompatibleDMDA()`, `DMStagCreateCompatibleDMStag()`
87998320bc6fSPatrick Sanan @*/
8800d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCompatibility(DM dm1, DM dm2, PetscBool *compatible, PetscBool *set)
8801d71ae5a4SJacob Faibussowitsch {
88028320bc6fSPatrick Sanan   PetscMPIInt compareResult;
88038320bc6fSPatrick Sanan   DMType      type, type2;
88048320bc6fSPatrick Sanan   PetscBool   sameType;
88058320bc6fSPatrick Sanan 
88068320bc6fSPatrick Sanan   PetscFunctionBegin;
8807a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dm1, DM_CLASSID, 1);
88088320bc6fSPatrick Sanan   PetscValidHeaderSpecific(dm2, DM_CLASSID, 2);
88098320bc6fSPatrick Sanan 
88108320bc6fSPatrick Sanan   /* Declare a DM compatible with itself */
8811a5bc1bf3SBarry Smith   if (dm1 == dm2) {
88128320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
88138320bc6fSPatrick Sanan     *compatible = PETSC_TRUE;
88143ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
88158320bc6fSPatrick Sanan   }
88168320bc6fSPatrick Sanan 
88178320bc6fSPatrick Sanan   /* Declare a DM incompatible with a DM that lives on an "unequal"
88188320bc6fSPatrick Sanan      communicator. Note that this does not preclude compatibility with
88198320bc6fSPatrick Sanan      DMs living on "congruent" or "similar" communicators, but this must be
88208320bc6fSPatrick Sanan      determined by the implementation-specific logic */
88219566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)dm1), PetscObjectComm((PetscObject)dm2), &compareResult));
88228320bc6fSPatrick Sanan   if (compareResult == MPI_UNEQUAL) {
88238320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
88248320bc6fSPatrick Sanan     *compatible = PETSC_FALSE;
88253ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
88268320bc6fSPatrick Sanan   }
88278320bc6fSPatrick Sanan 
88288320bc6fSPatrick Sanan   /* Pass to the implementation-specific routine, if one exists. */
8829a5bc1bf3SBarry Smith   if (dm1->ops->getcompatibility) {
8830dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm1, getcompatibility, dm2, compatible, set);
88313ba16761SJacob Faibussowitsch     if (*set) PetscFunctionReturn(PETSC_SUCCESS);
88328320bc6fSPatrick Sanan   }
88338320bc6fSPatrick Sanan 
8834a5bc1bf3SBarry Smith   /* If dm1 and dm2 are of different types, then attempt to check compatibility
88358320bc6fSPatrick Sanan      with an implementation of this function from dm2 */
88369566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm1, &type));
88379566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm2, &type2));
88389566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(type, type2, &sameType));
88398320bc6fSPatrick Sanan   if (!sameType && dm2->ops->getcompatibility) {
8840dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm2, getcompatibility, dm1, compatible, set); /* Note argument order */
88418320bc6fSPatrick Sanan   } else {
88428320bc6fSPatrick Sanan     *set = PETSC_FALSE;
88438320bc6fSPatrick Sanan   }
88443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
88458320bc6fSPatrick Sanan }
8846c0f0dcc3SMatthew G. Knepley 
8847c0f0dcc3SMatthew G. Knepley /*@C
8848bb7acecfSBarry Smith   DMMonitorSet - Sets an additional monitor function that is to be used after a solve to monitor discretization performance.
8849c0f0dcc3SMatthew G. Knepley 
885020f4b53cSBarry Smith   Logically Collective
8851c0f0dcc3SMatthew G. Knepley 
8852c0f0dcc3SMatthew G. Knepley   Input Parameters:
885360225df5SJacob Faibussowitsch + dm             - the `DM`
8854c0f0dcc3SMatthew G. Knepley . f              - the monitor function
885520f4b53cSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
885649abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
8857c0f0dcc3SMatthew G. Knepley 
885820f4b53cSBarry Smith   Options Database Key:
885960225df5SJacob Faibussowitsch . -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `DMMonitorSet()`, but
8860c0f0dcc3SMatthew G. Knepley                        does not cancel those set via the options database.
8861c0f0dcc3SMatthew G. Knepley 
88629bdbcad8SBarry Smith   Level: intermediate
88639bdbcad8SBarry Smith 
8864bb7acecfSBarry Smith   Note:
8865c0f0dcc3SMatthew G. Knepley   Several different monitoring routines may be set by calling
8866bb7acecfSBarry Smith   `DMMonitorSet()` multiple times or with `DMMonitorSetFromOptions()`; all will be called in the
8867c0f0dcc3SMatthew G. Knepley   order in which they were set.
8868c0f0dcc3SMatthew G. Knepley 
886973ff1848SBarry Smith   Fortran Note:
8870bb7acecfSBarry Smith   Only a single monitor function can be set for each `DM` object
8871bb7acecfSBarry Smith 
887273ff1848SBarry Smith   Developer Note:
8873bb7acecfSBarry Smith   This API has a generic name but seems specific to a very particular aspect of the use of `DM`
8874c0f0dcc3SMatthew G. Knepley 
887549abdd8aSBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorCancel()`, `DMMonitorSetFromOptions()`, `DMMonitor()`, `PetscCtxDestroyFn`
8876c0f0dcc3SMatthew G. Knepley @*/
887749abdd8aSBarry Smith PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscCtxDestroyFn *monitordestroy)
8878d71ae5a4SJacob Faibussowitsch {
8879c0f0dcc3SMatthew G. Knepley   PetscInt m;
8880c0f0dcc3SMatthew G. Knepley 
8881c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8882c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8883c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
8884c0f0dcc3SMatthew G. Knepley     PetscBool identical;
8885c0f0dcc3SMatthew G. Knepley 
88869566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical));
88873ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
8888c0f0dcc3SMatthew G. Knepley   }
88897a8be351SBarry Smith   PetscCheck(dm->numbermonitors < MAXDMMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
8890c0f0dcc3SMatthew G. Knepley   dm->monitor[dm->numbermonitors]          = f;
8891c0f0dcc3SMatthew G. Knepley   dm->monitordestroy[dm->numbermonitors]   = monitordestroy;
8892835f2295SStefano Zampini   dm->monitorcontext[dm->numbermonitors++] = mctx;
88933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8894c0f0dcc3SMatthew G. Knepley }
8895c0f0dcc3SMatthew G. Knepley 
8896c0f0dcc3SMatthew G. Knepley /*@
8897bb7acecfSBarry Smith   DMMonitorCancel - Clears all the monitor functions for a `DM` object.
8898c0f0dcc3SMatthew G. Knepley 
889920f4b53cSBarry Smith   Logically Collective
8900c0f0dcc3SMatthew G. Knepley 
8901c0f0dcc3SMatthew G. Knepley   Input Parameter:
8902c0f0dcc3SMatthew G. Knepley . dm - the DM
8903c0f0dcc3SMatthew G. Knepley 
8904c0f0dcc3SMatthew G. Knepley   Options Database Key:
8905c0f0dcc3SMatthew G. Knepley . -dm_monitor_cancel - cancels all monitors that have been hardwired
8906bb7acecfSBarry Smith   into a code by calls to `DMonitorSet()`, but does not cancel those
8907c0f0dcc3SMatthew G. Knepley   set via the options database
8908c0f0dcc3SMatthew G. Knepley 
89099bdbcad8SBarry Smith   Level: intermediate
89109bdbcad8SBarry Smith 
8911bb7acecfSBarry Smith   Note:
8912bb7acecfSBarry Smith   There is no way to clear one specific monitor from a `DM` object.
8913c0f0dcc3SMatthew G. Knepley 
89141cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMMonitorSetFromOptions()`, `DMMonitor()`
8915c0f0dcc3SMatthew G. Knepley @*/
8916d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorCancel(DM dm)
8917d71ae5a4SJacob Faibussowitsch {
8918c0f0dcc3SMatthew G. Knepley   PetscInt m;
8919c0f0dcc3SMatthew G. Knepley 
8920c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8921c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8922c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
89239566063dSJacob Faibussowitsch     if (dm->monitordestroy[m]) PetscCall((*dm->monitordestroy[m])(&dm->monitorcontext[m]));
8924c0f0dcc3SMatthew G. Knepley   }
8925c0f0dcc3SMatthew G. Knepley   dm->numbermonitors = 0;
89263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8927c0f0dcc3SMatthew G. Knepley }
8928c0f0dcc3SMatthew G. Knepley 
8929c0f0dcc3SMatthew G. Knepley /*@C
8930c0f0dcc3SMatthew G. Knepley   DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
8931c0f0dcc3SMatthew G. Knepley 
893220f4b53cSBarry Smith   Collective
8933c0f0dcc3SMatthew G. Knepley 
8934c0f0dcc3SMatthew G. Knepley   Input Parameters:
8935bb7acecfSBarry Smith + dm           - `DM` object you wish to monitor
8936c0f0dcc3SMatthew G. Knepley . name         - the monitor type one is seeking
8937c0f0dcc3SMatthew G. Knepley . help         - message indicating what monitoring is done
8938c0f0dcc3SMatthew G. Knepley . manual       - manual page for the monitor
893949abdd8aSBarry Smith . monitor      - the monitor function, this must use a `PetscViewerFormat` as its context
8940bb7acecfSBarry 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
8941c0f0dcc3SMatthew G. Knepley 
8942c0f0dcc3SMatthew G. Knepley   Output Parameter:
8943c0f0dcc3SMatthew G. Knepley . flg - Flag set if the monitor was created
8944c0f0dcc3SMatthew G. Knepley 
8945c0f0dcc3SMatthew G. Knepley   Level: developer
8946c0f0dcc3SMatthew G. Knepley 
8947648c30bcSBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
8948db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
894960225df5SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
8950db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
8951c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
8952db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
8953bb7acecfSBarry Smith           `PetscOptionsFList()`, `PetscOptionsEList()`, `DMMonitor()`, `DMMonitorSet()`
8954c0f0dcc3SMatthew G. Knepley @*/
8955d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg)
8956d71ae5a4SJacob Faibussowitsch {
8957c0f0dcc3SMatthew G. Knepley   PetscViewer       viewer;
8958c0f0dcc3SMatthew G. Knepley   PetscViewerFormat format;
8959c0f0dcc3SMatthew G. Knepley 
8960c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8961c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8962648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)dm), ((PetscObject)dm)->options, ((PetscObject)dm)->prefix, name, &viewer, &format, flg));
8963c0f0dcc3SMatthew G. Knepley   if (*flg) {
8964c0f0dcc3SMatthew G. Knepley     PetscViewerAndFormat *vf;
8965c0f0dcc3SMatthew G. Knepley 
89669566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
8967648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
89689566063dSJacob Faibussowitsch     if (monitorsetup) PetscCall((*monitorsetup)(dm, vf));
8969835f2295SStefano Zampini     PetscCall(DMMonitorSet(dm, monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
8970c0f0dcc3SMatthew G. Knepley   }
89713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8972c0f0dcc3SMatthew G. Knepley }
8973c0f0dcc3SMatthew G. Knepley 
8974c0f0dcc3SMatthew G. Knepley /*@
8975c0f0dcc3SMatthew G. Knepley   DMMonitor - runs the user provided monitor routines, if they exist
8976c0f0dcc3SMatthew G. Knepley 
897720f4b53cSBarry Smith   Collective
8978c0f0dcc3SMatthew G. Knepley 
89792fe279fdSBarry Smith   Input Parameter:
8980bb7acecfSBarry Smith . dm - The `DM`
8981c0f0dcc3SMatthew G. Knepley 
8982c0f0dcc3SMatthew G. Knepley   Level: developer
8983c0f0dcc3SMatthew G. Knepley 
898473ff1848SBarry Smith   Developer Note:
8985a4e35b19SJacob Faibussowitsch   Note should indicate when during the life of the `DM` the monitor is run. It appears to be
8986a4e35b19SJacob Faibussowitsch   related to the discretization process seems rather specialized since some `DM` have no
8987a4e35b19SJacob Faibussowitsch   concept of discretization.
8988bb7acecfSBarry Smith 
89891cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMMonitorSetFromOptions()`
8990c0f0dcc3SMatthew G. Knepley @*/
8991d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitor(DM dm)
8992d71ae5a4SJacob Faibussowitsch {
8993c0f0dcc3SMatthew G. Knepley   PetscInt m;
8994c0f0dcc3SMatthew G. Knepley 
8995c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
89963ba16761SJacob Faibussowitsch   if (!dm) PetscFunctionReturn(PETSC_SUCCESS);
8997c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
899848a46eb9SPierre Jolivet   for (m = 0; m < dm->numbermonitors; ++m) PetscCall((*dm->monitor[m])(dm, dm->monitorcontext[m]));
89993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9000c0f0dcc3SMatthew G. Knepley }
90012e4af2aeSMatthew G. Knepley 
90022e4af2aeSMatthew G. Knepley /*@
9003bb7acecfSBarry Smith   DMComputeError - Computes the error assuming the user has provided the exact solution functions
90042e4af2aeSMatthew G. Knepley 
900520f4b53cSBarry Smith   Collective
90062e4af2aeSMatthew G. Knepley 
90072e4af2aeSMatthew G. Knepley   Input Parameters:
9008bb7acecfSBarry Smith + dm  - The `DM`
90096b867d5aSJose E. Roman - sol - The solution vector
90102e4af2aeSMatthew G. Knepley 
90116b867d5aSJose E. Roman   Input/Output Parameter:
901220f4b53cSBarry Smith . errors - An array of length Nf, the number of fields, or `NULL` for no output; on output
90136b867d5aSJose E. Roman            contains the error in each field
90146b867d5aSJose E. Roman 
90156b867d5aSJose E. Roman   Output Parameter:
901620f4b53cSBarry Smith . errorVec - A vector to hold the cellwise error (may be `NULL`)
901720f4b53cSBarry Smith 
901820f4b53cSBarry Smith   Level: developer
90192e4af2aeSMatthew G. Knepley 
9020bb7acecfSBarry Smith   Note:
9021bb7acecfSBarry Smith   The exact solutions come from the `PetscDS` object, and the time comes from `DMGetOutputSequenceNumber()`.
90222e4af2aeSMatthew G. Knepley 
90231cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMGetRegionNumDS()`, `PetscDSGetExactSolution()`, `DMGetOutputSequenceNumber()`
90242e4af2aeSMatthew G. Knepley @*/
9025d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec)
9026d71ae5a4SJacob Faibussowitsch {
90272e4af2aeSMatthew G. Knepley   PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
90282e4af2aeSMatthew G. Knepley   void    **ctxs;
90292e4af2aeSMatthew G. Knepley   PetscReal time;
90302e4af2aeSMatthew G. Knepley   PetscInt  Nf, f, Nds, s;
90312e4af2aeSMatthew G. Knepley 
90322e4af2aeSMatthew G. Knepley   PetscFunctionBegin;
90339566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
90349566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(Nf, &exactSol, Nf, &ctxs));
90359566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
90362e4af2aeSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
90372e4af2aeSMatthew G. Knepley     PetscDS         ds;
90382e4af2aeSMatthew G. Knepley     DMLabel         label;
90392e4af2aeSMatthew G. Knepley     IS              fieldIS;
90402e4af2aeSMatthew G. Knepley     const PetscInt *fields;
90412e4af2aeSMatthew G. Knepley     PetscInt        dsNf;
90422e4af2aeSMatthew G. Knepley 
904307218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds, NULL));
90449566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
90459566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISGetIndices(fieldIS, &fields));
90462e4af2aeSMatthew G. Knepley     for (f = 0; f < dsNf; ++f) {
90472e4af2aeSMatthew G. Knepley       const PetscInt field = fields[f];
90489566063dSJacob Faibussowitsch       PetscCall(PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]));
90492e4af2aeSMatthew G. Knepley     }
90509566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISRestoreIndices(fieldIS, &fields));
90512e4af2aeSMatthew G. Knepley   }
9052ad540459SPierre 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);
90539566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
90549566063dSJacob Faibussowitsch   if (errors) PetscCall(DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors));
90552e4af2aeSMatthew G. Knepley   if (errorVec) {
90562e4af2aeSMatthew G. Knepley     DM             edm;
90572e4af2aeSMatthew G. Knepley     DMPolytopeType ct;
90582e4af2aeSMatthew G. Knepley     PetscBool      simplex;
90592e4af2aeSMatthew G. Knepley     PetscInt       dim, cStart, Nf;
90602e4af2aeSMatthew G. Knepley 
90619566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &edm));
90629566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(edm, &dim));
90639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
90649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cStart, &ct));
90652e4af2aeSMatthew G. Knepley     simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
90669566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
90672e4af2aeSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
90682e4af2aeSMatthew G. Knepley       PetscFE         fe, efe;
90692e4af2aeSMatthew G. Knepley       PetscQuadrature q;
90702e4af2aeSMatthew G. Knepley       const char     *name;
90712e4af2aeSMatthew G. Knepley 
90729566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe));
90739566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe));
90749566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)fe, &name));
90759566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)efe, name));
90769566063dSJacob Faibussowitsch       PetscCall(PetscFEGetQuadrature(fe, &q));
90779566063dSJacob Faibussowitsch       PetscCall(PetscFESetQuadrature(efe, q));
90789566063dSJacob Faibussowitsch       PetscCall(DMSetField(edm, f, NULL, (PetscObject)efe));
90799566063dSJacob Faibussowitsch       PetscCall(PetscFEDestroy(&efe));
90802e4af2aeSMatthew G. Knepley     }
90819566063dSJacob Faibussowitsch     PetscCall(DMCreateDS(edm));
90822e4af2aeSMatthew G. Knepley 
90839566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(edm, errorVec));
90849566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*errorVec, "Error"));
90859566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec));
90869566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&edm));
90872e4af2aeSMatthew G. Knepley   }
90889566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exactSol, ctxs));
90893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
90902e4af2aeSMatthew G. Knepley }
90919a2a23afSMatthew G. Knepley 
90929a2a23afSMatthew G. Knepley /*@
9093bb7acecfSBarry Smith   DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this `DM`
90949a2a23afSMatthew G. Knepley 
909520f4b53cSBarry Smith   Not Collective
90969a2a23afSMatthew G. Knepley 
90979a2a23afSMatthew G. Knepley   Input Parameter:
9098bb7acecfSBarry Smith . dm - The `DM`
90999a2a23afSMatthew G. Knepley 
91009a2a23afSMatthew G. Knepley   Output Parameter:
9101a5b23f4aSJose E. Roman . numAux - The number of auxiliary data vectors
91029a2a23afSMatthew G. Knepley 
91039a2a23afSMatthew G. Knepley   Level: advanced
91049a2a23afSMatthew G. Knepley 
9105e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMClearAuxiliaryVec()`, `DMSetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMGetAuxiliaryVec()`
91069a2a23afSMatthew G. Knepley @*/
9107d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux)
9108d71ae5a4SJacob Faibussowitsch {
91099a2a23afSMatthew G. Knepley   PetscFunctionBegin;
91109a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91119566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetSize(dm->auxData, numAux));
91123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91139a2a23afSMatthew G. Knepley }
91149a2a23afSMatthew G. Knepley 
91159a2a23afSMatthew G. Knepley /*@
9116ac17215fSMatthew G. Knepley   DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value, and equation part
91179a2a23afSMatthew G. Knepley 
911820f4b53cSBarry Smith   Not Collective
91199a2a23afSMatthew G. Knepley 
91209a2a23afSMatthew G. Knepley   Input Parameters:
9121bb7acecfSBarry Smith + dm    - The `DM`
9122bb7acecfSBarry Smith . label - The `DMLabel`
9123ac17215fSMatthew G. Knepley . value - The label value indicating the region
9124ac17215fSMatthew G. Knepley - part  - The equation part, or 0 if unused
91259a2a23afSMatthew G. Knepley 
91269a2a23afSMatthew G. Knepley   Output Parameter:
9127bb7acecfSBarry Smith . aux - The `Vec` holding auxiliary field data
91289a2a23afSMatthew G. Knepley 
91299bdbcad8SBarry Smith   Level: advanced
91309bdbcad8SBarry Smith 
9131bb7acecfSBarry Smith   Note:
9132bb7acecfSBarry Smith   If no auxiliary vector is found for this (label, value), (NULL, 0, 0) is checked as well.
913304c51a94SMatthew G. Knepley 
9134e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMClearAuxiliaryVec()`, `DMSetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryLabels()`
91359a2a23afSMatthew G. Knepley @*/
9136d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec *aux)
9137d71ae5a4SJacob Faibussowitsch {
9138ac17215fSMatthew G. Knepley   PetscHashAuxKey key, wild = {NULL, 0, 0};
913904c51a94SMatthew G. Knepley   PetscBool       has;
91409a2a23afSMatthew G. Knepley 
91419a2a23afSMatthew G. Knepley   PetscFunctionBegin;
91429a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91439a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
91449a2a23afSMatthew G. Knepley   key.label = label;
91459a2a23afSMatthew G. Knepley   key.value = value;
9146ac17215fSMatthew G. Knepley   key.part  = part;
91479566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxHas(dm->auxData, key, &has));
91489566063dSJacob Faibussowitsch   if (has) PetscCall(PetscHMapAuxGet(dm->auxData, key, aux));
91499566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxGet(dm->auxData, wild, aux));
91503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91519a2a23afSMatthew G. Knepley }
91529a2a23afSMatthew G. Knepley 
91539a2a23afSMatthew G. Knepley /*@
9154bb7acecfSBarry Smith   DMSetAuxiliaryVec - Set an auxiliary vector for region specified by the given label and value, and equation part
91559a2a23afSMatthew G. Knepley 
915620f4b53cSBarry Smith   Not Collective because auxiliary vectors are not parallel
91579a2a23afSMatthew G. Knepley 
91589a2a23afSMatthew G. Knepley   Input Parameters:
9159bb7acecfSBarry Smith + dm    - The `DM`
9160bb7acecfSBarry Smith . label - The `DMLabel`
91619a2a23afSMatthew G. Knepley . value - The label value indicating the region
9162ac17215fSMatthew G. Knepley . part  - The equation part, or 0 if unused
9163bb7acecfSBarry Smith - aux   - The `Vec` holding auxiliary field data
91649a2a23afSMatthew G. Knepley 
91659a2a23afSMatthew G. Knepley   Level: advanced
91669a2a23afSMatthew G. Knepley 
9167e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMClearAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMCopyAuxiliaryVec()`
91689a2a23afSMatthew G. Knepley @*/
9169d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec aux)
9170d71ae5a4SJacob Faibussowitsch {
91719a2a23afSMatthew G. Knepley   Vec             old;
91729a2a23afSMatthew G. Knepley   PetscHashAuxKey key;
91739a2a23afSMatthew G. Knepley 
91749a2a23afSMatthew G. Knepley   PetscFunctionBegin;
91759a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91769a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
91779a2a23afSMatthew G. Knepley   key.label = label;
91789a2a23afSMatthew G. Knepley   key.value = value;
9179ac17215fSMatthew G. Knepley   key.part  = part;
91809566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGet(dm->auxData, key, &old));
91819566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)aux));
91829566063dSJacob Faibussowitsch   if (!aux) PetscCall(PetscHMapAuxDel(dm->auxData, key));
91839566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxSet(dm->auxData, key, aux));
9184d705d0eaSStefano Zampini   PetscCall(VecDestroy(&old));
91853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91869a2a23afSMatthew G. Knepley }
91879a2a23afSMatthew G. Knepley 
9188cc4c1da9SBarry Smith /*@
9189bb7acecfSBarry Smith   DMGetAuxiliaryLabels - Get the labels, values, and parts for all auxiliary vectors in this `DM`
91909a2a23afSMatthew G. Knepley 
919120f4b53cSBarry Smith   Not Collective
91929a2a23afSMatthew G. Knepley 
91939a2a23afSMatthew G. Knepley   Input Parameter:
9194bb7acecfSBarry Smith . dm - The `DM`
91959a2a23afSMatthew G. Knepley 
91969a2a23afSMatthew G. Knepley   Output Parameters:
9197bb7acecfSBarry Smith + labels - The `DMLabel`s for each `Vec`
9198bb7acecfSBarry Smith . values - The label values for each `Vec`
9199bb7acecfSBarry Smith - parts  - The equation parts for each `Vec`
92009a2a23afSMatthew G. Knepley 
92019bdbcad8SBarry Smith   Level: advanced
92029bdbcad8SBarry Smith 
9203bb7acecfSBarry Smith   Note:
9204bb7acecfSBarry Smith   The arrays passed in must be at least as large as `DMGetNumAuxiliaryVec()`.
92059a2a23afSMatthew G. Knepley 
9206e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMClearAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`, `DMCopyAuxiliaryVec()`
92079a2a23afSMatthew G. Knepley @*/
9208d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[], PetscInt parts[])
9209d71ae5a4SJacob Faibussowitsch {
92109a2a23afSMatthew G. Knepley   PetscHashAuxKey *keys;
92119a2a23afSMatthew G. Knepley   PetscInt         n, i, off = 0;
92129a2a23afSMatthew G. Knepley 
92139a2a23afSMatthew G. Knepley   PetscFunctionBegin;
92149a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
92154f572ea9SToby Isaac   PetscAssertPointer(labels, 2);
92164f572ea9SToby Isaac   PetscAssertPointer(values, 3);
92174f572ea9SToby Isaac   PetscAssertPointer(parts, 4);
92189566063dSJacob Faibussowitsch   PetscCall(DMGetNumAuxiliaryVec(dm, &n));
92199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &keys));
92209566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetKeys(dm->auxData, &off, keys));
92219371c9d4SSatish Balay   for (i = 0; i < n; ++i) {
92229371c9d4SSatish Balay     labels[i] = keys[i].label;
92239371c9d4SSatish Balay     values[i] = keys[i].value;
92249371c9d4SSatish Balay     parts[i]  = keys[i].part;
92259371c9d4SSatish Balay   }
92269566063dSJacob Faibussowitsch   PetscCall(PetscFree(keys));
92273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
92289a2a23afSMatthew G. Knepley }
92299a2a23afSMatthew G. Knepley 
92309a2a23afSMatthew G. Knepley /*@
9231bb7acecfSBarry Smith   DMCopyAuxiliaryVec - Copy the auxiliary vector data on a `DM` to a new `DM`
92329a2a23afSMatthew G. Knepley 
923320f4b53cSBarry Smith   Not Collective
92349a2a23afSMatthew G. Knepley 
92359a2a23afSMatthew G. Knepley   Input Parameter:
9236bb7acecfSBarry Smith . dm - The `DM`
92379a2a23afSMatthew G. Knepley 
92389a2a23afSMatthew G. Knepley   Output Parameter:
9239bb7acecfSBarry Smith . dmNew - The new `DM`, now with the same auxiliary data
92409a2a23afSMatthew G. Knepley 
92419a2a23afSMatthew G. Knepley   Level: advanced
92429a2a23afSMatthew G. Knepley 
9243bb7acecfSBarry Smith   Note:
9244bb7acecfSBarry Smith   This is a shallow copy of the auxiliary vectors
9245bb7acecfSBarry Smith 
9246e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMClearAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
92479a2a23afSMatthew G. Knepley @*/
9248d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew)
9249d71ae5a4SJacob Faibussowitsch {
92509a2a23afSMatthew G. Knepley   PetscFunctionBegin;
92519a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9252d705d0eaSStefano Zampini   PetscValidHeaderSpecific(dmNew, DM_CLASSID, 2);
9253d705d0eaSStefano Zampini   if (dm == dmNew) PetscFunctionReturn(PETSC_SUCCESS);
9254e4d5475eSStefano Zampini   PetscCall(DMClearAuxiliaryVec(dmNew));
9255e4d5475eSStefano Zampini 
9256e4d5475eSStefano Zampini   PetscCall(PetscHMapAuxDestroy(&dmNew->auxData));
92579566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData));
9258d705d0eaSStefano Zampini   {
9259d705d0eaSStefano Zampini     Vec     *auxData;
9260d705d0eaSStefano Zampini     PetscInt n, i, off = 0;
9261d705d0eaSStefano Zampini 
9262d705d0eaSStefano Zampini     PetscCall(PetscHMapAuxGetSize(dmNew->auxData, &n));
9263d705d0eaSStefano Zampini     PetscCall(PetscMalloc1(n, &auxData));
9264d705d0eaSStefano Zampini     PetscCall(PetscHMapAuxGetVals(dmNew->auxData, &off, auxData));
9265d705d0eaSStefano Zampini     for (i = 0; i < n; ++i) PetscCall(PetscObjectReference((PetscObject)auxData[i]));
9266d705d0eaSStefano Zampini     PetscCall(PetscFree(auxData));
9267e4d5475eSStefano Zampini   }
9268e4d5475eSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
9269e4d5475eSStefano Zampini }
9270e4d5475eSStefano Zampini 
9271e4d5475eSStefano Zampini /*@
9272e4d5475eSStefano Zampini   DMClearAuxiliaryVec - Destroys the auxiliary vector information and creates a new empty one
9273e4d5475eSStefano Zampini 
9274e4d5475eSStefano Zampini   Not Collective
9275e4d5475eSStefano Zampini 
9276e4d5475eSStefano Zampini   Input Parameter:
9277e4d5475eSStefano Zampini . dm - The `DM`
9278e4d5475eSStefano Zampini 
9279e4d5475eSStefano Zampini   Level: advanced
9280e4d5475eSStefano Zampini 
9281e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMCopyAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
9282e4d5475eSStefano Zampini @*/
9283e4d5475eSStefano Zampini PetscErrorCode DMClearAuxiliaryVec(DM dm)
9284e4d5475eSStefano Zampini {
9285e4d5475eSStefano Zampini   Vec     *auxData;
9286e4d5475eSStefano Zampini   PetscInt n, i, off = 0;
9287e4d5475eSStefano Zampini 
9288e4d5475eSStefano Zampini   PetscFunctionBegin;
9289e4d5475eSStefano Zampini   PetscCall(PetscHMapAuxGetSize(dm->auxData, &n));
9290d705d0eaSStefano Zampini   PetscCall(PetscMalloc1(n, &auxData));
9291e4d5475eSStefano Zampini   PetscCall(PetscHMapAuxGetVals(dm->auxData, &off, auxData));
9292d705d0eaSStefano Zampini   for (i = 0; i < n; ++i) PetscCall(VecDestroy(&auxData[i]));
9293d705d0eaSStefano Zampini   PetscCall(PetscFree(auxData));
9294e4d5475eSStefano Zampini   PetscCall(PetscHMapAuxDestroy(&dm->auxData));
9295e4d5475eSStefano Zampini   PetscCall(PetscHMapAuxCreate(&dm->auxData));
92963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
92979a2a23afSMatthew G. Knepley }
9298b5a892a1SMatthew G. Knepley 
9299cc4c1da9SBarry Smith /*@
9300bb7acecfSBarry Smith   DMPolytopeMatchOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9301b5a892a1SMatthew G. Knepley 
930220f4b53cSBarry Smith   Not Collective
9303b5a892a1SMatthew G. Knepley 
9304b5a892a1SMatthew G. Knepley   Input Parameters:
9305bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9306b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9307b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9308b5a892a1SMatthew G. Knepley 
9309b5a892a1SMatthew G. Knepley   Output Parameters:
9310bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9311b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9312b5a892a1SMatthew G. Knepley 
9313b5a892a1SMatthew G. Knepley   Level: advanced
9314b5a892a1SMatthew G. Knepley 
9315bb7acecfSBarry Smith   Note:
9316bb7acecfSBarry Smith   An arrangement is a face order combined with an orientation for each face
9317bb7acecfSBarry Smith 
931885036b15SMatthew G. Knepley   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangements(ct)`/2 to `DMPolytopeTypeGetNumArrangements(ct)`/2
9319bb7acecfSBarry Smith   that labels each arrangement (face ordering plus orientation for each face).
9320bb7acecfSBarry Smith 
9321bb7acecfSBarry Smith   See `DMPolytopeMatchVertexOrientation()` to find a new vertex orientation that takes the source vertex arrangement to the target vertex arrangement
9322bb7acecfSBarry Smith 
93231cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetVertexOrientation()`
9324b5a892a1SMatthew G. Knepley @*/
9325d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt, PetscBool *found)
9326d71ae5a4SJacob Faibussowitsch {
9327b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetConeSize(ct);
932885036b15SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangements(ct) / 2;
9329b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9330b5a892a1SMatthew G. Knepley 
9331b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
93329371c9d4SSatish Balay   if (!nO) {
93339371c9d4SSatish Balay     *ornt  = 0;
93349371c9d4SSatish Balay     *found = PETSC_TRUE;
93353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
93369371c9d4SSatish Balay   }
9337b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
933885036b15SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o);
9339b5a892a1SMatthew G. Knepley 
93409371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
93419371c9d4SSatish Balay       if (sourceCone[arr[c * 2]] != targetCone[c]) break;
93429371c9d4SSatish Balay     if (c == cS) {
93439371c9d4SSatish Balay       *ornt = o;
93449371c9d4SSatish Balay       break;
93459371c9d4SSatish Balay     }
9346b5a892a1SMatthew G. Knepley   }
9347b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
93483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9349b5a892a1SMatthew G. Knepley }
9350b5a892a1SMatthew G. Knepley 
9351cc4c1da9SBarry Smith /*@
9352bb7acecfSBarry Smith   DMPolytopeGetOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9353b5a892a1SMatthew G. Knepley 
935420f4b53cSBarry Smith   Not Collective
9355b5a892a1SMatthew G. Knepley 
9356b5a892a1SMatthew G. Knepley   Input Parameters:
9357bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9358b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9359b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9360b5a892a1SMatthew G. Knepley 
93612fe279fdSBarry Smith   Output Parameter:
9362bb7acecfSBarry Smith . ornt - The orientation (transformation) which will take the source arrangement to the target arrangement
9363b5a892a1SMatthew G. Knepley 
9364b5a892a1SMatthew G. Knepley   Level: advanced
9365b5a892a1SMatthew G. Knepley 
9366bb7acecfSBarry Smith   Note:
9367bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchOrientation()` except it will generate an error if no suitable orientation can be found.
9368bb7acecfSBarry Smith 
936973ff1848SBarry Smith   Developer Note:
9370bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchOrientation()` and error if none is found
9371bb7acecfSBarry Smith 
93721cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeMatchOrientation()`, `DMPolytopeGetVertexOrientation()`, `DMPolytopeMatchVertexOrientation()`
9373b5a892a1SMatthew G. Knepley @*/
9374d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9375d71ae5a4SJacob Faibussowitsch {
9376b5a892a1SMatthew G. Knepley   PetscBool found;
9377b5a892a1SMatthew G. Knepley 
9378b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
93799566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchOrientation(ct, sourceCone, targetCone, ornt, &found));
93807a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
93813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9382b5a892a1SMatthew G. Knepley }
9383b5a892a1SMatthew G. Knepley 
9384cc4c1da9SBarry Smith /*@
9385bb7acecfSBarry Smith   DMPolytopeMatchVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9386b5a892a1SMatthew G. Knepley 
938720f4b53cSBarry Smith   Not Collective
9388b5a892a1SMatthew G. Knepley 
9389b5a892a1SMatthew G. Knepley   Input Parameters:
9390bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9391b5a892a1SMatthew G. Knepley . sourceVert - The source arrangement of vertices
9392b5a892a1SMatthew G. Knepley - targetVert - The target arrangement of vertices
9393b5a892a1SMatthew G. Knepley 
9394b5a892a1SMatthew G. Knepley   Output Parameters:
9395bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9396b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9397b5a892a1SMatthew G. Knepley 
9398b5a892a1SMatthew G. Knepley   Level: advanced
9399b5a892a1SMatthew G. Knepley 
940073ff1848SBarry Smith   Notes:
9401bb7acecfSBarry Smith   An arrangement is a vertex order
9402bb7acecfSBarry Smith 
940385036b15SMatthew G. Knepley   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangements(ct)`/2 to `DMPolytopeTypeGetNumArrangements(ct)`/2
9404bb7acecfSBarry Smith   that labels each arrangement (vertex ordering).
9405bb7acecfSBarry Smith 
9406bb7acecfSBarry Smith   See `DMPolytopeMatchOrientation()` to find a new face orientation that takes the source face arrangement to the target face arrangement
9407bb7acecfSBarry Smith 
940885036b15SMatthew G. Knepley .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchOrientation()`, `DMPolytopeTypeGetNumVertices()`, `DMPolytopeTypeGetVertexArrangement()`
9409b5a892a1SMatthew G. Knepley @*/
9410d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchVertexOrientation(DMPolytopeType ct, const PetscInt sourceVert[], const PetscInt targetVert[], PetscInt *ornt, PetscBool *found)
9411d71ae5a4SJacob Faibussowitsch {
9412b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetNumVertices(ct);
941385036b15SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangements(ct) / 2;
9414b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9415b5a892a1SMatthew G. Knepley 
9416b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
94179371c9d4SSatish Balay   if (!nO) {
94189371c9d4SSatish Balay     *ornt  = 0;
94199371c9d4SSatish Balay     *found = PETSC_TRUE;
94203ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
94219371c9d4SSatish Balay   }
9422b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
942385036b15SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetVertexArrangement(ct, o);
9424b5a892a1SMatthew G. Knepley 
94259371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
94269371c9d4SSatish Balay       if (sourceVert[arr[c]] != targetVert[c]) break;
94279371c9d4SSatish Balay     if (c == cS) {
94289371c9d4SSatish Balay       *ornt = o;
94299371c9d4SSatish Balay       break;
94309371c9d4SSatish Balay     }
9431b5a892a1SMatthew G. Knepley   }
9432b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
94333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9434b5a892a1SMatthew G. Knepley }
9435b5a892a1SMatthew G. Knepley 
9436cc4c1da9SBarry Smith /*@
9437bb7acecfSBarry Smith   DMPolytopeGetVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9438b5a892a1SMatthew G. Knepley 
943920f4b53cSBarry Smith   Not Collective
9440b5a892a1SMatthew G. Knepley 
9441b5a892a1SMatthew G. Knepley   Input Parameters:
9442bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9443b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of vertices
9444b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of vertices
9445b5a892a1SMatthew G. Knepley 
94462fe279fdSBarry Smith   Output Parameter:
9447bb7acecfSBarry Smith . ornt - The orientation (transformation) which will take the source arrangement to the target arrangement
9448b5a892a1SMatthew G. Knepley 
9449b5a892a1SMatthew G. Knepley   Level: advanced
9450b5a892a1SMatthew G. Knepley 
9451bb7acecfSBarry Smith   Note:
9452bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchVertexOrientation()` except it errors if not orientation is possible.
9453bb7acecfSBarry Smith 
945473ff1848SBarry Smith   Developer Note:
9455bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchVertexOrientation()` and error if none is found
9456bb7acecfSBarry Smith 
94571cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetOrientation()`
9458b5a892a1SMatthew G. Knepley @*/
9459d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetVertexOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9460d71ae5a4SJacob Faibussowitsch {
9461b5a892a1SMatthew G. Knepley   PetscBool found;
9462b5a892a1SMatthew G. Knepley 
9463b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
94649566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchVertexOrientation(ct, sourceCone, targetCone, ornt, &found));
94657a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
94663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9467b5a892a1SMatthew G. Knepley }
9468012bc364SMatthew G. Knepley 
9469cc4c1da9SBarry Smith /*@
9470012bc364SMatthew G. Knepley   DMPolytopeInCellTest - Check whether a point lies inside the reference cell of given type
9471012bc364SMatthew G. Knepley 
947220f4b53cSBarry Smith   Not Collective
9473012bc364SMatthew G. Knepley 
9474012bc364SMatthew G. Knepley   Input Parameters:
9475bb7acecfSBarry Smith + ct    - The `DMPolytopeType`
9476012bc364SMatthew G. Knepley - point - Coordinates of the point
9477012bc364SMatthew G. Knepley 
94782fe279fdSBarry Smith   Output Parameter:
9479012bc364SMatthew G. Knepley . inside - Flag indicating whether the point is inside the reference cell of given type
9480012bc364SMatthew G. Knepley 
9481012bc364SMatthew G. Knepley   Level: advanced
9482012bc364SMatthew G. Knepley 
94831cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMLocatePoints()`
9484012bc364SMatthew G. Knepley @*/
9485d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeInCellTest(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
9486d71ae5a4SJacob Faibussowitsch {
9487012bc364SMatthew G. Knepley   PetscReal sum = 0.0;
9488012bc364SMatthew G. Knepley   PetscInt  d;
9489012bc364SMatthew G. Knepley 
9490012bc364SMatthew G. Knepley   PetscFunctionBegin;
9491012bc364SMatthew G. Knepley   *inside = PETSC_TRUE;
9492012bc364SMatthew G. Knepley   switch (ct) {
9493012bc364SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
9494012bc364SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
9495012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
94969371c9d4SSatish Balay       if (point[d] < -1.0) {
94979371c9d4SSatish Balay         *inside = PETSC_FALSE;
94989371c9d4SSatish Balay         break;
94999371c9d4SSatish Balay       }
9500012bc364SMatthew G. Knepley       sum += point[d];
9501012bc364SMatthew G. Knepley     }
95029371c9d4SSatish Balay     if (sum > PETSC_SMALL) {
95039371c9d4SSatish Balay       *inside = PETSC_FALSE;
95049371c9d4SSatish Balay       break;
95059371c9d4SSatish Balay     }
9506012bc364SMatthew G. Knepley     break;
9507012bc364SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
9508012bc364SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
9509012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
95109371c9d4SSatish Balay       if (PetscAbsReal(point[d]) > 1. + PETSC_SMALL) {
95119371c9d4SSatish Balay         *inside = PETSC_FALSE;
9512012bc364SMatthew G. Knepley         break;
95139371c9d4SSatish Balay       }
95149371c9d4SSatish Balay     break;
9515d71ae5a4SJacob Faibussowitsch   default:
9516d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
9517012bc364SMatthew G. Knepley   }
95183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9519012bc364SMatthew G. Knepley }
9520adc21957SMatthew G. Knepley 
9521adc21957SMatthew G. Knepley /*@
9522adc21957SMatthew G. Knepley   DMReorderSectionSetDefault - Set flag indicating whether the local section should be reordered by default
9523adc21957SMatthew G. Knepley 
9524adc21957SMatthew G. Knepley   Logically collective
9525adc21957SMatthew G. Knepley 
9526adc21957SMatthew G. Knepley   Input Parameters:
9527adc21957SMatthew G. Knepley + dm      - The DM
9528adc21957SMatthew G. Knepley - reorder - Flag for reordering
9529adc21957SMatthew G. Knepley 
9530adc21957SMatthew G. Knepley   Level: intermediate
9531adc21957SMatthew G. Knepley 
9532adc21957SMatthew G. Knepley .seealso: `DMReorderSectionGetDefault()`
9533adc21957SMatthew G. Knepley @*/
9534adc21957SMatthew G. Knepley PetscErrorCode DMReorderSectionSetDefault(DM dm, DMReorderDefaultFlag reorder)
9535adc21957SMatthew G. Knepley {
9536adc21957SMatthew G. Knepley   PetscFunctionBegin;
9537adc21957SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9538adc21957SMatthew G. Knepley   PetscTryMethod(dm, "DMReorderSectionSetDefault_C", (DM, DMReorderDefaultFlag), (dm, reorder));
9539adc21957SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
9540adc21957SMatthew G. Knepley }
9541adc21957SMatthew G. Knepley 
9542adc21957SMatthew G. Knepley /*@
9543adc21957SMatthew G. Knepley   DMReorderSectionGetDefault - Get flag indicating whether the local section should be reordered by default
9544adc21957SMatthew G. Knepley 
9545adc21957SMatthew G. Knepley   Not collective
9546adc21957SMatthew G. Knepley 
9547adc21957SMatthew G. Knepley   Input Parameter:
9548adc21957SMatthew G. Knepley . dm - The DM
9549adc21957SMatthew G. Knepley 
9550adc21957SMatthew G. Knepley   Output Parameter:
9551adc21957SMatthew G. Knepley . reorder - Flag for reordering
9552adc21957SMatthew G. Knepley 
9553adc21957SMatthew G. Knepley   Level: intermediate
9554adc21957SMatthew G. Knepley 
9555adc21957SMatthew G. Knepley .seealso: `DMReorderSetDefault()`
9556adc21957SMatthew G. Knepley @*/
9557adc21957SMatthew G. Knepley PetscErrorCode DMReorderSectionGetDefault(DM dm, DMReorderDefaultFlag *reorder)
9558adc21957SMatthew G. Knepley {
9559adc21957SMatthew G. Knepley   PetscFunctionBegin;
9560adc21957SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9561adc21957SMatthew G. Knepley   PetscAssertPointer(reorder, 2);
9562adc21957SMatthew G. Knepley   *reorder = DM_REORDER_DEFAULT_NOTSET;
9563adc21957SMatthew G. Knepley   PetscTryMethod(dm, "DMReorderSectionGetDefault_C", (DM, DMReorderDefaultFlag *), (dm, reorder));
9564adc21957SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
9565adc21957SMatthew G. Knepley }
9566adc21957SMatthew G. Knepley 
9567cc4c1da9SBarry Smith /*@
9568adc21957SMatthew G. Knepley   DMReorderSectionSetType - Set the type of local section reordering
9569adc21957SMatthew G. Knepley 
9570adc21957SMatthew G. Knepley   Logically collective
9571adc21957SMatthew G. Knepley 
9572adc21957SMatthew G. Knepley   Input Parameters:
9573adc21957SMatthew G. Knepley + dm      - The DM
9574adc21957SMatthew G. Knepley - reorder - The reordering method
9575adc21957SMatthew G. Knepley 
9576adc21957SMatthew G. Knepley   Level: intermediate
9577adc21957SMatthew G. Knepley 
9578adc21957SMatthew G. Knepley .seealso: `DMReorderSectionGetType()`, `DMReorderSectionSetDefault()`
9579adc21957SMatthew G. Knepley @*/
9580adc21957SMatthew G. Knepley PetscErrorCode DMReorderSectionSetType(DM dm, MatOrderingType reorder)
9581adc21957SMatthew G. Knepley {
9582adc21957SMatthew G. Knepley   PetscFunctionBegin;
9583adc21957SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9584adc21957SMatthew G. Knepley   PetscTryMethod(dm, "DMReorderSectionSetType_C", (DM, MatOrderingType), (dm, reorder));
9585adc21957SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
9586adc21957SMatthew G. Knepley }
9587adc21957SMatthew G. Knepley 
9588cc4c1da9SBarry Smith /*@
9589adc21957SMatthew G. Knepley   DMReorderSectionGetType - Get the reordering type for the local section
9590adc21957SMatthew G. Knepley 
9591adc21957SMatthew G. Knepley   Not collective
9592adc21957SMatthew G. Knepley 
9593adc21957SMatthew G. Knepley   Input Parameter:
9594adc21957SMatthew G. Knepley . dm - The DM
9595adc21957SMatthew G. Knepley 
9596adc21957SMatthew G. Knepley   Output Parameter:
9597adc21957SMatthew G. Knepley . reorder - The reordering method
9598adc21957SMatthew G. Knepley 
9599adc21957SMatthew G. Knepley   Level: intermediate
9600adc21957SMatthew G. Knepley 
9601adc21957SMatthew G. Knepley .seealso: `DMReorderSetDefault()`, `DMReorderSectionGetDefault()`
9602adc21957SMatthew G. Knepley @*/
9603adc21957SMatthew G. Knepley PetscErrorCode DMReorderSectionGetType(DM dm, MatOrderingType *reorder)
9604adc21957SMatthew G. Knepley {
9605adc21957SMatthew G. Knepley   PetscFunctionBegin;
9606adc21957SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9607adc21957SMatthew G. Knepley   PetscAssertPointer(reorder, 2);
9608adc21957SMatthew G. Knepley   *reorder = NULL;
9609adc21957SMatthew G. Knepley   PetscTryMethod(dm, "DMReorderSectionGetType_C", (DM, MatOrderingType *), (dm, reorder));
9610adc21957SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
9611adc21957SMatthew G. Knepley }
9612