xref: /petsc/src/dm/interface/dm.c (revision 90df33566319c93f10359b4e87408aff0f85ca0c)
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;
17708be2fdSJed Brown PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_Refine, DM_CreateInterpolation, DM_CreateRestriction, DM_CreateInjection, DM_CreateMatrix, DM_CreateMassMatrix, DM_Load, DM_AdaptInterpolator, 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
29bb7acecfSBarry Smith   algebraic solvers, time integrators, and optimization algorithms.
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
45bb7acecfSBarry Smith   error when you try to use the dm.
46bb7acecfSBarry Smith 
471cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetType()`, `DMType`, `DMDACreate()`, `DMDA`, `DMSLICED`, `DMCOMPOSITE`, `DMPLEX`, `DMMOAB`, `DMNETWORK`
48a4121054SBarry Smith @*/
49d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreate(MPI_Comm comm, DM *dm)
50d71ae5a4SJacob Faibussowitsch {
51a4121054SBarry Smith   DM      v;
52e5e52638SMatthew G. Knepley   PetscDS ds;
53a4121054SBarry Smith 
54a4121054SBarry Smith   PetscFunctionBegin;
554f572ea9SToby Isaac   PetscAssertPointer(dm, 2);
56377f809aSBarry Smith 
579566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
589566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView));
5962e5d2d2SJDBetteridge   ((PetscObject)v)->non_cyclic_references = &DMCountNonCyclicReferences;
6049be4549SMatthew G. Knepley   v->setupcalled                          = PETSC_FALSE;
6149be4549SMatthew G. Knepley   v->setfromoptionscalled                 = PETSC_FALSE;
620298fd71SBarry Smith   v->ltogmap                              = NULL;
63a4ea9b21SRichard Tran Mills   v->bind_below                           = 0;
641411c6eeSJed Brown   v->bs                                   = 1;
65171400e9SBarry Smith   v->coloringtype                         = IS_COLORING_GLOBAL;
669566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &v->sf));
679566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &v->sectionSF));
68c58f1c22SToby Isaac   v->labels                    = NULL;
6934aa8a36SMatthew G. Knepley   v->adjacency[0]              = PETSC_FALSE;
7034aa8a36SMatthew G. Knepley   v->adjacency[1]              = PETSC_TRUE;
71c58f1c22SToby Isaac   v->depthLabel                = NULL;
72ba2698f1SMatthew G. Knepley   v->celltypeLabel             = NULL;
731bb6d2a8SBarry Smith   v->localSection              = NULL;
741bb6d2a8SBarry Smith   v->globalSection             = NULL;
753b8ba7d1SJed Brown   v->defaultConstraint.section = NULL;
763b8ba7d1SJed Brown   v->defaultConstraint.mat     = NULL;
7779769bd5SJed Brown   v->defaultConstraint.bias    = NULL;
786858538eSMatthew G. Knepley   v->coordinates[0].dim        = PETSC_DEFAULT;
796858538eSMatthew G. Knepley   v->coordinates[1].dim        = PETSC_DEFAULT;
806858538eSMatthew G. Knepley   v->sparseLocalize            = PETSC_TRUE;
8196173672SStefano Zampini   v->dim                       = PETSC_DETERMINE;
82435a35e8SMatthew G Knepley   {
83435a35e8SMatthew G Knepley     PetscInt i;
84435a35e8SMatthew G Knepley     for (i = 0; i < 10; ++i) {
850298fd71SBarry Smith       v->nullspaceConstructors[i]     = NULL;
86f9d4088aSMatthew G. Knepley       v->nearnullspaceConstructors[i] = NULL;
87435a35e8SMatthew G Knepley     }
88435a35e8SMatthew G Knepley   }
899566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
9007218a29SMatthew G. Knepley   PetscCall(DMSetRegionDS(v, NULL, NULL, ds, NULL));
919566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&ds));
929566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxCreate(&v->auxData));
9314f150ffSMatthew G. Knepley   v->dmBC              = NULL;
94a8fb8f29SToby Isaac   v->coarseMesh        = NULL;
95f4d763aaSMatthew G. Knepley   v->outputSequenceNum = -1;
96cdb7a50dSMatthew G. Knepley   v->outputSequenceVal = 0.0;
979566063dSJacob Faibussowitsch   PetscCall(DMSetVecType(v, VECSTANDARD));
989566063dSJacob Faibussowitsch   PetscCall(DMSetMatType(v, MATAIJ));
994a7a4c06SLawrence Mitchell 
1001411c6eeSJed Brown   *dm = v;
1013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
102a4121054SBarry Smith }
103a4121054SBarry Smith 
10438221697SMatthew G. Knepley /*@
105bb7acecfSBarry Smith   DMClone - Creates a `DM` object with the same topology as the original.
10638221697SMatthew G. Knepley 
107d083f849SBarry Smith   Collective
10838221697SMatthew G. Knepley 
10938221697SMatthew G. Knepley   Input Parameter:
110bb7acecfSBarry Smith . dm - The original `DM` object
11138221697SMatthew G. Knepley 
11238221697SMatthew G. Knepley   Output Parameter:
113bb7acecfSBarry Smith . newdm - The new `DM` object
11438221697SMatthew G. Knepley 
11538221697SMatthew G. Knepley   Level: beginner
11638221697SMatthew G. Knepley 
1171cb8cacdSPatrick Sanan   Notes:
118bb7acecfSBarry Smith   For some `DM` implementations this is a shallow clone, the result of which may share (reference counted) information with its parent. For example,
119bb7acecfSBarry Smith   `DMClone()` applied to a `DMPLEX` object will result in a new `DMPLEX` that shares the topology with the original `DMPLEX`. It does not
120bb7acecfSBarry Smith   share the `PetscSection` of the original `DM`.
1211bb6d2a8SBarry Smith 
122bb7acecfSBarry Smith   The clone is considered set up if the original has been set up.
12389706ed2SPatrick Sanan 
124bb7acecfSBarry Smith   Use `DMConvert()` for a general way to create new `DM` from a given `DM`
125bb7acecfSBarry Smith 
12660225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMSetType()`, `DMSetLocalSection()`, `DMSetGlobalSection()`, `DMPLEX`, `DMConvert()`
12738221697SMatthew G. Knepley @*/
128d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClone(DM dm, DM *newdm)
129d71ae5a4SJacob Faibussowitsch {
13038221697SMatthew G. Knepley   PetscSF              sf;
13138221697SMatthew G. Knepley   Vec                  coords;
13238221697SMatthew G. Knepley   void                *ctx;
133ec196627SMatthew G. Knepley   MatOrderingType      otype;
134ec196627SMatthew G. Knepley   DMReorderDefaultFlag flg;
1356858538eSMatthew G. Knepley   PetscInt             dim, cdim, i;
13638221697SMatthew G. Knepley 
13738221697SMatthew G. Knepley   PetscFunctionBegin;
13838221697SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1394f572ea9SToby Isaac   PetscAssertPointer(newdm, 2);
1409566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), newdm));
1419566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dm, *newdm, PETSC_COPY_VALUES, PETSC_TRUE, DM_COPY_LABELS_FAIL));
142ddf8437dSMatthew G. Knepley   (*newdm)->leveldown     = dm->leveldown;
143ddf8437dSMatthew G. Knepley   (*newdm)->levelup       = dm->levelup;
144c8a6034eSMark   (*newdm)->prealloc_only = dm->prealloc_only;
145fc214432SJed Brown   (*newdm)->prealloc_skip = dm->prealloc_skip;
1469566063dSJacob Faibussowitsch   PetscCall(PetscFree((*newdm)->vectype));
1479566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*newdm)->vectype));
1489566063dSJacob Faibussowitsch   PetscCall(PetscFree((*newdm)->mattype));
1499566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*newdm)->mattype));
1509566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1519566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*newdm, dim));
152dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, clone, newdm);
1533f22bcbcSToby Isaac   (*newdm)->setupcalled = dm->setupcalled;
1549566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
1559566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(*newdm, sf));
1569566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dm, &ctx));
1579566063dSJacob Faibussowitsch   PetscCall(DMSetApplicationContext(*newdm, ctx));
158ec196627SMatthew G. Knepley   PetscCall(DMReorderSectionGetDefault(dm, &flg));
159ec196627SMatthew G. Knepley   PetscCall(DMReorderSectionSetDefault(*newdm, flg));
160ec196627SMatthew G. Knepley   PetscCall(DMReorderSectionGetType(dm, &otype));
161ec196627SMatthew G. Knepley   PetscCall(DMReorderSectionSetType(*newdm, otype));
1626858538eSMatthew G. Knepley   for (i = 0; i < 2; ++i) {
1636858538eSMatthew G. Knepley     if (dm->coordinates[i].dm) {
164be4c1c3eSMatthew G. Knepley       DM           ncdm;
165be4c1c3eSMatthew G. Knepley       PetscSection cs;
1665a0206caSToby Isaac       PetscInt     pEnd = -1, pEndMax = -1;
167be4c1c3eSMatthew G. Knepley 
1686858538eSMatthew G. Knepley       PetscCall(DMGetLocalSection(dm->coordinates[i].dm, &cs));
1699566063dSJacob Faibussowitsch       if (cs) PetscCall(PetscSectionGetChart(cs, NULL, &pEnd));
170462c564dSBarry Smith       PetscCallMPI(MPIU_Allreduce(&pEnd, &pEndMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1715a0206caSToby Isaac       if (pEndMax >= 0) {
1726858538eSMatthew G. Knepley         PetscCall(DMClone(dm->coordinates[i].dm, &ncdm));
1736858538eSMatthew G. Knepley         PetscCall(DMCopyDisc(dm->coordinates[i].dm, ncdm));
1749566063dSJacob Faibussowitsch         PetscCall(DMSetLocalSection(ncdm, cs));
1755e50ca95SJames Wright         if (dm->coordinates[i].dm->periodic.setup) {
1765e50ca95SJames Wright           ncdm->periodic.setup = dm->coordinates[i].dm->periodic.setup;
1775e50ca95SJames Wright           PetscCall(ncdm->periodic.setup(ncdm));
1785e50ca95SJames Wright         }
1796858538eSMatthew G. Knepley         if (i) PetscCall(DMSetCellCoordinateDM(*newdm, ncdm));
1806858538eSMatthew G. Knepley         else PetscCall(DMSetCoordinateDM(*newdm, ncdm));
1819566063dSJacob Faibussowitsch         PetscCall(DMDestroy(&ncdm));
182be4c1c3eSMatthew G. Knepley       }
183be4c1c3eSMatthew G. Knepley     }
1846858538eSMatthew G. Knepley   }
1859566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1869566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*newdm, cdim));
1879566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coords));
18838221697SMatthew G. Knepley   if (coords) {
1899566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(*newdm, coords));
19038221697SMatthew G. Knepley   } else {
1919566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinates(dm, &coords));
1929566063dSJacob Faibussowitsch     if (coords) PetscCall(DMSetCoordinates(*newdm, coords));
19338221697SMatthew G. Knepley   }
1946858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &coords));
1956858538eSMatthew G. Knepley   if (coords) {
1966858538eSMatthew G. Knepley     PetscCall(DMSetCellCoordinatesLocal(*newdm, coords));
1976858538eSMatthew G. Knepley   } else {
1986858538eSMatthew G. Knepley     PetscCall(DMGetCellCoordinates(dm, &coords));
1996858538eSMatthew G. Knepley     if (coords) PetscCall(DMSetCellCoordinates(*newdm, coords));
2006858538eSMatthew G. Knepley   }
20190b157c4SStefano Zampini   {
2024fb89dddSMatthew G. Knepley     const PetscReal *maxCell, *Lstart, *L;
2036858538eSMatthew G. Knepley 
2044fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
2054fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(*newdm, maxCell, Lstart, L));
206c6b900c6SMatthew G. Knepley   }
20734aa8a36SMatthew G. Knepley   {
20834aa8a36SMatthew G. Knepley     PetscBool useCone, useClosure;
20934aa8a36SMatthew G. Knepley 
2109566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, PETSC_DEFAULT, &useCone, &useClosure));
2119566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(*newdm, PETSC_DEFAULT, useCone, useClosure));
21234aa8a36SMatthew G. Knepley   }
2133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21438221697SMatthew G. Knepley }
21538221697SMatthew G. Knepley 
2165d83a8b1SBarry Smith /*@
2175d83a8b1SBarry Smith   DMSetVecType - Sets the type of vector to be created with `DMCreateLocalVector()` and `DMCreateGlobalVector()`
2189a42bb27SBarry Smith 
21920f4b53cSBarry Smith   Logically Collective
2209a42bb27SBarry Smith 
221147403d9SBarry Smith   Input Parameters:
22232546409SMatthew G. Knepley + dm    - initial distributed array
223bb7acecfSBarry Smith - ctype - the vector type, for example `VECSTANDARD`, `VECCUDA`, or `VECVIENNACL`
2249a42bb27SBarry Smith 
22520f4b53cSBarry Smith   Options Database Key:
226147403d9SBarry Smith . -dm_vec_type ctype - the type of vector to create
2279a42bb27SBarry Smith 
2289a42bb27SBarry Smith   Level: intermediate
2299a42bb27SBarry Smith 
23060225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMDestroy()`, `DMDAInterpolationType`, `VecType`, `DMGetVecType()`, `DMSetMatType()`, `DMGetMatType()`,
231bb7acecfSBarry Smith           `VECSTANDARD`, `VECCUDA`, `VECVIENNACL`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`
2329a42bb27SBarry Smith @*/
23332546409SMatthew G. Knepley PetscErrorCode DMSetVecType(DM dm, VecType ctype)
234d71ae5a4SJacob Faibussowitsch {
23532546409SMatthew G. Knepley   char *tmp;
23632546409SMatthew G. Knepley 
2379a42bb27SBarry Smith   PetscFunctionBegin;
23832546409SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23932546409SMatthew G. Knepley   PetscAssertPointer(ctype, 2);
24032546409SMatthew G. Knepley   tmp = (char *)dm->vectype;
24132546409SMatthew G. Knepley   PetscCall(PetscStrallocpy(ctype, (char **)&dm->vectype));
24232546409SMatthew G. Knepley   PetscCall(PetscFree(tmp));
2433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2449a42bb27SBarry Smith }
2459a42bb27SBarry Smith 
2465d83a8b1SBarry Smith /*@
247bb7acecfSBarry Smith   DMGetVecType - Gets the type of vector created with `DMCreateLocalVector()` and `DMCreateGlobalVector()`
248c0dedaeaSBarry Smith 
24920f4b53cSBarry Smith   Logically Collective
250c0dedaeaSBarry Smith 
251c0dedaeaSBarry Smith   Input Parameter:
252c0dedaeaSBarry Smith . da - initial distributed array
253c0dedaeaSBarry Smith 
254c0dedaeaSBarry Smith   Output Parameter:
255c0dedaeaSBarry Smith . ctype - the vector type
256c0dedaeaSBarry Smith 
257c0dedaeaSBarry Smith   Level: intermediate
258c0dedaeaSBarry Smith 
25960225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMDestroy()`, `DMDAInterpolationType`, `VecType`, `DMSetMatType()`, `DMGetMatType()`, `DMSetVecType()`
260c0dedaeaSBarry Smith @*/
261d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetVecType(DM da, VecType *ctype)
262d71ae5a4SJacob Faibussowitsch {
263c0dedaeaSBarry Smith   PetscFunctionBegin;
264c0dedaeaSBarry Smith   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
265c0dedaeaSBarry Smith   *ctype = da->vectype;
2663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
267c0dedaeaSBarry Smith }
268c0dedaeaSBarry Smith 
2695f1ad066SMatthew G Knepley /*@
270bb7acecfSBarry Smith   VecGetDM - Gets the `DM` defining the data layout of the vector
2715f1ad066SMatthew G Knepley 
27220f4b53cSBarry Smith   Not Collective
2735f1ad066SMatthew G Knepley 
2745f1ad066SMatthew G Knepley   Input Parameter:
275bb7acecfSBarry Smith . v - The `Vec`
2765f1ad066SMatthew G Knepley 
2775f1ad066SMatthew G Knepley   Output Parameter:
278bb7acecfSBarry Smith . dm - The `DM`
2795f1ad066SMatthew G Knepley 
2805f1ad066SMatthew G Knepley   Level: intermediate
2815f1ad066SMatthew G Knepley 
282bb7acecfSBarry Smith   Note:
283bb7acecfSBarry Smith   A `Vec` may not have a `DM` associated with it.
284bb7acecfSBarry Smith 
2851cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecSetDM()`, `DMGetLocalVector()`, `DMGetGlobalVector()`, `DMSetVecType()`
2865f1ad066SMatthew G Knepley @*/
287d71ae5a4SJacob Faibussowitsch PetscErrorCode VecGetDM(Vec v, DM *dm)
288d71ae5a4SJacob Faibussowitsch {
2895f1ad066SMatthew G Knepley   PetscFunctionBegin;
2905f1ad066SMatthew G Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
2914f572ea9SToby Isaac   PetscAssertPointer(dm, 2);
2929566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)v, "__PETSc_dm", (PetscObject *)dm));
2933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2945f1ad066SMatthew G Knepley }
2955f1ad066SMatthew G Knepley 
2965f1ad066SMatthew G Knepley /*@
297bb7acecfSBarry Smith   VecSetDM - Sets the `DM` defining the data layout of the vector.
2985f1ad066SMatthew G Knepley 
29920f4b53cSBarry Smith   Not Collective
3005f1ad066SMatthew G Knepley 
3015f1ad066SMatthew G Knepley   Input Parameters:
302bb7acecfSBarry Smith + v  - The `Vec`
303bb7acecfSBarry Smith - dm - The `DM`
3045f1ad066SMatthew G Knepley 
30520f4b53cSBarry Smith   Level: developer
30620f4b53cSBarry Smith 
30773ff1848SBarry Smith   Notes:
308bb7acecfSBarry Smith   This is rarely used, generally one uses `DMGetLocalVector()` or  `DMGetGlobalVector()` to create a vector associated with a given `DM`
309d9805387SMatthew G. Knepley 
310bb7acecfSBarry 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.
311bb7acecfSBarry Smith 
3121cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecGetDM()`, `DMGetLocalVector()`, `DMGetGlobalVector()`, `DMSetVecType()`
3135f1ad066SMatthew G Knepley @*/
314d71ae5a4SJacob Faibussowitsch PetscErrorCode VecSetDM(Vec v, DM dm)
315d71ae5a4SJacob Faibussowitsch {
3165f1ad066SMatthew G Knepley   PetscFunctionBegin;
3175f1ad066SMatthew G Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
318d7f50e27SLisandro Dalcin   if (dm) PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
3199566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)v, "__PETSc_dm", (PetscObject)dm));
3203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3215f1ad066SMatthew G Knepley }
3225f1ad066SMatthew G Knepley 
323cc4c1da9SBarry Smith /*@
324bb7acecfSBarry Smith   DMSetISColoringType - Sets the type of coloring, `IS_COLORING_GLOBAL` or `IS_COLORING_LOCAL` that is created by the `DM`
3258f1509bcSBarry Smith 
32620f4b53cSBarry Smith   Logically Collective
3278f1509bcSBarry Smith 
3288f1509bcSBarry Smith   Input Parameters:
329bb7acecfSBarry Smith + dm    - the `DM` context
3308f1509bcSBarry Smith - ctype - the matrix type
3318f1509bcSBarry Smith 
33220f4b53cSBarry Smith   Options Database Key:
3338f1509bcSBarry Smith . -dm_is_coloring_type - global or local
3348f1509bcSBarry Smith 
3358f1509bcSBarry Smith   Level: intermediate
3368f1509bcSBarry Smith 
3371cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMGetMatType()`,
338bb7acecfSBarry Smith           `DMGetISColoringType()`, `ISColoringType`, `IS_COLORING_GLOBAL`, `IS_COLORING_LOCAL`
3398f1509bcSBarry Smith @*/
340d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetISColoringType(DM dm, ISColoringType ctype)
341d71ae5a4SJacob Faibussowitsch {
3428f1509bcSBarry Smith   PetscFunctionBegin;
3438f1509bcSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3448f1509bcSBarry Smith   dm->coloringtype = ctype;
3453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3468f1509bcSBarry Smith }
3478f1509bcSBarry Smith 
348cc4c1da9SBarry Smith /*@
349bb7acecfSBarry Smith   DMGetISColoringType - Gets the type of coloring, `IS_COLORING_GLOBAL` or `IS_COLORING_LOCAL` that is created by the `DM`
350521d9a4cSLisandro Dalcin 
35120f4b53cSBarry Smith   Logically Collective
352521d9a4cSLisandro Dalcin 
353521d9a4cSLisandro Dalcin   Input Parameter:
354bb7acecfSBarry Smith . dm - the `DM` context
3558f1509bcSBarry Smith 
3568f1509bcSBarry Smith   Output Parameter:
3578f1509bcSBarry Smith . ctype - the matrix type
3588f1509bcSBarry Smith 
35920f4b53cSBarry Smith   Options Database Key:
3608f1509bcSBarry Smith . -dm_is_coloring_type - global or local
3618f1509bcSBarry Smith 
3628f1509bcSBarry Smith   Level: intermediate
3638f1509bcSBarry Smith 
3641cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMGetMatType()`,
36542747ad1SJacob Faibussowitsch           `ISColoringType`, `IS_COLORING_GLOBAL`, `IS_COLORING_LOCAL`
3668f1509bcSBarry Smith @*/
367d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetISColoringType(DM dm, ISColoringType *ctype)
368d71ae5a4SJacob Faibussowitsch {
3698f1509bcSBarry Smith   PetscFunctionBegin;
3708f1509bcSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3718f1509bcSBarry Smith   *ctype = dm->coloringtype;
3723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3738f1509bcSBarry Smith }
3748f1509bcSBarry Smith 
375cc4c1da9SBarry Smith /*@
376bb7acecfSBarry Smith   DMSetMatType - Sets the type of matrix created with `DMCreateMatrix()`
3778f1509bcSBarry Smith 
37820f4b53cSBarry Smith   Logically Collective
3798f1509bcSBarry Smith 
3808f1509bcSBarry Smith   Input Parameters:
381bb7acecfSBarry Smith + dm    - the `DM` context
382bb7acecfSBarry Smith - ctype - the matrix type, for example `MATMPIAIJ`
383521d9a4cSLisandro Dalcin 
38420f4b53cSBarry Smith   Options Database Key:
385bb7acecfSBarry Smith . -dm_mat_type ctype - the type of the matrix to create, for example mpiaij
386521d9a4cSLisandro Dalcin 
387521d9a4cSLisandro Dalcin   Level: intermediate
388521d9a4cSLisandro Dalcin 
38942747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `MatType`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `DMGetMatType()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
390521d9a4cSLisandro Dalcin @*/
391d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatType(DM dm, MatType ctype)
392d71ae5a4SJacob Faibussowitsch {
39332546409SMatthew G. Knepley   char *tmp;
39432546409SMatthew G. Knepley 
395521d9a4cSLisandro Dalcin   PetscFunctionBegin;
396521d9a4cSLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39732546409SMatthew G. Knepley   PetscAssertPointer(ctype, 2);
39832546409SMatthew G. Knepley   tmp = (char *)dm->mattype;
3999566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ctype, (char **)&dm->mattype));
40032546409SMatthew G. Knepley   PetscCall(PetscFree(tmp));
4013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
402521d9a4cSLisandro Dalcin }
403521d9a4cSLisandro Dalcin 
404cc4c1da9SBarry Smith /*@
40520f4b53cSBarry Smith   DMGetMatType - Gets the type of matrix that would be created with `DMCreateMatrix()`
406c0dedaeaSBarry Smith 
40720f4b53cSBarry Smith   Logically Collective
408c0dedaeaSBarry Smith 
409c0dedaeaSBarry Smith   Input Parameter:
410bb7acecfSBarry Smith . dm - the `DM` context
411c0dedaeaSBarry Smith 
412c0dedaeaSBarry Smith   Output Parameter:
413c0dedaeaSBarry Smith . ctype - the matrix type
414c0dedaeaSBarry Smith 
415c0dedaeaSBarry Smith   Level: intermediate
416c0dedaeaSBarry Smith 
41742747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMSetMatType()`
418c0dedaeaSBarry Smith @*/
419d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetMatType(DM dm, MatType *ctype)
420d71ae5a4SJacob Faibussowitsch {
421c0dedaeaSBarry Smith   PetscFunctionBegin;
422c0dedaeaSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
423c0dedaeaSBarry Smith   *ctype = dm->mattype;
4243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
425c0dedaeaSBarry Smith }
426c0dedaeaSBarry Smith 
427c688c046SMatthew G Knepley /*@
428bb7acecfSBarry Smith   MatGetDM - Gets the `DM` defining the data layout of the matrix
429c688c046SMatthew G Knepley 
43020f4b53cSBarry Smith   Not Collective
431c688c046SMatthew G Knepley 
432c688c046SMatthew G Knepley   Input Parameter:
433bb7acecfSBarry Smith . A - The `Mat`
434c688c046SMatthew G Knepley 
435c688c046SMatthew G Knepley   Output Parameter:
436bb7acecfSBarry Smith . dm - The `DM`
437c688c046SMatthew G Knepley 
438c688c046SMatthew G Knepley   Level: intermediate
439c688c046SMatthew G Knepley 
440bb7acecfSBarry Smith   Note:
441bb7acecfSBarry Smith   A matrix may not have a `DM` associated with it
442bb7acecfSBarry Smith 
44373ff1848SBarry Smith   Developer Note:
444bb7acecfSBarry Smith   Since the `Mat` class doesn't know about the `DM` class the `DM` object is associated with the `Mat` through a `PetscObjectCompose()` operation
4458f1509bcSBarry Smith 
4461cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatSetDM()`, `DMCreateMatrix()`, `DMSetMatType()`
447c688c046SMatthew G Knepley @*/
448d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDM(Mat A, DM *dm)
449d71ae5a4SJacob Faibussowitsch {
450c688c046SMatthew G Knepley   PetscFunctionBegin;
451c688c046SMatthew G Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4524f572ea9SToby Isaac   PetscAssertPointer(dm, 2);
4539566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_dm", (PetscObject *)dm));
4543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
455c688c046SMatthew G Knepley }
456c688c046SMatthew G Knepley 
457c688c046SMatthew G Knepley /*@
458bb7acecfSBarry Smith   MatSetDM - Sets the `DM` defining the data layout of the matrix
459c688c046SMatthew G Knepley 
46020f4b53cSBarry Smith   Not Collective
461c688c046SMatthew G Knepley 
462c688c046SMatthew G Knepley   Input Parameters:
46320f4b53cSBarry Smith + A  - The `Mat`
46420f4b53cSBarry Smith - dm - The `DM`
465c688c046SMatthew G Knepley 
466bb7acecfSBarry Smith   Level: developer
467c688c046SMatthew G Knepley 
468bb7acecfSBarry Smith   Note:
469bb7acecfSBarry Smith   This is rarely used in practice, rather `DMCreateMatrix()` is used to create a matrix associated with a particular `DM`
470bb7acecfSBarry Smith 
47173ff1848SBarry Smith   Developer Note:
472bb7acecfSBarry Smith   Since the `Mat` class doesn't know about the `DM` class the `DM` object is associated with
473bb7acecfSBarry Smith   the `Mat` through a `PetscObjectCompose()` operation
4748f1509bcSBarry Smith 
4751cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatGetDM()`, `DMCreateMatrix()`, `DMSetMatType()`
476c688c046SMatthew G Knepley @*/
477d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetDM(Mat A, DM dm)
478d71ae5a4SJacob Faibussowitsch {
479c688c046SMatthew G Knepley   PetscFunctionBegin;
480c688c046SMatthew G Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4818865f1eaSKarl Rupp   if (dm) PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
4829566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_dm", (PetscObject)dm));
4833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
484c688c046SMatthew G Knepley }
485c688c046SMatthew G Knepley 
486cc4c1da9SBarry Smith /*@
487bb7acecfSBarry Smith   DMSetOptionsPrefix - Sets the prefix prepended to all option names when searching through the options database
4889a42bb27SBarry Smith 
48920f4b53cSBarry Smith   Logically Collective
4909a42bb27SBarry Smith 
491d8d19677SJose E. Roman   Input Parameters:
49260225df5SJacob Faibussowitsch + dm     - the `DM` context
493bb7acecfSBarry Smith - prefix - the prefix to prepend
4949a42bb27SBarry Smith 
49520f4b53cSBarry Smith   Level: advanced
49620f4b53cSBarry Smith 
49720f4b53cSBarry Smith   Note:
4989a42bb27SBarry Smith   A hyphen (-) must NOT be given at the beginning of the prefix name.
4999a42bb27SBarry Smith   The first character of all runtime options is AUTOMATICALLY the hyphen.
5009a42bb27SBarry Smith 
5011cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscObjectSetOptionsPrefix()`, `DMSetFromOptions()`
5029a42bb27SBarry Smith @*/
503d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOptionsPrefix(DM dm, const char prefix[])
504d71ae5a4SJacob Faibussowitsch {
5059a42bb27SBarry Smith   PetscFunctionBegin;
5069a42bb27SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5079566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
5081baa6e33SBarry Smith   if (dm->sf) PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm->sf, prefix));
5091baa6e33SBarry Smith   if (dm->sectionSF) PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm->sectionSF, prefix));
5103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5119a42bb27SBarry Smith }
5129a42bb27SBarry Smith 
513cc4c1da9SBarry Smith /*@
514da81f932SPierre Jolivet   DMAppendOptionsPrefix - Appends an additional string to an already existing prefix used for searching for
515bb7acecfSBarry Smith   `DM` options in the options database.
51631697293SDave May 
51720f4b53cSBarry Smith   Logically Collective
51831697293SDave May 
51931697293SDave May   Input Parameters:
520bb7acecfSBarry Smith + dm     - the `DM` context
521bb7acecfSBarry Smith - prefix - the string to append to the current prefix
52231697293SDave May 
52320f4b53cSBarry Smith   Level: advanced
52420f4b53cSBarry Smith 
52520f4b53cSBarry Smith   Note:
526bb7acecfSBarry 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.
52731697293SDave May   A hyphen (-) must NOT be given at the beginning of the prefix name.
52831697293SDave May   The first character of all runtime options is AUTOMATICALLY the hyphen.
52931697293SDave May 
5301cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetOptionsPrefix()`, `DMGetOptionsPrefix()`, `PetscObjectAppendOptionsPrefix()`, `DMSetFromOptions()`
53131697293SDave May @*/
532d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAppendOptionsPrefix(DM dm, const char prefix[])
533d71ae5a4SJacob Faibussowitsch {
53431697293SDave May   PetscFunctionBegin;
53531697293SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5369566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, prefix));
5373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53831697293SDave May }
53931697293SDave May 
540cc4c1da9SBarry Smith /*@
54131697293SDave May   DMGetOptionsPrefix - Gets the prefix used for searching for all
542bb7acecfSBarry Smith   DM options in the options database.
54331697293SDave May 
54431697293SDave May   Not Collective
54531697293SDave May 
5462fe279fdSBarry Smith   Input Parameter:
547bb7acecfSBarry Smith . dm - the `DM` context
54831697293SDave May 
5492fe279fdSBarry Smith   Output Parameter:
55031697293SDave May . prefix - pointer to the prefix string used is returned
55131697293SDave May 
55231697293SDave May   Level: advanced
55331697293SDave May 
55473ff1848SBarry Smith   Fortran Note:
55520f4b53cSBarry Smith   Pass in a string 'prefix' of
55620f4b53cSBarry Smith   sufficient length to hold the prefix.
55720f4b53cSBarry Smith 
5581cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetOptionsPrefix()`, `DMAppendOptionsPrefix()`, `DMSetFromOptions()`
55931697293SDave May @*/
560d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOptionsPrefix(DM dm, const char *prefix[])
561d71ae5a4SJacob Faibussowitsch {
56231697293SDave May   PetscFunctionBegin;
56331697293SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5649566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, prefix));
5653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56631697293SDave May }
56731697293SDave May 
56862e5d2d2SJDBetteridge static PetscErrorCode DMCountNonCyclicReferences_Internal(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
569d71ae5a4SJacob Faibussowitsch {
5706eb26441SStefano Zampini   PetscInt refct = ((PetscObject)dm)->refct;
57188bdff64SToby Isaac 
57288bdff64SToby Isaac   PetscFunctionBegin;
573aab5bcd8SJed Brown   *ncrefct = 0;
57488bdff64SToby Isaac   if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
57588bdff64SToby Isaac     refct--;
57688bdff64SToby Isaac     if (recurseCoarse) {
57788bdff64SToby Isaac       PetscInt coarseCount;
57888bdff64SToby Isaac 
57962e5d2d2SJDBetteridge       PetscCall(DMCountNonCyclicReferences_Internal(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE, &coarseCount));
58088bdff64SToby Isaac       refct += coarseCount;
58188bdff64SToby Isaac     }
58288bdff64SToby Isaac   }
58388bdff64SToby Isaac   if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
58488bdff64SToby Isaac     refct--;
58588bdff64SToby Isaac     if (recurseFine) {
58688bdff64SToby Isaac       PetscInt fineCount;
58788bdff64SToby Isaac 
58862e5d2d2SJDBetteridge       PetscCall(DMCountNonCyclicReferences_Internal(dm->fineMesh, PETSC_FALSE, PETSC_TRUE, &fineCount));
58988bdff64SToby Isaac       refct += fineCount;
59088bdff64SToby Isaac     }
59188bdff64SToby Isaac   }
59288bdff64SToby Isaac   *ncrefct = refct;
5933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59488bdff64SToby Isaac }
59588bdff64SToby Isaac 
59662e5d2d2SJDBetteridge /* Generic wrapper for DMCountNonCyclicReferences_Internal() */
59762e5d2d2SJDBetteridge PetscErrorCode DMCountNonCyclicReferences(PetscObject dm, PetscInt *ncrefct)
59862e5d2d2SJDBetteridge {
59962e5d2d2SJDBetteridge   PetscFunctionBegin;
60062e5d2d2SJDBetteridge   PetscCall(DMCountNonCyclicReferences_Internal((DM)dm, PETSC_TRUE, PETSC_TRUE, ncrefct));
6013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60262e5d2d2SJDBetteridge }
60362e5d2d2SJDBetteridge 
604d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroyLabelLinkList_Internal(DM dm)
605d71ae5a4SJacob Faibussowitsch {
6065d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
607354557abSToby Isaac 
608354557abSToby Isaac   PetscFunctionBegin;
609354557abSToby Isaac   /* destroy the labels */
610354557abSToby Isaac   while (next) {
611354557abSToby Isaac     DMLabelLink tmp = next->next;
612354557abSToby Isaac 
6135d80c0bfSVaclav Hapla     if (next->label == dm->depthLabel) dm->depthLabel = NULL;
614ba2698f1SMatthew G. Knepley     if (next->label == dm->celltypeLabel) dm->celltypeLabel = NULL;
6159566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&next->label));
6169566063dSJacob Faibussowitsch     PetscCall(PetscFree(next));
617354557abSToby Isaac     next = tmp;
618354557abSToby Isaac   }
6195d80c0bfSVaclav Hapla   dm->labels = NULL;
6203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
621354557abSToby Isaac }
622354557abSToby Isaac 
62366976f2fSJacob Faibussowitsch static PetscErrorCode DMDestroyCoordinates_Private(DMCoordinates *c)
624d71ae5a4SJacob Faibussowitsch {
6256858538eSMatthew G. Knepley   PetscFunctionBegin;
6266858538eSMatthew G. Knepley   c->dim = PETSC_DEFAULT;
6276858538eSMatthew G. Knepley   PetscCall(DMDestroy(&c->dm));
6286858538eSMatthew G. Knepley   PetscCall(VecDestroy(&c->x));
6296858538eSMatthew G. Knepley   PetscCall(VecDestroy(&c->xl));
6306858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&c->field));
6313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6326858538eSMatthew G. Knepley }
6336858538eSMatthew G. Knepley 
6340764c050SBarry Smith /*@
635bb7acecfSBarry Smith   DMDestroy - Destroys a `DM`.
63647c6ae99SBarry Smith 
63720f4b53cSBarry Smith   Collective
63847c6ae99SBarry Smith 
63947c6ae99SBarry Smith   Input Parameter:
640bb7acecfSBarry Smith . dm - the `DM` object to destroy
64147c6ae99SBarry Smith 
64247c6ae99SBarry Smith   Level: developer
64347c6ae99SBarry Smith 
6441cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMType`, `DMSetType()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
64547c6ae99SBarry Smith @*/
646d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy(DM *dm)
647d71ae5a4SJacob Faibussowitsch {
6486eb26441SStefano Zampini   PetscInt cnt;
64947c6ae99SBarry Smith 
65047c6ae99SBarry Smith   PetscFunctionBegin;
6513ba16761SJacob Faibussowitsch   if (!*dm) PetscFunctionReturn(PETSC_SUCCESS);
652f4f49eeaSPierre Jolivet   PetscValidHeaderSpecific(*dm, DM_CLASSID, 1);
65387e657c6SBarry Smith 
65488bdff64SToby Isaac   /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
65562e5d2d2SJDBetteridge   PetscCall(DMCountNonCyclicReferences_Internal(*dm, PETSC_TRUE, PETSC_TRUE, &cnt));
656f4f49eeaSPierre Jolivet   --((PetscObject)*dm)->refct;
6579371c9d4SSatish Balay   if (--cnt > 0) {
6589371c9d4SSatish Balay     *dm = NULL;
6593ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6609371c9d4SSatish Balay   }
661f4f49eeaSPierre Jolivet   if (((PetscObject)*dm)->refct < 0) PetscFunctionReturn(PETSC_SUCCESS);
662f4f49eeaSPierre Jolivet   ((PetscObject)*dm)->refct = 0;
6636eb26441SStefano Zampini 
6649566063dSJacob Faibussowitsch   PetscCall(DMClearGlobalVectors(*dm));
6659566063dSJacob Faibussowitsch   PetscCall(DMClearLocalVectors(*dm));
666974ca4ecSStefano Zampini   PetscCall(DMClearNamedGlobalVectors(*dm));
667974ca4ecSStefano Zampini   PetscCall(DMClearNamedLocalVectors(*dm));
6682348bcf4SPeter Brune 
669b17ce1afSJed Brown   /* Destroy the list of hooks */
670c833c3b5SJed Brown   {
671c833c3b5SJed Brown     DMCoarsenHookLink link, next;
672b17ce1afSJed Brown     for (link = (*dm)->coarsenhook; link; link = next) {
673b17ce1afSJed Brown       next = link->next;
6749566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
675b17ce1afSJed Brown     }
6760298fd71SBarry Smith     (*dm)->coarsenhook = NULL;
677c833c3b5SJed Brown   }
678c833c3b5SJed Brown   {
679c833c3b5SJed Brown     DMRefineHookLink link, next;
680c833c3b5SJed Brown     for (link = (*dm)->refinehook; link; link = next) {
681c833c3b5SJed Brown       next = link->next;
6829566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
683c833c3b5SJed Brown     }
6840298fd71SBarry Smith     (*dm)->refinehook = NULL;
685c833c3b5SJed Brown   }
686be081cd6SPeter Brune   {
687be081cd6SPeter Brune     DMSubDomainHookLink link, next;
688be081cd6SPeter Brune     for (link = (*dm)->subdomainhook; link; link = next) {
689be081cd6SPeter Brune       next = link->next;
6909566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
691be081cd6SPeter Brune     }
6920298fd71SBarry Smith     (*dm)->subdomainhook = NULL;
693be081cd6SPeter Brune   }
694baf369e7SPeter Brune   {
695baf369e7SPeter Brune     DMGlobalToLocalHookLink link, next;
696baf369e7SPeter Brune     for (link = (*dm)->gtolhook; link; link = next) {
697baf369e7SPeter Brune       next = link->next;
6989566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
699baf369e7SPeter Brune     }
7000298fd71SBarry Smith     (*dm)->gtolhook = NULL;
701baf369e7SPeter Brune   }
702d4d07f1eSToby Isaac   {
703d4d07f1eSToby Isaac     DMLocalToGlobalHookLink link, next;
704d4d07f1eSToby Isaac     for (link = (*dm)->ltoghook; link; link = next) {
705d4d07f1eSToby Isaac       next = link->next;
7069566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
707d4d07f1eSToby Isaac     }
708d4d07f1eSToby Isaac     (*dm)->ltoghook = NULL;
709d4d07f1eSToby Isaac   }
710aa1993deSMatthew G Knepley   /* Destroy the work arrays */
711aa1993deSMatthew G Knepley   {
712aa1993deSMatthew G Knepley     DMWorkLink link, next;
713835f2295SStefano Zampini     PetscCheck(!(*dm)->workout, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Work array still checked out %p %p", (void *)(*dm)->workout, (*dm)->workout->mem);
714aa1993deSMatthew G Knepley     for (link = (*dm)->workin; link; link = next) {
715aa1993deSMatthew G Knepley       next = link->next;
7169566063dSJacob Faibussowitsch       PetscCall(PetscFree(link->mem));
7179566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
718aa1993deSMatthew G Knepley     }
7190298fd71SBarry Smith     (*dm)->workin = NULL;
720aa1993deSMatthew G Knepley   }
721c58f1c22SToby Isaac   /* destroy the labels */
7229566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(*dm));
723f4cdcedcSVaclav Hapla   /* destroy the fields */
7249566063dSJacob Faibussowitsch   PetscCall(DMClearFields(*dm));
725f4cdcedcSVaclav Hapla   /* destroy the boundaries */
726e6f8dbb6SToby Isaac   {
727e6f8dbb6SToby Isaac     DMBoundary next = (*dm)->boundary;
728e6f8dbb6SToby Isaac     while (next) {
729e6f8dbb6SToby Isaac       DMBoundary b = next;
730e6f8dbb6SToby Isaac 
731e6f8dbb6SToby Isaac       next = b->next;
7329566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
733e6f8dbb6SToby Isaac     }
734e6f8dbb6SToby Isaac   }
735b17ce1afSJed Brown 
7369566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmksp));
7379566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmsnes));
7389566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmts));
73952536dc3SBarry Smith 
74048a46eb9SPierre Jolivet   if ((*dm)->ctx && (*dm)->ctxdestroy) PetscCall((*(*dm)->ctxdestroy)(&(*dm)->ctx));
7419566063dSJacob Faibussowitsch   PetscCall(MatFDColoringDestroy(&(*dm)->fd));
7429566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap));
7439566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->vectype));
7449566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->mattype));
74588ed4aceSMatthew G Knepley 
7469566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->localSection));
7479566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->globalSection));
748adc21957SMatthew G. Knepley   PetscCall(PetscFree((*dm)->reorderSectionType));
7499566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&(*dm)->map));
7509566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->defaultConstraint.section));
7519566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&(*dm)->defaultConstraint.mat));
7529566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&(*dm)->sf));
7539566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&(*dm)->sectionSF));
75448a46eb9SPierre Jolivet   if ((*dm)->sfNatural) PetscCall(PetscSFDestroy(&(*dm)->sfNatural));
7559566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)(*dm)->sfMigration));
756e4d5475eSStefano Zampini   PetscCall(DMClearAuxiliaryVec(*dm));
7579566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDestroy(&(*dm)->auxData));
75848a46eb9SPierre Jolivet   if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) PetscCall(DMSetFineDM((*dm)->coarseMesh, NULL));
7596eb26441SStefano Zampini 
7609566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->coarseMesh));
76148a46eb9SPierre Jolivet   if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) PetscCall(DMSetCoarseDM((*dm)->fineMesh, NULL));
7629566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->fineMesh));
7634fb89dddSMatthew G. Knepley   PetscCall(PetscFree((*dm)->Lstart));
7649566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->L));
7659566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->maxCell));
7666858538eSMatthew G. Knepley   PetscCall(DMDestroyCoordinates_Private(&(*dm)->coordinates[0]));
7676858538eSMatthew G. Knepley   PetscCall(DMDestroyCoordinates_Private(&(*dm)->coordinates[1]));
7689566063dSJacob Faibussowitsch   if ((*dm)->transformDestroy) PetscCall((*(*dm)->transformDestroy)(*dm, (*dm)->transformCtx));
7699566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->transformDM));
7709566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&(*dm)->transform));
771ddedc8f6SJames Wright   for (PetscInt i = 0; i < (*dm)->periodic.num_affines; i++) {
772ddedc8f6SJames Wright     PetscCall(VecScatterDestroy(&(*dm)->periodic.affine_to_local[i]));
773ddedc8f6SJames Wright     PetscCall(VecDestroy(&(*dm)->periodic.affine[i]));
774ddedc8f6SJames Wright   }
775ddedc8f6SJames Wright   if ((*dm)->periodic.num_affines > 0) PetscCall(PetscFree2((*dm)->periodic.affine_to_local, (*dm)->periodic.affine));
7766636e97aSMatthew G Knepley 
7779566063dSJacob Faibussowitsch   PetscCall(DMClearDS(*dm));
7789566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->dmBC));
779e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
7809566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*dm));
781732e2eb9SMatthew G Knepley 
782213acdd3SPierre Jolivet   PetscTryTypeMethod(*dm, destroy);
7839566063dSJacob Faibussowitsch   PetscCall(DMMonitorCancel(*dm));
784d2b2dc1eSMatthew G. Knepley   PetscCall(DMCeedDestroy(&(*dm)->dmceed));
785f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
7869566063dSJacob Faibussowitsch   PetscCallCEED(CeedElemRestrictionDestroy(&(*dm)->ceedERestrict));
7879566063dSJacob Faibussowitsch   PetscCallCEED(CeedDestroy(&(*dm)->ceed));
788f918ec44SMatthew G. Knepley #endif
789435a35e8SMatthew G Knepley   /* We do not destroy (*dm)->data here so that we can reference count backend objects */
7909566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(dm));
7913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79247c6ae99SBarry Smith }
79347c6ae99SBarry Smith 
794d7bf68aeSBarry Smith /*@
795bb7acecfSBarry Smith   DMSetUp - sets up the data structures inside a `DM` object
796d7bf68aeSBarry Smith 
79720f4b53cSBarry Smith   Collective
798d7bf68aeSBarry Smith 
799d7bf68aeSBarry Smith   Input Parameter:
800bb7acecfSBarry Smith . dm - the `DM` object to setup
801d7bf68aeSBarry Smith 
802bb7acecfSBarry Smith   Level: intermediate
803d7bf68aeSBarry Smith 
804bb7acecfSBarry Smith   Note:
805bb7acecfSBarry Smith   This is usually called after various parameter setting operations and `DMSetFromOptions()` are called on the `DM`
806bb7acecfSBarry Smith 
8071cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMSetType()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
808d7bf68aeSBarry Smith @*/
809d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp(DM dm)
810d71ae5a4SJacob Faibussowitsch {
811d7bf68aeSBarry Smith   PetscFunctionBegin;
812171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8133ba16761SJacob Faibussowitsch   if (dm->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
814dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, setup);
8158387afaaSJed Brown   dm->setupcalled = PETSC_TRUE;
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
817d7bf68aeSBarry Smith }
818d7bf68aeSBarry Smith 
819d7bf68aeSBarry Smith /*@
820bb7acecfSBarry Smith   DMSetFromOptions - sets parameters in a `DM` from the options database
821d7bf68aeSBarry Smith 
82220f4b53cSBarry Smith   Collective
823d7bf68aeSBarry Smith 
824d7bf68aeSBarry Smith   Input Parameter:
825bb7acecfSBarry Smith . dm - the `DM` object to set options for
826d7bf68aeSBarry Smith 
82720f4b53cSBarry Smith   Options Database Keys:
828bb7acecfSBarry Smith + -dm_preallocate_only                               - Only preallocate the matrix for `DMCreateMatrix()` and `DMCreateMassMatrix()`, but do not fill it with zeros
829bb7acecfSBarry Smith . -dm_vec_type <type>                                - type of vector to create inside `DM`
830bb7acecfSBarry Smith . -dm_mat_type <type>                                - type of matrix to create inside `DM`
831a4ea9b21SRichard Tran Mills . -dm_is_coloring_type                               - <global or local>
83220f4b53cSBarry 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`
83322d6dc08SStefano Zampini . -dm_plex_option_phases <ph0_, ph1_, ...>           - List of prefixes for option processing phases
83420f4b53cSBarry Smith . -dm_plex_filename <str>                            - File containing a mesh
8359318fe57SMatthew G. Knepley . -dm_plex_boundary_filename <str>                   - File containing a mesh boundary
836cd7e8a5eSksagiyam . -dm_plex_name <str>                                - Name of the mesh in the file
8375dca41c3SJed Brown . -dm_plex_shape <shape>                             - The domain shape, such as `BOX`, `SPHERE`, etc.
8389318fe57SMatthew G. Knepley . -dm_plex_cell <ct>                                 - Cell shape
8399318fe57SMatthew G. Knepley . -dm_plex_reference_cell_domain <bool>              - Use a reference cell domain
8409318fe57SMatthew G. Knepley . -dm_plex_dim <dim>                                 - Set the topological dimension
841bb7acecfSBarry Smith . -dm_plex_simplex <bool>                            - `PETSC_TRUE` for simplex elements, `PETSC_FALSE` for tensor elements
842bb7acecfSBarry Smith . -dm_plex_interpolate <bool>                        - `PETSC_TRUE` turns on topological interpolation (creating edges and faces)
8439318fe57SMatthew G. Knepley . -dm_plex_scale <sc>                                - Scale factor for mesh coordinates
844be664eb1SMatthew G. Knepley . -dm_coord_remap <bool>                             - Map coordinates using a function
845be664eb1SMatthew G. Knepley . -dm_coord_map <mapname>                            - Select a builtin coordinate map
846be664eb1SMatthew G. Knepley . -dm_coord_map_params <p0,p1,p2,...>                - Set coordinate mapping parameters
8479318fe57SMatthew G. Knepley . -dm_plex_box_faces <m,n,p>                         - Number of faces along each dimension
8489318fe57SMatthew G. Knepley . -dm_plex_box_lower <x,y,z>                         - Specify lower-left-bottom coordinates for the box
8499318fe57SMatthew G. Knepley . -dm_plex_box_upper <x,y,z>                         - Specify upper-right-top coordinates for the box
850bb7acecfSBarry Smith . -dm_plex_box_bd <bx,by,bz>                         - Specify the `DMBoundaryType` for each direction
8519318fe57SMatthew G. Knepley . -dm_plex_sphere_radius <r>                         - The sphere radius
8529318fe57SMatthew G. Knepley . -dm_plex_ball_radius <r>                           - Radius of the ball
8539318fe57SMatthew G. Knepley . -dm_plex_cylinder_bd <bz>                          - Boundary type in the z direction
8549318fe57SMatthew G. Knepley . -dm_plex_cylinder_num_wedges <n>                   - Number of wedges around the cylinder
855bdf63967SMatthew G. Knepley . -dm_plex_reorder <order>                           - Reorder the mesh using the specified algorithm
8569318fe57SMatthew G. Knepley . -dm_refine_pre <n>                                 - The number of refinements before distribution
8579318fe57SMatthew G. Knepley . -dm_refine_uniform_pre <bool>                      - Flag for uniform refinement before distribution
8589318fe57SMatthew G. Knepley . -dm_refine_volume_limit_pre <v>                    - The maximum cell volume after refinement before distribution
8599318fe57SMatthew G. Knepley . -dm_refine <n>                                     - The number of refinements after distribution
860bdf63967SMatthew G. Knepley . -dm_extrude <l>                                    - Activate extrusion and specify the number of layers to extrude
861d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_thickness <t>           - The total thickness of extruded layers
862d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_use_tensor <bool>       - Use tensor cells when extruding
863d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_symmetric <bool>        - Extrude layers symmetrically about the surface
864d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_normal <n0,...,nd>      - Specify the extrusion direction
865d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_thicknesses <t0,...,tl> - Specify thickness of each layer
866909dfd52SMatthew G. Knepley . -dm_plex_create_fv_ghost_cells                     - Flag to create finite volume ghost cells on the boundary
867909dfd52SMatthew G. Knepley . -dm_plex_fv_ghost_cells_label <name>               - Label name for ghost cells boundary
8689318fe57SMatthew G. Knepley . -dm_distribute <bool>                              - Flag to redistribute a mesh among processes
8699318fe57SMatthew G. Knepley . -dm_distribute_overlap <n>                         - The size of the overlap halo
8709318fe57SMatthew G. Knepley . -dm_plex_adj_cone <bool>                           - Set adjacency direction
87120f4b53cSBarry Smith . -dm_plex_adj_closure <bool>                        - Set adjacency size
872d2b2dc1eSMatthew G. Knepley . -dm_plex_use_ceed <bool>                           - Use LibCEED as the FEM backend
87320f4b53cSBarry Smith . -dm_plex_check_symmetry                            - Check that the adjacency information in the mesh is symmetric - `DMPlexCheckSymmetry()`
874bb7acecfSBarry Smith . -dm_plex_check_skeleton                            - Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes) - `DMPlexCheckSkeleton()`
875bb7acecfSBarry 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()`
876bb7acecfSBarry Smith . -dm_plex_check_geometry                            - Check that cells have positive volume - `DMPlexCheckGeometry()`
877bb7acecfSBarry Smith . -dm_plex_check_pointsf                             - Check some necessary conditions for `PointSF` - `DMPlexCheckPointSF()`
878bb7acecfSBarry Smith . -dm_plex_check_interface_cones                     - Check points on inter-partition interfaces have conforming order of cone points - `DMPlexCheckInterfaceCones()`
879384a6580SVaclav Hapla - -dm_plex_check_all                                 - Perform all the checks above
880d7bf68aeSBarry Smith 
88195eb5ee5SVaclav Hapla   Level: intermediate
88295eb5ee5SVaclav Hapla 
8838e704042SBarry Smith   Note:
8848e704042SBarry Smith   For some `DMType` such as `DMDA` this cannot be called after `DMSetUp()` has been called.
8858e704042SBarry Smith 
8861cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
887bb7acecfSBarry Smith          `DMPlexCheckSymmetry()`, `DMPlexCheckSkeleton()`, `DMPlexCheckFaces()`, `DMPlexCheckGeometry()`, `DMPlexCheckPointSF()`, `DMPlexCheckInterfaceCones()`,
8888e704042SBarry Smith          `DMSetOptionsPrefix()`, `DMType`, `DMPLEX`, `DMDA`, `DMSetUp()`
889d7bf68aeSBarry Smith @*/
890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions(DM dm)
891d71ae5a4SJacob Faibussowitsch {
8927781c08eSBarry Smith   char      typeName[256];
893ca266f36SBarry Smith   PetscBool flg;
894d7bf68aeSBarry Smith 
895d7bf68aeSBarry Smith   PetscFunctionBegin;
896171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89749be4549SMatthew G. Knepley   dm->setfromoptionscalled = PETSC_TRUE;
8989566063dSJacob Faibussowitsch   if (dm->sf) PetscCall(PetscSFSetFromOptions(dm->sf));
8999566063dSJacob Faibussowitsch   if (dm->sectionSF) PetscCall(PetscSFSetFromOptions(dm->sectionSF));
900dd4c3f67SMatthew G. Knepley   if (dm->coordinates[0].dm) PetscCall(DMSetFromOptions(dm->coordinates[0].dm));
901d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)dm);
9029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_preallocate_only", "only preallocate matrix, but do not set column indices", "DMSetMatrixPreallocateOnly", dm->prealloc_only, &dm->prealloc_only, NULL));
9039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_vec_type", "Vector type used for created vectors", "DMSetVecType", VecList, dm->vectype, typeName, 256, &flg));
9041baa6e33SBarry Smith   if (flg) PetscCall(DMSetVecType(dm, typeName));
9059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_mat_type", "Matrix type used for created matrices", "DMSetMatType", MatList, dm->mattype ? dm->mattype : typeName, typeName, sizeof(typeName), &flg));
9061baa6e33SBarry Smith   if (flg) PetscCall(DMSetMatType(dm, typeName));
907863027abSJed Brown   PetscCall(PetscOptionsEnum("-dm_blocking_type", "Topological point or field node blocking", "DMSetBlockingType", DMBlockingTypes, (PetscEnum)dm->blocking_type, (PetscEnum *)&dm->blocking_type, NULL));
9089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_is_coloring_type", "Global or local coloring of Jacobian", "DMSetISColoringType", ISColoringTypes, (PetscEnum)dm->coloringtype, (PetscEnum *)&dm->coloringtype, NULL));
9099566063dSJacob 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));
910eb9d3e4dSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_ignore_perm_output", "Ignore the local section permutation on output", "DMGetOutputDM", dm->ignorePermOutput, &dm->ignorePermOutput, NULL));
911dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, setfromoptions, PetscOptionsObject);
912f9ba7244SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
913dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)dm, PetscOptionsObject));
914d0609cedSBarry Smith   PetscOptionsEnd();
9153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
916d7bf68aeSBarry Smith }
917d7bf68aeSBarry Smith 
918ffeef943SBarry Smith /*@
919bb7acecfSBarry Smith   DMViewFromOptions - View a `DM` in a particular way based on a request in the options database
920fe2efc57SMark 
92120f4b53cSBarry Smith   Collective
922fe2efc57SMark 
923fe2efc57SMark   Input Parameters:
924bb7acecfSBarry Smith + dm   - the `DM` object
92520f4b53cSBarry Smith . obj  - optional object that provides the prefix for the options database (if `NULL` then the prefix in obj is used)
92660225df5SJacob Faibussowitsch - name - option string that is used to activate viewing
927fe2efc57SMark 
928fe2efc57SMark   Level: intermediate
929bb7acecfSBarry Smith 
930bb7acecfSBarry Smith   Note:
931bb7acecfSBarry Smith   See `PetscObjectViewFromOptions()` for a list of values that can be provided in the options database to determine how the `DM` is viewed
932bb7acecfSBarry Smith 
93360225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMView()`, `PetscObjectViewFromOptions()`, `DMCreate()`
934fe2efc57SMark @*/
935d71ae5a4SJacob Faibussowitsch PetscErrorCode DMViewFromOptions(DM dm, PetscObject obj, const char name[])
936d71ae5a4SJacob Faibussowitsch {
937fe2efc57SMark   PetscFunctionBegin;
938fe2efc57SMark   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9399566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, obj, name));
9403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
941fe2efc57SMark }
942fe2efc57SMark 
943ffeef943SBarry Smith /*@
944bb7acecfSBarry 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
945bb7acecfSBarry Smith   save the `DM` in a binary file to be loaded later or create a visualization of the `DM`
94647c6ae99SBarry Smith 
94720f4b53cSBarry Smith   Collective
94847c6ae99SBarry Smith 
949d8d19677SJose E. Roman   Input Parameters:
950bb7acecfSBarry Smith + dm - the `DM` object to view
95147c6ae99SBarry Smith - v  - the viewer
95247c6ae99SBarry Smith 
95320f4b53cSBarry Smith   Level: beginner
95420f4b53cSBarry Smith 
95549c89c76SBlaise Bourdin   Notes:
95649c89c76SBlaise Bourdin 
95749c89c76SBlaise Bourdin   `PetscViewer` = `PETSCVIEWERHDF5` i.e. HDF5 format can be used with `PETSC_VIEWER_HDF5_PETSC` as the `PetscViewerFormat` to save multiple `DMPLEX`
958bb7acecfSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
959bb7acecfSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
960cd7e8a5eSksagiyam 
96149c89c76SBlaise Bourdin   `PetscViewer` = `PETSCVIEWEREXODUSII` i.e. ExodusII format assumes that element blocks (mapped to "Cell sets" labels)
96249c89c76SBlaise Bourdin   consists of sequentially numbered cells.
96349c89c76SBlaise Bourdin 
96449c89c76SBlaise Bourdin   If `dm` has been distributed, only the part of the `DM` on MPI rank 0 (including "ghost" cells and vertices) will be written.
96549c89c76SBlaise Bourdin 
96649c89c76SBlaise Bourdin   Only TRI, TET, QUAD, and HEX cells are supported.
96749c89c76SBlaise Bourdin 
96849c89c76SBlaise 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.
96949c89c76SBlaise Bourdin   The order of the mesh shall be set using `PetscViewerExodusIISetOrder()`
97049c89c76SBlaise Bourdin 
971d7c1f440SPierre Jolivet   Variable names can be set and queried using `PetscViewerExodusII[Set/Get][Nodal/Zonal]VariableNames[s]`.
97249c89c76SBlaise Bourdin 
9731cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscViewer`, `PetscViewerFormat`, `PetscViewerSetFormat()`, `DMDestroy()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMLoad()`, `PetscObjectSetName()`
97447c6ae99SBarry Smith @*/
975d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView(DM dm, PetscViewer v)
976d71ae5a4SJacob Faibussowitsch {
97732c0f0efSBarry Smith   PetscBool         isbinary;
97876a8abe0SBarry Smith   PetscMPIInt       size;
97976a8abe0SBarry Smith   PetscViewerFormat format;
98047c6ae99SBarry Smith 
98147c6ae99SBarry Smith   PetscFunctionBegin;
982171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
98348a46eb9SPierre Jolivet   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &v));
984b1b135c8SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);
98574903a4fSStefano Zampini   /* Ideally, we would like to have this test on.
98674903a4fSStefano Zampini      However, it currently breaks socket viz via GLVis.
98774903a4fSStefano Zampini      During DMView(parallel_mesh,glvis_viewer), each
98874903a4fSStefano Zampini      process opens a sequential ASCII socket to visualize
98974903a4fSStefano Zampini      the local mesh, and PetscObjectView(dm,local_socket)
99074903a4fSStefano Zampini      is internally called inside VecView_GLVis, incurring
99174903a4fSStefano Zampini      in an error here */
99274903a4fSStefano Zampini   /* PetscCheckSameComm(dm,1,v,2); */
9939566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckWritable(v));
994b1b135c8SBarry Smith 
9959566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(v, &format));
9969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9973ba16761SJacob Faibussowitsch   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
9989566063dSJacob Faibussowitsch   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)dm, v));
9999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERBINARY, &isbinary));
100032c0f0efSBarry Smith   if (isbinary) {
100155849f57SBarry Smith     PetscInt classid = DM_FILE_CLASSID;
100232c0f0efSBarry Smith     char     type[256];
100332c0f0efSBarry Smith 
10049566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWrite(v, &classid, 1, PETSC_INT));
1005c6a7a370SJeremy L Thompson     PetscCall(PetscStrncpy(type, ((PetscObject)dm)->type_name, sizeof(type)));
10069566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWrite(v, type, 256, PETSC_CHAR));
100732c0f0efSBarry Smith   }
1008dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, view, v);
10093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
101047c6ae99SBarry Smith }
101147c6ae99SBarry Smith 
101247c6ae99SBarry Smith /*@
1013bb7acecfSBarry 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,
1014bb7acecfSBarry Smith   that is it has no ghost locations.
101547c6ae99SBarry Smith 
101620f4b53cSBarry Smith   Collective
101747c6ae99SBarry Smith 
101847c6ae99SBarry Smith   Input Parameter:
1019bb7acecfSBarry Smith . dm - the `DM` object
102047c6ae99SBarry Smith 
102147c6ae99SBarry Smith   Output Parameter:
102247c6ae99SBarry Smith . vec - the global vector
102347c6ae99SBarry Smith 
1024073dac72SJed Brown   Level: beginner
102547c6ae99SBarry Smith 
10261cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `Vec`, `DMCreateLocalVector()`, `DMGetGlobalVector()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
1027bb7acecfSBarry Smith          `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`
102847c6ae99SBarry Smith @*/
1029d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateGlobalVector(DM dm, Vec *vec)
1030d71ae5a4SJacob Faibussowitsch {
103147c6ae99SBarry Smith   PetscFunctionBegin;
1032171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10334f572ea9SToby Isaac   PetscAssertPointer(vec, 2);
1034dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createglobalvector, vec);
103576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1036c6b011d8SStefano Zampini     DM vdm;
1037c6b011d8SStefano Zampini 
10389566063dSJacob Faibussowitsch     PetscCall(VecGetDM(*vec, &vdm));
10397a8be351SBarry Smith     PetscCheck(vdm, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DM type '%s' did not attach the DM to the vector", ((PetscObject)dm)->type_name);
1040c6b011d8SStefano Zampini   }
10413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
104247c6ae99SBarry Smith }
104347c6ae99SBarry Smith 
104447c6ae99SBarry Smith /*@
1045bb7acecfSBarry Smith   DMCreateLocalVector - Creates a local vector from a `DM` object.
104647c6ae99SBarry Smith 
104747c6ae99SBarry Smith   Not Collective
104847c6ae99SBarry Smith 
104947c6ae99SBarry Smith   Input Parameter:
1050bb7acecfSBarry Smith . dm - the `DM` object
105147c6ae99SBarry Smith 
105247c6ae99SBarry Smith   Output Parameter:
105347c6ae99SBarry Smith . vec - the local vector
105447c6ae99SBarry Smith 
1055073dac72SJed Brown   Level: beginner
105647c6ae99SBarry Smith 
105720f4b53cSBarry Smith   Note:
1058bb7acecfSBarry 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.
1059bb7acecfSBarry Smith 
10601cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `Vec`, `DMCreateGlobalVector()`, `DMGetLocalVector()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
1061bb7acecfSBarry Smith          `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`
106247c6ae99SBarry Smith @*/
1063d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLocalVector(DM dm, Vec *vec)
1064d71ae5a4SJacob Faibussowitsch {
106547c6ae99SBarry Smith   PetscFunctionBegin;
1066171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10674f572ea9SToby Isaac   PetscAssertPointer(vec, 2);
1068dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createlocalvector, vec);
106976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1070c6b011d8SStefano Zampini     DM vdm;
1071c6b011d8SStefano Zampini 
10729566063dSJacob Faibussowitsch     PetscCall(VecGetDM(*vec, &vdm));
10737a8be351SBarry Smith     PetscCheck(vdm, PETSC_COMM_SELF, PETSC_ERR_LIB, "DM type '%s' did not attach the DM to the vector", ((PetscObject)dm)->type_name);
1074c6b011d8SStefano Zampini   }
10753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
107647c6ae99SBarry Smith }
107747c6ae99SBarry Smith 
10781411c6eeSJed Brown /*@
1079bb7acecfSBarry Smith   DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a `DM`.
10801411c6eeSJed Brown 
108120f4b53cSBarry Smith   Collective
10821411c6eeSJed Brown 
10831411c6eeSJed Brown   Input Parameter:
1084bb7acecfSBarry Smith . dm - the `DM` that provides the mapping
10851411c6eeSJed Brown 
10861411c6eeSJed Brown   Output Parameter:
10871411c6eeSJed Brown . ltog - the mapping
10881411c6eeSJed Brown 
1089bb7acecfSBarry Smith   Level: advanced
10901411c6eeSJed Brown 
10911411c6eeSJed Brown   Notes:
1092bb7acecfSBarry Smith   The global to local mapping allows one to set values into the global vector or matrix using `VecSetValuesLocal()` and `MatSetValuesLocal()`
10931411c6eeSJed Brown 
1094bb7acecfSBarry Smith   Vectors obtained with  `DMCreateGlobalVector()` and matrices obtained with `DMCreateMatrix()` already contain the global mapping so you do
1095bb7acecfSBarry Smith   need to use this function with those objects.
1096bb7acecfSBarry Smith 
1097bb7acecfSBarry Smith   This mapping can then be used by `VecSetLocalToGlobalMapping()` or `MatSetLocalToGlobalMapping()`.
1098bb7acecfSBarry Smith 
109960225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `VecSetLocalToGlobalMapping()`, `MatSetLocalToGlobalMapping()`,
1100bb7acecfSBarry Smith           `DMCreateMatrix()`
11011411c6eeSJed Brown @*/
1102d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalToGlobalMapping(DM dm, ISLocalToGlobalMapping *ltog)
1103d71ae5a4SJacob Faibussowitsch {
11040be3e97aSMatthew G. Knepley   PetscInt bs = -1, bsLocal[2], bsMinMax[2];
11051411c6eeSJed Brown 
11061411c6eeSJed Brown   PetscFunctionBegin;
11071411c6eeSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11084f572ea9SToby Isaac   PetscAssertPointer(ltog, 2);
11091411c6eeSJed Brown   if (!dm->ltogmap) {
111037d0c07bSMatthew G Knepley     PetscSection section, sectionGlobal;
111137d0c07bSMatthew G Knepley 
11129566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
111337d0c07bSMatthew G Knepley     if (section) {
1114a974ec88SMatthew G. Knepley       const PetscInt *cdofs;
111537d0c07bSMatthew G Knepley       PetscInt       *ltog;
1116ccf3bd66SMatthew G. Knepley       PetscInt        pStart, pEnd, n, p, k, l;
111737d0c07bSMatthew G Knepley 
11189566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
11199566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
11209566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetStorageSize(section, &n));
11219566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n, &ltog)); /* We want the local+overlap size */
112237d0c07bSMatthew G Knepley       for (p = pStart, l = 0; p < pEnd; ++p) {
1123e6befd46SJed Brown         PetscInt bdof, cdof, dof, off, c, cind;
112437d0c07bSMatthew G Knepley 
112537d0c07bSMatthew G Knepley         /* Should probably use constrained dofs */
11269566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, p, &dof));
11279566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
11289566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, p, &cdofs));
11299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &off));
11301a7dc684SMatthew G. Knepley         /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
11311a7dc684SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
1132ad540459SPierre Jolivet         if (dof) bs = bs < 0 ? bdof : PetscGCD(bs, bdof);
11335227eafbSStefano Zampini 
1134e6befd46SJed Brown         for (c = 0, cind = 0; c < dof; ++c, ++l) {
11355227eafbSStefano Zampini           if (cind < cdof && c == cdofs[cind]) {
1136e6befd46SJed Brown             ltog[l] = off < 0 ? off - c : -(off + c + 1);
1137e6befd46SJed Brown             cind++;
1138e6befd46SJed Brown           } else {
11395227eafbSStefano Zampini             ltog[l] = (off < 0 ? -(off + 1) : off) + c - cind;
1140e6befd46SJed Brown           }
114137d0c07bSMatthew G Knepley         }
114237d0c07bSMatthew G Knepley       }
1143bff27382SMatthew G. Knepley       /* Must have same blocksize on all procs (some might have no points) */
11441690c2aeSBarry Smith       bsLocal[0] = bs < 0 ? PETSC_INT_MAX : bs;
11459371c9d4SSatish Balay       bsLocal[1] = bs;
11469566063dSJacob Faibussowitsch       PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
11479371c9d4SSatish Balay       if (bsMinMax[0] != bsMinMax[1]) {
11489371c9d4SSatish Balay         bs = 1;
11499371c9d4SSatish Balay       } else {
11509371c9d4SSatish Balay         bs = bsMinMax[0];
11519371c9d4SSatish Balay       }
11527591dbb2SMatthew G. Knepley       bs = bs < 0 ? 1 : bs;
11537591dbb2SMatthew G. Knepley       /* Must reduce indices by blocksize */
1154ccf3bd66SMatthew G. Knepley       if (bs > 1) {
1155ca469d19SJed Brown         for (l = 0, k = 0; l < n; l += bs, ++k) {
1156ca469d19SJed Brown           // Integer division of negative values truncates toward zero(!), not toward negative infinity
1157ca469d19SJed Brown           ltog[k] = ltog[l] >= 0 ? ltog[l] / bs : -(-(ltog[l] + 1) / bs + 1);
1158ca469d19SJed Brown         }
1159ccf3bd66SMatthew G. Knepley         n /= bs;
1160ccf3bd66SMatthew G. Knepley       }
11619566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap));
1162dbbe0bcdSBarry Smith     } else PetscUseTypeMethod(dm, getlocaltoglobalmapping);
116337d0c07bSMatthew G Knepley   }
11641411c6eeSJed Brown   *ltog = dm->ltogmap;
11653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11661411c6eeSJed Brown }
11671411c6eeSJed Brown 
11681411c6eeSJed Brown /*@
1169bb7acecfSBarry Smith   DMGetBlockSize - Gets the inherent block size associated with a `DM`
11701411c6eeSJed Brown 
11711411c6eeSJed Brown   Not Collective
11721411c6eeSJed Brown 
11731411c6eeSJed Brown   Input Parameter:
1174bb7acecfSBarry Smith . dm - the `DM` with block structure
11751411c6eeSJed Brown 
11761411c6eeSJed Brown   Output Parameter:
11771411c6eeSJed Brown . bs - the block size, 1 implies no exploitable block structure
11781411c6eeSJed Brown 
11791411c6eeSJed Brown   Level: intermediate
11801411c6eeSJed Brown 
118173ff1848SBarry Smith   Notes:
1182bb7acecfSBarry Smith   This might be the number of degrees of freedom at each grid point for a structured grid.
1183bb7acecfSBarry Smith 
1184bb7acecfSBarry Smith   Complex `DM` that represent multiphysics or staggered grids or mixed-methods do not generally have a single inherent block size, but
1185bb7acecfSBarry Smith   rather different locations in the vectors may have a different block size.
1186bb7acecfSBarry Smith 
11871cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `ISCreateBlock()`, `VecSetBlockSize()`, `MatSetBlockSize()`, `DMGetLocalToGlobalMapping()`
11881411c6eeSJed Brown @*/
1189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBlockSize(DM dm, PetscInt *bs)
1190d71ae5a4SJacob Faibussowitsch {
11911411c6eeSJed Brown   PetscFunctionBegin;
11921411c6eeSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11934f572ea9SToby Isaac   PetscAssertPointer(bs, 2);
11947a8be351SBarry Smith   PetscCheck(dm->bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM does not have enough information to provide a block size yet");
11951411c6eeSJed Brown   *bs = dm->bs;
11963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11971411c6eeSJed Brown }
11981411c6eeSJed Brown 
1199ffeef943SBarry Smith /*@
1200bb7acecfSBarry Smith   DMCreateInterpolation - Gets the interpolation matrix between two `DM` objects. The resulting matrix map degrees of freedom in the vector obtained by
1201bb7acecfSBarry Smith   `DMCreateGlobalVector()` on the coarse `DM` to similar vectors on the fine grid `DM`.
120247c6ae99SBarry Smith 
120320f4b53cSBarry Smith   Collective
120447c6ae99SBarry Smith 
1205d8d19677SJose E. Roman   Input Parameters:
1206bb7acecfSBarry Smith + dmc - the `DM` object
1207bb7acecfSBarry Smith - dmf - the second, finer `DM` object
120847c6ae99SBarry Smith 
1209d8d19677SJose E. Roman   Output Parameters:
121047c6ae99SBarry Smith + mat - the interpolation
1211b6971eaeSBarry Smith - vec - the scaling (optional, pass `NULL` if not needed), see `DMCreateInterpolationScale()`
121247c6ae99SBarry Smith 
121347c6ae99SBarry Smith   Level: developer
121447c6ae99SBarry Smith 
121595452b02SPatrick Sanan   Notes:
1216bb7acecfSBarry 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
1217bb7acecfSBarry Smith   DMCoarsen(). The coordinates set into the `DMDA` are completely ignored in computing the interpolation.
1218d52bd9f3SBarry Smith 
1219bb7acecfSBarry Smith   For `DMDA` objects you can use this interpolation (more precisely the interpolation from the `DMGetCoordinateDM()`) to interpolate the mesh coordinate
1220bb7acecfSBarry Smith   vectors EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
122185afcc9aSBarry Smith 
12221cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolationScale()`
122347c6ae99SBarry Smith @*/
1224d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation(DM dmc, DM dmf, Mat *mat, Vec *vec)
1225d71ae5a4SJacob Faibussowitsch {
122647c6ae99SBarry Smith   PetscFunctionBegin;
1227a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1228a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
12294f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
12309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateInterpolation, dmc, dmf, 0, 0));
1231dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createinterpolation, dmf, mat, vec);
12329566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateInterpolation, dmc, dmf, 0, 0));
12333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
123447c6ae99SBarry Smith }
123547c6ae99SBarry Smith 
12363ad4599aSBarry Smith /*@
1237a4e35b19SJacob Faibussowitsch   DMCreateInterpolationScale - Forms L = 1/(R*1) where 1 is the vector of all ones, and R is
1238a4e35b19SJacob Faibussowitsch   the transpose of the interpolation between the `DM`.
12392ed6491fSPatrick Sanan 
12402ed6491fSPatrick Sanan   Input Parameters:
1241bb7acecfSBarry Smith + dac - `DM` that defines a coarse mesh
1242bb7acecfSBarry Smith . daf - `DM` that defines a fine mesh
12432ed6491fSPatrick Sanan - mat - the restriction (or interpolation operator) from fine to coarse
12442ed6491fSPatrick Sanan 
12452ed6491fSPatrick Sanan   Output Parameter:
12462ed6491fSPatrick Sanan . scale - the scaled vector
12472ed6491fSPatrick Sanan 
1248bb7acecfSBarry Smith   Level: advanced
12492ed6491fSPatrick Sanan 
125073ff1848SBarry Smith   Note:
1251a4e35b19SJacob Faibussowitsch   xcoarse = diag(L)*R*xfine preserves scale and is thus suitable for state (versus residual)
1252a4e35b19SJacob Faibussowitsch   restriction. In other words xcoarse is the coarse representation of xfine.
1253a4e35b19SJacob Faibussowitsch 
125473ff1848SBarry Smith   Developer Note:
1255bb7acecfSBarry Smith   If the fine-scale `DMDA` has the -dm_bind_below option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
1256e9c74fd6SRichard Tran Mills   on the restriction/interpolation operator to set the bindingpropagates flag to true.
1257e9c74fd6SRichard Tran Mills 
125860225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `MatRestrict()`, `MatInterpolate()`, `DMCreateInterpolation()`, `DMCreateRestriction()`, `DMCreateGlobalVector()`
12592ed6491fSPatrick Sanan @*/
1260d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolationScale(DM dac, DM daf, Mat mat, Vec *scale)
1261d71ae5a4SJacob Faibussowitsch {
12622ed6491fSPatrick Sanan   Vec         fine;
12632ed6491fSPatrick Sanan   PetscScalar one = 1.0;
12649704db99SRichard Tran Mills #if defined(PETSC_HAVE_CUDA)
1265e9c74fd6SRichard Tran Mills   PetscBool bindingpropagates, isbound;
12669704db99SRichard Tran Mills #endif
12672ed6491fSPatrick Sanan 
12682ed6491fSPatrick Sanan   PetscFunctionBegin;
12699566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(daf, &fine));
12709566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dac, scale));
12719566063dSJacob Faibussowitsch   PetscCall(VecSet(fine, one));
12729704db99SRichard Tran Mills #if defined(PETSC_HAVE_CUDA)
12739704db99SRichard Tran Mills   /* If the 'fine' Vec is bound to the CPU, it makes sense to bind 'mat' as well.
12749704db99SRichard Tran Mills    * Note that we only do this for the CUDA case, right now, but if we add support for MatMultTranspose() via ViennaCL,
12759704db99SRichard Tran Mills    * we'll need to do it for that case, too.*/
12769566063dSJacob Faibussowitsch   PetscCall(VecGetBindingPropagates(fine, &bindingpropagates));
1277e9c74fd6SRichard Tran Mills   if (bindingpropagates) {
12789566063dSJacob Faibussowitsch     PetscCall(MatSetBindingPropagates(mat, PETSC_TRUE));
12799566063dSJacob Faibussowitsch     PetscCall(VecBoundToCPU(fine, &isbound));
12809566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(mat, isbound));
128183aa49f4SRichard Tran Mills   }
12829704db99SRichard Tran Mills #endif
12839566063dSJacob Faibussowitsch   PetscCall(MatRestrict(mat, fine, *scale));
12849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fine));
12859566063dSJacob Faibussowitsch   PetscCall(VecReciprocal(*scale));
12863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12872ed6491fSPatrick Sanan }
12882ed6491fSPatrick Sanan 
12892ed6491fSPatrick Sanan /*@
1290bb7acecfSBarry Smith   DMCreateRestriction - Gets restriction matrix between two `DM` objects. The resulting matrix map degrees of freedom in the vector obtained by
1291bb7acecfSBarry Smith   `DMCreateGlobalVector()` on the fine `DM` to similar vectors on the coarse grid `DM`.
12923ad4599aSBarry Smith 
129320f4b53cSBarry Smith   Collective
12943ad4599aSBarry Smith 
1295d8d19677SJose E. Roman   Input Parameters:
1296bb7acecfSBarry Smith + dmc - the `DM` object
1297bb7acecfSBarry Smith - dmf - the second, finer `DM` object
12983ad4599aSBarry Smith 
12993ad4599aSBarry Smith   Output Parameter:
13003ad4599aSBarry Smith . mat - the restriction
13013ad4599aSBarry Smith 
13023ad4599aSBarry Smith   Level: developer
13033ad4599aSBarry Smith 
1304bb7acecfSBarry Smith   Note:
1305bb7acecfSBarry Smith   This only works for `DMSTAG`. For many situations either the transpose of the operator obtained with `DMCreateInterpolation()` or that
1306bb7acecfSBarry Smith   matrix multiplied by the vector obtained with `DMCreateInterpolationScale()` provides the desired object.
13073ad4599aSBarry Smith 
13081cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRestrict()`, `DMInterpolate()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateInterpolation()`
13093ad4599aSBarry Smith @*/
1310d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateRestriction(DM dmc, DM dmf, Mat *mat)
1311d71ae5a4SJacob Faibussowitsch {
13123ad4599aSBarry Smith   PetscFunctionBegin;
1313a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1314a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
13154f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
13169566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateRestriction, dmc, dmf, 0, 0));
1317dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createrestriction, dmf, mat);
13189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateRestriction, dmc, dmf, 0, 0));
13193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13203ad4599aSBarry Smith }
13213ad4599aSBarry Smith 
132247c6ae99SBarry Smith /*@
1323a4e35b19SJacob Faibussowitsch   DMCreateInjection - Gets injection matrix between two `DM` objects.
132447c6ae99SBarry Smith 
132520f4b53cSBarry Smith   Collective
132647c6ae99SBarry Smith 
1327d8d19677SJose E. Roman   Input Parameters:
1328bb7acecfSBarry Smith + dac - the `DM` object
1329bb7acecfSBarry Smith - daf - the second, finer `DM` object
133047c6ae99SBarry Smith 
133147c6ae99SBarry Smith   Output Parameter:
13326dbf9973SLawrence Mitchell . mat - the injection
133347c6ae99SBarry Smith 
133447c6ae99SBarry Smith   Level: developer
133547c6ae99SBarry Smith 
1336a4e35b19SJacob Faibussowitsch   Notes:
1337a4e35b19SJacob Faibussowitsch   This is an operator that applied to a vector obtained with `DMCreateGlobalVector()` on the
1338a4e35b19SJacob Faibussowitsch   fine grid maps the values to a vector on the vector on the coarse `DM` by simply selecting
1339a4e35b19SJacob Faibussowitsch   the values on the coarse grid points. This compares to the operator obtained by
1340a4e35b19SJacob Faibussowitsch   `DMCreateRestriction()` or the transpose of the operator obtained by
1341a4e35b19SJacob Faibussowitsch   `DMCreateInterpolation()` that uses a "local weighted average" of the values around the
1342a4e35b19SJacob Faibussowitsch   coarse grid point as the coarse grid value.
1343a4e35b19SJacob Faibussowitsch 
1344bb7acecfSBarry 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
1345bb7acecfSBarry Smith   `DMCoarsen()`. The coordinates set into the `DMDA` are completely ignored in computing the injection.
134685afcc9aSBarry Smith 
13471cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateInterpolation()`,
1348bb7acecfSBarry Smith           `DMCreateRestriction()`, `MatRestrict()`, `MatInterpolate()`
134947c6ae99SBarry Smith @*/
1350d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection(DM dac, DM daf, Mat *mat)
1351d71ae5a4SJacob Faibussowitsch {
135247c6ae99SBarry Smith   PetscFunctionBegin;
1353a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dac, DM_CLASSID, 1);
1354a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(daf, DM_CLASSID, 2);
13554f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
13569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateInjection, dac, daf, 0, 0));
1357dbbe0bcdSBarry Smith   PetscUseTypeMethod(dac, createinjection, daf, mat);
13589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateInjection, dac, daf, 0, 0));
13593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
136047c6ae99SBarry Smith }
136147c6ae99SBarry Smith 
1362b412c318SBarry Smith /*@
1363bb7acecfSBarry 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
1364bb7acecfSBarry Smith   a Galerkin finite element model on the `DM`
1365bd041c0cSMatthew G. Knepley 
136620f4b53cSBarry Smith   Collective
1367bd041c0cSMatthew G. Knepley 
1368d8d19677SJose E. Roman   Input Parameters:
1369bb7acecfSBarry Smith + dmc - the target `DM` object
13708c1c0954SStefano Zampini - dmf - the source `DM` object, can be `NULL`
1371bd041c0cSMatthew G. Knepley 
1372bd041c0cSMatthew G. Knepley   Output Parameter:
1373b4937a87SMatthew G. Knepley . mat - the mass matrix
1374bd041c0cSMatthew G. Knepley 
1375bd041c0cSMatthew G. Knepley   Level: developer
1376bd041c0cSMatthew G. Knepley 
1377bb7acecfSBarry Smith   Notes:
1378bb7acecfSBarry Smith   For `DMPLEX` the finite element model for the `DM` must have been already provided.
1379bb7acecfSBarry Smith 
13808c1c0954SStefano 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()`
1381bb7acecfSBarry Smith 
138242747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateMassMatrixLumped()`, `DMCreateMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolation()`, `DMCreateInjection()`
1383bd041c0cSMatthew G. Knepley @*/
1384d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix(DM dmc, DM dmf, Mat *mat)
1385d71ae5a4SJacob Faibussowitsch {
1386bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
1387b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
13888c1c0954SStefano Zampini   if (!dmf) dmf = dmc;
1389b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
13904f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
13918c1c0954SStefano Zampini   PetscCall(PetscLogEventBegin(DM_CreateMassMatrix, dmc, dmf, 0, 0));
1392dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createmassmatrix, dmf, mat);
13938c1c0954SStefano Zampini   PetscCall(PetscLogEventEnd(DM_CreateMassMatrix, dmc, dmf, 0, 0));
13943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1395b4937a87SMatthew G. Knepley }
1396b4937a87SMatthew G. Knepley 
1397b4937a87SMatthew G. Knepley /*@
1398bb7acecfSBarry Smith   DMCreateMassMatrixLumped - Gets the lumped mass matrix for a given `DM`
1399b4937a87SMatthew G. Knepley 
140020f4b53cSBarry Smith   Collective
1401b4937a87SMatthew G. Knepley 
1402b4937a87SMatthew G. Knepley   Input Parameter:
1403bb7acecfSBarry Smith . dm - the `DM` object
1404b4937a87SMatthew G. Knepley 
14057dcfde4dSJose E. Roman   Output Parameters:
14068e9849d2SStefano Zampini + llm - the local lumped mass matrix, which is a diagonal matrix, represented as a vector
14078e9849d2SStefano Zampini - lm  - the global lumped mass matrix, which is a diagonal matrix, represented as a vector
1408b4937a87SMatthew G. Knepley 
1409b4937a87SMatthew G. Knepley   Level: developer
1410b4937a87SMatthew G. Knepley 
1411bb7acecfSBarry Smith   Note:
1412bb7acecfSBarry Smith   See `DMCreateMassMatrix()` for how to create the non-lumped version of the mass matrix.
1413bb7acecfSBarry Smith 
141460225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateMassMatrix()`, `DMCreateMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolation()`, `DMCreateInjection()`
1415b4937a87SMatthew G. Knepley @*/
14168e9849d2SStefano Zampini PetscErrorCode DMCreateMassMatrixLumped(DM dm, Vec *llm, Vec *lm)
1417d71ae5a4SJacob Faibussowitsch {
1418b4937a87SMatthew G. Knepley   PetscFunctionBegin;
1419b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14208e9849d2SStefano Zampini   if (llm) PetscAssertPointer(llm, 2);
14218e9849d2SStefano Zampini   if (lm) PetscAssertPointer(lm, 3);
14228e9849d2SStefano Zampini   if (llm || lm) PetscUseTypeMethod(dm, createmassmatrixlumped, llm, lm);
14233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1424bd041c0cSMatthew G. Knepley }
1425bd041c0cSMatthew G. Knepley 
1426bd041c0cSMatthew G. Knepley /*@
1427bb7acecfSBarry Smith   DMCreateColoring - Gets coloring of a graph associated with the `DM`. Often the graph represents the operator matrix associated with the discretization
1428bb7acecfSBarry Smith   of a PDE on the `DM`.
142947c6ae99SBarry Smith 
143020f4b53cSBarry Smith   Collective
143147c6ae99SBarry Smith 
1432d8d19677SJose E. Roman   Input Parameters:
1433bb7acecfSBarry Smith + dm    - the `DM` object
1434bb7acecfSBarry Smith - ctype - `IS_COLORING_LOCAL` or `IS_COLORING_GLOBAL`
143547c6ae99SBarry Smith 
143647c6ae99SBarry Smith   Output Parameter:
143747c6ae99SBarry Smith . coloring - the coloring
143847c6ae99SBarry Smith 
14391bf8429eSBarry Smith   Level: developer
14401bf8429eSBarry Smith 
1441ec5066bdSBarry Smith   Notes:
1442bb7acecfSBarry 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
1443bb7acecfSBarry Smith   matrix comes from (what this function provides). In general using the mesh produces a more optimal coloring (fewer colors).
1444ec5066bdSBarry Smith 
1445bb7acecfSBarry Smith   This produces a coloring with the distance of 2, see `MatSetColoringDistance()` which can be used for efficiently computing Jacobians with `MatFDColoringCreate()`
14461bf8429eSBarry 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,
14471bf8429eSBarry Smith   otherwise an error will be generated.
1448ec5066bdSBarry Smith 
14491cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `ISColoring`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatType()`, `MatColoring`, `MatFDColoringCreate()`
1450aab9d709SJed Brown @*/
1451d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring(DM dm, ISColoringType ctype, ISColoring *coloring)
1452d71ae5a4SJacob Faibussowitsch {
145347c6ae99SBarry Smith   PetscFunctionBegin;
1454171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14554f572ea9SToby Isaac   PetscAssertPointer(coloring, 3);
1456dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getcoloring, ctype, coloring);
14573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
145847c6ae99SBarry Smith }
145947c6ae99SBarry Smith 
1460b412c318SBarry Smith /*@
1461bb7acecfSBarry Smith   DMCreateMatrix - Gets an empty matrix for a `DM` that is most commonly used to store the Jacobian of a discrete PDE operator.
146247c6ae99SBarry Smith 
146320f4b53cSBarry Smith   Collective
146447c6ae99SBarry Smith 
146547c6ae99SBarry Smith   Input Parameter:
1466bb7acecfSBarry Smith . dm - the `DM` object
146747c6ae99SBarry Smith 
146847c6ae99SBarry Smith   Output Parameter:
146947c6ae99SBarry Smith . mat - the empty Jacobian
147047c6ae99SBarry Smith 
147120f4b53cSBarry Smith   Options Database Key:
1472bb7acecfSBarry Smith . -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()` and `DMCreateMassMatrix()`, but do not fill it with zeros
1473f27dd7c6SMatthew G. Knepley 
147420f4b53cSBarry Smith   Level: beginner
147520f4b53cSBarry Smith 
147695452b02SPatrick Sanan   Notes:
147795452b02SPatrick Sanan   This properly preallocates the number of nonzeros in the sparse matrix so you
147894013140SBarry Smith   do not need to do it yourself.
147994013140SBarry Smith 
148094013140SBarry Smith   By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1481bb7acecfSBarry Smith   the nonzero pattern call `DMSetMatrixPreallocateOnly()`
148294013140SBarry Smith 
1483bb7acecfSBarry Smith   For `DMDA`, when you call `MatView()` on this matrix it is displayed using the global natural ordering, NOT in the ordering used
148494013140SBarry Smith   internally by PETSc.
148594013140SBarry Smith 
1486bb7acecfSBarry Smith   For `DMDA`, in general it is easiest to use `MatSetValuesStencil()` or `MatSetValuesLocal()` to put values into the matrix because
1487bb7acecfSBarry Smith   `MatSetValues()` requires the indices for the global numbering for the `DMDA` which is complic`ated to compute
148894013140SBarry Smith 
14891cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMSetMatType()`, `DMCreateMassMatrix()`
1490aab9d709SJed Brown @*/
1491d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix(DM dm, Mat *mat)
1492d71ae5a4SJacob Faibussowitsch {
149347c6ae99SBarry Smith   PetscFunctionBegin;
1494171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14954f572ea9SToby Isaac   PetscAssertPointer(mat, 2);
14969566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
14979566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateMatrix, 0, 0, 0, 0));
1498dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, creatematrix, mat);
149976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1500c6b011d8SStefano Zampini     DM mdm;
1501c6b011d8SStefano Zampini 
15029566063dSJacob Faibussowitsch     PetscCall(MatGetDM(*mat, &mdm));
15037a8be351SBarry Smith     PetscCheck(mdm, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DM type '%s' did not attach the DM to the matrix", ((PetscObject)dm)->type_name);
1504c6b011d8SStefano Zampini   }
1505e571a35bSMatthew G. Knepley   /* Handle nullspace and near nullspace */
1506e5e52638SMatthew G. Knepley   if (dm->Nf) {
1507e571a35bSMatthew G. Knepley     MatNullSpace nullSpace;
1508649ef022SMatthew Knepley     PetscInt     Nf, f;
1509e571a35bSMatthew G. Knepley 
15109566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
1511649ef022SMatthew Knepley     for (f = 0; f < Nf; ++f) {
1512649ef022SMatthew Knepley       if (dm->nullspaceConstructors[f]) {
15139566063dSJacob Faibussowitsch         PetscCall((*dm->nullspaceConstructors[f])(dm, f, f, &nullSpace));
15149566063dSJacob Faibussowitsch         PetscCall(MatSetNullSpace(*mat, nullSpace));
15159566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nullSpace));
1516649ef022SMatthew Knepley         break;
1517e571a35bSMatthew G. Knepley       }
1518649ef022SMatthew Knepley     }
1519649ef022SMatthew Knepley     for (f = 0; f < Nf; ++f) {
1520649ef022SMatthew Knepley       if (dm->nearnullspaceConstructors[f]) {
15219566063dSJacob Faibussowitsch         PetscCall((*dm->nearnullspaceConstructors[f])(dm, f, f, &nullSpace));
15229566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(*mat, nullSpace));
15239566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nullSpace));
1524e571a35bSMatthew G. Knepley       }
1525e571a35bSMatthew G. Knepley     }
1526e571a35bSMatthew G. Knepley   }
15279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateMatrix, 0, 0, 0, 0));
15283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
152947c6ae99SBarry Smith }
153047c6ae99SBarry Smith 
1531732e2eb9SMatthew G Knepley /*@
1532a4e35b19SJacob Faibussowitsch   DMSetMatrixPreallocateSkip - When `DMCreateMatrix()` is called the matrix sizes and
1533a4e35b19SJacob Faibussowitsch   `ISLocalToGlobalMapping` will be properly set, but the data structures to store values in the
1534a4e35b19SJacob Faibussowitsch   matrices will not be preallocated.
1535aa0f6e3cSJed Brown 
153620f4b53cSBarry Smith   Logically Collective
1537aa0f6e3cSJed Brown 
1538aa0f6e3cSJed Brown   Input Parameters:
1539bb7acecfSBarry Smith + dm   - the `DM`
1540bb7acecfSBarry Smith - skip - `PETSC_TRUE` to skip preallocation
1541aa0f6e3cSJed Brown 
1542aa0f6e3cSJed Brown   Level: developer
1543aa0f6e3cSJed Brown 
154473ff1848SBarry Smith   Note:
1545a4e35b19SJacob Faibussowitsch   This is most useful to reduce initialization costs when `MatSetPreallocationCOO()` and
1546a4e35b19SJacob Faibussowitsch   `MatSetValuesCOO()` will be used.
1547a4e35b19SJacob Faibussowitsch 
15481cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMSetMatrixStructureOnly()`, `DMSetMatrixPreallocateOnly()`
1549aa0f6e3cSJed Brown @*/
1550d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixPreallocateSkip(DM dm, PetscBool skip)
1551d71ae5a4SJacob Faibussowitsch {
1552aa0f6e3cSJed Brown   PetscFunctionBegin;
1553aa0f6e3cSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1554aa0f6e3cSJed Brown   dm->prealloc_skip = skip;
15553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1556aa0f6e3cSJed Brown }
1557aa0f6e3cSJed Brown 
1558aa0f6e3cSJed Brown /*@
1559bb7acecfSBarry Smith   DMSetMatrixPreallocateOnly - When `DMCreateMatrix()` is called the matrix will be properly
1560732e2eb9SMatthew G Knepley   preallocated but the nonzero structure and zero values will not be set.
1561732e2eb9SMatthew G Knepley 
156220f4b53cSBarry Smith   Logically Collective
1563732e2eb9SMatthew G Knepley 
1564d8d19677SJose E. Roman   Input Parameters:
1565bb7acecfSBarry Smith + dm   - the `DM`
1566bb7acecfSBarry Smith - only - `PETSC_TRUE` if only want preallocation
1567732e2eb9SMatthew G Knepley 
156820f4b53cSBarry Smith   Options Database Key:
1569bb7acecfSBarry Smith . -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()`, `DMCreateMassMatrix()`, but do not fill it with zeros
1570f27dd7c6SMatthew G. Knepley 
157120f4b53cSBarry Smith   Level: developer
157220f4b53cSBarry Smith 
15731cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixStructureOnly()`, `DMSetMatrixPreallocateSkip()`
1574732e2eb9SMatthew G Knepley @*/
1575d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1576d71ae5a4SJacob Faibussowitsch {
1577732e2eb9SMatthew G Knepley   PetscFunctionBegin;
1578732e2eb9SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1579732e2eb9SMatthew G Knepley   dm->prealloc_only = only;
15803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1581732e2eb9SMatthew G Knepley }
1582732e2eb9SMatthew G Knepley 
1583b06ff27eSHong Zhang /*@
1584bb7acecfSBarry Smith   DMSetMatrixStructureOnly - When `DMCreateMatrix()` is called, the matrix structure will be created
1585bb7acecfSBarry Smith   but the array for numerical values will not be allocated.
1586b06ff27eSHong Zhang 
158720f4b53cSBarry Smith   Logically Collective
1588b06ff27eSHong Zhang 
1589d8d19677SJose E. Roman   Input Parameters:
1590bb7acecfSBarry Smith + dm   - the `DM`
1591da81f932SPierre Jolivet - only - `PETSC_TRUE` if you only want matrix structure
1592b06ff27eSHong Zhang 
1593b06ff27eSHong Zhang   Level: developer
1594bb7acecfSBarry Smith 
15951cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMSetMatrixPreallocateOnly()`, `DMSetMatrixPreallocateSkip()`
1596b06ff27eSHong Zhang @*/
1597d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1598d71ae5a4SJacob Faibussowitsch {
1599b06ff27eSHong Zhang   PetscFunctionBegin;
1600b06ff27eSHong Zhang   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1601b06ff27eSHong Zhang   dm->structure_only = only;
16023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1603b06ff27eSHong Zhang }
1604b06ff27eSHong Zhang 
1605863027abSJed Brown /*@
1606863027abSJed Brown   DMSetBlockingType - set the blocking granularity to be used for variable block size `DMCreateMatrix()` is called
1607863027abSJed Brown 
160820f4b53cSBarry Smith   Logically Collective
1609863027abSJed Brown 
1610863027abSJed Brown   Input Parameters:
1611863027abSJed Brown + dm    - the `DM`
1612863027abSJed Brown - btype - block by topological point or field node
1613863027abSJed Brown 
161420f4b53cSBarry Smith   Options Database Key:
16150e762ea3SJed Brown . -dm_blocking_type [topological_point, field_node] - use topological point blocking or field node blocking
1616863027abSJed Brown 
161720f4b53cSBarry Smith   Level: advanced
161820f4b53cSBarry Smith 
16191cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `MatSetVariableBlockSizes()`
1620863027abSJed Brown @*/
1621863027abSJed Brown PetscErrorCode DMSetBlockingType(DM dm, DMBlockingType btype)
1622863027abSJed Brown {
1623863027abSJed Brown   PetscFunctionBegin;
1624863027abSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1625863027abSJed Brown   dm->blocking_type = btype;
16263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1627863027abSJed Brown }
1628863027abSJed Brown 
1629863027abSJed Brown /*@
1630863027abSJed Brown   DMGetBlockingType - get the blocking granularity to be used for variable block size `DMCreateMatrix()` is called
1631863027abSJed Brown 
1632863027abSJed Brown   Not Collective
1633863027abSJed Brown 
16342fe279fdSBarry Smith   Input Parameter:
1635863027abSJed Brown . dm - the `DM`
1636863027abSJed Brown 
16372fe279fdSBarry Smith   Output Parameter:
1638863027abSJed Brown . btype - block by topological point or field node
1639863027abSJed Brown 
1640863027abSJed Brown   Level: advanced
1641863027abSJed Brown 
16421cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `MatSetVariableBlockSizes()`
1643863027abSJed Brown @*/
1644863027abSJed Brown PetscErrorCode DMGetBlockingType(DM dm, DMBlockingType *btype)
1645863027abSJed Brown {
1646863027abSJed Brown   PetscFunctionBegin;
1647863027abSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
16484f572ea9SToby Isaac   PetscAssertPointer(btype, 2);
1649863027abSJed Brown   *btype = dm->blocking_type;
16503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1651863027abSJed Brown }
1652863027abSJed Brown 
1653a89ea682SMatthew G Knepley /*@C
1654bb7acecfSBarry Smith   DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with `DMRestoreWorkArray()`
1655a89ea682SMatthew G Knepley 
1656a89ea682SMatthew G Knepley   Not Collective
1657a89ea682SMatthew G Knepley 
1658a89ea682SMatthew G Knepley   Input Parameters:
1659bb7acecfSBarry Smith + dm    - the `DM` object
1660a5b23f4aSJose E. Roman . count - The minimum size
166120f4b53cSBarry Smith - dtype - MPI data type, often `MPIU_REAL`, `MPIU_SCALAR`, or `MPIU_INT`)
1662a89ea682SMatthew G Knepley 
1663a89ea682SMatthew G Knepley   Output Parameter:
166460225df5SJacob Faibussowitsch . mem - the work array
1665a89ea682SMatthew G Knepley 
1666a89ea682SMatthew G Knepley   Level: developer
1667a89ea682SMatthew G Knepley 
166873ff1848SBarry Smith   Notes:
1669da81f932SPierre Jolivet   A `DM` may stash the array between instantiations so using this routine may be more efficient than calling `PetscMalloc()`
1670bb7acecfSBarry Smith 
1671bb7acecfSBarry Smith   The array may contain nonzero values
1672bb7acecfSBarry Smith 
16731cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMRestoreWorkArray()`, `PetscMalloc()`
1674a89ea682SMatthew G Knepley @*/
1675d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetWorkArray(DM dm, PetscInt count, MPI_Datatype dtype, void *mem)
1676d71ae5a4SJacob Faibussowitsch {
1677aa1993deSMatthew G Knepley   DMWorkLink  link;
167869291d52SBarry Smith   PetscMPIInt dsize;
1679a89ea682SMatthew G Knepley 
1680a89ea682SMatthew G Knepley   PetscFunctionBegin;
1681a89ea682SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
16824f572ea9SToby Isaac   PetscAssertPointer(mem, 4);
1683442f3b32SStefano Zampini   if (!count) {
1684442f3b32SStefano Zampini     *(void **)mem = NULL;
1685442f3b32SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
1686442f3b32SStefano Zampini   }
1687aa1993deSMatthew G Knepley   if (dm->workin) {
1688aa1993deSMatthew G Knepley     link       = dm->workin;
1689aa1993deSMatthew G Knepley     dm->workin = dm->workin->next;
1690aa1993deSMatthew G Knepley   } else {
16914dfa11a4SJacob Faibussowitsch     PetscCall(PetscNew(&link));
1692a89ea682SMatthew G Knepley   }
1693b77fa653SStefano Zampini   /* Avoid MPI_Type_size for most used datatypes
1694b77fa653SStefano Zampini      Get size directly */
1695b77fa653SStefano Zampini   if (dtype == MPIU_INT) dsize = sizeof(PetscInt);
1696b77fa653SStefano Zampini   else if (dtype == MPIU_REAL) dsize = sizeof(PetscReal);
1697b77fa653SStefano Zampini #if defined(PETSC_USE_64BIT_INDICES)
1698b77fa653SStefano Zampini   else if (dtype == MPI_INT) dsize = sizeof(int);
1699b77fa653SStefano Zampini #endif
1700b77fa653SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1701b77fa653SStefano Zampini   else if (dtype == MPIU_SCALAR) dsize = sizeof(PetscScalar);
1702b77fa653SStefano Zampini #endif
1703b77fa653SStefano Zampini   else PetscCallMPI(MPI_Type_size(dtype, &dsize));
1704b77fa653SStefano Zampini 
17055056fcd2SBarry Smith   if (((size_t)dsize * count) > link->bytes) {
17069566063dSJacob Faibussowitsch     PetscCall(PetscFree(link->mem));
17079566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(dsize * count, &link->mem));
1708854ce69bSBarry Smith     link->bytes = dsize * count;
1709aa1993deSMatthew G Knepley   }
1710aa1993deSMatthew G Knepley   link->next    = dm->workout;
1711aa1993deSMatthew G Knepley   dm->workout   = link;
1712aa1993deSMatthew G Knepley   *(void **)mem = link->mem;
17133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1714a89ea682SMatthew G Knepley }
1715a89ea682SMatthew G Knepley 
1716aa1993deSMatthew G Knepley /*@C
1717bb7acecfSBarry Smith   DMRestoreWorkArray - Restores a work array obtained with `DMCreateWorkArray()`
1718aa1993deSMatthew G Knepley 
1719aa1993deSMatthew G Knepley   Not Collective
1720aa1993deSMatthew G Knepley 
1721aa1993deSMatthew G Knepley   Input Parameters:
1722bb7acecfSBarry Smith + dm    - the `DM` object
1723a5b23f4aSJose E. Roman . count - The minimum size
172420f4b53cSBarry Smith - dtype - MPI data type, often `MPIU_REAL`, `MPIU_SCALAR`, `MPIU_INT`
1725aa1993deSMatthew G Knepley 
1726aa1993deSMatthew G Knepley   Output Parameter:
172760225df5SJacob Faibussowitsch . mem - the work array
1728aa1993deSMatthew G Knepley 
1729aa1993deSMatthew G Knepley   Level: developer
1730aa1993deSMatthew G Knepley 
173173ff1848SBarry Smith   Developer Note:
1732bb7acecfSBarry Smith   count and dtype are ignored, they are only needed for `DMGetWorkArray()`
1733147403d9SBarry Smith 
17341cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMGetWorkArray()`
1735aa1993deSMatthew G Knepley @*/
1736d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestoreWorkArray(DM dm, PetscInt count, MPI_Datatype dtype, void *mem)
1737d71ae5a4SJacob Faibussowitsch {
1738aa1993deSMatthew G Knepley   DMWorkLink *p, link;
1739aa1993deSMatthew G Knepley 
1740aa1993deSMatthew G Knepley   PetscFunctionBegin;
1741aa1993deSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17424f572ea9SToby Isaac   PetscAssertPointer(mem, 4);
1743a4e35b19SJacob Faibussowitsch   (void)count;
1744a4e35b19SJacob Faibussowitsch   (void)dtype;
1745442f3b32SStefano Zampini   if (!*(void **)mem) PetscFunctionReturn(PETSC_SUCCESS);
1746aa1993deSMatthew G Knepley   for (p = &dm->workout; (link = *p); p = &link->next) {
1747aa1993deSMatthew G Knepley     if (link->mem == *(void **)mem) {
1748aa1993deSMatthew G Knepley       *p            = link->next;
1749aa1993deSMatthew G Knepley       link->next    = dm->workin;
1750aa1993deSMatthew G Knepley       dm->workin    = link;
17510298fd71SBarry Smith       *(void **)mem = NULL;
17523ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
1753aa1993deSMatthew G Knepley     }
1754aa1993deSMatthew G Knepley   }
1755aa1993deSMatthew G Knepley   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Array was not checked out");
1756aa1993deSMatthew G Knepley }
1757e7c4fc90SDmitry Karpeev 
17588cda7954SMatthew G. Knepley /*@C
1759bb7acecfSBarry Smith   DMSetNullSpaceConstructor - Provide a callback function which constructs the nullspace for a given field, defined with `DMAddField()`, when function spaces
1760bb7acecfSBarry Smith   are joined or split, such as in `DMCreateSubDM()`
17618cda7954SMatthew G. Knepley 
176220f4b53cSBarry Smith   Logically Collective; No Fortran Support
17638cda7954SMatthew G. Knepley 
17648cda7954SMatthew G. Knepley   Input Parameters:
1765bb7acecfSBarry Smith + dm     - The `DM`
17668cda7954SMatthew G. Knepley . field  - The field number for the nullspace
17678cda7954SMatthew G. Knepley - nullsp - A callback to create the nullspace
17688cda7954SMatthew G. Knepley 
176920f4b53cSBarry Smith   Calling sequence of `nullsp`:
1770bb7acecfSBarry Smith + dm        - The present `DM`
1771bb7acecfSBarry Smith . origField - The field number given above, in the original `DM`
1772147403d9SBarry Smith . field     - The field number in dm
1773147403d9SBarry Smith - nullSpace - The nullspace for the given field
17748cda7954SMatthew G. Knepley 
177549762cbcSSatish Balay   Level: intermediate
177649762cbcSSatish Balay 
17771cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetNullSpaceConstructor()`, `DMSetNearNullSpaceConstructor()`, `DMGetNearNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
1778147403d9SBarry Smith @*/
1779a4e35b19SJacob Faibussowitsch PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1780d71ae5a4SJacob Faibussowitsch {
1781435a35e8SMatthew G Knepley   PetscFunctionBegin;
1782435a35e8SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17837a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1784435a35e8SMatthew G Knepley   dm->nullspaceConstructors[field] = nullsp;
17853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1786435a35e8SMatthew G Knepley }
1787435a35e8SMatthew G Knepley 
17888cda7954SMatthew G. Knepley /*@C
1789bb7acecfSBarry Smith   DMGetNullSpaceConstructor - Return the callback function which constructs the nullspace for a given field, defined with `DMAddField()`
17908cda7954SMatthew G. Knepley 
179120f4b53cSBarry Smith   Not Collective; No Fortran Support
17928cda7954SMatthew G. Knepley 
17938cda7954SMatthew G. Knepley   Input Parameters:
1794bb7acecfSBarry Smith + dm    - The `DM`
17958cda7954SMatthew G. Knepley - field - The field number for the nullspace
17968cda7954SMatthew G. Knepley 
17978cda7954SMatthew G. Knepley   Output Parameter:
17988cda7954SMatthew G. Knepley . nullsp - A callback to create the nullspace
17998cda7954SMatthew G. Knepley 
180020f4b53cSBarry Smith   Calling sequence of `nullsp`:
1801147403d9SBarry Smith + dm        - The present DM
1802147403d9SBarry Smith . origField - The field number given above, in the original DM
1803147403d9SBarry Smith . field     - The field number in dm
1804147403d9SBarry Smith - nullSpace - The nullspace for the given field
18058cda7954SMatthew G. Knepley 
180649762cbcSSatish Balay   Level: intermediate
180749762cbcSSatish Balay 
18081cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMSetNullSpaceConstructor()`, `DMSetNearNullSpaceConstructor()`, `DMGetNearNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
1809147403d9SBarry Smith @*/
1810a4e35b19SJacob Faibussowitsch PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1811d71ae5a4SJacob Faibussowitsch {
18120a50eb56SMatthew G. Knepley   PetscFunctionBegin;
18130a50eb56SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18144f572ea9SToby Isaac   PetscAssertPointer(nullsp, 3);
18157a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
18160a50eb56SMatthew G. Knepley   *nullsp = dm->nullspaceConstructors[field];
18173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18180a50eb56SMatthew G. Knepley }
18190a50eb56SMatthew G. Knepley 
18208cda7954SMatthew G. Knepley /*@C
1821bb7acecfSBarry Smith   DMSetNearNullSpaceConstructor - Provide a callback function which constructs the near-nullspace for a given field, defined with `DMAddField()`
18228cda7954SMatthew G. Knepley 
182320f4b53cSBarry Smith   Logically Collective; No Fortran Support
18248cda7954SMatthew G. Knepley 
18258cda7954SMatthew G. Knepley   Input Parameters:
1826bb7acecfSBarry Smith + dm     - The `DM`
18278cda7954SMatthew G. Knepley . field  - The field number for the nullspace
18288cda7954SMatthew G. Knepley - nullsp - A callback to create the near-nullspace
18298cda7954SMatthew G. Knepley 
183020f4b53cSBarry Smith   Calling sequence of `nullsp`:
1831bb7acecfSBarry Smith + dm        - The present `DM`
1832bb7acecfSBarry Smith . origField - The field number given above, in the original `DM`
1833147403d9SBarry Smith . field     - The field number in dm
1834147403d9SBarry Smith - nullSpace - The nullspace for the given field
18358cda7954SMatthew G. Knepley 
183649762cbcSSatish Balay   Level: intermediate
183749762cbcSSatish Balay 
18381cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetNearNullSpaceConstructor()`, `DMSetNullSpaceConstructor()`, `DMGetNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`,
1839bb7acecfSBarry Smith           `MatNullSpace`
1840147403d9SBarry Smith @*/
1841a4e35b19SJacob Faibussowitsch PetscErrorCode DMSetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1842d71ae5a4SJacob Faibussowitsch {
1843f9d4088aSMatthew G. Knepley   PetscFunctionBegin;
1844f9d4088aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18457a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1846f9d4088aSMatthew G. Knepley   dm->nearnullspaceConstructors[field] = nullsp;
18473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1848f9d4088aSMatthew G. Knepley }
1849f9d4088aSMatthew G. Knepley 
18508cda7954SMatthew G. Knepley /*@C
1851bb7acecfSBarry Smith   DMGetNearNullSpaceConstructor - Return the callback function which constructs the near-nullspace for a given field, defined with `DMAddField()`
18528cda7954SMatthew G. Knepley 
185320f4b53cSBarry Smith   Not Collective; No Fortran Support
18548cda7954SMatthew G. Knepley 
18558cda7954SMatthew G. Knepley   Input Parameters:
1856bb7acecfSBarry Smith + dm    - The `DM`
18578cda7954SMatthew G. Knepley - field - The field number for the nullspace
18588cda7954SMatthew G. Knepley 
18598cda7954SMatthew G. Knepley   Output Parameter:
18608cda7954SMatthew G. Knepley . nullsp - A callback to create the near-nullspace
18618cda7954SMatthew G. Knepley 
186220f4b53cSBarry Smith   Calling sequence of `nullsp`:
1863bb7acecfSBarry Smith + dm        - The present `DM`
1864bb7acecfSBarry Smith . origField - The field number given above, in the original `DM`
1865147403d9SBarry Smith . field     - The field number in dm
1866147403d9SBarry Smith - nullSpace - The nullspace for the given field
18678cda7954SMatthew G. Knepley 
186849762cbcSSatish Balay   Level: intermediate
186949762cbcSSatish Balay 
18701cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMSetNearNullSpaceConstructor()`, `DMSetNullSpaceConstructor()`, `DMGetNullSpaceConstructor()`, `DMCreateSubDM()`,
1871bb7acecfSBarry Smith           `MatNullSpace`, `DMCreateSuperDM()`
1872147403d9SBarry Smith @*/
1873a4e35b19SJacob Faibussowitsch PetscErrorCode DMGetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1874d71ae5a4SJacob Faibussowitsch {
1875f9d4088aSMatthew G. Knepley   PetscFunctionBegin;
1876f9d4088aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18774f572ea9SToby Isaac   PetscAssertPointer(nullsp, 3);
18787a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1879f9d4088aSMatthew G. Knepley   *nullsp = dm->nearnullspaceConstructors[field];
18803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1881f9d4088aSMatthew G. Knepley }
1882f9d4088aSMatthew G. Knepley 
18834f3b5142SJed Brown /*@C
1884bb7acecfSBarry Smith   DMCreateFieldIS - Creates a set of `IS` objects with the global indices of dofs for each field defined with `DMAddField()`
18854d343eeaSMatthew G Knepley 
188620f4b53cSBarry Smith   Not Collective; No Fortran Support
18874d343eeaSMatthew G Knepley 
18884d343eeaSMatthew G Knepley   Input Parameter:
1889bb7acecfSBarry Smith . dm - the `DM` object
18904d343eeaSMatthew G Knepley 
18914d343eeaSMatthew G Knepley   Output Parameters:
189220f4b53cSBarry Smith + numFields  - The number of fields (or `NULL` if not requested)
189320f4b53cSBarry Smith . fieldNames - The number of each field (or `NULL` if not requested)
189420f4b53cSBarry Smith - fields     - The global indices for each field (or `NULL` if not requested)
18954d343eeaSMatthew G Knepley 
18964d343eeaSMatthew G Knepley   Level: intermediate
18974d343eeaSMatthew G Knepley 
1898bb7acecfSBarry Smith   Note:
189973ff1848SBarry Smith   The user is responsible for freeing all requested arrays. In particular, every entry of `fieldNames` should be freed with
190073ff1848SBarry Smith   `PetscFree()`, every entry of `fields` should be destroyed with `ISDestroy()`, and both arrays should be freed with
1901bb7acecfSBarry Smith   `PetscFree()`.
190221c9b008SJed Brown 
190373ff1848SBarry Smith   Developer Note:
1904bb7acecfSBarry Smith   It is not clear why both this function and `DMCreateFieldDecomposition()` exist. Having two seems redundant and confusing. This function should
1905bb7acecfSBarry Smith   likely be removed.
1906bb7acecfSBarry Smith 
19071cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
1908bb7acecfSBarry Smith           `DMCreateFieldDecomposition()`
19094d343eeaSMatthew G Knepley @*/
1910d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1911d71ae5a4SJacob Faibussowitsch {
191237d0c07bSMatthew G Knepley   PetscSection section, sectionGlobal;
19134d343eeaSMatthew G Knepley 
19144d343eeaSMatthew G Knepley   PetscFunctionBegin;
19154d343eeaSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
191669ca1f37SDmitry Karpeev   if (numFields) {
19174f572ea9SToby Isaac     PetscAssertPointer(numFields, 2);
191869ca1f37SDmitry Karpeev     *numFields = 0;
191969ca1f37SDmitry Karpeev   }
192037d0c07bSMatthew G Knepley   if (fieldNames) {
19214f572ea9SToby Isaac     PetscAssertPointer(fieldNames, 3);
19220298fd71SBarry Smith     *fieldNames = NULL;
192369ca1f37SDmitry Karpeev   }
192469ca1f37SDmitry Karpeev   if (fields) {
19254f572ea9SToby Isaac     PetscAssertPointer(fields, 4);
19260298fd71SBarry Smith     *fields = NULL;
192769ca1f37SDmitry Karpeev   }
19289566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
192937d0c07bSMatthew G Knepley   if (section) {
19303a544194SStefano Zampini     PetscInt *fieldSizes, *fieldNc, **fieldIndices;
193137d0c07bSMatthew G Knepley     PetscInt  nF, f, pStart, pEnd, p;
193237d0c07bSMatthew G Knepley 
19339566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
19349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &nF));
19359566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(nF, &fieldSizes, nF, &fieldNc, nF, &fieldIndices));
19369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
193737d0c07bSMatthew G Knepley     for (f = 0; f < nF; ++f) {
193837d0c07bSMatthew G Knepley       fieldSizes[f] = 0;
19399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &fieldNc[f]));
194037d0c07bSMatthew G Knepley     }
194137d0c07bSMatthew G Knepley     for (p = pStart; p < pEnd; ++p) {
194237d0c07bSMatthew G Knepley       PetscInt gdof;
194337d0c07bSMatthew G Knepley 
19449566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
194537d0c07bSMatthew G Knepley       if (gdof > 0) {
194637d0c07bSMatthew G Knepley         for (f = 0; f < nF; ++f) {
19473a544194SStefano Zampini           PetscInt fdof, fcdof, fpdof;
194837d0c07bSMatthew G Knepley 
19499566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
19509566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
19513a544194SStefano Zampini           fpdof = fdof - fcdof;
19523a544194SStefano Zampini           if (fpdof && fpdof != fieldNc[f]) {
19533a544194SStefano Zampini             /* Layout does not admit a pointwise block size */
19543a544194SStefano Zampini             fieldNc[f] = 1;
19553a544194SStefano Zampini           }
19563a544194SStefano Zampini           fieldSizes[f] += fpdof;
195737d0c07bSMatthew G Knepley         }
195837d0c07bSMatthew G Knepley       }
195937d0c07bSMatthew G Knepley     }
196037d0c07bSMatthew G Knepley     for (f = 0; f < nF; ++f) {
19619566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(fieldSizes[f], &fieldIndices[f]));
196237d0c07bSMatthew G Knepley       fieldSizes[f] = 0;
196337d0c07bSMatthew G Knepley     }
196437d0c07bSMatthew G Knepley     for (p = pStart; p < pEnd; ++p) {
196537d0c07bSMatthew G Knepley       PetscInt gdof, goff;
196637d0c07bSMatthew G Knepley 
19679566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
196837d0c07bSMatthew G Knepley       if (gdof > 0) {
19699566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff));
197037d0c07bSMatthew G Knepley         for (f = 0; f < nF; ++f) {
197137d0c07bSMatthew G Knepley           PetscInt fdof, fcdof, fc;
197237d0c07bSMatthew G Knepley 
19739566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
19749566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
1975ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++fieldSizes[f]) fieldIndices[f][fieldSizes[f]] = goff++;
197637d0c07bSMatthew G Knepley         }
197737d0c07bSMatthew G Knepley       }
197837d0c07bSMatthew G Knepley     }
19798865f1eaSKarl Rupp     if (numFields) *numFields = nF;
198037d0c07bSMatthew G Knepley     if (fieldNames) {
19819566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nF, fieldNames));
198237d0c07bSMatthew G Knepley       for (f = 0; f < nF; ++f) {
198337d0c07bSMatthew G Knepley         const char *fieldName;
198437d0c07bSMatthew G Knepley 
19859566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
1986835f2295SStefano Zampini         PetscCall(PetscStrallocpy(fieldName, &(*fieldNames)[f]));
198737d0c07bSMatthew G Knepley       }
198837d0c07bSMatthew G Knepley     }
198937d0c07bSMatthew G Knepley     if (fields) {
19909566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nF, fields));
199137d0c07bSMatthew G Knepley       for (f = 0; f < nF; ++f) {
19923a544194SStefano Zampini         PetscInt bs, in[2], out[2];
19933a544194SStefano Zampini 
19949566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]));
19953a544194SStefano Zampini         in[0] = -fieldNc[f];
19963a544194SStefano Zampini         in[1] = fieldNc[f];
1997462c564dSBarry Smith         PetscCallMPI(MPIU_Allreduce(in, out, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
19983a544194SStefano Zampini         bs = (-out[0] == out[1]) ? out[1] : 1;
19999566063dSJacob Faibussowitsch         PetscCall(ISSetBlockSize((*fields)[f], bs));
200037d0c07bSMatthew G Knepley       }
200137d0c07bSMatthew G Knepley     }
20029566063dSJacob Faibussowitsch     PetscCall(PetscFree3(fieldSizes, fieldNc, fieldIndices));
2003dbbe0bcdSBarry Smith   } else PetscTryTypeMethod(dm, createfieldis, numFields, fieldNames, fields);
20043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20054d343eeaSMatthew G Knepley }
20064d343eeaSMatthew G Knepley 
200716621825SDmitry Karpeev /*@C
2008bb7acecfSBarry Smith   DMCreateFieldDecomposition - Returns a list of `IS` objects defining a decomposition of a problem into subproblems
2009a4e35b19SJacob Faibussowitsch   corresponding to different fields.
2010e7c4fc90SDmitry Karpeev 
201120f4b53cSBarry Smith   Not Collective; No Fortran Support
2012e7c4fc90SDmitry Karpeev 
2013e7c4fc90SDmitry Karpeev   Input Parameter:
2014bb7acecfSBarry Smith . dm - the `DM` object
2015e7c4fc90SDmitry Karpeev 
2016e7c4fc90SDmitry Karpeev   Output Parameters:
201720f4b53cSBarry Smith + len      - The number of fields (or `NULL` if not requested)
201820f4b53cSBarry Smith . namelist - The name for each field (or `NULL` if not requested)
201920f4b53cSBarry Smith . islist   - The global indices for each field (or `NULL` if not requested)
202020f4b53cSBarry Smith - dmlist   - The `DM`s for each field subproblem (or `NULL`, if not requested; if `NULL` is returned, no `DM`s are defined)
2021e7c4fc90SDmitry Karpeev 
2022e7c4fc90SDmitry Karpeev   Level: intermediate
2023e7c4fc90SDmitry Karpeev 
2024a4e35b19SJacob Faibussowitsch   Notes:
2025a4e35b19SJacob Faibussowitsch   Each `IS` contains the global indices of the dofs of the corresponding field, defined by
2026a4e35b19SJacob Faibussowitsch   `DMAddField()`. The optional list of `DM`s define the `DM` for each subproblem.
2027a4e35b19SJacob Faibussowitsch 
2028a4e35b19SJacob Faibussowitsch   The same as `DMCreateFieldIS()` but also returns a `DM` for each field.
2029a4e35b19SJacob Faibussowitsch 
203073ff1848SBarry Smith   The user is responsible for freeing all requested arrays. In particular, every entry of `namelist` should be freed with
203173ff1848SBarry Smith   `PetscFree()`, every entry of `islist` should be destroyed with `ISDestroy()`, every entry of `dmlist` should be destroyed with `DMDestroy()`,
2032bb7acecfSBarry Smith   and all of the arrays should be freed with `PetscFree()`.
2033e7c4fc90SDmitry Karpeev 
203460225df5SJacob Faibussowitsch   Developer Notes:
2035bb7acecfSBarry Smith   It is not clear why this function and `DMCreateFieldIS()` exist. Having two seems redundant and confusing.
2036bb7acecfSBarry Smith 
203773ff1848SBarry Smith   Unlike  `DMRefine()`, `DMCoarsen()`, and `DMCreateDomainDecomposition()` this provides no mechanism to provide hooks that are called after the
203873ff1848SBarry Smith   decomposition is computed.
203973ff1848SBarry Smith 
204073ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMCreateFieldIS()`, `DMCreateSubDM()`, `DMCreateDomainDecomposition()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`
2041e7c4fc90SDmitry Karpeev @*/
2042d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
2043d71ae5a4SJacob Faibussowitsch {
2044e7c4fc90SDmitry Karpeev   PetscFunctionBegin;
2045e7c4fc90SDmitry Karpeev   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20468865f1eaSKarl Rupp   if (len) {
20474f572ea9SToby Isaac     PetscAssertPointer(len, 2);
20488865f1eaSKarl Rupp     *len = 0;
20498865f1eaSKarl Rupp   }
20508865f1eaSKarl Rupp   if (namelist) {
20514f572ea9SToby Isaac     PetscAssertPointer(namelist, 3);
2052ea78f98cSLisandro Dalcin     *namelist = NULL;
20538865f1eaSKarl Rupp   }
20548865f1eaSKarl Rupp   if (islist) {
20554f572ea9SToby Isaac     PetscAssertPointer(islist, 4);
2056ea78f98cSLisandro Dalcin     *islist = NULL;
20578865f1eaSKarl Rupp   }
20588865f1eaSKarl Rupp   if (dmlist) {
20594f572ea9SToby Isaac     PetscAssertPointer(dmlist, 5);
2060ea78f98cSLisandro Dalcin     *dmlist = NULL;
20618865f1eaSKarl Rupp   }
2062f3f0edfdSDmitry Karpeev   /*
2063f3f0edfdSDmitry Karpeev    Is it a good idea to apply the following check across all impls?
2064f3f0edfdSDmitry Karpeev    Perhaps some impls can have a well-defined decomposition before DMSetUp?
2065f3f0edfdSDmitry Karpeev    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
2066f3f0edfdSDmitry Karpeev    */
20677a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
206816621825SDmitry Karpeev   if (!dm->ops->createfielddecomposition) {
2069435a35e8SMatthew G Knepley     PetscSection section;
2070435a35e8SMatthew G Knepley     PetscInt     numFields, f;
2071435a35e8SMatthew G Knepley 
20729566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
20739566063dSJacob Faibussowitsch     if (section) PetscCall(PetscSectionGetNumFields(section, &numFields));
2074435a35e8SMatthew G Knepley     if (section && numFields && dm->ops->createsubdm) {
2075f25d98f1SMatthew G. Knepley       if (len) *len = numFields;
20769566063dSJacob Faibussowitsch       if (namelist) PetscCall(PetscMalloc1(numFields, namelist));
20779566063dSJacob Faibussowitsch       if (islist) PetscCall(PetscMalloc1(numFields, islist));
20789566063dSJacob Faibussowitsch       if (dmlist) PetscCall(PetscMalloc1(numFields, dmlist));
2079435a35e8SMatthew G Knepley       for (f = 0; f < numFields; ++f) {
2080435a35e8SMatthew G Knepley         const char *fieldName;
2081435a35e8SMatthew G Knepley 
20829566063dSJacob Faibussowitsch         PetscCall(DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL));
208303dc3394SMatthew G. Knepley         if (namelist) {
20849566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
2085835f2295SStefano Zampini           PetscCall(PetscStrallocpy(fieldName, &(*namelist)[f]));
2086435a35e8SMatthew G Knepley         }
208703dc3394SMatthew G. Knepley       }
2088435a35e8SMatthew G Knepley     } else {
20899566063dSJacob Faibussowitsch       PetscCall(DMCreateFieldIS(dm, len, namelist, islist));
2090e7c4fc90SDmitry Karpeev       /* By default there are no DMs associated with subproblems. */
20910298fd71SBarry Smith       if (dmlist) *dmlist = NULL;
2092e7c4fc90SDmitry Karpeev     }
2093dbbe0bcdSBarry Smith   } else PetscUseTypeMethod(dm, createfielddecomposition, len, namelist, islist, dmlist);
20943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209516621825SDmitry Karpeev }
209616621825SDmitry Karpeev 
20975d83a8b1SBarry Smith /*@
209820f4b53cSBarry Smith   DMCreateSubDM - Returns an `IS` and `DM` encapsulating a subproblem defined by the fields passed in.
209920f4b53cSBarry Smith   The fields are defined by `DMCreateFieldIS()`.
2100435a35e8SMatthew G Knepley 
2101435a35e8SMatthew G Knepley   Not collective
2102435a35e8SMatthew G Knepley 
2103435a35e8SMatthew G Knepley   Input Parameters:
2104bb7acecfSBarry Smith + dm        - The `DM` object
2105bb7acecfSBarry Smith . numFields - The number of fields to select
21062adcc780SMatthew G. Knepley - fields    - The field numbers of the selected fields
2107435a35e8SMatthew G Knepley 
2108435a35e8SMatthew G Knepley   Output Parameters:
2109b6971eaeSBarry Smith + is    - The global indices for all the degrees of freedom in the new sub `DM`, use `NULL` if not needed
2110b6971eaeSBarry Smith - subdm - The `DM` for the subproblem, use `NULL` if not needed
2111435a35e8SMatthew G Knepley 
211220f4b53cSBarry Smith   Level: intermediate
211320f4b53cSBarry Smith 
2114bb7acecfSBarry Smith   Note:
2115bb7acecfSBarry Smith   You need to call `DMPlexSetMigrationSF()` on the original `DM` if you want the Global-To-Natural map to be automatically constructed
21165d3b26e6SMatthew G. Knepley 
211760225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateFieldIS()`, `DMCreateFieldDecomposition()`, `DMAddField()`, `DMCreateSuperDM()`, `IS`, `DMPlexSetMigrationSF()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
2118435a35e8SMatthew G Knepley @*/
2119d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
2120d71ae5a4SJacob Faibussowitsch {
2121435a35e8SMatthew G Knepley   PetscFunctionBegin;
2122435a35e8SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21234f572ea9SToby Isaac   PetscAssertPointer(fields, 3);
21244f572ea9SToby Isaac   if (is) PetscAssertPointer(is, 4);
21254f572ea9SToby Isaac   if (subdm) PetscAssertPointer(subdm, 5);
2126dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createsubdm, numFields, fields, is, subdm);
21273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2128435a35e8SMatthew G Knepley }
2129435a35e8SMatthew G Knepley 
21302adcc780SMatthew G. Knepley /*@C
2131bb7acecfSBarry Smith   DMCreateSuperDM - Returns an arrays of `IS` and `DM` encapsulating a superproblem defined by multiple `DM`s passed in.
21322adcc780SMatthew G. Knepley 
21332adcc780SMatthew G. Knepley   Not collective
21342adcc780SMatthew G. Knepley 
2135d8d19677SJose E. Roman   Input Parameters:
2136bb7acecfSBarry Smith + dms - The `DM` objects
2137bb7acecfSBarry Smith - n   - The number of `DM`s
21382adcc780SMatthew G. Knepley 
21392adcc780SMatthew G. Knepley   Output Parameters:
2140bb7acecfSBarry Smith + is      - The global indices for each of subproblem within the super `DM`, or NULL
2141bb7acecfSBarry Smith - superdm - The `DM` for the superproblem
21422adcc780SMatthew G. Knepley 
214320f4b53cSBarry Smith   Level: intermediate
214420f4b53cSBarry Smith 
2145bb7acecfSBarry Smith   Note:
2146bb7acecfSBarry Smith   You need to call `DMPlexSetMigrationSF()` on the original `DM` if you want the Global-To-Natural map to be automatically constructed
21475d3b26e6SMatthew G. Knepley 
214873ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateSubDM()`, `DMPlexSetMigrationSF()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`, `DMCreateDomainDecomposition()`
21492adcc780SMatthew G. Knepley @*/
21505d83a8b1SBarry Smith PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt n, IS *is[], DM *superdm)
2151d71ae5a4SJacob Faibussowitsch {
21522adcc780SMatthew G. Knepley   PetscInt i;
21532adcc780SMatthew G. Knepley 
21542adcc780SMatthew G. Knepley   PetscFunctionBegin;
21554f572ea9SToby Isaac   PetscAssertPointer(dms, 1);
2156ad540459SPierre Jolivet   for (i = 0; i < n; ++i) PetscValidHeaderSpecific(dms[i], DM_CLASSID, 1);
21574f572ea9SToby Isaac   if (is) PetscAssertPointer(is, 3);
21584f572ea9SToby Isaac   PetscAssertPointer(superdm, 4);
2159bb7acecfSBarry Smith   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %" PetscInt_FMT, n);
2160bb7acecfSBarry Smith   if (n) {
2161b9d85ea2SLisandro Dalcin     DM dm = dms[0];
216200045ab3SPierre Jolivet     PetscCheck(dm->ops->createsuperdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No method createsuperdm for DM of type %s", ((PetscObject)dm)->type_name);
2163dbbe0bcdSBarry Smith     PetscCall((*dm->ops->createsuperdm)(dms, n, is, superdm));
21642adcc780SMatthew G. Knepley   }
21653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21662adcc780SMatthew G. Knepley }
21672adcc780SMatthew G. Knepley 
216816621825SDmitry Karpeev /*@C
2169a4e35b19SJacob Faibussowitsch   DMCreateDomainDecomposition - Returns lists of `IS` objects defining a decomposition of a
2170a4e35b19SJacob Faibussowitsch   problem into subproblems corresponding to restrictions to pairs of nested subdomains.
217116621825SDmitry Karpeev 
217220f4b53cSBarry Smith   Not Collective
217316621825SDmitry Karpeev 
217416621825SDmitry Karpeev   Input Parameter:
2175bb7acecfSBarry Smith . dm - the `DM` object
217616621825SDmitry Karpeev 
217716621825SDmitry Karpeev   Output Parameters:
217820f4b53cSBarry Smith + n           - The number of subproblems in the domain decomposition (or `NULL` if not requested)
217920f4b53cSBarry Smith . namelist    - The name for each subdomain (or `NULL` if not requested)
218073ff1848SBarry Smith . innerislist - The global indices for each inner subdomain (or `NULL`, if not requested)
218173ff1848SBarry Smith . outerislist - The global indices for each outer subdomain (or `NULL`, if not requested)
218273ff1848SBarry Smith - dmlist      - The `DM`s for each subdomain subproblem (or `NULL`, if not requested; if `NULL` is returned, no `DM`s are defined)
218316621825SDmitry Karpeev 
218416621825SDmitry Karpeev   Level: intermediate
218516621825SDmitry Karpeev 
218673ff1848SBarry Smith   Notes:
2187a4e35b19SJacob Faibussowitsch   Each `IS` contains the global indices of the dofs of the corresponding subdomains with in the
2188a4e35b19SJacob Faibussowitsch   dofs of the original `DM`. The inner subdomains conceptually define a nonoverlapping
2189a4e35b19SJacob Faibussowitsch   covering, while outer subdomains can overlap.
2190a4e35b19SJacob Faibussowitsch 
2191a4e35b19SJacob Faibussowitsch   The optional list of `DM`s define a `DM` for each subproblem.
2192a4e35b19SJacob Faibussowitsch 
219373ff1848SBarry Smith   The user is responsible for freeing all requested arrays. In particular, every entry of `namelist` should be freed with
219473ff1848SBarry Smith   `PetscFree()`, every entry of `innerislist` and `outerislist` should be destroyed with `ISDestroy()`, every entry of `dmlist` should be destroyed with `DMDestroy()`,
2195bb7acecfSBarry Smith   and all of the arrays should be freed with `PetscFree()`.
219616621825SDmitry Karpeev 
2197a4e35b19SJacob Faibussowitsch   Developer Notes:
219820f4b53cSBarry Smith   The `dmlist` is for the inner subdomains or the outer subdomains or all subdomains?
2199bb7acecfSBarry Smith 
220073ff1848SBarry Smith   The names are inconsistent, the hooks use `DMSubDomainHook` which is nothing like `DMCreateDomainDecomposition()` while `DMRefineHook` is used for `DMRefine()`.
220173ff1848SBarry Smith 
220273ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateFieldDecomposition()`, `DMDestroy()`, `DMCreateDomainDecompositionScatters()`, `DMView()`, `DMCreateInterpolation()`,
220373ff1848SBarry Smith           `DMSubDomainHookAdd()`, `DMSubDomainHookRemove()`,`DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`
220416621825SDmitry Karpeev @*/
2205d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *n, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
2206d71ae5a4SJacob Faibussowitsch {
2207be081cd6SPeter Brune   DMSubDomainHookLink link;
2208be081cd6SPeter Brune   PetscInt            i, l;
220916621825SDmitry Karpeev 
221016621825SDmitry Karpeev   PetscFunctionBegin;
221116621825SDmitry Karpeev   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22129371c9d4SSatish Balay   if (n) {
22134f572ea9SToby Isaac     PetscAssertPointer(n, 2);
22149371c9d4SSatish Balay     *n = 0;
22159371c9d4SSatish Balay   }
22169371c9d4SSatish Balay   if (namelist) {
22174f572ea9SToby Isaac     PetscAssertPointer(namelist, 3);
22189371c9d4SSatish Balay     *namelist = NULL;
22199371c9d4SSatish Balay   }
22209371c9d4SSatish Balay   if (innerislist) {
22214f572ea9SToby Isaac     PetscAssertPointer(innerislist, 4);
22229371c9d4SSatish Balay     *innerislist = NULL;
22239371c9d4SSatish Balay   }
22249371c9d4SSatish Balay   if (outerislist) {
22254f572ea9SToby Isaac     PetscAssertPointer(outerislist, 5);
22269371c9d4SSatish Balay     *outerislist = NULL;
22279371c9d4SSatish Balay   }
22289371c9d4SSatish Balay   if (dmlist) {
22294f572ea9SToby Isaac     PetscAssertPointer(dmlist, 6);
22309371c9d4SSatish Balay     *dmlist = NULL;
22319371c9d4SSatish Balay   }
2232f3f0edfdSDmitry Karpeev   /*
2233f3f0edfdSDmitry Karpeev    Is it a good idea to apply the following check across all impls?
2234f3f0edfdSDmitry Karpeev    Perhaps some impls can have a well-defined decomposition before DMSetUp?
2235f3f0edfdSDmitry Karpeev    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
2236f3f0edfdSDmitry Karpeev    */
22377a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
223816621825SDmitry Karpeev   if (dm->ops->createdomaindecomposition) {
2239dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createdomaindecomposition, &l, namelist, innerislist, outerislist, dmlist);
224014a18fd3SPeter Brune     /* copy subdomain hooks and context over to the subdomain DMs */
2241f891f5b9SPatrick Sanan     if (dmlist && *dmlist) {
2242be081cd6SPeter Brune       for (i = 0; i < l; i++) {
2243be081cd6SPeter Brune         for (link = dm->subdomainhook; link; link = link->next) {
22449566063dSJacob Faibussowitsch           if (link->ddhook) PetscCall((*link->ddhook)(dm, (*dmlist)[i], link->ctx));
2245be081cd6SPeter Brune         }
2246648262bbSPatrick Sanan         if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
2247e7c4fc90SDmitry Karpeev       }
224814a18fd3SPeter Brune     }
2249bb7acecfSBarry Smith     if (n) *n = l;
225014a18fd3SPeter Brune   }
22513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2252e30e807fSPeter Brune }
2253e30e807fSPeter Brune 
2254e30e807fSPeter Brune /*@C
225573ff1848SBarry Smith   DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector for subdomains created with
225673ff1848SBarry Smith   `DMCreateDomainDecomposition()`
2257e30e807fSPeter Brune 
225820f4b53cSBarry Smith   Not Collective
2259e30e807fSPeter Brune 
2260e30e807fSPeter Brune   Input Parameters:
2261bb7acecfSBarry Smith + dm     - the `DM` object
226273ff1848SBarry Smith . n      - the number of subdomains
2263e30e807fSPeter Brune - subdms - the local subdomains
2264e30e807fSPeter Brune 
2265e30e807fSPeter Brune   Output Parameters:
22666b867d5aSJose E. Roman + iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
2267e30e807fSPeter Brune . oscat - scatter from global vector to overlapping global vector entries on subdomain
2268e30e807fSPeter Brune - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
2269e30e807fSPeter Brune 
227020f4b53cSBarry Smith   Level: developer
227120f4b53cSBarry Smith 
2272bb7acecfSBarry Smith   Note:
2273bb7acecfSBarry Smith   This is an alternative to the iis and ois arguments in `DMCreateDomainDecomposition()` that allow for the solution
2274e30e807fSPeter Brune   of general nonlinear problems with overlapping subdomain methods.  While merely having index sets that enable subsets
2275e30e807fSPeter Brune   of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
2276e30e807fSPeter Brune   solution and residual data.
2277e30e807fSPeter Brune 
227873ff1848SBarry Smith   Developer Note:
2279a4e35b19SJacob Faibussowitsch   Can the subdms input be anything or are they exactly the `DM` obtained from
2280a4e35b19SJacob Faibussowitsch   `DMCreateDomainDecomposition()`?
2281bb7acecfSBarry Smith 
22821cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateDomainDecomposition()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
2283e30e807fSPeter Brune @*/
22845d83a8b1SBarry Smith PetscErrorCode DMCreateDomainDecompositionScatters(DM dm, PetscInt n, DM *subdms, VecScatter *iscat[], VecScatter *oscat[], VecScatter *gscat[])
2285d71ae5a4SJacob Faibussowitsch {
2286e30e807fSPeter Brune   PetscFunctionBegin;
2287e30e807fSPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22884f572ea9SToby Isaac   PetscAssertPointer(subdms, 3);
2289dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createddscatters, n, subdms, iscat, oscat, gscat);
22903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2291e7c4fc90SDmitry Karpeev }
2292e7c4fc90SDmitry Karpeev 
229347c6ae99SBarry Smith /*@
2294bb7acecfSBarry Smith   DMRefine - Refines a `DM` object using a standard nonadaptive refinement of the underlying mesh
229547c6ae99SBarry Smith 
229620f4b53cSBarry Smith   Collective
229747c6ae99SBarry Smith 
2298d8d19677SJose E. Roman   Input Parameters:
2299bb7acecfSBarry Smith + dm   - the `DM` object
2300bb7acecfSBarry Smith - comm - the communicator to contain the new `DM` object (or `MPI_COMM_NULL`)
230147c6ae99SBarry Smith 
230247c6ae99SBarry Smith   Output Parameter:
230320f4b53cSBarry Smith . dmf - the refined `DM`, or `NULL`
2304ae0a1c52SMatthew G Knepley 
230520f4b53cSBarry Smith   Options Database Key:
2306412e9a14SMatthew G. Knepley . -dm_plex_cell_refiner <strategy> - chooses the refinement strategy, e.g. regular, tohex
2307412e9a14SMatthew G. Knepley 
230847c6ae99SBarry Smith   Level: developer
230947c6ae99SBarry Smith 
231020f4b53cSBarry Smith   Note:
231120f4b53cSBarry Smith   If no refinement was done, the return value is `NULL`
231220f4b53cSBarry Smith 
231373ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateDomainDecomposition()`,
231473ff1848SBarry Smith           `DMRefineHookAdd()`, `DMRefineHookRemove()`
231547c6ae99SBarry Smith @*/
2316d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefine(DM dm, MPI_Comm comm, DM *dmf)
2317d71ae5a4SJacob Faibussowitsch {
2318c833c3b5SJed Brown   DMRefineHookLink link;
231947c6ae99SBarry Smith 
232047c6ae99SBarry Smith   PetscFunctionBegin;
2321732e2eb9SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Refine, dm, 0, 0, 0));
2323dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, refine, comm, dmf);
23244057135bSMatthew G Knepley   if (*dmf) {
232543842a1eSJed Brown     (*dmf)->ops->creatematrix = dm->ops->creatematrix;
23268865f1eaSKarl Rupp 
23279566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmf));
23288865f1eaSKarl Rupp 
2329644e2e5bSBarry Smith     (*dmf)->ctx       = dm->ctx;
23300598a293SJed Brown     (*dmf)->leveldown = dm->leveldown;
2331656b349aSBarry Smith     (*dmf)->levelup   = dm->levelup + 1;
23328865f1eaSKarl Rupp 
23339566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmf, dm->mattype));
2334c833c3b5SJed Brown     for (link = dm->refinehook; link; link = link->next) {
23351baa6e33SBarry Smith       if (link->refinehook) PetscCall((*link->refinehook)(dm, *dmf, link->ctx));
2336c833c3b5SJed Brown     }
2337c833c3b5SJed Brown   }
23389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Refine, dm, 0, 0, 0));
23393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2340c833c3b5SJed Brown }
2341c833c3b5SJed Brown 
2342bb9467b5SJed Brown /*@C
2343c833c3b5SJed Brown   DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
2344c833c3b5SJed Brown 
234520f4b53cSBarry Smith   Logically Collective; No Fortran Support
2346c833c3b5SJed Brown 
23474165533cSJose E. Roman   Input Parameters:
2348bb7acecfSBarry Smith + coarse     - `DM` on which to run a hook when interpolating to a finer level
2349bb7acecfSBarry Smith . refinehook - function to run when setting up the finer level
2350f826b5fcSPierre Jolivet . interphook - function to run to update data on finer levels (once per `SNESSolve()`)
235120f4b53cSBarry Smith - ctx        - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2352c833c3b5SJed Brown 
235320f4b53cSBarry Smith   Calling sequence of `refinehook`:
2354bb7acecfSBarry Smith + coarse - coarse level `DM`
2355bb7acecfSBarry Smith . fine   - fine level `DM` to interpolate problem to
2356c833c3b5SJed Brown - ctx    - optional user-defined function context
2357c833c3b5SJed Brown 
235820f4b53cSBarry Smith   Calling sequence of `interphook`:
2359bb7acecfSBarry Smith + coarse - coarse level `DM`
2360c833c3b5SJed Brown . interp - matrix interpolating a coarse-level solution to the finer grid
2361bb7acecfSBarry Smith . fine   - fine level `DM` to update
2362c833c3b5SJed Brown - ctx    - optional user-defined function context
2363c833c3b5SJed Brown 
2364c833c3b5SJed Brown   Level: advanced
2365c833c3b5SJed Brown 
2366c833c3b5SJed Brown   Notes:
2367bb7acecfSBarry Smith   This function is only needed if auxiliary data that is attached to the `DM`s via, for example, `PetscObjectCompose()`, needs to be
2368bb7acecfSBarry Smith   passed to fine grids while grid sequencing.
2369bb7acecfSBarry Smith 
2370bb7acecfSBarry Smith   The actual interpolation is done when `DMInterpolate()` is called.
2371c833c3b5SJed Brown 
2372c833c3b5SJed Brown   If this function is called multiple times, the hooks will be run in the order they are added.
2373c833c3b5SJed Brown 
23741cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `DMInterpolate()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2375c833c3b5SJed Brown @*/
2376a4e35b19SJacob 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)
2377d71ae5a4SJacob Faibussowitsch {
2378c833c3b5SJed Brown   DMRefineHookLink link, *p;
2379c833c3b5SJed Brown 
2380c833c3b5SJed Brown   PetscFunctionBegin;
2381c833c3b5SJed Brown   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
23823d8e3701SJed Brown   for (p = &coarse->refinehook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
23833ba16761SJacob Faibussowitsch     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
23843d8e3701SJed Brown   }
23859566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2386c833c3b5SJed Brown   link->refinehook = refinehook;
2387c833c3b5SJed Brown   link->interphook = interphook;
2388c833c3b5SJed Brown   link->ctx        = ctx;
23890298fd71SBarry Smith   link->next       = NULL;
2390c833c3b5SJed Brown   *p               = link;
23913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2392c833c3b5SJed Brown }
2393c833c3b5SJed Brown 
23943d8e3701SJed Brown /*@C
2395bb7acecfSBarry Smith   DMRefineHookRemove - remove a callback from the list of hooks, that have been set with `DMRefineHookAdd()`, to be run when interpolating
2396bb7acecfSBarry Smith   a nonlinear problem to a finer grid
23973d8e3701SJed Brown 
239820f4b53cSBarry Smith   Logically Collective; No Fortran Support
23993d8e3701SJed Brown 
24004165533cSJose E. Roman   Input Parameters:
2401bb7acecfSBarry Smith + coarse     - the `DM` on which to run a hook when restricting to a coarser level
2402bb7acecfSBarry Smith . refinehook - function to run when setting up a finer level
2403bb7acecfSBarry Smith . interphook - function to run to update data on finer levels
240420f4b53cSBarry Smith - ctx        - [optional] user-defined context for provide data for the hooks (may be `NULL`)
24053d8e3701SJed Brown 
24063d8e3701SJed Brown   Level: advanced
24073d8e3701SJed Brown 
2408bb7acecfSBarry Smith   Note:
24093d8e3701SJed Brown   This function does nothing if the hook is not in the list.
24103d8e3701SJed Brown 
24111cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefineHookAdd()`, `DMCoarsenHookRemove()`, `DMInterpolate()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
24123d8e3701SJed Brown @*/
2413d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHookRemove(DM coarse, PetscErrorCode (*refinehook)(DM, DM, void *), PetscErrorCode (*interphook)(DM, Mat, DM, void *), void *ctx)
2414d71ae5a4SJacob Faibussowitsch {
24153d8e3701SJed Brown   DMRefineHookLink link, *p;
24163d8e3701SJed Brown 
24173d8e3701SJed Brown   PetscFunctionBegin;
24183d8e3701SJed Brown   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
24193d8e3701SJed Brown   for (p = &coarse->refinehook; *p; p = &(*p)->next) { /* Search the list of current hooks */
24203d8e3701SJed Brown     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
24213d8e3701SJed Brown       link = *p;
24223d8e3701SJed Brown       *p   = link->next;
24239566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
24243d8e3701SJed Brown       break;
24253d8e3701SJed Brown     }
24263d8e3701SJed Brown   }
24273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24283d8e3701SJed Brown }
24293d8e3701SJed Brown 
2430c833c3b5SJed Brown /*@
2431bb7acecfSBarry Smith   DMInterpolate - interpolates user-defined problem data attached to a `DM` to a finer `DM` by running hooks registered by `DMRefineHookAdd()`
2432c833c3b5SJed Brown 
2433c833c3b5SJed Brown   Collective if any hooks are
2434c833c3b5SJed Brown 
24354165533cSJose E. Roman   Input Parameters:
2436bb7acecfSBarry Smith + coarse - coarser `DM` to use as a base
2437bb7acecfSBarry Smith . interp - interpolation matrix, apply using `MatInterpolate()`
2438bb7acecfSBarry Smith - fine   - finer `DM` to update
2439c833c3b5SJed Brown 
2440c833c3b5SJed Brown   Level: developer
2441c833c3b5SJed Brown 
244273ff1848SBarry Smith   Developer Note:
2443bb7acecfSBarry Smith   This routine is called `DMInterpolate()` while the hook is called `DMRefineHookAdd()`. It would be better to have an
2444bb7acecfSBarry Smith   an API with consistent terminology.
2445bb7acecfSBarry Smith 
24461cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefineHookAdd()`, `MatInterpolate()`
2447c833c3b5SJed Brown @*/
2448d71ae5a4SJacob Faibussowitsch PetscErrorCode DMInterpolate(DM coarse, Mat interp, DM fine)
2449d71ae5a4SJacob Faibussowitsch {
2450c833c3b5SJed Brown   DMRefineHookLink link;
2451c833c3b5SJed Brown 
2452c833c3b5SJed Brown   PetscFunctionBegin;
2453c833c3b5SJed Brown   for (link = fine->refinehook; link; link = link->next) {
24541baa6e33SBarry Smith     if (link->interphook) PetscCall((*link->interphook)(coarse, interp, fine, link->ctx));
24554057135bSMatthew G Knepley   }
24563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
245747c6ae99SBarry Smith }
245847c6ae99SBarry Smith 
2459eb3f98d2SBarry Smith /*@
24601f3379b2SToby Isaac   DMInterpolateSolution - Interpolates a solution from a coarse mesh to a fine mesh.
24611f3379b2SToby Isaac 
246220f4b53cSBarry Smith   Collective
24631f3379b2SToby Isaac 
24644165533cSJose E. Roman   Input Parameters:
2465bb7acecfSBarry Smith + coarse    - coarse `DM`
2466bb7acecfSBarry Smith . fine      - fine `DM`
2467bb7acecfSBarry Smith . interp    - (optional) the matrix computed by `DMCreateInterpolation()`.  Implementations may not need this, but if it
2468bb7acecfSBarry Smith             is available it can avoid some recomputation.  If it is provided, `MatInterpolate()` will be used if
2469bb7acecfSBarry Smith             the coarse `DM` does not have a specialized implementation.
24701f3379b2SToby Isaac - coarseSol - solution on the coarse mesh
24711f3379b2SToby Isaac 
24724165533cSJose E. Roman   Output Parameter:
24731f3379b2SToby Isaac . fineSol - the interpolation of coarseSol to the fine mesh
24741f3379b2SToby Isaac 
24751f3379b2SToby Isaac   Level: developer
24761f3379b2SToby Isaac 
2477bb7acecfSBarry Smith   Note:
2478bb7acecfSBarry Smith   This function exists because the interpolation of a solution vector between meshes is not always a linear
24791f3379b2SToby Isaac   map.  For example, if a boundary value problem has an inhomogeneous Dirichlet boundary condition that is compressed
24801f3379b2SToby Isaac   out of the solution vector.  Or if interpolation is inherently a nonlinear operation, such as a method using
24811f3379b2SToby Isaac   slope-limiting reconstruction.
24821f3379b2SToby Isaac 
248373ff1848SBarry Smith   Developer Note:
2484bb7acecfSBarry Smith   This doesn't just interpolate "solutions" so its API name is questionable.
2485bb7acecfSBarry Smith 
24861cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMInterpolate()`, `DMCreateInterpolation()`
24871f3379b2SToby Isaac @*/
2488d71ae5a4SJacob Faibussowitsch PetscErrorCode DMInterpolateSolution(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
2489d71ae5a4SJacob Faibussowitsch {
24901f3379b2SToby Isaac   PetscErrorCode (*interpsol)(DM, DM, Mat, Vec, Vec) = NULL;
24911f3379b2SToby Isaac 
24921f3379b2SToby Isaac   PetscFunctionBegin;
24931f3379b2SToby Isaac   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
24941f3379b2SToby Isaac   if (interp) PetscValidHeaderSpecific(interp, MAT_CLASSID, 3);
24951f3379b2SToby Isaac   PetscValidHeaderSpecific(coarseSol, VEC_CLASSID, 4);
24961f3379b2SToby Isaac   PetscValidHeaderSpecific(fineSol, VEC_CLASSID, 5);
24971f3379b2SToby Isaac 
24989566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)coarse, "DMInterpolateSolution_C", &interpsol));
24991f3379b2SToby Isaac   if (interpsol) {
25009566063dSJacob Faibussowitsch     PetscCall((*interpsol)(coarse, fine, interp, coarseSol, fineSol));
25011f3379b2SToby Isaac   } else if (interp) {
25029566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(interp, coarseSol, fineSol));
250398921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)coarse), PETSC_ERR_SUP, "DM %s does not implement DMInterpolateSolution()", ((PetscObject)coarse)->type_name);
25043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25051f3379b2SToby Isaac }
25061f3379b2SToby Isaac 
25071f3379b2SToby Isaac /*@
2508bb7acecfSBarry Smith   DMGetRefineLevel - Gets the number of refinements that have generated this `DM` from some initial `DM`.
2509eb3f98d2SBarry Smith 
2510eb3f98d2SBarry Smith   Not Collective
2511eb3f98d2SBarry Smith 
2512eb3f98d2SBarry Smith   Input Parameter:
2513bb7acecfSBarry Smith . dm - the `DM` object
2514eb3f98d2SBarry Smith 
2515eb3f98d2SBarry Smith   Output Parameter:
2516eb3f98d2SBarry Smith . level - number of refinements
2517eb3f98d2SBarry Smith 
2518eb3f98d2SBarry Smith   Level: developer
2519eb3f98d2SBarry Smith 
2520bb7acecfSBarry Smith   Note:
2521bb7acecfSBarry Smith   This can be used, by example, to set the number of coarser levels associated with this `DM` for a multigrid solver.
2522bb7acecfSBarry Smith 
25231cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
2524eb3f98d2SBarry Smith @*/
2525d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRefineLevel(DM dm, PetscInt *level)
2526d71ae5a4SJacob Faibussowitsch {
2527eb3f98d2SBarry Smith   PetscFunctionBegin;
2528eb3f98d2SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2529eb3f98d2SBarry Smith   *level = dm->levelup;
25303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2531eb3f98d2SBarry Smith }
2532eb3f98d2SBarry Smith 
2533fef3a512SBarry Smith /*@
2534bb7acecfSBarry Smith   DMSetRefineLevel - Sets the number of refinements that have generated this `DM`.
2535fef3a512SBarry Smith 
2536fef3a512SBarry Smith   Not Collective
2537fef3a512SBarry Smith 
2538d8d19677SJose E. Roman   Input Parameters:
2539bb7acecfSBarry Smith + dm    - the `DM` object
2540fef3a512SBarry Smith - level - number of refinements
2541fef3a512SBarry Smith 
2542fef3a512SBarry Smith   Level: advanced
2543fef3a512SBarry Smith 
254495452b02SPatrick Sanan   Notes:
2545bb7acecfSBarry Smith   This value is used by `PCMG` to determine how many multigrid levels to use
2546fef3a512SBarry Smith 
2547bb7acecfSBarry Smith   The values are usually set automatically by the process that is causing the refinements of an initial `DM` by calling this routine.
2548bb7acecfSBarry Smith 
25491cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRefineLevel()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
2550fef3a512SBarry Smith @*/
2551d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRefineLevel(DM dm, PetscInt level)
2552d71ae5a4SJacob Faibussowitsch {
2553fef3a512SBarry Smith   PetscFunctionBegin;
2554fef3a512SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2555fef3a512SBarry Smith   dm->levelup = level;
25563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2557fef3a512SBarry Smith }
2558fef3a512SBarry Smith 
2559d410b0cfSMatthew G. Knepley /*@
2560bb7acecfSBarry Smith   DMExtrude - Extrude a `DM` object from a surface
2561d410b0cfSMatthew G. Knepley 
256220f4b53cSBarry Smith   Collective
2563d410b0cfSMatthew G. Knepley 
2564f1a722f8SMatthew G. Knepley   Input Parameters:
2565bb7acecfSBarry Smith + dm     - the `DM` object
2566d410b0cfSMatthew G. Knepley - layers - the number of extruded cell layers
2567d410b0cfSMatthew G. Knepley 
2568d410b0cfSMatthew G. Knepley   Output Parameter:
256920f4b53cSBarry Smith . dme - the extruded `DM`, or `NULL`
2570d410b0cfSMatthew G. Knepley 
2571d410b0cfSMatthew G. Knepley   Level: developer
2572d410b0cfSMatthew G. Knepley 
257320f4b53cSBarry Smith   Note:
257420f4b53cSBarry Smith   If no extrusion was done, the return value is `NULL`
257520f4b53cSBarry Smith 
25761cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`
2577d410b0cfSMatthew G. Knepley @*/
2578d71ae5a4SJacob Faibussowitsch PetscErrorCode DMExtrude(DM dm, PetscInt layers, DM *dme)
2579d71ae5a4SJacob Faibussowitsch {
2580d410b0cfSMatthew G. Knepley   PetscFunctionBegin;
2581d410b0cfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2582dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, extrude, layers, dme);
2583d410b0cfSMatthew G. Knepley   if (*dme) {
2584d410b0cfSMatthew G. Knepley     (*dme)->ops->creatematrix = dm->ops->creatematrix;
25859566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dme));
2586d410b0cfSMatthew G. Knepley     (*dme)->ctx = dm->ctx;
25879566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dme, dm->mattype));
2588d410b0cfSMatthew G. Knepley   }
25893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2590d410b0cfSMatthew G. Knepley }
2591d410b0cfSMatthew G. Knepley 
2592d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasisTransformDM_Internal(DM dm, DM *tdm)
2593d71ae5a4SJacob Faibussowitsch {
2594ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2595ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25964f572ea9SToby Isaac   PetscAssertPointer(tdm, 2);
2597ca3d3a14SMatthew G. Knepley   *tdm = dm->transformDM;
25983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2599ca3d3a14SMatthew G. Knepley }
2600ca3d3a14SMatthew G. Knepley 
2601d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasisTransformVec_Internal(DM dm, Vec *tv)
2602d71ae5a4SJacob Faibussowitsch {
2603ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2604ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26054f572ea9SToby Isaac   PetscAssertPointer(tv, 2);
2606ca3d3a14SMatthew G. Knepley   *tv = dm->transform;
26073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2608ca3d3a14SMatthew G. Knepley }
2609ca3d3a14SMatthew G. Knepley 
2610ca3d3a14SMatthew G. Knepley /*@
2611bb7acecfSBarry Smith   DMHasBasisTransform - Whether the `DM` employs a basis transformation from functions in global vectors to functions in local vectors
2612ca3d3a14SMatthew G. Knepley 
2613ca3d3a14SMatthew G. Knepley   Input Parameter:
261420f4b53cSBarry Smith . dm - The `DM`
2615ca3d3a14SMatthew G. Knepley 
2616ca3d3a14SMatthew G. Knepley   Output Parameter:
261720f4b53cSBarry Smith . flg - `PETSC_TRUE` if a basis transformation should be done
2618ca3d3a14SMatthew G. Knepley 
2619ca3d3a14SMatthew G. Knepley   Level: developer
2620ca3d3a14SMatthew G. Knepley 
26211cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPlexGlobalToLocalBasis()`, `DMPlexLocalToGlobalBasis()`, `DMPlexCreateBasisRotation()`
2622ca3d3a14SMatthew G. Knepley @*/
2623d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasBasisTransform(DM dm, PetscBool *flg)
2624d71ae5a4SJacob Faibussowitsch {
2625ca3d3a14SMatthew G. Knepley   Vec tv;
2626ca3d3a14SMatthew G. Knepley 
2627ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2628ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26294f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
26309566063dSJacob Faibussowitsch   PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
2631ca3d3a14SMatthew G. Knepley   *flg = tv ? PETSC_TRUE : PETSC_FALSE;
26323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2633ca3d3a14SMatthew G. Knepley }
2634ca3d3a14SMatthew G. Knepley 
2635d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConstructBasisTransform_Internal(DM dm)
2636d71ae5a4SJacob Faibussowitsch {
2637ca3d3a14SMatthew G. Knepley   PetscSection s, ts;
2638ca3d3a14SMatthew G. Knepley   PetscScalar *ta;
2639ca3d3a14SMatthew G. Knepley   PetscInt     cdim, pStart, pEnd, p, Nf, f, Nc, dof;
2640ca3d3a14SMatthew G. Knepley 
2641ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
26429566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
26439566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
26449566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
26459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
26469566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dm->transformDM));
26479566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm->transformDM, &ts));
26489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(ts, Nf));
26499566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(ts, pStart, pEnd));
2650ca3d3a14SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
26519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
2652ca3d3a14SMatthew G. Knepley     /* We could start to label fields by their transformation properties */
2653ca3d3a14SMatthew G. Knepley     if (Nc != cdim) continue;
2654ca3d3a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
26559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, f, &dof));
2656ca3d3a14SMatthew G. Knepley       if (!dof) continue;
26579566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(ts, p, f, PetscSqr(cdim)));
26589566063dSJacob Faibussowitsch       PetscCall(PetscSectionAddDof(ts, p, PetscSqr(cdim)));
2659ca3d3a14SMatthew G. Knepley     }
2660ca3d3a14SMatthew G. Knepley   }
26619566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(ts));
26629566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm->transformDM, &dm->transform));
26639566063dSJacob Faibussowitsch   PetscCall(VecGetArray(dm->transform, &ta));
2664ca3d3a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
2665ca3d3a14SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
26669566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(ts, p, f, &dof));
2667ca3d3a14SMatthew G. Knepley       if (dof) {
2668ca3d3a14SMatthew G. Knepley         PetscReal          x[3] = {0.0, 0.0, 0.0};
2669ca3d3a14SMatthew G. Knepley         PetscScalar       *tva;
2670ca3d3a14SMatthew G. Knepley         const PetscScalar *A;
2671ca3d3a14SMatthew G. Knepley 
2672ca3d3a14SMatthew G. Knepley         /* TODO Get quadrature point for this dual basis vector for coordinate */
26739566063dSJacob Faibussowitsch         PetscCall((*dm->transformGetMatrix)(dm, x, PETSC_TRUE, &A, dm->transformCtx));
26749566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalFieldRef(dm->transformDM, p, f, ta, (void *)&tva));
26759566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(tva, A, PetscSqr(cdim)));
2676ca3d3a14SMatthew G. Knepley       }
2677ca3d3a14SMatthew G. Knepley     }
2678ca3d3a14SMatthew G. Knepley   }
26799566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(dm->transform, &ta));
26803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2681ca3d3a14SMatthew G. Knepley }
2682ca3d3a14SMatthew G. Knepley 
2683d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyTransform(DM dm, DM newdm)
2684d71ae5a4SJacob Faibussowitsch {
2685ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2686ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2687ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(newdm, DM_CLASSID, 2);
2688ca3d3a14SMatthew G. Knepley   newdm->transformCtx       = dm->transformCtx;
2689ca3d3a14SMatthew G. Knepley   newdm->transformSetUp     = dm->transformSetUp;
2690ca3d3a14SMatthew G. Knepley   newdm->transformDestroy   = NULL;
2691ca3d3a14SMatthew G. Knepley   newdm->transformGetMatrix = dm->transformGetMatrix;
26929566063dSJacob Faibussowitsch   if (newdm->transformSetUp) PetscCall(DMConstructBasisTransform_Internal(newdm));
26933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2694ca3d3a14SMatthew G. Knepley }
2695ca3d3a14SMatthew G. Knepley 
2696bb9467b5SJed Brown /*@C
2697bb7acecfSBarry Smith   DMGlobalToLocalHookAdd - adds a callback to be run when `DMGlobalToLocal()` is called
2698baf369e7SPeter Brune 
269920f4b53cSBarry Smith   Logically Collective
2700baf369e7SPeter Brune 
27014165533cSJose E. Roman   Input Parameters:
2702bb7acecfSBarry Smith + dm        - the `DM`
2703bb7acecfSBarry Smith . beginhook - function to run at the beginning of `DMGlobalToLocalBegin()`
2704bb7acecfSBarry Smith . endhook   - function to run after `DMGlobalToLocalEnd()` has completed
270520f4b53cSBarry Smith - ctx       - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2706baf369e7SPeter Brune 
270720f4b53cSBarry Smith   Calling sequence of `beginhook`:
2708a4e35b19SJacob Faibussowitsch + dm   - global `DM`
2709baf369e7SPeter Brune . g    - global vector
2710baf369e7SPeter Brune . mode - mode
2711baf369e7SPeter Brune . l    - local vector
2712baf369e7SPeter Brune - ctx  - optional user-defined function context
2713baf369e7SPeter Brune 
271420f4b53cSBarry Smith   Calling sequence of `endhook`:
2715a4e35b19SJacob Faibussowitsch + dm   - global `DM`
2716a4e35b19SJacob Faibussowitsch . g    - global vector
2717a4e35b19SJacob Faibussowitsch . mode - mode
2718a4e35b19SJacob Faibussowitsch . l    - local vector
2719baf369e7SPeter Brune - ctx  - optional user-defined function context
2720baf369e7SPeter Brune 
2721baf369e7SPeter Brune   Level: advanced
2722baf369e7SPeter Brune 
2723bb7acecfSBarry Smith   Note:
2724bb7acecfSBarry 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.
2725bb7acecfSBarry Smith 
27261cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGlobalToLocal()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2727baf369e7SPeter Brune @*/
2728a4e35b19SJacob 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)
2729d71ae5a4SJacob Faibussowitsch {
2730baf369e7SPeter Brune   DMGlobalToLocalHookLink link, *p;
2731baf369e7SPeter Brune 
2732baf369e7SPeter Brune   PetscFunctionBegin;
2733baf369e7SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2734baf369e7SPeter Brune   for (p = &dm->gtolhook; *p; p = &(*p)->next) { } /* Scan to the end of the current list of hooks */
27359566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2736baf369e7SPeter Brune   link->beginhook = beginhook;
2737baf369e7SPeter Brune   link->endhook   = endhook;
2738baf369e7SPeter Brune   link->ctx       = ctx;
27390298fd71SBarry Smith   link->next      = NULL;
2740baf369e7SPeter Brune   *p              = link;
27413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2742baf369e7SPeter Brune }
2743baf369e7SPeter Brune 
2744d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
2745d71ae5a4SJacob Faibussowitsch {
27464c274da1SToby Isaac   Mat          cMat;
274779769bd5SJed Brown   Vec          cVec, cBias;
27484c274da1SToby Isaac   PetscSection section, cSec;
27494c274da1SToby Isaac   PetscInt     pStart, pEnd, p, dof;
27504c274da1SToby Isaac 
27514c274da1SToby Isaac   PetscFunctionBegin;
2752a4e35b19SJacob Faibussowitsch   (void)g;
2753a4e35b19SJacob Faibussowitsch   (void)ctx;
27544c274da1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27559566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, &cBias));
27564c274da1SToby Isaac   if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
27575db9a05bSToby Isaac     PetscInt nRows;
27585db9a05bSToby Isaac 
27599566063dSJacob Faibussowitsch     PetscCall(MatGetSize(cMat, &nRows, NULL));
27603ba16761SJacob Faibussowitsch     if (nRows <= 0) PetscFunctionReturn(PETSC_SUCCESS);
27619566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
27629566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(cMat, NULL, &cVec));
27639566063dSJacob Faibussowitsch     PetscCall(MatMult(cMat, l, cVec));
27649566063dSJacob Faibussowitsch     if (cBias) PetscCall(VecAXPY(cVec, 1., cBias));
27659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
27664c274da1SToby Isaac     for (p = pStart; p < pEnd; p++) {
27679566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
27684c274da1SToby Isaac       if (dof) {
27694c274da1SToby Isaac         PetscScalar *vals;
27709566063dSJacob Faibussowitsch         PetscCall(VecGetValuesSection(cVec, cSec, p, &vals));
27719566063dSJacob Faibussowitsch         PetscCall(VecSetValuesSection(l, section, p, vals, INSERT_ALL_VALUES));
27724c274da1SToby Isaac       }
27734c274da1SToby Isaac     }
27749566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cVec));
27754c274da1SToby Isaac   }
27763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27774c274da1SToby Isaac }
27784c274da1SToby Isaac 
277947c6ae99SBarry Smith /*@
278001729b5cSPatrick Sanan   DMGlobalToLocal - update local vectors from global vector
278101729b5cSPatrick Sanan 
278220f4b53cSBarry Smith   Neighbor-wise Collective
278301729b5cSPatrick Sanan 
278401729b5cSPatrick Sanan   Input Parameters:
2785bb7acecfSBarry Smith + dm   - the `DM` object
278601729b5cSPatrick Sanan . g    - the global vector
2787bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
278801729b5cSPatrick Sanan - l    - the local vector
278901729b5cSPatrick Sanan 
279020f4b53cSBarry Smith   Level: beginner
279120f4b53cSBarry Smith 
279201729b5cSPatrick Sanan   Notes:
2793bb7acecfSBarry Smith   The communication involved in this update can be overlapped with computation by instead using
2794bb7acecfSBarry Smith   `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()`.
2795bb7acecfSBarry Smith 
2796bb7acecfSBarry Smith   `DMGlobalToLocalHookAdd()` may be used to provide additional operations that are performed during the update process.
279701729b5cSPatrick Sanan 
27981cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGlobalToLocalHookAdd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`,
279960225df5SJacob Faibussowitsch           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`,
2800bb7acecfSBarry Smith           `DMGlobalToLocalBegin()` `DMGlobalToLocalEnd()`
280101729b5cSPatrick Sanan @*/
2802d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocal(DM dm, Vec g, InsertMode mode, Vec l)
2803d71ae5a4SJacob Faibussowitsch {
280401729b5cSPatrick Sanan   PetscFunctionBegin;
28059566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dm, g, mode, l));
28069566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dm, g, mode, l));
28073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
280801729b5cSPatrick Sanan }
280901729b5cSPatrick Sanan 
281001729b5cSPatrick Sanan /*@
281147c6ae99SBarry Smith   DMGlobalToLocalBegin - Begins updating local vectors from global vector
281247c6ae99SBarry Smith 
281320f4b53cSBarry Smith   Neighbor-wise Collective
281447c6ae99SBarry Smith 
281547c6ae99SBarry Smith   Input Parameters:
2816bb7acecfSBarry Smith + dm   - the `DM` object
281747c6ae99SBarry Smith . g    - the global vector
2818bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
281947c6ae99SBarry Smith - l    - the local vector
282047c6ae99SBarry Smith 
282101729b5cSPatrick Sanan   Level: intermediate
282247c6ae99SBarry Smith 
2823bb7acecfSBarry Smith   Notes:
2824bb7acecfSBarry Smith   The operation is completed with `DMGlobalToLocalEnd()`
2825bb7acecfSBarry Smith 
2826bb7acecfSBarry Smith   One can perform local computations between the `DMGlobalToLocalBegin()` and  `DMGlobalToLocalEnd()` to overlap communication and computation
2827bb7acecfSBarry Smith 
2828bb7acecfSBarry Smith   `DMGlobalToLocal()` is a short form of  `DMGlobalToLocalBegin()` and  `DMGlobalToLocalEnd()`
2829bb7acecfSBarry Smith 
2830bb7acecfSBarry Smith   `DMGlobalToLocalHookAdd()` may be used to provide additional operations that are performed during the update process.
2831bb7acecfSBarry Smith 
283260225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`
283347c6ae99SBarry Smith @*/
2834d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalBegin(DM dm, Vec g, InsertMode mode, Vec l)
2835d71ae5a4SJacob Faibussowitsch {
28367128ae9fSMatthew G Knepley   PetscSF                 sf;
2837baf369e7SPeter Brune   DMGlobalToLocalHookLink link;
283847c6ae99SBarry Smith 
283947c6ae99SBarry Smith   PetscFunctionBegin;
2840171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2841baf369e7SPeter Brune   for (link = dm->gtolhook; link; link = link->next) {
28421baa6e33SBarry Smith     if (link->beginhook) PetscCall((*link->beginhook)(dm, g, mode, l, link->ctx));
2843baf369e7SPeter Brune   }
28449566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
28457128ae9fSMatthew G Knepley   if (sf) {
2846ae5cfb4aSMatthew G. Knepley     const PetscScalar *gArray;
2847ae5cfb4aSMatthew G. Knepley     PetscScalar       *lArray;
2848d0295fc0SJunchao Zhang     PetscMemType       lmtype, gmtype;
28497128ae9fSMatthew G Knepley 
28507a8be351SBarry Smith     PetscCheck(mode != ADD_VALUES, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", (int)mode);
28519566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(l, &lArray, &lmtype));
28529566063dSJacob Faibussowitsch     PetscCall(VecGetArrayReadAndMemType(g, &gArray, &gmtype));
28539566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastWithMemTypeBegin(sf, MPIU_SCALAR, gmtype, gArray, lmtype, lArray, MPI_REPLACE));
28549566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(l, &lArray));
28559566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayReadAndMemType(g, &gArray));
28567128ae9fSMatthew G Knepley   } else {
2857fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, globaltolocalbegin, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
28587128ae9fSMatthew G Knepley   }
28593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
286047c6ae99SBarry Smith }
286147c6ae99SBarry Smith 
286247c6ae99SBarry Smith /*@
286347c6ae99SBarry Smith   DMGlobalToLocalEnd - Ends updating local vectors from global vector
286447c6ae99SBarry Smith 
286520f4b53cSBarry Smith   Neighbor-wise Collective
286647c6ae99SBarry Smith 
286747c6ae99SBarry Smith   Input Parameters:
2868bb7acecfSBarry Smith + dm   - the `DM` object
286947c6ae99SBarry Smith . g    - the global vector
2870bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
287147c6ae99SBarry Smith - l    - the local vector
287247c6ae99SBarry Smith 
287301729b5cSPatrick Sanan   Level: intermediate
287447c6ae99SBarry Smith 
2875bb7acecfSBarry Smith   Note:
2876bb7acecfSBarry Smith   See `DMGlobalToLocalBegin()` for details.
2877bb7acecfSBarry Smith 
287860225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`
287947c6ae99SBarry Smith @*/
2880d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
2881d71ae5a4SJacob Faibussowitsch {
28827128ae9fSMatthew G Knepley   PetscSF                 sf;
2883ae5cfb4aSMatthew G. Knepley   const PetscScalar      *gArray;
2884ae5cfb4aSMatthew G. Knepley   PetscScalar            *lArray;
2885ca3d3a14SMatthew G. Knepley   PetscBool               transform;
2886baf369e7SPeter Brune   DMGlobalToLocalHookLink link;
2887d0295fc0SJunchao Zhang   PetscMemType            lmtype, gmtype;
288847c6ae99SBarry Smith 
288947c6ae99SBarry Smith   PetscFunctionBegin;
2890171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28919566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
28929566063dSJacob Faibussowitsch   PetscCall(DMHasBasisTransform(dm, &transform));
28937128ae9fSMatthew G Knepley   if (sf) {
28947a8be351SBarry Smith     PetscCheck(mode != ADD_VALUES, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", (int)mode);
28957128ae9fSMatthew G Knepley 
28969566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(l, &lArray, &lmtype));
28979566063dSJacob Faibussowitsch     PetscCall(VecGetArrayReadAndMemType(g, &gArray, &gmtype));
28989566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray, MPI_REPLACE));
28999566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(l, &lArray));
29009566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayReadAndMemType(g, &gArray));
29019566063dSJacob Faibussowitsch     if (transform) PetscCall(DMPlexGlobalToLocalBasis(dm, l));
29027128ae9fSMatthew G Knepley   } else {
2903fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, globaltolocalend, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
29047128ae9fSMatthew G Knepley   }
29059566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalHook_Constraints(dm, g, mode, l, NULL));
2906baf369e7SPeter Brune   for (link = dm->gtolhook; link; link = link->next) {
29079566063dSJacob Faibussowitsch     if (link->endhook) PetscCall((*link->endhook)(dm, g, mode, l, link->ctx));
2908baf369e7SPeter Brune   }
29093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
291047c6ae99SBarry Smith }
291147c6ae99SBarry Smith 
2912d4d07f1eSToby Isaac /*@C
2913d4d07f1eSToby Isaac   DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
2914d4d07f1eSToby Isaac 
291520f4b53cSBarry Smith   Logically Collective
2916d4d07f1eSToby Isaac 
29174165533cSJose E. Roman   Input Parameters:
2918bb7acecfSBarry Smith + dm        - the `DM`
2919bb7acecfSBarry Smith . beginhook - function to run at the beginning of `DMLocalToGlobalBegin()`
2920bb7acecfSBarry Smith . endhook   - function to run after `DMLocalToGlobalEnd()` has completed
292120f4b53cSBarry Smith - ctx       - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2922d4d07f1eSToby Isaac 
292320f4b53cSBarry Smith   Calling sequence of `beginhook`:
2924a4e35b19SJacob Faibussowitsch + global - global `DM`
2925d4d07f1eSToby Isaac . l      - local vector
2926d4d07f1eSToby Isaac . mode   - mode
2927d4d07f1eSToby Isaac . g      - global vector
2928d4d07f1eSToby Isaac - ctx    - optional user-defined function context
2929d4d07f1eSToby Isaac 
293020f4b53cSBarry Smith   Calling sequence of `endhook`:
2931bb7acecfSBarry Smith + global - global `DM`
2932d4d07f1eSToby Isaac . l      - local vector
2933d4d07f1eSToby Isaac . mode   - mode
2934d4d07f1eSToby Isaac . g      - global vector
2935d4d07f1eSToby Isaac - ctx    - optional user-defined function context
2936d4d07f1eSToby Isaac 
2937d4d07f1eSToby Isaac   Level: advanced
2938d4d07f1eSToby Isaac 
29391cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobal()`, `DMRefineHookAdd()`, `DMGlobalToLocalHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2940d4d07f1eSToby Isaac @*/
2941a4e35b19SJacob 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)
2942d71ae5a4SJacob Faibussowitsch {
2943d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link, *p;
2944d4d07f1eSToby Isaac 
2945d4d07f1eSToby Isaac   PetscFunctionBegin;
2946d4d07f1eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2947d4d07f1eSToby Isaac   for (p = &dm->ltoghook; *p; p = &(*p)->next) { } /* Scan to the end of the current list of hooks */
29489566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2949d4d07f1eSToby Isaac   link->beginhook = beginhook;
2950d4d07f1eSToby Isaac   link->endhook   = endhook;
2951d4d07f1eSToby Isaac   link->ctx       = ctx;
2952d4d07f1eSToby Isaac   link->next      = NULL;
2953d4d07f1eSToby Isaac   *p              = link;
29543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2955d4d07f1eSToby Isaac }
2956d4d07f1eSToby Isaac 
2957d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2958d71ae5a4SJacob Faibussowitsch {
29594c274da1SToby Isaac   PetscFunctionBegin;
2960a4e35b19SJacob Faibussowitsch   (void)g;
2961a4e35b19SJacob Faibussowitsch   (void)ctx;
29624c274da1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29632b6b7d09SToby Isaac   if (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES) {
29642b6b7d09SToby Isaac     Mat          cMat;
29652b6b7d09SToby Isaac     Vec          cVec;
29665db9a05bSToby Isaac     PetscInt     nRows;
29672b6b7d09SToby Isaac     PetscSection section, cSec;
29682b6b7d09SToby Isaac     PetscInt     pStart, pEnd, p, dof;
29692b6b7d09SToby Isaac 
29702b6b7d09SToby Isaac     PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
29712b6b7d09SToby Isaac     if (!cMat) PetscFunctionReturn(PETSC_SUCCESS);
29725db9a05bSToby Isaac 
29739566063dSJacob Faibussowitsch     PetscCall(MatGetSize(cMat, &nRows, NULL));
29743ba16761SJacob Faibussowitsch     if (nRows <= 0) PetscFunctionReturn(PETSC_SUCCESS);
29759566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
29769566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(cMat, NULL, &cVec));
29779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
29784c274da1SToby Isaac     for (p = pStart; p < pEnd; p++) {
29799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
29804c274da1SToby Isaac       if (dof) {
29814c274da1SToby Isaac         PetscInt     d;
29824c274da1SToby Isaac         PetscScalar *vals;
29839566063dSJacob Faibussowitsch         PetscCall(VecGetValuesSection(l, section, p, &vals));
29849566063dSJacob Faibussowitsch         PetscCall(VecSetValuesSection(cVec, cSec, p, vals, mode));
29854c274da1SToby Isaac         /* for this to be the true transpose, we have to zero the values that
29864c274da1SToby Isaac          * we just extracted */
2987ad540459SPierre Jolivet         for (d = 0; d < dof; d++) vals[d] = 0.;
29884c274da1SToby Isaac       }
29894c274da1SToby Isaac     }
29909566063dSJacob Faibussowitsch     PetscCall(MatMultTransposeAdd(cMat, cVec, l, l));
29919566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cVec));
29924c274da1SToby Isaac   }
29933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29944c274da1SToby Isaac }
299501729b5cSPatrick Sanan /*@
299601729b5cSPatrick Sanan   DMLocalToGlobal - updates global vectors from local vectors
299701729b5cSPatrick Sanan 
299820f4b53cSBarry Smith   Neighbor-wise Collective
299901729b5cSPatrick Sanan 
300001729b5cSPatrick Sanan   Input Parameters:
3001bb7acecfSBarry Smith + dm   - the `DM` object
300201729b5cSPatrick Sanan . l    - the local vector
3003bb7acecfSBarry 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.
300401729b5cSPatrick Sanan - g    - the global vector
300501729b5cSPatrick Sanan 
300620f4b53cSBarry Smith   Level: beginner
300720f4b53cSBarry Smith 
300801729b5cSPatrick Sanan   Notes:
300901729b5cSPatrick Sanan   The communication involved in this update can be overlapped with computation by using
3010bb7acecfSBarry Smith   `DMLocalToGlobalBegin()` and `DMLocalToGlobalEnd()`.
301101729b5cSPatrick Sanan 
3012bb7acecfSBarry Smith   In the `ADD_VALUES` case you normally would zero the receiving vector before beginning this operation.
3013bb7acecfSBarry Smith 
3014bb7acecfSBarry 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.
3015bb7acecfSBarry Smith 
3016bb7acecfSBarry Smith   Use `DMLocalToGlobalHookAdd()` to add additional operations that are performed on the data during the update process
301701729b5cSPatrick Sanan 
30181cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalBegin()`, `DMLocalToGlobalHookAdd()`, `DMGlobaToLocallHookAdd()`
301901729b5cSPatrick Sanan @*/
3020d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobal(DM dm, Vec l, InsertMode mode, Vec g)
3021d71ae5a4SJacob Faibussowitsch {
302201729b5cSPatrick Sanan   PetscFunctionBegin;
30239566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, l, mode, g));
30249566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, l, mode, g));
30253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
302601729b5cSPatrick Sanan }
30274c274da1SToby Isaac 
302847c6ae99SBarry Smith /*@
302901729b5cSPatrick Sanan   DMLocalToGlobalBegin - begins updating global vectors from local vectors
30309a42bb27SBarry Smith 
303120f4b53cSBarry Smith   Neighbor-wise Collective
30329a42bb27SBarry Smith 
30339a42bb27SBarry Smith   Input Parameters:
3034bb7acecfSBarry Smith + dm   - the `DM` object
3035f6813fd5SJed Brown . l    - the local vector
3036aa624791SPierre 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.
30371eb28f2eSBarry Smith - g    - the global vector
30389a42bb27SBarry Smith 
303920f4b53cSBarry Smith   Level: intermediate
304020f4b53cSBarry Smith 
304195452b02SPatrick Sanan   Notes:
3042bb7acecfSBarry Smith   In the `ADD_VALUES` case you normally would zero the receiving vector before beginning this operation.
3043bb7acecfSBarry Smith 
3044bb7acecfSBarry 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.
3045bb7acecfSBarry Smith 
3046bb7acecfSBarry Smith   Use `DMLocalToGlobalEnd()` to complete the communication process.
3047bb7acecfSBarry Smith 
3048bb7acecfSBarry Smith   `DMLocalToGlobal()` is a short form of  `DMLocalToGlobalBegin()` and  `DMLocalToGlobalEnd()`
3049bb7acecfSBarry Smith 
3050bb7acecfSBarry Smith   `DMLocalToGlobalHookAdd()` may be used to provide additional operations that are performed during the update process.
30519a42bb27SBarry Smith 
30521cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalBegin()`
30539a42bb27SBarry Smith @*/
3054d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalBegin(DM dm, Vec l, InsertMode mode, Vec g)
3055d71ae5a4SJacob Faibussowitsch {
30567128ae9fSMatthew G Knepley   PetscSF                 sf;
305784330215SMatthew G. Knepley   PetscSection            s, gs;
3058d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link;
3059ca3d3a14SMatthew G. Knepley   Vec                     tmpl;
3060ae5cfb4aSMatthew G. Knepley   const PetscScalar      *lArray;
3061ae5cfb4aSMatthew G. Knepley   PetscScalar            *gArray;
3062fa88e482SJed Brown   PetscBool               isInsert, transform, l_inplace = PETSC_FALSE, g_inplace = PETSC_FALSE;
3063d0295fc0SJunchao Zhang   PetscMemType            lmtype = PETSC_MEMTYPE_HOST, gmtype = PETSC_MEMTYPE_HOST;
30649a42bb27SBarry Smith 
30659a42bb27SBarry Smith   PetscFunctionBegin;
3066171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3067d4d07f1eSToby Isaac   for (link = dm->ltoghook; link; link = link->next) {
30681baa6e33SBarry Smith     if (link->beginhook) PetscCall((*link->beginhook)(dm, l, mode, g, link->ctx));
3069d4d07f1eSToby Isaac   }
30709566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalHook_Constraints(dm, l, mode, g, NULL));
30719566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
30729566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
30737128ae9fSMatthew G Knepley   switch (mode) {
30747128ae9fSMatthew G Knepley   case INSERT_VALUES:
30757128ae9fSMatthew G Knepley   case INSERT_ALL_VALUES:
3076d71ae5a4SJacob Faibussowitsch   case INSERT_BC_VALUES:
3077d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_TRUE;
3078d71ae5a4SJacob Faibussowitsch     break;
30797128ae9fSMatthew G Knepley   case ADD_VALUES:
30807128ae9fSMatthew G Knepley   case ADD_ALL_VALUES:
3081d71ae5a4SJacob Faibussowitsch   case ADD_BC_VALUES:
3082d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_FALSE;
3083d71ae5a4SJacob Faibussowitsch     break;
3084d71ae5a4SJacob Faibussowitsch   default:
3085d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", mode);
30867128ae9fSMatthew G Knepley   }
3087ca3d3a14SMatthew G. Knepley   if ((sf && !isInsert) || (s && isInsert)) {
30889566063dSJacob Faibussowitsch     PetscCall(DMHasBasisTransform(dm, &transform));
3089ca3d3a14SMatthew G. Knepley     if (transform) {
30909566063dSJacob Faibussowitsch       PetscCall(DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
30919566063dSJacob Faibussowitsch       PetscCall(VecCopy(l, tmpl));
30929566063dSJacob Faibussowitsch       PetscCall(DMPlexLocalToGlobalBasis(dm, tmpl));
30939566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tmpl, &lArray));
3094fa88e482SJed Brown     } else if (isInsert) {
30959566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(l, &lArray));
3096fa88e482SJed Brown     } else {
30979566063dSJacob Faibussowitsch       PetscCall(VecGetArrayReadAndMemType(l, &lArray, &lmtype));
3098fa88e482SJed Brown       l_inplace = PETSC_TRUE;
3099ca3d3a14SMatthew G. Knepley     }
3100fa88e482SJed Brown     if (s && isInsert) {
31019566063dSJacob Faibussowitsch       PetscCall(VecGetArray(g, &gArray));
3102fa88e482SJed Brown     } else {
31039566063dSJacob Faibussowitsch       PetscCall(VecGetArrayAndMemType(g, &gArray, &gmtype));
3104fa88e482SJed Brown       g_inplace = PETSC_TRUE;
3105fa88e482SJed Brown     }
3106ca3d3a14SMatthew G. Knepley     if (sf && !isInsert) {
31079566063dSJacob Faibussowitsch       PetscCall(PetscSFReduceWithMemTypeBegin(sf, MPIU_SCALAR, lmtype, lArray, gmtype, gArray, MPIU_SUM));
310884330215SMatthew G. Knepley     } else if (s && isInsert) {
310984330215SMatthew G. Knepley       PetscInt gStart, pStart, pEnd, p;
311084330215SMatthew G. Knepley 
31119566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gs));
31129566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
31139566063dSJacob Faibussowitsch       PetscCall(VecGetOwnershipRange(g, &gStart, NULL));
311484330215SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
3115b3b16f48SMatthew G. Knepley         PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
311684330215SMatthew G. Knepley 
31179566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(s, p, &dof));
31189566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(gs, p, &gdof));
31199566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
31209566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(gs, p, &gcdof));
31219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(s, p, &off));
31229566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(gs, p, &goff));
3123b3b16f48SMatthew G. Knepley         /* Ignore off-process data and points with no global data */
312403442857SMatthew G. Knepley         if (!gdof || goff < 0) continue;
31257a8be351SBarry 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);
3126b3b16f48SMatthew G. Knepley         /* If no constraints are enforced in the global vector */
3127b3b16f48SMatthew G. Knepley         if (!gcdof) {
312884330215SMatthew G. Knepley           for (d = 0; d < dof; ++d) gArray[goff - gStart + d] = lArray[off + d];
3129b3b16f48SMatthew G. Knepley           /* If constraints are enforced in the global vector */
3130b3b16f48SMatthew G. Knepley         } else if (cdof == gcdof) {
313184330215SMatthew G. Knepley           const PetscInt *cdofs;
313284330215SMatthew G. Knepley           PetscInt        cind = 0;
313384330215SMatthew G. Knepley 
31349566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetConstraintIndices(s, p, &cdofs));
3135b3b16f48SMatthew G. Knepley           for (d = 0, e = 0; d < dof; ++d) {
31369371c9d4SSatish Balay             if ((cind < cdof) && (d == cdofs[cind])) {
31379371c9d4SSatish Balay               ++cind;
31389371c9d4SSatish Balay               continue;
31399371c9d4SSatish Balay             }
3140b3b16f48SMatthew G. Knepley             gArray[goff - gStart + e++] = lArray[off + d];
314184330215SMatthew G. Knepley           }
31427a8be351SBarry 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);
314384330215SMatthew G. Knepley       }
3144ca3d3a14SMatthew G. Knepley     }
3145fa88e482SJed Brown     if (g_inplace) {
31469566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayAndMemType(g, &gArray));
3147fa88e482SJed Brown     } else {
31489566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(g, &gArray));
3149fa88e482SJed Brown     }
3150ca3d3a14SMatthew G. Knepley     if (transform) {
31519566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tmpl, &lArray));
31529566063dSJacob Faibussowitsch       PetscCall(DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
3153fa88e482SJed Brown     } else if (l_inplace) {
31549566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayReadAndMemType(l, &lArray));
3155ca3d3a14SMatthew G. Knepley     } else {
31569566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(l, &lArray));
3157ca3d3a14SMatthew G. Knepley     }
31587128ae9fSMatthew G Knepley   } else {
3159fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, localtoglobalbegin, l, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), g);
31607128ae9fSMatthew G Knepley   }
31613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31629a42bb27SBarry Smith }
31639a42bb27SBarry Smith 
31649a42bb27SBarry Smith /*@
31659a42bb27SBarry Smith   DMLocalToGlobalEnd - updates global vectors from local vectors
316647c6ae99SBarry Smith 
316720f4b53cSBarry Smith   Neighbor-wise Collective
316847c6ae99SBarry Smith 
316947c6ae99SBarry Smith   Input Parameters:
3170bb7acecfSBarry Smith + dm   - the `DM` object
3171f6813fd5SJed Brown . l    - the local vector
3172bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
3173f6813fd5SJed Brown - g    - the global vector
317447c6ae99SBarry Smith 
317501729b5cSPatrick Sanan   Level: intermediate
317647c6ae99SBarry Smith 
3177bb7acecfSBarry Smith   Note:
3178bb7acecfSBarry Smith   See `DMLocalToGlobalBegin()` for full details
3179bb7acecfSBarry Smith 
318060225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`
318147c6ae99SBarry Smith @*/
3182d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalEnd(DM dm, Vec l, InsertMode mode, Vec g)
3183d71ae5a4SJacob Faibussowitsch {
31847128ae9fSMatthew G Knepley   PetscSF                 sf;
318584330215SMatthew G. Knepley   PetscSection            s;
3186d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link;
3187ca3d3a14SMatthew G. Knepley   PetscBool               isInsert, transform;
318847c6ae99SBarry Smith 
318947c6ae99SBarry Smith   PetscFunctionBegin;
3190171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31919566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
31929566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
31937128ae9fSMatthew G Knepley   switch (mode) {
31947128ae9fSMatthew G Knepley   case INSERT_VALUES:
3195d71ae5a4SJacob Faibussowitsch   case INSERT_ALL_VALUES:
3196d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_TRUE;
3197d71ae5a4SJacob Faibussowitsch     break;
31987128ae9fSMatthew G Knepley   case ADD_VALUES:
3199d71ae5a4SJacob Faibussowitsch   case ADD_ALL_VALUES:
3200d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_FALSE;
3201d71ae5a4SJacob Faibussowitsch     break;
3202d71ae5a4SJacob Faibussowitsch   default:
3203d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", mode);
32047128ae9fSMatthew G Knepley   }
320584330215SMatthew G. Knepley   if (sf && !isInsert) {
3206ae5cfb4aSMatthew G. Knepley     const PetscScalar *lArray;
3207ae5cfb4aSMatthew G. Knepley     PetscScalar       *gArray;
3208ca3d3a14SMatthew G. Knepley     Vec                tmpl;
320984330215SMatthew G. Knepley 
32109566063dSJacob Faibussowitsch     PetscCall(DMHasBasisTransform(dm, &transform));
3211ca3d3a14SMatthew G. Knepley     if (transform) {
32129566063dSJacob Faibussowitsch       PetscCall(DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
32139566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tmpl, &lArray));
3214ca3d3a14SMatthew G. Knepley     } else {
32159566063dSJacob Faibussowitsch       PetscCall(VecGetArrayReadAndMemType(l, &lArray, NULL));
3216ca3d3a14SMatthew G. Knepley     }
32179566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(g, &gArray, NULL));
32189566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM));
3219ca3d3a14SMatthew G. Knepley     if (transform) {
32209566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tmpl, &lArray));
32219566063dSJacob Faibussowitsch       PetscCall(DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
3222ca3d3a14SMatthew G. Knepley     } else {
32239566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayReadAndMemType(l, &lArray));
3224ca3d3a14SMatthew G. Knepley     }
32259566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(g, &gArray));
322684330215SMatthew G. Knepley   } else if (s && isInsert) {
32277128ae9fSMatthew G Knepley   } else {
3228fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, localtoglobalend, l, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), g);
32297128ae9fSMatthew G Knepley   }
3230d4d07f1eSToby Isaac   for (link = dm->ltoghook; link; link = link->next) {
32319566063dSJacob Faibussowitsch     if (link->endhook) PetscCall((*link->endhook)(dm, g, mode, l, link->ctx));
3232d4d07f1eSToby Isaac   }
32333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
323447c6ae99SBarry Smith }
323547c6ae99SBarry Smith 
3236f089877aSRichard Tran Mills /*@
3237a4e35b19SJacob Faibussowitsch   DMLocalToLocalBegin - Begins the process of mapping values from a local vector (that include
3238a4e35b19SJacob Faibussowitsch   ghost points that contain irrelevant values) to another local vector where the ghost points
3239a4e35b19SJacob Faibussowitsch   in the second are set correctly from values on other MPI ranks.
3240f089877aSRichard Tran Mills 
324120f4b53cSBarry Smith   Neighbor-wise Collective
3242f089877aSRichard Tran Mills 
3243f089877aSRichard Tran Mills   Input Parameters:
3244bb7acecfSBarry Smith + dm   - the `DM` object
3245bc0a1609SRichard Tran Mills . g    - the original local vector
3246bb7acecfSBarry Smith - mode - one of `INSERT_VALUES` or `ADD_VALUES`
3247f089877aSRichard Tran Mills 
3248bc0a1609SRichard Tran Mills   Output Parameter:
3249bc0a1609SRichard Tran Mills . l - the local vector with correct ghost values
3250f089877aSRichard Tran Mills 
3251f089877aSRichard Tran Mills   Level: intermediate
3252f089877aSRichard Tran Mills 
325373ff1848SBarry Smith   Note:
3254a4e35b19SJacob Faibussowitsch   Must be followed by `DMLocalToLocalEnd()`.
3255a4e35b19SJacob Faibussowitsch 
325660225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLocalToLocalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3257f089877aSRichard Tran Mills @*/
3258d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalBegin(DM dm, Vec g, InsertMode mode, Vec l)
3259d71ae5a4SJacob Faibussowitsch {
3260f089877aSRichard Tran Mills   PetscFunctionBegin;
3261f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32629f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
32639f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(l, VEC_CLASSID, 4);
32649f4ada15SMatthew G. Knepley   PetscUseTypeMethod(dm, localtolocalbegin, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
32653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3266f089877aSRichard Tran Mills }
3267f089877aSRichard Tran Mills 
3268f089877aSRichard Tran Mills /*@
3269bb7acecfSBarry Smith   DMLocalToLocalEnd - Maps from a local vector to another local vector where the ghost
3270bb7acecfSBarry Smith   points in the second are set correctly. Must be preceded by `DMLocalToLocalBegin()`.
3271f089877aSRichard Tran Mills 
327220f4b53cSBarry Smith   Neighbor-wise Collective
3273f089877aSRichard Tran Mills 
3274f089877aSRichard Tran Mills   Input Parameters:
327560225df5SJacob Faibussowitsch + dm   - the `DM` object
3276bc0a1609SRichard Tran Mills . g    - the original local vector
3277bb7acecfSBarry Smith - mode - one of `INSERT_VALUES` or `ADD_VALUES`
3278f089877aSRichard Tran Mills 
3279bc0a1609SRichard Tran Mills   Output Parameter:
3280bc0a1609SRichard Tran Mills . l - the local vector with correct ghost values
3281f089877aSRichard Tran Mills 
3282f089877aSRichard Tran Mills   Level: intermediate
3283f089877aSRichard Tran Mills 
328460225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLocalToLocalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3285f089877aSRichard Tran Mills @*/
3286d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
3287d71ae5a4SJacob Faibussowitsch {
3288f089877aSRichard Tran Mills   PetscFunctionBegin;
3289f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32909f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
32919f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(l, VEC_CLASSID, 4);
32929f4ada15SMatthew G. Knepley   PetscUseTypeMethod(dm, localtolocalend, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
32933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3294f089877aSRichard Tran Mills }
3295f089877aSRichard Tran Mills 
329647c6ae99SBarry Smith /*@
3297bb7acecfSBarry Smith   DMCoarsen - Coarsens a `DM` object using a standard, non-adaptive coarsening of the underlying mesh
329847c6ae99SBarry Smith 
329920f4b53cSBarry Smith   Collective
330047c6ae99SBarry Smith 
3301d8d19677SJose E. Roman   Input Parameters:
3302bb7acecfSBarry Smith + dm   - the `DM` object
330320f4b53cSBarry Smith - comm - the communicator to contain the new `DM` object (or `MPI_COMM_NULL`)
330447c6ae99SBarry Smith 
330547c6ae99SBarry Smith   Output Parameter:
3306bb7acecfSBarry Smith . dmc - the coarsened `DM`
330747c6ae99SBarry Smith 
330847c6ae99SBarry Smith   Level: developer
330947c6ae99SBarry Smith 
331073ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateDomainDecomposition()`,
331173ff1848SBarry Smith           `DMCoarsenHookAdd()`, `DMCoarsenHookRemove()`
331247c6ae99SBarry Smith @*/
3313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
3314d71ae5a4SJacob Faibussowitsch {
3315b17ce1afSJed Brown   DMCoarsenHookLink link;
331647c6ae99SBarry Smith 
331747c6ae99SBarry Smith   PetscFunctionBegin;
3318171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Coarsen, dm, 0, 0, 0));
3320dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, coarsen, comm, dmc);
3321b9d85ea2SLisandro Dalcin   if (*dmc) {
3322a3574896SRichard Tran Mills     (*dmc)->bind_below = dm->bind_below; /* Propagate this from parent DM; otherwise -dm_bind_below will be useless for multigrid cases. */
33239566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dm, *dmc));
332443842a1eSJed Brown     (*dmc)->ops->creatematrix = dm->ops->creatematrix;
33259566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmc));
3326644e2e5bSBarry Smith     (*dmc)->ctx       = dm->ctx;
33270598a293SJed Brown     (*dmc)->levelup   = dm->levelup;
3328656b349aSBarry Smith     (*dmc)->leveldown = dm->leveldown + 1;
33299566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmc, dm->mattype));
3330b17ce1afSJed Brown     for (link = dm->coarsenhook; link; link = link->next) {
33319566063dSJacob Faibussowitsch       if (link->coarsenhook) PetscCall((*link->coarsenhook)(dm, *dmc, link->ctx));
3332b17ce1afSJed Brown     }
3333b9d85ea2SLisandro Dalcin   }
33349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Coarsen, dm, 0, 0, 0));
33357a8be351SBarry Smith   PetscCheck(*dmc, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
33363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3337b17ce1afSJed Brown }
3338b17ce1afSJed Brown 
3339bb9467b5SJed Brown /*@C
3340b17ce1afSJed Brown   DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
3341b17ce1afSJed Brown 
334220f4b53cSBarry Smith   Logically Collective; No Fortran Support
3343b17ce1afSJed Brown 
33444165533cSJose E. Roman   Input Parameters:
3345bb7acecfSBarry Smith + fine         - `DM` on which to run a hook when restricting to a coarser level
3346b17ce1afSJed Brown . coarsenhook  - function to run when setting up a coarser level
3347bb7acecfSBarry Smith . restricthook - function to run to update data on coarser levels (called once per `SNESSolve()`)
334820f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3349b17ce1afSJed Brown 
335020f4b53cSBarry Smith   Calling sequence of `coarsenhook`:
3351bb7acecfSBarry Smith + fine   - fine level `DM`
3352bb7acecfSBarry Smith . coarse - coarse level `DM` to restrict problem to
3353b17ce1afSJed Brown - ctx    - optional user-defined function context
3354b17ce1afSJed Brown 
335520f4b53cSBarry Smith   Calling sequence of `restricthook`:
3356bb7acecfSBarry Smith + fine      - fine level `DM`
3357bb7acecfSBarry Smith . mrestrict - matrix restricting a fine-level solution to the coarse grid, usually the transpose of the interpolation
3358c833c3b5SJed Brown . rscale    - scaling vector for restriction
3359c833c3b5SJed Brown . inject    - matrix restricting by injection
3360b17ce1afSJed Brown . coarse    - coarse level DM to update
3361b17ce1afSJed Brown - ctx       - optional user-defined function context
3362b17ce1afSJed Brown 
3363b17ce1afSJed Brown   Level: advanced
3364b17ce1afSJed Brown 
3365b17ce1afSJed Brown   Notes:
3366bb7acecfSBarry 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`.
3367b17ce1afSJed Brown 
3368b17ce1afSJed Brown   If this function is called multiple times, the hooks will be run in the order they are added.
3369b17ce1afSJed Brown 
3370b17ce1afSJed Brown   In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3371bb7acecfSBarry Smith   extract the finest level information from its context (instead of from the `SNES`).
3372b17ce1afSJed Brown 
3373bb7acecfSBarry Smith   The hooks are automatically called by `DMRestrict()`
3374bb7acecfSBarry Smith 
33751cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3376b17ce1afSJed Brown @*/
3377a4e35b19SJacob 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)
3378d71ae5a4SJacob Faibussowitsch {
3379b17ce1afSJed Brown   DMCoarsenHookLink link, *p;
3380b17ce1afSJed Brown 
3381b17ce1afSJed Brown   PetscFunctionBegin;
3382b17ce1afSJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
33831e3d8eccSJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
33843ba16761SJacob Faibussowitsch     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
33851e3d8eccSJed Brown   }
33869566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
3387b17ce1afSJed Brown   link->coarsenhook  = coarsenhook;
3388b17ce1afSJed Brown   link->restricthook = restricthook;
3389b17ce1afSJed Brown   link->ctx          = ctx;
33900298fd71SBarry Smith   link->next         = NULL;
3391b17ce1afSJed Brown   *p                 = link;
33923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3393b17ce1afSJed Brown }
3394b17ce1afSJed Brown 
3395dc822a44SJed Brown /*@C
3396bb7acecfSBarry Smith   DMCoarsenHookRemove - remove a callback set with `DMCoarsenHookAdd()`
3397dc822a44SJed Brown 
339820f4b53cSBarry Smith   Logically Collective; No Fortran Support
3399dc822a44SJed Brown 
34004165533cSJose E. Roman   Input Parameters:
3401bb7acecfSBarry Smith + fine         - `DM` on which to run a hook when restricting to a coarser level
3402dc822a44SJed Brown . coarsenhook  - function to run when setting up a coarser level
3403bb7acecfSBarry Smith . restricthook - function to run to update data on coarser levels
340420f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3405dc822a44SJed Brown 
3406dc822a44SJed Brown   Level: advanced
3407dc822a44SJed Brown 
340873ff1848SBarry Smith   Notes:
340973ff1848SBarry Smith   This function does nothing if the `coarsenhook` is not in the list.
341073ff1848SBarry Smith 
341173ff1848SBarry Smith   See `DMCoarsenHookAdd()` for the calling sequence of `coarsenhook` and `restricthook`
3412dc822a44SJed Brown 
34131cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3414dc822a44SJed Brown @*/
3415d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHookRemove(DM fine, PetscErrorCode (*coarsenhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, Mat, Vec, Mat, DM, void *), void *ctx)
3416d71ae5a4SJacob Faibussowitsch {
3417dc822a44SJed Brown   DMCoarsenHookLink link, *p;
3418dc822a44SJed Brown 
3419dc822a44SJed Brown   PetscFunctionBegin;
3420dc822a44SJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
3421dc822a44SJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3422dc822a44SJed Brown     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3423dc822a44SJed Brown       link = *p;
3424dc822a44SJed Brown       *p   = link->next;
34259566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3426dc822a44SJed Brown       break;
3427dc822a44SJed Brown     }
3428dc822a44SJed Brown   }
34293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3430dc822a44SJed Brown }
3431dc822a44SJed Brown 
3432b17ce1afSJed Brown /*@
3433bb7acecfSBarry Smith   DMRestrict - restricts user-defined problem data to a coarser `DM` by running hooks registered by `DMCoarsenHookAdd()`
3434b17ce1afSJed Brown 
3435b17ce1afSJed Brown   Collective if any hooks are
3436b17ce1afSJed Brown 
34374165533cSJose E. Roman   Input Parameters:
3438bb7acecfSBarry Smith + fine    - finer `DM` from which the data is obtained
3439bb7acecfSBarry Smith . restrct - restriction matrix, apply using `MatRestrict()`, usually the transpose of the interpolation
3440e91eccc2SStefano Zampini . rscale  - scaling vector for restriction
3441bb7acecfSBarry Smith . inject  - injection matrix, also use `MatRestrict()`
344220f4b53cSBarry Smith - coarse  - coarser `DM` to update
3443b17ce1afSJed Brown 
3444b17ce1afSJed Brown   Level: developer
3445b17ce1afSJed Brown 
344673ff1848SBarry Smith   Developer Note:
3447bb7acecfSBarry Smith   Though this routine is called `DMRestrict()` the hooks are added with `DMCoarsenHookAdd()`, a consistent terminology would be better
3448bb7acecfSBarry Smith 
34491cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `MatRestrict()`, `DMInterpolate()`, `DMRefineHookAdd()`
3450b17ce1afSJed Brown @*/
3451d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestrict(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse)
3452d71ae5a4SJacob Faibussowitsch {
3453b17ce1afSJed Brown   DMCoarsenHookLink link;
3454b17ce1afSJed Brown 
3455b17ce1afSJed Brown   PetscFunctionBegin;
3456b17ce1afSJed Brown   for (link = fine->coarsenhook; link; link = link->next) {
34571baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(fine, restrct, rscale, inject, coarse, link->ctx));
3458b17ce1afSJed Brown   }
34593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346047c6ae99SBarry Smith }
346147c6ae99SBarry Smith 
3462bb9467b5SJed Brown /*@C
346373ff1848SBarry Smith   DMSubDomainHookAdd - adds a callback to be run when restricting a problem to subdomain `DM`s with `DMCreateDomainDecomposition()`
34645dbd56e3SPeter Brune 
346520f4b53cSBarry Smith   Logically Collective; No Fortran Support
34665dbd56e3SPeter Brune 
34674165533cSJose E. Roman   Input Parameters:
3468bb7acecfSBarry Smith + global       - global `DM`
3469bb7acecfSBarry Smith . ddhook       - function to run to pass data to the decomposition `DM` upon its creation
34705dbd56e3SPeter Brune . restricthook - function to run to update data on block solve (at the beginning of the block solve)
347120f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
34725dbd56e3SPeter Brune 
347320f4b53cSBarry Smith   Calling sequence of `ddhook`:
3474bb7acecfSBarry Smith + global - global `DM`
347573ff1848SBarry Smith . block  - subdomain `DM`
3476ec4806b8SPeter Brune - ctx    - optional user-defined function context
3477ec4806b8SPeter Brune 
347820f4b53cSBarry Smith   Calling sequence of `restricthook`:
3479bb7acecfSBarry Smith + global - global `DM`
348073ff1848SBarry Smith . out    - scatter to the outer (with ghost and overlap points) sub vector
348173ff1848SBarry Smith . in     - scatter to sub vector values only owned locally
348273ff1848SBarry Smith . block  - subdomain `DM`
34835dbd56e3SPeter Brune - ctx    - optional user-defined function context
34845dbd56e3SPeter Brune 
34855dbd56e3SPeter Brune   Level: advanced
34865dbd56e3SPeter Brune 
34875dbd56e3SPeter Brune   Notes:
348873ff1848SBarry Smith   This function can be used if auxiliary data needs to be set up on subdomain `DM`s.
34895dbd56e3SPeter Brune 
34905dbd56e3SPeter Brune   If this function is called multiple times, the hooks will be run in the order they are added.
34915dbd56e3SPeter Brune 
34925dbd56e3SPeter Brune   In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3493bb7acecfSBarry Smith   extract the global information from its context (instead of from the `SNES`).
34945dbd56e3SPeter Brune 
349573ff1848SBarry Smith   Developer Note:
349673ff1848SBarry Smith   It is unclear what "block solve" means within the definition of `restricthook`
349773ff1848SBarry Smith 
349873ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSubDomainHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`, `DMCreateDomainDecomposition()`
34995dbd56e3SPeter Brune @*/
3500a4e35b19SJacob 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)
3501d71ae5a4SJacob Faibussowitsch {
3502be081cd6SPeter Brune   DMSubDomainHookLink link, *p;
35035dbd56e3SPeter Brune 
35045dbd56e3SPeter Brune   PetscFunctionBegin;
35055dbd56e3SPeter Brune   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3506b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
35073ba16761SJacob Faibussowitsch     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
3508b3a6b972SJed Brown   }
35099566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
35105dbd56e3SPeter Brune   link->restricthook = restricthook;
3511be081cd6SPeter Brune   link->ddhook       = ddhook;
35125dbd56e3SPeter Brune   link->ctx          = ctx;
35130298fd71SBarry Smith   link->next         = NULL;
35145dbd56e3SPeter Brune   *p                 = link;
35153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35165dbd56e3SPeter Brune }
35175dbd56e3SPeter Brune 
3518b3a6b972SJed Brown /*@C
351973ff1848SBarry Smith   DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to subdomain `DM`s with `DMCreateDomainDecomposition()`
3520b3a6b972SJed Brown 
352120f4b53cSBarry Smith   Logically Collective; No Fortran Support
3522b3a6b972SJed Brown 
35234165533cSJose E. Roman   Input Parameters:
3524bb7acecfSBarry Smith + global       - global `DM`
3525bb7acecfSBarry Smith . ddhook       - function to run to pass data to the decomposition `DM` upon its creation
3526b3a6b972SJed Brown . restricthook - function to run to update data on block solve (at the beginning of the block solve)
352720f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3528b3a6b972SJed Brown 
3529b3a6b972SJed Brown   Level: advanced
3530b3a6b972SJed Brown 
353173ff1848SBarry Smith   Note:
353273ff1848SBarry Smith   See `DMSubDomainHookAdd()` for the calling sequences of `ddhook` and `restricthook`
353373ff1848SBarry Smith 
353473ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSubDomainHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`,
353573ff1848SBarry Smith           `DMCreateDomainDecomposition()`
3536b3a6b972SJed Brown @*/
3537d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainHookRemove(DM global, PetscErrorCode (*ddhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, VecScatter, VecScatter, DM, void *), void *ctx)
3538d71ae5a4SJacob Faibussowitsch {
3539b3a6b972SJed Brown   DMSubDomainHookLink link, *p;
3540b3a6b972SJed Brown 
3541b3a6b972SJed Brown   PetscFunctionBegin;
3542b3a6b972SJed Brown   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3543b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3544b3a6b972SJed Brown     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3545b3a6b972SJed Brown       link = *p;
3546b3a6b972SJed Brown       *p   = link->next;
35479566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3548b3a6b972SJed Brown       break;
3549b3a6b972SJed Brown     }
3550b3a6b972SJed Brown   }
35513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3552b3a6b972SJed Brown }
3553b3a6b972SJed Brown 
35545dbd56e3SPeter Brune /*@
355573ff1848SBarry Smith   DMSubDomainRestrict - restricts user-defined problem data to a subdomain `DM` by running hooks registered by `DMSubDomainHookAdd()`
35565dbd56e3SPeter Brune 
35575dbd56e3SPeter Brune   Collective if any hooks are
35585dbd56e3SPeter Brune 
35594165533cSJose E. Roman   Input Parameters:
3560a4e35b19SJacob Faibussowitsch + global   - The global `DM` to use as a base
3561a4e35b19SJacob Faibussowitsch . oscatter - The scatter from domain global vector filling subdomain global vector with overlap
3562a4e35b19SJacob Faibussowitsch . gscatter - The scatter from domain global vector filling subdomain local vector with ghosts
3563a4e35b19SJacob Faibussowitsch - subdm    - The subdomain `DM` to update
35645dbd56e3SPeter Brune 
35655dbd56e3SPeter Brune   Level: developer
35665dbd56e3SPeter Brune 
356773ff1848SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `MatRestrict()`, `DMCreateDomainDecomposition()`
35685dbd56e3SPeter Brune @*/
3569d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainRestrict(DM global, VecScatter oscatter, VecScatter gscatter, DM subdm)
3570d71ae5a4SJacob Faibussowitsch {
3571be081cd6SPeter Brune   DMSubDomainHookLink link;
35725dbd56e3SPeter Brune 
35735dbd56e3SPeter Brune   PetscFunctionBegin;
3574be081cd6SPeter Brune   for (link = global->subdomainhook; link; link = link->next) {
35751baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(global, oscatter, gscatter, subdm, link->ctx));
35765dbd56e3SPeter Brune   }
35773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35785dbd56e3SPeter Brune }
35795dbd56e3SPeter Brune 
35805fe1f584SPeter Brune /*@
3581bb7acecfSBarry Smith   DMGetCoarsenLevel - Gets the number of coarsenings that have generated this `DM`.
35825fe1f584SPeter Brune 
35835fe1f584SPeter Brune   Not Collective
35845fe1f584SPeter Brune 
35855fe1f584SPeter Brune   Input Parameter:
3586bb7acecfSBarry Smith . dm - the `DM` object
35875fe1f584SPeter Brune 
35885fe1f584SPeter Brune   Output Parameter:
35896a7d9d85SPeter Brune . level - number of coarsenings
35905fe1f584SPeter Brune 
35915fe1f584SPeter Brune   Level: developer
35925fe1f584SPeter Brune 
35931cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMSetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
35945fe1f584SPeter Brune @*/
3595d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarsenLevel(DM dm, PetscInt *level)
3596d71ae5a4SJacob Faibussowitsch {
35975fe1f584SPeter Brune   PetscFunctionBegin;
35985fe1f584SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35994f572ea9SToby Isaac   PetscAssertPointer(level, 2);
36005fe1f584SPeter Brune   *level = dm->leveldown;
36013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36025fe1f584SPeter Brune }
36035fe1f584SPeter Brune 
36049a64c4a8SMatthew G. Knepley /*@
3605bb7acecfSBarry Smith   DMSetCoarsenLevel - Sets the number of coarsenings that have generated this `DM`.
36069a64c4a8SMatthew G. Knepley 
360720f4b53cSBarry Smith   Collective
36089a64c4a8SMatthew G. Knepley 
36099a64c4a8SMatthew G. Knepley   Input Parameters:
3610bb7acecfSBarry Smith + dm    - the `DM` object
36119a64c4a8SMatthew G. Knepley - level - number of coarsenings
36129a64c4a8SMatthew G. Knepley 
36139a64c4a8SMatthew G. Knepley   Level: developer
36149a64c4a8SMatthew G. Knepley 
3615bb7acecfSBarry Smith   Note:
3616bb7acecfSBarry Smith   This is rarely used directly, the information is automatically set when a `DM` is created with `DMCoarsen()`
3617bb7acecfSBarry Smith 
361842747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
36199a64c4a8SMatthew G. Knepley @*/
3620d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarsenLevel(DM dm, PetscInt level)
3621d71ae5a4SJacob Faibussowitsch {
36229a64c4a8SMatthew G. Knepley   PetscFunctionBegin;
36239a64c4a8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36249a64c4a8SMatthew G. Knepley   dm->leveldown = level;
36253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36269a64c4a8SMatthew G. Knepley }
36279a64c4a8SMatthew G. Knepley 
3628cc4c1da9SBarry Smith /*@
3629bb7acecfSBarry Smith   DMRefineHierarchy - Refines a `DM` object, all levels at once
363047c6ae99SBarry Smith 
363120f4b53cSBarry Smith   Collective
363247c6ae99SBarry Smith 
3633d8d19677SJose E. Roman   Input Parameters:
3634bb7acecfSBarry Smith + dm      - the `DM` object
363547c6ae99SBarry Smith - nlevels - the number of levels of refinement
363647c6ae99SBarry Smith 
363747c6ae99SBarry Smith   Output Parameter:
3638bb7acecfSBarry Smith . dmf - the refined `DM` hierarchy
363947c6ae99SBarry Smith 
364047c6ae99SBarry Smith   Level: developer
364147c6ae99SBarry Smith 
36421cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMCoarsenHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
364347c6ae99SBarry Smith @*/
3644d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHierarchy(DM dm, PetscInt nlevels, DM dmf[])
3645d71ae5a4SJacob Faibussowitsch {
364647c6ae99SBarry Smith   PetscFunctionBegin;
3647171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36487a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
36493ba16761SJacob Faibussowitsch   if (nlevels == 0) PetscFunctionReturn(PETSC_SUCCESS);
36504f572ea9SToby Isaac   PetscAssertPointer(dmf, 3);
3651213acdd3SPierre Jolivet   if (dm->ops->refine && !dm->ops->refinehierarchy) {
365247c6ae99SBarry Smith     PetscInt i;
365347c6ae99SBarry Smith 
36549566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &dmf[0]));
365548a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMRefine(dmf[i - 1], PetscObjectComm((PetscObject)dm), &dmf[i]));
3656213acdd3SPierre Jolivet   } else PetscUseTypeMethod(dm, refinehierarchy, nlevels, dmf);
36573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
365847c6ae99SBarry Smith }
365947c6ae99SBarry Smith 
3660cc4c1da9SBarry Smith /*@
3661bb7acecfSBarry Smith   DMCoarsenHierarchy - Coarsens a `DM` object, all levels at once
366247c6ae99SBarry Smith 
366320f4b53cSBarry Smith   Collective
366447c6ae99SBarry Smith 
3665d8d19677SJose E. Roman   Input Parameters:
3666bb7acecfSBarry Smith + dm      - the `DM` object
366747c6ae99SBarry Smith - nlevels - the number of levels of coarsening
366847c6ae99SBarry Smith 
366947c6ae99SBarry Smith   Output Parameter:
3670bb7acecfSBarry Smith . dmc - the coarsened `DM` hierarchy
367147c6ae99SBarry Smith 
367247c6ae99SBarry Smith   Level: developer
367347c6ae99SBarry Smith 
36741cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMRefineHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
367547c6ae99SBarry Smith @*/
3676d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
3677d71ae5a4SJacob Faibussowitsch {
367847c6ae99SBarry Smith   PetscFunctionBegin;
3679171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36807a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
36813ba16761SJacob Faibussowitsch   if (nlevels == 0) PetscFunctionReturn(PETSC_SUCCESS);
36824f572ea9SToby Isaac   PetscAssertPointer(dmc, 3);
3683213acdd3SPierre Jolivet   if (dm->ops->coarsen && !dm->ops->coarsenhierarchy) {
368447c6ae99SBarry Smith     PetscInt i;
368547c6ae99SBarry Smith 
36869566063dSJacob Faibussowitsch     PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &dmc[0]));
368748a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMCoarsen(dmc[i - 1], PetscObjectComm((PetscObject)dm), &dmc[i]));
3688213acdd3SPierre Jolivet   } else PetscUseTypeMethod(dm, coarsenhierarchy, nlevels, dmc);
36893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
369047c6ae99SBarry Smith }
369147c6ae99SBarry Smith 
36921a266240SBarry Smith /*@C
3693bb7acecfSBarry Smith   DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the `DM` is destroyed
36941a266240SBarry Smith 
3695bb7acecfSBarry Smith   Logically Collective if the function is collective
36961a266240SBarry Smith 
36971a266240SBarry Smith   Input Parameters:
3698bb7acecfSBarry Smith + dm      - the `DM` object
369949abdd8aSBarry Smith - destroy - the destroy function, see `PetscCtxDestroyFn` for the calling sequence
37001a266240SBarry Smith 
37011a266240SBarry Smith   Level: intermediate
37021a266240SBarry Smith 
370349abdd8aSBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`,
370449abdd8aSBarry Smith           `DMGetApplicationContext()`, `PetscCtxDestroyFn`
3705f07f9ceaSJed Brown @*/
370649abdd8aSBarry Smith PetscErrorCode DMSetApplicationContextDestroy(DM dm, PetscCtxDestroyFn *destroy)
3707d71ae5a4SJacob Faibussowitsch {
37081a266240SBarry Smith   PetscFunctionBegin;
3709171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37101a266240SBarry Smith   dm->ctxdestroy = destroy;
37113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37121a266240SBarry Smith }
37131a266240SBarry Smith 
3714b07ff414SBarry Smith /*@
3715bb7acecfSBarry Smith   DMSetApplicationContext - Set a user context into a `DM` object
371647c6ae99SBarry Smith 
371747c6ae99SBarry Smith   Not Collective
371847c6ae99SBarry Smith 
371947c6ae99SBarry Smith   Input Parameters:
3720bb7acecfSBarry Smith + dm  - the `DM` object
372147c6ae99SBarry Smith - ctx - the user context
372247c6ae99SBarry Smith 
372347c6ae99SBarry Smith   Level: intermediate
372447c6ae99SBarry Smith 
3725e33b3f0fSStefano Zampini   Notes:
372635cb6cd3SPierre Jolivet   A user context is a way to pass problem specific information that is accessible whenever the `DM` is available
3727e33b3f0fSStefano Zampini   In a multilevel solver, the user context is shared by all the `DM` in the hierarchy; it is thus not advisable
3728e33b3f0fSStefano Zampini   to store objects that represent discretized quantities inside the context.
3729bb7acecfSBarry Smith 
373060225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMGetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
373147c6ae99SBarry Smith @*/
3732d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetApplicationContext(DM dm, void *ctx)
3733d71ae5a4SJacob Faibussowitsch {
373447c6ae99SBarry Smith   PetscFunctionBegin;
3735171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
373647c6ae99SBarry Smith   dm->ctx = ctx;
37373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
373847c6ae99SBarry Smith }
373947c6ae99SBarry Smith 
374047c6ae99SBarry Smith /*@
3741bb7acecfSBarry Smith   DMGetApplicationContext - Gets a user context from a `DM` object
374247c6ae99SBarry Smith 
374347c6ae99SBarry Smith   Not Collective
374447c6ae99SBarry Smith 
374547c6ae99SBarry Smith   Input Parameter:
3746bb7acecfSBarry Smith . dm - the `DM` object
374747c6ae99SBarry Smith 
374847c6ae99SBarry Smith   Output Parameter:
374947c6ae99SBarry Smith . ctx - the user context
375047c6ae99SBarry Smith 
375147c6ae99SBarry Smith   Level: intermediate
375247c6ae99SBarry Smith 
3753bb7acecfSBarry Smith   Note:
375435cb6cd3SPierre Jolivet   A user context is a way to pass problem specific information that is accessible whenever the `DM` is available
3755bb7acecfSBarry Smith 
375642747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
375747c6ae99SBarry Smith @*/
3758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetApplicationContext(DM dm, void *ctx)
3759d71ae5a4SJacob Faibussowitsch {
376047c6ae99SBarry Smith   PetscFunctionBegin;
3761171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37621b2093e4SBarry Smith   *(void **)ctx = dm->ctx;
37633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
376447c6ae99SBarry Smith }
376547c6ae99SBarry Smith 
376608da532bSDmitry Karpeev /*@C
3767bb7acecfSBarry Smith   DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for `SNESVI`.
376808da532bSDmitry Karpeev 
376920f4b53cSBarry Smith   Logically Collective
377008da532bSDmitry Karpeev 
3771d8d19677SJose E. Roman   Input Parameters:
377208da532bSDmitry Karpeev + dm - the DM object
377320f4b53cSBarry Smith - f  - the function that computes variable bounds used by SNESVI (use `NULL` to cancel a previous function that was set)
377408da532bSDmitry Karpeev 
377508da532bSDmitry Karpeev   Level: intermediate
377608da532bSDmitry Karpeev 
37771cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMComputeVariableBounds()`, `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`,
3778db781477SPatrick Sanan          `DMSetJacobian()`
377908da532bSDmitry Karpeev @*/
3780d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetVariableBounds(DM dm, PetscErrorCode (*f)(DM, Vec, Vec))
3781d71ae5a4SJacob Faibussowitsch {
378208da532bSDmitry Karpeev   PetscFunctionBegin;
37835a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
378408da532bSDmitry Karpeev   dm->ops->computevariablebounds = f;
37853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
378608da532bSDmitry Karpeev }
378708da532bSDmitry Karpeev 
378808da532bSDmitry Karpeev /*@
3789bb7acecfSBarry Smith   DMHasVariableBounds - does the `DM` object have a variable bounds function?
379008da532bSDmitry Karpeev 
379108da532bSDmitry Karpeev   Not Collective
379208da532bSDmitry Karpeev 
379308da532bSDmitry Karpeev   Input Parameter:
3794bb7acecfSBarry Smith . dm - the `DM` object to destroy
379508da532bSDmitry Karpeev 
379608da532bSDmitry Karpeev   Output Parameter:
3797bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the variable bounds function exists
379808da532bSDmitry Karpeev 
379908da532bSDmitry Karpeev   Level: developer
380008da532bSDmitry Karpeev 
38011cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMComputeVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
380208da532bSDmitry Karpeev @*/
3803d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasVariableBounds(DM dm, PetscBool *flg)
3804d71ae5a4SJacob Faibussowitsch {
380508da532bSDmitry Karpeev   PetscFunctionBegin;
38065a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38074f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
380808da532bSDmitry Karpeev   *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
38093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
381008da532bSDmitry Karpeev }
381108da532bSDmitry Karpeev 
3812cc4c1da9SBarry Smith /*@
3813bb7acecfSBarry Smith   DMComputeVariableBounds - compute variable bounds used by `SNESVI`.
381408da532bSDmitry Karpeev 
381520f4b53cSBarry Smith   Logically Collective
381608da532bSDmitry Karpeev 
3817f899ff85SJose E. Roman   Input Parameter:
3818bb7acecfSBarry Smith . dm - the `DM` object
381908da532bSDmitry Karpeev 
382060225df5SJacob Faibussowitsch   Output Parameters:
382108da532bSDmitry Karpeev + xl - lower bound
382208da532bSDmitry Karpeev - xu - upper bound
382308da532bSDmitry Karpeev 
3824907376e6SBarry Smith   Level: advanced
3825907376e6SBarry Smith 
382620f4b53cSBarry Smith   Note:
382795452b02SPatrick Sanan   This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
382808da532bSDmitry Karpeev 
38291cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
383008da532bSDmitry Karpeev @*/
3831d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3832d71ae5a4SJacob Faibussowitsch {
383308da532bSDmitry Karpeev   PetscFunctionBegin;
38345a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
383508da532bSDmitry Karpeev   PetscValidHeaderSpecific(xl, VEC_CLASSID, 2);
38365a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(xu, VEC_CLASSID, 3);
3837dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, computevariablebounds, xl, xu);
38383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
383908da532bSDmitry Karpeev }
384008da532bSDmitry Karpeev 
3841b0ae01b7SPeter Brune /*@
3842bb7acecfSBarry Smith   DMHasColoring - does the `DM` object have a method of providing a coloring?
3843b0ae01b7SPeter Brune 
3844b0ae01b7SPeter Brune   Not Collective
3845b0ae01b7SPeter Brune 
3846b0ae01b7SPeter Brune   Input Parameter:
3847b0ae01b7SPeter Brune . dm - the DM object
3848b0ae01b7SPeter Brune 
3849b0ae01b7SPeter Brune   Output Parameter:
3850bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateColoring()`.
3851b0ae01b7SPeter Brune 
3852b0ae01b7SPeter Brune   Level: developer
3853b0ae01b7SPeter Brune 
38541cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateColoring()`
3855b0ae01b7SPeter Brune @*/
3856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasColoring(DM dm, PetscBool *flg)
3857d71ae5a4SJacob Faibussowitsch {
3858b0ae01b7SPeter Brune   PetscFunctionBegin;
38595a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38604f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
3861b0ae01b7SPeter Brune   *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
38623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3863b0ae01b7SPeter Brune }
3864b0ae01b7SPeter Brune 
38653ad4599aSBarry Smith /*@
3866bb7acecfSBarry Smith   DMHasCreateRestriction - does the `DM` object have a method of providing a restriction?
38673ad4599aSBarry Smith 
38683ad4599aSBarry Smith   Not Collective
38693ad4599aSBarry Smith 
38703ad4599aSBarry Smith   Input Parameter:
3871bb7acecfSBarry Smith . dm - the `DM` object
38723ad4599aSBarry Smith 
38733ad4599aSBarry Smith   Output Parameter:
3874bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateRestriction()`.
38753ad4599aSBarry Smith 
38763ad4599aSBarry Smith   Level: developer
38773ad4599aSBarry Smith 
38781cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateRestriction()`, `DMHasCreateInterpolation()`, `DMHasCreateInjection()`
38793ad4599aSBarry Smith @*/
3880d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateRestriction(DM dm, PetscBool *flg)
3881d71ae5a4SJacob Faibussowitsch {
38823ad4599aSBarry Smith   PetscFunctionBegin;
38835a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38844f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
38853ad4599aSBarry Smith   *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
38863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38873ad4599aSBarry Smith }
38883ad4599aSBarry Smith 
3889a7058e45SLawrence Mitchell /*@
3890bb7acecfSBarry Smith   DMHasCreateInjection - does the `DM` object have a method of providing an injection?
3891a7058e45SLawrence Mitchell 
3892a7058e45SLawrence Mitchell   Not Collective
3893a7058e45SLawrence Mitchell 
3894a7058e45SLawrence Mitchell   Input Parameter:
3895bb7acecfSBarry Smith . dm - the `DM` object
3896a7058e45SLawrence Mitchell 
3897a7058e45SLawrence Mitchell   Output Parameter:
3898bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateInjection()`.
3899a7058e45SLawrence Mitchell 
3900a7058e45SLawrence Mitchell   Level: developer
3901a7058e45SLawrence Mitchell 
39021cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateInjection()`, `DMHasCreateRestriction()`, `DMHasCreateInterpolation()`
3903a7058e45SLawrence Mitchell @*/
3904d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateInjection(DM dm, PetscBool *flg)
3905d71ae5a4SJacob Faibussowitsch {
3906a7058e45SLawrence Mitchell   PetscFunctionBegin;
39075a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39084f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
3909dbbe0bcdSBarry Smith   if (dm->ops->hascreateinjection) PetscUseTypeMethod(dm, hascreateinjection, flg);
3910ad540459SPierre Jolivet   else *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE;
39113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3912a7058e45SLawrence Mitchell }
3913a7058e45SLawrence Mitchell 
39140298fd71SBarry Smith PetscFunctionList DMList              = NULL;
3915264ace61SBarry Smith PetscBool         DMRegisterAllCalled = PETSC_FALSE;
3916264ace61SBarry Smith 
3917cc4c1da9SBarry Smith /*@
3918bb7acecfSBarry Smith   DMSetType - Builds a `DM`, for a particular `DM` implementation.
3919264ace61SBarry Smith 
392020f4b53cSBarry Smith   Collective
3921264ace61SBarry Smith 
3922264ace61SBarry Smith   Input Parameters:
3923bb7acecfSBarry Smith + dm     - The `DM` object
3924bb7acecfSBarry Smith - method - The name of the `DMType`, for example `DMDA`, `DMPLEX`
3925264ace61SBarry Smith 
3926264ace61SBarry Smith   Options Database Key:
3927bb7acecfSBarry Smith . -dm_type <type> - Sets the `DM` type; use -help for a list of available types
3928264ace61SBarry Smith 
3929264ace61SBarry Smith   Level: intermediate
3930264ace61SBarry Smith 
3931bb7acecfSBarry Smith   Note:
39320462cc06SPierre Jolivet   Of the `DM` is constructed by directly calling a function to construct a particular `DM`, for example, `DMDACreate2d()` or `DMPlexCreateBoxMesh()`
3933bb7acecfSBarry Smith 
39341cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMDA`, `DMPLEX`, `DMGetType()`, `DMCreate()`, `DMDACreate2d()`
3935264ace61SBarry Smith @*/
3936d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetType(DM dm, DMType method)
3937d71ae5a4SJacob Faibussowitsch {
3938264ace61SBarry Smith   PetscErrorCode (*r)(DM);
3939264ace61SBarry Smith   PetscBool match;
3940264ace61SBarry Smith 
3941264ace61SBarry Smith   PetscFunctionBegin;
3942264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, method, &match));
39443ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
3945264ace61SBarry Smith 
39469566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
39479566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(DMList, method, &r));
39487a8be351SBarry Smith   PetscCheck(r, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3949264ace61SBarry Smith 
3950dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, destroy);
39519566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(dm->ops, sizeof(*dm->ops)));
39529566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)dm, method));
39539566063dSJacob Faibussowitsch   PetscCall((*r)(dm));
39543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3955264ace61SBarry Smith }
3956264ace61SBarry Smith 
3957cc4c1da9SBarry Smith /*@
3958bb7acecfSBarry Smith   DMGetType - Gets the `DM` type name (as a string) from the `DM`.
3959264ace61SBarry Smith 
3960264ace61SBarry Smith   Not Collective
3961264ace61SBarry Smith 
3962264ace61SBarry Smith   Input Parameter:
3963bb7acecfSBarry Smith . dm - The `DM`
3964264ace61SBarry Smith 
3965264ace61SBarry Smith   Output Parameter:
3966bb7acecfSBarry Smith . type - The `DMType` name
3967264ace61SBarry Smith 
3968264ace61SBarry Smith   Level: intermediate
3969264ace61SBarry Smith 
39701cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMDA`, `DMPLEX`, `DMSetType()`, `DMCreate()`
3971264ace61SBarry Smith @*/
3972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetType(DM dm, DMType *type)
3973d71ae5a4SJacob Faibussowitsch {
3974264ace61SBarry Smith   PetscFunctionBegin;
3975264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39764f572ea9SToby Isaac   PetscAssertPointer(type, 2);
39779566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
3978264ace61SBarry Smith   *type = ((PetscObject)dm)->type_name;
39793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3980264ace61SBarry Smith }
3981264ace61SBarry Smith 
39825d83a8b1SBarry Smith /*@
3983bb7acecfSBarry Smith   DMConvert - Converts a `DM` to another `DM`, either of the same or different type.
398467a56275SMatthew G Knepley 
398520f4b53cSBarry Smith   Collective
398667a56275SMatthew G Knepley 
398767a56275SMatthew G Knepley   Input Parameters:
3988bb7acecfSBarry Smith + dm      - the `DM`
3989bb7acecfSBarry Smith - newtype - new `DM` type (use "same" for the same type)
399067a56275SMatthew G Knepley 
399167a56275SMatthew G Knepley   Output Parameter:
3992bb7acecfSBarry Smith . M - pointer to new `DM`
399367a56275SMatthew G Knepley 
399420f4b53cSBarry Smith   Level: intermediate
399520f4b53cSBarry Smith 
399673ff1848SBarry Smith   Note:
3997bb7acecfSBarry Smith   Cannot be used to convert a sequential `DM` to a parallel or a parallel to sequential,
3998bb7acecfSBarry Smith   the MPI communicator of the generated `DM` is always the same as the communicator
3999bb7acecfSBarry Smith   of the input `DM`.
400067a56275SMatthew G Knepley 
40011cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetType()`, `DMCreate()`, `DMClone()`
400267a56275SMatthew G Knepley @*/
4003d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
4004d71ae5a4SJacob Faibussowitsch {
400567a56275SMatthew G Knepley   DM        B;
400667a56275SMatthew G Knepley   char      convname[256];
4007c067b6caSMatthew G. Knepley   PetscBool sametype /*, issame */;
400867a56275SMatthew G Knepley 
400967a56275SMatthew G Knepley   PetscFunctionBegin;
401067a56275SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
401167a56275SMatthew G Knepley   PetscValidType(dm, 1);
40124f572ea9SToby Isaac   PetscAssertPointer(M, 3);
40139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, newtype, &sametype));
40149566063dSJacob Faibussowitsch   /* PetscCall(PetscStrcmp(newtype, "same", &issame)); */
4015c067b6caSMatthew G. Knepley   if (sametype) {
4016c067b6caSMatthew G. Knepley     *M = dm;
40179566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
40183ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
4019c067b6caSMatthew G. Knepley   } else {
40200298fd71SBarry Smith     PetscErrorCode (*conv)(DM, DMType, DM *) = NULL;
402167a56275SMatthew G Knepley 
402267a56275SMatthew G Knepley     /*
402367a56275SMatthew G Knepley        Order of precedence:
402467a56275SMatthew G Knepley        1) See if a specialized converter is known to the current DM.
402567a56275SMatthew G Knepley        2) See if a specialized converter is known to the desired DM class.
402667a56275SMatthew G Knepley        3) See if a good general converter is registered for the desired class
402767a56275SMatthew G Knepley        4) See if a good general converter is known for the current matrix.
402867a56275SMatthew G Knepley        5) Use a really basic converter.
402967a56275SMatthew G Knepley     */
403067a56275SMatthew G Knepley 
403167a56275SMatthew G Knepley     /* 1) See if a specialized converter is known to the current DM and the desired class */
40329566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
40339566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
40349566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
40359566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
40369566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
40379566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)dm, convname, &conv));
403867a56275SMatthew G Knepley     if (conv) goto foundconv;
403967a56275SMatthew G Knepley 
404067a56275SMatthew G Knepley     /* 2)  See if a specialized converter is known to the desired DM class. */
40419566063dSJacob Faibussowitsch     PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &B));
40429566063dSJacob Faibussowitsch     PetscCall(DMSetType(B, newtype));
40439566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
40449566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
40459566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
40469566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
40479566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
40489566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
404967a56275SMatthew G Knepley     if (conv) {
40509566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&B));
405167a56275SMatthew G Knepley       goto foundconv;
405267a56275SMatthew G Knepley     }
405367a56275SMatthew G Knepley 
405467a56275SMatthew G Knepley #if 0
405567a56275SMatthew G Knepley     /* 3) See if a good general converter is registered for the desired class */
405667a56275SMatthew G Knepley     conv = B->ops->convertfrom;
40579566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&B));
405867a56275SMatthew G Knepley     if (conv) goto foundconv;
405967a56275SMatthew G Knepley 
406067a56275SMatthew G Knepley     /* 4) See if a good general converter is known for the current matrix */
406167a56275SMatthew G Knepley     if (dm->ops->convert) {
406267a56275SMatthew G Knepley       conv = dm->ops->convert;
406367a56275SMatthew G Knepley     }
406467a56275SMatthew G Knepley     if (conv) goto foundconv;
406567a56275SMatthew G Knepley #endif
406667a56275SMatthew G Knepley 
406767a56275SMatthew G Knepley     /* 5) Use a really basic converter. */
406898921bdaSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject)dm)->type_name, newtype);
406967a56275SMatthew G Knepley 
407067a56275SMatthew G Knepley   foundconv:
40719566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(DM_Convert, dm, 0, 0, 0));
40729566063dSJacob Faibussowitsch     PetscCall((*conv)(dm, newtype, M));
407312fa691eSMatthew G. Knepley     /* Things that are independent of DM type: We should consult DMClone() here */
407490b157c4SStefano Zampini     {
40754fb89dddSMatthew G. Knepley       const PetscReal *maxCell, *Lstart, *L;
40766858538eSMatthew G. Knepley 
40774fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
40784fb89dddSMatthew G. Knepley       PetscCall(DMSetPeriodicity(*M, maxCell, Lstart, L));
4079c8a6034eSMark       (*M)->prealloc_only = dm->prealloc_only;
40809566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->vectype));
40819566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*M)->vectype));
40829566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->mattype));
40839566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*M)->mattype));
408412fa691eSMatthew G. Knepley     }
40859566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(DM_Convert, dm, 0, 0, 0));
408667a56275SMatthew G Knepley   }
40879566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
40883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
408967a56275SMatthew G Knepley }
4090264ace61SBarry Smith 
4091264ace61SBarry Smith /*--------------------------------------------------------------------------------------------------------------------*/
4092264ace61SBarry Smith 
4093264ace61SBarry Smith /*@C
4094bb7acecfSBarry Smith   DMRegister -  Adds a new `DM` type implementation
40951c84c290SBarry Smith 
4096cc4c1da9SBarry Smith   Not Collective, No Fortran Support
40971c84c290SBarry Smith 
40981c84c290SBarry Smith   Input Parameters:
409920f4b53cSBarry Smith + sname    - The name of a new user-defined creation routine
410020f4b53cSBarry Smith - function - The creation routine itself
410120f4b53cSBarry Smith 
410220f4b53cSBarry Smith   Level: advanced
41031c84c290SBarry Smith 
410473ff1848SBarry Smith   Note:
410520f4b53cSBarry Smith   `DMRegister()` may be called multiple times to add several user-defined `DM`s
41061c84c290SBarry Smith 
410760225df5SJacob Faibussowitsch   Example Usage:
41081c84c290SBarry Smith .vb
4109bdf89e91SBarry Smith     DMRegister("my_da", MyDMCreate);
41101c84c290SBarry Smith .ve
41111c84c290SBarry Smith 
411220f4b53cSBarry Smith   Then, your `DM` type can be chosen with the procedural interface via
41131c84c290SBarry Smith .vb
41141c84c290SBarry Smith     DMCreate(MPI_Comm, DM *);
41151c84c290SBarry Smith     DMSetType(DM,"my_da");
41161c84c290SBarry Smith .ve
41171c84c290SBarry Smith   or at runtime via the option
41181c84c290SBarry Smith .vb
41191c84c290SBarry Smith     -da_type my_da
41201c84c290SBarry Smith .ve
4121264ace61SBarry Smith 
41221cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMSetType()`, `DMRegisterAll()`, `DMRegisterDestroy()`
4123264ace61SBarry Smith @*/
4124d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRegister(const char sname[], PetscErrorCode (*function)(DM))
4125d71ae5a4SJacob Faibussowitsch {
4126264ace61SBarry Smith   PetscFunctionBegin;
41279566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
41289566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&DMList, sname, function));
41293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4130264ace61SBarry Smith }
4131264ace61SBarry Smith 
4132ffeef943SBarry Smith /*@
4133bb7acecfSBarry Smith   DMLoad - Loads a DM that has been stored in binary  with `DMView()`.
4134b859378eSBarry Smith 
413520f4b53cSBarry Smith   Collective
4136b859378eSBarry Smith 
4137b859378eSBarry Smith   Input Parameters:
4138bb7acecfSBarry Smith + newdm  - the newly loaded `DM`, this needs to have been created with `DMCreate()` or
4139bb7acecfSBarry Smith            some related function before a call to `DMLoad()`.
4140bb7acecfSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` or
4141bb7acecfSBarry Smith            `PETSCVIEWERHDF5` file viewer, obtained from `PetscViewerHDF5Open()`
4142b859378eSBarry Smith 
4143b859378eSBarry Smith   Level: intermediate
4144b859378eSBarry Smith 
4145b859378eSBarry Smith   Notes:
414655849f57SBarry Smith   The type is determined by the data in the file, any type set into the DM before this call is ignored.
4147b859378eSBarry Smith 
4148bb7acecfSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
4149bb7acecfSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
4150bb7acecfSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
4151cd7e8a5eSksagiyam 
41521cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscViewerBinaryOpen()`, `DMView()`, `MatLoad()`, `VecLoad()`
4153b859378eSBarry Smith @*/
4154d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
4155d71ae5a4SJacob Faibussowitsch {
41569331c7a4SMatthew G. Knepley   PetscBool isbinary, ishdf5;
4157b859378eSBarry Smith 
4158b859378eSBarry Smith   PetscFunctionBegin;
4159b859378eSBarry Smith   PetscValidHeaderSpecific(newdm, DM_CLASSID, 1);
4160b859378eSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
41619566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckReadable(viewer));
41629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
41639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
41649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Load, viewer, 0, 0, 0));
41659331c7a4SMatthew G. Knepley   if (isbinary) {
41669331c7a4SMatthew G. Knepley     PetscInt classid;
41679331c7a4SMatthew G. Knepley     char     type[256];
4168b859378eSBarry Smith 
41699566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
4170835f2295SStefano Zampini     PetscCheck(classid == DM_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not DM next in file, classid found %" PetscInt_FMT, classid);
41719566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
41729566063dSJacob Faibussowitsch     PetscCall(DMSetType(newdm, type));
4173dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41749331c7a4SMatthew G. Knepley   } else if (ishdf5) {
4175dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41769331c7a4SMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
41779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Load, viewer, 0, 0, 0));
41783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4179b859378eSBarry Smith }
4180b859378eSBarry Smith 
41814ee01570SBarry Smith /* FEM Support */
41827da65231SMatthew G Knepley 
41832ecf6ec3SMatthew G. Knepley PetscErrorCode DMPrintCellIndices(PetscInt c, const char name[], PetscInt len, const PetscInt x[])
41842ecf6ec3SMatthew G. Knepley {
41852ecf6ec3SMatthew G. Knepley   PetscInt f;
41862ecf6ec3SMatthew G. Knepley 
41872ecf6ec3SMatthew G. Knepley   PetscFunctionBegin;
41882ecf6ec3SMatthew G. Knepley   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
41892ecf6ec3SMatthew G. Knepley   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %" PetscInt_FMT " |\n", x[f]));
41902ecf6ec3SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
41912ecf6ec3SMatthew G. Knepley }
41922ecf6ec3SMatthew G. Knepley 
4193d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
4194d71ae5a4SJacob Faibussowitsch {
41951d47ebbbSSatish Balay   PetscInt f;
41961b30c384SMatthew G Knepley 
41977da65231SMatthew G Knepley   PetscFunctionBegin;
419863a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
419948a46eb9SPierre Jolivet   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f])));
42003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42017da65231SMatthew G Knepley }
42027da65231SMatthew G Knepley 
42035962854dSMatthew G. Knepley PetscErrorCode DMPrintCellVectorReal(PetscInt c, const char name[], PetscInt len, const PetscReal x[])
42045962854dSMatthew G. Knepley {
42055962854dSMatthew G. Knepley   PetscInt f;
42065962854dSMatthew G. Knepley 
42075962854dSMatthew G. Knepley   PetscFunctionBegin;
42085962854dSMatthew G. Knepley   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
42095962854dSMatthew G. Knepley   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)x[f]));
42105962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
42115962854dSMatthew G. Knepley }
42125962854dSMatthew G. Knepley 
4213d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
4214d71ae5a4SJacob Faibussowitsch {
42151b30c384SMatthew G Knepley   PetscInt f, g;
42167da65231SMatthew G Knepley 
42177da65231SMatthew G Knepley   PetscFunctionBegin;
421863a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
42191d47ebbbSSatish Balay   for (f = 0; f < rows; ++f) {
42209566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  |"));
422148a46eb9SPierre Jolivet     for (g = 0; g < cols; ++g) PetscCall(PetscPrintf(PETSC_COMM_SELF, " % 9.5g", (double)PetscRealPart(A[f * cols + g])));
42229566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, " |\n"));
42237da65231SMatthew G Knepley   }
42243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42257da65231SMatthew G Knepley }
4226e7c4fc90SDmitry Karpeev 
4227d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
4228d71ae5a4SJacob Faibussowitsch {
42290c5b8624SToby Isaac   PetscInt           localSize, bs;
42300c5b8624SToby Isaac   PetscMPIInt        size;
42310c5b8624SToby Isaac   Vec                x, xglob;
42320c5b8624SToby Isaac   const PetscScalar *xarray;
4233e759306cSMatthew G. Knepley 
4234e759306cSMatthew G. Knepley   PetscFunctionBegin;
42359566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
42369566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, &x));
42379566063dSJacob Faibussowitsch   PetscCall(VecCopy(X, x));
423893ec0da9SPierre Jolivet   PetscCall(VecFilter(x, tol));
42399566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "%s:\n", name));
42400c5b8624SToby Isaac   if (size > 1) {
42419566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(x, &localSize));
42429566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xarray));
42439566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(x, &bs));
42449566063dSJacob Faibussowitsch     PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)dm), bs, localSize, PETSC_DETERMINE, xarray, &xglob));
42450c5b8624SToby Isaac   } else {
42460c5b8624SToby Isaac     xglob = x;
42470c5b8624SToby Isaac   }
42489566063dSJacob Faibussowitsch   PetscCall(VecView(xglob, PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)dm))));
42490c5b8624SToby Isaac   if (size > 1) {
42509566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xglob));
42519566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xarray));
42520c5b8624SToby Isaac   }
42539566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
42543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4255e759306cSMatthew G. Knepley }
4256e759306cSMatthew G. Knepley 
425788ed4aceSMatthew G Knepley /*@
4258bb7acecfSBarry Smith   DMGetSection - Get the `PetscSection` encoding the local data layout for the `DM`.   This is equivalent to `DMGetLocalSection()`. Deprecated in v3.12
4259061576a5SJed Brown 
4260061576a5SJed Brown   Input Parameter:
4261bb7acecfSBarry Smith . dm - The `DM`
4262061576a5SJed Brown 
4263061576a5SJed Brown   Output Parameter:
4264bb7acecfSBarry Smith . section - The `PetscSection`
4265061576a5SJed Brown 
426620f4b53cSBarry Smith   Options Database Key:
4267bb7acecfSBarry Smith . -dm_petscsection_view - View the `PetscSection` created by the `DM`
4268061576a5SJed Brown 
4269061576a5SJed Brown   Level: advanced
4270061576a5SJed Brown 
4271061576a5SJed Brown   Notes:
4272bb7acecfSBarry Smith   Use `DMGetLocalSection()` in new code.
4273061576a5SJed Brown 
4274bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
4275061576a5SJed Brown 
42761cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetLocalSection()`, `DMSetLocalSection()`, `DMGetGlobalSection()`
4277061576a5SJed Brown @*/
4278d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSection(DM dm, PetscSection *section)
4279d71ae5a4SJacob Faibussowitsch {
4280061576a5SJed Brown   PetscFunctionBegin;
42819566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, section));
42823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4283061576a5SJed Brown }
4284061576a5SJed Brown 
4285061576a5SJed Brown /*@
4286bb7acecfSBarry Smith   DMGetLocalSection - Get the `PetscSection` encoding the local data layout for the `DM`.
428788ed4aceSMatthew G Knepley 
428888ed4aceSMatthew G Knepley   Input Parameter:
4289bb7acecfSBarry Smith . dm - The `DM`
429088ed4aceSMatthew G Knepley 
429188ed4aceSMatthew G Knepley   Output Parameter:
4292bb7acecfSBarry Smith . section - The `PetscSection`
429388ed4aceSMatthew G Knepley 
429420f4b53cSBarry Smith   Options Database Key:
4295bb7acecfSBarry Smith . -dm_petscsection_view - View the section created by the `DM`
4296e5893cccSMatthew G. Knepley 
429788ed4aceSMatthew G Knepley   Level: intermediate
429888ed4aceSMatthew G Knepley 
4299bb7acecfSBarry Smith   Note:
4300bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
430188ed4aceSMatthew G Knepley 
43021cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetGlobalSection()`
430388ed4aceSMatthew G Knepley @*/
4304d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section)
4305d71ae5a4SJacob Faibussowitsch {
430688ed4aceSMatthew G Knepley   PetscFunctionBegin;
430788ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
43084f572ea9SToby Isaac   PetscAssertPointer(section, 2);
43091bb6d2a8SBarry Smith   if (!dm->localSection && dm->ops->createlocalsection) {
4310e5e52638SMatthew G. Knepley     PetscInt d;
4311e5e52638SMatthew G. Knepley 
431245480ffeSMatthew G. Knepley     if (dm->setfromoptionscalled) {
431345480ffeSMatthew G. Knepley       PetscObject       obj = (PetscObject)dm;
431445480ffeSMatthew G. Knepley       PetscViewer       viewer;
431545480ffeSMatthew G. Knepley       PetscViewerFormat format;
431645480ffeSMatthew G. Knepley       PetscBool         flg;
431745480ffeSMatthew G. Knepley 
4318648c30bcSBarry Smith       PetscCall(PetscOptionsCreateViewer(PetscObjectComm(obj), obj->options, obj->prefix, "-dm_petscds_view", &viewer, &format, &flg));
43199566063dSJacob Faibussowitsch       if (flg) PetscCall(PetscViewerPushFormat(viewer, format));
432045480ffeSMatthew G. Knepley       for (d = 0; d < dm->Nds; ++d) {
43219566063dSJacob Faibussowitsch         PetscCall(PetscDSSetFromOptions(dm->probs[d].ds));
43229566063dSJacob Faibussowitsch         if (flg) PetscCall(PetscDSView(dm->probs[d].ds, viewer));
432345480ffeSMatthew G. Knepley       }
432445480ffeSMatthew G. Knepley       if (flg) {
43259566063dSJacob Faibussowitsch         PetscCall(PetscViewerFlush(viewer));
43269566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4327648c30bcSBarry Smith         PetscCall(PetscViewerDestroy(&viewer));
432845480ffeSMatthew G. Knepley       }
432945480ffeSMatthew G. Knepley     }
4330dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createlocalsection);
43319566063dSJacob Faibussowitsch     if (dm->localSection) PetscCall(PetscObjectViewFromOptions((PetscObject)dm->localSection, NULL, "-dm_petscsection_view"));
43322f0f8703SMatthew G. Knepley   }
43331bb6d2a8SBarry Smith   *section = dm->localSection;
43343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
433588ed4aceSMatthew G Knepley }
433688ed4aceSMatthew G Knepley 
433788ed4aceSMatthew G Knepley /*@
4338bb7acecfSBarry Smith   DMSetSection - Set the `PetscSection` encoding the local data layout for the `DM`.  This is equivalent to `DMSetLocalSection()`. Deprecated in v3.12
4339061576a5SJed Brown 
4340061576a5SJed Brown   Input Parameters:
4341bb7acecfSBarry Smith + dm      - The `DM`
4342bb7acecfSBarry Smith - section - The `PetscSection`
4343061576a5SJed Brown 
4344061576a5SJed Brown   Level: advanced
4345061576a5SJed Brown 
4346061576a5SJed Brown   Notes:
4347bb7acecfSBarry Smith   Use `DMSetLocalSection()` in new code.
4348061576a5SJed Brown 
4349bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4350061576a5SJed Brown 
43511cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetLocalSection()`, `DMSetGlobalSection()`
4352061576a5SJed Brown @*/
4353d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSection(DM dm, PetscSection section)
4354d71ae5a4SJacob Faibussowitsch {
4355061576a5SJed Brown   PetscFunctionBegin;
43569566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(dm, section));
43573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4358061576a5SJed Brown }
4359061576a5SJed Brown 
4360061576a5SJed Brown /*@
4361bb7acecfSBarry Smith   DMSetLocalSection - Set the `PetscSection` encoding the local data layout for the `DM`.
436288ed4aceSMatthew G Knepley 
436388ed4aceSMatthew G Knepley   Input Parameters:
4364bb7acecfSBarry Smith + dm      - The `DM`
4365bb7acecfSBarry Smith - section - The `PetscSection`
436688ed4aceSMatthew G Knepley 
436788ed4aceSMatthew G Knepley   Level: intermediate
436888ed4aceSMatthew G Knepley 
4369bb7acecfSBarry Smith   Note:
4370bb7acecfSBarry Smith   Any existing Section will be destroyed
437188ed4aceSMatthew G Knepley 
43721cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscSection`, `DMGetLocalSection()`, `DMSetGlobalSection()`
437388ed4aceSMatthew G Knepley @*/
4374d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLocalSection(DM dm, PetscSection section)
4375d71ae5a4SJacob Faibussowitsch {
4376c473ab19SMatthew G. Knepley   PetscInt numFields = 0;
4377af122d2aSMatthew G Knepley   PetscInt f;
437888ed4aceSMatthew G Knepley 
437988ed4aceSMatthew G Knepley   PetscFunctionBegin;
438088ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4381b9d85ea2SLisandro Dalcin   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
43829566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
43839566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->localSection));
43841bb6d2a8SBarry Smith   dm->localSection = section;
43859566063dSJacob Faibussowitsch   if (section) PetscCall(PetscSectionGetNumFields(dm->localSection, &numFields));
4386af122d2aSMatthew G Knepley   if (numFields) {
43879566063dSJacob Faibussowitsch     PetscCall(DMSetNumFields(dm, numFields));
4388af122d2aSMatthew G Knepley     for (f = 0; f < numFields; ++f) {
43890f21e855SMatthew G. Knepley       PetscObject disc;
4390af122d2aSMatthew G Knepley       const char *name;
4391af122d2aSMatthew G Knepley 
43929566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(dm->localSection, f, &name));
43939566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, &disc));
43949566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName(disc, name));
4395af122d2aSMatthew G Knepley     }
4396af122d2aSMatthew G Knepley   }
439750350c8eSStefano Zampini   /* The global section and the SectionSF will be rebuilt
439850350c8eSStefano Zampini      in the next call to DMGetGlobalSection() and DMGetSectionSF(). */
43999566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
440050350c8eSStefano Zampini   PetscCall(PetscSFDestroy(&dm->sectionSF));
440152947b74SStefano Zampini   PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &dm->sectionSF));
440250350c8eSStefano Zampini 
440350350c8eSStefano Zampini   /* Clear scratch vectors */
440450350c8eSStefano Zampini   PetscCall(DMClearGlobalVectors(dm));
440550350c8eSStefano Zampini   PetscCall(DMClearLocalVectors(dm));
440650350c8eSStefano Zampini   PetscCall(DMClearNamedGlobalVectors(dm));
440750350c8eSStefano Zampini   PetscCall(DMClearNamedLocalVectors(dm));
44083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
440988ed4aceSMatthew G Knepley }
441088ed4aceSMatthew G Knepley 
4411adc21957SMatthew G. Knepley /*@C
4412d8b4a066SPierre Jolivet   DMCreateSectionPermutation - Create a permutation of the `PetscSection` chart and optionally a block structure.
4413adc21957SMatthew G. Knepley 
4414adc21957SMatthew G. Knepley   Input Parameter:
4415adc21957SMatthew G. Knepley . dm - The `DM`
4416adc21957SMatthew G. Knepley 
44179cde84edSJose E. Roman   Output Parameters:
4418adc21957SMatthew G. Knepley + perm        - A permutation of the mesh points in the chart
4419b6971eaeSBarry Smith - blockStarts - A high bit is set for the point that begins every block, or `NULL` for default blocking
4420adc21957SMatthew G. Knepley 
4421adc21957SMatthew G. Knepley   Level: developer
4422adc21957SMatthew G. Knepley 
4423adc21957SMatthew G. Knepley .seealso: [](ch_dmbase), `DM`, `PetscSection`, `DMGetLocalSection()`, `DMGetGlobalSection()`
4424adc21957SMatthew G. Knepley @*/
4425adc21957SMatthew G. Knepley PetscErrorCode DMCreateSectionPermutation(DM dm, IS *perm, PetscBT *blockStarts)
4426adc21957SMatthew G. Knepley {
4427adc21957SMatthew G. Knepley   PetscFunctionBegin;
4428adc21957SMatthew G. Knepley   *perm        = NULL;
4429adc21957SMatthew G. Knepley   *blockStarts = NULL;
4430adc21957SMatthew G. Knepley   PetscTryTypeMethod(dm, createsectionpermutation, perm, blockStarts);
4431adc21957SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
4432adc21957SMatthew G. Knepley }
4433adc21957SMatthew G. Knepley 
44349435951eSToby Isaac /*@
4435bb7acecfSBarry Smith   DMGetDefaultConstraints - Get the `PetscSection` and `Mat` that specify the local constraint interpolation. See `DMSetDefaultConstraints()` for a description of the purpose of constraint interpolation.
44369435951eSToby Isaac 
443720f4b53cSBarry Smith   not Collective
4438e228b242SToby Isaac 
44399435951eSToby Isaac   Input Parameter:
4440bb7acecfSBarry Smith . dm - The `DM`
44419435951eSToby Isaac 
4442d8d19677SJose E. Roman   Output Parameters:
444320f4b53cSBarry 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.
444420f4b53cSBarry 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.
444579769bd5SJed Brown - bias    - Vector containing bias to be added to constrained dofs
44469435951eSToby Isaac 
44479435951eSToby Isaac   Level: advanced
44489435951eSToby Isaac 
4449bb7acecfSBarry Smith   Note:
4450bb7acecfSBarry Smith   This gets borrowed references, so the user should not destroy the `PetscSection`, `Mat`, or `Vec`.
44519435951eSToby Isaac 
44521cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetDefaultConstraints()`
44539435951eSToby Isaac @*/
4454d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat, Vec *bias)
4455d71ae5a4SJacob Faibussowitsch {
44569435951eSToby Isaac   PetscFunctionBegin;
44579435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4458dbbe0bcdSBarry Smith   if (!dm->defaultConstraint.section && !dm->defaultConstraint.mat && dm->ops->createdefaultconstraints) PetscUseTypeMethod(dm, createdefaultconstraints);
44593b8ba7d1SJed Brown   if (section) *section = dm->defaultConstraint.section;
44603b8ba7d1SJed Brown   if (mat) *mat = dm->defaultConstraint.mat;
446179769bd5SJed Brown   if (bias) *bias = dm->defaultConstraint.bias;
44623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44639435951eSToby Isaac }
44649435951eSToby Isaac 
44659435951eSToby Isaac /*@
4466bb7acecfSBarry Smith   DMSetDefaultConstraints - Set the `PetscSection` and `Mat` that specify the local constraint interpolation.
44679435951eSToby Isaac 
446820f4b53cSBarry Smith   Collective
4469e228b242SToby Isaac 
44709435951eSToby Isaac   Input Parameters:
4471bb7acecfSBarry Smith + dm      - The `DM`
4472bb7acecfSBarry 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).
447320f4b53cSBarry 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).
447420f4b53cSBarry 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).
44759435951eSToby Isaac 
44769435951eSToby Isaac   Level: advanced
44779435951eSToby Isaac 
447820f4b53cSBarry Smith   Notes:
447920f4b53cSBarry 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()`.
448020f4b53cSBarry Smith 
448120f4b53cSBarry 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.
448220f4b53cSBarry Smith 
4483bb7acecfSBarry Smith   This increments the references of the `PetscSection`, `Mat`, and `Vec`, so they user can destroy them.
44849435951eSToby Isaac 
44851cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDefaultConstraints()`
44869435951eSToby Isaac @*/
4487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat, Vec bias)
4488d71ae5a4SJacob Faibussowitsch {
4489e228b242SToby Isaac   PetscMPIInt result;
44909435951eSToby Isaac 
44919435951eSToby Isaac   PetscFunctionBegin;
44929435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4493e228b242SToby Isaac   if (section) {
4494e228b242SToby Isaac     PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
44959566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)section), &result));
44967a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint section must have local communicator");
4497e228b242SToby Isaac   }
4498e228b242SToby Isaac   if (mat) {
4499e228b242SToby Isaac     PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
45009566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)mat), &result));
45017a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint matrix must have local communicator");
4502e228b242SToby Isaac   }
450379769bd5SJed Brown   if (bias) {
450479769bd5SJed Brown     PetscValidHeaderSpecific(bias, VEC_CLASSID, 4);
45059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)bias), &result));
450679769bd5SJed Brown     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint bias must have local communicator");
450779769bd5SJed Brown   }
45089566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
45099566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->defaultConstraint.section));
45103b8ba7d1SJed Brown   dm->defaultConstraint.section = section;
45119566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)mat));
45129566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&dm->defaultConstraint.mat));
45133b8ba7d1SJed Brown   dm->defaultConstraint.mat = mat;
45149566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)bias));
45159566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&dm->defaultConstraint.bias));
451679769bd5SJed Brown   dm->defaultConstraint.bias = bias;
45173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45189435951eSToby Isaac }
45199435951eSToby Isaac 
4520497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
4521507e4973SMatthew G. Knepley /*
4522bb7acecfSBarry Smith   DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. Generates and error if they are not consistent.
4523507e4973SMatthew G. Knepley 
4524507e4973SMatthew G. Knepley   Input Parameters:
4525bb7acecfSBarry Smith + dm - The `DM`
4526bb7acecfSBarry Smith . localSection - `PetscSection` describing the local data layout
4527bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
4528507e4973SMatthew G. Knepley 
4529507e4973SMatthew G. Knepley   Level: intermediate
4530507e4973SMatthew G. Knepley 
45311cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMSetSectionSF()`
4532507e4973SMatthew G. Knepley */
4533d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
4534d71ae5a4SJacob Faibussowitsch {
4535507e4973SMatthew G. Knepley   MPI_Comm        comm;
4536507e4973SMatthew G. Knepley   PetscLayout     layout;
4537507e4973SMatthew G. Knepley   const PetscInt *ranges;
4538507e4973SMatthew G. Knepley   PetscInt        pStart, pEnd, p, nroots;
4539507e4973SMatthew G. Knepley   PetscMPIInt     size, rank;
4540507e4973SMatthew G. Knepley   PetscBool       valid = PETSC_TRUE, gvalid;
4541507e4973SMatthew G. Knepley 
4542507e4973SMatthew G. Knepley   PetscFunctionBegin;
45439566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4544507e4973SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45459566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
45469566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
45479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(globalSection, &pStart, &pEnd));
45489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(globalSection, &nroots));
45499566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &layout));
45509566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
45519566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, nroots));
45529566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(layout));
45539566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRanges(layout, &ranges));
4554507e4973SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4555f741bcd2SMatthew G. Knepley     PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
4556507e4973SMatthew G. Knepley 
45579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(localSection, p, &dof));
45589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(localSection, p, &off));
45599566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(localSection, p, &cdof));
45609566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(globalSection, p, &gdof));
45619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(globalSection, p, &gcdof));
45629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &goff));
4563507e4973SMatthew G. Knepley     if (!gdof) continue; /* Censored point */
45649371c9d4SSatish Balay     if ((gdof < 0 ? -(gdof + 1) : gdof) != dof) {
45659371c9d4SSatish 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));
45669371c9d4SSatish Balay       valid = PETSC_FALSE;
45679371c9d4SSatish Balay     }
45689371c9d4SSatish Balay     if (gcdof && (gcdof != cdof)) {
45699371c9d4SSatish 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));
45709371c9d4SSatish Balay       valid = PETSC_FALSE;
45719371c9d4SSatish Balay     }
4572507e4973SMatthew G. Knepley     if (gdof < 0) {
4573507e4973SMatthew G. Knepley       gsize = gdof < 0 ? -(gdof + 1) - gcdof : gdof - gcdof;
4574507e4973SMatthew G. Knepley       for (d = 0; d < gsize; ++d) {
4575507e4973SMatthew G. Knepley         PetscInt offset = -(goff + 1) + d, r;
4576507e4973SMatthew G. Knepley 
45779566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(offset, size + 1, ranges, &r));
4578507e4973SMatthew G. Knepley         if (r < 0) r = -(r + 2);
45799371c9d4SSatish Balay         if ((r < 0) || (r >= size)) {
45809371c9d4SSatish Balay           PetscCall(PetscSynchronizedPrintf(comm, "[%d]Point %" PetscInt_FMT " mapped to invalid process %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, p, r, gdof, goff));
45819371c9d4SSatish Balay           valid = PETSC_FALSE;
45829371c9d4SSatish Balay           break;
45839371c9d4SSatish Balay         }
4584507e4973SMatthew G. Knepley       }
4585507e4973SMatthew G. Knepley     }
4586507e4973SMatthew G. Knepley   }
45879566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
45889566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
4589462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm));
4590507e4973SMatthew G. Knepley   if (!gvalid) {
45919566063dSJacob Faibussowitsch     PetscCall(DMView(dm, NULL));
4592507e4973SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
4593507e4973SMatthew G. Knepley   }
45943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4595507e4973SMatthew G. Knepley }
4596f741bcd2SMatthew G. Knepley #endif
4597507e4973SMatthew G. Knepley 
4598*90df3356SJames Wright PetscErrorCode DMGetIsoperiodicPointSF_Internal(DM dm, PetscSF *sf)
45996725e60dSJed Brown {
46006725e60dSJed Brown   PetscErrorCode (*f)(DM, PetscSF *);
46014d86920dSPierre Jolivet 
46026725e60dSJed Brown   PetscFunctionBegin;
46036725e60dSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46044f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
46055f06a3ddSJed Brown   PetscCall(PetscObjectQueryFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", &f));
46066725e60dSJed Brown   if (f) PetscCall(f(dm, sf));
46076725e60dSJed Brown   else *sf = dm->sf;
46083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46096725e60dSJed Brown }
46106725e60dSJed Brown 
461188ed4aceSMatthew G Knepley /*@
4612bb7acecfSBarry Smith   DMGetGlobalSection - Get the `PetscSection` encoding the global data layout for the `DM`.
461388ed4aceSMatthew G Knepley 
461420f4b53cSBarry Smith   Collective
46158b1ab98fSJed Brown 
461688ed4aceSMatthew G Knepley   Input Parameter:
4617bb7acecfSBarry Smith . dm - The `DM`
461888ed4aceSMatthew G Knepley 
461988ed4aceSMatthew G Knepley   Output Parameter:
4620bb7acecfSBarry Smith . section - The `PetscSection`
462188ed4aceSMatthew G Knepley 
462288ed4aceSMatthew G Knepley   Level: intermediate
462388ed4aceSMatthew G Knepley 
4624bb7acecfSBarry Smith   Note:
4625bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
462688ed4aceSMatthew G Knepley 
46271cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetLocalSection()`
462888ed4aceSMatthew G Knepley @*/
4629d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section)
4630d71ae5a4SJacob Faibussowitsch {
463188ed4aceSMatthew G Knepley   PetscFunctionBegin;
463288ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46334f572ea9SToby Isaac   PetscAssertPointer(section, 2);
46341bb6d2a8SBarry Smith   if (!dm->globalSection) {
4635fd59a867SMatthew G. Knepley     PetscSection s;
46366725e60dSJed Brown     PetscSF      sf;
4637fd59a867SMatthew G. Knepley 
46389566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &s));
46397a8be351SBarry Smith     PetscCheck(s, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
46407a8be351SBarry Smith     PetscCheck(dm->sf, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection");
46415f06a3ddSJed Brown     PetscCall(DMGetIsoperiodicPointSF_Internal(dm, &sf));
4642eb9d3e4dSMatthew G. Knepley     PetscCall(PetscSectionCreateGlobalSection(s, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &dm->globalSection));
46439566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&dm->map));
46449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map));
46459566063dSJacob Faibussowitsch     PetscCall(PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view"));
464688ed4aceSMatthew G Knepley   }
46471bb6d2a8SBarry Smith   *section = dm->globalSection;
46483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
464988ed4aceSMatthew G Knepley }
465088ed4aceSMatthew G Knepley 
4651b21d0597SMatthew G Knepley /*@
4652bb7acecfSBarry Smith   DMSetGlobalSection - Set the `PetscSection` encoding the global data layout for the `DM`.
4653b21d0597SMatthew G Knepley 
4654b21d0597SMatthew G Knepley   Input Parameters:
4655bb7acecfSBarry Smith + dm      - The `DM`
46562fe279fdSBarry Smith - section - The PetscSection, or `NULL`
4657b21d0597SMatthew G Knepley 
4658b21d0597SMatthew G Knepley   Level: intermediate
4659b21d0597SMatthew G Knepley 
4660bb7acecfSBarry Smith   Note:
4661bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4662b21d0597SMatthew G Knepley 
46631cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetGlobalSection()`, `DMSetLocalSection()`
4664b21d0597SMatthew G Knepley @*/
4665d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section)
4666d71ae5a4SJacob Faibussowitsch {
4667b21d0597SMatthew G Knepley   PetscFunctionBegin;
4668b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46695080bbdbSMatthew G Knepley   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
46709566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
46719566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
46721bb6d2a8SBarry Smith   dm->globalSection = section;
4673497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
46749566063dSJacob Faibussowitsch   if (section) PetscCall(DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section));
4675507e4973SMatthew G. Knepley #endif
467650350c8eSStefano Zampini   /* Clear global scratch vectors and sectionSF */
467750350c8eSStefano Zampini   PetscCall(PetscSFDestroy(&dm->sectionSF));
467852947b74SStefano Zampini   PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &dm->sectionSF));
467950350c8eSStefano Zampini   PetscCall(DMClearGlobalVectors(dm));
468050350c8eSStefano Zampini   PetscCall(DMClearNamedGlobalVectors(dm));
46813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4682b21d0597SMatthew G Knepley }
4683b21d0597SMatthew G Knepley 
468488ed4aceSMatthew G Knepley /*@
4685bb7acecfSBarry Smith   DMGetSectionSF - Get the `PetscSF` encoding the parallel dof overlap for the `DM`. If it has not been set,
4686bb7acecfSBarry Smith   it is created from the default `PetscSection` layouts in the `DM`.
468788ed4aceSMatthew G Knepley 
468888ed4aceSMatthew G Knepley   Input Parameter:
4689bb7acecfSBarry Smith . dm - The `DM`
469088ed4aceSMatthew G Knepley 
469188ed4aceSMatthew G Knepley   Output Parameter:
4692bb7acecfSBarry Smith . sf - The `PetscSF`
469388ed4aceSMatthew G Knepley 
469488ed4aceSMatthew G Knepley   Level: intermediate
469588ed4aceSMatthew G Knepley 
4696bb7acecfSBarry Smith   Note:
4697bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
469888ed4aceSMatthew G Knepley 
46991cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetSectionSF()`, `DMCreateSectionSF()`
470088ed4aceSMatthew G Knepley @*/
4701d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf)
4702d71ae5a4SJacob Faibussowitsch {
470388ed4aceSMatthew G Knepley   PetscInt nroots;
470488ed4aceSMatthew G Knepley 
470588ed4aceSMatthew G Knepley   PetscFunctionBegin;
470688ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47074f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
470848a46eb9SPierre Jolivet   if (!dm->sectionSF) PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &dm->sectionSF));
47099566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL));
471088ed4aceSMatthew G Knepley   if (nroots < 0) {
471188ed4aceSMatthew G Knepley     PetscSection section, gSection;
471288ed4aceSMatthew G Knepley 
47139566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
471431ea6d37SMatthew G Knepley     if (section) {
47159566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gSection));
47169566063dSJacob Faibussowitsch       PetscCall(DMCreateSectionSF(dm, section, gSection));
471731ea6d37SMatthew G Knepley     } else {
47180298fd71SBarry Smith       *sf = NULL;
47193ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
472031ea6d37SMatthew G Knepley     }
472188ed4aceSMatthew G Knepley   }
47221bb6d2a8SBarry Smith   *sf = dm->sectionSF;
47233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
472488ed4aceSMatthew G Knepley }
472588ed4aceSMatthew G Knepley 
472688ed4aceSMatthew G Knepley /*@
4727bb7acecfSBarry Smith   DMSetSectionSF - Set the `PetscSF` encoding the parallel dof overlap for the `DM`
472888ed4aceSMatthew G Knepley 
472988ed4aceSMatthew G Knepley   Input Parameters:
4730bb7acecfSBarry Smith + dm - The `DM`
4731bb7acecfSBarry Smith - sf - The `PetscSF`
473288ed4aceSMatthew G Knepley 
473388ed4aceSMatthew G Knepley   Level: intermediate
473488ed4aceSMatthew G Knepley 
4735bb7acecfSBarry Smith   Note:
4736bb7acecfSBarry Smith   Any previous `PetscSF` is destroyed
473788ed4aceSMatthew G Knepley 
47381cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMCreateSectionSF()`
473988ed4aceSMatthew G Knepley @*/
4740d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf)
4741d71ae5a4SJacob Faibussowitsch {
474288ed4aceSMatthew G Knepley   PetscFunctionBegin;
474388ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4744b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47459566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47469566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sectionSF));
47471bb6d2a8SBarry Smith   dm->sectionSF = sf;
47483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
474988ed4aceSMatthew G Knepley }
475088ed4aceSMatthew G Knepley 
4751cc4c1da9SBarry Smith /*@
4752bb7acecfSBarry Smith   DMCreateSectionSF - Create the `PetscSF` encoding the parallel dof overlap for the `DM` based upon the `PetscSection`s
475388ed4aceSMatthew G Knepley   describing the data layout.
475488ed4aceSMatthew G Knepley 
475588ed4aceSMatthew G Knepley   Input Parameters:
4756bb7acecfSBarry Smith + dm            - The `DM`
4757bb7acecfSBarry Smith . localSection  - `PetscSection` describing the local data layout
4758bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
475988ed4aceSMatthew G Knepley 
47601bb6d2a8SBarry Smith   Level: developer
47611bb6d2a8SBarry Smith 
4762bb7acecfSBarry Smith   Note:
4763bb7acecfSBarry Smith   One usually uses `DMGetSectionSF()` to obtain the `PetscSF`
4764bb7acecfSBarry Smith 
476573ff1848SBarry Smith   Developer Note:
4766bb7acecfSBarry Smith   Since this routine has for arguments the two sections from the `DM` and puts the resulting `PetscSF`
4767bb7acecfSBarry Smith   directly into the `DM`, perhaps this function should not take the local and global sections as
4768b6971eaeSBarry Smith   input and should just obtain them from the `DM`? Plus PETSc creation functions return the thing
4769b6971eaeSBarry Smith   they create, this returns nothing
47701bb6d2a8SBarry Smith 
47711cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
477288ed4aceSMatthew G Knepley @*/
4773d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection)
4774d71ae5a4SJacob Faibussowitsch {
477588ed4aceSMatthew G Knepley   PetscFunctionBegin;
477688ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47779566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphSection(dm->sectionSF, localSection, globalSection));
47783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
477988ed4aceSMatthew G Knepley }
4780af122d2aSMatthew G Knepley 
4781b21d0597SMatthew G Knepley /*@
4782bb7acecfSBarry Smith   DMGetPointSF - Get the `PetscSF` encoding the parallel section point overlap for the `DM`.
4783bb7acecfSBarry Smith 
4784bb7acecfSBarry Smith   Not collective but the resulting `PetscSF` is collective
4785b21d0597SMatthew G Knepley 
4786b21d0597SMatthew G Knepley   Input Parameter:
4787bb7acecfSBarry Smith . dm - The `DM`
4788b21d0597SMatthew G Knepley 
4789b21d0597SMatthew G Knepley   Output Parameter:
4790bb7acecfSBarry Smith . sf - The `PetscSF`
4791b21d0597SMatthew G Knepley 
4792b21d0597SMatthew G Knepley   Level: intermediate
4793b21d0597SMatthew G Knepley 
4794bb7acecfSBarry Smith   Note:
4795bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
4796b21d0597SMatthew G Knepley 
47971cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4798b21d0597SMatthew G Knepley @*/
4799d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
4800d71ae5a4SJacob Faibussowitsch {
4801b21d0597SMatthew G Knepley   PetscFunctionBegin;
4802b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48034f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
4804b21d0597SMatthew G Knepley   *sf = dm->sf;
48053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4806b21d0597SMatthew G Knepley }
4807b21d0597SMatthew G Knepley 
4808057b4bcdSMatthew G Knepley /*@
4809bb7acecfSBarry Smith   DMSetPointSF - Set the `PetscSF` encoding the parallel section point overlap for the `DM`.
4810bb7acecfSBarry Smith 
481120f4b53cSBarry Smith   Collective
4812057b4bcdSMatthew G Knepley 
4813057b4bcdSMatthew G Knepley   Input Parameters:
4814bb7acecfSBarry Smith + dm - The `DM`
4815bb7acecfSBarry Smith - sf - The `PetscSF`
4816057b4bcdSMatthew G Knepley 
4817057b4bcdSMatthew G Knepley   Level: intermediate
4818057b4bcdSMatthew G Knepley 
48191cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4820057b4bcdSMatthew G Knepley @*/
4821d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
4822d71ae5a4SJacob Faibussowitsch {
4823057b4bcdSMatthew G Knepley   PetscFunctionBegin;
4824057b4bcdSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4825b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
48269566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
48279566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sf));
4828057b4bcdSMatthew G Knepley   dm->sf = sf;
48293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4830057b4bcdSMatthew G Knepley }
4831057b4bcdSMatthew G Knepley 
48324f37162bSMatthew G. Knepley /*@
4833bb7acecfSBarry Smith   DMGetNaturalSF - Get the `PetscSF` encoding the map back to the original mesh ordering
48344f37162bSMatthew G. Knepley 
48354f37162bSMatthew G. Knepley   Input Parameter:
4836bb7acecfSBarry Smith . dm - The `DM`
48374f37162bSMatthew G. Knepley 
48384f37162bSMatthew G. Knepley   Output Parameter:
4839bb7acecfSBarry Smith . sf - The `PetscSF`
48404f37162bSMatthew G. Knepley 
48414f37162bSMatthew G. Knepley   Level: intermediate
48424f37162bSMatthew G. Knepley 
4843bb7acecfSBarry Smith   Note:
4844bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
48454f37162bSMatthew G. Knepley 
48461cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
48474f37162bSMatthew G. Knepley @*/
4848d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNaturalSF(DM dm, PetscSF *sf)
4849d71ae5a4SJacob Faibussowitsch {
48504f37162bSMatthew G. Knepley   PetscFunctionBegin;
48514f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48524f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
48534f37162bSMatthew G. Knepley   *sf = dm->sfNatural;
48543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48554f37162bSMatthew G. Knepley }
48564f37162bSMatthew G. Knepley 
48574f37162bSMatthew G. Knepley /*@
48584f37162bSMatthew G. Knepley   DMSetNaturalSF - Set the PetscSF encoding the map back to the original mesh ordering
48594f37162bSMatthew G. Knepley 
48604f37162bSMatthew G. Knepley   Input Parameters:
48614f37162bSMatthew G. Knepley + dm - The DM
48624f37162bSMatthew G. Knepley - sf - The PetscSF
48634f37162bSMatthew G. Knepley 
48644f37162bSMatthew G. Knepley   Level: intermediate
48654f37162bSMatthew G. Knepley 
48661cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
48674f37162bSMatthew G. Knepley @*/
4868d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNaturalSF(DM dm, PetscSF sf)
4869d71ae5a4SJacob Faibussowitsch {
48704f37162bSMatthew G. Knepley   PetscFunctionBegin;
48714f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48724f37162bSMatthew G. Knepley   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
48739566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
48749566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sfNatural));
48754f37162bSMatthew G. Knepley   dm->sfNatural = sf;
48763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48774f37162bSMatthew G. Knepley }
48784f37162bSMatthew G. Knepley 
4879d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc)
4880d71ae5a4SJacob Faibussowitsch {
488134aa8a36SMatthew G. Knepley   PetscClassId id;
488234aa8a36SMatthew G. Knepley 
488334aa8a36SMatthew G. Knepley   PetscFunctionBegin;
48849566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId(disc, &id));
488534aa8a36SMatthew G. Knepley   if (id == PETSCFE_CLASSID) {
48869566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
488734aa8a36SMatthew G. Knepley   } else if (id == PETSCFV_CLASSID) {
48889566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE));
488917c1d62eSMatthew G. Knepley   } else {
48909566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
489134aa8a36SMatthew G. Knepley   }
48923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
489334aa8a36SMatthew G. Knepley }
489434aa8a36SMatthew G. Knepley 
4895d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew)
4896d71ae5a4SJacob Faibussowitsch {
489744a7f3ddSMatthew G. Knepley   RegionField *tmpr;
489844a7f3ddSMatthew G. Knepley   PetscInt     Nf = dm->Nf, f;
489944a7f3ddSMatthew G. Knepley 
490044a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
49013ba16761SJacob Faibussowitsch   if (Nf >= NfNew) PetscFunctionReturn(PETSC_SUCCESS);
49029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NfNew, &tmpr));
490344a7f3ddSMatthew G. Knepley   for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f];
49049371c9d4SSatish Balay   for (f = Nf; f < NfNew; ++f) {
49059371c9d4SSatish Balay     tmpr[f].disc        = NULL;
49069371c9d4SSatish Balay     tmpr[f].label       = NULL;
49079371c9d4SSatish Balay     tmpr[f].avoidTensor = PETSC_FALSE;
49089371c9d4SSatish Balay   }
49099566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
491044a7f3ddSMatthew G. Knepley   dm->Nf     = NfNew;
491144a7f3ddSMatthew G. Knepley   dm->fields = tmpr;
49123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
491344a7f3ddSMatthew G. Knepley }
491444a7f3ddSMatthew G. Knepley 
491544a7f3ddSMatthew G. Knepley /*@
491620f4b53cSBarry Smith   DMClearFields - Remove all fields from the `DM`
491744a7f3ddSMatthew G. Knepley 
491820f4b53cSBarry Smith   Logically Collective
491944a7f3ddSMatthew G. Knepley 
492044a7f3ddSMatthew G. Knepley   Input Parameter:
492120f4b53cSBarry Smith . dm - The `DM`
492244a7f3ddSMatthew G. Knepley 
492344a7f3ddSMatthew G. Knepley   Level: intermediate
492444a7f3ddSMatthew G. Knepley 
49251cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumFields()`, `DMSetNumFields()`, `DMSetField()`
492644a7f3ddSMatthew G. Knepley @*/
4927d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearFields(DM dm)
4928d71ae5a4SJacob Faibussowitsch {
492944a7f3ddSMatthew G. Knepley   PetscInt f;
493044a7f3ddSMatthew G. Knepley 
493144a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
493244a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
493344a7f3ddSMatthew G. Knepley   for (f = 0; f < dm->Nf; ++f) {
49349566063dSJacob Faibussowitsch     PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
49359566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->fields[f].label));
493644a7f3ddSMatthew G. Knepley   }
49379566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
493844a7f3ddSMatthew G. Knepley   dm->fields = NULL;
493944a7f3ddSMatthew G. Knepley   dm->Nf     = 0;
49403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
494144a7f3ddSMatthew G. Knepley }
494244a7f3ddSMatthew G. Knepley 
4943689b5837SMatthew G. Knepley /*@
494420f4b53cSBarry Smith   DMGetNumFields - Get the number of fields in the `DM`
4945689b5837SMatthew G. Knepley 
494620f4b53cSBarry Smith   Not Collective
4947689b5837SMatthew G. Knepley 
4948689b5837SMatthew G. Knepley   Input Parameter:
494920f4b53cSBarry Smith . dm - The `DM`
4950689b5837SMatthew G. Knepley 
4951689b5837SMatthew G. Knepley   Output Parameter:
495260225df5SJacob Faibussowitsch . numFields - The number of fields
4953689b5837SMatthew G. Knepley 
4954689b5837SMatthew G. Knepley   Level: intermediate
4955689b5837SMatthew G. Knepley 
49561cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetNumFields()`, `DMSetField()`
4957689b5837SMatthew G. Knepley @*/
4958d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4959d71ae5a4SJacob Faibussowitsch {
49600f21e855SMatthew G. Knepley   PetscFunctionBegin;
49610f21e855SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49624f572ea9SToby Isaac   PetscAssertPointer(numFields, 2);
496344a7f3ddSMatthew G. Knepley   *numFields = dm->Nf;
49643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4965af122d2aSMatthew G Knepley }
4966af122d2aSMatthew G Knepley 
4967689b5837SMatthew G. Knepley /*@
496820f4b53cSBarry Smith   DMSetNumFields - Set the number of fields in the `DM`
4969689b5837SMatthew G. Knepley 
497020f4b53cSBarry Smith   Logically Collective
4971689b5837SMatthew G. Knepley 
4972689b5837SMatthew G. Knepley   Input Parameters:
497320f4b53cSBarry Smith + dm        - The `DM`
497460225df5SJacob Faibussowitsch - numFields - The number of fields
4975689b5837SMatthew G. Knepley 
4976689b5837SMatthew G. Knepley   Level: intermediate
4977689b5837SMatthew G. Knepley 
49781cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumFields()`, `DMSetField()`
4979689b5837SMatthew G. Knepley @*/
4980d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4981d71ae5a4SJacob Faibussowitsch {
49820f21e855SMatthew G. Knepley   PetscInt Nf, f;
4983af122d2aSMatthew G Knepley 
4984af122d2aSMatthew G Knepley   PetscFunctionBegin;
4985af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49869566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
49870f21e855SMatthew G. Knepley   for (f = Nf; f < numFields; ++f) {
49880f21e855SMatthew G. Knepley     PetscContainer obj;
49890f21e855SMatthew G. Knepley 
49909566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)dm), &obj));
49919566063dSJacob Faibussowitsch     PetscCall(DMAddField(dm, NULL, (PetscObject)obj));
49929566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&obj));
4993af122d2aSMatthew G Knepley   }
49943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4995af122d2aSMatthew G Knepley }
4996af122d2aSMatthew G Knepley 
4997c1929be8SMatthew G. Knepley /*@
4998bb7acecfSBarry Smith   DMGetField - Return the `DMLabel` and discretization object for a given `DM` field
4999c1929be8SMatthew G. Knepley 
500020f4b53cSBarry Smith   Not Collective
5001c1929be8SMatthew G. Knepley 
5002c1929be8SMatthew G. Knepley   Input Parameters:
5003bb7acecfSBarry Smith + dm - The `DM`
5004c1929be8SMatthew G. Knepley - f  - The field number
5005c1929be8SMatthew G. Knepley 
500644a7f3ddSMatthew G. Knepley   Output Parameters:
500720f4b53cSBarry Smith + label - The label indicating the support of the field, or `NULL` for the entire mesh (pass in `NULL` if not needed)
500820f4b53cSBarry Smith - disc  - The discretization object (pass in `NULL` if not needed)
5009c1929be8SMatthew G. Knepley 
501044a7f3ddSMatthew G. Knepley   Level: intermediate
5011c1929be8SMatthew G. Knepley 
50121cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMSetField()`
5013c1929be8SMatthew G. Knepley @*/
5014d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *disc)
5015d71ae5a4SJacob Faibussowitsch {
5016af122d2aSMatthew G Knepley   PetscFunctionBegin;
5017af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50184f572ea9SToby Isaac   PetscAssertPointer(disc, 4);
50197a8be351SBarry 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);
502044a7f3ddSMatthew G. Knepley   if (label) *label = dm->fields[f].label;
5021bb7acecfSBarry Smith   if (disc) *disc = dm->fields[f].disc;
50223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5023decb47aaSMatthew G. Knepley }
5024decb47aaSMatthew G. Knepley 
5025083401c6SMatthew G. Knepley /* Does not clear the DS */
5026d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField_Internal(DM dm, PetscInt f, DMLabel label, PetscObject disc)
5027d71ae5a4SJacob Faibussowitsch {
5028083401c6SMatthew G. Knepley   PetscFunctionBegin;
50299566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, f + 1));
50309566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->fields[f].label));
50319566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
5032083401c6SMatthew G. Knepley   dm->fields[f].label = label;
5033bb7acecfSBarry Smith   dm->fields[f].disc  = disc;
50349566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
5035835f2295SStefano Zampini   PetscCall(PetscObjectReference(disc));
50363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5037083401c6SMatthew G. Knepley }
5038083401c6SMatthew G. Knepley 
5039ffeef943SBarry Smith /*@
5040bb7acecfSBarry Smith   DMSetField - Set the discretization object for a given `DM` field. Usually one would call `DMAddField()` which automatically handles
5041bb7acecfSBarry Smith   the field numbering.
5042c1929be8SMatthew G. Knepley 
504320f4b53cSBarry Smith   Logically Collective
5044c1929be8SMatthew G. Knepley 
5045c1929be8SMatthew G. Knepley   Input Parameters:
5046bb7acecfSBarry Smith + dm    - The `DM`
5047c1929be8SMatthew G. Knepley . f     - The field number
504820f4b53cSBarry Smith . label - The label indicating the support of the field, or `NULL` for the entire mesh
5049bb7acecfSBarry Smith - disc  - The discretization object
5050c1929be8SMatthew G. Knepley 
505144a7f3ddSMatthew G. Knepley   Level: intermediate
5052c1929be8SMatthew G. Knepley 
50531cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`
5054c1929be8SMatthew G. Knepley @*/
5055d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject disc)
5056d71ae5a4SJacob Faibussowitsch {
5057decb47aaSMatthew G. Knepley   PetscFunctionBegin;
5058decb47aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5059e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
5060bb7acecfSBarry Smith   PetscValidHeader(disc, 4);
50617a8be351SBarry Smith   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
5062bb7acecfSBarry Smith   PetscCall(DMSetField_Internal(dm, f, label, disc));
5063bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, f, disc));
50649566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
50653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
506644a7f3ddSMatthew G. Knepley }
506744a7f3ddSMatthew G. Knepley 
5068ffeef943SBarry Smith /*@
5069bb7acecfSBarry 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)
5070bb7acecfSBarry Smith   and a discretization object that defines the function space associated with those points.
507144a7f3ddSMatthew G. Knepley 
507220f4b53cSBarry Smith   Logically Collective
507344a7f3ddSMatthew G. Knepley 
507444a7f3ddSMatthew G. Knepley   Input Parameters:
5075bb7acecfSBarry Smith + dm    - The `DM`
507620f4b53cSBarry Smith . label - The label indicating the support of the field, or `NULL` for the entire mesh
5077bb7acecfSBarry Smith - disc  - The discretization object
507844a7f3ddSMatthew G. Knepley 
507944a7f3ddSMatthew G. Knepley   Level: intermediate
508044a7f3ddSMatthew G. Knepley 
5081bb7acecfSBarry Smith   Notes:
5082bb7acecfSBarry Smith   The label already exists or will be added to the `DM` with `DMSetLabel()`.
5083bb7acecfSBarry Smith 
5084da81f932SPierre Jolivet   For example, a piecewise continuous pressure field can be defined by coefficients at the cell centers of a mesh and piecewise constant functions
5085bb7acecfSBarry 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
5086bb7acecfSBarry Smith   geometry entities, a `DMLabel` indicating a subset of those geometric entities, and a discretization object, such as a `PetscFE`.
5087bb7acecfSBarry Smith 
50881cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLabel()`, `DMSetField()`, `DMGetField()`, `PetscFE`
508944a7f3ddSMatthew G. Knepley @*/
5090d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject disc)
5091d71ae5a4SJacob Faibussowitsch {
509244a7f3ddSMatthew G. Knepley   PetscInt Nf = dm->Nf;
509344a7f3ddSMatthew G. Knepley 
509444a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
509544a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5096064a246eSJacob Faibussowitsch   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
5097bb7acecfSBarry Smith   PetscValidHeader(disc, 3);
50989566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, Nf + 1));
509944a7f3ddSMatthew G. Knepley   dm->fields[Nf].label = label;
5100bb7acecfSBarry Smith   dm->fields[Nf].disc  = disc;
51019566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
5102835f2295SStefano Zampini   PetscCall(PetscObjectReference(disc));
5103bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, Nf, disc));
51049566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
51053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5106af122d2aSMatthew G Knepley }
51076636e97aSMatthew G Knepley 
5108e5e52638SMatthew G. Knepley /*@
5109e0b68406SMatthew Knepley   DMSetFieldAvoidTensor - Set flag to avoid defining the field on tensor cells
5110e0b68406SMatthew Knepley 
511120f4b53cSBarry Smith   Logically Collective
5112e0b68406SMatthew Knepley 
5113e0b68406SMatthew Knepley   Input Parameters:
5114bb7acecfSBarry Smith + dm          - The `DM`
5115e0b68406SMatthew Knepley . f           - The field index
5116bb7acecfSBarry Smith - avoidTensor - `PETSC_TRUE` to skip defining the field on tensor cells
5117e0b68406SMatthew Knepley 
5118e0b68406SMatthew Knepley   Level: intermediate
5119e0b68406SMatthew Knepley 
51201cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetFieldAvoidTensor()`, `DMSetField()`, `DMGetField()`
5121e0b68406SMatthew Knepley @*/
5122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFieldAvoidTensor(DM dm, PetscInt f, PetscBool avoidTensor)
5123d71ae5a4SJacob Faibussowitsch {
5124e0b68406SMatthew Knepley   PetscFunctionBegin;
512563a3b9bcSJacob 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);
5126e0b68406SMatthew Knepley   dm->fields[f].avoidTensor = avoidTensor;
51273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5128e0b68406SMatthew Knepley }
5129e0b68406SMatthew Knepley 
5130e0b68406SMatthew Knepley /*@
5131e0b68406SMatthew Knepley   DMGetFieldAvoidTensor - Get flag to avoid defining the field on tensor cells
5132e0b68406SMatthew Knepley 
513320f4b53cSBarry Smith   Not Collective
5134e0b68406SMatthew Knepley 
5135e0b68406SMatthew Knepley   Input Parameters:
5136bb7acecfSBarry Smith + dm - The `DM`
5137e0b68406SMatthew Knepley - f  - The field index
5138e0b68406SMatthew Knepley 
5139e0b68406SMatthew Knepley   Output Parameter:
5140e0b68406SMatthew Knepley . avoidTensor - The flag to avoid defining the field on tensor cells
5141e0b68406SMatthew Knepley 
5142e0b68406SMatthew Knepley   Level: intermediate
5143e0b68406SMatthew Knepley 
514460225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMSetField()`, `DMGetField()`, `DMSetFieldAvoidTensor()`
5145e0b68406SMatthew Knepley @*/
5146d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFieldAvoidTensor(DM dm, PetscInt f, PetscBool *avoidTensor)
5147d71ae5a4SJacob Faibussowitsch {
5148e0b68406SMatthew Knepley   PetscFunctionBegin;
514963a3b9bcSJacob 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);
5150e0b68406SMatthew Knepley   *avoidTensor = dm->fields[f].avoidTensor;
51513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5152e0b68406SMatthew Knepley }
5153e0b68406SMatthew Knepley 
5154e0b68406SMatthew Knepley /*@
5155bb7acecfSBarry Smith   DMCopyFields - Copy the discretizations for the `DM` into another `DM`
5156e5e52638SMatthew G. Knepley 
515720f4b53cSBarry Smith   Collective
5158e5e52638SMatthew G. Knepley 
5159bb4b53efSMatthew G. Knepley   Input Parameters:
5160bb4b53efSMatthew G. Knepley + dm        - The `DM`
5161bb4b53efSMatthew G. Knepley . minDegree - Minimum degree for a discretization, or `PETSC_DETERMINE` for no limit
5162bb4b53efSMatthew G. Knepley - maxDegree - Maximum degree for a discretization, or `PETSC_DETERMINE` for no limit
5163e5e52638SMatthew G. Knepley 
5164e5e52638SMatthew G. Knepley   Output Parameter:
5165bb7acecfSBarry Smith . newdm - The `DM`
5166e5e52638SMatthew G. Knepley 
5167e5e52638SMatthew G. Knepley   Level: advanced
5168e5e52638SMatthew G. Knepley 
51691cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetField()`, `DMSetField()`, `DMAddField()`, `DMCopyDS()`, `DMGetDS()`, `DMGetCellDS()`
5170e5e52638SMatthew G. Knepley @*/
5171bb4b53efSMatthew G. Knepley PetscErrorCode DMCopyFields(DM dm, PetscInt minDegree, PetscInt maxDegree, DM newdm)
5172d71ae5a4SJacob Faibussowitsch {
5173e5e52638SMatthew G. Knepley   PetscInt Nf, f;
5174e5e52638SMatthew G. Knepley 
5175e5e52638SMatthew G. Knepley   PetscFunctionBegin;
51763ba16761SJacob Faibussowitsch   if (dm == newdm) PetscFunctionReturn(PETSC_SUCCESS);
51779566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
51789566063dSJacob Faibussowitsch   PetscCall(DMClearFields(newdm));
5179e5e52638SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5180e5e52638SMatthew G. Knepley     DMLabel      label;
5181e5e52638SMatthew G. Knepley     PetscObject  field;
5182bb4b53efSMatthew G. Knepley     PetscClassId id;
518334aa8a36SMatthew G. Knepley     PetscBool    useCone, useClosure;
5184e5e52638SMatthew G. Knepley 
51859566063dSJacob Faibussowitsch     PetscCall(DMGetField(dm, f, &label, &field));
5186bb4b53efSMatthew G. Knepley     PetscCall(PetscObjectGetClassId(field, &id));
5187bb4b53efSMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
5188bb4b53efSMatthew G. Knepley       PetscFE newfe;
5189bb4b53efSMatthew G. Knepley 
5190bb4b53efSMatthew G. Knepley       PetscCall(PetscFELimitDegree((PetscFE)field, minDegree, maxDegree, &newfe));
5191bb4b53efSMatthew G. Knepley       PetscCall(DMSetField(newdm, f, label, (PetscObject)newfe));
5192bb4b53efSMatthew G. Knepley       PetscCall(PetscFEDestroy(&newfe));
5193bb4b53efSMatthew G. Knepley     } else {
51949566063dSJacob Faibussowitsch       PetscCall(DMSetField(newdm, f, label, field));
5195bb4b53efSMatthew G. Knepley     }
51969566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, f, &useCone, &useClosure));
51979566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(newdm, f, useCone, useClosure));
519834aa8a36SMatthew G. Knepley   }
51993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
520034aa8a36SMatthew G. Knepley }
520134aa8a36SMatthew G. Knepley 
520234aa8a36SMatthew G. Knepley /*@
520334aa8a36SMatthew G. Knepley   DMGetAdjacency - Returns the flags for determining variable influence
520434aa8a36SMatthew G. Knepley 
520520f4b53cSBarry Smith   Not Collective
520634aa8a36SMatthew G. Knepley 
520734aa8a36SMatthew G. Knepley   Input Parameters:
520820f4b53cSBarry Smith + dm - The `DM` object
520920f4b53cSBarry Smith - f  - The field number, or `PETSC_DEFAULT` for the default adjacency
521034aa8a36SMatthew G. Knepley 
5211d8d19677SJose E. Roman   Output Parameters:
521234aa8a36SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
521334aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
521434aa8a36SMatthew G. Knepley 
521534aa8a36SMatthew G. Knepley   Level: developer
521634aa8a36SMatthew G. Knepley 
521720f4b53cSBarry Smith   Notes:
521820f4b53cSBarry Smith .vb
521920f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
522020f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
522120f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
522220f4b53cSBarry Smith .ve
522320f4b53cSBarry Smith   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
522420f4b53cSBarry Smith 
52251cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetAdjacency()`, `DMGetField()`, `DMSetField()`
522634aa8a36SMatthew G. Knepley @*/
5227d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure)
5228d71ae5a4SJacob Faibussowitsch {
522934aa8a36SMatthew G. Knepley   PetscFunctionBegin;
523034aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52314f572ea9SToby Isaac   if (useCone) PetscAssertPointer(useCone, 3);
52324f572ea9SToby Isaac   if (useClosure) PetscAssertPointer(useClosure, 4);
523334aa8a36SMatthew G. Knepley   if (f < 0) {
523434aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->adjacency[0];
523534aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->adjacency[1];
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     if (useCone) *useCone = dm->fields[f].adjacency[0];
524234aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->fields[f].adjacency[1];
524334aa8a36SMatthew G. Knepley   }
52443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
524534aa8a36SMatthew G. Knepley }
524634aa8a36SMatthew G. Knepley 
524734aa8a36SMatthew G. Knepley /*@
524834aa8a36SMatthew G. Knepley   DMSetAdjacency - Set the flags for determining variable influence
524934aa8a36SMatthew G. Knepley 
525020f4b53cSBarry Smith   Not Collective
525134aa8a36SMatthew G. Knepley 
525234aa8a36SMatthew G. Knepley   Input Parameters:
525320f4b53cSBarry Smith + dm         - The `DM` object
525434aa8a36SMatthew G. Knepley . f          - The field number
525534aa8a36SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
525634aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
525734aa8a36SMatthew G. Knepley 
525834aa8a36SMatthew G. Knepley   Level: developer
525934aa8a36SMatthew G. Knepley 
526020f4b53cSBarry Smith   Notes:
526120f4b53cSBarry Smith .vb
526220f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
526320f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
526420f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
526520f4b53cSBarry Smith .ve
526620f4b53cSBarry Smith   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
526720f4b53cSBarry Smith 
52681cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetAdjacency()`, `DMGetField()`, `DMSetField()`
526934aa8a36SMatthew G. Knepley @*/
5270d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure)
5271d71ae5a4SJacob Faibussowitsch {
527234aa8a36SMatthew G. Knepley   PetscFunctionBegin;
527334aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
527434aa8a36SMatthew G. Knepley   if (f < 0) {
527534aa8a36SMatthew G. Knepley     dm->adjacency[0] = useCone;
527634aa8a36SMatthew G. Knepley     dm->adjacency[1] = useClosure;
527734aa8a36SMatthew G. Knepley   } else {
527834aa8a36SMatthew G. Knepley     PetscInt Nf;
527934aa8a36SMatthew G. Knepley 
52809566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
52817a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
528234aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[0] = useCone;
528334aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[1] = useClosure;
5284e5e52638SMatthew G. Knepley   }
52853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5286e5e52638SMatthew G. Knepley }
5287e5e52638SMatthew G. Knepley 
5288b0441da4SMatthew G. Knepley /*@
5289b0441da4SMatthew G. Knepley   DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined
5290b0441da4SMatthew G. Knepley 
5291b0441da4SMatthew G. Knepley   Not collective
5292b0441da4SMatthew G. Knepley 
5293f899ff85SJose E. Roman   Input Parameter:
529420f4b53cSBarry Smith . dm - The `DM` object
5295b0441da4SMatthew G. Knepley 
5296d8d19677SJose E. Roman   Output Parameters:
5297b0441da4SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
5298b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5299b0441da4SMatthew G. Knepley 
5300b0441da4SMatthew G. Knepley   Level: developer
5301b0441da4SMatthew G. Knepley 
530220f4b53cSBarry Smith   Notes:
530320f4b53cSBarry Smith .vb
530420f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
530520f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
530620f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
530720f4b53cSBarry Smith .ve
530820f4b53cSBarry Smith 
53091cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5310b0441da4SMatthew G. Knepley @*/
5311d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure)
5312d71ae5a4SJacob Faibussowitsch {
5313b0441da4SMatthew G. Knepley   PetscInt Nf;
5314b0441da4SMatthew G. Knepley 
5315b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5316b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53174f572ea9SToby Isaac   if (useCone) PetscAssertPointer(useCone, 2);
53184f572ea9SToby Isaac   if (useClosure) PetscAssertPointer(useClosure, 3);
53199566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5320b0441da4SMatthew G. Knepley   if (!Nf) {
53219566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5322b0441da4SMatthew G. Knepley   } else {
53239566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, 0, useCone, useClosure));
5324b0441da4SMatthew G. Knepley   }
53253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5326b0441da4SMatthew G. Knepley }
5327b0441da4SMatthew G. Knepley 
5328b0441da4SMatthew G. Knepley /*@
5329b0441da4SMatthew G. Knepley   DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined
5330b0441da4SMatthew G. Knepley 
533120f4b53cSBarry Smith   Not Collective
5332b0441da4SMatthew G. Knepley 
5333b0441da4SMatthew G. Knepley   Input Parameters:
533420f4b53cSBarry Smith + dm         - The `DM` object
5335b0441da4SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
5336b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5337b0441da4SMatthew G. Knepley 
5338b0441da4SMatthew G. Knepley   Level: developer
5339b0441da4SMatthew G. Knepley 
534020f4b53cSBarry Smith   Notes:
534120f4b53cSBarry Smith .vb
534220f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
534320f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
534420f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
534520f4b53cSBarry Smith .ve
534620f4b53cSBarry Smith 
53471cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5348b0441da4SMatthew G. Knepley @*/
5349d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure)
5350d71ae5a4SJacob Faibussowitsch {
5351b0441da4SMatthew G. Knepley   PetscInt Nf;
5352b0441da4SMatthew G. Knepley 
5353b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5354b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53559566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5356b0441da4SMatthew G. Knepley   if (!Nf) {
53579566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5358b0441da4SMatthew G. Knepley   } else {
53599566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, 0, useCone, useClosure));
5360e5e52638SMatthew G. Knepley   }
53613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5362e5e52638SMatthew G. Knepley }
5363e5e52638SMatthew G. Knepley 
5364d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompleteBCLabels_Internal(DM dm)
5365d71ae5a4SJacob Faibussowitsch {
5366799db056SMatthew G. Knepley   DM           plex;
5367799db056SMatthew G. Knepley   DMLabel     *labels, *glabels;
5368799db056SMatthew G. Knepley   const char **names;
5369799db056SMatthew G. Knepley   char        *sendNames, *recvNames;
5370799db056SMatthew G. Knepley   PetscInt     Nds, s, maxLabels = 0, maxLen = 0, gmaxLen, Nl = 0, gNl, l, gl, m;
5371799db056SMatthew G. Knepley   size_t       len;
5372799db056SMatthew G. Knepley   MPI_Comm     comm;
5373799db056SMatthew G. Knepley   PetscMPIInt  rank, size, p, *counts, *displs;
5374783e2ec8SMatthew G. Knepley 
5375783e2ec8SMatthew G. Knepley   PetscFunctionBegin;
5376799db056SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5377799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
5378799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5379799db056SMatthew G. Knepley   PetscCall(DMGetNumDS(dm, &Nds));
5380799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5381799db056SMatthew G. Knepley     PetscDS  dsBC;
5382799db056SMatthew G. Knepley     PetscInt numBd;
5383799db056SMatthew G. Knepley 
538407218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC, NULL));
5385799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5386799db056SMatthew G. Knepley     maxLabels += numBd;
5387799db056SMatthew G. Knepley   }
5388799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(maxLabels, &labels));
5389799db056SMatthew G. Knepley   /* Get list of labels to be completed */
5390799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5391799db056SMatthew G. Knepley     PetscDS  dsBC;
5392799db056SMatthew G. Knepley     PetscInt numBd, bd;
5393799db056SMatthew G. Knepley 
539407218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC, NULL));
5395799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5396799db056SMatthew G. Knepley     for (bd = 0; bd < numBd; ++bd) {
5397799db056SMatthew G. Knepley       DMLabel      label;
5398799db056SMatthew G. Knepley       PetscInt     field;
5399799db056SMatthew G. Knepley       PetscObject  obj;
5400799db056SMatthew G. Knepley       PetscClassId id;
5401799db056SMatthew G. Knepley 
5402799db056SMatthew G. Knepley       PetscCall(PetscDSGetBoundary(dsBC, bd, NULL, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
54039566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, field, NULL, &obj));
54049566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
5405799db056SMatthew G. Knepley       if (!(id == PETSCFE_CLASSID) || !label) continue;
54069371c9d4SSatish Balay       for (l = 0; l < Nl; ++l)
54079371c9d4SSatish Balay         if (labels[l] == label) break;
5408799db056SMatthew G. Knepley       if (l == Nl) labels[Nl++] = label;
5409783e2ec8SMatthew G. Knepley     }
5410799db056SMatthew G. Knepley   }
5411799db056SMatthew G. Knepley   /* Get label names */
5412799db056SMatthew G. Knepley   PetscCall(PetscMalloc1(Nl, &names));
5413799db056SMatthew G. Knepley   for (l = 0; l < Nl; ++l) PetscCall(PetscObjectGetName((PetscObject)labels[l], &names[l]));
54149371c9d4SSatish Balay   for (l = 0; l < Nl; ++l) {
54159371c9d4SSatish Balay     PetscCall(PetscStrlen(names[l], &len));
54169371c9d4SSatish Balay     maxLen = PetscMax(maxLen, (PetscInt)len + 2);
54179371c9d4SSatish Balay   }
5418799db056SMatthew G. Knepley   PetscCall(PetscFree(labels));
5419462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&maxLen, &gmaxLen, 1, MPIU_INT, MPI_MAX, comm));
5420799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(Nl * gmaxLen, &sendNames));
5421c6a7a370SJeremy L Thompson   for (l = 0; l < Nl; ++l) PetscCall(PetscStrncpy(&sendNames[gmaxLen * l], names[l], gmaxLen));
5422799db056SMatthew G. Knepley   PetscCall(PetscFree(names));
5423799db056SMatthew G. Knepley   /* Put all names on all processes */
5424799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(size, &counts, size + 1, &displs));
5425799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgather(&Nl, 1, MPI_INT, counts, 1, MPI_INT, comm));
5426799db056SMatthew G. Knepley   for (p = 0; p < size; ++p) displs[p + 1] = displs[p] + counts[p];
5427799db056SMatthew G. Knepley   gNl = displs[size];
54289371c9d4SSatish Balay   for (p = 0; p < size; ++p) {
54299371c9d4SSatish Balay     counts[p] *= gmaxLen;
54309371c9d4SSatish Balay     displs[p] *= gmaxLen;
54319371c9d4SSatish Balay   }
5432799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(gNl * gmaxLen, &recvNames, gNl, &glabels));
5433799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgatherv(sendNames, counts[rank], MPI_CHAR, recvNames, counts, displs, MPI_CHAR, comm));
5434799db056SMatthew G. Knepley   PetscCall(PetscFree2(counts, displs));
5435799db056SMatthew G. Knepley   PetscCall(PetscFree(sendNames));
5436799db056SMatthew G. Knepley   for (l = 0, gl = 0; l < gNl; ++l) {
5437799db056SMatthew G. Knepley     PetscCall(DMGetLabel(dm, &recvNames[l * gmaxLen], &glabels[gl]));
5438799db056SMatthew G. Knepley     PetscCheck(glabels[gl], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Label %s missing on rank %d", &recvNames[l * gmaxLen], rank);
54399371c9d4SSatish Balay     for (m = 0; m < gl; ++m)
54405d6b2bfcSJames Wright       if (glabels[m] == glabels[gl]) goto next_label;
54419566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
5442799db056SMatthew G. Knepley     PetscCall(DMPlexLabelComplete(plex, glabels[gl]));
54439566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5444799db056SMatthew G. Knepley     ++gl;
54455d6b2bfcSJames Wright   next_label:
54465d6b2bfcSJames Wright     continue;
5447783e2ec8SMatthew G. Knepley   }
5448799db056SMatthew G. Knepley   PetscCall(PetscFree2(recvNames, glabels));
54493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5450783e2ec8SMatthew G. Knepley }
5451783e2ec8SMatthew G. Knepley 
5452d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew)
5453d71ae5a4SJacob Faibussowitsch {
5454e5e52638SMatthew G. Knepley   DMSpace *tmpd;
5455e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5456e5e52638SMatthew G. Knepley 
5457e5e52638SMatthew G. Knepley   PetscFunctionBegin;
54583ba16761SJacob Faibussowitsch   if (Nds >= NdsNew) PetscFunctionReturn(PETSC_SUCCESS);
54599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NdsNew, &tmpd));
5460e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s];
54619371c9d4SSatish Balay   for (s = Nds; s < NdsNew; ++s) {
54629371c9d4SSatish Balay     tmpd[s].ds     = NULL;
54639371c9d4SSatish Balay     tmpd[s].label  = NULL;
54649371c9d4SSatish Balay     tmpd[s].fields = NULL;
54659371c9d4SSatish Balay   }
54669566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5467e5e52638SMatthew G. Knepley   dm->Nds   = NdsNew;
5468e5e52638SMatthew G. Knepley   dm->probs = tmpd;
54693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5470e5e52638SMatthew G. Knepley }
5471e5e52638SMatthew G. Knepley 
5472e5e52638SMatthew G. Knepley /*@
547320f4b53cSBarry Smith   DMGetNumDS - Get the number of discrete systems in the `DM`
5474e5e52638SMatthew G. Knepley 
547520f4b53cSBarry Smith   Not Collective
5476e5e52638SMatthew G. Knepley 
5477e5e52638SMatthew G. Knepley   Input Parameter:
547820f4b53cSBarry Smith . dm - The `DM`
5479e5e52638SMatthew G. Knepley 
5480e5e52638SMatthew G. Knepley   Output Parameter:
548120f4b53cSBarry Smith . Nds - The number of `PetscDS` objects
5482e5e52638SMatthew G. Knepley 
5483e5e52638SMatthew G. Knepley   Level: intermediate
5484e5e52638SMatthew G. Knepley 
54851cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDS()`, `DMGetCellDS()`
5486e5e52638SMatthew G. Knepley @*/
5487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds)
5488d71ae5a4SJacob Faibussowitsch {
5489e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5490e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54914f572ea9SToby Isaac   PetscAssertPointer(Nds, 2);
5492e5e52638SMatthew G. Knepley   *Nds = dm->Nds;
54933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5494e5e52638SMatthew G. Knepley }
5495e5e52638SMatthew G. Knepley 
5496e5e52638SMatthew G. Knepley /*@
549720f4b53cSBarry Smith   DMClearDS - Remove all discrete systems from the `DM`
5498e5e52638SMatthew G. Knepley 
549920f4b53cSBarry Smith   Logically Collective
5500e5e52638SMatthew G. Knepley 
5501e5e52638SMatthew G. Knepley   Input Parameter:
550220f4b53cSBarry Smith . dm - The `DM`
5503e5e52638SMatthew G. Knepley 
5504e5e52638SMatthew G. Knepley   Level: intermediate
5505e5e52638SMatthew G. Knepley 
55061cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumDS()`, `DMGetDS()`, `DMSetField()`
5507e5e52638SMatthew G. Knepley @*/
5508d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearDS(DM dm)
5509d71ae5a4SJacob Faibussowitsch {
5510e5e52638SMatthew G. Knepley   PetscInt s;
5511e5e52638SMatthew G. Knepley 
5512e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5513e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5514e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
55159566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[s].ds));
551607218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dm->probs[s].dsIn));
55179566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->probs[s].label));
55189566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[s].fields));
5519e5e52638SMatthew G. Knepley   }
55209566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5521e5e52638SMatthew G. Knepley   dm->probs = NULL;
5522e5e52638SMatthew G. Knepley   dm->Nds   = 0;
55233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5524e5e52638SMatthew G. Knepley }
5525e5e52638SMatthew G. Knepley 
5526e5e52638SMatthew G. Knepley /*@
552720f4b53cSBarry Smith   DMGetDS - Get the default `PetscDS`
5528e5e52638SMatthew G. Knepley 
552920f4b53cSBarry Smith   Not Collective
5530e5e52638SMatthew G. Knepley 
5531e5e52638SMatthew G. Knepley   Input Parameter:
553220f4b53cSBarry Smith . dm - The `DM`
5533e5e52638SMatthew G. Knepley 
5534e5e52638SMatthew G. Knepley   Output Parameter:
553507218a29SMatthew G. Knepley . ds - The default `PetscDS`
5536e5e52638SMatthew G. Knepley 
5537e5e52638SMatthew G. Knepley   Level: intermediate
5538e5e52638SMatthew G. Knepley 
55391cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetCellDS()`, `DMGetRegionDS()`
5540e5e52638SMatthew G. Knepley @*/
554107218a29SMatthew G. Knepley PetscErrorCode DMGetDS(DM dm, PetscDS *ds)
5542d71ae5a4SJacob Faibussowitsch {
5543e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5544e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
55454f572ea9SToby Isaac   PetscAssertPointer(ds, 2);
554607218a29SMatthew G. Knepley   PetscCheck(dm->Nds > 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Need to call DMCreateDS() before calling DMGetDS()");
554707218a29SMatthew G. Knepley   *ds = dm->probs[0].ds;
55483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5549e5e52638SMatthew G. Knepley }
5550e5e52638SMatthew G. Knepley 
5551e5e52638SMatthew G. Knepley /*@
555220f4b53cSBarry Smith   DMGetCellDS - Get the `PetscDS` defined on a given cell
5553e5e52638SMatthew G. Knepley 
555420f4b53cSBarry Smith   Not Collective
5555e5e52638SMatthew G. Knepley 
5556e5e52638SMatthew G. Knepley   Input Parameters:
555720f4b53cSBarry Smith + dm    - The `DM`
555820f4b53cSBarry Smith - point - Cell for the `PetscDS`
5559e5e52638SMatthew G. Knepley 
556007218a29SMatthew G. Knepley   Output Parameters:
556107218a29SMatthew G. Knepley + ds   - The `PetscDS` defined on the given cell
556207218a29SMatthew G. Knepley - dsIn - The `PetscDS` for input on the given cell, or NULL if the same ds
5563e5e52638SMatthew G. Knepley 
5564e5e52638SMatthew G. Knepley   Level: developer
5565e5e52638SMatthew G. Knepley 
55661cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDS()`, `DMSetRegionDS()`
5567e5e52638SMatthew G. Knepley @*/
556807218a29SMatthew G. Knepley PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *ds, PetscDS *dsIn)
5569d71ae5a4SJacob Faibussowitsch {
557007218a29SMatthew G. Knepley   PetscDS  dsDef = NULL;
5571e5e52638SMatthew G. Knepley   PetscInt s;
5572e5e52638SMatthew G. Knepley 
5573e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5574e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
55754f572ea9SToby Isaac   if (ds) PetscAssertPointer(ds, 3);
55764f572ea9SToby Isaac   if (dsIn) PetscAssertPointer(dsIn, 4);
557763a3b9bcSJacob Faibussowitsch   PetscCheck(point >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %" PetscInt_FMT, point);
557807218a29SMatthew G. Knepley   if (ds) *ds = NULL;
557907218a29SMatthew G. Knepley   if (dsIn) *dsIn = NULL;
5580e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5581e5e52638SMatthew G. Knepley     PetscInt val;
5582e5e52638SMatthew G. Knepley 
55839371c9d4SSatish Balay     if (!dm->probs[s].label) {
558407218a29SMatthew G. Knepley       dsDef = dm->probs[s].ds;
55859371c9d4SSatish Balay     } else {
55869566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(dm->probs[s].label, point, &val));
55879371c9d4SSatish Balay       if (val >= 0) {
558807218a29SMatthew G. Knepley         if (ds) *ds = dm->probs[s].ds;
558907218a29SMatthew G. Knepley         if (dsIn) *dsIn = dm->probs[s].dsIn;
55909371c9d4SSatish Balay         break;
55919371c9d4SSatish Balay       }
5592e5e52638SMatthew G. Knepley     }
5593e5e52638SMatthew G. Knepley   }
559407218a29SMatthew G. Knepley   if (ds && !*ds) *ds = dsDef;
55953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5596e5e52638SMatthew G. Knepley }
5597e5e52638SMatthew G. Knepley 
5598e5e52638SMatthew G. Knepley /*@
559920f4b53cSBarry Smith   DMGetRegionDS - Get the `PetscDS` for a given mesh region, defined by a `DMLabel`
5600e5e52638SMatthew G. Knepley 
560120f4b53cSBarry Smith   Not Collective
5602e5e52638SMatthew G. Knepley 
5603e5e52638SMatthew G. Knepley   Input Parameters:
560420f4b53cSBarry Smith + dm    - The `DM`
560520f4b53cSBarry Smith - label - The `DMLabel` defining the mesh region, or `NULL` for the entire mesh
5606e5e52638SMatthew G. Knepley 
5607b3cf3223SMatthew G. Knepley   Output Parameters:
560820f4b53cSBarry Smith + fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL`
560907218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL`
561007218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input in the given region, or `NULL`
5611e5e52638SMatthew G. Knepley 
5612e5e52638SMatthew G. Knepley   Level: advanced
5613e5e52638SMatthew G. Knepley 
561420f4b53cSBarry Smith   Note:
561520f4b53cSBarry Smith   If a non-`NULL` label is given, but there is no `PetscDS` on that specific label,
561620f4b53cSBarry Smith   the `PetscDS` for the full domain (if present) is returned. Returns with
561707218a29SMatthew G. Knepley   fields = `NULL` and ds = `NULL` if there is no `PetscDS` for the full domain.
561820f4b53cSBarry Smith 
56191cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionNumDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5620e5e52638SMatthew G. Knepley @*/
562107218a29SMatthew G. Knepley PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds, PetscDS *dsIn)
5622d71ae5a4SJacob Faibussowitsch {
5623e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5624e5e52638SMatthew G. Knepley 
5625e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5626e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5627e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
56289371c9d4SSatish Balay   if (fields) {
56294f572ea9SToby Isaac     PetscAssertPointer(fields, 3);
56309371c9d4SSatish Balay     *fields = NULL;
56319371c9d4SSatish Balay   }
56329371c9d4SSatish Balay   if (ds) {
56334f572ea9SToby Isaac     PetscAssertPointer(ds, 4);
56349371c9d4SSatish Balay     *ds = NULL;
56359371c9d4SSatish Balay   }
563607218a29SMatthew G. Knepley   if (dsIn) {
56374f572ea9SToby Isaac     PetscAssertPointer(dsIn, 5);
563807218a29SMatthew G. Knepley     *dsIn = NULL;
563907218a29SMatthew G. Knepley   }
5640e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5641154ca461SJed Brown     if (dm->probs[s].label == label || !dm->probs[s].label) {
5642b3cf3223SMatthew G. Knepley       if (fields) *fields = dm->probs[s].fields;
5643b3cf3223SMatthew G. Knepley       if (ds) *ds = dm->probs[s].ds;
564407218a29SMatthew G. Knepley       if (dsIn) *dsIn = dm->probs[s].dsIn;
56453ba16761SJacob Faibussowitsch       if (dm->probs[s].label) PetscFunctionReturn(PETSC_SUCCESS);
5646b3cf3223SMatthew G. Knepley     }
5647e5e52638SMatthew G. Knepley   }
56483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5649e5e52638SMatthew G. Knepley }
5650e5e52638SMatthew G. Knepley 
5651e5e52638SMatthew G. Knepley /*@
5652bb7acecfSBarry Smith   DMSetRegionDS - Set the `PetscDS` for a given mesh region, defined by a `DMLabel`
5653083401c6SMatthew G. Knepley 
565420f4b53cSBarry Smith   Collective
5655083401c6SMatthew G. Knepley 
5656083401c6SMatthew G. Knepley   Input Parameters:
5657bb7acecfSBarry Smith + dm     - The `DM`
565820f4b53cSBarry Smith . label  - The `DMLabel` defining the mesh region, or `NULL` for the entire mesh
565907218a29SMatthew G. Knepley . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL` for all fields
566007218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region
566107218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input on the given cell, or `NULL` if it is the same `PetscDS`
5662083401c6SMatthew G. Knepley 
566320f4b53cSBarry Smith   Level: advanced
566420f4b53cSBarry Smith 
5665bb7acecfSBarry Smith   Note:
5666bb7acecfSBarry 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,
5667083401c6SMatthew G. Knepley   the fields argument is ignored.
5668083401c6SMatthew G. Knepley 
56691cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionNumDS()`, `DMGetDS()`, `DMGetCellDS()`
5670083401c6SMatthew G. Knepley @*/
567107218a29SMatthew G. Knepley PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds, PetscDS dsIn)
5672d71ae5a4SJacob Faibussowitsch {
5673083401c6SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5674083401c6SMatthew G. Knepley 
5675083401c6SMatthew G. Knepley   PetscFunctionBegin;
5676083401c6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5677083401c6SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
567807218a29SMatthew G. Knepley   if (fields) PetscValidHeaderSpecific(fields, IS_CLASSID, 3);
5679064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 4);
568007218a29SMatthew G. Knepley   if (dsIn) PetscValidHeaderSpecific(dsIn, PETSCDS_CLASSID, 5);
5681083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5682083401c6SMatthew G. Knepley     if (dm->probs[s].label == label) {
56839566063dSJacob Faibussowitsch       PetscCall(PetscDSDestroy(&dm->probs[s].ds));
568407218a29SMatthew G. Knepley       PetscCall(PetscDSDestroy(&dm->probs[s].dsIn));
5685083401c6SMatthew G. Knepley       dm->probs[s].ds   = ds;
568607218a29SMatthew G. Knepley       dm->probs[s].dsIn = dsIn;
56873ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
5688083401c6SMatthew G. Knepley     }
5689083401c6SMatthew G. Knepley   }
56909566063dSJacob Faibussowitsch   PetscCall(DMDSEnlarge_Static(dm, Nds + 1));
56919566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
56929566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fields));
56939566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ds));
569407218a29SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)dsIn));
5695083401c6SMatthew G. Knepley   if (!label) {
5696083401c6SMatthew G. Knepley     /* Put the NULL label at the front, so it is returned as the default */
5697083401c6SMatthew G. Knepley     for (s = Nds - 1; s >= 0; --s) dm->probs[s + 1] = dm->probs[s];
5698083401c6SMatthew G. Knepley     Nds = 0;
5699083401c6SMatthew G. Knepley   }
5700083401c6SMatthew G. Knepley   dm->probs[Nds].label  = label;
5701083401c6SMatthew G. Knepley   dm->probs[Nds].fields = fields;
5702083401c6SMatthew G. Knepley   dm->probs[Nds].ds     = ds;
570307218a29SMatthew G. Knepley   dm->probs[Nds].dsIn   = dsIn;
57043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5705083401c6SMatthew G. Knepley }
5706083401c6SMatthew G. Knepley 
5707083401c6SMatthew G. Knepley /*@
570820f4b53cSBarry Smith   DMGetRegionNumDS - Get the `PetscDS` for a given mesh region, defined by the region number
5709e5e52638SMatthew G. Knepley 
571020f4b53cSBarry Smith   Not Collective
5711e5e52638SMatthew G. Knepley 
5712e5e52638SMatthew G. Knepley   Input Parameters:
571320f4b53cSBarry Smith + dm  - The `DM`
5714e5e52638SMatthew G. Knepley - num - The region number, in [0, Nds)
5715e5e52638SMatthew G. Knepley 
5716e5e52638SMatthew G. Knepley   Output Parameters:
571720f4b53cSBarry Smith + label  - The region label, or `NULL`
571820f4b53cSBarry Smith . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL`
571907218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL`
572007218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input in the given region, or `NULL`
5721e5e52638SMatthew G. Knepley 
5722e5e52638SMatthew G. Knepley   Level: advanced
5723e5e52638SMatthew G. Knepley 
57241cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5725e5e52638SMatthew G. Knepley @*/
572607218a29SMatthew G. Knepley PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds, PetscDS *dsIn)
5727d71ae5a4SJacob Faibussowitsch {
5728e5e52638SMatthew G. Knepley   PetscInt Nds;
5729e5e52638SMatthew G. Knepley 
5730e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5731e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57329566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
573363a3b9bcSJacob 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);
5734e5e52638SMatthew G. Knepley   if (label) {
57354f572ea9SToby Isaac     PetscAssertPointer(label, 3);
5736e5e52638SMatthew G. Knepley     *label = dm->probs[num].label;
5737e5e52638SMatthew G. Knepley   }
5738b3cf3223SMatthew G. Knepley   if (fields) {
57394f572ea9SToby Isaac     PetscAssertPointer(fields, 4);
5740b3cf3223SMatthew G. Knepley     *fields = dm->probs[num].fields;
5741b3cf3223SMatthew G. Knepley   }
5742e5e52638SMatthew G. Knepley   if (ds) {
57434f572ea9SToby Isaac     PetscAssertPointer(ds, 5);
5744e5e52638SMatthew G. Knepley     *ds = dm->probs[num].ds;
5745e5e52638SMatthew G. Knepley   }
574607218a29SMatthew G. Knepley   if (dsIn) {
57474f572ea9SToby Isaac     PetscAssertPointer(dsIn, 6);
574807218a29SMatthew G. Knepley     *dsIn = dm->probs[num].dsIn;
574907218a29SMatthew G. Knepley   }
57503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5751e5e52638SMatthew G. Knepley }
5752e5e52638SMatthew G. Knepley 
5753e5e52638SMatthew G. Knepley /*@
575420f4b53cSBarry Smith   DMSetRegionNumDS - Set the `PetscDS` for a given mesh region, defined by the region number
5755e5e52638SMatthew G. Knepley 
575620f4b53cSBarry Smith   Not Collective
5757e5e52638SMatthew G. Knepley 
5758e5e52638SMatthew G. Knepley   Input Parameters:
575920f4b53cSBarry Smith + dm     - The `DM`
5760083401c6SMatthew G. Knepley . num    - The region number, in [0, Nds)
576120f4b53cSBarry Smith . label  - The region label, or `NULL`
576207218a29SMatthew G. Knepley . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL` to prevent setting
576307218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL` to prevent setting
576407218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input on the given cell, or `NULL` if it is the same `PetscDS`
5765e5e52638SMatthew G. Knepley 
5766e5e52638SMatthew G. Knepley   Level: advanced
5767e5e52638SMatthew G. Knepley 
57681cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5769e5e52638SMatthew G. Knepley @*/
577007218a29SMatthew G. Knepley PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds, PetscDS dsIn)
5771d71ae5a4SJacob Faibussowitsch {
5772083401c6SMatthew G. Knepley   PetscInt Nds;
5773e5e52638SMatthew G. Knepley 
5774e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5775e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5776ad540459SPierre Jolivet   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
57779566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
577863a3b9bcSJacob 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);
57799566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
57809566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->probs[num].label));
5781083401c6SMatthew G. Knepley   dm->probs[num].label = label;
5782083401c6SMatthew G. Knepley   if (fields) {
5783083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(fields, IS_CLASSID, 4);
57849566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)fields));
57859566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[num].fields));
5786083401c6SMatthew G. Knepley     dm->probs[num].fields = fields;
5787e5e52638SMatthew G. Knepley   }
5788083401c6SMatthew G. Knepley   if (ds) {
5789083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 5);
57909566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ds));
57919566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[num].ds));
5792083401c6SMatthew G. Knepley     dm->probs[num].ds = ds;
5793083401c6SMatthew G. Knepley   }
579407218a29SMatthew G. Knepley   if (dsIn) {
579507218a29SMatthew G. Knepley     PetscValidHeaderSpecific(dsIn, PETSCDS_CLASSID, 6);
579607218a29SMatthew G. Knepley     PetscCall(PetscObjectReference((PetscObject)dsIn));
579707218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dm->probs[num].dsIn));
579807218a29SMatthew G. Knepley     dm->probs[num].dsIn = dsIn;
579907218a29SMatthew G. Knepley   }
58003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5801e5e52638SMatthew G. Knepley }
5802e5e52638SMatthew G. Knepley 
5803e5e52638SMatthew G. Knepley /*@
580420f4b53cSBarry Smith   DMFindRegionNum - Find the region number for a given `PetscDS`, or -1 if it is not found.
58051d3af9e0SMatthew G. Knepley 
580620f4b53cSBarry Smith   Not Collective
58071d3af9e0SMatthew G. Knepley 
58081d3af9e0SMatthew G. Knepley   Input Parameters:
580920f4b53cSBarry Smith + dm - The `DM`
581020f4b53cSBarry Smith - ds - The `PetscDS` defined on the given region
58111d3af9e0SMatthew G. Knepley 
58121d3af9e0SMatthew G. Knepley   Output Parameter:
58131d3af9e0SMatthew G. Knepley . num - The region number, in [0, Nds), or -1 if not found
58141d3af9e0SMatthew G. Knepley 
58151d3af9e0SMatthew G. Knepley   Level: advanced
58161d3af9e0SMatthew G. Knepley 
58171cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionNumDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
58181d3af9e0SMatthew G. Knepley @*/
5819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num)
5820d71ae5a4SJacob Faibussowitsch {
58211d3af9e0SMatthew G. Knepley   PetscInt Nds, n;
58221d3af9e0SMatthew G. Knepley 
58231d3af9e0SMatthew G. Knepley   PetscFunctionBegin;
58241d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58251d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 2);
58264f572ea9SToby Isaac   PetscAssertPointer(num, 3);
58279566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
58289371c9d4SSatish Balay   for (n = 0; n < Nds; ++n)
58299371c9d4SSatish Balay     if (ds == dm->probs[n].ds) break;
58301d3af9e0SMatthew G. Knepley   if (n >= Nds) *num = -1;
58311d3af9e0SMatthew G. Knepley   else *num = n;
58323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58331d3af9e0SMatthew G. Knepley }
58341d3af9e0SMatthew G. Knepley 
5835cc4c1da9SBarry Smith /*@
5836bb7acecfSBarry Smith   DMCreateFEDefault - Create a `PetscFE` based on the celltype for the mesh
58372df84da0SMatthew G. Knepley 
583820f4b53cSBarry Smith   Not Collective
58392df84da0SMatthew G. Knepley 
5840f1a722f8SMatthew G. Knepley   Input Parameters:
5841bb7acecfSBarry Smith + dm     - The `DM`
58422df84da0SMatthew G. Knepley . Nc     - The number of components for the field
584320f4b53cSBarry Smith . prefix - The options prefix for the output `PetscFE`, or `NULL`
5844bb7acecfSBarry Smith - qorder - The quadrature order or `PETSC_DETERMINE` to use `PetscSpace` polynomial degree
58452df84da0SMatthew G. Knepley 
58462df84da0SMatthew G. Knepley   Output Parameter:
5847bb7acecfSBarry Smith . fem - The `PetscFE`
58482df84da0SMatthew G. Knepley 
584920f4b53cSBarry Smith   Level: intermediate
585020f4b53cSBarry Smith 
5851bb7acecfSBarry Smith   Note:
5852bb7acecfSBarry Smith   This is a convenience method that just calls `PetscFECreateByCell()` underneath.
58532df84da0SMatthew G. Knepley 
58541cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscFECreateByCell()`, `DMAddField()`, `DMCreateDS()`, `DMGetCellDS()`, `DMGetRegionDS()`
58552df84da0SMatthew G. Knepley @*/
5856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFEDefault(DM dm, PetscInt Nc, const char prefix[], PetscInt qorder, PetscFE *fem)
5857d71ae5a4SJacob Faibussowitsch {
58582df84da0SMatthew G. Knepley   DMPolytopeType ct;
58592df84da0SMatthew G. Knepley   PetscInt       dim, cStart;
58602df84da0SMatthew G. Knepley 
58612df84da0SMatthew G. Knepley   PetscFunctionBegin;
58622df84da0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58632df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 2);
58644f572ea9SToby Isaac   if (prefix) PetscAssertPointer(prefix, 3);
58652df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, qorder, 4);
58664f572ea9SToby Isaac   PetscAssertPointer(fem, 5);
58679566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
58689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
58699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
58709566063dSJacob Faibussowitsch   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, Nc, ct, prefix, qorder, fem));
58713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58722df84da0SMatthew G. Knepley }
58732df84da0SMatthew G. Knepley 
58741d3af9e0SMatthew G. Knepley /*@
5875bb7acecfSBarry Smith   DMCreateDS - Create the discrete systems for the `DM` based upon the fields added to the `DM`
5876e5e52638SMatthew G. Knepley 
587720f4b53cSBarry Smith   Collective
5878e5e52638SMatthew G. Knepley 
5879e5e52638SMatthew G. Knepley   Input Parameter:
5880bb7acecfSBarry Smith . dm - The `DM`
5881e5e52638SMatthew G. Knepley 
588220f4b53cSBarry Smith   Options Database Key:
5883bb7acecfSBarry Smith . -dm_petscds_view - View all the `PetscDS` objects in this `DM`
588445480ffeSMatthew G. Knepley 
588520f4b53cSBarry Smith   Level: intermediate
588620f4b53cSBarry Smith 
58871cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetField`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
5888e5e52638SMatthew G. Knepley @*/
5889d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDS(DM dm)
5890d71ae5a4SJacob Faibussowitsch {
5891e5e52638SMatthew G. Knepley   MPI_Comm  comm;
5892083401c6SMatthew G. Knepley   PetscDS   dsDef;
5893083401c6SMatthew G. Knepley   DMLabel  *labelSet;
5894f9244615SMatthew G. Knepley   PetscInt  dE, Nf = dm->Nf, f, s, Nl, l, Ndef, k;
5895f9244615SMatthew G. Knepley   PetscBool doSetup = PETSC_TRUE, flg;
5896e5e52638SMatthew G. Knepley 
5897e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5898e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58993ba16761SJacob Faibussowitsch   if (!dm->fields) PetscFunctionReturn(PETSC_SUCCESS);
59009566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
59019566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
5902083401c6SMatthew G. Knepley   /* Determine how many regions we have */
59039566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(Nf, &labelSet));
5904083401c6SMatthew G. Knepley   Nl   = 0;
5905083401c6SMatthew G. Knepley   Ndef = 0;
5906083401c6SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5907083401c6SMatthew G. Knepley     DMLabel  label = dm->fields[f].label;
5908083401c6SMatthew G. Knepley     PetscInt l;
5909083401c6SMatthew G. Knepley 
5910f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
5911f918ec44SMatthew G. Knepley     /* Move CEED context to discretizations */
5912f918ec44SMatthew G. Knepley     {
5913f918ec44SMatthew G. Knepley       PetscClassId id;
5914f918ec44SMatthew G. Knepley 
59159566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(dm->fields[f].disc, &id));
5916f918ec44SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
5917f918ec44SMatthew G. Knepley         Ceed ceed;
5918f918ec44SMatthew G. Knepley 
59199566063dSJacob Faibussowitsch         PetscCall(DMGetCeed(dm, &ceed));
59209566063dSJacob Faibussowitsch         PetscCall(PetscFESetCeed((PetscFE)dm->fields[f].disc, ceed));
5921f918ec44SMatthew G. Knepley       }
5922f918ec44SMatthew G. Knepley     }
5923f918ec44SMatthew G. Knepley #endif
59249371c9d4SSatish Balay     if (!label) {
59259371c9d4SSatish Balay       ++Ndef;
59269371c9d4SSatish Balay       continue;
59279371c9d4SSatish Balay     }
59289371c9d4SSatish Balay     for (l = 0; l < Nl; ++l)
59299371c9d4SSatish Balay       if (label == labelSet[l]) break;
5930083401c6SMatthew G. Knepley     if (l < Nl) continue;
5931083401c6SMatthew G. Knepley     labelSet[Nl++] = label;
5932083401c6SMatthew G. Knepley   }
5933083401c6SMatthew G. Knepley   /* Create default DS if there are no labels to intersect with */
593407218a29SMatthew G. Knepley   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef, NULL));
5935083401c6SMatthew G. Knepley   if (!dsDef && Ndef && !Nl) {
5936b3cf3223SMatthew G. Knepley     IS        fields;
5937b3cf3223SMatthew G. Knepley     PetscInt *fld, nf;
5938b3cf3223SMatthew G. Knepley 
59399371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
59409371c9d4SSatish Balay       if (!dm->fields[f].label) ++nf;
59417a8be351SBarry Smith     PetscCheck(nf, comm, PETSC_ERR_PLIB, "All fields have labels, but we are trying to create a default DS");
59429566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
59439371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
59449371c9d4SSatish Balay       if (!dm->fields[f].label) fld[nf++] = f;
59459566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
59469566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
59479566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
59489566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
594988f0c812SMatthew G. Knepley 
59509566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
595107218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, NULL, fields, dsDef, NULL));
59529566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
59539566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fields));
59542df9ee95SMatthew G. Knepley   }
595507218a29SMatthew G. Knepley   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef, NULL));
59569566063dSJacob Faibussowitsch   if (dsDef) PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
5957083401c6SMatthew G. Knepley   /* Intersect labels with default fields */
5958083401c6SMatthew G. Knepley   if (Ndef && Nl) {
59590122748bSMatthew G. Knepley     DM              plex;
5960083401c6SMatthew G. Knepley     DMLabel         cellLabel;
5961083401c6SMatthew G. Knepley     IS              fieldIS, allcellIS, defcellIS = NULL;
5962083401c6SMatthew G. Knepley     PetscInt       *fields;
5963083401c6SMatthew G. Knepley     const PetscInt *cells;
5964083401c6SMatthew G. Knepley     PetscInt        depth, nf = 0, n, c;
59650122748bSMatthew G. Knepley 
59669566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
59679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(plex, &depth));
59689566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(plex, "dim", depth, &allcellIS));
59699566063dSJacob Faibussowitsch     if (!allcellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, &allcellIS));
59705fedec97SMatthew G. Knepley     /* TODO This looks like it only works for one label */
5971083401c6SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
5972083401c6SMatthew G. Knepley       DMLabel label = labelSet[l];
5973083401c6SMatthew G. Knepley       IS      pointIS;
5974083401c6SMatthew G. Knepley 
59759566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&defcellIS));
59769566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(label, 1, &pointIS));
59779566063dSJacob Faibussowitsch       PetscCall(ISDifference(allcellIS, pointIS, &defcellIS));
59789566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pointIS));
5979083401c6SMatthew G. Knepley     }
59809566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&allcellIS));
5981083401c6SMatthew G. Knepley 
59829566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel));
59839566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(defcellIS, &n));
59849566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(defcellIS, &cells));
59859566063dSJacob Faibussowitsch     for (c = 0; c < n; ++c) PetscCall(DMLabelSetValue(cellLabel, cells[c], 1));
59869566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(defcellIS, &cells));
59879566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&defcellIS));
59889566063dSJacob Faibussowitsch     PetscCall(DMPlexLabelComplete(plex, cellLabel));
5989083401c6SMatthew G. Knepley 
59909566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Ndef, &fields));
59919371c9d4SSatish Balay     for (f = 0; f < Nf; ++f)
59929371c9d4SSatish Balay       if (!dm->fields[f].label) fields[nf++] = f;
59939566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fieldIS));
59949566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fieldIS, "dm_fields_"));
59959566063dSJacob Faibussowitsch     PetscCall(ISSetType(fieldIS, ISGENERAL));
59969566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER));
5997083401c6SMatthew G. Knepley 
59989566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
599907218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, cellLabel, fieldIS, dsDef, NULL));
60009566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
60019566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&cellLabel));
60029566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
60039566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fieldIS));
60049566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
6005083401c6SMatthew G. Knepley   }
6006083401c6SMatthew G. Knepley   /* Create label DSes
6007083401c6SMatthew G. Knepley      - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS
6008083401c6SMatthew G. Knepley   */
6009083401c6SMatthew G. Knepley   /* TODO Should check that labels are disjoint */
6010083401c6SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
6011083401c6SMatthew G. Knepley     DMLabel   label = labelSet[l];
601207218a29SMatthew G. Knepley     PetscDS   ds, dsIn = NULL;
6013083401c6SMatthew G. Knepley     IS        fields;
6014083401c6SMatthew G. Knepley     PetscInt *fld, nf;
6015083401c6SMatthew G. Knepley 
60169566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
60179371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
60189371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) ++nf;
60199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
60209371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
60219371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f;
60229566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
60239566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
60249566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
60259566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
60269566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(ds, dE));
6027083401c6SMatthew G. Knepley     {
6028083401c6SMatthew G. Knepley       DMPolytopeType ct;
6029083401c6SMatthew G. Knepley       PetscInt       lStart, lEnd;
60305fedec97SMatthew G. Knepley       PetscBool      isCohesiveLocal = PETSC_FALSE, isCohesive;
60310122748bSMatthew G. Knepley 
60329566063dSJacob Faibussowitsch       PetscCall(DMLabelGetBounds(label, &lStart, &lEnd));
6033665f567fSMatthew G. Knepley       if (lStart >= 0) {
60349566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, lStart, &ct));
6035412e9a14SMatthew G. Knepley         switch (ct) {
6036412e9a14SMatthew G. Knepley         case DM_POLYTOPE_POINT_PRISM_TENSOR:
6037412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
6038412e9a14SMatthew G. Knepley         case DM_POLYTOPE_TRI_PRISM_TENSOR:
6039d71ae5a4SJacob Faibussowitsch         case DM_POLYTOPE_QUAD_PRISM_TENSOR:
6040d71ae5a4SJacob Faibussowitsch           isCohesiveLocal = PETSC_TRUE;
6041d71ae5a4SJacob Faibussowitsch           break;
6042d71ae5a4SJacob Faibussowitsch         default:
6043d71ae5a4SJacob Faibussowitsch           break;
6044412e9a14SMatthew G. Knepley         }
6045665f567fSMatthew G. Knepley       }
6046462c564dSBarry Smith       PetscCallMPI(MPIU_Allreduce(&isCohesiveLocal, &isCohesive, 1, MPIU_BOOL, MPI_LOR, comm));
604707218a29SMatthew G. Knepley       if (isCohesive) {
604807218a29SMatthew G. Knepley         PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsIn));
604907218a29SMatthew G. Knepley         PetscCall(PetscDSSetCoordinateDimension(dsIn, dE));
605007218a29SMatthew G. Knepley       }
60515fedec97SMatthew G. Knepley       for (f = 0, nf = 0; f < Nf; ++f) {
60525fedec97SMatthew G. Knepley         if (label == dm->fields[f].label || !dm->fields[f].label) {
60535fedec97SMatthew G. Knepley           if (label == dm->fields[f].label) {
60549566063dSJacob Faibussowitsch             PetscCall(PetscDSSetDiscretization(ds, nf, NULL));
60559566063dSJacob Faibussowitsch             PetscCall(PetscDSSetCohesive(ds, nf, isCohesive));
605607218a29SMatthew G. Knepley             if (dsIn) {
605707218a29SMatthew G. Knepley               PetscCall(PetscDSSetDiscretization(dsIn, nf, NULL));
605807218a29SMatthew G. Knepley               PetscCall(PetscDSSetCohesive(dsIn, nf, isCohesive));
605907218a29SMatthew G. Knepley             }
60605fedec97SMatthew G. Knepley           }
60615fedec97SMatthew G. Knepley           ++nf;
60625fedec97SMatthew G. Knepley         }
60635fedec97SMatthew G. Knepley       }
6064e5e52638SMatthew G. Knepley     }
606507218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, label, fields, ds, dsIn));
606607218a29SMatthew G. Knepley     PetscCall(ISDestroy(&fields));
60679566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&ds));
606807218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dsIn));
6069e5e52638SMatthew G. Knepley   }
60709566063dSJacob Faibussowitsch   PetscCall(PetscFree(labelSet));
6071e5e52638SMatthew G. Knepley   /* Set fields in DSes */
6072083401c6SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
6073083401c6SMatthew G. Knepley     PetscDS         ds     = dm->probs[s].ds;
607407218a29SMatthew G. Knepley     PetscDS         dsIn   = dm->probs[s].dsIn;
6075083401c6SMatthew G. Knepley     IS              fields = dm->probs[s].fields;
6076083401c6SMatthew G. Knepley     const PetscInt *fld;
60775fedec97SMatthew G. Knepley     PetscInt        nf, dsnf;
60785fedec97SMatthew G. Knepley     PetscBool       isCohesive;
6079e5e52638SMatthew G. Knepley 
60809566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsnf));
60819566063dSJacob Faibussowitsch     PetscCall(PetscDSIsCohesive(ds, &isCohesive));
60829566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(fields, &nf));
60839566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fields, &fld));
6084083401c6SMatthew G. Knepley     for (f = 0; f < nf; ++f) {
6085083401c6SMatthew G. Knepley       PetscObject  disc = dm->fields[fld[f]].disc;
60865fedec97SMatthew G. Knepley       PetscBool    isCohesiveField;
6087e5e52638SMatthew G. Knepley       PetscClassId id;
6088e5e52638SMatthew G. Knepley 
60895fedec97SMatthew G. Knepley       /* Handle DS with no fields */
60909566063dSJacob Faibussowitsch       if (dsnf) PetscCall(PetscDSGetCohesive(ds, f, &isCohesiveField));
60915fedec97SMatthew G. Knepley       /* If this is a cohesive cell, then regular fields need the lower dimensional discretization */
609207218a29SMatthew G. Knepley       if (isCohesive) {
609307218a29SMatthew G. Knepley         if (!isCohesiveField) {
609407218a29SMatthew G. Knepley           PetscObject bdDisc;
609507218a29SMatthew G. Knepley 
609607218a29SMatthew G. Knepley           PetscCall(PetscFEGetHeightSubspace((PetscFE)disc, 1, (PetscFE *)&bdDisc));
609707218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(ds, f, bdDisc));
609807218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(dsIn, f, disc));
609907218a29SMatthew G. Knepley         } else {
61009566063dSJacob Faibussowitsch           PetscCall(PetscDSSetDiscretization(ds, f, disc));
610107218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(dsIn, f, disc));
610207218a29SMatthew G. Knepley         }
610307218a29SMatthew G. Knepley       } else {
610407218a29SMatthew G. Knepley         PetscCall(PetscDSSetDiscretization(ds, f, disc));
610507218a29SMatthew G. Knepley       }
6106083401c6SMatthew G. Knepley       /* We allow people to have placeholder fields and construct the Section by hand */
61079566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(disc, &id));
6108e5e52638SMatthew G. Knepley       if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE;
6109e5e52638SMatthew G. Knepley     }
61109566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fields, &fld));
6111e5e52638SMatthew G. Knepley   }
6112f9244615SMatthew G. Knepley   /* Allow k-jet tabulation */
61139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)dm)->prefix, "-dm_ds_jet_degree", &k, &flg));
6114f9244615SMatthew G. Knepley   if (flg) {
61153b4aee56SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
61163b4aee56SMatthew G. Knepley       PetscDS  ds   = dm->probs[s].ds;
611707218a29SMatthew G. Knepley       PetscDS  dsIn = dm->probs[s].dsIn;
61183b4aee56SMatthew G. Knepley       PetscInt Nf, f;
61193b4aee56SMatthew G. Knepley 
61209566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(ds, &Nf));
612107218a29SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
612207218a29SMatthew G. Knepley         PetscCall(PetscDSSetJetDegree(ds, f, k));
612307218a29SMatthew G. Knepley         if (dsIn) PetscCall(PetscDSSetJetDegree(dsIn, f, k));
612407218a29SMatthew G. Knepley       }
61253b4aee56SMatthew G. Knepley     }
6126f9244615SMatthew G. Knepley   }
6127e5e52638SMatthew G. Knepley   /* Setup DSes */
6128e5e52638SMatthew G. Knepley   if (doSetup) {
612907218a29SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
6130cf1363e4SMatthew G. Knepley       if (dm->setfromoptionscalled) {
6131cf1363e4SMatthew G. Knepley         PetscCall(PetscDSSetFromOptions(dm->probs[s].ds));
6132cf1363e4SMatthew G. Knepley         if (dm->probs[s].dsIn) PetscCall(PetscDSSetFromOptions(dm->probs[s].dsIn));
6133cf1363e4SMatthew G. Knepley       }
613407218a29SMatthew G. Knepley       PetscCall(PetscDSSetUp(dm->probs[s].ds));
613507218a29SMatthew G. Knepley       if (dm->probs[s].dsIn) PetscCall(PetscDSSetUp(dm->probs[s].dsIn));
613607218a29SMatthew G. Knepley     }
6137e5e52638SMatthew G. Knepley   }
61383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6139e5e52638SMatthew G. Knepley }
6140e5e52638SMatthew G. Knepley 
6141e5e52638SMatthew G. Knepley /*@
6142d2b2dc1eSMatthew G. Knepley   DMUseTensorOrder - Use a tensor product closure ordering for the default section
6143d2b2dc1eSMatthew G. Knepley 
6144d2b2dc1eSMatthew G. Knepley   Input Parameters:
6145d2b2dc1eSMatthew G. Knepley + dm     - The DM
6146d2b2dc1eSMatthew G. Knepley - tensor - Flag for tensor order
6147d2b2dc1eSMatthew G. Knepley 
6148d2b2dc1eSMatthew G. Knepley   Level: developer
6149d2b2dc1eSMatthew G. Knepley 
6150d2b2dc1eSMatthew G. Knepley .seealso: `DMPlexSetClosurePermutationTensor()`, `PetscSectionResetClosurePermutation()`
6151d2b2dc1eSMatthew G. Knepley @*/
6152d2b2dc1eSMatthew G. Knepley PetscErrorCode DMUseTensorOrder(DM dm, PetscBool tensor)
6153d2b2dc1eSMatthew G. Knepley {
6154d2b2dc1eSMatthew G. Knepley   PetscInt  Nf;
6155d2b2dc1eSMatthew G. Knepley   PetscBool reorder = PETSC_TRUE, isPlex;
6156d2b2dc1eSMatthew G. Knepley 
6157d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
6158d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isPlex));
6159d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetNumFields(dm, &Nf));
6160d2b2dc1eSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
6161d2b2dc1eSMatthew G. Knepley     PetscObject  obj;
6162d2b2dc1eSMatthew G. Knepley     PetscClassId id;
6163d2b2dc1eSMatthew G. Knepley 
6164d2b2dc1eSMatthew G. Knepley     PetscCall(DMGetField(dm, f, NULL, &obj));
6165d2b2dc1eSMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
6166d2b2dc1eSMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
6167d2b2dc1eSMatthew G. Knepley       PetscSpace sp;
6168d2b2dc1eSMatthew G. Knepley       PetscBool  tensor;
6169d2b2dc1eSMatthew G. Knepley 
6170d2b2dc1eSMatthew G. Knepley       PetscCall(PetscFEGetBasisSpace((PetscFE)obj, &sp));
6171d2b2dc1eSMatthew G. Knepley       PetscCall(PetscSpacePolynomialGetTensor(sp, &tensor));
6172d2b2dc1eSMatthew G. Knepley       reorder = reorder && tensor ? PETSC_TRUE : PETSC_FALSE;
6173d2b2dc1eSMatthew G. Knepley     } else reorder = PETSC_FALSE;
6174d2b2dc1eSMatthew G. Knepley   }
6175d2b2dc1eSMatthew G. Knepley   if (tensor) {
6176d2b2dc1eSMatthew G. Knepley     if (reorder && isPlex) PetscCall(DMPlexSetClosurePermutationTensor(dm, PETSC_DETERMINE, NULL));
6177d2b2dc1eSMatthew G. Knepley   } else {
6178d2b2dc1eSMatthew G. Knepley     PetscSection s;
6179d2b2dc1eSMatthew G. Knepley 
6180d2b2dc1eSMatthew G. Knepley     PetscCall(DMGetLocalSection(dm, &s));
6181d2b2dc1eSMatthew G. Knepley     if (s) PetscCall(PetscSectionResetClosurePermutation(s));
6182d2b2dc1eSMatthew G. Knepley   }
6183d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6184d2b2dc1eSMatthew G. Knepley }
6185d2b2dc1eSMatthew G. Knepley 
6186d2b2dc1eSMatthew G. Knepley /*@
6187bb7acecfSBarry Smith   DMComputeExactSolution - Compute the exact solution for a given `DM`, using the `PetscDS` information.
61887f96f943SMatthew G. Knepley 
618920f4b53cSBarry Smith   Collective
6190f2cacb80SMatthew G. Knepley 
61917f96f943SMatthew G. Knepley   Input Parameters:
6192bb7acecfSBarry Smith + dm   - The `DM`
61937f96f943SMatthew G. Knepley - time - The time
61947f96f943SMatthew G. Knepley 
61957f96f943SMatthew G. Knepley   Output Parameters:
619620f4b53cSBarry Smith + u   - The vector will be filled with exact solution values, or `NULL`
619720f4b53cSBarry Smith - u_t - The vector will be filled with the time derivative of exact solution values, or `NULL`
619820f4b53cSBarry Smith 
619920f4b53cSBarry Smith   Level: developer
62007f96f943SMatthew G. Knepley 
6201bb7acecfSBarry Smith   Note:
6202bb7acecfSBarry Smith   The user must call `PetscDSSetExactSolution()` before using this routine
62037f96f943SMatthew G. Knepley 
62041cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscDSSetExactSolution()`
62057f96f943SMatthew G. Knepley @*/
6206d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t)
6207d71ae5a4SJacob Faibussowitsch {
62087f96f943SMatthew G. Knepley   PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
62097f96f943SMatthew G. Knepley   void   **ectxs;
6210f60fa741SMatthew G. Knepley   Vec      locu, locu_t;
62117f96f943SMatthew G. Knepley   PetscInt Nf, Nds, s;
62127f96f943SMatthew G. Knepley 
62137f96f943SMatthew G. Knepley   PetscFunctionBegin;
6214f2cacb80SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6215f60fa741SMatthew G. Knepley   if (u) {
6216f60fa741SMatthew G. Knepley     PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
6217f60fa741SMatthew G. Knepley     PetscCall(DMGetLocalVector(dm, &locu));
6218f60fa741SMatthew G. Knepley     PetscCall(VecSet(locu, 0.));
6219f60fa741SMatthew G. Knepley   }
6220f60fa741SMatthew G. Knepley   if (u_t) {
6221f60fa741SMatthew G. Knepley     PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4);
6222f60fa741SMatthew G. Knepley     PetscCall(DMGetLocalVector(dm, &locu_t));
6223f60fa741SMatthew G. Knepley     PetscCall(VecSet(locu_t, 0.));
6224f60fa741SMatthew G. Knepley   }
62259566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
62269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(Nf, &exacts, Nf, &ectxs));
62279566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
62287f96f943SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
62297f96f943SMatthew G. Knepley     PetscDS         ds;
62307f96f943SMatthew G. Knepley     DMLabel         label;
62317f96f943SMatthew G. Knepley     IS              fieldIS;
62327f96f943SMatthew G. Knepley     const PetscInt *fields, id = 1;
62337f96f943SMatthew G. Knepley     PetscInt        dsNf, f;
62347f96f943SMatthew G. Knepley 
623507218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds, NULL));
62369566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
62379566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fieldIS, &fields));
62389566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(exacts, Nf));
62399566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(ectxs, Nf));
6240f2cacb80SMatthew G. Knepley     if (u) {
6241f60fa741SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) PetscCall(PetscDSGetExactSolution(ds, fields[f], &exacts[fields[f]], &ectxs[fields[f]]));
6242f60fa741SMatthew G. Knepley       if (label) PetscCall(DMProjectFunctionLabelLocal(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, locu));
6243f60fa741SMatthew G. Knepley       else PetscCall(DMProjectFunctionLocal(dm, time, exacts, ectxs, INSERT_ALL_VALUES, locu));
62447f96f943SMatthew G. Knepley     }
6245f2cacb80SMatthew G. Knepley     if (u_t) {
62469566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(exacts, Nf));
62479566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ectxs, Nf));
6248f60fa741SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, fields[f], &exacts[fields[f]], &ectxs[fields[f]]));
6249f60fa741SMatthew G. Knepley       if (label) PetscCall(DMProjectFunctionLabelLocal(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, locu_t));
6250f60fa741SMatthew G. Knepley       else PetscCall(DMProjectFunctionLocal(dm, time, exacts, ectxs, INSERT_ALL_VALUES, locu_t));
6251f2cacb80SMatthew G. Knepley     }
62529566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fieldIS, &fields));
6253f2cacb80SMatthew G. Knepley   }
6254f2cacb80SMatthew G. Knepley   if (u) {
62559566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution"));
62569566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u, "exact_"));
6257f2cacb80SMatthew G. Knepley   }
6258f2cacb80SMatthew G. Knepley   if (u_t) {
62599566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution Time Derivative"));
62609566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u_t, "exact_t_"));
6261f2cacb80SMatthew G. Knepley   }
62629566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exacts, ectxs));
6263f60fa741SMatthew G. Knepley   if (u) {
6264f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(dm, locu, INSERT_ALL_VALUES, u));
6265f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(dm, locu, INSERT_ALL_VALUES, u));
6266f60fa741SMatthew G. Knepley     PetscCall(DMRestoreLocalVector(dm, &locu));
6267f60fa741SMatthew G. Knepley   }
6268f60fa741SMatthew G. Knepley   if (u_t) {
6269f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(dm, locu_t, INSERT_ALL_VALUES, u_t));
6270f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(dm, locu_t, INSERT_ALL_VALUES, u_t));
6271f60fa741SMatthew G. Knepley     PetscCall(DMRestoreLocalVector(dm, &locu_t));
6272f60fa741SMatthew G. Knepley   }
62733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
62747f96f943SMatthew G. Knepley }
62757f96f943SMatthew G. Knepley 
6276bb4b53efSMatthew G. Knepley static PetscErrorCode DMTransferDS_Internal(DM dm, DMLabel label, IS fields, PetscInt minDegree, PetscInt maxDegree, PetscDS ds, PetscDS dsIn)
6277d71ae5a4SJacob Faibussowitsch {
627807218a29SMatthew G. Knepley   PetscDS dsNew, dsInNew = NULL;
627945480ffeSMatthew G. Knepley 
628045480ffeSMatthew G. Knepley   PetscFunctionBegin;
62819566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)ds), &dsNew));
6282bb4b53efSMatthew G. Knepley   PetscCall(PetscDSCopy(ds, minDegree, maxDegree, dm, dsNew));
628307218a29SMatthew G. Knepley   if (dsIn) {
628407218a29SMatthew G. Knepley     PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)dsIn), &dsInNew));
6285bb4b53efSMatthew G. Knepley     PetscCall(PetscDSCopy(dsIn, minDegree, maxDegree, dm, dsInNew));
628645480ffeSMatthew G. Knepley   }
628707218a29SMatthew G. Knepley   PetscCall(DMSetRegionDS(dm, label, fields, dsNew, dsInNew));
62889566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&dsNew));
628907218a29SMatthew G. Knepley   PetscCall(PetscDSDestroy(&dsInNew));
62903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
629145480ffeSMatthew G. Knepley }
629245480ffeSMatthew G. Knepley 
62937f96f943SMatthew G. Knepley /*@
6294bb7acecfSBarry Smith   DMCopyDS - Copy the discrete systems for the `DM` into another `DM`
6295e5e52638SMatthew G. Knepley 
629620f4b53cSBarry Smith   Collective
6297e5e52638SMatthew G. Knepley 
6298bb4b53efSMatthew G. Knepley   Input Parameters:
6299bb4b53efSMatthew G. Knepley + dm        - The `DM`
6300bb4b53efSMatthew G. Knepley . minDegree - Minimum degree for a discretization, or `PETSC_DETERMINE` for no limit
6301bb4b53efSMatthew G. Knepley - maxDegree - Maximum degree for a discretization, or `PETSC_DETERMINE` for no limit
6302e5e52638SMatthew G. Knepley 
6303e5e52638SMatthew G. Knepley   Output Parameter:
6304bb7acecfSBarry Smith . newdm - The `DM`
6305e5e52638SMatthew G. Knepley 
6306e5e52638SMatthew G. Knepley   Level: advanced
6307e5e52638SMatthew G. Knepley 
63081cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCopyFields()`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
6309e5e52638SMatthew G. Knepley @*/
6310bb4b53efSMatthew G. Knepley PetscErrorCode DMCopyDS(DM dm, PetscInt minDegree, PetscInt maxDegree, DM newdm)
6311d71ae5a4SJacob Faibussowitsch {
6312e5e52638SMatthew G. Knepley   PetscInt Nds, s;
6313e5e52638SMatthew G. Knepley 
6314e5e52638SMatthew G. Knepley   PetscFunctionBegin;
63153ba16761SJacob Faibussowitsch   if (dm == newdm) PetscFunctionReturn(PETSC_SUCCESS);
63169566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
63179566063dSJacob Faibussowitsch   PetscCall(DMClearDS(newdm));
6318e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
6319e5e52638SMatthew G. Knepley     DMLabel  label;
6320b3cf3223SMatthew G. Knepley     IS       fields;
632107218a29SMatthew G. Knepley     PetscDS  ds, dsIn, newds;
6322783e2ec8SMatthew G. Knepley     PetscInt Nbd, bd;
6323e5e52638SMatthew G. Knepley 
632407218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fields, &ds, &dsIn));
6325b8025e53SMatthew G. Knepley     /* TODO: We need to change all keys from labels in the old DM to labels in the new DM */
6326bb4b53efSMatthew G. Knepley     PetscCall(DMTransferDS_Internal(newdm, label, fields, minDegree, maxDegree, ds, dsIn));
6327d5b43468SJose E. Roman     /* Complete new labels in the new DS */
632807218a29SMatthew G. Knepley     PetscCall(DMGetRegionDS(newdm, label, NULL, &newds, NULL));
63299566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumBoundary(newds, &Nbd));
6330783e2ec8SMatthew G. Knepley     for (bd = 0; bd < Nbd; ++bd) {
6331b8025e53SMatthew G. Knepley       PetscWeakForm wf;
633245480ffeSMatthew G. Knepley       DMLabel       label;
6333783e2ec8SMatthew G. Knepley       PetscInt      field;
6334783e2ec8SMatthew G. Knepley 
63359566063dSJacob Faibussowitsch       PetscCall(PetscDSGetBoundary(newds, bd, &wf, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
63369566063dSJacob Faibussowitsch       PetscCall(PetscWeakFormReplaceLabel(wf, label));
6337783e2ec8SMatthew G. Knepley     }
6338e5e52638SMatthew G. Knepley   }
6339799db056SMatthew G. Knepley   PetscCall(DMCompleteBCLabels_Internal(newdm));
63403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6341e5e52638SMatthew G. Knepley }
6342e5e52638SMatthew G. Knepley 
6343e5e52638SMatthew G. Knepley /*@
6344bb7acecfSBarry Smith   DMCopyDisc - Copy the fields and discrete systems for the `DM` into another `DM`
6345e5e52638SMatthew G. Knepley 
634620f4b53cSBarry Smith   Collective
6347e5e52638SMatthew G. Knepley 
6348e5e52638SMatthew G. Knepley   Input Parameter:
6349bb7acecfSBarry Smith . dm - The `DM`
6350e5e52638SMatthew G. Knepley 
6351e5e52638SMatthew G. Knepley   Output Parameter:
6352bb7acecfSBarry Smith . newdm - The `DM`
6353e5e52638SMatthew G. Knepley 
6354e5e52638SMatthew G. Knepley   Level: advanced
6355e5e52638SMatthew G. Knepley 
635673ff1848SBarry Smith   Developer Note:
6357bb7acecfSBarry Smith   Really ugly name, nothing in PETSc is called a `Disc` plus it is an ugly abbreviation
6358bb7acecfSBarry Smith 
63591cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCopyFields()`, `DMCopyDS()`
6360e5e52638SMatthew G. Knepley @*/
6361d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDisc(DM dm, DM newdm)
6362d71ae5a4SJacob Faibussowitsch {
6363e5e52638SMatthew G. Knepley   PetscFunctionBegin;
6364bb4b53efSMatthew G. Knepley   PetscCall(DMCopyFields(dm, PETSC_DETERMINE, PETSC_DETERMINE, newdm));
6365bb4b53efSMatthew G. Knepley   PetscCall(DMCopyDS(dm, PETSC_DETERMINE, PETSC_DETERMINE, newdm));
63663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6367e5e52638SMatthew G. Knepley }
6368e5e52638SMatthew G. Knepley 
6369c73cfb54SMatthew G. Knepley /*@
6370bb7acecfSBarry Smith   DMGetDimension - Return the topological dimension of the `DM`
6371c73cfb54SMatthew G. Knepley 
637220f4b53cSBarry Smith   Not Collective
6373c73cfb54SMatthew G. Knepley 
6374c73cfb54SMatthew G. Knepley   Input Parameter:
6375bb7acecfSBarry Smith . dm - The `DM`
6376c73cfb54SMatthew G. Knepley 
6377c73cfb54SMatthew G. Knepley   Output Parameter:
6378c73cfb54SMatthew G. Knepley . dim - The topological dimension
6379c73cfb54SMatthew G. Knepley 
6380c73cfb54SMatthew G. Knepley   Level: beginner
6381c73cfb54SMatthew G. Knepley 
63821cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetDimension()`, `DMCreate()`
6383c73cfb54SMatthew G. Knepley @*/
6384d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
6385d71ae5a4SJacob Faibussowitsch {
6386c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6387c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63884f572ea9SToby Isaac   PetscAssertPointer(dim, 2);
6389c73cfb54SMatthew G. Knepley   *dim = dm->dim;
63903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6391c73cfb54SMatthew G. Knepley }
6392c73cfb54SMatthew G. Knepley 
6393c73cfb54SMatthew G. Knepley /*@
6394bb7acecfSBarry Smith   DMSetDimension - Set the topological dimension of the `DM`
6395c73cfb54SMatthew G. Knepley 
639620f4b53cSBarry Smith   Collective
6397c73cfb54SMatthew G. Knepley 
6398c73cfb54SMatthew G. Knepley   Input Parameters:
6399bb7acecfSBarry Smith + dm  - The `DM`
6400c73cfb54SMatthew G. Knepley - dim - The topological dimension
6401c73cfb54SMatthew G. Knepley 
6402c73cfb54SMatthew G. Knepley   Level: beginner
6403c73cfb54SMatthew G. Knepley 
64041cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDimension()`, `DMCreate()`
6405c73cfb54SMatthew G. Knepley @*/
6406d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
6407d71ae5a4SJacob Faibussowitsch {
6408e5e52638SMatthew G. Knepley   PetscDS  ds;
640945480ffeSMatthew G. Knepley   PetscInt Nds, n;
6410f17e8794SMatthew G. Knepley 
6411c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6412c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6413c73cfb54SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6414c73cfb54SMatthew G. Knepley   dm->dim = dim;
6415d17bd122SMatthew G. Knepley   if (dm->dim >= 0) {
64169566063dSJacob Faibussowitsch     PetscCall(DMGetNumDS(dm, &Nds));
641745480ffeSMatthew G. Knepley     for (n = 0; n < Nds; ++n) {
641807218a29SMatthew G. Knepley       PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds, NULL));
64199566063dSJacob Faibussowitsch       if (ds->dimEmbed < 0) PetscCall(PetscDSSetCoordinateDimension(ds, dim));
642045480ffeSMatthew G. Knepley     }
6421d17bd122SMatthew G. Knepley   }
64223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6423c73cfb54SMatthew G. Knepley }
6424c73cfb54SMatthew G. Knepley 
6425793f3fe5SMatthew G. Knepley /*@
6426793f3fe5SMatthew G. Knepley   DMGetDimPoints - Get the half-open interval for all points of a given dimension
6427793f3fe5SMatthew G. Knepley 
642820f4b53cSBarry Smith   Collective
6429793f3fe5SMatthew G. Knepley 
6430793f3fe5SMatthew G. Knepley   Input Parameters:
6431bb7acecfSBarry Smith + dm  - the `DM`
6432793f3fe5SMatthew G. Knepley - dim - the dimension
6433793f3fe5SMatthew G. Knepley 
6434793f3fe5SMatthew G. Knepley   Output Parameters:
6435793f3fe5SMatthew G. Knepley + pStart - The first point of the given dimension
6436aa049354SPatrick Sanan - pEnd   - The first point following points of the given dimension
6437793f3fe5SMatthew G. Knepley 
643820f4b53cSBarry Smith   Level: intermediate
643920f4b53cSBarry Smith 
6440793f3fe5SMatthew G. Knepley   Note:
6441793f3fe5SMatthew G. Knepley   The points are vertices in the Hasse diagram encoding the topology. This is explained in
6442a8d69d7bSBarry Smith   https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme,
6443793f3fe5SMatthew G. Knepley   then the interval is empty.
6444793f3fe5SMatthew G. Knepley 
64451cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
6446793f3fe5SMatthew G. Knepley @*/
6447d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
6448d71ae5a4SJacob Faibussowitsch {
6449793f3fe5SMatthew G. Knepley   PetscInt d;
6450793f3fe5SMatthew G. Knepley 
6451793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
6452793f3fe5SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64539566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &d));
64547a8be351SBarry Smith   PetscCheck((dim >= 0) && (dim <= d), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %" PetscInt_FMT, dim);
6455dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getdimpoints, dim, pStart, pEnd);
64563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6457793f3fe5SMatthew G. Knepley }
6458793f3fe5SMatthew G. Knepley 
64596636e97aSMatthew G Knepley /*@
6460bb7acecfSBarry Smith   DMGetOutputDM - Retrieve the `DM` associated with the layout for output
6461f4d763aaSMatthew G. Knepley 
646220f4b53cSBarry Smith   Collective
64638f700142SStefano Zampini 
6464f4d763aaSMatthew G. Knepley   Input Parameter:
6465bb7acecfSBarry Smith . dm - The original `DM`
6466f4d763aaSMatthew G. Knepley 
6467f4d763aaSMatthew G. Knepley   Output Parameter:
6468bb7acecfSBarry Smith . odm - The `DM` which provides the layout for output
6469f4d763aaSMatthew G. Knepley 
6470f4d763aaSMatthew G. Knepley   Level: intermediate
6471f4d763aaSMatthew G. Knepley 
6472bb7acecfSBarry Smith   Note:
6473bb7acecfSBarry Smith   In some situations the vector obtained with `DMCreateGlobalVector()` excludes points for degrees of freedom that are associated with fixed (Dirichelet) boundary
6474bb7acecfSBarry 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
6475bb7acecfSBarry Smith   locations for those dof so that they can be output to a file or other viewer along with the unconstrained dof.
6476bb7acecfSBarry Smith 
64771cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`, `DMGetGlobalSection()`, `DMCreateGlobalVector()`, `PetscSectionHasConstraints()`, `DMSetGlobalSection()`
6478f4d763aaSMatthew G. Knepley @*/
6479d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
6480d71ae5a4SJacob Faibussowitsch {
6481c26acbdeSMatthew G. Knepley   PetscSection section;
6482eb9d3e4dSMatthew G. Knepley   IS           perm;
6483eb9d3e4dSMatthew G. Knepley   PetscBool    hasConstraints, newDM, gnewDM;
648414f150ffSMatthew G. Knepley 
648514f150ffSMatthew G. Knepley   PetscFunctionBegin;
648614f150ffSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64874f572ea9SToby Isaac   PetscAssertPointer(odm, 2);
64889566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
64899566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
6490eb9d3e4dSMatthew G. Knepley   PetscCall(PetscSectionGetPermutation(section, &perm));
6491eb9d3e4dSMatthew G. Knepley   newDM = hasConstraints || perm ? PETSC_TRUE : PETSC_FALSE;
6492462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&newDM, &gnewDM, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
6493eb9d3e4dSMatthew G. Knepley   if (!gnewDM) {
6494c26acbdeSMatthew G. Knepley     *odm = dm;
64953ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6496c26acbdeSMatthew G. Knepley   }
649714f150ffSMatthew G. Knepley   if (!dm->dmBC) {
6498c26acbdeSMatthew G. Knepley     PetscSection newSection, gsection;
649914f150ffSMatthew G. Knepley     PetscSF      sf;
6500eb9d3e4dSMatthew G. Knepley     PetscBool    usePerm = dm->ignorePermOutput ? PETSC_FALSE : PETSC_TRUE;
650114f150ffSMatthew G. Knepley 
65029566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &dm->dmBC));
65039566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dm, dm->dmBC));
65049566063dSJacob Faibussowitsch     PetscCall(PetscSectionClone(section, &newSection));
65059566063dSJacob Faibussowitsch     PetscCall(DMSetLocalSection(dm->dmBC, newSection));
65069566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&newSection));
65079566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm->dmBC, &sf));
6508eb9d3e4dSMatthew G. Knepley     PetscCall(PetscSectionCreateGlobalSection(section, sf, usePerm, PETSC_TRUE, PETSC_FALSE, &gsection));
65099566063dSJacob Faibussowitsch     PetscCall(DMSetGlobalSection(dm->dmBC, gsection));
65109566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&gsection));
651114f150ffSMatthew G. Knepley   }
651214f150ffSMatthew G. Knepley   *odm = dm->dmBC;
65133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
651414f150ffSMatthew G. Knepley }
6515f4d763aaSMatthew G. Knepley 
6516f4d763aaSMatthew G. Knepley /*@
6517cdb7a50dSMatthew G. Knepley   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
6518f4d763aaSMatthew G. Knepley 
6519f4d763aaSMatthew G. Knepley   Input Parameter:
6520bb7acecfSBarry Smith . dm - The original `DM`
6521f4d763aaSMatthew G. Knepley 
6522cdb7a50dSMatthew G. Knepley   Output Parameters:
6523cdb7a50dSMatthew G. Knepley + num - The output sequence number
6524cdb7a50dSMatthew G. Knepley - val - The output sequence value
6525f4d763aaSMatthew G. Knepley 
6526f4d763aaSMatthew G. Knepley   Level: intermediate
6527f4d763aaSMatthew G. Knepley 
6528bb7acecfSBarry Smith   Note:
6529bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6530bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6531bb7acecfSBarry Smith 
653273ff1848SBarry Smith   Developer Note:
6533bb7acecfSBarry Smith   The `DM` serves as a convenient place to store the current iteration value. The iteration is not
6534bb7acecfSBarry Smith   not directly related to the `DM`.
6535f4d763aaSMatthew G. Knepley 
65361cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`
6537f4d763aaSMatthew G. Knepley @*/
6538d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
6539d71ae5a4SJacob Faibussowitsch {
6540f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6541f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65429371c9d4SSatish Balay   if (num) {
65434f572ea9SToby Isaac     PetscAssertPointer(num, 2);
65449371c9d4SSatish Balay     *num = dm->outputSequenceNum;
65459371c9d4SSatish Balay   }
65469371c9d4SSatish Balay   if (val) {
65474f572ea9SToby Isaac     PetscAssertPointer(val, 3);
65489371c9d4SSatish Balay     *val = dm->outputSequenceVal;
65499371c9d4SSatish Balay   }
65503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6551f4d763aaSMatthew G. Knepley }
6552f4d763aaSMatthew G. Knepley 
6553f4d763aaSMatthew G. Knepley /*@
6554cdb7a50dSMatthew G. Knepley   DMSetOutputSequenceNumber - Set the sequence number/value for output
6555f4d763aaSMatthew G. Knepley 
6556f4d763aaSMatthew G. Knepley   Input Parameters:
6557bb7acecfSBarry Smith + dm  - The original `DM`
6558cdb7a50dSMatthew G. Knepley . num - The output sequence number
6559cdb7a50dSMatthew G. Knepley - val - The output sequence value
6560f4d763aaSMatthew G. Knepley 
6561f4d763aaSMatthew G. Knepley   Level: intermediate
6562f4d763aaSMatthew G. Knepley 
6563bb7acecfSBarry Smith   Note:
6564bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6565bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6566f4d763aaSMatthew G. Knepley 
65671cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`
6568f4d763aaSMatthew G. Knepley @*/
6569d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
6570d71ae5a4SJacob Faibussowitsch {
6571f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6572f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6573f4d763aaSMatthew G. Knepley   dm->outputSequenceNum = num;
6574cdb7a50dSMatthew G. Knepley   dm->outputSequenceVal = val;
65753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6576cdb7a50dSMatthew G. Knepley }
6577cdb7a50dSMatthew G. Knepley 
65785d83a8b1SBarry Smith /*@
6579bb7acecfSBarry Smith   DMOutputSequenceLoad - Retrieve the sequence value from a `PetscViewer`
6580cdb7a50dSMatthew G. Knepley 
6581cdb7a50dSMatthew G. Knepley   Input Parameters:
6582bb7acecfSBarry Smith + dm     - The original `DM`
6583b2033f5dSMatthew G. Knepley . viewer - The `PetscViewer` to get it from
6584cdb7a50dSMatthew G. Knepley . name   - The sequence name
6585cdb7a50dSMatthew G. Knepley - num    - The output sequence number
6586cdb7a50dSMatthew G. Knepley 
6587cdb7a50dSMatthew G. Knepley   Output Parameter:
6588cdb7a50dSMatthew G. Knepley . val - The output sequence value
6589cdb7a50dSMatthew G. Knepley 
6590cdb7a50dSMatthew G. Knepley   Level: intermediate
6591cdb7a50dSMatthew G. Knepley 
6592bb7acecfSBarry Smith   Note:
6593bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6594bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6595bb7acecfSBarry Smith 
659673ff1848SBarry Smith   Developer Note:
6597bb7acecfSBarry Smith   It is unclear at the user API level why a `DM` is needed as input
6598cdb7a50dSMatthew G. Knepley 
65991cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetOutputSequenceNumber()`, `DMSetOutputSequenceNumber()`, `VecView()`
6600cdb7a50dSMatthew G. Knepley @*/
6601b2033f5dSMatthew G. Knepley PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char name[], PetscInt num, PetscReal *val)
6602d71ae5a4SJacob Faibussowitsch {
6603cdb7a50dSMatthew G. Knepley   PetscBool ishdf5;
6604cdb7a50dSMatthew G. Knepley 
6605cdb7a50dSMatthew G. Knepley   PetscFunctionBegin;
6606cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6607cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
6608b2033f5dSMatthew G. Knepley   PetscAssertPointer(name, 3);
66094f572ea9SToby Isaac   PetscAssertPointer(val, 5);
66109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6611cdb7a50dSMatthew G. Knepley   if (ishdf5) {
6612cdb7a50dSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6613cdb7a50dSMatthew G. Knepley     PetscScalar value;
6614cdb7a50dSMatthew G. Knepley 
66159566063dSJacob Faibussowitsch     PetscCall(DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer));
66164aeb217fSMatthew G. Knepley     *val = PetscRealPart(value);
6617cdb7a50dSMatthew G. Knepley #endif
6618cdb7a50dSMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
66193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6620f4d763aaSMatthew G. Knepley }
66218e4ac7eaSMatthew G. Knepley 
66228e4ac7eaSMatthew G. Knepley /*@
6623b2033f5dSMatthew G. Knepley   DMGetOutputSequenceLength - Retrieve the number of sequence values from a `PetscViewer`
6624b2033f5dSMatthew G. Knepley 
6625b2033f5dSMatthew G. Knepley   Input Parameters:
6626b2033f5dSMatthew G. Knepley + dm     - The original `DM`
6627b2033f5dSMatthew G. Knepley . viewer - The `PetscViewer` to get it from
6628b2033f5dSMatthew G. Knepley - name   - The sequence name
6629b2033f5dSMatthew G. Knepley 
6630b2033f5dSMatthew G. Knepley   Output Parameter:
6631b2033f5dSMatthew G. Knepley . len - The length of the output sequence
6632b2033f5dSMatthew G. Knepley 
6633b2033f5dSMatthew G. Knepley   Level: intermediate
6634b2033f5dSMatthew G. Knepley 
6635b2033f5dSMatthew G. Knepley   Note:
6636b2033f5dSMatthew G. Knepley   This is intended for output that should appear in sequence, for instance
6637b2033f5dSMatthew G. Knepley   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6638b2033f5dSMatthew G. Knepley 
6639b2033f5dSMatthew G. Knepley   Developer Note:
6640b2033f5dSMatthew G. Knepley   It is unclear at the user API level why a `DM` is needed as input
6641b2033f5dSMatthew G. Knepley 
6642b2033f5dSMatthew G. Knepley .seealso: [](ch_dmbase), `DM`, `DMGetOutputSequenceNumber()`, `DMSetOutputSequenceNumber()`, `VecView()`
6643b2033f5dSMatthew G. Knepley @*/
6644b2033f5dSMatthew G. Knepley PetscErrorCode DMGetOutputSequenceLength(DM dm, PetscViewer viewer, const char name[], PetscInt *len)
6645b2033f5dSMatthew G. Knepley {
6646b2033f5dSMatthew G. Knepley   PetscBool ishdf5;
6647b2033f5dSMatthew G. Knepley 
6648b2033f5dSMatthew G. Knepley   PetscFunctionBegin;
6649b2033f5dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6650b2033f5dSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
6651b2033f5dSMatthew G. Knepley   PetscAssertPointer(name, 3);
6652b2033f5dSMatthew G. Knepley   PetscAssertPointer(len, 4);
6653b2033f5dSMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6654b2033f5dSMatthew G. Knepley   if (ishdf5) {
6655b2033f5dSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6656b2033f5dSMatthew G. Knepley     PetscCall(DMSequenceGetLength_HDF5_Internal(dm, name, len, viewer));
6657b2033f5dSMatthew G. Knepley #endif
6658b2033f5dSMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
6659b2033f5dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6660b2033f5dSMatthew G. Knepley }
6661b2033f5dSMatthew G. Knepley 
6662b2033f5dSMatthew G. Knepley /*@
6663bb7acecfSBarry Smith   DMGetUseNatural - Get the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
66648e4ac7eaSMatthew G. Knepley 
666520f4b53cSBarry Smith   Not Collective
66668e4ac7eaSMatthew G. Knepley 
66678e4ac7eaSMatthew G. Knepley   Input Parameter:
6668bb7acecfSBarry Smith . dm - The `DM`
66698e4ac7eaSMatthew G. Knepley 
66708e4ac7eaSMatthew G. Knepley   Output Parameter:
6671bb7acecfSBarry Smith . useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
66728e4ac7eaSMatthew G. Knepley 
66738e4ac7eaSMatthew G. Knepley   Level: beginner
66748e4ac7eaSMatthew G. Knepley 
66751cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetUseNatural()`, `DMCreate()`
66768e4ac7eaSMatthew G. Knepley @*/
6677d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
6678d71ae5a4SJacob Faibussowitsch {
66798e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
66808e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
66814f572ea9SToby Isaac   PetscAssertPointer(useNatural, 2);
66828e4ac7eaSMatthew G. Knepley   *useNatural = dm->useNatural;
66833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66848e4ac7eaSMatthew G. Knepley }
66858e4ac7eaSMatthew G. Knepley 
66868e4ac7eaSMatthew G. Knepley /*@
6687bb7acecfSBarry Smith   DMSetUseNatural - Set the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
66888e4ac7eaSMatthew G. Knepley 
668920f4b53cSBarry Smith   Collective
66908e4ac7eaSMatthew G. Knepley 
66918e4ac7eaSMatthew G. Knepley   Input Parameters:
6692bb7acecfSBarry Smith + dm         - The `DM`
6693bb7acecfSBarry Smith - useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
66948e4ac7eaSMatthew G. Knepley 
669573ff1848SBarry Smith   Level: beginner
669673ff1848SBarry Smith 
6697bb7acecfSBarry Smith   Note:
6698bb7acecfSBarry Smith   This also causes the map to be build after `DMCreateSubDM()` and `DMCreateSuperDM()`
66995d3b26e6SMatthew G. Knepley 
67001cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetUseNatural()`, `DMCreate()`, `DMPlexDistribute()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
67018e4ac7eaSMatthew G. Knepley @*/
6702d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
6703d71ae5a4SJacob Faibussowitsch {
67048e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
67058e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67068833efb5SBlaise Bourdin   PetscValidLogicalCollectiveBool(dm, useNatural, 2);
67078e4ac7eaSMatthew G. Knepley   dm->useNatural = useNatural;
67083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67098e4ac7eaSMatthew G. Knepley }
6710c58f1c22SToby Isaac 
6711cc4c1da9SBarry Smith /*@
6712bb7acecfSBarry Smith   DMCreateLabel - Create a label of the given name if it does not already exist in the `DM`
6713c58f1c22SToby Isaac 
6714c58f1c22SToby Isaac   Not Collective
6715c58f1c22SToby Isaac 
6716c58f1c22SToby Isaac   Input Parameters:
6717bb7acecfSBarry Smith + dm   - The `DM` object
6718c58f1c22SToby Isaac - name - The label name
6719c58f1c22SToby Isaac 
6720c58f1c22SToby Isaac   Level: intermediate
6721c58f1c22SToby Isaac 
67221cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6723c58f1c22SToby Isaac @*/
6724d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabel(DM dm, const char name[])
6725d71ae5a4SJacob Faibussowitsch {
67265d80c0bfSVaclav Hapla   PetscBool flg;
67275d80c0bfSVaclav Hapla   DMLabel   label;
6728c58f1c22SToby Isaac 
6729c58f1c22SToby Isaac   PetscFunctionBegin;
6730c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67314f572ea9SToby Isaac   PetscAssertPointer(name, 2);
67329566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
6733c58f1c22SToby Isaac   if (!flg) {
67349566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
67359566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
67369566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
6737c58f1c22SToby Isaac   }
67383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6739c58f1c22SToby Isaac }
6740c58f1c22SToby Isaac 
6741cc4c1da9SBarry Smith /*@
6742bb7acecfSBarry 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.
67430fdc7489SMatthew Knepley 
67440fdc7489SMatthew Knepley   Not Collective
67450fdc7489SMatthew Knepley 
67460fdc7489SMatthew Knepley   Input Parameters:
6747bb7acecfSBarry Smith + dm   - The `DM` object
67480fdc7489SMatthew Knepley . l    - The index for the label
67490fdc7489SMatthew Knepley - name - The label name
67500fdc7489SMatthew Knepley 
67510fdc7489SMatthew Knepley   Level: intermediate
67520fdc7489SMatthew Knepley 
67531cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateLabel()`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
67540fdc7489SMatthew Knepley @*/
6755d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[])
6756d71ae5a4SJacob Faibussowitsch {
67570fdc7489SMatthew Knepley   DMLabelLink orig, prev = NULL;
67580fdc7489SMatthew Knepley   DMLabel     label;
67590fdc7489SMatthew Knepley   PetscInt    Nl, m;
67600fdc7489SMatthew Knepley   PetscBool   flg, match;
67610fdc7489SMatthew Knepley   const char *lname;
67620fdc7489SMatthew Knepley 
67630fdc7489SMatthew Knepley   PetscFunctionBegin;
67640fdc7489SMatthew Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67654f572ea9SToby Isaac   PetscAssertPointer(name, 3);
67669566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
67670fdc7489SMatthew Knepley   if (!flg) {
67689566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
67699566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
67709566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
67710fdc7489SMatthew Knepley   }
67729566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
677363a3b9bcSJacob Faibussowitsch   PetscCheck(l < Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", l, Nl);
67740fdc7489SMatthew Knepley   for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) {
67759566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)orig->label, &lname));
67769566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &match));
67770fdc7489SMatthew Knepley     if (match) break;
67780fdc7489SMatthew Knepley   }
67793ba16761SJacob Faibussowitsch   if (m == l) PetscFunctionReturn(PETSC_SUCCESS);
67800fdc7489SMatthew Knepley   if (!m) dm->labels = orig->next;
67810fdc7489SMatthew Knepley   else prev->next = orig->next;
67820fdc7489SMatthew Knepley   if (!l) {
67830fdc7489SMatthew Knepley     orig->next = dm->labels;
67840fdc7489SMatthew Knepley     dm->labels = orig;
67850fdc7489SMatthew Knepley   } else {
6786fbccb6d4SPierre Jolivet     for (m = 0, prev = dm->labels; m < l - 1; ++m, prev = prev->next);
67870fdc7489SMatthew Knepley     orig->next = prev->next;
67880fdc7489SMatthew Knepley     prev->next = orig;
67890fdc7489SMatthew Knepley   }
67903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
67910fdc7489SMatthew Knepley }
67920fdc7489SMatthew Knepley 
6793cc4c1da9SBarry Smith /*@
6794bb7acecfSBarry Smith   DMGetLabelValue - Get the value in a `DMLabel` for the given point, with -1 as the default
6795c58f1c22SToby Isaac 
6796c58f1c22SToby Isaac   Not Collective
6797c58f1c22SToby Isaac 
6798c58f1c22SToby Isaac   Input Parameters:
6799bb7acecfSBarry Smith + dm    - The `DM` object
6800c58f1c22SToby Isaac . name  - The label name
6801c58f1c22SToby Isaac - point - The mesh point
6802c58f1c22SToby Isaac 
6803c58f1c22SToby Isaac   Output Parameter:
6804c58f1c22SToby Isaac . value - The label value for this point, or -1 if the point is not in the label
6805c58f1c22SToby Isaac 
6806c58f1c22SToby Isaac   Level: beginner
6807c58f1c22SToby Isaac 
68081cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6809c58f1c22SToby Isaac @*/
6810d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
6811d71ae5a4SJacob Faibussowitsch {
6812c58f1c22SToby Isaac   DMLabel label;
6813c58f1c22SToby Isaac 
6814c58f1c22SToby Isaac   PetscFunctionBegin;
6815c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68164f572ea9SToby Isaac   PetscAssertPointer(name, 2);
68179566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
68187a8be351SBarry Smith   PetscCheck(label, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
68199566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, point, value));
68203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6821c58f1c22SToby Isaac }
6822c58f1c22SToby Isaac 
6823cc4c1da9SBarry Smith /*@
6824bb7acecfSBarry Smith   DMSetLabelValue - Add a point to a `DMLabel` with given value
6825c58f1c22SToby Isaac 
6826c58f1c22SToby Isaac   Not Collective
6827c58f1c22SToby Isaac 
6828c58f1c22SToby Isaac   Input Parameters:
6829bb7acecfSBarry Smith + dm    - The `DM` object
6830c58f1c22SToby Isaac . name  - The label name
6831c58f1c22SToby Isaac . point - The mesh point
6832c58f1c22SToby Isaac - value - The label value for this point
6833c58f1c22SToby Isaac 
6834c58f1c22SToby Isaac   Output Parameter:
6835c58f1c22SToby Isaac 
6836c58f1c22SToby Isaac   Level: beginner
6837c58f1c22SToby Isaac 
68381cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelSetValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6839c58f1c22SToby Isaac @*/
6840d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6841d71ae5a4SJacob Faibussowitsch {
6842c58f1c22SToby Isaac   DMLabel label;
6843c58f1c22SToby Isaac 
6844c58f1c22SToby Isaac   PetscFunctionBegin;
6845c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68464f572ea9SToby Isaac   PetscAssertPointer(name, 2);
68479566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6848c58f1c22SToby Isaac   if (!label) {
68499566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
68509566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
6851c58f1c22SToby Isaac   }
68529566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, point, value));
68533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6854c58f1c22SToby Isaac }
6855c58f1c22SToby Isaac 
6856cc4c1da9SBarry Smith /*@
6857bb7acecfSBarry Smith   DMClearLabelValue - Remove a point from a `DMLabel` with given value
6858c58f1c22SToby Isaac 
6859c58f1c22SToby Isaac   Not Collective
6860c58f1c22SToby Isaac 
6861c58f1c22SToby Isaac   Input Parameters:
6862bb7acecfSBarry Smith + dm    - The `DM` object
6863c58f1c22SToby Isaac . name  - The label name
6864c58f1c22SToby Isaac . point - The mesh point
6865c58f1c22SToby Isaac - value - The label value for this point
6866c58f1c22SToby Isaac 
6867c58f1c22SToby Isaac   Level: beginner
6868c58f1c22SToby Isaac 
68691cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelClearValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6870c58f1c22SToby Isaac @*/
6871d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6872d71ae5a4SJacob Faibussowitsch {
6873c58f1c22SToby Isaac   DMLabel label;
6874c58f1c22SToby Isaac 
6875c58f1c22SToby Isaac   PetscFunctionBegin;
6876c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68774f572ea9SToby Isaac   PetscAssertPointer(name, 2);
68789566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
68793ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
68809566063dSJacob Faibussowitsch   PetscCall(DMLabelClearValue(label, point, value));
68813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6882c58f1c22SToby Isaac }
6883c58f1c22SToby Isaac 
6884cc4c1da9SBarry Smith /*@
6885bb7acecfSBarry Smith   DMGetLabelSize - Get the value of `DMLabelGetNumValues()` of a `DMLabel` in the `DM`
6886c58f1c22SToby Isaac 
6887c58f1c22SToby Isaac   Not Collective
6888c58f1c22SToby Isaac 
6889c58f1c22SToby Isaac   Input Parameters:
6890bb7acecfSBarry Smith + dm   - The `DM` object
6891c58f1c22SToby Isaac - name - The label name
6892c58f1c22SToby Isaac 
6893c58f1c22SToby Isaac   Output Parameter:
6894c58f1c22SToby Isaac . size - The number of different integer ids, or 0 if the label does not exist
6895c58f1c22SToby Isaac 
6896c58f1c22SToby Isaac   Level: beginner
6897c58f1c22SToby Isaac 
689873ff1848SBarry Smith   Developer Note:
6899bb7acecfSBarry Smith   This should be renamed to something like `DMGetLabelNumValues()` or removed.
6900bb7acecfSBarry Smith 
69011cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetNumValues()`, `DMSetLabelValue()`, `DMGetLabel()`
6902c58f1c22SToby Isaac @*/
6903d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
6904d71ae5a4SJacob Faibussowitsch {
6905c58f1c22SToby Isaac   DMLabel label;
6906c58f1c22SToby Isaac 
6907c58f1c22SToby Isaac   PetscFunctionBegin;
6908c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69094f572ea9SToby Isaac   PetscAssertPointer(name, 2);
69104f572ea9SToby Isaac   PetscAssertPointer(size, 3);
69119566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6912c58f1c22SToby Isaac   *size = 0;
69133ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
69149566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, size));
69153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6916c58f1c22SToby Isaac }
6917c58f1c22SToby Isaac 
6918cc4c1da9SBarry Smith /*@
6919bb7acecfSBarry Smith   DMGetLabelIdIS - Get the `DMLabelGetValueIS()` from a `DMLabel` in the `DM`
6920c58f1c22SToby Isaac 
6921c58f1c22SToby Isaac   Not Collective
6922c58f1c22SToby Isaac 
6923c58f1c22SToby Isaac   Input Parameters:
692460225df5SJacob Faibussowitsch + dm   - The `DM` object
6925c58f1c22SToby Isaac - name - The label name
6926c58f1c22SToby Isaac 
6927c58f1c22SToby Isaac   Output Parameter:
692820f4b53cSBarry Smith . ids - The integer ids, or `NULL` if the label does not exist
6929c58f1c22SToby Isaac 
6930c58f1c22SToby Isaac   Level: beginner
6931c58f1c22SToby Isaac 
69321cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetValueIS()`, `DMGetLabelSize()`
6933c58f1c22SToby Isaac @*/
6934d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
6935d71ae5a4SJacob Faibussowitsch {
6936c58f1c22SToby Isaac   DMLabel label;
6937c58f1c22SToby Isaac 
6938c58f1c22SToby Isaac   PetscFunctionBegin;
6939c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69404f572ea9SToby Isaac   PetscAssertPointer(name, 2);
69414f572ea9SToby Isaac   PetscAssertPointer(ids, 3);
69429566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6943c58f1c22SToby Isaac   *ids = NULL;
6944dab2e251SBlaise Bourdin   if (label) {
69459566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, ids));
6946dab2e251SBlaise Bourdin   } else {
6947dab2e251SBlaise Bourdin     /* returning an empty IS */
69489566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, ids));
6949dab2e251SBlaise Bourdin   }
69503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6951c58f1c22SToby Isaac }
6952c58f1c22SToby Isaac 
6953cc4c1da9SBarry Smith /*@
6954c58f1c22SToby Isaac   DMGetStratumSize - Get the number of points in a label stratum
6955c58f1c22SToby Isaac 
6956c58f1c22SToby Isaac   Not Collective
6957c58f1c22SToby Isaac 
6958c58f1c22SToby Isaac   Input Parameters:
6959bb7acecfSBarry Smith + dm    - The `DM` object
6960b6971eaeSBarry Smith . name  - The label name of the stratum
6961c58f1c22SToby Isaac - value - The stratum value
6962c58f1c22SToby Isaac 
6963c58f1c22SToby Isaac   Output Parameter:
6964bb7acecfSBarry Smith . size - The number of points, also called the stratum size
6965c58f1c22SToby Isaac 
6966c58f1c22SToby Isaac   Level: beginner
6967c58f1c22SToby Isaac 
69681cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetStratumSize()`, `DMGetLabelSize()`, `DMGetLabelIds()`
6969c58f1c22SToby Isaac @*/
6970d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
6971d71ae5a4SJacob Faibussowitsch {
6972c58f1c22SToby Isaac   DMLabel label;
6973c58f1c22SToby Isaac 
6974c58f1c22SToby Isaac   PetscFunctionBegin;
6975c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69764f572ea9SToby Isaac   PetscAssertPointer(name, 2);
69774f572ea9SToby Isaac   PetscAssertPointer(size, 4);
69789566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6979c58f1c22SToby Isaac   *size = 0;
69803ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
69819566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize(label, value, size));
69823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6983c58f1c22SToby Isaac }
6984c58f1c22SToby Isaac 
6985cc4c1da9SBarry Smith /*@
6986c58f1c22SToby Isaac   DMGetStratumIS - Get the points in a label stratum
6987c58f1c22SToby Isaac 
6988c58f1c22SToby Isaac   Not Collective
6989c58f1c22SToby Isaac 
6990c58f1c22SToby Isaac   Input Parameters:
6991bb7acecfSBarry Smith + dm    - The `DM` object
6992c58f1c22SToby Isaac . name  - The label name
6993c58f1c22SToby Isaac - value - The stratum value
6994c58f1c22SToby Isaac 
6995c58f1c22SToby Isaac   Output Parameter:
699620f4b53cSBarry Smith . points - The stratum points, or `NULL` if the label does not exist or does not have that value
6997c58f1c22SToby Isaac 
6998c58f1c22SToby Isaac   Level: beginner
6999c58f1c22SToby Isaac 
70001cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetStratumIS()`, `DMGetStratumSize()`
7001c58f1c22SToby Isaac @*/
7002d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
7003d71ae5a4SJacob Faibussowitsch {
7004c58f1c22SToby Isaac   DMLabel label;
7005c58f1c22SToby Isaac 
7006c58f1c22SToby Isaac   PetscFunctionBegin;
7007c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70084f572ea9SToby Isaac   PetscAssertPointer(name, 2);
70094f572ea9SToby Isaac   PetscAssertPointer(points, 4);
70109566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
7011c58f1c22SToby Isaac   *points = NULL;
70123ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
70139566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, points));
70143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7015c58f1c22SToby Isaac }
7016c58f1c22SToby Isaac 
7017cc4c1da9SBarry Smith /*@
70189044fa66SMatthew G. Knepley   DMSetStratumIS - Set the points in a label stratum
70194de306b1SToby Isaac 
70204de306b1SToby Isaac   Not Collective
70214de306b1SToby Isaac 
70224de306b1SToby Isaac   Input Parameters:
7023bb7acecfSBarry Smith + dm     - The `DM` object
70244de306b1SToby Isaac . name   - The label name
70254de306b1SToby Isaac . value  - The stratum value
70264de306b1SToby Isaac - points - The stratum points
70274de306b1SToby Isaac 
70284de306b1SToby Isaac   Level: beginner
70294de306b1SToby Isaac 
70301cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMClearLabelStratum()`, `DMLabelClearStratum()`, `DMLabelSetStratumIS()`, `DMGetStratumSize()`
70314de306b1SToby Isaac @*/
7032d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
7033d71ae5a4SJacob Faibussowitsch {
70344de306b1SToby Isaac   DMLabel label;
70354de306b1SToby Isaac 
70364de306b1SToby Isaac   PetscFunctionBegin;
70374de306b1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70384f572ea9SToby Isaac   PetscAssertPointer(name, 2);
7039292bffcbSToby Isaac   PetscValidHeaderSpecific(points, IS_CLASSID, 4);
70409566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
70413ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
70429566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, points));
70433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70444de306b1SToby Isaac }
70454de306b1SToby Isaac 
7046cc4c1da9SBarry Smith /*@
7047bb7acecfSBarry Smith   DMClearLabelStratum - Remove all points from a stratum from a `DMLabel`
7048c58f1c22SToby Isaac 
7049c58f1c22SToby Isaac   Not Collective
7050c58f1c22SToby Isaac 
7051c58f1c22SToby Isaac   Input Parameters:
7052bb7acecfSBarry Smith + dm    - The `DM` object
7053c58f1c22SToby Isaac . name  - The label name
7054c58f1c22SToby Isaac - value - The label value for this point
7055c58f1c22SToby Isaac 
7056c58f1c22SToby Isaac   Output Parameter:
7057c58f1c22SToby Isaac 
7058c58f1c22SToby Isaac   Level: beginner
7059c58f1c22SToby Isaac 
70601cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMLabelClearStratum()`, `DMSetLabelValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
7061c58f1c22SToby Isaac @*/
7062d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
7063d71ae5a4SJacob Faibussowitsch {
7064c58f1c22SToby Isaac   DMLabel label;
7065c58f1c22SToby Isaac 
7066c58f1c22SToby Isaac   PetscFunctionBegin;
7067c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70684f572ea9SToby Isaac   PetscAssertPointer(name, 2);
70699566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
70703ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
70719566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
70723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7073c58f1c22SToby Isaac }
7074c58f1c22SToby Isaac 
7075c58f1c22SToby Isaac /*@
7076bb7acecfSBarry Smith   DMGetNumLabels - Return the number of labels defined by on the `DM`
7077c58f1c22SToby Isaac 
7078c58f1c22SToby Isaac   Not Collective
7079c58f1c22SToby Isaac 
7080c58f1c22SToby Isaac   Input Parameter:
7081bb7acecfSBarry Smith . dm - The `DM` object
7082c58f1c22SToby Isaac 
7083c58f1c22SToby Isaac   Output Parameter:
7084c58f1c22SToby Isaac . numLabels - the number of Labels
7085c58f1c22SToby Isaac 
7086c58f1c22SToby Isaac   Level: intermediate
7087c58f1c22SToby Isaac 
70881cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabelByNum()`, `DMGetLabelName()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7089c58f1c22SToby Isaac @*/
7090d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
7091d71ae5a4SJacob Faibussowitsch {
70925d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7093c58f1c22SToby Isaac   PetscInt    n    = 0;
7094c58f1c22SToby Isaac 
7095c58f1c22SToby Isaac   PetscFunctionBegin;
7096c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70974f572ea9SToby Isaac   PetscAssertPointer(numLabels, 2);
70989371c9d4SSatish Balay   while (next) {
70999371c9d4SSatish Balay     ++n;
71009371c9d4SSatish Balay     next = next->next;
71019371c9d4SSatish Balay   }
7102c58f1c22SToby Isaac   *numLabels = n;
71033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7104c58f1c22SToby Isaac }
7105c58f1c22SToby Isaac 
7106cc4c1da9SBarry Smith /*@
7107c58f1c22SToby Isaac   DMGetLabelName - Return the name of nth label
7108c58f1c22SToby Isaac 
7109c58f1c22SToby Isaac   Not Collective
7110c58f1c22SToby Isaac 
7111c58f1c22SToby Isaac   Input Parameters:
7112bb7acecfSBarry Smith + dm - The `DM` object
7113c58f1c22SToby Isaac - n  - the label number
7114c58f1c22SToby Isaac 
7115c58f1c22SToby Isaac   Output Parameter:
7116c58f1c22SToby Isaac . name - the label name
7117c58f1c22SToby Isaac 
7118c58f1c22SToby Isaac   Level: intermediate
7119c58f1c22SToby Isaac 
712073ff1848SBarry Smith   Developer Note:
7121bb7acecfSBarry Smith   Some of the functions that appropriate on labels using their number have the suffix ByNum, others do not.
7122bb7acecfSBarry Smith 
71231cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabelByNum()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7124c58f1c22SToby Isaac @*/
7125cc4c1da9SBarry Smith PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char *name[])
7126d71ae5a4SJacob Faibussowitsch {
71275d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7128c58f1c22SToby Isaac   PetscInt    l    = 0;
7129c58f1c22SToby Isaac 
7130c58f1c22SToby Isaac   PetscFunctionBegin;
7131c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71324f572ea9SToby Isaac   PetscAssertPointer(name, 3);
7133c58f1c22SToby Isaac   while (next) {
7134c58f1c22SToby Isaac     if (l == n) {
71359566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)next->label, name));
71363ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
7137c58f1c22SToby Isaac     }
7138c58f1c22SToby Isaac     ++l;
7139c58f1c22SToby Isaac     next = next->next;
7140c58f1c22SToby Isaac   }
714163a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
7142c58f1c22SToby Isaac }
7143c58f1c22SToby Isaac 
7144cc4c1da9SBarry Smith /*@
7145bb7acecfSBarry Smith   DMHasLabel - Determine whether the `DM` has a label of a given name
7146c58f1c22SToby Isaac 
7147c58f1c22SToby Isaac   Not Collective
7148c58f1c22SToby Isaac 
7149c58f1c22SToby Isaac   Input Parameters:
7150bb7acecfSBarry Smith + dm   - The `DM` object
7151c58f1c22SToby Isaac - name - The label name
7152c58f1c22SToby Isaac 
7153c58f1c22SToby Isaac   Output Parameter:
7154bb7acecfSBarry Smith . hasLabel - `PETSC_TRUE` if the label is present
7155c58f1c22SToby Isaac 
7156c58f1c22SToby Isaac   Level: intermediate
7157c58f1c22SToby Isaac 
71581cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabel()`, `DMGetLabelByNum()`, `DMCreateLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7159c58f1c22SToby Isaac @*/
7160d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
7161d71ae5a4SJacob Faibussowitsch {
71625d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7163d67d17b1SMatthew G. Knepley   const char *lname;
7164c58f1c22SToby Isaac 
7165c58f1c22SToby Isaac   PetscFunctionBegin;
7166c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71674f572ea9SToby Isaac   PetscAssertPointer(name, 2);
71684f572ea9SToby Isaac   PetscAssertPointer(hasLabel, 3);
7169c58f1c22SToby Isaac   *hasLabel = PETSC_FALSE;
7170c58f1c22SToby Isaac   while (next) {
71719566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
71729566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, hasLabel));
7173c58f1c22SToby Isaac     if (*hasLabel) break;
7174c58f1c22SToby Isaac     next = next->next;
7175c58f1c22SToby Isaac   }
71763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7177c58f1c22SToby Isaac }
7178c58f1c22SToby Isaac 
7179a4e35b19SJacob Faibussowitsch // PetscClangLinter pragma ignore: -fdoc-section-header-unknown
7180cc4c1da9SBarry Smith /*@
718120f4b53cSBarry Smith   DMGetLabel - Return the label of a given name, or `NULL`, from a `DM`
7182c58f1c22SToby Isaac 
7183c58f1c22SToby Isaac   Not Collective
7184c58f1c22SToby Isaac 
7185c58f1c22SToby Isaac   Input Parameters:
7186bb7acecfSBarry Smith + dm   - The `DM` object
7187c58f1c22SToby Isaac - name - The label name
7188c58f1c22SToby Isaac 
7189c58f1c22SToby Isaac   Output Parameter:
719020f4b53cSBarry Smith . label - The `DMLabel`, or `NULL` if the label is absent
7191c58f1c22SToby Isaac 
7192bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
7193bb7acecfSBarry Smith + "depth"       - Holds the depth (co-dimension) of each mesh point
7194bb7acecfSBarry Smith . "celltype"    - Holds the topological type of each cell
7195bb7acecfSBarry Smith . "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
7196bb7acecfSBarry Smith . "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
7197bb7acecfSBarry Smith . "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
7198bb7acecfSBarry Smith - "Vertex Sets" - Mirrors the vertex sets defined by GMsh
71996d7c9049SMatthew G. Knepley 
7200c58f1c22SToby Isaac   Level: intermediate
7201c58f1c22SToby Isaac 
720260225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMHasLabel()`, `DMGetLabelByNum()`, `DMAddLabel()`, `DMCreateLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
7203c58f1c22SToby Isaac @*/
7204d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
7205d71ae5a4SJacob Faibussowitsch {
72065d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7207c58f1c22SToby Isaac   PetscBool   hasLabel;
7208d67d17b1SMatthew G. Knepley   const char *lname;
7209c58f1c22SToby Isaac 
7210c58f1c22SToby Isaac   PetscFunctionBegin;
7211c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72124f572ea9SToby Isaac   PetscAssertPointer(name, 2);
72134f572ea9SToby Isaac   PetscAssertPointer(label, 3);
7214c58f1c22SToby Isaac   *label = NULL;
7215c58f1c22SToby Isaac   while (next) {
72169566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
72179566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
7218c58f1c22SToby Isaac     if (hasLabel) {
7219c58f1c22SToby Isaac       *label = next->label;
7220c58f1c22SToby Isaac       break;
7221c58f1c22SToby Isaac     }
7222c58f1c22SToby Isaac     next = next->next;
7223c58f1c22SToby Isaac   }
72243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7225c58f1c22SToby Isaac }
7226c58f1c22SToby Isaac 
7227cc4c1da9SBarry Smith /*@
7228bb7acecfSBarry Smith   DMGetLabelByNum - Return the nth label on a `DM`
7229c58f1c22SToby Isaac 
7230c58f1c22SToby Isaac   Not Collective
7231c58f1c22SToby Isaac 
7232c58f1c22SToby Isaac   Input Parameters:
7233bb7acecfSBarry Smith + dm - The `DM` object
7234c58f1c22SToby Isaac - n  - the label number
7235c58f1c22SToby Isaac 
7236c58f1c22SToby Isaac   Output Parameter:
7237c58f1c22SToby Isaac . label - the label
7238c58f1c22SToby Isaac 
7239c58f1c22SToby Isaac   Level: intermediate
7240c58f1c22SToby Isaac 
72411cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7242c58f1c22SToby Isaac @*/
7243d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
7244d71ae5a4SJacob Faibussowitsch {
72455d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7246c58f1c22SToby Isaac   PetscInt    l    = 0;
7247c58f1c22SToby Isaac 
7248c58f1c22SToby Isaac   PetscFunctionBegin;
7249c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72504f572ea9SToby Isaac   PetscAssertPointer(label, 3);
7251c58f1c22SToby Isaac   while (next) {
7252c58f1c22SToby Isaac     if (l == n) {
7253c58f1c22SToby Isaac       *label = next->label;
72543ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
7255c58f1c22SToby Isaac     }
7256c58f1c22SToby Isaac     ++l;
7257c58f1c22SToby Isaac     next = next->next;
7258c58f1c22SToby Isaac   }
725963a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
7260c58f1c22SToby Isaac }
7261c58f1c22SToby Isaac 
7262cc4c1da9SBarry Smith /*@
7263bb7acecfSBarry Smith   DMAddLabel - Add the label to this `DM`
7264c58f1c22SToby Isaac 
7265c58f1c22SToby Isaac   Not Collective
7266c58f1c22SToby Isaac 
7267c58f1c22SToby Isaac   Input Parameters:
7268bb7acecfSBarry Smith + dm    - The `DM` object
7269bb7acecfSBarry Smith - label - The `DMLabel`
7270c58f1c22SToby Isaac 
7271c58f1c22SToby Isaac   Level: developer
7272c58f1c22SToby Isaac 
727360225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7274c58f1c22SToby Isaac @*/
7275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddLabel(DM dm, DMLabel label)
7276d71ae5a4SJacob Faibussowitsch {
72775d80c0bfSVaclav Hapla   DMLabelLink l, *p, tmpLabel;
7278c58f1c22SToby Isaac   PetscBool   hasLabel;
7279d67d17b1SMatthew G. Knepley   const char *lname;
72805d80c0bfSVaclav Hapla   PetscBool   flg;
7281c58f1c22SToby Isaac 
7282c58f1c22SToby Isaac   PetscFunctionBegin;
7283c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72849566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
72859566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, lname, &hasLabel));
72867a8be351SBarry Smith   PetscCheck(!hasLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname);
72879566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(1, &tmpLabel));
7288c58f1c22SToby Isaac   tmpLabel->label  = label;
7289c58f1c22SToby Isaac   tmpLabel->output = PETSC_TRUE;
72905d80c0bfSVaclav Hapla   for (p = &dm->labels; (l = *p); p = &l->next) { }
72915d80c0bfSVaclav Hapla   *p = tmpLabel;
72929566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
72939566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "depth", &flg));
72945d80c0bfSVaclav Hapla   if (flg) dm->depthLabel = label;
72959566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "celltype", &flg));
7296ba2698f1SMatthew G. Knepley   if (flg) dm->celltypeLabel = label;
72973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7298c58f1c22SToby Isaac }
7299c58f1c22SToby Isaac 
7300a4e35b19SJacob Faibussowitsch // PetscClangLinter pragma ignore: -fdoc-section-header-unknown
7301cc4c1da9SBarry Smith /*@
73024a7ee7d0SMatthew G. Knepley   DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present
73034a7ee7d0SMatthew G. Knepley 
73044a7ee7d0SMatthew G. Knepley   Not Collective
73054a7ee7d0SMatthew G. Knepley 
73064a7ee7d0SMatthew G. Knepley   Input Parameters:
7307bb7acecfSBarry Smith + dm    - The `DM` object
7308bb7acecfSBarry Smith - label - The `DMLabel`, having the same name, to substitute
73094a7ee7d0SMatthew G. Knepley 
7310bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
7311bb7acecfSBarry Smith + "depth"       - Holds the depth (co-dimension) of each mesh point
7312bb7acecfSBarry Smith . "celltype"    - Holds the topological type of each cell
7313bb7acecfSBarry Smith . "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
7314bb7acecfSBarry Smith . "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
7315bb7acecfSBarry Smith . "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
7316bb7acecfSBarry Smith - "Vertex Sets" - Mirrors the vertex sets defined by GMsh
73174a7ee7d0SMatthew G. Knepley 
73184a7ee7d0SMatthew G. Knepley   Level: intermediate
73194a7ee7d0SMatthew G. Knepley 
73201cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
73214a7ee7d0SMatthew G. Knepley @*/
7322d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabel(DM dm, DMLabel label)
7323d71ae5a4SJacob Faibussowitsch {
73244a7ee7d0SMatthew G. Knepley   DMLabelLink next = dm->labels;
73254a7ee7d0SMatthew G. Knepley   PetscBool   hasLabel, flg;
73264a7ee7d0SMatthew G. Knepley   const char *name, *lname;
73274a7ee7d0SMatthew G. Knepley 
73284a7ee7d0SMatthew G. Knepley   PetscFunctionBegin;
73294a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73304a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
73319566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
73324a7ee7d0SMatthew G. Knepley   while (next) {
73339566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
73349566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
73354a7ee7d0SMatthew G. Knepley     if (hasLabel) {
73369566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)label));
73379566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "depth", &flg));
73384a7ee7d0SMatthew G. Knepley       if (flg) dm->depthLabel = label;
73399566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "celltype", &flg));
73404a7ee7d0SMatthew G. Knepley       if (flg) dm->celltypeLabel = label;
73419566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&next->label));
73424a7ee7d0SMatthew G. Knepley       next->label = label;
73434a7ee7d0SMatthew G. Knepley       break;
73444a7ee7d0SMatthew G. Knepley     }
73454a7ee7d0SMatthew G. Knepley     next = next->next;
73464a7ee7d0SMatthew G. Knepley   }
73473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
73484a7ee7d0SMatthew G. Knepley }
73494a7ee7d0SMatthew G. Knepley 
7350cc4c1da9SBarry Smith /*@
7351bb7acecfSBarry Smith   DMRemoveLabel - Remove the label given by name from this `DM`
7352c58f1c22SToby Isaac 
7353c58f1c22SToby Isaac   Not Collective
7354c58f1c22SToby Isaac 
7355c58f1c22SToby Isaac   Input Parameters:
7356bb7acecfSBarry Smith + dm   - The `DM` object
7357c58f1c22SToby Isaac - name - The label name
7358c58f1c22SToby Isaac 
7359c58f1c22SToby Isaac   Output Parameter:
736020f4b53cSBarry Smith . label - The `DMLabel`, or `NULL` if the label is absent. Pass in `NULL` to call `DMLabelDestroy()` on the label, otherwise the
7361bb7acecfSBarry Smith           caller is responsible for calling `DMLabelDestroy()`.
7362c58f1c22SToby Isaac 
7363c58f1c22SToby Isaac   Level: developer
7364c58f1c22SToby Isaac 
73651cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabelBySelf()`
7366c58f1c22SToby Isaac @*/
7367d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
7368d71ae5a4SJacob Faibussowitsch {
736995d578d6SVaclav Hapla   DMLabelLink link, *pnext;
7370c58f1c22SToby Isaac   PetscBool   hasLabel;
7371d67d17b1SMatthew G. Knepley   const char *lname;
7372c58f1c22SToby Isaac 
7373c58f1c22SToby Isaac   PetscFunctionBegin;
7374c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73754f572ea9SToby Isaac   PetscAssertPointer(name, 2);
7376e5472504SVaclav Hapla   if (label) {
73774f572ea9SToby Isaac     PetscAssertPointer(label, 3);
7378c58f1c22SToby Isaac     *label = NULL;
7379e5472504SVaclav Hapla   }
73805d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
73819566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)link->label, &lname));
73829566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
7383c58f1c22SToby Isaac     if (hasLabel) {
738495d578d6SVaclav Hapla       *pnext = link->next; /* Remove from list */
73859566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &hasLabel));
738695d578d6SVaclav Hapla       if (hasLabel) dm->depthLabel = NULL;
73879566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &hasLabel));
7388ba2698f1SMatthew G. Knepley       if (hasLabel) dm->celltypeLabel = NULL;
738995d578d6SVaclav Hapla       if (label) *label = link->label;
73909566063dSJacob Faibussowitsch       else PetscCall(DMLabelDestroy(&link->label));
73919566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7392c58f1c22SToby Isaac       break;
7393c58f1c22SToby Isaac     }
7394c58f1c22SToby Isaac   }
73953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7396c58f1c22SToby Isaac }
7397c58f1c22SToby Isaac 
7398306894acSVaclav Hapla /*@
7399bb7acecfSBarry Smith   DMRemoveLabelBySelf - Remove the label from this `DM`
7400306894acSVaclav Hapla 
7401306894acSVaclav Hapla   Not Collective
7402306894acSVaclav Hapla 
7403306894acSVaclav Hapla   Input Parameters:
7404bb7acecfSBarry Smith + dm           - The `DM` object
7405bb7acecfSBarry Smith . label        - The `DMLabel` to be removed from the `DM`
740620f4b53cSBarry Smith - failNotFound - Should it fail if the label is not found in the `DM`?
7407306894acSVaclav Hapla 
7408306894acSVaclav Hapla   Level: developer
7409306894acSVaclav Hapla 
7410bb7acecfSBarry Smith   Note:
7411306894acSVaclav Hapla   Only exactly the same instance is removed if found, name match is ignored.
7412bb7acecfSBarry Smith   If the `DM` has an exclusive reference to the label, the label gets destroyed and
7413306894acSVaclav Hapla   *label nullified.
7414306894acSVaclav Hapla 
74151cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()` `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabel()`
7416306894acSVaclav Hapla @*/
7417d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound)
7418d71ae5a4SJacob Faibussowitsch {
741943e45a93SVaclav Hapla   DMLabelLink link, *pnext;
7420306894acSVaclav Hapla   PetscBool   hasLabel = PETSC_FALSE;
7421306894acSVaclav Hapla 
7422306894acSVaclav Hapla   PetscFunctionBegin;
7423306894acSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
74244f572ea9SToby Isaac   PetscAssertPointer(label, 2);
74253ba16761SJacob Faibussowitsch   if (!*label && !failNotFound) PetscFunctionReturn(PETSC_SUCCESS);
7426306894acSVaclav Hapla   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2);
7427306894acSVaclav Hapla   PetscValidLogicalCollectiveBool(dm, failNotFound, 3);
74285d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
742943e45a93SVaclav Hapla     if (*label == link->label) {
7430306894acSVaclav Hapla       hasLabel = PETSC_TRUE;
743143e45a93SVaclav Hapla       *pnext   = link->next; /* Remove from list */
7432306894acSVaclav Hapla       if (*label == dm->depthLabel) dm->depthLabel = NULL;
7433ba2698f1SMatthew G. Knepley       if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL;
743443e45a93SVaclav Hapla       if (((PetscObject)link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */
74359566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&link->label));
74369566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7437306894acSVaclav Hapla       break;
7438306894acSVaclav Hapla     }
7439306894acSVaclav Hapla   }
74407a8be351SBarry Smith   PetscCheck(hasLabel || !failNotFound, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM");
74413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7442306894acSVaclav Hapla }
7443306894acSVaclav Hapla 
7444cc4c1da9SBarry Smith /*@
7445c58f1c22SToby Isaac   DMGetLabelOutput - Get the output flag for a given label
7446c58f1c22SToby Isaac 
7447c58f1c22SToby Isaac   Not Collective
7448c58f1c22SToby Isaac 
7449c58f1c22SToby Isaac   Input Parameters:
7450bb7acecfSBarry Smith + dm   - The `DM` object
7451c58f1c22SToby Isaac - name - The label name
7452c58f1c22SToby Isaac 
7453c58f1c22SToby Isaac   Output Parameter:
7454c58f1c22SToby Isaac . output - The flag for output
7455c58f1c22SToby Isaac 
7456c58f1c22SToby Isaac   Level: developer
7457c58f1c22SToby Isaac 
74581cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMSetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7459c58f1c22SToby Isaac @*/
7460d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelOutput(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);
74684f572ea9SToby Isaac   PetscAssertPointer(output, 3);
7469c58f1c22SToby Isaac   while (next) {
7470c58f1c22SToby Isaac     PetscBool flg;
7471c58f1c22SToby Isaac 
74729566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
74739566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
74749371c9d4SSatish Balay     if (flg) {
74759371c9d4SSatish Balay       *output = next->output;
74763ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
74779371c9d4SSatish Balay     }
7478c58f1c22SToby Isaac     next = next->next;
7479c58f1c22SToby Isaac   }
748098921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7481c58f1c22SToby Isaac }
7482c58f1c22SToby Isaac 
7483cc4c1da9SBarry Smith /*@
7484bb7acecfSBarry Smith   DMSetLabelOutput - Set if a given label should be saved to a `PetscViewer` in calls to `DMView()`
7485c58f1c22SToby Isaac 
7486c58f1c22SToby Isaac   Not Collective
7487c58f1c22SToby Isaac 
7488c58f1c22SToby Isaac   Input Parameters:
7489bb7acecfSBarry Smith + dm     - The `DM` object
7490c58f1c22SToby Isaac . name   - The label name
7491bb7acecfSBarry Smith - output - `PETSC_TRUE` to save the label to the viewer
7492c58f1c22SToby Isaac 
7493c58f1c22SToby Isaac   Level: developer
7494c58f1c22SToby Isaac 
74951cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetOutputFlag()`, `DMGetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7496c58f1c22SToby Isaac @*/
7497d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
7498d71ae5a4SJacob Faibussowitsch {
74995d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7500d67d17b1SMatthew G. Knepley   const char *lname;
7501c58f1c22SToby Isaac 
7502c58f1c22SToby Isaac   PetscFunctionBegin;
7503c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
75044f572ea9SToby Isaac   PetscAssertPointer(name, 2);
7505c58f1c22SToby Isaac   while (next) {
7506c58f1c22SToby Isaac     PetscBool flg;
7507c58f1c22SToby Isaac 
75089566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
75099566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
75109371c9d4SSatish Balay     if (flg) {
75119371c9d4SSatish Balay       next->output = output;
75123ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
75139371c9d4SSatish Balay     }
7514c58f1c22SToby Isaac     next = next->next;
7515c58f1c22SToby Isaac   }
751698921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7517c58f1c22SToby Isaac }
7518c58f1c22SToby Isaac 
7519c58f1c22SToby Isaac /*@
7520bb7acecfSBarry Smith   DMCopyLabels - Copy labels from one `DM` mesh to another `DM` with a superset of the points
7521c58f1c22SToby Isaac 
752220f4b53cSBarry Smith   Collective
7523c58f1c22SToby Isaac 
7524d8d19677SJose E. Roman   Input Parameters:
7525bb7acecfSBarry Smith + dmA   - The `DM` object with initial labels
7526bb7acecfSBarry Smith . dmB   - The `DM` object to which labels are copied
7527bb7acecfSBarry Smith . mode  - Copy labels by pointers (`PETSC_OWN_POINTER`) or duplicate them (`PETSC_COPY_VALUES`)
7528bb7acecfSBarry Smith . all   - Copy all labels including "depth", "dim", and "celltype" (`PETSC_TRUE`) which are otherwise ignored (`PETSC_FALSE`)
7529bb7acecfSBarry Smith - emode - How to behave when a `DMLabel` in the source and destination `DM`s with the same name is encountered (see `DMCopyLabelsMode`)
7530c58f1c22SToby Isaac 
7531c58f1c22SToby Isaac   Level: intermediate
7532c58f1c22SToby Isaac 
7533bb7acecfSBarry Smith   Note:
75342cbb9b06SVaclav Hapla   This is typically used when interpolating or otherwise adding to a mesh, or testing.
7535c58f1c22SToby Isaac 
75361cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`
7537c58f1c22SToby Isaac @*/
7538d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all, DMCopyLabelsMode emode)
7539d71ae5a4SJacob Faibussowitsch {
75402cbb9b06SVaclav Hapla   DMLabel     label, labelNew, labelOld;
7541c58f1c22SToby Isaac   const char *name;
7542c58f1c22SToby Isaac   PetscBool   flg;
75435d80c0bfSVaclav Hapla   DMLabelLink link;
7544c58f1c22SToby Isaac 
75455d80c0bfSVaclav Hapla   PetscFunctionBegin;
75465d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
75475d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
75485d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveEnum(dmA, mode, 3);
75495d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveBool(dmA, all, 4);
75507a8be351SBarry Smith   PetscCheck(mode != PETSC_USE_POINTER, PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects");
75513ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
75525d80c0bfSVaclav Hapla   for (link = dmA->labels; link; link = link->next) {
75535d80c0bfSVaclav Hapla     label = link->label;
75549566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
75555d80c0bfSVaclav Hapla     if (!all) {
75569566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &flg));
7557c58f1c22SToby Isaac       if (flg) continue;
75589566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "dim", &flg));
75597d5acc75SStefano Zampini       if (flg) continue;
75609566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &flg));
7561ba2698f1SMatthew G. Knepley       if (flg) continue;
75625d80c0bfSVaclav Hapla     }
75639566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dmB, name, &labelOld));
75642cbb9b06SVaclav Hapla     if (labelOld) {
75652cbb9b06SVaclav Hapla       switch (emode) {
7566d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_KEEP:
7567d71ae5a4SJacob Faibussowitsch         continue;
7568d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_REPLACE:
7569d71ae5a4SJacob Faibussowitsch         PetscCall(DMRemoveLabelBySelf(dmB, &labelOld, PETSC_TRUE));
7570d71ae5a4SJacob Faibussowitsch         break;
7571d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_FAIL:
7572d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in destination DM", name);
7573d71ae5a4SJacob Faibussowitsch       default:
7574d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Unhandled DMCopyLabelsMode %d", (int)emode);
75752cbb9b06SVaclav Hapla       }
75762cbb9b06SVaclav Hapla     }
75775d80c0bfSVaclav Hapla     if (mode == PETSC_COPY_VALUES) {
75789566063dSJacob Faibussowitsch       PetscCall(DMLabelDuplicate(label, &labelNew));
75795d80c0bfSVaclav Hapla     } else {
75805d80c0bfSVaclav Hapla       labelNew = label;
75815d80c0bfSVaclav Hapla     }
75829566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dmB, labelNew));
75839566063dSJacob Faibussowitsch     if (mode == PETSC_COPY_VALUES) PetscCall(DMLabelDestroy(&labelNew));
7584c58f1c22SToby Isaac   }
75853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7586c58f1c22SToby Isaac }
7587461a15a0SLisandro Dalcin 
7588609dae6eSVaclav Hapla /*@C
7589b4028c23SStefano Zampini   DMCompareLabels - Compare labels between two `DM` objects
7590609dae6eSVaclav Hapla 
759120f4b53cSBarry Smith   Collective; No Fortran Support
7592609dae6eSVaclav Hapla 
7593609dae6eSVaclav Hapla   Input Parameters:
7594bb7acecfSBarry Smith + dm0 - First `DM` object
7595bb7acecfSBarry Smith - dm1 - Second `DM` object
7596609dae6eSVaclav Hapla 
7597a4e35b19SJacob Faibussowitsch   Output Parameters:
75985efe38ccSVaclav Hapla + equal   - (Optional) Flag whether labels of dm0 and dm1 are the same
759920f4b53cSBarry Smith - message - (Optional) Message describing the difference, or `NULL` if there is no difference
7600609dae6eSVaclav Hapla 
7601609dae6eSVaclav Hapla   Level: intermediate
7602609dae6eSVaclav Hapla 
7603609dae6eSVaclav Hapla   Notes:
7604bb7acecfSBarry Smith   The output flag equal will be the same on all processes.
7605bb7acecfSBarry Smith 
760620f4b53cSBarry Smith   If equal is passed as `NULL` and difference is found, an error is thrown on all processes.
7607bb7acecfSBarry Smith 
760820f4b53cSBarry Smith   Make sure to pass equal is `NULL` on all processes or none of them.
7609609dae6eSVaclav Hapla 
76105efe38ccSVaclav Hapla   The output message is set independently on each rank.
7611bb7acecfSBarry Smith 
7612bb7acecfSBarry Smith   message must be freed with `PetscFree()`
7613bb7acecfSBarry Smith 
761420f4b53cSBarry Smith   If message is passed as `NULL` and a difference is found, the difference description is printed to stderr in synchronized manner.
7615bb7acecfSBarry Smith 
761620f4b53cSBarry Smith   Make sure to pass message as `NULL` on all processes or no processes.
7617609dae6eSVaclav Hapla 
7618609dae6eSVaclav Hapla   Labels are matched by name. If the number of labels and their names are equal,
7619bb7acecfSBarry Smith   `DMLabelCompare()` is used to compare each pair of labels with the same name.
7620609dae6eSVaclav Hapla 
7621cc4c1da9SBarry Smith   Developer Note:
7622cc4c1da9SBarry Smith   Can automatically generate the Fortran stub because `message` must be freed with `PetscFree()`
7623cc4c1da9SBarry Smith 
76241cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`, `DMLabelCompare()`
7625609dae6eSVaclav Hapla @*/
7626d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompareLabels(DM dm0, DM dm1, PetscBool *equal, char **message)
7627d71ae5a4SJacob Faibussowitsch {
76285efe38ccSVaclav Hapla   PetscInt    n, i;
7629609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
76305efe38ccSVaclav Hapla   PetscBool   eq;
7631609dae6eSVaclav Hapla   MPI_Comm    comm;
76325efe38ccSVaclav Hapla   PetscMPIInt rank;
7633609dae6eSVaclav Hapla 
7634609dae6eSVaclav Hapla   PetscFunctionBegin;
7635609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm0, DM_CLASSID, 1);
7636609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm1, DM_CLASSID, 2);
7637609dae6eSVaclav Hapla   PetscCheckSameComm(dm0, 1, dm1, 2);
76384f572ea9SToby Isaac   if (equal) PetscAssertPointer(equal, 3);
76394f572ea9SToby Isaac   if (message) PetscAssertPointer(message, 4);
76409566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm0, &comm));
76419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
76425efe38ccSVaclav Hapla   {
76435efe38ccSVaclav Hapla     PetscInt n1;
76445efe38ccSVaclav Hapla 
76459566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm0, &n));
76469566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm1, &n1));
76475efe38ccSVaclav Hapla     eq = (PetscBool)(n == n1);
764848a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Number of labels in dm0 = %" PetscInt_FMT " != %" PetscInt_FMT " = Number of labels in dm1", n, n1));
7649462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
76505efe38ccSVaclav Hapla     if (!eq) goto finish;
76515efe38ccSVaclav Hapla   }
76525efe38ccSVaclav Hapla   for (i = 0; i < n; i++) {
7653609dae6eSVaclav Hapla     DMLabel     l0, l1;
7654609dae6eSVaclav Hapla     const char *name;
7655609dae6eSVaclav Hapla     char       *msgInner;
7656609dae6eSVaclav Hapla 
7657609dae6eSVaclav Hapla     /* Ignore label order */
76589566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm0, i, &l0));
76599566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)l0, &name));
76609566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm1, name, &l1));
7661609dae6eSVaclav Hapla     if (!l1) {
766263a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Label \"%s\" (#%" PetscInt_FMT " in dm0) not found in dm1", name, i));
76635efe38ccSVaclav Hapla       eq = PETSC_FALSE;
76645efe38ccSVaclav Hapla       break;
7665609dae6eSVaclav Hapla     }
76669566063dSJacob Faibussowitsch     PetscCall(DMLabelCompare(comm, l0, l1, &eq, &msgInner));
76679566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(msg, msgInner, sizeof(msg)));
76689566063dSJacob Faibussowitsch     PetscCall(PetscFree(msgInner));
76695efe38ccSVaclav Hapla     if (!eq) break;
7670609dae6eSVaclav Hapla   }
7671462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
7672609dae6eSVaclav Hapla finish:
76735efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
7674609dae6eSVaclav Hapla   if (message) {
7675609dae6eSVaclav Hapla     *message = NULL;
767648a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
76775efe38ccSVaclav Hapla   } else {
767848a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
76799566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
76805efe38ccSVaclav Hapla   }
76815efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
76825efe38ccSVaclav Hapla   if (equal) *equal = eq;
76837a8be351SBarry Smith   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels are not the same in dm0 and dm1");
76843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7685609dae6eSVaclav Hapla }
7686609dae6eSVaclav Hapla 
7687d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value)
7688d71ae5a4SJacob Faibussowitsch {
7689461a15a0SLisandro Dalcin   PetscFunctionBegin;
76904f572ea9SToby Isaac   PetscAssertPointer(label, 2);
7691461a15a0SLisandro Dalcin   if (!*label) {
76929566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
76939566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, label));
7694461a15a0SLisandro Dalcin   }
76959566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(*label, point, value));
76963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7697461a15a0SLisandro Dalcin }
7698461a15a0SLisandro Dalcin 
76990fdc7489SMatthew Knepley /*
77000fdc7489SMatthew Knepley   Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would
77010fdc7489SMatthew Knepley   like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every
77020fdc7489SMatthew Knepley   (label, id) pair in the DM.
77030fdc7489SMatthew Knepley 
77040fdc7489SMatthew Knepley   However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to
77050fdc7489SMatthew Knepley   each label.
77060fdc7489SMatthew Knepley */
7707d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal)
7708d71ae5a4SJacob Faibussowitsch {
77090fdc7489SMatthew Knepley   DMUniversalLabel ul;
77100fdc7489SMatthew Knepley   PetscBool       *active;
77110fdc7489SMatthew Knepley   PetscInt         pStart, pEnd, p, Nl, l, m;
77120fdc7489SMatthew Knepley 
77130fdc7489SMatthew Knepley   PetscFunctionBegin;
77149566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, &ul));
77159566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label));
77169566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
77179566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Nl, &active));
77180fdc7489SMatthew Knepley   ul->Nl = 0;
77190fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
77200fdc7489SMatthew Knepley     PetscBool   isdepth, iscelltype;
77210fdc7489SMatthew Knepley     const char *name;
77220fdc7489SMatthew Knepley 
77239566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
77249566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "depth", 6, &isdepth));
77259566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "celltype", 9, &iscelltype));
77260fdc7489SMatthew Knepley     active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE;
77270fdc7489SMatthew Knepley     if (active[l]) ++ul->Nl;
77280fdc7489SMatthew Knepley   }
77299566063dSJacob 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));
77300fdc7489SMatthew Knepley   ul->Nv = 0;
77310fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
77320fdc7489SMatthew Knepley     DMLabel     label;
77330fdc7489SMatthew Knepley     PetscInt    nv;
77340fdc7489SMatthew Knepley     const char *name;
77350fdc7489SMatthew Knepley 
77360fdc7489SMatthew Knepley     if (!active[l]) continue;
77379566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
77389566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
77399566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
77409566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &ul->names[m]));
77410fdc7489SMatthew Knepley     ul->indices[m] = l;
77420fdc7489SMatthew Knepley     ul->Nv += nv;
77430fdc7489SMatthew Knepley     ul->offsets[m + 1] = nv;
77440fdc7489SMatthew Knepley     ul->bits[m + 1]    = PetscCeilReal(PetscLog2Real(nv + 1));
77450fdc7489SMatthew Knepley     ++m;
77460fdc7489SMatthew Knepley   }
77470fdc7489SMatthew Knepley   for (l = 1; l <= ul->Nl; ++l) {
77480fdc7489SMatthew Knepley     ul->offsets[l] = ul->offsets[l - 1] + ul->offsets[l];
77490fdc7489SMatthew Knepley     ul->bits[l]    = ul->bits[l - 1] + ul->bits[l];
77500fdc7489SMatthew Knepley   }
77510fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
77520fdc7489SMatthew Knepley     PetscInt b;
77530fdc7489SMatthew Knepley 
77540fdc7489SMatthew Knepley     ul->masks[l] = 0;
77550fdc7489SMatthew Knepley     for (b = ul->bits[l]; b < ul->bits[l + 1]; ++b) ul->masks[l] |= 1 << b;
77560fdc7489SMatthew Knepley   }
77579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ul->Nv, &ul->values));
77580fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
77590fdc7489SMatthew Knepley     DMLabel         label;
77600fdc7489SMatthew Knepley     IS              valueIS;
77610fdc7489SMatthew Knepley     const PetscInt *varr;
77620fdc7489SMatthew Knepley     PetscInt        nv, v;
77630fdc7489SMatthew Knepley 
77640fdc7489SMatthew Knepley     if (!active[l]) continue;
77659566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
77669566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
77679566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, &valueIS));
77689566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(valueIS, &varr));
7769ad540459SPierre Jolivet     for (v = 0; v < nv; ++v) ul->values[ul->offsets[m] + v] = varr[v];
77709566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(valueIS, &varr));
77719566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&valueIS));
77729566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(nv, &ul->values[ul->offsets[m]]));
77730fdc7489SMatthew Knepley     ++m;
77740fdc7489SMatthew Knepley   }
77759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
77760fdc7489SMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
77770fdc7489SMatthew Knepley     PetscInt  uval   = 0;
77780fdc7489SMatthew Knepley     PetscBool marked = PETSC_FALSE;
77790fdc7489SMatthew Knepley 
77800fdc7489SMatthew Knepley     for (l = 0, m = 0; l < Nl; ++l) {
77810fdc7489SMatthew Knepley       DMLabel  label;
77820649b39aSStefano Zampini       PetscInt val, defval, loc, nv;
77830fdc7489SMatthew Knepley 
77840fdc7489SMatthew Knepley       if (!active[l]) continue;
77859566063dSJacob Faibussowitsch       PetscCall(DMGetLabelByNum(dm, l, &label));
77869566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, p, &val));
77879566063dSJacob Faibussowitsch       PetscCall(DMLabelGetDefaultValue(label, &defval));
77889371c9d4SSatish Balay       if (val == defval) {
77899371c9d4SSatish Balay         ++m;
77909371c9d4SSatish Balay         continue;
77919371c9d4SSatish Balay       }
77920649b39aSStefano Zampini       nv     = ul->offsets[m + 1] - ul->offsets[m];
77930fdc7489SMatthew Knepley       marked = PETSC_TRUE;
77949566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc));
779563a3b9bcSJacob Faibussowitsch       PetscCheck(loc >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %" PetscInt_FMT " not found in compression array", val);
77960fdc7489SMatthew Knepley       uval += (loc + 1) << ul->bits[m];
77970fdc7489SMatthew Knepley       ++m;
77980fdc7489SMatthew Knepley     }
77999566063dSJacob Faibussowitsch     if (marked) PetscCall(DMLabelSetValue(ul->label, p, uval));
78000fdc7489SMatthew Knepley   }
78019566063dSJacob Faibussowitsch   PetscCall(PetscFree(active));
78020fdc7489SMatthew Knepley   *universal = ul;
78033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78040fdc7489SMatthew Knepley }
78050fdc7489SMatthew Knepley 
7806d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal)
7807d71ae5a4SJacob Faibussowitsch {
78080fdc7489SMatthew Knepley   PetscInt l;
78090fdc7489SMatthew Knepley 
78100fdc7489SMatthew Knepley   PetscFunctionBegin;
78119566063dSJacob Faibussowitsch   for (l = 0; l < (*universal)->Nl; ++l) PetscCall(PetscFree((*universal)->names[l]));
78129566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&(*universal)->label));
78139566063dSJacob Faibussowitsch   PetscCall(PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks));
78149566063dSJacob Faibussowitsch   PetscCall(PetscFree((*universal)->values));
78159566063dSJacob Faibussowitsch   PetscCall(PetscFree(*universal));
78160fdc7489SMatthew Knepley   *universal = NULL;
78173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78180fdc7489SMatthew Knepley }
78190fdc7489SMatthew Knepley 
7820d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel)
7821d71ae5a4SJacob Faibussowitsch {
78220fdc7489SMatthew Knepley   PetscFunctionBegin;
78234f572ea9SToby Isaac   PetscAssertPointer(ulabel, 2);
78240fdc7489SMatthew Knepley   *ulabel = ul->label;
78253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78260fdc7489SMatthew Knepley }
78270fdc7489SMatthew Knepley 
7828d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm)
7829d71ae5a4SJacob Faibussowitsch {
78300fdc7489SMatthew Knepley   PetscInt Nl = ul->Nl, l;
78310fdc7489SMatthew Knepley 
78320fdc7489SMatthew Knepley   PetscFunctionBegin;
7833064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 3);
78340fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
78359566063dSJacob Faibussowitsch     if (preserveOrder) PetscCall(DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]));
78369566063dSJacob Faibussowitsch     else PetscCall(DMCreateLabel(dm, ul->names[l]));
78370fdc7489SMatthew Knepley   }
78380fdc7489SMatthew Knepley   if (preserveOrder) {
78390fdc7489SMatthew Knepley     for (l = 0; l < ul->Nl; ++l) {
78400fdc7489SMatthew Knepley       const char *name;
78410fdc7489SMatthew Knepley       PetscBool   match;
78420fdc7489SMatthew Knepley 
78439566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, ul->indices[l], &name));
78449566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, ul->names[l], &match));
784563a3b9bcSJacob 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]);
78460fdc7489SMatthew Knepley     }
78470fdc7489SMatthew Knepley   }
78483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78490fdc7489SMatthew Knepley }
78500fdc7489SMatthew Knepley 
7851d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value)
7852d71ae5a4SJacob Faibussowitsch {
78530fdc7489SMatthew Knepley   PetscInt l;
78540fdc7489SMatthew Knepley 
78550fdc7489SMatthew Knepley   PetscFunctionBegin;
78560fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
78570fdc7489SMatthew Knepley     DMLabel  label;
78580fdc7489SMatthew Knepley     PetscInt lval = (value & ul->masks[l]) >> ul->bits[l];
78590fdc7489SMatthew Knepley 
78600fdc7489SMatthew Knepley     if (lval) {
78619566063dSJacob Faibussowitsch       if (useIndex) PetscCall(DMGetLabelByNum(dm, ul->indices[l], &label));
78629566063dSJacob Faibussowitsch       else PetscCall(DMGetLabel(dm, ul->names[l], &label));
78639566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(label, p, ul->values[ul->offsets[l] + lval - 1]));
78640fdc7489SMatthew Knepley     }
78650fdc7489SMatthew Knepley   }
78663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78670fdc7489SMatthew Knepley }
7868a8fb8f29SToby Isaac 
7869a8fb8f29SToby Isaac /*@
7870bb7acecfSBarry Smith   DMGetCoarseDM - Get the coarse `DM`from which this `DM` was obtained by refinement
7871bb7acecfSBarry Smith 
787220f4b53cSBarry Smith   Not Collective
7873a8fb8f29SToby Isaac 
7874a8fb8f29SToby Isaac   Input Parameter:
7875bb7acecfSBarry Smith . dm - The `DM` object
7876a8fb8f29SToby Isaac 
7877a8fb8f29SToby Isaac   Output Parameter:
7878bb7acecfSBarry Smith . cdm - The coarse `DM`
7879a8fb8f29SToby Isaac 
7880a8fb8f29SToby Isaac   Level: intermediate
7881a8fb8f29SToby Isaac 
78821cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetCoarseDM()`, `DMCoarsen()`
7883a8fb8f29SToby Isaac @*/
7884d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
7885d71ae5a4SJacob Faibussowitsch {
7886a8fb8f29SToby Isaac   PetscFunctionBegin;
7887a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78884f572ea9SToby Isaac   PetscAssertPointer(cdm, 2);
7889a8fb8f29SToby Isaac   *cdm = dm->coarseMesh;
78903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7891a8fb8f29SToby Isaac }
7892a8fb8f29SToby Isaac 
7893a8fb8f29SToby Isaac /*@
7894bb7acecfSBarry Smith   DMSetCoarseDM - Set the coarse `DM` from which this `DM` was obtained by refinement
7895a8fb8f29SToby Isaac 
7896a8fb8f29SToby Isaac   Input Parameters:
7897bb7acecfSBarry Smith + dm  - The `DM` object
7898bb7acecfSBarry Smith - cdm - The coarse `DM`
7899a8fb8f29SToby Isaac 
7900a8fb8f29SToby Isaac   Level: intermediate
7901a8fb8f29SToby Isaac 
7902bb7acecfSBarry Smith   Note:
7903bb7acecfSBarry Smith   Normally this is set automatically by `DMRefine()`
7904bb7acecfSBarry Smith 
79051cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetCoarseDM()`, `DMCoarsen()`, `DMSetRefine()`, `DMSetFineDM()`
7906a8fb8f29SToby Isaac @*/
7907d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
7908d71ae5a4SJacob Faibussowitsch {
7909a8fb8f29SToby Isaac   PetscFunctionBegin;
7910a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7911a8fb8f29SToby Isaac   if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
791289d734beSBarry Smith   if (dm == cdm) cdm = NULL;
79139566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)cdm));
79149566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->coarseMesh));
7915a8fb8f29SToby Isaac   dm->coarseMesh = cdm;
79163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7917a8fb8f29SToby Isaac }
7918a8fb8f29SToby Isaac 
791988bdff64SToby Isaac /*@
7920bb7acecfSBarry Smith   DMGetFineDM - Get the fine mesh from which this `DM` was obtained by coarsening
792188bdff64SToby Isaac 
792288bdff64SToby Isaac   Input Parameter:
7923bb7acecfSBarry Smith . dm - The `DM` object
792488bdff64SToby Isaac 
792588bdff64SToby Isaac   Output Parameter:
7926bb7acecfSBarry Smith . fdm - The fine `DM`
792788bdff64SToby Isaac 
792888bdff64SToby Isaac   Level: intermediate
792988bdff64SToby Isaac 
79301cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetFineDM()`, `DMCoarsen()`, `DMRefine()`
793188bdff64SToby Isaac @*/
7932d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
7933d71ae5a4SJacob Faibussowitsch {
793488bdff64SToby Isaac   PetscFunctionBegin;
793588bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79364f572ea9SToby Isaac   PetscAssertPointer(fdm, 2);
793788bdff64SToby Isaac   *fdm = dm->fineMesh;
79383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
793988bdff64SToby Isaac }
794088bdff64SToby Isaac 
794188bdff64SToby Isaac /*@
7942bb7acecfSBarry Smith   DMSetFineDM - Set the fine mesh from which this was obtained by coarsening
794388bdff64SToby Isaac 
794488bdff64SToby Isaac   Input Parameters:
7945bb7acecfSBarry Smith + dm  - The `DM` object
7946bb7acecfSBarry Smith - fdm - The fine `DM`
794788bdff64SToby Isaac 
7948bb7acecfSBarry Smith   Level: developer
794988bdff64SToby Isaac 
7950bb7acecfSBarry Smith   Note:
7951bb7acecfSBarry Smith   Normally this is set automatically by `DMCoarsen()`
7952bb7acecfSBarry Smith 
79531cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetFineDM()`, `DMCoarsen()`, `DMRefine()`
795488bdff64SToby Isaac @*/
7955d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFineDM(DM dm, DM fdm)
7956d71ae5a4SJacob Faibussowitsch {
795788bdff64SToby Isaac   PetscFunctionBegin;
795888bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
795988bdff64SToby Isaac   if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2);
796089d734beSBarry Smith   if (dm == fdm) fdm = NULL;
79619566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fdm));
79629566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->fineMesh));
796388bdff64SToby Isaac   dm->fineMesh = fdm;
79643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
796588bdff64SToby Isaac }
796688bdff64SToby Isaac 
7967a6ba4734SToby Isaac /*@C
7968bb7acecfSBarry Smith   DMAddBoundary - Add a boundary condition to a model represented by a `DM`
7969a6ba4734SToby Isaac 
797020f4b53cSBarry Smith   Collective
7971783e2ec8SMatthew G. Knepley 
7972a6ba4734SToby Isaac   Input Parameters:
7973bb7acecfSBarry Smith + dm       - The `DM`, with a `PetscDS` that matches the problem being constrained
7974bb7acecfSBarry Smith . type     - The type of condition, e.g. `DM_BC_ESSENTIAL_ANALYTIC`, `DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
7975a6ba4734SToby Isaac . name     - The BC name
797645480ffeSMatthew G. Knepley . label    - The label defining constrained points
7977bb7acecfSBarry Smith . Nv       - The number of `DMLabel` values for constrained points
797845480ffeSMatthew G. Knepley . values   - An array of values for constrained points
7979a6ba4734SToby Isaac . field    - The field to constrain
798045480ffeSMatthew G. Knepley . Nc       - The number of constrained field components (0 will constrain all fields)
7981a6ba4734SToby Isaac . comps    - An array of constrained component numbers
7982a6ba4734SToby Isaac . bcFunc   - A pointwise function giving boundary values
798356cf3b9cSMatthew G. Knepley . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL
7984a6ba4734SToby Isaac - ctx      - An optional user context for bcFunc
7985a6ba4734SToby Isaac 
798645480ffeSMatthew G. Knepley   Output Parameter:
798745480ffeSMatthew G. Knepley . bd - (Optional) Boundary number
798845480ffeSMatthew G. Knepley 
7989a6ba4734SToby Isaac   Options Database Keys:
7990a6ba4734SToby Isaac + -bc_<boundary name> <num>      - Overrides the boundary ids
7991a6ba4734SToby Isaac - -bc_<boundary name>_comp <num> - Overrides the boundary components
7992a6ba4734SToby Isaac 
799320f4b53cSBarry Smith   Level: intermediate
799420f4b53cSBarry Smith 
7995bb7acecfSBarry Smith   Notes:
7996aeebefc2SPierre 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\:
799773ff1848SBarry Smith .vb
799873ff1848SBarry Smith  void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
799973ff1848SBarry Smith .ve
800056cf3b9cSMatthew G. Knepley 
8001a4e35b19SJacob Faibussowitsch   If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is\:
800256cf3b9cSMatthew G. Knepley 
800320f4b53cSBarry Smith .vb
800420f4b53cSBarry Smith   void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
800520f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
800620f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
800720f4b53cSBarry Smith               PetscReal time, const PetscReal x[], PetscScalar bcval[])
800820f4b53cSBarry Smith .ve
800956cf3b9cSMatthew G. Knepley + dim - the spatial dimension
801056cf3b9cSMatthew G. Knepley . Nf - the number of fields
801156cf3b9cSMatthew G. Knepley . uOff - the offset into u[] and u_t[] for each field
801256cf3b9cSMatthew G. Knepley . uOff_x - the offset into u_x[] for each field
801356cf3b9cSMatthew G. Knepley . u - each field evaluated at the current point
801456cf3b9cSMatthew G. Knepley . u_t - the time derivative of each field evaluated at the current point
801556cf3b9cSMatthew G. Knepley . u_x - the gradient of each field evaluated at the current point
801656cf3b9cSMatthew G. Knepley . aOff - the offset into a[] and a_t[] for each auxiliary field
801756cf3b9cSMatthew G. Knepley . aOff_x - the offset into a_x[] for each auxiliary field
801856cf3b9cSMatthew G. Knepley . a - each auxiliary field evaluated at the current point
801956cf3b9cSMatthew G. Knepley . a_t - the time derivative of each auxiliary field evaluated at the current point
802056cf3b9cSMatthew G. Knepley . a_x - the gradient of auxiliary each field evaluated at the current point
802156cf3b9cSMatthew G. Knepley . t - current time
802256cf3b9cSMatthew G. Knepley . x - coordinates of the current point
802356cf3b9cSMatthew G. Knepley . numConstants - number of constant parameters
802456cf3b9cSMatthew G. Knepley . constants - constant parameters
802556cf3b9cSMatthew G. Knepley - bcval - output values at the current point
802656cf3b9cSMatthew G. Knepley 
80271cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DSGetBoundary()`, `PetscDSAddBoundary()`
8028a6ba4734SToby Isaac @*/
8029d71ae5a4SJacob 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)
8030d71ae5a4SJacob Faibussowitsch {
8031e5e52638SMatthew G. Knepley   PetscDS ds;
8032a6ba4734SToby Isaac 
8033a6ba4734SToby Isaac   PetscFunctionBegin;
8034a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8035783e2ec8SMatthew G. Knepley   PetscValidLogicalCollectiveEnum(dm, type, 2);
803645480ffeSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
803745480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nv, 5);
803845480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, field, 7);
803945480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 8);
804001a5d20dSJed Brown   PetscCheck(!dm->localSection, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot add boundary to DM after creating local section");
80419566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
8042799db056SMatthew G. Knepley   /* Complete label */
8043799db056SMatthew G. Knepley   if (label) {
8044799db056SMatthew G. Knepley     PetscObject  obj;
8045799db056SMatthew G. Knepley     PetscClassId id;
8046799db056SMatthew G. Knepley 
8047799db056SMatthew G. Knepley     PetscCall(DMGetField(dm, field, NULL, &obj));
8048799db056SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
8049799db056SMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
8050799db056SMatthew G. Knepley       DM plex;
8051799db056SMatthew G. Knepley 
8052799db056SMatthew G. Knepley       PetscCall(DMConvert(dm, DMPLEX, &plex));
8053799db056SMatthew G. Knepley       if (plex) PetscCall(DMPlexLabelComplete(plex, label));
8054799db056SMatthew G. Knepley       PetscCall(DMDestroy(&plex));
8055799db056SMatthew G. Knepley     }
8056799db056SMatthew G. Knepley   }
80579566063dSJacob Faibussowitsch   PetscCall(PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd));
80583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8059a6ba4734SToby Isaac }
8060a6ba4734SToby Isaac 
806145480ffeSMatthew G. Knepley /* TODO Remove this since now the structures are the same */
8062d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPopulateBoundary(DM dm)
8063d71ae5a4SJacob Faibussowitsch {
8064e5e52638SMatthew G. Knepley   PetscDS     ds;
8065dff059c6SToby Isaac   DMBoundary *lastnext;
8066e6f8dbb6SToby Isaac   DSBoundary  dsbound;
8067e6f8dbb6SToby Isaac 
8068e6f8dbb6SToby Isaac   PetscFunctionBegin;
80699566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
8070e5e52638SMatthew G. Knepley   dsbound = ds->boundary;
807147a1f5adSToby Isaac   if (dm->boundary) {
807247a1f5adSToby Isaac     DMBoundary next = dm->boundary;
807347a1f5adSToby Isaac 
807447a1f5adSToby Isaac     /* quick check to see if the PetscDS has changed */
80753ba16761SJacob Faibussowitsch     if (next->dsboundary == dsbound) PetscFunctionReturn(PETSC_SUCCESS);
807647a1f5adSToby Isaac     /* the PetscDS has changed: tear down and rebuild */
807747a1f5adSToby Isaac     while (next) {
807847a1f5adSToby Isaac       DMBoundary b = next;
807947a1f5adSToby Isaac 
808047a1f5adSToby Isaac       next = b->next;
80819566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
8082a6ba4734SToby Isaac     }
808347a1f5adSToby Isaac     dm->boundary = NULL;
8084a6ba4734SToby Isaac   }
808547a1f5adSToby Isaac 
8086f4f49eeaSPierre Jolivet   lastnext = &dm->boundary;
8087e6f8dbb6SToby Isaac   while (dsbound) {
8088e6f8dbb6SToby Isaac     DMBoundary dmbound;
8089e6f8dbb6SToby Isaac 
80909566063dSJacob Faibussowitsch     PetscCall(PetscNew(&dmbound));
8091e6f8dbb6SToby Isaac     dmbound->dsboundary = dsbound;
809245480ffeSMatthew G. Knepley     dmbound->label      = dsbound->label;
809347a1f5adSToby Isaac     /* push on the back instead of the front so that it is in the same order as in the PetscDS */
8094dff059c6SToby Isaac     *lastnext = dmbound;
8095f4f49eeaSPierre Jolivet     lastnext  = &dmbound->next;
8096dff059c6SToby Isaac     dsbound   = dsbound->next;
8097a6ba4734SToby Isaac   }
80983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8099a6ba4734SToby Isaac }
8100a6ba4734SToby Isaac 
8101bb7acecfSBarry Smith /* TODO: missing manual page */
8102d71ae5a4SJacob Faibussowitsch PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
8103d71ae5a4SJacob Faibussowitsch {
8104b95f2879SToby Isaac   DMBoundary b;
8105a6ba4734SToby Isaac 
8106a6ba4734SToby Isaac   PetscFunctionBegin;
8107a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81084f572ea9SToby Isaac   PetscAssertPointer(isBd, 3);
8109a6ba4734SToby Isaac   *isBd = PETSC_FALSE;
81109566063dSJacob Faibussowitsch   PetscCall(DMPopulateBoundary(dm));
8111b95f2879SToby Isaac   b = dm->boundary;
811257508eceSPierre Jolivet   while (b && !*isBd) {
8113e6f8dbb6SToby Isaac     DMLabel    label = b->label;
8114e6f8dbb6SToby Isaac     DSBoundary dsb   = b->dsboundary;
8115a6ba4734SToby Isaac     PetscInt   i;
8116a6ba4734SToby Isaac 
811745480ffeSMatthew G. Knepley     if (label) {
811857508eceSPierre Jolivet       for (i = 0; i < dsb->Nv && !*isBd; ++i) PetscCall(DMLabelStratumHasPoint(label, dsb->values[i], point, isBd));
8119a6ba4734SToby Isaac     }
8120a6ba4734SToby Isaac     b = b->next;
8121a6ba4734SToby Isaac   }
81223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8123a6ba4734SToby Isaac }
81244d6f44ffSToby Isaac 
81254d6f44ffSToby Isaac /*@C
8126bb7acecfSBarry Smith   DMProjectFunction - This projects the given function into the function space provided by a `DM`, putting the coefficients in a global vector.
8127a6e0b375SMatthew G. Knepley 
812820f4b53cSBarry Smith   Collective
81294d6f44ffSToby Isaac 
81304d6f44ffSToby Isaac   Input Parameters:
8131bb7acecfSBarry Smith + dm    - The `DM`
81320709b2feSToby Isaac . time  - The time
81334d6f44ffSToby Isaac . funcs - The coordinate functions to evaluate, one per field
81344d6f44ffSToby Isaac . ctxs  - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
81354d6f44ffSToby Isaac - mode  - The insertion mode for values
81364d6f44ffSToby Isaac 
81374d6f44ffSToby Isaac   Output Parameter:
81384d6f44ffSToby Isaac . X - vector
81394d6f44ffSToby Isaac 
814020f4b53cSBarry Smith   Calling sequence of `funcs`:
81414d6f44ffSToby Isaac + dim  - The spatial dimension
81428ec8862eSJed Brown . time - The time at which to sample
81434d6f44ffSToby Isaac . x    - The coordinates
814477b739a6SMatthew Knepley . Nc   - The number of components
81454d6f44ffSToby Isaac . u    - The output field values
81464d6f44ffSToby Isaac - ctx  - optional user-defined function context
81474d6f44ffSToby Isaac 
81484d6f44ffSToby Isaac   Level: developer
81494d6f44ffSToby Isaac 
8150bb7acecfSBarry Smith   Developer Notes:
8151bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8152bb7acecfSBarry Smith 
8153bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8154bb7acecfSBarry Smith 
81551cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
81564d6f44ffSToby Isaac @*/
8157a4e35b19SJacob 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)
8158d71ae5a4SJacob Faibussowitsch {
81594d6f44ffSToby Isaac   Vec localX;
81604d6f44ffSToby Isaac 
81614d6f44ffSToby Isaac   PetscFunctionBegin;
81624d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8163708be2fdSJed Brown   PetscCall(PetscLogEventBegin(DM_ProjectFunction, dm, X, 0, 0));
81649566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
8165f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
81669566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX));
81679566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
81689566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
81699566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
8170708be2fdSJed Brown   PetscCall(PetscLogEventEnd(DM_ProjectFunction, dm, X, 0, 0));
81713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81724d6f44ffSToby Isaac }
81734d6f44ffSToby Isaac 
8174a6e0b375SMatthew G. Knepley /*@C
8175bb7acecfSBarry Smith   DMProjectFunctionLocal - This projects the given function into the function space provided by a `DM`, putting the coefficients in a local vector.
8176a6e0b375SMatthew G. Knepley 
817720f4b53cSBarry Smith   Not Collective
8178a6e0b375SMatthew G. Knepley 
8179a6e0b375SMatthew G. Knepley   Input Parameters:
8180bb7acecfSBarry Smith + dm    - The `DM`
8181a6e0b375SMatthew G. Knepley . time  - The time
8182a6e0b375SMatthew G. Knepley . funcs - The coordinate functions to evaluate, one per field
8183a6e0b375SMatthew G. Knepley . ctxs  - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
8184a6e0b375SMatthew G. Knepley - mode  - The insertion mode for values
8185a6e0b375SMatthew G. Knepley 
8186a6e0b375SMatthew G. Knepley   Output Parameter:
8187a6e0b375SMatthew G. Knepley . localX - vector
8188a6e0b375SMatthew G. Knepley 
818920f4b53cSBarry Smith   Calling sequence of `funcs`:
8190a6e0b375SMatthew G. Knepley + dim  - The spatial dimension
8191a4e35b19SJacob Faibussowitsch . time - The current timestep
8192a6e0b375SMatthew G. Knepley . x    - The coordinates
819377b739a6SMatthew Knepley . Nc   - The number of components
8194a6e0b375SMatthew G. Knepley . u    - The output field values
8195a6e0b375SMatthew G. Knepley - ctx  - optional user-defined function context
8196a6e0b375SMatthew G. Knepley 
8197a6e0b375SMatthew G. Knepley   Level: developer
8198a6e0b375SMatthew G. Knepley 
8199bb7acecfSBarry Smith   Developer Notes:
8200bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8201bb7acecfSBarry Smith 
8202bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8203bb7acecfSBarry Smith 
82041cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
8205a6e0b375SMatthew G. Knepley @*/
8206a4e35b19SJacob 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)
8207d71ae5a4SJacob Faibussowitsch {
82084d6f44ffSToby Isaac   PetscFunctionBegin;
82094d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8210064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
8211fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfunctionlocal, time, funcs, ctxs, mode, localX);
82123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82134d6f44ffSToby Isaac }
82144d6f44ffSToby Isaac 
8215a6e0b375SMatthew G. Knepley /*@C
8216bb7acecfSBarry 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.
8217a6e0b375SMatthew G. Knepley 
821820f4b53cSBarry Smith   Collective
8219a6e0b375SMatthew G. Knepley 
8220a6e0b375SMatthew G. Knepley   Input Parameters:
8221bb7acecfSBarry Smith + dm     - The `DM`
8222a6e0b375SMatthew G. Knepley . time   - The time
8223a4e35b19SJacob Faibussowitsch . numIds - The number of ids
8224a4e35b19SJacob Faibussowitsch . ids    - The ids
8225a4e35b19SJacob Faibussowitsch . Nc     - The number of components
8226a4e35b19SJacob Faibussowitsch . comps  - The components
8227bb7acecfSBarry Smith . label  - The `DMLabel` selecting the portion of the mesh for projection
8228a6e0b375SMatthew G. Knepley . funcs  - The coordinate functions to evaluate, one per field
8229bb7acecfSBarry Smith . ctxs   - Optional array of contexts to pass to each coordinate function.  ctxs may be null.
8230a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8231a6e0b375SMatthew G. Knepley 
8232a6e0b375SMatthew G. Knepley   Output Parameter:
8233a6e0b375SMatthew G. Knepley . X - vector
8234a6e0b375SMatthew G. Knepley 
823520f4b53cSBarry Smith   Calling sequence of `funcs`:
8236a6e0b375SMatthew G. Knepley + dim  - The spatial dimension
8237a4e35b19SJacob Faibussowitsch . time - The current timestep
8238a6e0b375SMatthew G. Knepley . x    - The coordinates
823977b739a6SMatthew Knepley . Nc   - The number of components
8240a6e0b375SMatthew G. Knepley . u    - The output field values
8241a6e0b375SMatthew G. Knepley - ctx  - optional user-defined function context
8242a6e0b375SMatthew G. Knepley 
8243a6e0b375SMatthew G. Knepley   Level: developer
8244a6e0b375SMatthew G. Knepley 
8245bb7acecfSBarry Smith   Developer Notes:
8246bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8247bb7acecfSBarry Smith 
8248bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8249bb7acecfSBarry Smith 
82501cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabelLocal()`, `DMComputeL2Diff()`
8251a6e0b375SMatthew G. Knepley @*/
8252a4e35b19SJacob 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)
8253d71ae5a4SJacob Faibussowitsch {
82542c53366bSMatthew G. Knepley   Vec localX;
82552c53366bSMatthew G. Knepley 
82562c53366bSMatthew G. Knepley   PetscFunctionBegin;
82572c53366bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
82589566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
8259f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
82609566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
82619566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
82629566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
82639566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
82643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82652c53366bSMatthew G. Knepley }
82662c53366bSMatthew G. Knepley 
8267a6e0b375SMatthew G. Knepley /*@C
8268bb7acecfSBarry 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.
8269a6e0b375SMatthew G. Knepley 
827020f4b53cSBarry Smith   Not Collective
8271a6e0b375SMatthew G. Knepley 
8272a6e0b375SMatthew G. Knepley   Input Parameters:
8273bb7acecfSBarry Smith + dm     - The `DM`
8274a6e0b375SMatthew G. Knepley . time   - The time
8275bb7acecfSBarry Smith . label  - The `DMLabel` selecting the portion of the mesh for projection
8276a4e35b19SJacob Faibussowitsch . numIds - The number of ids
8277a4e35b19SJacob Faibussowitsch . ids    - The ids
8278a4e35b19SJacob Faibussowitsch . Nc     - The number of components
8279a4e35b19SJacob Faibussowitsch . comps  - The components
8280a6e0b375SMatthew G. Knepley . funcs  - The coordinate functions to evaluate, one per field
8281a6e0b375SMatthew G. Knepley . ctxs   - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
8282a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8283a6e0b375SMatthew G. Knepley 
8284a6e0b375SMatthew G. Knepley   Output Parameter:
8285a6e0b375SMatthew G. Knepley . localX - vector
8286a6e0b375SMatthew G. Knepley 
828720f4b53cSBarry Smith   Calling sequence of `funcs`:
8288a6e0b375SMatthew G. Knepley + dim  - The spatial dimension
8289a4e35b19SJacob Faibussowitsch . time - The current time
8290a6e0b375SMatthew G. Knepley . x    - The coordinates
829177b739a6SMatthew Knepley . Nc   - The number of components
8292a6e0b375SMatthew G. Knepley . u    - The output field values
8293a6e0b375SMatthew G. Knepley - ctx  - optional user-defined function context
8294a6e0b375SMatthew G. Knepley 
8295a6e0b375SMatthew G. Knepley   Level: developer
8296a6e0b375SMatthew G. Knepley 
8297bb7acecfSBarry Smith   Developer Notes:
8298bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8299bb7acecfSBarry Smith 
8300bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8301bb7acecfSBarry Smith 
83021cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
8303a6e0b375SMatthew G. Knepley @*/
8304a4e35b19SJacob 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)
8305d71ae5a4SJacob Faibussowitsch {
83064d6f44ffSToby Isaac   PetscFunctionBegin;
83074d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8308064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
8309fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfunctionlabellocal, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
83103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83114d6f44ffSToby Isaac }
83122716604bSToby Isaac 
8313a6e0b375SMatthew G. Knepley /*@C
8314bb7acecfSBarry 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.
8315a6e0b375SMatthew G. Knepley 
831620f4b53cSBarry Smith   Not Collective
8317a6e0b375SMatthew G. Knepley 
8318a6e0b375SMatthew G. Knepley   Input Parameters:
8319bb7acecfSBarry Smith + dm     - The `DM`
8320a6e0b375SMatthew G. Knepley . time   - The time
832120f4b53cSBarry Smith . localU - The input field vector; may be `NULL` if projection is defined purely by coordinates
8322a6e0b375SMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8323a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8324a6e0b375SMatthew G. Knepley 
8325a6e0b375SMatthew G. Knepley   Output Parameter:
8326a6e0b375SMatthew G. Knepley . localX - The output vector
8327a6e0b375SMatthew G. Knepley 
832820f4b53cSBarry Smith   Calling sequence of `funcs`:
8329a6e0b375SMatthew G. Knepley + dim          - The spatial dimension
8330a6e0b375SMatthew G. Knepley . Nf           - The number of input fields
8331a6e0b375SMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8332a6e0b375SMatthew G. Knepley . uOff         - The offset of each field in u[]
8333a6e0b375SMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8334a6e0b375SMatthew G. Knepley . u            - The field values at this point in space
8335a6e0b375SMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8336a6e0b375SMatthew G. Knepley . u_x          - The field derivatives at this point in space
8337a6e0b375SMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8338a6e0b375SMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8339a6e0b375SMatthew G. Knepley . a            - The auxiliary field values at this point in space
8340a6e0b375SMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8341a6e0b375SMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8342a6e0b375SMatthew G. Knepley . t            - The current time
8343a6e0b375SMatthew G. Knepley . x            - The coordinates of this point
8344a6e0b375SMatthew G. Knepley . numConstants - The number of constants
8345a6e0b375SMatthew G. Knepley . constants    - The value of each constant
8346a6e0b375SMatthew G. Knepley - f            - The value of the function at this point in space
8347a6e0b375SMatthew G. Knepley 
834873ff1848SBarry Smith   Level: intermediate
834973ff1848SBarry Smith 
8350bb7acecfSBarry Smith   Note:
8351bb7acecfSBarry 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.
8352bb7acecfSBarry 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
8353bb7acecfSBarry 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
8354a6e0b375SMatthew 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.
8355a6e0b375SMatthew G. Knepley 
8356bb7acecfSBarry Smith   Developer Notes:
8357bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8358bb7acecfSBarry Smith 
8359bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8360bb7acecfSBarry Smith 
8361a4e35b19SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`,
8362a4e35b19SJacob Faibussowitsch `DMProjectFunction()`, `DMComputeL2Diff()`
8363a6e0b375SMatthew G. Knepley @*/
8364a4e35b19SJacob 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)
8365d71ae5a4SJacob Faibussowitsch {
83668c6c5593SMatthew G. Knepley   PetscFunctionBegin;
83678c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8368eb8f539aSJed Brown   if (localU) PetscValidHeaderSpecific(localU, VEC_CLASSID, 3);
83698c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
8370fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfieldlocal, time, localU, funcs, mode, localX);
83713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83728c6c5593SMatthew G. Knepley }
83738c6c5593SMatthew G. Knepley 
8374a6e0b375SMatthew G. Knepley /*@C
8375a6e0b375SMatthew 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.
8376a6e0b375SMatthew G. Knepley 
837720f4b53cSBarry Smith   Not Collective
8378a6e0b375SMatthew G. Knepley 
8379a6e0b375SMatthew G. Knepley   Input Parameters:
8380bb7acecfSBarry Smith + dm     - The `DM`
8381a6e0b375SMatthew G. Knepley . time   - The time
8382bb7acecfSBarry Smith . label  - The `DMLabel` marking the portion of the domain to output
8383a6e0b375SMatthew G. Knepley . numIds - The number of label ids to use
8384a6e0b375SMatthew G. Knepley . ids    - The label ids to use for marking
8385bb7acecfSBarry Smith . Nc     - The number of components to set in the output, or `PETSC_DETERMINE` for all components
838620f4b53cSBarry Smith . comps  - The components to set in the output, or `NULL` for all components
8387a6e0b375SMatthew G. Knepley . localU - The input field vector
8388a6e0b375SMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8389a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8390a6e0b375SMatthew G. Knepley 
8391a6e0b375SMatthew G. Knepley   Output Parameter:
8392a6e0b375SMatthew G. Knepley . localX - The output vector
8393a6e0b375SMatthew G. Knepley 
839420f4b53cSBarry Smith   Calling sequence of `funcs`:
8395a6e0b375SMatthew G. Knepley + dim          - The spatial dimension
8396a6e0b375SMatthew G. Knepley . Nf           - The number of input fields
8397a6e0b375SMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8398a6e0b375SMatthew G. Knepley . uOff         - The offset of each field in u[]
8399a6e0b375SMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8400a6e0b375SMatthew G. Knepley . u            - The field values at this point in space
8401a6e0b375SMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8402a6e0b375SMatthew G. Knepley . u_x          - The field derivatives at this point in space
8403a6e0b375SMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8404a6e0b375SMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8405a6e0b375SMatthew G. Knepley . a            - The auxiliary field values at this point in space
8406a6e0b375SMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8407a6e0b375SMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8408a6e0b375SMatthew G. Knepley . t            - The current time
8409a6e0b375SMatthew G. Knepley . x            - The coordinates of this point
8410a6e0b375SMatthew G. Knepley . numConstants - The number of constants
8411a6e0b375SMatthew G. Knepley . constants    - The value of each constant
8412a6e0b375SMatthew G. Knepley - f            - The value of the function at this point in space
8413a6e0b375SMatthew G. Knepley 
841473ff1848SBarry Smith   Level: intermediate
841573ff1848SBarry Smith 
8416bb7acecfSBarry Smith   Note:
8417bb7acecfSBarry 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.
8418bb7acecfSBarry 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
8419bb7acecfSBarry 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
8420a6e0b375SMatthew 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.
8421a6e0b375SMatthew G. Knepley 
8422bb7acecfSBarry Smith   Developer Notes:
8423bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8424bb7acecfSBarry Smith 
8425bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8426bb7acecfSBarry Smith 
84271cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabel()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8428a6e0b375SMatthew G. Knepley @*/
8429a4e35b19SJacob 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)
8430d71ae5a4SJacob Faibussowitsch {
84318c6c5593SMatthew G. Knepley   PetscFunctionBegin;
84328c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8433064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8434064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
8435fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfieldlabellocal, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
84363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84378c6c5593SMatthew G. Knepley }
84388c6c5593SMatthew G. Knepley 
84392716604bSToby Isaac /*@C
8440d29d7c6eSMatthew 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.
8441d29d7c6eSMatthew G. Knepley 
844220f4b53cSBarry Smith   Not Collective
8443d29d7c6eSMatthew G. Knepley 
8444d29d7c6eSMatthew G. Knepley   Input Parameters:
8445bb7acecfSBarry Smith + dm     - The `DM`
8446d29d7c6eSMatthew G. Knepley . time   - The time
8447bb7acecfSBarry Smith . label  - The `DMLabel` marking the portion of the domain to output
8448d29d7c6eSMatthew G. Knepley . numIds - The number of label ids to use
8449d29d7c6eSMatthew G. Knepley . ids    - The label ids to use for marking
8450bb7acecfSBarry Smith . Nc     - The number of components to set in the output, or `PETSC_DETERMINE` for all components
845120f4b53cSBarry Smith . comps  - The components to set in the output, or `NULL` for all components
8452d29d7c6eSMatthew G. Knepley . U      - The input field vector
8453d29d7c6eSMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8454d29d7c6eSMatthew G. Knepley - mode   - The insertion mode for values
8455d29d7c6eSMatthew G. Knepley 
8456d29d7c6eSMatthew G. Knepley   Output Parameter:
8457d29d7c6eSMatthew G. Knepley . X - The output vector
8458d29d7c6eSMatthew G. Knepley 
845920f4b53cSBarry Smith   Calling sequence of `funcs`:
8460d29d7c6eSMatthew G. Knepley + dim          - The spatial dimension
8461d29d7c6eSMatthew G. Knepley . Nf           - The number of input fields
8462d29d7c6eSMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8463d29d7c6eSMatthew G. Knepley . uOff         - The offset of each field in u[]
8464d29d7c6eSMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8465d29d7c6eSMatthew G. Knepley . u            - The field values at this point in space
8466d29d7c6eSMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8467d29d7c6eSMatthew G. Knepley . u_x          - The field derivatives at this point in space
8468d29d7c6eSMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8469d29d7c6eSMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8470d29d7c6eSMatthew G. Knepley . a            - The auxiliary field values at this point in space
8471d29d7c6eSMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8472d29d7c6eSMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8473d29d7c6eSMatthew G. Knepley . t            - The current time
8474d29d7c6eSMatthew G. Knepley . x            - The coordinates of this point
8475d29d7c6eSMatthew G. Knepley . numConstants - The number of constants
8476d29d7c6eSMatthew G. Knepley . constants    - The value of each constant
8477d29d7c6eSMatthew G. Knepley - f            - The value of the function at this point in space
8478d29d7c6eSMatthew G. Knepley 
847973ff1848SBarry Smith   Level: intermediate
848073ff1848SBarry Smith 
8481bb7acecfSBarry Smith   Note:
8482bb7acecfSBarry 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.
8483bb7acecfSBarry 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
8484bb7acecfSBarry 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
8485d29d7c6eSMatthew 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.
8486d29d7c6eSMatthew G. Knepley 
8487bb7acecfSBarry Smith   Developer Notes:
8488bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8489bb7acecfSBarry Smith 
8490bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8491bb7acecfSBarry Smith 
84921cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8493d29d7c6eSMatthew G. Knepley @*/
8494a4e35b19SJacob 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)
8495d71ae5a4SJacob Faibussowitsch {
8496d29d7c6eSMatthew G. Knepley   DM  dmIn;
8497d29d7c6eSMatthew G. Knepley   Vec localU, localX;
8498d29d7c6eSMatthew G. Knepley 
8499d29d7c6eSMatthew G. Knepley   PetscFunctionBegin;
8500d29d7c6eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8501d29d7c6eSMatthew G. Knepley   PetscCall(VecGetDM(U, &dmIn));
8502d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dmIn, &localU));
8503d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dm, &localX));
8504f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
850572fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalBegin(dmIn, U, mode, localU));
850672fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalEnd(dmIn, U, mode, localU));
8507d29d7c6eSMatthew G. Knepley   PetscCall(DMProjectFieldLabelLocal(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
8508d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
8509d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
8510d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dm, &localX));
8511d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dmIn, &localU));
85123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8513d29d7c6eSMatthew G. Knepley }
8514d29d7c6eSMatthew G. Knepley 
8515d29d7c6eSMatthew G. Knepley /*@C
8516ece3a9fcSMatthew 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.
8517ece3a9fcSMatthew G. Knepley 
851820f4b53cSBarry Smith   Not Collective
8519ece3a9fcSMatthew G. Knepley 
8520ece3a9fcSMatthew G. Knepley   Input Parameters:
8521bb7acecfSBarry Smith + dm     - The `DM`
8522ece3a9fcSMatthew G. Knepley . time   - The time
8523bb7acecfSBarry Smith . label  - The `DMLabel` marking the portion of the domain boundary to output
8524ece3a9fcSMatthew G. Knepley . numIds - The number of label ids to use
8525ece3a9fcSMatthew G. Knepley . ids    - The label ids to use for marking
8526bb7acecfSBarry Smith . Nc     - The number of components to set in the output, or `PETSC_DETERMINE` for all components
852720f4b53cSBarry Smith . comps  - The components to set in the output, or `NULL` for all components
8528ece3a9fcSMatthew G. Knepley . localU - The input field vector
8529ece3a9fcSMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8530ece3a9fcSMatthew G. Knepley - mode   - The insertion mode for values
8531ece3a9fcSMatthew G. Knepley 
8532ece3a9fcSMatthew G. Knepley   Output Parameter:
8533ece3a9fcSMatthew G. Knepley . localX - The output vector
8534ece3a9fcSMatthew G. Knepley 
853520f4b53cSBarry Smith   Calling sequence of `funcs`:
8536ece3a9fcSMatthew G. Knepley + dim          - The spatial dimension
8537ece3a9fcSMatthew G. Knepley . Nf           - The number of input fields
8538ece3a9fcSMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8539ece3a9fcSMatthew G. Knepley . uOff         - The offset of each field in u[]
8540ece3a9fcSMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8541ece3a9fcSMatthew G. Knepley . u            - The field values at this point in space
8542ece3a9fcSMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8543ece3a9fcSMatthew G. Knepley . u_x          - The field derivatives at this point in space
8544ece3a9fcSMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8545ece3a9fcSMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8546ece3a9fcSMatthew G. Knepley . a            - The auxiliary field values at this point in space
8547ece3a9fcSMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8548ece3a9fcSMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8549ece3a9fcSMatthew G. Knepley . t            - The current time
8550ece3a9fcSMatthew G. Knepley . x            - The coordinates of this point
8551ece3a9fcSMatthew G. Knepley . n            - The face normal
8552ece3a9fcSMatthew G. Knepley . numConstants - The number of constants
8553ece3a9fcSMatthew G. Knepley . constants    - The value of each constant
8554ece3a9fcSMatthew G. Knepley - f            - The value of the function at this point in space
8555ece3a9fcSMatthew G. Knepley 
855673ff1848SBarry Smith   Level: intermediate
855773ff1848SBarry Smith 
8558ece3a9fcSMatthew G. Knepley   Note:
8559bb7acecfSBarry 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.
8560bb7acecfSBarry 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
8561bb7acecfSBarry 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
8562ece3a9fcSMatthew 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.
8563ece3a9fcSMatthew G. Knepley 
8564bb7acecfSBarry Smith   Developer Notes:
8565bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8566bb7acecfSBarry Smith 
8567bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8568bb7acecfSBarry Smith 
85691cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8570ece3a9fcSMatthew G. Knepley @*/
8571a4e35b19SJacob 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)
8572d71ae5a4SJacob Faibussowitsch {
8573ece3a9fcSMatthew G. Knepley   PetscFunctionBegin;
8574ece3a9fcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8575064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8576064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
8577fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectbdfieldlabellocal, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
85783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8579ece3a9fcSMatthew G. Knepley }
8580ece3a9fcSMatthew G. Knepley 
8581ece3a9fcSMatthew G. Knepley /*@C
85822716604bSToby Isaac   DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
85832716604bSToby Isaac 
858420f4b53cSBarry Smith   Collective
8585bb7acecfSBarry Smith 
85862716604bSToby Isaac   Input Parameters:
8587bb7acecfSBarry Smith + dm    - The `DM`
85880709b2feSToby Isaac . time  - The time
85892716604bSToby Isaac . funcs - The functions to evaluate for each field component
85902716604bSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8591574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
85922716604bSToby Isaac 
85932716604bSToby Isaac   Output Parameter:
85942716604bSToby Isaac . diff - The diff ||u - u_h||_2
85952716604bSToby Isaac 
85962716604bSToby Isaac   Level: developer
85972716604bSToby Isaac 
8598bb7acecfSBarry Smith   Developer Notes:
8599bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8600bb7acecfSBarry Smith 
8601bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8602bb7acecfSBarry Smith 
86031cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
86042716604bSToby Isaac @*/
8605d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
8606d71ae5a4SJacob Faibussowitsch {
86072716604bSToby Isaac   PetscFunctionBegin;
86082716604bSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8609b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
8610fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, computel2diff, time, funcs, ctxs, X, diff);
86113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86122716604bSToby Isaac }
8613b698f381SToby Isaac 
8614b698f381SToby Isaac /*@C
8615b698f381SToby Isaac   DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
8616b698f381SToby Isaac 
861720f4b53cSBarry Smith   Collective
8618d083f849SBarry Smith 
8619b698f381SToby Isaac   Input Parameters:
8620bb7acecfSBarry Smith + dm    - The `DM`
8621a4e35b19SJacob Faibussowitsch . time  - The time
8622b698f381SToby Isaac . funcs - The gradient functions to evaluate for each field component
8623b698f381SToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8624574a98acSMatthew G. Knepley . X     - The coefficient vector u_h, a global vector
8625b698f381SToby Isaac - n     - The vector to project along
8626b698f381SToby Isaac 
8627b698f381SToby Isaac   Output Parameter:
8628b698f381SToby Isaac . diff - The diff ||(grad u - grad u_h) . n||_2
8629b698f381SToby Isaac 
8630b698f381SToby Isaac   Level: developer
8631b698f381SToby Isaac 
8632bb7acecfSBarry Smith   Developer Notes:
8633bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8634bb7acecfSBarry Smith 
8635bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8636bb7acecfSBarry Smith 
86371cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2Diff()`, `DMComputeL2FieldDiff()`
8638b698f381SToby Isaac @*/
8639d71ae5a4SJacob 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)
8640d71ae5a4SJacob Faibussowitsch {
8641b698f381SToby Isaac   PetscFunctionBegin;
8642b698f381SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8643b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
8644fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, computel2gradientdiff, time, funcs, ctxs, X, n, diff);
86453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8646b698f381SToby Isaac }
8647b698f381SToby Isaac 
86482a16baeaSToby Isaac /*@C
86492a16baeaSToby Isaac   DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
86502a16baeaSToby Isaac 
865120f4b53cSBarry Smith   Collective
8652d083f849SBarry Smith 
86532a16baeaSToby Isaac   Input Parameters:
8654bb7acecfSBarry Smith + dm    - The `DM`
86552a16baeaSToby Isaac . time  - The time
86562a16baeaSToby Isaac . funcs - The functions to evaluate for each field component
86572a16baeaSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8658574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
86592a16baeaSToby Isaac 
86602a16baeaSToby Isaac   Output Parameter:
86612a16baeaSToby Isaac . diff - The array of differences, ||u^f - u^f_h||_2
86622a16baeaSToby Isaac 
86632a16baeaSToby Isaac   Level: developer
86642a16baeaSToby Isaac 
8665bb7acecfSBarry Smith   Developer Notes:
8666bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8667bb7acecfSBarry Smith 
8668bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8669bb7acecfSBarry Smith 
867042747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2GradientDiff()`
86712a16baeaSToby Isaac @*/
8672d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
8673d71ae5a4SJacob Faibussowitsch {
86742a16baeaSToby Isaac   PetscFunctionBegin;
86752a16baeaSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86762a16baeaSToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
8677fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, computel2fielddiff, time, funcs, ctxs, X, diff);
86783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86792a16baeaSToby Isaac }
86802a16baeaSToby Isaac 
8681df0b854cSToby Isaac /*@C
8682bb7acecfSBarry Smith   DMGetNeighbors - Gets an array containing the MPI ranks of all the processes neighbors
8683502a2867SDave May 
8684502a2867SDave May   Not Collective
8685502a2867SDave May 
8686502a2867SDave May   Input Parameter:
8687bb7acecfSBarry Smith . dm - The `DM`
8688502a2867SDave May 
86890a19bb7dSprj-   Output Parameters:
86900a19bb7dSprj- + nranks - the number of neighbours
86910a19bb7dSprj- - ranks  - the neighbors ranks
8692502a2867SDave May 
86939bdbcad8SBarry Smith   Level: beginner
86949bdbcad8SBarry Smith 
8695bb7acecfSBarry Smith   Note:
8696bb7acecfSBarry Smith   Do not free the array, it is freed when the `DM` is destroyed.
8697502a2867SDave May 
86981cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDAGetNeighbors()`, `PetscSFGetRootRanks()`
8699502a2867SDave May @*/
8700d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNeighbors(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
8701d71ae5a4SJacob Faibussowitsch {
8702502a2867SDave May   PetscFunctionBegin;
8703502a2867SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8704fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, getneighbors, nranks, ranks);
87053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8706502a2867SDave May }
8707502a2867SDave May 
8708531c7667SBarry Smith #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
8709531c7667SBarry Smith 
8710531c7667SBarry Smith /*
8711531c7667SBarry Smith     Converts the input vector to a ghosted vector and then calls the standard coloring code.
87122b6f951bSStefano Zampini     This must be a different function because it requires DM which is not defined in the Mat library
8713531c7667SBarry Smith */
871466976f2fSJacob Faibussowitsch static PetscErrorCode MatFDColoringApply_AIJDM(Mat J, MatFDColoring coloring, Vec x1, void *sctx)
8715d71ae5a4SJacob Faibussowitsch {
8716531c7667SBarry Smith   PetscFunctionBegin;
8717531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8718531c7667SBarry Smith     Vec x1local;
8719531c7667SBarry Smith     DM  dm;
87209566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
87217a8be351SBarry Smith     PetscCheck(dm, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_INCOMP, "IS_COLORING_LOCAL requires a DM");
87229566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &x1local));
87239566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, x1, INSERT_VALUES, x1local));
87249566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, x1, INSERT_VALUES, x1local));
8725531c7667SBarry Smith     x1 = x1local;
8726531c7667SBarry Smith   }
87279566063dSJacob Faibussowitsch   PetscCall(MatFDColoringApply_AIJ(J, coloring, x1, sctx));
8728531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8729531c7667SBarry Smith     DM dm;
87309566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
87319566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &x1));
8732531c7667SBarry Smith   }
87333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8734531c7667SBarry Smith }
8735531c7667SBarry Smith 
8736531c7667SBarry Smith /*@
8737bb7acecfSBarry Smith   MatFDColoringUseDM - allows a `MatFDColoring` object to use the `DM` associated with the matrix to compute a `IS_COLORING_LOCAL` coloring
8738531c7667SBarry Smith 
8739a4e35b19SJacob Faibussowitsch   Input Parameters:
8740a4e35b19SJacob Faibussowitsch + coloring   - The matrix to get the `DM` from
8741a4e35b19SJacob Faibussowitsch - fdcoloring - the `MatFDColoring` object
8742531c7667SBarry Smith 
87439bdbcad8SBarry Smith   Level: advanced
87449bdbcad8SBarry Smith 
874573ff1848SBarry Smith   Developer Note:
874673ff1848SBarry Smith   This routine exists because the PETSc `Mat` library does not know about the `DM` objects
8747531c7667SBarry Smith 
87481cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatFDColoring`, `MatFDColoringCreate()`, `ISColoringType`
8749531c7667SBarry Smith @*/
8750d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringUseDM(Mat coloring, MatFDColoring fdcoloring)
8751d71ae5a4SJacob Faibussowitsch {
8752531c7667SBarry Smith   PetscFunctionBegin;
8753531c7667SBarry Smith   coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
87543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8755531c7667SBarry Smith }
87568320bc6fSPatrick Sanan 
87578320bc6fSPatrick Sanan /*@
8758bb7acecfSBarry Smith   DMGetCompatibility - determine if two `DM`s are compatible
87598320bc6fSPatrick Sanan 
87608320bc6fSPatrick Sanan   Collective
87618320bc6fSPatrick Sanan 
87628320bc6fSPatrick Sanan   Input Parameters:
8763bb7acecfSBarry Smith + dm1 - the first `DM`
8764bb7acecfSBarry Smith - dm2 - the second `DM`
87658320bc6fSPatrick Sanan 
87668320bc6fSPatrick Sanan   Output Parameters:
8767bb7acecfSBarry Smith + compatible - whether or not the two `DM`s are compatible
8768bb7acecfSBarry Smith - set        - whether or not the compatible value was actually determined and set
87698320bc6fSPatrick Sanan 
877020f4b53cSBarry Smith   Level: advanced
877120f4b53cSBarry Smith 
87728320bc6fSPatrick Sanan   Notes:
8773bb7acecfSBarry Smith   Two `DM`s are deemed compatible if they represent the same parallel decomposition
87743d862458SPatrick Sanan   of the same topology. This implies that the section (field data) on one
87758320bc6fSPatrick Sanan   "makes sense" with respect to the topology and parallel decomposition of the other.
8776bb7acecfSBarry Smith   Loosely speaking, compatible `DM`s represent the same domain and parallel
87773d862458SPatrick Sanan   decomposition, but hold different data.
87788320bc6fSPatrick Sanan 
87798320bc6fSPatrick Sanan   Typically, one would confirm compatibility if intending to simultaneously iterate
8780bb7acecfSBarry Smith   over a pair of vectors obtained from different `DM`s.
87818320bc6fSPatrick Sanan 
8782bb7acecfSBarry Smith   For example, two `DMDA` objects are compatible if they have the same local
87838320bc6fSPatrick Sanan   and global sizes and the same stencil width. They can have different numbers
87848320bc6fSPatrick Sanan   of degrees of freedom per node. Thus, one could use the node numbering from
8785bb7acecfSBarry Smith   either `DM` in bounds for a loop over vectors derived from either `DM`.
87868320bc6fSPatrick Sanan 
8787bb7acecfSBarry Smith   Consider the operation of summing data living on a 2-dof `DMDA` to data living
8788bb7acecfSBarry Smith   on a 1-dof `DMDA`, which should be compatible, as in the following snippet.
87898320bc6fSPatrick Sanan .vb
87908320bc6fSPatrick Sanan   ...
87919566063dSJacob Faibussowitsch   PetscCall(DMGetCompatibility(da1,da2,&compatible,&set));
87928320bc6fSPatrick Sanan   if (set && compatible)  {
87939566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da1,vec1,&arr1));
87949566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da2,vec2,&arr2));
87959566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL));
87968320bc6fSPatrick Sanan     for (j=y; j<y+n; ++j) {
87978320bc6fSPatrick Sanan       for (i=x; i<x+m, ++i) {
87988320bc6fSPatrick Sanan         arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1];
87998320bc6fSPatrick Sanan       }
88008320bc6fSPatrick Sanan     }
88019566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da1,vec1,&arr1));
88029566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da2,vec2,&arr2));
88038320bc6fSPatrick Sanan   } else {
88048320bc6fSPatrick Sanan     SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible");
88058320bc6fSPatrick Sanan   }
88068320bc6fSPatrick Sanan   ...
88078320bc6fSPatrick Sanan .ve
88088320bc6fSPatrick Sanan 
8809bb7acecfSBarry Smith   Checking compatibility might be expensive for a given implementation of `DM`,
88108320bc6fSPatrick Sanan   or might be impossible to unambiguously confirm or deny. For this reason,
88118320bc6fSPatrick Sanan   this function may decline to determine compatibility, and hence users should
88128320bc6fSPatrick Sanan   always check the "set" output parameter.
88138320bc6fSPatrick Sanan 
8814bb7acecfSBarry Smith   A `DM` is always compatible with itself.
88158320bc6fSPatrick Sanan 
8816bb7acecfSBarry Smith   In the current implementation, `DM`s which live on "unequal" communicators
88178320bc6fSPatrick Sanan   (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed
88188320bc6fSPatrick Sanan   incompatible.
88198320bc6fSPatrick Sanan 
88208320bc6fSPatrick Sanan   This function is labeled "Collective," as information about all subdomains
8821bb7acecfSBarry Smith   is required on each rank. However, in `DM` implementations which store all this
88228320bc6fSPatrick Sanan   information locally, this function may be merely "Logically Collective".
88238320bc6fSPatrick Sanan 
882473ff1848SBarry Smith   Developer Note:
8825bb7acecfSBarry Smith   Compatibility is assumed to be a symmetric concept; `DM` A is compatible with `DM` B
88263d862458SPatrick Sanan   iff B is compatible with A. Thus, this function checks the implementations
8827a5bc1bf3SBarry Smith   of both dm and dmc (if they are of different types), attempting to determine
8828bb7acecfSBarry Smith   compatibility. It is left to `DM` implementers to ensure that symmetry is
88298320bc6fSPatrick Sanan   preserved. The simplest way to do this is, when implementing type-specific
88303d862458SPatrick Sanan   logic for this function, is to check for existing logic in the implementation
8831bb7acecfSBarry Smith   of other `DM` types and let *set = PETSC_FALSE if found.
88328320bc6fSPatrick Sanan 
88331cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreateCompatibleDMDA()`, `DMStagCreateCompatibleDMStag()`
88348320bc6fSPatrick Sanan @*/
8835d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCompatibility(DM dm1, DM dm2, PetscBool *compatible, PetscBool *set)
8836d71ae5a4SJacob Faibussowitsch {
88378320bc6fSPatrick Sanan   PetscMPIInt compareResult;
88388320bc6fSPatrick Sanan   DMType      type, type2;
88398320bc6fSPatrick Sanan   PetscBool   sameType;
88408320bc6fSPatrick Sanan 
88418320bc6fSPatrick Sanan   PetscFunctionBegin;
8842a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dm1, DM_CLASSID, 1);
88438320bc6fSPatrick Sanan   PetscValidHeaderSpecific(dm2, DM_CLASSID, 2);
88448320bc6fSPatrick Sanan 
88458320bc6fSPatrick Sanan   /* Declare a DM compatible with itself */
8846a5bc1bf3SBarry Smith   if (dm1 == dm2) {
88478320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
88488320bc6fSPatrick Sanan     *compatible = PETSC_TRUE;
88493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
88508320bc6fSPatrick Sanan   }
88518320bc6fSPatrick Sanan 
88528320bc6fSPatrick Sanan   /* Declare a DM incompatible with a DM that lives on an "unequal"
88538320bc6fSPatrick Sanan      communicator. Note that this does not preclude compatibility with
88548320bc6fSPatrick Sanan      DMs living on "congruent" or "similar" communicators, but this must be
88558320bc6fSPatrick Sanan      determined by the implementation-specific logic */
88569566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)dm1), PetscObjectComm((PetscObject)dm2), &compareResult));
88578320bc6fSPatrick Sanan   if (compareResult == MPI_UNEQUAL) {
88588320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
88598320bc6fSPatrick Sanan     *compatible = PETSC_FALSE;
88603ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
88618320bc6fSPatrick Sanan   }
88628320bc6fSPatrick Sanan 
88638320bc6fSPatrick Sanan   /* Pass to the implementation-specific routine, if one exists. */
8864a5bc1bf3SBarry Smith   if (dm1->ops->getcompatibility) {
8865dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm1, getcompatibility, dm2, compatible, set);
88663ba16761SJacob Faibussowitsch     if (*set) PetscFunctionReturn(PETSC_SUCCESS);
88678320bc6fSPatrick Sanan   }
88688320bc6fSPatrick Sanan 
8869a5bc1bf3SBarry Smith   /* If dm1 and dm2 are of different types, then attempt to check compatibility
88708320bc6fSPatrick Sanan      with an implementation of this function from dm2 */
88719566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm1, &type));
88729566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm2, &type2));
88739566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(type, type2, &sameType));
88748320bc6fSPatrick Sanan   if (!sameType && dm2->ops->getcompatibility) {
8875dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm2, getcompatibility, dm1, compatible, set); /* Note argument order */
88768320bc6fSPatrick Sanan   } else {
88778320bc6fSPatrick Sanan     *set = PETSC_FALSE;
88788320bc6fSPatrick Sanan   }
88793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
88808320bc6fSPatrick Sanan }
8881c0f0dcc3SMatthew G. Knepley 
8882c0f0dcc3SMatthew G. Knepley /*@C
8883bb7acecfSBarry Smith   DMMonitorSet - Sets an additional monitor function that is to be used after a solve to monitor discretization performance.
8884c0f0dcc3SMatthew G. Knepley 
888520f4b53cSBarry Smith   Logically Collective
8886c0f0dcc3SMatthew G. Knepley 
8887c0f0dcc3SMatthew G. Knepley   Input Parameters:
888860225df5SJacob Faibussowitsch + dm             - the `DM`
8889c0f0dcc3SMatthew G. Knepley . f              - the monitor function
889020f4b53cSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
889149abdd8aSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for the calling sequence
8892c0f0dcc3SMatthew G. Knepley 
889320f4b53cSBarry Smith   Options Database Key:
889460225df5SJacob Faibussowitsch . -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `DMMonitorSet()`, but
8895c0f0dcc3SMatthew G. Knepley                        does not cancel those set via the options database.
8896c0f0dcc3SMatthew G. Knepley 
88979bdbcad8SBarry Smith   Level: intermediate
88989bdbcad8SBarry Smith 
8899bb7acecfSBarry Smith   Note:
8900c0f0dcc3SMatthew G. Knepley   Several different monitoring routines may be set by calling
8901bb7acecfSBarry Smith   `DMMonitorSet()` multiple times or with `DMMonitorSetFromOptions()`; all will be called in the
8902c0f0dcc3SMatthew G. Knepley   order in which they were set.
8903c0f0dcc3SMatthew G. Knepley 
890473ff1848SBarry Smith   Fortran Note:
8905bb7acecfSBarry Smith   Only a single monitor function can be set for each `DM` object
8906bb7acecfSBarry Smith 
890773ff1848SBarry Smith   Developer Note:
8908bb7acecfSBarry Smith   This API has a generic name but seems specific to a very particular aspect of the use of `DM`
8909c0f0dcc3SMatthew G. Knepley 
891049abdd8aSBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorCancel()`, `DMMonitorSetFromOptions()`, `DMMonitor()`, `PetscCtxDestroyFn`
8911c0f0dcc3SMatthew G. Knepley @*/
891249abdd8aSBarry Smith PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscCtxDestroyFn *monitordestroy)
8913d71ae5a4SJacob Faibussowitsch {
8914c0f0dcc3SMatthew G. Knepley   PetscInt m;
8915c0f0dcc3SMatthew G. Knepley 
8916c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8917c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8918c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
8919c0f0dcc3SMatthew G. Knepley     PetscBool identical;
8920c0f0dcc3SMatthew G. Knepley 
89219566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode (*)(void))f, mctx, monitordestroy, (PetscErrorCode (*)(void))dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical));
89223ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
8923c0f0dcc3SMatthew G. Knepley   }
89247a8be351SBarry Smith   PetscCheck(dm->numbermonitors < MAXDMMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
8925c0f0dcc3SMatthew G. Knepley   dm->monitor[dm->numbermonitors]          = f;
8926c0f0dcc3SMatthew G. Knepley   dm->monitordestroy[dm->numbermonitors]   = monitordestroy;
8927835f2295SStefano Zampini   dm->monitorcontext[dm->numbermonitors++] = mctx;
89283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8929c0f0dcc3SMatthew G. Knepley }
8930c0f0dcc3SMatthew G. Knepley 
8931c0f0dcc3SMatthew G. Knepley /*@
8932bb7acecfSBarry Smith   DMMonitorCancel - Clears all the monitor functions for a `DM` object.
8933c0f0dcc3SMatthew G. Knepley 
893420f4b53cSBarry Smith   Logically Collective
8935c0f0dcc3SMatthew G. Knepley 
8936c0f0dcc3SMatthew G. Knepley   Input Parameter:
8937c0f0dcc3SMatthew G. Knepley . dm - the DM
8938c0f0dcc3SMatthew G. Knepley 
8939c0f0dcc3SMatthew G. Knepley   Options Database Key:
8940c0f0dcc3SMatthew G. Knepley . -dm_monitor_cancel - cancels all monitors that have been hardwired
8941bb7acecfSBarry Smith   into a code by calls to `DMonitorSet()`, but does not cancel those
8942c0f0dcc3SMatthew G. Knepley   set via the options database
8943c0f0dcc3SMatthew G. Knepley 
89449bdbcad8SBarry Smith   Level: intermediate
89459bdbcad8SBarry Smith 
8946bb7acecfSBarry Smith   Note:
8947bb7acecfSBarry Smith   There is no way to clear one specific monitor from a `DM` object.
8948c0f0dcc3SMatthew G. Knepley 
89491cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMMonitorSetFromOptions()`, `DMMonitor()`
8950c0f0dcc3SMatthew G. Knepley @*/
8951d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorCancel(DM dm)
8952d71ae5a4SJacob Faibussowitsch {
8953c0f0dcc3SMatthew G. Knepley   PetscInt m;
8954c0f0dcc3SMatthew G. Knepley 
8955c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8956c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8957c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
89589566063dSJacob Faibussowitsch     if (dm->monitordestroy[m]) PetscCall((*dm->monitordestroy[m])(&dm->monitorcontext[m]));
8959c0f0dcc3SMatthew G. Knepley   }
8960c0f0dcc3SMatthew G. Knepley   dm->numbermonitors = 0;
89613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8962c0f0dcc3SMatthew G. Knepley }
8963c0f0dcc3SMatthew G. Knepley 
8964c0f0dcc3SMatthew G. Knepley /*@C
8965c0f0dcc3SMatthew G. Knepley   DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
8966c0f0dcc3SMatthew G. Knepley 
896720f4b53cSBarry Smith   Collective
8968c0f0dcc3SMatthew G. Knepley 
8969c0f0dcc3SMatthew G. Knepley   Input Parameters:
8970bb7acecfSBarry Smith + dm           - `DM` object you wish to monitor
8971c0f0dcc3SMatthew G. Knepley . name         - the monitor type one is seeking
8972c0f0dcc3SMatthew G. Knepley . help         - message indicating what monitoring is done
8973c0f0dcc3SMatthew G. Knepley . manual       - manual page for the monitor
897449abdd8aSBarry Smith . monitor      - the monitor function, this must use a `PetscViewerFormat` as its context
8975bb7acecfSBarry 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
8976c0f0dcc3SMatthew G. Knepley 
8977c0f0dcc3SMatthew G. Knepley   Output Parameter:
8978c0f0dcc3SMatthew G. Knepley . flg - Flag set if the monitor was created
8979c0f0dcc3SMatthew G. Knepley 
8980c0f0dcc3SMatthew G. Knepley   Level: developer
8981c0f0dcc3SMatthew G. Knepley 
8982648c30bcSBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
8983db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
898460225df5SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
8985db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
8986c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
8987db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
8988bb7acecfSBarry Smith           `PetscOptionsFList()`, `PetscOptionsEList()`, `DMMonitor()`, `DMMonitorSet()`
8989c0f0dcc3SMatthew G. Knepley @*/
8990d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg)
8991d71ae5a4SJacob Faibussowitsch {
8992c0f0dcc3SMatthew G. Knepley   PetscViewer       viewer;
8993c0f0dcc3SMatthew G. Knepley   PetscViewerFormat format;
8994c0f0dcc3SMatthew G. Knepley 
8995c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8996c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8997648c30bcSBarry Smith   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)dm), ((PetscObject)dm)->options, ((PetscObject)dm)->prefix, name, &viewer, &format, flg));
8998c0f0dcc3SMatthew G. Knepley   if (*flg) {
8999c0f0dcc3SMatthew G. Knepley     PetscViewerAndFormat *vf;
9000c0f0dcc3SMatthew G. Knepley 
90019566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
9002648c30bcSBarry Smith     PetscCall(PetscViewerDestroy(&viewer));
90039566063dSJacob Faibussowitsch     if (monitorsetup) PetscCall((*monitorsetup)(dm, vf));
9004835f2295SStefano Zampini     PetscCall(DMMonitorSet(dm, monitor, vf, (PetscCtxDestroyFn *)PetscViewerAndFormatDestroy));
9005c0f0dcc3SMatthew G. Knepley   }
90063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9007c0f0dcc3SMatthew G. Knepley }
9008c0f0dcc3SMatthew G. Knepley 
9009c0f0dcc3SMatthew G. Knepley /*@
9010c0f0dcc3SMatthew G. Knepley   DMMonitor - runs the user provided monitor routines, if they exist
9011c0f0dcc3SMatthew G. Knepley 
901220f4b53cSBarry Smith   Collective
9013c0f0dcc3SMatthew G. Knepley 
90142fe279fdSBarry Smith   Input Parameter:
9015bb7acecfSBarry Smith . dm - The `DM`
9016c0f0dcc3SMatthew G. Knepley 
9017c0f0dcc3SMatthew G. Knepley   Level: developer
9018c0f0dcc3SMatthew G. Knepley 
901973ff1848SBarry Smith   Developer Note:
9020a4e35b19SJacob Faibussowitsch   Note should indicate when during the life of the `DM` the monitor is run. It appears to be
9021a4e35b19SJacob Faibussowitsch   related to the discretization process seems rather specialized since some `DM` have no
9022a4e35b19SJacob Faibussowitsch   concept of discretization.
9023bb7acecfSBarry Smith 
90241cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMMonitorSetFromOptions()`
9025c0f0dcc3SMatthew G. Knepley @*/
9026d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitor(DM dm)
9027d71ae5a4SJacob Faibussowitsch {
9028c0f0dcc3SMatthew G. Knepley   PetscInt m;
9029c0f0dcc3SMatthew G. Knepley 
9030c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
90313ba16761SJacob Faibussowitsch   if (!dm) PetscFunctionReturn(PETSC_SUCCESS);
9032c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
903348a46eb9SPierre Jolivet   for (m = 0; m < dm->numbermonitors; ++m) PetscCall((*dm->monitor[m])(dm, dm->monitorcontext[m]));
90343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9035c0f0dcc3SMatthew G. Knepley }
90362e4af2aeSMatthew G. Knepley 
90372e4af2aeSMatthew G. Knepley /*@
9038bb7acecfSBarry Smith   DMComputeError - Computes the error assuming the user has provided the exact solution functions
90392e4af2aeSMatthew G. Knepley 
904020f4b53cSBarry Smith   Collective
90412e4af2aeSMatthew G. Knepley 
90422e4af2aeSMatthew G. Knepley   Input Parameters:
9043bb7acecfSBarry Smith + dm  - The `DM`
90446b867d5aSJose E. Roman - sol - The solution vector
90452e4af2aeSMatthew G. Knepley 
90466b867d5aSJose E. Roman   Input/Output Parameter:
904720f4b53cSBarry Smith . errors - An array of length Nf, the number of fields, or `NULL` for no output; on output
90486b867d5aSJose E. Roman            contains the error in each field
90496b867d5aSJose E. Roman 
90506b867d5aSJose E. Roman   Output Parameter:
905120f4b53cSBarry Smith . errorVec - A vector to hold the cellwise error (may be `NULL`)
905220f4b53cSBarry Smith 
905320f4b53cSBarry Smith   Level: developer
90542e4af2aeSMatthew G. Knepley 
9055bb7acecfSBarry Smith   Note:
9056bb7acecfSBarry Smith   The exact solutions come from the `PetscDS` object, and the time comes from `DMGetOutputSequenceNumber()`.
90572e4af2aeSMatthew G. Knepley 
90581cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMGetRegionNumDS()`, `PetscDSGetExactSolution()`, `DMGetOutputSequenceNumber()`
90592e4af2aeSMatthew G. Knepley @*/
9060d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec)
9061d71ae5a4SJacob Faibussowitsch {
90622e4af2aeSMatthew G. Knepley   PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
90632e4af2aeSMatthew G. Knepley   void    **ctxs;
90642e4af2aeSMatthew G. Knepley   PetscReal time;
90652e4af2aeSMatthew G. Knepley   PetscInt  Nf, f, Nds, s;
90662e4af2aeSMatthew G. Knepley 
90672e4af2aeSMatthew G. Knepley   PetscFunctionBegin;
90689566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
90699566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(Nf, &exactSol, Nf, &ctxs));
90709566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
90712e4af2aeSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
90722e4af2aeSMatthew G. Knepley     PetscDS         ds;
90732e4af2aeSMatthew G. Knepley     DMLabel         label;
90742e4af2aeSMatthew G. Knepley     IS              fieldIS;
90752e4af2aeSMatthew G. Knepley     const PetscInt *fields;
90762e4af2aeSMatthew G. Knepley     PetscInt        dsNf;
90772e4af2aeSMatthew G. Knepley 
907807218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds, NULL));
90799566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
90809566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISGetIndices(fieldIS, &fields));
90812e4af2aeSMatthew G. Knepley     for (f = 0; f < dsNf; ++f) {
90822e4af2aeSMatthew G. Knepley       const PetscInt field = fields[f];
90839566063dSJacob Faibussowitsch       PetscCall(PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]));
90842e4af2aeSMatthew G. Knepley     }
90859566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISRestoreIndices(fieldIS, &fields));
90862e4af2aeSMatthew G. Knepley   }
9087ad540459SPierre 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);
90889566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
90899566063dSJacob Faibussowitsch   if (errors) PetscCall(DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors));
90902e4af2aeSMatthew G. Knepley   if (errorVec) {
90912e4af2aeSMatthew G. Knepley     DM             edm;
90922e4af2aeSMatthew G. Knepley     DMPolytopeType ct;
90932e4af2aeSMatthew G. Knepley     PetscBool      simplex;
90942e4af2aeSMatthew G. Knepley     PetscInt       dim, cStart, Nf;
90952e4af2aeSMatthew G. Knepley 
90969566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &edm));
90979566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(edm, &dim));
90989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
90999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cStart, &ct));
91002e4af2aeSMatthew G. Knepley     simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
91019566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
91022e4af2aeSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
91032e4af2aeSMatthew G. Knepley       PetscFE         fe, efe;
91042e4af2aeSMatthew G. Knepley       PetscQuadrature q;
91052e4af2aeSMatthew G. Knepley       const char     *name;
91062e4af2aeSMatthew G. Knepley 
91079566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe));
91089566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe));
91099566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)fe, &name));
91109566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)efe, name));
91119566063dSJacob Faibussowitsch       PetscCall(PetscFEGetQuadrature(fe, &q));
91129566063dSJacob Faibussowitsch       PetscCall(PetscFESetQuadrature(efe, q));
91139566063dSJacob Faibussowitsch       PetscCall(DMSetField(edm, f, NULL, (PetscObject)efe));
91149566063dSJacob Faibussowitsch       PetscCall(PetscFEDestroy(&efe));
91152e4af2aeSMatthew G. Knepley     }
91169566063dSJacob Faibussowitsch     PetscCall(DMCreateDS(edm));
91172e4af2aeSMatthew G. Knepley 
91189566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(edm, errorVec));
91199566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*errorVec, "Error"));
91209566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec));
91219566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&edm));
91222e4af2aeSMatthew G. Knepley   }
91239566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exactSol, ctxs));
91243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91252e4af2aeSMatthew G. Knepley }
91269a2a23afSMatthew G. Knepley 
91279a2a23afSMatthew G. Knepley /*@
9128bb7acecfSBarry Smith   DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this `DM`
91299a2a23afSMatthew G. Knepley 
913020f4b53cSBarry Smith   Not Collective
91319a2a23afSMatthew G. Knepley 
91329a2a23afSMatthew G. Knepley   Input Parameter:
9133bb7acecfSBarry Smith . dm - The `DM`
91349a2a23afSMatthew G. Knepley 
91359a2a23afSMatthew G. Knepley   Output Parameter:
9136a5b23f4aSJose E. Roman . numAux - The number of auxiliary data vectors
91379a2a23afSMatthew G. Knepley 
91389a2a23afSMatthew G. Knepley   Level: advanced
91399a2a23afSMatthew G. Knepley 
9140e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMClearAuxiliaryVec()`, `DMSetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMGetAuxiliaryVec()`
91419a2a23afSMatthew G. Knepley @*/
9142d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux)
9143d71ae5a4SJacob Faibussowitsch {
91449a2a23afSMatthew G. Knepley   PetscFunctionBegin;
91459a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91469566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetSize(dm->auxData, numAux));
91473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91489a2a23afSMatthew G. Knepley }
91499a2a23afSMatthew G. Knepley 
91509a2a23afSMatthew G. Knepley /*@
9151ac17215fSMatthew G. Knepley   DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value, and equation part
91529a2a23afSMatthew G. Knepley 
915320f4b53cSBarry Smith   Not Collective
91549a2a23afSMatthew G. Knepley 
91559a2a23afSMatthew G. Knepley   Input Parameters:
9156bb7acecfSBarry Smith + dm    - The `DM`
9157bb7acecfSBarry Smith . label - The `DMLabel`
9158ac17215fSMatthew G. Knepley . value - The label value indicating the region
9159ac17215fSMatthew G. Knepley - part  - The equation part, or 0 if unused
91609a2a23afSMatthew G. Knepley 
91619a2a23afSMatthew G. Knepley   Output Parameter:
9162bb7acecfSBarry Smith . aux - The `Vec` holding auxiliary field data
91639a2a23afSMatthew G. Knepley 
91649bdbcad8SBarry Smith   Level: advanced
91659bdbcad8SBarry Smith 
9166bb7acecfSBarry Smith   Note:
9167bb7acecfSBarry Smith   If no auxiliary vector is found for this (label, value), (NULL, 0, 0) is checked as well.
916804c51a94SMatthew G. Knepley 
9169e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMClearAuxiliaryVec()`, `DMSetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryLabels()`
91709a2a23afSMatthew G. Knepley @*/
9171d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec *aux)
9172d71ae5a4SJacob Faibussowitsch {
9173ac17215fSMatthew G. Knepley   PetscHashAuxKey key, wild = {NULL, 0, 0};
917404c51a94SMatthew G. Knepley   PetscBool       has;
91759a2a23afSMatthew G. Knepley 
91769a2a23afSMatthew G. Knepley   PetscFunctionBegin;
91779a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91789a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
91799a2a23afSMatthew G. Knepley   key.label = label;
91809a2a23afSMatthew G. Knepley   key.value = value;
9181ac17215fSMatthew G. Knepley   key.part  = part;
91829566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxHas(dm->auxData, key, &has));
91839566063dSJacob Faibussowitsch   if (has) PetscCall(PetscHMapAuxGet(dm->auxData, key, aux));
91849566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxGet(dm->auxData, wild, aux));
91853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91869a2a23afSMatthew G. Knepley }
91879a2a23afSMatthew G. Knepley 
91889a2a23afSMatthew G. Knepley /*@
9189bb7acecfSBarry Smith   DMSetAuxiliaryVec - Set an auxiliary vector for region specified by the given label and value, and equation part
91909a2a23afSMatthew G. Knepley 
919120f4b53cSBarry Smith   Not Collective because auxiliary vectors are not parallel
91929a2a23afSMatthew G. Knepley 
91939a2a23afSMatthew G. Knepley   Input Parameters:
9194bb7acecfSBarry Smith + dm    - The `DM`
9195bb7acecfSBarry Smith . label - The `DMLabel`
91969a2a23afSMatthew G. Knepley . value - The label value indicating the region
9197ac17215fSMatthew G. Knepley . part  - The equation part, or 0 if unused
9198bb7acecfSBarry Smith - aux   - The `Vec` holding auxiliary field data
91999a2a23afSMatthew G. Knepley 
92009a2a23afSMatthew G. Knepley   Level: advanced
92019a2a23afSMatthew G. Knepley 
9202e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMClearAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMCopyAuxiliaryVec()`
92039a2a23afSMatthew G. Knepley @*/
9204d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec aux)
9205d71ae5a4SJacob Faibussowitsch {
92069a2a23afSMatthew G. Knepley   Vec             old;
92079a2a23afSMatthew G. Knepley   PetscHashAuxKey key;
92089a2a23afSMatthew G. Knepley 
92099a2a23afSMatthew G. Knepley   PetscFunctionBegin;
92109a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
92119a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
92129a2a23afSMatthew G. Knepley   key.label = label;
92139a2a23afSMatthew G. Knepley   key.value = value;
9214ac17215fSMatthew G. Knepley   key.part  = part;
92159566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGet(dm->auxData, key, &old));
92169566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)aux));
92179566063dSJacob Faibussowitsch   if (!aux) PetscCall(PetscHMapAuxDel(dm->auxData, key));
92189566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxSet(dm->auxData, key, aux));
9219d705d0eaSStefano Zampini   PetscCall(VecDestroy(&old));
92203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
92219a2a23afSMatthew G. Knepley }
92229a2a23afSMatthew G. Knepley 
9223cc4c1da9SBarry Smith /*@
9224bb7acecfSBarry Smith   DMGetAuxiliaryLabels - Get the labels, values, and parts for all auxiliary vectors in this `DM`
92259a2a23afSMatthew G. Knepley 
922620f4b53cSBarry Smith   Not Collective
92279a2a23afSMatthew G. Knepley 
92289a2a23afSMatthew G. Knepley   Input Parameter:
9229bb7acecfSBarry Smith . dm - The `DM`
92309a2a23afSMatthew G. Knepley 
92319a2a23afSMatthew G. Knepley   Output Parameters:
9232bb7acecfSBarry Smith + labels - The `DMLabel`s for each `Vec`
9233bb7acecfSBarry Smith . values - The label values for each `Vec`
9234bb7acecfSBarry Smith - parts  - The equation parts for each `Vec`
92359a2a23afSMatthew G. Knepley 
92369bdbcad8SBarry Smith   Level: advanced
92379bdbcad8SBarry Smith 
9238bb7acecfSBarry Smith   Note:
9239bb7acecfSBarry Smith   The arrays passed in must be at least as large as `DMGetNumAuxiliaryVec()`.
92409a2a23afSMatthew G. Knepley 
9241e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMClearAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`, `DMCopyAuxiliaryVec()`
92429a2a23afSMatthew G. Knepley @*/
9243d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[], PetscInt parts[])
9244d71ae5a4SJacob Faibussowitsch {
92459a2a23afSMatthew G. Knepley   PetscHashAuxKey *keys;
92469a2a23afSMatthew G. Knepley   PetscInt         n, i, off = 0;
92479a2a23afSMatthew G. Knepley 
92489a2a23afSMatthew G. Knepley   PetscFunctionBegin;
92499a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
92504f572ea9SToby Isaac   PetscAssertPointer(labels, 2);
92514f572ea9SToby Isaac   PetscAssertPointer(values, 3);
92524f572ea9SToby Isaac   PetscAssertPointer(parts, 4);
92539566063dSJacob Faibussowitsch   PetscCall(DMGetNumAuxiliaryVec(dm, &n));
92549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &keys));
92559566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetKeys(dm->auxData, &off, keys));
92569371c9d4SSatish Balay   for (i = 0; i < n; ++i) {
92579371c9d4SSatish Balay     labels[i] = keys[i].label;
92589371c9d4SSatish Balay     values[i] = keys[i].value;
92599371c9d4SSatish Balay     parts[i]  = keys[i].part;
92609371c9d4SSatish Balay   }
92619566063dSJacob Faibussowitsch   PetscCall(PetscFree(keys));
92623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
92639a2a23afSMatthew G. Knepley }
92649a2a23afSMatthew G. Knepley 
92659a2a23afSMatthew G. Knepley /*@
9266bb7acecfSBarry Smith   DMCopyAuxiliaryVec - Copy the auxiliary vector data on a `DM` to a new `DM`
92679a2a23afSMatthew G. Knepley 
926820f4b53cSBarry Smith   Not Collective
92699a2a23afSMatthew G. Knepley 
92709a2a23afSMatthew G. Knepley   Input Parameter:
9271bb7acecfSBarry Smith . dm - The `DM`
92729a2a23afSMatthew G. Knepley 
92739a2a23afSMatthew G. Knepley   Output Parameter:
9274bb7acecfSBarry Smith . dmNew - The new `DM`, now with the same auxiliary data
92759a2a23afSMatthew G. Knepley 
92769a2a23afSMatthew G. Knepley   Level: advanced
92779a2a23afSMatthew G. Knepley 
9278bb7acecfSBarry Smith   Note:
9279bb7acecfSBarry Smith   This is a shallow copy of the auxiliary vectors
9280bb7acecfSBarry Smith 
9281e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMClearAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
92829a2a23afSMatthew G. Knepley @*/
9283d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew)
9284d71ae5a4SJacob Faibussowitsch {
92859a2a23afSMatthew G. Knepley   PetscFunctionBegin;
92869a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9287d705d0eaSStefano Zampini   PetscValidHeaderSpecific(dmNew, DM_CLASSID, 2);
9288d705d0eaSStefano Zampini   if (dm == dmNew) PetscFunctionReturn(PETSC_SUCCESS);
9289e4d5475eSStefano Zampini   PetscCall(DMClearAuxiliaryVec(dmNew));
9290e4d5475eSStefano Zampini 
9291e4d5475eSStefano Zampini   PetscCall(PetscHMapAuxDestroy(&dmNew->auxData));
92929566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData));
9293d705d0eaSStefano Zampini   {
9294d705d0eaSStefano Zampini     Vec     *auxData;
9295d705d0eaSStefano Zampini     PetscInt n, i, off = 0;
9296d705d0eaSStefano Zampini 
9297d705d0eaSStefano Zampini     PetscCall(PetscHMapAuxGetSize(dmNew->auxData, &n));
9298d705d0eaSStefano Zampini     PetscCall(PetscMalloc1(n, &auxData));
9299d705d0eaSStefano Zampini     PetscCall(PetscHMapAuxGetVals(dmNew->auxData, &off, auxData));
9300d705d0eaSStefano Zampini     for (i = 0; i < n; ++i) PetscCall(PetscObjectReference((PetscObject)auxData[i]));
9301d705d0eaSStefano Zampini     PetscCall(PetscFree(auxData));
9302e4d5475eSStefano Zampini   }
9303e4d5475eSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
9304e4d5475eSStefano Zampini }
9305e4d5475eSStefano Zampini 
9306e4d5475eSStefano Zampini /*@
9307e4d5475eSStefano Zampini   DMClearAuxiliaryVec - Destroys the auxiliary vector information and creates a new empty one
9308e4d5475eSStefano Zampini 
9309e4d5475eSStefano Zampini   Not Collective
9310e4d5475eSStefano Zampini 
9311e4d5475eSStefano Zampini   Input Parameter:
9312e4d5475eSStefano Zampini . dm - The `DM`
9313e4d5475eSStefano Zampini 
9314e4d5475eSStefano Zampini   Level: advanced
9315e4d5475eSStefano Zampini 
9316e4d5475eSStefano Zampini .seealso: [](ch_dmbase), `DM`, `DMCopyAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
9317e4d5475eSStefano Zampini @*/
9318e4d5475eSStefano Zampini PetscErrorCode DMClearAuxiliaryVec(DM dm)
9319e4d5475eSStefano Zampini {
9320e4d5475eSStefano Zampini   Vec     *auxData;
9321e4d5475eSStefano Zampini   PetscInt n, i, off = 0;
9322e4d5475eSStefano Zampini 
9323e4d5475eSStefano Zampini   PetscFunctionBegin;
9324e4d5475eSStefano Zampini   PetscCall(PetscHMapAuxGetSize(dm->auxData, &n));
9325d705d0eaSStefano Zampini   PetscCall(PetscMalloc1(n, &auxData));
9326e4d5475eSStefano Zampini   PetscCall(PetscHMapAuxGetVals(dm->auxData, &off, auxData));
9327d705d0eaSStefano Zampini   for (i = 0; i < n; ++i) PetscCall(VecDestroy(&auxData[i]));
9328d705d0eaSStefano Zampini   PetscCall(PetscFree(auxData));
9329e4d5475eSStefano Zampini   PetscCall(PetscHMapAuxDestroy(&dm->auxData));
9330e4d5475eSStefano Zampini   PetscCall(PetscHMapAuxCreate(&dm->auxData));
93313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
93329a2a23afSMatthew G. Knepley }
9333b5a892a1SMatthew G. Knepley 
9334cc4c1da9SBarry Smith /*@
9335bb7acecfSBarry Smith   DMPolytopeMatchOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9336b5a892a1SMatthew G. Knepley 
933720f4b53cSBarry Smith   Not Collective
9338b5a892a1SMatthew G. Knepley 
9339b5a892a1SMatthew G. Knepley   Input Parameters:
9340bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9341b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9342b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9343b5a892a1SMatthew G. Knepley 
9344b5a892a1SMatthew G. Knepley   Output Parameters:
9345bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9346b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9347b5a892a1SMatthew G. Knepley 
9348b5a892a1SMatthew G. Knepley   Level: advanced
9349b5a892a1SMatthew G. Knepley 
9350bb7acecfSBarry Smith   Note:
9351bb7acecfSBarry Smith   An arrangement is a face order combined with an orientation for each face
9352bb7acecfSBarry Smith 
935385036b15SMatthew G. Knepley   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangements(ct)`/2 to `DMPolytopeTypeGetNumArrangements(ct)`/2
9354bb7acecfSBarry Smith   that labels each arrangement (face ordering plus orientation for each face).
9355bb7acecfSBarry Smith 
9356bb7acecfSBarry Smith   See `DMPolytopeMatchVertexOrientation()` to find a new vertex orientation that takes the source vertex arrangement to the target vertex arrangement
9357bb7acecfSBarry Smith 
93581cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetVertexOrientation()`
9359b5a892a1SMatthew G. Knepley @*/
9360d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt, PetscBool *found)
9361d71ae5a4SJacob Faibussowitsch {
9362b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetConeSize(ct);
936385036b15SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangements(ct) / 2;
9364b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9365b5a892a1SMatthew G. Knepley 
9366b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
93679371c9d4SSatish Balay   if (!nO) {
93689371c9d4SSatish Balay     *ornt  = 0;
93699371c9d4SSatish Balay     *found = PETSC_TRUE;
93703ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
93719371c9d4SSatish Balay   }
9372b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
937385036b15SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o);
9374b5a892a1SMatthew G. Knepley 
93759371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
93769371c9d4SSatish Balay       if (sourceCone[arr[c * 2]] != targetCone[c]) break;
93779371c9d4SSatish Balay     if (c == cS) {
93789371c9d4SSatish Balay       *ornt = o;
93799371c9d4SSatish Balay       break;
93809371c9d4SSatish Balay     }
9381b5a892a1SMatthew G. Knepley   }
9382b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
93833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9384b5a892a1SMatthew G. Knepley }
9385b5a892a1SMatthew G. Knepley 
9386cc4c1da9SBarry Smith /*@
9387bb7acecfSBarry Smith   DMPolytopeGetOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9388b5a892a1SMatthew G. Knepley 
938920f4b53cSBarry Smith   Not Collective
9390b5a892a1SMatthew G. Knepley 
9391b5a892a1SMatthew G. Knepley   Input Parameters:
9392bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9393b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9394b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9395b5a892a1SMatthew G. Knepley 
93962fe279fdSBarry Smith   Output Parameter:
9397bb7acecfSBarry Smith . ornt - The orientation (transformation) which will take the source arrangement to the target arrangement
9398b5a892a1SMatthew G. Knepley 
9399b5a892a1SMatthew G. Knepley   Level: advanced
9400b5a892a1SMatthew G. Knepley 
9401bb7acecfSBarry Smith   Note:
9402bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchOrientation()` except it will generate an error if no suitable orientation can be found.
9403bb7acecfSBarry Smith 
940473ff1848SBarry Smith   Developer Note:
9405bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchOrientation()` and error if none is found
9406bb7acecfSBarry Smith 
94071cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeMatchOrientation()`, `DMPolytopeGetVertexOrientation()`, `DMPolytopeMatchVertexOrientation()`
9408b5a892a1SMatthew G. Knepley @*/
9409d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9410d71ae5a4SJacob Faibussowitsch {
9411b5a892a1SMatthew G. Knepley   PetscBool found;
9412b5a892a1SMatthew G. Knepley 
9413b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
94149566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchOrientation(ct, sourceCone, targetCone, ornt, &found));
94157a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
94163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9417b5a892a1SMatthew G. Knepley }
9418b5a892a1SMatthew G. Knepley 
9419cc4c1da9SBarry Smith /*@
9420bb7acecfSBarry Smith   DMPolytopeMatchVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9421b5a892a1SMatthew G. Knepley 
942220f4b53cSBarry Smith   Not Collective
9423b5a892a1SMatthew G. Knepley 
9424b5a892a1SMatthew G. Knepley   Input Parameters:
9425bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9426b5a892a1SMatthew G. Knepley . sourceVert - The source arrangement of vertices
9427b5a892a1SMatthew G. Knepley - targetVert - The target arrangement of vertices
9428b5a892a1SMatthew G. Knepley 
9429b5a892a1SMatthew G. Knepley   Output Parameters:
9430bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9431b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9432b5a892a1SMatthew G. Knepley 
9433b5a892a1SMatthew G. Knepley   Level: advanced
9434b5a892a1SMatthew G. Knepley 
943573ff1848SBarry Smith   Notes:
9436bb7acecfSBarry Smith   An arrangement is a vertex order
9437bb7acecfSBarry Smith 
943885036b15SMatthew G. Knepley   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangements(ct)`/2 to `DMPolytopeTypeGetNumArrangements(ct)`/2
9439bb7acecfSBarry Smith   that labels each arrangement (vertex ordering).
9440bb7acecfSBarry Smith 
9441bb7acecfSBarry Smith   See `DMPolytopeMatchOrientation()` to find a new face orientation that takes the source face arrangement to the target face arrangement
9442bb7acecfSBarry Smith 
944385036b15SMatthew G. Knepley .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchOrientation()`, `DMPolytopeTypeGetNumVertices()`, `DMPolytopeTypeGetVertexArrangement()`
9444b5a892a1SMatthew G. Knepley @*/
9445d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchVertexOrientation(DMPolytopeType ct, const PetscInt sourceVert[], const PetscInt targetVert[], PetscInt *ornt, PetscBool *found)
9446d71ae5a4SJacob Faibussowitsch {
9447b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetNumVertices(ct);
944885036b15SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangements(ct) / 2;
9449b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9450b5a892a1SMatthew G. Knepley 
9451b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
94529371c9d4SSatish Balay   if (!nO) {
94539371c9d4SSatish Balay     *ornt  = 0;
94549371c9d4SSatish Balay     *found = PETSC_TRUE;
94553ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
94569371c9d4SSatish Balay   }
9457b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
945885036b15SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetVertexArrangement(ct, o);
9459b5a892a1SMatthew G. Knepley 
94609371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
94619371c9d4SSatish Balay       if (sourceVert[arr[c]] != targetVert[c]) break;
94629371c9d4SSatish Balay     if (c == cS) {
94639371c9d4SSatish Balay       *ornt = o;
94649371c9d4SSatish Balay       break;
94659371c9d4SSatish Balay     }
9466b5a892a1SMatthew G. Knepley   }
9467b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
94683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9469b5a892a1SMatthew G. Knepley }
9470b5a892a1SMatthew G. Knepley 
9471cc4c1da9SBarry Smith /*@
9472bb7acecfSBarry Smith   DMPolytopeGetVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9473b5a892a1SMatthew G. Knepley 
947420f4b53cSBarry Smith   Not Collective
9475b5a892a1SMatthew G. Knepley 
9476b5a892a1SMatthew G. Knepley   Input Parameters:
9477bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9478b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of vertices
9479b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of vertices
9480b5a892a1SMatthew G. Knepley 
94812fe279fdSBarry Smith   Output Parameter:
9482bb7acecfSBarry Smith . ornt - The orientation (transformation) which will take the source arrangement to the target arrangement
9483b5a892a1SMatthew G. Knepley 
9484b5a892a1SMatthew G. Knepley   Level: advanced
9485b5a892a1SMatthew G. Knepley 
9486bb7acecfSBarry Smith   Note:
9487bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchVertexOrientation()` except it errors if not orientation is possible.
9488bb7acecfSBarry Smith 
948973ff1848SBarry Smith   Developer Note:
9490bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchVertexOrientation()` and error if none is found
9491bb7acecfSBarry Smith 
94921cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetOrientation()`
9493b5a892a1SMatthew G. Knepley @*/
9494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetVertexOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9495d71ae5a4SJacob Faibussowitsch {
9496b5a892a1SMatthew G. Knepley   PetscBool found;
9497b5a892a1SMatthew G. Knepley 
9498b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
94999566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchVertexOrientation(ct, sourceCone, targetCone, ornt, &found));
95007a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
95013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9502b5a892a1SMatthew G. Knepley }
9503012bc364SMatthew G. Knepley 
9504cc4c1da9SBarry Smith /*@
9505012bc364SMatthew G. Knepley   DMPolytopeInCellTest - Check whether a point lies inside the reference cell of given type
9506012bc364SMatthew G. Knepley 
950720f4b53cSBarry Smith   Not Collective
9508012bc364SMatthew G. Knepley 
9509012bc364SMatthew G. Knepley   Input Parameters:
9510bb7acecfSBarry Smith + ct    - The `DMPolytopeType`
9511012bc364SMatthew G. Knepley - point - Coordinates of the point
9512012bc364SMatthew G. Knepley 
95132fe279fdSBarry Smith   Output Parameter:
9514012bc364SMatthew G. Knepley . inside - Flag indicating whether the point is inside the reference cell of given type
9515012bc364SMatthew G. Knepley 
9516012bc364SMatthew G. Knepley   Level: advanced
9517012bc364SMatthew G. Knepley 
95181cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMLocatePoints()`
9519012bc364SMatthew G. Knepley @*/
9520d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeInCellTest(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
9521d71ae5a4SJacob Faibussowitsch {
9522012bc364SMatthew G. Knepley   PetscReal sum = 0.0;
9523012bc364SMatthew G. Knepley   PetscInt  d;
9524012bc364SMatthew G. Knepley 
9525012bc364SMatthew G. Knepley   PetscFunctionBegin;
9526012bc364SMatthew G. Knepley   *inside = PETSC_TRUE;
9527012bc364SMatthew G. Knepley   switch (ct) {
9528012bc364SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
9529012bc364SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
9530012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
95319371c9d4SSatish Balay       if (point[d] < -1.0) {
95329371c9d4SSatish Balay         *inside = PETSC_FALSE;
95339371c9d4SSatish Balay         break;
95349371c9d4SSatish Balay       }
9535012bc364SMatthew G. Knepley       sum += point[d];
9536012bc364SMatthew G. Knepley     }
95379371c9d4SSatish Balay     if (sum > PETSC_SMALL) {
95389371c9d4SSatish Balay       *inside = PETSC_FALSE;
95399371c9d4SSatish Balay       break;
95409371c9d4SSatish Balay     }
9541012bc364SMatthew G. Knepley     break;
9542012bc364SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
9543012bc364SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
9544012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
95459371c9d4SSatish Balay       if (PetscAbsReal(point[d]) > 1. + PETSC_SMALL) {
95469371c9d4SSatish Balay         *inside = PETSC_FALSE;
9547012bc364SMatthew G. Knepley         break;
95489371c9d4SSatish Balay       }
95499371c9d4SSatish Balay     break;
9550d71ae5a4SJacob Faibussowitsch   default:
9551d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
9552012bc364SMatthew G. Knepley   }
95533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9554012bc364SMatthew G. Knepley }
9555adc21957SMatthew G. Knepley 
9556adc21957SMatthew G. Knepley /*@
9557adc21957SMatthew G. Knepley   DMReorderSectionSetDefault - Set flag indicating whether the local section should be reordered by default
9558adc21957SMatthew G. Knepley 
9559adc21957SMatthew G. Knepley   Logically collective
9560adc21957SMatthew G. Knepley 
9561adc21957SMatthew G. Knepley   Input Parameters:
9562adc21957SMatthew G. Knepley + dm      - The DM
9563adc21957SMatthew G. Knepley - reorder - Flag for reordering
9564adc21957SMatthew G. Knepley 
9565adc21957SMatthew G. Knepley   Level: intermediate
9566adc21957SMatthew G. Knepley 
9567adc21957SMatthew G. Knepley .seealso: `DMReorderSectionGetDefault()`
9568adc21957SMatthew G. Knepley @*/
9569adc21957SMatthew G. Knepley PetscErrorCode DMReorderSectionSetDefault(DM dm, DMReorderDefaultFlag reorder)
9570adc21957SMatthew G. Knepley {
9571adc21957SMatthew G. Knepley   PetscFunctionBegin;
9572adc21957SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9573adc21957SMatthew G. Knepley   PetscTryMethod(dm, "DMReorderSectionSetDefault_C", (DM, DMReorderDefaultFlag), (dm, reorder));
9574adc21957SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
9575adc21957SMatthew G. Knepley }
9576adc21957SMatthew G. Knepley 
9577adc21957SMatthew G. Knepley /*@
9578adc21957SMatthew G. Knepley   DMReorderSectionGetDefault - Get flag indicating whether the local section should be reordered by default
9579adc21957SMatthew G. Knepley 
9580adc21957SMatthew G. Knepley   Not collective
9581adc21957SMatthew G. Knepley 
9582adc21957SMatthew G. Knepley   Input Parameter:
9583adc21957SMatthew G. Knepley . dm - The DM
9584adc21957SMatthew G. Knepley 
9585adc21957SMatthew G. Knepley   Output Parameter:
9586adc21957SMatthew G. Knepley . reorder - Flag for reordering
9587adc21957SMatthew G. Knepley 
9588adc21957SMatthew G. Knepley   Level: intermediate
9589adc21957SMatthew G. Knepley 
9590adc21957SMatthew G. Knepley .seealso: `DMReorderSetDefault()`
9591adc21957SMatthew G. Knepley @*/
9592adc21957SMatthew G. Knepley PetscErrorCode DMReorderSectionGetDefault(DM dm, DMReorderDefaultFlag *reorder)
9593adc21957SMatthew G. Knepley {
9594adc21957SMatthew G. Knepley   PetscFunctionBegin;
9595adc21957SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9596adc21957SMatthew G. Knepley   PetscAssertPointer(reorder, 2);
9597adc21957SMatthew G. Knepley   *reorder = DM_REORDER_DEFAULT_NOTSET;
9598adc21957SMatthew G. Knepley   PetscTryMethod(dm, "DMReorderSectionGetDefault_C", (DM, DMReorderDefaultFlag *), (dm, reorder));
9599adc21957SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
9600adc21957SMatthew G. Knepley }
9601adc21957SMatthew G. Knepley 
9602cc4c1da9SBarry Smith /*@
9603adc21957SMatthew G. Knepley   DMReorderSectionSetType - Set the type of local section reordering
9604adc21957SMatthew G. Knepley 
9605adc21957SMatthew G. Knepley   Logically collective
9606adc21957SMatthew G. Knepley 
9607adc21957SMatthew G. Knepley   Input Parameters:
9608adc21957SMatthew G. Knepley + dm      - The DM
9609adc21957SMatthew G. Knepley - reorder - The reordering method
9610adc21957SMatthew G. Knepley 
9611adc21957SMatthew G. Knepley   Level: intermediate
9612adc21957SMatthew G. Knepley 
9613adc21957SMatthew G. Knepley .seealso: `DMReorderSectionGetType()`, `DMReorderSectionSetDefault()`
9614adc21957SMatthew G. Knepley @*/
9615adc21957SMatthew G. Knepley PetscErrorCode DMReorderSectionSetType(DM dm, MatOrderingType reorder)
9616adc21957SMatthew G. Knepley {
9617adc21957SMatthew G. Knepley   PetscFunctionBegin;
9618adc21957SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9619adc21957SMatthew G. Knepley   PetscTryMethod(dm, "DMReorderSectionSetType_C", (DM, MatOrderingType), (dm, reorder));
9620adc21957SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
9621adc21957SMatthew G. Knepley }
9622adc21957SMatthew G. Knepley 
9623cc4c1da9SBarry Smith /*@
9624adc21957SMatthew G. Knepley   DMReorderSectionGetType - Get the reordering type for the local section
9625adc21957SMatthew G. Knepley 
9626adc21957SMatthew G. Knepley   Not collective
9627adc21957SMatthew G. Knepley 
9628adc21957SMatthew G. Knepley   Input Parameter:
9629adc21957SMatthew G. Knepley . dm - The DM
9630adc21957SMatthew G. Knepley 
9631adc21957SMatthew G. Knepley   Output Parameter:
9632adc21957SMatthew G. Knepley . reorder - The reordering method
9633adc21957SMatthew G. Knepley 
9634adc21957SMatthew G. Knepley   Level: intermediate
9635adc21957SMatthew G. Knepley 
9636adc21957SMatthew G. Knepley .seealso: `DMReorderSetDefault()`, `DMReorderSectionGetDefault()`
9637adc21957SMatthew G. Knepley @*/
9638adc21957SMatthew G. Knepley PetscErrorCode DMReorderSectionGetType(DM dm, MatOrderingType *reorder)
9639adc21957SMatthew G. Knepley {
9640adc21957SMatthew G. Knepley   PetscFunctionBegin;
9641adc21957SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9642adc21957SMatthew G. Knepley   PetscAssertPointer(reorder, 2);
9643adc21957SMatthew G. Knepley   *reorder = NULL;
9644adc21957SMatthew G. Knepley   PetscTryMethod(dm, "DMReorderSectionGetType_C", (DM, MatOrderingType *), (dm, reorder));
9645adc21957SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
9646adc21957SMatthew G. Knepley }
9647