xref: /petsc/src/dm/interface/dmcoordinates.c (revision e44f6aeb0c7eee2716d50e70cd976c48a5d3c225)
16858538eSMatthew G. Knepley #include <petsc/private/dmimpl.h> /*I      "petscdm.h"          I*/
26858538eSMatthew G. Knepley 
3*e44f6aebSMatthew G. Knepley #include <petscdmplex.h> /* For DMCreateAffineCoordinates_Internal() */
46858538eSMatthew G. Knepley #include <petscsf.h>     /* For DMLocatePoints() */
56858538eSMatthew G. Knepley 
6d71ae5a4SJacob Faibussowitsch PetscErrorCode DMRestrictHook_Coordinates(DM dm, DM dmc, void *ctx)
7d71ae5a4SJacob Faibussowitsch {
86858538eSMatthew G. Knepley   DM  dm_coord, dmc_coord;
96858538eSMatthew G. Knepley   Vec coords, ccoords;
106858538eSMatthew G. Knepley   Mat inject;
116858538eSMatthew G. Knepley   PetscFunctionBegin;
126858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &dm_coord));
136858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dmc, &dmc_coord));
146858538eSMatthew G. Knepley   PetscCall(DMGetCoordinates(dm, &coords));
156858538eSMatthew G. Knepley   PetscCall(DMGetCoordinates(dmc, &ccoords));
166858538eSMatthew G. Knepley   if (coords && !ccoords) {
176858538eSMatthew G. Knepley     PetscCall(DMCreateGlobalVector(dmc_coord, &ccoords));
186858538eSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)ccoords, "coordinates"));
196858538eSMatthew G. Knepley     PetscCall(DMCreateInjection(dmc_coord, dm_coord, &inject));
206858538eSMatthew G. Knepley     PetscCall(MatRestrict(inject, coords, ccoords));
216858538eSMatthew G. Knepley     PetscCall(MatDestroy(&inject));
226858538eSMatthew G. Knepley     PetscCall(DMSetCoordinates(dmc, ccoords));
236858538eSMatthew G. Knepley     PetscCall(VecDestroy(&ccoords));
246858538eSMatthew G. Knepley   }
253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
266858538eSMatthew G. Knepley }
276858538eSMatthew G. Knepley 
28d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSubDomainHook_Coordinates(DM dm, DM subdm, void *ctx)
29d71ae5a4SJacob Faibussowitsch {
306858538eSMatthew G. Knepley   DM          dm_coord, subdm_coord;
316858538eSMatthew G. Knepley   Vec         coords, ccoords, clcoords;
326858538eSMatthew G. Knepley   VecScatter *scat_i, *scat_g;
336858538eSMatthew G. Knepley   PetscFunctionBegin;
346858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &dm_coord));
356858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(subdm, &subdm_coord));
366858538eSMatthew G. Knepley   PetscCall(DMGetCoordinates(dm, &coords));
376858538eSMatthew G. Knepley   PetscCall(DMGetCoordinates(subdm, &ccoords));
386858538eSMatthew G. Knepley   if (coords && !ccoords) {
396858538eSMatthew G. Knepley     PetscCall(DMCreateGlobalVector(subdm_coord, &ccoords));
406858538eSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)ccoords, "coordinates"));
416858538eSMatthew G. Knepley     PetscCall(DMCreateLocalVector(subdm_coord, &clcoords));
426858538eSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)clcoords, "coordinates"));
436858538eSMatthew G. Knepley     PetscCall(DMCreateDomainDecompositionScatters(dm_coord, 1, &subdm_coord, NULL, &scat_i, &scat_g));
446858538eSMatthew G. Knepley     PetscCall(VecScatterBegin(scat_i[0], coords, ccoords, INSERT_VALUES, SCATTER_FORWARD));
456858538eSMatthew G. Knepley     PetscCall(VecScatterEnd(scat_i[0], coords, ccoords, INSERT_VALUES, SCATTER_FORWARD));
466858538eSMatthew G. Knepley     PetscCall(VecScatterBegin(scat_g[0], coords, clcoords, INSERT_VALUES, SCATTER_FORWARD));
476858538eSMatthew G. Knepley     PetscCall(VecScatterEnd(scat_g[0], coords, clcoords, INSERT_VALUES, SCATTER_FORWARD));
486858538eSMatthew G. Knepley     PetscCall(DMSetCoordinates(subdm, ccoords));
496858538eSMatthew G. Knepley     PetscCall(DMSetCoordinatesLocal(subdm, clcoords));
506858538eSMatthew G. Knepley     PetscCall(VecScatterDestroy(&scat_i[0]));
516858538eSMatthew G. Knepley     PetscCall(VecScatterDestroy(&scat_g[0]));
526858538eSMatthew G. Knepley     PetscCall(VecDestroy(&ccoords));
536858538eSMatthew G. Knepley     PetscCall(VecDestroy(&clcoords));
546858538eSMatthew G. Knepley     PetscCall(PetscFree(scat_i));
556858538eSMatthew G. Knepley     PetscCall(PetscFree(scat_g));
566858538eSMatthew G. Knepley   }
573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
586858538eSMatthew G. Knepley }
596858538eSMatthew G. Knepley 
606858538eSMatthew G. Knepley /*@
61dce8aebaSBarry Smith   DMGetCoordinateDM - Gets the `DM` that prescribes coordinate layout and scatters between global and local coordinates
626858538eSMatthew G. Knepley 
6320f4b53cSBarry Smith   Collective
646858538eSMatthew G. Knepley 
656858538eSMatthew G. Knepley   Input Parameter:
66dce8aebaSBarry Smith . dm - the `DM`
676858538eSMatthew G. Knepley 
686858538eSMatthew G. Knepley   Output Parameter:
69dce8aebaSBarry Smith . cdm - coordinate `DM`
706858538eSMatthew G. Knepley 
716858538eSMatthew G. Knepley   Level: intermediate
726858538eSMatthew G. Knepley 
73dce8aebaSBarry Smith .seealso: `DM`, `DMSetCoordinateDM()`, `DMSetCoordinates()`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGSetCellCoordinateDM()`,
7460225df5SJacob Faibussowitsch 
756858538eSMatthew G. Knepley @*/
76d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm)
77d71ae5a4SJacob Faibussowitsch {
786858538eSMatthew G. Knepley   PetscFunctionBegin;
796858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
804f572ea9SToby Isaac   PetscAssertPointer(cdm, 2);
816858538eSMatthew G. Knepley   if (!dm->coordinates[0].dm) {
826858538eSMatthew G. Knepley     DM cdm;
836858538eSMatthew G. Knepley 
84dbbe0bcdSBarry Smith     PetscUseTypeMethod(dm, createcoordinatedm, &cdm);
856858538eSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)cdm, "coordinateDM"));
866858538eSMatthew G. Knepley     /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup
876858538eSMatthew G. Knepley      * until the call to CreateCoordinateDM) */
886858538eSMatthew G. Knepley     PetscCall(DMDestroy(&dm->coordinates[0].dm));
896858538eSMatthew G. Knepley     dm->coordinates[0].dm = cdm;
906858538eSMatthew G. Knepley   }
916858538eSMatthew G. Knepley   *cdm = dm->coordinates[0].dm;
923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
936858538eSMatthew G. Knepley }
946858538eSMatthew G. Knepley 
956858538eSMatthew G. Knepley /*@
96dce8aebaSBarry Smith   DMSetCoordinateDM - Sets the `DM` that prescribes coordinate layout and scatters between global and local coordinates
976858538eSMatthew G. Knepley 
9820f4b53cSBarry Smith   Logically Collective
996858538eSMatthew G. Knepley 
1006858538eSMatthew G. Knepley   Input Parameters:
101dce8aebaSBarry Smith + dm  - the `DM`
102dce8aebaSBarry Smith - cdm - coordinate `DM`
1036858538eSMatthew G. Knepley 
1046858538eSMatthew G. Knepley   Level: intermediate
1056858538eSMatthew G. Knepley 
106dce8aebaSBarry Smith .seealso: `DM`, `DMGetCoordinateDM()`, `DMSetCoordinates()`, `DMGetCellCoordinateDM()`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`,
107dce8aebaSBarry Smith           `DMGSetCellCoordinateDM()`
1086858538eSMatthew G. Knepley @*/
109d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm)
110d71ae5a4SJacob Faibussowitsch {
1116858538eSMatthew G. Knepley   PetscFunctionBegin;
1126858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11390612307SJed Brown   if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
1146858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)cdm));
1156858538eSMatthew G. Knepley   PetscCall(DMDestroy(&dm->coordinates[0].dm));
1166858538eSMatthew G. Knepley   dm->coordinates[0].dm = cdm;
1173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1186858538eSMatthew G. Knepley }
1196858538eSMatthew G. Knepley 
1206858538eSMatthew G. Knepley /*@
121dce8aebaSBarry Smith   DMGetCellCoordinateDM - Gets the `DM` that prescribes cellwise coordinate layout and scatters between global and local cellwise coordinates
1226858538eSMatthew G. Knepley 
12320f4b53cSBarry Smith   Collective
1246858538eSMatthew G. Knepley 
1256858538eSMatthew G. Knepley   Input Parameter:
126dce8aebaSBarry Smith . dm - the `DM`
1276858538eSMatthew G. Knepley 
1286858538eSMatthew G. Knepley   Output Parameter:
129dce8aebaSBarry Smith . cdm - cellwise coordinate `DM`, or NULL if they are not defined
1306858538eSMatthew G. Knepley 
1316858538eSMatthew G. Knepley   Level: intermediate
1326858538eSMatthew G. Knepley 
133dce8aebaSBarry Smith   Note:
134dce8aebaSBarry Smith   Call `DMLocalizeCoordinates()` to automatically create cellwise coordinates for periodic geometries.
135dce8aebaSBarry Smith 
136dce8aebaSBarry Smith .seealso: `DM`, `DMSetCellCoordinateDM()`, `DMSetCellCoordinates()`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMGetCellCoordinatesLocal()`,
137dce8aebaSBarry Smith           `DMLocalizeCoordinates()`, `DMSetCoordinateDM()`, `DMGetCoordinateDM()`
1386858538eSMatthew G. Knepley @*/
139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCellCoordinateDM(DM dm, DM *cdm)
140d71ae5a4SJacob Faibussowitsch {
1416858538eSMatthew G. Knepley   PetscFunctionBegin;
1426858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1434f572ea9SToby Isaac   PetscAssertPointer(cdm, 2);
1446858538eSMatthew G. Knepley   *cdm = dm->coordinates[1].dm;
1453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1466858538eSMatthew G. Knepley }
1476858538eSMatthew G. Knepley 
1486858538eSMatthew G. Knepley /*@
149dce8aebaSBarry Smith   DMSetCellCoordinateDM - Sets the `DM` that prescribes cellwise coordinate layout and scatters between global and local cellwise coordinates
1506858538eSMatthew G. Knepley 
15120f4b53cSBarry Smith   Logically Collective
1526858538eSMatthew G. Knepley 
1536858538eSMatthew G. Knepley   Input Parameters:
154dce8aebaSBarry Smith + dm  - the `DM`
155dce8aebaSBarry Smith - cdm - cellwise coordinate `DM`
1566858538eSMatthew G. Knepley 
1576858538eSMatthew G. Knepley   Level: intermediate
1586858538eSMatthew G. Knepley 
159dce8aebaSBarry Smith   Note:
16035cb6cd3SPierre Jolivet   As opposed to `DMSetCoordinateDM()` these coordinates are useful for discontinuous Galerkin methods since they support coordinate fields that are discontinuous at cell boundaries.
161dce8aebaSBarry Smith 
162dce8aebaSBarry Smith .seealso: `DMGetCellCoordinateDM()`, `DMSetCellCoordinates()`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMGetCellCoordinatesLocal()`,
163dce8aebaSBarry Smith           `DMSetCoordinateDM()`, `DMGetCoordinateDM()`
1646858538eSMatthew G. Knepley @*/
165d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCellCoordinateDM(DM dm, DM cdm)
166d71ae5a4SJacob Faibussowitsch {
1676858538eSMatthew G. Knepley   PetscInt dim;
1686858538eSMatthew G. Knepley 
1696858538eSMatthew G. Knepley   PetscFunctionBegin;
1706858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1716858538eSMatthew G. Knepley   if (cdm) {
1726858538eSMatthew G. Knepley     PetscValidHeaderSpecific(cdm, DM_CLASSID, 2);
1736858538eSMatthew G. Knepley     PetscCall(DMGetCoordinateDim(dm, &dim));
1746858538eSMatthew G. Knepley     dm->coordinates[1].dim = dim;
1756858538eSMatthew G. Knepley   }
1766858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)cdm));
1776858538eSMatthew G. Knepley   PetscCall(DMDestroy(&dm->coordinates[1].dm));
1786858538eSMatthew G. Knepley   dm->coordinates[1].dm = cdm;
1793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1806858538eSMatthew G. Knepley }
1816858538eSMatthew G. Knepley 
1826858538eSMatthew G. Knepley /*@
183dce8aebaSBarry Smith   DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. For example a mesh on the surface of a sphere would have a 3 dimensional embedding space
1846858538eSMatthew G. Knepley 
1856858538eSMatthew G. Knepley   Not Collective
1866858538eSMatthew G. Knepley 
1876858538eSMatthew G. Knepley   Input Parameter:
188dce8aebaSBarry Smith . dm - The `DM` object
1896858538eSMatthew G. Knepley 
1906858538eSMatthew G. Knepley   Output Parameter:
1916858538eSMatthew G. Knepley . dim - The embedding dimension
1926858538eSMatthew G. Knepley 
1936858538eSMatthew G. Knepley   Level: intermediate
1946858538eSMatthew G. Knepley 
195dce8aebaSBarry Smith .seealso: `DM`, `DMSetCoordinateDim()`, `DMGetCoordinateSection()`, `DMGetCoordinateDM()`, `DMGetLocalSection()`, `DMSetLocalSection()`
1966858538eSMatthew G. Knepley @*/
197d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim)
198d71ae5a4SJacob Faibussowitsch {
1996858538eSMatthew G. Knepley   PetscFunctionBegin;
2006858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2014f572ea9SToby Isaac   PetscAssertPointer(dim, 2);
2026858538eSMatthew G. Knepley   if (dm->coordinates[0].dim == PETSC_DEFAULT) dm->coordinates[0].dim = dm->dim;
2036858538eSMatthew G. Knepley   *dim = dm->coordinates[0].dim;
2043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2056858538eSMatthew G. Knepley }
2066858538eSMatthew G. Knepley 
2076858538eSMatthew G. Knepley /*@
2086858538eSMatthew G. Knepley   DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values.
2096858538eSMatthew G. Knepley 
2106858538eSMatthew G. Knepley   Not Collective
2116858538eSMatthew G. Knepley 
2126858538eSMatthew G. Knepley   Input Parameters:
213dce8aebaSBarry Smith + dm  - The `DM` object
2146858538eSMatthew G. Knepley - dim - The embedding dimension
2156858538eSMatthew G. Knepley 
2166858538eSMatthew G. Knepley   Level: intermediate
2176858538eSMatthew G. Knepley 
218dce8aebaSBarry Smith .seealso: `DM`, `DMGetCoordinateDim()`, `DMSetCoordinateSection()`, `DMGetCoordinateSection()`, `DMGetLocalSection()`, `DMSetLocalSection()`
2196858538eSMatthew G. Knepley @*/
220d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim)
221d71ae5a4SJacob Faibussowitsch {
2226858538eSMatthew G. Knepley   PetscDS  ds;
2236858538eSMatthew G. Knepley   PetscInt Nds, n;
2246858538eSMatthew G. Knepley 
2256858538eSMatthew G. Knepley   PetscFunctionBegin;
2266858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2276858538eSMatthew G. Knepley   dm->coordinates[0].dim = dim;
2286858538eSMatthew G. Knepley   if (dm->dim >= 0) {
2296858538eSMatthew G. Knepley     PetscCall(DMGetNumDS(dm, &Nds));
2306858538eSMatthew G. Knepley     for (n = 0; n < Nds; ++n) {
23107218a29SMatthew G. Knepley       PetscCall(DMGetRegionNumDS(dm, n, NULL, NULL, &ds, NULL));
2326858538eSMatthew G. Knepley       PetscCall(PetscDSSetCoordinateDimension(ds, dim));
2336858538eSMatthew G. Knepley     }
2346858538eSMatthew G. Knepley   }
2353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2366858538eSMatthew G. Knepley }
2376858538eSMatthew G. Knepley 
2386858538eSMatthew G. Knepley /*@
2396858538eSMatthew G. Knepley   DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
2406858538eSMatthew G. Knepley 
24120f4b53cSBarry Smith   Collective
2426858538eSMatthew G. Knepley 
2436858538eSMatthew G. Knepley   Input Parameter:
244dce8aebaSBarry Smith . dm - The `DM` object
2456858538eSMatthew G. Knepley 
2466858538eSMatthew G. Knepley   Output Parameter:
247dce8aebaSBarry Smith . section - The `PetscSection` object
2486858538eSMatthew G. Knepley 
2496858538eSMatthew G. Knepley   Level: intermediate
2506858538eSMatthew G. Knepley 
251dce8aebaSBarry Smith   Note:
252dce8aebaSBarry Smith   This just retrieves the local section from the coordinate `DM`. In other words,
253dce8aebaSBarry Smith .vb
254dce8aebaSBarry Smith   DMGetCoordinateDM(dm, &cdm);
255dce8aebaSBarry Smith   DMGetLocalSection(cdm, &section);
256dce8aebaSBarry Smith .ve
257dce8aebaSBarry Smith 
2586858538eSMatthew G. Knepley .seealso: `DMGetCoordinateDM()`, `DMGetLocalSection()`, `DMSetLocalSection()`
2596858538eSMatthew G. Knepley @*/
260d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section)
261d71ae5a4SJacob Faibussowitsch {
2626858538eSMatthew G. Knepley   DM cdm;
2636858538eSMatthew G. Knepley 
2646858538eSMatthew G. Knepley   PetscFunctionBegin;
2656858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2664f572ea9SToby Isaac   PetscAssertPointer(section, 2);
2676858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
2686858538eSMatthew G. Knepley   PetscCall(DMGetLocalSection(cdm, section));
2693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2706858538eSMatthew G. Knepley }
2716858538eSMatthew G. Knepley 
2726858538eSMatthew G. Knepley /*@
2736858538eSMatthew G. Knepley   DMSetCoordinateSection - Set the layout of coordinate values over the mesh.
2746858538eSMatthew G. Knepley 
2756858538eSMatthew G. Knepley   Not Collective
2766858538eSMatthew G. Knepley 
2776858538eSMatthew G. Knepley   Input Parameters:
278dce8aebaSBarry Smith + dm      - The `DM` object
279dce8aebaSBarry Smith . dim     - The embedding dimension, or `PETSC_DETERMINE`
280dce8aebaSBarry Smith - section - The `PetscSection` object
2816858538eSMatthew G. Knepley 
2826858538eSMatthew G. Knepley   Level: intermediate
2836858538eSMatthew G. Knepley 
284dce8aebaSBarry Smith .seealso: `DM`, `DMGetCoordinateDim()`, `DMGetCoordinateSection()`, `DMGetLocalSection()`, `DMSetLocalSection()`
2856858538eSMatthew G. Knepley @*/
286d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section)
287d71ae5a4SJacob Faibussowitsch {
2886858538eSMatthew G. Knepley   DM cdm;
2896858538eSMatthew G. Knepley 
2906858538eSMatthew G. Knepley   PetscFunctionBegin;
2916858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2926858538eSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 3);
2936858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
2946858538eSMatthew G. Knepley   PetscCall(DMSetLocalSection(cdm, section));
2956858538eSMatthew G. Knepley   if (dim == PETSC_DETERMINE) {
2966858538eSMatthew G. Knepley     PetscInt d = PETSC_DEFAULT;
2976858538eSMatthew G. Knepley     PetscInt pStart, pEnd, vStart, vEnd, v, dd;
2986858538eSMatthew G. Knepley 
2996858538eSMatthew G. Knepley     PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
3006858538eSMatthew G. Knepley     PetscCall(DMGetDimPoints(dm, 0, &vStart, &vEnd));
3016858538eSMatthew G. Knepley     pStart = PetscMax(vStart, pStart);
3026858538eSMatthew G. Knepley     pEnd   = PetscMin(vEnd, pEnd);
3036858538eSMatthew G. Knepley     for (v = pStart; v < pEnd; ++v) {
3046858538eSMatthew G. Knepley       PetscCall(PetscSectionGetDof(section, v, &dd));
3059371c9d4SSatish Balay       if (dd) {
3069371c9d4SSatish Balay         d = dd;
3079371c9d4SSatish Balay         break;
3089371c9d4SSatish Balay       }
3096858538eSMatthew G. Knepley     }
3106858538eSMatthew G. Knepley     if (d >= 0) PetscCall(DMSetCoordinateDim(dm, d));
3116858538eSMatthew G. Knepley   }
3123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3136858538eSMatthew G. Knepley }
3146858538eSMatthew G. Knepley 
3156858538eSMatthew G. Knepley /*@
3166858538eSMatthew G. Knepley   DMGetCellCoordinateSection - Retrieve the layout of cellwise coordinate values over the mesh.
3176858538eSMatthew G. Knepley 
31820f4b53cSBarry Smith   Collective
3196858538eSMatthew G. Knepley 
3206858538eSMatthew G. Knepley   Input Parameter:
321dce8aebaSBarry Smith . dm - The `DM` object
3226858538eSMatthew G. Knepley 
3236858538eSMatthew G. Knepley   Output Parameter:
32420f4b53cSBarry Smith . section - The `PetscSection` object, or `NULL` if no cellwise coordinates are defined
3256858538eSMatthew G. Knepley 
3266858538eSMatthew G. Knepley   Level: intermediate
3276858538eSMatthew G. Knepley 
328dce8aebaSBarry Smith   Note:
329dce8aebaSBarry Smith   This just retrieves the local section from the cell coordinate `DM`. In other words,
330dce8aebaSBarry Smith .vb
331dce8aebaSBarry Smith   DMGetCellCoordinateDM(dm, &cdm);
332dce8aebaSBarry Smith   DMGetLocalSection(cdm, &section);
333dce8aebaSBarry Smith .ve
334dce8aebaSBarry Smith 
335dce8aebaSBarry Smith .seealso: `DM`, `DMGetCoordinateSection()`, `DMSetCellCoordinateSection()`, `DMGetCellCoordinateDM()`, `DMGetCoordinateDM()`, `DMGetLocalSection()`, `DMSetLocalSection()`
3366858538eSMatthew G. Knepley @*/
337d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCellCoordinateSection(DM dm, PetscSection *section)
338d71ae5a4SJacob Faibussowitsch {
3396858538eSMatthew G. Knepley   DM cdm;
3406858538eSMatthew G. Knepley 
3416858538eSMatthew G. Knepley   PetscFunctionBegin;
3426858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3434f572ea9SToby Isaac   PetscAssertPointer(section, 2);
3446858538eSMatthew G. Knepley   *section = NULL;
3456858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cdm));
3466858538eSMatthew G. Knepley   if (cdm) PetscCall(DMGetLocalSection(cdm, section));
3473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3486858538eSMatthew G. Knepley }
3496858538eSMatthew G. Knepley 
3506858538eSMatthew G. Knepley /*@
3516858538eSMatthew G. Knepley   DMSetCellCoordinateSection - Set the layout of cellwise coordinate values over the mesh.
3526858538eSMatthew G. Knepley 
3536858538eSMatthew G. Knepley   Not Collective
3546858538eSMatthew G. Knepley 
3556858538eSMatthew G. Knepley   Input Parameters:
356dce8aebaSBarry Smith + dm      - The `DM` object
357dce8aebaSBarry Smith . dim     - The embedding dimension, or `PETSC_DETERMINE`
358dce8aebaSBarry Smith - section - The `PetscSection` object for a cellwise layout
3596858538eSMatthew G. Knepley 
3606858538eSMatthew G. Knepley   Level: intermediate
3616858538eSMatthew G. Knepley 
362dce8aebaSBarry Smith .seealso: `DM`, `DMGetCoordinateDim()`, `DMSetCoordinateSection()`, `DMGetCellCoordinateSection()`, `DMGetCoordinateSection()`, `DMGetCellCoordinateDM()`, `DMGetLocalSection()`, `DMSetLocalSection()`
3636858538eSMatthew G. Knepley @*/
364d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCellCoordinateSection(DM dm, PetscInt dim, PetscSection section)
365d71ae5a4SJacob Faibussowitsch {
3666858538eSMatthew G. Knepley   DM cdm;
3676858538eSMatthew G. Knepley 
3686858538eSMatthew G. Knepley   PetscFunctionBegin;
3696858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3706858538eSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 3);
3716858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cdm));
3726858538eSMatthew G. Knepley   PetscCheck(cdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "No DM defined for cellwise coordinates");
3736858538eSMatthew G. Knepley   PetscCall(DMSetLocalSection(cdm, section));
3746858538eSMatthew G. Knepley   if (dim == PETSC_DETERMINE) {
3756858538eSMatthew G. Knepley     PetscInt d = PETSC_DEFAULT;
3766858538eSMatthew G. Knepley     PetscInt pStart, pEnd, vStart, vEnd, v, dd;
3776858538eSMatthew G. Knepley 
3786858538eSMatthew G. Knepley     PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
3796858538eSMatthew G. Knepley     PetscCall(DMGetDimPoints(dm, 0, &vStart, &vEnd));
3806858538eSMatthew G. Knepley     pStart = PetscMax(vStart, pStart);
3816858538eSMatthew G. Knepley     pEnd   = PetscMin(vEnd, pEnd);
3826858538eSMatthew G. Knepley     for (v = pStart; v < pEnd; ++v) {
3836858538eSMatthew G. Knepley       PetscCall(PetscSectionGetDof(section, v, &dd));
3849371c9d4SSatish Balay       if (dd) {
3859371c9d4SSatish Balay         d = dd;
3869371c9d4SSatish Balay         break;
3879371c9d4SSatish Balay       }
3886858538eSMatthew G. Knepley     }
3896858538eSMatthew G. Knepley     if (d >= 0) PetscCall(DMSetCoordinateDim(dm, d));
3906858538eSMatthew G. Knepley   }
3913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3926858538eSMatthew G. Knepley }
3936858538eSMatthew G. Knepley 
3946858538eSMatthew G. Knepley /*@
395dce8aebaSBarry Smith   DMGetCoordinates - Gets a global vector with the coordinates associated with the `DM`.
3966858538eSMatthew G. Knepley 
39720f4b53cSBarry Smith   Collective
3986858538eSMatthew G. Knepley 
3996858538eSMatthew G. Knepley   Input Parameter:
400dce8aebaSBarry Smith . dm - the `DM`
4016858538eSMatthew G. Knepley 
4026858538eSMatthew G. Knepley   Output Parameter:
4036858538eSMatthew G. Knepley . c - global coordinate vector
4046858538eSMatthew G. Knepley 
405dce8aebaSBarry Smith   Level: intermediate
406dce8aebaSBarry Smith 
407dce8aebaSBarry Smith   Notes:
408dce8aebaSBarry Smith   This is a borrowed reference, so the user should NOT destroy this vector. When the `DM` is
4096858538eSMatthew G. Knepley   destroyed the array will no longer be valid.
4106858538eSMatthew G. Knepley 
4116858538eSMatthew G. Knepley   Each process has only the locally-owned portion of the global coordinates (does NOT have the ghost coordinates).
4126858538eSMatthew G. Knepley 
413dce8aebaSBarry Smith   For `DMDA`, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
4146858538eSMatthew G. Knepley   and (x_0,y_0,z_0,x_1,y_1,z_1...)
4156858538eSMatthew G. Knepley 
416dce8aebaSBarry Smith .seealso: `DM`, `DMDA`, `DMSetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMDASetUniformCoordinates()`
4176858538eSMatthew G. Knepley @*/
418d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinates(DM dm, Vec *c)
419d71ae5a4SJacob Faibussowitsch {
4206858538eSMatthew G. Knepley   PetscFunctionBegin;
4216858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4224f572ea9SToby Isaac   PetscAssertPointer(c, 2);
4236858538eSMatthew G. Knepley   if (!dm->coordinates[0].x && dm->coordinates[0].xl) {
4246858538eSMatthew G. Knepley     DM cdm = NULL;
4256858538eSMatthew G. Knepley 
4266858538eSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
4276858538eSMatthew G. Knepley     PetscCall(DMCreateGlobalVector(cdm, &dm->coordinates[0].x));
4286858538eSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm->coordinates[0].x, "coordinates"));
4296858538eSMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(cdm, dm->coordinates[0].xl, INSERT_VALUES, dm->coordinates[0].x));
4306858538eSMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(cdm, dm->coordinates[0].xl, INSERT_VALUES, dm->coordinates[0].x));
4316858538eSMatthew G. Knepley   }
4326858538eSMatthew G. Knepley   *c = dm->coordinates[0].x;
4333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4346858538eSMatthew G. Knepley }
4356858538eSMatthew G. Knepley 
4366858538eSMatthew G. Knepley /*@
437dce8aebaSBarry Smith   DMSetCoordinates - Sets into the `DM` a global vector that holds the coordinates
4386858538eSMatthew G. Knepley 
43920f4b53cSBarry Smith   Collective
4406858538eSMatthew G. Knepley 
4416858538eSMatthew G. Knepley   Input Parameters:
442dce8aebaSBarry Smith + dm - the `DM`
4436858538eSMatthew G. Knepley - c  - coordinate vector
4446858538eSMatthew G. Knepley 
4456858538eSMatthew G. Knepley   Level: intermediate
4466858538eSMatthew G. Knepley 
447dce8aebaSBarry Smith   Notes:
448dce8aebaSBarry Smith   The coordinates do not include those for ghost points, which are in the local vector.
449dce8aebaSBarry Smith 
45020f4b53cSBarry Smith   The vector `c` can be destroyed after the call
451dce8aebaSBarry Smith 
452dce8aebaSBarry Smith .seealso: `DM`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetCoordinateDM()`, `DMDASetUniformCoordinates()`
4536858538eSMatthew G. Knepley @*/
454d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoordinates(DM dm, Vec c)
455d71ae5a4SJacob Faibussowitsch {
4566858538eSMatthew G. Knepley   PetscFunctionBegin;
4576858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4586858538eSMatthew G. Knepley   if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2);
4596858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)c));
4606858538eSMatthew G. Knepley   PetscCall(VecDestroy(&dm->coordinates[0].x));
4616858538eSMatthew G. Knepley   dm->coordinates[0].x = c;
4626858538eSMatthew G. Knepley   PetscCall(VecDestroy(&dm->coordinates[0].xl));
4636858538eSMatthew G. Knepley   PetscCall(DMCoarsenHookAdd(dm, DMRestrictHook_Coordinates, NULL, NULL));
4646858538eSMatthew G. Knepley   PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_Coordinates, NULL, NULL));
4653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4666858538eSMatthew G. Knepley }
4676858538eSMatthew G. Knepley 
4686858538eSMatthew G. Knepley /*@
469dce8aebaSBarry Smith   DMGetCellCoordinates - Gets a global vector with the cellwise coordinates associated with the `DM`.
4706858538eSMatthew G. Knepley 
47120f4b53cSBarry Smith   Collective
4726858538eSMatthew G. Knepley 
4736858538eSMatthew G. Knepley   Input Parameter:
474dce8aebaSBarry Smith . dm - the `DM`
4756858538eSMatthew G. Knepley 
4766858538eSMatthew G. Knepley   Output Parameter:
4776858538eSMatthew G. Knepley . c - global coordinate vector
4786858538eSMatthew G. Knepley 
479dce8aebaSBarry Smith   Level: intermediate
480dce8aebaSBarry Smith 
481dce8aebaSBarry Smith   Notes:
482dce8aebaSBarry Smith   This is a borrowed reference, so the user should NOT destroy this vector. When the `DM` is
4836858538eSMatthew G. Knepley   destroyed the array will no longer be valid.
4846858538eSMatthew G. Knepley 
4856858538eSMatthew G. Knepley   Each process has only the locally-owned portion of the global coordinates (does NOT have the ghost coordinates).
4866858538eSMatthew G. Knepley 
487dce8aebaSBarry Smith .seealso: `DM`, `DMGetCoordinates()`, `DMSetCellCoordinates()`, `DMGetCellCoordinatesLocal()`, `DMGetCellCoordinateDM()`
4886858538eSMatthew G. Knepley @*/
489d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCellCoordinates(DM dm, Vec *c)
490d71ae5a4SJacob Faibussowitsch {
4916858538eSMatthew G. Knepley   PetscFunctionBegin;
4926858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4934f572ea9SToby Isaac   PetscAssertPointer(c, 2);
4946858538eSMatthew G. Knepley   if (!dm->coordinates[1].x && dm->coordinates[1].xl) {
4956858538eSMatthew G. Knepley     DM cdm = NULL;
4966858538eSMatthew G. Knepley 
49711ea91a7SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdm));
4986858538eSMatthew G. Knepley     PetscCall(DMCreateGlobalVector(cdm, &dm->coordinates[1].x));
4996858538eSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm->coordinates[1].x, "DG coordinates"));
5006858538eSMatthew G. Knepley     PetscCall(DMLocalToGlobalBegin(cdm, dm->coordinates[1].xl, INSERT_VALUES, dm->coordinates[1].x));
5016858538eSMatthew G. Knepley     PetscCall(DMLocalToGlobalEnd(cdm, dm->coordinates[1].xl, INSERT_VALUES, dm->coordinates[1].x));
5026858538eSMatthew G. Knepley   }
5036858538eSMatthew G. Knepley   *c = dm->coordinates[1].x;
5043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5056858538eSMatthew G. Knepley }
5066858538eSMatthew G. Knepley 
5076858538eSMatthew G. Knepley /*@
508dce8aebaSBarry Smith   DMSetCellCoordinates - Sets into the `DM` a global vector that holds the cellwise coordinates
5096858538eSMatthew G. Knepley 
51020f4b53cSBarry Smith   Collective
5116858538eSMatthew G. Knepley 
5126858538eSMatthew G. Knepley   Input Parameters:
513dce8aebaSBarry Smith + dm - the `DM`
5146858538eSMatthew G. Knepley - c  - cellwise coordinate vector
5156858538eSMatthew G. Knepley 
5166858538eSMatthew G. Knepley   Level: intermediate
5176858538eSMatthew G. Knepley 
518dce8aebaSBarry Smith   Notes:
519dce8aebaSBarry Smith   The coordinates do not include those for ghost points, which are in the local vector.
520dce8aebaSBarry Smith 
52120f4b53cSBarry Smith   The vector `c` should be destroyed by the caller.
522dce8aebaSBarry Smith 
523dce8aebaSBarry Smith .seealso: `DM`, `DMGetCoordinates()`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMGetCellCoordinatesLocal()`, `DMGetCellCoordinateDM()`
5246858538eSMatthew G. Knepley @*/
525d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCellCoordinates(DM dm, Vec c)
526d71ae5a4SJacob Faibussowitsch {
5276858538eSMatthew G. Knepley   PetscFunctionBegin;
5286858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5296858538eSMatthew G. Knepley   if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2);
5306858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)c));
5316858538eSMatthew G. Knepley   PetscCall(VecDestroy(&dm->coordinates[1].x));
5326858538eSMatthew G. Knepley   dm->coordinates[1].x = c;
5336858538eSMatthew G. Knepley   PetscCall(VecDestroy(&dm->coordinates[1].xl));
5343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5356858538eSMatthew G. Knepley }
5366858538eSMatthew G. Knepley 
5376858538eSMatthew G. Knepley /*@
538dce8aebaSBarry Smith   DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that `DMGetCoordinatesLocalNoncollective()` can be used as non-collective afterwards.
5396858538eSMatthew G. Knepley 
54020f4b53cSBarry Smith   Collective
5416858538eSMatthew G. Knepley 
5426858538eSMatthew G. Knepley   Input Parameter:
543dce8aebaSBarry Smith . dm - the `DM`
5446858538eSMatthew G. Knepley 
5456858538eSMatthew G. Knepley   Level: advanced
5466858538eSMatthew G. Knepley 
547dce8aebaSBarry Smith .seealso: `DM`, `DMSetCoordinates()`, `DMGetCoordinatesLocalNoncollective()`
5486858538eSMatthew G. Knepley @*/
549d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm)
550d71ae5a4SJacob Faibussowitsch {
5516858538eSMatthew G. Knepley   PetscFunctionBegin;
5526858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5536858538eSMatthew G. Knepley   if (!dm->coordinates[0].xl && dm->coordinates[0].x) {
5546858538eSMatthew G. Knepley     DM       cdm = NULL;
5559d92f5ffSMatthew G. Knepley     PetscInt bs;
5566858538eSMatthew G. Knepley 
5576858538eSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
5586858538eSMatthew G. Knepley     PetscCall(DMCreateLocalVector(cdm, &dm->coordinates[0].xl));
5599d92f5ffSMatthew G. Knepley     // If the size of the vector is 0, it will not get the right block size
5609d92f5ffSMatthew G. Knepley     PetscCall(VecGetBlockSize(dm->coordinates[0].x, &bs));
5619d92f5ffSMatthew G. Knepley     PetscCall(VecSetBlockSize(dm->coordinates[0].xl, bs));
5626858538eSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm->coordinates[0].xl, "coordinates"));
5636858538eSMatthew G. Knepley     PetscCall(DMGlobalToLocalBegin(cdm, dm->coordinates[0].x, INSERT_VALUES, dm->coordinates[0].xl));
5646858538eSMatthew G. Knepley     PetscCall(DMGlobalToLocalEnd(cdm, dm->coordinates[0].x, INSERT_VALUES, dm->coordinates[0].xl));
5656858538eSMatthew G. Knepley   }
5663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5676858538eSMatthew G. Knepley }
5686858538eSMatthew G. Knepley 
5696858538eSMatthew G. Knepley /*@
570dce8aebaSBarry Smith   DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the `DM`.
5716858538eSMatthew G. Knepley 
57220f4b53cSBarry Smith   Collective the first time it is called
5736858538eSMatthew G. Knepley 
5746858538eSMatthew G. Knepley   Input Parameter:
575dce8aebaSBarry Smith . dm - the `DM`
5766858538eSMatthew G. Knepley 
5776858538eSMatthew G. Knepley   Output Parameter:
5786858538eSMatthew G. Knepley . c - coordinate vector
5796858538eSMatthew G. Knepley 
580dce8aebaSBarry Smith   Level: intermediate
581dce8aebaSBarry Smith 
582dce8aebaSBarry Smith   Notes:
5836858538eSMatthew G. Knepley   This is a borrowed reference, so the user should NOT destroy this vector
5846858538eSMatthew G. Knepley 
5856858538eSMatthew G. Knepley   Each process has the local and ghost coordinates
5866858538eSMatthew G. Knepley 
587dce8aebaSBarry Smith   For `DMDA`, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
5886858538eSMatthew G. Knepley   and (x_0,y_0,z_0,x_1,y_1,z_1...)
5896858538eSMatthew G. Knepley 
590dce8aebaSBarry Smith .seealso: `DM`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMSetCoordinates()`, `DMGetCoordinateDM()`, `DMGetCoordinatesLocalNoncollective()`
5916858538eSMatthew G. Knepley @*/
592d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c)
593d71ae5a4SJacob Faibussowitsch {
5946858538eSMatthew G. Knepley   PetscFunctionBegin;
5956858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5964f572ea9SToby Isaac   PetscAssertPointer(c, 2);
5976858538eSMatthew G. Knepley   PetscCall(DMGetCoordinatesLocalSetUp(dm));
5986858538eSMatthew G. Knepley   *c = dm->coordinates[0].xl;
5993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6006858538eSMatthew G. Knepley }
6016858538eSMatthew G. Knepley 
6026858538eSMatthew G. Knepley /*@
603dce8aebaSBarry Smith   DMGetCoordinatesLocalNoncollective - Non-collective version of `DMGetCoordinatesLocal()`. Fails if global coordinates have been set and `DMGetCoordinatesLocalSetUp()` not called.
6046858538eSMatthew G. Knepley 
60520f4b53cSBarry Smith   Not Collective
6066858538eSMatthew G. Knepley 
6076858538eSMatthew G. Knepley   Input Parameter:
608dce8aebaSBarry Smith . dm - the `DM`
6096858538eSMatthew G. Knepley 
6106858538eSMatthew G. Knepley   Output Parameter:
6116858538eSMatthew G. Knepley . c - coordinate vector
6126858538eSMatthew G. Knepley 
6136858538eSMatthew G. Knepley   Level: advanced
6146858538eSMatthew G. Knepley 
615dce8aebaSBarry Smith   Note:
616dce8aebaSBarry Smith   A previous call to  `DMGetCoordinatesLocal()` or `DMGetCoordinatesLocalSetUp()` ensures that a call to this function will not error.
617dce8aebaSBarry Smith 
618dce8aebaSBarry Smith .seealso: `DM`, `DMGetCoordinatesLocalSetUp()`, `DMGetCoordinatesLocal()`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMSetCoordinates()`, `DMGetCoordinateDM()`
6196858538eSMatthew G. Knepley @*/
620d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c)
621d71ae5a4SJacob Faibussowitsch {
6226858538eSMatthew G. Knepley   PetscFunctionBegin;
6236858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6244f572ea9SToby Isaac   PetscAssertPointer(c, 2);
6256858538eSMatthew G. Knepley   PetscCheck(dm->coordinates[0].xl || !dm->coordinates[0].x, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called");
6266858538eSMatthew G. Knepley   *c = dm->coordinates[0].xl;
6273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6286858538eSMatthew G. Knepley }
6296858538eSMatthew G. Knepley 
6306858538eSMatthew G. Knepley /*@
631dce8aebaSBarry Smith   DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and the section describing its layout.
6326858538eSMatthew G. Knepley 
63320f4b53cSBarry Smith   Not Collective
6346858538eSMatthew G. Knepley 
6356858538eSMatthew G. Knepley   Input Parameters:
636dce8aebaSBarry Smith + dm - the `DM`
637dce8aebaSBarry Smith - p  - the `IS` of points whose coordinates will be returned
6386858538eSMatthew G. Knepley 
6396858538eSMatthew G. Knepley   Output Parameters:
640dce8aebaSBarry Smith + pCoordSection - the `PetscSection` describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates
641dce8aebaSBarry Smith - pCoord        - the `Vec` with coordinates of points in p
6426858538eSMatthew G. Knepley 
643dce8aebaSBarry Smith   Level: advanced
644dce8aebaSBarry Smith 
645dce8aebaSBarry Smith   Notes:
646dce8aebaSBarry Smith   `DMGetCoordinatesLocalSetUp()` must be called first. This function employs `DMGetCoordinatesLocalNoncollective()` so it is not collective.
6476858538eSMatthew G. Knepley 
6486858538eSMatthew G. Knepley   This creates a new vector, so the user SHOULD destroy this vector
6496858538eSMatthew G. Knepley 
6506858538eSMatthew G. Knepley   Each process has the local and ghost coordinates
6516858538eSMatthew G. Knepley 
652dce8aebaSBarry Smith   For `DMDA`, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
6536858538eSMatthew G. Knepley   and (x_0,y_0,z_0,x_1,y_1,z_1...)
6546858538eSMatthew G. Knepley 
655dce8aebaSBarry Smith .seealso: `DM`, `DMDA`, `DMSetCoordinatesLocal()`, `DMGetCoordinatesLocal()`, `DMGetCoordinatesLocalNoncollective()`, `DMGetCoordinatesLocalSetUp()`, `DMGetCoordinates()`, `DMSetCoordinates()`, `DMGetCoordinateDM()`
6566858538eSMatthew G. Knepley @*/
657d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord)
658d71ae5a4SJacob Faibussowitsch {
6596858538eSMatthew G. Knepley   DM                 cdm;
6606858538eSMatthew G. Knepley   PetscSection       cs, newcs;
6616858538eSMatthew G. Knepley   Vec                coords;
6626858538eSMatthew G. Knepley   const PetscScalar *arr;
6636858538eSMatthew G. Knepley   PetscScalar       *newarr = NULL;
6646858538eSMatthew G. Knepley   PetscInt           n;
6656858538eSMatthew G. Knepley 
6666858538eSMatthew G. Knepley   PetscFunctionBegin;
6676858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6686858538eSMatthew G. Knepley   PetscValidHeaderSpecific(p, IS_CLASSID, 2);
6694f572ea9SToby Isaac   if (pCoordSection) PetscAssertPointer(pCoordSection, 3);
6704f572ea9SToby Isaac   if (pCoord) PetscAssertPointer(pCoord, 4);
6716858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
6726858538eSMatthew G. Knepley   PetscCall(DMGetLocalSection(cdm, &cs));
6736858538eSMatthew G. Knepley   PetscCall(DMGetCoordinatesLocal(dm, &coords));
6746858538eSMatthew G. Knepley   PetscCheck(coords, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set");
6756858538eSMatthew G. Knepley   PetscCheck(cdm && cs, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported");
6766858538eSMatthew G. Knepley   PetscCall(VecGetArrayRead(coords, &arr));
6776858538eSMatthew G. Knepley   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void **)&newarr) : NULL));
6786858538eSMatthew G. Knepley   PetscCall(VecRestoreArrayRead(coords, &arr));
6796858538eSMatthew G. Knepley   if (pCoord) {
6806858538eSMatthew G. Knepley     PetscCall(PetscSectionGetStorageSize(newcs, &n));
6816858538eSMatthew G. Knepley     /* set array in two steps to mimic PETSC_OWN_POINTER */
6826858538eSMatthew G. Knepley     PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord));
6836858538eSMatthew G. Knepley     PetscCall(VecReplaceArray(*pCoord, newarr));
6846858538eSMatthew G. Knepley   } else {
6856858538eSMatthew G. Knepley     PetscCall(PetscFree(newarr));
6866858538eSMatthew G. Knepley   }
6879371c9d4SSatish Balay   if (pCoordSection) {
6889371c9d4SSatish Balay     *pCoordSection = newcs;
6899371c9d4SSatish Balay   } else PetscCall(PetscSectionDestroy(&newcs));
6903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6916858538eSMatthew G. Knepley }
6926858538eSMatthew G. Knepley 
6936858538eSMatthew G. Knepley /*@
694dce8aebaSBarry Smith   DMSetCoordinatesLocal - Sets into the `DM` a local vector, including ghost points, that holds the coordinates
6956858538eSMatthew G. Knepley 
69620f4b53cSBarry Smith   Not Collective
6976858538eSMatthew G. Knepley 
6986858538eSMatthew G. Knepley   Input Parameters:
699dce8aebaSBarry Smith + dm - the `DM`
7006858538eSMatthew G. Knepley - c  - coordinate vector
7016858538eSMatthew G. Knepley 
702dce8aebaSBarry Smith   Level: intermediate
703dce8aebaSBarry Smith 
7046858538eSMatthew G. Knepley   Notes:
705dce8aebaSBarry Smith   The coordinates of ghost points can be set using `DMSetCoordinates()`
706dce8aebaSBarry Smith   followed by `DMGetCoordinatesLocal()`. This is intended to enable the
7076858538eSMatthew G. Knepley   setting of ghost coordinates outside of the domain.
7086858538eSMatthew G. Knepley 
7096858538eSMatthew G. Knepley   The vector c should be destroyed by the caller.
7106858538eSMatthew G. Knepley 
711dce8aebaSBarry Smith .seealso: `DM`, `DMGetCoordinatesLocal()`, `DMSetCoordinates()`, `DMGetCoordinates()`, `DMGetCoordinateDM()`
7126858538eSMatthew G. Knepley @*/
713d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c)
714d71ae5a4SJacob Faibussowitsch {
7156858538eSMatthew G. Knepley   PetscFunctionBegin;
7166858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7176858538eSMatthew G. Knepley   if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2);
7186858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)c));
7196858538eSMatthew G. Knepley   PetscCall(VecDestroy(&dm->coordinates[0].xl));
7206858538eSMatthew G. Knepley   dm->coordinates[0].xl = c;
7216858538eSMatthew G. Knepley   PetscCall(VecDestroy(&dm->coordinates[0].x));
7223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7236858538eSMatthew G. Knepley }
7246858538eSMatthew G. Knepley 
7256858538eSMatthew G. Knepley /*@
726dce8aebaSBarry Smith   DMGetCellCoordinatesLocalSetUp - Prepares a local vector of cellwise coordinates, so that `DMGetCellCoordinatesLocalNoncollective()` can be used as non-collective afterwards.
7276858538eSMatthew G. Knepley 
72820f4b53cSBarry Smith   Collective
7296858538eSMatthew G. Knepley 
7306858538eSMatthew G. Knepley   Input Parameter:
731dce8aebaSBarry Smith . dm - the `DM`
7326858538eSMatthew G. Knepley 
7336858538eSMatthew G. Knepley   Level: advanced
7346858538eSMatthew G. Knepley 
735dce8aebaSBarry Smith .seealso: `DM`, `DMGetCellCoordinatesLocalNoncollective()`
7366858538eSMatthew G. Knepley @*/
737d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCellCoordinatesLocalSetUp(DM dm)
738d71ae5a4SJacob Faibussowitsch {
7396858538eSMatthew G. Knepley   PetscFunctionBegin;
7406858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7416858538eSMatthew G. Knepley   if (!dm->coordinates[1].xl && dm->coordinates[1].x) {
7426858538eSMatthew G. Knepley     DM cdm = NULL;
7436858538eSMatthew G. Knepley 
74411ea91a7SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdm));
7456858538eSMatthew G. Knepley     PetscCall(DMCreateLocalVector(cdm, &dm->coordinates[1].xl));
7466858538eSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm->coordinates[1].xl, "DG coordinates"));
7476858538eSMatthew G. Knepley     PetscCall(DMGlobalToLocalBegin(cdm, dm->coordinates[1].x, INSERT_VALUES, dm->coordinates[1].xl));
7486858538eSMatthew G. Knepley     PetscCall(DMGlobalToLocalEnd(cdm, dm->coordinates[1].x, INSERT_VALUES, dm->coordinates[1].xl));
7496858538eSMatthew G. Knepley   }
7503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7516858538eSMatthew G. Knepley }
7526858538eSMatthew G. Knepley 
7536858538eSMatthew G. Knepley /*@
754dce8aebaSBarry Smith   DMGetCellCoordinatesLocal - Gets a local vector with the cellwise coordinates associated with the `DM`.
7556858538eSMatthew G. Knepley 
75620f4b53cSBarry Smith   Collective
7576858538eSMatthew G. Knepley 
7586858538eSMatthew G. Knepley   Input Parameter:
759dce8aebaSBarry Smith . dm - the `DM`
7606858538eSMatthew G. Knepley 
7616858538eSMatthew G. Knepley   Output Parameter:
7626858538eSMatthew G. Knepley . c - coordinate vector
7636858538eSMatthew G. Knepley 
764dce8aebaSBarry Smith   Level: intermediate
765dce8aebaSBarry Smith 
766dce8aebaSBarry Smith   Notes:
7676858538eSMatthew G. Knepley   This is a borrowed reference, so the user should NOT destroy this vector
7686858538eSMatthew G. Knepley 
7696858538eSMatthew G. Knepley   Each process has the local and ghost coordinates
7706858538eSMatthew G. Knepley 
771dce8aebaSBarry Smith .seealso: `DM`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMSetCellCoordinates()`, `DMGetCellCoordinateDM()`, `DMGetCellCoordinatesLocalNoncollective()`
7726858538eSMatthew G. Knepley @*/
773d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCellCoordinatesLocal(DM dm, Vec *c)
774d71ae5a4SJacob Faibussowitsch {
7756858538eSMatthew G. Knepley   PetscFunctionBegin;
7766858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7774f572ea9SToby Isaac   PetscAssertPointer(c, 2);
7786858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocalSetUp(dm));
7796858538eSMatthew G. Knepley   *c = dm->coordinates[1].xl;
7803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7816858538eSMatthew G. Knepley }
7826858538eSMatthew G. Knepley 
7836858538eSMatthew G. Knepley /*@
784dce8aebaSBarry Smith   DMGetCellCoordinatesLocalNoncollective - Non-collective version of `DMGetCellCoordinatesLocal()`. Fails if global cellwise coordinates have been set and `DMGetCellCoordinatesLocalSetUp()` not called.
7856858538eSMatthew G. Knepley 
78620f4b53cSBarry Smith   Not Collective
7876858538eSMatthew G. Knepley 
7886858538eSMatthew G. Knepley   Input Parameter:
789dce8aebaSBarry Smith . dm - the `DM`
7906858538eSMatthew G. Knepley 
7916858538eSMatthew G. Knepley   Output Parameter:
7926858538eSMatthew G. Knepley . c - cellwise coordinate vector
7936858538eSMatthew G. Knepley 
7946858538eSMatthew G. Knepley   Level: advanced
7956858538eSMatthew G. Knepley 
796dce8aebaSBarry Smith .seealso: `DM`, `DMGetCellCoordinatesLocalSetUp()`, `DMGetCellCoordinatesLocal()`, `DMSetCellCoordinatesLocal()`, `DMGetCellCoordinates()`, `DMSetCellCoordinates()`, `DMGetCellCoordinateDM()`
7976858538eSMatthew G. Knepley @*/
798d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCellCoordinatesLocalNoncollective(DM dm, Vec *c)
799d71ae5a4SJacob Faibussowitsch {
8006858538eSMatthew G. Knepley   PetscFunctionBegin;
8016858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8024f572ea9SToby Isaac   PetscAssertPointer(c, 2);
8036858538eSMatthew G. Knepley   PetscCheck(dm->coordinates[1].xl || !dm->coordinates[1].x, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCellCoordinatesLocalSetUp() has not been called");
8046858538eSMatthew G. Knepley   *c = dm->coordinates[1].xl;
8053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8066858538eSMatthew G. Knepley }
8076858538eSMatthew G. Knepley 
8086858538eSMatthew G. Knepley /*@
809dce8aebaSBarry Smith   DMSetCellCoordinatesLocal - Sets into the `DM` a local vector including ghost points that holds the cellwise coordinates
8106858538eSMatthew G. Knepley 
81120f4b53cSBarry Smith   Not Collective
8126858538eSMatthew G. Knepley 
8136858538eSMatthew G. Knepley   Input Parameters:
814dce8aebaSBarry Smith + dm - the `DM`
8156858538eSMatthew G. Knepley - c  - cellwise coordinate vector
8166858538eSMatthew G. Knepley 
817dce8aebaSBarry Smith   Level: intermediate
818dce8aebaSBarry Smith 
8196858538eSMatthew G. Knepley   Notes:
820dce8aebaSBarry Smith   The coordinates of ghost points can be set using `DMSetCoordinates()`
821dce8aebaSBarry Smith   followed by `DMGetCoordinatesLocal()`. This is intended to enable the
8226858538eSMatthew G. Knepley   setting of ghost coordinates outside of the domain.
8236858538eSMatthew G. Knepley 
8246858538eSMatthew G. Knepley   The vector c should be destroyed by the caller.
8256858538eSMatthew G. Knepley 
826dce8aebaSBarry Smith .seealso: `DM`, `DMGetCellCoordinatesLocal()`, `DMSetCellCoordinates()`, `DMGetCellCoordinates()`, `DMGetCellCoordinateDM()`
8276858538eSMatthew G. Knepley @*/
828d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCellCoordinatesLocal(DM dm, Vec c)
829d71ae5a4SJacob Faibussowitsch {
8306858538eSMatthew G. Knepley   PetscFunctionBegin;
8316858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8326858538eSMatthew G. Knepley   if (c) PetscValidHeaderSpecific(c, VEC_CLASSID, 2);
8336858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)c));
8346858538eSMatthew G. Knepley   PetscCall(VecDestroy(&dm->coordinates[1].xl));
8356858538eSMatthew G. Knepley   dm->coordinates[1].xl = c;
8366858538eSMatthew G. Knepley   PetscCall(VecDestroy(&dm->coordinates[1].x));
8373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8386858538eSMatthew G. Knepley }
8396858538eSMatthew G. Knepley 
840d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinateField(DM dm, DMField *field)
841d71ae5a4SJacob Faibussowitsch {
8426858538eSMatthew G. Knepley   PetscFunctionBegin;
8436858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8444f572ea9SToby Isaac   PetscAssertPointer(field, 2);
8456858538eSMatthew G. Knepley   if (!dm->coordinates[0].field) {
8466858538eSMatthew G. Knepley     if (dm->ops->createcoordinatefield) PetscCall((*dm->ops->createcoordinatefield)(dm, &dm->coordinates[0].field));
8476858538eSMatthew G. Knepley   }
8486858538eSMatthew G. Knepley   *field = dm->coordinates[0].field;
8493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8506858538eSMatthew G. Knepley }
8516858538eSMatthew G. Knepley 
852d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetCoordinateField(DM dm, DMField field)
853d71ae5a4SJacob Faibussowitsch {
8546858538eSMatthew G. Knepley   PetscFunctionBegin;
8556858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8566858538eSMatthew G. Knepley   if (field) PetscValidHeaderSpecific(field, DMFIELD_CLASSID, 2);
8576858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)field));
8586858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&dm->coordinates[0].field));
8596858538eSMatthew G. Knepley   dm->coordinates[0].field = field;
8603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8616858538eSMatthew G. Knepley }
8626858538eSMatthew G. Knepley 
8636858538eSMatthew G. Knepley /*@
864dce8aebaSBarry Smith   DMGetLocalBoundingBox - Returns the bounding box for the piece of the `DM` on this process.
8656858538eSMatthew G. Knepley 
86620f4b53cSBarry Smith   Not Collective
8676858538eSMatthew G. Knepley 
8686858538eSMatthew G. Knepley   Input Parameter:
869dce8aebaSBarry Smith . dm - the `DM`
8706858538eSMatthew G. Knepley 
8716858538eSMatthew G. Knepley   Output Parameters:
8726858538eSMatthew G. Knepley + lmin - local minimum coordinates (length coord dim, optional)
87335cb6cd3SPierre Jolivet - lmax - local maximum coordinates (length coord dim, optional)
8746858538eSMatthew G. Knepley 
8756858538eSMatthew G. Knepley   Level: beginner
8766858538eSMatthew G. Knepley 
877dce8aebaSBarry Smith   Note:
878dce8aebaSBarry Smith   If the `DM` is a `DMDA` and has no coordinates, the index bounds are returned instead.
8796858538eSMatthew G. Knepley 
880dce8aebaSBarry Smith .seealso: `DM`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMGetBoundingBox()`
8816858538eSMatthew G. Knepley @*/
882d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetLocalBoundingBox(DM dm, PetscReal lmin[], PetscReal lmax[])
883d71ae5a4SJacob Faibussowitsch {
8846858538eSMatthew G. Knepley   Vec       coords = NULL;
8856858538eSMatthew G. Knepley   PetscReal min[3] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL};
8866858538eSMatthew G. Knepley   PetscReal max[3] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
8876858538eSMatthew G. Knepley   PetscInt  cdim, i, j;
8886858538eSMatthew G. Knepley 
8896858538eSMatthew G. Knepley   PetscFunctionBegin;
8906858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8916858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDim(dm, &cdim));
892bdf15c88SMatthew G. Knepley   PetscCall(DMGetCoordinatesLocal(dm, &coords));
893bdf15c88SMatthew G. Knepley   if (coords) {
894bdf15c88SMatthew G. Knepley     const PetscScalar *local_coords;
895bdf15c88SMatthew G. Knepley     PetscInt           N, Ni;
896bdf15c88SMatthew G. Knepley 
897bdf15c88SMatthew G. Knepley     for (j = cdim; j < 3; ++j) {
898bdf15c88SMatthew G. Knepley       min[j] = 0;
899bdf15c88SMatthew G. Knepley       max[j] = 0;
900bdf15c88SMatthew G. Knepley     }
901bdf15c88SMatthew G. Knepley     PetscCall(VecGetArrayRead(coords, &local_coords));
902bdf15c88SMatthew G. Knepley     PetscCall(VecGetLocalSize(coords, &N));
903bdf15c88SMatthew G. Knepley     Ni = N / cdim;
904bdf15c88SMatthew G. Knepley     for (i = 0; i < Ni; ++i) {
905bdf15c88SMatthew G. Knepley       for (j = 0; j < cdim; ++j) {
906bdf15c88SMatthew G. Knepley         min[j] = PetscMin(min[j], PetscRealPart(local_coords[i * cdim + j]));
907bdf15c88SMatthew G. Knepley         max[j] = PetscMax(max[j], PetscRealPart(local_coords[i * cdim + j]));
908bdf15c88SMatthew G. Knepley       }
909bdf15c88SMatthew G. Knepley     }
910bdf15c88SMatthew G. Knepley     PetscCall(VecRestoreArrayRead(coords, &local_coords));
911bdf15c88SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coords));
9126858538eSMatthew G. Knepley     if (coords) {
9136858538eSMatthew G. Knepley       PetscCall(VecGetArrayRead(coords, &local_coords));
9146858538eSMatthew G. Knepley       PetscCall(VecGetLocalSize(coords, &N));
9156858538eSMatthew G. Knepley       Ni = N / cdim;
9166858538eSMatthew G. Knepley       for (i = 0; i < Ni; ++i) {
917bdf15c88SMatthew G. Knepley         for (j = 0; j < cdim; ++j) {
918bdf15c88SMatthew G. Knepley           min[j] = PetscMin(min[j], PetscRealPart(local_coords[i * cdim + j]));
919bdf15c88SMatthew G. Knepley           max[j] = PetscMax(max[j], PetscRealPart(local_coords[i * cdim + j]));
9206858538eSMatthew G. Knepley         }
9216858538eSMatthew G. Knepley       }
9226858538eSMatthew G. Knepley       PetscCall(VecRestoreArrayRead(coords, &local_coords));
923bdf15c88SMatthew G. Knepley     }
9246858538eSMatthew G. Knepley   } else {
9256858538eSMatthew G. Knepley     PetscBool isda;
9266858538eSMatthew G. Knepley 
9276858538eSMatthew G. Knepley     PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMDA, &isda));
9286858538eSMatthew G. Knepley     if (isda) PetscCall(DMGetLocalBoundingIndices_DMDA(dm, min, max));
9296858538eSMatthew G. Knepley   }
9306858538eSMatthew G. Knepley   if (lmin) PetscCall(PetscArraycpy(lmin, min, cdim));
9316858538eSMatthew G. Knepley   if (lmax) PetscCall(PetscArraycpy(lmax, max, cdim));
9323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9336858538eSMatthew G. Knepley }
9346858538eSMatthew G. Knepley 
9356858538eSMatthew G. Knepley /*@
936dce8aebaSBarry Smith   DMGetBoundingBox - Returns the global bounding box for the `DM`.
9376858538eSMatthew G. Knepley 
9386858538eSMatthew G. Knepley   Collective
9396858538eSMatthew G. Knepley 
9406858538eSMatthew G. Knepley   Input Parameter:
941dce8aebaSBarry Smith . dm - the `DM`
9426858538eSMatthew G. Knepley 
9436858538eSMatthew G. Knepley   Output Parameters:
9446858538eSMatthew G. Knepley + gmin - global minimum coordinates (length coord dim, optional)
94535cb6cd3SPierre Jolivet - gmax - global maximum coordinates (length coord dim, optional)
9466858538eSMatthew G. Knepley 
9476858538eSMatthew G. Knepley   Level: beginner
9486858538eSMatthew G. Knepley 
949dce8aebaSBarry Smith .seealso: `DM`, `DMGetLocalBoundingBox()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`
9506858538eSMatthew G. Knepley @*/
951d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetBoundingBox(DM dm, PetscReal gmin[], PetscReal gmax[])
952d71ae5a4SJacob Faibussowitsch {
9536858538eSMatthew G. Knepley   PetscReal   lmin[3], lmax[3];
9546858538eSMatthew G. Knepley   PetscInt    cdim;
9556858538eSMatthew G. Knepley   PetscMPIInt count;
9566858538eSMatthew G. Knepley 
9576858538eSMatthew G. Knepley   PetscFunctionBegin;
9586858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9596858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDim(dm, &cdim));
9606858538eSMatthew G. Knepley   PetscCall(PetscMPIIntCast(cdim, &count));
9616858538eSMatthew G. Knepley   PetscCall(DMGetLocalBoundingBox(dm, lmin, lmax));
9626858538eSMatthew G. Knepley   if (gmin) PetscCall(MPIU_Allreduce(lmin, gmin, count, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)dm)));
9636858538eSMatthew G. Knepley   if (gmax) PetscCall(MPIU_Allreduce(lmax, gmax, count, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm)));
9643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9656858538eSMatthew G. Knepley }
9666858538eSMatthew G. Knepley 
967*e44f6aebSMatthew G. Knepley static PetscErrorCode DMCreateAffineCoordinates_Internal(DM dm)
96890612307SJed Brown {
969*e44f6aebSMatthew G. Knepley   DM             cdm;
970*e44f6aebSMatthew G. Knepley   PetscFE        feLinear;
971*e44f6aebSMatthew G. Knepley   DMPolytopeType ct;
972*e44f6aebSMatthew G. Knepley   PetscInt       dim, dE, cStart, cEnd, gct;
973*e44f6aebSMatthew G. Knepley 
974*e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
975*e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
976*e44f6aebSMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
977*e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDim(dm, &dE));
978*e44f6aebSMatthew G. Knepley   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
979*e44f6aebSMatthew G. Knepley   if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct));
980*e44f6aebSMatthew G. Knepley   else ct = DM_POLYTOPE_UNKNOWN;
981*e44f6aebSMatthew G. Knepley   gct = (PetscInt)ct;
982*e44f6aebSMatthew G. Knepley   PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm)));
983*e44f6aebSMatthew G. Knepley   ct = (DMPolytopeType)gct;
984*e44f6aebSMatthew G. Knepley   // Work around current bug in PetscDualSpaceSetUp_Lagrange()
985*e44f6aebSMatthew G. Knepley   //   Can be seen in plex_tutorials-ex10_1
986*e44f6aebSMatthew G. Knepley   if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) {
987*e44f6aebSMatthew G. Knepley     PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, 1, -1, &feLinear));
988*e44f6aebSMatthew G. Knepley     PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)feLinear));
989*e44f6aebSMatthew G. Knepley     PetscCall(PetscFEDestroy(&feLinear));
990*e44f6aebSMatthew G. Knepley     PetscCall(DMCreateDS(cdm));
991*e44f6aebSMatthew G. Knepley   }
992*e44f6aebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
993*e44f6aebSMatthew G. Knepley }
994*e44f6aebSMatthew G. Knepley 
995*e44f6aebSMatthew G. Knepley PetscErrorCode DMGetCoordinateDegree_Internal(DM dm, PetscInt *degree)
996*e44f6aebSMatthew G. Knepley {
997*e44f6aebSMatthew G. Knepley   DM           cdm;
998*e44f6aebSMatthew G. Knepley   PetscFE      fe;
999*e44f6aebSMatthew G. Knepley   PetscSpace   sp;
1000*e44f6aebSMatthew G. Knepley   PetscClassId id;
1001*e44f6aebSMatthew G. Knepley 
1002*e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
1003*e44f6aebSMatthew G. Knepley   *degree = 1;
1004*e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
1005*e44f6aebSMatthew G. Knepley   PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe));
1006*e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
1007*e44f6aebSMatthew G. Knepley   if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS);
1008*e44f6aebSMatthew G. Knepley   PetscCall(PetscFEGetBasisSpace(fe, &sp));
1009*e44f6aebSMatthew G. Knepley   PetscCall(PetscSpaceGetDegree(sp, degree, NULL));
1010*e44f6aebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
101190612307SJed Brown }
101290612307SJed Brown 
10136858538eSMatthew G. Knepley /*@
1014*e44f6aebSMatthew G. Knepley   DMSetCoordinateDisc - Set a coordinate space
10156858538eSMatthew G. Knepley 
10166858538eSMatthew G. Knepley   Input Parameters:
1017dce8aebaSBarry Smith + dm      - The `DM` object
1018*e44f6aebSMatthew G. Knepley . disc    - The new coordinate discretization or NULL to ensure a coordinate discretization exists
1019*e44f6aebSMatthew G. Knepley - project - Project coordinates to new discretization
10206858538eSMatthew G. Knepley 
10216858538eSMatthew G. Knepley   Level: intermediate
10226858538eSMatthew G. Knepley 
1023dce8aebaSBarry Smith   Notes:
1024*e44f6aebSMatthew G. Knepley   A `PetscFE` defines an approximation space using a `PetscSpace`, which represents the basis functions, and a `PetscDualSpace`, which defines the interpolation operation in the space.
1025dce8aebaSBarry Smith 
1026dce8aebaSBarry Smith   This function takes the current mesh coordinates, which are discretized using some `PetscFE` space, and projects this function into a new `PetscFE` space.
1027*e44f6aebSMatthew G. Knepley   The coordinate projection is done on the continuous coordinates, but the discontinuous coordinates are not updated.
1028dce8aebaSBarry Smith 
102960225df5SJacob Faibussowitsch   Developer Notes:
1030dce8aebaSBarry Smith   With more effort, we could directly project the discontinuous coordinates also.
1031dce8aebaSBarry Smith 
1032dce8aebaSBarry Smith .seealso: `DM`, `PetscFE`, `DMGetCoordinateField()`
10336858538eSMatthew G. Knepley @*/
1034*e44f6aebSMatthew G. Knepley PetscErrorCode DMSetCoordinateDisc(DM dm, PetscFE disc, PetscBool project)
1035d71ae5a4SJacob Faibussowitsch {
1036*e44f6aebSMatthew G. Knepley   DM           cdmOld, cdmNew;
10376858538eSMatthew G. Knepley   PetscFE      discOld;
10386858538eSMatthew G. Knepley   PetscClassId classid;
10396858538eSMatthew G. Knepley   Vec          coordsOld, coordsNew;
10406858538eSMatthew G. Knepley   PetscBool    same_space = PETSC_TRUE;
1041dd4c3f67SMatthew G. Knepley   const char  *prefix;
10426858538eSMatthew G. Knepley 
10436858538eSMatthew G. Knepley   PetscFunctionBegin;
10446858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10456858538eSMatthew G. Knepley   if (disc) PetscValidHeaderSpecific(disc, PETSCFE_CLASSID, 2);
10466858538eSMatthew G. Knepley 
10476858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdmOld));
10486858538eSMatthew G. Knepley   /* Check current discretization is compatible */
10496858538eSMatthew G. Knepley   PetscCall(DMGetField(cdmOld, 0, NULL, (PetscObject *)&discOld));
10506858538eSMatthew G. Knepley   PetscCall(PetscObjectGetClassId((PetscObject)discOld, &classid));
10516858538eSMatthew G. Knepley   if (classid != PETSCFE_CLASSID) {
10526858538eSMatthew G. Knepley     if (classid == PETSC_CONTAINER_CLASSID) {
1053*e44f6aebSMatthew G. Knepley       PetscCall(DMCreateAffineCoordinates_Internal(dm));
10546858538eSMatthew G. Knepley       PetscCall(DMGetField(cdmOld, 0, NULL, (PetscObject *)&discOld));
10556858538eSMatthew G. Knepley     } else {
10566858538eSMatthew G. Knepley       const char *discname;
10576858538eSMatthew G. Knepley 
10586858538eSMatthew G. Knepley       PetscCall(PetscObjectGetType((PetscObject)discOld, &discname));
10596858538eSMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)discOld), PETSC_ERR_SUP, "Discretization type %s not supported", discname);
10606858538eSMatthew G. Knepley     }
10616858538eSMatthew G. Knepley   }
1062*e44f6aebSMatthew G. Knepley   // Linear space has been created by now
10633ba16761SJacob Faibussowitsch   if (!disc) PetscFunctionReturn(PETSC_SUCCESS);
1064*e44f6aebSMatthew G. Knepley   // Check if the new space is the same as the old modulo quadrature
1065*e44f6aebSMatthew G. Knepley   {
10666858538eSMatthew G. Knepley     PetscDualSpace dsOld, ds;
10676858538eSMatthew G. Knepley     PetscCall(PetscFEGetDualSpace(discOld, &dsOld));
10686858538eSMatthew G. Knepley     PetscCall(PetscFEGetDualSpace(disc, &ds));
10696858538eSMatthew G. Knepley     PetscCall(PetscDualSpaceEqual(dsOld, ds, &same_space));
10706858538eSMatthew G. Knepley   }
1071*e44f6aebSMatthew G. Knepley   // Make a fresh clone of the coordinate DM
10726858538eSMatthew G. Knepley   PetscCall(DMClone(cdmOld, &cdmNew));
1073dd4c3f67SMatthew G. Knepley   cdmNew->cloneOpts = PETSC_TRUE;
1074dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)cdmOld, &prefix));
1075dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)cdmNew, prefix));
10766858538eSMatthew G. Knepley   PetscCall(DMSetField(cdmNew, 0, NULL, (PetscObject)disc));
10776858538eSMatthew G. Knepley   PetscCall(DMCreateDS(cdmNew));
1078*e44f6aebSMatthew G. Knepley   {
1079*e44f6aebSMatthew G. Knepley     PetscDS ds, nds;
1080*e44f6aebSMatthew G. Knepley 
1081*e44f6aebSMatthew G. Knepley     PetscCall(DMGetDS(cdmOld, &ds));
1082*e44f6aebSMatthew G. Knepley     PetscCall(DMGetDS(cdmNew, &nds));
1083*e44f6aebSMatthew G. Knepley     PetscCall(PetscDSCopyConstants(ds, nds));
1084*e44f6aebSMatthew G. Knepley   }
10856725e60dSJed Brown   if (cdmOld->periodic.setup) {
10866725e60dSJed Brown     cdmNew->periodic.setup = cdmOld->periodic.setup;
10876725e60dSJed Brown     PetscCall(cdmNew->periodic.setup(cdmNew));
10886725e60dSJed Brown   }
1089dd4c3f67SMatthew G. Knepley   if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(cdmNew));
1090*e44f6aebSMatthew G. Knepley   if (project) {
10916858538eSMatthew G. Knepley     PetscCall(DMGetCoordinates(dm, &coordsOld));
10926858538eSMatthew G. Knepley     PetscCall(DMCreateGlobalVector(cdmNew, &coordsNew));
1093f0ac6e35SMatthew G. Knepley     if (same_space) {
1094f0ac6e35SMatthew G. Knepley       // Need to copy so that the new vector has the right dm
1095f0ac6e35SMatthew G. Knepley       PetscCall(VecCopy(coordsOld, coordsNew));
1096*e44f6aebSMatthew G. Knepley     } else {
1097*e44f6aebSMatthew G. Knepley       Mat In;
1098*e44f6aebSMatthew G. Knepley 
1099*e44f6aebSMatthew G. Knepley       PetscCall(DMCreateInterpolation(cdmOld, cdmNew, &In, NULL));
1100*e44f6aebSMatthew G. Knepley       PetscCall(MatMult(In, coordsOld, coordsNew));
1101*e44f6aebSMatthew G. Knepley       PetscCall(MatDestroy(&In));
1102*e44f6aebSMatthew G. Knepley     }
1103*e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoordinates(dm, coordsNew));
1104*e44f6aebSMatthew G. Knepley     PetscCall(VecDestroy(&coordsNew));
11056858538eSMatthew G. Knepley   }
11066858538eSMatthew G. Knepley   /* Set new coordinate structures */
11076858538eSMatthew G. Knepley   PetscCall(DMSetCoordinateField(dm, NULL));
11086858538eSMatthew G. Knepley   PetscCall(DMSetCoordinateDM(dm, cdmNew));
11096858538eSMatthew G. Knepley   PetscCall(DMDestroy(&cdmNew));
11103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11116858538eSMatthew G. Knepley }
11126858538eSMatthew G. Knepley 
11136858538eSMatthew G. Knepley /*@
1114dce8aebaSBarry Smith   DMLocatePoints - Locate the points in v in the mesh and return a `PetscSF` of the containing cells
11156858538eSMatthew G. Knepley 
111620f4b53cSBarry Smith   Collective
11176858538eSMatthew G. Knepley 
11186858538eSMatthew G. Knepley   Input Parameters:
1119dce8aebaSBarry Smith + dm    - The `DM`
1120dce8aebaSBarry Smith - ltype - The type of point location, e.g. `DM_POINTLOCATION_NONE` or `DM_POINTLOCATION_NEAREST`
11216858538eSMatthew G. Knepley 
11226858538eSMatthew G. Knepley   Input/Output Parameters:
1123dce8aebaSBarry Smith + v      - The `Vec` of points, on output contains the nearest mesh points to the given points if `DM_POINTLOCATION_NEAREST` is used
112420f4b53cSBarry Smith - cellSF - Points to either `NULL`, or a `PetscSF` with guesses for which cells contain each point;
1125dce8aebaSBarry Smith            on output, the `PetscSF` containing the ranks and local indices of the containing points
11266858538eSMatthew G. Knepley 
11276858538eSMatthew G. Knepley   Level: developer
11286858538eSMatthew G. Knepley 
11296858538eSMatthew G. Knepley   Notes:
11304a8fad2eSMatthew G. Knepley   To do a search of the local cells of the mesh, v should have `PETSC_COMM_SELF` as its communicator.
113120f4b53cSBarry Smith   To do a search of all the cells in the distributed mesh, `v` should have the same communicator as `dm`.
11326858538eSMatthew G. Knepley 
1133d8206211SMatthew G. Knepley   Points will only be located in owned cells, not overlap cells arising from `DMPlexDistribute()` or other overlapping distributions.
1134d8206211SMatthew G. Knepley 
113520f4b53cSBarry Smith   If *cellSF is `NULL` on input, a `PetscSF` will be created.
113620f4b53cSBarry Smith   If *cellSF is not `NULL` on input, it should point to an existing `PetscSF`, whose graph will be used as initial guesses.
11376858538eSMatthew G. Knepley 
11386858538eSMatthew G. Knepley   An array that maps each point to its containing cell can be obtained with
1139dce8aebaSBarry Smith .vb
1140dce8aebaSBarry Smith     const PetscSFNode *cells;
1141dce8aebaSBarry Smith     PetscInt           nFound;
1142dce8aebaSBarry Smith     const PetscInt    *found;
11436858538eSMatthew G. Knepley 
1144dce8aebaSBarry Smith     PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells);
1145dce8aebaSBarry Smith .ve
11466858538eSMatthew G. Knepley 
11474a8fad2eSMatthew G. Knepley   Where cells[i].rank is the rank of the process owning the cell containing point found[i] (or i if found == NULL), and cells[i].index is
114820f4b53cSBarry Smith   the index of the cell in its rank's local numbering. This rank is in the communicator for `v`, so if `v` is on `PETSC_COMM_SELF` then the rank will always be 0.
11496858538eSMatthew G. Knepley 
1150dce8aebaSBarry Smith .seealso: `DM`, `DMSetCoordinates()`, `DMSetCoordinatesLocal()`, `DMGetCoordinates()`, `DMGetCoordinatesLocal()`, `DMPointLocationType`
11516858538eSMatthew G. Knepley @*/
1152d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF)
1153d71ae5a4SJacob Faibussowitsch {
11546858538eSMatthew G. Knepley   PetscFunctionBegin;
11556858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
11566858538eSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
11574f572ea9SToby Isaac   PetscAssertPointer(cellSF, 4);
11586858538eSMatthew G. Knepley   if (*cellSF) {
11596858538eSMatthew G. Knepley     PetscMPIInt result;
11606858538eSMatthew G. Knepley 
11616858538eSMatthew G. Knepley     PetscValidHeaderSpecific(*cellSF, PETSCSF_CLASSID, 4);
11626858538eSMatthew G. Knepley     PetscCallMPI(MPI_Comm_compare(PetscObjectComm((PetscObject)v), PetscObjectComm((PetscObject)*cellSF), &result));
11636858538eSMatthew G. Knepley     PetscCheck(result == MPI_IDENT || result == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "cellSF must have a communicator congruent to v's");
11646858538eSMatthew G. Knepley   } else {
11656858538eSMatthew G. Knepley     PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)v), cellSF));
11666858538eSMatthew G. Knepley   }
11676858538eSMatthew G. Knepley   PetscCall(PetscLogEventBegin(DM_LocatePoints, dm, 0, 0, 0));
1168dbbe0bcdSBarry Smith   PetscUseTypeMethod(dm, locatepoints, v, ltype, *cellSF);
11696858538eSMatthew G. Knepley   PetscCall(PetscLogEventEnd(DM_LocatePoints, dm, 0, 0, 0));
11703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11716858538eSMatthew G. Knepley }
1172