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 86858538eSMatthew G. Knepley Input Parameter: 96858538eSMatthew G. Knepley . dm - The DM object 106858538eSMatthew G. Knepley 116858538eSMatthew G. Knepley Output Parameters: 126858538eSMatthew 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 134fb89dddSMatthew G. Knepley . Lstart - If we assume the mesh is a torus, this is the start of each coordinate, or NULL for 0.0 146858538eSMatthew G. Knepley - L - If we assume the mesh is a torus, this is the length of each coordinate, otherwise it is < 0.0 156858538eSMatthew G. Knepley 166858538eSMatthew G. Knepley Level: developer 176858538eSMatthew G. Knepley 186858538eSMatthew G. Knepley .seealso: `DMGetPeriodicity()` 196858538eSMatthew G. Knepley @*/ 20*9371c9d4SSatish Balay PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **Lstart, const PetscReal **L) { 216858538eSMatthew G. Knepley PetscFunctionBegin; 226858538eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 236858538eSMatthew G. Knepley if (maxCell) *maxCell = dm->maxCell; 244fb89dddSMatthew G. Knepley if (Lstart) *Lstart = dm->Lstart; 254fb89dddSMatthew G. Knepley if (L) *L = dm->L; 266858538eSMatthew G. Knepley PetscFunctionReturn(0); 276858538eSMatthew G. Knepley } 286858538eSMatthew G. Knepley 296858538eSMatthew G. Knepley /*@C 306858538eSMatthew G. Knepley DMSetPeriodicity - Set the description of mesh periodicity 316858538eSMatthew G. Knepley 326858538eSMatthew G. Knepley Input Parameters: 336858538eSMatthew G. Knepley + dm - The DM object 346858538eSMatthew 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. Pass NULL to remove such information. 354fb89dddSMatthew G. Knepley . Lstart - If we assume the mesh is a torus, this is the start of each coordinate, or NULL for 0.0 366858538eSMatthew G. Knepley - L - If we assume the mesh is a torus, this is the length of each coordinate, otherwise it is < 0.0 376858538eSMatthew G. Knepley 386858538eSMatthew G. Knepley Level: developer 396858538eSMatthew G. Knepley 406858538eSMatthew G. Knepley .seealso: `DMGetPeriodicity()` 416858538eSMatthew G. Knepley @*/ 42*9371c9d4SSatish Balay PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal Lstart[], const PetscReal L[]) { 436858538eSMatthew G. Knepley PetscInt dim, d; 446858538eSMatthew G. Knepley 456858538eSMatthew G. Knepley PetscFunctionBegin; 466858538eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 476858538eSMatthew G. Knepley if (maxCell) { PetscValidRealPointer(maxCell, 2); } 484fb89dddSMatthew G. Knepley if (Lstart) { PetscValidRealPointer(Lstart, 3); } 494fb89dddSMatthew G. Knepley if (L) { PetscValidRealPointer(L, 4); } 506858538eSMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 516858538eSMatthew G. Knepley if (maxCell) { 526858538eSMatthew G. Knepley if (!dm->maxCell) PetscCall(PetscMalloc1(dim, &dm->maxCell)); 536858538eSMatthew G. Knepley for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d]; 546858538eSMatthew G. Knepley } else { /* remove maxCell information to disable automatic computation of localized vertices */ 556858538eSMatthew G. Knepley PetscCall(PetscFree(dm->maxCell)); 566858538eSMatthew G. Knepley dm->maxCell = NULL; 576858538eSMatthew G. Knepley } 584fb89dddSMatthew G. Knepley if (Lstart) { 594fb89dddSMatthew G. Knepley if (!dm->Lstart) PetscCall(PetscMalloc1(dim, &dm->Lstart)); 604fb89dddSMatthew G. Knepley for (d = 0; d < dim; ++d) dm->Lstart[d] = Lstart[d]; 614fb89dddSMatthew G. Knepley } else { /* remove L information to disable automatic computation of localized vertices */ 624fb89dddSMatthew G. Knepley PetscCall(PetscFree(dm->Lstart)); 634fb89dddSMatthew G. Knepley dm->Lstart = NULL; 644fb89dddSMatthew G. Knepley } 656858538eSMatthew G. Knepley if (L) { 666858538eSMatthew G. Knepley if (!dm->L) PetscCall(PetscMalloc1(dim, &dm->L)); 676858538eSMatthew G. Knepley for (d = 0; d < dim; ++d) dm->L[d] = L[d]; 686858538eSMatthew G. Knepley } else { /* remove L information to disable automatic computation of localized vertices */ 696858538eSMatthew G. Knepley PetscCall(PetscFree(dm->L)); 706858538eSMatthew G. Knepley dm->L = NULL; 716858538eSMatthew G. Knepley } 726858538eSMatthew 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"); 736858538eSMatthew G. Knepley PetscFunctionReturn(0); 746858538eSMatthew G. Knepley } 756858538eSMatthew G. Knepley 766858538eSMatthew G. Knepley /*@ 776858538eSMatthew 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. 786858538eSMatthew G. Knepley 796858538eSMatthew G. Knepley Input Parameters: 806858538eSMatthew G. Knepley + dm - The DM 816858538eSMatthew G. Knepley . in - The input coordinate point (dim numbers) 826858538eSMatthew G. Knepley - endpoint - Include the endpoint L_i 836858538eSMatthew G. Knepley 846858538eSMatthew G. Knepley Output Parameter: 856858538eSMatthew G. Knepley . out - The localized coordinate point 866858538eSMatthew G. Knepley 876858538eSMatthew G. Knepley Level: developer 886858538eSMatthew G. Knepley 896858538eSMatthew G. Knepley .seealso: `DMLocalizeCoordinates()`, `DMLocalizeAddCoordinate()` 906858538eSMatthew G. Knepley @*/ 91*9371c9d4SSatish Balay PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) { 926858538eSMatthew G. Knepley PetscInt dim, d; 936858538eSMatthew G. Knepley 946858538eSMatthew G. Knepley PetscFunctionBegin; 956858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &dim)); 966858538eSMatthew G. Knepley if (!dm->maxCell) { 976858538eSMatthew G. Knepley for (d = 0; d < dim; ++d) out[d] = in[d]; 986858538eSMatthew G. Knepley } else { 996858538eSMatthew G. Knepley if (endpoint) { 1006858538eSMatthew G. Knepley for (d = 0; d < dim; ++d) { 1016858538eSMatthew 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)) { 1026858538eSMatthew G. Knepley out[d] = in[d] - dm->L[d] * (PetscFloorReal(PetscRealPart(in[d]) / dm->L[d]) - 1); 1036858538eSMatthew G. Knepley } else { 1046858538eSMatthew G. Knepley out[d] = in[d] - dm->L[d] * PetscFloorReal(PetscRealPart(in[d]) / dm->L[d]); 1056858538eSMatthew G. Knepley } 1066858538eSMatthew G. Knepley } 1076858538eSMatthew G. Knepley } else { 108*9371c9d4SSatish Balay for (d = 0; d < dim; ++d) { out[d] = in[d] - dm->L[d] * PetscFloorReal(PetscRealPart(in[d]) / dm->L[d]); } 1096858538eSMatthew G. Knepley } 1106858538eSMatthew G. Knepley } 1116858538eSMatthew G. Knepley PetscFunctionReturn(0); 1126858538eSMatthew G. Knepley } 1136858538eSMatthew G. Knepley 1146858538eSMatthew G. Knepley /* 1156858538eSMatthew 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. 1166858538eSMatthew G. Knepley 1176858538eSMatthew G. Knepley Input Parameters: 1186858538eSMatthew G. Knepley + dm - The DM 1196858538eSMatthew G. Knepley . dim - The spatial dimension 1206858538eSMatthew G. Knepley . anchor - The anchor point, the input point can be no more than maxCell away from it 1216858538eSMatthew G. Knepley - in - The input coordinate point (dim numbers) 1226858538eSMatthew G. Knepley 1236858538eSMatthew G. Knepley Output Parameter: 1246858538eSMatthew G. Knepley . out - The localized coordinate point 1256858538eSMatthew G. Knepley 1266858538eSMatthew G. Knepley Level: developer 1276858538eSMatthew G. Knepley 1286858538eSMatthew G. Knepley Note: 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 1296858538eSMatthew G. Knepley 1306858538eSMatthew G. Knepley .seealso: `DMLocalizeCoordinates()`, `DMLocalizeAddCoordinate()` 1316858538eSMatthew G. Knepley */ 132*9371c9d4SSatish Balay PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) { 1336858538eSMatthew G. Knepley PetscInt d; 1346858538eSMatthew G. Knepley 1356858538eSMatthew G. Knepley PetscFunctionBegin; 1366858538eSMatthew G. Knepley if (!dm->maxCell) { 1376858538eSMatthew G. Knepley for (d = 0; d < dim; ++d) out[d] = in[d]; 1386858538eSMatthew G. Knepley } else { 1396858538eSMatthew G. Knepley for (d = 0; d < dim; ++d) { 1406858538eSMatthew G. Knepley if ((dm->L[d] > 0.0) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 1416858538eSMatthew G. Knepley out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 1426858538eSMatthew G. Knepley } else { 1436858538eSMatthew G. Knepley out[d] = in[d]; 1446858538eSMatthew G. Knepley } 1456858538eSMatthew G. Knepley } 1466858538eSMatthew G. Knepley } 1476858538eSMatthew G. Knepley PetscFunctionReturn(0); 1486858538eSMatthew G. Knepley } 1496858538eSMatthew G. Knepley 150*9371c9d4SSatish Balay PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) { 1516858538eSMatthew G. Knepley PetscInt d; 1526858538eSMatthew G. Knepley 1536858538eSMatthew G. Knepley PetscFunctionBegin; 1546858538eSMatthew G. Knepley if (!dm->maxCell) { 1556858538eSMatthew G. Knepley for (d = 0; d < dim; ++d) out[d] = in[d]; 1566858538eSMatthew G. Knepley } else { 1576858538eSMatthew G. Knepley for (d = 0; d < dim; ++d) { 1586858538eSMatthew G. Knepley if ((dm->L[d] > 0.0) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 1596858538eSMatthew G. Knepley out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 1606858538eSMatthew G. Knepley } else { 1616858538eSMatthew G. Knepley out[d] = in[d]; 1626858538eSMatthew G. Knepley } 1636858538eSMatthew G. Knepley } 1646858538eSMatthew G. Knepley } 1656858538eSMatthew G. Knepley PetscFunctionReturn(0); 1666858538eSMatthew G. Knepley } 1676858538eSMatthew G. Knepley 1686858538eSMatthew G. Knepley /* 1696858538eSMatthew 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. 1706858538eSMatthew G. Knepley 1716858538eSMatthew G. Knepley Input Parameters: 1726858538eSMatthew G. Knepley + dm - The DM 1736858538eSMatthew G. Knepley . dim - The spatial dimension 1746858538eSMatthew G. Knepley . anchor - The anchor point, the input point can be no more than maxCell away from it 1756858538eSMatthew G. Knepley . in - The input coordinate delta (dim numbers) 1766858538eSMatthew G. Knepley - out - The input coordinate point (dim numbers) 1776858538eSMatthew G. Knepley 1786858538eSMatthew G. Knepley Output Parameter: 1796858538eSMatthew G. Knepley . out - The localized coordinate in + out 1806858538eSMatthew G. Knepley 1816858538eSMatthew G. Knepley Level: developer 1826858538eSMatthew G. Knepley 1836858538eSMatthew G. Knepley Note: 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 1846858538eSMatthew G. Knepley 1856858538eSMatthew G. Knepley .seealso: `DMLocalizeCoordinates()`, `DMLocalizeCoordinate()` 1866858538eSMatthew G. Knepley */ 187*9371c9d4SSatish Balay PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) { 1886858538eSMatthew G. Knepley PetscInt d; 1896858538eSMatthew G. Knepley 1906858538eSMatthew G. Knepley PetscFunctionBegin; 1916858538eSMatthew G. Knepley if (!dm->maxCell) { 1926858538eSMatthew G. Knepley for (d = 0; d < dim; ++d) out[d] += in[d]; 1936858538eSMatthew G. Knepley } else { 1946858538eSMatthew G. Knepley for (d = 0; d < dim; ++d) { 1956858538eSMatthew G. Knepley const PetscReal maxC = dm->maxCell[d]; 1966858538eSMatthew G. Knepley 1976858538eSMatthew G. Knepley if ((dm->L[d] > 0.0) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) { 1986858538eSMatthew G. Knepley const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 1996858538eSMatthew G. Knepley 2006858538eSMatthew G. Knepley if (PetscAbsScalar(newCoord - anchor[d]) > maxC) 2016858538eSMatthew 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])); 2026858538eSMatthew G. Knepley out[d] += newCoord; 2036858538eSMatthew G. Knepley } else { 2046858538eSMatthew G. Knepley out[d] += in[d]; 2056858538eSMatthew G. Knepley } 2066858538eSMatthew G. Knepley } 2076858538eSMatthew G. Knepley } 2086858538eSMatthew G. Knepley PetscFunctionReturn(0); 2096858538eSMatthew G. Knepley } 2106858538eSMatthew G. Knepley 2116858538eSMatthew G. Knepley /*@ 2126858538eSMatthew G. Knepley DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 2136858538eSMatthew G. Knepley 2146858538eSMatthew G. Knepley Not collective 2156858538eSMatthew G. Knepley 2166858538eSMatthew G. Knepley Input Parameter: 2176858538eSMatthew G. Knepley . dm - The DM 2186858538eSMatthew G. Knepley 2196858538eSMatthew G. Knepley Output Parameter: 2206858538eSMatthew G. Knepley areLocalized - True if localized 2216858538eSMatthew G. Knepley 2226858538eSMatthew G. Knepley Level: developer 2236858538eSMatthew G. Knepley 2246858538eSMatthew G. Knepley .seealso: `DMLocalizeCoordinates()`, `DMGetCoordinatesLocalized()`, `DMSetPeriodicity()` 2256858538eSMatthew G. Knepley @*/ 226*9371c9d4SSatish Balay PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm, PetscBool *areLocalized) { 2276858538eSMatthew G. Knepley PetscFunctionBegin; 2286858538eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2296858538eSMatthew G. Knepley PetscValidBoolPointer(areLocalized, 2); 2306858538eSMatthew G. Knepley *areLocalized = dm->coordinates[1].dim < 0 ? PETSC_FALSE : PETSC_TRUE; 2316858538eSMatthew G. Knepley PetscFunctionReturn(0); 2326858538eSMatthew G. Knepley } 2336858538eSMatthew G. Knepley 2346858538eSMatthew G. Knepley /*@ 2356858538eSMatthew G. Knepley DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 2366858538eSMatthew G. Knepley 2376858538eSMatthew G. Knepley Collective on dm 2386858538eSMatthew G. Knepley 2396858538eSMatthew G. Knepley Input Parameter: 2406858538eSMatthew G. Knepley . dm - The DM 2416858538eSMatthew G. Knepley 2426858538eSMatthew G. Knepley Output Parameter: 2436858538eSMatthew G. Knepley areLocalized - True if localized 2446858538eSMatthew G. Knepley 2456858538eSMatthew G. Knepley Level: developer 2466858538eSMatthew G. Knepley 2476858538eSMatthew G. Knepley .seealso: `DMLocalizeCoordinates()`, `DMSetPeriodicity()`, `DMGetCoordinatesLocalizedLocal()` 2486858538eSMatthew G. Knepley @*/ 249*9371c9d4SSatish Balay PetscErrorCode DMGetCoordinatesLocalized(DM dm, PetscBool *areLocalized) { 2506858538eSMatthew G. Knepley PetscBool localized; 2516858538eSMatthew G. Knepley 2526858538eSMatthew G. Knepley PetscFunctionBegin; 2536858538eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2546858538eSMatthew G. Knepley PetscValidBoolPointer(areLocalized, 2); 2556858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalizedLocal(dm, &localized)); 2566858538eSMatthew G. Knepley PetscCall(MPIU_Allreduce(&localized, areLocalized, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 2576858538eSMatthew G. Knepley PetscFunctionReturn(0); 2586858538eSMatthew G. Knepley } 2596858538eSMatthew G. Knepley 2606858538eSMatthew G. Knepley /*@ 2616858538eSMatthew G. Knepley DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 2626858538eSMatthew G. Knepley 2636858538eSMatthew G. Knepley Collective on dm 2646858538eSMatthew G. Knepley 2656858538eSMatthew G. Knepley Input Parameter: 2666858538eSMatthew G. Knepley . dm - The DM 2676858538eSMatthew G. Knepley 2686858538eSMatthew G. Knepley Level: developer 2696858538eSMatthew G. Knepley 2706858538eSMatthew G. Knepley .seealso: `DMSetPeriodicity()`, `DMLocalizeCoordinate()`, `DMLocalizeAddCoordinate()` 2716858538eSMatthew G. Knepley @*/ 272*9371c9d4SSatish Balay PetscErrorCode DMLocalizeCoordinates(DM dm) { 2736858538eSMatthew G. Knepley DM cdm, cdgdm, cplex, plex; 2746858538eSMatthew G. Knepley PetscSection cs, csDG; 2756858538eSMatthew G. Knepley Vec coordinates, cVec; 2766858538eSMatthew G. Knepley PetscScalar *coordsDG, *anchor, *localized; 2774fb89dddSMatthew G. Knepley const PetscReal *Lstart, *L; 2786858538eSMatthew G. Knepley PetscInt Nc, vStart, vEnd, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, bs, coordSize; 2796858538eSMatthew G. Knepley PetscBool isLocalized, sparseLocalize = dm->sparseLocalize, useDG = PETSC_FALSE, useDGGlobal; 2806858538eSMatthew G. Knepley PetscInt maxHeight = 0, h; 2816858538eSMatthew G. Knepley PetscInt *pStart = NULL, *pEnd = NULL; 2826858538eSMatthew G. Knepley MPI_Comm comm; 2836858538eSMatthew G. Knepley 2846858538eSMatthew G. Knepley PetscFunctionBegin; 2856858538eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2864fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, NULL, &Lstart, &L)); 2876858538eSMatthew G. Knepley /* Cannot automatically localize without L and maxCell right now */ 2886858538eSMatthew G. Knepley if (!L) PetscFunctionReturn(0); 2896858538eSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 2906858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalized(dm, &isLocalized)); 2916858538eSMatthew G. Knepley if (isLocalized) PetscFunctionReturn(0); 2926858538eSMatthew G. Knepley 2936858538eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 2946858538eSMatthew G. Knepley PetscCall(DMConvert(dm, DMPLEX, &plex)); 2956858538eSMatthew G. Knepley PetscCall(DMConvert(cdm, DMPLEX, &cplex)); 2966858538eSMatthew G. Knepley if (cplex) { 2976858538eSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(cplex, 0, &vStart, &vEnd)); 2986858538eSMatthew G. Knepley PetscCall(DMPlexGetMaxProjectionHeight(cplex, &maxHeight)); 2996858538eSMatthew G. Knepley PetscCall(DMGetWorkArray(dm, 2 * (maxHeight + 1), MPIU_INT, &pStart)); 3006858538eSMatthew G. Knepley pEnd = &pStart[maxHeight + 1]; 3016858538eSMatthew G. Knepley newStart = vStart; 3026858538eSMatthew G. Knepley newEnd = vEnd; 3036858538eSMatthew G. Knepley for (h = 0; h <= maxHeight; h++) { 3046858538eSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cplex, h, &pStart[h], &pEnd[h])); 3056858538eSMatthew G. Knepley newStart = PetscMin(newStart, pStart[h]); 3066858538eSMatthew G. Knepley newEnd = PetscMax(newEnd, pEnd[h]); 3076858538eSMatthew G. Knepley } 3086858538eSMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 3096858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3106858538eSMatthew G. Knepley PetscCheck(coordinates, comm, PETSC_ERR_SUP, "Missing local coordinate vector"); 3116858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &cs)); 3126858538eSMatthew G. Knepley PetscCall(VecGetBlockSize(coordinates, &bs)); 3136858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(cs, &sStart, &sEnd)); 3146858538eSMatthew G. Knepley 3156858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(comm, &csDG)); 3166858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csDG, 1)); 3176858538eSMatthew G. Knepley PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc)); 3186858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csDG, 0, Nc)); 3196858538eSMatthew G. Knepley PetscCall(PetscSectionSetChart(csDG, newStart, newEnd)); 3206858538eSMatthew G. Knepley PetscCheck(bs == Nc, comm, PETSC_ERR_ARG_INCOMP, "Coordinate block size %" PetscInt_FMT " != %" PetscInt_FMT " number of components", bs, Nc); 3216858538eSMatthew G. Knepley 3226858538eSMatthew G. Knepley PetscCall(DMGetWorkArray(dm, 2 * Nc, MPIU_SCALAR, &anchor)); 3236858538eSMatthew G. Knepley localized = &anchor[Nc]; 3246858538eSMatthew G. Knepley for (h = 0; h <= maxHeight; h++) { 3256858538eSMatthew G. Knepley PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 3266858538eSMatthew G. Knepley 3276858538eSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 3286858538eSMatthew G. Knepley PetscScalar *cellCoords = NULL; 3296858538eSMatthew G. Knepley DMPolytopeType ct; 3306858538eSMatthew G. Knepley PetscInt dof, d, p; 3316858538eSMatthew G. Knepley 3326858538eSMatthew G. Knepley PetscCall(DMPlexGetCellType(plex, c, &ct)); 3336858538eSMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST) continue; 3346858538eSMatthew G. Knepley PetscCall(DMPlexVecGetClosure(cplex, cs, coordinates, c, &dof, &cellCoords)); 3356858538eSMatthew 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); 3366858538eSMatthew G. Knepley for (d = 0; d < Nc; ++d) anchor[d] = cellCoords[d]; 3376858538eSMatthew G. Knepley for (p = 0; p < dof / Nc; ++p) { 3386858538eSMatthew G. Knepley PetscCall(DMLocalizeCoordinate_Internal(dm, Nc, anchor, &cellCoords[p * Nc], localized)); 339*9371c9d4SSatish Balay for (d = 0; d < Nc; ++d) 340*9371c9d4SSatish Balay if (cellCoords[p * Nc + d] != localized[d]) break; 3416858538eSMatthew G. Knepley if (d < Nc) break; 3426858538eSMatthew G. Knepley } 3436858538eSMatthew G. Knepley if (p < dof / Nc) useDG = PETSC_TRUE; 3446858538eSMatthew G. Knepley if (p < dof / Nc || !sparseLocalize) { 3456858538eSMatthew G. Knepley PetscCall(PetscSectionSetDof(csDG, c, dof)); 3466858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csDG, c, 0, dof)); 3476858538eSMatthew G. Knepley } 3486858538eSMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(cplex, cs, coordinates, c, &dof, &cellCoords)); 3496858538eSMatthew G. Knepley } 3506858538eSMatthew G. Knepley } 3516858538eSMatthew G. Knepley PetscCallMPI(MPI_Allreduce(&useDG, &useDGGlobal, 1, MPIU_BOOL, MPI_LOR, comm)); 3526858538eSMatthew G. Knepley if (!useDGGlobal) goto end; 3536858538eSMatthew G. Knepley 3546858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(csDG)); 3556858538eSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(csDG, &coordSize)); 3566858538eSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &cVec)); 3576858538eSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)cVec, "coordinates")); 3586858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(cVec, bs)); 3596858538eSMatthew G. Knepley PetscCall(VecSetSizes(cVec, coordSize, PETSC_DETERMINE)); 3606858538eSMatthew G. Knepley PetscCall(VecSetType(cVec, VECSTANDARD)); 3616858538eSMatthew G. Knepley PetscCall(VecGetArray(cVec, &coordsDG)); 3626858538eSMatthew G. Knepley for (h = 0; h <= maxHeight; h++) { 3636858538eSMatthew G. Knepley PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 3646858538eSMatthew G. Knepley 3656858538eSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 3666858538eSMatthew G. Knepley PetscScalar *cellCoords = NULL; 3676858538eSMatthew G. Knepley PetscInt p = 0, q, dof, cdof, d, offDG; 3686858538eSMatthew G. Knepley 3696858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(csDG, c, &cdof)); 3706858538eSMatthew G. Knepley if (!cdof) continue; 3716858538eSMatthew G. Knepley PetscCall(DMPlexVecGetClosure(cplex, cs, coordinates, c, &dof, &cellCoords)); 3726858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(csDG, c, &offDG)); 3737c48043bSMatthew G. Knepley // TODO The coordinates are set in closure order, which might not be the tensor order 3746858538eSMatthew G. Knepley for (q = 0; q < dof / Nc; ++q) { 3756858538eSMatthew G. Knepley // Select a trial anchor 3766858538eSMatthew G. Knepley for (d = 0; d < Nc; ++d) anchor[d] = cellCoords[q * Nc + d]; 3776858538eSMatthew G. Knepley for (p = 0; p < dof / Nc; ++p) { 3786858538eSMatthew G. Knepley PetscCall(DMLocalizeCoordinate_Internal(dm, Nc, anchor, &cellCoords[p * Nc], &coordsDG[offDG + p * Nc])); 3794fb89dddSMatthew G. Knepley // We need the cell to fit into the torus [lower, lower+L) 3806858538eSMatthew G. Knepley for (d = 0; d < Nc; ++d) 3814fb89dddSMatthew 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; 3826858538eSMatthew G. Knepley if (d < Nc) break; 3836858538eSMatthew G. Knepley } 3846858538eSMatthew G. Knepley if (p == dof / Nc) break; 3856858538eSMatthew G. Knepley } 3864fb89dddSMatthew 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 + " : ""); 3876858538eSMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(cplex, cs, coordinates, c, &dof, &cellCoords)); 3886858538eSMatthew G. Knepley } 3896858538eSMatthew G. Knepley } 3906858538eSMatthew G. Knepley PetscCall(VecRestoreArray(cVec, &coordsDG)); 3916858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdgdm)); 3926858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, cdgdm)); 3936858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(dm, PETSC_DETERMINE, csDG)); 3946858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, cVec)); 3956858538eSMatthew G. Knepley PetscCall(VecDestroy(&cVec)); 3967c48043bSMatthew G. Knepley // Convert the discretization 3977c48043bSMatthew G. Knepley { 3987c48043bSMatthew G. Knepley PetscFE fe, dgfe; 3997c48043bSMatthew G. Knepley PetscSpace P; 4007c48043bSMatthew G. Knepley PetscDualSpace Q, dgQ; 4017c48043bSMatthew G. Knepley PetscQuadrature q, fq; 4027c48043bSMatthew G. Knepley PetscClassId id; 4037c48043bSMatthew G. Knepley 4047c48043bSMatthew G. Knepley PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe)); 4057c48043bSMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 4067c48043bSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 4077c48043bSMatthew G. Knepley PetscCall(PetscFEGetBasisSpace(fe, &P)); 4087c48043bSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)P)); 4097c48043bSMatthew G. Knepley PetscCall(PetscFEGetDualSpace(fe, &Q)); 4107c48043bSMatthew G. Knepley PetscCall(PetscDualSpaceDuplicate(Q, &dgQ)); 4117c48043bSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeSetContinuity(dgQ, PETSC_FALSE)); 4127c48043bSMatthew G. Knepley PetscCall(PetscDualSpaceSetUp(dgQ)); 4137c48043bSMatthew G. Knepley PetscCall(PetscFEGetQuadrature(fe, &q)); 4147c48043bSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)q)); 4157c48043bSMatthew G. Knepley PetscCall(PetscFEGetFaceQuadrature(fe, &fq)); 4167c48043bSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)fq)); 4177c48043bSMatthew G. Knepley PetscCall(PetscFECreateFromSpaces(P, dgQ, q, fq, &dgfe)); 4187c48043bSMatthew G. Knepley PetscCall(DMSetField(cdgdm, 0, NULL, (PetscObject)dgfe)); 4197c48043bSMatthew G. Knepley PetscCall(PetscFEDestroy(&dgfe)); 4207c48043bSMatthew G. Knepley PetscCall(DMCreateDS(cdgdm)); 4217c48043bSMatthew G. Knepley } 4227c48043bSMatthew G. Knepley } 4236858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdgdm)); 4246858538eSMatthew G. Knepley 4256858538eSMatthew G. Knepley end: 4266858538eSMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor)); 4276858538eSMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, 2 * (maxHeight + 1), MPIU_INT, &pStart)); 4286858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&csDG)); 4296858538eSMatthew G. Knepley PetscCall(DMDestroy(&plex)); 4306858538eSMatthew G. Knepley PetscCall(DMDestroy(&cplex)); 4316858538eSMatthew G. Knepley PetscFunctionReturn(0); 4326858538eSMatthew G. Knepley } 433