xref: /petsc/src/dm/interface/dm.c (revision fa1e479a18002119fe707bd096ac0ebb681731fe)
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 
15cea3dcb8SSatish Balay #if !defined(PETSC_HAVE_WINDOWS_COMPILERS)
16cea3dcb8SSatish Balay   #include <petsc/private/valgrind/memcheck.h>
1700d952a4SJed Brown #endif
1800d952a4SJed Brown 
19732e2eb9SMatthew G Knepley PetscClassId DM_CLASSID;
20d67d17b1SMatthew G. Knepley PetscClassId DMLABEL_CLASSID;
21708be2fdSJed 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;
2267a56275SMatthew G Knepley 
23ea78f98cSLisandro Dalcin const char *const DMBoundaryTypes[]          = {"NONE", "GHOSTED", "MIRROR", "PERIODIC", "TWIST", "DMBoundaryType", "DM_BOUNDARY_", NULL};
24d1b3049bSMatthew 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};
250e762ea3SJed Brown const char *const DMBlockingTypes[]          = {"TOPOLOGICAL_POINT", "FIELD_NODE", "DMBlockingType", "DM_BLOCKING_", NULL};
26476787b7SMatthew G. Knepley const char *const DMPolytopeTypes[] =
27476787b7SMatthew 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",
28476787b7SMatthew G. Knepley    "unknown", "unknown_cell", "unknown_face",   "invalid",  "DMPolytopeType", "DM_POLYTOPE_", NULL};
292cbb9b06SVaclav Hapla const char *const DMCopyLabelsModes[] = {"replace", "keep", "fail", "DMCopyLabelsMode", "DM_COPY_LABELS_", NULL};
3060c22052SBarry Smith 
31a4121054SBarry Smith /*@
32bb7acecfSBarry Smith   DMCreate - Creates an empty `DM` object. `DM`s are the abstract objects in PETSc that mediate between meshes and discretizations and the
33bb7acecfSBarry Smith   algebraic solvers, time integrators, and optimization algorithms.
34a4121054SBarry Smith 
35d083f849SBarry Smith   Collective
36a4121054SBarry Smith 
37a4121054SBarry Smith   Input Parameter:
38bb7acecfSBarry Smith . comm - The communicator for the `DM` object
39a4121054SBarry Smith 
40a4121054SBarry Smith   Output Parameter:
41bb7acecfSBarry Smith . dm - The `DM` object
42a4121054SBarry Smith 
43a4121054SBarry Smith   Level: beginner
44a4121054SBarry Smith 
45bb7acecfSBarry Smith   Notes:
46bb7acecfSBarry Smith   See `DMType` for a brief summary of available `DM`.
47bb7acecfSBarry Smith 
48bb7acecfSBarry Smith   The type must then be set with `DMSetType()`. If you never call `DMSetType()` it will generate an
49bb7acecfSBarry Smith   error when you try to use the dm.
50bb7acecfSBarry Smith 
511cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetType()`, `DMType`, `DMDACreate()`, `DMDA`, `DMSLICED`, `DMCOMPOSITE`, `DMPLEX`, `DMMOAB`, `DMNETWORK`
52a4121054SBarry Smith @*/
53d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreate(MPI_Comm comm, DM *dm)
54d71ae5a4SJacob Faibussowitsch {
55a4121054SBarry Smith   DM      v;
56e5e52638SMatthew G. Knepley   PetscDS ds;
57a4121054SBarry Smith 
58a4121054SBarry Smith   PetscFunctionBegin;
594f572ea9SToby Isaac   PetscAssertPointer(dm, 2);
600298fd71SBarry Smith   *dm = NULL;
619566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
62a4121054SBarry Smith 
639566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView));
64e7c4fc90SDmitry Karpeev 
6562e5d2d2SJDBetteridge   ((PetscObject)v)->non_cyclic_references = &DMCountNonCyclicReferences;
6662e5d2d2SJDBetteridge 
6749be4549SMatthew G. Knepley   v->setupcalled          = PETSC_FALSE;
6849be4549SMatthew G. Knepley   v->setfromoptionscalled = PETSC_FALSE;
690298fd71SBarry Smith   v->ltogmap              = NULL;
70a4ea9b21SRichard Tran Mills   v->bind_below           = 0;
711411c6eeSJed Brown   v->bs                   = 1;
72171400e9SBarry Smith   v->coloringtype         = IS_COLORING_GLOBAL;
739566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &v->sf));
749566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(comm, &v->sectionSF));
75c58f1c22SToby Isaac   v->labels                    = NULL;
7634aa8a36SMatthew G. Knepley   v->adjacency[0]              = PETSC_FALSE;
7734aa8a36SMatthew G. Knepley   v->adjacency[1]              = PETSC_TRUE;
78c58f1c22SToby Isaac   v->depthLabel                = NULL;
79ba2698f1SMatthew G. Knepley   v->celltypeLabel             = NULL;
801bb6d2a8SBarry Smith   v->localSection              = NULL;
811bb6d2a8SBarry Smith   v->globalSection             = NULL;
823b8ba7d1SJed Brown   v->defaultConstraint.section = NULL;
833b8ba7d1SJed Brown   v->defaultConstraint.mat     = NULL;
8479769bd5SJed Brown   v->defaultConstraint.bias    = NULL;
856858538eSMatthew G. Knepley   v->coordinates[0].dim        = PETSC_DEFAULT;
866858538eSMatthew G. Knepley   v->coordinates[1].dim        = PETSC_DEFAULT;
876858538eSMatthew G. Knepley   v->sparseLocalize            = PETSC_TRUE;
8896173672SStefano Zampini   v->dim                       = PETSC_DETERMINE;
89435a35e8SMatthew G Knepley   {
90435a35e8SMatthew G Knepley     PetscInt i;
91435a35e8SMatthew G Knepley     for (i = 0; i < 10; ++i) {
920298fd71SBarry Smith       v->nullspaceConstructors[i]     = NULL;
93f9d4088aSMatthew G. Knepley       v->nearnullspaceConstructors[i] = NULL;
94435a35e8SMatthew G Knepley     }
95435a35e8SMatthew G Knepley   }
969566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
9707218a29SMatthew G. Knepley   PetscCall(DMSetRegionDS(v, NULL, NULL, ds, NULL));
989566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&ds));
999566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxCreate(&v->auxData));
10014f150ffSMatthew G. Knepley   v->dmBC              = NULL;
101a8fb8f29SToby Isaac   v->coarseMesh        = NULL;
102f4d763aaSMatthew G. Knepley   v->outputSequenceNum = -1;
103cdb7a50dSMatthew G. Knepley   v->outputSequenceVal = 0.0;
1049566063dSJacob Faibussowitsch   PetscCall(DMSetVecType(v, VECSTANDARD));
1059566063dSJacob Faibussowitsch   PetscCall(DMSetMatType(v, MATAIJ));
1064a7a4c06SLawrence Mitchell 
1071411c6eeSJed Brown   *dm = v;
1083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
109a4121054SBarry Smith }
110a4121054SBarry Smith 
11138221697SMatthew G. Knepley /*@
112bb7acecfSBarry Smith   DMClone - Creates a `DM` object with the same topology as the original.
11338221697SMatthew G. Knepley 
114d083f849SBarry Smith   Collective
11538221697SMatthew G. Knepley 
11638221697SMatthew G. Knepley   Input Parameter:
117bb7acecfSBarry Smith . dm - The original `DM` object
11838221697SMatthew G. Knepley 
11938221697SMatthew G. Knepley   Output Parameter:
120bb7acecfSBarry Smith . newdm - The new `DM` object
12138221697SMatthew G. Knepley 
12238221697SMatthew G. Knepley   Level: beginner
12338221697SMatthew G. Knepley 
1241cb8cacdSPatrick Sanan   Notes:
125bb7acecfSBarry Smith   For some `DM` implementations this is a shallow clone, the result of which may share (reference counted) information with its parent. For example,
126bb7acecfSBarry Smith   `DMClone()` applied to a `DMPLEX` object will result in a new `DMPLEX` that shares the topology with the original `DMPLEX`. It does not
127bb7acecfSBarry Smith   share the `PetscSection` of the original `DM`.
1281bb6d2a8SBarry Smith 
129bb7acecfSBarry Smith   The clone is considered set up if the original has been set up.
13089706ed2SPatrick Sanan 
131bb7acecfSBarry Smith   Use `DMConvert()` for a general way to create new `DM` from a given `DM`
132bb7acecfSBarry Smith 
13360225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMSetType()`, `DMSetLocalSection()`, `DMSetGlobalSection()`, `DMPLEX`, `DMConvert()`
13438221697SMatthew G. Knepley @*/
135d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClone(DM dm, DM *newdm)
136d71ae5a4SJacob Faibussowitsch {
13738221697SMatthew G. Knepley   PetscSF  sf;
13838221697SMatthew G. Knepley   Vec      coords;
13938221697SMatthew G. Knepley   void    *ctx;
1406858538eSMatthew G. Knepley   PetscInt dim, cdim, i;
14138221697SMatthew G. Knepley 
14238221697SMatthew G. Knepley   PetscFunctionBegin;
14338221697SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1444f572ea9SToby Isaac   PetscAssertPointer(newdm, 2);
1459566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), newdm));
1469566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dm, *newdm, PETSC_COPY_VALUES, PETSC_TRUE, DM_COPY_LABELS_FAIL));
147ddf8437dSMatthew G. Knepley   (*newdm)->leveldown     = dm->leveldown;
148ddf8437dSMatthew G. Knepley   (*newdm)->levelup       = dm->levelup;
149c8a6034eSMark   (*newdm)->prealloc_only = dm->prealloc_only;
150fc214432SJed Brown   (*newdm)->prealloc_skip = dm->prealloc_skip;
1519566063dSJacob Faibussowitsch   PetscCall(PetscFree((*newdm)->vectype));
1529566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*newdm)->vectype));
1539566063dSJacob Faibussowitsch   PetscCall(PetscFree((*newdm)->mattype));
1549566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*newdm)->mattype));
1559566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1569566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*newdm, dim));
157dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, clone, newdm);
1583f22bcbcSToby Isaac   (*newdm)->setupcalled = dm->setupcalled;
1599566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
1609566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(*newdm, sf));
1619566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dm, &ctx));
1629566063dSJacob Faibussowitsch   PetscCall(DMSetApplicationContext(*newdm, ctx));
1636858538eSMatthew G. Knepley   for (i = 0; i < 2; ++i) {
1646858538eSMatthew G. Knepley     if (dm->coordinates[i].dm) {
165be4c1c3eSMatthew G. Knepley       DM           ncdm;
166be4c1c3eSMatthew G. Knepley       PetscSection cs;
1675a0206caSToby Isaac       PetscInt     pEnd = -1, pEndMax = -1;
168be4c1c3eSMatthew G. Knepley 
1696858538eSMatthew G. Knepley       PetscCall(DMGetLocalSection(dm->coordinates[i].dm, &cs));
1709566063dSJacob Faibussowitsch       if (cs) PetscCall(PetscSectionGetChart(cs, NULL, &pEnd));
171712fec58SPierre Jolivet       PetscCall(MPIU_Allreduce(&pEnd, &pEndMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1725a0206caSToby Isaac       if (pEndMax >= 0) {
1736858538eSMatthew G. Knepley         PetscCall(DMClone(dm->coordinates[i].dm, &ncdm));
1746858538eSMatthew G. Knepley         PetscCall(DMCopyDisc(dm->coordinates[i].dm, ncdm));
1759566063dSJacob Faibussowitsch         PetscCall(DMSetLocalSection(ncdm, cs));
1766858538eSMatthew G. Knepley         if (i) PetscCall(DMSetCellCoordinateDM(*newdm, ncdm));
1776858538eSMatthew G. Knepley         else PetscCall(DMSetCoordinateDM(*newdm, ncdm));
1789566063dSJacob Faibussowitsch         PetscCall(DMDestroy(&ncdm));
179be4c1c3eSMatthew G. Knepley       }
180be4c1c3eSMatthew G. Knepley     }
1816858538eSMatthew G. Knepley   }
1829566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1839566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*newdm, cdim));
1849566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coords));
18538221697SMatthew G. Knepley   if (coords) {
1869566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(*newdm, coords));
18738221697SMatthew G. Knepley   } else {
1889566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinates(dm, &coords));
1899566063dSJacob Faibussowitsch     if (coords) PetscCall(DMSetCoordinates(*newdm, coords));
19038221697SMatthew G. Knepley   }
1916858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &coords));
1926858538eSMatthew G. Knepley   if (coords) {
1936858538eSMatthew G. Knepley     PetscCall(DMSetCellCoordinatesLocal(*newdm, coords));
1946858538eSMatthew G. Knepley   } else {
1956858538eSMatthew G. Knepley     PetscCall(DMGetCellCoordinates(dm, &coords));
1966858538eSMatthew G. Knepley     if (coords) PetscCall(DMSetCellCoordinates(*newdm, coords));
1976858538eSMatthew G. Knepley   }
19890b157c4SStefano Zampini   {
1994fb89dddSMatthew G. Knepley     const PetscReal *maxCell, *Lstart, *L;
2006858538eSMatthew G. Knepley 
2014fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
2024fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(*newdm, maxCell, Lstart, L));
203c6b900c6SMatthew G. Knepley   }
20434aa8a36SMatthew G. Knepley   {
20534aa8a36SMatthew G. Knepley     PetscBool useCone, useClosure;
20634aa8a36SMatthew G. Knepley 
2079566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, PETSC_DEFAULT, &useCone, &useClosure));
2089566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(*newdm, PETSC_DEFAULT, useCone, useClosure));
20934aa8a36SMatthew G. Knepley   }
2103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21138221697SMatthew G. Knepley }
21238221697SMatthew G. Knepley 
2139a42bb27SBarry Smith /*@C
214bb7acecfSBarry Smith   DMSetVecType - Sets the type of vector created with `DMCreateLocalVector()` and `DMCreateGlobalVector()`
2159a42bb27SBarry Smith 
21620f4b53cSBarry Smith   Logically Collective
2179a42bb27SBarry Smith 
218147403d9SBarry Smith   Input Parameters:
21932546409SMatthew G. Knepley + dm    - initial distributed array
220bb7acecfSBarry Smith - ctype - the vector type, for example `VECSTANDARD`, `VECCUDA`, or `VECVIENNACL`
2219a42bb27SBarry Smith 
22220f4b53cSBarry Smith   Options Database Key:
223147403d9SBarry Smith . -dm_vec_type ctype - the type of vector to create
2249a42bb27SBarry Smith 
2259a42bb27SBarry Smith   Level: intermediate
2269a42bb27SBarry Smith 
22760225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMDestroy()`, `DMDAInterpolationType`, `VecType`, `DMGetVecType()`, `DMSetMatType()`, `DMGetMatType()`,
228bb7acecfSBarry Smith           `VECSTANDARD`, `VECCUDA`, `VECVIENNACL`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`
2299a42bb27SBarry Smith @*/
23032546409SMatthew G. Knepley PetscErrorCode DMSetVecType(DM dm, VecType ctype)
231d71ae5a4SJacob Faibussowitsch {
23232546409SMatthew G. Knepley   char *tmp;
23332546409SMatthew G. Knepley 
2349a42bb27SBarry Smith   PetscFunctionBegin;
23532546409SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23632546409SMatthew G. Knepley   PetscAssertPointer(ctype, 2);
23732546409SMatthew G. Knepley   tmp = (char *)dm->vectype;
23832546409SMatthew G. Knepley   PetscCall(PetscStrallocpy(ctype, (char **)&dm->vectype));
23932546409SMatthew G. Knepley   PetscCall(PetscFree(tmp));
2403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2419a42bb27SBarry Smith }
2429a42bb27SBarry Smith 
243c0dedaeaSBarry Smith /*@C
244bb7acecfSBarry Smith   DMGetVecType - Gets the type of vector created with `DMCreateLocalVector()` and `DMCreateGlobalVector()`
245c0dedaeaSBarry Smith 
24620f4b53cSBarry Smith   Logically Collective
247c0dedaeaSBarry Smith 
248c0dedaeaSBarry Smith   Input Parameter:
249c0dedaeaSBarry Smith . da - initial distributed array
250c0dedaeaSBarry Smith 
251c0dedaeaSBarry Smith   Output Parameter:
252c0dedaeaSBarry Smith . ctype - the vector type
253c0dedaeaSBarry Smith 
254c0dedaeaSBarry Smith   Level: intermediate
255c0dedaeaSBarry Smith 
25660225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMDestroy()`, `DMDAInterpolationType`, `VecType`, `DMSetMatType()`, `DMGetMatType()`, `DMSetVecType()`
257c0dedaeaSBarry Smith @*/
258d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetVecType(DM da, VecType *ctype)
259d71ae5a4SJacob Faibussowitsch {
260c0dedaeaSBarry Smith   PetscFunctionBegin;
261c0dedaeaSBarry Smith   PetscValidHeaderSpecific(da, DM_CLASSID, 1);
262c0dedaeaSBarry Smith   *ctype = da->vectype;
2633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
264c0dedaeaSBarry Smith }
265c0dedaeaSBarry Smith 
2665f1ad066SMatthew G Knepley /*@
267bb7acecfSBarry Smith   VecGetDM - Gets the `DM` defining the data layout of the vector
2685f1ad066SMatthew G Knepley 
26920f4b53cSBarry Smith   Not Collective
2705f1ad066SMatthew G Knepley 
2715f1ad066SMatthew G Knepley   Input Parameter:
272bb7acecfSBarry Smith . v - The `Vec`
2735f1ad066SMatthew G Knepley 
2745f1ad066SMatthew G Knepley   Output Parameter:
275bb7acecfSBarry Smith . dm - The `DM`
2765f1ad066SMatthew G Knepley 
2775f1ad066SMatthew G Knepley   Level: intermediate
2785f1ad066SMatthew G Knepley 
279bb7acecfSBarry Smith   Note:
280bb7acecfSBarry Smith   A `Vec` may not have a `DM` associated with it.
281bb7acecfSBarry Smith 
2821cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecSetDM()`, `DMGetLocalVector()`, `DMGetGlobalVector()`, `DMSetVecType()`
2835f1ad066SMatthew G Knepley @*/
284d71ae5a4SJacob Faibussowitsch PetscErrorCode VecGetDM(Vec v, DM *dm)
285d71ae5a4SJacob Faibussowitsch {
2865f1ad066SMatthew G Knepley   PetscFunctionBegin;
2875f1ad066SMatthew G Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
2884f572ea9SToby Isaac   PetscAssertPointer(dm, 2);
2899566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)v, "__PETSc_dm", (PetscObject *)dm));
2903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2915f1ad066SMatthew G Knepley }
2925f1ad066SMatthew G Knepley 
2935f1ad066SMatthew G Knepley /*@
294bb7acecfSBarry Smith   VecSetDM - Sets the `DM` defining the data layout of the vector.
2955f1ad066SMatthew G Knepley 
29620f4b53cSBarry Smith   Not Collective
2975f1ad066SMatthew G Knepley 
2985f1ad066SMatthew G Knepley   Input Parameters:
299bb7acecfSBarry Smith + v  - The `Vec`
300bb7acecfSBarry Smith - dm - The `DM`
3015f1ad066SMatthew G Knepley 
30220f4b53cSBarry Smith   Level: developer
30320f4b53cSBarry Smith 
304bb7acecfSBarry Smith   Note:
305bb7acecfSBarry Smith   This is rarely used, generally one uses `DMGetLocalVector()` or  `DMGetGlobalVector()` to create a vector associated with a given `DM`
306d9805387SMatthew G. Knepley 
307bb7acecfSBarry 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.
308bb7acecfSBarry Smith 
3091cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecGetDM()`, `DMGetLocalVector()`, `DMGetGlobalVector()`, `DMSetVecType()`
3105f1ad066SMatthew G Knepley @*/
311d71ae5a4SJacob Faibussowitsch PetscErrorCode VecSetDM(Vec v, DM dm)
312d71ae5a4SJacob Faibussowitsch {
3135f1ad066SMatthew G Knepley   PetscFunctionBegin;
3145f1ad066SMatthew G Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 1);
315d7f50e27SLisandro Dalcin   if (dm) PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
3169566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)v, "__PETSc_dm", (PetscObject)dm));
3173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3185f1ad066SMatthew G Knepley }
3195f1ad066SMatthew G Knepley 
320521d9a4cSLisandro Dalcin /*@C
321bb7acecfSBarry Smith   DMSetISColoringType - Sets the type of coloring, `IS_COLORING_GLOBAL` or `IS_COLORING_LOCAL` that is created by the `DM`
3228f1509bcSBarry Smith 
32320f4b53cSBarry Smith   Logically Collective
3248f1509bcSBarry Smith 
3258f1509bcSBarry Smith   Input Parameters:
326bb7acecfSBarry Smith + dm    - the `DM` context
3278f1509bcSBarry Smith - ctype - the matrix type
3288f1509bcSBarry Smith 
32920f4b53cSBarry Smith   Options Database Key:
3308f1509bcSBarry Smith . -dm_is_coloring_type - global or local
3318f1509bcSBarry Smith 
3328f1509bcSBarry Smith   Level: intermediate
3338f1509bcSBarry Smith 
3341cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMGetMatType()`,
335bb7acecfSBarry Smith           `DMGetISColoringType()`, `ISColoringType`, `IS_COLORING_GLOBAL`, `IS_COLORING_LOCAL`
3368f1509bcSBarry Smith @*/
337d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetISColoringType(DM dm, ISColoringType ctype)
338d71ae5a4SJacob Faibussowitsch {
3398f1509bcSBarry Smith   PetscFunctionBegin;
3408f1509bcSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3418f1509bcSBarry Smith   dm->coloringtype = ctype;
3423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3438f1509bcSBarry Smith }
3448f1509bcSBarry Smith 
3458f1509bcSBarry Smith /*@C
346bb7acecfSBarry Smith   DMGetISColoringType - Gets the type of coloring, `IS_COLORING_GLOBAL` or `IS_COLORING_LOCAL` that is created by the `DM`
347521d9a4cSLisandro Dalcin 
34820f4b53cSBarry Smith   Logically Collective
349521d9a4cSLisandro Dalcin 
350521d9a4cSLisandro Dalcin   Input Parameter:
351bb7acecfSBarry Smith . dm - the `DM` context
3528f1509bcSBarry Smith 
3538f1509bcSBarry Smith   Output Parameter:
3548f1509bcSBarry Smith . ctype - the matrix type
3558f1509bcSBarry Smith 
35620f4b53cSBarry Smith   Options Database Key:
3578f1509bcSBarry Smith . -dm_is_coloring_type - global or local
3588f1509bcSBarry Smith 
3598f1509bcSBarry Smith   Level: intermediate
3608f1509bcSBarry Smith 
3611cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMGetMatType()`,
36242747ad1SJacob Faibussowitsch           `ISColoringType`, `IS_COLORING_GLOBAL`, `IS_COLORING_LOCAL`
3638f1509bcSBarry Smith @*/
364d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetISColoringType(DM dm, ISColoringType *ctype)
365d71ae5a4SJacob Faibussowitsch {
3668f1509bcSBarry Smith   PetscFunctionBegin;
3678f1509bcSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3688f1509bcSBarry Smith   *ctype = dm->coloringtype;
3693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3708f1509bcSBarry Smith }
3718f1509bcSBarry Smith 
3728f1509bcSBarry Smith /*@C
373bb7acecfSBarry Smith   DMSetMatType - Sets the type of matrix created with `DMCreateMatrix()`
3748f1509bcSBarry Smith 
37520f4b53cSBarry Smith   Logically Collective
3768f1509bcSBarry Smith 
3778f1509bcSBarry Smith   Input Parameters:
378bb7acecfSBarry Smith + dm    - the `DM` context
379bb7acecfSBarry Smith - ctype - the matrix type, for example `MATMPIAIJ`
380521d9a4cSLisandro Dalcin 
38120f4b53cSBarry Smith   Options Database Key:
382bb7acecfSBarry Smith . -dm_mat_type ctype - the type of the matrix to create, for example mpiaij
383521d9a4cSLisandro Dalcin 
384521d9a4cSLisandro Dalcin   Level: intermediate
385521d9a4cSLisandro Dalcin 
38642747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `MatType`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `DMGetMatType()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
387521d9a4cSLisandro Dalcin @*/
388d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatType(DM dm, MatType ctype)
389d71ae5a4SJacob Faibussowitsch {
39032546409SMatthew G. Knepley   char *tmp;
39132546409SMatthew G. Knepley 
392521d9a4cSLisandro Dalcin   PetscFunctionBegin;
393521d9a4cSLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39432546409SMatthew G. Knepley   PetscAssertPointer(ctype, 2);
39532546409SMatthew G. Knepley   tmp = (char *)dm->mattype;
3969566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(ctype, (char **)&dm->mattype));
39732546409SMatthew G. Knepley   PetscCall(PetscFree(tmp));
3983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
399521d9a4cSLisandro Dalcin }
400521d9a4cSLisandro Dalcin 
401c0dedaeaSBarry Smith /*@C
40220f4b53cSBarry Smith   DMGetMatType - Gets the type of matrix that would be created with `DMCreateMatrix()`
403c0dedaeaSBarry Smith 
40420f4b53cSBarry Smith   Logically Collective
405c0dedaeaSBarry Smith 
406c0dedaeaSBarry Smith   Input Parameter:
407bb7acecfSBarry Smith . dm - the `DM` context
408c0dedaeaSBarry Smith 
409c0dedaeaSBarry Smith   Output Parameter:
410c0dedaeaSBarry Smith . ctype - the matrix type
411c0dedaeaSBarry Smith 
412c0dedaeaSBarry Smith   Level: intermediate
413c0dedaeaSBarry Smith 
41442747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixPreallocateOnly()`, `MatType`, `DMSetMatType()`
415c0dedaeaSBarry Smith @*/
416d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetMatType(DM dm, MatType *ctype)
417d71ae5a4SJacob Faibussowitsch {
418c0dedaeaSBarry Smith   PetscFunctionBegin;
419c0dedaeaSBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
420c0dedaeaSBarry Smith   *ctype = dm->mattype;
4213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
422c0dedaeaSBarry Smith }
423c0dedaeaSBarry Smith 
424c688c046SMatthew G Knepley /*@
425bb7acecfSBarry Smith   MatGetDM - Gets the `DM` defining the data layout of the matrix
426c688c046SMatthew G Knepley 
42720f4b53cSBarry Smith   Not Collective
428c688c046SMatthew G Knepley 
429c688c046SMatthew G Knepley   Input Parameter:
430bb7acecfSBarry Smith . A - The `Mat`
431c688c046SMatthew G Knepley 
432c688c046SMatthew G Knepley   Output Parameter:
433bb7acecfSBarry Smith . dm - The `DM`
434c688c046SMatthew G Knepley 
435c688c046SMatthew G Knepley   Level: intermediate
436c688c046SMatthew G Knepley 
437bb7acecfSBarry Smith   Note:
438bb7acecfSBarry Smith   A matrix may not have a `DM` associated with it
439bb7acecfSBarry Smith 
44060225df5SJacob Faibussowitsch   Developer Notes:
441bb7acecfSBarry Smith   Since the `Mat` class doesn't know about the `DM` class the `DM` object is associated with the `Mat` through a `PetscObjectCompose()` operation
4428f1509bcSBarry Smith 
4431cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatSetDM()`, `DMCreateMatrix()`, `DMSetMatType()`
444c688c046SMatthew G Knepley @*/
445d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetDM(Mat A, DM *dm)
446d71ae5a4SJacob Faibussowitsch {
447c688c046SMatthew G Knepley   PetscFunctionBegin;
448c688c046SMatthew G Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4494f572ea9SToby Isaac   PetscAssertPointer(dm, 2);
4509566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_dm", (PetscObject *)dm));
4513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
452c688c046SMatthew G Knepley }
453c688c046SMatthew G Knepley 
454c688c046SMatthew G Knepley /*@
455bb7acecfSBarry Smith   MatSetDM - Sets the `DM` defining the data layout of the matrix
456c688c046SMatthew G Knepley 
45720f4b53cSBarry Smith   Not Collective
458c688c046SMatthew G Knepley 
459c688c046SMatthew G Knepley   Input Parameters:
46020f4b53cSBarry Smith + A  - The `Mat`
46120f4b53cSBarry Smith - dm - The `DM`
462c688c046SMatthew G Knepley 
463bb7acecfSBarry Smith   Level: developer
464c688c046SMatthew G Knepley 
465bb7acecfSBarry Smith   Note:
466bb7acecfSBarry Smith   This is rarely used in practice, rather `DMCreateMatrix()` is used to create a matrix associated with a particular `DM`
467bb7acecfSBarry Smith 
46860225df5SJacob Faibussowitsch   Developer Notes:
469bb7acecfSBarry Smith   Since the `Mat` class doesn't know about the `DM` class the `DM` object is associated with
470bb7acecfSBarry Smith   the `Mat` through a `PetscObjectCompose()` operation
4718f1509bcSBarry Smith 
4721cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatGetDM()`, `DMCreateMatrix()`, `DMSetMatType()`
473c688c046SMatthew G Knepley @*/
474d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetDM(Mat A, DM dm)
475d71ae5a4SJacob Faibussowitsch {
476c688c046SMatthew G Knepley   PetscFunctionBegin;
477c688c046SMatthew G Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4788865f1eaSKarl Rupp   if (dm) PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
4799566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "__PETSc_dm", (PetscObject)dm));
4803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
481c688c046SMatthew G Knepley }
482c688c046SMatthew G Knepley 
4839a42bb27SBarry Smith /*@C
484bb7acecfSBarry Smith   DMSetOptionsPrefix - Sets the prefix prepended to all option names when searching through the options database
4859a42bb27SBarry Smith 
48620f4b53cSBarry Smith   Logically Collective
4879a42bb27SBarry Smith 
488d8d19677SJose E. Roman   Input Parameters:
48960225df5SJacob Faibussowitsch + dm     - the `DM` context
490bb7acecfSBarry Smith - prefix - the prefix to prepend
4919a42bb27SBarry Smith 
49220f4b53cSBarry Smith   Level: advanced
49320f4b53cSBarry Smith 
49420f4b53cSBarry Smith   Note:
4959a42bb27SBarry Smith   A hyphen (-) must NOT be given at the beginning of the prefix name.
4969a42bb27SBarry Smith   The first character of all runtime options is AUTOMATICALLY the hyphen.
4979a42bb27SBarry Smith 
4981cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscObjectSetOptionsPrefix()`, `DMSetFromOptions()`
4999a42bb27SBarry Smith @*/
500d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOptionsPrefix(DM dm, const char prefix[])
501d71ae5a4SJacob Faibussowitsch {
5029a42bb27SBarry Smith   PetscFunctionBegin;
5039a42bb27SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5049566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
5051baa6e33SBarry Smith   if (dm->sf) PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm->sf, prefix));
5061baa6e33SBarry Smith   if (dm->sectionSF) PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm->sectionSF, prefix));
5073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5089a42bb27SBarry Smith }
5099a42bb27SBarry Smith 
51031697293SDave May /*@C
511da81f932SPierre Jolivet   DMAppendOptionsPrefix - Appends an additional string to an already existing prefix used for searching for
512bb7acecfSBarry Smith   `DM` options in the options database.
51331697293SDave May 
51420f4b53cSBarry Smith   Logically Collective
51531697293SDave May 
51631697293SDave May   Input Parameters:
517bb7acecfSBarry Smith + dm     - the `DM` context
518bb7acecfSBarry Smith - prefix - the string to append to the current prefix
51931697293SDave May 
52020f4b53cSBarry Smith   Level: advanced
52120f4b53cSBarry Smith 
52220f4b53cSBarry Smith   Note:
523bb7acecfSBarry 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.
52431697293SDave May   A hyphen (-) must NOT be given at the beginning of the prefix name.
52531697293SDave May   The first character of all runtime options is AUTOMATICALLY the hyphen.
52631697293SDave May 
5271cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetOptionsPrefix()`, `DMGetOptionsPrefix()`, `PetscObjectAppendOptionsPrefix()`, `DMSetFromOptions()`
52831697293SDave May @*/
529d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAppendOptionsPrefix(DM dm, const char prefix[])
530d71ae5a4SJacob Faibussowitsch {
53131697293SDave May   PetscFunctionBegin;
53231697293SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5339566063dSJacob Faibussowitsch   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, prefix));
5343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53531697293SDave May }
53631697293SDave May 
53731697293SDave May /*@C
53831697293SDave May   DMGetOptionsPrefix - Gets the prefix used for searching for all
539bb7acecfSBarry Smith   DM options in the options database.
54031697293SDave May 
54131697293SDave May   Not Collective
54231697293SDave May 
5432fe279fdSBarry Smith   Input Parameter:
544bb7acecfSBarry Smith . dm - the `DM` context
54531697293SDave May 
5462fe279fdSBarry Smith   Output Parameter:
54731697293SDave May . prefix - pointer to the prefix string used is returned
54831697293SDave May 
54931697293SDave May   Level: advanced
55031697293SDave May 
55160225df5SJacob Faibussowitsch   Fortran Notes:
55220f4b53cSBarry Smith   Pass in a string 'prefix' of
55320f4b53cSBarry Smith   sufficient length to hold the prefix.
55420f4b53cSBarry Smith 
5551cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetOptionsPrefix()`, `DMAppendOptionsPrefix()`, `DMSetFromOptions()`
55631697293SDave May @*/
557d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOptionsPrefix(DM dm, const char *prefix[])
558d71ae5a4SJacob Faibussowitsch {
55931697293SDave May   PetscFunctionBegin;
56031697293SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5619566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, prefix));
5623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56331697293SDave May }
56431697293SDave May 
56562e5d2d2SJDBetteridge static PetscErrorCode DMCountNonCyclicReferences_Internal(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct)
566d71ae5a4SJacob Faibussowitsch {
5676eb26441SStefano Zampini   PetscInt refct = ((PetscObject)dm)->refct;
56888bdff64SToby Isaac 
56988bdff64SToby Isaac   PetscFunctionBegin;
570aab5bcd8SJed Brown   *ncrefct = 0;
57188bdff64SToby Isaac   if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) {
57288bdff64SToby Isaac     refct--;
57388bdff64SToby Isaac     if (recurseCoarse) {
57488bdff64SToby Isaac       PetscInt coarseCount;
57588bdff64SToby Isaac 
57662e5d2d2SJDBetteridge       PetscCall(DMCountNonCyclicReferences_Internal(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE, &coarseCount));
57788bdff64SToby Isaac       refct += coarseCount;
57888bdff64SToby Isaac     }
57988bdff64SToby Isaac   }
58088bdff64SToby Isaac   if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) {
58188bdff64SToby Isaac     refct--;
58288bdff64SToby Isaac     if (recurseFine) {
58388bdff64SToby Isaac       PetscInt fineCount;
58488bdff64SToby Isaac 
58562e5d2d2SJDBetteridge       PetscCall(DMCountNonCyclicReferences_Internal(dm->fineMesh, PETSC_FALSE, PETSC_TRUE, &fineCount));
58688bdff64SToby Isaac       refct += fineCount;
58788bdff64SToby Isaac     }
58888bdff64SToby Isaac   }
58988bdff64SToby Isaac   *ncrefct = refct;
5903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59188bdff64SToby Isaac }
59288bdff64SToby Isaac 
59362e5d2d2SJDBetteridge /* Generic wrapper for DMCountNonCyclicReferences_Internal() */
59462e5d2d2SJDBetteridge PetscErrorCode DMCountNonCyclicReferences(PetscObject dm, PetscInt *ncrefct)
59562e5d2d2SJDBetteridge {
59662e5d2d2SJDBetteridge   PetscFunctionBegin;
59762e5d2d2SJDBetteridge   PetscCall(DMCountNonCyclicReferences_Internal((DM)dm, PETSC_TRUE, PETSC_TRUE, ncrefct));
5983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59962e5d2d2SJDBetteridge }
60062e5d2d2SJDBetteridge 
601d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroyLabelLinkList_Internal(DM dm)
602d71ae5a4SJacob Faibussowitsch {
6035d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
604354557abSToby Isaac 
605354557abSToby Isaac   PetscFunctionBegin;
606354557abSToby Isaac   /* destroy the labels */
607354557abSToby Isaac   while (next) {
608354557abSToby Isaac     DMLabelLink tmp = next->next;
609354557abSToby Isaac 
6105d80c0bfSVaclav Hapla     if (next->label == dm->depthLabel) dm->depthLabel = NULL;
611ba2698f1SMatthew G. Knepley     if (next->label == dm->celltypeLabel) dm->celltypeLabel = NULL;
6129566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&next->label));
6139566063dSJacob Faibussowitsch     PetscCall(PetscFree(next));
614354557abSToby Isaac     next = tmp;
615354557abSToby Isaac   }
6165d80c0bfSVaclav Hapla   dm->labels = NULL;
6173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
618354557abSToby Isaac }
619354557abSToby Isaac 
62066976f2fSJacob Faibussowitsch static PetscErrorCode DMDestroyCoordinates_Private(DMCoordinates *c)
621d71ae5a4SJacob Faibussowitsch {
6226858538eSMatthew G. Knepley   PetscFunctionBegin;
6236858538eSMatthew G. Knepley   c->dim = PETSC_DEFAULT;
6246858538eSMatthew G. Knepley   PetscCall(DMDestroy(&c->dm));
6256858538eSMatthew G. Knepley   PetscCall(VecDestroy(&c->x));
6266858538eSMatthew G. Knepley   PetscCall(VecDestroy(&c->xl));
6276858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&c->field));
6283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6296858538eSMatthew G. Knepley }
6306858538eSMatthew G. Knepley 
6311fb7b255SJunchao Zhang /*@C
632bb7acecfSBarry Smith   DMDestroy - Destroys a `DM`.
63347c6ae99SBarry Smith 
63420f4b53cSBarry Smith   Collective
63547c6ae99SBarry Smith 
63647c6ae99SBarry Smith   Input Parameter:
637bb7acecfSBarry Smith . dm - the `DM` object to destroy
63847c6ae99SBarry Smith 
63947c6ae99SBarry Smith   Level: developer
64047c6ae99SBarry Smith 
6411cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMType`, `DMSetType()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
64247c6ae99SBarry Smith @*/
643d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy(DM *dm)
644d71ae5a4SJacob Faibussowitsch {
6456eb26441SStefano Zampini   PetscInt cnt;
64647c6ae99SBarry Smith 
64747c6ae99SBarry Smith   PetscFunctionBegin;
6483ba16761SJacob Faibussowitsch   if (!*dm) PetscFunctionReturn(PETSC_SUCCESS);
6496bf464f9SBarry Smith   PetscValidHeaderSpecific((*dm), DM_CLASSID, 1);
65087e657c6SBarry Smith 
65188bdff64SToby Isaac   /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */
65262e5d2d2SJDBetteridge   PetscCall(DMCountNonCyclicReferences_Internal(*dm, PETSC_TRUE, PETSC_TRUE, &cnt));
65388bdff64SToby Isaac   --((PetscObject)(*dm))->refct;
6549371c9d4SSatish Balay   if (--cnt > 0) {
6559371c9d4SSatish Balay     *dm = NULL;
6563ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6579371c9d4SSatish Balay   }
6583ba16761SJacob Faibussowitsch   if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(PETSC_SUCCESS);
6596bf464f9SBarry Smith   ((PetscObject)(*dm))->refct = 0;
6606eb26441SStefano Zampini 
6619566063dSJacob Faibussowitsch   PetscCall(DMClearGlobalVectors(*dm));
6629566063dSJacob Faibussowitsch   PetscCall(DMClearLocalVectors(*dm));
663974ca4ecSStefano Zampini   PetscCall(DMClearNamedGlobalVectors(*dm));
664974ca4ecSStefano Zampini   PetscCall(DMClearNamedLocalVectors(*dm));
6652348bcf4SPeter Brune 
666b17ce1afSJed Brown   /* Destroy the list of hooks */
667c833c3b5SJed Brown   {
668c833c3b5SJed Brown     DMCoarsenHookLink link, next;
669b17ce1afSJed Brown     for (link = (*dm)->coarsenhook; link; link = next) {
670b17ce1afSJed Brown       next = link->next;
6719566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
672b17ce1afSJed Brown     }
6730298fd71SBarry Smith     (*dm)->coarsenhook = NULL;
674c833c3b5SJed Brown   }
675c833c3b5SJed Brown   {
676c833c3b5SJed Brown     DMRefineHookLink link, next;
677c833c3b5SJed Brown     for (link = (*dm)->refinehook; link; link = next) {
678c833c3b5SJed Brown       next = link->next;
6799566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
680c833c3b5SJed Brown     }
6810298fd71SBarry Smith     (*dm)->refinehook = NULL;
682c833c3b5SJed Brown   }
683be081cd6SPeter Brune   {
684be081cd6SPeter Brune     DMSubDomainHookLink link, next;
685be081cd6SPeter Brune     for (link = (*dm)->subdomainhook; link; link = next) {
686be081cd6SPeter Brune       next = link->next;
6879566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
688be081cd6SPeter Brune     }
6890298fd71SBarry Smith     (*dm)->subdomainhook = NULL;
690be081cd6SPeter Brune   }
691baf369e7SPeter Brune   {
692baf369e7SPeter Brune     DMGlobalToLocalHookLink link, next;
693baf369e7SPeter Brune     for (link = (*dm)->gtolhook; link; link = next) {
694baf369e7SPeter Brune       next = link->next;
6959566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
696baf369e7SPeter Brune     }
6970298fd71SBarry Smith     (*dm)->gtolhook = NULL;
698baf369e7SPeter Brune   }
699d4d07f1eSToby Isaac   {
700d4d07f1eSToby Isaac     DMLocalToGlobalHookLink link, next;
701d4d07f1eSToby Isaac     for (link = (*dm)->ltoghook; link; link = next) {
702d4d07f1eSToby Isaac       next = link->next;
7039566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
704d4d07f1eSToby Isaac     }
705d4d07f1eSToby Isaac     (*dm)->ltoghook = NULL;
706d4d07f1eSToby Isaac   }
707aa1993deSMatthew G Knepley   /* Destroy the work arrays */
708aa1993deSMatthew G Knepley   {
709aa1993deSMatthew G Knepley     DMWorkLink link, next;
710936381afSPierre Jolivet     PetscCheck(!(*dm)->workout, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Work array still checked out %p %p", (void *)(*dm)->workout, (void *)(*dm)->workout->mem);
711aa1993deSMatthew G Knepley     for (link = (*dm)->workin; link; link = next) {
712aa1993deSMatthew G Knepley       next = link->next;
7139566063dSJacob Faibussowitsch       PetscCall(PetscFree(link->mem));
7149566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
715aa1993deSMatthew G Knepley     }
7160298fd71SBarry Smith     (*dm)->workin = NULL;
717aa1993deSMatthew G Knepley   }
718c58f1c22SToby Isaac   /* destroy the labels */
7199566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(*dm));
720f4cdcedcSVaclav Hapla   /* destroy the fields */
7219566063dSJacob Faibussowitsch   PetscCall(DMClearFields(*dm));
722f4cdcedcSVaclav Hapla   /* destroy the boundaries */
723e6f8dbb6SToby Isaac   {
724e6f8dbb6SToby Isaac     DMBoundary next = (*dm)->boundary;
725e6f8dbb6SToby Isaac     while (next) {
726e6f8dbb6SToby Isaac       DMBoundary b = next;
727e6f8dbb6SToby Isaac 
728e6f8dbb6SToby Isaac       next = b->next;
7299566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
730e6f8dbb6SToby Isaac     }
731e6f8dbb6SToby Isaac   }
732b17ce1afSJed Brown 
7339566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmksp));
7349566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmsnes));
7359566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&(*dm)->dmts));
73652536dc3SBarry Smith 
73748a46eb9SPierre Jolivet   if ((*dm)->ctx && (*dm)->ctxdestroy) PetscCall((*(*dm)->ctxdestroy)(&(*dm)->ctx));
7389566063dSJacob Faibussowitsch   PetscCall(MatFDColoringDestroy(&(*dm)->fd));
7399566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap));
7409566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->vectype));
7419566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->mattype));
74288ed4aceSMatthew G Knepley 
7439566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->localSection));
7449566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->globalSection));
7459566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&(*dm)->map));
7469566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&(*dm)->defaultConstraint.section));
7479566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&(*dm)->defaultConstraint.mat));
7489566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&(*dm)->sf));
7499566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&(*dm)->sectionSF));
75048a46eb9SPierre Jolivet   if ((*dm)->sfNatural) PetscCall(PetscSFDestroy(&(*dm)->sfNatural));
7519566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)(*dm)->sfMigration));
7529a2a23afSMatthew G. Knepley   {
7539a2a23afSMatthew G. Knepley     Vec     *auxData;
7549a2a23afSMatthew G. Knepley     PetscInt n, i, off = 0;
7559a2a23afSMatthew G. Knepley 
7569566063dSJacob Faibussowitsch     PetscCall(PetscHMapAuxGetSize((*dm)->auxData, &n));
7579566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n, &auxData));
7589566063dSJacob Faibussowitsch     PetscCall(PetscHMapAuxGetVals((*dm)->auxData, &off, auxData));
7599566063dSJacob Faibussowitsch     for (i = 0; i < n; ++i) PetscCall(VecDestroy(&auxData[i]));
7609566063dSJacob Faibussowitsch     PetscCall(PetscFree(auxData));
7619566063dSJacob Faibussowitsch     PetscCall(PetscHMapAuxDestroy(&(*dm)->auxData));
7629a2a23afSMatthew G. Knepley   }
76348a46eb9SPierre Jolivet   if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) PetscCall(DMSetFineDM((*dm)->coarseMesh, NULL));
7646eb26441SStefano Zampini 
7659566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->coarseMesh));
76648a46eb9SPierre Jolivet   if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) PetscCall(DMSetCoarseDM((*dm)->fineMesh, NULL));
7679566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->fineMesh));
7684fb89dddSMatthew G. Knepley   PetscCall(PetscFree((*dm)->Lstart));
7699566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->L));
7709566063dSJacob Faibussowitsch   PetscCall(PetscFree((*dm)->maxCell));
7716858538eSMatthew G. Knepley   PetscCall(DMDestroyCoordinates_Private(&(*dm)->coordinates[0]));
7726858538eSMatthew G. Knepley   PetscCall(DMDestroyCoordinates_Private(&(*dm)->coordinates[1]));
7739566063dSJacob Faibussowitsch   if ((*dm)->transformDestroy) PetscCall((*(*dm)->transformDestroy)(*dm, (*dm)->transformCtx));
7749566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->transformDM));
7759566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&(*dm)->transform));
7766725e60dSJed Brown   PetscCall(VecScatterDestroy(&(*dm)->periodic.affine_to_local));
7776725e60dSJed Brown   PetscCall(VecDestroy(&(*dm)->periodic.affine));
7786636e97aSMatthew G Knepley 
7799566063dSJacob Faibussowitsch   PetscCall(DMClearDS(*dm));
7809566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&(*dm)->dmBC));
781e04113cfSBarry Smith   /* if memory was published with SAWs then destroy it */
7829566063dSJacob Faibussowitsch   PetscCall(PetscObjectSAWsViewOff((PetscObject)*dm));
783732e2eb9SMatthew G Knepley 
784213acdd3SPierre Jolivet   PetscTryTypeMethod(*dm, destroy);
7859566063dSJacob Faibussowitsch   PetscCall(DMMonitorCancel(*dm));
786d2b2dc1eSMatthew G. Knepley   PetscCall(DMCeedDestroy(&(*dm)->dmceed));
787f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
7889566063dSJacob Faibussowitsch   PetscCallCEED(CeedElemRestrictionDestroy(&(*dm)->ceedERestrict));
7899566063dSJacob Faibussowitsch   PetscCallCEED(CeedDestroy(&(*dm)->ceed));
790f918ec44SMatthew G. Knepley #endif
791435a35e8SMatthew G Knepley   /* We do not destroy (*dm)->data here so that we can reference count backend objects */
7929566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(dm));
7933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79447c6ae99SBarry Smith }
79547c6ae99SBarry Smith 
796d7bf68aeSBarry Smith /*@
797bb7acecfSBarry Smith   DMSetUp - sets up the data structures inside a `DM` object
798d7bf68aeSBarry Smith 
79920f4b53cSBarry Smith   Collective
800d7bf68aeSBarry Smith 
801d7bf68aeSBarry Smith   Input Parameter:
802bb7acecfSBarry Smith . dm - the `DM` object to setup
803d7bf68aeSBarry Smith 
804bb7acecfSBarry Smith   Level: intermediate
805d7bf68aeSBarry Smith 
806bb7acecfSBarry Smith   Note:
807bb7acecfSBarry Smith   This is usually called after various parameter setting operations and `DMSetFromOptions()` are called on the `DM`
808bb7acecfSBarry Smith 
8091cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreate()`, `DMSetType()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
810d7bf68aeSBarry Smith @*/
811d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp(DM dm)
812d71ae5a4SJacob Faibussowitsch {
813d7bf68aeSBarry Smith   PetscFunctionBegin;
814171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8153ba16761SJacob Faibussowitsch   if (dm->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
816dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, setup);
8178387afaaSJed Brown   dm->setupcalled = PETSC_TRUE;
8183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
819d7bf68aeSBarry Smith }
820d7bf68aeSBarry Smith 
821d7bf68aeSBarry Smith /*@
822bb7acecfSBarry Smith   DMSetFromOptions - sets parameters in a `DM` from the options database
823d7bf68aeSBarry Smith 
82420f4b53cSBarry Smith   Collective
825d7bf68aeSBarry Smith 
826d7bf68aeSBarry Smith   Input Parameter:
827bb7acecfSBarry Smith . dm - the `DM` object to set options for
828d7bf68aeSBarry Smith 
82920f4b53cSBarry Smith   Options Database Keys:
830bb7acecfSBarry Smith + -dm_preallocate_only                               - Only preallocate the matrix for `DMCreateMatrix()` and `DMCreateMassMatrix()`, but do not fill it with zeros
831bb7acecfSBarry Smith . -dm_vec_type <type>                                - type of vector to create inside `DM`
832bb7acecfSBarry Smith . -dm_mat_type <type>                                - type of matrix to create inside `DM`
833a4ea9b21SRichard Tran Mills . -dm_is_coloring_type                               - <global or local>
83420f4b53cSBarry Smith . -dm_bind_below <n>                                 - bind (force execution on CPU) for `Vec` and `Mat` objects with local size (number of vector entries or matrix rows) below n; currently only supported for `DMDA`
83520f4b53cSBarry Smith . -dm_plex_filename <str>                            - File containing a mesh
8369318fe57SMatthew G. Knepley . -dm_plex_boundary_filename <str>                   - File containing a mesh boundary
837cd7e8a5eSksagiyam . -dm_plex_name <str>                                - Name of the mesh in the file
8385dca41c3SJed Brown . -dm_plex_shape <shape>                             - The domain shape, such as `BOX`, `SPHERE`, etc.
8399318fe57SMatthew G. Knepley . -dm_plex_cell <ct>                                 - Cell shape
8409318fe57SMatthew G. Knepley . -dm_plex_reference_cell_domain <bool>              - Use a reference cell domain
8419318fe57SMatthew G. Knepley . -dm_plex_dim <dim>                                 - Set the topological dimension
842bb7acecfSBarry Smith . -dm_plex_simplex <bool>                            - `PETSC_TRUE` for simplex elements, `PETSC_FALSE` for tensor elements
843bb7acecfSBarry Smith . -dm_plex_interpolate <bool>                        - `PETSC_TRUE` turns on topological interpolation (creating edges and faces)
8449318fe57SMatthew G. Knepley . -dm_plex_scale <sc>                                - Scale factor for mesh coordinates
8459318fe57SMatthew G. Knepley . -dm_plex_box_faces <m,n,p>                         - Number of faces along each dimension
8469318fe57SMatthew G. Knepley . -dm_plex_box_lower <x,y,z>                         - Specify lower-left-bottom coordinates for the box
8479318fe57SMatthew G. Knepley . -dm_plex_box_upper <x,y,z>                         - Specify upper-right-top coordinates for the box
848bb7acecfSBarry Smith . -dm_plex_box_bd <bx,by,bz>                         - Specify the `DMBoundaryType` for each direction
8499318fe57SMatthew G. Knepley . -dm_plex_sphere_radius <r>                         - The sphere radius
8509318fe57SMatthew G. Knepley . -dm_plex_ball_radius <r>                           - Radius of the ball
8519318fe57SMatthew G. Knepley . -dm_plex_cylinder_bd <bz>                          - Boundary type in the z direction
8529318fe57SMatthew G. Knepley . -dm_plex_cylinder_num_wedges <n>                   - Number of wedges around the cylinder
853bdf63967SMatthew G. Knepley . -dm_plex_reorder <order>                           - Reorder the mesh using the specified algorithm
8549318fe57SMatthew G. Knepley . -dm_refine_pre <n>                                 - The number of refinements before distribution
8559318fe57SMatthew G. Knepley . -dm_refine_uniform_pre <bool>                      - Flag for uniform refinement before distribution
8569318fe57SMatthew G. Knepley . -dm_refine_volume_limit_pre <v>                    - The maximum cell volume after refinement before distribution
8579318fe57SMatthew G. Knepley . -dm_refine <n>                                     - The number of refinements after distribution
858bdf63967SMatthew G. Knepley . -dm_extrude <l>                                    - Activate extrusion and specify the number of layers to extrude
859d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_thickness <t>           - The total thickness of extruded layers
860d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_use_tensor <bool>       - Use tensor cells when extruding
861d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_symmetric <bool>        - Extrude layers symmetrically about the surface
862d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_normal <n0,...,nd>      - Specify the extrusion direction
863d410b0cfSMatthew G. Knepley . -dm_plex_transform_extrude_thicknesses <t0,...,tl> - Specify thickness of each layer
864909dfd52SMatthew G. Knepley . -dm_plex_create_fv_ghost_cells                     - Flag to create finite volume ghost cells on the boundary
865909dfd52SMatthew G. Knepley . -dm_plex_fv_ghost_cells_label <name>               - Label name for ghost cells boundary
8669318fe57SMatthew G. Knepley . -dm_distribute <bool>                              - Flag to redistribute a mesh among processes
8679318fe57SMatthew G. Knepley . -dm_distribute_overlap <n>                         - The size of the overlap halo
8689318fe57SMatthew G. Knepley . -dm_plex_adj_cone <bool>                           - Set adjacency direction
86920f4b53cSBarry Smith . -dm_plex_adj_closure <bool>                        - Set adjacency size
870d2b2dc1eSMatthew G. Knepley . -dm_plex_use_ceed <bool>                           - Use LibCEED as the FEM backend
87120f4b53cSBarry Smith . -dm_plex_check_symmetry                            - Check that the adjacency information in the mesh is symmetric - `DMPlexCheckSymmetry()`
872bb7acecfSBarry Smith . -dm_plex_check_skeleton                            - Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes) - `DMPlexCheckSkeleton()`
873bb7acecfSBarry 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()`
874bb7acecfSBarry Smith . -dm_plex_check_geometry                            - Check that cells have positive volume - `DMPlexCheckGeometry()`
875bb7acecfSBarry Smith . -dm_plex_check_pointsf                             - Check some necessary conditions for `PointSF` - `DMPlexCheckPointSF()`
876bb7acecfSBarry Smith . -dm_plex_check_interface_cones                     - Check points on inter-partition interfaces have conforming order of cone points - `DMPlexCheckInterfaceCones()`
877384a6580SVaclav Hapla - -dm_plex_check_all                                 - Perform all the checks above
878d7bf68aeSBarry Smith 
87995eb5ee5SVaclav Hapla   Level: intermediate
88095eb5ee5SVaclav Hapla 
8811cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
882bb7acecfSBarry Smith          `DMPlexCheckSymmetry()`, `DMPlexCheckSkeleton()`, `DMPlexCheckFaces()`, `DMPlexCheckGeometry()`, `DMPlexCheckPointSF()`, `DMPlexCheckInterfaceCones()`,
88360225df5SJacob Faibussowitsch          `DMSetOptionsPrefix()`, `DMType`, `DMPLEX`, `DMDA`
884d7bf68aeSBarry Smith @*/
885d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions(DM dm)
886d71ae5a4SJacob Faibussowitsch {
8877781c08eSBarry Smith   char      typeName[256];
888ca266f36SBarry Smith   PetscBool flg;
889d7bf68aeSBarry Smith 
890d7bf68aeSBarry Smith   PetscFunctionBegin;
891171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89249be4549SMatthew G. Knepley   dm->setfromoptionscalled = PETSC_TRUE;
8939566063dSJacob Faibussowitsch   if (dm->sf) PetscCall(PetscSFSetFromOptions(dm->sf));
8949566063dSJacob Faibussowitsch   if (dm->sectionSF) PetscCall(PetscSFSetFromOptions(dm->sectionSF));
895dd4c3f67SMatthew G. Knepley   if (dm->coordinates[0].dm) PetscCall(DMSetFromOptions(dm->coordinates[0].dm));
896d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)dm);
8979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_preallocate_only", "only preallocate matrix, but do not set column indices", "DMSetMatrixPreallocateOnly", dm->prealloc_only, &dm->prealloc_only, NULL));
8989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_vec_type", "Vector type used for created vectors", "DMSetVecType", VecList, dm->vectype, typeName, 256, &flg));
8991baa6e33SBarry Smith   if (flg) PetscCall(DMSetVecType(dm, typeName));
9009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_mat_type", "Matrix type used for created matrices", "DMSetMatType", MatList, dm->mattype ? dm->mattype : typeName, typeName, sizeof(typeName), &flg));
9011baa6e33SBarry Smith   if (flg) PetscCall(DMSetMatType(dm, typeName));
902863027abSJed Brown   PetscCall(PetscOptionsEnum("-dm_blocking_type", "Topological point or field node blocking", "DMSetBlockingType", DMBlockingTypes, (PetscEnum)dm->blocking_type, (PetscEnum *)&dm->blocking_type, NULL));
9039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_is_coloring_type", "Global or local coloring of Jacobian", "DMSetISColoringType", ISColoringTypes, (PetscEnum)dm->coloringtype, (PetscEnum *)&dm->coloringtype, NULL));
9049566063dSJacob 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));
905dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, setfromoptions, PetscOptionsObject);
906f9ba7244SBarry Smith   /* process any options handlers added with PetscObjectAddOptionsHandler() */
907dbbe0bcdSBarry Smith   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)dm, PetscOptionsObject));
908d0609cedSBarry Smith   PetscOptionsEnd();
9093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
910d7bf68aeSBarry Smith }
911d7bf68aeSBarry Smith 
912fc9bc008SSatish Balay /*@C
913bb7acecfSBarry Smith   DMViewFromOptions - View a `DM` in a particular way based on a request in the options database
914fe2efc57SMark 
91520f4b53cSBarry Smith   Collective
916fe2efc57SMark 
917fe2efc57SMark   Input Parameters:
918bb7acecfSBarry Smith + dm   - the `DM` object
91920f4b53cSBarry Smith . obj  - optional object that provides the prefix for the options database (if `NULL` then the prefix in obj is used)
92060225df5SJacob Faibussowitsch - name - option string that is used to activate viewing
921fe2efc57SMark 
922fe2efc57SMark   Level: intermediate
923bb7acecfSBarry Smith 
924bb7acecfSBarry Smith   Note:
925bb7acecfSBarry Smith   See `PetscObjectViewFromOptions()` for a list of values that can be provided in the options database to determine how the `DM` is viewed
926bb7acecfSBarry Smith 
92760225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMView()`, `PetscObjectViewFromOptions()`, `DMCreate()`
928fe2efc57SMark @*/
929d71ae5a4SJacob Faibussowitsch PetscErrorCode DMViewFromOptions(DM dm, PetscObject obj, const char name[])
930d71ae5a4SJacob Faibussowitsch {
931fe2efc57SMark   PetscFunctionBegin;
932fe2efc57SMark   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9339566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)dm, obj, name));
9343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
935fe2efc57SMark }
936fe2efc57SMark 
937fe2efc57SMark /*@C
938bb7acecfSBarry 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
939bb7acecfSBarry Smith   save the `DM` in a binary file to be loaded later or create a visualization of the `DM`
94047c6ae99SBarry Smith 
94120f4b53cSBarry Smith   Collective
94247c6ae99SBarry Smith 
943d8d19677SJose E. Roman   Input Parameters:
944bb7acecfSBarry Smith + dm - the `DM` object to view
94547c6ae99SBarry Smith - v  - the viewer
94647c6ae99SBarry Smith 
94720f4b53cSBarry Smith   Level: beginner
94820f4b53cSBarry Smith 
949cd7e8a5eSksagiyam   Notes:
950bb7acecfSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` as the `PetscViewerFormat` one can save multiple `DMPLEX`
951bb7acecfSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
952bb7acecfSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
953cd7e8a5eSksagiyam 
9541cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscViewer`, `PetscViewerFormat`, `PetscViewerSetFormat()`, `DMDestroy()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMLoad()`, `PetscObjectSetName()`
95547c6ae99SBarry Smith @*/
956d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView(DM dm, PetscViewer v)
957d71ae5a4SJacob Faibussowitsch {
95832c0f0efSBarry Smith   PetscBool         isbinary;
95976a8abe0SBarry Smith   PetscMPIInt       size;
96076a8abe0SBarry Smith   PetscViewerFormat format;
96147c6ae99SBarry Smith 
96247c6ae99SBarry Smith   PetscFunctionBegin;
963171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
96448a46eb9SPierre Jolivet   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm), &v));
965b1b135c8SBarry Smith   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);
96674903a4fSStefano Zampini   /* Ideally, we would like to have this test on.
96774903a4fSStefano Zampini      However, it currently breaks socket viz via GLVis.
96874903a4fSStefano Zampini      During DMView(parallel_mesh,glvis_viewer), each
96974903a4fSStefano Zampini      process opens a sequential ASCII socket to visualize
97074903a4fSStefano Zampini      the local mesh, and PetscObjectView(dm,local_socket)
97174903a4fSStefano Zampini      is internally called inside VecView_GLVis, incurring
97274903a4fSStefano Zampini      in an error here */
97374903a4fSStefano Zampini   /* PetscCheckSameComm(dm,1,v,2); */
9749566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckWritable(v));
975b1b135c8SBarry Smith 
9769566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(v, &format));
9779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9783ba16761SJacob Faibussowitsch   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
9799566063dSJacob Faibussowitsch   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)dm, v));
9809566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERBINARY, &isbinary));
98132c0f0efSBarry Smith   if (isbinary) {
98255849f57SBarry Smith     PetscInt classid = DM_FILE_CLASSID;
98332c0f0efSBarry Smith     char     type[256];
98432c0f0efSBarry Smith 
9859566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWrite(v, &classid, 1, PETSC_INT));
986c6a7a370SJeremy L Thompson     PetscCall(PetscStrncpy(type, ((PetscObject)dm)->type_name, sizeof(type)));
9879566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWrite(v, type, 256, PETSC_CHAR));
98832c0f0efSBarry Smith   }
989dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, view, v);
9903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99147c6ae99SBarry Smith }
99247c6ae99SBarry Smith 
99347c6ae99SBarry Smith /*@
994bb7acecfSBarry 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,
995bb7acecfSBarry Smith   that is it has no ghost locations.
99647c6ae99SBarry Smith 
99720f4b53cSBarry Smith   Collective
99847c6ae99SBarry Smith 
99947c6ae99SBarry Smith   Input Parameter:
1000bb7acecfSBarry Smith . dm - the `DM` object
100147c6ae99SBarry Smith 
100247c6ae99SBarry Smith   Output Parameter:
100347c6ae99SBarry Smith . vec - the global vector
100447c6ae99SBarry Smith 
1005073dac72SJed Brown   Level: beginner
100647c6ae99SBarry Smith 
10071cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `Vec`, `DMCreateLocalVector()`, `DMGetGlobalVector()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
1008bb7acecfSBarry Smith          `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`
100947c6ae99SBarry Smith @*/
1010d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateGlobalVector(DM dm, Vec *vec)
1011d71ae5a4SJacob Faibussowitsch {
101247c6ae99SBarry Smith   PetscFunctionBegin;
1013171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10144f572ea9SToby Isaac   PetscAssertPointer(vec, 2);
1015dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createglobalvector, vec);
101676bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1017c6b011d8SStefano Zampini     DM vdm;
1018c6b011d8SStefano Zampini 
10199566063dSJacob Faibussowitsch     PetscCall(VecGetDM(*vec, &vdm));
10207a8be351SBarry Smith     PetscCheck(vdm, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DM type '%s' did not attach the DM to the vector", ((PetscObject)dm)->type_name);
1021c6b011d8SStefano Zampini   }
10223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
102347c6ae99SBarry Smith }
102447c6ae99SBarry Smith 
102547c6ae99SBarry Smith /*@
1026bb7acecfSBarry Smith   DMCreateLocalVector - Creates a local vector from a `DM` object.
102747c6ae99SBarry Smith 
102847c6ae99SBarry Smith   Not Collective
102947c6ae99SBarry Smith 
103047c6ae99SBarry Smith   Input Parameter:
1031bb7acecfSBarry Smith . dm - the `DM` object
103247c6ae99SBarry Smith 
103347c6ae99SBarry Smith   Output Parameter:
103447c6ae99SBarry Smith . vec - the local vector
103547c6ae99SBarry Smith 
1036073dac72SJed Brown   Level: beginner
103747c6ae99SBarry Smith 
103820f4b53cSBarry Smith   Note:
1039bb7acecfSBarry 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.
1040bb7acecfSBarry Smith 
10411cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `Vec`, `DMCreateGlobalVector()`, `DMGetLocalVector()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`
1042bb7acecfSBarry Smith          `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`
104347c6ae99SBarry Smith @*/
1044d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLocalVector(DM dm, Vec *vec)
1045d71ae5a4SJacob Faibussowitsch {
104647c6ae99SBarry Smith   PetscFunctionBegin;
1047171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10484f572ea9SToby Isaac   PetscAssertPointer(vec, 2);
1049dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createlocalvector, vec);
105076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1051c6b011d8SStefano Zampini     DM vdm;
1052c6b011d8SStefano Zampini 
10539566063dSJacob Faibussowitsch     PetscCall(VecGetDM(*vec, &vdm));
10547a8be351SBarry Smith     PetscCheck(vdm, PETSC_COMM_SELF, PETSC_ERR_LIB, "DM type '%s' did not attach the DM to the vector", ((PetscObject)dm)->type_name);
1055c6b011d8SStefano Zampini   }
10563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
105747c6ae99SBarry Smith }
105847c6ae99SBarry Smith 
10591411c6eeSJed Brown /*@
1060bb7acecfSBarry Smith   DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a `DM`.
10611411c6eeSJed Brown 
106220f4b53cSBarry Smith   Collective
10631411c6eeSJed Brown 
10641411c6eeSJed Brown   Input Parameter:
1065bb7acecfSBarry Smith . dm - the `DM` that provides the mapping
10661411c6eeSJed Brown 
10671411c6eeSJed Brown   Output Parameter:
10681411c6eeSJed Brown . ltog - the mapping
10691411c6eeSJed Brown 
1070bb7acecfSBarry Smith   Level: advanced
10711411c6eeSJed Brown 
10721411c6eeSJed Brown   Notes:
1073bb7acecfSBarry Smith   The global to local mapping allows one to set values into the global vector or matrix using `VecSetValuesLocal()` and `MatSetValuesLocal()`
10741411c6eeSJed Brown 
1075bb7acecfSBarry Smith   Vectors obtained with  `DMCreateGlobalVector()` and matrices obtained with `DMCreateMatrix()` already contain the global mapping so you do
1076bb7acecfSBarry Smith   need to use this function with those objects.
1077bb7acecfSBarry Smith 
1078bb7acecfSBarry Smith   This mapping can then be used by `VecSetLocalToGlobalMapping()` or `MatSetLocalToGlobalMapping()`.
1079bb7acecfSBarry Smith 
108060225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `VecSetLocalToGlobalMapping()`, `MatSetLocalToGlobalMapping()`,
1081bb7acecfSBarry Smith           `DMCreateMatrix()`
10821411c6eeSJed Brown @*/
1083d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalToGlobalMapping(DM dm, ISLocalToGlobalMapping *ltog)
1084d71ae5a4SJacob Faibussowitsch {
10850be3e97aSMatthew G. Knepley   PetscInt bs = -1, bsLocal[2], bsMinMax[2];
10861411c6eeSJed Brown 
10871411c6eeSJed Brown   PetscFunctionBegin;
10881411c6eeSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10894f572ea9SToby Isaac   PetscAssertPointer(ltog, 2);
10901411c6eeSJed Brown   if (!dm->ltogmap) {
109137d0c07bSMatthew G Knepley     PetscSection section, sectionGlobal;
109237d0c07bSMatthew G Knepley 
10939566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
109437d0c07bSMatthew G Knepley     if (section) {
1095a974ec88SMatthew G. Knepley       const PetscInt *cdofs;
109637d0c07bSMatthew G Knepley       PetscInt       *ltog;
1097ccf3bd66SMatthew G. Knepley       PetscInt        pStart, pEnd, n, p, k, l;
109837d0c07bSMatthew G Knepley 
10999566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
11009566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
11019566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetStorageSize(section, &n));
11029566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n, &ltog)); /* We want the local+overlap size */
110337d0c07bSMatthew G Knepley       for (p = pStart, l = 0; p < pEnd; ++p) {
1104e6befd46SJed Brown         PetscInt bdof, cdof, dof, off, c, cind;
110537d0c07bSMatthew G Knepley 
110637d0c07bSMatthew G Knepley         /* Should probably use constrained dofs */
11079566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, p, &dof));
11089566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(section, p, &cdof));
11099566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, p, &cdofs));
11109566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &off));
11111a7dc684SMatthew G. Knepley         /* If you have dofs, and constraints, and they are unequal, we set the blocksize to 1 */
11121a7dc684SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
1113ad540459SPierre Jolivet         if (dof) bs = bs < 0 ? bdof : PetscGCD(bs, bdof);
11145227eafbSStefano Zampini 
1115e6befd46SJed Brown         for (c = 0, cind = 0; c < dof; ++c, ++l) {
11165227eafbSStefano Zampini           if (cind < cdof && c == cdofs[cind]) {
1117e6befd46SJed Brown             ltog[l] = off < 0 ? off - c : -(off + c + 1);
1118e6befd46SJed Brown             cind++;
1119e6befd46SJed Brown           } else {
11205227eafbSStefano Zampini             ltog[l] = (off < 0 ? -(off + 1) : off) + c - cind;
1121e6befd46SJed Brown           }
112237d0c07bSMatthew G Knepley         }
112337d0c07bSMatthew G Knepley       }
1124bff27382SMatthew G. Knepley       /* Must have same blocksize on all procs (some might have no points) */
11259371c9d4SSatish Balay       bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
11269371c9d4SSatish Balay       bsLocal[1] = bs;
11279566063dSJacob Faibussowitsch       PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
11289371c9d4SSatish Balay       if (bsMinMax[0] != bsMinMax[1]) {
11299371c9d4SSatish Balay         bs = 1;
11309371c9d4SSatish Balay       } else {
11319371c9d4SSatish Balay         bs = bsMinMax[0];
11329371c9d4SSatish Balay       }
11337591dbb2SMatthew G. Knepley       bs = bs < 0 ? 1 : bs;
11347591dbb2SMatthew G. Knepley       /* Must reduce indices by blocksize */
1135ccf3bd66SMatthew G. Knepley       if (bs > 1) {
1136ca469d19SJed Brown         for (l = 0, k = 0; l < n; l += bs, ++k) {
1137ca469d19SJed Brown           // Integer division of negative values truncates toward zero(!), not toward negative infinity
1138ca469d19SJed Brown           ltog[k] = ltog[l] >= 0 ? ltog[l] / bs : -(-(ltog[l] + 1) / bs + 1);
1139ca469d19SJed Brown         }
1140ccf3bd66SMatthew G. Knepley         n /= bs;
1141ccf3bd66SMatthew G. Knepley       }
11429566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, n, ltog, PETSC_OWN_POINTER, &dm->ltogmap));
1143dbbe0bcdSBarry Smith     } else PetscUseTypeMethod(dm, getlocaltoglobalmapping);
114437d0c07bSMatthew G Knepley   }
11451411c6eeSJed Brown   *ltog = dm->ltogmap;
11463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11471411c6eeSJed Brown }
11481411c6eeSJed Brown 
11491411c6eeSJed Brown /*@
1150bb7acecfSBarry Smith   DMGetBlockSize - Gets the inherent block size associated with a `DM`
11511411c6eeSJed Brown 
11521411c6eeSJed Brown   Not Collective
11531411c6eeSJed Brown 
11541411c6eeSJed Brown   Input Parameter:
1155bb7acecfSBarry Smith . dm - the `DM` with block structure
11561411c6eeSJed Brown 
11571411c6eeSJed Brown   Output Parameter:
11581411c6eeSJed Brown . bs - the block size, 1 implies no exploitable block structure
11591411c6eeSJed Brown 
11601411c6eeSJed Brown   Level: intermediate
11611411c6eeSJed Brown 
1162bb7acecfSBarry Smith   Note:
1163bb7acecfSBarry Smith   This might be the number of degrees of freedom at each grid point for a structured grid.
1164bb7acecfSBarry Smith 
1165bb7acecfSBarry Smith   Complex `DM` that represent multiphysics or staggered grids or mixed-methods do not generally have a single inherent block size, but
1166bb7acecfSBarry Smith   rather different locations in the vectors may have a different block size.
1167bb7acecfSBarry Smith 
11681cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `ISCreateBlock()`, `VecSetBlockSize()`, `MatSetBlockSize()`, `DMGetLocalToGlobalMapping()`
11691411c6eeSJed Brown @*/
1170d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBlockSize(DM dm, PetscInt *bs)
1171d71ae5a4SJacob Faibussowitsch {
11721411c6eeSJed Brown   PetscFunctionBegin;
11731411c6eeSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11744f572ea9SToby Isaac   PetscAssertPointer(bs, 2);
11757a8be351SBarry Smith   PetscCheck(dm->bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM does not have enough information to provide a block size yet");
11761411c6eeSJed Brown   *bs = dm->bs;
11773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11781411c6eeSJed Brown }
11791411c6eeSJed Brown 
118048eeb7c8SBarry Smith /*@C
1181bb7acecfSBarry Smith   DMCreateInterpolation - Gets the interpolation matrix between two `DM` objects. The resulting matrix map degrees of freedom in the vector obtained by
1182bb7acecfSBarry Smith   `DMCreateGlobalVector()` on the coarse `DM` to similar vectors on the fine grid `DM`.
118347c6ae99SBarry Smith 
118420f4b53cSBarry Smith   Collective
118547c6ae99SBarry Smith 
1186d8d19677SJose E. Roman   Input Parameters:
1187bb7acecfSBarry Smith + dmc - the `DM` object
1188bb7acecfSBarry Smith - dmf - the second, finer `DM` object
118947c6ae99SBarry Smith 
1190d8d19677SJose E. Roman   Output Parameters:
119147c6ae99SBarry Smith + mat - the interpolation
1192bb7acecfSBarry Smith - vec - the scaling (optional), see `DMCreateInterpolationScale()`
119347c6ae99SBarry Smith 
119447c6ae99SBarry Smith   Level: developer
119547c6ae99SBarry Smith 
119695452b02SPatrick Sanan   Notes:
1197bb7acecfSBarry 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
1198bb7acecfSBarry Smith   DMCoarsen(). The coordinates set into the `DMDA` are completely ignored in computing the interpolation.
1199d52bd9f3SBarry Smith 
1200bb7acecfSBarry Smith   For `DMDA` objects you can use this interpolation (more precisely the interpolation from the `DMGetCoordinateDM()`) to interpolate the mesh coordinate
1201bb7acecfSBarry Smith   vectors EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic.
120285afcc9aSBarry Smith 
12031cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolationScale()`
120447c6ae99SBarry Smith @*/
1205d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation(DM dmc, DM dmf, Mat *mat, Vec *vec)
1206d71ae5a4SJacob Faibussowitsch {
120747c6ae99SBarry Smith   PetscFunctionBegin;
1208a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1209a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
12104f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
12119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateInterpolation, dmc, dmf, 0, 0));
1212dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createinterpolation, dmf, mat, vec);
12139566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateInterpolation, dmc, dmf, 0, 0));
12143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121547c6ae99SBarry Smith }
121647c6ae99SBarry Smith 
12173ad4599aSBarry Smith /*@
1218a4e35b19SJacob Faibussowitsch   DMCreateInterpolationScale - Forms L = 1/(R*1) where 1 is the vector of all ones, and R is
1219a4e35b19SJacob Faibussowitsch   the transpose of the interpolation between the `DM`.
12202ed6491fSPatrick Sanan 
12212ed6491fSPatrick Sanan   Input Parameters:
1222bb7acecfSBarry Smith + dac - `DM` that defines a coarse mesh
1223bb7acecfSBarry Smith . daf - `DM` that defines a fine mesh
12242ed6491fSPatrick Sanan - mat - the restriction (or interpolation operator) from fine to coarse
12252ed6491fSPatrick Sanan 
12262ed6491fSPatrick Sanan   Output Parameter:
12272ed6491fSPatrick Sanan . scale - the scaled vector
12282ed6491fSPatrick Sanan 
1229bb7acecfSBarry Smith   Level: advanced
12302ed6491fSPatrick Sanan 
1231a4e35b19SJacob Faibussowitsch   Notes:
1232a4e35b19SJacob Faibussowitsch   xcoarse = diag(L)*R*xfine preserves scale and is thus suitable for state (versus residual)
1233a4e35b19SJacob Faibussowitsch   restriction. In other words xcoarse is the coarse representation of xfine.
1234a4e35b19SJacob Faibussowitsch 
123560225df5SJacob Faibussowitsch   Developer Notes:
1236bb7acecfSBarry Smith   If the fine-scale `DMDA` has the -dm_bind_below option set to true, then `DMCreateInterpolationScale()` calls `MatSetBindingPropagates()`
1237e9c74fd6SRichard Tran Mills   on the restriction/interpolation operator to set the bindingpropagates flag to true.
1238e9c74fd6SRichard Tran Mills 
123960225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `MatRestrict()`, `MatInterpolate()`, `DMCreateInterpolation()`, `DMCreateRestriction()`, `DMCreateGlobalVector()`
12402ed6491fSPatrick Sanan @*/
1241d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolationScale(DM dac, DM daf, Mat mat, Vec *scale)
1242d71ae5a4SJacob Faibussowitsch {
12432ed6491fSPatrick Sanan   Vec         fine;
12442ed6491fSPatrick Sanan   PetscScalar one = 1.0;
12459704db99SRichard Tran Mills #if defined(PETSC_HAVE_CUDA)
1246e9c74fd6SRichard Tran Mills   PetscBool bindingpropagates, isbound;
12479704db99SRichard Tran Mills #endif
12482ed6491fSPatrick Sanan 
12492ed6491fSPatrick Sanan   PetscFunctionBegin;
12509566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(daf, &fine));
12519566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dac, scale));
12529566063dSJacob Faibussowitsch   PetscCall(VecSet(fine, one));
12539704db99SRichard Tran Mills #if defined(PETSC_HAVE_CUDA)
12549704db99SRichard Tran Mills   /* If the 'fine' Vec is bound to the CPU, it makes sense to bind 'mat' as well.
12559704db99SRichard Tran Mills    * Note that we only do this for the CUDA case, right now, but if we add support for MatMultTranspose() via ViennaCL,
12569704db99SRichard Tran Mills    * we'll need to do it for that case, too.*/
12579566063dSJacob Faibussowitsch   PetscCall(VecGetBindingPropagates(fine, &bindingpropagates));
1258e9c74fd6SRichard Tran Mills   if (bindingpropagates) {
12599566063dSJacob Faibussowitsch     PetscCall(MatSetBindingPropagates(mat, PETSC_TRUE));
12609566063dSJacob Faibussowitsch     PetscCall(VecBoundToCPU(fine, &isbound));
12619566063dSJacob Faibussowitsch     PetscCall(MatBindToCPU(mat, isbound));
126283aa49f4SRichard Tran Mills   }
12639704db99SRichard Tran Mills #endif
12649566063dSJacob Faibussowitsch   PetscCall(MatRestrict(mat, fine, *scale));
12659566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fine));
12669566063dSJacob Faibussowitsch   PetscCall(VecReciprocal(*scale));
12673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12682ed6491fSPatrick Sanan }
12692ed6491fSPatrick Sanan 
12702ed6491fSPatrick Sanan /*@
1271bb7acecfSBarry Smith   DMCreateRestriction - Gets restriction matrix between two `DM` objects. The resulting matrix map degrees of freedom in the vector obtained by
1272bb7acecfSBarry Smith   `DMCreateGlobalVector()` on the fine `DM` to similar vectors on the coarse grid `DM`.
12733ad4599aSBarry Smith 
127420f4b53cSBarry Smith   Collective
12753ad4599aSBarry Smith 
1276d8d19677SJose E. Roman   Input Parameters:
1277bb7acecfSBarry Smith + dmc - the `DM` object
1278bb7acecfSBarry Smith - dmf - the second, finer `DM` object
12793ad4599aSBarry Smith 
12803ad4599aSBarry Smith   Output Parameter:
12813ad4599aSBarry Smith . mat - the restriction
12823ad4599aSBarry Smith 
12833ad4599aSBarry Smith   Level: developer
12843ad4599aSBarry Smith 
1285bb7acecfSBarry Smith   Note:
1286bb7acecfSBarry Smith   This only works for `DMSTAG`. For many situations either the transpose of the operator obtained with `DMCreateInterpolation()` or that
1287bb7acecfSBarry Smith   matrix multiplied by the vector obtained with `DMCreateInterpolationScale()` provides the desired object.
12883ad4599aSBarry Smith 
12891cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRestrict()`, `DMInterpolate()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateInterpolation()`
12903ad4599aSBarry Smith @*/
1291d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateRestriction(DM dmc, DM dmf, Mat *mat)
1292d71ae5a4SJacob Faibussowitsch {
12933ad4599aSBarry Smith   PetscFunctionBegin;
1294a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1295a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
12964f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
12979566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateRestriction, dmc, dmf, 0, 0));
1298dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createrestriction, dmf, mat);
12999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateRestriction, dmc, dmf, 0, 0));
13003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13013ad4599aSBarry Smith }
13023ad4599aSBarry Smith 
130347c6ae99SBarry Smith /*@
1304a4e35b19SJacob Faibussowitsch   DMCreateInjection - Gets injection matrix between two `DM` objects.
130547c6ae99SBarry Smith 
130620f4b53cSBarry Smith   Collective
130747c6ae99SBarry Smith 
1308d8d19677SJose E. Roman   Input Parameters:
1309bb7acecfSBarry Smith + dac - the `DM` object
1310bb7acecfSBarry Smith - daf - the second, finer `DM` object
131147c6ae99SBarry Smith 
131247c6ae99SBarry Smith   Output Parameter:
13136dbf9973SLawrence Mitchell . mat - the injection
131447c6ae99SBarry Smith 
131547c6ae99SBarry Smith   Level: developer
131647c6ae99SBarry Smith 
1317a4e35b19SJacob Faibussowitsch   Notes:
1318a4e35b19SJacob Faibussowitsch   This is an operator that applied to a vector obtained with `DMCreateGlobalVector()` on the
1319a4e35b19SJacob Faibussowitsch   fine grid maps the values to a vector on the vector on the coarse `DM` by simply selecting
1320a4e35b19SJacob Faibussowitsch   the values on the coarse grid points. This compares to the operator obtained by
1321a4e35b19SJacob Faibussowitsch   `DMCreateRestriction()` or the transpose of the operator obtained by
1322a4e35b19SJacob Faibussowitsch   `DMCreateInterpolation()` that uses a "local weighted average" of the values around the
1323a4e35b19SJacob Faibussowitsch   coarse grid point as the coarse grid value.
1324a4e35b19SJacob Faibussowitsch 
1325bb7acecfSBarry Smith   For `DMDA` objects this only works for "uniform refinement", that is the refined mesh was obtained `DMRefine()` or the coarse mesh was obtained by
1326bb7acecfSBarry Smith   `DMCoarsen()`. The coordinates set into the `DMDA` are completely ignored in computing the injection.
132785afcc9aSBarry Smith 
13281cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateInterpolation()`,
1329bb7acecfSBarry Smith           `DMCreateRestriction()`, `MatRestrict()`, `MatInterpolate()`
133047c6ae99SBarry Smith @*/
1331d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection(DM dac, DM daf, Mat *mat)
1332d71ae5a4SJacob Faibussowitsch {
133347c6ae99SBarry Smith   PetscFunctionBegin;
1334a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dac, DM_CLASSID, 1);
1335a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(daf, DM_CLASSID, 2);
13364f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
13379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateInjection, dac, daf, 0, 0));
1338dbbe0bcdSBarry Smith   PetscUseTypeMethod(dac, createinjection, daf, mat);
13399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateInjection, dac, daf, 0, 0));
13403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134147c6ae99SBarry Smith }
134247c6ae99SBarry Smith 
1343b412c318SBarry Smith /*@
1344bb7acecfSBarry Smith   DMCreateMassMatrix - Gets the mass matrix between two `DM` objects, M_ij = \int \phi_i \psi_j where the \phi are Galerkin basis functions for a
1345bb7acecfSBarry Smith   a Galerkin finite element model on the `DM`
1346bd041c0cSMatthew G. Knepley 
134720f4b53cSBarry Smith   Collective
1348bd041c0cSMatthew G. Knepley 
1349d8d19677SJose E. Roman   Input Parameters:
1350bb7acecfSBarry Smith + dmc - the target `DM` object
1351bb7acecfSBarry Smith - dmf - the source `DM` object
1352bd041c0cSMatthew G. Knepley 
1353bd041c0cSMatthew G. Knepley   Output Parameter:
1354b4937a87SMatthew G. Knepley . mat - the mass matrix
1355bd041c0cSMatthew G. Knepley 
1356bd041c0cSMatthew G. Knepley   Level: developer
1357bd041c0cSMatthew G. Knepley 
1358bb7acecfSBarry Smith   Notes:
1359bb7acecfSBarry Smith   For `DMPLEX` the finite element model for the `DM` must have been already provided.
1360bb7acecfSBarry Smith 
136120f4b53cSBarry Smith   if `dmc` is `dmf` then x^t M x is an approximation to the L2 norm of the vector x which is obtained by `DMCreateGlobalVector()`
1362bb7acecfSBarry Smith 
136342747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateMassMatrixLumped()`, `DMCreateMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolation()`, `DMCreateInjection()`
1364bd041c0cSMatthew G. Knepley @*/
1365d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix(DM dmc, DM dmf, Mat *mat)
1366d71ae5a4SJacob Faibussowitsch {
1367bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
1368b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
1369b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 2);
13704f572ea9SToby Isaac   PetscAssertPointer(mat, 3);
13715b8ffe73SMark Adams   PetscCall(PetscLogEventBegin(DM_CreateMassMatrix, 0, 0, 0, 0));
1372dbbe0bcdSBarry Smith   PetscUseTypeMethod(dmc, createmassmatrix, dmf, mat);
13735b8ffe73SMark Adams   PetscCall(PetscLogEventEnd(DM_CreateMassMatrix, 0, 0, 0, 0));
13743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1375b4937a87SMatthew G. Knepley }
1376b4937a87SMatthew G. Knepley 
1377b4937a87SMatthew G. Knepley /*@
1378bb7acecfSBarry Smith   DMCreateMassMatrixLumped - Gets the lumped mass matrix for a given `DM`
1379b4937a87SMatthew G. Knepley 
138020f4b53cSBarry Smith   Collective
1381b4937a87SMatthew G. Knepley 
1382b4937a87SMatthew G. Knepley   Input Parameter:
1383bb7acecfSBarry Smith . dm - the `DM` object
1384b4937a87SMatthew G. Knepley 
1385b4937a87SMatthew G. Knepley   Output Parameter:
1386bb7acecfSBarry Smith . lm - the lumped mass matrix, which is a diagonal matrix, represented as a vector
1387b4937a87SMatthew G. Knepley 
1388b4937a87SMatthew G. Knepley   Level: developer
1389b4937a87SMatthew G. Knepley 
1390bb7acecfSBarry Smith   Note:
1391bb7acecfSBarry Smith   See `DMCreateMassMatrix()` for how to create the non-lumped version of the mass matrix.
1392bb7acecfSBarry Smith 
139360225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateMassMatrix()`, `DMCreateMatrix()`, `DMRefine()`, `DMCoarsen()`, `DMCreateRestriction()`, `DMCreateInterpolation()`, `DMCreateInjection()`
1394b4937a87SMatthew G. Knepley @*/
1395d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped(DM dm, Vec *lm)
1396d71ae5a4SJacob Faibussowitsch {
1397b4937a87SMatthew G. Knepley   PetscFunctionBegin;
1398b4937a87SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
13994f572ea9SToby Isaac   PetscAssertPointer(lm, 2);
1400dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createmassmatrixlumped, lm);
14013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1402bd041c0cSMatthew G. Knepley }
1403bd041c0cSMatthew G. Knepley 
1404bd041c0cSMatthew G. Knepley /*@
1405bb7acecfSBarry Smith   DMCreateColoring - Gets coloring of a graph associated with the `DM`. Often the graph represents the operator matrix associated with the discretization
1406bb7acecfSBarry Smith   of a PDE on the `DM`.
140747c6ae99SBarry Smith 
140820f4b53cSBarry Smith   Collective
140947c6ae99SBarry Smith 
1410d8d19677SJose E. Roman   Input Parameters:
1411bb7acecfSBarry Smith + dm    - the `DM` object
1412bb7acecfSBarry Smith - ctype - `IS_COLORING_LOCAL` or `IS_COLORING_GLOBAL`
141347c6ae99SBarry Smith 
141447c6ae99SBarry Smith   Output Parameter:
141547c6ae99SBarry Smith . coloring - the coloring
141647c6ae99SBarry Smith 
14171bf8429eSBarry Smith   Level: developer
14181bf8429eSBarry Smith 
1419ec5066bdSBarry Smith   Notes:
1420bb7acecfSBarry Smith   Coloring of matrices can also be computed directly from the sparse matrix nonzero structure via the `MatColoring` object or from the mesh from which the
1421bb7acecfSBarry Smith   matrix comes from (what this function provides). In general using the mesh produces a more optimal coloring (fewer colors).
1422ec5066bdSBarry Smith 
1423bb7acecfSBarry Smith   This produces a coloring with the distance of 2, see `MatSetColoringDistance()` which can be used for efficiently computing Jacobians with `MatFDColoringCreate()`
14241bf8429eSBarry Smith   For `DMDA` in three dimensions with periodic boundary conditions the number of grid points in each dimension must be divisible by 2*stencil_width + 1,
14251bf8429eSBarry Smith   otherwise an error will be generated.
1426ec5066bdSBarry Smith 
14271cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `ISColoring`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatType()`, `MatColoring`, `MatFDColoringCreate()`
1428aab9d709SJed Brown @*/
1429d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateColoring(DM dm, ISColoringType ctype, ISColoring *coloring)
1430d71ae5a4SJacob Faibussowitsch {
143147c6ae99SBarry Smith   PetscFunctionBegin;
1432171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14334f572ea9SToby Isaac   PetscAssertPointer(coloring, 3);
1434dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getcoloring, ctype, coloring);
14353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
143647c6ae99SBarry Smith }
143747c6ae99SBarry Smith 
1438b412c318SBarry Smith /*@
1439bb7acecfSBarry Smith   DMCreateMatrix - Gets an empty matrix for a `DM` that is most commonly used to store the Jacobian of a discrete PDE operator.
144047c6ae99SBarry Smith 
144120f4b53cSBarry Smith   Collective
144247c6ae99SBarry Smith 
144347c6ae99SBarry Smith   Input Parameter:
1444bb7acecfSBarry Smith . dm - the `DM` object
144547c6ae99SBarry Smith 
144647c6ae99SBarry Smith   Output Parameter:
144747c6ae99SBarry Smith . mat - the empty Jacobian
144847c6ae99SBarry Smith 
144920f4b53cSBarry Smith   Options Database Key:
1450bb7acecfSBarry Smith . -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()` and `DMCreateMassMatrix()`, but do not fill it with zeros
1451f27dd7c6SMatthew G. Knepley 
145220f4b53cSBarry Smith   Level: beginner
145320f4b53cSBarry Smith 
145495452b02SPatrick Sanan   Notes:
145595452b02SPatrick Sanan   This properly preallocates the number of nonzeros in the sparse matrix so you
145694013140SBarry Smith   do not need to do it yourself.
145794013140SBarry Smith 
145894013140SBarry Smith   By default it also sets the nonzero structure and puts in the zero entries. To prevent setting
1459bb7acecfSBarry Smith   the nonzero pattern call `DMSetMatrixPreallocateOnly()`
146094013140SBarry Smith 
1461bb7acecfSBarry Smith   For `DMDA`, when you call `MatView()` on this matrix it is displayed using the global natural ordering, NOT in the ordering used
146294013140SBarry Smith   internally by PETSc.
146394013140SBarry Smith 
1464bb7acecfSBarry Smith   For `DMDA`, in general it is easiest to use `MatSetValuesStencil()` or `MatSetValuesLocal()` to put values into the matrix because
1465bb7acecfSBarry Smith   `MatSetValues()` requires the indices for the global numbering for the `DMDA` which is complic`ated to compute
146694013140SBarry Smith 
14671cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMSetMatType()`, `DMCreateMassMatrix()`
1468aab9d709SJed Brown @*/
1469d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix(DM dm, Mat *mat)
1470d71ae5a4SJacob Faibussowitsch {
147147c6ae99SBarry Smith   PetscFunctionBegin;
1472171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14734f572ea9SToby Isaac   PetscAssertPointer(mat, 2);
14749566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
14759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_CreateMatrix, 0, 0, 0, 0));
1476dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, creatematrix, mat);
147776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1478c6b011d8SStefano Zampini     DM mdm;
1479c6b011d8SStefano Zampini 
14809566063dSJacob Faibussowitsch     PetscCall(MatGetDM(*mat, &mdm));
14817a8be351SBarry Smith     PetscCheck(mdm, PETSC_COMM_SELF, PETSC_ERR_PLIB, "DM type '%s' did not attach the DM to the matrix", ((PetscObject)dm)->type_name);
1482c6b011d8SStefano Zampini   }
1483e571a35bSMatthew G. Knepley   /* Handle nullspace and near nullspace */
1484e5e52638SMatthew G. Knepley   if (dm->Nf) {
1485e571a35bSMatthew G. Knepley     MatNullSpace nullSpace;
1486649ef022SMatthew Knepley     PetscInt     Nf, f;
1487e571a35bSMatthew G. Knepley 
14889566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
1489649ef022SMatthew Knepley     for (f = 0; f < Nf; ++f) {
1490649ef022SMatthew Knepley       if (dm->nullspaceConstructors[f]) {
14919566063dSJacob Faibussowitsch         PetscCall((*dm->nullspaceConstructors[f])(dm, f, f, &nullSpace));
14929566063dSJacob Faibussowitsch         PetscCall(MatSetNullSpace(*mat, nullSpace));
14939566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nullSpace));
1494649ef022SMatthew Knepley         break;
1495e571a35bSMatthew G. Knepley       }
1496649ef022SMatthew Knepley     }
1497649ef022SMatthew Knepley     for (f = 0; f < Nf; ++f) {
1498649ef022SMatthew Knepley       if (dm->nearnullspaceConstructors[f]) {
14999566063dSJacob Faibussowitsch         PetscCall((*dm->nearnullspaceConstructors[f])(dm, f, f, &nullSpace));
15009566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(*mat, nullSpace));
15019566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nullSpace));
1502e571a35bSMatthew G. Knepley       }
1503e571a35bSMatthew G. Knepley     }
1504e571a35bSMatthew G. Knepley   }
15059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_CreateMatrix, 0, 0, 0, 0));
15063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
150747c6ae99SBarry Smith }
150847c6ae99SBarry Smith 
1509732e2eb9SMatthew G Knepley /*@
1510a4e35b19SJacob Faibussowitsch   DMSetMatrixPreallocateSkip - When `DMCreateMatrix()` is called the matrix sizes and
1511a4e35b19SJacob Faibussowitsch   `ISLocalToGlobalMapping` will be properly set, but the data structures to store values in the
1512a4e35b19SJacob Faibussowitsch   matrices will not be preallocated.
1513aa0f6e3cSJed Brown 
151420f4b53cSBarry Smith   Logically Collective
1515aa0f6e3cSJed Brown 
1516aa0f6e3cSJed Brown   Input Parameters:
1517bb7acecfSBarry Smith + dm   - the `DM`
1518bb7acecfSBarry Smith - skip - `PETSC_TRUE` to skip preallocation
1519aa0f6e3cSJed Brown 
1520aa0f6e3cSJed Brown   Level: developer
1521aa0f6e3cSJed Brown 
1522a4e35b19SJacob Faibussowitsch   Notes:
1523a4e35b19SJacob Faibussowitsch   This is most useful to reduce initialization costs when `MatSetPreallocationCOO()` and
1524a4e35b19SJacob Faibussowitsch   `MatSetValuesCOO()` will be used.
1525a4e35b19SJacob Faibussowitsch 
15261cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMSetMatrixStructureOnly()`, `DMSetMatrixPreallocateOnly()`
1527aa0f6e3cSJed Brown @*/
1528d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixPreallocateSkip(DM dm, PetscBool skip)
1529d71ae5a4SJacob Faibussowitsch {
1530aa0f6e3cSJed Brown   PetscFunctionBegin;
1531aa0f6e3cSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1532aa0f6e3cSJed Brown   dm->prealloc_skip = skip;
15333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1534aa0f6e3cSJed Brown }
1535aa0f6e3cSJed Brown 
1536aa0f6e3cSJed Brown /*@
1537bb7acecfSBarry Smith   DMSetMatrixPreallocateOnly - When `DMCreateMatrix()` is called the matrix will be properly
1538732e2eb9SMatthew G Knepley   preallocated but the nonzero structure and zero values will not be set.
1539732e2eb9SMatthew G Knepley 
154020f4b53cSBarry Smith   Logically Collective
1541732e2eb9SMatthew G Knepley 
1542d8d19677SJose E. Roman   Input Parameters:
1543bb7acecfSBarry Smith + dm   - the `DM`
1544bb7acecfSBarry Smith - only - `PETSC_TRUE` if only want preallocation
1545732e2eb9SMatthew G Knepley 
154620f4b53cSBarry Smith   Options Database Key:
1547bb7acecfSBarry Smith . -dm_preallocate_only - Only preallocate the matrix for `DMCreateMatrix()`, `DMCreateMassMatrix()`, but do not fill it with zeros
1548f27dd7c6SMatthew G. Knepley 
154920f4b53cSBarry Smith   Level: developer
155020f4b53cSBarry Smith 
15511cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMSetMatrixStructureOnly()`, `DMSetMatrixPreallocateSkip()`
1552732e2eb9SMatthew G Knepley @*/
1553d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only)
1554d71ae5a4SJacob Faibussowitsch {
1555732e2eb9SMatthew G Knepley   PetscFunctionBegin;
1556732e2eb9SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1557732e2eb9SMatthew G Knepley   dm->prealloc_only = only;
15583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1559732e2eb9SMatthew G Knepley }
1560732e2eb9SMatthew G Knepley 
1561b06ff27eSHong Zhang /*@
1562bb7acecfSBarry Smith   DMSetMatrixStructureOnly - When `DMCreateMatrix()` is called, the matrix structure will be created
1563bb7acecfSBarry Smith   but the array for numerical values will not be allocated.
1564b06ff27eSHong Zhang 
156520f4b53cSBarry Smith   Logically Collective
1566b06ff27eSHong Zhang 
1567d8d19677SJose E. Roman   Input Parameters:
1568bb7acecfSBarry Smith + dm   - the `DM`
1569da81f932SPierre Jolivet - only - `PETSC_TRUE` if you only want matrix structure
1570b06ff27eSHong Zhang 
1571b06ff27eSHong Zhang   Level: developer
1572bb7acecfSBarry Smith 
15731cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `DMSetMatrixPreallocateOnly()`, `DMSetMatrixPreallocateSkip()`
1574b06ff27eSHong Zhang @*/
1575d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetMatrixStructureOnly(DM dm, PetscBool only)
1576d71ae5a4SJacob Faibussowitsch {
1577b06ff27eSHong Zhang   PetscFunctionBegin;
1578b06ff27eSHong Zhang   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1579b06ff27eSHong Zhang   dm->structure_only = only;
15803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1581b06ff27eSHong Zhang }
1582b06ff27eSHong Zhang 
1583863027abSJed Brown /*@
1584863027abSJed Brown   DMSetBlockingType - set the blocking granularity to be used for variable block size `DMCreateMatrix()` is called
1585863027abSJed Brown 
158620f4b53cSBarry Smith   Logically Collective
1587863027abSJed Brown 
1588863027abSJed Brown   Input Parameters:
1589863027abSJed Brown + dm    - the `DM`
1590863027abSJed Brown - btype - block by topological point or field node
1591863027abSJed Brown 
159220f4b53cSBarry Smith   Options Database Key:
15930e762ea3SJed Brown . -dm_blocking_type [topological_point, field_node] - use topological point blocking or field node blocking
1594863027abSJed Brown 
159520f4b53cSBarry Smith   Level: advanced
159620f4b53cSBarry Smith 
15971cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `MatSetVariableBlockSizes()`
1598863027abSJed Brown @*/
1599863027abSJed Brown PetscErrorCode DMSetBlockingType(DM dm, DMBlockingType btype)
1600863027abSJed Brown {
1601863027abSJed Brown   PetscFunctionBegin;
1602863027abSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1603863027abSJed Brown   dm->blocking_type = btype;
16043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1605863027abSJed Brown }
1606863027abSJed Brown 
1607863027abSJed Brown /*@
1608863027abSJed Brown   DMGetBlockingType - get the blocking granularity to be used for variable block size `DMCreateMatrix()` is called
1609863027abSJed Brown 
1610863027abSJed Brown   Not Collective
1611863027abSJed Brown 
16122fe279fdSBarry Smith   Input Parameter:
1613863027abSJed Brown . dm - the `DM`
1614863027abSJed Brown 
16152fe279fdSBarry Smith   Output Parameter:
1616863027abSJed Brown . btype - block by topological point or field node
1617863027abSJed Brown 
1618863027abSJed Brown   Level: advanced
1619863027abSJed Brown 
16201cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateMatrix()`, `MatSetVariableBlockSizes()`
1621863027abSJed Brown @*/
1622863027abSJed Brown PetscErrorCode DMGetBlockingType(DM dm, DMBlockingType *btype)
1623863027abSJed Brown {
1624863027abSJed Brown   PetscFunctionBegin;
1625863027abSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
16264f572ea9SToby Isaac   PetscAssertPointer(btype, 2);
1627863027abSJed Brown   *btype = dm->blocking_type;
16283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1629863027abSJed Brown }
1630863027abSJed Brown 
1631a89ea682SMatthew G Knepley /*@C
1632bb7acecfSBarry Smith   DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with `DMRestoreWorkArray()`
1633a89ea682SMatthew G Knepley 
1634a89ea682SMatthew G Knepley   Not Collective
1635a89ea682SMatthew G Knepley 
1636a89ea682SMatthew G Knepley   Input Parameters:
1637bb7acecfSBarry Smith + dm    - the `DM` object
1638a5b23f4aSJose E. Roman . count - The minimum size
163920f4b53cSBarry Smith - dtype - MPI data type, often `MPIU_REAL`, `MPIU_SCALAR`, or `MPIU_INT`)
1640a89ea682SMatthew G Knepley 
1641a89ea682SMatthew G Knepley   Output Parameter:
164260225df5SJacob Faibussowitsch . mem - the work array
1643a89ea682SMatthew G Knepley 
1644a89ea682SMatthew G Knepley   Level: developer
1645a89ea682SMatthew G Knepley 
1646bb7acecfSBarry Smith   Note:
1647da81f932SPierre Jolivet   A `DM` may stash the array between instantiations so using this routine may be more efficient than calling `PetscMalloc()`
1648bb7acecfSBarry Smith 
1649bb7acecfSBarry Smith   The array may contain nonzero values
1650bb7acecfSBarry Smith 
16511cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMRestoreWorkArray()`, `PetscMalloc()`
1652a89ea682SMatthew G Knepley @*/
1653d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetWorkArray(DM dm, PetscInt count, MPI_Datatype dtype, void *mem)
1654d71ae5a4SJacob Faibussowitsch {
1655aa1993deSMatthew G Knepley   DMWorkLink  link;
165669291d52SBarry Smith   PetscMPIInt dsize;
1657a89ea682SMatthew G Knepley 
1658a89ea682SMatthew G Knepley   PetscFunctionBegin;
1659a89ea682SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
16604f572ea9SToby Isaac   PetscAssertPointer(mem, 4);
1661442f3b32SStefano Zampini   if (!count) {
1662442f3b32SStefano Zampini     *(void **)mem = NULL;
1663442f3b32SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
1664442f3b32SStefano Zampini   }
1665aa1993deSMatthew G Knepley   if (dm->workin) {
1666aa1993deSMatthew G Knepley     link       = dm->workin;
1667aa1993deSMatthew G Knepley     dm->workin = dm->workin->next;
1668aa1993deSMatthew G Knepley   } else {
16694dfa11a4SJacob Faibussowitsch     PetscCall(PetscNew(&link));
1670a89ea682SMatthew G Knepley   }
1671b77fa653SStefano Zampini   /* Avoid MPI_Type_size for most used datatypes
1672b77fa653SStefano Zampini      Get size directly */
1673b77fa653SStefano Zampini   if (dtype == MPIU_INT) dsize = sizeof(PetscInt);
1674b77fa653SStefano Zampini   else if (dtype == MPIU_REAL) dsize = sizeof(PetscReal);
1675b77fa653SStefano Zampini #if defined(PETSC_USE_64BIT_INDICES)
1676b77fa653SStefano Zampini   else if (dtype == MPI_INT) dsize = sizeof(int);
1677b77fa653SStefano Zampini #endif
1678b77fa653SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1679b77fa653SStefano Zampini   else if (dtype == MPIU_SCALAR) dsize = sizeof(PetscScalar);
1680b77fa653SStefano Zampini #endif
1681b77fa653SStefano Zampini   else PetscCallMPI(MPI_Type_size(dtype, &dsize));
1682b77fa653SStefano Zampini 
16835056fcd2SBarry Smith   if (((size_t)dsize * count) > link->bytes) {
16849566063dSJacob Faibussowitsch     PetscCall(PetscFree(link->mem));
16859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(dsize * count, &link->mem));
1686854ce69bSBarry Smith     link->bytes = dsize * count;
1687aa1993deSMatthew G Knepley   }
1688aa1993deSMatthew G Knepley   link->next  = dm->workout;
1689aa1993deSMatthew G Knepley   dm->workout = link;
1690cea3dcb8SSatish Balay #if defined(__MEMCHECK_H) && (defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) || defined(PLAT_amd64_darwin))
169100d952a4SJed Brown   VALGRIND_MAKE_MEM_NOACCESS((char *)link->mem + (size_t)dsize * count, link->bytes - (size_t)dsize * count);
169200d952a4SJed Brown   VALGRIND_MAKE_MEM_UNDEFINED(link->mem, (size_t)dsize * count);
169300d952a4SJed Brown #endif
1694aa1993deSMatthew G Knepley   *(void **)mem = link->mem;
16953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1696a89ea682SMatthew G Knepley }
1697a89ea682SMatthew G Knepley 
1698aa1993deSMatthew G Knepley /*@C
1699bb7acecfSBarry Smith   DMRestoreWorkArray - Restores a work array obtained with `DMCreateWorkArray()`
1700aa1993deSMatthew G Knepley 
1701aa1993deSMatthew G Knepley   Not Collective
1702aa1993deSMatthew G Knepley 
1703aa1993deSMatthew G Knepley   Input Parameters:
1704bb7acecfSBarry Smith + dm    - the `DM` object
1705a5b23f4aSJose E. Roman . count - The minimum size
170620f4b53cSBarry Smith - dtype - MPI data type, often `MPIU_REAL`, `MPIU_SCALAR`, `MPIU_INT`
1707aa1993deSMatthew G Knepley 
1708aa1993deSMatthew G Knepley   Output Parameter:
170960225df5SJacob Faibussowitsch . mem - the work array
1710aa1993deSMatthew G Knepley 
1711aa1993deSMatthew G Knepley   Level: developer
1712aa1993deSMatthew G Knepley 
171360225df5SJacob Faibussowitsch   Developer Notes:
1714bb7acecfSBarry Smith   count and dtype are ignored, they are only needed for `DMGetWorkArray()`
1715147403d9SBarry Smith 
17161cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDestroy()`, `DMCreate()`, `DMGetWorkArray()`
1717aa1993deSMatthew G Knepley @*/
1718d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestoreWorkArray(DM dm, PetscInt count, MPI_Datatype dtype, void *mem)
1719d71ae5a4SJacob Faibussowitsch {
1720aa1993deSMatthew G Knepley   DMWorkLink *p, link;
1721aa1993deSMatthew G Knepley 
1722aa1993deSMatthew G Knepley   PetscFunctionBegin;
1723aa1993deSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17244f572ea9SToby Isaac   PetscAssertPointer(mem, 4);
1725a4e35b19SJacob Faibussowitsch   (void)count;
1726a4e35b19SJacob Faibussowitsch   (void)dtype;
1727442f3b32SStefano Zampini   if (!*(void **)mem) PetscFunctionReturn(PETSC_SUCCESS);
1728aa1993deSMatthew G Knepley   for (p = &dm->workout; (link = *p); p = &link->next) {
1729aa1993deSMatthew G Knepley     if (link->mem == *(void **)mem) {
1730aa1993deSMatthew G Knepley       *p            = link->next;
1731aa1993deSMatthew G Knepley       link->next    = dm->workin;
1732aa1993deSMatthew G Knepley       dm->workin    = link;
17330298fd71SBarry Smith       *(void **)mem = NULL;
17343ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
1735aa1993deSMatthew G Knepley     }
1736aa1993deSMatthew G Knepley   }
1737aa1993deSMatthew G Knepley   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Array was not checked out");
1738aa1993deSMatthew G Knepley }
1739e7c4fc90SDmitry Karpeev 
17408cda7954SMatthew G. Knepley /*@C
1741bb7acecfSBarry Smith   DMSetNullSpaceConstructor - Provide a callback function which constructs the nullspace for a given field, defined with `DMAddField()`, when function spaces
1742bb7acecfSBarry Smith   are joined or split, such as in `DMCreateSubDM()`
17438cda7954SMatthew G. Knepley 
174420f4b53cSBarry Smith   Logically Collective; No Fortran Support
17458cda7954SMatthew G. Knepley 
17468cda7954SMatthew G. Knepley   Input Parameters:
1747bb7acecfSBarry Smith + dm     - The `DM`
17488cda7954SMatthew G. Knepley . field  - The field number for the nullspace
17498cda7954SMatthew G. Knepley - nullsp - A callback to create the nullspace
17508cda7954SMatthew G. Knepley 
175120f4b53cSBarry Smith   Calling sequence of `nullsp`:
1752bb7acecfSBarry Smith + dm        - The present `DM`
1753bb7acecfSBarry Smith . origField - The field number given above, in the original `DM`
1754147403d9SBarry Smith . field     - The field number in dm
1755147403d9SBarry Smith - nullSpace - The nullspace for the given field
17568cda7954SMatthew G. Knepley 
175749762cbcSSatish Balay   Level: intermediate
175849762cbcSSatish Balay 
17591cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetNullSpaceConstructor()`, `DMSetNearNullSpaceConstructor()`, `DMGetNearNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
1760147403d9SBarry Smith @*/
1761a4e35b19SJacob Faibussowitsch PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1762d71ae5a4SJacob Faibussowitsch {
1763435a35e8SMatthew G Knepley   PetscFunctionBegin;
1764435a35e8SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17657a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1766435a35e8SMatthew G Knepley   dm->nullspaceConstructors[field] = nullsp;
17673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1768435a35e8SMatthew G Knepley }
1769435a35e8SMatthew G Knepley 
17708cda7954SMatthew G. Knepley /*@C
1771bb7acecfSBarry Smith   DMGetNullSpaceConstructor - Return the callback function which constructs the nullspace for a given field, defined with `DMAddField()`
17728cda7954SMatthew G. Knepley 
177320f4b53cSBarry Smith   Not Collective; No Fortran Support
17748cda7954SMatthew G. Knepley 
17758cda7954SMatthew G. Knepley   Input Parameters:
1776bb7acecfSBarry Smith + dm    - The `DM`
17778cda7954SMatthew G. Knepley - field - The field number for the nullspace
17788cda7954SMatthew G. Knepley 
17798cda7954SMatthew G. Knepley   Output Parameter:
17808cda7954SMatthew G. Knepley . nullsp - A callback to create the nullspace
17818cda7954SMatthew G. Knepley 
178220f4b53cSBarry Smith   Calling sequence of `nullsp`:
1783147403d9SBarry Smith + dm        - The present DM
1784147403d9SBarry Smith . origField - The field number given above, in the original DM
1785147403d9SBarry Smith . field     - The field number in dm
1786147403d9SBarry Smith - nullSpace - The nullspace for the given field
17878cda7954SMatthew G. Knepley 
178849762cbcSSatish Balay   Level: intermediate
178949762cbcSSatish Balay 
17901cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMSetNullSpaceConstructor()`, `DMSetNearNullSpaceConstructor()`, `DMGetNearNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
1791147403d9SBarry Smith @*/
1792a4e35b19SJacob Faibussowitsch PetscErrorCode DMGetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1793d71ae5a4SJacob Faibussowitsch {
17940a50eb56SMatthew G. Knepley   PetscFunctionBegin;
17950a50eb56SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17964f572ea9SToby Isaac   PetscAssertPointer(nullsp, 3);
17977a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
17980a50eb56SMatthew G. Knepley   *nullsp = dm->nullspaceConstructors[field];
17993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18000a50eb56SMatthew G. Knepley }
18010a50eb56SMatthew G. Knepley 
18028cda7954SMatthew G. Knepley /*@C
1803bb7acecfSBarry Smith   DMSetNearNullSpaceConstructor - Provide a callback function which constructs the near-nullspace for a given field, defined with `DMAddField()`
18048cda7954SMatthew G. Knepley 
180520f4b53cSBarry Smith   Logically Collective; No Fortran Support
18068cda7954SMatthew G. Knepley 
18078cda7954SMatthew G. Knepley   Input Parameters:
1808bb7acecfSBarry Smith + dm     - The `DM`
18098cda7954SMatthew G. Knepley . field  - The field number for the nullspace
18108cda7954SMatthew G. Knepley - nullsp - A callback to create the near-nullspace
18118cda7954SMatthew G. Knepley 
181220f4b53cSBarry Smith   Calling sequence of `nullsp`:
1813bb7acecfSBarry Smith + dm        - The present `DM`
1814bb7acecfSBarry Smith . origField - The field number given above, in the original `DM`
1815147403d9SBarry Smith . field     - The field number in dm
1816147403d9SBarry Smith - nullSpace - The nullspace for the given field
18178cda7954SMatthew G. Knepley 
181849762cbcSSatish Balay   Level: intermediate
181949762cbcSSatish Balay 
18201cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetNearNullSpaceConstructor()`, `DMSetNullSpaceConstructor()`, `DMGetNullSpaceConstructor()`, `DMCreateSubDM()`, `DMCreateSuperDM()`,
1821bb7acecfSBarry Smith           `MatNullSpace`
1822147403d9SBarry Smith @*/
1823a4e35b19SJacob Faibussowitsch PetscErrorCode DMSetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1824d71ae5a4SJacob Faibussowitsch {
1825f9d4088aSMatthew G. Knepley   PetscFunctionBegin;
1826f9d4088aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18277a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1828f9d4088aSMatthew G. Knepley   dm->nearnullspaceConstructors[field] = nullsp;
18293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1830f9d4088aSMatthew G. Knepley }
1831f9d4088aSMatthew G. Knepley 
18328cda7954SMatthew G. Knepley /*@C
1833bb7acecfSBarry Smith   DMGetNearNullSpaceConstructor - Return the callback function which constructs the near-nullspace for a given field, defined with `DMAddField()`
18348cda7954SMatthew G. Knepley 
183520f4b53cSBarry Smith   Not Collective; No Fortran Support
18368cda7954SMatthew G. Knepley 
18378cda7954SMatthew G. Knepley   Input Parameters:
1838bb7acecfSBarry Smith + dm    - The `DM`
18398cda7954SMatthew G. Knepley - field - The field number for the nullspace
18408cda7954SMatthew G. Knepley 
18418cda7954SMatthew G. Knepley   Output Parameter:
18428cda7954SMatthew G. Knepley . nullsp - A callback to create the near-nullspace
18438cda7954SMatthew G. Knepley 
184420f4b53cSBarry Smith   Calling sequence of `nullsp`:
1845bb7acecfSBarry Smith + dm        - The present `DM`
1846bb7acecfSBarry Smith . origField - The field number given above, in the original `DM`
1847147403d9SBarry Smith . field     - The field number in dm
1848147403d9SBarry Smith - nullSpace - The nullspace for the given field
18498cda7954SMatthew G. Knepley 
185049762cbcSSatish Balay   Level: intermediate
185149762cbcSSatish Balay 
18521cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMSetNearNullSpaceConstructor()`, `DMSetNullSpaceConstructor()`, `DMGetNullSpaceConstructor()`, `DMCreateSubDM()`,
1853bb7acecfSBarry Smith           `MatNullSpace`, `DMCreateSuperDM()`
1854147403d9SBarry Smith @*/
1855a4e35b19SJacob Faibussowitsch PetscErrorCode DMGetNearNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (**nullsp)(DM dm, PetscInt origField, PetscInt field, MatNullSpace *nullSpace))
1856d71ae5a4SJacob Faibussowitsch {
1857f9d4088aSMatthew G. Knepley   PetscFunctionBegin;
1858f9d4088aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18594f572ea9SToby Isaac   PetscAssertPointer(nullsp, 3);
18607a8be351SBarry Smith   PetscCheck(field < 10, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %" PetscInt_FMT " >= 10 fields", field);
1861f9d4088aSMatthew G. Knepley   *nullsp = dm->nearnullspaceConstructors[field];
18623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1863f9d4088aSMatthew G. Knepley }
1864f9d4088aSMatthew G. Knepley 
18654f3b5142SJed Brown /*@C
1866bb7acecfSBarry Smith   DMCreateFieldIS - Creates a set of `IS` objects with the global indices of dofs for each field defined with `DMAddField()`
18674d343eeaSMatthew G Knepley 
186820f4b53cSBarry Smith   Not Collective; No Fortran Support
18694d343eeaSMatthew G Knepley 
18704d343eeaSMatthew G Knepley   Input Parameter:
1871bb7acecfSBarry Smith . dm - the `DM` object
18724d343eeaSMatthew G Knepley 
18734d343eeaSMatthew G Knepley   Output Parameters:
187420f4b53cSBarry Smith + numFields  - The number of fields (or `NULL` if not requested)
187520f4b53cSBarry Smith . fieldNames - The number of each field (or `NULL` if not requested)
187620f4b53cSBarry Smith - fields     - The global indices for each field (or `NULL` if not requested)
18774d343eeaSMatthew G Knepley 
18784d343eeaSMatthew G Knepley   Level: intermediate
18794d343eeaSMatthew G Knepley 
1880bb7acecfSBarry Smith   Note:
188121c9b008SJed Brown   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
1882bb7acecfSBarry Smith   `PetscFree()`, every entry of fields should be destroyed with `ISDestroy()`, and both arrays should be freed with
1883bb7acecfSBarry Smith   `PetscFree()`.
188421c9b008SJed Brown 
188560225df5SJacob Faibussowitsch   Developer Notes:
1886bb7acecfSBarry Smith   It is not clear why both this function and `DMCreateFieldDecomposition()` exist. Having two seems redundant and confusing. This function should
1887bb7acecfSBarry Smith   likely be removed.
1888bb7acecfSBarry Smith 
18891cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`,
1890bb7acecfSBarry Smith           `DMCreateFieldDecomposition()`
18914d343eeaSMatthew G Knepley @*/
1892d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1893d71ae5a4SJacob Faibussowitsch {
189437d0c07bSMatthew G Knepley   PetscSection section, sectionGlobal;
18954d343eeaSMatthew G Knepley 
18964d343eeaSMatthew G Knepley   PetscFunctionBegin;
18974d343eeaSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
189869ca1f37SDmitry Karpeev   if (numFields) {
18994f572ea9SToby Isaac     PetscAssertPointer(numFields, 2);
190069ca1f37SDmitry Karpeev     *numFields = 0;
190169ca1f37SDmitry Karpeev   }
190237d0c07bSMatthew G Knepley   if (fieldNames) {
19034f572ea9SToby Isaac     PetscAssertPointer(fieldNames, 3);
19040298fd71SBarry Smith     *fieldNames = NULL;
190569ca1f37SDmitry Karpeev   }
190669ca1f37SDmitry Karpeev   if (fields) {
19074f572ea9SToby Isaac     PetscAssertPointer(fields, 4);
19080298fd71SBarry Smith     *fields = NULL;
190969ca1f37SDmitry Karpeev   }
19109566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
191137d0c07bSMatthew G Knepley   if (section) {
19123a544194SStefano Zampini     PetscInt *fieldSizes, *fieldNc, **fieldIndices;
191337d0c07bSMatthew G Knepley     PetscInt  nF, f, pStart, pEnd, p;
191437d0c07bSMatthew G Knepley 
19159566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
19169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &nF));
19179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(nF, &fieldSizes, nF, &fieldNc, nF, &fieldIndices));
19189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
191937d0c07bSMatthew G Knepley     for (f = 0; f < nF; ++f) {
192037d0c07bSMatthew G Knepley       fieldSizes[f] = 0;
19219566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &fieldNc[f]));
192237d0c07bSMatthew G Knepley     }
192337d0c07bSMatthew G Knepley     for (p = pStart; p < pEnd; ++p) {
192437d0c07bSMatthew G Knepley       PetscInt gdof;
192537d0c07bSMatthew G Knepley 
19269566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
192737d0c07bSMatthew G Knepley       if (gdof > 0) {
192837d0c07bSMatthew G Knepley         for (f = 0; f < nF; ++f) {
19293a544194SStefano Zampini           PetscInt fdof, fcdof, fpdof;
193037d0c07bSMatthew G Knepley 
19319566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
19329566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
19333a544194SStefano Zampini           fpdof = fdof - fcdof;
19343a544194SStefano Zampini           if (fpdof && fpdof != fieldNc[f]) {
19353a544194SStefano Zampini             /* Layout does not admit a pointwise block size */
19363a544194SStefano Zampini             fieldNc[f] = 1;
19373a544194SStefano Zampini           }
19383a544194SStefano Zampini           fieldSizes[f] += fpdof;
193937d0c07bSMatthew G Knepley         }
194037d0c07bSMatthew G Knepley       }
194137d0c07bSMatthew G Knepley     }
194237d0c07bSMatthew G Knepley     for (f = 0; f < nF; ++f) {
19439566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(fieldSizes[f], &fieldIndices[f]));
194437d0c07bSMatthew G Knepley       fieldSizes[f] = 0;
194537d0c07bSMatthew G Knepley     }
194637d0c07bSMatthew G Knepley     for (p = pStart; p < pEnd; ++p) {
194737d0c07bSMatthew G Knepley       PetscInt gdof, goff;
194837d0c07bSMatthew G Knepley 
19499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
195037d0c07bSMatthew G Knepley       if (gdof > 0) {
19519566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff));
195237d0c07bSMatthew G Knepley         for (f = 0; f < nF; ++f) {
195337d0c07bSMatthew G Knepley           PetscInt fdof, fcdof, fc;
195437d0c07bSMatthew G Knepley 
19559566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
19569566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
1957ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++fieldSizes[f]) fieldIndices[f][fieldSizes[f]] = goff++;
195837d0c07bSMatthew G Knepley         }
195937d0c07bSMatthew G Knepley       }
196037d0c07bSMatthew G Knepley     }
19618865f1eaSKarl Rupp     if (numFields) *numFields = nF;
196237d0c07bSMatthew G Knepley     if (fieldNames) {
19639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nF, fieldNames));
196437d0c07bSMatthew G Knepley       for (f = 0; f < nF; ++f) {
196537d0c07bSMatthew G Knepley         const char *fieldName;
196637d0c07bSMatthew G Knepley 
19679566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
19689566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(fieldName, (char **)&(*fieldNames)[f]));
196937d0c07bSMatthew G Knepley       }
197037d0c07bSMatthew G Knepley     }
197137d0c07bSMatthew G Knepley     if (fields) {
19729566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nF, fields));
197337d0c07bSMatthew G Knepley       for (f = 0; f < nF; ++f) {
19743a544194SStefano Zampini         PetscInt bs, in[2], out[2];
19753a544194SStefano Zampini 
19769566063dSJacob Faibussowitsch         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]));
19773a544194SStefano Zampini         in[0] = -fieldNc[f];
19783a544194SStefano Zampini         in[1] = fieldNc[f];
19791c2dc1cbSBarry Smith         PetscCall(MPIU_Allreduce(in, out, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
19803a544194SStefano Zampini         bs = (-out[0] == out[1]) ? out[1] : 1;
19819566063dSJacob Faibussowitsch         PetscCall(ISSetBlockSize((*fields)[f], bs));
198237d0c07bSMatthew G Knepley       }
198337d0c07bSMatthew G Knepley     }
19849566063dSJacob Faibussowitsch     PetscCall(PetscFree3(fieldSizes, fieldNc, fieldIndices));
1985dbbe0bcdSBarry Smith   } else PetscTryTypeMethod(dm, createfieldis, numFields, fieldNames, fields);
19863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19874d343eeaSMatthew G Knepley }
19884d343eeaSMatthew G Knepley 
198916621825SDmitry Karpeev /*@C
1990bb7acecfSBarry Smith   DMCreateFieldDecomposition - Returns a list of `IS` objects defining a decomposition of a problem into subproblems
1991a4e35b19SJacob Faibussowitsch   corresponding to different fields.
1992e7c4fc90SDmitry Karpeev 
199320f4b53cSBarry Smith   Not Collective; No Fortran Support
1994e7c4fc90SDmitry Karpeev 
1995e7c4fc90SDmitry Karpeev   Input Parameter:
1996bb7acecfSBarry Smith . dm - the `DM` object
1997e7c4fc90SDmitry Karpeev 
1998e7c4fc90SDmitry Karpeev   Output Parameters:
199920f4b53cSBarry Smith + len      - The number of fields (or `NULL` if not requested)
200020f4b53cSBarry Smith . namelist - The name for each field (or `NULL` if not requested)
200120f4b53cSBarry Smith . islist   - The global indices for each field (or `NULL` if not requested)
200220f4b53cSBarry Smith - dmlist   - The `DM`s for each field subproblem (or `NULL`, if not requested; if `NULL` is returned, no `DM`s are defined)
2003e7c4fc90SDmitry Karpeev 
2004e7c4fc90SDmitry Karpeev   Level: intermediate
2005e7c4fc90SDmitry Karpeev 
2006a4e35b19SJacob Faibussowitsch   Notes:
2007a4e35b19SJacob Faibussowitsch   Each `IS` contains the global indices of the dofs of the corresponding field, defined by
2008a4e35b19SJacob Faibussowitsch   `DMAddField()`. The optional list of `DM`s define the `DM` for each subproblem.
2009a4e35b19SJacob Faibussowitsch 
2010a4e35b19SJacob Faibussowitsch   The same as `DMCreateFieldIS()` but also returns a `DM` for each field.
2011a4e35b19SJacob Faibussowitsch 
2012e7c4fc90SDmitry Karpeev   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
2013bb7acecfSBarry Smith   `PetscFree()`, every entry of is should be destroyed with `ISDestroy()`, every entry of dm should be destroyed with `DMDestroy()`,
2014bb7acecfSBarry Smith   and all of the arrays should be freed with `PetscFree()`.
2015e7c4fc90SDmitry Karpeev 
201660225df5SJacob Faibussowitsch   Developer Notes:
2017bb7acecfSBarry Smith   It is not clear why this function and `DMCreateFieldIS()` exist. Having two seems redundant and confusing.
2018bb7acecfSBarry Smith 
201960225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMCreateFieldIS()`, `DMCreateSubDM()`, `DMCreateDomainDecomposition()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
2020e7c4fc90SDmitry Karpeev @*/
2021d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
2022d71ae5a4SJacob Faibussowitsch {
2023e7c4fc90SDmitry Karpeev   PetscFunctionBegin;
2024e7c4fc90SDmitry Karpeev   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20258865f1eaSKarl Rupp   if (len) {
20264f572ea9SToby Isaac     PetscAssertPointer(len, 2);
20278865f1eaSKarl Rupp     *len = 0;
20288865f1eaSKarl Rupp   }
20298865f1eaSKarl Rupp   if (namelist) {
20304f572ea9SToby Isaac     PetscAssertPointer(namelist, 3);
2031ea78f98cSLisandro Dalcin     *namelist = NULL;
20328865f1eaSKarl Rupp   }
20338865f1eaSKarl Rupp   if (islist) {
20344f572ea9SToby Isaac     PetscAssertPointer(islist, 4);
2035ea78f98cSLisandro Dalcin     *islist = NULL;
20368865f1eaSKarl Rupp   }
20378865f1eaSKarl Rupp   if (dmlist) {
20384f572ea9SToby Isaac     PetscAssertPointer(dmlist, 5);
2039ea78f98cSLisandro Dalcin     *dmlist = NULL;
20408865f1eaSKarl Rupp   }
2041f3f0edfdSDmitry Karpeev   /*
2042f3f0edfdSDmitry Karpeev    Is it a good idea to apply the following check across all impls?
2043f3f0edfdSDmitry Karpeev    Perhaps some impls can have a well-defined decomposition before DMSetUp?
2044f3f0edfdSDmitry Karpeev    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
2045f3f0edfdSDmitry Karpeev    */
20467a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
204716621825SDmitry Karpeev   if (!dm->ops->createfielddecomposition) {
2048435a35e8SMatthew G Knepley     PetscSection section;
2049435a35e8SMatthew G Knepley     PetscInt     numFields, f;
2050435a35e8SMatthew G Knepley 
20519566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
20529566063dSJacob Faibussowitsch     if (section) PetscCall(PetscSectionGetNumFields(section, &numFields));
2053435a35e8SMatthew G Knepley     if (section && numFields && dm->ops->createsubdm) {
2054f25d98f1SMatthew G. Knepley       if (len) *len = numFields;
20559566063dSJacob Faibussowitsch       if (namelist) PetscCall(PetscMalloc1(numFields, namelist));
20569566063dSJacob Faibussowitsch       if (islist) PetscCall(PetscMalloc1(numFields, islist));
20579566063dSJacob Faibussowitsch       if (dmlist) PetscCall(PetscMalloc1(numFields, dmlist));
2058435a35e8SMatthew G Knepley       for (f = 0; f < numFields; ++f) {
2059435a35e8SMatthew G Knepley         const char *fieldName;
2060435a35e8SMatthew G Knepley 
20619566063dSJacob Faibussowitsch         PetscCall(DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL));
206203dc3394SMatthew G. Knepley         if (namelist) {
20639566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldName(section, f, &fieldName));
20649566063dSJacob Faibussowitsch           PetscCall(PetscStrallocpy(fieldName, (char **)&(*namelist)[f]));
2065435a35e8SMatthew G Knepley         }
206603dc3394SMatthew G. Knepley       }
2067435a35e8SMatthew G Knepley     } else {
20689566063dSJacob Faibussowitsch       PetscCall(DMCreateFieldIS(dm, len, namelist, islist));
2069e7c4fc90SDmitry Karpeev       /* By default there are no DMs associated with subproblems. */
20700298fd71SBarry Smith       if (dmlist) *dmlist = NULL;
2071e7c4fc90SDmitry Karpeev     }
2072dbbe0bcdSBarry Smith   } else PetscUseTypeMethod(dm, createfielddecomposition, len, namelist, islist, dmlist);
20733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207416621825SDmitry Karpeev }
207516621825SDmitry Karpeev 
2076412a4547SAlexis Marboeuf /*@C
207720f4b53cSBarry Smith   DMCreateSubDM - Returns an `IS` and `DM` encapsulating a subproblem defined by the fields passed in.
207820f4b53cSBarry Smith   The fields are defined by `DMCreateFieldIS()`.
2079435a35e8SMatthew G Knepley 
2080435a35e8SMatthew G Knepley   Not collective
2081435a35e8SMatthew G Knepley 
2082435a35e8SMatthew G Knepley   Input Parameters:
2083bb7acecfSBarry Smith + dm        - The `DM` object
2084bb7acecfSBarry Smith . numFields - The number of fields to select
20852adcc780SMatthew G. Knepley - fields    - The field numbers of the selected fields
2086435a35e8SMatthew G Knepley 
2087435a35e8SMatthew G Knepley   Output Parameters:
2088bb7acecfSBarry Smith + is    - The global indices for all the degrees of freedom in the new sub `DM`
2089bb7acecfSBarry Smith - subdm - The `DM` for the subproblem
2090435a35e8SMatthew G Knepley 
209120f4b53cSBarry Smith   Level: intermediate
209220f4b53cSBarry Smith 
2093bb7acecfSBarry Smith   Note:
2094bb7acecfSBarry Smith   You need to call `DMPlexSetMigrationSF()` on the original `DM` if you want the Global-To-Natural map to be automatically constructed
20955d3b26e6SMatthew G. Knepley 
209660225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateFieldIS()`, `DMCreateFieldDecomposition()`, `DMAddField()`, `DMCreateSuperDM()`, `IS`, `DMPlexSetMigrationSF()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
2097435a35e8SMatthew G Knepley @*/
2098d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
2099d71ae5a4SJacob Faibussowitsch {
2100435a35e8SMatthew G Knepley   PetscFunctionBegin;
2101435a35e8SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21024f572ea9SToby Isaac   PetscAssertPointer(fields, 3);
21034f572ea9SToby Isaac   if (is) PetscAssertPointer(is, 4);
21044f572ea9SToby Isaac   if (subdm) PetscAssertPointer(subdm, 5);
2105dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createsubdm, numFields, fields, is, subdm);
21063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2107435a35e8SMatthew G Knepley }
2108435a35e8SMatthew G Knepley 
21092adcc780SMatthew G. Knepley /*@C
2110bb7acecfSBarry Smith   DMCreateSuperDM - Returns an arrays of `IS` and `DM` encapsulating a superproblem defined by multiple `DM`s passed in.
21112adcc780SMatthew G. Knepley 
21122adcc780SMatthew G. Knepley   Not collective
21132adcc780SMatthew G. Knepley 
2114d8d19677SJose E. Roman   Input Parameters:
2115bb7acecfSBarry Smith + dms - The `DM` objects
2116bb7acecfSBarry Smith - n   - The number of `DM`s
21172adcc780SMatthew G. Knepley 
21182adcc780SMatthew G. Knepley   Output Parameters:
2119bb7acecfSBarry Smith + is      - The global indices for each of subproblem within the super `DM`, or NULL
2120bb7acecfSBarry Smith - superdm - The `DM` for the superproblem
21212adcc780SMatthew G. Knepley 
212220f4b53cSBarry Smith   Level: intermediate
212320f4b53cSBarry Smith 
2124bb7acecfSBarry Smith   Note:
2125bb7acecfSBarry Smith   You need to call `DMPlexSetMigrationSF()` on the original `DM` if you want the Global-To-Natural map to be automatically constructed
21265d3b26e6SMatthew G. Knepley 
21271cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateSubDM()`, `DMPlexSetMigrationSF()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
21282adcc780SMatthew G. Knepley @*/
2129d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM(DM dms[], PetscInt n, IS **is, DM *superdm)
2130d71ae5a4SJacob Faibussowitsch {
21312adcc780SMatthew G. Knepley   PetscInt i;
21322adcc780SMatthew G. Knepley 
21332adcc780SMatthew G. Knepley   PetscFunctionBegin;
21344f572ea9SToby Isaac   PetscAssertPointer(dms, 1);
2135ad540459SPierre Jolivet   for (i = 0; i < n; ++i) PetscValidHeaderSpecific(dms[i], DM_CLASSID, 1);
21364f572ea9SToby Isaac   if (is) PetscAssertPointer(is, 3);
21374f572ea9SToby Isaac   PetscAssertPointer(superdm, 4);
2138bb7acecfSBarry Smith   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of DMs must be nonnegative: %" PetscInt_FMT, n);
2139bb7acecfSBarry Smith   if (n) {
2140b9d85ea2SLisandro Dalcin     DM dm = dms[0];
2141*fa1e479aSStefano Zampini     PetscCheck(dm->ops->createsuperdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No method createsuperdm for DM of type %s\n", ((PetscObject)dm)->type_name);
2142dbbe0bcdSBarry Smith     PetscCall((*dm->ops->createsuperdm)(dms, n, is, superdm));
21432adcc780SMatthew G. Knepley   }
21443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21452adcc780SMatthew G. Knepley }
21462adcc780SMatthew G. Knepley 
214716621825SDmitry Karpeev /*@C
2148a4e35b19SJacob Faibussowitsch   DMCreateDomainDecomposition - Returns lists of `IS` objects defining a decomposition of a
2149a4e35b19SJacob Faibussowitsch   problem into subproblems corresponding to restrictions to pairs of nested subdomains.
215016621825SDmitry Karpeev 
215120f4b53cSBarry Smith   Not Collective
215216621825SDmitry Karpeev 
215316621825SDmitry Karpeev   Input Parameter:
2154bb7acecfSBarry Smith . dm - the `DM` object
215516621825SDmitry Karpeev 
215616621825SDmitry Karpeev   Output Parameters:
215720f4b53cSBarry Smith + n           - The number of subproblems in the domain decomposition (or `NULL` if not requested)
215820f4b53cSBarry Smith . namelist    - The name for each subdomain (or `NULL` if not requested)
21590298fd71SBarry Smith . innerislist - The global indices for each inner subdomain (or NULL, if not requested)
21600298fd71SBarry Smith . outerislist - The global indices for each outer subdomain (or NULL, if not requested)
216120f4b53cSBarry Smith - dmlist      - The `DM`s for each subdomain subproblem (or NULL, if not requested; if `NULL` is returned, no `DM`s are defined)
216216621825SDmitry Karpeev 
216316621825SDmitry Karpeev   Level: intermediate
216416621825SDmitry Karpeev 
2165bb7acecfSBarry Smith   Note:
2166a4e35b19SJacob Faibussowitsch   Each `IS` contains the global indices of the dofs of the corresponding subdomains with in the
2167a4e35b19SJacob Faibussowitsch   dofs of the original `DM`. The inner subdomains conceptually define a nonoverlapping
2168a4e35b19SJacob Faibussowitsch   covering, while outer subdomains can overlap.
2169a4e35b19SJacob Faibussowitsch 
2170a4e35b19SJacob Faibussowitsch   The optional list of `DM`s define a `DM` for each subproblem.
2171a4e35b19SJacob Faibussowitsch 
217216621825SDmitry Karpeev   The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with
2173bb7acecfSBarry Smith   `PetscFree()`, every entry of is should be destroyed with `ISDestroy()`, every entry of dm should be destroyed with `DMDestroy()`,
2174bb7acecfSBarry Smith   and all of the arrays should be freed with `PetscFree()`.
217516621825SDmitry Karpeev 
2176a4e35b19SJacob Faibussowitsch   Developer Notes:
217720f4b53cSBarry Smith   The `dmlist` is for the inner subdomains or the outer subdomains or all subdomains?
2178bb7acecfSBarry Smith 
217960225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCreateFieldDecomposition()`, `DMDestroy()`, `DMCreateDomainDecompositionScatters()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
218016621825SDmitry Karpeev @*/
2181d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *n, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist)
2182d71ae5a4SJacob Faibussowitsch {
2183be081cd6SPeter Brune   DMSubDomainHookLink link;
2184be081cd6SPeter Brune   PetscInt            i, l;
218516621825SDmitry Karpeev 
218616621825SDmitry Karpeev   PetscFunctionBegin;
218716621825SDmitry Karpeev   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21889371c9d4SSatish Balay   if (n) {
21894f572ea9SToby Isaac     PetscAssertPointer(n, 2);
21909371c9d4SSatish Balay     *n = 0;
21919371c9d4SSatish Balay   }
21929371c9d4SSatish Balay   if (namelist) {
21934f572ea9SToby Isaac     PetscAssertPointer(namelist, 3);
21949371c9d4SSatish Balay     *namelist = NULL;
21959371c9d4SSatish Balay   }
21969371c9d4SSatish Balay   if (innerislist) {
21974f572ea9SToby Isaac     PetscAssertPointer(innerislist, 4);
21989371c9d4SSatish Balay     *innerislist = NULL;
21999371c9d4SSatish Balay   }
22009371c9d4SSatish Balay   if (outerislist) {
22014f572ea9SToby Isaac     PetscAssertPointer(outerislist, 5);
22029371c9d4SSatish Balay     *outerislist = NULL;
22039371c9d4SSatish Balay   }
22049371c9d4SSatish Balay   if (dmlist) {
22054f572ea9SToby Isaac     PetscAssertPointer(dmlist, 6);
22069371c9d4SSatish Balay     *dmlist = NULL;
22079371c9d4SSatish Balay   }
2208f3f0edfdSDmitry Karpeev   /*
2209f3f0edfdSDmitry Karpeev    Is it a good idea to apply the following check across all impls?
2210f3f0edfdSDmitry Karpeev    Perhaps some impls can have a well-defined decomposition before DMSetUp?
2211f3f0edfdSDmitry Karpeev    This, however, follows the general principle that accessors are not well-behaved until the object is set up.
2212f3f0edfdSDmitry Karpeev    */
22137a8be351SBarry Smith   PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp");
221416621825SDmitry Karpeev   if (dm->ops->createdomaindecomposition) {
2215dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createdomaindecomposition, &l, namelist, innerislist, outerislist, dmlist);
221614a18fd3SPeter Brune     /* copy subdomain hooks and context over to the subdomain DMs */
2217f891f5b9SPatrick Sanan     if (dmlist && *dmlist) {
2218be081cd6SPeter Brune       for (i = 0; i < l; i++) {
2219be081cd6SPeter Brune         for (link = dm->subdomainhook; link; link = link->next) {
22209566063dSJacob Faibussowitsch           if (link->ddhook) PetscCall((*link->ddhook)(dm, (*dmlist)[i], link->ctx));
2221be081cd6SPeter Brune         }
2222648262bbSPatrick Sanan         if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx;
2223e7c4fc90SDmitry Karpeev       }
222414a18fd3SPeter Brune     }
2225bb7acecfSBarry Smith     if (n) *n = l;
222614a18fd3SPeter Brune   }
22273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2228e30e807fSPeter Brune }
2229e30e807fSPeter Brune 
2230e30e807fSPeter Brune /*@C
2231e30e807fSPeter Brune   DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector
2232e30e807fSPeter Brune 
223320f4b53cSBarry Smith   Not Collective
2234e30e807fSPeter Brune 
2235e30e807fSPeter Brune   Input Parameters:
2236bb7acecfSBarry Smith + dm     - the `DM` object
2237e30e807fSPeter Brune . n      - the number of subdomain scatters
2238e30e807fSPeter Brune - subdms - the local subdomains
2239e30e807fSPeter Brune 
2240e30e807fSPeter Brune   Output Parameters:
22416b867d5aSJose E. Roman + iscat - scatter from global vector to nonoverlapping global vector entries on subdomain
2242e30e807fSPeter Brune . oscat - scatter from global vector to overlapping global vector entries on subdomain
2243e30e807fSPeter Brune - gscat - scatter from global vector to local vector on subdomain (fills in ghosts)
2244e30e807fSPeter Brune 
224520f4b53cSBarry Smith   Level: developer
224620f4b53cSBarry Smith 
2247bb7acecfSBarry Smith   Note:
2248bb7acecfSBarry Smith   This is an alternative to the iis and ois arguments in `DMCreateDomainDecomposition()` that allow for the solution
2249e30e807fSPeter Brune   of general nonlinear problems with overlapping subdomain methods.  While merely having index sets that enable subsets
2250e30e807fSPeter Brune   of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of
2251e30e807fSPeter Brune   solution and residual data.
2252e30e807fSPeter Brune 
2253a4e35b19SJacob Faibussowitsch   Developer Notes:
2254a4e35b19SJacob Faibussowitsch   Can the subdms input be anything or are they exactly the `DM` obtained from
2255a4e35b19SJacob Faibussowitsch   `DMCreateDomainDecomposition()`?
2256bb7acecfSBarry Smith 
22571cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateDomainDecomposition()`, `DMDestroy()`, `DMView()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMCreateFieldIS()`
2258e30e807fSPeter Brune @*/
2259d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDomainDecompositionScatters(DM dm, PetscInt n, DM *subdms, VecScatter **iscat, VecScatter **oscat, VecScatter **gscat)
2260d71ae5a4SJacob Faibussowitsch {
2261e30e807fSPeter Brune   PetscFunctionBegin;
2262e30e807fSPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22634f572ea9SToby Isaac   PetscAssertPointer(subdms, 3);
2264dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, createddscatters, n, subdms, iscat, oscat, gscat);
22653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2266e7c4fc90SDmitry Karpeev }
2267e7c4fc90SDmitry Karpeev 
226847c6ae99SBarry Smith /*@
2269bb7acecfSBarry Smith   DMRefine - Refines a `DM` object using a standard nonadaptive refinement of the underlying mesh
227047c6ae99SBarry Smith 
227120f4b53cSBarry Smith   Collective
227247c6ae99SBarry Smith 
2273d8d19677SJose E. Roman   Input Parameters:
2274bb7acecfSBarry Smith + dm   - the `DM` object
2275bb7acecfSBarry Smith - comm - the communicator to contain the new `DM` object (or `MPI_COMM_NULL`)
227647c6ae99SBarry Smith 
227747c6ae99SBarry Smith   Output Parameter:
227820f4b53cSBarry Smith . dmf - the refined `DM`, or `NULL`
2279ae0a1c52SMatthew G Knepley 
228020f4b53cSBarry Smith   Options Database Key:
2281412e9a14SMatthew G. Knepley . -dm_plex_cell_refiner <strategy> - chooses the refinement strategy, e.g. regular, tohex
2282412e9a14SMatthew G. Knepley 
228347c6ae99SBarry Smith   Level: developer
228447c6ae99SBarry Smith 
228520f4b53cSBarry Smith   Note:
228620f4b53cSBarry Smith   If no refinement was done, the return value is `NULL`
228720f4b53cSBarry Smith 
22881cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
228947c6ae99SBarry Smith @*/
2290d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefine(DM dm, MPI_Comm comm, DM *dmf)
2291d71ae5a4SJacob Faibussowitsch {
2292c833c3b5SJed Brown   DMRefineHookLink link;
229347c6ae99SBarry Smith 
229447c6ae99SBarry Smith   PetscFunctionBegin;
2295732e2eb9SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Refine, dm, 0, 0, 0));
2297dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, refine, comm, dmf);
22984057135bSMatthew G Knepley   if (*dmf) {
229943842a1eSJed Brown     (*dmf)->ops->creatematrix = dm->ops->creatematrix;
23008865f1eaSKarl Rupp 
23019566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmf));
23028865f1eaSKarl Rupp 
2303644e2e5bSBarry Smith     (*dmf)->ctx       = dm->ctx;
23040598a293SJed Brown     (*dmf)->leveldown = dm->leveldown;
2305656b349aSBarry Smith     (*dmf)->levelup   = dm->levelup + 1;
23068865f1eaSKarl Rupp 
23079566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmf, dm->mattype));
2308c833c3b5SJed Brown     for (link = dm->refinehook; link; link = link->next) {
23091baa6e33SBarry Smith       if (link->refinehook) PetscCall((*link->refinehook)(dm, *dmf, link->ctx));
2310c833c3b5SJed Brown     }
2311c833c3b5SJed Brown   }
23129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Refine, dm, 0, 0, 0));
23133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2314c833c3b5SJed Brown }
2315c833c3b5SJed Brown 
2316bb9467b5SJed Brown /*@C
2317c833c3b5SJed Brown   DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid
2318c833c3b5SJed Brown 
231920f4b53cSBarry Smith   Logically Collective; No Fortran Support
2320c833c3b5SJed Brown 
23214165533cSJose E. Roman   Input Parameters:
2322bb7acecfSBarry Smith + coarse     - `DM` on which to run a hook when interpolating to a finer level
2323bb7acecfSBarry Smith . refinehook - function to run when setting up the finer level
2324f826b5fcSPierre Jolivet . interphook - function to run to update data on finer levels (once per `SNESSolve()`)
232520f4b53cSBarry Smith - ctx        - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2326c833c3b5SJed Brown 
232720f4b53cSBarry Smith   Calling sequence of `refinehook`:
2328bb7acecfSBarry Smith + coarse - coarse level `DM`
2329bb7acecfSBarry Smith . fine   - fine level `DM` to interpolate problem to
2330c833c3b5SJed Brown - ctx    - optional user-defined function context
2331c833c3b5SJed Brown 
233220f4b53cSBarry Smith   Calling sequence of `interphook`:
2333bb7acecfSBarry Smith + coarse - coarse level `DM`
2334c833c3b5SJed Brown . interp - matrix interpolating a coarse-level solution to the finer grid
2335bb7acecfSBarry Smith . fine   - fine level `DM` to update
2336c833c3b5SJed Brown - ctx    - optional user-defined function context
2337c833c3b5SJed Brown 
2338c833c3b5SJed Brown   Level: advanced
2339c833c3b5SJed Brown 
2340c833c3b5SJed Brown   Notes:
2341bb7acecfSBarry Smith   This function is only needed if auxiliary data that is attached to the `DM`s via, for example, `PetscObjectCompose()`, needs to be
2342bb7acecfSBarry Smith   passed to fine grids while grid sequencing.
2343bb7acecfSBarry Smith 
2344bb7acecfSBarry Smith   The actual interpolation is done when `DMInterpolate()` is called.
2345c833c3b5SJed Brown 
2346c833c3b5SJed Brown   If this function is called multiple times, the hooks will be run in the order they are added.
2347c833c3b5SJed Brown 
23481cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `DMInterpolate()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2349c833c3b5SJed Brown @*/
2350a4e35b19SJacob 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)
2351d71ae5a4SJacob Faibussowitsch {
2352c833c3b5SJed Brown   DMRefineHookLink link, *p;
2353c833c3b5SJed Brown 
2354c833c3b5SJed Brown   PetscFunctionBegin;
2355c833c3b5SJed Brown   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
23563d8e3701SJed Brown   for (p = &coarse->refinehook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
23573ba16761SJacob Faibussowitsch     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
23583d8e3701SJed Brown   }
23599566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2360c833c3b5SJed Brown   link->refinehook = refinehook;
2361c833c3b5SJed Brown   link->interphook = interphook;
2362c833c3b5SJed Brown   link->ctx        = ctx;
23630298fd71SBarry Smith   link->next       = NULL;
2364c833c3b5SJed Brown   *p               = link;
23653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2366c833c3b5SJed Brown }
2367c833c3b5SJed Brown 
23683d8e3701SJed Brown /*@C
2369bb7acecfSBarry Smith   DMRefineHookRemove - remove a callback from the list of hooks, that have been set with `DMRefineHookAdd()`, to be run when interpolating
2370bb7acecfSBarry Smith   a nonlinear problem to a finer grid
23713d8e3701SJed Brown 
237220f4b53cSBarry Smith   Logically Collective; No Fortran Support
23733d8e3701SJed Brown 
23744165533cSJose E. Roman   Input Parameters:
2375bb7acecfSBarry Smith + coarse     - the `DM` on which to run a hook when restricting to a coarser level
2376bb7acecfSBarry Smith . refinehook - function to run when setting up a finer level
2377bb7acecfSBarry Smith . interphook - function to run to update data on finer levels
237820f4b53cSBarry Smith - ctx        - [optional] user-defined context for provide data for the hooks (may be `NULL`)
23793d8e3701SJed Brown 
23803d8e3701SJed Brown   Level: advanced
23813d8e3701SJed Brown 
2382bb7acecfSBarry Smith   Note:
23833d8e3701SJed Brown   This function does nothing if the hook is not in the list.
23843d8e3701SJed Brown 
23851cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefineHookAdd()`, `DMCoarsenHookRemove()`, `DMInterpolate()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
23863d8e3701SJed Brown @*/
2387d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHookRemove(DM coarse, PetscErrorCode (*refinehook)(DM, DM, void *), PetscErrorCode (*interphook)(DM, Mat, DM, void *), void *ctx)
2388d71ae5a4SJacob Faibussowitsch {
23893d8e3701SJed Brown   DMRefineHookLink link, *p;
23903d8e3701SJed Brown 
23913d8e3701SJed Brown   PetscFunctionBegin;
23923d8e3701SJed Brown   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
23933d8e3701SJed Brown   for (p = &coarse->refinehook; *p; p = &(*p)->next) { /* Search the list of current hooks */
23943d8e3701SJed Brown     if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) {
23953d8e3701SJed Brown       link = *p;
23963d8e3701SJed Brown       *p   = link->next;
23979566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
23983d8e3701SJed Brown       break;
23993d8e3701SJed Brown     }
24003d8e3701SJed Brown   }
24013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24023d8e3701SJed Brown }
24033d8e3701SJed Brown 
2404c833c3b5SJed Brown /*@
2405bb7acecfSBarry Smith   DMInterpolate - interpolates user-defined problem data attached to a `DM` to a finer `DM` by running hooks registered by `DMRefineHookAdd()`
2406c833c3b5SJed Brown 
2407c833c3b5SJed Brown   Collective if any hooks are
2408c833c3b5SJed Brown 
24094165533cSJose E. Roman   Input Parameters:
2410bb7acecfSBarry Smith + coarse - coarser `DM` to use as a base
2411bb7acecfSBarry Smith . interp - interpolation matrix, apply using `MatInterpolate()`
2412bb7acecfSBarry Smith - fine   - finer `DM` to update
2413c833c3b5SJed Brown 
2414c833c3b5SJed Brown   Level: developer
2415c833c3b5SJed Brown 
241660225df5SJacob Faibussowitsch   Developer Notes:
2417bb7acecfSBarry Smith   This routine is called `DMInterpolate()` while the hook is called `DMRefineHookAdd()`. It would be better to have an
2418bb7acecfSBarry Smith   an API with consistent terminology.
2419bb7acecfSBarry Smith 
24201cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefineHookAdd()`, `MatInterpolate()`
2421c833c3b5SJed Brown @*/
2422d71ae5a4SJacob Faibussowitsch PetscErrorCode DMInterpolate(DM coarse, Mat interp, DM fine)
2423d71ae5a4SJacob Faibussowitsch {
2424c833c3b5SJed Brown   DMRefineHookLink link;
2425c833c3b5SJed Brown 
2426c833c3b5SJed Brown   PetscFunctionBegin;
2427c833c3b5SJed Brown   for (link = fine->refinehook; link; link = link->next) {
24281baa6e33SBarry Smith     if (link->interphook) PetscCall((*link->interphook)(coarse, interp, fine, link->ctx));
24294057135bSMatthew G Knepley   }
24303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
243147c6ae99SBarry Smith }
243247c6ae99SBarry Smith 
2433eb3f98d2SBarry Smith /*@
24341f3379b2SToby Isaac   DMInterpolateSolution - Interpolates a solution from a coarse mesh to a fine mesh.
24351f3379b2SToby Isaac 
243620f4b53cSBarry Smith   Collective
24371f3379b2SToby Isaac 
24384165533cSJose E. Roman   Input Parameters:
2439bb7acecfSBarry Smith + coarse    - coarse `DM`
2440bb7acecfSBarry Smith . fine      - fine `DM`
2441bb7acecfSBarry Smith . interp    - (optional) the matrix computed by `DMCreateInterpolation()`.  Implementations may not need this, but if it
2442bb7acecfSBarry Smith             is available it can avoid some recomputation.  If it is provided, `MatInterpolate()` will be used if
2443bb7acecfSBarry Smith             the coarse `DM` does not have a specialized implementation.
24441f3379b2SToby Isaac - coarseSol - solution on the coarse mesh
24451f3379b2SToby Isaac 
24464165533cSJose E. Roman   Output Parameter:
24471f3379b2SToby Isaac . fineSol - the interpolation of coarseSol to the fine mesh
24481f3379b2SToby Isaac 
24491f3379b2SToby Isaac   Level: developer
24501f3379b2SToby Isaac 
2451bb7acecfSBarry Smith   Note:
2452bb7acecfSBarry Smith   This function exists because the interpolation of a solution vector between meshes is not always a linear
24531f3379b2SToby Isaac   map.  For example, if a boundary value problem has an inhomogeneous Dirichlet boundary condition that is compressed
24541f3379b2SToby Isaac   out of the solution vector.  Or if interpolation is inherently a nonlinear operation, such as a method using
24551f3379b2SToby Isaac   slope-limiting reconstruction.
24561f3379b2SToby Isaac 
245760225df5SJacob Faibussowitsch   Developer Notes:
2458bb7acecfSBarry Smith   This doesn't just interpolate "solutions" so its API name is questionable.
2459bb7acecfSBarry Smith 
24601cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMInterpolate()`, `DMCreateInterpolation()`
24611f3379b2SToby Isaac @*/
2462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMInterpolateSolution(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
2463d71ae5a4SJacob Faibussowitsch {
24641f3379b2SToby Isaac   PetscErrorCode (*interpsol)(DM, DM, Mat, Vec, Vec) = NULL;
24651f3379b2SToby Isaac 
24661f3379b2SToby Isaac   PetscFunctionBegin;
24671f3379b2SToby Isaac   PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
24681f3379b2SToby Isaac   if (interp) PetscValidHeaderSpecific(interp, MAT_CLASSID, 3);
24691f3379b2SToby Isaac   PetscValidHeaderSpecific(coarseSol, VEC_CLASSID, 4);
24701f3379b2SToby Isaac   PetscValidHeaderSpecific(fineSol, VEC_CLASSID, 5);
24711f3379b2SToby Isaac 
24729566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)coarse, "DMInterpolateSolution_C", &interpsol));
24731f3379b2SToby Isaac   if (interpsol) {
24749566063dSJacob Faibussowitsch     PetscCall((*interpsol)(coarse, fine, interp, coarseSol, fineSol));
24751f3379b2SToby Isaac   } else if (interp) {
24769566063dSJacob Faibussowitsch     PetscCall(MatInterpolate(interp, coarseSol, fineSol));
247798921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)coarse), PETSC_ERR_SUP, "DM %s does not implement DMInterpolateSolution()", ((PetscObject)coarse)->type_name);
24783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24791f3379b2SToby Isaac }
24801f3379b2SToby Isaac 
24811f3379b2SToby Isaac /*@
2482bb7acecfSBarry Smith   DMGetRefineLevel - Gets the number of refinements that have generated this `DM` from some initial `DM`.
2483eb3f98d2SBarry Smith 
2484eb3f98d2SBarry Smith   Not Collective
2485eb3f98d2SBarry Smith 
2486eb3f98d2SBarry Smith   Input Parameter:
2487bb7acecfSBarry Smith . dm - the `DM` object
2488eb3f98d2SBarry Smith 
2489eb3f98d2SBarry Smith   Output Parameter:
2490eb3f98d2SBarry Smith . level - number of refinements
2491eb3f98d2SBarry Smith 
2492eb3f98d2SBarry Smith   Level: developer
2493eb3f98d2SBarry Smith 
2494bb7acecfSBarry Smith   Note:
2495bb7acecfSBarry Smith   This can be used, by example, to set the number of coarser levels associated with this `DM` for a multigrid solver.
2496bb7acecfSBarry Smith 
24971cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
2498eb3f98d2SBarry Smith @*/
2499d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetRefineLevel(DM dm, PetscInt *level)
2500d71ae5a4SJacob Faibussowitsch {
2501eb3f98d2SBarry Smith   PetscFunctionBegin;
2502eb3f98d2SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2503eb3f98d2SBarry Smith   *level = dm->levelup;
25043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2505eb3f98d2SBarry Smith }
2506eb3f98d2SBarry Smith 
2507fef3a512SBarry Smith /*@
2508bb7acecfSBarry Smith   DMSetRefineLevel - Sets the number of refinements that have generated this `DM`.
2509fef3a512SBarry Smith 
2510fef3a512SBarry Smith   Not Collective
2511fef3a512SBarry Smith 
2512d8d19677SJose E. Roman   Input Parameters:
2513bb7acecfSBarry Smith + dm    - the `DM` object
2514fef3a512SBarry Smith - level - number of refinements
2515fef3a512SBarry Smith 
2516fef3a512SBarry Smith   Level: advanced
2517fef3a512SBarry Smith 
251895452b02SPatrick Sanan   Notes:
2519bb7acecfSBarry Smith   This value is used by `PCMG` to determine how many multigrid levels to use
2520fef3a512SBarry Smith 
2521bb7acecfSBarry Smith   The values are usually set automatically by the process that is causing the refinements of an initial `DM` by calling this routine.
2522bb7acecfSBarry Smith 
25231cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRefineLevel()`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
2524fef3a512SBarry Smith @*/
2525d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetRefineLevel(DM dm, PetscInt level)
2526d71ae5a4SJacob Faibussowitsch {
2527fef3a512SBarry Smith   PetscFunctionBegin;
2528fef3a512SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2529fef3a512SBarry Smith   dm->levelup = level;
25303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2531fef3a512SBarry Smith }
2532fef3a512SBarry Smith 
2533d410b0cfSMatthew G. Knepley /*@
2534bb7acecfSBarry Smith   DMExtrude - Extrude a `DM` object from a surface
2535d410b0cfSMatthew G. Knepley 
253620f4b53cSBarry Smith   Collective
2537d410b0cfSMatthew G. Knepley 
2538f1a722f8SMatthew G. Knepley   Input Parameters:
2539bb7acecfSBarry Smith + dm     - the `DM` object
2540d410b0cfSMatthew G. Knepley - layers - the number of extruded cell layers
2541d410b0cfSMatthew G. Knepley 
2542d410b0cfSMatthew G. Knepley   Output Parameter:
254320f4b53cSBarry Smith . dme - the extruded `DM`, or `NULL`
2544d410b0cfSMatthew G. Knepley 
2545d410b0cfSMatthew G. Knepley   Level: developer
2546d410b0cfSMatthew G. Knepley 
254720f4b53cSBarry Smith   Note:
254820f4b53cSBarry Smith   If no extrusion was done, the return value is `NULL`
254920f4b53cSBarry Smith 
25501cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`
2551d410b0cfSMatthew G. Knepley @*/
2552d71ae5a4SJacob Faibussowitsch PetscErrorCode DMExtrude(DM dm, PetscInt layers, DM *dme)
2553d71ae5a4SJacob Faibussowitsch {
2554d410b0cfSMatthew G. Knepley   PetscFunctionBegin;
2555d410b0cfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2556dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, extrude, layers, dme);
2557d410b0cfSMatthew G. Knepley   if (*dme) {
2558d410b0cfSMatthew G. Knepley     (*dme)->ops->creatematrix = dm->ops->creatematrix;
25599566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dme));
2560d410b0cfSMatthew G. Knepley     (*dme)->ctx = dm->ctx;
25619566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dme, dm->mattype));
2562d410b0cfSMatthew G. Knepley   }
25633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2564d410b0cfSMatthew G. Knepley }
2565d410b0cfSMatthew G. Knepley 
2566d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasisTransformDM_Internal(DM dm, DM *tdm)
2567d71ae5a4SJacob Faibussowitsch {
2568ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2569ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25704f572ea9SToby Isaac   PetscAssertPointer(tdm, 2);
2571ca3d3a14SMatthew G. Knepley   *tdm = dm->transformDM;
25723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2573ca3d3a14SMatthew G. Knepley }
2574ca3d3a14SMatthew G. Knepley 
2575d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasisTransformVec_Internal(DM dm, Vec *tv)
2576d71ae5a4SJacob Faibussowitsch {
2577ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2578ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25794f572ea9SToby Isaac   PetscAssertPointer(tv, 2);
2580ca3d3a14SMatthew G. Knepley   *tv = dm->transform;
25813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2582ca3d3a14SMatthew G. Knepley }
2583ca3d3a14SMatthew G. Knepley 
2584ca3d3a14SMatthew G. Knepley /*@
2585bb7acecfSBarry Smith   DMHasBasisTransform - Whether the `DM` employs a basis transformation from functions in global vectors to functions in local vectors
2586ca3d3a14SMatthew G. Knepley 
2587ca3d3a14SMatthew G. Knepley   Input Parameter:
258820f4b53cSBarry Smith . dm - The `DM`
2589ca3d3a14SMatthew G. Knepley 
2590ca3d3a14SMatthew G. Knepley   Output Parameter:
259120f4b53cSBarry Smith . flg - `PETSC_TRUE` if a basis transformation should be done
2592ca3d3a14SMatthew G. Knepley 
2593ca3d3a14SMatthew G. Knepley   Level: developer
2594ca3d3a14SMatthew G. Knepley 
25951cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPlexGlobalToLocalBasis()`, `DMPlexLocalToGlobalBasis()`, `DMPlexCreateBasisRotation()`
2596ca3d3a14SMatthew G. Knepley @*/
2597d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasBasisTransform(DM dm, PetscBool *flg)
2598d71ae5a4SJacob Faibussowitsch {
2599ca3d3a14SMatthew G. Knepley   Vec tv;
2600ca3d3a14SMatthew G. Knepley 
2601ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2602ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26034f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
26049566063dSJacob Faibussowitsch   PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
2605ca3d3a14SMatthew G. Knepley   *flg = tv ? PETSC_TRUE : PETSC_FALSE;
26063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2607ca3d3a14SMatthew G. Knepley }
2608ca3d3a14SMatthew G. Knepley 
2609d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConstructBasisTransform_Internal(DM dm)
2610d71ae5a4SJacob Faibussowitsch {
2611ca3d3a14SMatthew G. Knepley   PetscSection s, ts;
2612ca3d3a14SMatthew G. Knepley   PetscScalar *ta;
2613ca3d3a14SMatthew G. Knepley   PetscInt     cdim, pStart, pEnd, p, Nf, f, Nc, dof;
2614ca3d3a14SMatthew G. Knepley 
2615ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
26169566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
26179566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
26189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
26199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
26209566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dm->transformDM));
26219566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm->transformDM, &ts));
26229566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(ts, Nf));
26239566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(ts, pStart, pEnd));
2624ca3d3a14SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
26259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
2626ca3d3a14SMatthew G. Knepley     /* We could start to label fields by their transformation properties */
2627ca3d3a14SMatthew G. Knepley     if (Nc != cdim) continue;
2628ca3d3a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
26299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(s, p, f, &dof));
2630ca3d3a14SMatthew G. Knepley       if (!dof) continue;
26319566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(ts, p, f, PetscSqr(cdim)));
26329566063dSJacob Faibussowitsch       PetscCall(PetscSectionAddDof(ts, p, PetscSqr(cdim)));
2633ca3d3a14SMatthew G. Knepley     }
2634ca3d3a14SMatthew G. Knepley   }
26359566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(ts));
26369566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm->transformDM, &dm->transform));
26379566063dSJacob Faibussowitsch   PetscCall(VecGetArray(dm->transform, &ta));
2638ca3d3a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
2639ca3d3a14SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
26409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(ts, p, f, &dof));
2641ca3d3a14SMatthew G. Knepley       if (dof) {
2642ca3d3a14SMatthew G. Knepley         PetscReal          x[3] = {0.0, 0.0, 0.0};
2643ca3d3a14SMatthew G. Knepley         PetscScalar       *tva;
2644ca3d3a14SMatthew G. Knepley         const PetscScalar *A;
2645ca3d3a14SMatthew G. Knepley 
2646ca3d3a14SMatthew G. Knepley         /* TODO Get quadrature point for this dual basis vector for coordinate */
26479566063dSJacob Faibussowitsch         PetscCall((*dm->transformGetMatrix)(dm, x, PETSC_TRUE, &A, dm->transformCtx));
26489566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalFieldRef(dm->transformDM, p, f, ta, (void *)&tva));
26499566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(tva, A, PetscSqr(cdim)));
2650ca3d3a14SMatthew G. Knepley       }
2651ca3d3a14SMatthew G. Knepley     }
2652ca3d3a14SMatthew G. Knepley   }
26539566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(dm->transform, &ta));
26543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2655ca3d3a14SMatthew G. Knepley }
2656ca3d3a14SMatthew G. Knepley 
2657d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyTransform(DM dm, DM newdm)
2658d71ae5a4SJacob Faibussowitsch {
2659ca3d3a14SMatthew G. Knepley   PetscFunctionBegin;
2660ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2661ca3d3a14SMatthew G. Knepley   PetscValidHeaderSpecific(newdm, DM_CLASSID, 2);
2662ca3d3a14SMatthew G. Knepley   newdm->transformCtx       = dm->transformCtx;
2663ca3d3a14SMatthew G. Knepley   newdm->transformSetUp     = dm->transformSetUp;
2664ca3d3a14SMatthew G. Knepley   newdm->transformDestroy   = NULL;
2665ca3d3a14SMatthew G. Knepley   newdm->transformGetMatrix = dm->transformGetMatrix;
26669566063dSJacob Faibussowitsch   if (newdm->transformSetUp) PetscCall(DMConstructBasisTransform_Internal(newdm));
26673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2668ca3d3a14SMatthew G. Knepley }
2669ca3d3a14SMatthew G. Knepley 
2670bb9467b5SJed Brown /*@C
2671bb7acecfSBarry Smith   DMGlobalToLocalHookAdd - adds a callback to be run when `DMGlobalToLocal()` is called
2672baf369e7SPeter Brune 
267320f4b53cSBarry Smith   Logically Collective
2674baf369e7SPeter Brune 
26754165533cSJose E. Roman   Input Parameters:
2676bb7acecfSBarry Smith + dm        - the `DM`
2677bb7acecfSBarry Smith . beginhook - function to run at the beginning of `DMGlobalToLocalBegin()`
2678bb7acecfSBarry Smith . endhook   - function to run after `DMGlobalToLocalEnd()` has completed
267920f4b53cSBarry Smith - ctx       - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2680baf369e7SPeter Brune 
268120f4b53cSBarry Smith   Calling sequence of `beginhook`:
2682a4e35b19SJacob Faibussowitsch + dm   - global `DM`
2683baf369e7SPeter Brune . g    - global vector
2684baf369e7SPeter Brune . mode - mode
2685baf369e7SPeter Brune . l    - local vector
2686baf369e7SPeter Brune - ctx  - optional user-defined function context
2687baf369e7SPeter Brune 
268820f4b53cSBarry Smith   Calling sequence of `endhook`:
2689a4e35b19SJacob Faibussowitsch + dm   - global `DM`
2690a4e35b19SJacob Faibussowitsch . g    - global vector
2691a4e35b19SJacob Faibussowitsch . mode - mode
2692a4e35b19SJacob Faibussowitsch . l    - local vector
2693baf369e7SPeter Brune - ctx  - optional user-defined function context
2694baf369e7SPeter Brune 
2695baf369e7SPeter Brune   Level: advanced
2696baf369e7SPeter Brune 
2697bb7acecfSBarry Smith   Note:
2698bb7acecfSBarry 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.
2699bb7acecfSBarry Smith 
27001cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGlobalToLocal()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2701baf369e7SPeter Brune @*/
2702a4e35b19SJacob 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)
2703d71ae5a4SJacob Faibussowitsch {
2704baf369e7SPeter Brune   DMGlobalToLocalHookLink link, *p;
2705baf369e7SPeter Brune 
2706baf369e7SPeter Brune   PetscFunctionBegin;
2707baf369e7SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2708baf369e7SPeter Brune   for (p = &dm->gtolhook; *p; p = &(*p)->next) { } /* Scan to the end of the current list of hooks */
27099566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2710baf369e7SPeter Brune   link->beginhook = beginhook;
2711baf369e7SPeter Brune   link->endhook   = endhook;
2712baf369e7SPeter Brune   link->ctx       = ctx;
27130298fd71SBarry Smith   link->next      = NULL;
2714baf369e7SPeter Brune   *p              = link;
27153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2716baf369e7SPeter Brune }
2717baf369e7SPeter Brune 
2718d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx)
2719d71ae5a4SJacob Faibussowitsch {
27204c274da1SToby Isaac   Mat          cMat;
272179769bd5SJed Brown   Vec          cVec, cBias;
27224c274da1SToby Isaac   PetscSection section, cSec;
27234c274da1SToby Isaac   PetscInt     pStart, pEnd, p, dof;
27244c274da1SToby Isaac 
27254c274da1SToby Isaac   PetscFunctionBegin;
2726a4e35b19SJacob Faibussowitsch   (void)g;
2727a4e35b19SJacob Faibussowitsch   (void)ctx;
27284c274da1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27299566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, &cBias));
27304c274da1SToby Isaac   if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) {
27315db9a05bSToby Isaac     PetscInt nRows;
27325db9a05bSToby Isaac 
27339566063dSJacob Faibussowitsch     PetscCall(MatGetSize(cMat, &nRows, NULL));
27343ba16761SJacob Faibussowitsch     if (nRows <= 0) PetscFunctionReturn(PETSC_SUCCESS);
27359566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
27369566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(cMat, NULL, &cVec));
27379566063dSJacob Faibussowitsch     PetscCall(MatMult(cMat, l, cVec));
27389566063dSJacob Faibussowitsch     if (cBias) PetscCall(VecAXPY(cVec, 1., cBias));
27399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
27404c274da1SToby Isaac     for (p = pStart; p < pEnd; p++) {
27419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
27424c274da1SToby Isaac       if (dof) {
27434c274da1SToby Isaac         PetscScalar *vals;
27449566063dSJacob Faibussowitsch         PetscCall(VecGetValuesSection(cVec, cSec, p, &vals));
27459566063dSJacob Faibussowitsch         PetscCall(VecSetValuesSection(l, section, p, vals, INSERT_ALL_VALUES));
27464c274da1SToby Isaac       }
27474c274da1SToby Isaac     }
27489566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cVec));
27494c274da1SToby Isaac   }
27503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27514c274da1SToby Isaac }
27524c274da1SToby Isaac 
275347c6ae99SBarry Smith /*@
275401729b5cSPatrick Sanan   DMGlobalToLocal - update local vectors from global vector
275501729b5cSPatrick Sanan 
275620f4b53cSBarry Smith   Neighbor-wise Collective
275701729b5cSPatrick Sanan 
275801729b5cSPatrick Sanan   Input Parameters:
2759bb7acecfSBarry Smith + dm   - the `DM` object
276001729b5cSPatrick Sanan . g    - the global vector
2761bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
276201729b5cSPatrick Sanan - l    - the local vector
276301729b5cSPatrick Sanan 
276420f4b53cSBarry Smith   Level: beginner
276520f4b53cSBarry Smith 
276601729b5cSPatrick Sanan   Notes:
2767bb7acecfSBarry Smith   The communication involved in this update can be overlapped with computation by instead using
2768bb7acecfSBarry Smith   `DMGlobalToLocalBegin()` and `DMGlobalToLocalEnd()`.
2769bb7acecfSBarry Smith 
2770bb7acecfSBarry Smith   `DMGlobalToLocalHookAdd()` may be used to provide additional operations that are performed during the update process.
277101729b5cSPatrick Sanan 
27721cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGlobalToLocalHookAdd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`,
277360225df5SJacob Faibussowitsch           `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`,
2774bb7acecfSBarry Smith           `DMGlobalToLocalBegin()` `DMGlobalToLocalEnd()`
277501729b5cSPatrick Sanan @*/
2776d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocal(DM dm, Vec g, InsertMode mode, Vec l)
2777d71ae5a4SJacob Faibussowitsch {
277801729b5cSPatrick Sanan   PetscFunctionBegin;
27799566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dm, g, mode, l));
27809566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dm, g, mode, l));
27813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
278201729b5cSPatrick Sanan }
278301729b5cSPatrick Sanan 
278401729b5cSPatrick Sanan /*@
278547c6ae99SBarry Smith   DMGlobalToLocalBegin - Begins updating local vectors from global vector
278647c6ae99SBarry Smith 
278720f4b53cSBarry Smith   Neighbor-wise Collective
278847c6ae99SBarry Smith 
278947c6ae99SBarry Smith   Input Parameters:
2790bb7acecfSBarry Smith + dm   - the `DM` object
279147c6ae99SBarry Smith . g    - the global vector
2792bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
279347c6ae99SBarry Smith - l    - the local vector
279447c6ae99SBarry Smith 
279501729b5cSPatrick Sanan   Level: intermediate
279647c6ae99SBarry Smith 
2797bb7acecfSBarry Smith   Notes:
2798bb7acecfSBarry Smith   The operation is completed with `DMGlobalToLocalEnd()`
2799bb7acecfSBarry Smith 
2800bb7acecfSBarry Smith   One can perform local computations between the `DMGlobalToLocalBegin()` and  `DMGlobalToLocalEnd()` to overlap communication and computation
2801bb7acecfSBarry Smith 
2802bb7acecfSBarry Smith   `DMGlobalToLocal()` is a short form of  `DMGlobalToLocalBegin()` and  `DMGlobalToLocalEnd()`
2803bb7acecfSBarry Smith 
2804bb7acecfSBarry Smith   `DMGlobalToLocalHookAdd()` may be used to provide additional operations that are performed during the update process.
2805bb7acecfSBarry Smith 
280660225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`
280747c6ae99SBarry Smith @*/
2808d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalBegin(DM dm, Vec g, InsertMode mode, Vec l)
2809d71ae5a4SJacob Faibussowitsch {
28107128ae9fSMatthew G Knepley   PetscSF                 sf;
2811baf369e7SPeter Brune   DMGlobalToLocalHookLink link;
281247c6ae99SBarry Smith 
281347c6ae99SBarry Smith   PetscFunctionBegin;
2814171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2815baf369e7SPeter Brune   for (link = dm->gtolhook; link; link = link->next) {
28161baa6e33SBarry Smith     if (link->beginhook) PetscCall((*link->beginhook)(dm, g, mode, l, link->ctx));
2817baf369e7SPeter Brune   }
28189566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
28197128ae9fSMatthew G Knepley   if (sf) {
2820ae5cfb4aSMatthew G. Knepley     const PetscScalar *gArray;
2821ae5cfb4aSMatthew G. Knepley     PetscScalar       *lArray;
2822d0295fc0SJunchao Zhang     PetscMemType       lmtype, gmtype;
28237128ae9fSMatthew G Knepley 
28247a8be351SBarry Smith     PetscCheck(mode != ADD_VALUES, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", (int)mode);
28259566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(l, &lArray, &lmtype));
28269566063dSJacob Faibussowitsch     PetscCall(VecGetArrayReadAndMemType(g, &gArray, &gmtype));
28279566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastWithMemTypeBegin(sf, MPIU_SCALAR, gmtype, gArray, lmtype, lArray, MPI_REPLACE));
28289566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(l, &lArray));
28299566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayReadAndMemType(g, &gArray));
28307128ae9fSMatthew G Knepley   } else {
2831*fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, globaltolocalbegin, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
28327128ae9fSMatthew G Knepley   }
28333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
283447c6ae99SBarry Smith }
283547c6ae99SBarry Smith 
283647c6ae99SBarry Smith /*@
283747c6ae99SBarry Smith   DMGlobalToLocalEnd - Ends updating local vectors from global vector
283847c6ae99SBarry Smith 
283920f4b53cSBarry Smith   Neighbor-wise Collective
284047c6ae99SBarry Smith 
284147c6ae99SBarry Smith   Input Parameters:
2842bb7acecfSBarry Smith + dm   - the `DM` object
284347c6ae99SBarry Smith . g    - the global vector
2844bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
284547c6ae99SBarry Smith - l    - the local vector
284647c6ae99SBarry Smith 
284701729b5cSPatrick Sanan   Level: intermediate
284847c6ae99SBarry Smith 
2849bb7acecfSBarry Smith   Note:
2850bb7acecfSBarry Smith   See `DMGlobalToLocalBegin()` for details.
2851bb7acecfSBarry Smith 
285260225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMLocalToGlobalBegin()`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`
285347c6ae99SBarry Smith @*/
2854d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGlobalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
2855d71ae5a4SJacob Faibussowitsch {
28567128ae9fSMatthew G Knepley   PetscSF                 sf;
2857ae5cfb4aSMatthew G. Knepley   const PetscScalar      *gArray;
2858ae5cfb4aSMatthew G. Knepley   PetscScalar            *lArray;
2859ca3d3a14SMatthew G. Knepley   PetscBool               transform;
2860baf369e7SPeter Brune   DMGlobalToLocalHookLink link;
2861d0295fc0SJunchao Zhang   PetscMemType            lmtype, gmtype;
286247c6ae99SBarry Smith 
286347c6ae99SBarry Smith   PetscFunctionBegin;
2864171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28659566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
28669566063dSJacob Faibussowitsch   PetscCall(DMHasBasisTransform(dm, &transform));
28677128ae9fSMatthew G Knepley   if (sf) {
28687a8be351SBarry Smith     PetscCheck(mode != ADD_VALUES, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", (int)mode);
28697128ae9fSMatthew G Knepley 
28709566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(l, &lArray, &lmtype));
28719566063dSJacob Faibussowitsch     PetscCall(VecGetArrayReadAndMemType(g, &gArray, &gmtype));
28729566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray, MPI_REPLACE));
28739566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(l, &lArray));
28749566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayReadAndMemType(g, &gArray));
28759566063dSJacob Faibussowitsch     if (transform) PetscCall(DMPlexGlobalToLocalBasis(dm, l));
28767128ae9fSMatthew G Knepley   } else {
2877*fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, globaltolocalend, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
28787128ae9fSMatthew G Knepley   }
28799566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalHook_Constraints(dm, g, mode, l, NULL));
2880baf369e7SPeter Brune   for (link = dm->gtolhook; link; link = link->next) {
28819566063dSJacob Faibussowitsch     if (link->endhook) PetscCall((*link->endhook)(dm, g, mode, l, link->ctx));
2882baf369e7SPeter Brune   }
28833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
288447c6ae99SBarry Smith }
288547c6ae99SBarry Smith 
2886d4d07f1eSToby Isaac /*@C
2887d4d07f1eSToby Isaac   DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called
2888d4d07f1eSToby Isaac 
288920f4b53cSBarry Smith   Logically Collective
2890d4d07f1eSToby Isaac 
28914165533cSJose E. Roman   Input Parameters:
2892bb7acecfSBarry Smith + dm        - the `DM`
2893bb7acecfSBarry Smith . beginhook - function to run at the beginning of `DMLocalToGlobalBegin()`
2894bb7acecfSBarry Smith . endhook   - function to run after `DMLocalToGlobalEnd()` has completed
289520f4b53cSBarry Smith - ctx       - [optional] user-defined context for provide data for the hooks (may be `NULL`)
2896d4d07f1eSToby Isaac 
289720f4b53cSBarry Smith   Calling sequence of `beginhook`:
2898a4e35b19SJacob Faibussowitsch + global - global `DM`
2899d4d07f1eSToby Isaac . l      - local vector
2900d4d07f1eSToby Isaac . mode   - mode
2901d4d07f1eSToby Isaac . g      - global vector
2902d4d07f1eSToby Isaac - ctx    - optional user-defined function context
2903d4d07f1eSToby Isaac 
290420f4b53cSBarry Smith   Calling sequence of `endhook`:
2905bb7acecfSBarry Smith + global - global `DM`
2906d4d07f1eSToby Isaac . l      - local vector
2907d4d07f1eSToby Isaac . mode   - mode
2908d4d07f1eSToby Isaac . g      - global vector
2909d4d07f1eSToby Isaac - ctx    - optional user-defined function context
2910d4d07f1eSToby Isaac 
2911d4d07f1eSToby Isaac   Level: advanced
2912d4d07f1eSToby Isaac 
29131cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobal()`, `DMRefineHookAdd()`, `DMGlobalToLocalHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
2914d4d07f1eSToby Isaac @*/
2915a4e35b19SJacob 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)
2916d71ae5a4SJacob Faibussowitsch {
2917d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link, *p;
2918d4d07f1eSToby Isaac 
2919d4d07f1eSToby Isaac   PetscFunctionBegin;
2920d4d07f1eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2921d4d07f1eSToby Isaac   for (p = &dm->ltoghook; *p; p = &(*p)->next) { } /* Scan to the end of the current list of hooks */
29229566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
2923d4d07f1eSToby Isaac   link->beginhook = beginhook;
2924d4d07f1eSToby Isaac   link->endhook   = endhook;
2925d4d07f1eSToby Isaac   link->ctx       = ctx;
2926d4d07f1eSToby Isaac   link->next      = NULL;
2927d4d07f1eSToby Isaac   *p              = link;
29283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2929d4d07f1eSToby Isaac }
2930d4d07f1eSToby Isaac 
2931d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx)
2932d71ae5a4SJacob Faibussowitsch {
29334c274da1SToby Isaac   Mat          cMat;
29344c274da1SToby Isaac   Vec          cVec;
29354c274da1SToby Isaac   PetscSection section, cSec;
29364c274da1SToby Isaac   PetscInt     pStart, pEnd, p, dof;
29374c274da1SToby Isaac 
29384c274da1SToby Isaac   PetscFunctionBegin;
2939a4e35b19SJacob Faibussowitsch   (void)g;
2940a4e35b19SJacob Faibussowitsch   (void)ctx;
29414c274da1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29429566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
29434c274da1SToby Isaac   if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) {
29445db9a05bSToby Isaac     PetscInt nRows;
29455db9a05bSToby Isaac 
29469566063dSJacob Faibussowitsch     PetscCall(MatGetSize(cMat, &nRows, NULL));
29473ba16761SJacob Faibussowitsch     if (nRows <= 0) PetscFunctionReturn(PETSC_SUCCESS);
29489566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
29499566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(cMat, NULL, &cVec));
29509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
29514c274da1SToby Isaac     for (p = pStart; p < pEnd; p++) {
29529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
29534c274da1SToby Isaac       if (dof) {
29544c274da1SToby Isaac         PetscInt     d;
29554c274da1SToby Isaac         PetscScalar *vals;
29569566063dSJacob Faibussowitsch         PetscCall(VecGetValuesSection(l, section, p, &vals));
29579566063dSJacob Faibussowitsch         PetscCall(VecSetValuesSection(cVec, cSec, p, vals, mode));
29584c274da1SToby Isaac         /* for this to be the true transpose, we have to zero the values that
29594c274da1SToby Isaac          * we just extracted */
2960ad540459SPierre Jolivet         for (d = 0; d < dof; d++) vals[d] = 0.;
29614c274da1SToby Isaac       }
29624c274da1SToby Isaac     }
29639566063dSJacob Faibussowitsch     PetscCall(MatMultTransposeAdd(cMat, cVec, l, l));
29649566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cVec));
29654c274da1SToby Isaac   }
29663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29674c274da1SToby Isaac }
296801729b5cSPatrick Sanan /*@
296901729b5cSPatrick Sanan   DMLocalToGlobal - updates global vectors from local vectors
297001729b5cSPatrick Sanan 
297120f4b53cSBarry Smith   Neighbor-wise Collective
297201729b5cSPatrick Sanan 
297301729b5cSPatrick Sanan   Input Parameters:
2974bb7acecfSBarry Smith + dm   - the `DM` object
297501729b5cSPatrick Sanan . l    - the local vector
2976bb7acecfSBarry 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.
297701729b5cSPatrick Sanan - g    - the global vector
297801729b5cSPatrick Sanan 
297920f4b53cSBarry Smith   Level: beginner
298020f4b53cSBarry Smith 
298101729b5cSPatrick Sanan   Notes:
298201729b5cSPatrick Sanan   The communication involved in this update can be overlapped with computation by using
2983bb7acecfSBarry Smith   `DMLocalToGlobalBegin()` and `DMLocalToGlobalEnd()`.
298401729b5cSPatrick Sanan 
2985bb7acecfSBarry Smith   In the `ADD_VALUES` case you normally would zero the receiving vector before beginning this operation.
2986bb7acecfSBarry Smith 
2987bb7acecfSBarry 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.
2988bb7acecfSBarry Smith 
2989bb7acecfSBarry Smith   Use `DMLocalToGlobalHookAdd()` to add additional operations that are performed on the data during the update process
299001729b5cSPatrick Sanan 
29911cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobalBegin()`, `DMLocalToGlobalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalBegin()`, `DMLocalToGlobalHookAdd()`, `DMGlobaToLocallHookAdd()`
299201729b5cSPatrick Sanan @*/
2993d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobal(DM dm, Vec l, InsertMode mode, Vec g)
2994d71ae5a4SJacob Faibussowitsch {
299501729b5cSPatrick Sanan   PetscFunctionBegin;
29969566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, l, mode, g));
29979566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, l, mode, g));
29983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
299901729b5cSPatrick Sanan }
30004c274da1SToby Isaac 
300147c6ae99SBarry Smith /*@
300201729b5cSPatrick Sanan   DMLocalToGlobalBegin - begins updating global vectors from local vectors
30039a42bb27SBarry Smith 
300420f4b53cSBarry Smith   Neighbor-wise Collective
30059a42bb27SBarry Smith 
30069a42bb27SBarry Smith   Input Parameters:
3007bb7acecfSBarry Smith + dm   - the `DM` object
3008f6813fd5SJed Brown . l    - the local vector
3009aa624791SPierre 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.
30101eb28f2eSBarry Smith - g    - the global vector
30119a42bb27SBarry Smith 
301220f4b53cSBarry Smith   Level: intermediate
301320f4b53cSBarry Smith 
301495452b02SPatrick Sanan   Notes:
3015bb7acecfSBarry Smith   In the `ADD_VALUES` case you normally would zero the receiving vector before beginning this operation.
3016bb7acecfSBarry Smith 
3017bb7acecfSBarry 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.
3018bb7acecfSBarry Smith 
3019bb7acecfSBarry Smith   Use `DMLocalToGlobalEnd()` to complete the communication process.
3020bb7acecfSBarry Smith 
3021bb7acecfSBarry Smith   `DMLocalToGlobal()` is a short form of  `DMLocalToGlobalBegin()` and  `DMLocalToGlobalEnd()`
3022bb7acecfSBarry Smith 
3023bb7acecfSBarry Smith   `DMLocalToGlobalHookAdd()` may be used to provide additional operations that are performed during the update process.
30249a42bb27SBarry Smith 
30251cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobal()`, `DMLocalToGlobalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocal()`, `DMGlobalToLocalEnd()`, `DMGlobalToLocalBegin()`
30269a42bb27SBarry Smith @*/
3027d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalBegin(DM dm, Vec l, InsertMode mode, Vec g)
3028d71ae5a4SJacob Faibussowitsch {
30297128ae9fSMatthew G Knepley   PetscSF                 sf;
303084330215SMatthew G. Knepley   PetscSection            s, gs;
3031d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link;
3032ca3d3a14SMatthew G. Knepley   Vec                     tmpl;
3033ae5cfb4aSMatthew G. Knepley   const PetscScalar      *lArray;
3034ae5cfb4aSMatthew G. Knepley   PetscScalar            *gArray;
3035fa88e482SJed Brown   PetscBool               isInsert, transform, l_inplace = PETSC_FALSE, g_inplace = PETSC_FALSE;
3036d0295fc0SJunchao Zhang   PetscMemType            lmtype = PETSC_MEMTYPE_HOST, gmtype = PETSC_MEMTYPE_HOST;
30379a42bb27SBarry Smith 
30389a42bb27SBarry Smith   PetscFunctionBegin;
3039171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3040d4d07f1eSToby Isaac   for (link = dm->ltoghook; link; link = link->next) {
30411baa6e33SBarry Smith     if (link->beginhook) PetscCall((*link->beginhook)(dm, l, mode, g, link->ctx));
3042d4d07f1eSToby Isaac   }
30439566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalHook_Constraints(dm, l, mode, g, NULL));
30449566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
30459566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
30467128ae9fSMatthew G Knepley   switch (mode) {
30477128ae9fSMatthew G Knepley   case INSERT_VALUES:
30487128ae9fSMatthew G Knepley   case INSERT_ALL_VALUES:
3049d71ae5a4SJacob Faibussowitsch   case INSERT_BC_VALUES:
3050d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_TRUE;
3051d71ae5a4SJacob Faibussowitsch     break;
30527128ae9fSMatthew G Knepley   case ADD_VALUES:
30537128ae9fSMatthew G Knepley   case ADD_ALL_VALUES:
3054d71ae5a4SJacob Faibussowitsch   case ADD_BC_VALUES:
3055d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_FALSE;
3056d71ae5a4SJacob Faibussowitsch     break;
3057d71ae5a4SJacob Faibussowitsch   default:
3058d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", mode);
30597128ae9fSMatthew G Knepley   }
3060ca3d3a14SMatthew G. Knepley   if ((sf && !isInsert) || (s && isInsert)) {
30619566063dSJacob Faibussowitsch     PetscCall(DMHasBasisTransform(dm, &transform));
3062ca3d3a14SMatthew G. Knepley     if (transform) {
30639566063dSJacob Faibussowitsch       PetscCall(DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
30649566063dSJacob Faibussowitsch       PetscCall(VecCopy(l, tmpl));
30659566063dSJacob Faibussowitsch       PetscCall(DMPlexLocalToGlobalBasis(dm, tmpl));
30669566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tmpl, &lArray));
3067fa88e482SJed Brown     } else if (isInsert) {
30689566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(l, &lArray));
3069fa88e482SJed Brown     } else {
30709566063dSJacob Faibussowitsch       PetscCall(VecGetArrayReadAndMemType(l, &lArray, &lmtype));
3071fa88e482SJed Brown       l_inplace = PETSC_TRUE;
3072ca3d3a14SMatthew G. Knepley     }
3073fa88e482SJed Brown     if (s && isInsert) {
30749566063dSJacob Faibussowitsch       PetscCall(VecGetArray(g, &gArray));
3075fa88e482SJed Brown     } else {
30769566063dSJacob Faibussowitsch       PetscCall(VecGetArrayAndMemType(g, &gArray, &gmtype));
3077fa88e482SJed Brown       g_inplace = PETSC_TRUE;
3078fa88e482SJed Brown     }
3079ca3d3a14SMatthew G. Knepley     if (sf && !isInsert) {
30809566063dSJacob Faibussowitsch       PetscCall(PetscSFReduceWithMemTypeBegin(sf, MPIU_SCALAR, lmtype, lArray, gmtype, gArray, MPIU_SUM));
308184330215SMatthew G. Knepley     } else if (s && isInsert) {
308284330215SMatthew G. Knepley       PetscInt gStart, pStart, pEnd, p;
308384330215SMatthew G. Knepley 
30849566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gs));
30859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
30869566063dSJacob Faibussowitsch       PetscCall(VecGetOwnershipRange(g, &gStart, NULL));
308784330215SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
3088b3b16f48SMatthew G. Knepley         PetscInt dof, gdof, cdof, gcdof, off, goff, d, e;
308984330215SMatthew G. Knepley 
30909566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(s, p, &dof));
30919566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(gs, p, &gdof));
30929566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(s, p, &cdof));
30939566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(gs, p, &gcdof));
30949566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(s, p, &off));
30959566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(gs, p, &goff));
3096b3b16f48SMatthew G. Knepley         /* Ignore off-process data and points with no global data */
309703442857SMatthew G. Knepley         if (!gdof || goff < 0) continue;
30987a8be351SBarry 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);
3099b3b16f48SMatthew G. Knepley         /* If no constraints are enforced in the global vector */
3100b3b16f48SMatthew G. Knepley         if (!gcdof) {
310184330215SMatthew G. Knepley           for (d = 0; d < dof; ++d) gArray[goff - gStart + d] = lArray[off + d];
3102b3b16f48SMatthew G. Knepley           /* If constraints are enforced in the global vector */
3103b3b16f48SMatthew G. Knepley         } else if (cdof == gcdof) {
310484330215SMatthew G. Knepley           const PetscInt *cdofs;
310584330215SMatthew G. Knepley           PetscInt        cind = 0;
310684330215SMatthew G. Knepley 
31079566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetConstraintIndices(s, p, &cdofs));
3108b3b16f48SMatthew G. Knepley           for (d = 0, e = 0; d < dof; ++d) {
31099371c9d4SSatish Balay             if ((cind < cdof) && (d == cdofs[cind])) {
31109371c9d4SSatish Balay               ++cind;
31119371c9d4SSatish Balay               continue;
31129371c9d4SSatish Balay             }
3113b3b16f48SMatthew G. Knepley             gArray[goff - gStart + e++] = lArray[off + d];
311484330215SMatthew G. Knepley           }
31157a8be351SBarry 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);
311684330215SMatthew G. Knepley       }
3117ca3d3a14SMatthew G. Knepley     }
3118fa88e482SJed Brown     if (g_inplace) {
31199566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayAndMemType(g, &gArray));
3120fa88e482SJed Brown     } else {
31219566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(g, &gArray));
3122fa88e482SJed Brown     }
3123ca3d3a14SMatthew G. Knepley     if (transform) {
31249566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tmpl, &lArray));
31259566063dSJacob Faibussowitsch       PetscCall(DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
3126fa88e482SJed Brown     } else if (l_inplace) {
31279566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayReadAndMemType(l, &lArray));
3128ca3d3a14SMatthew G. Knepley     } else {
31299566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(l, &lArray));
3130ca3d3a14SMatthew G. Knepley     }
31317128ae9fSMatthew G Knepley   } else {
3132*fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, localtoglobalbegin, l, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), g);
31337128ae9fSMatthew G Knepley   }
31343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31359a42bb27SBarry Smith }
31369a42bb27SBarry Smith 
31379a42bb27SBarry Smith /*@
31389a42bb27SBarry Smith   DMLocalToGlobalEnd - updates global vectors from local vectors
313947c6ae99SBarry Smith 
314020f4b53cSBarry Smith   Neighbor-wise Collective
314147c6ae99SBarry Smith 
314247c6ae99SBarry Smith   Input Parameters:
3143bb7acecfSBarry Smith + dm   - the `DM` object
3144f6813fd5SJed Brown . l    - the local vector
3145bb7acecfSBarry Smith . mode - `INSERT_VALUES` or `ADD_VALUES`
3146f6813fd5SJed Brown - g    - the global vector
314747c6ae99SBarry Smith 
314801729b5cSPatrick Sanan   Level: intermediate
314947c6ae99SBarry Smith 
3150bb7acecfSBarry Smith   Note:
3151bb7acecfSBarry Smith   See `DMLocalToGlobalBegin()` for full details
3152bb7acecfSBarry Smith 
315360225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLocalToGlobalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`
315447c6ae99SBarry Smith @*/
3155d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToGlobalEnd(DM dm, Vec l, InsertMode mode, Vec g)
3156d71ae5a4SJacob Faibussowitsch {
31577128ae9fSMatthew G Knepley   PetscSF                 sf;
315884330215SMatthew G. Knepley   PetscSection            s;
3159d4d07f1eSToby Isaac   DMLocalToGlobalHookLink link;
3160ca3d3a14SMatthew G. Knepley   PetscBool               isInsert, transform;
316147c6ae99SBarry Smith 
316247c6ae99SBarry Smith   PetscFunctionBegin;
3163171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31649566063dSJacob Faibussowitsch   PetscCall(DMGetSectionSF(dm, &sf));
31659566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
31667128ae9fSMatthew G Knepley   switch (mode) {
31677128ae9fSMatthew G Knepley   case INSERT_VALUES:
3168d71ae5a4SJacob Faibussowitsch   case INSERT_ALL_VALUES:
3169d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_TRUE;
3170d71ae5a4SJacob Faibussowitsch     break;
31717128ae9fSMatthew G Knepley   case ADD_VALUES:
3172d71ae5a4SJacob Faibussowitsch   case ADD_ALL_VALUES:
3173d71ae5a4SJacob Faibussowitsch     isInsert = PETSC_FALSE;
3174d71ae5a4SJacob Faibussowitsch     break;
3175d71ae5a4SJacob Faibussowitsch   default:
3176d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %d", mode);
31777128ae9fSMatthew G Knepley   }
317884330215SMatthew G. Knepley   if (sf && !isInsert) {
3179ae5cfb4aSMatthew G. Knepley     const PetscScalar *lArray;
3180ae5cfb4aSMatthew G. Knepley     PetscScalar       *gArray;
3181ca3d3a14SMatthew G. Knepley     Vec                tmpl;
318284330215SMatthew G. Knepley 
31839566063dSJacob Faibussowitsch     PetscCall(DMHasBasisTransform(dm, &transform));
3184ca3d3a14SMatthew G. Knepley     if (transform) {
31859566063dSJacob Faibussowitsch       PetscCall(DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
31869566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(tmpl, &lArray));
3187ca3d3a14SMatthew G. Knepley     } else {
31889566063dSJacob Faibussowitsch       PetscCall(VecGetArrayReadAndMemType(l, &lArray, NULL));
3189ca3d3a14SMatthew G. Knepley     }
31909566063dSJacob Faibussowitsch     PetscCall(VecGetArrayAndMemType(g, &gArray, NULL));
31919566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM));
3192ca3d3a14SMatthew G. Knepley     if (transform) {
31939566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(tmpl, &lArray));
31949566063dSJacob Faibussowitsch       PetscCall(DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl));
3195ca3d3a14SMatthew G. Knepley     } else {
31969566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayReadAndMemType(l, &lArray));
3197ca3d3a14SMatthew G. Knepley     }
31989566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayAndMemType(g, &gArray));
319984330215SMatthew G. Knepley   } else if (s && isInsert) {
32007128ae9fSMatthew G Knepley   } else {
3201*fa1e479aSStefano Zampini     PetscUseTypeMethod(dm, localtoglobalend, l, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), g);
32027128ae9fSMatthew G Knepley   }
3203d4d07f1eSToby Isaac   for (link = dm->ltoghook; link; link = link->next) {
32049566063dSJacob Faibussowitsch     if (link->endhook) PetscCall((*link->endhook)(dm, g, mode, l, link->ctx));
3205d4d07f1eSToby Isaac   }
32063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
320747c6ae99SBarry Smith }
320847c6ae99SBarry Smith 
3209f089877aSRichard Tran Mills /*@
3210a4e35b19SJacob Faibussowitsch   DMLocalToLocalBegin - Begins the process of mapping values from a local vector (that include
3211a4e35b19SJacob Faibussowitsch   ghost points that contain irrelevant values) to another local vector where the ghost points
3212a4e35b19SJacob Faibussowitsch   in the second are set correctly from values on other MPI ranks.
3213f089877aSRichard Tran Mills 
321420f4b53cSBarry Smith   Neighbor-wise Collective
3215f089877aSRichard Tran Mills 
3216f089877aSRichard Tran Mills   Input Parameters:
3217bb7acecfSBarry Smith + dm   - the `DM` object
3218bc0a1609SRichard Tran Mills . g    - the original local vector
3219bb7acecfSBarry Smith - mode - one of `INSERT_VALUES` or `ADD_VALUES`
3220f089877aSRichard Tran Mills 
3221bc0a1609SRichard Tran Mills   Output Parameter:
3222bc0a1609SRichard Tran Mills . l - the local vector with correct ghost values
3223f089877aSRichard Tran Mills 
3224f089877aSRichard Tran Mills   Level: intermediate
3225f089877aSRichard Tran Mills 
3226a4e35b19SJacob Faibussowitsch   Notes:
3227a4e35b19SJacob Faibussowitsch   Must be followed by `DMLocalToLocalEnd()`.
3228a4e35b19SJacob Faibussowitsch 
322960225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLocalToLocalEnd()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3230f089877aSRichard Tran Mills @*/
3231d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalBegin(DM dm, Vec g, InsertMode mode, Vec l)
3232d71ae5a4SJacob Faibussowitsch {
3233f089877aSRichard Tran Mills   PetscFunctionBegin;
3234f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32359f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
32369f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(l, VEC_CLASSID, 4);
32379f4ada15SMatthew G. Knepley   PetscUseTypeMethod(dm, localtolocalbegin, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
32383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3239f089877aSRichard Tran Mills }
3240f089877aSRichard Tran Mills 
3241f089877aSRichard Tran Mills /*@
3242bb7acecfSBarry Smith   DMLocalToLocalEnd - Maps from a local vector to another local vector where the ghost
3243bb7acecfSBarry Smith   points in the second are set correctly. Must be preceded by `DMLocalToLocalBegin()`.
3244f089877aSRichard Tran Mills 
324520f4b53cSBarry Smith   Neighbor-wise Collective
3246f089877aSRichard Tran Mills 
3247f089877aSRichard Tran Mills   Input Parameters:
324860225df5SJacob Faibussowitsch + dm   - the `DM` object
3249bc0a1609SRichard Tran Mills . g    - the original local vector
3250bb7acecfSBarry Smith - mode - one of `INSERT_VALUES` or `ADD_VALUES`
3251f089877aSRichard Tran Mills 
3252bc0a1609SRichard Tran Mills   Output Parameter:
3253bc0a1609SRichard Tran Mills . l - the local vector with correct ghost values
3254f089877aSRichard Tran Mills 
3255f089877aSRichard Tran Mills   Level: intermediate
3256f089877aSRichard Tran Mills 
325760225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLocalToLocalBegin()`, `DMCoarsen()`, `DMDestroy()`, `DMView()`, `DMCreateLocalVector()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`
3258f089877aSRichard Tran Mills @*/
3259d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalToLocalEnd(DM dm, Vec g, InsertMode mode, Vec l)
3260d71ae5a4SJacob Faibussowitsch {
3261f089877aSRichard Tran Mills   PetscFunctionBegin;
3262f089877aSRichard Tran Mills   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32639f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(g, VEC_CLASSID, 2);
32649f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(l, VEC_CLASSID, 4);
32659f4ada15SMatthew G. Knepley   PetscUseTypeMethod(dm, localtolocalend, g, mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode), l);
32663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3267f089877aSRichard Tran Mills }
3268f089877aSRichard Tran Mills 
326947c6ae99SBarry Smith /*@
3270bb7acecfSBarry Smith   DMCoarsen - Coarsens a `DM` object using a standard, non-adaptive coarsening of the underlying mesh
327147c6ae99SBarry Smith 
327220f4b53cSBarry Smith   Collective
327347c6ae99SBarry Smith 
3274d8d19677SJose E. Roman   Input Parameters:
3275bb7acecfSBarry Smith + dm   - the `DM` object
327620f4b53cSBarry Smith - comm - the communicator to contain the new `DM` object (or `MPI_COMM_NULL`)
327747c6ae99SBarry Smith 
327847c6ae99SBarry Smith   Output Parameter:
3279bb7acecfSBarry Smith . dmc - the coarsened `DM`
328047c6ae99SBarry Smith 
328147c6ae99SBarry Smith   Level: developer
328247c6ae99SBarry Smith 
32831cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMRefine()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
328447c6ae99SBarry Smith @*/
3285d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc)
3286d71ae5a4SJacob Faibussowitsch {
3287b17ce1afSJed Brown   DMCoarsenHookLink link;
328847c6ae99SBarry Smith 
328947c6ae99SBarry Smith   PetscFunctionBegin;
3290171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32919566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Coarsen, dm, 0, 0, 0));
3292dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, coarsen, comm, dmc);
3293b9d85ea2SLisandro Dalcin   if (*dmc) {
3294a3574896SRichard Tran Mills     (*dmc)->bind_below = dm->bind_below; /* Propagate this from parent DM; otherwise -dm_bind_below will be useless for multigrid cases. */
32959566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dm, *dmc));
329643842a1eSJed Brown     (*dmc)->ops->creatematrix = dm->ops->creatematrix;
32979566063dSJacob Faibussowitsch     PetscCall(PetscObjectCopyFortranFunctionPointers((PetscObject)dm, (PetscObject)*dmc));
3298644e2e5bSBarry Smith     (*dmc)->ctx       = dm->ctx;
32990598a293SJed Brown     (*dmc)->levelup   = dm->levelup;
3300656b349aSBarry Smith     (*dmc)->leveldown = dm->leveldown + 1;
33019566063dSJacob Faibussowitsch     PetscCall(DMSetMatType(*dmc, dm->mattype));
3302b17ce1afSJed Brown     for (link = dm->coarsenhook; link; link = link->next) {
33039566063dSJacob Faibussowitsch       if (link->coarsenhook) PetscCall((*link->coarsenhook)(dm, *dmc, link->ctx));
3304b17ce1afSJed Brown     }
3305b9d85ea2SLisandro Dalcin   }
33069566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Coarsen, dm, 0, 0, 0));
33077a8be351SBarry Smith   PetscCheck(*dmc, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced");
33083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3309b17ce1afSJed Brown }
3310b17ce1afSJed Brown 
3311bb9467b5SJed Brown /*@C
3312b17ce1afSJed Brown   DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid
3313b17ce1afSJed Brown 
331420f4b53cSBarry Smith   Logically Collective; No Fortran Support
3315b17ce1afSJed Brown 
33164165533cSJose E. Roman   Input Parameters:
3317bb7acecfSBarry Smith + fine         - `DM` on which to run a hook when restricting to a coarser level
3318b17ce1afSJed Brown . coarsenhook  - function to run when setting up a coarser level
3319bb7acecfSBarry Smith . restricthook - function to run to update data on coarser levels (called once per `SNESSolve()`)
332020f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3321b17ce1afSJed Brown 
332220f4b53cSBarry Smith   Calling sequence of `coarsenhook`:
3323bb7acecfSBarry Smith + fine   - fine level `DM`
3324bb7acecfSBarry Smith . coarse - coarse level `DM` to restrict problem to
3325b17ce1afSJed Brown - ctx    - optional user-defined function context
3326b17ce1afSJed Brown 
332720f4b53cSBarry Smith   Calling sequence of `restricthook`:
3328bb7acecfSBarry Smith + fine      - fine level `DM`
3329bb7acecfSBarry Smith . mrestrict - matrix restricting a fine-level solution to the coarse grid, usually the transpose of the interpolation
3330c833c3b5SJed Brown . rscale    - scaling vector for restriction
3331c833c3b5SJed Brown . inject    - matrix restricting by injection
3332b17ce1afSJed Brown . coarse    - coarse level DM to update
3333b17ce1afSJed Brown - ctx       - optional user-defined function context
3334b17ce1afSJed Brown 
3335b17ce1afSJed Brown   Level: advanced
3336b17ce1afSJed Brown 
3337b17ce1afSJed Brown   Notes:
3338bb7acecfSBarry 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`.
3339b17ce1afSJed Brown 
3340b17ce1afSJed Brown   If this function is called multiple times, the hooks will be run in the order they are added.
3341b17ce1afSJed Brown 
3342b17ce1afSJed Brown   In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3343bb7acecfSBarry Smith   extract the finest level information from its context (instead of from the `SNES`).
3344b17ce1afSJed Brown 
3345bb7acecfSBarry Smith   The hooks are automatically called by `DMRestrict()`
3346bb7acecfSBarry Smith 
33471cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3348b17ce1afSJed Brown @*/
3349a4e35b19SJacob 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)
3350d71ae5a4SJacob Faibussowitsch {
3351b17ce1afSJed Brown   DMCoarsenHookLink link, *p;
3352b17ce1afSJed Brown 
3353b17ce1afSJed Brown   PetscFunctionBegin;
3354b17ce1afSJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
33551e3d8eccSJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
33563ba16761SJacob Faibussowitsch     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
33571e3d8eccSJed Brown   }
33589566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
3359b17ce1afSJed Brown   link->coarsenhook  = coarsenhook;
3360b17ce1afSJed Brown   link->restricthook = restricthook;
3361b17ce1afSJed Brown   link->ctx          = ctx;
33620298fd71SBarry Smith   link->next         = NULL;
3363b17ce1afSJed Brown   *p                 = link;
33643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3365b17ce1afSJed Brown }
3366b17ce1afSJed Brown 
3367dc822a44SJed Brown /*@C
3368bb7acecfSBarry Smith   DMCoarsenHookRemove - remove a callback set with `DMCoarsenHookAdd()`
3369dc822a44SJed Brown 
337020f4b53cSBarry Smith   Logically Collective; No Fortran Support
3371dc822a44SJed Brown 
33724165533cSJose E. Roman   Input Parameters:
3373bb7acecfSBarry Smith + fine         - `DM` on which to run a hook when restricting to a coarser level
3374dc822a44SJed Brown . coarsenhook  - function to run when setting up a coarser level
3375bb7acecfSBarry Smith . restricthook - function to run to update data on coarser levels
337620f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3377dc822a44SJed Brown 
3378dc822a44SJed Brown   Level: advanced
3379dc822a44SJed Brown 
3380bb7acecfSBarry Smith   Note:
3381dc822a44SJed Brown   This function does nothing if the hook is not in the list.
3382dc822a44SJed Brown 
33831cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3384dc822a44SJed Brown @*/
3385d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHookRemove(DM fine, PetscErrorCode (*coarsenhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, Mat, Vec, Mat, DM, void *), void *ctx)
3386d71ae5a4SJacob Faibussowitsch {
3387dc822a44SJed Brown   DMCoarsenHookLink link, *p;
3388dc822a44SJed Brown 
3389dc822a44SJed Brown   PetscFunctionBegin;
3390dc822a44SJed Brown   PetscValidHeaderSpecific(fine, DM_CLASSID, 1);
3391dc822a44SJed Brown   for (p = &fine->coarsenhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3392dc822a44SJed Brown     if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3393dc822a44SJed Brown       link = *p;
3394dc822a44SJed Brown       *p   = link->next;
33959566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3396dc822a44SJed Brown       break;
3397dc822a44SJed Brown     }
3398dc822a44SJed Brown   }
33993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3400dc822a44SJed Brown }
3401dc822a44SJed Brown 
3402b17ce1afSJed Brown /*@
3403bb7acecfSBarry Smith   DMRestrict - restricts user-defined problem data to a coarser `DM` by running hooks registered by `DMCoarsenHookAdd()`
3404b17ce1afSJed Brown 
3405b17ce1afSJed Brown   Collective if any hooks are
3406b17ce1afSJed Brown 
34074165533cSJose E. Roman   Input Parameters:
3408bb7acecfSBarry Smith + fine    - finer `DM` from which the data is obtained
3409bb7acecfSBarry Smith . restrct - restriction matrix, apply using `MatRestrict()`, usually the transpose of the interpolation
3410e91eccc2SStefano Zampini . rscale  - scaling vector for restriction
3411bb7acecfSBarry Smith . inject  - injection matrix, also use `MatRestrict()`
341220f4b53cSBarry Smith - coarse  - coarser `DM` to update
3413b17ce1afSJed Brown 
3414b17ce1afSJed Brown   Level: developer
3415b17ce1afSJed Brown 
341660225df5SJacob Faibussowitsch   Developer Notes:
3417bb7acecfSBarry Smith   Though this routine is called `DMRestrict()` the hooks are added with `DMCoarsenHookAdd()`, a consistent terminology would be better
3418bb7acecfSBarry Smith 
34191cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `MatRestrict()`, `DMInterpolate()`, `DMRefineHookAdd()`
3420b17ce1afSJed Brown @*/
3421d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestrict(DM fine, Mat restrct, Vec rscale, Mat inject, DM coarse)
3422d71ae5a4SJacob Faibussowitsch {
3423b17ce1afSJed Brown   DMCoarsenHookLink link;
3424b17ce1afSJed Brown 
3425b17ce1afSJed Brown   PetscFunctionBegin;
3426b17ce1afSJed Brown   for (link = fine->coarsenhook; link; link = link->next) {
34271baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(fine, restrct, rscale, inject, coarse, link->ctx));
3428b17ce1afSJed Brown   }
34293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
343047c6ae99SBarry Smith }
343147c6ae99SBarry Smith 
3432bb9467b5SJed Brown /*@C
3433be081cd6SPeter Brune   DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid
34345dbd56e3SPeter Brune 
343520f4b53cSBarry Smith   Logically Collective; No Fortran Support
34365dbd56e3SPeter Brune 
34374165533cSJose E. Roman   Input Parameters:
3438bb7acecfSBarry Smith + global       - global `DM`
3439bb7acecfSBarry Smith . ddhook       - function to run to pass data to the decomposition `DM` upon its creation
34405dbd56e3SPeter Brune . restricthook - function to run to update data on block solve (at the beginning of the block solve)
344120f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
34425dbd56e3SPeter Brune 
344320f4b53cSBarry Smith   Calling sequence of `ddhook`:
3444bb7acecfSBarry Smith + global - global `DM`
3445bb7acecfSBarry Smith . block  - block `DM`
3446ec4806b8SPeter Brune - ctx    - optional user-defined function context
3447ec4806b8SPeter Brune 
344820f4b53cSBarry Smith   Calling sequence of `restricthook`:
3449bb7acecfSBarry Smith + global - global `DM`
34505dbd56e3SPeter Brune . out    - scatter to the outer (with ghost and overlap points) block vector
34515dbd56e3SPeter Brune . in     - scatter to block vector values only owned locally
3452bb7acecfSBarry Smith . block  - block `DM`
34535dbd56e3SPeter Brune - ctx    - optional user-defined function context
34545dbd56e3SPeter Brune 
34555dbd56e3SPeter Brune   Level: advanced
34565dbd56e3SPeter Brune 
34575dbd56e3SPeter Brune   Notes:
3458bb7acecfSBarry Smith   This function is only needed if auxiliary data needs to be set up on subdomain `DM`s.
34595dbd56e3SPeter Brune 
34605dbd56e3SPeter Brune   If this function is called multiple times, the hooks will be run in the order they are added.
34615dbd56e3SPeter Brune 
34625dbd56e3SPeter Brune   In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to
3463bb7acecfSBarry Smith   extract the global information from its context (instead of from the `SNES`).
34645dbd56e3SPeter Brune 
34651cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSubDomainHookRemove()`, `DMRefineHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
34665dbd56e3SPeter Brune @*/
3467a4e35b19SJacob 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)
3468d71ae5a4SJacob Faibussowitsch {
3469be081cd6SPeter Brune   DMSubDomainHookLink link, *p;
34705dbd56e3SPeter Brune 
34715dbd56e3SPeter Brune   PetscFunctionBegin;
34725dbd56e3SPeter Brune   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3473b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Scan to the end of the current list of hooks */
34743ba16761SJacob Faibussowitsch     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(PETSC_SUCCESS);
3475b3a6b972SJed Brown   }
34769566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
34775dbd56e3SPeter Brune   link->restricthook = restricthook;
3478be081cd6SPeter Brune   link->ddhook       = ddhook;
34795dbd56e3SPeter Brune   link->ctx          = ctx;
34800298fd71SBarry Smith   link->next         = NULL;
34815dbd56e3SPeter Brune   *p                 = link;
34823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34835dbd56e3SPeter Brune }
34845dbd56e3SPeter Brune 
3485b3a6b972SJed Brown /*@C
3486b3a6b972SJed Brown   DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid
3487b3a6b972SJed Brown 
348820f4b53cSBarry Smith   Logically Collective; No Fortran Support
3489b3a6b972SJed Brown 
34904165533cSJose E. Roman   Input Parameters:
3491bb7acecfSBarry Smith + global       - global `DM`
3492bb7acecfSBarry Smith . ddhook       - function to run to pass data to the decomposition `DM` upon its creation
3493b3a6b972SJed Brown . restricthook - function to run to update data on block solve (at the beginning of the block solve)
349420f4b53cSBarry Smith - ctx          - [optional] user-defined context for provide data for the hooks (may be `NULL`)
3495b3a6b972SJed Brown 
3496b3a6b972SJed Brown   Level: advanced
3497b3a6b972SJed Brown 
34981cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSubDomainHookAdd()`, `SNESFASGetInterpolation()`, `SNESFASGetInjection()`, `PetscObjectCompose()`, `PetscContainerCreate()`
3499b3a6b972SJed Brown @*/
3500d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainHookRemove(DM global, PetscErrorCode (*ddhook)(DM, DM, void *), PetscErrorCode (*restricthook)(DM, VecScatter, VecScatter, DM, void *), void *ctx)
3501d71ae5a4SJacob Faibussowitsch {
3502b3a6b972SJed Brown   DMSubDomainHookLink link, *p;
3503b3a6b972SJed Brown 
3504b3a6b972SJed Brown   PetscFunctionBegin;
3505b3a6b972SJed Brown   PetscValidHeaderSpecific(global, DM_CLASSID, 1);
3506b3a6b972SJed Brown   for (p = &global->subdomainhook; *p; p = &(*p)->next) { /* Search the list of current hooks */
3507b3a6b972SJed Brown     if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) {
3508b3a6b972SJed Brown       link = *p;
3509b3a6b972SJed Brown       *p   = link->next;
35109566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
3511b3a6b972SJed Brown       break;
3512b3a6b972SJed Brown     }
3513b3a6b972SJed Brown   }
35143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3515b3a6b972SJed Brown }
3516b3a6b972SJed Brown 
35175dbd56e3SPeter Brune /*@
3518bb7acecfSBarry Smith   DMSubDomainRestrict - restricts user-defined problem data to a block `DM` by running hooks registered by `DMSubDomainHookAdd()`
35195dbd56e3SPeter Brune 
35205dbd56e3SPeter Brune   Collective if any hooks are
35215dbd56e3SPeter Brune 
35224165533cSJose E. Roman   Input Parameters:
3523a4e35b19SJacob Faibussowitsch + global   - The global `DM` to use as a base
3524a4e35b19SJacob Faibussowitsch . oscatter - The scatter from domain global vector filling subdomain global vector with overlap
3525a4e35b19SJacob Faibussowitsch . gscatter - The scatter from domain global vector filling subdomain local vector with ghosts
3526a4e35b19SJacob Faibussowitsch - subdm    - The subdomain `DM` to update
35275dbd56e3SPeter Brune 
35285dbd56e3SPeter Brune   Level: developer
35295dbd56e3SPeter Brune 
35301cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsenHookAdd()`, `MatRestrict()`
35315dbd56e3SPeter Brune @*/
3532d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSubDomainRestrict(DM global, VecScatter oscatter, VecScatter gscatter, DM subdm)
3533d71ae5a4SJacob Faibussowitsch {
3534be081cd6SPeter Brune   DMSubDomainHookLink link;
35355dbd56e3SPeter Brune 
35365dbd56e3SPeter Brune   PetscFunctionBegin;
3537be081cd6SPeter Brune   for (link = global->subdomainhook; link; link = link->next) {
35381baa6e33SBarry Smith     if (link->restricthook) PetscCall((*link->restricthook)(global, oscatter, gscatter, subdm, link->ctx));
35395dbd56e3SPeter Brune   }
35403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35415dbd56e3SPeter Brune }
35425dbd56e3SPeter Brune 
35435fe1f584SPeter Brune /*@
3544bb7acecfSBarry Smith   DMGetCoarsenLevel - Gets the number of coarsenings that have generated this `DM`.
35455fe1f584SPeter Brune 
35465fe1f584SPeter Brune   Not Collective
35475fe1f584SPeter Brune 
35485fe1f584SPeter Brune   Input Parameter:
3549bb7acecfSBarry Smith . dm - the `DM` object
35505fe1f584SPeter Brune 
35515fe1f584SPeter Brune   Output Parameter:
35526a7d9d85SPeter Brune . level - number of coarsenings
35535fe1f584SPeter Brune 
35545fe1f584SPeter Brune   Level: developer
35555fe1f584SPeter Brune 
35561cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMSetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
35575fe1f584SPeter Brune @*/
3558d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarsenLevel(DM dm, PetscInt *level)
3559d71ae5a4SJacob Faibussowitsch {
35605fe1f584SPeter Brune   PetscFunctionBegin;
35615fe1f584SPeter Brune   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35624f572ea9SToby Isaac   PetscAssertPointer(level, 2);
35635fe1f584SPeter Brune   *level = dm->leveldown;
35643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35655fe1f584SPeter Brune }
35665fe1f584SPeter Brune 
35679a64c4a8SMatthew G. Knepley /*@
3568bb7acecfSBarry Smith   DMSetCoarsenLevel - Sets the number of coarsenings that have generated this `DM`.
35699a64c4a8SMatthew G. Knepley 
357020f4b53cSBarry Smith   Collective
35719a64c4a8SMatthew G. Knepley 
35729a64c4a8SMatthew G. Knepley   Input Parameters:
3573bb7acecfSBarry Smith + dm    - the `DM` object
35749a64c4a8SMatthew G. Knepley - level - number of coarsenings
35759a64c4a8SMatthew G. Knepley 
35769a64c4a8SMatthew G. Knepley   Level: developer
35779a64c4a8SMatthew G. Knepley 
3578bb7acecfSBarry Smith   Note:
3579bb7acecfSBarry Smith   This is rarely used directly, the information is automatically set when a `DM` is created with `DMCoarsen()`
3580bb7acecfSBarry Smith 
358142747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMGetCoarsenLevel()`, `DMGetRefineLevel()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
35829a64c4a8SMatthew G. Knepley @*/
3583d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarsenLevel(DM dm, PetscInt level)
3584d71ae5a4SJacob Faibussowitsch {
35859a64c4a8SMatthew G. Knepley   PetscFunctionBegin;
35869a64c4a8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35879a64c4a8SMatthew G. Knepley   dm->leveldown = level;
35883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35899a64c4a8SMatthew G. Knepley }
35909a64c4a8SMatthew G. Knepley 
359147c6ae99SBarry Smith /*@C
3592bb7acecfSBarry Smith   DMRefineHierarchy - Refines a `DM` object, all levels at once
359347c6ae99SBarry Smith 
359420f4b53cSBarry Smith   Collective
359547c6ae99SBarry Smith 
3596d8d19677SJose E. Roman   Input Parameters:
3597bb7acecfSBarry Smith + dm      - the `DM` object
359847c6ae99SBarry Smith - nlevels - the number of levels of refinement
359947c6ae99SBarry Smith 
360047c6ae99SBarry Smith   Output Parameter:
3601bb7acecfSBarry Smith . dmf - the refined `DM` hierarchy
360247c6ae99SBarry Smith 
360347c6ae99SBarry Smith   Level: developer
360447c6ae99SBarry Smith 
36051cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMCoarsenHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
360647c6ae99SBarry Smith @*/
3607d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRefineHierarchy(DM dm, PetscInt nlevels, DM dmf[])
3608d71ae5a4SJacob Faibussowitsch {
360947c6ae99SBarry Smith   PetscFunctionBegin;
3610171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36117a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
36123ba16761SJacob Faibussowitsch   if (nlevels == 0) PetscFunctionReturn(PETSC_SUCCESS);
36134f572ea9SToby Isaac   PetscAssertPointer(dmf, 3);
3614213acdd3SPierre Jolivet   if (dm->ops->refine && !dm->ops->refinehierarchy) {
361547c6ae99SBarry Smith     PetscInt i;
361647c6ae99SBarry Smith 
36179566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &dmf[0]));
361848a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMRefine(dmf[i - 1], PetscObjectComm((PetscObject)dm), &dmf[i]));
3619213acdd3SPierre Jolivet   } else PetscUseTypeMethod(dm, refinehierarchy, nlevels, dmf);
36203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
362147c6ae99SBarry Smith }
362247c6ae99SBarry Smith 
362347c6ae99SBarry Smith /*@C
3624bb7acecfSBarry Smith   DMCoarsenHierarchy - Coarsens a `DM` object, all levels at once
362547c6ae99SBarry Smith 
362620f4b53cSBarry Smith   Collective
362747c6ae99SBarry Smith 
3628d8d19677SJose E. Roman   Input Parameters:
3629bb7acecfSBarry Smith + dm      - the `DM` object
363047c6ae99SBarry Smith - nlevels - the number of levels of coarsening
363147c6ae99SBarry Smith 
363247c6ae99SBarry Smith   Output Parameter:
3633bb7acecfSBarry Smith . dmc - the coarsened `DM` hierarchy
363447c6ae99SBarry Smith 
363547c6ae99SBarry Smith   Level: developer
363647c6ae99SBarry Smith 
36371cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCoarsen()`, `DMRefineHierarchy()`, `DMDestroy()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`
363847c6ae99SBarry Smith @*/
3639d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[])
3640d71ae5a4SJacob Faibussowitsch {
364147c6ae99SBarry Smith   PetscFunctionBegin;
3642171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36437a8be351SBarry Smith   PetscCheck(nlevels >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "nlevels cannot be negative");
36443ba16761SJacob Faibussowitsch   if (nlevels == 0) PetscFunctionReturn(PETSC_SUCCESS);
36454f572ea9SToby Isaac   PetscAssertPointer(dmc, 3);
3646213acdd3SPierre Jolivet   if (dm->ops->coarsen && !dm->ops->coarsenhierarchy) {
364747c6ae99SBarry Smith     PetscInt i;
364847c6ae99SBarry Smith 
36499566063dSJacob Faibussowitsch     PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &dmc[0]));
365048a46eb9SPierre Jolivet     for (i = 1; i < nlevels; i++) PetscCall(DMCoarsen(dmc[i - 1], PetscObjectComm((PetscObject)dm), &dmc[i]));
3651213acdd3SPierre Jolivet   } else PetscUseTypeMethod(dm, coarsenhierarchy, nlevels, dmc);
36523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
365347c6ae99SBarry Smith }
365447c6ae99SBarry Smith 
36551a266240SBarry Smith /*@C
3656bb7acecfSBarry Smith   DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the `DM` is destroyed
36571a266240SBarry Smith 
3658bb7acecfSBarry Smith   Logically Collective if the function is collective
36591a266240SBarry Smith 
36601a266240SBarry Smith   Input Parameters:
3661bb7acecfSBarry Smith + dm      - the `DM` object
36621a266240SBarry Smith - destroy - the destroy function
36631a266240SBarry Smith 
36641a266240SBarry Smith   Level: intermediate
36651a266240SBarry Smith 
36661cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
3667f07f9ceaSJed Brown @*/
3668d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetApplicationContextDestroy(DM dm, PetscErrorCode (*destroy)(void **))
3669d71ae5a4SJacob Faibussowitsch {
36701a266240SBarry Smith   PetscFunctionBegin;
3671171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36721a266240SBarry Smith   dm->ctxdestroy = destroy;
36733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36741a266240SBarry Smith }
36751a266240SBarry Smith 
3676b07ff414SBarry Smith /*@
3677bb7acecfSBarry Smith   DMSetApplicationContext - Set a user context into a `DM` object
367847c6ae99SBarry Smith 
367947c6ae99SBarry Smith   Not Collective
368047c6ae99SBarry Smith 
368147c6ae99SBarry Smith   Input Parameters:
3682bb7acecfSBarry Smith + dm  - the `DM` object
368347c6ae99SBarry Smith - ctx - the user context
368447c6ae99SBarry Smith 
368547c6ae99SBarry Smith   Level: intermediate
368647c6ae99SBarry Smith 
3687bb7acecfSBarry Smith   Note:
368835cb6cd3SPierre Jolivet   A user context is a way to pass problem specific information that is accessible whenever the `DM` is available
3689bb7acecfSBarry Smith 
369060225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMGetApplicationContext()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
369147c6ae99SBarry Smith @*/
3692d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetApplicationContext(DM dm, void *ctx)
3693d71ae5a4SJacob Faibussowitsch {
369447c6ae99SBarry Smith   PetscFunctionBegin;
3695171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
369647c6ae99SBarry Smith   dm->ctx = ctx;
36973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
369847c6ae99SBarry Smith }
369947c6ae99SBarry Smith 
370047c6ae99SBarry Smith /*@
3701bb7acecfSBarry Smith   DMGetApplicationContext - Gets a user context from a `DM` object
370247c6ae99SBarry Smith 
370347c6ae99SBarry Smith   Not Collective
370447c6ae99SBarry Smith 
370547c6ae99SBarry Smith   Input Parameter:
3706bb7acecfSBarry Smith . dm - the `DM` object
370747c6ae99SBarry Smith 
370847c6ae99SBarry Smith   Output Parameter:
370947c6ae99SBarry Smith . ctx - the user context
371047c6ae99SBarry Smith 
371147c6ae99SBarry Smith   Level: intermediate
371247c6ae99SBarry Smith 
3713bb7acecfSBarry Smith   Note:
371435cb6cd3SPierre Jolivet   A user context is a way to pass problem specific information that is accessible whenever the `DM` is available
3715bb7acecfSBarry Smith 
371642747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`
371747c6ae99SBarry Smith @*/
3718d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetApplicationContext(DM dm, void *ctx)
3719d71ae5a4SJacob Faibussowitsch {
372047c6ae99SBarry Smith   PetscFunctionBegin;
3721171400e9SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37221b2093e4SBarry Smith   *(void **)ctx = dm->ctx;
37233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
372447c6ae99SBarry Smith }
372547c6ae99SBarry Smith 
372608da532bSDmitry Karpeev /*@C
3727bb7acecfSBarry Smith   DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for `SNESVI`.
372808da532bSDmitry Karpeev 
372920f4b53cSBarry Smith   Logically Collective
373008da532bSDmitry Karpeev 
3731d8d19677SJose E. Roman   Input Parameters:
373208da532bSDmitry Karpeev + dm - the DM object
373320f4b53cSBarry Smith - f  - the function that computes variable bounds used by SNESVI (use `NULL` to cancel a previous function that was set)
373408da532bSDmitry Karpeev 
373508da532bSDmitry Karpeev   Level: intermediate
373608da532bSDmitry Karpeev 
37371cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMComputeVariableBounds()`, `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`,
3738db781477SPatrick Sanan          `DMSetJacobian()`
373908da532bSDmitry Karpeev @*/
3740d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetVariableBounds(DM dm, PetscErrorCode (*f)(DM, Vec, Vec))
3741d71ae5a4SJacob Faibussowitsch {
374208da532bSDmitry Karpeev   PetscFunctionBegin;
37435a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
374408da532bSDmitry Karpeev   dm->ops->computevariablebounds = f;
37453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
374608da532bSDmitry Karpeev }
374708da532bSDmitry Karpeev 
374808da532bSDmitry Karpeev /*@
3749bb7acecfSBarry Smith   DMHasVariableBounds - does the `DM` object have a variable bounds function?
375008da532bSDmitry Karpeev 
375108da532bSDmitry Karpeev   Not Collective
375208da532bSDmitry Karpeev 
375308da532bSDmitry Karpeev   Input Parameter:
3754bb7acecfSBarry Smith . dm - the `DM` object to destroy
375508da532bSDmitry Karpeev 
375608da532bSDmitry Karpeev   Output Parameter:
3757bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the variable bounds function exists
375808da532bSDmitry Karpeev 
375908da532bSDmitry Karpeev   Level: developer
376008da532bSDmitry Karpeev 
37611cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMComputeVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
376208da532bSDmitry Karpeev @*/
3763d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasVariableBounds(DM dm, PetscBool *flg)
3764d71ae5a4SJacob Faibussowitsch {
376508da532bSDmitry Karpeev   PetscFunctionBegin;
37665a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37674f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
376808da532bSDmitry Karpeev   *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE;
37693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
377008da532bSDmitry Karpeev }
377108da532bSDmitry Karpeev 
377208da532bSDmitry Karpeev /*@C
3773bb7acecfSBarry Smith   DMComputeVariableBounds - compute variable bounds used by `SNESVI`.
377408da532bSDmitry Karpeev 
377520f4b53cSBarry Smith   Logically Collective
377608da532bSDmitry Karpeev 
3777f899ff85SJose E. Roman   Input Parameter:
3778bb7acecfSBarry Smith . dm - the `DM` object
377908da532bSDmitry Karpeev 
378060225df5SJacob Faibussowitsch   Output Parameters:
378108da532bSDmitry Karpeev + xl - lower bound
378208da532bSDmitry Karpeev - xu - upper bound
378308da532bSDmitry Karpeev 
3784907376e6SBarry Smith   Level: advanced
3785907376e6SBarry Smith 
378620f4b53cSBarry Smith   Note:
378795452b02SPatrick Sanan   This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds()
378808da532bSDmitry Karpeev 
37891cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMHasVariableBounds()`, `DMView()`, `DMCreateGlobalVector()`, `DMCreateInterpolation()`, `DMCreateColoring()`, `DMCreateMatrix()`, `DMCreateMassMatrix()`, `DMGetApplicationContext()`
379008da532bSDmitry Karpeev @*/
3791d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu)
3792d71ae5a4SJacob Faibussowitsch {
379308da532bSDmitry Karpeev   PetscFunctionBegin;
37945a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
379508da532bSDmitry Karpeev   PetscValidHeaderSpecific(xl, VEC_CLASSID, 2);
37965a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(xu, VEC_CLASSID, 3);
3797dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, computevariablebounds, xl, xu);
37983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
379908da532bSDmitry Karpeev }
380008da532bSDmitry Karpeev 
3801b0ae01b7SPeter Brune /*@
3802bb7acecfSBarry Smith   DMHasColoring - does the `DM` object have a method of providing a coloring?
3803b0ae01b7SPeter Brune 
3804b0ae01b7SPeter Brune   Not Collective
3805b0ae01b7SPeter Brune 
3806b0ae01b7SPeter Brune   Input Parameter:
3807b0ae01b7SPeter Brune . dm - the DM object
3808b0ae01b7SPeter Brune 
3809b0ae01b7SPeter Brune   Output Parameter:
3810bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateColoring()`.
3811b0ae01b7SPeter Brune 
3812b0ae01b7SPeter Brune   Level: developer
3813b0ae01b7SPeter Brune 
38141cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateColoring()`
3815b0ae01b7SPeter Brune @*/
3816d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasColoring(DM dm, PetscBool *flg)
3817d71ae5a4SJacob Faibussowitsch {
3818b0ae01b7SPeter Brune   PetscFunctionBegin;
38195a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38204f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
3821b0ae01b7SPeter Brune   *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE;
38223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3823b0ae01b7SPeter Brune }
3824b0ae01b7SPeter Brune 
38253ad4599aSBarry Smith /*@
3826bb7acecfSBarry Smith   DMHasCreateRestriction - does the `DM` object have a method of providing a restriction?
38273ad4599aSBarry Smith 
38283ad4599aSBarry Smith   Not Collective
38293ad4599aSBarry Smith 
38303ad4599aSBarry Smith   Input Parameter:
3831bb7acecfSBarry Smith . dm - the `DM` object
38323ad4599aSBarry Smith 
38333ad4599aSBarry Smith   Output Parameter:
3834bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateRestriction()`.
38353ad4599aSBarry Smith 
38363ad4599aSBarry Smith   Level: developer
38373ad4599aSBarry Smith 
38381cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateRestriction()`, `DMHasCreateInterpolation()`, `DMHasCreateInjection()`
38393ad4599aSBarry Smith @*/
3840d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateRestriction(DM dm, PetscBool *flg)
3841d71ae5a4SJacob Faibussowitsch {
38423ad4599aSBarry Smith   PetscFunctionBegin;
38435a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38444f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
38453ad4599aSBarry Smith   *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE;
38463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38473ad4599aSBarry Smith }
38483ad4599aSBarry Smith 
3849a7058e45SLawrence Mitchell /*@
3850bb7acecfSBarry Smith   DMHasCreateInjection - does the `DM` object have a method of providing an injection?
3851a7058e45SLawrence Mitchell 
3852a7058e45SLawrence Mitchell   Not Collective
3853a7058e45SLawrence Mitchell 
3854a7058e45SLawrence Mitchell   Input Parameter:
3855bb7acecfSBarry Smith . dm - the `DM` object
3856a7058e45SLawrence Mitchell 
3857a7058e45SLawrence Mitchell   Output Parameter:
3858bb7acecfSBarry Smith . flg - `PETSC_TRUE` if the `DM` has facilities for `DMCreateInjection()`.
3859a7058e45SLawrence Mitchell 
3860a7058e45SLawrence Mitchell   Level: developer
3861a7058e45SLawrence Mitchell 
38621cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateInjection()`, `DMHasCreateRestriction()`, `DMHasCreateInterpolation()`
3863a7058e45SLawrence Mitchell @*/
3864d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasCreateInjection(DM dm, PetscBool *flg)
3865d71ae5a4SJacob Faibussowitsch {
3866a7058e45SLawrence Mitchell   PetscFunctionBegin;
38675a84ad33SLisandro Dalcin   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38684f572ea9SToby Isaac   PetscAssertPointer(flg, 2);
3869dbbe0bcdSBarry Smith   if (dm->ops->hascreateinjection) PetscUseTypeMethod(dm, hascreateinjection, flg);
3870ad540459SPierre Jolivet   else *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE;
38713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3872a7058e45SLawrence Mitchell }
3873a7058e45SLawrence Mitchell 
38740298fd71SBarry Smith PetscFunctionList DMList              = NULL;
3875264ace61SBarry Smith PetscBool         DMRegisterAllCalled = PETSC_FALSE;
3876264ace61SBarry Smith 
3877264ace61SBarry Smith /*@C
3878bb7acecfSBarry Smith   DMSetType - Builds a `DM`, for a particular `DM` implementation.
3879264ace61SBarry Smith 
388020f4b53cSBarry Smith   Collective
3881264ace61SBarry Smith 
3882264ace61SBarry Smith   Input Parameters:
3883bb7acecfSBarry Smith + dm     - The `DM` object
3884bb7acecfSBarry Smith - method - The name of the `DMType`, for example `DMDA`, `DMPLEX`
3885264ace61SBarry Smith 
3886264ace61SBarry Smith   Options Database Key:
3887bb7acecfSBarry Smith . -dm_type <type> - Sets the `DM` type; use -help for a list of available types
3888264ace61SBarry Smith 
3889264ace61SBarry Smith   Level: intermediate
3890264ace61SBarry Smith 
3891bb7acecfSBarry Smith   Note:
38920462cc06SPierre Jolivet   Of the `DM` is constructed by directly calling a function to construct a particular `DM`, for example, `DMDACreate2d()` or `DMPlexCreateBoxMesh()`
3893bb7acecfSBarry Smith 
38941cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMDA`, `DMPLEX`, `DMGetType()`, `DMCreate()`, `DMDACreate2d()`
3895264ace61SBarry Smith @*/
3896d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetType(DM dm, DMType method)
3897d71ae5a4SJacob Faibussowitsch {
3898264ace61SBarry Smith   PetscErrorCode (*r)(DM);
3899264ace61SBarry Smith   PetscBool match;
3900264ace61SBarry Smith 
3901264ace61SBarry Smith   PetscFunctionBegin;
3902264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, method, &match));
39043ba16761SJacob Faibussowitsch   if (match) PetscFunctionReturn(PETSC_SUCCESS);
3905264ace61SBarry Smith 
39069566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
39079566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(DMList, method, &r));
39087a8be351SBarry Smith   PetscCheck(r, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method);
3909264ace61SBarry Smith 
3910dbbe0bcdSBarry Smith   PetscTryTypeMethod(dm, destroy);
39119566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(dm->ops, sizeof(*dm->ops)));
39129566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)dm, method));
39139566063dSJacob Faibussowitsch   PetscCall((*r)(dm));
39143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3915264ace61SBarry Smith }
3916264ace61SBarry Smith 
3917264ace61SBarry Smith /*@C
3918bb7acecfSBarry Smith   DMGetType - Gets the `DM` type name (as a string) from the `DM`.
3919264ace61SBarry Smith 
3920264ace61SBarry Smith   Not Collective
3921264ace61SBarry Smith 
3922264ace61SBarry Smith   Input Parameter:
3923bb7acecfSBarry Smith . dm - The `DM`
3924264ace61SBarry Smith 
3925264ace61SBarry Smith   Output Parameter:
3926bb7acecfSBarry Smith . type - The `DMType` name
3927264ace61SBarry Smith 
3928264ace61SBarry Smith   Level: intermediate
3929264ace61SBarry Smith 
39301cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMDA`, `DMPLEX`, `DMSetType()`, `DMCreate()`
3931264ace61SBarry Smith @*/
3932d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetType(DM dm, DMType *type)
3933d71ae5a4SJacob Faibussowitsch {
3934264ace61SBarry Smith   PetscFunctionBegin;
3935264ace61SBarry Smith   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39364f572ea9SToby Isaac   PetscAssertPointer(type, 2);
39379566063dSJacob Faibussowitsch   PetscCall(DMRegisterAll());
3938264ace61SBarry Smith   *type = ((PetscObject)dm)->type_name;
39393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3940264ace61SBarry Smith }
3941264ace61SBarry Smith 
394267a56275SMatthew G Knepley /*@C
3943bb7acecfSBarry Smith   DMConvert - Converts a `DM` to another `DM`, either of the same or different type.
394467a56275SMatthew G Knepley 
394520f4b53cSBarry Smith   Collective
394667a56275SMatthew G Knepley 
394767a56275SMatthew G Knepley   Input Parameters:
3948bb7acecfSBarry Smith + dm      - the `DM`
3949bb7acecfSBarry Smith - newtype - new `DM` type (use "same" for the same type)
395067a56275SMatthew G Knepley 
395167a56275SMatthew G Knepley   Output Parameter:
3952bb7acecfSBarry Smith . M - pointer to new `DM`
395367a56275SMatthew G Knepley 
395420f4b53cSBarry Smith   Level: intermediate
395520f4b53cSBarry Smith 
395667a56275SMatthew G Knepley   Notes:
3957bb7acecfSBarry Smith   Cannot be used to convert a sequential `DM` to a parallel or a parallel to sequential,
3958bb7acecfSBarry Smith   the MPI communicator of the generated `DM` is always the same as the communicator
3959bb7acecfSBarry Smith   of the input `DM`.
396067a56275SMatthew G Knepley 
39611cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetType()`, `DMCreate()`, `DMClone()`
396267a56275SMatthew G Knepley @*/
3963d71ae5a4SJacob Faibussowitsch PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M)
3964d71ae5a4SJacob Faibussowitsch {
396567a56275SMatthew G Knepley   DM        B;
396667a56275SMatthew G Knepley   char      convname[256];
3967c067b6caSMatthew G. Knepley   PetscBool sametype /*, issame */;
396867a56275SMatthew G Knepley 
396967a56275SMatthew G Knepley   PetscFunctionBegin;
397067a56275SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
397167a56275SMatthew G Knepley   PetscValidType(dm, 1);
39724f572ea9SToby Isaac   PetscAssertPointer(M, 3);
39739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dm, newtype, &sametype));
39749566063dSJacob Faibussowitsch   /* PetscCall(PetscStrcmp(newtype, "same", &issame)); */
3975c067b6caSMatthew G. Knepley   if (sametype) {
3976c067b6caSMatthew G. Knepley     *M = dm;
39779566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
39783ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3979c067b6caSMatthew G. Knepley   } else {
39800298fd71SBarry Smith     PetscErrorCode (*conv)(DM, DMType, DM *) = NULL;
398167a56275SMatthew G Knepley 
398267a56275SMatthew G Knepley     /*
398367a56275SMatthew G Knepley        Order of precedence:
398467a56275SMatthew G Knepley        1) See if a specialized converter is known to the current DM.
398567a56275SMatthew G Knepley        2) See if a specialized converter is known to the desired DM class.
398667a56275SMatthew G Knepley        3) See if a good general converter is registered for the desired class
398767a56275SMatthew G Knepley        4) See if a good general converter is known for the current matrix.
398867a56275SMatthew G Knepley        5) Use a really basic converter.
398967a56275SMatthew G Knepley     */
399067a56275SMatthew G Knepley 
399167a56275SMatthew G Knepley     /* 1) See if a specialized converter is known to the current DM and the desired class */
39929566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
39939566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
39949566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
39959566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
39969566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
39979566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)dm, convname, &conv));
399867a56275SMatthew G Knepley     if (conv) goto foundconv;
399967a56275SMatthew G Knepley 
400067a56275SMatthew G Knepley     /* 2)  See if a specialized converter is known to the desired DM class. */
40019566063dSJacob Faibussowitsch     PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &B));
40029566063dSJacob Faibussowitsch     PetscCall(DMSetType(B, newtype));
40039566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(convname, "DMConvert_", sizeof(convname)));
40049566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, ((PetscObject)dm)->type_name, sizeof(convname)));
40059566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
40069566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
40079566063dSJacob Faibussowitsch     PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
40089566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
400967a56275SMatthew G Knepley     if (conv) {
40109566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&B));
401167a56275SMatthew G Knepley       goto foundconv;
401267a56275SMatthew G Knepley     }
401367a56275SMatthew G Knepley 
401467a56275SMatthew G Knepley #if 0
401567a56275SMatthew G Knepley     /* 3) See if a good general converter is registered for the desired class */
401667a56275SMatthew G Knepley     conv = B->ops->convertfrom;
40179566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&B));
401867a56275SMatthew G Knepley     if (conv) goto foundconv;
401967a56275SMatthew G Knepley 
402067a56275SMatthew G Knepley     /* 4) See if a good general converter is known for the current matrix */
402167a56275SMatthew G Knepley     if (dm->ops->convert) {
402267a56275SMatthew G Knepley       conv = dm->ops->convert;
402367a56275SMatthew G Knepley     }
402467a56275SMatthew G Knepley     if (conv) goto foundconv;
402567a56275SMatthew G Knepley #endif
402667a56275SMatthew G Knepley 
402767a56275SMatthew G Knepley     /* 5) Use a really basic converter. */
402898921bdaSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject)dm)->type_name, newtype);
402967a56275SMatthew G Knepley 
403067a56275SMatthew G Knepley   foundconv:
40319566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(DM_Convert, dm, 0, 0, 0));
40329566063dSJacob Faibussowitsch     PetscCall((*conv)(dm, newtype, M));
403312fa691eSMatthew G. Knepley     /* Things that are independent of DM type: We should consult DMClone() here */
403490b157c4SStefano Zampini     {
40354fb89dddSMatthew G. Knepley       const PetscReal *maxCell, *Lstart, *L;
40366858538eSMatthew G. Knepley 
40374fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L));
40384fb89dddSMatthew G. Knepley       PetscCall(DMSetPeriodicity(*M, maxCell, Lstart, L));
4039c8a6034eSMark       (*M)->prealloc_only = dm->prealloc_only;
40409566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->vectype));
40419566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->vectype, (char **)&(*M)->vectype));
40429566063dSJacob Faibussowitsch       PetscCall(PetscFree((*M)->mattype));
40439566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(dm->mattype, (char **)&(*M)->mattype));
404412fa691eSMatthew G. Knepley     }
40459566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(DM_Convert, dm, 0, 0, 0));
404667a56275SMatthew G Knepley   }
40479566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
40483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
404967a56275SMatthew G Knepley }
4050264ace61SBarry Smith 
4051264ace61SBarry Smith /*--------------------------------------------------------------------------------------------------------------------*/
4052264ace61SBarry Smith 
4053264ace61SBarry Smith /*@C
4054bb7acecfSBarry Smith   DMRegister -  Adds a new `DM` type implementation
40551c84c290SBarry Smith 
40561c84c290SBarry Smith   Not Collective
40571c84c290SBarry Smith 
40581c84c290SBarry Smith   Input Parameters:
405920f4b53cSBarry Smith + sname    - The name of a new user-defined creation routine
406020f4b53cSBarry Smith - function - The creation routine itself
406120f4b53cSBarry Smith 
406220f4b53cSBarry Smith   Level: advanced
40631c84c290SBarry Smith 
40641c84c290SBarry Smith   Notes:
406520f4b53cSBarry Smith   `DMRegister()` may be called multiple times to add several user-defined `DM`s
40661c84c290SBarry Smith 
406760225df5SJacob Faibussowitsch   Example Usage:
40681c84c290SBarry Smith .vb
4069bdf89e91SBarry Smith     DMRegister("my_da", MyDMCreate);
40701c84c290SBarry Smith .ve
40711c84c290SBarry Smith 
407220f4b53cSBarry Smith   Then, your `DM` type can be chosen with the procedural interface via
40731c84c290SBarry Smith .vb
40741c84c290SBarry Smith     DMCreate(MPI_Comm, DM *);
40751c84c290SBarry Smith     DMSetType(DM,"my_da");
40761c84c290SBarry Smith .ve
40771c84c290SBarry Smith   or at runtime via the option
40781c84c290SBarry Smith .vb
40791c84c290SBarry Smith     -da_type my_da
40801c84c290SBarry Smith .ve
4081264ace61SBarry Smith 
40821cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMType`, `DMSetType()`, `DMRegisterAll()`, `DMRegisterDestroy()`
4083264ace61SBarry Smith @*/
4084d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRegister(const char sname[], PetscErrorCode (*function)(DM))
4085d71ae5a4SJacob Faibussowitsch {
4086264ace61SBarry Smith   PetscFunctionBegin;
40879566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
40889566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&DMList, sname, function));
40893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4090264ace61SBarry Smith }
4091264ace61SBarry Smith 
4092b859378eSBarry Smith /*@C
4093bb7acecfSBarry Smith   DMLoad - Loads a DM that has been stored in binary  with `DMView()`.
4094b859378eSBarry Smith 
409520f4b53cSBarry Smith   Collective
4096b859378eSBarry Smith 
4097b859378eSBarry Smith   Input Parameters:
4098bb7acecfSBarry Smith + newdm  - the newly loaded `DM`, this needs to have been created with `DMCreate()` or
4099bb7acecfSBarry Smith            some related function before a call to `DMLoad()`.
4100bb7acecfSBarry Smith - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` or
4101bb7acecfSBarry Smith            `PETSCVIEWERHDF5` file viewer, obtained from `PetscViewerHDF5Open()`
4102b859378eSBarry Smith 
4103b859378eSBarry Smith   Level: intermediate
4104b859378eSBarry Smith 
4105b859378eSBarry Smith   Notes:
410655849f57SBarry Smith   The type is determined by the data in the file, any type set into the DM before this call is ignored.
4107b859378eSBarry Smith 
4108bb7acecfSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
4109bb7acecfSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
4110bb7acecfSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
4111cd7e8a5eSksagiyam 
41121cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscViewerBinaryOpen()`, `DMView()`, `MatLoad()`, `VecLoad()`
4113b859378eSBarry Smith @*/
4114d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad(DM newdm, PetscViewer viewer)
4115d71ae5a4SJacob Faibussowitsch {
41169331c7a4SMatthew G. Knepley   PetscBool isbinary, ishdf5;
4117b859378eSBarry Smith 
4118b859378eSBarry Smith   PetscFunctionBegin;
4119b859378eSBarry Smith   PetscValidHeaderSpecific(newdm, DM_CLASSID, 1);
4120b859378eSBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
41219566063dSJacob Faibussowitsch   PetscCall(PetscViewerCheckReadable(viewer));
41229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
41239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
41249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DM_Load, viewer, 0, 0, 0));
41259331c7a4SMatthew G. Knepley   if (isbinary) {
41269331c7a4SMatthew G. Knepley     PetscInt classid;
41279331c7a4SMatthew G. Knepley     char     type[256];
4128b859378eSBarry Smith 
41299566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, &classid, 1, NULL, PETSC_INT));
41307a8be351SBarry Smith     PetscCheck(classid == DM_FILE_CLASSID, PetscObjectComm((PetscObject)newdm), PETSC_ERR_ARG_WRONG, "Not DM next in file, classid found %d", (int)classid);
41319566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
41329566063dSJacob Faibussowitsch     PetscCall(DMSetType(newdm, type));
4133dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41349331c7a4SMatthew G. Knepley   } else if (ishdf5) {
4135dbbe0bcdSBarry Smith     PetscTryTypeMethod(newdm, load, viewer);
41369331c7a4SMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()");
41379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DM_Load, viewer, 0, 0, 0));
41383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4139b859378eSBarry Smith }
4140b859378eSBarry Smith 
41417da65231SMatthew G Knepley /******************************** FEM Support **********************************/
41427da65231SMatthew G Knepley 
41432ecf6ec3SMatthew G. Knepley PetscErrorCode DMPrintCellIndices(PetscInt c, const char name[], PetscInt len, const PetscInt x[])
41442ecf6ec3SMatthew G. Knepley {
41452ecf6ec3SMatthew G. Knepley   PetscInt f;
41462ecf6ec3SMatthew G. Knepley 
41472ecf6ec3SMatthew G. Knepley   PetscFunctionBegin;
41482ecf6ec3SMatthew G. Knepley   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
41492ecf6ec3SMatthew G. Knepley   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %" PetscInt_FMT " |\n", x[f]));
41502ecf6ec3SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
41512ecf6ec3SMatthew G. Knepley }
41522ecf6ec3SMatthew G. Knepley 
4153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[])
4154d71ae5a4SJacob Faibussowitsch {
41551d47ebbbSSatish Balay   PetscInt f;
41561b30c384SMatthew G Knepley 
41577da65231SMatthew G Knepley   PetscFunctionBegin;
415863a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
415948a46eb9SPierre Jolivet   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)PetscRealPart(x[f])));
41603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41617da65231SMatthew G Knepley }
41627da65231SMatthew G Knepley 
41635962854dSMatthew G. Knepley PetscErrorCode DMPrintCellVectorReal(PetscInt c, const char name[], PetscInt len, const PetscReal x[])
41645962854dSMatthew G. Knepley {
41655962854dSMatthew G. Knepley   PetscInt f;
41665962854dSMatthew G. Knepley 
41675962854dSMatthew G. Knepley   PetscFunctionBegin;
41685962854dSMatthew G. Knepley   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
41695962854dSMatthew G. Knepley   for (f = 0; f < len; ++f) PetscCall(PetscPrintf(PETSC_COMM_SELF, "  | %g |\n", (double)x[f]));
41705962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
41715962854dSMatthew G. Knepley }
41725962854dSMatthew G. Knepley 
4173d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[])
4174d71ae5a4SJacob Faibussowitsch {
41751b30c384SMatthew G Knepley   PetscInt f, g;
41767da65231SMatthew G Knepley 
41777da65231SMatthew G Knepley   PetscFunctionBegin;
417863a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_SELF, "Cell %" PetscInt_FMT " Element %s\n", c, name));
41791d47ebbbSSatish Balay   for (f = 0; f < rows; ++f) {
41809566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  |"));
418148a46eb9SPierre Jolivet     for (g = 0; g < cols; ++g) PetscCall(PetscPrintf(PETSC_COMM_SELF, " % 9.5g", (double)PetscRealPart(A[f * cols + g])));
41829566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, " |\n"));
41837da65231SMatthew G Knepley   }
41843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41857da65231SMatthew G Knepley }
4186e7c4fc90SDmitry Karpeev 
4187d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X)
4188d71ae5a4SJacob Faibussowitsch {
41890c5b8624SToby Isaac   PetscInt           localSize, bs;
41900c5b8624SToby Isaac   PetscMPIInt        size;
41910c5b8624SToby Isaac   Vec                x, xglob;
41920c5b8624SToby Isaac   const PetscScalar *xarray;
4193e759306cSMatthew G. Knepley 
4194e759306cSMatthew G. Knepley   PetscFunctionBegin;
41959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
41969566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(X, &x));
41979566063dSJacob Faibussowitsch   PetscCall(VecCopy(X, x));
419893ec0da9SPierre Jolivet   PetscCall(VecFilter(x, tol));
41999566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "%s:\n", name));
42000c5b8624SToby Isaac   if (size > 1) {
42019566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(x, &localSize));
42029566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xarray));
42039566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(x, &bs));
42049566063dSJacob Faibussowitsch     PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)dm), bs, localSize, PETSC_DETERMINE, xarray, &xglob));
42050c5b8624SToby Isaac   } else {
42060c5b8624SToby Isaac     xglob = x;
42070c5b8624SToby Isaac   }
42089566063dSJacob Faibussowitsch   PetscCall(VecView(xglob, PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)dm))));
42090c5b8624SToby Isaac   if (size > 1) {
42109566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xglob));
42119566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xarray));
42120c5b8624SToby Isaac   }
42139566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
42143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4215e759306cSMatthew G. Knepley }
4216e759306cSMatthew G. Knepley 
421788ed4aceSMatthew G Knepley /*@
4218bb7acecfSBarry Smith   DMGetSection - Get the `PetscSection` encoding the local data layout for the `DM`.   This is equivalent to `DMGetLocalSection()`. Deprecated in v3.12
4219061576a5SJed Brown 
4220061576a5SJed Brown   Input Parameter:
4221bb7acecfSBarry Smith . dm - The `DM`
4222061576a5SJed Brown 
4223061576a5SJed Brown   Output Parameter:
4224bb7acecfSBarry Smith . section - The `PetscSection`
4225061576a5SJed Brown 
422620f4b53cSBarry Smith   Options Database Key:
4227bb7acecfSBarry Smith . -dm_petscsection_view - View the `PetscSection` created by the `DM`
4228061576a5SJed Brown 
4229061576a5SJed Brown   Level: advanced
4230061576a5SJed Brown 
4231061576a5SJed Brown   Notes:
4232bb7acecfSBarry Smith   Use `DMGetLocalSection()` in new code.
4233061576a5SJed Brown 
4234bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
4235061576a5SJed Brown 
42361cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetLocalSection()`, `DMSetLocalSection()`, `DMGetGlobalSection()`
4237061576a5SJed Brown @*/
4238d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSection(DM dm, PetscSection *section)
4239d71ae5a4SJacob Faibussowitsch {
4240061576a5SJed Brown   PetscFunctionBegin;
42419566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, section));
42423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4243061576a5SJed Brown }
4244061576a5SJed Brown 
4245061576a5SJed Brown /*@
4246bb7acecfSBarry Smith   DMGetLocalSection - Get the `PetscSection` encoding the local data layout for the `DM`.
424788ed4aceSMatthew G Knepley 
424888ed4aceSMatthew G Knepley   Input Parameter:
4249bb7acecfSBarry Smith . dm - The `DM`
425088ed4aceSMatthew G Knepley 
425188ed4aceSMatthew G Knepley   Output Parameter:
4252bb7acecfSBarry Smith . section - The `PetscSection`
425388ed4aceSMatthew G Knepley 
425420f4b53cSBarry Smith   Options Database Key:
4255bb7acecfSBarry Smith . -dm_petscsection_view - View the section created by the `DM`
4256e5893cccSMatthew G. Knepley 
425788ed4aceSMatthew G Knepley   Level: intermediate
425888ed4aceSMatthew G Knepley 
4259bb7acecfSBarry Smith   Note:
4260bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
426188ed4aceSMatthew G Knepley 
42621cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetGlobalSection()`
426388ed4aceSMatthew G Knepley @*/
4264d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section)
4265d71ae5a4SJacob Faibussowitsch {
426688ed4aceSMatthew G Knepley   PetscFunctionBegin;
426788ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
42684f572ea9SToby Isaac   PetscAssertPointer(section, 2);
42691bb6d2a8SBarry Smith   if (!dm->localSection && dm->ops->createlocalsection) {
4270e5e52638SMatthew G. Knepley     PetscInt d;
4271e5e52638SMatthew G. Knepley 
427245480ffeSMatthew G. Knepley     if (dm->setfromoptionscalled) {
427345480ffeSMatthew G. Knepley       PetscObject       obj = (PetscObject)dm;
427445480ffeSMatthew G. Knepley       PetscViewer       viewer;
427545480ffeSMatthew G. Knepley       PetscViewerFormat format;
427645480ffeSMatthew G. Knepley       PetscBool         flg;
427745480ffeSMatthew G. Knepley 
42789566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetViewer(PetscObjectComm(obj), obj->options, obj->prefix, "-dm_petscds_view", &viewer, &format, &flg));
42799566063dSJacob Faibussowitsch       if (flg) PetscCall(PetscViewerPushFormat(viewer, format));
428045480ffeSMatthew G. Knepley       for (d = 0; d < dm->Nds; ++d) {
42819566063dSJacob Faibussowitsch         PetscCall(PetscDSSetFromOptions(dm->probs[d].ds));
42829566063dSJacob Faibussowitsch         if (flg) PetscCall(PetscDSView(dm->probs[d].ds, viewer));
428345480ffeSMatthew G. Knepley       }
428445480ffeSMatthew G. Knepley       if (flg) {
42859566063dSJacob Faibussowitsch         PetscCall(PetscViewerFlush(viewer));
42869566063dSJacob Faibussowitsch         PetscCall(PetscViewerPopFormat(viewer));
4287cd791dc2SBarry Smith         PetscCall(PetscOptionsRestoreViewer(&viewer));
428845480ffeSMatthew G. Knepley       }
428945480ffeSMatthew G. Knepley     }
4290dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createlocalsection);
42919566063dSJacob Faibussowitsch     if (dm->localSection) PetscCall(PetscObjectViewFromOptions((PetscObject)dm->localSection, NULL, "-dm_petscsection_view"));
42922f0f8703SMatthew G. Knepley   }
42931bb6d2a8SBarry Smith   *section = dm->localSection;
42943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
429588ed4aceSMatthew G Knepley }
429688ed4aceSMatthew G Knepley 
429788ed4aceSMatthew G Knepley /*@
4298bb7acecfSBarry Smith   DMSetSection - Set the `PetscSection` encoding the local data layout for the `DM`.  This is equivalent to `DMSetLocalSection()`. Deprecated in v3.12
4299061576a5SJed Brown 
4300061576a5SJed Brown   Input Parameters:
4301bb7acecfSBarry Smith + dm      - The `DM`
4302bb7acecfSBarry Smith - section - The `PetscSection`
4303061576a5SJed Brown 
4304061576a5SJed Brown   Level: advanced
4305061576a5SJed Brown 
4306061576a5SJed Brown   Notes:
4307bb7acecfSBarry Smith   Use `DMSetLocalSection()` in new code.
4308061576a5SJed Brown 
4309bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4310061576a5SJed Brown 
43111cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetLocalSection()`, `DMSetGlobalSection()`
4312061576a5SJed Brown @*/
4313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSection(DM dm, PetscSection section)
4314d71ae5a4SJacob Faibussowitsch {
4315061576a5SJed Brown   PetscFunctionBegin;
43169566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(dm, section));
43173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4318061576a5SJed Brown }
4319061576a5SJed Brown 
4320061576a5SJed Brown /*@
4321bb7acecfSBarry Smith   DMSetLocalSection - Set the `PetscSection` encoding the local data layout for the `DM`.
432288ed4aceSMatthew G Knepley 
432388ed4aceSMatthew G Knepley   Input Parameters:
4324bb7acecfSBarry Smith + dm      - The `DM`
4325bb7acecfSBarry Smith - section - The `PetscSection`
432688ed4aceSMatthew G Knepley 
432788ed4aceSMatthew G Knepley   Level: intermediate
432888ed4aceSMatthew G Knepley 
4329bb7acecfSBarry Smith   Note:
4330bb7acecfSBarry Smith   Any existing Section will be destroyed
433188ed4aceSMatthew G Knepley 
43321cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscSection`, `DMGetLocalSection()`, `DMSetGlobalSection()`
433388ed4aceSMatthew G Knepley @*/
4334d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLocalSection(DM dm, PetscSection section)
4335d71ae5a4SJacob Faibussowitsch {
4336c473ab19SMatthew G. Knepley   PetscInt numFields = 0;
4337af122d2aSMatthew G Knepley   PetscInt f;
433888ed4aceSMatthew G Knepley 
433988ed4aceSMatthew G Knepley   PetscFunctionBegin;
434088ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4341b9d85ea2SLisandro Dalcin   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
43429566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
43439566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->localSection));
43441bb6d2a8SBarry Smith   dm->localSection = section;
43459566063dSJacob Faibussowitsch   if (section) PetscCall(PetscSectionGetNumFields(dm->localSection, &numFields));
4346af122d2aSMatthew G Knepley   if (numFields) {
43479566063dSJacob Faibussowitsch     PetscCall(DMSetNumFields(dm, numFields));
4348af122d2aSMatthew G Knepley     for (f = 0; f < numFields; ++f) {
43490f21e855SMatthew G. Knepley       PetscObject disc;
4350af122d2aSMatthew G Knepley       const char *name;
4351af122d2aSMatthew G Knepley 
43529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(dm->localSection, f, &name));
43539566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, &disc));
43549566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName(disc, name));
4355af122d2aSMatthew G Knepley     }
4356af122d2aSMatthew G Knepley   }
4357e87a4003SBarry Smith   /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */
43589566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
43593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
436088ed4aceSMatthew G Knepley }
436188ed4aceSMatthew G Knepley 
43629435951eSToby Isaac /*@
4363bb7acecfSBarry Smith   DMGetDefaultConstraints - Get the `PetscSection` and `Mat` that specify the local constraint interpolation. See `DMSetDefaultConstraints()` for a description of the purpose of constraint interpolation.
43649435951eSToby Isaac 
436520f4b53cSBarry Smith   not Collective
4366e228b242SToby Isaac 
43679435951eSToby Isaac   Input Parameter:
4368bb7acecfSBarry Smith . dm - The `DM`
43699435951eSToby Isaac 
4370d8d19677SJose E. Roman   Output Parameters:
437120f4b53cSBarry 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.
437220f4b53cSBarry 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.
437379769bd5SJed Brown - bias    - Vector containing bias to be added to constrained dofs
43749435951eSToby Isaac 
43759435951eSToby Isaac   Level: advanced
43769435951eSToby Isaac 
4377bb7acecfSBarry Smith   Note:
4378bb7acecfSBarry Smith   This gets borrowed references, so the user should not destroy the `PetscSection`, `Mat`, or `Vec`.
43799435951eSToby Isaac 
43801cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetDefaultConstraints()`
43819435951eSToby Isaac @*/
4382d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat, Vec *bias)
4383d71ae5a4SJacob Faibussowitsch {
43849435951eSToby Isaac   PetscFunctionBegin;
43859435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4386dbbe0bcdSBarry Smith   if (!dm->defaultConstraint.section && !dm->defaultConstraint.mat && dm->ops->createdefaultconstraints) PetscUseTypeMethod(dm, createdefaultconstraints);
43873b8ba7d1SJed Brown   if (section) *section = dm->defaultConstraint.section;
43883b8ba7d1SJed Brown   if (mat) *mat = dm->defaultConstraint.mat;
438979769bd5SJed Brown   if (bias) *bias = dm->defaultConstraint.bias;
43903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43919435951eSToby Isaac }
43929435951eSToby Isaac 
43939435951eSToby Isaac /*@
4394bb7acecfSBarry Smith   DMSetDefaultConstraints - Set the `PetscSection` and `Mat` that specify the local constraint interpolation.
43959435951eSToby Isaac 
439620f4b53cSBarry Smith   Collective
4397e228b242SToby Isaac 
43989435951eSToby Isaac   Input Parameters:
4399bb7acecfSBarry Smith + dm      - The `DM`
4400bb7acecfSBarry 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).
440120f4b53cSBarry 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).
440220f4b53cSBarry 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).
44039435951eSToby Isaac 
44049435951eSToby Isaac   Level: advanced
44059435951eSToby Isaac 
440620f4b53cSBarry Smith   Notes:
440720f4b53cSBarry 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()`.
440820f4b53cSBarry Smith 
440920f4b53cSBarry 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.
441020f4b53cSBarry Smith 
4411bb7acecfSBarry Smith   This increments the references of the `PetscSection`, `Mat`, and `Vec`, so they user can destroy them.
44129435951eSToby Isaac 
44131cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDefaultConstraints()`
44149435951eSToby Isaac @*/
4415d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat, Vec bias)
4416d71ae5a4SJacob Faibussowitsch {
4417e228b242SToby Isaac   PetscMPIInt result;
44189435951eSToby Isaac 
44199435951eSToby Isaac   PetscFunctionBegin;
44209435951eSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4421e228b242SToby Isaac   if (section) {
4422e228b242SToby Isaac     PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
44239566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)section), &result));
44247a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint section must have local communicator");
4425e228b242SToby Isaac   }
4426e228b242SToby Isaac   if (mat) {
4427e228b242SToby Isaac     PetscValidHeaderSpecific(mat, MAT_CLASSID, 3);
44289566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)mat), &result));
44297a8be351SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint matrix must have local communicator");
4430e228b242SToby Isaac   }
443179769bd5SJed Brown   if (bias) {
443279769bd5SJed Brown     PetscValidHeaderSpecific(bias, VEC_CLASSID, 4);
44339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)bias), &result));
443479769bd5SJed Brown     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "constraint bias must have local communicator");
443579769bd5SJed Brown   }
44369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
44379566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->defaultConstraint.section));
44383b8ba7d1SJed Brown   dm->defaultConstraint.section = section;
44399566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)mat));
44409566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&dm->defaultConstraint.mat));
44413b8ba7d1SJed Brown   dm->defaultConstraint.mat = mat;
44429566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)bias));
44439566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&dm->defaultConstraint.bias));
444479769bd5SJed Brown   dm->defaultConstraint.bias = bias;
44453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44469435951eSToby Isaac }
44479435951eSToby Isaac 
4448497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
4449507e4973SMatthew G. Knepley /*
4450bb7acecfSBarry Smith   DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. Generates and error if they are not consistent.
4451507e4973SMatthew G. Knepley 
4452507e4973SMatthew G. Knepley   Input Parameters:
4453bb7acecfSBarry Smith + dm - The `DM`
4454bb7acecfSBarry Smith . localSection - `PetscSection` describing the local data layout
4455bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
4456507e4973SMatthew G. Knepley 
4457507e4973SMatthew G. Knepley   Level: intermediate
4458507e4973SMatthew G. Knepley 
44591cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMSetSectionSF()`
4460507e4973SMatthew G. Knepley */
4461d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection)
4462d71ae5a4SJacob Faibussowitsch {
4463507e4973SMatthew G. Knepley   MPI_Comm        comm;
4464507e4973SMatthew G. Knepley   PetscLayout     layout;
4465507e4973SMatthew G. Knepley   const PetscInt *ranges;
4466507e4973SMatthew G. Knepley   PetscInt        pStart, pEnd, p, nroots;
4467507e4973SMatthew G. Knepley   PetscMPIInt     size, rank;
4468507e4973SMatthew G. Knepley   PetscBool       valid = PETSC_TRUE, gvalid;
4469507e4973SMatthew G. Knepley 
4470507e4973SMatthew G. Knepley   PetscFunctionBegin;
44719566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4472507e4973SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44739566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
44749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
44759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(globalSection, &pStart, &pEnd));
44769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(globalSection, &nroots));
44779566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &layout));
44789566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
44799566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, nroots));
44809566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(layout));
44819566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRanges(layout, &ranges));
4482507e4973SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4483f741bcd2SMatthew G. Knepley     PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d;
4484507e4973SMatthew G. Knepley 
44859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(localSection, p, &dof));
44869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(localSection, p, &off));
44879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(localSection, p, &cdof));
44889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(globalSection, p, &gdof));
44899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintDof(globalSection, p, &gcdof));
44909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &goff));
4491507e4973SMatthew G. Knepley     if (!gdof) continue; /* Censored point */
44929371c9d4SSatish Balay     if ((gdof < 0 ? -(gdof + 1) : gdof) != dof) {
44939371c9d4SSatish 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));
44949371c9d4SSatish Balay       valid = PETSC_FALSE;
44959371c9d4SSatish Balay     }
44969371c9d4SSatish Balay     if (gcdof && (gcdof != cdof)) {
44979371c9d4SSatish 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));
44989371c9d4SSatish Balay       valid = PETSC_FALSE;
44999371c9d4SSatish Balay     }
4500507e4973SMatthew G. Knepley     if (gdof < 0) {
4501507e4973SMatthew G. Knepley       gsize = gdof < 0 ? -(gdof + 1) - gcdof : gdof - gcdof;
4502507e4973SMatthew G. Knepley       for (d = 0; d < gsize; ++d) {
4503507e4973SMatthew G. Knepley         PetscInt offset = -(goff + 1) + d, r;
4504507e4973SMatthew G. Knepley 
45059566063dSJacob Faibussowitsch         PetscCall(PetscFindInt(offset, size + 1, ranges, &r));
4506507e4973SMatthew G. Knepley         if (r < 0) r = -(r + 2);
45079371c9d4SSatish Balay         if ((r < 0) || (r >= size)) {
45089371c9d4SSatish Balay           PetscCall(PetscSynchronizedPrintf(comm, "[%d]Point %" PetscInt_FMT " mapped to invalid process %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", rank, p, r, gdof, goff));
45099371c9d4SSatish Balay           valid = PETSC_FALSE;
45109371c9d4SSatish Balay           break;
45119371c9d4SSatish Balay         }
4512507e4973SMatthew G. Knepley       }
4513507e4973SMatthew G. Knepley     }
4514507e4973SMatthew G. Knepley   }
45159566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
45169566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
45171c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm));
4518507e4973SMatthew G. Knepley   if (!gvalid) {
45199566063dSJacob Faibussowitsch     PetscCall(DMView(dm, NULL));
4520507e4973SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections");
4521507e4973SMatthew G. Knepley   }
45223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4523507e4973SMatthew G. Knepley }
4524f741bcd2SMatthew G. Knepley #endif
4525507e4973SMatthew G. Knepley 
45265f06a3ddSJed Brown static PetscErrorCode DMGetIsoperiodicPointSF_Internal(DM dm, PetscSF *sf)
45276725e60dSJed Brown {
45286725e60dSJed Brown   PetscErrorCode (*f)(DM, PetscSF *);
45296725e60dSJed Brown   PetscFunctionBegin;
45306725e60dSJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45314f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
45325f06a3ddSJed Brown   PetscCall(PetscObjectQueryFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", &f));
45336725e60dSJed Brown   if (f) PetscCall(f(dm, sf));
45346725e60dSJed Brown   else *sf = dm->sf;
45353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45366725e60dSJed Brown }
45376725e60dSJed Brown 
453888ed4aceSMatthew G Knepley /*@
4539bb7acecfSBarry Smith   DMGetGlobalSection - Get the `PetscSection` encoding the global data layout for the `DM`.
454088ed4aceSMatthew G Knepley 
454120f4b53cSBarry Smith   Collective
45428b1ab98fSJed Brown 
454388ed4aceSMatthew G Knepley   Input Parameter:
4544bb7acecfSBarry Smith . dm - The `DM`
454588ed4aceSMatthew G Knepley 
454688ed4aceSMatthew G Knepley   Output Parameter:
4547bb7acecfSBarry Smith . section - The `PetscSection`
454888ed4aceSMatthew G Knepley 
454988ed4aceSMatthew G Knepley   Level: intermediate
455088ed4aceSMatthew G Knepley 
4551bb7acecfSBarry Smith   Note:
4552bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSection`.
455388ed4aceSMatthew G Knepley 
45541cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLocalSection()`, `DMGetLocalSection()`
455588ed4aceSMatthew G Knepley @*/
4556d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section)
4557d71ae5a4SJacob Faibussowitsch {
455888ed4aceSMatthew G Knepley   PetscFunctionBegin;
455988ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45604f572ea9SToby Isaac   PetscAssertPointer(section, 2);
45611bb6d2a8SBarry Smith   if (!dm->globalSection) {
4562fd59a867SMatthew G. Knepley     PetscSection s;
45636725e60dSJed Brown     PetscSF      sf;
4564fd59a867SMatthew G. Knepley 
45659566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &s));
45667a8be351SBarry Smith     PetscCheck(s, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection");
45677a8be351SBarry Smith     PetscCheck(dm->sf, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection");
45685f06a3ddSJed Brown     PetscCall(DMGetIsoperiodicPointSF_Internal(dm, &sf));
45696725e60dSJed Brown     PetscCall(PetscSectionCreateGlobalSection(s, sf, PETSC_FALSE, PETSC_FALSE, &dm->globalSection));
45709566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&dm->map));
45719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map));
45729566063dSJacob Faibussowitsch     PetscCall(PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view"));
457388ed4aceSMatthew G Knepley   }
45741bb6d2a8SBarry Smith   *section = dm->globalSection;
45753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
457688ed4aceSMatthew G Knepley }
457788ed4aceSMatthew G Knepley 
4578b21d0597SMatthew G Knepley /*@
4579bb7acecfSBarry Smith   DMSetGlobalSection - Set the `PetscSection` encoding the global data layout for the `DM`.
4580b21d0597SMatthew G Knepley 
4581b21d0597SMatthew G Knepley   Input Parameters:
4582bb7acecfSBarry Smith + dm      - The `DM`
45832fe279fdSBarry Smith - section - The PetscSection, or `NULL`
4584b21d0597SMatthew G Knepley 
4585b21d0597SMatthew G Knepley   Level: intermediate
4586b21d0597SMatthew G Knepley 
4587bb7acecfSBarry Smith   Note:
4588bb7acecfSBarry Smith   Any existing `PetscSection` will be destroyed
4589b21d0597SMatthew G Knepley 
45901cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetGlobalSection()`, `DMSetLocalSection()`
4591b21d0597SMatthew G Knepley @*/
4592d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section)
4593d71ae5a4SJacob Faibussowitsch {
4594b21d0597SMatthew G Knepley   PetscFunctionBegin;
4595b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45965080bbdbSMatthew G Knepley   if (section) PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
45979566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)section));
45989566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&dm->globalSection));
45991bb6d2a8SBarry Smith   dm->globalSection = section;
4600497880caSRichard Tran Mills #if defined(PETSC_USE_DEBUG)
46019566063dSJacob Faibussowitsch   if (section) PetscCall(DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section));
4602507e4973SMatthew G. Knepley #endif
46033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4604b21d0597SMatthew G Knepley }
4605b21d0597SMatthew G Knepley 
460688ed4aceSMatthew G Knepley /*@
4607bb7acecfSBarry Smith   DMGetSectionSF - Get the `PetscSF` encoding the parallel dof overlap for the `DM`. If it has not been set,
4608bb7acecfSBarry Smith   it is created from the default `PetscSection` layouts in the `DM`.
460988ed4aceSMatthew G Knepley 
461088ed4aceSMatthew G Knepley   Input Parameter:
4611bb7acecfSBarry Smith . dm - The `DM`
461288ed4aceSMatthew G Knepley 
461388ed4aceSMatthew G Knepley   Output Parameter:
4614bb7acecfSBarry Smith . sf - The `PetscSF`
461588ed4aceSMatthew G Knepley 
461688ed4aceSMatthew G Knepley   Level: intermediate
461788ed4aceSMatthew G Knepley 
4618bb7acecfSBarry Smith   Note:
4619bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
462088ed4aceSMatthew G Knepley 
46211cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetSectionSF()`, `DMCreateSectionSF()`
462288ed4aceSMatthew G Knepley @*/
4623d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf)
4624d71ae5a4SJacob Faibussowitsch {
462588ed4aceSMatthew G Knepley   PetscInt nroots;
462688ed4aceSMatthew G Knepley 
462788ed4aceSMatthew G Knepley   PetscFunctionBegin;
462888ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46294f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
463048a46eb9SPierre Jolivet   if (!dm->sectionSF) PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &dm->sectionSF));
46319566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL));
463288ed4aceSMatthew G Knepley   if (nroots < 0) {
463388ed4aceSMatthew G Knepley     PetscSection section, gSection;
463488ed4aceSMatthew G Knepley 
46359566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
463631ea6d37SMatthew G Knepley     if (section) {
46379566063dSJacob Faibussowitsch       PetscCall(DMGetGlobalSection(dm, &gSection));
46389566063dSJacob Faibussowitsch       PetscCall(DMCreateSectionSF(dm, section, gSection));
463931ea6d37SMatthew G Knepley     } else {
46400298fd71SBarry Smith       *sf = NULL;
46413ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
464231ea6d37SMatthew G Knepley     }
464388ed4aceSMatthew G Knepley   }
46441bb6d2a8SBarry Smith   *sf = dm->sectionSF;
46453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
464688ed4aceSMatthew G Knepley }
464788ed4aceSMatthew G Knepley 
464888ed4aceSMatthew G Knepley /*@
4649bb7acecfSBarry Smith   DMSetSectionSF - Set the `PetscSF` encoding the parallel dof overlap for the `DM`
465088ed4aceSMatthew G Knepley 
465188ed4aceSMatthew G Knepley   Input Parameters:
4652bb7acecfSBarry Smith + dm - The `DM`
4653bb7acecfSBarry Smith - sf - The `PetscSF`
465488ed4aceSMatthew G Knepley 
465588ed4aceSMatthew G Knepley   Level: intermediate
465688ed4aceSMatthew G Knepley 
4657bb7acecfSBarry Smith   Note:
4658bb7acecfSBarry Smith   Any previous `PetscSF` is destroyed
465988ed4aceSMatthew G Knepley 
46601cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMCreateSectionSF()`
466188ed4aceSMatthew G Knepley @*/
4662d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf)
4663d71ae5a4SJacob Faibussowitsch {
466488ed4aceSMatthew G Knepley   PetscFunctionBegin;
466588ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4666b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
46679566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
46689566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sectionSF));
46691bb6d2a8SBarry Smith   dm->sectionSF = sf;
46703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
467188ed4aceSMatthew G Knepley }
467288ed4aceSMatthew G Knepley 
467388ed4aceSMatthew G Knepley /*@C
4674bb7acecfSBarry Smith   DMCreateSectionSF - Create the `PetscSF` encoding the parallel dof overlap for the `DM` based upon the `PetscSection`s
467588ed4aceSMatthew G Knepley   describing the data layout.
467688ed4aceSMatthew G Knepley 
467788ed4aceSMatthew G Knepley   Input Parameters:
4678bb7acecfSBarry Smith + dm            - The `DM`
4679bb7acecfSBarry Smith . localSection  - `PetscSection` describing the local data layout
4680bb7acecfSBarry Smith - globalSection - `PetscSection` describing the global data layout
468188ed4aceSMatthew G Knepley 
46821bb6d2a8SBarry Smith   Level: developer
46831bb6d2a8SBarry Smith 
4684bb7acecfSBarry Smith   Note:
4685bb7acecfSBarry Smith   One usually uses `DMGetSectionSF()` to obtain the `PetscSF`
4686bb7acecfSBarry Smith 
468760225df5SJacob Faibussowitsch   Developer Notes:
4688bb7acecfSBarry Smith   Since this routine has for arguments the two sections from the `DM` and puts the resulting `PetscSF`
4689bb7acecfSBarry Smith   directly into the `DM`, perhaps this function should not take the local and global sections as
4690bb7acecfSBarry Smith   input and should just obtain them from the `DM`?
46911bb6d2a8SBarry Smith 
46921cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
469388ed4aceSMatthew G Knepley @*/
4694d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection)
4695d71ae5a4SJacob Faibussowitsch {
469688ed4aceSMatthew G Knepley   PetscFunctionBegin;
469788ed4aceSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46989566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphSection(dm->sectionSF, localSection, globalSection));
46993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
470088ed4aceSMatthew G Knepley }
4701af122d2aSMatthew G Knepley 
4702b21d0597SMatthew G Knepley /*@
4703bb7acecfSBarry Smith   DMGetPointSF - Get the `PetscSF` encoding the parallel section point overlap for the `DM`.
4704bb7acecfSBarry Smith 
4705bb7acecfSBarry Smith   Not collective but the resulting `PetscSF` is collective
4706b21d0597SMatthew G Knepley 
4707b21d0597SMatthew G Knepley   Input Parameter:
4708bb7acecfSBarry Smith . dm - The `DM`
4709b21d0597SMatthew G Knepley 
4710b21d0597SMatthew G Knepley   Output Parameter:
4711bb7acecfSBarry Smith . sf - The `PetscSF`
4712b21d0597SMatthew G Knepley 
4713b21d0597SMatthew G Knepley   Level: intermediate
4714b21d0597SMatthew G Knepley 
4715bb7acecfSBarry Smith   Note:
4716bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
4717b21d0597SMatthew G Knepley 
47181cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4719b21d0597SMatthew G Knepley @*/
4720d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf)
4721d71ae5a4SJacob Faibussowitsch {
4722b21d0597SMatthew G Knepley   PetscFunctionBegin;
4723b21d0597SMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47244f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
4725b21d0597SMatthew G Knepley   *sf = dm->sf;
47263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4727b21d0597SMatthew G Knepley }
4728b21d0597SMatthew G Knepley 
4729057b4bcdSMatthew G Knepley /*@
4730bb7acecfSBarry Smith   DMSetPointSF - Set the `PetscSF` encoding the parallel section point overlap for the `DM`.
4731bb7acecfSBarry Smith 
473220f4b53cSBarry Smith   Collective
4733057b4bcdSMatthew G Knepley 
4734057b4bcdSMatthew G Knepley   Input Parameters:
4735bb7acecfSBarry Smith + dm - The `DM`
4736bb7acecfSBarry Smith - sf - The `PetscSF`
4737057b4bcdSMatthew G Knepley 
4738057b4bcdSMatthew G Knepley   Level: intermediate
4739057b4bcdSMatthew G Knepley 
47401cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetPointSF()`, `DMGetSectionSF()`, `DMSetSectionSF()`, `DMCreateSectionSF()`
4741057b4bcdSMatthew G Knepley @*/
4742d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetPointSF(DM dm, PetscSF sf)
4743d71ae5a4SJacob Faibussowitsch {
4744057b4bcdSMatthew G Knepley   PetscFunctionBegin;
4745057b4bcdSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4746b9d85ea2SLisandro Dalcin   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47479566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47489566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sf));
4749057b4bcdSMatthew G Knepley   dm->sf = sf;
47503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4751057b4bcdSMatthew G Knepley }
4752057b4bcdSMatthew G Knepley 
47534f37162bSMatthew G. Knepley /*@
4754bb7acecfSBarry Smith   DMGetNaturalSF - Get the `PetscSF` encoding the map back to the original mesh ordering
47554f37162bSMatthew G. Knepley 
47564f37162bSMatthew G. Knepley   Input Parameter:
4757bb7acecfSBarry Smith . dm - The `DM`
47584f37162bSMatthew G. Knepley 
47594f37162bSMatthew G. Knepley   Output Parameter:
4760bb7acecfSBarry Smith . sf - The `PetscSF`
47614f37162bSMatthew G. Knepley 
47624f37162bSMatthew G. Knepley   Level: intermediate
47634f37162bSMatthew G. Knepley 
4764bb7acecfSBarry Smith   Note:
4765bb7acecfSBarry Smith   This gets a borrowed reference, so the user should not destroy this `PetscSF`.
47664f37162bSMatthew G. Knepley 
47671cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
47684f37162bSMatthew G. Knepley @*/
4769d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNaturalSF(DM dm, PetscSF *sf)
4770d71ae5a4SJacob Faibussowitsch {
47714f37162bSMatthew G. Knepley   PetscFunctionBegin;
47724f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47734f572ea9SToby Isaac   PetscAssertPointer(sf, 2);
47744f37162bSMatthew G. Knepley   *sf = dm->sfNatural;
47753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47764f37162bSMatthew G. Knepley }
47774f37162bSMatthew G. Knepley 
47784f37162bSMatthew G. Knepley /*@
47794f37162bSMatthew G. Knepley   DMSetNaturalSF - Set the PetscSF encoding the map back to the original mesh ordering
47804f37162bSMatthew G. Knepley 
47814f37162bSMatthew G. Knepley   Input Parameters:
47824f37162bSMatthew G. Knepley + dm - The DM
47834f37162bSMatthew G. Knepley - sf - The PetscSF
47844f37162bSMatthew G. Knepley 
47854f37162bSMatthew G. Knepley   Level: intermediate
47864f37162bSMatthew G. Knepley 
47871cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNaturalSF()`, `DMSetUseNatural()`, `DMGetUseNatural()`, `DMPlexCreateGlobalToNaturalSF()`, `DMPlexDistribute()`
47884f37162bSMatthew G. Knepley @*/
4789d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNaturalSF(DM dm, PetscSF sf)
4790d71ae5a4SJacob Faibussowitsch {
47914f37162bSMatthew G. Knepley   PetscFunctionBegin;
47924f37162bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47934f37162bSMatthew G. Knepley   if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2);
47949566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sf));
47959566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&dm->sfNatural));
47964f37162bSMatthew G. Knepley   dm->sfNatural = sf;
47973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47984f37162bSMatthew G. Knepley }
47994f37162bSMatthew G. Knepley 
4800d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc)
4801d71ae5a4SJacob Faibussowitsch {
480234aa8a36SMatthew G. Knepley   PetscClassId id;
480334aa8a36SMatthew G. Knepley 
480434aa8a36SMatthew G. Knepley   PetscFunctionBegin;
48059566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId(disc, &id));
480634aa8a36SMatthew G. Knepley   if (id == PETSCFE_CLASSID) {
48079566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
480834aa8a36SMatthew G. Knepley   } else if (id == PETSCFV_CLASSID) {
48099566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE));
481017c1d62eSMatthew G. Knepley   } else {
48119566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE));
481234aa8a36SMatthew G. Knepley   }
48133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
481434aa8a36SMatthew G. Knepley }
481534aa8a36SMatthew G. Knepley 
4816d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew)
4817d71ae5a4SJacob Faibussowitsch {
481844a7f3ddSMatthew G. Knepley   RegionField *tmpr;
481944a7f3ddSMatthew G. Knepley   PetscInt     Nf = dm->Nf, f;
482044a7f3ddSMatthew G. Knepley 
482144a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
48223ba16761SJacob Faibussowitsch   if (Nf >= NfNew) PetscFunctionReturn(PETSC_SUCCESS);
48239566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NfNew, &tmpr));
482444a7f3ddSMatthew G. Knepley   for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f];
48259371c9d4SSatish Balay   for (f = Nf; f < NfNew; ++f) {
48269371c9d4SSatish Balay     tmpr[f].disc        = NULL;
48279371c9d4SSatish Balay     tmpr[f].label       = NULL;
48289371c9d4SSatish Balay     tmpr[f].avoidTensor = PETSC_FALSE;
48299371c9d4SSatish Balay   }
48309566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
483144a7f3ddSMatthew G. Knepley   dm->Nf     = NfNew;
483244a7f3ddSMatthew G. Knepley   dm->fields = tmpr;
48333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
483444a7f3ddSMatthew G. Knepley }
483544a7f3ddSMatthew G. Knepley 
483644a7f3ddSMatthew G. Knepley /*@
483720f4b53cSBarry Smith   DMClearFields - Remove all fields from the `DM`
483844a7f3ddSMatthew G. Knepley 
483920f4b53cSBarry Smith   Logically Collective
484044a7f3ddSMatthew G. Knepley 
484144a7f3ddSMatthew G. Knepley   Input Parameter:
484220f4b53cSBarry Smith . dm - The `DM`
484344a7f3ddSMatthew G. Knepley 
484444a7f3ddSMatthew G. Knepley   Level: intermediate
484544a7f3ddSMatthew G. Knepley 
48461cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumFields()`, `DMSetNumFields()`, `DMSetField()`
484744a7f3ddSMatthew G. Knepley @*/
4848d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearFields(DM dm)
4849d71ae5a4SJacob Faibussowitsch {
485044a7f3ddSMatthew G. Knepley   PetscInt f;
485144a7f3ddSMatthew G. Knepley 
485244a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
485344a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
485444a7f3ddSMatthew G. Knepley   for (f = 0; f < dm->Nf; ++f) {
48559566063dSJacob Faibussowitsch     PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
48569566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->fields[f].label));
485744a7f3ddSMatthew G. Knepley   }
48589566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->fields));
485944a7f3ddSMatthew G. Knepley   dm->fields = NULL;
486044a7f3ddSMatthew G. Knepley   dm->Nf     = 0;
48613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
486244a7f3ddSMatthew G. Knepley }
486344a7f3ddSMatthew G. Knepley 
4864689b5837SMatthew G. Knepley /*@
486520f4b53cSBarry Smith   DMGetNumFields - Get the number of fields in the `DM`
4866689b5837SMatthew G. Knepley 
486720f4b53cSBarry Smith   Not Collective
4868689b5837SMatthew G. Knepley 
4869689b5837SMatthew G. Knepley   Input Parameter:
487020f4b53cSBarry Smith . dm - The `DM`
4871689b5837SMatthew G. Knepley 
4872689b5837SMatthew G. Knepley   Output Parameter:
487360225df5SJacob Faibussowitsch . numFields - The number of fields
4874689b5837SMatthew G. Knepley 
4875689b5837SMatthew G. Knepley   Level: intermediate
4876689b5837SMatthew G. Knepley 
48771cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetNumFields()`, `DMSetField()`
4878689b5837SMatthew G. Knepley @*/
4879d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields)
4880d71ae5a4SJacob Faibussowitsch {
48810f21e855SMatthew G. Knepley   PetscFunctionBegin;
48820f21e855SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48834f572ea9SToby Isaac   PetscAssertPointer(numFields, 2);
488444a7f3ddSMatthew G. Knepley   *numFields = dm->Nf;
48853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4886af122d2aSMatthew G Knepley }
4887af122d2aSMatthew G Knepley 
4888689b5837SMatthew G. Knepley /*@
488920f4b53cSBarry Smith   DMSetNumFields - Set the number of fields in the `DM`
4890689b5837SMatthew G. Knepley 
489120f4b53cSBarry Smith   Logically Collective
4892689b5837SMatthew G. Knepley 
4893689b5837SMatthew G. Knepley   Input Parameters:
489420f4b53cSBarry Smith + dm        - The `DM`
489560225df5SJacob Faibussowitsch - numFields - The number of fields
4896689b5837SMatthew G. Knepley 
4897689b5837SMatthew G. Knepley   Level: intermediate
4898689b5837SMatthew G. Knepley 
48991cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumFields()`, `DMSetField()`
4900689b5837SMatthew G. Knepley @*/
4901d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields)
4902d71ae5a4SJacob Faibussowitsch {
49030f21e855SMatthew G. Knepley   PetscInt Nf, f;
4904af122d2aSMatthew G Knepley 
4905af122d2aSMatthew G Knepley   PetscFunctionBegin;
4906af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49079566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
49080f21e855SMatthew G. Knepley   for (f = Nf; f < numFields; ++f) {
49090f21e855SMatthew G. Knepley     PetscContainer obj;
49100f21e855SMatthew G. Knepley 
49119566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)dm), &obj));
49129566063dSJacob Faibussowitsch     PetscCall(DMAddField(dm, NULL, (PetscObject)obj));
49139566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&obj));
4914af122d2aSMatthew G Knepley   }
49153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4916af122d2aSMatthew G Knepley }
4917af122d2aSMatthew G Knepley 
4918c1929be8SMatthew G. Knepley /*@
4919bb7acecfSBarry Smith   DMGetField - Return the `DMLabel` and discretization object for a given `DM` field
4920c1929be8SMatthew G. Knepley 
492120f4b53cSBarry Smith   Not Collective
4922c1929be8SMatthew G. Knepley 
4923c1929be8SMatthew G. Knepley   Input Parameters:
4924bb7acecfSBarry Smith + dm - The `DM`
4925c1929be8SMatthew G. Knepley - f  - The field number
4926c1929be8SMatthew G. Knepley 
492744a7f3ddSMatthew G. Knepley   Output Parameters:
492820f4b53cSBarry Smith + label - The label indicating the support of the field, or `NULL` for the entire mesh (pass in `NULL` if not needed)
492920f4b53cSBarry Smith - disc  - The discretization object (pass in `NULL` if not needed)
4930c1929be8SMatthew G. Knepley 
493144a7f3ddSMatthew G. Knepley   Level: intermediate
4932c1929be8SMatthew G. Knepley 
49331cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMSetField()`
4934c1929be8SMatthew G. Knepley @*/
4935d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *disc)
4936d71ae5a4SJacob Faibussowitsch {
4937af122d2aSMatthew G Knepley   PetscFunctionBegin;
4938af122d2aSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49394f572ea9SToby Isaac   PetscAssertPointer(disc, 4);
49407a8be351SBarry 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);
494144a7f3ddSMatthew G. Knepley   if (label) *label = dm->fields[f].label;
4942bb7acecfSBarry Smith   if (disc) *disc = dm->fields[f].disc;
49433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4944decb47aaSMatthew G. Knepley }
4945decb47aaSMatthew G. Knepley 
4946083401c6SMatthew G. Knepley /* Does not clear the DS */
4947d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField_Internal(DM dm, PetscInt f, DMLabel label, PetscObject disc)
4948d71ae5a4SJacob Faibussowitsch {
4949083401c6SMatthew G. Knepley   PetscFunctionBegin;
49509566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, f + 1));
49519566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->fields[f].label));
49529566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&dm->fields[f].disc));
4953083401c6SMatthew G. Knepley   dm->fields[f].label = label;
4954bb7acecfSBarry Smith   dm->fields[f].disc  = disc;
49559566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
4956bb7acecfSBarry Smith   PetscCall(PetscObjectReference((PetscObject)disc));
49573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4958083401c6SMatthew G. Knepley }
4959083401c6SMatthew G. Knepley 
496046560f82SMatthew G. Knepley /*@C
4961bb7acecfSBarry Smith   DMSetField - Set the discretization object for a given `DM` field. Usually one would call `DMAddField()` which automatically handles
4962bb7acecfSBarry Smith   the field numbering.
4963c1929be8SMatthew G. Knepley 
496420f4b53cSBarry Smith   Logically Collective
4965c1929be8SMatthew G. Knepley 
4966c1929be8SMatthew G. Knepley   Input Parameters:
4967bb7acecfSBarry Smith + dm    - The `DM`
4968c1929be8SMatthew G. Knepley . f     - The field number
496920f4b53cSBarry Smith . label - The label indicating the support of the field, or `NULL` for the entire mesh
4970bb7acecfSBarry Smith - disc  - The discretization object
4971c1929be8SMatthew G. Knepley 
497244a7f3ddSMatthew G. Knepley   Level: intermediate
4973c1929be8SMatthew G. Knepley 
49741cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMGetField()`
4975c1929be8SMatthew G. Knepley @*/
4976d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject disc)
4977d71ae5a4SJacob Faibussowitsch {
4978decb47aaSMatthew G. Knepley   PetscFunctionBegin;
4979decb47aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4980e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
4981bb7acecfSBarry Smith   PetscValidHeader(disc, 4);
49827a8be351SBarry Smith   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
4983bb7acecfSBarry Smith   PetscCall(DMSetField_Internal(dm, f, label, disc));
4984bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, f, disc));
49859566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
49863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
498744a7f3ddSMatthew G. Knepley }
498844a7f3ddSMatthew G. Knepley 
498946560f82SMatthew G. Knepley /*@C
4990bb7acecfSBarry 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)
4991bb7acecfSBarry Smith   and a discretization object that defines the function space associated with those points.
499244a7f3ddSMatthew G. Knepley 
499320f4b53cSBarry Smith   Logically Collective
499444a7f3ddSMatthew G. Knepley 
499544a7f3ddSMatthew G. Knepley   Input Parameters:
4996bb7acecfSBarry Smith + dm    - The `DM`
499720f4b53cSBarry Smith . label - The label indicating the support of the field, or `NULL` for the entire mesh
4998bb7acecfSBarry Smith - disc  - The discretization object
499944a7f3ddSMatthew G. Knepley 
500044a7f3ddSMatthew G. Knepley   Level: intermediate
500144a7f3ddSMatthew G. Knepley 
5002bb7acecfSBarry Smith   Notes:
5003bb7acecfSBarry Smith   The label already exists or will be added to the `DM` with `DMSetLabel()`.
5004bb7acecfSBarry Smith 
5005da81f932SPierre Jolivet   For example, a piecewise continuous pressure field can be defined by coefficients at the cell centers of a mesh and piecewise constant functions
5006bb7acecfSBarry 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
5007bb7acecfSBarry Smith   geometry entities, a `DMLabel` indicating a subset of those geometric entities, and a discretization object, such as a `PetscFE`.
5008bb7acecfSBarry Smith 
50091cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetLabel()`, `DMSetField()`, `DMGetField()`, `PetscFE`
501044a7f3ddSMatthew G. Knepley @*/
5011d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject disc)
5012d71ae5a4SJacob Faibussowitsch {
501344a7f3ddSMatthew G. Knepley   PetscInt Nf = dm->Nf;
501444a7f3ddSMatthew G. Knepley 
501544a7f3ddSMatthew G. Knepley   PetscFunctionBegin;
501644a7f3ddSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5017064a246eSJacob Faibussowitsch   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
5018bb7acecfSBarry Smith   PetscValidHeader(disc, 3);
50199566063dSJacob Faibussowitsch   PetscCall(DMFieldEnlarge_Static(dm, Nf + 1));
502044a7f3ddSMatthew G. Knepley   dm->fields[Nf].label = label;
5021bb7acecfSBarry Smith   dm->fields[Nf].disc  = disc;
50229566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
5023bb7acecfSBarry Smith   PetscCall(PetscObjectReference((PetscObject)disc));
5024bb7acecfSBarry Smith   PetscCall(DMSetDefaultAdjacency_Private(dm, Nf, disc));
50259566063dSJacob Faibussowitsch   PetscCall(DMClearDS(dm));
50263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5027af122d2aSMatthew G Knepley }
50286636e97aSMatthew G Knepley 
5029e5e52638SMatthew G. Knepley /*@
5030e0b68406SMatthew Knepley   DMSetFieldAvoidTensor - Set flag to avoid defining the field on tensor cells
5031e0b68406SMatthew Knepley 
503220f4b53cSBarry Smith   Logically Collective
5033e0b68406SMatthew Knepley 
5034e0b68406SMatthew Knepley   Input Parameters:
5035bb7acecfSBarry Smith + dm          - The `DM`
5036e0b68406SMatthew Knepley . f           - The field index
5037bb7acecfSBarry Smith - avoidTensor - `PETSC_TRUE` to skip defining the field on tensor cells
5038e0b68406SMatthew Knepley 
5039e0b68406SMatthew Knepley   Level: intermediate
5040e0b68406SMatthew Knepley 
50411cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetFieldAvoidTensor()`, `DMSetField()`, `DMGetField()`
5042e0b68406SMatthew Knepley @*/
5043d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFieldAvoidTensor(DM dm, PetscInt f, PetscBool avoidTensor)
5044d71ae5a4SJacob Faibussowitsch {
5045e0b68406SMatthew Knepley   PetscFunctionBegin;
504663a3b9bcSJacob 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);
5047e0b68406SMatthew Knepley   dm->fields[f].avoidTensor = avoidTensor;
50483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5049e0b68406SMatthew Knepley }
5050e0b68406SMatthew Knepley 
5051e0b68406SMatthew Knepley /*@
5052e0b68406SMatthew Knepley   DMGetFieldAvoidTensor - Get flag to avoid defining the field on tensor cells
5053e0b68406SMatthew Knepley 
505420f4b53cSBarry Smith   Not Collective
5055e0b68406SMatthew Knepley 
5056e0b68406SMatthew Knepley   Input Parameters:
5057bb7acecfSBarry Smith + dm - The `DM`
5058e0b68406SMatthew Knepley - f  - The field index
5059e0b68406SMatthew Knepley 
5060e0b68406SMatthew Knepley   Output Parameter:
5061e0b68406SMatthew Knepley . avoidTensor - The flag to avoid defining the field on tensor cells
5062e0b68406SMatthew Knepley 
5063e0b68406SMatthew Knepley   Level: intermediate
5064e0b68406SMatthew Knepley 
506560225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMAddField()`, `DMSetField()`, `DMGetField()`, `DMSetFieldAvoidTensor()`
5066e0b68406SMatthew Knepley @*/
5067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFieldAvoidTensor(DM dm, PetscInt f, PetscBool *avoidTensor)
5068d71ae5a4SJacob Faibussowitsch {
5069e0b68406SMatthew Knepley   PetscFunctionBegin;
507063a3b9bcSJacob 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);
5071e0b68406SMatthew Knepley   *avoidTensor = dm->fields[f].avoidTensor;
50723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5073e0b68406SMatthew Knepley }
5074e0b68406SMatthew Knepley 
5075e0b68406SMatthew Knepley /*@
5076bb7acecfSBarry Smith   DMCopyFields - Copy the discretizations for the `DM` into another `DM`
5077e5e52638SMatthew G. Knepley 
507820f4b53cSBarry Smith   Collective
5079e5e52638SMatthew G. Knepley 
5080e5e52638SMatthew G. Knepley   Input Parameter:
5081bb7acecfSBarry Smith . dm - The `DM`
5082e5e52638SMatthew G. Knepley 
5083e5e52638SMatthew G. Knepley   Output Parameter:
5084bb7acecfSBarry Smith . newdm - The `DM`
5085e5e52638SMatthew G. Knepley 
5086e5e52638SMatthew G. Knepley   Level: advanced
5087e5e52638SMatthew G. Knepley 
50881cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetField()`, `DMSetField()`, `DMAddField()`, `DMCopyDS()`, `DMGetDS()`, `DMGetCellDS()`
5089e5e52638SMatthew G. Knepley @*/
5090d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyFields(DM dm, DM newdm)
5091d71ae5a4SJacob Faibussowitsch {
5092e5e52638SMatthew G. Knepley   PetscInt Nf, f;
5093e5e52638SMatthew G. Knepley 
5094e5e52638SMatthew G. Knepley   PetscFunctionBegin;
50953ba16761SJacob Faibussowitsch   if (dm == newdm) PetscFunctionReturn(PETSC_SUCCESS);
50969566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
50979566063dSJacob Faibussowitsch   PetscCall(DMClearFields(newdm));
5098e5e52638SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5099e5e52638SMatthew G. Knepley     DMLabel     label;
5100e5e52638SMatthew G. Knepley     PetscObject field;
510134aa8a36SMatthew G. Knepley     PetscBool   useCone, useClosure;
5102e5e52638SMatthew G. Knepley 
51039566063dSJacob Faibussowitsch     PetscCall(DMGetField(dm, f, &label, &field));
51049566063dSJacob Faibussowitsch     PetscCall(DMSetField(newdm, f, label, field));
51059566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, f, &useCone, &useClosure));
51069566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(newdm, f, useCone, useClosure));
510734aa8a36SMatthew G. Knepley   }
51083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
510934aa8a36SMatthew G. Knepley }
511034aa8a36SMatthew G. Knepley 
511134aa8a36SMatthew G. Knepley /*@
511234aa8a36SMatthew G. Knepley   DMGetAdjacency - Returns the flags for determining variable influence
511334aa8a36SMatthew G. Knepley 
511420f4b53cSBarry Smith   Not Collective
511534aa8a36SMatthew G. Knepley 
511634aa8a36SMatthew G. Knepley   Input Parameters:
511720f4b53cSBarry Smith + dm - The `DM` object
511820f4b53cSBarry Smith - f  - The field number, or `PETSC_DEFAULT` for the default adjacency
511934aa8a36SMatthew G. Knepley 
5120d8d19677SJose E. Roman   Output Parameters:
512134aa8a36SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
512234aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
512334aa8a36SMatthew G. Knepley 
512434aa8a36SMatthew G. Knepley   Level: developer
512534aa8a36SMatthew G. Knepley 
512620f4b53cSBarry Smith   Notes:
512720f4b53cSBarry Smith .vb
512820f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
512920f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
513020f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
513120f4b53cSBarry Smith .ve
513220f4b53cSBarry Smith   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
513320f4b53cSBarry Smith 
51341cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetAdjacency()`, `DMGetField()`, `DMSetField()`
513534aa8a36SMatthew G. Knepley @*/
5136d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure)
5137d71ae5a4SJacob Faibussowitsch {
513834aa8a36SMatthew G. Knepley   PetscFunctionBegin;
513934aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51404f572ea9SToby Isaac   if (useCone) PetscAssertPointer(useCone, 3);
51414f572ea9SToby Isaac   if (useClosure) PetscAssertPointer(useClosure, 4);
514234aa8a36SMatthew G. Knepley   if (f < 0) {
514334aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->adjacency[0];
514434aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->adjacency[1];
514534aa8a36SMatthew G. Knepley   } else {
514634aa8a36SMatthew G. Knepley     PetscInt Nf;
514734aa8a36SMatthew G. Knepley 
51489566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
51497a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
515034aa8a36SMatthew G. Knepley     if (useCone) *useCone = dm->fields[f].adjacency[0];
515134aa8a36SMatthew G. Knepley     if (useClosure) *useClosure = dm->fields[f].adjacency[1];
515234aa8a36SMatthew G. Knepley   }
51533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
515434aa8a36SMatthew G. Knepley }
515534aa8a36SMatthew G. Knepley 
515634aa8a36SMatthew G. Knepley /*@
515734aa8a36SMatthew G. Knepley   DMSetAdjacency - Set the flags for determining variable influence
515834aa8a36SMatthew G. Knepley 
515920f4b53cSBarry Smith   Not Collective
516034aa8a36SMatthew G. Knepley 
516134aa8a36SMatthew G. Knepley   Input Parameters:
516220f4b53cSBarry Smith + dm         - The `DM` object
516334aa8a36SMatthew G. Knepley . f          - The field number
516434aa8a36SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
516534aa8a36SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
516634aa8a36SMatthew G. Knepley 
516734aa8a36SMatthew G. Knepley   Level: developer
516834aa8a36SMatthew G. Knepley 
516920f4b53cSBarry Smith   Notes:
517020f4b53cSBarry Smith .vb
517120f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
517220f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
517320f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
517420f4b53cSBarry Smith .ve
517520f4b53cSBarry Smith   Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another.
517620f4b53cSBarry Smith 
51771cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetAdjacency()`, `DMGetField()`, `DMSetField()`
517834aa8a36SMatthew G. Knepley @*/
5179d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure)
5180d71ae5a4SJacob Faibussowitsch {
518134aa8a36SMatthew G. Knepley   PetscFunctionBegin;
518234aa8a36SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
518334aa8a36SMatthew G. Knepley   if (f < 0) {
518434aa8a36SMatthew G. Knepley     dm->adjacency[0] = useCone;
518534aa8a36SMatthew G. Knepley     dm->adjacency[1] = useClosure;
518634aa8a36SMatthew G. Knepley   } else {
518734aa8a36SMatthew G. Knepley     PetscInt Nf;
518834aa8a36SMatthew G. Knepley 
51899566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
51907a8be351SBarry Smith     PetscCheck(f < Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
519134aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[0] = useCone;
519234aa8a36SMatthew G. Knepley     dm->fields[f].adjacency[1] = useClosure;
5193e5e52638SMatthew G. Knepley   }
51943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5195e5e52638SMatthew G. Knepley }
5196e5e52638SMatthew G. Knepley 
5197b0441da4SMatthew G. Knepley /*@
5198b0441da4SMatthew G. Knepley   DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined
5199b0441da4SMatthew G. Knepley 
5200b0441da4SMatthew G. Knepley   Not collective
5201b0441da4SMatthew G. Knepley 
5202f899ff85SJose E. Roman   Input Parameter:
520320f4b53cSBarry Smith . dm - The `DM` object
5204b0441da4SMatthew G. Knepley 
5205d8d19677SJose E. Roman   Output Parameters:
5206b0441da4SMatthew G. Knepley + useCone    - Flag for variable influence starting with the cone operation
5207b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5208b0441da4SMatthew G. Knepley 
5209b0441da4SMatthew G. Knepley   Level: developer
5210b0441da4SMatthew G. Knepley 
521120f4b53cSBarry Smith   Notes:
521220f4b53cSBarry Smith .vb
521320f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
521420f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
521520f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
521620f4b53cSBarry Smith .ve
521720f4b53cSBarry Smith 
52181cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5219b0441da4SMatthew G. Knepley @*/
5220d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure)
5221d71ae5a4SJacob Faibussowitsch {
5222b0441da4SMatthew G. Knepley   PetscInt Nf;
5223b0441da4SMatthew G. Knepley 
5224b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5225b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52264f572ea9SToby Isaac   if (useCone) PetscAssertPointer(useCone, 2);
52274f572ea9SToby Isaac   if (useClosure) PetscAssertPointer(useClosure, 3);
52289566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5229b0441da4SMatthew G. Knepley   if (!Nf) {
52309566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5231b0441da4SMatthew G. Knepley   } else {
52329566063dSJacob Faibussowitsch     PetscCall(DMGetAdjacency(dm, 0, useCone, useClosure));
5233b0441da4SMatthew G. Knepley   }
52343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5235b0441da4SMatthew G. Knepley }
5236b0441da4SMatthew G. Knepley 
5237b0441da4SMatthew G. Knepley /*@
5238b0441da4SMatthew G. Knepley   DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined
5239b0441da4SMatthew G. Knepley 
524020f4b53cSBarry Smith   Not Collective
5241b0441da4SMatthew G. Knepley 
5242b0441da4SMatthew G. Knepley   Input Parameters:
524320f4b53cSBarry Smith + dm         - The `DM` object
5244b0441da4SMatthew G. Knepley . useCone    - Flag for variable influence starting with the cone operation
5245b0441da4SMatthew G. Knepley - useClosure - Flag for variable influence using transitive closure
5246b0441da4SMatthew G. Knepley 
5247b0441da4SMatthew G. Knepley   Level: developer
5248b0441da4SMatthew G. Knepley 
524920f4b53cSBarry Smith   Notes:
525020f4b53cSBarry Smith .vb
525120f4b53cSBarry Smith      FEM:   Two points p and q are adjacent if q \in closure(star(p)),   useCone = PETSC_FALSE, useClosure = PETSC_TRUE
525220f4b53cSBarry Smith      FVM:   Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE,  useClosure = PETSC_FALSE
525320f4b53cSBarry Smith      FVM++: Two points p and q are adjacent if q \in star(closure(p)),   useCone = PETSC_TRUE,  useClosure = PETSC_TRUE
525420f4b53cSBarry Smith .ve
525520f4b53cSBarry Smith 
52561cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetBasicAdjacency()`, `DMGetField()`, `DMSetField()`
5257b0441da4SMatthew G. Knepley @*/
5258d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure)
5259d71ae5a4SJacob Faibussowitsch {
5260b0441da4SMatthew G. Knepley   PetscInt Nf;
5261b0441da4SMatthew G. Knepley 
5262b0441da4SMatthew G. Knepley   PetscFunctionBegin;
5263b0441da4SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52649566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
5265b0441da4SMatthew G. Knepley   if (!Nf) {
52669566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure));
5267b0441da4SMatthew G. Knepley   } else {
52689566063dSJacob Faibussowitsch     PetscCall(DMSetAdjacency(dm, 0, useCone, useClosure));
5269e5e52638SMatthew G. Knepley   }
52703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5271e5e52638SMatthew G. Knepley }
5272e5e52638SMatthew G. Knepley 
5273d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompleteBCLabels_Internal(DM dm)
5274d71ae5a4SJacob Faibussowitsch {
5275799db056SMatthew G. Knepley   DM           plex;
5276799db056SMatthew G. Knepley   DMLabel     *labels, *glabels;
5277799db056SMatthew G. Knepley   const char **names;
5278799db056SMatthew G. Knepley   char        *sendNames, *recvNames;
5279799db056SMatthew G. Knepley   PetscInt     Nds, s, maxLabels = 0, maxLen = 0, gmaxLen, Nl = 0, gNl, l, gl, m;
5280799db056SMatthew G. Knepley   size_t       len;
5281799db056SMatthew G. Knepley   MPI_Comm     comm;
5282799db056SMatthew G. Knepley   PetscMPIInt  rank, size, p, *counts, *displs;
5283783e2ec8SMatthew G. Knepley 
5284783e2ec8SMatthew G. Knepley   PetscFunctionBegin;
5285799db056SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5286799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
5287799db056SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
5288799db056SMatthew G. Knepley   PetscCall(DMGetNumDS(dm, &Nds));
5289799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5290799db056SMatthew G. Knepley     PetscDS  dsBC;
5291799db056SMatthew G. Knepley     PetscInt numBd;
5292799db056SMatthew G. Knepley 
529307218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC, NULL));
5294799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5295799db056SMatthew G. Knepley     maxLabels += numBd;
5296799db056SMatthew G. Knepley   }
5297799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(maxLabels, &labels));
5298799db056SMatthew G. Knepley   /* Get list of labels to be completed */
5299799db056SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5300799db056SMatthew G. Knepley     PetscDS  dsBC;
5301799db056SMatthew G. Knepley     PetscInt numBd, bd;
5302799db056SMatthew G. Knepley 
530307218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, NULL, NULL, &dsBC, NULL));
5304799db056SMatthew G. Knepley     PetscCall(PetscDSGetNumBoundary(dsBC, &numBd));
5305799db056SMatthew G. Knepley     for (bd = 0; bd < numBd; ++bd) {
5306799db056SMatthew G. Knepley       DMLabel      label;
5307799db056SMatthew G. Knepley       PetscInt     field;
5308799db056SMatthew G. Knepley       PetscObject  obj;
5309799db056SMatthew G. Knepley       PetscClassId id;
5310799db056SMatthew G. Knepley 
5311799db056SMatthew G. Knepley       PetscCall(PetscDSGetBoundary(dsBC, bd, NULL, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
53129566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, field, NULL, &obj));
53139566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
5314799db056SMatthew G. Knepley       if (!(id == PETSCFE_CLASSID) || !label) continue;
53159371c9d4SSatish Balay       for (l = 0; l < Nl; ++l)
53169371c9d4SSatish Balay         if (labels[l] == label) break;
5317799db056SMatthew G. Knepley       if (l == Nl) labels[Nl++] = label;
5318783e2ec8SMatthew G. Knepley     }
5319799db056SMatthew G. Knepley   }
5320799db056SMatthew G. Knepley   /* Get label names */
5321799db056SMatthew G. Knepley   PetscCall(PetscMalloc1(Nl, &names));
5322799db056SMatthew G. Knepley   for (l = 0; l < Nl; ++l) PetscCall(PetscObjectGetName((PetscObject)labels[l], &names[l]));
53239371c9d4SSatish Balay   for (l = 0; l < Nl; ++l) {
53249371c9d4SSatish Balay     PetscCall(PetscStrlen(names[l], &len));
53259371c9d4SSatish Balay     maxLen = PetscMax(maxLen, (PetscInt)len + 2);
53269371c9d4SSatish Balay   }
5327799db056SMatthew G. Knepley   PetscCall(PetscFree(labels));
5328712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&maxLen, &gmaxLen, 1, MPIU_INT, MPI_MAX, comm));
5329799db056SMatthew G. Knepley   PetscCall(PetscCalloc1(Nl * gmaxLen, &sendNames));
5330c6a7a370SJeremy L Thompson   for (l = 0; l < Nl; ++l) PetscCall(PetscStrncpy(&sendNames[gmaxLen * l], names[l], gmaxLen));
5331799db056SMatthew G. Knepley   PetscCall(PetscFree(names));
5332799db056SMatthew G. Knepley   /* Put all names on all processes */
5333799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(size, &counts, size + 1, &displs));
5334799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgather(&Nl, 1, MPI_INT, counts, 1, MPI_INT, comm));
5335799db056SMatthew G. Knepley   for (p = 0; p < size; ++p) displs[p + 1] = displs[p] + counts[p];
5336799db056SMatthew G. Knepley   gNl = displs[size];
53379371c9d4SSatish Balay   for (p = 0; p < size; ++p) {
53389371c9d4SSatish Balay     counts[p] *= gmaxLen;
53399371c9d4SSatish Balay     displs[p] *= gmaxLen;
53409371c9d4SSatish Balay   }
5341799db056SMatthew G. Knepley   PetscCall(PetscCalloc2(gNl * gmaxLen, &recvNames, gNl, &glabels));
5342799db056SMatthew G. Knepley   PetscCallMPI(MPI_Allgatherv(sendNames, counts[rank], MPI_CHAR, recvNames, counts, displs, MPI_CHAR, comm));
5343799db056SMatthew G. Knepley   PetscCall(PetscFree2(counts, displs));
5344799db056SMatthew G. Knepley   PetscCall(PetscFree(sendNames));
5345799db056SMatthew G. Knepley   for (l = 0, gl = 0; l < gNl; ++l) {
5346799db056SMatthew G. Knepley     PetscCall(DMGetLabel(dm, &recvNames[l * gmaxLen], &glabels[gl]));
5347799db056SMatthew G. Knepley     PetscCheck(glabels[gl], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Label %s missing on rank %d", &recvNames[l * gmaxLen], rank);
53489371c9d4SSatish Balay     for (m = 0; m < gl; ++m)
53499371c9d4SSatish Balay       if (glabels[m] == glabels[gl]) continue;
53509566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
5351799db056SMatthew G. Knepley     PetscCall(DMPlexLabelComplete(plex, glabels[gl]));
53529566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5353799db056SMatthew G. Knepley     ++gl;
5354783e2ec8SMatthew G. Knepley   }
5355799db056SMatthew G. Knepley   PetscCall(PetscFree2(recvNames, glabels));
53563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5357783e2ec8SMatthew G. Knepley }
5358783e2ec8SMatthew G. Knepley 
5359d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew)
5360d71ae5a4SJacob Faibussowitsch {
5361e5e52638SMatthew G. Knepley   DMSpace *tmpd;
5362e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5363e5e52638SMatthew G. Knepley 
5364e5e52638SMatthew G. Knepley   PetscFunctionBegin;
53653ba16761SJacob Faibussowitsch   if (Nds >= NdsNew) PetscFunctionReturn(PETSC_SUCCESS);
53669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(NdsNew, &tmpd));
5367e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s];
53689371c9d4SSatish Balay   for (s = Nds; s < NdsNew; ++s) {
53699371c9d4SSatish Balay     tmpd[s].ds     = NULL;
53709371c9d4SSatish Balay     tmpd[s].label  = NULL;
53719371c9d4SSatish Balay     tmpd[s].fields = NULL;
53729371c9d4SSatish Balay   }
53739566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5374e5e52638SMatthew G. Knepley   dm->Nds   = NdsNew;
5375e5e52638SMatthew G. Knepley   dm->probs = tmpd;
53763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5377e5e52638SMatthew G. Knepley }
5378e5e52638SMatthew G. Knepley 
5379e5e52638SMatthew G. Knepley /*@
538020f4b53cSBarry Smith   DMGetNumDS - Get the number of discrete systems in the `DM`
5381e5e52638SMatthew G. Knepley 
538220f4b53cSBarry Smith   Not Collective
5383e5e52638SMatthew G. Knepley 
5384e5e52638SMatthew G. Knepley   Input Parameter:
538520f4b53cSBarry Smith . dm - The `DM`
5386e5e52638SMatthew G. Knepley 
5387e5e52638SMatthew G. Knepley   Output Parameter:
538820f4b53cSBarry Smith . Nds - The number of `PetscDS` objects
5389e5e52638SMatthew G. Knepley 
5390e5e52638SMatthew G. Knepley   Level: intermediate
5391e5e52638SMatthew G. Knepley 
53921cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDS()`, `DMGetCellDS()`
5393e5e52638SMatthew G. Knepley @*/
5394d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds)
5395d71ae5a4SJacob Faibussowitsch {
5396e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5397e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53984f572ea9SToby Isaac   PetscAssertPointer(Nds, 2);
5399e5e52638SMatthew G. Knepley   *Nds = dm->Nds;
54003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5401e5e52638SMatthew G. Knepley }
5402e5e52638SMatthew G. Knepley 
5403e5e52638SMatthew G. Knepley /*@
540420f4b53cSBarry Smith   DMClearDS - Remove all discrete systems from the `DM`
5405e5e52638SMatthew G. Knepley 
540620f4b53cSBarry Smith   Logically Collective
5407e5e52638SMatthew G. Knepley 
5408e5e52638SMatthew G. Knepley   Input Parameter:
540920f4b53cSBarry Smith . dm - The `DM`
5410e5e52638SMatthew G. Knepley 
5411e5e52638SMatthew G. Knepley   Level: intermediate
5412e5e52638SMatthew G. Knepley 
54131cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumDS()`, `DMGetDS()`, `DMSetField()`
5414e5e52638SMatthew G. Knepley @*/
5415d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearDS(DM dm)
5416d71ae5a4SJacob Faibussowitsch {
5417e5e52638SMatthew G. Knepley   PetscInt s;
5418e5e52638SMatthew G. Knepley 
5419e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5420e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5421e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
54229566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[s].ds));
542307218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dm->probs[s].dsIn));
54249566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&dm->probs[s].label));
54259566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[s].fields));
5426e5e52638SMatthew G. Knepley   }
54279566063dSJacob Faibussowitsch   PetscCall(PetscFree(dm->probs));
5428e5e52638SMatthew G. Knepley   dm->probs = NULL;
5429e5e52638SMatthew G. Knepley   dm->Nds   = 0;
54303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5431e5e52638SMatthew G. Knepley }
5432e5e52638SMatthew G. Knepley 
5433e5e52638SMatthew G. Knepley /*@
543420f4b53cSBarry Smith   DMGetDS - Get the default `PetscDS`
5435e5e52638SMatthew G. Knepley 
543620f4b53cSBarry Smith   Not Collective
5437e5e52638SMatthew G. Knepley 
5438e5e52638SMatthew G. Knepley   Input Parameter:
543920f4b53cSBarry Smith . dm - The `DM`
5440e5e52638SMatthew G. Knepley 
5441e5e52638SMatthew G. Knepley   Output Parameter:
544207218a29SMatthew G. Knepley . ds - The default `PetscDS`
5443e5e52638SMatthew G. Knepley 
5444e5e52638SMatthew G. Knepley   Level: intermediate
5445e5e52638SMatthew G. Knepley 
54461cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetCellDS()`, `DMGetRegionDS()`
5447e5e52638SMatthew G. Knepley @*/
544807218a29SMatthew G. Knepley PetscErrorCode DMGetDS(DM dm, PetscDS *ds)
5449d71ae5a4SJacob Faibussowitsch {
5450e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5451e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54524f572ea9SToby Isaac   PetscAssertPointer(ds, 2);
545307218a29SMatthew G. Knepley   PetscCheck(dm->Nds > 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Need to call DMCreateDS() before calling DMGetDS()");
545407218a29SMatthew G. Knepley   *ds = dm->probs[0].ds;
54553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5456e5e52638SMatthew G. Knepley }
5457e5e52638SMatthew G. Knepley 
5458e5e52638SMatthew G. Knepley /*@
545920f4b53cSBarry Smith   DMGetCellDS - Get the `PetscDS` defined on a given cell
5460e5e52638SMatthew G. Knepley 
546120f4b53cSBarry Smith   Not Collective
5462e5e52638SMatthew G. Knepley 
5463e5e52638SMatthew G. Knepley   Input Parameters:
546420f4b53cSBarry Smith + dm    - The `DM`
546520f4b53cSBarry Smith - point - Cell for the `PetscDS`
5466e5e52638SMatthew G. Knepley 
546707218a29SMatthew G. Knepley   Output Parameters:
546807218a29SMatthew G. Knepley + ds   - The `PetscDS` defined on the given cell
546907218a29SMatthew G. Knepley - dsIn - The `PetscDS` for input on the given cell, or NULL if the same ds
5470e5e52638SMatthew G. Knepley 
5471e5e52638SMatthew G. Knepley   Level: developer
5472e5e52638SMatthew G. Knepley 
54731cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDS()`, `DMSetRegionDS()`
5474e5e52638SMatthew G. Knepley @*/
547507218a29SMatthew G. Knepley PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *ds, PetscDS *dsIn)
5476d71ae5a4SJacob Faibussowitsch {
547707218a29SMatthew G. Knepley   PetscDS  dsDef = NULL;
5478e5e52638SMatthew G. Knepley   PetscInt s;
5479e5e52638SMatthew G. Knepley 
5480e5e52638SMatthew G. Knepley   PetscFunctionBeginHot;
5481e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54824f572ea9SToby Isaac   if (ds) PetscAssertPointer(ds, 3);
54834f572ea9SToby Isaac   if (dsIn) PetscAssertPointer(dsIn, 4);
548463a3b9bcSJacob Faibussowitsch   PetscCheck(point >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point cannot be negative: %" PetscInt_FMT, point);
548507218a29SMatthew G. Knepley   if (ds) *ds = NULL;
548607218a29SMatthew G. Knepley   if (dsIn) *dsIn = NULL;
5487e5e52638SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5488e5e52638SMatthew G. Knepley     PetscInt val;
5489e5e52638SMatthew G. Knepley 
54909371c9d4SSatish Balay     if (!dm->probs[s].label) {
549107218a29SMatthew G. Knepley       dsDef = dm->probs[s].ds;
54929371c9d4SSatish Balay     } else {
54939566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(dm->probs[s].label, point, &val));
54949371c9d4SSatish Balay       if (val >= 0) {
549507218a29SMatthew G. Knepley         if (ds) *ds = dm->probs[s].ds;
549607218a29SMatthew G. Knepley         if (dsIn) *dsIn = dm->probs[s].dsIn;
54979371c9d4SSatish Balay         break;
54989371c9d4SSatish Balay       }
5499e5e52638SMatthew G. Knepley     }
5500e5e52638SMatthew G. Knepley   }
550107218a29SMatthew G. Knepley   if (ds && !*ds) *ds = dsDef;
55023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5503e5e52638SMatthew G. Knepley }
5504e5e52638SMatthew G. Knepley 
5505e5e52638SMatthew G. Knepley /*@
550620f4b53cSBarry Smith   DMGetRegionDS - Get the `PetscDS` for a given mesh region, defined by a `DMLabel`
5507e5e52638SMatthew G. Knepley 
550820f4b53cSBarry Smith   Not Collective
5509e5e52638SMatthew G. Knepley 
5510e5e52638SMatthew G. Knepley   Input Parameters:
551120f4b53cSBarry Smith + dm    - The `DM`
551220f4b53cSBarry Smith - label - The `DMLabel` defining the mesh region, or `NULL` for the entire mesh
5513e5e52638SMatthew G. Knepley 
5514b3cf3223SMatthew G. Knepley   Output Parameters:
551520f4b53cSBarry Smith + fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL`
551607218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL`
551707218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input in the given region, or `NULL`
5518e5e52638SMatthew G. Knepley 
5519e5e52638SMatthew G. Knepley   Level: advanced
5520e5e52638SMatthew G. Knepley 
552120f4b53cSBarry Smith   Note:
552220f4b53cSBarry Smith   If a non-`NULL` label is given, but there is no `PetscDS` on that specific label,
552320f4b53cSBarry Smith   the `PetscDS` for the full domain (if present) is returned. Returns with
552407218a29SMatthew G. Knepley   fields = `NULL` and ds = `NULL` if there is no `PetscDS` for the full domain.
552520f4b53cSBarry Smith 
55261cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionNumDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5527e5e52638SMatthew G. Knepley @*/
552807218a29SMatthew G. Knepley PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds, PetscDS *dsIn)
5529d71ae5a4SJacob Faibussowitsch {
5530e5e52638SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5531e5e52638SMatthew G. Knepley 
5532e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5533e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5534e5e52638SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
55359371c9d4SSatish Balay   if (fields) {
55364f572ea9SToby Isaac     PetscAssertPointer(fields, 3);
55379371c9d4SSatish Balay     *fields = NULL;
55389371c9d4SSatish Balay   }
55399371c9d4SSatish Balay   if (ds) {
55404f572ea9SToby Isaac     PetscAssertPointer(ds, 4);
55419371c9d4SSatish Balay     *ds = NULL;
55429371c9d4SSatish Balay   }
554307218a29SMatthew G. Knepley   if (dsIn) {
55444f572ea9SToby Isaac     PetscAssertPointer(dsIn, 5);
554507218a29SMatthew G. Knepley     *dsIn = NULL;
554607218a29SMatthew G. Knepley   }
5547e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5548154ca461SJed Brown     if (dm->probs[s].label == label || !dm->probs[s].label) {
5549b3cf3223SMatthew G. Knepley       if (fields) *fields = dm->probs[s].fields;
5550b3cf3223SMatthew G. Knepley       if (ds) *ds = dm->probs[s].ds;
555107218a29SMatthew G. Knepley       if (dsIn) *dsIn = dm->probs[s].dsIn;
55523ba16761SJacob Faibussowitsch       if (dm->probs[s].label) PetscFunctionReturn(PETSC_SUCCESS);
5553b3cf3223SMatthew G. Knepley     }
5554e5e52638SMatthew G. Knepley   }
55553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5556e5e52638SMatthew G. Knepley }
5557e5e52638SMatthew G. Knepley 
5558e5e52638SMatthew G. Knepley /*@
5559bb7acecfSBarry Smith   DMSetRegionDS - Set the `PetscDS` for a given mesh region, defined by a `DMLabel`
5560083401c6SMatthew G. Knepley 
556120f4b53cSBarry Smith   Collective
5562083401c6SMatthew G. Knepley 
5563083401c6SMatthew G. Knepley   Input Parameters:
5564bb7acecfSBarry Smith + dm     - The `DM`
556520f4b53cSBarry Smith . label  - The `DMLabel` defining the mesh region, or `NULL` for the entire mesh
556607218a29SMatthew G. Knepley . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL` for all fields
556707218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region
556807218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input on the given cell, or `NULL` if it is the same `PetscDS`
5569083401c6SMatthew G. Knepley 
557020f4b53cSBarry Smith   Level: advanced
557120f4b53cSBarry Smith 
5572bb7acecfSBarry Smith   Note:
5573bb7acecfSBarry 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,
5574083401c6SMatthew G. Knepley   the fields argument is ignored.
5575083401c6SMatthew G. Knepley 
55761cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionNumDS()`, `DMGetDS()`, `DMGetCellDS()`
5577083401c6SMatthew G. Knepley @*/
557807218a29SMatthew G. Knepley PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds, PetscDS dsIn)
5579d71ae5a4SJacob Faibussowitsch {
5580083401c6SMatthew G. Knepley   PetscInt Nds = dm->Nds, s;
5581083401c6SMatthew G. Knepley 
5582083401c6SMatthew G. Knepley   PetscFunctionBegin;
5583083401c6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5584083401c6SMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
558507218a29SMatthew G. Knepley   if (fields) PetscValidHeaderSpecific(fields, IS_CLASSID, 3);
5586064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 4);
558707218a29SMatthew G. Knepley   if (dsIn) PetscValidHeaderSpecific(dsIn, PETSCDS_CLASSID, 5);
5588083401c6SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
5589083401c6SMatthew G. Knepley     if (dm->probs[s].label == label) {
55909566063dSJacob Faibussowitsch       PetscCall(PetscDSDestroy(&dm->probs[s].ds));
559107218a29SMatthew G. Knepley       PetscCall(PetscDSDestroy(&dm->probs[s].dsIn));
5592083401c6SMatthew G. Knepley       dm->probs[s].ds   = ds;
559307218a29SMatthew G. Knepley       dm->probs[s].dsIn = dsIn;
55943ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
5595083401c6SMatthew G. Knepley     }
5596083401c6SMatthew G. Knepley   }
55979566063dSJacob Faibussowitsch   PetscCall(DMDSEnlarge_Static(dm, Nds + 1));
55989566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
55999566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fields));
56009566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)ds));
560107218a29SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)dsIn));
5602083401c6SMatthew G. Knepley   if (!label) {
5603083401c6SMatthew G. Knepley     /* Put the NULL label at the front, so it is returned as the default */
5604083401c6SMatthew G. Knepley     for (s = Nds - 1; s >= 0; --s) dm->probs[s + 1] = dm->probs[s];
5605083401c6SMatthew G. Knepley     Nds = 0;
5606083401c6SMatthew G. Knepley   }
5607083401c6SMatthew G. Knepley   dm->probs[Nds].label  = label;
5608083401c6SMatthew G. Knepley   dm->probs[Nds].fields = fields;
5609083401c6SMatthew G. Knepley   dm->probs[Nds].ds     = ds;
561007218a29SMatthew G. Knepley   dm->probs[Nds].dsIn   = dsIn;
56113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5612083401c6SMatthew G. Knepley }
5613083401c6SMatthew G. Knepley 
5614083401c6SMatthew G. Knepley /*@
561520f4b53cSBarry Smith   DMGetRegionNumDS - Get the `PetscDS` for a given mesh region, defined by the region number
5616e5e52638SMatthew G. Knepley 
561720f4b53cSBarry Smith   Not Collective
5618e5e52638SMatthew G. Knepley 
5619e5e52638SMatthew G. Knepley   Input Parameters:
562020f4b53cSBarry Smith + dm  - The `DM`
5621e5e52638SMatthew G. Knepley - num - The region number, in [0, Nds)
5622e5e52638SMatthew G. Knepley 
5623e5e52638SMatthew G. Knepley   Output Parameters:
562420f4b53cSBarry Smith + label  - The region label, or `NULL`
562520f4b53cSBarry Smith . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL`
562607218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL`
562707218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input in the given region, or `NULL`
5628e5e52638SMatthew G. Knepley 
5629e5e52638SMatthew G. Knepley   Level: advanced
5630e5e52638SMatthew G. Knepley 
56311cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5632e5e52638SMatthew G. Knepley @*/
563307218a29SMatthew G. Knepley PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds, PetscDS *dsIn)
5634d71ae5a4SJacob Faibussowitsch {
5635e5e52638SMatthew G. Knepley   PetscInt Nds;
5636e5e52638SMatthew G. Knepley 
5637e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5638e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56399566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
564063a3b9bcSJacob 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);
5641e5e52638SMatthew G. Knepley   if (label) {
56424f572ea9SToby Isaac     PetscAssertPointer(label, 3);
5643e5e52638SMatthew G. Knepley     *label = dm->probs[num].label;
5644e5e52638SMatthew G. Knepley   }
5645b3cf3223SMatthew G. Knepley   if (fields) {
56464f572ea9SToby Isaac     PetscAssertPointer(fields, 4);
5647b3cf3223SMatthew G. Knepley     *fields = dm->probs[num].fields;
5648b3cf3223SMatthew G. Knepley   }
5649e5e52638SMatthew G. Knepley   if (ds) {
56504f572ea9SToby Isaac     PetscAssertPointer(ds, 5);
5651e5e52638SMatthew G. Knepley     *ds = dm->probs[num].ds;
5652e5e52638SMatthew G. Knepley   }
565307218a29SMatthew G. Knepley   if (dsIn) {
56544f572ea9SToby Isaac     PetscAssertPointer(dsIn, 6);
565507218a29SMatthew G. Knepley     *dsIn = dm->probs[num].dsIn;
565607218a29SMatthew G. Knepley   }
56573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5658e5e52638SMatthew G. Knepley }
5659e5e52638SMatthew G. Knepley 
5660e5e52638SMatthew G. Knepley /*@
566120f4b53cSBarry Smith   DMSetRegionNumDS - Set the `PetscDS` for a given mesh region, defined by the region number
5662e5e52638SMatthew G. Knepley 
566320f4b53cSBarry Smith   Not Collective
5664e5e52638SMatthew G. Knepley 
5665e5e52638SMatthew G. Knepley   Input Parameters:
566620f4b53cSBarry Smith + dm     - The `DM`
5667083401c6SMatthew G. Knepley . num    - The region number, in [0, Nds)
566820f4b53cSBarry Smith . label  - The region label, or `NULL`
566907218a29SMatthew G. Knepley . fields - The `IS` containing the `DM` field numbers for the fields in this `PetscDS`, or `NULL` to prevent setting
567007218a29SMatthew G. Knepley . ds     - The `PetscDS` defined on the given region, or `NULL` to prevent setting
567107218a29SMatthew G. Knepley - dsIn   - The `PetscDS` for input on the given cell, or `NULL` if it is the same `PetscDS`
5672e5e52638SMatthew G. Knepley 
5673e5e52638SMatthew G. Knepley   Level: advanced
5674e5e52638SMatthew G. Knepley 
56751cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
5676e5e52638SMatthew G. Knepley @*/
567707218a29SMatthew G. Knepley PetscErrorCode DMSetRegionNumDS(DM dm, PetscInt num, DMLabel label, IS fields, PetscDS ds, PetscDS dsIn)
5678d71ae5a4SJacob Faibussowitsch {
5679083401c6SMatthew G. Knepley   PetscInt Nds;
5680e5e52638SMatthew G. Knepley 
5681e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5682e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5683ad540459SPierre Jolivet   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
56849566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
568563a3b9bcSJacob 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);
56869566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
56879566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&dm->probs[num].label));
5688083401c6SMatthew G. Knepley   dm->probs[num].label = label;
5689083401c6SMatthew G. Knepley   if (fields) {
5690083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(fields, IS_CLASSID, 4);
56919566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)fields));
56929566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&dm->probs[num].fields));
5693083401c6SMatthew G. Knepley     dm->probs[num].fields = fields;
5694e5e52638SMatthew G. Knepley   }
5695083401c6SMatthew G. Knepley   if (ds) {
5696083401c6SMatthew G. Knepley     PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 5);
56979566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ds));
56989566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dm->probs[num].ds));
5699083401c6SMatthew G. Knepley     dm->probs[num].ds = ds;
5700083401c6SMatthew G. Knepley   }
570107218a29SMatthew G. Knepley   if (dsIn) {
570207218a29SMatthew G. Knepley     PetscValidHeaderSpecific(dsIn, PETSCDS_CLASSID, 6);
570307218a29SMatthew G. Knepley     PetscCall(PetscObjectReference((PetscObject)dsIn));
570407218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dm->probs[num].dsIn));
570507218a29SMatthew G. Knepley     dm->probs[num].dsIn = dsIn;
570607218a29SMatthew G. Knepley   }
57073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5708e5e52638SMatthew G. Knepley }
5709e5e52638SMatthew G. Knepley 
5710e5e52638SMatthew G. Knepley /*@
571120f4b53cSBarry Smith   DMFindRegionNum - Find the region number for a given `PetscDS`, or -1 if it is not found.
57121d3af9e0SMatthew G. Knepley 
571320f4b53cSBarry Smith   Not Collective
57141d3af9e0SMatthew G. Knepley 
57151d3af9e0SMatthew G. Knepley   Input Parameters:
571620f4b53cSBarry Smith + dm - The `DM`
571720f4b53cSBarry Smith - ds - The `PetscDS` defined on the given region
57181d3af9e0SMatthew G. Knepley 
57191d3af9e0SMatthew G. Knepley   Output Parameter:
57201d3af9e0SMatthew G. Knepley . num - The region number, in [0, Nds), or -1 if not found
57211d3af9e0SMatthew G. Knepley 
57221d3af9e0SMatthew G. Knepley   Level: advanced
57231d3af9e0SMatthew G. Knepley 
57241cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetRegionNumDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`, `DMGetDS()`, `DMGetCellDS()`
57251d3af9e0SMatthew G. Knepley @*/
5726d71ae5a4SJacob Faibussowitsch PetscErrorCode DMFindRegionNum(DM dm, PetscDS ds, PetscInt *num)
5727d71ae5a4SJacob Faibussowitsch {
57281d3af9e0SMatthew G. Knepley   PetscInt Nds, n;
57291d3af9e0SMatthew G. Knepley 
57301d3af9e0SMatthew G. Knepley   PetscFunctionBegin;
57311d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57321d3af9e0SMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 2);
57334f572ea9SToby Isaac   PetscAssertPointer(num, 3);
57349566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
57359371c9d4SSatish Balay   for (n = 0; n < Nds; ++n)
57369371c9d4SSatish Balay     if (ds == dm->probs[n].ds) break;
57371d3af9e0SMatthew G. Knepley   if (n >= Nds) *num = -1;
57381d3af9e0SMatthew G. Knepley   else *num = n;
57393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57401d3af9e0SMatthew G. Knepley }
57411d3af9e0SMatthew G. Knepley 
57422df84da0SMatthew G. Knepley /*@C
5743bb7acecfSBarry Smith   DMCreateFEDefault - Create a `PetscFE` based on the celltype for the mesh
57442df84da0SMatthew G. Knepley 
574520f4b53cSBarry Smith   Not Collective
57462df84da0SMatthew G. Knepley 
5747f1a722f8SMatthew G. Knepley   Input Parameters:
5748bb7acecfSBarry Smith + dm     - The `DM`
57492df84da0SMatthew G. Knepley . Nc     - The number of components for the field
575020f4b53cSBarry Smith . prefix - The options prefix for the output `PetscFE`, or `NULL`
5751bb7acecfSBarry Smith - qorder - The quadrature order or `PETSC_DETERMINE` to use `PetscSpace` polynomial degree
57522df84da0SMatthew G. Knepley 
57532df84da0SMatthew G. Knepley   Output Parameter:
5754bb7acecfSBarry Smith . fem - The `PetscFE`
57552df84da0SMatthew G. Knepley 
575620f4b53cSBarry Smith   Level: intermediate
575720f4b53cSBarry Smith 
5758bb7acecfSBarry Smith   Note:
5759bb7acecfSBarry Smith   This is a convenience method that just calls `PetscFECreateByCell()` underneath.
57602df84da0SMatthew G. Knepley 
57611cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscFECreateByCell()`, `DMAddField()`, `DMCreateDS()`, `DMGetCellDS()`, `DMGetRegionDS()`
57622df84da0SMatthew G. Knepley @*/
5763d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateFEDefault(DM dm, PetscInt Nc, const char prefix[], PetscInt qorder, PetscFE *fem)
5764d71ae5a4SJacob Faibussowitsch {
57652df84da0SMatthew G. Knepley   DMPolytopeType ct;
57662df84da0SMatthew G. Knepley   PetscInt       dim, cStart;
57672df84da0SMatthew G. Knepley 
57682df84da0SMatthew G. Knepley   PetscFunctionBegin;
57692df84da0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57702df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 2);
57714f572ea9SToby Isaac   if (prefix) PetscAssertPointer(prefix, 3);
57722df84da0SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, qorder, 4);
57734f572ea9SToby Isaac   PetscAssertPointer(fem, 5);
57749566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
57759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
57769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
57779566063dSJacob Faibussowitsch   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, Nc, ct, prefix, qorder, fem));
57783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57792df84da0SMatthew G. Knepley }
57802df84da0SMatthew G. Knepley 
57811d3af9e0SMatthew G. Knepley /*@
5782bb7acecfSBarry Smith   DMCreateDS - Create the discrete systems for the `DM` based upon the fields added to the `DM`
5783e5e52638SMatthew G. Knepley 
578420f4b53cSBarry Smith   Collective
5785e5e52638SMatthew G. Knepley 
5786e5e52638SMatthew G. Knepley   Input Parameter:
5787bb7acecfSBarry Smith . dm - The `DM`
5788e5e52638SMatthew G. Knepley 
578920f4b53cSBarry Smith   Options Database Key:
5790bb7acecfSBarry Smith . -dm_petscds_view - View all the `PetscDS` objects in this `DM`
579145480ffeSMatthew G. Knepley 
579220f4b53cSBarry Smith   Level: intermediate
579320f4b53cSBarry Smith 
57941cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetField`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
5795e5e52638SMatthew G. Knepley @*/
5796d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDS(DM dm)
5797d71ae5a4SJacob Faibussowitsch {
5798e5e52638SMatthew G. Knepley   MPI_Comm  comm;
5799083401c6SMatthew G. Knepley   PetscDS   dsDef;
5800083401c6SMatthew G. Knepley   DMLabel  *labelSet;
5801f9244615SMatthew G. Knepley   PetscInt  dE, Nf = dm->Nf, f, s, Nl, l, Ndef, k;
5802f9244615SMatthew G. Knepley   PetscBool doSetup = PETSC_TRUE, flg;
5803e5e52638SMatthew G. Knepley 
5804e5e52638SMatthew G. Knepley   PetscFunctionBegin;
5805e5e52638SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58063ba16761SJacob Faibussowitsch   if (!dm->fields) PetscFunctionReturn(PETSC_SUCCESS);
58079566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
58089566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
5809083401c6SMatthew G. Knepley   /* Determine how many regions we have */
58109566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(Nf, &labelSet));
5811083401c6SMatthew G. Knepley   Nl   = 0;
5812083401c6SMatthew G. Knepley   Ndef = 0;
5813083401c6SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
5814083401c6SMatthew G. Knepley     DMLabel  label = dm->fields[f].label;
5815083401c6SMatthew G. Knepley     PetscInt l;
5816083401c6SMatthew G. Knepley 
5817f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
5818f918ec44SMatthew G. Knepley     /* Move CEED context to discretizations */
5819f918ec44SMatthew G. Knepley     {
5820f918ec44SMatthew G. Knepley       PetscClassId id;
5821f918ec44SMatthew G. Knepley 
58229566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(dm->fields[f].disc, &id));
5823f918ec44SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
5824f918ec44SMatthew G. Knepley         Ceed ceed;
5825f918ec44SMatthew G. Knepley 
58269566063dSJacob Faibussowitsch         PetscCall(DMGetCeed(dm, &ceed));
58279566063dSJacob Faibussowitsch         PetscCall(PetscFESetCeed((PetscFE)dm->fields[f].disc, ceed));
5828f918ec44SMatthew G. Knepley       }
5829f918ec44SMatthew G. Knepley     }
5830f918ec44SMatthew G. Knepley #endif
58319371c9d4SSatish Balay     if (!label) {
58329371c9d4SSatish Balay       ++Ndef;
58339371c9d4SSatish Balay       continue;
58349371c9d4SSatish Balay     }
58359371c9d4SSatish Balay     for (l = 0; l < Nl; ++l)
58369371c9d4SSatish Balay       if (label == labelSet[l]) break;
5837083401c6SMatthew G. Knepley     if (l < Nl) continue;
5838083401c6SMatthew G. Knepley     labelSet[Nl++] = label;
5839083401c6SMatthew G. Knepley   }
5840083401c6SMatthew G. Knepley   /* Create default DS if there are no labels to intersect with */
584107218a29SMatthew G. Knepley   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef, NULL));
5842083401c6SMatthew G. Knepley   if (!dsDef && Ndef && !Nl) {
5843b3cf3223SMatthew G. Knepley     IS        fields;
5844b3cf3223SMatthew G. Knepley     PetscInt *fld, nf;
5845b3cf3223SMatthew G. Knepley 
58469371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58479371c9d4SSatish Balay       if (!dm->fields[f].label) ++nf;
58487a8be351SBarry Smith     PetscCheck(nf, comm, PETSC_ERR_PLIB, "All fields have labels, but we are trying to create a default DS");
58499566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
58509371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
58519371c9d4SSatish Balay       if (!dm->fields[f].label) fld[nf++] = f;
58529566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
58539566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
58549566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
58559566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
585688f0c812SMatthew G. Knepley 
58579566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
585807218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, NULL, fields, dsDef, NULL));
58599566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
58609566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fields));
58612df9ee95SMatthew G. Knepley   }
586207218a29SMatthew G. Knepley   PetscCall(DMGetRegionDS(dm, NULL, NULL, &dsDef, NULL));
58639566063dSJacob Faibussowitsch   if (dsDef) PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
5864083401c6SMatthew G. Knepley   /* Intersect labels with default fields */
5865083401c6SMatthew G. Knepley   if (Ndef && Nl) {
58660122748bSMatthew G. Knepley     DM              plex;
5867083401c6SMatthew G. Knepley     DMLabel         cellLabel;
5868083401c6SMatthew G. Knepley     IS              fieldIS, allcellIS, defcellIS = NULL;
5869083401c6SMatthew G. Knepley     PetscInt       *fields;
5870083401c6SMatthew G. Knepley     const PetscInt *cells;
5871083401c6SMatthew G. Knepley     PetscInt        depth, nf = 0, n, c;
58720122748bSMatthew G. Knepley 
58739566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
58749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(plex, &depth));
58759566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(plex, "dim", depth, &allcellIS));
58769566063dSJacob Faibussowitsch     if (!allcellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, &allcellIS));
58775fedec97SMatthew G. Knepley     /* TODO This looks like it only works for one label */
5878083401c6SMatthew G. Knepley     for (l = 0; l < Nl; ++l) {
5879083401c6SMatthew G. Knepley       DMLabel label = labelSet[l];
5880083401c6SMatthew G. Knepley       IS      pointIS;
5881083401c6SMatthew G. Knepley 
58829566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&defcellIS));
58839566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(label, 1, &pointIS));
58849566063dSJacob Faibussowitsch       PetscCall(ISDifference(allcellIS, pointIS, &defcellIS));
58859566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&pointIS));
5886083401c6SMatthew G. Knepley     }
58879566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&allcellIS));
5888083401c6SMatthew G. Knepley 
58899566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, "defaultCells", &cellLabel));
58909566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(defcellIS, &n));
58919566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(defcellIS, &cells));
58929566063dSJacob Faibussowitsch     for (c = 0; c < n; ++c) PetscCall(DMLabelSetValue(cellLabel, cells[c], 1));
58939566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(defcellIS, &cells));
58949566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&defcellIS));
58959566063dSJacob Faibussowitsch     PetscCall(DMPlexLabelComplete(plex, cellLabel));
5896083401c6SMatthew G. Knepley 
58979566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(Ndef, &fields));
58989371c9d4SSatish Balay     for (f = 0; f < Nf; ++f)
58999371c9d4SSatish Balay       if (!dm->fields[f].label) fields[nf++] = f;
59009566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fieldIS));
59019566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fieldIS, "dm_fields_"));
59029566063dSJacob Faibussowitsch     PetscCall(ISSetType(fieldIS, ISGENERAL));
59039566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fieldIS, nf, fields, PETSC_OWN_POINTER));
5904083401c6SMatthew G. Knepley 
59059566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsDef));
590607218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, cellLabel, fieldIS, dsDef, NULL));
59079566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(dsDef, dE));
59089566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&cellLabel));
59099566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&dsDef));
59109566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&fieldIS));
59119566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
5912083401c6SMatthew G. Knepley   }
5913083401c6SMatthew G. Knepley   /* Create label DSes
5914083401c6SMatthew G. Knepley      - WE ONLY SUPPORT IDENTICAL OR DISJOINT LABELS
5915083401c6SMatthew G. Knepley   */
5916083401c6SMatthew G. Knepley   /* TODO Should check that labels are disjoint */
5917083401c6SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
5918083401c6SMatthew G. Knepley     DMLabel   label = labelSet[l];
591907218a29SMatthew G. Knepley     PetscDS   ds, dsIn = NULL;
5920083401c6SMatthew G. Knepley     IS        fields;
5921083401c6SMatthew G. Knepley     PetscInt *fld, nf;
5922083401c6SMatthew G. Knepley 
59239566063dSJacob Faibussowitsch     PetscCall(PetscDSCreate(PETSC_COMM_SELF, &ds));
59249371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
59259371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) ++nf;
59269566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nf, &fld));
59279371c9d4SSatish Balay     for (f = 0, nf = 0; f < Nf; ++f)
59289371c9d4SSatish Balay       if (label == dm->fields[f].label || !dm->fields[f].label) fld[nf++] = f;
59299566063dSJacob Faibussowitsch     PetscCall(ISCreate(PETSC_COMM_SELF, &fields));
59309566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)fields, "dm_fields_"));
59319566063dSJacob Faibussowitsch     PetscCall(ISSetType(fields, ISGENERAL));
59329566063dSJacob Faibussowitsch     PetscCall(ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER));
59339566063dSJacob Faibussowitsch     PetscCall(PetscDSSetCoordinateDimension(ds, dE));
5934083401c6SMatthew G. Knepley     {
5935083401c6SMatthew G. Knepley       DMPolytopeType ct;
5936083401c6SMatthew G. Knepley       PetscInt       lStart, lEnd;
59375fedec97SMatthew G. Knepley       PetscBool      isCohesiveLocal = PETSC_FALSE, isCohesive;
59380122748bSMatthew G. Knepley 
59399566063dSJacob Faibussowitsch       PetscCall(DMLabelGetBounds(label, &lStart, &lEnd));
5940665f567fSMatthew G. Knepley       if (lStart >= 0) {
59419566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, lStart, &ct));
5942412e9a14SMatthew G. Knepley         switch (ct) {
5943412e9a14SMatthew G. Knepley         case DM_POLYTOPE_POINT_PRISM_TENSOR:
5944412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
5945412e9a14SMatthew G. Knepley         case DM_POLYTOPE_TRI_PRISM_TENSOR:
5946d71ae5a4SJacob Faibussowitsch         case DM_POLYTOPE_QUAD_PRISM_TENSOR:
5947d71ae5a4SJacob Faibussowitsch           isCohesiveLocal = PETSC_TRUE;
5948d71ae5a4SJacob Faibussowitsch           break;
5949d71ae5a4SJacob Faibussowitsch         default:
5950d71ae5a4SJacob Faibussowitsch           break;
5951412e9a14SMatthew G. Knepley         }
5952665f567fSMatthew G. Knepley       }
5953712fec58SPierre Jolivet       PetscCall(MPIU_Allreduce(&isCohesiveLocal, &isCohesive, 1, MPIU_BOOL, MPI_LOR, comm));
595407218a29SMatthew G. Knepley       if (isCohesive) {
595507218a29SMatthew G. Knepley         PetscCall(PetscDSCreate(PETSC_COMM_SELF, &dsIn));
595607218a29SMatthew G. Knepley         PetscCall(PetscDSSetCoordinateDimension(dsIn, dE));
595707218a29SMatthew G. Knepley       }
59585fedec97SMatthew G. Knepley       for (f = 0, nf = 0; f < Nf; ++f) {
59595fedec97SMatthew G. Knepley         if (label == dm->fields[f].label || !dm->fields[f].label) {
59605fedec97SMatthew G. Knepley           if (label == dm->fields[f].label) {
59619566063dSJacob Faibussowitsch             PetscCall(PetscDSSetDiscretization(ds, nf, NULL));
59629566063dSJacob Faibussowitsch             PetscCall(PetscDSSetCohesive(ds, nf, isCohesive));
596307218a29SMatthew G. Knepley             if (dsIn) {
596407218a29SMatthew G. Knepley               PetscCall(PetscDSSetDiscretization(dsIn, nf, NULL));
596507218a29SMatthew G. Knepley               PetscCall(PetscDSSetCohesive(dsIn, nf, isCohesive));
596607218a29SMatthew G. Knepley             }
59675fedec97SMatthew G. Knepley           }
59685fedec97SMatthew G. Knepley           ++nf;
59695fedec97SMatthew G. Knepley         }
59705fedec97SMatthew G. Knepley       }
5971e5e52638SMatthew G. Knepley     }
597207218a29SMatthew G. Knepley     PetscCall(DMSetRegionDS(dm, label, fields, ds, dsIn));
597307218a29SMatthew G. Knepley     PetscCall(ISDestroy(&fields));
59749566063dSJacob Faibussowitsch     PetscCall(PetscDSDestroy(&ds));
597507218a29SMatthew G. Knepley     PetscCall(PetscDSDestroy(&dsIn));
5976e5e52638SMatthew G. Knepley   }
59779566063dSJacob Faibussowitsch   PetscCall(PetscFree(labelSet));
5978e5e52638SMatthew G. Knepley   /* Set fields in DSes */
5979083401c6SMatthew G. Knepley   for (s = 0; s < dm->Nds; ++s) {
5980083401c6SMatthew G. Knepley     PetscDS         ds     = dm->probs[s].ds;
598107218a29SMatthew G. Knepley     PetscDS         dsIn   = dm->probs[s].dsIn;
5982083401c6SMatthew G. Knepley     IS              fields = dm->probs[s].fields;
5983083401c6SMatthew G. Knepley     const PetscInt *fld;
59845fedec97SMatthew G. Knepley     PetscInt        nf, dsnf;
59855fedec97SMatthew G. Knepley     PetscBool       isCohesive;
5986e5e52638SMatthew G. Knepley 
59879566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsnf));
59889566063dSJacob Faibussowitsch     PetscCall(PetscDSIsCohesive(ds, &isCohesive));
59899566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(fields, &nf));
59909566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fields, &fld));
5991083401c6SMatthew G. Knepley     for (f = 0; f < nf; ++f) {
5992083401c6SMatthew G. Knepley       PetscObject  disc = dm->fields[fld[f]].disc;
59935fedec97SMatthew G. Knepley       PetscBool    isCohesiveField;
5994e5e52638SMatthew G. Knepley       PetscClassId id;
5995e5e52638SMatthew G. Knepley 
59965fedec97SMatthew G. Knepley       /* Handle DS with no fields */
59979566063dSJacob Faibussowitsch       if (dsnf) PetscCall(PetscDSGetCohesive(ds, f, &isCohesiveField));
59985fedec97SMatthew G. Knepley       /* If this is a cohesive cell, then regular fields need the lower dimensional discretization */
599907218a29SMatthew G. Knepley       if (isCohesive) {
600007218a29SMatthew G. Knepley         if (!isCohesiveField) {
600107218a29SMatthew G. Knepley           PetscObject bdDisc;
600207218a29SMatthew G. Knepley 
600307218a29SMatthew G. Knepley           PetscCall(PetscFEGetHeightSubspace((PetscFE)disc, 1, (PetscFE *)&bdDisc));
600407218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(ds, f, bdDisc));
600507218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(dsIn, f, disc));
600607218a29SMatthew G. Knepley         } else {
60079566063dSJacob Faibussowitsch           PetscCall(PetscDSSetDiscretization(ds, f, disc));
600807218a29SMatthew G. Knepley           PetscCall(PetscDSSetDiscretization(dsIn, f, disc));
600907218a29SMatthew G. Knepley         }
601007218a29SMatthew G. Knepley       } else {
601107218a29SMatthew G. Knepley         PetscCall(PetscDSSetDiscretization(ds, f, disc));
601207218a29SMatthew G. Knepley       }
6013083401c6SMatthew G. Knepley       /* We allow people to have placeholder fields and construct the Section by hand */
60149566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(disc, &id));
6015e5e52638SMatthew G. Knepley       if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE;
6016e5e52638SMatthew G. Knepley     }
60179566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fields, &fld));
6018e5e52638SMatthew G. Knepley   }
6019f9244615SMatthew G. Knepley   /* Allow k-jet tabulation */
60209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)dm)->prefix, "-dm_ds_jet_degree", &k, &flg));
6021f9244615SMatthew G. Knepley   if (flg) {
60223b4aee56SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
60233b4aee56SMatthew G. Knepley       PetscDS  ds   = dm->probs[s].ds;
602407218a29SMatthew G. Knepley       PetscDS  dsIn = dm->probs[s].dsIn;
60253b4aee56SMatthew G. Knepley       PetscInt Nf, f;
60263b4aee56SMatthew G. Knepley 
60279566063dSJacob Faibussowitsch       PetscCall(PetscDSGetNumFields(ds, &Nf));
602807218a29SMatthew G. Knepley       for (f = 0; f < Nf; ++f) {
602907218a29SMatthew G. Knepley         PetscCall(PetscDSSetJetDegree(ds, f, k));
603007218a29SMatthew G. Knepley         if (dsIn) PetscCall(PetscDSSetJetDegree(dsIn, f, k));
603107218a29SMatthew G. Knepley       }
60323b4aee56SMatthew G. Knepley     }
6033f9244615SMatthew G. Knepley   }
6034e5e52638SMatthew G. Knepley   /* Setup DSes */
6035e5e52638SMatthew G. Knepley   if (doSetup) {
603607218a29SMatthew G. Knepley     for (s = 0; s < dm->Nds; ++s) {
6037cf1363e4SMatthew G. Knepley       if (dm->setfromoptionscalled) {
6038cf1363e4SMatthew G. Knepley         PetscCall(PetscDSSetFromOptions(dm->probs[s].ds));
6039cf1363e4SMatthew G. Knepley         if (dm->probs[s].dsIn) PetscCall(PetscDSSetFromOptions(dm->probs[s].dsIn));
6040cf1363e4SMatthew G. Knepley       }
604107218a29SMatthew G. Knepley       PetscCall(PetscDSSetUp(dm->probs[s].ds));
604207218a29SMatthew G. Knepley       if (dm->probs[s].dsIn) PetscCall(PetscDSSetUp(dm->probs[s].dsIn));
604307218a29SMatthew G. Knepley     }
6044e5e52638SMatthew G. Knepley   }
60453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6046e5e52638SMatthew G. Knepley }
6047e5e52638SMatthew G. Knepley 
6048e5e52638SMatthew G. Knepley /*@
6049d2b2dc1eSMatthew G. Knepley   DMUseTensorOrder - Use a tensor product closure ordering for the default section
6050d2b2dc1eSMatthew G. Knepley 
6051d2b2dc1eSMatthew G. Knepley   Input Parameters:
6052d2b2dc1eSMatthew G. Knepley + dm     - The DM
6053d2b2dc1eSMatthew G. Knepley - tensor - Flag for tensor order
6054d2b2dc1eSMatthew G. Knepley 
6055d2b2dc1eSMatthew G. Knepley   Level: developer
6056d2b2dc1eSMatthew G. Knepley 
6057d2b2dc1eSMatthew G. Knepley .seealso: `DMPlexSetClosurePermutationTensor()`, `PetscSectionResetClosurePermutation()`
6058d2b2dc1eSMatthew G. Knepley @*/
6059d2b2dc1eSMatthew G. Knepley PetscErrorCode DMUseTensorOrder(DM dm, PetscBool tensor)
6060d2b2dc1eSMatthew G. Knepley {
6061d2b2dc1eSMatthew G. Knepley   PetscInt  Nf;
6062d2b2dc1eSMatthew G. Knepley   PetscBool reorder = PETSC_TRUE, isPlex;
6063d2b2dc1eSMatthew G. Knepley 
6064d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
6065d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isPlex));
6066d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetNumFields(dm, &Nf));
6067d2b2dc1eSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
6068d2b2dc1eSMatthew G. Knepley     PetscObject  obj;
6069d2b2dc1eSMatthew G. Knepley     PetscClassId id;
6070d2b2dc1eSMatthew G. Knepley 
6071d2b2dc1eSMatthew G. Knepley     PetscCall(DMGetField(dm, f, NULL, &obj));
6072d2b2dc1eSMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
6073d2b2dc1eSMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
6074d2b2dc1eSMatthew G. Knepley       PetscSpace sp;
6075d2b2dc1eSMatthew G. Knepley       PetscBool  tensor;
6076d2b2dc1eSMatthew G. Knepley 
6077d2b2dc1eSMatthew G. Knepley       PetscCall(PetscFEGetBasisSpace((PetscFE)obj, &sp));
6078d2b2dc1eSMatthew G. Knepley       PetscCall(PetscSpacePolynomialGetTensor(sp, &tensor));
6079d2b2dc1eSMatthew G. Knepley       reorder = reorder && tensor ? PETSC_TRUE : PETSC_FALSE;
6080d2b2dc1eSMatthew G. Knepley     } else reorder = PETSC_FALSE;
6081d2b2dc1eSMatthew G. Knepley   }
6082d2b2dc1eSMatthew G. Knepley   if (tensor) {
6083d2b2dc1eSMatthew G. Knepley     if (reorder && isPlex) PetscCall(DMPlexSetClosurePermutationTensor(dm, PETSC_DETERMINE, NULL));
6084d2b2dc1eSMatthew G. Knepley   } else {
6085d2b2dc1eSMatthew G. Knepley     PetscSection s;
6086d2b2dc1eSMatthew G. Knepley 
6087d2b2dc1eSMatthew G. Knepley     PetscCall(DMGetLocalSection(dm, &s));
6088d2b2dc1eSMatthew G. Knepley     if (s) PetscCall(PetscSectionResetClosurePermutation(s));
6089d2b2dc1eSMatthew G. Knepley   }
6090d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6091d2b2dc1eSMatthew G. Knepley }
6092d2b2dc1eSMatthew G. Knepley 
6093d2b2dc1eSMatthew G. Knepley /*@
6094bb7acecfSBarry Smith   DMComputeExactSolution - Compute the exact solution for a given `DM`, using the `PetscDS` information.
60957f96f943SMatthew G. Knepley 
609620f4b53cSBarry Smith   Collective
6097f2cacb80SMatthew G. Knepley 
60987f96f943SMatthew G. Knepley   Input Parameters:
6099bb7acecfSBarry Smith + dm   - The `DM`
61007f96f943SMatthew G. Knepley - time - The time
61017f96f943SMatthew G. Knepley 
61027f96f943SMatthew G. Knepley   Output Parameters:
610320f4b53cSBarry Smith + u   - The vector will be filled with exact solution values, or `NULL`
610420f4b53cSBarry Smith - u_t - The vector will be filled with the time derivative of exact solution values, or `NULL`
610520f4b53cSBarry Smith 
610620f4b53cSBarry Smith   Level: developer
61077f96f943SMatthew G. Knepley 
6108bb7acecfSBarry Smith   Note:
6109bb7acecfSBarry Smith   The user must call `PetscDSSetExactSolution()` before using this routine
61107f96f943SMatthew G. Knepley 
61111cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscDSSetExactSolution()`
61127f96f943SMatthew G. Knepley @*/
6113d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t)
6114d71ae5a4SJacob Faibussowitsch {
61157f96f943SMatthew G. Knepley   PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx);
61167f96f943SMatthew G. Knepley   void   **ectxs;
6117f60fa741SMatthew G. Knepley   Vec      locu, locu_t;
61187f96f943SMatthew G. Knepley   PetscInt Nf, Nds, s;
61197f96f943SMatthew G. Knepley 
61207f96f943SMatthew G. Knepley   PetscFunctionBegin;
6121f2cacb80SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6122f60fa741SMatthew G. Knepley   if (u) {
6123f60fa741SMatthew G. Knepley     PetscValidHeaderSpecific(u, VEC_CLASSID, 3);
6124f60fa741SMatthew G. Knepley     PetscCall(DMGetLocalVector(dm, &locu));
6125f60fa741SMatthew G. Knepley     PetscCall(VecSet(locu, 0.));
6126f60fa741SMatthew G. Knepley   }
6127f60fa741SMatthew G. Knepley   if (u_t) {
6128f60fa741SMatthew G. Knepley     PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4);
6129f60fa741SMatthew G. Knepley     PetscCall(DMGetLocalVector(dm, &locu_t));
6130f60fa741SMatthew G. Knepley     PetscCall(VecSet(locu_t, 0.));
6131f60fa741SMatthew G. Knepley   }
61329566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
61339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(Nf, &exacts, Nf, &ectxs));
61349566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
61357f96f943SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
61367f96f943SMatthew G. Knepley     PetscDS         ds;
61377f96f943SMatthew G. Knepley     DMLabel         label;
61387f96f943SMatthew G. Knepley     IS              fieldIS;
61397f96f943SMatthew G. Knepley     const PetscInt *fields, id = 1;
61407f96f943SMatthew G. Knepley     PetscInt        dsNf, f;
61417f96f943SMatthew G. Knepley 
614207218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds, NULL));
61439566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
61449566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(fieldIS, &fields));
61459566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(exacts, Nf));
61469566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(ectxs, Nf));
6147f2cacb80SMatthew G. Knepley     if (u) {
6148f60fa741SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) PetscCall(PetscDSGetExactSolution(ds, fields[f], &exacts[fields[f]], &ectxs[fields[f]]));
6149f60fa741SMatthew G. Knepley       if (label) PetscCall(DMProjectFunctionLabelLocal(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, locu));
6150f60fa741SMatthew G. Knepley       else PetscCall(DMProjectFunctionLocal(dm, time, exacts, ectxs, INSERT_ALL_VALUES, locu));
61517f96f943SMatthew G. Knepley     }
6152f2cacb80SMatthew G. Knepley     if (u_t) {
61539566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(exacts, Nf));
61549566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(ectxs, Nf));
6155f60fa741SMatthew G. Knepley       for (f = 0; f < dsNf; ++f) PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, fields[f], &exacts[fields[f]], &ectxs[fields[f]]));
6156f60fa741SMatthew G. Knepley       if (label) PetscCall(DMProjectFunctionLabelLocal(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, locu_t));
6157f60fa741SMatthew G. Knepley       else PetscCall(DMProjectFunctionLocal(dm, time, exacts, ectxs, INSERT_ALL_VALUES, locu_t));
6158f2cacb80SMatthew G. Knepley     }
61599566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(fieldIS, &fields));
6160f2cacb80SMatthew G. Knepley   }
6161f2cacb80SMatthew G. Knepley   if (u) {
61629566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution"));
61639566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u, "exact_"));
6164f2cacb80SMatthew G. Knepley   }
6165f2cacb80SMatthew G. Knepley   if (u_t) {
61669566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)u, "Exact Solution Time Derivative"));
61679566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)u_t, "exact_t_"));
6168f2cacb80SMatthew G. Knepley   }
61699566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exacts, ectxs));
6170f60fa741SMatthew G. Knepley   if (u) {
6171f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(dm, locu, INSERT_ALL_VALUES, u));
6172f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(dm, locu, INSERT_ALL_VALUES, u));
6173f60fa741SMatthew G. Knepley     PetscCall(DMRestoreLocalVector(dm, &locu));
6174f60fa741SMatthew G. Knepley   }
6175f60fa741SMatthew G. Knepley   if (u_t) {
6176f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(dm, locu_t, INSERT_ALL_VALUES, u_t));
6177f60fa741SMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(dm, locu_t, INSERT_ALL_VALUES, u_t));
6178f60fa741SMatthew G. Knepley     PetscCall(DMRestoreLocalVector(dm, &locu_t));
6179f60fa741SMatthew G. Knepley   }
61803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61817f96f943SMatthew G. Knepley }
61827f96f943SMatthew G. Knepley 
618307218a29SMatthew G. Knepley static PetscErrorCode DMTransferDS_Internal(DM dm, DMLabel label, IS fields, PetscDS ds, PetscDS dsIn)
6184d71ae5a4SJacob Faibussowitsch {
618507218a29SMatthew G. Knepley   PetscDS dsNew, dsInNew = NULL;
618645480ffeSMatthew G. Knepley 
618745480ffeSMatthew G. Knepley   PetscFunctionBegin;
61889566063dSJacob Faibussowitsch   PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)ds), &dsNew));
618907218a29SMatthew G. Knepley   PetscCall(PetscDSCopy(ds, dm, dsNew));
619007218a29SMatthew G. Knepley   if (dsIn) {
619107218a29SMatthew G. Knepley     PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)dsIn), &dsInNew));
619207218a29SMatthew G. Knepley     PetscCall(PetscDSCopy(dsIn, dm, dsInNew));
619345480ffeSMatthew G. Knepley   }
619407218a29SMatthew G. Knepley   PetscCall(DMSetRegionDS(dm, label, fields, dsNew, dsInNew));
61959566063dSJacob Faibussowitsch   PetscCall(PetscDSDestroy(&dsNew));
619607218a29SMatthew G. Knepley   PetscCall(PetscDSDestroy(&dsInNew));
61973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
619845480ffeSMatthew G. Knepley }
619945480ffeSMatthew G. Knepley 
62007f96f943SMatthew G. Knepley /*@
6201bb7acecfSBarry Smith   DMCopyDS - Copy the discrete systems for the `DM` into another `DM`
6202e5e52638SMatthew G. Knepley 
620320f4b53cSBarry Smith   Collective
6204e5e52638SMatthew G. Knepley 
6205e5e52638SMatthew G. Knepley   Input Parameter:
6206bb7acecfSBarry Smith . dm - The `DM`
6207e5e52638SMatthew G. Knepley 
6208e5e52638SMatthew G. Knepley   Output Parameter:
6209bb7acecfSBarry Smith . newdm - The `DM`
6210e5e52638SMatthew G. Knepley 
6211e5e52638SMatthew G. Knepley   Level: advanced
6212e5e52638SMatthew G. Knepley 
62131cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCopyFields()`, `DMAddField()`, `DMGetDS()`, `DMGetCellDS()`, `DMGetRegionDS()`, `DMSetRegionDS()`
6214e5e52638SMatthew G. Knepley @*/
6215d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDS(DM dm, DM newdm)
6216d71ae5a4SJacob Faibussowitsch {
6217e5e52638SMatthew G. Knepley   PetscInt Nds, s;
6218e5e52638SMatthew G. Knepley 
6219e5e52638SMatthew G. Knepley   PetscFunctionBegin;
62203ba16761SJacob Faibussowitsch   if (dm == newdm) PetscFunctionReturn(PETSC_SUCCESS);
62219566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
62229566063dSJacob Faibussowitsch   PetscCall(DMClearDS(newdm));
6223e5e52638SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
6224e5e52638SMatthew G. Knepley     DMLabel  label;
6225b3cf3223SMatthew G. Knepley     IS       fields;
622607218a29SMatthew G. Knepley     PetscDS  ds, dsIn, newds;
6227783e2ec8SMatthew G. Knepley     PetscInt Nbd, bd;
6228e5e52638SMatthew G. Knepley 
622907218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fields, &ds, &dsIn));
6230b8025e53SMatthew G. Knepley     /* TODO: We need to change all keys from labels in the old DM to labels in the new DM */
623107218a29SMatthew G. Knepley     PetscCall(DMTransferDS_Internal(newdm, label, fields, ds, dsIn));
6232d5b43468SJose E. Roman     /* Complete new labels in the new DS */
623307218a29SMatthew G. Knepley     PetscCall(DMGetRegionDS(newdm, label, NULL, &newds, NULL));
62349566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumBoundary(newds, &Nbd));
6235783e2ec8SMatthew G. Knepley     for (bd = 0; bd < Nbd; ++bd) {
6236b8025e53SMatthew G. Knepley       PetscWeakForm wf;
623745480ffeSMatthew G. Knepley       DMLabel       label;
6238783e2ec8SMatthew G. Knepley       PetscInt      field;
6239783e2ec8SMatthew G. Knepley 
62409566063dSJacob Faibussowitsch       PetscCall(PetscDSGetBoundary(newds, bd, &wf, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL));
62419566063dSJacob Faibussowitsch       PetscCall(PetscWeakFormReplaceLabel(wf, label));
6242783e2ec8SMatthew G. Knepley     }
6243e5e52638SMatthew G. Knepley   }
6244799db056SMatthew G. Knepley   PetscCall(DMCompleteBCLabels_Internal(newdm));
62453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6246e5e52638SMatthew G. Knepley }
6247e5e52638SMatthew G. Knepley 
6248e5e52638SMatthew G. Knepley /*@
6249bb7acecfSBarry Smith   DMCopyDisc - Copy the fields and discrete systems for the `DM` into another `DM`
6250e5e52638SMatthew G. Knepley 
625120f4b53cSBarry Smith   Collective
6252e5e52638SMatthew G. Knepley 
6253e5e52638SMatthew G. Knepley   Input Parameter:
6254bb7acecfSBarry Smith . dm - The `DM`
6255e5e52638SMatthew G. Knepley 
6256e5e52638SMatthew G. Knepley   Output Parameter:
6257bb7acecfSBarry Smith . newdm - The `DM`
6258e5e52638SMatthew G. Knepley 
6259e5e52638SMatthew G. Knepley   Level: advanced
6260e5e52638SMatthew G. Knepley 
626160225df5SJacob Faibussowitsch   Developer Notes:
6262bb7acecfSBarry Smith   Really ugly name, nothing in PETSc is called a `Disc` plus it is an ugly abbreviation
6263bb7acecfSBarry Smith 
62641cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCopyFields()`, `DMCopyDS()`
6265e5e52638SMatthew G. Knepley @*/
6266d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyDisc(DM dm, DM newdm)
6267d71ae5a4SJacob Faibussowitsch {
6268e5e52638SMatthew G. Knepley   PetscFunctionBegin;
62699566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, newdm));
62709566063dSJacob Faibussowitsch   PetscCall(DMCopyDS(dm, newdm));
62713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6272e5e52638SMatthew G. Knepley }
6273e5e52638SMatthew G. Knepley 
6274c73cfb54SMatthew G. Knepley /*@
6275bb7acecfSBarry Smith   DMGetDimension - Return the topological dimension of the `DM`
6276c73cfb54SMatthew G. Knepley 
627720f4b53cSBarry Smith   Not Collective
6278c73cfb54SMatthew G. Knepley 
6279c73cfb54SMatthew G. Knepley   Input Parameter:
6280bb7acecfSBarry Smith . dm - The `DM`
6281c73cfb54SMatthew G. Knepley 
6282c73cfb54SMatthew G. Knepley   Output Parameter:
6283c73cfb54SMatthew G. Knepley . dim - The topological dimension
6284c73cfb54SMatthew G. Knepley 
6285c73cfb54SMatthew G. Knepley   Level: beginner
6286c73cfb54SMatthew G. Knepley 
62871cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetDimension()`, `DMCreate()`
6288c73cfb54SMatthew G. Knepley @*/
6289d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimension(DM dm, PetscInt *dim)
6290d71ae5a4SJacob Faibussowitsch {
6291c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6292c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62934f572ea9SToby Isaac   PetscAssertPointer(dim, 2);
6294c73cfb54SMatthew G. Knepley   *dim = dm->dim;
62953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6296c73cfb54SMatthew G. Knepley }
6297c73cfb54SMatthew G. Knepley 
6298c73cfb54SMatthew G. Knepley /*@
6299bb7acecfSBarry Smith   DMSetDimension - Set the topological dimension of the `DM`
6300c73cfb54SMatthew G. Knepley 
630120f4b53cSBarry Smith   Collective
6302c73cfb54SMatthew G. Knepley 
6303c73cfb54SMatthew G. Knepley   Input Parameters:
6304bb7acecfSBarry Smith + dm  - The `DM`
6305c73cfb54SMatthew G. Knepley - dim - The topological dimension
6306c73cfb54SMatthew G. Knepley 
6307c73cfb54SMatthew G. Knepley   Level: beginner
6308c73cfb54SMatthew G. Knepley 
63091cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetDimension()`, `DMCreate()`
6310c73cfb54SMatthew G. Knepley @*/
6311d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetDimension(DM dm, PetscInt dim)
6312d71ae5a4SJacob Faibussowitsch {
6313e5e52638SMatthew G. Knepley   PetscDS  ds;
631445480ffeSMatthew G. Knepley   PetscInt Nds, n;
6315f17e8794SMatthew G. Knepley 
6316c73cfb54SMatthew G. Knepley   PetscFunctionBegin;
6317c73cfb54SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6318c73cfb54SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6319c73cfb54SMatthew G. Knepley   dm->dim = dim;
6320d17bd122SMatthew G. Knepley   if (dm->dim >= 0) {
63219566063dSJacob Faibussowitsch     PetscCall(DMGetNumDS(dm, &Nds));
632245480ffeSMatthew G. Knepley     for (n = 0; n < Nds; ++n) {
632307218a29SMatthew G. Knepley       PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds, NULL));
63249566063dSJacob Faibussowitsch       if (ds->dimEmbed < 0) PetscCall(PetscDSSetCoordinateDimension(ds, dim));
632545480ffeSMatthew G. Knepley     }
6326d17bd122SMatthew G. Knepley   }
63273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6328c73cfb54SMatthew G. Knepley }
6329c73cfb54SMatthew G. Knepley 
6330793f3fe5SMatthew G. Knepley /*@
6331793f3fe5SMatthew G. Knepley   DMGetDimPoints - Get the half-open interval for all points of a given dimension
6332793f3fe5SMatthew G. Knepley 
633320f4b53cSBarry Smith   Collective
6334793f3fe5SMatthew G. Knepley 
6335793f3fe5SMatthew G. Knepley   Input Parameters:
6336bb7acecfSBarry Smith + dm  - the `DM`
6337793f3fe5SMatthew G. Knepley - dim - the dimension
6338793f3fe5SMatthew G. Knepley 
6339793f3fe5SMatthew G. Knepley   Output Parameters:
6340793f3fe5SMatthew G. Knepley + pStart - The first point of the given dimension
6341aa049354SPatrick Sanan - pEnd   - The first point following points of the given dimension
6342793f3fe5SMatthew G. Knepley 
634320f4b53cSBarry Smith   Level: intermediate
634420f4b53cSBarry Smith 
6345793f3fe5SMatthew G. Knepley   Note:
6346793f3fe5SMatthew G. Knepley   The points are vertices in the Hasse diagram encoding the topology. This is explained in
6347a8d69d7bSBarry Smith   https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme,
6348793f3fe5SMatthew G. Knepley   then the interval is empty.
6349793f3fe5SMatthew G. Knepley 
63501cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
6351793f3fe5SMatthew G. Knepley @*/
6352d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
6353d71ae5a4SJacob Faibussowitsch {
6354793f3fe5SMatthew G. Knepley   PetscInt d;
6355793f3fe5SMatthew G. Knepley 
6356793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
6357793f3fe5SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63589566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &d));
63597a8be351SBarry Smith   PetscCheck((dim >= 0) && (dim <= d), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %" PetscInt_FMT, dim);
6360dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, getdimpoints, dim, pStart, pEnd);
63613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6362793f3fe5SMatthew G. Knepley }
6363793f3fe5SMatthew G. Knepley 
63646636e97aSMatthew G Knepley /*@
6365bb7acecfSBarry Smith   DMGetOutputDM - Retrieve the `DM` associated with the layout for output
6366f4d763aaSMatthew G. Knepley 
636720f4b53cSBarry Smith   Collective
63688f700142SStefano Zampini 
6369f4d763aaSMatthew G. Knepley   Input Parameter:
6370bb7acecfSBarry Smith . dm - The original `DM`
6371f4d763aaSMatthew G. Knepley 
6372f4d763aaSMatthew G. Knepley   Output Parameter:
6373bb7acecfSBarry Smith . odm - The `DM` which provides the layout for output
6374f4d763aaSMatthew G. Knepley 
6375f4d763aaSMatthew G. Knepley   Level: intermediate
6376f4d763aaSMatthew G. Knepley 
6377bb7acecfSBarry Smith   Note:
6378bb7acecfSBarry Smith   In some situations the vector obtained with `DMCreateGlobalVector()` excludes points for degrees of freedom that are associated with fixed (Dirichelet) boundary
6379bb7acecfSBarry 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
6380bb7acecfSBarry Smith   locations for those dof so that they can be output to a file or other viewer along with the unconstrained dof.
6381bb7acecfSBarry Smith 
63821cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`, `DMGetGlobalSection()`, `DMCreateGlobalVector()`, `PetscSectionHasConstraints()`, `DMSetGlobalSection()`
6383f4d763aaSMatthew G. Knepley @*/
6384d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputDM(DM dm, DM *odm)
6385d71ae5a4SJacob Faibussowitsch {
6386c26acbdeSMatthew G. Knepley   PetscSection section;
63872d4e4a49SMatthew G. Knepley   PetscBool    hasConstraints, ghasConstraints;
638814f150ffSMatthew G. Knepley 
638914f150ffSMatthew G. Knepley   PetscFunctionBegin;
639014f150ffSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63914f572ea9SToby Isaac   PetscAssertPointer(odm, 2);
63929566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
63939566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
6394712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
63952d4e4a49SMatthew G. Knepley   if (!ghasConstraints) {
6396c26acbdeSMatthew G. Knepley     *odm = dm;
63973ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6398c26acbdeSMatthew G. Knepley   }
639914f150ffSMatthew G. Knepley   if (!dm->dmBC) {
6400c26acbdeSMatthew G. Knepley     PetscSection newSection, gsection;
640114f150ffSMatthew G. Knepley     PetscSF      sf;
640214f150ffSMatthew G. Knepley 
64039566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &dm->dmBC));
64049566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dm, dm->dmBC));
64059566063dSJacob Faibussowitsch     PetscCall(PetscSectionClone(section, &newSection));
64069566063dSJacob Faibussowitsch     PetscCall(DMSetLocalSection(dm->dmBC, newSection));
64079566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&newSection));
64089566063dSJacob Faibussowitsch     PetscCall(DMGetPointSF(dm->dmBC, &sf));
64099566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
64109566063dSJacob Faibussowitsch     PetscCall(DMSetGlobalSection(dm->dmBC, gsection));
64119566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&gsection));
641214f150ffSMatthew G. Knepley   }
641314f150ffSMatthew G. Knepley   *odm = dm->dmBC;
64143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
641514f150ffSMatthew G. Knepley }
6416f4d763aaSMatthew G. Knepley 
6417f4d763aaSMatthew G. Knepley /*@
6418cdb7a50dSMatthew G. Knepley   DMGetOutputSequenceNumber - Retrieve the sequence number/value for output
6419f4d763aaSMatthew G. Knepley 
6420f4d763aaSMatthew G. Knepley   Input Parameter:
6421bb7acecfSBarry Smith . dm - The original `DM`
6422f4d763aaSMatthew G. Knepley 
6423cdb7a50dSMatthew G. Knepley   Output Parameters:
6424cdb7a50dSMatthew G. Knepley + num - The output sequence number
6425cdb7a50dSMatthew G. Knepley - val - The output sequence value
6426f4d763aaSMatthew G. Knepley 
6427f4d763aaSMatthew G. Knepley   Level: intermediate
6428f4d763aaSMatthew G. Knepley 
6429bb7acecfSBarry Smith   Note:
6430bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6431bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6432bb7acecfSBarry Smith 
643360225df5SJacob Faibussowitsch   Developer Notes:
6434bb7acecfSBarry Smith   The `DM` serves as a convenient place to store the current iteration value. The iteration is not
6435bb7acecfSBarry Smith   not directly related to the `DM`.
6436f4d763aaSMatthew G. Knepley 
64371cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`
6438f4d763aaSMatthew G. Knepley @*/
6439d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val)
6440d71ae5a4SJacob Faibussowitsch {
6441f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6442f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64439371c9d4SSatish Balay   if (num) {
64444f572ea9SToby Isaac     PetscAssertPointer(num, 2);
64459371c9d4SSatish Balay     *num = dm->outputSequenceNum;
64469371c9d4SSatish Balay   }
64479371c9d4SSatish Balay   if (val) {
64484f572ea9SToby Isaac     PetscAssertPointer(val, 3);
64499371c9d4SSatish Balay     *val = dm->outputSequenceVal;
64509371c9d4SSatish Balay   }
64513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6452f4d763aaSMatthew G. Knepley }
6453f4d763aaSMatthew G. Knepley 
6454f4d763aaSMatthew G. Knepley /*@
6455cdb7a50dSMatthew G. Knepley   DMSetOutputSequenceNumber - Set the sequence number/value for output
6456f4d763aaSMatthew G. Knepley 
6457f4d763aaSMatthew G. Knepley   Input Parameters:
6458bb7acecfSBarry Smith + dm  - The original `DM`
6459cdb7a50dSMatthew G. Knepley . num - The output sequence number
6460cdb7a50dSMatthew G. Knepley - val - The output sequence value
6461f4d763aaSMatthew G. Knepley 
6462f4d763aaSMatthew G. Knepley   Level: intermediate
6463f4d763aaSMatthew G. Knepley 
6464bb7acecfSBarry Smith   Note:
6465bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6466bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6467f4d763aaSMatthew G. Knepley 
64681cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `VecView()`
6469f4d763aaSMatthew G. Knepley @*/
6470d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val)
6471d71ae5a4SJacob Faibussowitsch {
6472f4d763aaSMatthew G. Knepley   PetscFunctionBegin;
6473f4d763aaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6474f4d763aaSMatthew G. Knepley   dm->outputSequenceNum = num;
6475cdb7a50dSMatthew G. Knepley   dm->outputSequenceVal = val;
64763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6477cdb7a50dSMatthew G. Knepley }
6478cdb7a50dSMatthew G. Knepley 
6479cdb7a50dSMatthew G. Knepley /*@C
6480bb7acecfSBarry Smith   DMOutputSequenceLoad - Retrieve the sequence value from a `PetscViewer`
6481cdb7a50dSMatthew G. Knepley 
6482cdb7a50dSMatthew G. Knepley   Input Parameters:
6483bb7acecfSBarry Smith + dm     - The original `DM`
6484a4e35b19SJacob Faibussowitsch . viewer - The viewer to get it from
6485cdb7a50dSMatthew G. Knepley . name   - The sequence name
6486cdb7a50dSMatthew G. Knepley - num    - The output sequence number
6487cdb7a50dSMatthew G. Knepley 
6488cdb7a50dSMatthew G. Knepley   Output Parameter:
6489cdb7a50dSMatthew G. Knepley . val - The output sequence value
6490cdb7a50dSMatthew G. Knepley 
6491cdb7a50dSMatthew G. Knepley   Level: intermediate
6492cdb7a50dSMatthew G. Knepley 
6493bb7acecfSBarry Smith   Note:
6494bb7acecfSBarry Smith   This is intended for output that should appear in sequence, for instance
6495bb7acecfSBarry Smith   a set of timesteps in an `PETSCVIEWERHDF5` file, or a set of realizations of a stochastic system.
6496bb7acecfSBarry Smith 
649760225df5SJacob Faibussowitsch   Developer Notes:
6498bb7acecfSBarry Smith   It is unclear at the user API level why a `DM` is needed as input
6499cdb7a50dSMatthew G. Knepley 
65001cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetOutputSequenceNumber()`, `DMSetOutputSequenceNumber()`, `VecView()`
6501cdb7a50dSMatthew G. Knepley @*/
6502d71ae5a4SJacob Faibussowitsch PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val)
6503d71ae5a4SJacob Faibussowitsch {
6504cdb7a50dSMatthew G. Knepley   PetscBool ishdf5;
6505cdb7a50dSMatthew G. Knepley 
6506cdb7a50dSMatthew G. Knepley   PetscFunctionBegin;
6507cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6508cdb7a50dSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
65094f572ea9SToby Isaac   PetscAssertPointer(val, 5);
65109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6511cdb7a50dSMatthew G. Knepley   if (ishdf5) {
6512cdb7a50dSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6513cdb7a50dSMatthew G. Knepley     PetscScalar value;
6514cdb7a50dSMatthew G. Knepley 
65159566063dSJacob Faibussowitsch     PetscCall(DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer));
65164aeb217fSMatthew G. Knepley     *val = PetscRealPart(value);
6517cdb7a50dSMatthew G. Knepley #endif
6518cdb7a50dSMatthew G. Knepley   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()");
65193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6520f4d763aaSMatthew G. Knepley }
65218e4ac7eaSMatthew G. Knepley 
65228e4ac7eaSMatthew G. Knepley /*@
6523bb7acecfSBarry Smith   DMGetUseNatural - Get the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
65248e4ac7eaSMatthew G. Knepley 
652520f4b53cSBarry Smith   Not Collective
65268e4ac7eaSMatthew G. Knepley 
65278e4ac7eaSMatthew G. Knepley   Input Parameter:
6528bb7acecfSBarry Smith . dm - The `DM`
65298e4ac7eaSMatthew G. Knepley 
65308e4ac7eaSMatthew G. Knepley   Output Parameter:
6531bb7acecfSBarry Smith . useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
65328e4ac7eaSMatthew G. Knepley 
65338e4ac7eaSMatthew G. Knepley   Level: beginner
65348e4ac7eaSMatthew G. Knepley 
65351cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetUseNatural()`, `DMCreate()`
65368e4ac7eaSMatthew G. Knepley @*/
6537d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural)
6538d71ae5a4SJacob Faibussowitsch {
65398e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
65408e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65414f572ea9SToby Isaac   PetscAssertPointer(useNatural, 2);
65428e4ac7eaSMatthew G. Knepley   *useNatural = dm->useNatural;
65433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65448e4ac7eaSMatthew G. Knepley }
65458e4ac7eaSMatthew G. Knepley 
65468e4ac7eaSMatthew G. Knepley /*@
6547bb7acecfSBarry Smith   DMSetUseNatural - Set the flag for creating a mapping to the natural order when a `DM` is (re)distributed in parallel
65488e4ac7eaSMatthew G. Knepley 
654920f4b53cSBarry Smith   Collective
65508e4ac7eaSMatthew G. Knepley 
65518e4ac7eaSMatthew G. Knepley   Input Parameters:
6552bb7acecfSBarry Smith + dm         - The `DM`
6553bb7acecfSBarry Smith - useNatural - `PETSC_TRUE` to build the mapping to a natural order during distribution
65548e4ac7eaSMatthew G. Knepley 
6555bb7acecfSBarry Smith   Note:
6556bb7acecfSBarry Smith   This also causes the map to be build after `DMCreateSubDM()` and `DMCreateSuperDM()`
65575d3b26e6SMatthew G. Knepley 
65588e4ac7eaSMatthew G. Knepley   Level: beginner
65598e4ac7eaSMatthew G. Knepley 
65601cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetUseNatural()`, `DMCreate()`, `DMPlexDistribute()`, `DMCreateSubDM()`, `DMCreateSuperDM()`
65618e4ac7eaSMatthew G. Knepley @*/
6562d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural)
6563d71ae5a4SJacob Faibussowitsch {
65648e4ac7eaSMatthew G. Knepley   PetscFunctionBegin;
65658e4ac7eaSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65668833efb5SBlaise Bourdin   PetscValidLogicalCollectiveBool(dm, useNatural, 2);
65678e4ac7eaSMatthew G. Knepley   dm->useNatural = useNatural;
65683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65698e4ac7eaSMatthew G. Knepley }
6570c58f1c22SToby Isaac 
6571c58f1c22SToby Isaac /*@C
6572bb7acecfSBarry Smith   DMCreateLabel - Create a label of the given name if it does not already exist in the `DM`
6573c58f1c22SToby Isaac 
6574c58f1c22SToby Isaac   Not Collective
6575c58f1c22SToby Isaac 
6576c58f1c22SToby Isaac   Input Parameters:
6577bb7acecfSBarry Smith + dm   - The `DM` object
6578c58f1c22SToby Isaac - name - The label name
6579c58f1c22SToby Isaac 
6580c58f1c22SToby Isaac   Level: intermediate
6581c58f1c22SToby Isaac 
65821cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6583c58f1c22SToby Isaac @*/
6584d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabel(DM dm, const char name[])
6585d71ae5a4SJacob Faibussowitsch {
65865d80c0bfSVaclav Hapla   PetscBool flg;
65875d80c0bfSVaclav Hapla   DMLabel   label;
6588c58f1c22SToby Isaac 
6589c58f1c22SToby Isaac   PetscFunctionBegin;
6590c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
65914f572ea9SToby Isaac   PetscAssertPointer(name, 2);
65929566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
6593c58f1c22SToby Isaac   if (!flg) {
65949566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
65959566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
65969566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
6597c58f1c22SToby Isaac   }
65983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6599c58f1c22SToby Isaac }
6600c58f1c22SToby Isaac 
6601c58f1c22SToby Isaac /*@C
6602bb7acecfSBarry 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.
66030fdc7489SMatthew Knepley 
66040fdc7489SMatthew Knepley   Not Collective
66050fdc7489SMatthew Knepley 
66060fdc7489SMatthew Knepley   Input Parameters:
6607bb7acecfSBarry Smith + dm   - The `DM` object
66080fdc7489SMatthew Knepley . l    - The index for the label
66090fdc7489SMatthew Knepley - name - The label name
66100fdc7489SMatthew Knepley 
66110fdc7489SMatthew Knepley   Level: intermediate
66120fdc7489SMatthew Knepley 
66131cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMCreateLabel()`, `DMLabelCreate()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
66140fdc7489SMatthew Knepley @*/
6615d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[])
6616d71ae5a4SJacob Faibussowitsch {
66170fdc7489SMatthew Knepley   DMLabelLink orig, prev = NULL;
66180fdc7489SMatthew Knepley   DMLabel     label;
66190fdc7489SMatthew Knepley   PetscInt    Nl, m;
66200fdc7489SMatthew Knepley   PetscBool   flg, match;
66210fdc7489SMatthew Knepley   const char *lname;
66220fdc7489SMatthew Knepley 
66230fdc7489SMatthew Knepley   PetscFunctionBegin;
66240fdc7489SMatthew Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
66254f572ea9SToby Isaac   PetscAssertPointer(name, 3);
66269566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &flg));
66270fdc7489SMatthew Knepley   if (!flg) {
66289566063dSJacob Faibussowitsch     PetscCall(DMLabelCreate(PETSC_COMM_SELF, name, &label));
66299566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dm, label));
66309566063dSJacob Faibussowitsch     PetscCall(DMLabelDestroy(&label));
66310fdc7489SMatthew Knepley   }
66329566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
663363a3b9bcSJacob Faibussowitsch   PetscCheck(l < Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", l, Nl);
66340fdc7489SMatthew Knepley   for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) {
66359566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)orig->label, &lname));
66369566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &match));
66370fdc7489SMatthew Knepley     if (match) break;
66380fdc7489SMatthew Knepley   }
66393ba16761SJacob Faibussowitsch   if (m == l) PetscFunctionReturn(PETSC_SUCCESS);
66400fdc7489SMatthew Knepley   if (!m) dm->labels = orig->next;
66410fdc7489SMatthew Knepley   else prev->next = orig->next;
66420fdc7489SMatthew Knepley   if (!l) {
66430fdc7489SMatthew Knepley     orig->next = dm->labels;
66440fdc7489SMatthew Knepley     dm->labels = orig;
66450fdc7489SMatthew Knepley   } else {
66469371c9d4SSatish Balay     for (m = 0, prev = dm->labels; m < l - 1; ++m, prev = prev->next)
66479371c9d4SSatish Balay       ;
66480fdc7489SMatthew Knepley     orig->next = prev->next;
66490fdc7489SMatthew Knepley     prev->next = orig;
66500fdc7489SMatthew Knepley   }
66513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66520fdc7489SMatthew Knepley }
66530fdc7489SMatthew Knepley 
66540fdc7489SMatthew Knepley /*@C
6655bb7acecfSBarry Smith   DMGetLabelValue - Get the value in a `DMLabel` for the given point, with -1 as the default
6656c58f1c22SToby Isaac 
6657c58f1c22SToby Isaac   Not Collective
6658c58f1c22SToby Isaac 
6659c58f1c22SToby Isaac   Input Parameters:
6660bb7acecfSBarry Smith + dm    - The `DM` object
6661c58f1c22SToby Isaac . name  - The label name
6662c58f1c22SToby Isaac - point - The mesh point
6663c58f1c22SToby Isaac 
6664c58f1c22SToby Isaac   Output Parameter:
6665c58f1c22SToby Isaac . value - The label value for this point, or -1 if the point is not in the label
6666c58f1c22SToby Isaac 
6667c58f1c22SToby Isaac   Level: beginner
6668c58f1c22SToby Isaac 
66691cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6670c58f1c22SToby Isaac @*/
6671d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value)
6672d71ae5a4SJacob Faibussowitsch {
6673c58f1c22SToby Isaac   DMLabel label;
6674c58f1c22SToby Isaac 
6675c58f1c22SToby Isaac   PetscFunctionBegin;
6676c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
66774f572ea9SToby Isaac   PetscAssertPointer(name, 2);
66789566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
66797a8be351SBarry Smith   PetscCheck(label, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);
66809566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, point, value));
66813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6682c58f1c22SToby Isaac }
6683c58f1c22SToby Isaac 
6684c58f1c22SToby Isaac /*@C
6685bb7acecfSBarry Smith   DMSetLabelValue - Add a point to a `DMLabel` with given value
6686c58f1c22SToby Isaac 
6687c58f1c22SToby Isaac   Not Collective
6688c58f1c22SToby Isaac 
6689c58f1c22SToby Isaac   Input Parameters:
6690bb7acecfSBarry Smith + dm    - The `DM` object
6691c58f1c22SToby Isaac . name  - The label name
6692c58f1c22SToby Isaac . point - The mesh point
6693c58f1c22SToby Isaac - value - The label value for this point
6694c58f1c22SToby Isaac 
6695c58f1c22SToby Isaac   Output Parameter:
6696c58f1c22SToby Isaac 
6697c58f1c22SToby Isaac   Level: beginner
6698c58f1c22SToby Isaac 
66991cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelSetValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6700c58f1c22SToby Isaac @*/
6701d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6702d71ae5a4SJacob Faibussowitsch {
6703c58f1c22SToby Isaac   DMLabel label;
6704c58f1c22SToby Isaac 
6705c58f1c22SToby Isaac   PetscFunctionBegin;
6706c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67074f572ea9SToby Isaac   PetscAssertPointer(name, 2);
67089566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6709c58f1c22SToby Isaac   if (!label) {
67109566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
67119566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
6712c58f1c22SToby Isaac   }
67139566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, point, value));
67143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6715c58f1c22SToby Isaac }
6716c58f1c22SToby Isaac 
6717c58f1c22SToby Isaac /*@C
6718bb7acecfSBarry Smith   DMClearLabelValue - Remove a point from a `DMLabel` with given value
6719c58f1c22SToby Isaac 
6720c58f1c22SToby Isaac   Not Collective
6721c58f1c22SToby Isaac 
6722c58f1c22SToby Isaac   Input Parameters:
6723bb7acecfSBarry Smith + dm    - The `DM` object
6724c58f1c22SToby Isaac . name  - The label name
6725c58f1c22SToby Isaac . point - The mesh point
6726c58f1c22SToby Isaac - value - The label value for this point
6727c58f1c22SToby Isaac 
6728c58f1c22SToby Isaac   Level: beginner
6729c58f1c22SToby Isaac 
67301cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelClearValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6731c58f1c22SToby Isaac @*/
6732d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value)
6733d71ae5a4SJacob Faibussowitsch {
6734c58f1c22SToby Isaac   DMLabel label;
6735c58f1c22SToby Isaac 
6736c58f1c22SToby Isaac   PetscFunctionBegin;
6737c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67384f572ea9SToby Isaac   PetscAssertPointer(name, 2);
67399566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
67403ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
67419566063dSJacob Faibussowitsch   PetscCall(DMLabelClearValue(label, point, value));
67423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6743c58f1c22SToby Isaac }
6744c58f1c22SToby Isaac 
6745c58f1c22SToby Isaac /*@C
6746bb7acecfSBarry Smith   DMGetLabelSize - Get the value of `DMLabelGetNumValues()` of a `DMLabel` in the `DM`
6747c58f1c22SToby Isaac 
6748c58f1c22SToby Isaac   Not Collective
6749c58f1c22SToby Isaac 
6750c58f1c22SToby Isaac   Input Parameters:
6751bb7acecfSBarry Smith + dm   - The `DM` object
6752c58f1c22SToby Isaac - name - The label name
6753c58f1c22SToby Isaac 
6754c58f1c22SToby Isaac   Output Parameter:
6755c58f1c22SToby Isaac . size - The number of different integer ids, or 0 if the label does not exist
6756c58f1c22SToby Isaac 
6757c58f1c22SToby Isaac   Level: beginner
6758c58f1c22SToby Isaac 
675960225df5SJacob Faibussowitsch   Developer Notes:
6760bb7acecfSBarry Smith   This should be renamed to something like `DMGetLabelNumValues()` or removed.
6761bb7acecfSBarry Smith 
67621cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetNumValues()`, `DMSetLabelValue()`, `DMGetLabel()`
6763c58f1c22SToby Isaac @*/
6764d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size)
6765d71ae5a4SJacob Faibussowitsch {
6766c58f1c22SToby Isaac   DMLabel label;
6767c58f1c22SToby Isaac 
6768c58f1c22SToby Isaac   PetscFunctionBegin;
6769c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
67704f572ea9SToby Isaac   PetscAssertPointer(name, 2);
67714f572ea9SToby Isaac   PetscAssertPointer(size, 3);
67729566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6773c58f1c22SToby Isaac   *size = 0;
67743ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
67759566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, size));
67763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6777c58f1c22SToby Isaac }
6778c58f1c22SToby Isaac 
6779c58f1c22SToby Isaac /*@C
6780bb7acecfSBarry Smith   DMGetLabelIdIS - Get the `DMLabelGetValueIS()` from a `DMLabel` in the `DM`
6781c58f1c22SToby Isaac 
6782c58f1c22SToby Isaac   Not Collective
6783c58f1c22SToby Isaac 
6784c58f1c22SToby Isaac   Input Parameters:
678560225df5SJacob Faibussowitsch + dm   - The `DM` object
6786c58f1c22SToby Isaac - name - The label name
6787c58f1c22SToby Isaac 
6788c58f1c22SToby Isaac   Output Parameter:
678920f4b53cSBarry Smith . ids - The integer ids, or `NULL` if the label does not exist
6790c58f1c22SToby Isaac 
6791c58f1c22SToby Isaac   Level: beginner
6792c58f1c22SToby Isaac 
67931cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetValueIS()`, `DMGetLabelSize()`
6794c58f1c22SToby Isaac @*/
6795d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids)
6796d71ae5a4SJacob Faibussowitsch {
6797c58f1c22SToby Isaac   DMLabel label;
6798c58f1c22SToby Isaac 
6799c58f1c22SToby Isaac   PetscFunctionBegin;
6800c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68014f572ea9SToby Isaac   PetscAssertPointer(name, 2);
68024f572ea9SToby Isaac   PetscAssertPointer(ids, 3);
68039566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6804c58f1c22SToby Isaac   *ids = NULL;
6805dab2e251SBlaise Bourdin   if (label) {
68069566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, ids));
6807dab2e251SBlaise Bourdin   } else {
6808dab2e251SBlaise Bourdin     /* returning an empty IS */
68099566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, ids));
6810dab2e251SBlaise Bourdin   }
68113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6812c58f1c22SToby Isaac }
6813c58f1c22SToby Isaac 
6814c58f1c22SToby Isaac /*@C
6815c58f1c22SToby Isaac   DMGetStratumSize - Get the number of points in a label stratum
6816c58f1c22SToby Isaac 
6817c58f1c22SToby Isaac   Not Collective
6818c58f1c22SToby Isaac 
6819c58f1c22SToby Isaac   Input Parameters:
6820bb7acecfSBarry Smith + dm    - The `DM` object
6821c58f1c22SToby Isaac . name  - The label name
6822c58f1c22SToby Isaac - value - The stratum value
6823c58f1c22SToby Isaac 
6824c58f1c22SToby Isaac   Output Parameter:
6825bb7acecfSBarry Smith . size - The number of points, also called the stratum size
6826c58f1c22SToby Isaac 
6827c58f1c22SToby Isaac   Level: beginner
6828c58f1c22SToby Isaac 
68291cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetStratumSize()`, `DMGetLabelSize()`, `DMGetLabelIds()`
6830c58f1c22SToby Isaac @*/
6831d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size)
6832d71ae5a4SJacob Faibussowitsch {
6833c58f1c22SToby Isaac   DMLabel label;
6834c58f1c22SToby Isaac 
6835c58f1c22SToby Isaac   PetscFunctionBegin;
6836c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68374f572ea9SToby Isaac   PetscAssertPointer(name, 2);
68384f572ea9SToby Isaac   PetscAssertPointer(size, 4);
68399566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6840c58f1c22SToby Isaac   *size = 0;
68413ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
68429566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumSize(label, value, size));
68433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6844c58f1c22SToby Isaac }
6845c58f1c22SToby Isaac 
6846c58f1c22SToby Isaac /*@C
6847c58f1c22SToby Isaac   DMGetStratumIS - Get the points in a label stratum
6848c58f1c22SToby Isaac 
6849c58f1c22SToby Isaac   Not Collective
6850c58f1c22SToby Isaac 
6851c58f1c22SToby Isaac   Input Parameters:
6852bb7acecfSBarry Smith + dm    - The `DM` object
6853c58f1c22SToby Isaac . name  - The label name
6854c58f1c22SToby Isaac - value - The stratum value
6855c58f1c22SToby Isaac 
6856c58f1c22SToby Isaac   Output Parameter:
685720f4b53cSBarry Smith . points - The stratum points, or `NULL` if the label does not exist or does not have that value
6858c58f1c22SToby Isaac 
6859c58f1c22SToby Isaac   Level: beginner
6860c58f1c22SToby Isaac 
68611cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabelGetStratumIS()`, `DMGetStratumSize()`
6862c58f1c22SToby Isaac @*/
6863d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points)
6864d71ae5a4SJacob Faibussowitsch {
6865c58f1c22SToby Isaac   DMLabel label;
6866c58f1c22SToby Isaac 
6867c58f1c22SToby Isaac   PetscFunctionBegin;
6868c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68694f572ea9SToby Isaac   PetscAssertPointer(name, 2);
68704f572ea9SToby Isaac   PetscAssertPointer(points, 4);
68719566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
6872c58f1c22SToby Isaac   *points = NULL;
68733ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
68749566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumIS(label, value, points));
68753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6876c58f1c22SToby Isaac }
6877c58f1c22SToby Isaac 
68784de306b1SToby Isaac /*@C
68799044fa66SMatthew G. Knepley   DMSetStratumIS - Set the points in a label stratum
68804de306b1SToby Isaac 
68814de306b1SToby Isaac   Not Collective
68824de306b1SToby Isaac 
68834de306b1SToby Isaac   Input Parameters:
6884bb7acecfSBarry Smith + dm     - The `DM` object
68854de306b1SToby Isaac . name   - The label name
68864de306b1SToby Isaac . value  - The stratum value
68874de306b1SToby Isaac - points - The stratum points
68884de306b1SToby Isaac 
68894de306b1SToby Isaac   Level: beginner
68904de306b1SToby Isaac 
68911cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMClearLabelStratum()`, `DMLabelClearStratum()`, `DMLabelSetStratumIS()`, `DMGetStratumSize()`
68924de306b1SToby Isaac @*/
6893d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points)
6894d71ae5a4SJacob Faibussowitsch {
68954de306b1SToby Isaac   DMLabel label;
68964de306b1SToby Isaac 
68974de306b1SToby Isaac   PetscFunctionBegin;
68984de306b1SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68994f572ea9SToby Isaac   PetscAssertPointer(name, 2);
6900292bffcbSToby Isaac   PetscValidHeaderSpecific(points, IS_CLASSID, 4);
69019566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
69023ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
69039566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, value, points));
69043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
69054de306b1SToby Isaac }
69064de306b1SToby Isaac 
6907c58f1c22SToby Isaac /*@C
6908bb7acecfSBarry Smith   DMClearLabelStratum - Remove all points from a stratum from a `DMLabel`
6909c58f1c22SToby Isaac 
6910c58f1c22SToby Isaac   Not Collective
6911c58f1c22SToby Isaac 
6912c58f1c22SToby Isaac   Input Parameters:
6913bb7acecfSBarry Smith + dm    - The `DM` object
6914c58f1c22SToby Isaac . name  - The label name
6915c58f1c22SToby Isaac - value - The label value for this point
6916c58f1c22SToby Isaac 
6917c58f1c22SToby Isaac   Output Parameter:
6918c58f1c22SToby Isaac 
6919c58f1c22SToby Isaac   Level: beginner
6920c58f1c22SToby Isaac 
69211cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMLabelClearStratum()`, `DMSetLabelValue()`, `DMGetStratumIS()`, `DMClearLabelValue()`
6922c58f1c22SToby Isaac @*/
6923d71ae5a4SJacob Faibussowitsch PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value)
6924d71ae5a4SJacob Faibussowitsch {
6925c58f1c22SToby Isaac   DMLabel label;
6926c58f1c22SToby Isaac 
6927c58f1c22SToby Isaac   PetscFunctionBegin;
6928c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69294f572ea9SToby Isaac   PetscAssertPointer(name, 2);
69309566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
69313ba16761SJacob Faibussowitsch   if (!label) PetscFunctionReturn(PETSC_SUCCESS);
69329566063dSJacob Faibussowitsch   PetscCall(DMLabelClearStratum(label, value));
69333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6934c58f1c22SToby Isaac }
6935c58f1c22SToby Isaac 
6936c58f1c22SToby Isaac /*@
6937bb7acecfSBarry Smith   DMGetNumLabels - Return the number of labels defined by on the `DM`
6938c58f1c22SToby Isaac 
6939c58f1c22SToby Isaac   Not Collective
6940c58f1c22SToby Isaac 
6941c58f1c22SToby Isaac   Input Parameter:
6942bb7acecfSBarry Smith . dm - The `DM` object
6943c58f1c22SToby Isaac 
6944c58f1c22SToby Isaac   Output Parameter:
6945c58f1c22SToby Isaac . numLabels - the number of Labels
6946c58f1c22SToby Isaac 
6947c58f1c22SToby Isaac   Level: intermediate
6948c58f1c22SToby Isaac 
69491cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabelByNum()`, `DMGetLabelName()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6950c58f1c22SToby Isaac @*/
6951d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels)
6952d71ae5a4SJacob Faibussowitsch {
69535d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6954c58f1c22SToby Isaac   PetscInt    n    = 0;
6955c58f1c22SToby Isaac 
6956c58f1c22SToby Isaac   PetscFunctionBegin;
6957c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69584f572ea9SToby Isaac   PetscAssertPointer(numLabels, 2);
69599371c9d4SSatish Balay   while (next) {
69609371c9d4SSatish Balay     ++n;
69619371c9d4SSatish Balay     next = next->next;
69629371c9d4SSatish Balay   }
6963c58f1c22SToby Isaac   *numLabels = n;
69643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6965c58f1c22SToby Isaac }
6966c58f1c22SToby Isaac 
6967c58f1c22SToby Isaac /*@C
6968c58f1c22SToby Isaac   DMGetLabelName - Return the name of nth label
6969c58f1c22SToby Isaac 
6970c58f1c22SToby Isaac   Not Collective
6971c58f1c22SToby Isaac 
6972c58f1c22SToby Isaac   Input Parameters:
6973bb7acecfSBarry Smith + dm - The `DM` object
6974c58f1c22SToby Isaac - n  - the label number
6975c58f1c22SToby Isaac 
6976c58f1c22SToby Isaac   Output Parameter:
6977c58f1c22SToby Isaac . name - the label name
6978c58f1c22SToby Isaac 
6979c58f1c22SToby Isaac   Level: intermediate
6980c58f1c22SToby Isaac 
698160225df5SJacob Faibussowitsch   Developer Notes:
6982bb7acecfSBarry Smith   Some of the functions that appropriate on labels using their number have the suffix ByNum, others do not.
6983bb7acecfSBarry Smith 
69841cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabelByNum()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
6985c58f1c22SToby Isaac @*/
6986d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name)
6987d71ae5a4SJacob Faibussowitsch {
69885d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
6989c58f1c22SToby Isaac   PetscInt    l    = 0;
6990c58f1c22SToby Isaac 
6991c58f1c22SToby Isaac   PetscFunctionBegin;
6992c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69934f572ea9SToby Isaac   PetscAssertPointer(name, 3);
6994c58f1c22SToby Isaac   while (next) {
6995c58f1c22SToby Isaac     if (l == n) {
69969566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)next->label, name));
69973ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6998c58f1c22SToby Isaac     }
6999c58f1c22SToby Isaac     ++l;
7000c58f1c22SToby Isaac     next = next->next;
7001c58f1c22SToby Isaac   }
700263a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
7003c58f1c22SToby Isaac }
7004c58f1c22SToby Isaac 
7005c58f1c22SToby Isaac /*@C
7006bb7acecfSBarry Smith   DMHasLabel - Determine whether the `DM` has a label of a given name
7007c58f1c22SToby Isaac 
7008c58f1c22SToby Isaac   Not Collective
7009c58f1c22SToby Isaac 
7010c58f1c22SToby Isaac   Input Parameters:
7011bb7acecfSBarry Smith + dm   - The `DM` object
7012c58f1c22SToby Isaac - name - The label name
7013c58f1c22SToby Isaac 
7014c58f1c22SToby Isaac   Output Parameter:
7015bb7acecfSBarry Smith . hasLabel - `PETSC_TRUE` if the label is present
7016c58f1c22SToby Isaac 
7017c58f1c22SToby Isaac   Level: intermediate
7018c58f1c22SToby Isaac 
70191cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetLabel()`, `DMGetLabelByNum()`, `DMCreateLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7020c58f1c22SToby Isaac @*/
7021d71ae5a4SJacob Faibussowitsch PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel)
7022d71ae5a4SJacob Faibussowitsch {
70235d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7024d67d17b1SMatthew G. Knepley   const char *lname;
7025c58f1c22SToby Isaac 
7026c58f1c22SToby Isaac   PetscFunctionBegin;
7027c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70284f572ea9SToby Isaac   PetscAssertPointer(name, 2);
70294f572ea9SToby Isaac   PetscAssertPointer(hasLabel, 3);
7030c58f1c22SToby Isaac   *hasLabel = PETSC_FALSE;
7031c58f1c22SToby Isaac   while (next) {
70329566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
70339566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, hasLabel));
7034c58f1c22SToby Isaac     if (*hasLabel) break;
7035c58f1c22SToby Isaac     next = next->next;
7036c58f1c22SToby Isaac   }
70373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7038c58f1c22SToby Isaac }
7039c58f1c22SToby Isaac 
7040a4e35b19SJacob Faibussowitsch // PetscClangLinter pragma ignore: -fdoc-section-header-unknown
7041c58f1c22SToby Isaac /*@C
704220f4b53cSBarry Smith   DMGetLabel - Return the label of a given name, or `NULL`, from a `DM`
7043c58f1c22SToby Isaac 
7044c58f1c22SToby Isaac   Not Collective
7045c58f1c22SToby Isaac 
7046c58f1c22SToby Isaac   Input Parameters:
7047bb7acecfSBarry Smith + dm   - The `DM` object
7048c58f1c22SToby Isaac - name - The label name
7049c58f1c22SToby Isaac 
7050c58f1c22SToby Isaac   Output Parameter:
705120f4b53cSBarry Smith . label - The `DMLabel`, or `NULL` if the label is absent
7052c58f1c22SToby Isaac 
7053bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
7054bb7acecfSBarry Smith + "depth"       - Holds the depth (co-dimension) of each mesh point
7055bb7acecfSBarry Smith . "celltype"    - Holds the topological type of each cell
7056bb7acecfSBarry Smith . "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
7057bb7acecfSBarry Smith . "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
7058bb7acecfSBarry Smith . "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
7059bb7acecfSBarry Smith - "Vertex Sets" - Mirrors the vertex sets defined by GMsh
70606d7c9049SMatthew G. Knepley 
7061c58f1c22SToby Isaac   Level: intermediate
7062c58f1c22SToby Isaac 
706360225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMHasLabel()`, `DMGetLabelByNum()`, `DMAddLabel()`, `DMCreateLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
7064c58f1c22SToby Isaac @*/
7065d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label)
7066d71ae5a4SJacob Faibussowitsch {
70675d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7068c58f1c22SToby Isaac   PetscBool   hasLabel;
7069d67d17b1SMatthew G. Knepley   const char *lname;
7070c58f1c22SToby Isaac 
7071c58f1c22SToby Isaac   PetscFunctionBegin;
7072c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70734f572ea9SToby Isaac   PetscAssertPointer(name, 2);
70744f572ea9SToby Isaac   PetscAssertPointer(label, 3);
7075c58f1c22SToby Isaac   *label = NULL;
7076c58f1c22SToby Isaac   while (next) {
70779566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
70789566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
7079c58f1c22SToby Isaac     if (hasLabel) {
7080c58f1c22SToby Isaac       *label = next->label;
7081c58f1c22SToby Isaac       break;
7082c58f1c22SToby Isaac     }
7083c58f1c22SToby Isaac     next = next->next;
7084c58f1c22SToby Isaac   }
70853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7086c58f1c22SToby Isaac }
7087c58f1c22SToby Isaac 
7088c58f1c22SToby Isaac /*@C
7089bb7acecfSBarry Smith   DMGetLabelByNum - Return the nth label on a `DM`
7090c58f1c22SToby Isaac 
7091c58f1c22SToby Isaac   Not Collective
7092c58f1c22SToby Isaac 
7093c58f1c22SToby Isaac   Input Parameters:
7094bb7acecfSBarry Smith + dm - The `DM` object
7095c58f1c22SToby Isaac - n  - the label number
7096c58f1c22SToby Isaac 
7097c58f1c22SToby Isaac   Output Parameter:
7098c58f1c22SToby Isaac . label - the label
7099c58f1c22SToby Isaac 
7100c58f1c22SToby Isaac   Level: intermediate
7101c58f1c22SToby Isaac 
71021cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7103c58f1c22SToby Isaac @*/
7104d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label)
7105d71ae5a4SJacob Faibussowitsch {
71065d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7107c58f1c22SToby Isaac   PetscInt    l    = 0;
7108c58f1c22SToby Isaac 
7109c58f1c22SToby Isaac   PetscFunctionBegin;
7110c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71114f572ea9SToby Isaac   PetscAssertPointer(label, 3);
7112c58f1c22SToby Isaac   while (next) {
7113c58f1c22SToby Isaac     if (l == n) {
7114c58f1c22SToby Isaac       *label = next->label;
71153ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
7116c58f1c22SToby Isaac     }
7117c58f1c22SToby Isaac     ++l;
7118c58f1c22SToby Isaac     next = next->next;
7119c58f1c22SToby Isaac   }
712063a3b9bcSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %" PetscInt_FMT " does not exist in this DM", n);
7121c58f1c22SToby Isaac }
7122c58f1c22SToby Isaac 
7123c58f1c22SToby Isaac /*@C
7124bb7acecfSBarry Smith   DMAddLabel - Add the label to this `DM`
7125c58f1c22SToby Isaac 
7126c58f1c22SToby Isaac   Not Collective
7127c58f1c22SToby Isaac 
7128c58f1c22SToby Isaac   Input Parameters:
7129bb7acecfSBarry Smith + dm    - The `DM` object
7130bb7acecfSBarry Smith - label - The `DMLabel`
7131c58f1c22SToby Isaac 
7132c58f1c22SToby Isaac   Level: developer
7133c58f1c22SToby Isaac 
713460225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7135c58f1c22SToby Isaac @*/
7136d71ae5a4SJacob Faibussowitsch PetscErrorCode DMAddLabel(DM dm, DMLabel label)
7137d71ae5a4SJacob Faibussowitsch {
71385d80c0bfSVaclav Hapla   DMLabelLink l, *p, tmpLabel;
7139c58f1c22SToby Isaac   PetscBool   hasLabel;
7140d67d17b1SMatthew G. Knepley   const char *lname;
71415d80c0bfSVaclav Hapla   PetscBool   flg;
7142c58f1c22SToby Isaac 
7143c58f1c22SToby Isaac   PetscFunctionBegin;
7144c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71459566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
71469566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, lname, &hasLabel));
71477a8be351SBarry Smith   PetscCheck(!hasLabel, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname);
71489566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(1, &tmpLabel));
7149c58f1c22SToby Isaac   tmpLabel->label  = label;
7150c58f1c22SToby Isaac   tmpLabel->output = PETSC_TRUE;
71515d80c0bfSVaclav Hapla   for (p = &dm->labels; (l = *p); p = &l->next) { }
71525d80c0bfSVaclav Hapla   *p = tmpLabel;
71539566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)label));
71549566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "depth", &flg));
71555d80c0bfSVaclav Hapla   if (flg) dm->depthLabel = label;
71569566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(lname, "celltype", &flg));
7157ba2698f1SMatthew G. Knepley   if (flg) dm->celltypeLabel = label;
71583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7159c58f1c22SToby Isaac }
7160c58f1c22SToby Isaac 
7161a4e35b19SJacob Faibussowitsch // PetscClangLinter pragma ignore: -fdoc-section-header-unknown
7162c58f1c22SToby Isaac /*@C
71634a7ee7d0SMatthew G. Knepley   DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present
71644a7ee7d0SMatthew G. Knepley 
71654a7ee7d0SMatthew G. Knepley   Not Collective
71664a7ee7d0SMatthew G. Knepley 
71674a7ee7d0SMatthew G. Knepley   Input Parameters:
7168bb7acecfSBarry Smith + dm    - The `DM` object
7169bb7acecfSBarry Smith - label - The `DMLabel`, having the same name, to substitute
71704a7ee7d0SMatthew G. Knepley 
7171bb7acecfSBarry Smith   Default labels in a `DMPLEX`:
7172bb7acecfSBarry Smith + "depth"       - Holds the depth (co-dimension) of each mesh point
7173bb7acecfSBarry Smith . "celltype"    - Holds the topological type of each cell
7174bb7acecfSBarry Smith . "ghost"       - If the DM is distributed with overlap, this marks the cells and faces in the overlap
7175bb7acecfSBarry Smith . "Cell Sets"   - Mirrors the cell sets defined by GMsh and ExodusII
7176bb7acecfSBarry Smith . "Face Sets"   - Mirrors the face sets defined by GMsh and ExodusII
7177bb7acecfSBarry Smith - "Vertex Sets" - Mirrors the vertex sets defined by GMsh
71784a7ee7d0SMatthew G. Knepley 
71794a7ee7d0SMatthew G. Knepley   Level: intermediate
71804a7ee7d0SMatthew G. Knepley 
71811cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetCellType()`
71824a7ee7d0SMatthew G. Knepley @*/
7183d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabel(DM dm, DMLabel label)
7184d71ae5a4SJacob Faibussowitsch {
71854a7ee7d0SMatthew G. Knepley   DMLabelLink next = dm->labels;
71864a7ee7d0SMatthew G. Knepley   PetscBool   hasLabel, flg;
71874a7ee7d0SMatthew G. Knepley   const char *name, *lname;
71884a7ee7d0SMatthew G. Knepley 
71894a7ee7d0SMatthew G. Knepley   PetscFunctionBegin;
71904a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71914a7ee7d0SMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
71929566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)label, &name));
71934a7ee7d0SMatthew G. Knepley   while (next) {
71949566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
71959566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
71964a7ee7d0SMatthew G. Knepley     if (hasLabel) {
71979566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)label));
71989566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "depth", &flg));
71994a7ee7d0SMatthew G. Knepley       if (flg) dm->depthLabel = label;
72009566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(lname, "celltype", &flg));
72014a7ee7d0SMatthew G. Knepley       if (flg) dm->celltypeLabel = label;
72029566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&next->label));
72034a7ee7d0SMatthew G. Knepley       next->label = label;
72044a7ee7d0SMatthew G. Knepley       break;
72054a7ee7d0SMatthew G. Knepley     }
72064a7ee7d0SMatthew G. Knepley     next = next->next;
72074a7ee7d0SMatthew G. Knepley   }
72083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
72094a7ee7d0SMatthew G. Knepley }
72104a7ee7d0SMatthew G. Knepley 
72114a7ee7d0SMatthew G. Knepley /*@C
7212bb7acecfSBarry Smith   DMRemoveLabel - Remove the label given by name from this `DM`
7213c58f1c22SToby Isaac 
7214c58f1c22SToby Isaac   Not Collective
7215c58f1c22SToby Isaac 
7216c58f1c22SToby Isaac   Input Parameters:
7217bb7acecfSBarry Smith + dm   - The `DM` object
7218c58f1c22SToby Isaac - name - The label name
7219c58f1c22SToby Isaac 
7220c58f1c22SToby Isaac   Output Parameter:
722120f4b53cSBarry Smith . label - The `DMLabel`, or `NULL` if the label is absent. Pass in `NULL` to call `DMLabelDestroy()` on the label, otherwise the
7222bb7acecfSBarry Smith           caller is responsible for calling `DMLabelDestroy()`.
7223c58f1c22SToby Isaac 
7224c58f1c22SToby Isaac   Level: developer
7225c58f1c22SToby Isaac 
72261cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabelBySelf()`
7227c58f1c22SToby Isaac @*/
7228d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label)
7229d71ae5a4SJacob Faibussowitsch {
723095d578d6SVaclav Hapla   DMLabelLink link, *pnext;
7231c58f1c22SToby Isaac   PetscBool   hasLabel;
7232d67d17b1SMatthew G. Knepley   const char *lname;
7233c58f1c22SToby Isaac 
7234c58f1c22SToby Isaac   PetscFunctionBegin;
7235c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72364f572ea9SToby Isaac   PetscAssertPointer(name, 2);
7237e5472504SVaclav Hapla   if (label) {
72384f572ea9SToby Isaac     PetscAssertPointer(label, 3);
7239c58f1c22SToby Isaac     *label = NULL;
7240e5472504SVaclav Hapla   }
72415d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
72429566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)link->label, &lname));
72439566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &hasLabel));
7244c58f1c22SToby Isaac     if (hasLabel) {
724595d578d6SVaclav Hapla       *pnext = link->next; /* Remove from list */
72469566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &hasLabel));
724795d578d6SVaclav Hapla       if (hasLabel) dm->depthLabel = NULL;
72489566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &hasLabel));
7249ba2698f1SMatthew G. Knepley       if (hasLabel) dm->celltypeLabel = NULL;
725095d578d6SVaclav Hapla       if (label) *label = link->label;
72519566063dSJacob Faibussowitsch       else PetscCall(DMLabelDestroy(&link->label));
72529566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7253c58f1c22SToby Isaac       break;
7254c58f1c22SToby Isaac     }
7255c58f1c22SToby Isaac   }
72563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7257c58f1c22SToby Isaac }
7258c58f1c22SToby Isaac 
7259306894acSVaclav Hapla /*@
7260bb7acecfSBarry Smith   DMRemoveLabelBySelf - Remove the label from this `DM`
7261306894acSVaclav Hapla 
7262306894acSVaclav Hapla   Not Collective
7263306894acSVaclav Hapla 
7264306894acSVaclav Hapla   Input Parameters:
7265bb7acecfSBarry Smith + dm           - The `DM` object
7266bb7acecfSBarry Smith . label        - The `DMLabel` to be removed from the `DM`
726720f4b53cSBarry Smith - failNotFound - Should it fail if the label is not found in the `DM`?
7268306894acSVaclav Hapla 
7269306894acSVaclav Hapla   Level: developer
7270306894acSVaclav Hapla 
7271bb7acecfSBarry Smith   Note:
7272306894acSVaclav Hapla   Only exactly the same instance is removed if found, name match is ignored.
7273bb7acecfSBarry Smith   If the `DM` has an exclusive reference to the label, the label gets destroyed and
7274306894acSVaclav Hapla   *label nullified.
7275306894acSVaclav Hapla 
72761cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabel()` `DMGetLabelValue()`, `DMSetLabelValue()`, `DMLabelDestroy()`, `DMRemoveLabel()`
7277306894acSVaclav Hapla @*/
7278d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound)
7279d71ae5a4SJacob Faibussowitsch {
728043e45a93SVaclav Hapla   DMLabelLink link, *pnext;
7281306894acSVaclav Hapla   PetscBool   hasLabel = PETSC_FALSE;
7282306894acSVaclav Hapla 
7283306894acSVaclav Hapla   PetscFunctionBegin;
7284306894acSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72854f572ea9SToby Isaac   PetscAssertPointer(label, 2);
72863ba16761SJacob Faibussowitsch   if (!*label && !failNotFound) PetscFunctionReturn(PETSC_SUCCESS);
7287306894acSVaclav Hapla   PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2);
7288306894acSVaclav Hapla   PetscValidLogicalCollectiveBool(dm, failNotFound, 3);
72895d80c0bfSVaclav Hapla   for (pnext = &dm->labels; (link = *pnext); pnext = &link->next) {
729043e45a93SVaclav Hapla     if (*label == link->label) {
7291306894acSVaclav Hapla       hasLabel = PETSC_TRUE;
729243e45a93SVaclav Hapla       *pnext   = link->next; /* Remove from list */
7293306894acSVaclav Hapla       if (*label == dm->depthLabel) dm->depthLabel = NULL;
7294ba2698f1SMatthew G. Knepley       if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL;
729543e45a93SVaclav Hapla       if (((PetscObject)link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */
72969566063dSJacob Faibussowitsch       PetscCall(DMLabelDestroy(&link->label));
72979566063dSJacob Faibussowitsch       PetscCall(PetscFree(link));
7298306894acSVaclav Hapla       break;
7299306894acSVaclav Hapla     }
7300306894acSVaclav Hapla   }
73017a8be351SBarry Smith   PetscCheck(hasLabel || !failNotFound, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM");
73023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7303306894acSVaclav Hapla }
7304306894acSVaclav Hapla 
7305c58f1c22SToby Isaac /*@C
7306c58f1c22SToby Isaac   DMGetLabelOutput - Get the output flag for a given label
7307c58f1c22SToby Isaac 
7308c58f1c22SToby Isaac   Not Collective
7309c58f1c22SToby Isaac 
7310c58f1c22SToby Isaac   Input Parameters:
7311bb7acecfSBarry Smith + dm   - The `DM` object
7312c58f1c22SToby Isaac - name - The label name
7313c58f1c22SToby Isaac 
7314c58f1c22SToby Isaac   Output Parameter:
7315c58f1c22SToby Isaac . output - The flag for output
7316c58f1c22SToby Isaac 
7317c58f1c22SToby Isaac   Level: developer
7318c58f1c22SToby Isaac 
73191cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMSetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7320c58f1c22SToby Isaac @*/
7321d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output)
7322d71ae5a4SJacob Faibussowitsch {
73235d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7324d67d17b1SMatthew G. Knepley   const char *lname;
7325c58f1c22SToby Isaac 
7326c58f1c22SToby Isaac   PetscFunctionBegin;
7327c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73284f572ea9SToby Isaac   PetscAssertPointer(name, 2);
73294f572ea9SToby Isaac   PetscAssertPointer(output, 3);
7330c58f1c22SToby Isaac   while (next) {
7331c58f1c22SToby Isaac     PetscBool flg;
7332c58f1c22SToby Isaac 
73339566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
73349566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
73359371c9d4SSatish Balay     if (flg) {
73369371c9d4SSatish Balay       *output = next->output;
73373ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
73389371c9d4SSatish Balay     }
7339c58f1c22SToby Isaac     next = next->next;
7340c58f1c22SToby Isaac   }
734198921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7342c58f1c22SToby Isaac }
7343c58f1c22SToby Isaac 
7344c58f1c22SToby Isaac /*@C
7345bb7acecfSBarry Smith   DMSetLabelOutput - Set if a given label should be saved to a `PetscViewer` in calls to `DMView()`
7346c58f1c22SToby Isaac 
7347c58f1c22SToby Isaac   Not Collective
7348c58f1c22SToby Isaac 
7349c58f1c22SToby Isaac   Input Parameters:
7350bb7acecfSBarry Smith + dm     - The `DM` object
7351c58f1c22SToby Isaac . name   - The label name
7352bb7acecfSBarry Smith - output - `PETSC_TRUE` to save the label to the viewer
7353c58f1c22SToby Isaac 
7354c58f1c22SToby Isaac   Level: developer
7355c58f1c22SToby Isaac 
73561cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMGetOutputFlag()`, `DMGetLabelOutput()`, `DMCreateLabel()`, `DMHasLabel()`, `DMGetLabelValue()`, `DMSetLabelValue()`, `DMGetStratumIS()`
7357c58f1c22SToby Isaac @*/
7358d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output)
7359d71ae5a4SJacob Faibussowitsch {
73605d80c0bfSVaclav Hapla   DMLabelLink next = dm->labels;
7361d67d17b1SMatthew G. Knepley   const char *lname;
7362c58f1c22SToby Isaac 
7363c58f1c22SToby Isaac   PetscFunctionBegin;
7364c58f1c22SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73654f572ea9SToby Isaac   PetscAssertPointer(name, 2);
7366c58f1c22SToby Isaac   while (next) {
7367c58f1c22SToby Isaac     PetscBool flg;
7368c58f1c22SToby Isaac 
73699566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)next->label, &lname));
73709566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, lname, &flg));
73719371c9d4SSatish Balay     if (flg) {
73729371c9d4SSatish Balay       next->output = output;
73733ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
73749371c9d4SSatish Balay     }
7375c58f1c22SToby Isaac     next = next->next;
7376c58f1c22SToby Isaac   }
737798921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name);
7378c58f1c22SToby Isaac }
7379c58f1c22SToby Isaac 
7380c58f1c22SToby Isaac /*@
7381bb7acecfSBarry Smith   DMCopyLabels - Copy labels from one `DM` mesh to another `DM` with a superset of the points
7382c58f1c22SToby Isaac 
738320f4b53cSBarry Smith   Collective
7384c58f1c22SToby Isaac 
7385d8d19677SJose E. Roman   Input Parameters:
7386bb7acecfSBarry Smith + dmA   - The `DM` object with initial labels
7387bb7acecfSBarry Smith . dmB   - The `DM` object to which labels are copied
7388bb7acecfSBarry Smith . mode  - Copy labels by pointers (`PETSC_OWN_POINTER`) or duplicate them (`PETSC_COPY_VALUES`)
7389bb7acecfSBarry Smith . all   - Copy all labels including "depth", "dim", and "celltype" (`PETSC_TRUE`) which are otherwise ignored (`PETSC_FALSE`)
7390bb7acecfSBarry Smith - emode - How to behave when a `DMLabel` in the source and destination `DM`s with the same name is encountered (see `DMCopyLabelsMode`)
7391c58f1c22SToby Isaac 
7392c58f1c22SToby Isaac   Level: intermediate
7393c58f1c22SToby Isaac 
7394bb7acecfSBarry Smith   Note:
73952cbb9b06SVaclav Hapla   This is typically used when interpolating or otherwise adding to a mesh, or testing.
7396c58f1c22SToby Isaac 
73971cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`
7398c58f1c22SToby Isaac @*/
7399d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all, DMCopyLabelsMode emode)
7400d71ae5a4SJacob Faibussowitsch {
74012cbb9b06SVaclav Hapla   DMLabel     label, labelNew, labelOld;
7402c58f1c22SToby Isaac   const char *name;
7403c58f1c22SToby Isaac   PetscBool   flg;
74045d80c0bfSVaclav Hapla   DMLabelLink link;
7405c58f1c22SToby Isaac 
74065d80c0bfSVaclav Hapla   PetscFunctionBegin;
74075d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
74085d80c0bfSVaclav Hapla   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
74095d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveEnum(dmA, mode, 3);
74105d80c0bfSVaclav Hapla   PetscValidLogicalCollectiveBool(dmA, all, 4);
74117a8be351SBarry Smith   PetscCheck(mode != PETSC_USE_POINTER, PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects");
74123ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
74135d80c0bfSVaclav Hapla   for (link = dmA->labels; link; link = link->next) {
74145d80c0bfSVaclav Hapla     label = link->label;
74159566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)label, &name));
74165d80c0bfSVaclav Hapla     if (!all) {
74179566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &flg));
7418c58f1c22SToby Isaac       if (flg) continue;
74199566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "dim", &flg));
74207d5acc75SStefano Zampini       if (flg) continue;
74219566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "celltype", &flg));
7422ba2698f1SMatthew G. Knepley       if (flg) continue;
74235d80c0bfSVaclav Hapla     }
74249566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dmB, name, &labelOld));
74252cbb9b06SVaclav Hapla     if (labelOld) {
74262cbb9b06SVaclav Hapla       switch (emode) {
7427d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_KEEP:
7428d71ae5a4SJacob Faibussowitsch         continue;
7429d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_REPLACE:
7430d71ae5a4SJacob Faibussowitsch         PetscCall(DMRemoveLabelBySelf(dmB, &labelOld, PETSC_TRUE));
7431d71ae5a4SJacob Faibussowitsch         break;
7432d71ae5a4SJacob Faibussowitsch       case DM_COPY_LABELS_FAIL:
7433d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in destination DM", name);
7434d71ae5a4SJacob Faibussowitsch       default:
7435d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Unhandled DMCopyLabelsMode %d", (int)emode);
74362cbb9b06SVaclav Hapla       }
74372cbb9b06SVaclav Hapla     }
74385d80c0bfSVaclav Hapla     if (mode == PETSC_COPY_VALUES) {
74399566063dSJacob Faibussowitsch       PetscCall(DMLabelDuplicate(label, &labelNew));
74405d80c0bfSVaclav Hapla     } else {
74415d80c0bfSVaclav Hapla       labelNew = label;
74425d80c0bfSVaclav Hapla     }
74439566063dSJacob Faibussowitsch     PetscCall(DMAddLabel(dmB, labelNew));
74449566063dSJacob Faibussowitsch     if (mode == PETSC_COPY_VALUES) PetscCall(DMLabelDestroy(&labelNew));
7445c58f1c22SToby Isaac   }
74463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7447c58f1c22SToby Isaac }
7448461a15a0SLisandro Dalcin 
7449609dae6eSVaclav Hapla /*@C
7450b4028c23SStefano Zampini   DMCompareLabels - Compare labels between two `DM` objects
7451609dae6eSVaclav Hapla 
745220f4b53cSBarry Smith   Collective; No Fortran Support
7453609dae6eSVaclav Hapla 
7454609dae6eSVaclav Hapla   Input Parameters:
7455bb7acecfSBarry Smith + dm0 - First `DM` object
7456bb7acecfSBarry Smith - dm1 - Second `DM` object
7457609dae6eSVaclav Hapla 
7458a4e35b19SJacob Faibussowitsch   Output Parameters:
74595efe38ccSVaclav Hapla + equal   - (Optional) Flag whether labels of dm0 and dm1 are the same
746020f4b53cSBarry Smith - message - (Optional) Message describing the difference, or `NULL` if there is no difference
7461609dae6eSVaclav Hapla 
7462609dae6eSVaclav Hapla   Level: intermediate
7463609dae6eSVaclav Hapla 
7464609dae6eSVaclav Hapla   Notes:
7465bb7acecfSBarry Smith   The output flag equal will be the same on all processes.
7466bb7acecfSBarry Smith 
746720f4b53cSBarry Smith   If equal is passed as `NULL` and difference is found, an error is thrown on all processes.
7468bb7acecfSBarry Smith 
746920f4b53cSBarry Smith   Make sure to pass equal is `NULL` on all processes or none of them.
7470609dae6eSVaclav Hapla 
74715efe38ccSVaclav Hapla   The output message is set independently on each rank.
7472bb7acecfSBarry Smith 
7473bb7acecfSBarry Smith   message must be freed with `PetscFree()`
7474bb7acecfSBarry Smith 
747520f4b53cSBarry Smith   If message is passed as `NULL` and a difference is found, the difference description is printed to stderr in synchronized manner.
7476bb7acecfSBarry Smith 
747720f4b53cSBarry Smith   Make sure to pass message as `NULL` on all processes or no processes.
7478609dae6eSVaclav Hapla 
7479609dae6eSVaclav Hapla   Labels are matched by name. If the number of labels and their names are equal,
7480bb7acecfSBarry Smith   `DMLabelCompare()` is used to compare each pair of labels with the same name.
7481609dae6eSVaclav Hapla 
74821cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMLabel`, `DMAddLabel()`, `DMCopyLabelsMode`, `DMLabelCompare()`
7483609dae6eSVaclav Hapla @*/
7484d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCompareLabels(DM dm0, DM dm1, PetscBool *equal, char **message)
7485d71ae5a4SJacob Faibussowitsch {
74865efe38ccSVaclav Hapla   PetscInt    n, i;
7487609dae6eSVaclav Hapla   char        msg[PETSC_MAX_PATH_LEN] = "";
74885efe38ccSVaclav Hapla   PetscBool   eq;
7489609dae6eSVaclav Hapla   MPI_Comm    comm;
74905efe38ccSVaclav Hapla   PetscMPIInt rank;
7491609dae6eSVaclav Hapla 
7492609dae6eSVaclav Hapla   PetscFunctionBegin;
7493609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm0, DM_CLASSID, 1);
7494609dae6eSVaclav Hapla   PetscValidHeaderSpecific(dm1, DM_CLASSID, 2);
7495609dae6eSVaclav Hapla   PetscCheckSameComm(dm0, 1, dm1, 2);
74964f572ea9SToby Isaac   if (equal) PetscAssertPointer(equal, 3);
74974f572ea9SToby Isaac   if (message) PetscAssertPointer(message, 4);
74989566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm0, &comm));
74999566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
75005efe38ccSVaclav Hapla   {
75015efe38ccSVaclav Hapla     PetscInt n1;
75025efe38ccSVaclav Hapla 
75039566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm0, &n));
75049566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm1, &n1));
75055efe38ccSVaclav Hapla     eq = (PetscBool)(n == n1);
750648a46eb9SPierre Jolivet     if (!eq) PetscCall(PetscSNPrintf(msg, sizeof(msg), "Number of labels in dm0 = %" PetscInt_FMT " != %" PetscInt_FMT " = Number of labels in dm1", n, n1));
7507712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
75085efe38ccSVaclav Hapla     if (!eq) goto finish;
75095efe38ccSVaclav Hapla   }
75105efe38ccSVaclav Hapla   for (i = 0; i < n; i++) {
7511609dae6eSVaclav Hapla     DMLabel     l0, l1;
7512609dae6eSVaclav Hapla     const char *name;
7513609dae6eSVaclav Hapla     char       *msgInner;
7514609dae6eSVaclav Hapla 
7515609dae6eSVaclav Hapla     /* Ignore label order */
75169566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm0, i, &l0));
75179566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)l0, &name));
75189566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm1, name, &l1));
7519609dae6eSVaclav Hapla     if (!l1) {
752063a3b9bcSJacob Faibussowitsch       PetscCall(PetscSNPrintf(msg, sizeof(msg), "Label \"%s\" (#%" PetscInt_FMT " in dm0) not found in dm1", name, i));
75215efe38ccSVaclav Hapla       eq = PETSC_FALSE;
75225efe38ccSVaclav Hapla       break;
7523609dae6eSVaclav Hapla     }
75249566063dSJacob Faibussowitsch     PetscCall(DMLabelCompare(comm, l0, l1, &eq, &msgInner));
75259566063dSJacob Faibussowitsch     PetscCall(PetscStrncpy(msg, msgInner, sizeof(msg)));
75269566063dSJacob Faibussowitsch     PetscCall(PetscFree(msgInner));
75275efe38ccSVaclav Hapla     if (!eq) break;
7528609dae6eSVaclav Hapla   }
7529712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm));
7530609dae6eSVaclav Hapla finish:
75315efe38ccSVaclav Hapla   /* If message output arg not set, print to stderr */
7532609dae6eSVaclav Hapla   if (message) {
7533609dae6eSVaclav Hapla     *message = NULL;
753448a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscStrallocpy(msg, message));
75355efe38ccSVaclav Hapla   } else {
753648a46eb9SPierre Jolivet     if (msg[0]) PetscCall(PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg));
75379566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(comm, PETSC_STDERR));
75385efe38ccSVaclav Hapla   }
75395efe38ccSVaclav Hapla   /* If same output arg not ser and labels are not equal, throw error */
75405efe38ccSVaclav Hapla   if (equal) *equal = eq;
75417a8be351SBarry Smith   else PetscCheck(eq, comm, PETSC_ERR_ARG_INCOMP, "DMLabels are not the same in dm0 and dm1");
75423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7543609dae6eSVaclav Hapla }
7544609dae6eSVaclav Hapla 
7545d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value)
7546d71ae5a4SJacob Faibussowitsch {
7547461a15a0SLisandro Dalcin   PetscFunctionBegin;
75484f572ea9SToby Isaac   PetscAssertPointer(label, 2);
7549461a15a0SLisandro Dalcin   if (!*label) {
75509566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, name));
75519566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, label));
7552461a15a0SLisandro Dalcin   }
75539566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(*label, point, value));
75543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7555461a15a0SLisandro Dalcin }
7556461a15a0SLisandro Dalcin 
75570fdc7489SMatthew Knepley /*
75580fdc7489SMatthew Knepley   Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would
75590fdc7489SMatthew Knepley   like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every
75600fdc7489SMatthew Knepley   (label, id) pair in the DM.
75610fdc7489SMatthew Knepley 
75620fdc7489SMatthew Knepley   However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to
75630fdc7489SMatthew Knepley   each label.
75640fdc7489SMatthew Knepley */
7565d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal)
7566d71ae5a4SJacob Faibussowitsch {
75670fdc7489SMatthew Knepley   DMUniversalLabel ul;
75680fdc7489SMatthew Knepley   PetscBool       *active;
75690fdc7489SMatthew Knepley   PetscInt         pStart, pEnd, p, Nl, l, m;
75700fdc7489SMatthew Knepley 
75710fdc7489SMatthew Knepley   PetscFunctionBegin;
75729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(1, &ul));
75739566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label));
75749566063dSJacob Faibussowitsch   PetscCall(DMGetNumLabels(dm, &Nl));
75759566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Nl, &active));
75760fdc7489SMatthew Knepley   ul->Nl = 0;
75770fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
75780fdc7489SMatthew Knepley     PetscBool   isdepth, iscelltype;
75790fdc7489SMatthew Knepley     const char *name;
75800fdc7489SMatthew Knepley 
75819566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
75829566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "depth", 6, &isdepth));
75839566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(name, "celltype", 9, &iscelltype));
75840fdc7489SMatthew Knepley     active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE;
75850fdc7489SMatthew Knepley     if (active[l]) ++ul->Nl;
75860fdc7489SMatthew Knepley   }
75879566063dSJacob 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));
75880fdc7489SMatthew Knepley   ul->Nv = 0;
75890fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
75900fdc7489SMatthew Knepley     DMLabel     label;
75910fdc7489SMatthew Knepley     PetscInt    nv;
75920fdc7489SMatthew Knepley     const char *name;
75930fdc7489SMatthew Knepley 
75940fdc7489SMatthew Knepley     if (!active[l]) continue;
75959566063dSJacob Faibussowitsch     PetscCall(DMGetLabelName(dm, l, &name));
75969566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
75979566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
75989566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &ul->names[m]));
75990fdc7489SMatthew Knepley     ul->indices[m] = l;
76000fdc7489SMatthew Knepley     ul->Nv += nv;
76010fdc7489SMatthew Knepley     ul->offsets[m + 1] = nv;
76020fdc7489SMatthew Knepley     ul->bits[m + 1]    = PetscCeilReal(PetscLog2Real(nv + 1));
76030fdc7489SMatthew Knepley     ++m;
76040fdc7489SMatthew Knepley   }
76050fdc7489SMatthew Knepley   for (l = 1; l <= ul->Nl; ++l) {
76060fdc7489SMatthew Knepley     ul->offsets[l] = ul->offsets[l - 1] + ul->offsets[l];
76070fdc7489SMatthew Knepley     ul->bits[l]    = ul->bits[l - 1] + ul->bits[l];
76080fdc7489SMatthew Knepley   }
76090fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
76100fdc7489SMatthew Knepley     PetscInt b;
76110fdc7489SMatthew Knepley 
76120fdc7489SMatthew Knepley     ul->masks[l] = 0;
76130fdc7489SMatthew Knepley     for (b = ul->bits[l]; b < ul->bits[l + 1]; ++b) ul->masks[l] |= 1 << b;
76140fdc7489SMatthew Knepley   }
76159566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ul->Nv, &ul->values));
76160fdc7489SMatthew Knepley   for (l = 0, m = 0; l < Nl; ++l) {
76170fdc7489SMatthew Knepley     DMLabel         label;
76180fdc7489SMatthew Knepley     IS              valueIS;
76190fdc7489SMatthew Knepley     const PetscInt *varr;
76200fdc7489SMatthew Knepley     PetscInt        nv, v;
76210fdc7489SMatthew Knepley 
76220fdc7489SMatthew Knepley     if (!active[l]) continue;
76239566063dSJacob Faibussowitsch     PetscCall(DMGetLabelByNum(dm, l, &label));
76249566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &nv));
76259566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValueIS(label, &valueIS));
76269566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(valueIS, &varr));
7627ad540459SPierre Jolivet     for (v = 0; v < nv; ++v) ul->values[ul->offsets[m] + v] = varr[v];
76289566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(valueIS, &varr));
76299566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&valueIS));
76309566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(nv, &ul->values[ul->offsets[m]]));
76310fdc7489SMatthew Knepley     ++m;
76320fdc7489SMatthew Knepley   }
76339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
76340fdc7489SMatthew Knepley   for (p = pStart; p < pEnd; ++p) {
76350fdc7489SMatthew Knepley     PetscInt  uval   = 0;
76360fdc7489SMatthew Knepley     PetscBool marked = PETSC_FALSE;
76370fdc7489SMatthew Knepley 
76380fdc7489SMatthew Knepley     for (l = 0, m = 0; l < Nl; ++l) {
76390fdc7489SMatthew Knepley       DMLabel  label;
76400649b39aSStefano Zampini       PetscInt val, defval, loc, nv;
76410fdc7489SMatthew Knepley 
76420fdc7489SMatthew Knepley       if (!active[l]) continue;
76439566063dSJacob Faibussowitsch       PetscCall(DMGetLabelByNum(dm, l, &label));
76449566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, p, &val));
76459566063dSJacob Faibussowitsch       PetscCall(DMLabelGetDefaultValue(label, &defval));
76469371c9d4SSatish Balay       if (val == defval) {
76479371c9d4SSatish Balay         ++m;
76489371c9d4SSatish Balay         continue;
76499371c9d4SSatish Balay       }
76500649b39aSStefano Zampini       nv     = ul->offsets[m + 1] - ul->offsets[m];
76510fdc7489SMatthew Knepley       marked = PETSC_TRUE;
76529566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc));
765363a3b9bcSJacob Faibussowitsch       PetscCheck(loc >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %" PetscInt_FMT " not found in compression array", val);
76540fdc7489SMatthew Knepley       uval += (loc + 1) << ul->bits[m];
76550fdc7489SMatthew Knepley       ++m;
76560fdc7489SMatthew Knepley     }
76579566063dSJacob Faibussowitsch     if (marked) PetscCall(DMLabelSetValue(ul->label, p, uval));
76580fdc7489SMatthew Knepley   }
76599566063dSJacob Faibussowitsch   PetscCall(PetscFree(active));
76600fdc7489SMatthew Knepley   *universal = ul;
76613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76620fdc7489SMatthew Knepley }
76630fdc7489SMatthew Knepley 
7664d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal)
7665d71ae5a4SJacob Faibussowitsch {
76660fdc7489SMatthew Knepley   PetscInt l;
76670fdc7489SMatthew Knepley 
76680fdc7489SMatthew Knepley   PetscFunctionBegin;
76699566063dSJacob Faibussowitsch   for (l = 0; l < (*universal)->Nl; ++l) PetscCall(PetscFree((*universal)->names[l]));
76709566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&(*universal)->label));
76719566063dSJacob Faibussowitsch   PetscCall(PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks));
76729566063dSJacob Faibussowitsch   PetscCall(PetscFree((*universal)->values));
76739566063dSJacob Faibussowitsch   PetscCall(PetscFree(*universal));
76740fdc7489SMatthew Knepley   *universal = NULL;
76753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76760fdc7489SMatthew Knepley }
76770fdc7489SMatthew Knepley 
7678d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel)
7679d71ae5a4SJacob Faibussowitsch {
76800fdc7489SMatthew Knepley   PetscFunctionBegin;
76814f572ea9SToby Isaac   PetscAssertPointer(ulabel, 2);
76820fdc7489SMatthew Knepley   *ulabel = ul->label;
76833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76840fdc7489SMatthew Knepley }
76850fdc7489SMatthew Knepley 
7686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm)
7687d71ae5a4SJacob Faibussowitsch {
76880fdc7489SMatthew Knepley   PetscInt Nl = ul->Nl, l;
76890fdc7489SMatthew Knepley 
76900fdc7489SMatthew Knepley   PetscFunctionBegin;
7691064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 3);
76920fdc7489SMatthew Knepley   for (l = 0; l < Nl; ++l) {
76939566063dSJacob Faibussowitsch     if (preserveOrder) PetscCall(DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]));
76949566063dSJacob Faibussowitsch     else PetscCall(DMCreateLabel(dm, ul->names[l]));
76950fdc7489SMatthew Knepley   }
76960fdc7489SMatthew Knepley   if (preserveOrder) {
76970fdc7489SMatthew Knepley     for (l = 0; l < ul->Nl; ++l) {
76980fdc7489SMatthew Knepley       const char *name;
76990fdc7489SMatthew Knepley       PetscBool   match;
77000fdc7489SMatthew Knepley 
77019566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, ul->indices[l], &name));
77029566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, ul->names[l], &match));
770363a3b9bcSJacob 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]);
77040fdc7489SMatthew Knepley     }
77050fdc7489SMatthew Knepley   }
77063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77070fdc7489SMatthew Knepley }
77080fdc7489SMatthew Knepley 
7709d71ae5a4SJacob Faibussowitsch PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value)
7710d71ae5a4SJacob Faibussowitsch {
77110fdc7489SMatthew Knepley   PetscInt l;
77120fdc7489SMatthew Knepley 
77130fdc7489SMatthew Knepley   PetscFunctionBegin;
77140fdc7489SMatthew Knepley   for (l = 0; l < ul->Nl; ++l) {
77150fdc7489SMatthew Knepley     DMLabel  label;
77160fdc7489SMatthew Knepley     PetscInt lval = (value & ul->masks[l]) >> ul->bits[l];
77170fdc7489SMatthew Knepley 
77180fdc7489SMatthew Knepley     if (lval) {
77199566063dSJacob Faibussowitsch       if (useIndex) PetscCall(DMGetLabelByNum(dm, ul->indices[l], &label));
77209566063dSJacob Faibussowitsch       else PetscCall(DMGetLabel(dm, ul->names[l], &label));
77219566063dSJacob Faibussowitsch       PetscCall(DMLabelSetValue(label, p, ul->values[ul->offsets[l] + lval - 1]));
77220fdc7489SMatthew Knepley     }
77230fdc7489SMatthew Knepley   }
77243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77250fdc7489SMatthew Knepley }
7726a8fb8f29SToby Isaac 
7727a8fb8f29SToby Isaac /*@
7728bb7acecfSBarry Smith   DMGetCoarseDM - Get the coarse `DM`from which this `DM` was obtained by refinement
7729bb7acecfSBarry Smith 
773020f4b53cSBarry Smith   Not Collective
7731a8fb8f29SToby Isaac 
7732a8fb8f29SToby Isaac   Input Parameter:
7733bb7acecfSBarry Smith . dm - The `DM` object
7734a8fb8f29SToby Isaac 
7735a8fb8f29SToby Isaac   Output Parameter:
7736bb7acecfSBarry Smith . cdm - The coarse `DM`
7737a8fb8f29SToby Isaac 
7738a8fb8f29SToby Isaac   Level: intermediate
7739a8fb8f29SToby Isaac 
77401cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetCoarseDM()`, `DMCoarsen()`
7741a8fb8f29SToby Isaac @*/
7742d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm)
7743d71ae5a4SJacob Faibussowitsch {
7744a8fb8f29SToby Isaac   PetscFunctionBegin;
7745a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
77464f572ea9SToby Isaac   PetscAssertPointer(cdm, 2);
7747a8fb8f29SToby Isaac   *cdm = dm->coarseMesh;
77483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7749a8fb8f29SToby Isaac }
7750a8fb8f29SToby Isaac 
7751a8fb8f29SToby Isaac /*@
7752bb7acecfSBarry Smith   DMSetCoarseDM - Set the coarse `DM` from which this `DM` was obtained by refinement
7753a8fb8f29SToby Isaac 
7754a8fb8f29SToby Isaac   Input Parameters:
7755bb7acecfSBarry Smith + dm  - The `DM` object
7756bb7acecfSBarry Smith - cdm - The coarse `DM`
7757a8fb8f29SToby Isaac 
7758a8fb8f29SToby Isaac   Level: intermediate
7759a8fb8f29SToby Isaac 
7760bb7acecfSBarry Smith   Note:
7761bb7acecfSBarry Smith   Normally this is set automatically by `DMRefine()`
7762bb7acecfSBarry Smith 
77631cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetCoarseDM()`, `DMCoarsen()`, `DMSetRefine()`, `DMSetFineDM()`
7764a8fb8f29SToby Isaac @*/
7765d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoarseDM(DM dm, DM cdm)
7766d71ae5a4SJacob Faibussowitsch {
7767a8fb8f29SToby Isaac   PetscFunctionBegin;
7768a8fb8f29SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7769a8fb8f29SToby Isaac   if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
777089d734beSBarry Smith   if (dm == cdm) cdm = NULL;
77719566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)cdm));
77729566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->coarseMesh));
7773a8fb8f29SToby Isaac   dm->coarseMesh = cdm;
77743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7775a8fb8f29SToby Isaac }
7776a8fb8f29SToby Isaac 
777788bdff64SToby Isaac /*@
7778bb7acecfSBarry Smith   DMGetFineDM - Get the fine mesh from which this `DM` was obtained by coarsening
777988bdff64SToby Isaac 
778088bdff64SToby Isaac   Input Parameter:
7781bb7acecfSBarry Smith . dm - The `DM` object
778288bdff64SToby Isaac 
778388bdff64SToby Isaac   Output Parameter:
7784bb7acecfSBarry Smith . fdm - The fine `DM`
778588bdff64SToby Isaac 
778688bdff64SToby Isaac   Level: intermediate
778788bdff64SToby Isaac 
77881cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetFineDM()`, `DMCoarsen()`, `DMRefine()`
778988bdff64SToby Isaac @*/
7790d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetFineDM(DM dm, DM *fdm)
7791d71ae5a4SJacob Faibussowitsch {
779288bdff64SToby Isaac   PetscFunctionBegin;
779388bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
77944f572ea9SToby Isaac   PetscAssertPointer(fdm, 2);
779588bdff64SToby Isaac   *fdm = dm->fineMesh;
77963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
779788bdff64SToby Isaac }
779888bdff64SToby Isaac 
779988bdff64SToby Isaac /*@
7800bb7acecfSBarry Smith   DMSetFineDM - Set the fine mesh from which this was obtained by coarsening
780188bdff64SToby Isaac 
780288bdff64SToby Isaac   Input Parameters:
7803bb7acecfSBarry Smith + dm  - The `DM` object
7804bb7acecfSBarry Smith - fdm - The fine `DM`
780588bdff64SToby Isaac 
7806bb7acecfSBarry Smith   Level: developer
780788bdff64SToby Isaac 
7808bb7acecfSBarry Smith   Note:
7809bb7acecfSBarry Smith   Normally this is set automatically by `DMCoarsen()`
7810bb7acecfSBarry Smith 
78111cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetFineDM()`, `DMCoarsen()`, `DMRefine()`
781288bdff64SToby Isaac @*/
7813d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFineDM(DM dm, DM fdm)
7814d71ae5a4SJacob Faibussowitsch {
781588bdff64SToby Isaac   PetscFunctionBegin;
781688bdff64SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
781788bdff64SToby Isaac   if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2);
781889d734beSBarry Smith   if (dm == fdm) fdm = NULL;
78199566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)fdm));
78209566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm->fineMesh));
782188bdff64SToby Isaac   dm->fineMesh = fdm;
78223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
782388bdff64SToby Isaac }
782488bdff64SToby Isaac 
7825a6ba4734SToby Isaac /*@C
7826bb7acecfSBarry Smith   DMAddBoundary - Add a boundary condition to a model represented by a `DM`
7827a6ba4734SToby Isaac 
782820f4b53cSBarry Smith   Collective
7829783e2ec8SMatthew G. Knepley 
7830a6ba4734SToby Isaac   Input Parameters:
7831bb7acecfSBarry Smith + dm       - The `DM`, with a `PetscDS` that matches the problem being constrained
7832bb7acecfSBarry Smith . type     - The type of condition, e.g. `DM_BC_ESSENTIAL_ANALYTIC`, `DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
7833a6ba4734SToby Isaac . name     - The BC name
783445480ffeSMatthew G. Knepley . label    - The label defining constrained points
7835bb7acecfSBarry Smith . Nv       - The number of `DMLabel` values for constrained points
783645480ffeSMatthew G. Knepley . values   - An array of values for constrained points
7837a6ba4734SToby Isaac . field    - The field to constrain
783845480ffeSMatthew G. Knepley . Nc       - The number of constrained field components (0 will constrain all fields)
7839a6ba4734SToby Isaac . comps    - An array of constrained component numbers
7840a6ba4734SToby Isaac . bcFunc   - A pointwise function giving boundary values
784156cf3b9cSMatthew G. Knepley . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL
7842a6ba4734SToby Isaac - ctx      - An optional user context for bcFunc
7843a6ba4734SToby Isaac 
784445480ffeSMatthew G. Knepley   Output Parameter:
784545480ffeSMatthew G. Knepley . bd - (Optional) Boundary number
784645480ffeSMatthew G. Knepley 
7847a6ba4734SToby Isaac   Options Database Keys:
7848a6ba4734SToby Isaac + -bc_<boundary name> <num>      - Overrides the boundary ids
7849a6ba4734SToby Isaac - -bc_<boundary name>_comp <num> - Overrides the boundary components
7850a6ba4734SToby Isaac 
785120f4b53cSBarry Smith   Level: intermediate
785220f4b53cSBarry Smith 
7853bb7acecfSBarry Smith   Notes:
785437fdd005SBarry Smith   Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if `DM_BC_ESSENTIAL`, then the calling sequence is\:
785556cf3b9cSMatthew G. Knepley 
785620f4b53cSBarry Smith $ void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
785756cf3b9cSMatthew G. Knepley 
7858a4e35b19SJacob Faibussowitsch   If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is\:
785956cf3b9cSMatthew G. Knepley 
786020f4b53cSBarry Smith .vb
786120f4b53cSBarry Smith   void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
786220f4b53cSBarry Smith               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
786320f4b53cSBarry Smith               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
786420f4b53cSBarry Smith               PetscReal time, const PetscReal x[], PetscScalar bcval[])
786520f4b53cSBarry Smith .ve
786656cf3b9cSMatthew G. Knepley + dim - the spatial dimension
786756cf3b9cSMatthew G. Knepley . Nf - the number of fields
786856cf3b9cSMatthew G. Knepley . uOff - the offset into u[] and u_t[] for each field
786956cf3b9cSMatthew G. Knepley . uOff_x - the offset into u_x[] for each field
787056cf3b9cSMatthew G. Knepley . u - each field evaluated at the current point
787156cf3b9cSMatthew G. Knepley . u_t - the time derivative of each field evaluated at the current point
787256cf3b9cSMatthew G. Knepley . u_x - the gradient of each field evaluated at the current point
787356cf3b9cSMatthew G. Knepley . aOff - the offset into a[] and a_t[] for each auxiliary field
787456cf3b9cSMatthew G. Knepley . aOff_x - the offset into a_x[] for each auxiliary field
787556cf3b9cSMatthew G. Knepley . a - each auxiliary field evaluated at the current point
787656cf3b9cSMatthew G. Knepley . a_t - the time derivative of each auxiliary field evaluated at the current point
787756cf3b9cSMatthew G. Knepley . a_x - the gradient of auxiliary each field evaluated at the current point
787856cf3b9cSMatthew G. Knepley . t - current time
787956cf3b9cSMatthew G. Knepley . x - coordinates of the current point
788056cf3b9cSMatthew G. Knepley . numConstants - number of constant parameters
788156cf3b9cSMatthew G. Knepley . constants - constant parameters
788256cf3b9cSMatthew G. Knepley - bcval - output values at the current point
788356cf3b9cSMatthew G. Knepley 
78841cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DSGetBoundary()`, `PetscDSAddBoundary()`
7885a6ba4734SToby Isaac @*/
7886d71ae5a4SJacob 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)
7887d71ae5a4SJacob Faibussowitsch {
7888e5e52638SMatthew G. Knepley   PetscDS ds;
7889a6ba4734SToby Isaac 
7890a6ba4734SToby Isaac   PetscFunctionBegin;
7891a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7892783e2ec8SMatthew G. Knepley   PetscValidLogicalCollectiveEnum(dm, type, 2);
789345480ffeSMatthew G. Knepley   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
789445480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nv, 5);
789545480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, field, 7);
789645480ffeSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, Nc, 8);
789701a5d20dSJed Brown   PetscCheck(!dm->localSection, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Cannot add boundary to DM after creating local section");
78989566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
7899799db056SMatthew G. Knepley   /* Complete label */
7900799db056SMatthew G. Knepley   if (label) {
7901799db056SMatthew G. Knepley     PetscObject  obj;
7902799db056SMatthew G. Knepley     PetscClassId id;
7903799db056SMatthew G. Knepley 
7904799db056SMatthew G. Knepley     PetscCall(DMGetField(dm, field, NULL, &obj));
7905799db056SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
7906799db056SMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
7907799db056SMatthew G. Knepley       DM plex;
7908799db056SMatthew G. Knepley 
7909799db056SMatthew G. Knepley       PetscCall(DMConvert(dm, DMPLEX, &plex));
7910799db056SMatthew G. Knepley       if (plex) PetscCall(DMPlexLabelComplete(plex, label));
7911799db056SMatthew G. Knepley       PetscCall(DMDestroy(&plex));
7912799db056SMatthew G. Knepley     }
7913799db056SMatthew G. Knepley   }
79149566063dSJacob Faibussowitsch   PetscCall(PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd));
79153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7916a6ba4734SToby Isaac }
7917a6ba4734SToby Isaac 
791845480ffeSMatthew G. Knepley /* TODO Remove this since now the structures are the same */
7919d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPopulateBoundary(DM dm)
7920d71ae5a4SJacob Faibussowitsch {
7921e5e52638SMatthew G. Knepley   PetscDS     ds;
7922dff059c6SToby Isaac   DMBoundary *lastnext;
7923e6f8dbb6SToby Isaac   DSBoundary  dsbound;
7924e6f8dbb6SToby Isaac 
7925e6f8dbb6SToby Isaac   PetscFunctionBegin;
79269566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
7927e5e52638SMatthew G. Knepley   dsbound = ds->boundary;
792847a1f5adSToby Isaac   if (dm->boundary) {
792947a1f5adSToby Isaac     DMBoundary next = dm->boundary;
793047a1f5adSToby Isaac 
793147a1f5adSToby Isaac     /* quick check to see if the PetscDS has changed */
79323ba16761SJacob Faibussowitsch     if (next->dsboundary == dsbound) PetscFunctionReturn(PETSC_SUCCESS);
793347a1f5adSToby Isaac     /* the PetscDS has changed: tear down and rebuild */
793447a1f5adSToby Isaac     while (next) {
793547a1f5adSToby Isaac       DMBoundary b = next;
793647a1f5adSToby Isaac 
793747a1f5adSToby Isaac       next = b->next;
79389566063dSJacob Faibussowitsch       PetscCall(PetscFree(b));
7939a6ba4734SToby Isaac     }
794047a1f5adSToby Isaac     dm->boundary = NULL;
7941a6ba4734SToby Isaac   }
794247a1f5adSToby Isaac 
7943dff059c6SToby Isaac   lastnext = &(dm->boundary);
7944e6f8dbb6SToby Isaac   while (dsbound) {
7945e6f8dbb6SToby Isaac     DMBoundary dmbound;
7946e6f8dbb6SToby Isaac 
79479566063dSJacob Faibussowitsch     PetscCall(PetscNew(&dmbound));
7948e6f8dbb6SToby Isaac     dmbound->dsboundary = dsbound;
794945480ffeSMatthew G. Knepley     dmbound->label      = dsbound->label;
795047a1f5adSToby Isaac     /* push on the back instead of the front so that it is in the same order as in the PetscDS */
7951dff059c6SToby Isaac     *lastnext = dmbound;
7952dff059c6SToby Isaac     lastnext  = &(dmbound->next);
7953dff059c6SToby Isaac     dsbound   = dsbound->next;
7954a6ba4734SToby Isaac   }
79553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7956a6ba4734SToby Isaac }
7957a6ba4734SToby Isaac 
7958bb7acecfSBarry Smith /* TODO: missing manual page */
7959d71ae5a4SJacob Faibussowitsch PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd)
7960d71ae5a4SJacob Faibussowitsch {
7961b95f2879SToby Isaac   DMBoundary b;
7962a6ba4734SToby Isaac 
7963a6ba4734SToby Isaac   PetscFunctionBegin;
7964a6ba4734SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79654f572ea9SToby Isaac   PetscAssertPointer(isBd, 3);
7966a6ba4734SToby Isaac   *isBd = PETSC_FALSE;
79679566063dSJacob Faibussowitsch   PetscCall(DMPopulateBoundary(dm));
7968b95f2879SToby Isaac   b = dm->boundary;
7969a6ba4734SToby Isaac   while (b && !(*isBd)) {
7970e6f8dbb6SToby Isaac     DMLabel    label = b->label;
7971e6f8dbb6SToby Isaac     DSBoundary dsb   = b->dsboundary;
7972a6ba4734SToby Isaac     PetscInt   i;
7973a6ba4734SToby Isaac 
797445480ffeSMatthew G. Knepley     if (label) {
79759566063dSJacob Faibussowitsch       for (i = 0; i < dsb->Nv && !(*isBd); ++i) PetscCall(DMLabelStratumHasPoint(label, dsb->values[i], point, isBd));
7976a6ba4734SToby Isaac     }
7977a6ba4734SToby Isaac     b = b->next;
7978a6ba4734SToby Isaac   }
79793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7980a6ba4734SToby Isaac }
79814d6f44ffSToby Isaac 
79824d6f44ffSToby Isaac /*@C
7983bb7acecfSBarry Smith   DMProjectFunction - This projects the given function into the function space provided by a `DM`, putting the coefficients in a global vector.
7984a6e0b375SMatthew G. Knepley 
798520f4b53cSBarry Smith   Collective
79864d6f44ffSToby Isaac 
79874d6f44ffSToby Isaac   Input Parameters:
7988bb7acecfSBarry Smith + dm    - The `DM`
79890709b2feSToby Isaac . time  - The time
79904d6f44ffSToby Isaac . funcs - The coordinate functions to evaluate, one per field
79914d6f44ffSToby Isaac . ctxs  - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
79924d6f44ffSToby Isaac - mode  - The insertion mode for values
79934d6f44ffSToby Isaac 
79944d6f44ffSToby Isaac   Output Parameter:
79954d6f44ffSToby Isaac . X - vector
79964d6f44ffSToby Isaac 
799720f4b53cSBarry Smith   Calling sequence of `funcs`:
79984d6f44ffSToby Isaac + dim  - The spatial dimension
79998ec8862eSJed Brown . time - The time at which to sample
80004d6f44ffSToby Isaac . x    - The coordinates
800177b739a6SMatthew Knepley . Nc   - The number of components
80024d6f44ffSToby Isaac . u    - The output field values
80034d6f44ffSToby Isaac - ctx  - optional user-defined function context
80044d6f44ffSToby Isaac 
80054d6f44ffSToby Isaac   Level: developer
80064d6f44ffSToby Isaac 
8007bb7acecfSBarry Smith   Developer Notes:
8008bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8009bb7acecfSBarry Smith 
8010bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8011bb7acecfSBarry Smith 
80121cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
80134d6f44ffSToby Isaac @*/
8014a4e35b19SJacob 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)
8015d71ae5a4SJacob Faibussowitsch {
80164d6f44ffSToby Isaac   Vec localX;
80174d6f44ffSToby Isaac 
80184d6f44ffSToby Isaac   PetscFunctionBegin;
80194d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8020708be2fdSJed Brown   PetscCall(PetscLogEventBegin(DM_ProjectFunction, dm, X, 0, 0));
80219566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
8022f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
80239566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX));
80249566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
80259566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
80269566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
8027708be2fdSJed Brown   PetscCall(PetscLogEventEnd(DM_ProjectFunction, dm, X, 0, 0));
80283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80294d6f44ffSToby Isaac }
80304d6f44ffSToby Isaac 
8031a6e0b375SMatthew G. Knepley /*@C
8032bb7acecfSBarry Smith   DMProjectFunctionLocal - This projects the given function into the function space provided by a `DM`, putting the coefficients in a local vector.
8033a6e0b375SMatthew G. Knepley 
803420f4b53cSBarry Smith   Not Collective
8035a6e0b375SMatthew G. Knepley 
8036a6e0b375SMatthew G. Knepley   Input Parameters:
8037bb7acecfSBarry Smith + dm    - The `DM`
8038a6e0b375SMatthew G. Knepley . time  - The time
8039a6e0b375SMatthew G. Knepley . funcs - The coordinate functions to evaluate, one per field
8040a6e0b375SMatthew G. Knepley . ctxs  - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
8041a6e0b375SMatthew G. Knepley - mode  - The insertion mode for values
8042a6e0b375SMatthew G. Knepley 
8043a6e0b375SMatthew G. Knepley   Output Parameter:
8044a6e0b375SMatthew G. Knepley . localX - vector
8045a6e0b375SMatthew G. Knepley 
804620f4b53cSBarry Smith   Calling sequence of `funcs`:
8047a6e0b375SMatthew G. Knepley + dim  - The spatial dimension
8048a4e35b19SJacob Faibussowitsch . time - The current timestep
8049a6e0b375SMatthew G. Knepley . x    - The coordinates
805077b739a6SMatthew Knepley . Nc   - The number of components
8051a6e0b375SMatthew G. Knepley . u    - The output field values
8052a6e0b375SMatthew G. Knepley - ctx  - optional user-defined function context
8053a6e0b375SMatthew G. Knepley 
8054a6e0b375SMatthew G. Knepley   Level: developer
8055a6e0b375SMatthew G. Knepley 
8056bb7acecfSBarry Smith   Developer Notes:
8057bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8058bb7acecfSBarry Smith 
8059bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8060bb7acecfSBarry Smith 
80611cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
8062a6e0b375SMatthew G. Knepley @*/
8063a4e35b19SJacob 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)
8064d71ae5a4SJacob Faibussowitsch {
80654d6f44ffSToby Isaac   PetscFunctionBegin;
80664d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8067064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
8068*fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfunctionlocal, time, funcs, ctxs, mode, localX);
80693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80704d6f44ffSToby Isaac }
80714d6f44ffSToby Isaac 
8072a6e0b375SMatthew G. Knepley /*@C
8073bb7acecfSBarry 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.
8074a6e0b375SMatthew G. Knepley 
807520f4b53cSBarry Smith   Collective
8076a6e0b375SMatthew G. Knepley 
8077a6e0b375SMatthew G. Knepley   Input Parameters:
8078bb7acecfSBarry Smith + dm     - The `DM`
8079a6e0b375SMatthew G. Knepley . time   - The time
8080a4e35b19SJacob Faibussowitsch . numIds - The number of ids
8081a4e35b19SJacob Faibussowitsch . ids    - The ids
8082a4e35b19SJacob Faibussowitsch . Nc     - The number of components
8083a4e35b19SJacob Faibussowitsch . comps  - The components
8084bb7acecfSBarry Smith . label  - The `DMLabel` selecting the portion of the mesh for projection
8085a6e0b375SMatthew G. Knepley . funcs  - The coordinate functions to evaluate, one per field
8086bb7acecfSBarry Smith . ctxs   - Optional array of contexts to pass to each coordinate function.  ctxs may be null.
8087a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8088a6e0b375SMatthew G. Knepley 
8089a6e0b375SMatthew G. Knepley   Output Parameter:
8090a6e0b375SMatthew G. Knepley . X - vector
8091a6e0b375SMatthew G. Knepley 
809220f4b53cSBarry Smith   Calling sequence of `funcs`:
8093a6e0b375SMatthew G. Knepley + dim  - The spatial dimension
8094a4e35b19SJacob Faibussowitsch . time - The current timestep
8095a6e0b375SMatthew G. Knepley . x    - The coordinates
809677b739a6SMatthew Knepley . Nc   - The number of components
8097a6e0b375SMatthew G. Knepley . u    - The output field values
8098a6e0b375SMatthew G. Knepley - ctx  - optional user-defined function context
8099a6e0b375SMatthew G. Knepley 
8100a6e0b375SMatthew G. Knepley   Level: developer
8101a6e0b375SMatthew G. Knepley 
8102bb7acecfSBarry Smith   Developer Notes:
8103bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8104bb7acecfSBarry Smith 
8105bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8106bb7acecfSBarry Smith 
81071cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabelLocal()`, `DMComputeL2Diff()`
8108a6e0b375SMatthew G. Knepley @*/
8109a4e35b19SJacob 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)
8110d71ae5a4SJacob Faibussowitsch {
81112c53366bSMatthew G. Knepley   Vec localX;
81122c53366bSMatthew G. Knepley 
81132c53366bSMatthew G. Knepley   PetscFunctionBegin;
81142c53366bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81159566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &localX));
8116f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
81179566063dSJacob Faibussowitsch   PetscCall(DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX));
81189566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
81199566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
81209566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &localX));
81213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81222c53366bSMatthew G. Knepley }
81232c53366bSMatthew G. Knepley 
8124a6e0b375SMatthew G. Knepley /*@C
8125bb7acecfSBarry 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.
8126a6e0b375SMatthew G. Knepley 
812720f4b53cSBarry Smith   Not Collective
8128a6e0b375SMatthew G. Knepley 
8129a6e0b375SMatthew G. Knepley   Input Parameters:
8130bb7acecfSBarry Smith + dm     - The `DM`
8131a6e0b375SMatthew G. Knepley . time   - The time
8132bb7acecfSBarry Smith . label  - The `DMLabel` selecting the portion of the mesh for projection
8133a4e35b19SJacob Faibussowitsch . numIds - The number of ids
8134a4e35b19SJacob Faibussowitsch . ids    - The ids
8135a4e35b19SJacob Faibussowitsch . Nc     - The number of components
8136a4e35b19SJacob Faibussowitsch . comps  - The components
8137a6e0b375SMatthew G. Knepley . funcs  - The coordinate functions to evaluate, one per field
8138a6e0b375SMatthew G. Knepley . ctxs   - Optional array of contexts to pass to each coordinate function.  ctxs itself may be null.
8139a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8140a6e0b375SMatthew G. Knepley 
8141a6e0b375SMatthew G. Knepley   Output Parameter:
8142a6e0b375SMatthew G. Knepley . localX - vector
8143a6e0b375SMatthew G. Knepley 
814420f4b53cSBarry Smith   Calling sequence of `funcs`:
8145a6e0b375SMatthew G. Knepley + dim  - The spatial dimension
8146a4e35b19SJacob Faibussowitsch . time - The current time
8147a6e0b375SMatthew G. Knepley . x    - The coordinates
814877b739a6SMatthew Knepley . Nc   - The number of components
8149a6e0b375SMatthew G. Knepley . u    - The output field values
8150a6e0b375SMatthew G. Knepley - ctx  - optional user-defined function context
8151a6e0b375SMatthew G. Knepley 
8152a6e0b375SMatthew G. Knepley   Level: developer
8153a6e0b375SMatthew G. Knepley 
8154bb7acecfSBarry Smith   Developer Notes:
8155bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8156bb7acecfSBarry Smith 
8157bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8158bb7acecfSBarry Smith 
81591cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabel()`, `DMComputeL2Diff()`
8160a6e0b375SMatthew G. Knepley @*/
8161a4e35b19SJacob 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)
8162d71ae5a4SJacob Faibussowitsch {
81634d6f44ffSToby Isaac   PetscFunctionBegin;
81644d6f44ffSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8165064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
8166*fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfunctionlabellocal, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);
81673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81684d6f44ffSToby Isaac }
81692716604bSToby Isaac 
8170a6e0b375SMatthew G. Knepley /*@C
8171bb7acecfSBarry 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.
8172a6e0b375SMatthew G. Knepley 
817320f4b53cSBarry Smith   Not Collective
8174a6e0b375SMatthew G. Knepley 
8175a6e0b375SMatthew G. Knepley   Input Parameters:
8176bb7acecfSBarry Smith + dm     - The `DM`
8177a6e0b375SMatthew G. Knepley . time   - The time
817820f4b53cSBarry Smith . localU - The input field vector; may be `NULL` if projection is defined purely by coordinates
8179a6e0b375SMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8180a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8181a6e0b375SMatthew G. Knepley 
8182a6e0b375SMatthew G. Knepley   Output Parameter:
8183a6e0b375SMatthew G. Knepley . localX - The output vector
8184a6e0b375SMatthew G. Knepley 
818520f4b53cSBarry Smith   Calling sequence of `funcs`:
8186a6e0b375SMatthew G. Knepley + dim          - The spatial dimension
8187a6e0b375SMatthew G. Knepley . Nf           - The number of input fields
8188a6e0b375SMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8189a6e0b375SMatthew G. Knepley . uOff         - The offset of each field in u[]
8190a6e0b375SMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8191a6e0b375SMatthew G. Knepley . u            - The field values at this point in space
8192a6e0b375SMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8193a6e0b375SMatthew G. Knepley . u_x          - The field derivatives at this point in space
8194a6e0b375SMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8195a6e0b375SMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8196a6e0b375SMatthew G. Knepley . a            - The auxiliary field values at this point in space
8197a6e0b375SMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8198a6e0b375SMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8199a6e0b375SMatthew G. Knepley . t            - The current time
8200a6e0b375SMatthew G. Knepley . x            - The coordinates of this point
8201a6e0b375SMatthew G. Knepley . numConstants - The number of constants
8202a6e0b375SMatthew G. Knepley . constants    - The value of each constant
8203a6e0b375SMatthew G. Knepley - f            - The value of the function at this point in space
8204a6e0b375SMatthew G. Knepley 
8205bb7acecfSBarry Smith   Note:
8206bb7acecfSBarry 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.
8207bb7acecfSBarry 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
8208bb7acecfSBarry 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
8209a6e0b375SMatthew 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.
8210a6e0b375SMatthew G. Knepley 
8211a6e0b375SMatthew G. Knepley   Level: intermediate
8212a6e0b375SMatthew G. Knepley 
8213bb7acecfSBarry Smith   Developer Notes:
8214bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8215bb7acecfSBarry Smith 
8216bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8217bb7acecfSBarry Smith 
8218a4e35b19SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`,
8219a4e35b19SJacob Faibussowitsch `DMProjectFunction()`, `DMComputeL2Diff()`
8220a6e0b375SMatthew G. Knepley @*/
8221a4e35b19SJacob 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)
8222d71ae5a4SJacob Faibussowitsch {
82238c6c5593SMatthew G. Knepley   PetscFunctionBegin;
82248c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8225eb8f539aSJed Brown   if (localU) PetscValidHeaderSpecific(localU, VEC_CLASSID, 3);
82268c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(localX, VEC_CLASSID, 6);
8227*fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfieldlocal, time, localU, funcs, mode, localX);
82283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82298c6c5593SMatthew G. Knepley }
82308c6c5593SMatthew G. Knepley 
8231a6e0b375SMatthew G. Knepley /*@C
8232a6e0b375SMatthew 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.
8233a6e0b375SMatthew G. Knepley 
823420f4b53cSBarry Smith   Not Collective
8235a6e0b375SMatthew G. Knepley 
8236a6e0b375SMatthew G. Knepley   Input Parameters:
8237bb7acecfSBarry Smith + dm     - The `DM`
8238a6e0b375SMatthew G. Knepley . time   - The time
8239bb7acecfSBarry Smith . label  - The `DMLabel` marking the portion of the domain to output
8240a6e0b375SMatthew G. Knepley . numIds - The number of label ids to use
8241a6e0b375SMatthew G. Knepley . ids    - The label ids to use for marking
8242bb7acecfSBarry Smith . Nc     - The number of components to set in the output, or `PETSC_DETERMINE` for all components
824320f4b53cSBarry Smith . comps  - The components to set in the output, or `NULL` for all components
8244a6e0b375SMatthew G. Knepley . localU - The input field vector
8245a6e0b375SMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8246a6e0b375SMatthew G. Knepley - mode   - The insertion mode for values
8247a6e0b375SMatthew G. Knepley 
8248a6e0b375SMatthew G. Knepley   Output Parameter:
8249a6e0b375SMatthew G. Knepley . localX - The output vector
8250a6e0b375SMatthew G. Knepley 
825120f4b53cSBarry Smith   Calling sequence of `funcs`:
8252a6e0b375SMatthew G. Knepley + dim          - The spatial dimension
8253a6e0b375SMatthew G. Knepley . Nf           - The number of input fields
8254a6e0b375SMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8255a6e0b375SMatthew G. Knepley . uOff         - The offset of each field in u[]
8256a6e0b375SMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8257a6e0b375SMatthew G. Knepley . u            - The field values at this point in space
8258a6e0b375SMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8259a6e0b375SMatthew G. Knepley . u_x          - The field derivatives at this point in space
8260a6e0b375SMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8261a6e0b375SMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8262a6e0b375SMatthew G. Knepley . a            - The auxiliary field values at this point in space
8263a6e0b375SMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8264a6e0b375SMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8265a6e0b375SMatthew G. Knepley . t            - The current time
8266a6e0b375SMatthew G. Knepley . x            - The coordinates of this point
8267a6e0b375SMatthew G. Knepley . numConstants - The number of constants
8268a6e0b375SMatthew G. Knepley . constants    - The value of each constant
8269a6e0b375SMatthew G. Knepley - f            - The value of the function at this point in space
8270a6e0b375SMatthew G. Knepley 
8271bb7acecfSBarry Smith   Note:
8272bb7acecfSBarry 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.
8273bb7acecfSBarry 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
8274bb7acecfSBarry 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
8275a6e0b375SMatthew 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.
8276a6e0b375SMatthew G. Knepley 
8277a6e0b375SMatthew G. Knepley   Level: intermediate
8278a6e0b375SMatthew G. Knepley 
8279bb7acecfSBarry Smith   Developer Notes:
8280bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8281bb7acecfSBarry Smith 
8282bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8283bb7acecfSBarry Smith 
82841cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabel()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8285a6e0b375SMatthew G. Knepley @*/
8286a4e35b19SJacob 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)
8287d71ae5a4SJacob Faibussowitsch {
82888c6c5593SMatthew G. Knepley   PetscFunctionBegin;
82898c6c5593SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8290064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8291064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
8292*fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectfieldlabellocal, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
82933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82948c6c5593SMatthew G. Knepley }
82958c6c5593SMatthew G. Knepley 
82962716604bSToby Isaac /*@C
8297d29d7c6eSMatthew 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.
8298d29d7c6eSMatthew G. Knepley 
829920f4b53cSBarry Smith   Not Collective
8300d29d7c6eSMatthew G. Knepley 
8301d29d7c6eSMatthew G. Knepley   Input Parameters:
8302bb7acecfSBarry Smith + dm     - The `DM`
8303d29d7c6eSMatthew G. Knepley . time   - The time
8304bb7acecfSBarry Smith . label  - The `DMLabel` marking the portion of the domain to output
8305d29d7c6eSMatthew G. Knepley . numIds - The number of label ids to use
8306d29d7c6eSMatthew G. Knepley . ids    - The label ids to use for marking
8307bb7acecfSBarry Smith . Nc     - The number of components to set in the output, or `PETSC_DETERMINE` for all components
830820f4b53cSBarry Smith . comps  - The components to set in the output, or `NULL` for all components
8309d29d7c6eSMatthew G. Knepley . U      - The input field vector
8310d29d7c6eSMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8311d29d7c6eSMatthew G. Knepley - mode   - The insertion mode for values
8312d29d7c6eSMatthew G. Knepley 
8313d29d7c6eSMatthew G. Knepley   Output Parameter:
8314d29d7c6eSMatthew G. Knepley . X - The output vector
8315d29d7c6eSMatthew G. Knepley 
831620f4b53cSBarry Smith   Calling sequence of `funcs`:
8317d29d7c6eSMatthew G. Knepley + dim          - The spatial dimension
8318d29d7c6eSMatthew G. Knepley . Nf           - The number of input fields
8319d29d7c6eSMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8320d29d7c6eSMatthew G. Knepley . uOff         - The offset of each field in u[]
8321d29d7c6eSMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8322d29d7c6eSMatthew G. Knepley . u            - The field values at this point in space
8323d29d7c6eSMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8324d29d7c6eSMatthew G. Knepley . u_x          - The field derivatives at this point in space
8325d29d7c6eSMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8326d29d7c6eSMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8327d29d7c6eSMatthew G. Knepley . a            - The auxiliary field values at this point in space
8328d29d7c6eSMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8329d29d7c6eSMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8330d29d7c6eSMatthew G. Knepley . t            - The current time
8331d29d7c6eSMatthew G. Knepley . x            - The coordinates of this point
8332d29d7c6eSMatthew G. Knepley . numConstants - The number of constants
8333d29d7c6eSMatthew G. Knepley . constants    - The value of each constant
8334d29d7c6eSMatthew G. Knepley - f            - The value of the function at this point in space
8335d29d7c6eSMatthew G. Knepley 
8336bb7acecfSBarry Smith   Note:
8337bb7acecfSBarry 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.
8338bb7acecfSBarry 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
8339bb7acecfSBarry 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
8340d29d7c6eSMatthew 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.
8341d29d7c6eSMatthew G. Knepley 
8342d29d7c6eSMatthew G. Knepley   Level: intermediate
8343d29d7c6eSMatthew G. Knepley 
8344bb7acecfSBarry Smith   Developer Notes:
8345bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8346bb7acecfSBarry Smith 
8347bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8348bb7acecfSBarry Smith 
83491cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8350d29d7c6eSMatthew G. Knepley @*/
8351a4e35b19SJacob 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)
8352d71ae5a4SJacob Faibussowitsch {
8353d29d7c6eSMatthew G. Knepley   DM  dmIn;
8354d29d7c6eSMatthew G. Knepley   Vec localU, localX;
8355d29d7c6eSMatthew G. Knepley 
8356d29d7c6eSMatthew G. Knepley   PetscFunctionBegin;
8357d29d7c6eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8358d29d7c6eSMatthew G. Knepley   PetscCall(VecGetDM(U, &dmIn));
8359d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dmIn, &localU));
8360d29d7c6eSMatthew G. Knepley   PetscCall(DMGetLocalVector(dm, &localX));
8361f60fa741SMatthew G. Knepley   PetscCall(VecSet(localX, 0.));
836272fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalBegin(dmIn, U, mode, localU));
836372fc1ce5SMatthew G. Knepley   PetscCall(DMGlobalToLocalEnd(dmIn, U, mode, localU));
8364d29d7c6eSMatthew G. Knepley   PetscCall(DMProjectFieldLabelLocal(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX));
8365d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalBegin(dm, localX, mode, X));
8366d29d7c6eSMatthew G. Knepley   PetscCall(DMLocalToGlobalEnd(dm, localX, mode, X));
8367d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dm, &localX));
8368d29d7c6eSMatthew G. Knepley   PetscCall(DMRestoreLocalVector(dmIn, &localU));
83693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8370d29d7c6eSMatthew G. Knepley }
8371d29d7c6eSMatthew G. Knepley 
8372d29d7c6eSMatthew G. Knepley /*@C
8373ece3a9fcSMatthew 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.
8374ece3a9fcSMatthew G. Knepley 
837520f4b53cSBarry Smith   Not Collective
8376ece3a9fcSMatthew G. Knepley 
8377ece3a9fcSMatthew G. Knepley   Input Parameters:
8378bb7acecfSBarry Smith + dm     - The `DM`
8379ece3a9fcSMatthew G. Knepley . time   - The time
8380bb7acecfSBarry Smith . label  - The `DMLabel` marking the portion of the domain boundary to output
8381ece3a9fcSMatthew G. Knepley . numIds - The number of label ids to use
8382ece3a9fcSMatthew G. Knepley . ids    - The label ids to use for marking
8383bb7acecfSBarry Smith . Nc     - The number of components to set in the output, or `PETSC_DETERMINE` for all components
838420f4b53cSBarry Smith . comps  - The components to set in the output, or `NULL` for all components
8385ece3a9fcSMatthew G. Knepley . localU - The input field vector
8386ece3a9fcSMatthew G. Knepley . funcs  - The functions to evaluate, one per field
8387ece3a9fcSMatthew G. Knepley - mode   - The insertion mode for values
8388ece3a9fcSMatthew G. Knepley 
8389ece3a9fcSMatthew G. Knepley   Output Parameter:
8390ece3a9fcSMatthew G. Knepley . localX - The output vector
8391ece3a9fcSMatthew G. Knepley 
839220f4b53cSBarry Smith   Calling sequence of `funcs`:
8393ece3a9fcSMatthew G. Knepley + dim          - The spatial dimension
8394ece3a9fcSMatthew G. Knepley . Nf           - The number of input fields
8395ece3a9fcSMatthew G. Knepley . NfAux        - The number of input auxiliary fields
8396ece3a9fcSMatthew G. Knepley . uOff         - The offset of each field in u[]
8397ece3a9fcSMatthew G. Knepley . uOff_x       - The offset of each field in u_x[]
8398ece3a9fcSMatthew G. Knepley . u            - The field values at this point in space
8399ece3a9fcSMatthew G. Knepley . u_t          - The field time derivative at this point in space (or NULL)
8400ece3a9fcSMatthew G. Knepley . u_x          - The field derivatives at this point in space
8401ece3a9fcSMatthew G. Knepley . aOff         - The offset of each auxiliary field in u[]
8402ece3a9fcSMatthew G. Knepley . aOff_x       - The offset of each auxiliary field in u_x[]
8403ece3a9fcSMatthew G. Knepley . a            - The auxiliary field values at this point in space
8404ece3a9fcSMatthew G. Knepley . a_t          - The auxiliary field time derivative at this point in space (or NULL)
8405ece3a9fcSMatthew G. Knepley . a_x          - The auxiliary field derivatives at this point in space
8406ece3a9fcSMatthew G. Knepley . t            - The current time
8407ece3a9fcSMatthew G. Knepley . x            - The coordinates of this point
8408ece3a9fcSMatthew G. Knepley . n            - The face normal
8409ece3a9fcSMatthew G. Knepley . numConstants - The number of constants
8410ece3a9fcSMatthew G. Knepley . constants    - The value of each constant
8411ece3a9fcSMatthew G. Knepley - f            - The value of the function at this point in space
8412ece3a9fcSMatthew G. Knepley 
8413ece3a9fcSMatthew G. Knepley   Note:
8414bb7acecfSBarry 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.
8415bb7acecfSBarry 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
8416bb7acecfSBarry 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
8417ece3a9fcSMatthew 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.
8418ece3a9fcSMatthew G. Knepley 
8419ece3a9fcSMatthew G. Knepley   Level: intermediate
8420ece3a9fcSMatthew G. Knepley 
8421bb7acecfSBarry Smith   Developer Notes:
8422bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8423bb7acecfSBarry Smith 
8424bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8425bb7acecfSBarry Smith 
84261cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectField()`, `DMProjectFieldLabelLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`
8427ece3a9fcSMatthew G. Knepley @*/
8428a4e35b19SJacob 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)
8429d71ae5a4SJacob Faibussowitsch {
8430ece3a9fcSMatthew G. Knepley   PetscFunctionBegin;
8431ece3a9fcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8432064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localU, VEC_CLASSID, 8);
8433064a246eSJacob Faibussowitsch   PetscValidHeaderSpecific(localX, VEC_CLASSID, 11);
8434*fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, projectbdfieldlabellocal, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);
84353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8436ece3a9fcSMatthew G. Knepley }
8437ece3a9fcSMatthew G. Knepley 
8438ece3a9fcSMatthew G. Knepley /*@C
84392716604bSToby Isaac   DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
84402716604bSToby Isaac 
844120f4b53cSBarry Smith   Collective
8442bb7acecfSBarry Smith 
84432716604bSToby Isaac   Input Parameters:
8444bb7acecfSBarry Smith + dm    - The `DM`
84450709b2feSToby Isaac . time  - The time
84462716604bSToby Isaac . funcs - The functions to evaluate for each field component
84472716604bSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8448574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
84492716604bSToby Isaac 
84502716604bSToby Isaac   Output Parameter:
84512716604bSToby Isaac . diff - The diff ||u - u_h||_2
84522716604bSToby Isaac 
84532716604bSToby Isaac   Level: developer
84542716604bSToby Isaac 
8455bb7acecfSBarry Smith   Developer Notes:
8456bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8457bb7acecfSBarry Smith 
8458bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8459bb7acecfSBarry Smith 
84601cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
84612716604bSToby Isaac @*/
8462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
8463d71ae5a4SJacob Faibussowitsch {
84642716604bSToby Isaac   PetscFunctionBegin;
84652716604bSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8466b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
8467*fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, computel2diff, time, funcs, ctxs, X, diff);
84683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84692716604bSToby Isaac }
8470b698f381SToby Isaac 
8471b698f381SToby Isaac /*@C
8472b698f381SToby Isaac   DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h.
8473b698f381SToby Isaac 
847420f4b53cSBarry Smith   Collective
8475d083f849SBarry Smith 
8476b698f381SToby Isaac   Input Parameters:
8477bb7acecfSBarry Smith + dm    - The `DM`
8478a4e35b19SJacob Faibussowitsch . time  - The time
8479b698f381SToby Isaac . funcs - The gradient functions to evaluate for each field component
8480b698f381SToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8481574a98acSMatthew G. Knepley . X     - The coefficient vector u_h, a global vector
8482b698f381SToby Isaac - n     - The vector to project along
8483b698f381SToby Isaac 
8484b698f381SToby Isaac   Output Parameter:
8485b698f381SToby Isaac . diff - The diff ||(grad u - grad u_h) . n||_2
8486b698f381SToby Isaac 
8487b698f381SToby Isaac   Level: developer
8488b698f381SToby Isaac 
8489bb7acecfSBarry Smith   Developer Notes:
8490bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8491bb7acecfSBarry Smith 
8492bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8493bb7acecfSBarry Smith 
84941cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2Diff()`, `DMComputeL2FieldDiff()`
8495b698f381SToby Isaac @*/
8496d71ae5a4SJacob 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)
8497d71ae5a4SJacob Faibussowitsch {
8498b698f381SToby Isaac   PetscFunctionBegin;
8499b698f381SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8500b698f381SToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
8501*fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, computel2gradientdiff, time, funcs, ctxs, X, n, diff);
85023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8503b698f381SToby Isaac }
8504b698f381SToby Isaac 
85052a16baeaSToby Isaac /*@C
85062a16baeaSToby Isaac   DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components.
85072a16baeaSToby Isaac 
850820f4b53cSBarry Smith   Collective
8509d083f849SBarry Smith 
85102a16baeaSToby Isaac   Input Parameters:
8511bb7acecfSBarry Smith + dm    - The `DM`
85122a16baeaSToby Isaac . time  - The time
85132a16baeaSToby Isaac . funcs - The functions to evaluate for each field component
85142a16baeaSToby Isaac . ctxs  - Optional array of contexts to pass to each function, or NULL.
8515574a98acSMatthew G. Knepley - X     - The coefficient vector u_h, a global vector
85162a16baeaSToby Isaac 
85172a16baeaSToby Isaac   Output Parameter:
85182a16baeaSToby Isaac . diff - The array of differences, ||u^f - u^f_h||_2
85192a16baeaSToby Isaac 
85202a16baeaSToby Isaac   Level: developer
85212a16baeaSToby Isaac 
8522bb7acecfSBarry Smith   Developer Notes:
8523bb7acecfSBarry Smith   This API is specific to only particular usage of `DM`
8524bb7acecfSBarry Smith 
8525bb7acecfSBarry Smith   The notes need to provide some information about what has to be provided to the `DM` to be able to perform the computation.
8526bb7acecfSBarry Smith 
852742747ad1SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMProjectFunction()`, `DMComputeL2GradientDiff()`
85282a16baeaSToby Isaac @*/
8529d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[])
8530d71ae5a4SJacob Faibussowitsch {
85312a16baeaSToby Isaac   PetscFunctionBegin;
85322a16baeaSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85332a16baeaSToby Isaac   PetscValidHeaderSpecific(X, VEC_CLASSID, 5);
8534*fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, computel2fielddiff, time, funcs, ctxs, X, diff);
85353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
85362a16baeaSToby Isaac }
85372a16baeaSToby Isaac 
8538df0b854cSToby Isaac /*@C
8539bb7acecfSBarry Smith   DMGetNeighbors - Gets an array containing the MPI ranks of all the processes neighbors
8540502a2867SDave May 
8541502a2867SDave May   Not Collective
8542502a2867SDave May 
8543502a2867SDave May   Input Parameter:
8544bb7acecfSBarry Smith . dm - The `DM`
8545502a2867SDave May 
85460a19bb7dSprj-   Output Parameters:
85470a19bb7dSprj- + nranks - the number of neighbours
85480a19bb7dSprj- - ranks  - the neighbors ranks
8549502a2867SDave May 
85509bdbcad8SBarry Smith   Level: beginner
85519bdbcad8SBarry Smith 
8552bb7acecfSBarry Smith   Note:
8553bb7acecfSBarry Smith   Do not free the array, it is freed when the `DM` is destroyed.
8554502a2867SDave May 
85551cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDAGetNeighbors()`, `PetscSFGetRootRanks()`
8556502a2867SDave May @*/
8557d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNeighbors(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
8558d71ae5a4SJacob Faibussowitsch {
8559502a2867SDave May   PetscFunctionBegin;
8560502a2867SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8561*fa1e479aSStefano Zampini   PetscUseTypeMethod(dm, getneighbors, nranks, ranks);
85623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8563502a2867SDave May }
8564502a2867SDave May 
8565531c7667SBarry Smith #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */
8566531c7667SBarry Smith 
8567531c7667SBarry Smith /*
8568531c7667SBarry Smith     Converts the input vector to a ghosted vector and then calls the standard coloring code.
85692b6f951bSStefano Zampini     This must be a different function because it requires DM which is not defined in the Mat library
8570531c7667SBarry Smith */
857166976f2fSJacob Faibussowitsch static PetscErrorCode MatFDColoringApply_AIJDM(Mat J, MatFDColoring coloring, Vec x1, void *sctx)
8572d71ae5a4SJacob Faibussowitsch {
8573531c7667SBarry Smith   PetscFunctionBegin;
8574531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8575531c7667SBarry Smith     Vec x1local;
8576531c7667SBarry Smith     DM  dm;
85779566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
85787a8be351SBarry Smith     PetscCheck(dm, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_INCOMP, "IS_COLORING_LOCAL requires a DM");
85799566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &x1local));
85809566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, x1, INSERT_VALUES, x1local));
85819566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, x1, INSERT_VALUES, x1local));
8582531c7667SBarry Smith     x1 = x1local;
8583531c7667SBarry Smith   }
85849566063dSJacob Faibussowitsch   PetscCall(MatFDColoringApply_AIJ(J, coloring, x1, sctx));
8585531c7667SBarry Smith   if (coloring->ctype == IS_COLORING_LOCAL) {
8586531c7667SBarry Smith     DM dm;
85879566063dSJacob Faibussowitsch     PetscCall(MatGetDM(J, &dm));
85889566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &x1));
8589531c7667SBarry Smith   }
85903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8591531c7667SBarry Smith }
8592531c7667SBarry Smith 
8593531c7667SBarry Smith /*@
8594bb7acecfSBarry Smith   MatFDColoringUseDM - allows a `MatFDColoring` object to use the `DM` associated with the matrix to compute a `IS_COLORING_LOCAL` coloring
8595531c7667SBarry Smith 
8596a4e35b19SJacob Faibussowitsch   Input Parameters:
8597a4e35b19SJacob Faibussowitsch + coloring   - The matrix to get the `DM` from
8598a4e35b19SJacob Faibussowitsch - fdcoloring - the `MatFDColoring` object
8599531c7667SBarry Smith 
86009bdbcad8SBarry Smith   Level: advanced
86019bdbcad8SBarry Smith 
860260225df5SJacob Faibussowitsch   Developer Notes:
8603bb7acecfSBarry Smith   this routine exists because the PETSc `Mat` library does not know about the `DM` objects
8604531c7667SBarry Smith 
86051cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `MatFDColoring`, `MatFDColoringCreate()`, `ISColoringType`
8606531c7667SBarry Smith @*/
8607d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFDColoringUseDM(Mat coloring, MatFDColoring fdcoloring)
8608d71ae5a4SJacob Faibussowitsch {
8609531c7667SBarry Smith   PetscFunctionBegin;
8610531c7667SBarry Smith   coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM;
86113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8612531c7667SBarry Smith }
86138320bc6fSPatrick Sanan 
86148320bc6fSPatrick Sanan /*@
8615bb7acecfSBarry Smith   DMGetCompatibility - determine if two `DM`s are compatible
86168320bc6fSPatrick Sanan 
86178320bc6fSPatrick Sanan   Collective
86188320bc6fSPatrick Sanan 
86198320bc6fSPatrick Sanan   Input Parameters:
8620bb7acecfSBarry Smith + dm1 - the first `DM`
8621bb7acecfSBarry Smith - dm2 - the second `DM`
86228320bc6fSPatrick Sanan 
86238320bc6fSPatrick Sanan   Output Parameters:
8624bb7acecfSBarry Smith + compatible - whether or not the two `DM`s are compatible
8625bb7acecfSBarry Smith - set        - whether or not the compatible value was actually determined and set
86268320bc6fSPatrick Sanan 
862720f4b53cSBarry Smith   Level: advanced
862820f4b53cSBarry Smith 
86298320bc6fSPatrick Sanan   Notes:
8630bb7acecfSBarry Smith   Two `DM`s are deemed compatible if they represent the same parallel decomposition
86313d862458SPatrick Sanan   of the same topology. This implies that the section (field data) on one
86328320bc6fSPatrick Sanan   "makes sense" with respect to the topology and parallel decomposition of the other.
8633bb7acecfSBarry Smith   Loosely speaking, compatible `DM`s represent the same domain and parallel
86343d862458SPatrick Sanan   decomposition, but hold different data.
86358320bc6fSPatrick Sanan 
86368320bc6fSPatrick Sanan   Typically, one would confirm compatibility if intending to simultaneously iterate
8637bb7acecfSBarry Smith   over a pair of vectors obtained from different `DM`s.
86388320bc6fSPatrick Sanan 
8639bb7acecfSBarry Smith   For example, two `DMDA` objects are compatible if they have the same local
86408320bc6fSPatrick Sanan   and global sizes and the same stencil width. They can have different numbers
86418320bc6fSPatrick Sanan   of degrees of freedom per node. Thus, one could use the node numbering from
8642bb7acecfSBarry Smith   either `DM` in bounds for a loop over vectors derived from either `DM`.
86438320bc6fSPatrick Sanan 
8644bb7acecfSBarry Smith   Consider the operation of summing data living on a 2-dof `DMDA` to data living
8645bb7acecfSBarry Smith   on a 1-dof `DMDA`, which should be compatible, as in the following snippet.
86468320bc6fSPatrick Sanan .vb
86478320bc6fSPatrick Sanan   ...
86489566063dSJacob Faibussowitsch   PetscCall(DMGetCompatibility(da1,da2,&compatible,&set));
86498320bc6fSPatrick Sanan   if (set && compatible)  {
86509566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da1,vec1,&arr1));
86519566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayDOF(da2,vec2,&arr2));
86529566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL));
86538320bc6fSPatrick Sanan     for (j=y; j<y+n; ++j) {
86548320bc6fSPatrick Sanan       for (i=x; i<x+m, ++i) {
86558320bc6fSPatrick Sanan         arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1];
86568320bc6fSPatrick Sanan       }
86578320bc6fSPatrick Sanan     }
86589566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da1,vec1,&arr1));
86599566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayDOF(da2,vec2,&arr2));
86608320bc6fSPatrick Sanan   } else {
86618320bc6fSPatrick Sanan     SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible");
86628320bc6fSPatrick Sanan   }
86638320bc6fSPatrick Sanan   ...
86648320bc6fSPatrick Sanan .ve
86658320bc6fSPatrick Sanan 
8666bb7acecfSBarry Smith   Checking compatibility might be expensive for a given implementation of `DM`,
86678320bc6fSPatrick Sanan   or might be impossible to unambiguously confirm or deny. For this reason,
86688320bc6fSPatrick Sanan   this function may decline to determine compatibility, and hence users should
86698320bc6fSPatrick Sanan   always check the "set" output parameter.
86708320bc6fSPatrick Sanan 
8671bb7acecfSBarry Smith   A `DM` is always compatible with itself.
86728320bc6fSPatrick Sanan 
8673bb7acecfSBarry Smith   In the current implementation, `DM`s which live on "unequal" communicators
86748320bc6fSPatrick Sanan   (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed
86758320bc6fSPatrick Sanan   incompatible.
86768320bc6fSPatrick Sanan 
86778320bc6fSPatrick Sanan   This function is labeled "Collective," as information about all subdomains
8678bb7acecfSBarry Smith   is required on each rank. However, in `DM` implementations which store all this
86798320bc6fSPatrick Sanan   information locally, this function may be merely "Logically Collective".
86808320bc6fSPatrick Sanan 
868160225df5SJacob Faibussowitsch   Developer Notes:
8682bb7acecfSBarry Smith   Compatibility is assumed to be a symmetric concept; `DM` A is compatible with `DM` B
86833d862458SPatrick Sanan   iff B is compatible with A. Thus, this function checks the implementations
8684a5bc1bf3SBarry Smith   of both dm and dmc (if they are of different types), attempting to determine
8685bb7acecfSBarry Smith   compatibility. It is left to `DM` implementers to ensure that symmetry is
86868320bc6fSPatrick Sanan   preserved. The simplest way to do this is, when implementing type-specific
86873d862458SPatrick Sanan   logic for this function, is to check for existing logic in the implementation
8688bb7acecfSBarry Smith   of other `DM` types and let *set = PETSC_FALSE if found.
86898320bc6fSPatrick Sanan 
86901cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMDACreateCompatibleDMDA()`, `DMStagCreateCompatibleDMStag()`
86918320bc6fSPatrick Sanan @*/
8692d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCompatibility(DM dm1, DM dm2, PetscBool *compatible, PetscBool *set)
8693d71ae5a4SJacob Faibussowitsch {
86948320bc6fSPatrick Sanan   PetscMPIInt compareResult;
86958320bc6fSPatrick Sanan   DMType      type, type2;
86968320bc6fSPatrick Sanan   PetscBool   sameType;
86978320bc6fSPatrick Sanan 
86988320bc6fSPatrick Sanan   PetscFunctionBegin;
8699a5bc1bf3SBarry Smith   PetscValidHeaderSpecific(dm1, DM_CLASSID, 1);
87008320bc6fSPatrick Sanan   PetscValidHeaderSpecific(dm2, DM_CLASSID, 2);
87018320bc6fSPatrick Sanan 
87028320bc6fSPatrick Sanan   /* Declare a DM compatible with itself */
8703a5bc1bf3SBarry Smith   if (dm1 == dm2) {
87048320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
87058320bc6fSPatrick Sanan     *compatible = PETSC_TRUE;
87063ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
87078320bc6fSPatrick Sanan   }
87088320bc6fSPatrick Sanan 
87098320bc6fSPatrick Sanan   /* Declare a DM incompatible with a DM that lives on an "unequal"
87108320bc6fSPatrick Sanan      communicator. Note that this does not preclude compatibility with
87118320bc6fSPatrick Sanan      DMs living on "congruent" or "similar" communicators, but this must be
87128320bc6fSPatrick Sanan      determined by the implementation-specific logic */
87139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)dm1), PetscObjectComm((PetscObject)dm2), &compareResult));
87148320bc6fSPatrick Sanan   if (compareResult == MPI_UNEQUAL) {
87158320bc6fSPatrick Sanan     *set        = PETSC_TRUE;
87168320bc6fSPatrick Sanan     *compatible = PETSC_FALSE;
87173ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
87188320bc6fSPatrick Sanan   }
87198320bc6fSPatrick Sanan 
87208320bc6fSPatrick Sanan   /* Pass to the implementation-specific routine, if one exists. */
8721a5bc1bf3SBarry Smith   if (dm1->ops->getcompatibility) {
8722dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm1, getcompatibility, dm2, compatible, set);
87233ba16761SJacob Faibussowitsch     if (*set) PetscFunctionReturn(PETSC_SUCCESS);
87248320bc6fSPatrick Sanan   }
87258320bc6fSPatrick Sanan 
8726a5bc1bf3SBarry Smith   /* If dm1 and dm2 are of different types, then attempt to check compatibility
87278320bc6fSPatrick Sanan      with an implementation of this function from dm2 */
87289566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm1, &type));
87299566063dSJacob Faibussowitsch   PetscCall(DMGetType(dm2, &type2));
87309566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(type, type2, &sameType));
87318320bc6fSPatrick Sanan   if (!sameType && dm2->ops->getcompatibility) {
8732dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm2, getcompatibility, dm1, compatible, set); /* Note argument order */
87338320bc6fSPatrick Sanan   } else {
87348320bc6fSPatrick Sanan     *set = PETSC_FALSE;
87358320bc6fSPatrick Sanan   }
87363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
87378320bc6fSPatrick Sanan }
8738c0f0dcc3SMatthew G. Knepley 
8739c0f0dcc3SMatthew G. Knepley /*@C
8740bb7acecfSBarry Smith   DMMonitorSet - Sets an additional monitor function that is to be used after a solve to monitor discretization performance.
8741c0f0dcc3SMatthew G. Knepley 
874220f4b53cSBarry Smith   Logically Collective
8743c0f0dcc3SMatthew G. Knepley 
8744c0f0dcc3SMatthew G. Knepley   Input Parameters:
874560225df5SJacob Faibussowitsch + dm             - the `DM`
8746c0f0dcc3SMatthew G. Knepley . f              - the monitor function
874720f4b53cSBarry Smith . mctx           - [optional] user-defined context for private data for the monitor routine (use `NULL` if no context is desired)
874820f4b53cSBarry Smith - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
8749c0f0dcc3SMatthew G. Knepley 
875020f4b53cSBarry Smith   Options Database Key:
875160225df5SJacob Faibussowitsch . -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to `DMMonitorSet()`, but
8752c0f0dcc3SMatthew G. Knepley                             does not cancel those set via the options database.
8753c0f0dcc3SMatthew G. Knepley 
87549bdbcad8SBarry Smith   Level: intermediate
87559bdbcad8SBarry Smith 
8756bb7acecfSBarry Smith   Note:
8757c0f0dcc3SMatthew G. Knepley   Several different monitoring routines may be set by calling
8758bb7acecfSBarry Smith   `DMMonitorSet()` multiple times or with `DMMonitorSetFromOptions()`; all will be called in the
8759c0f0dcc3SMatthew G. Knepley   order in which they were set.
8760c0f0dcc3SMatthew G. Knepley 
876160225df5SJacob Faibussowitsch   Fortran Notes:
8762bb7acecfSBarry Smith   Only a single monitor function can be set for each `DM` object
8763bb7acecfSBarry Smith 
876460225df5SJacob Faibussowitsch   Developer Notes:
8765bb7acecfSBarry Smith   This API has a generic name but seems specific to a very particular aspect of the use of `DM`
8766c0f0dcc3SMatthew G. Knepley 
87671cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorCancel()`, `DMMonitorSetFromOptions()`, `DMMonitor()`
8768c0f0dcc3SMatthew G. Knepley @*/
8769d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void **))
8770d71ae5a4SJacob Faibussowitsch {
8771c0f0dcc3SMatthew G. Knepley   PetscInt m;
8772c0f0dcc3SMatthew G. Knepley 
8773c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8774c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8775c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
8776c0f0dcc3SMatthew G. Knepley     PetscBool identical;
8777c0f0dcc3SMatthew G. Knepley 
87789566063dSJacob Faibussowitsch     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))f, mctx, monitordestroy, (PetscErrorCode(*)(void))dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical));
87793ba16761SJacob Faibussowitsch     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
8780c0f0dcc3SMatthew G. Knepley   }
87817a8be351SBarry Smith   PetscCheck(dm->numbermonitors < MAXDMMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set");
8782c0f0dcc3SMatthew G. Knepley   dm->monitor[dm->numbermonitors]          = f;
8783c0f0dcc3SMatthew G. Knepley   dm->monitordestroy[dm->numbermonitors]   = monitordestroy;
8784c0f0dcc3SMatthew G. Knepley   dm->monitorcontext[dm->numbermonitors++] = (void *)mctx;
87853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8786c0f0dcc3SMatthew G. Knepley }
8787c0f0dcc3SMatthew G. Knepley 
8788c0f0dcc3SMatthew G. Knepley /*@
8789bb7acecfSBarry Smith   DMMonitorCancel - Clears all the monitor functions for a `DM` object.
8790c0f0dcc3SMatthew G. Knepley 
879120f4b53cSBarry Smith   Logically Collective
8792c0f0dcc3SMatthew G. Knepley 
8793c0f0dcc3SMatthew G. Knepley   Input Parameter:
8794c0f0dcc3SMatthew G. Knepley . dm - the DM
8795c0f0dcc3SMatthew G. Knepley 
8796c0f0dcc3SMatthew G. Knepley   Options Database Key:
8797c0f0dcc3SMatthew G. Knepley . -dm_monitor_cancel - cancels all monitors that have been hardwired
8798bb7acecfSBarry Smith   into a code by calls to `DMonitorSet()`, but does not cancel those
8799c0f0dcc3SMatthew G. Knepley   set via the options database
8800c0f0dcc3SMatthew G. Knepley 
88019bdbcad8SBarry Smith   Level: intermediate
88029bdbcad8SBarry Smith 
8803bb7acecfSBarry Smith   Note:
8804bb7acecfSBarry Smith   There is no way to clear one specific monitor from a `DM` object.
8805c0f0dcc3SMatthew G. Knepley 
88061cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMMonitorSetFromOptions()`, `DMMonitor()`
8807c0f0dcc3SMatthew G. Knepley @*/
8808d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorCancel(DM dm)
8809d71ae5a4SJacob Faibussowitsch {
8810c0f0dcc3SMatthew G. Knepley   PetscInt m;
8811c0f0dcc3SMatthew G. Knepley 
8812c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8813c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8814c0f0dcc3SMatthew G. Knepley   for (m = 0; m < dm->numbermonitors; ++m) {
88159566063dSJacob Faibussowitsch     if (dm->monitordestroy[m]) PetscCall((*dm->monitordestroy[m])(&dm->monitorcontext[m]));
8816c0f0dcc3SMatthew G. Knepley   }
8817c0f0dcc3SMatthew G. Knepley   dm->numbermonitors = 0;
88183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8819c0f0dcc3SMatthew G. Knepley }
8820c0f0dcc3SMatthew G. Knepley 
8821c0f0dcc3SMatthew G. Knepley /*@C
8822c0f0dcc3SMatthew G. Knepley   DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user
8823c0f0dcc3SMatthew G. Knepley 
882420f4b53cSBarry Smith   Collective
8825c0f0dcc3SMatthew G. Knepley 
8826c0f0dcc3SMatthew G. Knepley   Input Parameters:
8827bb7acecfSBarry Smith + dm           - `DM` object you wish to monitor
8828c0f0dcc3SMatthew G. Knepley . name         - the monitor type one is seeking
8829c0f0dcc3SMatthew G. Knepley . help         - message indicating what monitoring is done
8830c0f0dcc3SMatthew G. Knepley . manual       - manual page for the monitor
8831c0f0dcc3SMatthew G. Knepley . monitor      - the monitor function
8832bb7acecfSBarry 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
8833c0f0dcc3SMatthew G. Knepley 
8834c0f0dcc3SMatthew G. Knepley   Output Parameter:
8835c0f0dcc3SMatthew G. Knepley . flg - Flag set if the monitor was created
8836c0f0dcc3SMatthew G. Knepley 
8837c0f0dcc3SMatthew G. Knepley   Level: developer
8838c0f0dcc3SMatthew G. Knepley 
88391cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
8840db781477SPatrick Sanan           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
884160225df5SJacob Faibussowitsch           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
8842db781477SPatrick Sanan           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
8843c2e3fba1SPatrick Sanan           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
8844db781477SPatrick Sanan           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
8845bb7acecfSBarry Smith           `PetscOptionsFList()`, `PetscOptionsEList()`, `DMMonitor()`, `DMMonitorSet()`
8846c0f0dcc3SMatthew G. Knepley @*/
8847d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg)
8848d71ae5a4SJacob Faibussowitsch {
8849c0f0dcc3SMatthew G. Knepley   PetscViewer       viewer;
8850c0f0dcc3SMatthew G. Knepley   PetscViewerFormat format;
8851c0f0dcc3SMatthew G. Knepley 
8852c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
8853c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)dm), ((PetscObject)dm)->options, ((PetscObject)dm)->prefix, name, &viewer, &format, flg));
8855c0f0dcc3SMatthew G. Knepley   if (*flg) {
8856c0f0dcc3SMatthew G. Knepley     PetscViewerAndFormat *vf;
8857c0f0dcc3SMatthew G. Knepley 
88589566063dSJacob Faibussowitsch     PetscCall(PetscViewerAndFormatCreate(viewer, format, &vf));
8859cd791dc2SBarry Smith     PetscCall(PetscOptionsRestoreViewer(&viewer));
88609566063dSJacob Faibussowitsch     if (monitorsetup) PetscCall((*monitorsetup)(dm, vf));
88619566063dSJacob Faibussowitsch     PetscCall(DMMonitorSet(dm, (PetscErrorCode(*)(DM, void *))monitor, vf, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy));
8862c0f0dcc3SMatthew G. Knepley   }
88633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8864c0f0dcc3SMatthew G. Knepley }
8865c0f0dcc3SMatthew G. Knepley 
8866c0f0dcc3SMatthew G. Knepley /*@
8867c0f0dcc3SMatthew G. Knepley   DMMonitor - runs the user provided monitor routines, if they exist
8868c0f0dcc3SMatthew G. Knepley 
886920f4b53cSBarry Smith   Collective
8870c0f0dcc3SMatthew G. Knepley 
88712fe279fdSBarry Smith   Input Parameter:
8872bb7acecfSBarry Smith . dm - The `DM`
8873c0f0dcc3SMatthew G. Knepley 
8874c0f0dcc3SMatthew G. Knepley   Level: developer
8875c0f0dcc3SMatthew G. Knepley 
8876a4e35b19SJacob Faibussowitsch   Developer Notes:
8877a4e35b19SJacob Faibussowitsch   Note should indicate when during the life of the `DM` the monitor is run. It appears to be
8878a4e35b19SJacob Faibussowitsch   related to the discretization process seems rather specialized since some `DM` have no
8879a4e35b19SJacob Faibussowitsch   concept of discretization.
8880bb7acecfSBarry Smith 
88811cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMMonitorSetFromOptions()`
8882c0f0dcc3SMatthew G. Knepley @*/
8883d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMonitor(DM dm)
8884d71ae5a4SJacob Faibussowitsch {
8885c0f0dcc3SMatthew G. Knepley   PetscInt m;
8886c0f0dcc3SMatthew G. Knepley 
8887c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
88883ba16761SJacob Faibussowitsch   if (!dm) PetscFunctionReturn(PETSC_SUCCESS);
8889c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
889048a46eb9SPierre Jolivet   for (m = 0; m < dm->numbermonitors; ++m) PetscCall((*dm->monitor[m])(dm, dm->monitorcontext[m]));
88913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8892c0f0dcc3SMatthew G. Knepley }
88932e4af2aeSMatthew G. Knepley 
88942e4af2aeSMatthew G. Knepley /*@
8895bb7acecfSBarry Smith   DMComputeError - Computes the error assuming the user has provided the exact solution functions
88962e4af2aeSMatthew G. Knepley 
889720f4b53cSBarry Smith   Collective
88982e4af2aeSMatthew G. Knepley 
88992e4af2aeSMatthew G. Knepley   Input Parameters:
8900bb7acecfSBarry Smith + dm  - The `DM`
89016b867d5aSJose E. Roman - sol - The solution vector
89022e4af2aeSMatthew G. Knepley 
89036b867d5aSJose E. Roman   Input/Output Parameter:
890420f4b53cSBarry Smith . errors - An array of length Nf, the number of fields, or `NULL` for no output; on output
89056b867d5aSJose E. Roman            contains the error in each field
89066b867d5aSJose E. Roman 
89076b867d5aSJose E. Roman   Output Parameter:
890820f4b53cSBarry Smith . errorVec - A vector to hold the cellwise error (may be `NULL`)
890920f4b53cSBarry Smith 
891020f4b53cSBarry Smith   Level: developer
89112e4af2aeSMatthew G. Knepley 
8912bb7acecfSBarry Smith   Note:
8913bb7acecfSBarry Smith   The exact solutions come from the `PetscDS` object, and the time comes from `DMGetOutputSequenceNumber()`.
89142e4af2aeSMatthew G. Knepley 
89151cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMMonitorSet()`, `DMGetRegionNumDS()`, `PetscDSGetExactSolution()`, `DMGetOutputSequenceNumber()`
89162e4af2aeSMatthew G. Knepley @*/
8917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec)
8918d71ae5a4SJacob Faibussowitsch {
89192e4af2aeSMatthew G. Knepley   PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *);
89202e4af2aeSMatthew G. Knepley   void    **ctxs;
89212e4af2aeSMatthew G. Knepley   PetscReal time;
89222e4af2aeSMatthew G. Knepley   PetscInt  Nf, f, Nds, s;
89232e4af2aeSMatthew G. Knepley 
89242e4af2aeSMatthew G. Knepley   PetscFunctionBegin;
89259566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
89269566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(Nf, &exactSol, Nf, &ctxs));
89279566063dSJacob Faibussowitsch   PetscCall(DMGetNumDS(dm, &Nds));
89282e4af2aeSMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
89292e4af2aeSMatthew G. Knepley     PetscDS         ds;
89302e4af2aeSMatthew G. Knepley     DMLabel         label;
89312e4af2aeSMatthew G. Knepley     IS              fieldIS;
89322e4af2aeSMatthew G. Knepley     const PetscInt *fields;
89332e4af2aeSMatthew G. Knepley     PetscInt        dsNf;
89342e4af2aeSMatthew G. Knepley 
893507218a29SMatthew G. Knepley     PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds, NULL));
89369566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(ds, &dsNf));
89379566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISGetIndices(fieldIS, &fields));
89382e4af2aeSMatthew G. Knepley     for (f = 0; f < dsNf; ++f) {
89392e4af2aeSMatthew G. Knepley       const PetscInt field = fields[f];
89409566063dSJacob Faibussowitsch       PetscCall(PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]));
89412e4af2aeSMatthew G. Knepley     }
89429566063dSJacob Faibussowitsch     if (fieldIS) PetscCall(ISRestoreIndices(fieldIS, &fields));
89432e4af2aeSMatthew G. Knepley   }
8944ad540459SPierre 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);
89459566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
89469566063dSJacob Faibussowitsch   if (errors) PetscCall(DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors));
89472e4af2aeSMatthew G. Knepley   if (errorVec) {
89482e4af2aeSMatthew G. Knepley     DM             edm;
89492e4af2aeSMatthew G. Knepley     DMPolytopeType ct;
89502e4af2aeSMatthew G. Knepley     PetscBool      simplex;
89512e4af2aeSMatthew G. Knepley     PetscInt       dim, cStart, Nf;
89522e4af2aeSMatthew G. Knepley 
89539566063dSJacob Faibussowitsch     PetscCall(DMClone(dm, &edm));
89549566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(edm, &dim));
89559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, NULL));
89569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cStart, &ct));
89572e4af2aeSMatthew G. Knepley     simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
89589566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
89592e4af2aeSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
89602e4af2aeSMatthew G. Knepley       PetscFE         fe, efe;
89612e4af2aeSMatthew G. Knepley       PetscQuadrature q;
89622e4af2aeSMatthew G. Knepley       const char     *name;
89632e4af2aeSMatthew G. Knepley 
89649566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe));
89659566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe));
89669566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)fe, &name));
89679566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)efe, name));
89689566063dSJacob Faibussowitsch       PetscCall(PetscFEGetQuadrature(fe, &q));
89699566063dSJacob Faibussowitsch       PetscCall(PetscFESetQuadrature(efe, q));
89709566063dSJacob Faibussowitsch       PetscCall(DMSetField(edm, f, NULL, (PetscObject)efe));
89719566063dSJacob Faibussowitsch       PetscCall(PetscFEDestroy(&efe));
89722e4af2aeSMatthew G. Knepley     }
89739566063dSJacob Faibussowitsch     PetscCall(DMCreateDS(edm));
89742e4af2aeSMatthew G. Knepley 
89759566063dSJacob Faibussowitsch     PetscCall(DMCreateGlobalVector(edm, errorVec));
89769566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)*errorVec, "Error"));
89779566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec));
89789566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&edm));
89792e4af2aeSMatthew G. Knepley   }
89809566063dSJacob Faibussowitsch   PetscCall(PetscFree2(exactSol, ctxs));
89813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
89822e4af2aeSMatthew G. Knepley }
89839a2a23afSMatthew G. Knepley 
89849a2a23afSMatthew G. Knepley /*@
8985bb7acecfSBarry Smith   DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this `DM`
89869a2a23afSMatthew G. Knepley 
898720f4b53cSBarry Smith   Not Collective
89889a2a23afSMatthew G. Knepley 
89899a2a23afSMatthew G. Knepley   Input Parameter:
8990bb7acecfSBarry Smith . dm - The `DM`
89919a2a23afSMatthew G. Knepley 
89929a2a23afSMatthew G. Knepley   Output Parameter:
8993a5b23f4aSJose E. Roman . numAux - The number of auxiliary data vectors
89949a2a23afSMatthew G. Knepley 
89959a2a23afSMatthew G. Knepley   Level: advanced
89969a2a23afSMatthew G. Knepley 
899760225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMSetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMGetAuxiliaryVec()`
89989a2a23afSMatthew G. Knepley @*/
8999d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux)
9000d71ae5a4SJacob Faibussowitsch {
90019a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90029a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90039566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetSize(dm->auxData, numAux));
90043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
90059a2a23afSMatthew G. Knepley }
90069a2a23afSMatthew G. Knepley 
90079a2a23afSMatthew G. Knepley /*@
9008ac17215fSMatthew G. Knepley   DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value, and equation part
90099a2a23afSMatthew G. Knepley 
901020f4b53cSBarry Smith   Not Collective
90119a2a23afSMatthew G. Knepley 
90129a2a23afSMatthew G. Knepley   Input Parameters:
9013bb7acecfSBarry Smith + dm    - The `DM`
9014bb7acecfSBarry Smith . label - The `DMLabel`
9015ac17215fSMatthew G. Knepley . value - The label value indicating the region
9016ac17215fSMatthew G. Knepley - part  - The equation part, or 0 if unused
90179a2a23afSMatthew G. Knepley 
90189a2a23afSMatthew G. Knepley   Output Parameter:
9019bb7acecfSBarry Smith . aux - The `Vec` holding auxiliary field data
90209a2a23afSMatthew G. Knepley 
90219bdbcad8SBarry Smith   Level: advanced
90229bdbcad8SBarry Smith 
9023bb7acecfSBarry Smith   Note:
9024bb7acecfSBarry Smith   If no auxiliary vector is found for this (label, value), (NULL, 0, 0) is checked as well.
902504c51a94SMatthew G. Knepley 
90261cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMSetAuxiliaryVec()`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryLabels()`
90279a2a23afSMatthew G. Knepley @*/
9028d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec *aux)
9029d71ae5a4SJacob Faibussowitsch {
9030ac17215fSMatthew G. Knepley   PetscHashAuxKey key, wild = {NULL, 0, 0};
903104c51a94SMatthew G. Knepley   PetscBool       has;
90329a2a23afSMatthew G. Knepley 
90339a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90349a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90359a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
90369a2a23afSMatthew G. Knepley   key.label = label;
90379a2a23afSMatthew G. Knepley   key.value = value;
9038ac17215fSMatthew G. Knepley   key.part  = part;
90399566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxHas(dm->auxData, key, &has));
90409566063dSJacob Faibussowitsch   if (has) PetscCall(PetscHMapAuxGet(dm->auxData, key, aux));
90419566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxGet(dm->auxData, wild, aux));
90423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
90439a2a23afSMatthew G. Knepley }
90449a2a23afSMatthew G. Knepley 
90459a2a23afSMatthew G. Knepley /*@
9046bb7acecfSBarry Smith   DMSetAuxiliaryVec - Set an auxiliary vector for region specified by the given label and value, and equation part
90479a2a23afSMatthew G. Knepley 
904820f4b53cSBarry Smith   Not Collective because auxiliary vectors are not parallel
90499a2a23afSMatthew G. Knepley 
90509a2a23afSMatthew G. Knepley   Input Parameters:
9051bb7acecfSBarry Smith + dm    - The `DM`
9052bb7acecfSBarry Smith . label - The `DMLabel`
90539a2a23afSMatthew G. Knepley . value - The label value indicating the region
9054ac17215fSMatthew G. Knepley . part  - The equation part, or 0 if unused
9055bb7acecfSBarry Smith - aux   - The `Vec` holding auxiliary field data
90569a2a23afSMatthew G. Knepley 
90579a2a23afSMatthew G. Knepley   Level: advanced
90589a2a23afSMatthew G. Knepley 
90591cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetAuxiliaryVec()`, `DMGetAuxiliaryLabels()`, `DMCopyAuxiliaryVec()`
90609a2a23afSMatthew G. Knepley @*/
9061d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, PetscInt part, Vec aux)
9062d71ae5a4SJacob Faibussowitsch {
90639a2a23afSMatthew G. Knepley   Vec             old;
90649a2a23afSMatthew G. Knepley   PetscHashAuxKey key;
90659a2a23afSMatthew G. Knepley 
90669a2a23afSMatthew G. Knepley   PetscFunctionBegin;
90679a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90689a2a23afSMatthew G. Knepley   if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2);
90699a2a23afSMatthew G. Knepley   key.label = label;
90709a2a23afSMatthew G. Knepley   key.value = value;
9071ac17215fSMatthew G. Knepley   key.part  = part;
90729566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGet(dm->auxData, key, &old));
90739566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)aux));
90749566063dSJacob Faibussowitsch   if (!aux) PetscCall(PetscHMapAuxDel(dm->auxData, key));
90759566063dSJacob Faibussowitsch   else PetscCall(PetscHMapAuxSet(dm->auxData, key, aux));
9076d705d0eaSStefano Zampini   PetscCall(VecDestroy(&old));
90773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
90789a2a23afSMatthew G. Knepley }
90799a2a23afSMatthew G. Knepley 
90809a2a23afSMatthew G. Knepley /*@C
9081bb7acecfSBarry Smith   DMGetAuxiliaryLabels - Get the labels, values, and parts for all auxiliary vectors in this `DM`
90829a2a23afSMatthew G. Knepley 
908320f4b53cSBarry Smith   Not Collective
90849a2a23afSMatthew G. Knepley 
90859a2a23afSMatthew G. Knepley   Input Parameter:
9086bb7acecfSBarry Smith . dm - The `DM`
90879a2a23afSMatthew G. Knepley 
90889a2a23afSMatthew G. Knepley   Output Parameters:
9089bb7acecfSBarry Smith + labels - The `DMLabel`s for each `Vec`
9090bb7acecfSBarry Smith . values - The label values for each `Vec`
9091bb7acecfSBarry Smith - parts  - The equation parts for each `Vec`
90929a2a23afSMatthew G. Knepley 
90939bdbcad8SBarry Smith   Level: advanced
90949bdbcad8SBarry Smith 
9095bb7acecfSBarry Smith   Note:
9096bb7acecfSBarry Smith   The arrays passed in must be at least as large as `DMGetNumAuxiliaryVec()`.
90979a2a23afSMatthew G. Knepley 
909860225df5SJacob Faibussowitsch .seealso: [](ch_dmbase), `DM`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`, `DMCopyAuxiliaryVec()`
90999a2a23afSMatthew G. Knepley @*/
9100d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[], PetscInt parts[])
9101d71ae5a4SJacob Faibussowitsch {
91029a2a23afSMatthew G. Knepley   PetscHashAuxKey *keys;
91039a2a23afSMatthew G. Knepley   PetscInt         n, i, off = 0;
91049a2a23afSMatthew G. Knepley 
91059a2a23afSMatthew G. Knepley   PetscFunctionBegin;
91069a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91074f572ea9SToby Isaac   PetscAssertPointer(labels, 2);
91084f572ea9SToby Isaac   PetscAssertPointer(values, 3);
91094f572ea9SToby Isaac   PetscAssertPointer(parts, 4);
91109566063dSJacob Faibussowitsch   PetscCall(DMGetNumAuxiliaryVec(dm, &n));
91119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n, &keys));
91129566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxGetKeys(dm->auxData, &off, keys));
91139371c9d4SSatish Balay   for (i = 0; i < n; ++i) {
91149371c9d4SSatish Balay     labels[i] = keys[i].label;
91159371c9d4SSatish Balay     values[i] = keys[i].value;
91169371c9d4SSatish Balay     parts[i]  = keys[i].part;
91179371c9d4SSatish Balay   }
91189566063dSJacob Faibussowitsch   PetscCall(PetscFree(keys));
91193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91209a2a23afSMatthew G. Knepley }
91219a2a23afSMatthew G. Knepley 
91229a2a23afSMatthew G. Knepley /*@
9123bb7acecfSBarry Smith   DMCopyAuxiliaryVec - Copy the auxiliary vector data on a `DM` to a new `DM`
91249a2a23afSMatthew G. Knepley 
912520f4b53cSBarry Smith   Not Collective
91269a2a23afSMatthew G. Knepley 
91279a2a23afSMatthew G. Knepley   Input Parameter:
9128bb7acecfSBarry Smith . dm - The `DM`
91299a2a23afSMatthew G. Knepley 
91309a2a23afSMatthew G. Knepley   Output Parameter:
9131bb7acecfSBarry Smith . dmNew - The new `DM`, now with the same auxiliary data
91329a2a23afSMatthew G. Knepley 
91339a2a23afSMatthew G. Knepley   Level: advanced
91349a2a23afSMatthew G. Knepley 
9135bb7acecfSBarry Smith   Note:
9136bb7acecfSBarry Smith   This is a shallow copy of the auxiliary vectors
9137bb7acecfSBarry Smith 
91381cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMGetNumAuxiliaryVec()`, `DMGetAuxiliaryVec()`, `DMSetAuxiliaryVec()`
91399a2a23afSMatthew G. Knepley @*/
9140d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew)
9141d71ae5a4SJacob Faibussowitsch {
91429a2a23afSMatthew G. Knepley   PetscFunctionBegin;
91439a2a23afSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9144d705d0eaSStefano Zampini   PetscValidHeaderSpecific(dmNew, DM_CLASSID, 2);
9145d705d0eaSStefano Zampini   if (dm == dmNew) PetscFunctionReturn(PETSC_SUCCESS);
9146d705d0eaSStefano Zampini   PetscHMapAux oldData = dmNew->auxData;
91479566063dSJacob Faibussowitsch   PetscCall(PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData));
9148d705d0eaSStefano Zampini   {
9149d705d0eaSStefano Zampini     Vec     *auxData;
9150d705d0eaSStefano Zampini     PetscInt n, i, off = 0;
9151d705d0eaSStefano Zampini 
9152d705d0eaSStefano Zampini     PetscCall(PetscHMapAuxGetSize(dmNew->auxData, &n));
9153d705d0eaSStefano Zampini     PetscCall(PetscMalloc1(n, &auxData));
9154d705d0eaSStefano Zampini     PetscCall(PetscHMapAuxGetVals(dmNew->auxData, &off, auxData));
9155d705d0eaSStefano Zampini     for (i = 0; i < n; ++i) PetscCall(PetscObjectReference((PetscObject)auxData[i]));
9156d705d0eaSStefano Zampini     PetscCall(PetscFree(auxData));
9157d705d0eaSStefano Zampini     off = 0;
9158d705d0eaSStefano Zampini     PetscCall(PetscHMapAuxGetSize(oldData, &n));
9159d705d0eaSStefano Zampini     PetscCall(PetscMalloc1(n, &auxData));
9160d705d0eaSStefano Zampini     PetscCall(PetscHMapAuxGetVals(oldData, &off, auxData));
9161d705d0eaSStefano Zampini     for (i = 0; i < n; ++i) PetscCall(VecDestroy(&auxData[i]));
9162d705d0eaSStefano Zampini     PetscCall(PetscFree(auxData));
9163d705d0eaSStefano Zampini   }
9164d705d0eaSStefano Zampini   PetscCall(PetscHMapAuxDestroy(&oldData));
91653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91669a2a23afSMatthew G. Knepley }
9167b5a892a1SMatthew G. Knepley 
9168b5a892a1SMatthew G. Knepley /*@C
9169bb7acecfSBarry Smith   DMPolytopeMatchOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9170b5a892a1SMatthew G. Knepley 
917120f4b53cSBarry Smith   Not Collective
9172b5a892a1SMatthew G. Knepley 
9173b5a892a1SMatthew G. Knepley   Input Parameters:
9174bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9175b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9176b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9177b5a892a1SMatthew G. Knepley 
9178b5a892a1SMatthew G. Knepley   Output Parameters:
9179bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9180b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9181b5a892a1SMatthew G. Knepley 
9182b5a892a1SMatthew G. Knepley   Level: advanced
9183b5a892a1SMatthew G. Knepley 
9184bb7acecfSBarry Smith   Note:
9185bb7acecfSBarry Smith   An arrangement is a face order combined with an orientation for each face
9186bb7acecfSBarry Smith 
918785036b15SMatthew G. Knepley   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangements(ct)`/2 to `DMPolytopeTypeGetNumArrangements(ct)`/2
9188bb7acecfSBarry Smith   that labels each arrangement (face ordering plus orientation for each face).
9189bb7acecfSBarry Smith 
9190bb7acecfSBarry Smith   See `DMPolytopeMatchVertexOrientation()` to find a new vertex orientation that takes the source vertex arrangement to the target vertex arrangement
9191bb7acecfSBarry Smith 
91921cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetVertexOrientation()`
9193b5a892a1SMatthew G. Knepley @*/
9194d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt, PetscBool *found)
9195d71ae5a4SJacob Faibussowitsch {
9196b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetConeSize(ct);
919785036b15SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangements(ct) / 2;
9198b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9199b5a892a1SMatthew G. Knepley 
9200b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
92019371c9d4SSatish Balay   if (!nO) {
92029371c9d4SSatish Balay     *ornt  = 0;
92039371c9d4SSatish Balay     *found = PETSC_TRUE;
92043ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
92059371c9d4SSatish Balay   }
9206b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
920785036b15SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o);
9208b5a892a1SMatthew G. Knepley 
92099371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
92109371c9d4SSatish Balay       if (sourceCone[arr[c * 2]] != targetCone[c]) break;
92119371c9d4SSatish Balay     if (c == cS) {
92129371c9d4SSatish Balay       *ornt = o;
92139371c9d4SSatish Balay       break;
92149371c9d4SSatish Balay     }
9215b5a892a1SMatthew G. Knepley   }
9216b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
92173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9218b5a892a1SMatthew G. Knepley }
9219b5a892a1SMatthew G. Knepley 
9220b5a892a1SMatthew G. Knepley /*@C
9221bb7acecfSBarry Smith   DMPolytopeGetOrientation - Determine an orientation (transformation) that takes the source face arrangement to the target face arrangement
9222b5a892a1SMatthew G. Knepley 
922320f4b53cSBarry Smith   Not Collective
9224b5a892a1SMatthew G. Knepley 
9225b5a892a1SMatthew G. Knepley   Input Parameters:
9226bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9227b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of faces
9228b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of faces
9229b5a892a1SMatthew G. Knepley 
92302fe279fdSBarry Smith   Output Parameter:
9231bb7acecfSBarry Smith . ornt - The orientation (transformation) which will take the source arrangement to the target arrangement
9232b5a892a1SMatthew G. Knepley 
9233b5a892a1SMatthew G. Knepley   Level: advanced
9234b5a892a1SMatthew G. Knepley 
9235bb7acecfSBarry Smith   Note:
9236bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchOrientation()` except it will generate an error if no suitable orientation can be found.
9237bb7acecfSBarry Smith 
923860225df5SJacob Faibussowitsch   Developer Notes:
9239bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchOrientation()` and error if none is found
9240bb7acecfSBarry Smith 
92411cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeMatchOrientation()`, `DMPolytopeGetVertexOrientation()`, `DMPolytopeMatchVertexOrientation()`
9242b5a892a1SMatthew G. Knepley @*/
9243d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9244d71ae5a4SJacob Faibussowitsch {
9245b5a892a1SMatthew G. Knepley   PetscBool found;
9246b5a892a1SMatthew G. Knepley 
9247b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
92489566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchOrientation(ct, sourceCone, targetCone, ornt, &found));
92497a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
92503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9251b5a892a1SMatthew G. Knepley }
9252b5a892a1SMatthew G. Knepley 
9253b5a892a1SMatthew G. Knepley /*@C
9254bb7acecfSBarry Smith   DMPolytopeMatchVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9255b5a892a1SMatthew G. Knepley 
925620f4b53cSBarry Smith   Not Collective
9257b5a892a1SMatthew G. Knepley 
9258b5a892a1SMatthew G. Knepley   Input Parameters:
9259bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9260b5a892a1SMatthew G. Knepley . sourceVert - The source arrangement of vertices
9261b5a892a1SMatthew G. Knepley - targetVert - The target arrangement of vertices
9262b5a892a1SMatthew G. Knepley 
9263b5a892a1SMatthew G. Knepley   Output Parameters:
9264bb7acecfSBarry Smith + ornt  - The orientation (transformation) which will take the source arrangement to the target arrangement
9265b5a892a1SMatthew G. Knepley - found - Flag indicating that a suitable orientation was found
9266b5a892a1SMatthew G. Knepley 
9267b5a892a1SMatthew G. Knepley   Level: advanced
9268b5a892a1SMatthew G. Knepley 
9269bb7acecfSBarry Smith   Note:
9270bb7acecfSBarry Smith   An arrangement is a vertex order
9271bb7acecfSBarry Smith 
927285036b15SMatthew G. Knepley   Each orientation (transformation) is labeled with an integer from negative `DMPolytopeTypeGetNumArrangements(ct)`/2 to `DMPolytopeTypeGetNumArrangements(ct)`/2
9273bb7acecfSBarry Smith   that labels each arrangement (vertex ordering).
9274bb7acecfSBarry Smith 
9275bb7acecfSBarry Smith   See `DMPolytopeMatchOrientation()` to find a new face orientation that takes the source face arrangement to the target face arrangement
9276bb7acecfSBarry Smith 
927785036b15SMatthew G. Knepley .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeGetOrientation()`, `DMPolytopeMatchOrientation()`, `DMPolytopeTypeGetNumVertices()`, `DMPolytopeTypeGetVertexArrangement()`
9278b5a892a1SMatthew G. Knepley @*/
9279d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeMatchVertexOrientation(DMPolytopeType ct, const PetscInt sourceVert[], const PetscInt targetVert[], PetscInt *ornt, PetscBool *found)
9280d71ae5a4SJacob Faibussowitsch {
9281b5a892a1SMatthew G. Knepley   const PetscInt cS = DMPolytopeTypeGetNumVertices(ct);
928285036b15SMatthew G. Knepley   const PetscInt nO = DMPolytopeTypeGetNumArrangements(ct) / 2;
9283b5a892a1SMatthew G. Knepley   PetscInt       o, c;
9284b5a892a1SMatthew G. Knepley 
9285b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
92869371c9d4SSatish Balay   if (!nO) {
92879371c9d4SSatish Balay     *ornt  = 0;
92889371c9d4SSatish Balay     *found = PETSC_TRUE;
92893ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
92909371c9d4SSatish Balay   }
9291b5a892a1SMatthew G. Knepley   for (o = -nO; o < nO; ++o) {
929285036b15SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetVertexArrangement(ct, o);
9293b5a892a1SMatthew G. Knepley 
92949371c9d4SSatish Balay     for (c = 0; c < cS; ++c)
92959371c9d4SSatish Balay       if (sourceVert[arr[c]] != targetVert[c]) break;
92969371c9d4SSatish Balay     if (c == cS) {
92979371c9d4SSatish Balay       *ornt = o;
92989371c9d4SSatish Balay       break;
92999371c9d4SSatish Balay     }
9300b5a892a1SMatthew G. Knepley   }
9301b5a892a1SMatthew G. Knepley   *found = o == nO ? PETSC_FALSE : PETSC_TRUE;
93023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9303b5a892a1SMatthew G. Knepley }
9304b5a892a1SMatthew G. Knepley 
9305b5a892a1SMatthew G. Knepley /*@C
9306bb7acecfSBarry Smith   DMPolytopeGetVertexOrientation - Determine an orientation (transformation) that takes the source vertex arrangement to the target vertex arrangement
9307b5a892a1SMatthew G. Knepley 
930820f4b53cSBarry Smith   Not Collective
9309b5a892a1SMatthew G. Knepley 
9310b5a892a1SMatthew G. Knepley   Input Parameters:
9311bb7acecfSBarry Smith + ct         - The `DMPolytopeType`
9312b5a892a1SMatthew G. Knepley . sourceCone - The source arrangement of vertices
9313b5a892a1SMatthew G. Knepley - targetCone - The target arrangement of vertices
9314b5a892a1SMatthew G. Knepley 
93152fe279fdSBarry Smith   Output Parameter:
9316bb7acecfSBarry Smith . ornt - The orientation (transformation) which will take the source arrangement to the target arrangement
9317b5a892a1SMatthew G. Knepley 
9318b5a892a1SMatthew G. Knepley   Level: advanced
9319b5a892a1SMatthew G. Knepley 
9320bb7acecfSBarry Smith   Note:
9321bb7acecfSBarry Smith   This function is the same as `DMPolytopeMatchVertexOrientation()` except it errors if not orientation is possible.
9322bb7acecfSBarry Smith 
932360225df5SJacob Faibussowitsch   Developer Notes:
9324bb7acecfSBarry Smith   It is unclear why this function needs to exist since one can simply call `DMPolytopeMatchVertexOrientation()` and error if none is found
9325bb7acecfSBarry Smith 
93261cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMPolytopeMatchVertexOrientation()`, `DMPolytopeGetOrientation()`
9327b5a892a1SMatthew G. Knepley @*/
9328d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeGetVertexOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt)
9329d71ae5a4SJacob Faibussowitsch {
9330b5a892a1SMatthew G. Knepley   PetscBool found;
9331b5a892a1SMatthew G. Knepley 
9332b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
93339566063dSJacob Faibussowitsch   PetscCall(DMPolytopeMatchVertexOrientation(ct, sourceCone, targetCone, ornt, &found));
93347a8be351SBarry Smith   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]);
93353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9336b5a892a1SMatthew G. Knepley }
9337012bc364SMatthew G. Knepley 
9338012bc364SMatthew G. Knepley /*@C
9339012bc364SMatthew G. Knepley   DMPolytopeInCellTest - Check whether a point lies inside the reference cell of given type
9340012bc364SMatthew G. Knepley 
934120f4b53cSBarry Smith   Not Collective
9342012bc364SMatthew G. Knepley 
9343012bc364SMatthew G. Knepley   Input Parameters:
9344bb7acecfSBarry Smith + ct    - The `DMPolytopeType`
9345012bc364SMatthew G. Knepley - point - Coordinates of the point
9346012bc364SMatthew G. Knepley 
93472fe279fdSBarry Smith   Output Parameter:
9348012bc364SMatthew G. Knepley . inside - Flag indicating whether the point is inside the reference cell of given type
9349012bc364SMatthew G. Knepley 
9350012bc364SMatthew G. Knepley   Level: advanced
9351012bc364SMatthew G. Knepley 
93521cc06b55SBarry Smith .seealso: [](ch_dmbase), `DM`, `DMPolytopeType`, `DMLocatePoints()`
9353012bc364SMatthew G. Knepley @*/
9354d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPolytopeInCellTest(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
9355d71ae5a4SJacob Faibussowitsch {
9356012bc364SMatthew G. Knepley   PetscReal sum = 0.0;
9357012bc364SMatthew G. Knepley   PetscInt  d;
9358012bc364SMatthew G. Knepley 
9359012bc364SMatthew G. Knepley   PetscFunctionBegin;
9360012bc364SMatthew G. Knepley   *inside = PETSC_TRUE;
9361012bc364SMatthew G. Knepley   switch (ct) {
9362012bc364SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
9363012bc364SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
9364012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
93659371c9d4SSatish Balay       if (point[d] < -1.0) {
93669371c9d4SSatish Balay         *inside = PETSC_FALSE;
93679371c9d4SSatish Balay         break;
93689371c9d4SSatish Balay       }
9369012bc364SMatthew G. Knepley       sum += point[d];
9370012bc364SMatthew G. Knepley     }
93719371c9d4SSatish Balay     if (sum > PETSC_SMALL) {
93729371c9d4SSatish Balay       *inside = PETSC_FALSE;
93739371c9d4SSatish Balay       break;
93749371c9d4SSatish Balay     }
9375012bc364SMatthew G. Knepley     break;
9376012bc364SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
9377012bc364SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
9378012bc364SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
93799371c9d4SSatish Balay       if (PetscAbsReal(point[d]) > 1. + PETSC_SMALL) {
93809371c9d4SSatish Balay         *inside = PETSC_FALSE;
9381012bc364SMatthew G. Knepley         break;
93829371c9d4SSatish Balay       }
93839371c9d4SSatish Balay     break;
9384d71ae5a4SJacob Faibussowitsch   default:
9385d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
9386012bc364SMatthew G. Knepley   }
93873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9388012bc364SMatthew G. Knepley }
9389