xref: /petsc/src/dm/interface/dmperiodicity.c (revision 8112c1cbf372cb53bf7c5aca994a84a6a303db4d)
16858538eSMatthew G. Knepley #include <petsc/private/dmimpl.h> /*I      "petscdm.h"          I*/
26858538eSMatthew G. Knepley 
36858538eSMatthew G. Knepley #include <petscdmplex.h>
46858538eSMatthew G. Knepley 
56858538eSMatthew G. Knepley /*@C
66858538eSMatthew G. Knepley   DMGetPeriodicity - Get the description of mesh periodicity
76858538eSMatthew G. Knepley 
842b02d39SMatthew G. Knepley   Not collective
942b02d39SMatthew G. Knepley 
106858538eSMatthew G. Knepley   Input Parameter:
1120f4b53cSBarry Smith . dm - The `DM` object
126858538eSMatthew G. Knepley 
136858538eSMatthew G. Knepley   Output Parameters:
146858538eSMatthew G. Knepley + maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates
1520f4b53cSBarry Smith . Lstart  - If we assume the mesh is a torus, this is the start of each coordinate, or `NULL` for 0.0
166858538eSMatthew G. Knepley - L       - If we assume the mesh is a torus, this is the length of each coordinate, otherwise it is < 0.0
176858538eSMatthew G. Knepley 
186858538eSMatthew G. Knepley   Level: developer
196858538eSMatthew G. Knepley 
2042747ad1SJacob Faibussowitsch .seealso: `DM`
216858538eSMatthew G. Knepley @*/
DMGetPeriodicity(DM dm,const PetscReal * maxCell[],const PetscReal * Lstart[],const PetscReal * L[])225d83a8b1SBarry Smith PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal *maxCell[], const PetscReal *Lstart[], const PetscReal *L[])
23d71ae5a4SJacob Faibussowitsch {
246858538eSMatthew G. Knepley   PetscFunctionBegin;
256858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
266858538eSMatthew G. Knepley   if (maxCell) *maxCell = dm->maxCell;
274fb89dddSMatthew G. Knepley   if (Lstart) *Lstart = dm->Lstart;
284fb89dddSMatthew G. Knepley   if (L) *L = dm->L;
293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
306858538eSMatthew G. Knepley }
316858538eSMatthew G. Knepley 
32cc4c1da9SBarry Smith /*@
336858538eSMatthew G. Knepley   DMSetPeriodicity - Set the description of mesh periodicity
346858538eSMatthew G. Knepley 
3542b02d39SMatthew G. Knepley   Logically Collective
3642b02d39SMatthew G. Knepley 
376858538eSMatthew G. Knepley   Input Parameters:
3820f4b53cSBarry Smith + dm      - The `DM` object
3920f4b53cSBarry Smith . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates. Pass `NULL` to remove such information.
4020f4b53cSBarry Smith . Lstart  - If we assume the mesh is a torus, this is the start of each coordinate, or `NULL` for 0.0
416858538eSMatthew G. Knepley - L       - If we assume the mesh is a torus, this is the length of each coordinate, otherwise it is < 0.0
426858538eSMatthew G. Knepley 
436858538eSMatthew G. Knepley   Level: developer
446858538eSMatthew G. Knepley 
4520f4b53cSBarry Smith .seealso: `DM`, `DMGetPeriodicity()`
466858538eSMatthew G. Knepley @*/
DMSetPeriodicity(DM dm,const PetscReal maxCell[],const PetscReal Lstart[],const PetscReal L[])47d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal Lstart[], const PetscReal L[])
48d71ae5a4SJacob Faibussowitsch {
496858538eSMatthew G. Knepley   PetscInt dim, d;
506858538eSMatthew G. Knepley 
516858538eSMatthew G. Knepley   PetscFunctionBegin;
526858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
534f572ea9SToby Isaac   if (maxCell) PetscAssertPointer(maxCell, 2);
544f572ea9SToby Isaac   if (Lstart) PetscAssertPointer(Lstart, 3);
554f572ea9SToby Isaac   if (L) PetscAssertPointer(L, 4);
566858538eSMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
576858538eSMatthew G. Knepley   if (maxCell) {
586858538eSMatthew G. Knepley     if (!dm->maxCell) PetscCall(PetscMalloc1(dim, &dm->maxCell));
596858538eSMatthew G. Knepley     for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d];
606858538eSMatthew G. Knepley   } else { /* remove maxCell information to disable automatic computation of localized vertices */
616858538eSMatthew G. Knepley     PetscCall(PetscFree(dm->maxCell));
626858538eSMatthew G. Knepley     dm->maxCell = NULL;
636858538eSMatthew G. Knepley   }
644fb89dddSMatthew G. Knepley   if (Lstart) {
654fb89dddSMatthew G. Knepley     if (!dm->Lstart) PetscCall(PetscMalloc1(dim, &dm->Lstart));
664fb89dddSMatthew G. Knepley     for (d = 0; d < dim; ++d) dm->Lstart[d] = Lstart[d];
674fb89dddSMatthew G. Knepley   } else { /* remove L information to disable automatic computation of localized vertices */
684fb89dddSMatthew G. Knepley     PetscCall(PetscFree(dm->Lstart));
694fb89dddSMatthew G. Knepley     dm->Lstart = NULL;
704fb89dddSMatthew G. Knepley   }
716858538eSMatthew G. Knepley   if (L) {
726858538eSMatthew G. Knepley     if (!dm->L) PetscCall(PetscMalloc1(dim, &dm->L));
736858538eSMatthew G. Knepley     for (d = 0; d < dim; ++d) dm->L[d] = L[d];
746858538eSMatthew G. Knepley   } else { /* remove L information to disable automatic computation of localized vertices */
756858538eSMatthew G. Knepley     PetscCall(PetscFree(dm->L));
766858538eSMatthew G. Knepley     dm->L = NULL;
776858538eSMatthew G. Knepley   }
786858538eSMatthew G. Knepley   PetscCheck((dm->maxCell && dm->L) || (!dm->maxCell && !dm->L), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot set only one of maxCell/L");
793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
806858538eSMatthew G. Knepley }
816858538eSMatthew G. Knepley 
826858538eSMatthew G. Knepley /*@
836858538eSMatthew G. Knepley   DMLocalizeCoordinate - If a mesh is periodic (a torus with lengths L_i, some of which can be infinite), project the coordinate onto [0, L_i) in each dimension.
846858538eSMatthew G. Knepley 
856858538eSMatthew G. Knepley   Input Parameters:
8620f4b53cSBarry Smith + dm       - The `DM`
876858538eSMatthew G. Knepley . in       - The input coordinate point (dim numbers)
886858538eSMatthew G. Knepley - endpoint - Include the endpoint L_i
896858538eSMatthew G. Knepley 
906858538eSMatthew G. Knepley   Output Parameter:
910b3275a6SBarry Smith . out - The localized coordinate point (dim numbers)
926858538eSMatthew G. Knepley 
936858538eSMatthew G. Knepley   Level: developer
946858538eSMatthew G. Knepley 
9520f4b53cSBarry Smith .seealso: `DM`, `DMLocalizeCoordinates()`, `DMLocalizeAddCoordinate()`
966858538eSMatthew G. Knepley @*/
DMLocalizeCoordinate(DM dm,const PetscScalar in[],PetscBool endpoint,PetscScalar out[])97d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[])
98d71ae5a4SJacob Faibussowitsch {
996858538eSMatthew G. Knepley   PetscInt dim, d;
1006858538eSMatthew G. Knepley 
1016858538eSMatthew G. Knepley   PetscFunctionBegin;
1026858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDim(dm, &dim));
1036858538eSMatthew G. Knepley   if (!dm->maxCell) {
1046858538eSMatthew G. Knepley     for (d = 0; d < dim; ++d) out[d] = in[d];
1056858538eSMatthew G. Knepley   } else {
1066858538eSMatthew G. Knepley     if (endpoint) {
1076858538eSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
1086858538eSMatthew G. Knepley         if ((PetscAbsReal(PetscRealPart(in[d]) / dm->L[d] - PetscFloorReal(PetscRealPart(in[d]) / dm->L[d])) < PETSC_SMALL) && (PetscRealPart(in[d]) / dm->L[d] > PETSC_SMALL)) {
1096858538eSMatthew G. Knepley           out[d] = in[d] - dm->L[d] * (PetscFloorReal(PetscRealPart(in[d]) / dm->L[d]) - 1);
1106858538eSMatthew G. Knepley         } else {
1116858538eSMatthew G. Knepley           out[d] = in[d] - dm->L[d] * PetscFloorReal(PetscRealPart(in[d]) / dm->L[d]);
1126858538eSMatthew G. Knepley         }
1136858538eSMatthew G. Knepley       }
1146858538eSMatthew G. Knepley     } else {
115ad540459SPierre Jolivet       for (d = 0; d < dim; ++d) out[d] = in[d] - dm->L[d] * PetscFloorReal(PetscRealPart(in[d]) / dm->L[d]);
1166858538eSMatthew G. Knepley     }
1176858538eSMatthew G. Knepley   }
1183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1196858538eSMatthew G. Knepley }
1206858538eSMatthew G. Knepley 
1216858538eSMatthew G. Knepley /*
1226858538eSMatthew G. Knepley   DMLocalizeCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer.
1236858538eSMatthew G. Knepley 
1246858538eSMatthew G. Knepley   Input Parameters:
12520f4b53cSBarry Smith + dm     - The `DM`
1266858538eSMatthew G. Knepley . dim    - The spatial dimension
1276858538eSMatthew G. Knepley . anchor - The anchor point, the input point can be no more than maxCell away from it
1286858538eSMatthew G. Knepley - in     - The input coordinate point (dim numbers)
1296858538eSMatthew G. Knepley 
1306858538eSMatthew G. Knepley   Output Parameter:
1310b3275a6SBarry Smith . out - The localized coordinate point (dim numbers)
1326858538eSMatthew G. Knepley 
1336858538eSMatthew G. Knepley   Level: developer
1346858538eSMatthew G. Knepley 
13520f4b53cSBarry Smith   Note:
13620f4b53cSBarry Smith   This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell
1376858538eSMatthew G. Knepley 
13820f4b53cSBarry Smith .seealso: `DM`, `DMLocalizeCoordinates()`, `DMLocalizeAddCoordinate()`
1396858538eSMatthew G. Knepley */
DMLocalizeCoordinate_Internal(DM dm,PetscInt dim,const PetscScalar anchor[],const PetscScalar in[],PetscScalar out[])140d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
141d71ae5a4SJacob Faibussowitsch {
1426858538eSMatthew G. Knepley   PetscInt d;
1436858538eSMatthew G. Knepley 
1446858538eSMatthew G. Knepley   PetscFunctionBegin;
1456858538eSMatthew G. Knepley   if (!dm->maxCell) {
1466858538eSMatthew G. Knepley     for (d = 0; d < dim; ++d) out[d] = in[d];
1476858538eSMatthew G. Knepley   } else {
1486858538eSMatthew G. Knepley     for (d = 0; d < dim; ++d) {
1496858538eSMatthew G. Knepley       if ((dm->L[d] > 0.0) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) {
1506858538eSMatthew G. Knepley         out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
1516858538eSMatthew G. Knepley       } else {
1526858538eSMatthew G. Knepley         out[d] = in[d];
1536858538eSMatthew G. Knepley       }
1546858538eSMatthew G. Knepley     }
1556858538eSMatthew G. Knepley   }
1563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1576858538eSMatthew G. Knepley }
1586858538eSMatthew G. Knepley 
DMLocalizeCoordinateReal_Internal(DM dm,PetscInt dim,const PetscReal anchor[],const PetscReal in[],PetscReal out[])159d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[])
160d71ae5a4SJacob Faibussowitsch {
1616858538eSMatthew G. Knepley   PetscInt d;
1626858538eSMatthew G. Knepley 
1636858538eSMatthew G. Knepley   PetscFunctionBegin;
1646858538eSMatthew G. Knepley   if (!dm->maxCell) {
1656858538eSMatthew G. Knepley     for (d = 0; d < dim; ++d) out[d] = in[d];
1666858538eSMatthew G. Knepley   } else {
1676858538eSMatthew G. Knepley     for (d = 0; d < dim; ++d) {
1686858538eSMatthew G. Knepley       if ((dm->L[d] > 0.0) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) {
1696858538eSMatthew G. Knepley         out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d];
1706858538eSMatthew G. Knepley       } else {
1716858538eSMatthew G. Knepley         out[d] = in[d];
1726858538eSMatthew G. Knepley       }
1736858538eSMatthew G. Knepley     }
1746858538eSMatthew G. Knepley   }
1753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1766858538eSMatthew G. Knepley }
1776858538eSMatthew G. Knepley 
1786858538eSMatthew G. Knepley /*
1796858538eSMatthew G. Knepley   DMLocalizeAddCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer.
1806858538eSMatthew G. Knepley 
1816858538eSMatthew G. Knepley   Input Parameters:
18220f4b53cSBarry Smith + dm     - The `DM`
1836858538eSMatthew G. Knepley . dim    - The spatial dimension
1846858538eSMatthew G. Knepley . anchor - The anchor point, the input point can be no more than maxCell away from it
1856858538eSMatthew G. Knepley . in     - The input coordinate delta (dim numbers)
1866858538eSMatthew G. Knepley - out    - The input coordinate point (dim numbers)
1876858538eSMatthew G. Knepley 
1886858538eSMatthew G. Knepley   Output Parameter:
1896858538eSMatthew G. Knepley . out    - The localized coordinate in + out
1906858538eSMatthew G. Knepley 
1916858538eSMatthew G. Knepley   Level: developer
1926858538eSMatthew G. Knepley 
19320f4b53cSBarry Smith   Note:
1940b3275a6SBarry Smith   This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually one of the vertices on a containing cell
1956858538eSMatthew G. Knepley 
19620f4b53cSBarry Smith .seealso: `DM`, `DMLocalizeCoordinates()`, `DMLocalizeCoordinate()`
1976858538eSMatthew G. Knepley */
DMLocalizeAddCoordinate_Internal(DM dm,PetscInt dim,const PetscScalar anchor[],const PetscScalar in[],PetscScalar out[])198d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[])
199d71ae5a4SJacob Faibussowitsch {
2006858538eSMatthew G. Knepley   PetscInt d;
2016858538eSMatthew G. Knepley 
2026858538eSMatthew G. Knepley   PetscFunctionBegin;
2036858538eSMatthew G. Knepley   if (!dm->maxCell) {
2046858538eSMatthew G. Knepley     for (d = 0; d < dim; ++d) out[d] += in[d];
2056858538eSMatthew G. Knepley   } else {
2066858538eSMatthew G. Knepley     for (d = 0; d < dim; ++d) {
2076858538eSMatthew G. Knepley       const PetscReal maxC = dm->maxCell[d];
2086858538eSMatthew G. Knepley 
2096858538eSMatthew G. Knepley       if ((dm->L[d] > 0.0) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) {
2106858538eSMatthew G. Knepley         const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d];
2116858538eSMatthew G. Knepley 
2126858538eSMatthew G. Knepley         if (PetscAbsScalar(newCoord - anchor[d]) > maxC)
2136858538eSMatthew G. Knepley           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "%" PetscInt_FMT "-Coordinate %g more than %g away from anchor %g", d, (double)PetscRealPart(in[d]), (double)maxC, (double)PetscRealPart(anchor[d]));
2146858538eSMatthew G. Knepley         out[d] += newCoord;
2156858538eSMatthew G. Knepley       } else {
2166858538eSMatthew G. Knepley         out[d] += in[d];
2176858538eSMatthew G. Knepley       }
2186858538eSMatthew G. Knepley     }
2196858538eSMatthew G. Knepley   }
2203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2216858538eSMatthew G. Knepley }
2226858538eSMatthew G. Knepley 
2236858538eSMatthew G. Knepley /*@
22420f4b53cSBarry Smith   DMGetCoordinatesLocalizedLocal - Check if the `DM` coordinates have been localized for cells on this process
2256858538eSMatthew G. Knepley 
22620f4b53cSBarry Smith   Not Collective
2276858538eSMatthew G. Knepley 
2286858538eSMatthew G. Knepley   Input Parameter:
22920f4b53cSBarry Smith . dm - The `DM`
2306858538eSMatthew G. Knepley 
2316858538eSMatthew G. Knepley   Output Parameter:
232a4e35b19SJacob Faibussowitsch . areLocalized - `PETSC_TRUE` if localized
2336858538eSMatthew G. Knepley 
2346858538eSMatthew G. Knepley   Level: developer
2356858538eSMatthew G. Knepley 
23620f4b53cSBarry Smith .seealso: `DM`, `DMLocalizeCoordinates()`, `DMGetCoordinatesLocalized()`, `DMSetPeriodicity()`
2376858538eSMatthew G. Knepley @*/
DMGetCoordinatesLocalizedLocal(DM dm,PetscBool * areLocalized)238d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm, PetscBool *areLocalized)
239d71ae5a4SJacob Faibussowitsch {
2406858538eSMatthew G. Knepley   PetscFunctionBegin;
2416858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2424f572ea9SToby Isaac   PetscAssertPointer(areLocalized, 2);
2436858538eSMatthew G. Knepley   *areLocalized = dm->coordinates[1].dim < 0 ? PETSC_FALSE : PETSC_TRUE;
2443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2456858538eSMatthew G. Knepley }
2466858538eSMatthew G. Knepley 
2476858538eSMatthew G. Knepley /*@
24820f4b53cSBarry Smith   DMGetCoordinatesLocalized - Check if the `DM` coordinates have been localized for cells
2496858538eSMatthew G. Knepley 
25020f4b53cSBarry Smith   Collective
2516858538eSMatthew G. Knepley 
2526858538eSMatthew G. Knepley   Input Parameter:
25320f4b53cSBarry Smith . dm - The `DM`
2546858538eSMatthew G. Knepley 
2556858538eSMatthew G. Knepley   Output Parameter:
256a4e35b19SJacob Faibussowitsch . areLocalized - `PETSC_TRUE` if localized
2576858538eSMatthew G. Knepley 
2586858538eSMatthew G. Knepley   Level: developer
2596858538eSMatthew G. Knepley 
26020f4b53cSBarry Smith .seealso: `DM`, `DMLocalizeCoordinates()`, `DMSetPeriodicity()`, `DMGetCoordinatesLocalizedLocal()`
2616858538eSMatthew G. Knepley @*/
DMGetCoordinatesLocalized(DM dm,PetscBool * areLocalized)262d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetCoordinatesLocalized(DM dm, PetscBool *areLocalized)
263d71ae5a4SJacob Faibussowitsch {
2646858538eSMatthew G. Knepley   PetscBool localized;
2656858538eSMatthew G. Knepley 
2666858538eSMatthew G. Knepley   PetscFunctionBegin;
2676858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2684f572ea9SToby Isaac   PetscAssertPointer(areLocalized, 2);
2696858538eSMatthew G. Knepley   PetscCall(DMGetCoordinatesLocalizedLocal(dm, &localized));
270*5440e5dcSBarry Smith   PetscCallMPI(MPIU_Allreduce(&localized, areLocalized, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
2713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2726858538eSMatthew G. Knepley }
2736858538eSMatthew G. Knepley 
2746858538eSMatthew G. Knepley /*@
275a4b8866cSMatthew G. Knepley   DMGetSparseLocalize - Check if the `DM` coordinates should be localized only for cells near the periodic boundary.
276a4b8866cSMatthew G. Knepley 
277a4b8866cSMatthew G. Knepley   Not collective
278a4b8866cSMatthew G. Knepley 
279a4b8866cSMatthew G. Knepley   Input Parameter:
280a4b8866cSMatthew G. Knepley . dm - The `DM`
281a4b8866cSMatthew G. Knepley 
282a4b8866cSMatthew G. Knepley   Output Parameter:
283d7c1f440SPierre Jolivet . sparse - `PETSC_TRUE` if only cells near the periodic boundary are localized
284a4b8866cSMatthew G. Knepley 
285a4b8866cSMatthew G. Knepley   Level: intermediate
286a4b8866cSMatthew G. Knepley 
287a4b8866cSMatthew G. Knepley .seealso: `DMSetSparseLocalize()`, `DMLocalizeCoordinates()`, `DMSetPeriodicity()`
288a4b8866cSMatthew G. Knepley @*/
DMGetSparseLocalize(DM dm,PetscBool * sparse)289a4b8866cSMatthew G. Knepley PetscErrorCode DMGetSparseLocalize(DM dm, PetscBool *sparse)
290a4b8866cSMatthew G. Knepley {
291a4b8866cSMatthew G. Knepley   PetscFunctionBegin;
292a4b8866cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
293a4b8866cSMatthew G. Knepley   PetscAssertPointer(sparse, 2);
294a4b8866cSMatthew G. Knepley   *sparse = dm->sparseLocalize;
295a4b8866cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
296a4b8866cSMatthew G. Knepley }
297a4b8866cSMatthew G. Knepley 
298a4b8866cSMatthew G. Knepley /*@
299a4b8866cSMatthew G. Knepley   DMSetSparseLocalize - Set the flag indicating that `DM` coordinates should be localized only for cells near the periodic boundary.
300a4b8866cSMatthew G. Knepley 
301a4b8866cSMatthew G. Knepley   Logically collective
302a4b8866cSMatthew G. Knepley 
303a4b8866cSMatthew G. Knepley   Input Parameters:
304a4b8866cSMatthew G. Knepley + dm     - The `DM`
305d7c1f440SPierre Jolivet - sparse - `PETSC_TRUE` if only cells near the periodic boundary are localized
306a4b8866cSMatthew G. Knepley 
307a4b8866cSMatthew G. Knepley   Level: intermediate
308a4b8866cSMatthew G. Knepley 
309a4b8866cSMatthew G. Knepley .seealso: `DMGetSparseLocalize()`, `DMLocalizeCoordinates()`, `DMSetPeriodicity()`
310a4b8866cSMatthew G. Knepley @*/
DMSetSparseLocalize(DM dm,PetscBool sparse)311a4b8866cSMatthew G. Knepley PetscErrorCode DMSetSparseLocalize(DM dm, PetscBool sparse)
312a4b8866cSMatthew G. Knepley {
313a4b8866cSMatthew G. Knepley   PetscFunctionBegin;
314a4b8866cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
315a4b8866cSMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, sparse, 2);
316a4b8866cSMatthew G. Knepley   dm->sparseLocalize = sparse;
317a4b8866cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
318a4b8866cSMatthew G. Knepley }
319a4b8866cSMatthew G. Knepley 
320a4b8866cSMatthew G. Knepley /*@
3216858538eSMatthew G. Knepley   DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces
3226858538eSMatthew G. Knepley 
32320f4b53cSBarry Smith   Collective
3246858538eSMatthew G. Knepley 
3256858538eSMatthew G. Knepley   Input Parameter:
32620f4b53cSBarry Smith . dm - The `DM`
3276858538eSMatthew G. Knepley 
3286858538eSMatthew G. Knepley   Level: developer
3296858538eSMatthew G. Knepley 
33020f4b53cSBarry Smith .seealso: `DM`, `DMSetPeriodicity()`, `DMLocalizeCoordinate()`, `DMLocalizeAddCoordinate()`
3316858538eSMatthew G. Knepley @*/
DMLocalizeCoordinates(DM dm)332d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLocalizeCoordinates(DM dm)
333d71ae5a4SJacob Faibussowitsch {
3346858538eSMatthew G. Knepley   DM               cdm, cdgdm, cplex, plex;
3356858538eSMatthew G. Knepley   PetscSection     cs, csDG;
3366858538eSMatthew G. Knepley   Vec              coordinates, cVec;
3376858538eSMatthew G. Knepley   PetscScalar     *coordsDG, *anchor, *localized;
3384fb89dddSMatthew G. Knepley   const PetscReal *Lstart, *L;
3391690c2aeSBarry Smith   PetscInt         Nc, vStart, vEnd, sStart, sEnd, newStart = PETSC_INT_MAX, newEnd = PETSC_INT_MIN, bs, coordSize;
340a4b8866cSMatthew G. Knepley   PetscBool        isLocalized, sparseLocalize, useDG = PETSC_FALSE, useDGGlobal;
3416858538eSMatthew G. Knepley   PetscInt         maxHeight = 0, h;
3426858538eSMatthew G. Knepley   PetscInt        *pStart = NULL, *pEnd = NULL;
3436858538eSMatthew G. Knepley   MPI_Comm         comm;
3446858538eSMatthew G. Knepley 
3456858538eSMatthew G. Knepley   PetscFunctionBegin;
3466858538eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3474fb89dddSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dm, NULL, &Lstart, &L));
348a4b8866cSMatthew G. Knepley   PetscCall(DMGetSparseLocalize(dm, &sparseLocalize));
3496858538eSMatthew G. Knepley   /* Cannot automatically localize without L and maxCell right now */
3503ba16761SJacob Faibussowitsch   if (!L) PetscFunctionReturn(PETSC_SUCCESS);
3516858538eSMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
3526858538eSMatthew G. Knepley   PetscCall(DMGetCoordinatesLocalized(dm, &isLocalized));
3533ba16761SJacob Faibussowitsch   if (isLocalized) PetscFunctionReturn(PETSC_SUCCESS);
3546858538eSMatthew G. Knepley 
3556858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
3566858538eSMatthew G. Knepley   PetscCall(DMConvert(dm, DMPLEX, &plex));
3576858538eSMatthew G. Knepley   PetscCall(DMConvert(cdm, DMPLEX, &cplex));
358966bd95aSPierre Jolivet   PetscCheck(cplex, comm, PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM");
3596858538eSMatthew G. Knepley   PetscCall(DMPlexGetDepthStratum(cplex, 0, &vStart, &vEnd));
3606858538eSMatthew G. Knepley   PetscCall(DMPlexGetMaxProjectionHeight(cplex, &maxHeight));
3616858538eSMatthew G. Knepley   PetscCall(DMGetWorkArray(dm, 2 * (maxHeight + 1), MPIU_INT, &pStart));
3626858538eSMatthew G. Knepley   pEnd     = &pStart[maxHeight + 1];
3636858538eSMatthew G. Knepley   newStart = vStart;
3646858538eSMatthew G. Knepley   newEnd   = vEnd;
3656858538eSMatthew G. Knepley   for (h = 0; h <= maxHeight; h++) {
3666858538eSMatthew G. Knepley     PetscCall(DMPlexGetHeightStratum(cplex, h, &pStart[h], &pEnd[h]));
3676858538eSMatthew G. Knepley     newStart = PetscMin(newStart, pStart[h]);
3686858538eSMatthew G. Knepley     newEnd   = PetscMax(newEnd, pEnd[h]);
3696858538eSMatthew G. Knepley   }
3706858538eSMatthew G. Knepley   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3716858538eSMatthew G. Knepley   PetscCheck(coordinates, comm, PETSC_ERR_SUP, "Missing local coordinate vector");
3726858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &cs));
3736858538eSMatthew G. Knepley   PetscCall(VecGetBlockSize(coordinates, &bs));
3746858538eSMatthew G. Knepley   PetscCall(PetscSectionGetChart(cs, &sStart, &sEnd));
3756858538eSMatthew G. Knepley 
3766858538eSMatthew G. Knepley   PetscCall(PetscSectionCreate(comm, &csDG));
3776858538eSMatthew G. Knepley   PetscCall(PetscSectionSetNumFields(csDG, 1));
3786858538eSMatthew G. Knepley   PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc));
3796858538eSMatthew G. Knepley   PetscCall(PetscSectionSetFieldComponents(csDG, 0, Nc));
3806858538eSMatthew G. Knepley   PetscCall(PetscSectionSetChart(csDG, newStart, newEnd));
3816858538eSMatthew G. Knepley   PetscCheck(bs == Nc, comm, PETSC_ERR_ARG_INCOMP, "Coordinate block size %" PetscInt_FMT " != %" PetscInt_FMT " number of components", bs, Nc);
3826858538eSMatthew G. Knepley 
3836858538eSMatthew G. Knepley   PetscCall(DMGetWorkArray(dm, 2 * Nc, MPIU_SCALAR, &anchor));
3846858538eSMatthew G. Knepley   localized = &anchor[Nc];
3856858538eSMatthew G. Knepley   for (h = 0; h <= maxHeight; h++) {
3866858538eSMatthew G. Knepley     PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
3876858538eSMatthew G. Knepley 
3886858538eSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
3896858538eSMatthew G. Knepley       PetscScalar   *cellCoords = NULL;
3906858538eSMatthew G. Knepley       DMPolytopeType ct;
3916858538eSMatthew G. Knepley       PetscInt       dof, d, p;
3926858538eSMatthew G. Knepley 
3936858538eSMatthew G. Knepley       PetscCall(DMPlexGetCellType(plex, c, &ct));
3946858538eSMatthew G. Knepley       if (ct == DM_POLYTOPE_FV_GHOST) continue;
3956858538eSMatthew G. Knepley       PetscCall(DMPlexVecGetClosure(cplex, cs, coordinates, c, &dof, &cellCoords));
3966858538eSMatthew G. Knepley       PetscCheck(!(dof % Nc), comm, PETSC_ERR_ARG_INCOMP, "Coordinate size on cell %" PetscInt_FMT " closure %" PetscInt_FMT " not divisible by %" PetscInt_FMT " number of components", c, dof, Nc);
3976858538eSMatthew G. Knepley       for (d = 0; d < Nc; ++d) anchor[d] = cellCoords[d];
3986858538eSMatthew G. Knepley       for (p = 0; p < dof / Nc; ++p) {
3996858538eSMatthew G. Knepley         PetscCall(DMLocalizeCoordinate_Internal(dm, Nc, anchor, &cellCoords[p * Nc], localized));
4009371c9d4SSatish Balay         for (d = 0; d < Nc; ++d)
4019371c9d4SSatish Balay           if (cellCoords[p * Nc + d] != localized[d]) break;
4026858538eSMatthew G. Knepley         if (d < Nc) break;
4036858538eSMatthew G. Knepley       }
4046858538eSMatthew G. Knepley       if (p < dof / Nc) useDG = PETSC_TRUE;
4056858538eSMatthew G. Knepley       if (p < dof / Nc || !sparseLocalize) {
4066858538eSMatthew G. Knepley         PetscCall(PetscSectionSetDof(csDG, c, dof));
4076858538eSMatthew G. Knepley         PetscCall(PetscSectionSetFieldDof(csDG, c, 0, dof));
4086858538eSMatthew G. Knepley       }
4096858538eSMatthew G. Knepley       PetscCall(DMPlexVecRestoreClosure(cplex, cs, coordinates, c, &dof, &cellCoords));
4106858538eSMatthew G. Knepley     }
4116858538eSMatthew G. Knepley   }
412*5440e5dcSBarry Smith   PetscCallMPI(MPIU_Allreduce(&useDG, &useDGGlobal, 1, MPI_C_BOOL, MPI_LOR, comm));
4136858538eSMatthew G. Knepley   if (!useDGGlobal) goto end;
4146858538eSMatthew G. Knepley 
4156858538eSMatthew G. Knepley   PetscCall(PetscSectionSetUp(csDG));
4166858538eSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(csDG, &coordSize));
4176858538eSMatthew G. Knepley   PetscCall(VecCreate(PETSC_COMM_SELF, &cVec));
4186858538eSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)cVec, "coordinates"));
4196858538eSMatthew G. Knepley   PetscCall(VecSetBlockSize(cVec, bs));
4206858538eSMatthew G. Knepley   PetscCall(VecSetSizes(cVec, coordSize, PETSC_DETERMINE));
4216858538eSMatthew G. Knepley   PetscCall(VecSetType(cVec, VECSTANDARD));
4226858538eSMatthew G. Knepley   PetscCall(VecGetArray(cVec, &coordsDG));
4236858538eSMatthew G. Knepley   for (h = 0; h <= maxHeight; h++) {
4246858538eSMatthew G. Knepley     PetscInt cStart = pStart[h], cEnd = pEnd[h], c;
4256858538eSMatthew G. Knepley 
4266858538eSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
4276858538eSMatthew G. Knepley       PetscScalar *cellCoords = NULL;
4286858538eSMatthew G. Knepley       PetscInt     p          = 0, q, dof, cdof, d, offDG;
4296858538eSMatthew G. Knepley 
4306858538eSMatthew G. Knepley       PetscCall(PetscSectionGetDof(csDG, c, &cdof));
4316858538eSMatthew G. Knepley       if (!cdof) continue;
4326858538eSMatthew G. Knepley       PetscCall(DMPlexVecGetClosure(cplex, cs, coordinates, c, &dof, &cellCoords));
4336858538eSMatthew G. Knepley       PetscCall(PetscSectionGetOffset(csDG, c, &offDG));
4347c48043bSMatthew G. Knepley       // TODO The coordinates are set in closure order, which might not be the tensor order
4356858538eSMatthew G. Knepley       for (q = 0; q < dof / Nc; ++q) {
4366858538eSMatthew G. Knepley         // Select a trial anchor
4376858538eSMatthew G. Knepley         for (d = 0; d < Nc; ++d) anchor[d] = cellCoords[q * Nc + d];
4386858538eSMatthew G. Knepley         for (p = 0; p < dof / Nc; ++p) {
4396858538eSMatthew G. Knepley           PetscCall(DMLocalizeCoordinate_Internal(dm, Nc, anchor, &cellCoords[p * Nc], &coordsDG[offDG + p * Nc]));
4404fb89dddSMatthew G. Knepley           // We need the cell to fit into the torus [lower, lower+L)
4416858538eSMatthew G. Knepley           for (d = 0; d < Nc; ++d)
4424fb89dddSMatthew G. Knepley             if (L[d] > 0. && ((PetscRealPart(coordsDG[offDG + p * Nc + d]) < (Lstart ? Lstart[d] : 0.)) || (PetscRealPart(coordsDG[offDG + p * Nc + d]) > (Lstart ? Lstart[d] : 0.) + L[d]))) break;
4436858538eSMatthew G. Knepley           if (d < Nc) break;
4446858538eSMatthew G. Knepley         }
4456858538eSMatthew G. Knepley         if (p == dof / Nc) break;
4466858538eSMatthew G. Knepley       }
4474fb89dddSMatthew G. Knepley       PetscCheck(p == dof / Nc, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " does not fit into the torus %s[0, L]", c, Lstart ? "Lstart + " : "");
4486858538eSMatthew G. Knepley       PetscCall(DMPlexVecRestoreClosure(cplex, cs, coordinates, c, &dof, &cellCoords));
4496858538eSMatthew G. Knepley     }
4506858538eSMatthew G. Knepley   }
4516858538eSMatthew G. Knepley   PetscCall(VecRestoreArray(cVec, &coordsDG));
45299acd26cSksagiyam   PetscUseTypeMethod(dm, createcellcoordinatedm, &cdgdm);
4536858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dm, cdgdm));
4544c712d99Sksagiyam   PetscCall(DMDestroy(&cdgdm));
4557c48043bSMatthew G. Knepley   // Convert the discretization
4567c48043bSMatthew G. Knepley   {
4574c712d99Sksagiyam     PetscFE      fe;
4587c48043bSMatthew G. Knepley     PetscClassId id;
4597c48043bSMatthew G. Knepley 
4607c48043bSMatthew G. Knepley     PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe));
4617c48043bSMatthew G. Knepley     PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
4627c48043bSMatthew G. Knepley     if (id == PETSCFE_CLASSID) {
4634c712d99Sksagiyam       PetscSpace P;
4644c712d99Sksagiyam       PetscInt   degree;
4654c712d99Sksagiyam 
4667c48043bSMatthew G. Knepley       PetscCall(PetscFEGetBasisSpace(fe, &P));
4674c712d99Sksagiyam       PetscCall(PetscSpaceGetDegree(P, &degree, NULL));
468e65c294aSksagiyam       PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_TRUE, PETSC_FALSE));
4697c48043bSMatthew G. Knepley     }
4707c48043bSMatthew G. Knepley   }
4714c712d99Sksagiyam   PetscCall(DMSetCellCoordinateSection(dm, PETSC_DETERMINE, csDG));
4724c712d99Sksagiyam   PetscCall(DMSetCellCoordinatesLocal(dm, cVec));
4734c712d99Sksagiyam   PetscCall(VecDestroy(&cVec));
4746858538eSMatthew G. Knepley 
4756858538eSMatthew G. Knepley end:
4766858538eSMatthew G. Knepley   PetscCall(DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor));
4776858538eSMatthew G. Knepley   PetscCall(DMRestoreWorkArray(dm, 2 * (maxHeight + 1), MPIU_INT, &pStart));
4786858538eSMatthew G. Knepley   PetscCall(PetscSectionDestroy(&csDG));
4796858538eSMatthew G. Knepley   PetscCall(DMDestroy(&plex));
4806858538eSMatthew G. Knepley   PetscCall(DMDestroy(&cplex));
4813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4826858538eSMatthew G. Knepley }
483