1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 29d150b73SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 39d150b73SToby Isaac #include <petscblaslapack.h> 4af74b616SDave May #include <petsctime.h> 5ccd2543fSMatthew G Knepley 63985bb02SVaclav Hapla /*@ 73985bb02SVaclav Hapla DMPlexFindVertices - Try to find DAG points based on their coordinates. 83985bb02SVaclav Hapla 93985bb02SVaclav Hapla Not Collective (provided DMGetCoordinatesLocalSetUp() has been called already) 103985bb02SVaclav Hapla 113985bb02SVaclav Hapla Input Parameters: 123985bb02SVaclav Hapla + dm - The DMPlex object 133985bb02SVaclav Hapla . npoints - The number of sought points 143985bb02SVaclav Hapla . coords - The array of coordinates of the sought points 153985bb02SVaclav Hapla - eps - The tolerance or PETSC_DEFAULT 163985bb02SVaclav Hapla 173985bb02SVaclav Hapla Output Parameters: 183985bb02SVaclav Hapla . dagPoints - The array of found DAG points, or -1 if not found 193985bb02SVaclav Hapla 203985bb02SVaclav Hapla Level: intermediate 213985bb02SVaclav Hapla 223985bb02SVaclav Hapla Notes: 233985bb02SVaclav Hapla The length of the array coords must be npoints * dim where dim is the spatial dimension returned by DMGetDimension(). 243985bb02SVaclav Hapla 253985bb02SVaclav Hapla The output array dagPoints is NOT newly allocated; the user must pass an array of length npoints. 263985bb02SVaclav Hapla 273985bb02SVaclav Hapla Each rank does the search independently; a nonnegative value is returned only if this rank's local DMPlex portion contains the point. 283985bb02SVaclav Hapla 293985bb02SVaclav Hapla The tolerance is interpreted as the maximum Euclidean (L2) distance of the sought point from the specified coordinates. 303985bb02SVaclav Hapla 31*335ef845SVaclav Hapla Complexity of this function is currently O(mn) with m number of vertices to find and n number of vertices in the local mesh. This could probably be improved. 32*335ef845SVaclav Hapla 333985bb02SVaclav Hapla .seealso: DMPlexCreate(), DMGetCoordinates() 343985bb02SVaclav Hapla @*/ 353985bb02SVaclav Hapla PetscErrorCode DMPlexFindVertices(DM dm, PetscInt npoints, const PetscReal coord[], PetscReal eps, PetscInt dagPoints[]) 363985bb02SVaclav Hapla { 37*335ef845SVaclav Hapla PetscInt c, dim, i, j, o, p, vStart, vEnd; 383985bb02SVaclav Hapla Vec allCoordsVec; 393985bb02SVaclav Hapla const PetscScalar *allCoords; 403985bb02SVaclav Hapla PetscReal norm; 413985bb02SVaclav Hapla PetscErrorCode ierr; 423985bb02SVaclav Hapla 433985bb02SVaclav Hapla PetscFunctionBegin; 443985bb02SVaclav Hapla if (eps < 0) eps = PETSC_SQRT_MACHINE_EPSILON; 453985bb02SVaclav Hapla ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 463985bb02SVaclav Hapla ierr = DMGetCoordinatesLocal(dm, &allCoordsVec);CHKERRQ(ierr); 473985bb02SVaclav Hapla ierr = VecGetArrayRead(allCoordsVec, &allCoords);CHKERRQ(ierr); 483985bb02SVaclav Hapla ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 49*335ef845SVaclav Hapla #if defined(PETSC_USE_DEBUG) 50*335ef845SVaclav Hapla /* check coordinate section is consistent with DM dimension */ 51*335ef845SVaclav Hapla { 52*335ef845SVaclav Hapla PetscSection cs; 53*335ef845SVaclav Hapla PetscInt ndof; 54*335ef845SVaclav Hapla 55*335ef845SVaclav Hapla ierr = DMGetCoordinateSection(dm, &cs);CHKERRQ(ierr); 563985bb02SVaclav Hapla for (p = vStart; p < vEnd; p++) { 573985bb02SVaclav Hapla ierr = PetscSectionGetDof(cs, p, &ndof);CHKERRQ(ierr); 583985bb02SVaclav Hapla if (PetscUnlikely(ndof != dim)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "point %D: ndof = %D != %D = dim", p, ndof, dim); 59*335ef845SVaclav Hapla } 60*335ef845SVaclav Hapla } 61*335ef845SVaclav Hapla #endif 62*335ef845SVaclav Hapla for (i=0,j=0; i < npoints; i++,j+=dim) { 63*335ef845SVaclav Hapla dagPoints[i] = -1; 64*335ef845SVaclav Hapla for (p = vStart,o=0; p < vEnd; p++,o+=dim) { 653985bb02SVaclav Hapla norm = 0.0; 663985bb02SVaclav Hapla for (c = 0; c < dim; c++) { 673985bb02SVaclav Hapla norm += PetscSqr(coord[j+c] - PetscRealPart(allCoords[o+c])); 683985bb02SVaclav Hapla } 693985bb02SVaclav Hapla norm = PetscSqrtReal(norm); 703985bb02SVaclav Hapla if (norm <= eps) { 713985bb02SVaclav Hapla dagPoints[i] = p; 723985bb02SVaclav Hapla break; 733985bb02SVaclav Hapla } 743985bb02SVaclav Hapla } 753985bb02SVaclav Hapla } 763985bb02SVaclav Hapla ierr = VecRestoreArrayRead(allCoordsVec, &allCoords);CHKERRQ(ierr); 773985bb02SVaclav Hapla PetscFunctionReturn(0); 783985bb02SVaclav Hapla } 793985bb02SVaclav Hapla 80fea14342SMatthew G. Knepley static PetscErrorCode DMPlexGetLineIntersection_2D_Internal(const PetscReal segmentA[], const PetscReal segmentB[], PetscReal intersection[], PetscBool *hasIntersection) 81fea14342SMatthew G. Knepley { 82fea14342SMatthew G. Knepley const PetscReal p0_x = segmentA[0*2+0]; 83fea14342SMatthew G. Knepley const PetscReal p0_y = segmentA[0*2+1]; 84fea14342SMatthew G. Knepley const PetscReal p1_x = segmentA[1*2+0]; 85fea14342SMatthew G. Knepley const PetscReal p1_y = segmentA[1*2+1]; 86fea14342SMatthew G. Knepley const PetscReal p2_x = segmentB[0*2+0]; 87fea14342SMatthew G. Knepley const PetscReal p2_y = segmentB[0*2+1]; 88fea14342SMatthew G. Knepley const PetscReal p3_x = segmentB[1*2+0]; 89fea14342SMatthew G. Knepley const PetscReal p3_y = segmentB[1*2+1]; 90fea14342SMatthew G. Knepley const PetscReal s1_x = p1_x - p0_x; 91fea14342SMatthew G. Knepley const PetscReal s1_y = p1_y - p0_y; 92fea14342SMatthew G. Knepley const PetscReal s2_x = p3_x - p2_x; 93fea14342SMatthew G. Knepley const PetscReal s2_y = p3_y - p2_y; 94fea14342SMatthew G. Knepley const PetscReal denom = (-s2_x * s1_y + s1_x * s2_y); 95fea14342SMatthew G. Knepley 96fea14342SMatthew G. Knepley PetscFunctionBegin; 97fea14342SMatthew G. Knepley *hasIntersection = PETSC_FALSE; 98fea14342SMatthew G. Knepley /* Non-parallel lines */ 99fea14342SMatthew G. Knepley if (denom != 0.0) { 100fea14342SMatthew G. Knepley const PetscReal s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / denom; 101fea14342SMatthew G. Knepley const PetscReal t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / denom; 102fea14342SMatthew G. Knepley 103fea14342SMatthew G. Knepley if (s >= 0 && s <= 1 && t >= 0 && t <= 1) { 104fea14342SMatthew G. Knepley *hasIntersection = PETSC_TRUE; 105fea14342SMatthew G. Knepley if (intersection) { 106fea14342SMatthew G. Knepley intersection[0] = p0_x + (t * s1_x); 107fea14342SMatthew G. Knepley intersection[1] = p0_y + (t * s1_y); 108fea14342SMatthew G. Knepley } 109fea14342SMatthew G. Knepley } 110fea14342SMatthew G. Knepley } 111fea14342SMatthew G. Knepley PetscFunctionReturn(0); 112fea14342SMatthew G. Knepley } 113fea14342SMatthew G. Knepley 114ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexLocatePoint_Simplex_2D_Internal(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 115ccd2543fSMatthew G Knepley { 116ccd2543fSMatthew G Knepley const PetscInt embedDim = 2; 117f5ebc837SMatthew G. Knepley const PetscReal eps = PETSC_SQRT_MACHINE_EPSILON; 118ccd2543fSMatthew G Knepley PetscReal x = PetscRealPart(point[0]); 119ccd2543fSMatthew G Knepley PetscReal y = PetscRealPart(point[1]); 120ccd2543fSMatthew G Knepley PetscReal v0[2], J[4], invJ[4], detJ; 121ccd2543fSMatthew G Knepley PetscReal xi, eta; 122ccd2543fSMatthew G Knepley PetscErrorCode ierr; 123ccd2543fSMatthew G Knepley 124ccd2543fSMatthew G Knepley PetscFunctionBegin; 1258e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 126ccd2543fSMatthew G Knepley xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 127ccd2543fSMatthew G Knepley eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 128ccd2543fSMatthew G Knepley 129f5ebc837SMatthew G. Knepley if ((xi >= -eps) && (eta >= -eps) && (xi + eta <= 2.0+eps)) *cell = c; 130c1496c66SMatthew G. Knepley else *cell = DMLOCATEPOINT_POINT_NOT_FOUND; 131ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 132ccd2543fSMatthew G Knepley } 133ccd2543fSMatthew G Knepley 13462a38674SMatthew G. Knepley static PetscErrorCode DMPlexClosestPoint_Simplex_2D_Internal(DM dm, const PetscScalar point[], PetscInt c, PetscReal cpoint[]) 13562a38674SMatthew G. Knepley { 13662a38674SMatthew G. Knepley const PetscInt embedDim = 2; 13762a38674SMatthew G. Knepley PetscReal x = PetscRealPart(point[0]); 13862a38674SMatthew G. Knepley PetscReal y = PetscRealPart(point[1]); 13962a38674SMatthew G. Knepley PetscReal v0[2], J[4], invJ[4], detJ; 14062a38674SMatthew G. Knepley PetscReal xi, eta, r; 14162a38674SMatthew G. Knepley PetscErrorCode ierr; 14262a38674SMatthew G. Knepley 14362a38674SMatthew G. Knepley PetscFunctionBegin; 14462a38674SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 14562a38674SMatthew G. Knepley xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 14662a38674SMatthew G. Knepley eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 14762a38674SMatthew G. Knepley 14862a38674SMatthew G. Knepley xi = PetscMax(xi, 0.0); 14962a38674SMatthew G. Knepley eta = PetscMax(eta, 0.0); 15062a38674SMatthew G. Knepley if (xi + eta > 2.0) { 15162a38674SMatthew G. Knepley r = (xi + eta)/2.0; 15262a38674SMatthew G. Knepley xi /= r; 15362a38674SMatthew G. Knepley eta /= r; 15462a38674SMatthew G. Knepley } 15562a38674SMatthew G. Knepley cpoint[0] = J[0*embedDim+0]*xi + J[0*embedDim+1]*eta + v0[0]; 15662a38674SMatthew G. Knepley cpoint[1] = J[1*embedDim+0]*xi + J[1*embedDim+1]*eta + v0[1]; 15762a38674SMatthew G. Knepley PetscFunctionReturn(0); 15862a38674SMatthew G. Knepley } 15962a38674SMatthew G. Knepley 160ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexLocatePoint_General_2D_Internal(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 161ccd2543fSMatthew G Knepley { 162ccd2543fSMatthew G Knepley PetscSection coordSection; 163ccd2543fSMatthew G Knepley Vec coordsLocal; 164a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 165ccd2543fSMatthew G Knepley const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 166ccd2543fSMatthew G Knepley PetscReal x = PetscRealPart(point[0]); 167ccd2543fSMatthew G Knepley PetscReal y = PetscRealPart(point[1]); 168ccd2543fSMatthew G Knepley PetscInt crossings = 0, f; 169ccd2543fSMatthew G Knepley PetscErrorCode ierr; 170ccd2543fSMatthew G Knepley 171ccd2543fSMatthew G Knepley PetscFunctionBegin; 172ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 17369d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 174ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 175ccd2543fSMatthew G Knepley for (f = 0; f < 4; ++f) { 176ccd2543fSMatthew G Knepley PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 177ccd2543fSMatthew G Knepley PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 178ccd2543fSMatthew G Knepley PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 179ccd2543fSMatthew G Knepley PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 180ccd2543fSMatthew G Knepley PetscReal slope = (y_j - y_i) / (x_j - x_i); 181ccd2543fSMatthew G Knepley PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 182ccd2543fSMatthew G Knepley PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 183ccd2543fSMatthew G Knepley PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 184ccd2543fSMatthew G Knepley if ((cond1 || cond2) && above) ++crossings; 185ccd2543fSMatthew G Knepley } 186ccd2543fSMatthew G Knepley if (crossings % 2) *cell = c; 187c1496c66SMatthew G. Knepley else *cell = DMLOCATEPOINT_POINT_NOT_FOUND; 188ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 189ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 190ccd2543fSMatthew G Knepley } 191ccd2543fSMatthew G Knepley 192ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexLocatePoint_Simplex_3D_Internal(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 193ccd2543fSMatthew G Knepley { 194ccd2543fSMatthew G Knepley const PetscInt embedDim = 3; 195ccd2543fSMatthew G Knepley PetscReal v0[3], J[9], invJ[9], detJ; 196ccd2543fSMatthew G Knepley PetscReal x = PetscRealPart(point[0]); 197ccd2543fSMatthew G Knepley PetscReal y = PetscRealPart(point[1]); 198ccd2543fSMatthew G Knepley PetscReal z = PetscRealPart(point[2]); 199ccd2543fSMatthew G Knepley PetscReal xi, eta, zeta; 200ccd2543fSMatthew G Knepley PetscErrorCode ierr; 201ccd2543fSMatthew G Knepley 202ccd2543fSMatthew G Knepley PetscFunctionBegin; 2038e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 204ccd2543fSMatthew G Knepley xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 205ccd2543fSMatthew G Knepley eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 206ccd2543fSMatthew G Knepley zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 207ccd2543fSMatthew G Knepley 208ccd2543fSMatthew G Knepley if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 209c1496c66SMatthew G. Knepley else *cell = DMLOCATEPOINT_POINT_NOT_FOUND; 210ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 211ccd2543fSMatthew G Knepley } 212ccd2543fSMatthew G Knepley 213ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexLocatePoint_General_3D_Internal(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 214ccd2543fSMatthew G Knepley { 215ccd2543fSMatthew G Knepley PetscSection coordSection; 216ccd2543fSMatthew G Knepley Vec coordsLocal; 217872a9804SMatthew G. Knepley PetscScalar *coords = NULL; 218fb150da6SMatthew G. Knepley const PetscInt faces[24] = {0, 3, 2, 1, 5, 4, 7, 6, 3, 0, 4, 5, 219fb150da6SMatthew G. Knepley 1, 2, 6, 7, 3, 5, 6, 2, 0, 1, 7, 4}; 220ccd2543fSMatthew G Knepley PetscBool found = PETSC_TRUE; 221ccd2543fSMatthew G Knepley PetscInt f; 222ccd2543fSMatthew G Knepley PetscErrorCode ierr; 223ccd2543fSMatthew G Knepley 224ccd2543fSMatthew G Knepley PetscFunctionBegin; 225ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 22669d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 227ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 228ccd2543fSMatthew G Knepley for (f = 0; f < 6; ++f) { 229ccd2543fSMatthew G Knepley /* Check the point is under plane */ 230ccd2543fSMatthew G Knepley /* Get face normal */ 231ccd2543fSMatthew G Knepley PetscReal v_i[3]; 232ccd2543fSMatthew G Knepley PetscReal v_j[3]; 233ccd2543fSMatthew G Knepley PetscReal normal[3]; 234ccd2543fSMatthew G Knepley PetscReal pp[3]; 235ccd2543fSMatthew G Knepley PetscReal dot; 236ccd2543fSMatthew G Knepley 237ccd2543fSMatthew G Knepley v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 238ccd2543fSMatthew G Knepley v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 239ccd2543fSMatthew G Knepley v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 240ccd2543fSMatthew G Knepley v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 241ccd2543fSMatthew G Knepley v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 242ccd2543fSMatthew G Knepley v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 243ccd2543fSMatthew G Knepley normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 244ccd2543fSMatthew G Knepley normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 245ccd2543fSMatthew G Knepley normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 246ccd2543fSMatthew G Knepley pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 247ccd2543fSMatthew G Knepley pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 248ccd2543fSMatthew G Knepley pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 249ccd2543fSMatthew G Knepley dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 250ccd2543fSMatthew G Knepley 251ccd2543fSMatthew G Knepley /* Check that projected point is in face (2D location problem) */ 252ccd2543fSMatthew G Knepley if (dot < 0.0) { 253ccd2543fSMatthew G Knepley found = PETSC_FALSE; 254ccd2543fSMatthew G Knepley break; 255ccd2543fSMatthew G Knepley } 256ccd2543fSMatthew G Knepley } 257ccd2543fSMatthew G Knepley if (found) *cell = c; 258c1496c66SMatthew G. Knepley else *cell = DMLOCATEPOINT_POINT_NOT_FOUND; 259ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 260ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 261ccd2543fSMatthew G Knepley } 262ccd2543fSMatthew G Knepley 263c4eade1cSMatthew G. Knepley static PetscErrorCode PetscGridHashInitialize_Internal(PetscGridHash box, PetscInt dim, const PetscScalar point[]) 264c4eade1cSMatthew G. Knepley { 265c4eade1cSMatthew G. Knepley PetscInt d; 266c4eade1cSMatthew G. Knepley 267c4eade1cSMatthew G. Knepley PetscFunctionBegin; 268c4eade1cSMatthew G. Knepley box->dim = dim; 269c4eade1cSMatthew G. Knepley for (d = 0; d < dim; ++d) box->lower[d] = box->upper[d] = PetscRealPart(point[d]); 270c4eade1cSMatthew G. Knepley PetscFunctionReturn(0); 271c4eade1cSMatthew G. Knepley } 272c4eade1cSMatthew G. Knepley 273c4eade1cSMatthew G. Knepley PetscErrorCode PetscGridHashCreate(MPI_Comm comm, PetscInt dim, const PetscScalar point[], PetscGridHash *box) 274c4eade1cSMatthew G. Knepley { 275c4eade1cSMatthew G. Knepley PetscErrorCode ierr; 276c4eade1cSMatthew G. Knepley 277c4eade1cSMatthew G. Knepley PetscFunctionBegin; 278c4eade1cSMatthew G. Knepley ierr = PetscMalloc1(1, box);CHKERRQ(ierr); 279c4eade1cSMatthew G. Knepley ierr = PetscGridHashInitialize_Internal(*box, dim, point);CHKERRQ(ierr); 280c4eade1cSMatthew G. Knepley PetscFunctionReturn(0); 281c4eade1cSMatthew G. Knepley } 282c4eade1cSMatthew G. Knepley 283c4eade1cSMatthew G. Knepley PetscErrorCode PetscGridHashEnlarge(PetscGridHash box, const PetscScalar point[]) 284c4eade1cSMatthew G. Knepley { 285c4eade1cSMatthew G. Knepley PetscInt d; 286c4eade1cSMatthew G. Knepley 287c4eade1cSMatthew G. Knepley PetscFunctionBegin; 288c4eade1cSMatthew G. Knepley for (d = 0; d < box->dim; ++d) { 289c4eade1cSMatthew G. Knepley box->lower[d] = PetscMin(box->lower[d], PetscRealPart(point[d])); 290c4eade1cSMatthew G. Knepley box->upper[d] = PetscMax(box->upper[d], PetscRealPart(point[d])); 291c4eade1cSMatthew G. Knepley } 292c4eade1cSMatthew G. Knepley PetscFunctionReturn(0); 293c4eade1cSMatthew G. Knepley } 294c4eade1cSMatthew G. Knepley 29562a38674SMatthew G. Knepley /* 29662a38674SMatthew G. Knepley PetscGridHashSetGrid - Divide the grid into boxes 29762a38674SMatthew G. Knepley 29862a38674SMatthew G. Knepley Not collective 29962a38674SMatthew G. Knepley 30062a38674SMatthew G. Knepley Input Parameters: 30162a38674SMatthew G. Knepley + box - The grid hash object 30262a38674SMatthew G. Knepley . n - The number of boxes in each dimension, or PETSC_DETERMINE 30362a38674SMatthew G. Knepley - h - The box size in each dimension, only used if n[d] == PETSC_DETERMINE 30462a38674SMatthew G. Knepley 30562a38674SMatthew G. Knepley Level: developer 30662a38674SMatthew G. Knepley 30762a38674SMatthew G. Knepley .seealso: PetscGridHashCreate() 30862a38674SMatthew G. Knepley */ 309c4eade1cSMatthew G. Knepley PetscErrorCode PetscGridHashSetGrid(PetscGridHash box, const PetscInt n[], const PetscReal h[]) 310c4eade1cSMatthew G. Knepley { 311c4eade1cSMatthew G. Knepley PetscInt d; 312c4eade1cSMatthew G. Knepley 313c4eade1cSMatthew G. Knepley PetscFunctionBegin; 314c4eade1cSMatthew G. Knepley for (d = 0; d < box->dim; ++d) { 315c4eade1cSMatthew G. Knepley box->extent[d] = box->upper[d] - box->lower[d]; 316c4eade1cSMatthew G. Knepley if (n[d] == PETSC_DETERMINE) { 317c4eade1cSMatthew G. Knepley box->h[d] = h[d]; 318c4eade1cSMatthew G. Knepley box->n[d] = PetscCeilReal(box->extent[d]/h[d]); 319c4eade1cSMatthew G. Knepley } else { 320c4eade1cSMatthew G. Knepley box->n[d] = n[d]; 321c4eade1cSMatthew G. Knepley box->h[d] = box->extent[d]/n[d]; 322c4eade1cSMatthew G. Knepley } 323c4eade1cSMatthew G. Knepley } 324c4eade1cSMatthew G. Knepley PetscFunctionReturn(0); 325c4eade1cSMatthew G. Knepley } 326c4eade1cSMatthew G. Knepley 32762a38674SMatthew G. Knepley /* 32862a38674SMatthew G. Knepley PetscGridHashGetEnclosingBox - Find the grid boxes containing each input point 32962a38674SMatthew G. Knepley 33062a38674SMatthew G. Knepley Not collective 33162a38674SMatthew G. Knepley 33262a38674SMatthew G. Knepley Input Parameters: 33362a38674SMatthew G. Knepley + box - The grid hash object 33462a38674SMatthew G. Knepley . numPoints - The number of input points 33562a38674SMatthew G. Knepley - points - The input point coordinates 33662a38674SMatthew G. Knepley 33762a38674SMatthew G. Knepley Output Parameters: 33862a38674SMatthew G. Knepley + dboxes - An array of numPoints*dim integers expressing the enclosing box as (i_0, i_1, ..., i_dim) 33962a38674SMatthew G. Knepley - boxes - An array of numPoints integers expressing the enclosing box as single number, or NULL 34062a38674SMatthew G. Knepley 34162a38674SMatthew G. Knepley Level: developer 34262a38674SMatthew G. Knepley 34362a38674SMatthew G. Knepley .seealso: PetscGridHashCreate() 34462a38674SMatthew G. Knepley */ 3451c6dfc3eSMatthew G. Knepley PetscErrorCode PetscGridHashGetEnclosingBox(PetscGridHash box, PetscInt numPoints, const PetscScalar points[], PetscInt dboxes[], PetscInt boxes[]) 346c4eade1cSMatthew G. Knepley { 347c4eade1cSMatthew G. Knepley const PetscReal *lower = box->lower; 348c4eade1cSMatthew G. Knepley const PetscReal *upper = box->upper; 349c4eade1cSMatthew G. Knepley const PetscReal *h = box->h; 350c4eade1cSMatthew G. Knepley const PetscInt *n = box->n; 351c4eade1cSMatthew G. Knepley const PetscInt dim = box->dim; 352c4eade1cSMatthew G. Knepley PetscInt d, p; 353c4eade1cSMatthew G. Knepley 354c4eade1cSMatthew G. Knepley PetscFunctionBegin; 355c4eade1cSMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 356c4eade1cSMatthew G. Knepley for (d = 0; d < dim; ++d) { 3571c6dfc3eSMatthew G. Knepley PetscInt dbox = PetscFloorReal((PetscRealPart(points[p*dim+d]) - lower[d])/h[d]); 358c4eade1cSMatthew G. Knepley 3591c6dfc3eSMatthew G. Knepley if (dbox == n[d] && PetscAbsReal(PetscRealPart(points[p*dim+d]) - upper[d]) < 1.0e-9) dbox = n[d]-1; 3602a705cacSMatthew G. Knepley if (dbox == -1 && PetscAbsReal(PetscRealPart(points[p*dim+d]) - lower[d]) < 1.0e-9) dbox = 0; 361c4eade1cSMatthew G. Knepley if (dbox < 0 || dbox >= n[d]) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input point %d (%g, %g, %g) is outside of our bounding box", 362087ef6b2SMatthew G. Knepley p, (double) PetscRealPart(points[p*dim+0]), dim > 1 ? (double) PetscRealPart(points[p*dim+1]) : 0.0, dim > 2 ? (double) PetscRealPart(points[p*dim+2]) : 0.0); 363c4eade1cSMatthew G. Knepley dboxes[p*dim+d] = dbox; 364c4eade1cSMatthew G. Knepley } 365c4eade1cSMatthew G. Knepley if (boxes) for (d = 1, boxes[p] = dboxes[p*dim]; d < dim; ++d) boxes[p] += dboxes[p*dim+d]*n[d-1]; 366c4eade1cSMatthew G. Knepley } 367c4eade1cSMatthew G. Knepley PetscFunctionReturn(0); 368c4eade1cSMatthew G. Knepley } 369c4eade1cSMatthew G. Knepley 370af74b616SDave May /* 371af74b616SDave May PetscGridHashGetEnclosingBoxQuery - Find the grid boxes containing each input point 372af74b616SDave May 373af74b616SDave May Not collective 374af74b616SDave May 375af74b616SDave May Input Parameters: 376af74b616SDave May + box - The grid hash object 377af74b616SDave May . numPoints - The number of input points 378af74b616SDave May - points - The input point coordinates 379af74b616SDave May 380af74b616SDave May Output Parameters: 381af74b616SDave May + dboxes - An array of numPoints*dim integers expressing the enclosing box as (i_0, i_1, ..., i_dim) 382af74b616SDave May . boxes - An array of numPoints integers expressing the enclosing box as single number, or NULL 383af74b616SDave May - found - Flag indicating if point was located within a box 384af74b616SDave May 385af74b616SDave May Level: developer 386af74b616SDave May 387af74b616SDave May .seealso: PetscGridHashGetEnclosingBox() 388af74b616SDave May */ 389af74b616SDave May PetscErrorCode PetscGridHashGetEnclosingBoxQuery(PetscGridHash box, PetscInt numPoints, const PetscScalar points[], PetscInt dboxes[], PetscInt boxes[],PetscBool *found) 390af74b616SDave May { 391af74b616SDave May const PetscReal *lower = box->lower; 392af74b616SDave May const PetscReal *upper = box->upper; 393af74b616SDave May const PetscReal *h = box->h; 394af74b616SDave May const PetscInt *n = box->n; 395af74b616SDave May const PetscInt dim = box->dim; 396af74b616SDave May PetscInt d, p; 397af74b616SDave May 398af74b616SDave May PetscFunctionBegin; 399af74b616SDave May *found = PETSC_FALSE; 400af74b616SDave May for (p = 0; p < numPoints; ++p) { 401af74b616SDave May for (d = 0; d < dim; ++d) { 402af74b616SDave May PetscInt dbox = PetscFloorReal((PetscRealPart(points[p*dim+d]) - lower[d])/h[d]); 403af74b616SDave May 404af74b616SDave May if (dbox == n[d] && PetscAbsReal(PetscRealPart(points[p*dim+d]) - upper[d]) < 1.0e-9) dbox = n[d]-1; 405af74b616SDave May if (dbox < 0 || dbox >= n[d]) { 406af74b616SDave May PetscFunctionReturn(0); 407af74b616SDave May } 408af74b616SDave May dboxes[p*dim+d] = dbox; 409af74b616SDave May } 410af74b616SDave May if (boxes) for (d = 1, boxes[p] = dboxes[p*dim]; d < dim; ++d) boxes[p] += dboxes[p*dim+d]*n[d-1]; 411af74b616SDave May } 412af74b616SDave May *found = PETSC_TRUE; 413af74b616SDave May PetscFunctionReturn(0); 414af74b616SDave May } 415af74b616SDave May 416c4eade1cSMatthew G. Knepley PetscErrorCode PetscGridHashDestroy(PetscGridHash *box) 417c4eade1cSMatthew G. Knepley { 418c4eade1cSMatthew G. Knepley PetscErrorCode ierr; 419c4eade1cSMatthew G. Knepley 420c4eade1cSMatthew G. Knepley PetscFunctionBegin; 421c4eade1cSMatthew G. Knepley if (*box) { 422c4eade1cSMatthew G. Knepley ierr = PetscSectionDestroy(&(*box)->cellSection);CHKERRQ(ierr); 423c4eade1cSMatthew G. Knepley ierr = ISDestroy(&(*box)->cells);CHKERRQ(ierr); 424c4eade1cSMatthew G. Knepley ierr = DMLabelDestroy(&(*box)->cellsSparse);CHKERRQ(ierr); 425c4eade1cSMatthew G. Knepley } 426c4eade1cSMatthew G. Knepley ierr = PetscFree(*box);CHKERRQ(ierr); 427c4eade1cSMatthew G. Knepley PetscFunctionReturn(0); 428c4eade1cSMatthew G. Knepley } 429c4eade1cSMatthew G. Knepley 430cafe43deSMatthew G. Knepley PetscErrorCode DMPlexLocatePoint_Internal(DM dm, PetscInt dim, const PetscScalar point[], PetscInt cellStart, PetscInt *cell) 431cafe43deSMatthew G. Knepley { 432cafe43deSMatthew G. Knepley PetscInt coneSize; 433cafe43deSMatthew G. Knepley PetscErrorCode ierr; 434cafe43deSMatthew G. Knepley 435cafe43deSMatthew G. Knepley PetscFunctionBegin; 436cafe43deSMatthew G. Knepley switch (dim) { 437cafe43deSMatthew G. Knepley case 2: 438cafe43deSMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cellStart, &coneSize);CHKERRQ(ierr); 439cafe43deSMatthew G. Knepley switch (coneSize) { 440cafe43deSMatthew G. Knepley case 3: 441cafe43deSMatthew G. Knepley ierr = DMPlexLocatePoint_Simplex_2D_Internal(dm, point, cellStart, cell);CHKERRQ(ierr); 442cafe43deSMatthew G. Knepley break; 443cafe43deSMatthew G. Knepley case 4: 444cafe43deSMatthew G. Knepley ierr = DMPlexLocatePoint_General_2D_Internal(dm, point, cellStart, cell);CHKERRQ(ierr); 445cafe43deSMatthew G. Knepley break; 446cafe43deSMatthew G. Knepley default: 447cafe43deSMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %D", coneSize); 448cafe43deSMatthew G. Knepley } 449cafe43deSMatthew G. Knepley break; 450cafe43deSMatthew G. Knepley case 3: 451cafe43deSMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cellStart, &coneSize);CHKERRQ(ierr); 452cafe43deSMatthew G. Knepley switch (coneSize) { 453cafe43deSMatthew G. Knepley case 4: 454cafe43deSMatthew G. Knepley ierr = DMPlexLocatePoint_Simplex_3D_Internal(dm, point, cellStart, cell);CHKERRQ(ierr); 455cafe43deSMatthew G. Knepley break; 456cafe43deSMatthew G. Knepley case 6: 457cafe43deSMatthew G. Knepley ierr = DMPlexLocatePoint_General_3D_Internal(dm, point, cellStart, cell);CHKERRQ(ierr); 458cafe43deSMatthew G. Knepley break; 459cafe43deSMatthew G. Knepley default: 460cafe43deSMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %D", coneSize); 461cafe43deSMatthew G. Knepley } 462cafe43deSMatthew G. Knepley break; 463cafe43deSMatthew G. Knepley default: 464cafe43deSMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %D", dim); 465cafe43deSMatthew G. Knepley } 466cafe43deSMatthew G. Knepley PetscFunctionReturn(0); 467cafe43deSMatthew G. Knepley } 468cafe43deSMatthew G. Knepley 46962a38674SMatthew G. Knepley /* 47062a38674SMatthew G. Knepley DMPlexClosestPoint_Internal - Returns the closest point in the cell to the given point 47162a38674SMatthew G. Knepley */ 47262a38674SMatthew G. Knepley PetscErrorCode DMPlexClosestPoint_Internal(DM dm, PetscInt dim, const PetscScalar point[], PetscInt cell, PetscReal cpoint[]) 47362a38674SMatthew G. Knepley { 47462a38674SMatthew G. Knepley PetscInt coneSize; 47562a38674SMatthew G. Knepley PetscErrorCode ierr; 47662a38674SMatthew G. Knepley 47762a38674SMatthew G. Knepley PetscFunctionBegin; 47862a38674SMatthew G. Knepley switch (dim) { 47962a38674SMatthew G. Knepley case 2: 48062a38674SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 48162a38674SMatthew G. Knepley switch (coneSize) { 48262a38674SMatthew G. Knepley case 3: 48362a38674SMatthew G. Knepley ierr = DMPlexClosestPoint_Simplex_2D_Internal(dm, point, cell, cpoint);CHKERRQ(ierr); 48462a38674SMatthew G. Knepley break; 48562a38674SMatthew G. Knepley #if 0 48662a38674SMatthew G. Knepley case 4: 48762a38674SMatthew G. Knepley ierr = DMPlexClosestPoint_General_2D_Internal(dm, point, cell, cpoint);CHKERRQ(ierr); 48862a38674SMatthew G. Knepley break; 48962a38674SMatthew G. Knepley #endif 49062a38674SMatthew G. Knepley default: 49162a38674SMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No closest point location for cell with cone size %D", coneSize); 49262a38674SMatthew G. Knepley } 49362a38674SMatthew G. Knepley break; 49462a38674SMatthew G. Knepley #if 0 49562a38674SMatthew G. Knepley case 3: 49662a38674SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 49762a38674SMatthew G. Knepley switch (coneSize) { 49862a38674SMatthew G. Knepley case 4: 49962a38674SMatthew G. Knepley ierr = DMPlexClosestPoint_Simplex_3D_Internal(dm, point, cell, cpoint);CHKERRQ(ierr); 50062a38674SMatthew G. Knepley break; 50162a38674SMatthew G. Knepley case 6: 50262a38674SMatthew G. Knepley ierr = DMPlexClosestPoint_General_3D_Internal(dm, point, cell, cpoint);CHKERRQ(ierr); 50362a38674SMatthew G. Knepley break; 50462a38674SMatthew G. Knepley default: 50562a38674SMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No closest point location for cell with cone size %D", coneSize); 50662a38674SMatthew G. Knepley } 50762a38674SMatthew G. Knepley break; 50862a38674SMatthew G. Knepley #endif 50962a38674SMatthew G. Knepley default: 51062a38674SMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No closest point location for mesh dimension %D", dim); 51162a38674SMatthew G. Knepley } 51262a38674SMatthew G. Knepley PetscFunctionReturn(0); 51362a38674SMatthew G. Knepley } 51462a38674SMatthew G. Knepley 51562a38674SMatthew G. Knepley /* 51662a38674SMatthew G. Knepley DMPlexComputeGridHash_Internal - Create a grid hash structure covering the Plex 51762a38674SMatthew G. Knepley 518d083f849SBarry Smith Collective on dm 51962a38674SMatthew G. Knepley 52062a38674SMatthew G. Knepley Input Parameter: 52162a38674SMatthew G. Knepley . dm - The Plex 52262a38674SMatthew G. Knepley 52362a38674SMatthew G. Knepley Output Parameter: 52462a38674SMatthew G. Knepley . localBox - The grid hash object 52562a38674SMatthew G. Knepley 52662a38674SMatthew G. Knepley Level: developer 52762a38674SMatthew G. Knepley 52862a38674SMatthew G. Knepley .seealso: PetscGridHashCreate(), PetscGridHashGetEnclosingBox() 52962a38674SMatthew G. Knepley */ 530cafe43deSMatthew G. Knepley PetscErrorCode DMPlexComputeGridHash_Internal(DM dm, PetscGridHash *localBox) 531cafe43deSMatthew G. Knepley { 532cafe43deSMatthew G. Knepley MPI_Comm comm; 533cafe43deSMatthew G. Knepley PetscGridHash lbox; 534cafe43deSMatthew G. Knepley Vec coordinates; 535cafe43deSMatthew G. Knepley PetscSection coordSection; 536cafe43deSMatthew G. Knepley Vec coordsLocal; 537cafe43deSMatthew G. Knepley const PetscScalar *coords; 538722d0f5cSMatthew G. Knepley PetscInt *dboxes, *boxes; 539cafe43deSMatthew G. Knepley PetscInt n[3] = {10, 10, 10}; 5401d0c6c94SMatthew G. Knepley PetscInt dim, N, cStart, cEnd, cMax, c, i; 541cafe43deSMatthew G. Knepley PetscErrorCode ierr; 542cafe43deSMatthew G. Knepley 543cafe43deSMatthew G. Knepley PetscFunctionBegin; 544cafe43deSMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 545cafe43deSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 546cafe43deSMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 5475b3353d8SMatthew G. Knepley if (dim != 2) SETERRQ(comm, PETSC_ERR_SUP, "I have only coded this for 2D"); 548cafe43deSMatthew G. Knepley ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 549cafe43deSMatthew G. Knepley ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 550cafe43deSMatthew G. Knepley ierr = PetscGridHashCreate(comm, dim, coords, &lbox);CHKERRQ(ierr); 551cafe43deSMatthew G. Knepley for (i = 0; i < N; i += dim) {ierr = PetscGridHashEnlarge(lbox, &coords[i]);CHKERRQ(ierr);} 552cafe43deSMatthew G. Knepley ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 5539cb35068SDave May ierr = PetscOptionsGetInt(NULL,NULL,"-dm_plex_hash_box_nijk",&n[0],NULL);CHKERRQ(ierr); 5549cb35068SDave May n[1] = n[0]; 5559cb35068SDave May n[2] = n[0]; 556cafe43deSMatthew G. Knepley ierr = PetscGridHashSetGrid(lbox, n, NULL);CHKERRQ(ierr); 557cafe43deSMatthew G. Knepley #if 0 558cafe43deSMatthew G. Knepley /* Could define a custom reduction to merge these */ 559b2566f29SBarry Smith ierr = MPIU_Allreduce(lbox->lower, gbox->lower, 3, MPIU_REAL, MPI_MIN, comm);CHKERRQ(ierr); 560b2566f29SBarry Smith ierr = MPIU_Allreduce(lbox->upper, gbox->upper, 3, MPIU_REAL, MPI_MAX, comm);CHKERRQ(ierr); 561cafe43deSMatthew G. Knepley #endif 562cafe43deSMatthew G. Knepley /* Is there a reason to snap the local bounding box to a division of the global box? */ 563cafe43deSMatthew G. Knepley /* Should we compute all overlaps of local boxes? We could do this with a rendevouz scheme partitioning the global box */ 564cafe43deSMatthew G. Knepley /* Create label */ 565cafe43deSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5661d0c6c94SMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5671d0c6c94SMatthew G. Knepley if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 568d67d17b1SMatthew G. Knepley ierr = DMLabelCreate(PETSC_COMM_SELF, "cells", &lbox->cellsSparse);CHKERRQ(ierr); 569cafe43deSMatthew G. Knepley ierr = DMLabelCreateIndex(lbox->cellsSparse, cStart, cEnd);CHKERRQ(ierr); 570a8d69d7bSBarry Smith /* Compute boxes which overlap each cell: https://stackoverflow.com/questions/13790208/triangle-square-intersection-test-in-2d */ 571cafe43deSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 572cafe43deSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 57338353de4SMatthew G. Knepley ierr = PetscCalloc2(16 * dim, &dboxes, 16, &boxes);CHKERRQ(ierr); 574cafe43deSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 575cafe43deSMatthew G. Knepley const PetscReal *h = lbox->h; 576cafe43deSMatthew G. Knepley PetscScalar *ccoords = NULL; 57738353de4SMatthew G. Knepley PetscInt csize = 0; 578cafe43deSMatthew G. Knepley PetscScalar point[3]; 579cafe43deSMatthew G. Knepley PetscInt dlim[6], d, e, i, j, k; 580cafe43deSMatthew G. Knepley 581cafe43deSMatthew G. Knepley /* Find boxes enclosing each vertex */ 58238353de4SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &csize, &ccoords);CHKERRQ(ierr); 58338353de4SMatthew G. Knepley ierr = PetscGridHashGetEnclosingBox(lbox, csize/dim, ccoords, dboxes, boxes);CHKERRQ(ierr); 584722d0f5cSMatthew G. Knepley /* Mark cells containing the vertices */ 58538353de4SMatthew G. Knepley for (e = 0; e < csize/dim; ++e) {ierr = DMLabelSetValue(lbox->cellsSparse, c, boxes[e]);CHKERRQ(ierr);} 586cafe43deSMatthew G. Knepley /* Get grid of boxes containing these */ 587cafe43deSMatthew G. Knepley for (d = 0; d < dim; ++d) {dlim[d*2+0] = dlim[d*2+1] = dboxes[d];} 5882291669eSMatthew G. Knepley for (d = dim; d < 3; ++d) {dlim[d*2+0] = dlim[d*2+1] = 0;} 589cafe43deSMatthew G. Knepley for (e = 1; e < dim+1; ++e) { 590cafe43deSMatthew G. Knepley for (d = 0; d < dim; ++d) { 591cafe43deSMatthew G. Knepley dlim[d*2+0] = PetscMin(dlim[d*2+0], dboxes[e*dim+d]); 592cafe43deSMatthew G. Knepley dlim[d*2+1] = PetscMax(dlim[d*2+1], dboxes[e*dim+d]); 593cafe43deSMatthew G. Knepley } 594cafe43deSMatthew G. Knepley } 595fea14342SMatthew G. Knepley /* Check for intersection of box with cell */ 596cafe43deSMatthew G. Knepley for (k = dlim[2*2+0], point[2] = lbox->lower[2] + k*h[2]; k <= dlim[2*2+1]; ++k, point[2] += h[2]) { 597cafe43deSMatthew G. Knepley for (j = dlim[1*2+0], point[1] = lbox->lower[1] + j*h[1]; j <= dlim[1*2+1]; ++j, point[1] += h[1]) { 598cafe43deSMatthew G. Knepley for (i = dlim[0*2+0], point[0] = lbox->lower[0] + i*h[0]; i <= dlim[0*2+1]; ++i, point[0] += h[0]) { 599cafe43deSMatthew G. Knepley const PetscInt box = (k*lbox->n[1] + j)*lbox->n[0] + i; 600cafe43deSMatthew G. Knepley PetscScalar cpoint[3]; 601fea14342SMatthew G. Knepley PetscInt cell, edge, ii, jj, kk; 602cafe43deSMatthew G. Knepley 603fea14342SMatthew G. Knepley /* Check whether cell contains any vertex of these subboxes TODO vectorize this */ 604cafe43deSMatthew G. Knepley for (kk = 0, cpoint[2] = point[2]; kk < (dim > 2 ? 2 : 1); ++kk, cpoint[2] += h[2]) { 605cafe43deSMatthew G. Knepley for (jj = 0, cpoint[1] = point[1]; jj < (dim > 1 ? 2 : 1); ++jj, cpoint[1] += h[1]) { 606cafe43deSMatthew G. Knepley for (ii = 0, cpoint[0] = point[0]; ii < 2; ++ii, cpoint[0] += h[0]) { 607cafe43deSMatthew G. Knepley 608cafe43deSMatthew G. Knepley ierr = DMPlexLocatePoint_Internal(dm, dim, cpoint, c, &cell);CHKERRQ(ierr); 609367003a6SStefano Zampini if (cell >= 0) { ierr = DMLabelSetValue(lbox->cellsSparse, c, box);CHKERRQ(ierr); ii = jj = kk = 2;} 610cafe43deSMatthew G. Knepley } 611cafe43deSMatthew G. Knepley } 612cafe43deSMatthew G. Knepley } 613fea14342SMatthew G. Knepley /* Check whether cell edge intersects any edge of these subboxes TODO vectorize this */ 614fea14342SMatthew G. Knepley for (edge = 0; edge < dim+1; ++edge) { 615fea14342SMatthew G. Knepley PetscReal segA[6], segB[6]; 616fea14342SMatthew G. Knepley 617aab5bcd8SJed Brown if (PetscUnlikely(dim > 3)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected dim %d > 3",dim); 618fea14342SMatthew G. Knepley for (d = 0; d < dim; ++d) {segA[d] = PetscRealPart(ccoords[edge*dim+d]); segA[dim+d] = PetscRealPart(ccoords[((edge+1)%(dim+1))*dim+d]);} 619fea14342SMatthew G. Knepley for (kk = 0; kk < (dim > 2 ? 2 : 1); ++kk) { 6209a128ed2SMatthew G. Knepley if (dim > 2) {segB[2] = PetscRealPart(point[2]); 6219a128ed2SMatthew G. Knepley segB[dim+2] = PetscRealPart(point[2]) + kk*h[2];} 622fea14342SMatthew G. Knepley for (jj = 0; jj < (dim > 1 ? 2 : 1); ++jj) { 6239a128ed2SMatthew G. Knepley if (dim > 1) {segB[1] = PetscRealPart(point[1]); 6249a128ed2SMatthew G. Knepley segB[dim+1] = PetscRealPart(point[1]) + jj*h[1];} 625fea14342SMatthew G. Knepley for (ii = 0; ii < 2; ++ii) { 626fea14342SMatthew G. Knepley PetscBool intersects; 627fea14342SMatthew G. Knepley 6289a128ed2SMatthew G. Knepley segB[0] = PetscRealPart(point[0]); 6299a128ed2SMatthew G. Knepley segB[dim+0] = PetscRealPart(point[0]) + ii*h[0]; 630fea14342SMatthew G. Knepley ierr = DMPlexGetLineIntersection_2D_Internal(segA, segB, NULL, &intersects);CHKERRQ(ierr); 631367003a6SStefano Zampini if (intersects) { ierr = DMLabelSetValue(lbox->cellsSparse, c, box);CHKERRQ(ierr); edge = ii = jj = kk = dim+1;} 632cafe43deSMatthew G. Knepley } 633cafe43deSMatthew G. Knepley } 634cafe43deSMatthew G. Knepley } 635cafe43deSMatthew G. Knepley } 636fea14342SMatthew G. Knepley } 637fea14342SMatthew G. Knepley } 638fea14342SMatthew G. Knepley } 639fea14342SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &ccoords);CHKERRQ(ierr); 640fea14342SMatthew G. Knepley } 641722d0f5cSMatthew G. Knepley ierr = PetscFree2(dboxes, boxes);CHKERRQ(ierr); 642cafe43deSMatthew G. Knepley ierr = DMLabelConvertToSection(lbox->cellsSparse, &lbox->cellSection, &lbox->cells);CHKERRQ(ierr); 643cafe43deSMatthew G. Knepley ierr = DMLabelDestroy(&lbox->cellsSparse);CHKERRQ(ierr); 644cafe43deSMatthew G. Knepley *localBox = lbox; 645cafe43deSMatthew G. Knepley PetscFunctionReturn(0); 646cafe43deSMatthew G. Knepley } 647cafe43deSMatthew G. Knepley 64862a38674SMatthew G. Knepley PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, DMPointLocationType ltype, PetscSF cellSF) 649ccd2543fSMatthew G Knepley { 650cafe43deSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 651af74b616SDave May PetscBool hash = mesh->useHashLocation, reuse = PETSC_FALSE; 6523a93e3b7SToby Isaac PetscInt bs, numPoints, p, numFound, *found = NULL; 6539cb35068SDave May PetscInt dim, cStart, cEnd, cMax, numCells, c, d; 654cafe43deSMatthew G. Knepley const PetscInt *boxCells; 6553a93e3b7SToby Isaac PetscSFNode *cells; 656ccd2543fSMatthew G Knepley PetscScalar *a; 6573a93e3b7SToby Isaac PetscMPIInt result; 658af74b616SDave May PetscLogDouble t0,t1; 6599cb35068SDave May PetscReal gmin[3],gmax[3]; 6609cb35068SDave May PetscInt terminating_query_type[] = { 0, 0, 0 }; 661ccd2543fSMatthew G Knepley PetscErrorCode ierr; 662ccd2543fSMatthew G Knepley 663ccd2543fSMatthew G Knepley PetscFunctionBegin; 664af74b616SDave May ierr = PetscTime(&t0);CHKERRQ(ierr); 665080342d1SMatthew G. Knepley if (ltype == DM_POINTLOCATION_NEAREST && !hash) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Nearest point location only supported with grid hashing. Use -dm_plex_hash_location to enable it."); 666cafe43deSMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 667cafe43deSMatthew G. Knepley ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 6683a93e3b7SToby Isaac ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)cellSF),PETSC_COMM_SELF,&result);CHKERRQ(ierr); 6693a93e3b7SToby Isaac if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PetscObjectComm((PetscObject)cellSF),PETSC_ERR_SUP, "Trying parallel point location: only local point location supported"); 670cafe43deSMatthew G. Knepley if (bs != dim) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Block size for point vector %D must be the mesh coordinate dimension %D", bs, dim); 671ccd2543fSMatthew G Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 672ccd2543fSMatthew G Knepley ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 673ccd2543fSMatthew G Knepley if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 674ccd2543fSMatthew G Knepley ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 675ccd2543fSMatthew G Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 676ccd2543fSMatthew G Knepley numPoints /= bs; 677af74b616SDave May { 678af74b616SDave May const PetscSFNode *sf_cells; 679af74b616SDave May 680af74b616SDave May ierr = PetscSFGetGraph(cellSF,NULL,NULL,NULL,&sf_cells);CHKERRQ(ierr); 681af74b616SDave May if (sf_cells) { 682af74b616SDave May ierr = PetscInfo(dm,"[DMLocatePoints_Plex] Re-using existing StarForest node list\n");CHKERRQ(ierr); 683af74b616SDave May cells = (PetscSFNode*)sf_cells; 684af74b616SDave May reuse = PETSC_TRUE; 685af74b616SDave May } else { 686af74b616SDave May ierr = PetscInfo(dm,"[DMLocatePoints_Plex] Creating and initializing new StarForest node list\n");CHKERRQ(ierr); 687785e854fSJed Brown ierr = PetscMalloc1(numPoints, &cells);CHKERRQ(ierr); 688af74b616SDave May /* initialize cells if created */ 689af74b616SDave May for (p=0; p<numPoints; p++) { 690af74b616SDave May cells[p].rank = 0; 691af74b616SDave May cells[p].index = DMLOCATEPOINT_POINT_NOT_FOUND; 692af74b616SDave May } 693af74b616SDave May } 694af74b616SDave May } 6959cb35068SDave May /* define domain bounding box */ 6969cb35068SDave May { 6979cb35068SDave May Vec coorglobal; 6989cb35068SDave May 6999cb35068SDave May ierr = DMGetCoordinates(dm,&coorglobal);CHKERRQ(ierr); 7009cb35068SDave May ierr = VecStrideMaxAll(coorglobal,NULL,gmax);CHKERRQ(ierr); 7019cb35068SDave May ierr = VecStrideMinAll(coorglobal,NULL,gmin);CHKERRQ(ierr); 7029cb35068SDave May } 703953fc75cSMatthew G. Knepley if (hash) { 704ac6ec2abSMatthew G. Knepley if (!mesh->lbox) {ierr = PetscInfo(dm, "Initializing grid hashing");CHKERRQ(ierr);ierr = DMPlexComputeGridHash_Internal(dm, &mesh->lbox);CHKERRQ(ierr);} 705cafe43deSMatthew G. Knepley /* Designate the local box for each point */ 706cafe43deSMatthew G. Knepley /* Send points to correct process */ 707cafe43deSMatthew G. Knepley /* Search cells that lie in each subbox */ 708cafe43deSMatthew G. Knepley /* Should we bin points before doing search? */ 709cafe43deSMatthew G. Knepley ierr = ISGetIndices(mesh->lbox->cells, &boxCells);CHKERRQ(ierr); 710953fc75cSMatthew G. Knepley } 7113a93e3b7SToby Isaac for (p = 0, numFound = 0; p < numPoints; ++p) { 712ccd2543fSMatthew G Knepley const PetscScalar *point = &a[p*bs]; 713e56f9228SJed Brown PetscInt dbin[3] = {-1,-1,-1}, bin, cell = -1, cellOffset; 7149cb35068SDave May PetscBool point_outside_domain = PETSC_FALSE; 715ccd2543fSMatthew G Knepley 7169cb35068SDave May /* check bounding box of domain */ 7179cb35068SDave May for (d=0; d<dim; d++) { 718a5f152d1SDave May if (PetscRealPart(point[d]) < gmin[d]) { point_outside_domain = PETSC_TRUE; break; } 719a5f152d1SDave May if (PetscRealPart(point[d]) > gmax[d]) { point_outside_domain = PETSC_TRUE; break; } 7209cb35068SDave May } 7219cb35068SDave May if (point_outside_domain) { 722e9b685f5SMatthew G. Knepley cells[p].rank = 0; 723e9b685f5SMatthew G. Knepley cells[p].index = DMLOCATEPOINT_POINT_NOT_FOUND; 7249cb35068SDave May terminating_query_type[0]++; 7259cb35068SDave May continue; 7269cb35068SDave May } 727ccd2543fSMatthew G Knepley 728af74b616SDave May /* check initial values in cells[].index - abort early if found */ 729af74b616SDave May if (cells[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 730af74b616SDave May c = cells[p].index; 7313a93e3b7SToby Isaac cells[p].index = DMLOCATEPOINT_POINT_NOT_FOUND; 732af74b616SDave May ierr = DMPlexLocatePoint_Internal(dm, dim, point, c, &cell);CHKERRQ(ierr); 733af74b616SDave May if (cell >= 0) { 734af74b616SDave May cells[p].rank = 0; 735af74b616SDave May cells[p].index = cell; 736af74b616SDave May numFound++; 737af74b616SDave May } 738af74b616SDave May } 7399cb35068SDave May if (cells[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 7409cb35068SDave May terminating_query_type[1]++; 7419cb35068SDave May continue; 7429cb35068SDave May } 743af74b616SDave May 744953fc75cSMatthew G. Knepley if (hash) { 745af74b616SDave May PetscBool found_box; 746af74b616SDave May 747af74b616SDave May /* allow for case that point is outside box - abort early */ 748af74b616SDave May ierr = PetscGridHashGetEnclosingBoxQuery(mesh->lbox, 1, point, dbin, &bin,&found_box);CHKERRQ(ierr); 749af74b616SDave May if (found_box) { 750cafe43deSMatthew G. Knepley /* TODO Lay an interface over this so we can switch between Section (dense) and Label (sparse) */ 751cafe43deSMatthew G. Knepley ierr = PetscSectionGetDof(mesh->lbox->cellSection, bin, &numCells);CHKERRQ(ierr); 752cafe43deSMatthew G. Knepley ierr = PetscSectionGetOffset(mesh->lbox->cellSection, bin, &cellOffset);CHKERRQ(ierr); 753cafe43deSMatthew G. Knepley for (c = cellOffset; c < cellOffset + numCells; ++c) { 754cafe43deSMatthew G. Knepley ierr = DMPlexLocatePoint_Internal(dm, dim, point, boxCells[c], &cell);CHKERRQ(ierr); 7553a93e3b7SToby Isaac if (cell >= 0) { 7563a93e3b7SToby Isaac cells[p].rank = 0; 7573a93e3b7SToby Isaac cells[p].index = cell; 7583a93e3b7SToby Isaac numFound++; 7599cb35068SDave May terminating_query_type[2]++; 7603a93e3b7SToby Isaac break; 761ccd2543fSMatthew G Knepley } 7623a93e3b7SToby Isaac } 763af74b616SDave May } 764953fc75cSMatthew G. Knepley } else { 765953fc75cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 766953fc75cSMatthew G. Knepley ierr = DMPlexLocatePoint_Internal(dm, dim, point, c, &cell);CHKERRQ(ierr); 7673a93e3b7SToby Isaac if (cell >= 0) { 7683a93e3b7SToby Isaac cells[p].rank = 0; 7693a93e3b7SToby Isaac cells[p].index = cell; 7703a93e3b7SToby Isaac numFound++; 7719cb35068SDave May terminating_query_type[2]++; 7723a93e3b7SToby Isaac break; 773953fc75cSMatthew G. Knepley } 774953fc75cSMatthew G. Knepley } 7753a93e3b7SToby Isaac } 776ccd2543fSMatthew G Knepley } 777953fc75cSMatthew G. Knepley if (hash) {ierr = ISRestoreIndices(mesh->lbox->cells, &boxCells);CHKERRQ(ierr);} 77862a38674SMatthew G. Knepley if (ltype == DM_POINTLOCATION_NEAREST && hash && numFound < numPoints) { 77962a38674SMatthew G. Knepley for (p = 0; p < numPoints; p++) { 78062a38674SMatthew G. Knepley const PetscScalar *point = &a[p*bs]; 78162a38674SMatthew G. Knepley PetscReal cpoint[3], diff[3], dist, distMax = PETSC_MAX_REAL; 782e56f9228SJed Brown PetscInt dbin[3] = {-1,-1,-1}, bin, cellOffset, d; 78362a38674SMatthew G. Knepley 784e9b685f5SMatthew G. Knepley if (cells[p].index < 0) { 78562a38674SMatthew G. Knepley ++numFound; 78662a38674SMatthew G. Knepley ierr = PetscGridHashGetEnclosingBox(mesh->lbox, 1, point, dbin, &bin);CHKERRQ(ierr); 78762a38674SMatthew G. Knepley ierr = PetscSectionGetDof(mesh->lbox->cellSection, bin, &numCells);CHKERRQ(ierr); 78862a38674SMatthew G. Knepley ierr = PetscSectionGetOffset(mesh->lbox->cellSection, bin, &cellOffset);CHKERRQ(ierr); 78962a38674SMatthew G. Knepley for (c = cellOffset; c < cellOffset + numCells; ++c) { 79062a38674SMatthew G. Knepley ierr = DMPlexClosestPoint_Internal(dm, dim, point, boxCells[c], cpoint);CHKERRQ(ierr); 791b716b415SMatthew G. Knepley for (d = 0; d < dim; ++d) diff[d] = cpoint[d] - PetscRealPart(point[d]); 79262a38674SMatthew G. Knepley dist = DMPlex_NormD_Internal(dim, diff); 79362a38674SMatthew G. Knepley if (dist < distMax) { 79462a38674SMatthew G. Knepley for (d = 0; d < dim; ++d) a[p*bs+d] = cpoint[d]; 79562a38674SMatthew G. Knepley cells[p].rank = 0; 79662a38674SMatthew G. Knepley cells[p].index = boxCells[c]; 79762a38674SMatthew G. Knepley distMax = dist; 79862a38674SMatthew G. Knepley break; 79962a38674SMatthew G. Knepley } 80062a38674SMatthew G. Knepley } 80162a38674SMatthew G. Knepley } 80262a38674SMatthew G. Knepley } 80362a38674SMatthew G. Knepley } 80462a38674SMatthew G. Knepley /* This code is only be relevant when interfaced to parallel point location */ 805cafe43deSMatthew G. Knepley /* Check for highest numbered proc that claims a point (do we care?) */ 8062d1fa6caSMatthew G. Knepley if (ltype == DM_POINTLOCATION_REMOVE && numFound < numPoints) { 8073a93e3b7SToby Isaac ierr = PetscMalloc1(numFound,&found);CHKERRQ(ierr); 8083a93e3b7SToby Isaac for (p = 0, numFound = 0; p < numPoints; p++) { 8093a93e3b7SToby Isaac if (cells[p].rank >= 0 && cells[p].index >= 0) { 8103a93e3b7SToby Isaac if (numFound < p) { 8113a93e3b7SToby Isaac cells[numFound] = cells[p]; 8123a93e3b7SToby Isaac } 8133a93e3b7SToby Isaac found[numFound++] = p; 8143a93e3b7SToby Isaac } 8153a93e3b7SToby Isaac } 8163a93e3b7SToby Isaac } 81762a38674SMatthew G. Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 818af74b616SDave May if (!reuse) { 8193a93e3b7SToby Isaac ierr = PetscSFSetGraph(cellSF, cEnd - cStart, numFound, found, PETSC_OWN_POINTER, cells, PETSC_OWN_POINTER);CHKERRQ(ierr); 820af74b616SDave May } 821af74b616SDave May ierr = PetscTime(&t1);CHKERRQ(ierr); 8229cb35068SDave May if (hash) { 823d6e0b8ebSSatish Balay ierr = PetscInfo3(dm,"[DMLocatePoints_Plex] terminating_query_type : %D [outside domain] : %D [inside intial cell] : %D [hash]\n",terminating_query_type[0],terminating_query_type[1],terminating_query_type[2]);CHKERRQ(ierr); 8249cb35068SDave May } else { 825d6e0b8ebSSatish Balay ierr = PetscInfo3(dm,"[DMLocatePoints_Plex] terminating_query_type : %D [outside domain] : %D [inside intial cell] : %D [brute-force]\n",terminating_query_type[0],terminating_query_type[1],terminating_query_type[2]);CHKERRQ(ierr); 8269cb35068SDave May } 827af74b616SDave May ierr = PetscInfo3(dm,"[DMLocatePoints_Plex] npoints %D : time(rank0) %1.2e (sec): points/sec %1.4e\n",numPoints,t1-t0,(double)((double)numPoints/(t1-t0)));CHKERRQ(ierr); 828ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 829ccd2543fSMatthew G Knepley } 830ccd2543fSMatthew G Knepley 831741bfc07SMatthew G. Knepley /*@C 832741bfc07SMatthew G. Knepley DMPlexComputeProjection2Dto1D - Rewrite coordinates to be the 1D projection of the 2D coordinates 833741bfc07SMatthew G. Knepley 834741bfc07SMatthew G. Knepley Not collective 835741bfc07SMatthew G. Knepley 836741bfc07SMatthew G. Knepley Input Parameter: 837741bfc07SMatthew G. Knepley . coords - The coordinates of a segment 838741bfc07SMatthew G. Knepley 839741bfc07SMatthew G. Knepley Output Parameters: 840741bfc07SMatthew G. Knepley + coords - The new y-coordinate, and 0 for x 841741bfc07SMatthew G. Knepley - R - The rotation which accomplishes the projection 842741bfc07SMatthew G. Knepley 843741bfc07SMatthew G. Knepley Level: developer 844741bfc07SMatthew G. Knepley 845741bfc07SMatthew G. Knepley .seealso: DMPlexComputeProjection3Dto1D(), DMPlexComputeProjection3Dto2D() 846741bfc07SMatthew G. Knepley @*/ 847741bfc07SMatthew G. Knepley PetscErrorCode DMPlexComputeProjection2Dto1D(PetscScalar coords[], PetscReal R[]) 84817fe8556SMatthew G. Knepley { 84917fe8556SMatthew G. Knepley const PetscReal x = PetscRealPart(coords[2] - coords[0]); 85017fe8556SMatthew G. Knepley const PetscReal y = PetscRealPart(coords[3] - coords[1]); 8518b49ba18SBarry Smith const PetscReal r = PetscSqrtReal(x*x + y*y), c = x/r, s = y/r; 85217fe8556SMatthew G. Knepley 85317fe8556SMatthew G. Knepley PetscFunctionBegin; 8541c99cf0cSGeoffrey Irving R[0] = c; R[1] = -s; 8551c99cf0cSGeoffrey Irving R[2] = s; R[3] = c; 85617fe8556SMatthew G. Knepley coords[0] = 0.0; 8577f07f362SMatthew G. Knepley coords[1] = r; 85817fe8556SMatthew G. Knepley PetscFunctionReturn(0); 85917fe8556SMatthew G. Knepley } 86017fe8556SMatthew G. Knepley 861741bfc07SMatthew G. Knepley /*@C 862741bfc07SMatthew G. Knepley DMPlexComputeProjection3Dto1D - Rewrite coordinates to be the 1D projection of the 3D coordinates 86328dbe442SToby Isaac 864741bfc07SMatthew G. Knepley Not collective 86528dbe442SToby Isaac 866741bfc07SMatthew G. Knepley Input Parameter: 867741bfc07SMatthew G. Knepley . coords - The coordinates of a segment 868741bfc07SMatthew G. Knepley 869741bfc07SMatthew G. Knepley Output Parameters: 870741bfc07SMatthew G. Knepley + coords - The new y-coordinate, and 0 for x and z 871741bfc07SMatthew G. Knepley - R - The rotation which accomplishes the projection 872741bfc07SMatthew G. Knepley 873741bfc07SMatthew G. Knepley Note: This uses the basis completion described by Frisvad in http://www.imm.dtu.dk/~jerf/papers/abstracts/onb.html, DOI:10.1080/2165347X.2012.689606 874741bfc07SMatthew G. Knepley 875741bfc07SMatthew G. Knepley Level: developer 876741bfc07SMatthew G. Knepley 877741bfc07SMatthew G. Knepley .seealso: DMPlexComputeProjection2Dto1D(), DMPlexComputeProjection3Dto2D() 878741bfc07SMatthew G. Knepley @*/ 879741bfc07SMatthew G. Knepley PetscErrorCode DMPlexComputeProjection3Dto1D(PetscScalar coords[], PetscReal R[]) 88028dbe442SToby Isaac { 88128dbe442SToby Isaac PetscReal x = PetscRealPart(coords[3] - coords[0]); 88228dbe442SToby Isaac PetscReal y = PetscRealPart(coords[4] - coords[1]); 88328dbe442SToby Isaac PetscReal z = PetscRealPart(coords[5] - coords[2]); 88428dbe442SToby Isaac PetscReal r = PetscSqrtReal(x*x + y*y + z*z); 88528dbe442SToby Isaac PetscReal rinv = 1. / r; 88628dbe442SToby Isaac PetscFunctionBegin; 88728dbe442SToby Isaac 88828dbe442SToby Isaac x *= rinv; y *= rinv; z *= rinv; 88928dbe442SToby Isaac if (x > 0.) { 89028dbe442SToby Isaac PetscReal inv1pX = 1./ (1. + x); 89128dbe442SToby Isaac 89228dbe442SToby Isaac R[0] = x; R[1] = -y; R[2] = -z; 89328dbe442SToby Isaac R[3] = y; R[4] = 1. - y*y*inv1pX; R[5] = -y*z*inv1pX; 89428dbe442SToby Isaac R[6] = z; R[7] = -y*z*inv1pX; R[8] = 1. - z*z*inv1pX; 89528dbe442SToby Isaac } 89628dbe442SToby Isaac else { 89728dbe442SToby Isaac PetscReal inv1mX = 1./ (1. - x); 89828dbe442SToby Isaac 89928dbe442SToby Isaac R[0] = x; R[1] = z; R[2] = y; 90028dbe442SToby Isaac R[3] = y; R[4] = -y*z*inv1mX; R[5] = 1. - y*y*inv1mX; 90128dbe442SToby Isaac R[6] = z; R[7] = 1. - z*z*inv1mX; R[8] = -y*z*inv1mX; 90228dbe442SToby Isaac } 90328dbe442SToby Isaac coords[0] = 0.0; 90428dbe442SToby Isaac coords[1] = r; 90528dbe442SToby Isaac PetscFunctionReturn(0); 90628dbe442SToby Isaac } 90728dbe442SToby Isaac 908741bfc07SMatthew G. Knepley /*@ 909741bfc07SMatthew G. Knepley DMPlexComputeProjection3Dto2D - Rewrite coordinates to be the 2D projection of the 3D coordinates 910741bfc07SMatthew G. Knepley 911741bfc07SMatthew G. Knepley Not collective 912741bfc07SMatthew G. Knepley 913741bfc07SMatthew G. Knepley Input Parameter: 914741bfc07SMatthew G. Knepley . coords - The coordinates of a segment 915741bfc07SMatthew G. Knepley 916741bfc07SMatthew G. Knepley Output Parameters: 917741bfc07SMatthew G. Knepley + coords - The new y- and z-coordinates, and 0 for x 918741bfc07SMatthew G. Knepley - R - The rotation which accomplishes the projection 919741bfc07SMatthew G. Knepley 920741bfc07SMatthew G. Knepley Level: developer 921741bfc07SMatthew G. Knepley 922741bfc07SMatthew G. Knepley .seealso: DMPlexComputeProjection2Dto1D(), DMPlexComputeProjection3Dto1D() 923741bfc07SMatthew G. Knepley @*/ 924741bfc07SMatthew G. Knepley PetscErrorCode DMPlexComputeProjection3Dto2D(PetscInt coordSize, PetscScalar coords[], PetscReal R[]) 925ccd2543fSMatthew G Knepley { 9261ee9d5ecSMatthew G. Knepley PetscReal x1[3], x2[3], n[3], norm; 92799dec3a6SMatthew G. Knepley PetscReal x1p[3], x2p[3], xnp[3]; 9284a217a95SMatthew G. Knepley PetscReal sqrtz, alpha; 929ccd2543fSMatthew G Knepley const PetscInt dim = 3; 93099dec3a6SMatthew G. Knepley PetscInt d, e, p; 931ccd2543fSMatthew G Knepley 932ccd2543fSMatthew G Knepley PetscFunctionBegin; 933ccd2543fSMatthew G Knepley /* 0) Calculate normal vector */ 934ccd2543fSMatthew G Knepley for (d = 0; d < dim; ++d) { 9351ee9d5ecSMatthew G. Knepley x1[d] = PetscRealPart(coords[1*dim+d] - coords[0*dim+d]); 9361ee9d5ecSMatthew G. Knepley x2[d] = PetscRealPart(coords[2*dim+d] - coords[0*dim+d]); 937ccd2543fSMatthew G Knepley } 938ccd2543fSMatthew G Knepley n[0] = x1[1]*x2[2] - x1[2]*x2[1]; 939ccd2543fSMatthew G Knepley n[1] = x1[2]*x2[0] - x1[0]*x2[2]; 940ccd2543fSMatthew G Knepley n[2] = x1[0]*x2[1] - x1[1]*x2[0]; 9418b49ba18SBarry Smith norm = PetscSqrtReal(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]); 942ccd2543fSMatthew G Knepley n[0] /= norm; 943ccd2543fSMatthew G Knepley n[1] /= norm; 944ccd2543fSMatthew G Knepley n[2] /= norm; 945ccd2543fSMatthew G Knepley /* 1) Take the normal vector and rotate until it is \hat z 946ccd2543fSMatthew G Knepley 947ccd2543fSMatthew G Knepley Let the normal vector be <nx, ny, nz> and alpha = 1/sqrt(1 - nz^2), then 948ccd2543fSMatthew G Knepley 949ccd2543fSMatthew G Knepley R = / alpha nx nz alpha ny nz -1/alpha \ 950ccd2543fSMatthew G Knepley | -alpha ny alpha nx 0 | 951ccd2543fSMatthew G Knepley \ nx ny nz / 952ccd2543fSMatthew G Knepley 953ccd2543fSMatthew G Knepley will rotate the normal vector to \hat z 954ccd2543fSMatthew G Knepley */ 9558b49ba18SBarry Smith sqrtz = PetscSqrtReal(1.0 - n[2]*n[2]); 95673868372SMatthew G. Knepley /* Check for n = z */ 95773868372SMatthew G. Knepley if (sqrtz < 1.0e-10) { 9587df32b8bSSanderA const PetscInt s = PetscSign(n[2]); 9597df32b8bSSanderA /* If nz < 0, rotate 180 degrees around x-axis */ 96099dec3a6SMatthew G. Knepley for (p = 3; p < coordSize/3; ++p) { 96199dec3a6SMatthew G. Knepley coords[p*2+0] = PetscRealPart(coords[p*dim+0] - coords[0*dim+0]); 9627df32b8bSSanderA coords[p*2+1] = (PetscRealPart(coords[p*dim+1] - coords[0*dim+1])) * s; 96373868372SMatthew G. Knepley } 96499dec3a6SMatthew G. Knepley coords[0] = 0.0; 96599dec3a6SMatthew G. Knepley coords[1] = 0.0; 9667df32b8bSSanderA coords[2] = x1[0]; 9677df32b8bSSanderA coords[3] = x1[1] * s; 9687df32b8bSSanderA coords[4] = x2[0]; 9697df32b8bSSanderA coords[5] = x2[1] * s; 9707df32b8bSSanderA R[0] = 1.0; R[1] = 0.0; R[2] = 0.0; 9717df32b8bSSanderA R[3] = 0.0; R[4] = 1.0 * s; R[5] = 0.0; 9727df32b8bSSanderA R[6] = 0.0; R[7] = 0.0; R[8] = 1.0 * s; 97373868372SMatthew G. Knepley PetscFunctionReturn(0); 97473868372SMatthew G. Knepley } 975da18b5e6SMatthew G Knepley alpha = 1.0/sqrtz; 976ccd2543fSMatthew G Knepley R[0] = alpha*n[0]*n[2]; R[1] = alpha*n[1]*n[2]; R[2] = -sqrtz; 977ccd2543fSMatthew G Knepley R[3] = -alpha*n[1]; R[4] = alpha*n[0]; R[5] = 0.0; 978ccd2543fSMatthew G Knepley R[6] = n[0]; R[7] = n[1]; R[8] = n[2]; 979ccd2543fSMatthew G Knepley for (d = 0; d < dim; ++d) { 980ccd2543fSMatthew G Knepley x1p[d] = 0.0; 981ccd2543fSMatthew G Knepley x2p[d] = 0.0; 982ccd2543fSMatthew G Knepley for (e = 0; e < dim; ++e) { 983ccd2543fSMatthew G Knepley x1p[d] += R[d*dim+e]*x1[e]; 984ccd2543fSMatthew G Knepley x2p[d] += R[d*dim+e]*x2[e]; 985ccd2543fSMatthew G Knepley } 986ccd2543fSMatthew G Knepley } 98748120919SToby Isaac if (PetscAbsReal(x1p[2]) > 10. * PETSC_SMALL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid rotation calculated"); 98848120919SToby Isaac if (PetscAbsReal(x2p[2]) > 10. * PETSC_SMALL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid rotation calculated"); 989ccd2543fSMatthew G Knepley /* 2) Project to (x, y) */ 99099dec3a6SMatthew G. Knepley for (p = 3; p < coordSize/3; ++p) { 99199dec3a6SMatthew G. Knepley for (d = 0; d < dim; ++d) { 99299dec3a6SMatthew G. Knepley xnp[d] = 0.0; 99399dec3a6SMatthew G. Knepley for (e = 0; e < dim; ++e) { 99499dec3a6SMatthew G. Knepley xnp[d] += R[d*dim+e]*PetscRealPart(coords[p*dim+e] - coords[0*dim+e]); 99599dec3a6SMatthew G. Knepley } 99699dec3a6SMatthew G. Knepley if (d < dim-1) coords[p*2+d] = xnp[d]; 99799dec3a6SMatthew G. Knepley } 99899dec3a6SMatthew G. Knepley } 999ccd2543fSMatthew G Knepley coords[0] = 0.0; 1000ccd2543fSMatthew G Knepley coords[1] = 0.0; 1001ccd2543fSMatthew G Knepley coords[2] = x1p[0]; 1002ccd2543fSMatthew G Knepley coords[3] = x1p[1]; 1003ccd2543fSMatthew G Knepley coords[4] = x2p[0]; 1004ccd2543fSMatthew G Knepley coords[5] = x2p[1]; 10057f07f362SMatthew G. Knepley /* Output R^T which rotates \hat z to the input normal */ 10067f07f362SMatthew G. Knepley for (d = 0; d < dim; ++d) { 10077f07f362SMatthew G. Knepley for (e = d+1; e < dim; ++e) { 10087f07f362SMatthew G. Knepley PetscReal tmp; 10097f07f362SMatthew G. Knepley 10107f07f362SMatthew G. Knepley tmp = R[d*dim+e]; 10117f07f362SMatthew G. Knepley R[d*dim+e] = R[e*dim+d]; 10127f07f362SMatthew G. Knepley R[e*dim+d] = tmp; 10137f07f362SMatthew G. Knepley } 10147f07f362SMatthew G. Knepley } 1015ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 1016ccd2543fSMatthew G Knepley } 1017ccd2543fSMatthew G Knepley 10186322fe33SJed Brown PETSC_UNUSED 1019834e62ceSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Triangle_Internal(PetscReal *vol, PetscReal coords[]) 1020834e62ceSMatthew G. Knepley { 1021834e62ceSMatthew G. Knepley /* Signed volume is 1/2 the determinant 1022834e62ceSMatthew G. Knepley 1023834e62ceSMatthew G. Knepley | 1 1 1 | 1024834e62ceSMatthew G. Knepley | x0 x1 x2 | 1025834e62ceSMatthew G. Knepley | y0 y1 y2 | 1026834e62ceSMatthew G. Knepley 1027834e62ceSMatthew G. Knepley but if x0,y0 is the origin, we have 1028834e62ceSMatthew G. Knepley 1029834e62ceSMatthew G. Knepley | x1 x2 | 1030834e62ceSMatthew G. Knepley | y1 y2 | 1031834e62ceSMatthew G. Knepley */ 1032834e62ceSMatthew G. Knepley const PetscReal x1 = coords[2] - coords[0], y1 = coords[3] - coords[1]; 1033834e62ceSMatthew G. Knepley const PetscReal x2 = coords[4] - coords[0], y2 = coords[5] - coords[1]; 1034834e62ceSMatthew G. Knepley PetscReal M[4], detM; 1035834e62ceSMatthew G. Knepley M[0] = x1; M[1] = x2; 103686623015SMatthew G. Knepley M[2] = y1; M[3] = y2; 1037923591dfSMatthew G. Knepley DMPlex_Det2D_Internal(&detM, M); 1038834e62ceSMatthew G. Knepley *vol = 0.5*detM; 10393bc0b13bSBarry Smith (void)PetscLogFlops(5.0); 1040834e62ceSMatthew G. Knepley } 1041834e62ceSMatthew G. Knepley 1042834e62ceSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Triangle_Origin_Internal(PetscReal *vol, PetscReal coords[]) 1043834e62ceSMatthew G. Knepley { 1044923591dfSMatthew G. Knepley DMPlex_Det2D_Internal(vol, coords); 1045834e62ceSMatthew G. Knepley *vol *= 0.5; 1046834e62ceSMatthew G. Knepley } 1047834e62ceSMatthew G. Knepley 10486322fe33SJed Brown PETSC_UNUSED 1049834e62ceSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Tetrahedron_Internal(PetscReal *vol, PetscReal coords[]) 1050834e62ceSMatthew G. Knepley { 1051834e62ceSMatthew G. Knepley /* Signed volume is 1/6th of the determinant 1052834e62ceSMatthew G. Knepley 1053834e62ceSMatthew G. Knepley | 1 1 1 1 | 1054834e62ceSMatthew G. Knepley | x0 x1 x2 x3 | 1055834e62ceSMatthew G. Knepley | y0 y1 y2 y3 | 1056834e62ceSMatthew G. Knepley | z0 z1 z2 z3 | 1057834e62ceSMatthew G. Knepley 1058834e62ceSMatthew G. Knepley but if x0,y0,z0 is the origin, we have 1059834e62ceSMatthew G. Knepley 1060834e62ceSMatthew G. Knepley | x1 x2 x3 | 1061834e62ceSMatthew G. Knepley | y1 y2 y3 | 1062834e62ceSMatthew G. Knepley | z1 z2 z3 | 1063834e62ceSMatthew G. Knepley */ 1064834e62ceSMatthew G. Knepley const PetscReal x1 = coords[3] - coords[0], y1 = coords[4] - coords[1], z1 = coords[5] - coords[2]; 1065834e62ceSMatthew G. Knepley const PetscReal x2 = coords[6] - coords[0], y2 = coords[7] - coords[1], z2 = coords[8] - coords[2]; 1066834e62ceSMatthew G. Knepley const PetscReal x3 = coords[9] - coords[0], y3 = coords[10] - coords[1], z3 = coords[11] - coords[2]; 10670a3da2c2SToby Isaac const PetscReal onesixth = ((PetscReal)1./(PetscReal)6.); 1068834e62ceSMatthew G. Knepley PetscReal M[9], detM; 1069834e62ceSMatthew G. Knepley M[0] = x1; M[1] = x2; M[2] = x3; 1070834e62ceSMatthew G. Knepley M[3] = y1; M[4] = y2; M[5] = y3; 1071834e62ceSMatthew G. Knepley M[6] = z1; M[7] = z2; M[8] = z3; 1072923591dfSMatthew G. Knepley DMPlex_Det3D_Internal(&detM, M); 10730a3da2c2SToby Isaac *vol = -onesixth*detM; 10743bc0b13bSBarry Smith (void)PetscLogFlops(10.0); 1075834e62ceSMatthew G. Knepley } 1076834e62ceSMatthew G. Knepley 10770ec8681fSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Tetrahedron_Origin_Internal(PetscReal *vol, PetscReal coords[]) 10780ec8681fSMatthew G. Knepley { 10790a3da2c2SToby Isaac const PetscReal onesixth = ((PetscReal)1./(PetscReal)6.); 1080923591dfSMatthew G. Knepley DMPlex_Det3D_Internal(vol, coords); 10810a3da2c2SToby Isaac *vol *= -onesixth; 10820ec8681fSMatthew G. Knepley } 10830ec8681fSMatthew G. Knepley 1084cb92db44SToby Isaac static PetscErrorCode DMPlexComputePointGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 1085cb92db44SToby Isaac { 1086cb92db44SToby Isaac PetscSection coordSection; 1087cb92db44SToby Isaac Vec coordinates; 1088cb92db44SToby Isaac const PetscScalar *coords; 1089cb92db44SToby Isaac PetscInt dim, d, off; 1090cb92db44SToby Isaac PetscErrorCode ierr; 1091cb92db44SToby Isaac 1092cb92db44SToby Isaac PetscFunctionBegin; 1093cb92db44SToby Isaac ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1094cb92db44SToby Isaac ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 1095cb92db44SToby Isaac ierr = PetscSectionGetDof(coordSection,e,&dim);CHKERRQ(ierr); 1096cb92db44SToby Isaac if (!dim) PetscFunctionReturn(0); 1097cb92db44SToby Isaac ierr = PetscSectionGetOffset(coordSection,e,&off);CHKERRQ(ierr); 1098cb92db44SToby Isaac ierr = VecGetArrayRead(coordinates,&coords);CHKERRQ(ierr); 1099cb92db44SToby Isaac if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[off + d]);} 1100cb92db44SToby Isaac ierr = VecRestoreArrayRead(coordinates,&coords);CHKERRQ(ierr); 1101cb92db44SToby Isaac *detJ = 1.; 1102cb92db44SToby Isaac if (J) { 1103cb92db44SToby Isaac for (d = 0; d < dim * dim; d++) J[d] = 0.; 1104cb92db44SToby Isaac for (d = 0; d < dim; d++) J[d * dim + d] = 1.; 1105cb92db44SToby Isaac if (invJ) { 1106cb92db44SToby Isaac for (d = 0; d < dim * dim; d++) invJ[d] = 0.; 1107cb92db44SToby Isaac for (d = 0; d < dim; d++) invJ[d * dim + d] = 1.; 1108cb92db44SToby Isaac } 1109cb92db44SToby Isaac } 1110cb92db44SToby Isaac PetscFunctionReturn(0); 1111cb92db44SToby Isaac } 1112cb92db44SToby Isaac 111317fe8556SMatthew G. Knepley static PetscErrorCode DMPlexComputeLineGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 111417fe8556SMatthew G. Knepley { 111517fe8556SMatthew G. Knepley PetscSection coordSection; 111617fe8556SMatthew G. Knepley Vec coordinates; 1117a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 11188bf5c034SToby Isaac PetscInt numCoords, d, pStart, pEnd, numSelfCoords = 0; 111917fe8556SMatthew G. Knepley PetscErrorCode ierr; 112017fe8556SMatthew G. Knepley 112117fe8556SMatthew G. Knepley PetscFunctionBegin; 112217fe8556SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 112369d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 11248bf5c034SToby Isaac ierr = PetscSectionGetChart(coordSection,&pStart,&pEnd);CHKERRQ(ierr); 11258bf5c034SToby Isaac if (e >= pStart && e < pEnd) {ierr = PetscSectionGetDof(coordSection,e,&numSelfCoords);CHKERRQ(ierr);} 112617fe8556SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 11278bf5c034SToby Isaac numCoords = numSelfCoords ? numSelfCoords : numCoords; 1128adac9986SMatthew G. Knepley if (invJ && !J) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "In order to compute invJ, J must not be NULL"); 11297f07f362SMatthew G. Knepley *detJ = 0.0; 113028dbe442SToby Isaac if (numCoords == 6) { 113128dbe442SToby Isaac const PetscInt dim = 3; 113228dbe442SToby Isaac PetscReal R[9], J0; 113328dbe442SToby Isaac 113428dbe442SToby Isaac if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 1135741bfc07SMatthew G. Knepley ierr = DMPlexComputeProjection3Dto1D(coords, R);CHKERRQ(ierr); 113628dbe442SToby Isaac if (J) { 113728dbe442SToby Isaac J0 = 0.5*PetscRealPart(coords[1]); 113828dbe442SToby Isaac J[0] = R[0]*J0; J[1] = R[1]; J[2] = R[2]; 113928dbe442SToby Isaac J[3] = R[3]*J0; J[4] = R[4]; J[5] = R[5]; 114028dbe442SToby Isaac J[6] = R[6]*J0; J[7] = R[7]; J[8] = R[8]; 114128dbe442SToby Isaac DMPlex_Det3D_Internal(detJ, J); 114228dbe442SToby Isaac if (invJ) {DMPlex_Invert2D_Internal(invJ, J, *detJ);} 1143adac9986SMatthew G. Knepley } 114428dbe442SToby Isaac } else if (numCoords == 4) { 11457f07f362SMatthew G. Knepley const PetscInt dim = 2; 11467f07f362SMatthew G. Knepley PetscReal R[4], J0; 11477f07f362SMatthew G. Knepley 11487f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 1149741bfc07SMatthew G. Knepley ierr = DMPlexComputeProjection2Dto1D(coords, R);CHKERRQ(ierr); 115017fe8556SMatthew G. Knepley if (J) { 11517f07f362SMatthew G. Knepley J0 = 0.5*PetscRealPart(coords[1]); 11527f07f362SMatthew G. Knepley J[0] = R[0]*J0; J[1] = R[1]; 11537f07f362SMatthew G. Knepley J[2] = R[2]*J0; J[3] = R[3]; 1154923591dfSMatthew G. Knepley DMPlex_Det2D_Internal(detJ, J); 1155923591dfSMatthew G. Knepley if (invJ) {DMPlex_Invert2D_Internal(invJ, J, *detJ);} 1156adac9986SMatthew G. Knepley } 11577f07f362SMatthew G. Knepley } else if (numCoords == 2) { 11587f07f362SMatthew G. Knepley const PetscInt dim = 1; 11597f07f362SMatthew G. Knepley 11607f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 11617f07f362SMatthew G. Knepley if (J) { 11627f07f362SMatthew G. Knepley J[0] = 0.5*(PetscRealPart(coords[1]) - PetscRealPart(coords[0])); 116317fe8556SMatthew G. Knepley *detJ = J[0]; 11643bc0b13bSBarry Smith ierr = PetscLogFlops(2.0);CHKERRQ(ierr); 11653bc0b13bSBarry Smith if (invJ) {invJ[0] = 1.0/J[0]; ierr = PetscLogFlops(1.0);CHKERRQ(ierr);} 1166adac9986SMatthew G. Knepley } 1167796f034aSJed Brown } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of coordinates for this segment is %D != 2", numCoords); 116817fe8556SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 116917fe8556SMatthew G. Knepley PetscFunctionReturn(0); 117017fe8556SMatthew G. Knepley } 117117fe8556SMatthew G. Knepley 1172ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexComputeTriangleGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 1173ccd2543fSMatthew G Knepley { 1174ccd2543fSMatthew G Knepley PetscSection coordSection; 1175ccd2543fSMatthew G Knepley Vec coordinates; 1176a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 117703d7ed2eSStefano Zampini PetscInt numCoords, numSelfCoords = 0, d, f, g, pStart, pEnd; 1178ccd2543fSMatthew G Knepley PetscErrorCode ierr; 1179ccd2543fSMatthew G Knepley 1180ccd2543fSMatthew G Knepley PetscFunctionBegin; 1181ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 118269d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 118303d7ed2eSStefano Zampini ierr = PetscSectionGetChart(coordSection,&pStart,&pEnd);CHKERRQ(ierr); 118403d7ed2eSStefano Zampini if (e >= pStart && e < pEnd) {ierr = PetscSectionGetDof(coordSection,e,&numSelfCoords);CHKERRQ(ierr);} 1185ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 118603d7ed2eSStefano Zampini numCoords = numSelfCoords ? numSelfCoords : numCoords; 11877f07f362SMatthew G. Knepley *detJ = 0.0; 1188ccd2543fSMatthew G Knepley if (numCoords == 9) { 11897f07f362SMatthew G. Knepley const PetscInt dim = 3; 11907f07f362SMatthew G. Knepley PetscReal R[9], J0[9] = {1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0}; 11917f07f362SMatthew G. Knepley 11927f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 1193741bfc07SMatthew G. Knepley ierr = DMPlexComputeProjection3Dto2D(numCoords, coords, R);CHKERRQ(ierr); 11947f07f362SMatthew G. Knepley if (J) { 1195b7ad821dSMatthew G. Knepley const PetscInt pdim = 2; 1196b7ad821dSMatthew G. Knepley 1197b7ad821dSMatthew G. Knepley for (d = 0; d < pdim; d++) { 1198b7ad821dSMatthew G. Knepley for (f = 0; f < pdim; f++) { 1199b7ad821dSMatthew G. Knepley J0[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*pdim+d]) - PetscRealPart(coords[0*pdim+d])); 1200ccd2543fSMatthew G Knepley } 12017f07f362SMatthew G. Knepley } 12023bc0b13bSBarry Smith ierr = PetscLogFlops(8.0);CHKERRQ(ierr); 1203923591dfSMatthew G. Knepley DMPlex_Det3D_Internal(detJ, J0); 12047f07f362SMatthew G. Knepley for (d = 0; d < dim; d++) { 12057f07f362SMatthew G. Knepley for (f = 0; f < dim; f++) { 12067f07f362SMatthew G. Knepley J[d*dim+f] = 0.0; 12077f07f362SMatthew G. Knepley for (g = 0; g < dim; g++) { 12087f07f362SMatthew G. Knepley J[d*dim+f] += R[d*dim+g]*J0[g*dim+f]; 12097f07f362SMatthew G. Knepley } 12107f07f362SMatthew G. Knepley } 12117f07f362SMatthew G. Knepley } 12123bc0b13bSBarry Smith ierr = PetscLogFlops(18.0);CHKERRQ(ierr); 12137f07f362SMatthew G. Knepley } 1214923591dfSMatthew G. Knepley if (invJ) {DMPlex_Invert3D_Internal(invJ, J, *detJ);} 12157f07f362SMatthew G. Knepley } else if (numCoords == 6) { 12167f07f362SMatthew G. Knepley const PetscInt dim = 2; 12177f07f362SMatthew G. Knepley 12187f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 1219ccd2543fSMatthew G Knepley if (J) { 1220ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 1221ccd2543fSMatthew G Knepley for (f = 0; f < dim; f++) { 1222ccd2543fSMatthew G Knepley J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 1223ccd2543fSMatthew G Knepley } 1224ccd2543fSMatthew G Knepley } 12253bc0b13bSBarry Smith ierr = PetscLogFlops(8.0);CHKERRQ(ierr); 1226923591dfSMatthew G. Knepley DMPlex_Det2D_Internal(detJ, J); 1227ccd2543fSMatthew G Knepley } 1228923591dfSMatthew G. Knepley if (invJ) {DMPlex_Invert2D_Internal(invJ, J, *detJ);} 1229796f034aSJed Brown } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of coordinates for this triangle is %D != 6 or 9", numCoords); 1230ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 1231ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 1232ccd2543fSMatthew G Knepley } 1233ccd2543fSMatthew G Knepley 1234dfccc68fSToby Isaac static PetscErrorCode DMPlexComputeRectangleGeometry_Internal(DM dm, PetscInt e, PetscInt Nq, const PetscReal points[], PetscReal v[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 1235ccd2543fSMatthew G Knepley { 1236ccd2543fSMatthew G Knepley PetscSection coordSection; 1237ccd2543fSMatthew G Knepley Vec coordinates; 1238a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 12390d29256aSToby Isaac PetscInt numCoords, numSelfCoords = 0, d, f, g, pStart, pEnd; 1240ccd2543fSMatthew G Knepley PetscErrorCode ierr; 1241ccd2543fSMatthew G Knepley 1242ccd2543fSMatthew G Knepley PetscFunctionBegin; 1243ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 124469d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 12450d29256aSToby Isaac ierr = PetscSectionGetChart(coordSection,&pStart,&pEnd);CHKERRQ(ierr); 12460d29256aSToby Isaac if (e >= pStart && e < pEnd) {ierr = PetscSectionGetDof(coordSection,e,&numSelfCoords);CHKERRQ(ierr);} 124799dec3a6SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 124871f58de1SToby Isaac numCoords = numSelfCoords ? numSelfCoords : numCoords; 1249dfccc68fSToby Isaac if (!Nq) { 12507f07f362SMatthew G. Knepley *detJ = 0.0; 125199dec3a6SMatthew G. Knepley if (numCoords == 12) { 125299dec3a6SMatthew G. Knepley const PetscInt dim = 3; 125399dec3a6SMatthew G. Knepley PetscReal R[9], J0[9] = {1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0}; 125499dec3a6SMatthew G. Knepley 1255dfccc68fSToby Isaac if (v) {for (d = 0; d < dim; d++) v[d] = PetscRealPart(coords[d]);} 1256741bfc07SMatthew G. Knepley ierr = DMPlexComputeProjection3Dto2D(numCoords, coords, R);CHKERRQ(ierr); 125799dec3a6SMatthew G. Knepley if (J) { 125899dec3a6SMatthew G. Knepley const PetscInt pdim = 2; 125999dec3a6SMatthew G. Knepley 126099dec3a6SMatthew G. Knepley for (d = 0; d < pdim; d++) { 126199dec3a6SMatthew G. Knepley J0[d*dim+0] = 0.5*(PetscRealPart(coords[1*pdim+d]) - PetscRealPart(coords[0*pdim+d])); 12620892ce5fSStefano Zampini J0[d*dim+1] = 0.5*(PetscRealPart(coords[2*pdim+d]) - PetscRealPart(coords[1*pdim+d])); 126399dec3a6SMatthew G. Knepley } 12643bc0b13bSBarry Smith ierr = PetscLogFlops(8.0);CHKERRQ(ierr); 1265923591dfSMatthew G. Knepley DMPlex_Det3D_Internal(detJ, J0); 126699dec3a6SMatthew G. Knepley for (d = 0; d < dim; d++) { 126799dec3a6SMatthew G. Knepley for (f = 0; f < dim; f++) { 126899dec3a6SMatthew G. Knepley J[d*dim+f] = 0.0; 126999dec3a6SMatthew G. Knepley for (g = 0; g < dim; g++) { 127099dec3a6SMatthew G. Knepley J[d*dim+f] += R[d*dim+g]*J0[g*dim+f]; 127199dec3a6SMatthew G. Knepley } 127299dec3a6SMatthew G. Knepley } 127399dec3a6SMatthew G. Knepley } 12743bc0b13bSBarry Smith ierr = PetscLogFlops(18.0);CHKERRQ(ierr); 127599dec3a6SMatthew G. Knepley } 1276923591dfSMatthew G. Knepley if (invJ) {DMPlex_Invert3D_Internal(invJ, J, *detJ);} 127771f58de1SToby Isaac } else if (numCoords == 8) { 127899dec3a6SMatthew G. Knepley const PetscInt dim = 2; 127999dec3a6SMatthew G. Knepley 1280dfccc68fSToby Isaac if (v) {for (d = 0; d < dim; d++) v[d] = PetscRealPart(coords[d]);} 1281ccd2543fSMatthew G Knepley if (J) { 1282ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 128399dec3a6SMatthew G. Knepley J[d*dim+0] = 0.5*(PetscRealPart(coords[1*dim+d]) - PetscRealPart(coords[0*dim+d])); 128499dec3a6SMatthew G. Knepley J[d*dim+1] = 0.5*(PetscRealPart(coords[3*dim+d]) - PetscRealPart(coords[0*dim+d])); 1285ccd2543fSMatthew G Knepley } 12863bc0b13bSBarry Smith ierr = PetscLogFlops(8.0);CHKERRQ(ierr); 1287923591dfSMatthew G. Knepley DMPlex_Det2D_Internal(detJ, J); 1288ccd2543fSMatthew G Knepley } 1289923591dfSMatthew G. Knepley if (invJ) {DMPlex_Invert2D_Internal(invJ, J, *detJ);} 1290796f034aSJed Brown } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of coordinates for this quadrilateral is %D != 8 or 12", numCoords); 1291dfccc68fSToby Isaac } else { 1292dfccc68fSToby Isaac const PetscInt Nv = 4; 1293dfccc68fSToby Isaac const PetscInt dimR = 2; 1294dfccc68fSToby Isaac const PetscInt zToPlex[4] = {0, 1, 3, 2}; 1295dfccc68fSToby Isaac PetscReal zOrder[12]; 1296dfccc68fSToby Isaac PetscReal zCoeff[12]; 1297dfccc68fSToby Isaac PetscInt i, j, k, l, dim; 1298dfccc68fSToby Isaac 1299dfccc68fSToby Isaac if (numCoords == 12) { 1300dfccc68fSToby Isaac dim = 3; 1301dfccc68fSToby Isaac } else if (numCoords == 8) { 1302dfccc68fSToby Isaac dim = 2; 1303dfccc68fSToby Isaac } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of coordinates for this quadrilateral is %D != 8 or 12", numCoords); 1304dfccc68fSToby Isaac for (i = 0; i < Nv; i++) { 1305dfccc68fSToby Isaac PetscInt zi = zToPlex[i]; 1306dfccc68fSToby Isaac 1307dfccc68fSToby Isaac for (j = 0; j < dim; j++) { 1308dfccc68fSToby Isaac zOrder[dim * i + j] = PetscRealPart(coords[dim * zi + j]); 1309dfccc68fSToby Isaac } 1310dfccc68fSToby Isaac } 1311dfccc68fSToby Isaac for (j = 0; j < dim; j++) { 1312dfccc68fSToby Isaac zCoeff[dim * 0 + j] = 0.25 * ( zOrder[dim * 0 + j] + zOrder[dim * 1 + j] + zOrder[dim * 2 + j] + zOrder[dim * 3 + j]); 1313dfccc68fSToby Isaac zCoeff[dim * 1 + j] = 0.25 * (- zOrder[dim * 0 + j] + zOrder[dim * 1 + j] - zOrder[dim * 2 + j] + zOrder[dim * 3 + j]); 1314dfccc68fSToby Isaac zCoeff[dim * 2 + j] = 0.25 * (- zOrder[dim * 0 + j] - zOrder[dim * 1 + j] + zOrder[dim * 2 + j] + zOrder[dim * 3 + j]); 1315dfccc68fSToby Isaac zCoeff[dim * 3 + j] = 0.25 * ( zOrder[dim * 0 + j] - zOrder[dim * 1 + j] - zOrder[dim * 2 + j] + zOrder[dim * 3 + j]); 1316dfccc68fSToby Isaac } 1317dfccc68fSToby Isaac for (i = 0; i < Nq; i++) { 1318dfccc68fSToby Isaac PetscReal xi = points[dimR * i], eta = points[dimR * i + 1]; 1319dfccc68fSToby Isaac 1320dfccc68fSToby Isaac if (v) { 1321dfccc68fSToby Isaac PetscReal extPoint[4]; 1322dfccc68fSToby Isaac 1323dfccc68fSToby Isaac extPoint[0] = 1.; 1324dfccc68fSToby Isaac extPoint[1] = xi; 1325dfccc68fSToby Isaac extPoint[2] = eta; 1326dfccc68fSToby Isaac extPoint[3] = xi * eta; 1327dfccc68fSToby Isaac for (j = 0; j < dim; j++) { 1328dfccc68fSToby Isaac PetscReal val = 0.; 1329dfccc68fSToby Isaac 1330dfccc68fSToby Isaac for (k = 0; k < Nv; k++) { 1331dfccc68fSToby Isaac val += extPoint[k] * zCoeff[dim * k + j]; 1332dfccc68fSToby Isaac } 1333dfccc68fSToby Isaac v[i * dim + j] = val; 1334dfccc68fSToby Isaac } 1335dfccc68fSToby Isaac } 1336dfccc68fSToby Isaac if (J) { 1337dfccc68fSToby Isaac PetscReal extJ[8]; 1338dfccc68fSToby Isaac 1339dfccc68fSToby Isaac extJ[0] = 0.; 1340dfccc68fSToby Isaac extJ[1] = 0.; 1341dfccc68fSToby Isaac extJ[2] = 1.; 1342dfccc68fSToby Isaac extJ[3] = 0.; 1343dfccc68fSToby Isaac extJ[4] = 0.; 1344dfccc68fSToby Isaac extJ[5] = 1.; 1345dfccc68fSToby Isaac extJ[6] = eta; 1346dfccc68fSToby Isaac extJ[7] = xi; 1347dfccc68fSToby Isaac for (j = 0; j < dim; j++) { 1348dfccc68fSToby Isaac for (k = 0; k < dimR; k++) { 1349dfccc68fSToby Isaac PetscReal val = 0.; 1350dfccc68fSToby Isaac 1351dfccc68fSToby Isaac for (l = 0; l < Nv; l++) { 1352dfccc68fSToby Isaac val += zCoeff[dim * l + j] * extJ[dimR * l + k]; 1353dfccc68fSToby Isaac } 1354dfccc68fSToby Isaac J[i * dim * dim + dim * j + k] = val; 1355dfccc68fSToby Isaac } 1356dfccc68fSToby Isaac } 1357dfccc68fSToby Isaac if (dim == 3) { /* put the cross product in the third component of the Jacobian */ 1358dfccc68fSToby Isaac PetscReal x, y, z; 1359dfccc68fSToby Isaac PetscReal *iJ = &J[i * dim * dim]; 1360dfccc68fSToby Isaac PetscReal norm; 1361dfccc68fSToby Isaac 1362dfccc68fSToby Isaac x = iJ[1 * dim + 0] * iJ[2 * dim + 1] - iJ[1 * dim + 1] * iJ[2 * dim + 0]; 1363dfccc68fSToby Isaac y = iJ[0 * dim + 1] * iJ[2 * dim + 0] - iJ[0 * dim + 0] * iJ[2 * dim + 1]; 1364dfccc68fSToby Isaac z = iJ[0 * dim + 0] * iJ[1 * dim + 1] - iJ[0 * dim + 1] * iJ[1 * dim + 0]; 1365dfccc68fSToby Isaac norm = PetscSqrtReal(x * x + y * y + z * z); 1366dfccc68fSToby Isaac iJ[2] = x / norm; 1367dfccc68fSToby Isaac iJ[5] = y / norm; 1368dfccc68fSToby Isaac iJ[8] = z / norm; 1369dfccc68fSToby Isaac DMPlex_Det3D_Internal(&detJ[i], &J[i * dim * dim]); 1370dfccc68fSToby Isaac if (invJ) {DMPlex_Invert3D_Internal(&invJ[i * dim * dim], &J[i * dim * dim], detJ[i]);} 1371dfccc68fSToby Isaac } else { 1372dfccc68fSToby Isaac DMPlex_Det2D_Internal(&detJ[i], &J[i * dim * dim]); 1373dfccc68fSToby Isaac if (invJ) {DMPlex_Invert2D_Internal(&invJ[i * dim * dim], &J[i * dim * dim], detJ[i]);} 1374dfccc68fSToby Isaac } 1375dfccc68fSToby Isaac } 1376dfccc68fSToby Isaac } 1377dfccc68fSToby Isaac } 137899dec3a6SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 1379ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 1380ccd2543fSMatthew G Knepley } 1381ccd2543fSMatthew G Knepley 1382ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexComputeTetrahedronGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 1383ccd2543fSMatthew G Knepley { 1384ccd2543fSMatthew G Knepley PetscSection coordSection; 1385ccd2543fSMatthew G Knepley Vec coordinates; 1386a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 1387ccd2543fSMatthew G Knepley const PetscInt dim = 3; 138899dec3a6SMatthew G. Knepley PetscInt d; 1389ccd2543fSMatthew G Knepley PetscErrorCode ierr; 1390ccd2543fSMatthew G Knepley 1391ccd2543fSMatthew G Knepley PetscFunctionBegin; 1392ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 139369d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 1394ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 13957f07f362SMatthew G. Knepley *detJ = 0.0; 13967f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 1397ccd2543fSMatthew G Knepley if (J) { 1398ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 1399f0df753eSMatthew G. Knepley /* I orient with outward face normals */ 1400f0df753eSMatthew G. Knepley J[d*dim+0] = 0.5*(PetscRealPart(coords[2*dim+d]) - PetscRealPart(coords[0*dim+d])); 1401f0df753eSMatthew G. Knepley J[d*dim+1] = 0.5*(PetscRealPart(coords[1*dim+d]) - PetscRealPart(coords[0*dim+d])); 1402f0df753eSMatthew G. Knepley J[d*dim+2] = 0.5*(PetscRealPart(coords[3*dim+d]) - PetscRealPart(coords[0*dim+d])); 1403ccd2543fSMatthew G Knepley } 14043bc0b13bSBarry Smith ierr = PetscLogFlops(18.0);CHKERRQ(ierr); 1405923591dfSMatthew G. Knepley DMPlex_Det3D_Internal(detJ, J); 1406ccd2543fSMatthew G Knepley } 1407923591dfSMatthew G. Knepley if (invJ) {DMPlex_Invert3D_Internal(invJ, J, *detJ);} 1408ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 1409ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 1410ccd2543fSMatthew G Knepley } 1411ccd2543fSMatthew G Knepley 1412dfccc68fSToby Isaac static PetscErrorCode DMPlexComputeHexahedronGeometry_Internal(DM dm, PetscInt e, PetscInt Nq, const PetscReal points[], PetscReal v[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 1413ccd2543fSMatthew G Knepley { 1414ccd2543fSMatthew G Knepley PetscSection coordSection; 1415ccd2543fSMatthew G Knepley Vec coordinates; 1416a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 1417ccd2543fSMatthew G Knepley const PetscInt dim = 3; 1418ccd2543fSMatthew G Knepley PetscInt d; 1419ccd2543fSMatthew G Knepley PetscErrorCode ierr; 1420ccd2543fSMatthew G Knepley 1421ccd2543fSMatthew G Knepley PetscFunctionBegin; 1422ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 142369d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 1424ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 1425dfccc68fSToby Isaac if (!Nq) { 14267f07f362SMatthew G. Knepley *detJ = 0.0; 1427dfccc68fSToby Isaac if (v) {for (d = 0; d < dim; d++) v[d] = PetscRealPart(coords[d]);} 1428ccd2543fSMatthew G Knepley if (J) { 1429ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 1430f0df753eSMatthew G. Knepley J[d*dim+0] = 0.5*(PetscRealPart(coords[3*dim+d]) - PetscRealPart(coords[0*dim+d])); 1431f0df753eSMatthew G. Knepley J[d*dim+1] = 0.5*(PetscRealPart(coords[1*dim+d]) - PetscRealPart(coords[0*dim+d])); 1432f0df753eSMatthew G. Knepley J[d*dim+2] = 0.5*(PetscRealPart(coords[4*dim+d]) - PetscRealPart(coords[0*dim+d])); 1433ccd2543fSMatthew G Knepley } 14343bc0b13bSBarry Smith ierr = PetscLogFlops(18.0);CHKERRQ(ierr); 1435923591dfSMatthew G. Knepley DMPlex_Det3D_Internal(detJ, J); 1436ccd2543fSMatthew G Knepley } 1437923591dfSMatthew G. Knepley if (invJ) {DMPlex_Invert3D_Internal(invJ, J, *detJ);} 1438dfccc68fSToby Isaac } else { 1439dfccc68fSToby Isaac const PetscInt Nv = 8; 1440dfccc68fSToby Isaac const PetscInt zToPlex[8] = {0, 3, 1, 2, 4, 5, 7, 6}; 1441dfccc68fSToby Isaac const PetscInt dim = 3; 1442dfccc68fSToby Isaac const PetscInt dimR = 3; 1443dfccc68fSToby Isaac PetscReal zOrder[24]; 1444dfccc68fSToby Isaac PetscReal zCoeff[24]; 1445dfccc68fSToby Isaac PetscInt i, j, k, l; 1446dfccc68fSToby Isaac 1447dfccc68fSToby Isaac for (i = 0; i < Nv; i++) { 1448dfccc68fSToby Isaac PetscInt zi = zToPlex[i]; 1449dfccc68fSToby Isaac 1450dfccc68fSToby Isaac for (j = 0; j < dim; j++) { 1451dfccc68fSToby Isaac zOrder[dim * i + j] = PetscRealPart(coords[dim * zi + j]); 1452dfccc68fSToby Isaac } 1453dfccc68fSToby Isaac } 1454dfccc68fSToby Isaac for (j = 0; j < dim; j++) { 1455dfccc68fSToby Isaac zCoeff[dim * 0 + j] = 0.125 * ( zOrder[dim * 0 + j] + zOrder[dim * 1 + j] + zOrder[dim * 2 + j] + zOrder[dim * 3 + j] + zOrder[dim * 4 + j] + zOrder[dim * 5 + j] + zOrder[dim * 6 + j] + zOrder[dim * 7 + j]); 1456dfccc68fSToby Isaac zCoeff[dim * 1 + j] = 0.125 * (- zOrder[dim * 0 + j] + zOrder[dim * 1 + j] - zOrder[dim * 2 + j] + zOrder[dim * 3 + j] - zOrder[dim * 4 + j] + zOrder[dim * 5 + j] - zOrder[dim * 6 + j] + zOrder[dim * 7 + j]); 1457dfccc68fSToby Isaac zCoeff[dim * 2 + j] = 0.125 * (- zOrder[dim * 0 + j] - zOrder[dim * 1 + j] + zOrder[dim * 2 + j] + zOrder[dim * 3 + j] - zOrder[dim * 4 + j] - zOrder[dim * 5 + j] + zOrder[dim * 6 + j] + zOrder[dim * 7 + j]); 1458dfccc68fSToby Isaac zCoeff[dim * 3 + j] = 0.125 * ( zOrder[dim * 0 + j] - zOrder[dim * 1 + j] - zOrder[dim * 2 + j] + zOrder[dim * 3 + j] + zOrder[dim * 4 + j] - zOrder[dim * 5 + j] - zOrder[dim * 6 + j] + zOrder[dim * 7 + j]); 1459dfccc68fSToby Isaac zCoeff[dim * 4 + j] = 0.125 * (- zOrder[dim * 0 + j] - zOrder[dim * 1 + j] - zOrder[dim * 2 + j] - zOrder[dim * 3 + j] + zOrder[dim * 4 + j] + zOrder[dim * 5 + j] + zOrder[dim * 6 + j] + zOrder[dim * 7 + j]); 1460dfccc68fSToby Isaac zCoeff[dim * 5 + j] = 0.125 * (+ zOrder[dim * 0 + j] - zOrder[dim * 1 + j] + zOrder[dim * 2 + j] - zOrder[dim * 3 + j] - zOrder[dim * 4 + j] + zOrder[dim * 5 + j] - zOrder[dim * 6 + j] + zOrder[dim * 7 + j]); 1461dfccc68fSToby Isaac zCoeff[dim * 6 + j] = 0.125 * (+ zOrder[dim * 0 + j] + zOrder[dim * 1 + j] - zOrder[dim * 2 + j] - zOrder[dim * 3 + j] - zOrder[dim * 4 + j] - zOrder[dim * 5 + j] + zOrder[dim * 6 + j] + zOrder[dim * 7 + j]); 1462dfccc68fSToby Isaac zCoeff[dim * 7 + j] = 0.125 * (- zOrder[dim * 0 + j] + zOrder[dim * 1 + j] + zOrder[dim * 2 + j] - zOrder[dim * 3 + j] + zOrder[dim * 4 + j] - zOrder[dim * 5 + j] - zOrder[dim * 6 + j] + zOrder[dim * 7 + j]); 1463dfccc68fSToby Isaac } 1464dfccc68fSToby Isaac for (i = 0; i < Nq; i++) { 1465dfccc68fSToby Isaac PetscReal xi = points[dimR * i], eta = points[dimR * i + 1], theta = points[dimR * i + 2]; 1466dfccc68fSToby Isaac 1467dfccc68fSToby Isaac if (v) { 146891d2b7ceSToby Isaac PetscReal extPoint[8]; 1469dfccc68fSToby Isaac 1470dfccc68fSToby Isaac extPoint[0] = 1.; 1471dfccc68fSToby Isaac extPoint[1] = xi; 1472dfccc68fSToby Isaac extPoint[2] = eta; 1473dfccc68fSToby Isaac extPoint[3] = xi * eta; 1474dfccc68fSToby Isaac extPoint[4] = theta; 1475dfccc68fSToby Isaac extPoint[5] = theta * xi; 1476dfccc68fSToby Isaac extPoint[6] = theta * eta; 1477dfccc68fSToby Isaac extPoint[7] = theta * eta * xi; 1478dfccc68fSToby Isaac for (j = 0; j < dim; j++) { 1479dfccc68fSToby Isaac PetscReal val = 0.; 1480dfccc68fSToby Isaac 1481dfccc68fSToby Isaac for (k = 0; k < Nv; k++) { 1482dfccc68fSToby Isaac val += extPoint[k] * zCoeff[dim * k + j]; 1483dfccc68fSToby Isaac } 1484dfccc68fSToby Isaac v[i * dim + j] = val; 1485dfccc68fSToby Isaac } 1486dfccc68fSToby Isaac } 1487dfccc68fSToby Isaac if (J) { 1488dfccc68fSToby Isaac PetscReal extJ[24]; 1489dfccc68fSToby Isaac 1490dfccc68fSToby Isaac extJ[0] = 0. ; extJ[1] = 0. ; extJ[2] = 0. ; 1491dfccc68fSToby Isaac extJ[3] = 1. ; extJ[4] = 0. ; extJ[5] = 0. ; 1492dfccc68fSToby Isaac extJ[6] = 0. ; extJ[7] = 1. ; extJ[8] = 0. ; 1493dfccc68fSToby Isaac extJ[9] = eta ; extJ[10] = xi ; extJ[11] = 0. ; 1494dfccc68fSToby Isaac extJ[12] = 0. ; extJ[13] = 0. ; extJ[14] = 1. ; 1495dfccc68fSToby Isaac extJ[15] = theta ; extJ[16] = 0. ; extJ[17] = xi ; 1496dfccc68fSToby Isaac extJ[18] = 0. ; extJ[19] = theta ; extJ[20] = eta ; 1497dfccc68fSToby Isaac extJ[21] = theta * eta; extJ[22] = theta * xi; extJ[23] = eta * xi; 1498dfccc68fSToby Isaac 1499dfccc68fSToby Isaac for (j = 0; j < dim; j++) { 1500dfccc68fSToby Isaac for (k = 0; k < dimR; k++) { 1501dfccc68fSToby Isaac PetscReal val = 0.; 1502dfccc68fSToby Isaac 1503dfccc68fSToby Isaac for (l = 0; l < Nv; l++) { 1504dfccc68fSToby Isaac val += zCoeff[dim * l + j] * extJ[dimR * l + k]; 1505dfccc68fSToby Isaac } 1506dfccc68fSToby Isaac J[i * dim * dim + dim * j + k] = val; 1507dfccc68fSToby Isaac } 1508dfccc68fSToby Isaac } 1509dfccc68fSToby Isaac DMPlex_Det3D_Internal(&detJ[i], &J[i * dim * dim]); 1510dfccc68fSToby Isaac if (invJ) {DMPlex_Invert3D_Internal(&invJ[i * dim * dim], &J[i * dim * dim], detJ[i]);} 1511dfccc68fSToby Isaac } 1512dfccc68fSToby Isaac } 1513dfccc68fSToby Isaac } 1514ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 1515ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 1516ccd2543fSMatthew G Knepley } 1517ccd2543fSMatthew G Knepley 1518dfccc68fSToby Isaac static PetscErrorCode DMPlexComputeCellGeometryFEM_Implicit(DM dm, PetscInt cell, PetscQuadrature quad, PetscReal *v, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 1519dfccc68fSToby Isaac { 1520dfccc68fSToby Isaac PetscInt depth, dim, coordDim, coneSize, i; 1521dfccc68fSToby Isaac PetscInt Nq = 0; 1522dfccc68fSToby Isaac const PetscReal *points = NULL; 1523dfccc68fSToby Isaac DMLabel depthLabel; 1524c330f8ffSToby Isaac PetscReal xi0[3] = {-1.,-1.,-1.}, v0[3], J0[9], detJ0; 1525dfccc68fSToby Isaac PetscBool isAffine = PETSC_TRUE; 1526dfccc68fSToby Isaac PetscErrorCode ierr; 1527dfccc68fSToby Isaac 1528dfccc68fSToby Isaac PetscFunctionBegin; 1529dfccc68fSToby Isaac ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1530dfccc68fSToby Isaac ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 1531dfccc68fSToby Isaac ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 1532dfccc68fSToby Isaac ierr = DMLabelGetValue(depthLabel, cell, &dim);CHKERRQ(ierr); 1533dfccc68fSToby Isaac if (depth == 1 && dim == 1) { 1534dfccc68fSToby Isaac ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1535dfccc68fSToby Isaac } 1536dfccc68fSToby Isaac ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 1537dfccc68fSToby Isaac if (coordDim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported coordinate dimension %D > 3", coordDim); 15389c3cf19fSMatthew G. Knepley if (quad) {ierr = PetscQuadratureGetData(quad, NULL, NULL, &Nq, &points, NULL);CHKERRQ(ierr);} 1539dfccc68fSToby Isaac switch (dim) { 1540dfccc68fSToby Isaac case 0: 1541dfccc68fSToby Isaac ierr = DMPlexComputePointGeometry_Internal(dm, cell, v, J, invJ, detJ);CHKERRQ(ierr); 1542dfccc68fSToby Isaac isAffine = PETSC_FALSE; 1543dfccc68fSToby Isaac break; 1544dfccc68fSToby Isaac case 1: 15457318780aSToby Isaac if (Nq) { 15467318780aSToby Isaac ierr = DMPlexComputeLineGeometry_Internal(dm, cell, v0, J0, NULL, &detJ0);CHKERRQ(ierr); 15477318780aSToby Isaac } else { 15487318780aSToby Isaac ierr = DMPlexComputeLineGeometry_Internal(dm, cell, v, J, invJ, detJ);CHKERRQ(ierr); 15497318780aSToby Isaac } 1550dfccc68fSToby Isaac break; 1551dfccc68fSToby Isaac case 2: 1552dfccc68fSToby Isaac switch (coneSize) { 1553dfccc68fSToby Isaac case 3: 15547318780aSToby Isaac if (Nq) { 15557318780aSToby Isaac ierr = DMPlexComputeTriangleGeometry_Internal(dm, cell, v0, J0, NULL, &detJ0);CHKERRQ(ierr); 15567318780aSToby Isaac } else { 15577318780aSToby Isaac ierr = DMPlexComputeTriangleGeometry_Internal(dm, cell, v, J, invJ, detJ);CHKERRQ(ierr); 15587318780aSToby Isaac } 1559dfccc68fSToby Isaac break; 1560dfccc68fSToby Isaac case 4: 1561dfccc68fSToby Isaac ierr = DMPlexComputeRectangleGeometry_Internal(dm, cell, Nq, points, v, J, invJ, detJ);CHKERRQ(ierr); 1562dfccc68fSToby Isaac isAffine = PETSC_FALSE; 1563dfccc68fSToby Isaac break; 1564dfccc68fSToby Isaac default: 1565dfccc68fSToby Isaac SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of faces %D in cell %D for element geometry computation", coneSize, cell); 1566dfccc68fSToby Isaac } 1567dfccc68fSToby Isaac break; 1568dfccc68fSToby Isaac case 3: 1569dfccc68fSToby Isaac switch (coneSize) { 1570dfccc68fSToby Isaac case 4: 15717318780aSToby Isaac if (Nq) { 15727318780aSToby Isaac ierr = DMPlexComputeTetrahedronGeometry_Internal(dm, cell, v0, J0, NULL, &detJ0);CHKERRQ(ierr); 15737318780aSToby Isaac } else { 15747318780aSToby Isaac ierr = DMPlexComputeTetrahedronGeometry_Internal(dm, cell, v, J, invJ, detJ);CHKERRQ(ierr); 15757318780aSToby Isaac } 1576dfccc68fSToby Isaac break; 1577dfccc68fSToby Isaac case 6: /* Faces */ 1578dfccc68fSToby Isaac case 8: /* Vertices */ 1579dfccc68fSToby Isaac ierr = DMPlexComputeHexahedronGeometry_Internal(dm, cell, Nq, points, v, J, invJ, detJ);CHKERRQ(ierr); 1580dfccc68fSToby Isaac isAffine = PETSC_FALSE; 1581dfccc68fSToby Isaac break; 1582dfccc68fSToby Isaac default: 1583dfccc68fSToby Isaac SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of faces %D in cell %D for element geometry computation", coneSize, cell); 1584dfccc68fSToby Isaac } 1585dfccc68fSToby Isaac break; 1586dfccc68fSToby Isaac default: 1587dfccc68fSToby Isaac SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 1588dfccc68fSToby Isaac } 15897318780aSToby Isaac if (isAffine && Nq) { 1590dfccc68fSToby Isaac if (v) { 1591dfccc68fSToby Isaac for (i = 0; i < Nq; i++) { 1592c330f8ffSToby Isaac CoordinatesRefToReal(coordDim, dim, xi0, v0, J0, &points[dim * i], &v[coordDim * i]); 1593dfccc68fSToby Isaac } 1594dfccc68fSToby Isaac } 15957318780aSToby Isaac if (detJ) { 15967318780aSToby Isaac for (i = 0; i < Nq; i++) { 15977318780aSToby Isaac detJ[i] = detJ0; 1598dfccc68fSToby Isaac } 15997318780aSToby Isaac } 16007318780aSToby Isaac if (J) { 16017318780aSToby Isaac PetscInt k; 16027318780aSToby Isaac 16037318780aSToby Isaac for (i = 0, k = 0; i < Nq; i++) { 1604dfccc68fSToby Isaac PetscInt j; 1605dfccc68fSToby Isaac 16067318780aSToby Isaac for (j = 0; j < coordDim * coordDim; j++, k++) { 16077318780aSToby Isaac J[k] = J0[j]; 16087318780aSToby Isaac } 16097318780aSToby Isaac } 16107318780aSToby Isaac } 16117318780aSToby Isaac if (invJ) { 16127318780aSToby Isaac PetscInt k; 16137318780aSToby Isaac switch (coordDim) { 16147318780aSToby Isaac case 0: 16157318780aSToby Isaac break; 16167318780aSToby Isaac case 1: 16177318780aSToby Isaac invJ[0] = 1./J0[0]; 16187318780aSToby Isaac break; 16197318780aSToby Isaac case 2: 16207318780aSToby Isaac DMPlex_Invert2D_Internal(invJ, J0, detJ0); 16217318780aSToby Isaac break; 16227318780aSToby Isaac case 3: 16237318780aSToby Isaac DMPlex_Invert3D_Internal(invJ, J0, detJ0); 16247318780aSToby Isaac break; 16257318780aSToby Isaac } 16267318780aSToby Isaac for (i = 1, k = coordDim * coordDim; i < Nq; i++) { 16277318780aSToby Isaac PetscInt j; 16287318780aSToby Isaac 16297318780aSToby Isaac for (j = 0; j < coordDim * coordDim; j++, k++) { 16307318780aSToby Isaac invJ[k] = invJ[j]; 16317318780aSToby Isaac } 1632dfccc68fSToby Isaac } 1633dfccc68fSToby Isaac } 1634dfccc68fSToby Isaac } 1635dfccc68fSToby Isaac PetscFunctionReturn(0); 1636dfccc68fSToby Isaac } 1637dfccc68fSToby Isaac 1638ccd2543fSMatthew G Knepley /*@C 16398e0841e0SMatthew G. Knepley DMPlexComputeCellGeometryAffineFEM - Assuming an affine map, compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 1640ccd2543fSMatthew G Knepley 1641d083f849SBarry Smith Collective on dm 1642ccd2543fSMatthew G Knepley 1643ccd2543fSMatthew G Knepley Input Arguments: 1644ccd2543fSMatthew G Knepley + dm - the DM 1645ccd2543fSMatthew G Knepley - cell - the cell 1646ccd2543fSMatthew G Knepley 1647ccd2543fSMatthew G Knepley Output Arguments: 1648ccd2543fSMatthew G Knepley + v0 - the translation part of this affine transform 1649ccd2543fSMatthew G Knepley . J - the Jacobian of the transform from the reference element 1650ccd2543fSMatthew G Knepley . invJ - the inverse of the Jacobian 1651ccd2543fSMatthew G Knepley - detJ - the Jacobian determinant 1652ccd2543fSMatthew G Knepley 1653ccd2543fSMatthew G Knepley Level: advanced 1654ccd2543fSMatthew G Knepley 1655ccd2543fSMatthew G Knepley Fortran Notes: 1656ccd2543fSMatthew G Knepley Since it returns arrays, this routine is only available in Fortran 90, and you must 1657ccd2543fSMatthew G Knepley include petsc.h90 in your code. 1658ccd2543fSMatthew G Knepley 1659e8964c0aSStefano Zampini .seealso: DMPlexComputeCellGeometryFEM(), DMGetCoordinateSection(), DMGetCoordinates() 1660ccd2543fSMatthew G Knepley @*/ 16618e0841e0SMatthew G. Knepley PetscErrorCode DMPlexComputeCellGeometryAffineFEM(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 1662ccd2543fSMatthew G Knepley { 1663ccd2543fSMatthew G Knepley PetscErrorCode ierr; 1664ccd2543fSMatthew G Knepley 1665ccd2543fSMatthew G Knepley PetscFunctionBegin; 1666dfccc68fSToby Isaac ierr = DMPlexComputeCellGeometryFEM_Implicit(dm,cell,NULL,v0,J,invJ,detJ);CHKERRQ(ierr); 16678e0841e0SMatthew G. Knepley PetscFunctionReturn(0); 16688e0841e0SMatthew G. Knepley } 16698e0841e0SMatthew G. Knepley 1670dfccc68fSToby Isaac static PetscErrorCode DMPlexComputeCellGeometryFEM_FE(DM dm, PetscFE fe, PetscInt point, PetscQuadrature quad, PetscReal v[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 16718e0841e0SMatthew G. Knepley { 1672dfccc68fSToby Isaac PetscQuadrature feQuad; 16738e0841e0SMatthew G. Knepley PetscSection coordSection; 16748e0841e0SMatthew G. Knepley Vec coordinates; 16758e0841e0SMatthew G. Knepley PetscScalar *coords = NULL; 16768e0841e0SMatthew G. Knepley const PetscReal *quadPoints; 1677f960e424SToby Isaac PetscReal *basisDer, *basis, detJt; 1678f960e424SToby Isaac PetscInt dim, cdim, pdim, qdim, Nq, numCoords, q; 16798e0841e0SMatthew G. Knepley PetscErrorCode ierr; 16808e0841e0SMatthew G. Knepley 16818e0841e0SMatthew G. Knepley PetscFunctionBegin; 16828e0841e0SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 16838e0841e0SMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 16848e0841e0SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, point, &numCoords, &coords);CHKERRQ(ierr); 16858e0841e0SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 16868e0841e0SMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 1687dfccc68fSToby Isaac if (!quad) { /* use the first point of the first functional of the dual space */ 1688dfccc68fSToby Isaac PetscDualSpace dsp; 1689dfccc68fSToby Isaac 1690dfccc68fSToby Isaac ierr = PetscFEGetDualSpace(fe, &dsp);CHKERRQ(ierr); 1691dfccc68fSToby Isaac ierr = PetscDualSpaceGetFunctional(dsp, 0, &quad);CHKERRQ(ierr); 16929c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, &qdim, NULL, &Nq, &quadPoints, NULL);CHKERRQ(ierr); 1693dfccc68fSToby Isaac Nq = 1; 1694dfccc68fSToby Isaac } else { 16959c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, &qdim, NULL, &Nq, &quadPoints, NULL);CHKERRQ(ierr); 1696dfccc68fSToby Isaac } 169791d2b7ceSToby Isaac ierr = PetscFEGetDimension(fe, &pdim);CHKERRQ(ierr); 1698dfccc68fSToby Isaac ierr = PetscFEGetQuadrature(fe, &feQuad);CHKERRQ(ierr); 1699dfccc68fSToby Isaac if (feQuad == quad) { 17008135c375SStefano Zampini ierr = PetscFEGetDefaultTabulation(fe, &basis, J ? &basisDer : NULL, NULL);CHKERRQ(ierr); 17018e0841e0SMatthew G. Knepley if (numCoords != pdim*cdim) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "There are %d coordinates for point %d != %d*%d", numCoords, point, pdim, cdim); 1702dfccc68fSToby Isaac } else { 17038135c375SStefano Zampini ierr = PetscFEGetTabulation(fe, Nq, quadPoints, &basis, J ? &basisDer : NULL, NULL);CHKERRQ(ierr); 1704dfccc68fSToby Isaac } 1705dfccc68fSToby Isaac if (qdim != dim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Point dimension %d != quadrature dimension %d", dim, qdim); 1706dfccc68fSToby Isaac if (v) { 1707580bdb30SBarry Smith ierr = PetscArrayzero(v, Nq*cdim);CHKERRQ(ierr); 1708f960e424SToby Isaac for (q = 0; q < Nq; ++q) { 1709f960e424SToby Isaac PetscInt i, k; 1710f960e424SToby Isaac 1711f960e424SToby Isaac for (k = 0; k < pdim; ++k) 1712f960e424SToby Isaac for (i = 0; i < cdim; ++i) 1713dfccc68fSToby Isaac v[q*cdim + i] += basis[q*pdim + k] * PetscRealPart(coords[k*cdim + i]); 1714f960e424SToby Isaac ierr = PetscLogFlops(2.0*pdim*cdim);CHKERRQ(ierr); 1715f960e424SToby Isaac } 1716f960e424SToby Isaac } 17178e0841e0SMatthew G. Knepley if (J) { 1718580bdb30SBarry Smith ierr = PetscArrayzero(J, Nq*cdim*cdim);CHKERRQ(ierr); 17198e0841e0SMatthew G. Knepley for (q = 0; q < Nq; ++q) { 17208e0841e0SMatthew G. Knepley PetscInt i, j, k, c, r; 17218e0841e0SMatthew G. Knepley 17228e0841e0SMatthew G. Knepley /* J = dx_i/d\xi_j = sum[k=0,n-1] dN_k/d\xi_j * x_i(k) */ 17238e0841e0SMatthew G. Knepley for (k = 0; k < pdim; ++k) 17248e0841e0SMatthew G. Knepley for (j = 0; j < dim; ++j) 17258e0841e0SMatthew G. Knepley for (i = 0; i < cdim; ++i) 1726dfccc68fSToby Isaac J[(q*cdim + i)*cdim + j] += basisDer[(q*pdim + k)*dim + j] * PetscRealPart(coords[k*cdim + i]); 17273bc0b13bSBarry Smith ierr = PetscLogFlops(2.0*pdim*dim*cdim);CHKERRQ(ierr); 17288e0841e0SMatthew G. Knepley if (cdim > dim) { 17298e0841e0SMatthew G. Knepley for (c = dim; c < cdim; ++c) 17308e0841e0SMatthew G. Knepley for (r = 0; r < cdim; ++r) 17318e0841e0SMatthew G. Knepley J[r*cdim+c] = r == c ? 1.0 : 0.0; 17328e0841e0SMatthew G. Knepley } 1733f960e424SToby Isaac if (!detJ && !invJ) continue; 1734a63b72c6SToby Isaac detJt = 0.; 17358e0841e0SMatthew G. Knepley switch (cdim) { 17368e0841e0SMatthew G. Knepley case 3: 1737037dc194SToby Isaac DMPlex_Det3D_Internal(&detJt, &J[q*cdim*dim]); 1738037dc194SToby Isaac if (invJ) {DMPlex_Invert3D_Internal(&invJ[q*cdim*dim], &J[q*cdim*dim], detJt);} 173917fe8556SMatthew G. Knepley break; 174049dc4407SMatthew G. Knepley case 2: 17419f328543SToby Isaac DMPlex_Det2D_Internal(&detJt, &J[q*cdim*dim]); 1742037dc194SToby Isaac if (invJ) {DMPlex_Invert2D_Internal(&invJ[q*cdim*dim], &J[q*cdim*dim], detJt);} 174349dc4407SMatthew G. Knepley break; 17448e0841e0SMatthew G. Knepley case 1: 1745037dc194SToby Isaac detJt = J[q*cdim*dim]; 1746037dc194SToby Isaac if (invJ) invJ[q*cdim*dim] = 1.0/detJt; 174749dc4407SMatthew G. Knepley } 1748f960e424SToby Isaac if (detJ) detJ[q] = detJt; 174949dc4407SMatthew G. Knepley } 175049dc4407SMatthew G. Knepley } 1751037dc194SToby Isaac else if (detJ || invJ) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Need J to compute invJ or detJ"); 1752dfccc68fSToby Isaac if (feQuad != quad) { 17538135c375SStefano Zampini ierr = PetscFERestoreTabulation(fe, Nq, quadPoints, &basis, J ? &basisDer : NULL, NULL);CHKERRQ(ierr); 1754dfccc68fSToby Isaac } 17558e0841e0SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, point, &numCoords, &coords);CHKERRQ(ierr); 17568e0841e0SMatthew G. Knepley PetscFunctionReturn(0); 17578e0841e0SMatthew G. Knepley } 17588e0841e0SMatthew G. Knepley 17598e0841e0SMatthew G. Knepley /*@C 17608e0841e0SMatthew G. Knepley DMPlexComputeCellGeometryFEM - Compute the Jacobian, inverse Jacobian, and Jacobian determinant at each quadrature point in the given cell 17618e0841e0SMatthew G. Knepley 1762d083f849SBarry Smith Collective on dm 17638e0841e0SMatthew G. Knepley 17648e0841e0SMatthew G. Knepley Input Arguments: 17658e0841e0SMatthew G. Knepley + dm - the DM 17668e0841e0SMatthew G. Knepley . cell - the cell 1767dfccc68fSToby Isaac - quad - the quadrature containing the points in the reference element where the geometry will be evaluated. If quad == NULL, geometry will be 1768dfccc68fSToby Isaac evaluated at the first vertex of the reference element 17698e0841e0SMatthew G. Knepley 17708e0841e0SMatthew G. Knepley Output Arguments: 1771dfccc68fSToby Isaac + v - the image of the transformed quadrature points, otherwise the image of the first vertex in the closure of the reference element 17728e0841e0SMatthew G. Knepley . J - the Jacobian of the transform from the reference element at each quadrature point 17738e0841e0SMatthew G. Knepley . invJ - the inverse of the Jacobian at each quadrature point 17748e0841e0SMatthew G. Knepley - detJ - the Jacobian determinant at each quadrature point 17758e0841e0SMatthew G. Knepley 17768e0841e0SMatthew G. Knepley Level: advanced 17778e0841e0SMatthew G. Knepley 17788e0841e0SMatthew G. Knepley Fortran Notes: 17798e0841e0SMatthew G. Knepley Since it returns arrays, this routine is only available in Fortran 90, and you must 17808e0841e0SMatthew G. Knepley include petsc.h90 in your code. 17818e0841e0SMatthew G. Knepley 1782e8964c0aSStefano Zampini .seealso: DMGetCoordinateSection(), DMGetCoordinates() 17838e0841e0SMatthew G. Knepley @*/ 1784dfccc68fSToby Isaac PetscErrorCode DMPlexComputeCellGeometryFEM(DM dm, PetscInt cell, PetscQuadrature quad, PetscReal *v, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 17858e0841e0SMatthew G. Knepley { 1786bb4a5db5SMatthew G. Knepley DM cdm; 1787dfccc68fSToby Isaac PetscFE fe = NULL; 17888e0841e0SMatthew G. Knepley PetscErrorCode ierr; 17898e0841e0SMatthew G. Knepley 17908e0841e0SMatthew G. Knepley PetscFunctionBegin; 17912d89661fSMatthew G. Knepley PetscValidPointer(detJ, 7); 1792bb4a5db5SMatthew G. Knepley ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1793bb4a5db5SMatthew G. Knepley if (cdm) { 1794dfccc68fSToby Isaac PetscClassId id; 1795dfccc68fSToby Isaac PetscInt numFields; 1796e5e52638SMatthew G. Knepley PetscDS prob; 1797dfccc68fSToby Isaac PetscObject disc; 1798dfccc68fSToby Isaac 1799bb4a5db5SMatthew G. Knepley ierr = DMGetNumFields(cdm, &numFields);CHKERRQ(ierr); 1800dfccc68fSToby Isaac if (numFields) { 1801bb4a5db5SMatthew G. Knepley ierr = DMGetDS(cdm, &prob);CHKERRQ(ierr); 1802dfccc68fSToby Isaac ierr = PetscDSGetDiscretization(prob,0,&disc);CHKERRQ(ierr); 1803dfccc68fSToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 1804dfccc68fSToby Isaac if (id == PETSCFE_CLASSID) { 1805dfccc68fSToby Isaac fe = (PetscFE) disc; 1806dfccc68fSToby Isaac } 1807dfccc68fSToby Isaac } 1808dfccc68fSToby Isaac } 1809dfccc68fSToby Isaac if (!fe) {ierr = DMPlexComputeCellGeometryFEM_Implicit(dm, cell, quad, v, J, invJ, detJ);CHKERRQ(ierr);} 1810dfccc68fSToby Isaac else {ierr = DMPlexComputeCellGeometryFEM_FE(dm, fe, cell, quad, v, J, invJ, detJ);CHKERRQ(ierr);} 1811ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 1812ccd2543fSMatthew G Knepley } 1813834e62ceSMatthew G. Knepley 1814011ea5d8SMatthew G. Knepley static PetscErrorCode DMPlexComputeGeometryFVM_1D_Internal(DM dm, PetscInt dim, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 1815cc08537eSMatthew G. Knepley { 1816cc08537eSMatthew G. Knepley PetscSection coordSection; 1817cc08537eSMatthew G. Knepley Vec coordinates; 1818a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 181906e2781eSMatthew G. Knepley PetscScalar tmp[2]; 1820714b99b6SMatthew G. Knepley PetscInt coordSize, d; 1821cc08537eSMatthew G. Knepley PetscErrorCode ierr; 1822cc08537eSMatthew G. Knepley 1823cc08537eSMatthew G. Knepley PetscFunctionBegin; 1824cc08537eSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 182569d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 1826cc08537eSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 18272e17dfb7SMatthew G. Knepley ierr = DMLocalizeCoordinate_Internal(dm, dim, coords, &coords[dim], tmp);CHKERRQ(ierr); 1828cc08537eSMatthew G. Knepley if (centroid) { 1829714b99b6SMatthew G. Knepley for (d = 0; d < dim; ++d) centroid[d] = 0.5*PetscRealPart(coords[d] + tmp[d]); 1830cc08537eSMatthew G. Knepley } 1831cc08537eSMatthew G. Knepley if (normal) { 1832a60a936bSMatthew G. Knepley PetscReal norm; 1833a60a936bSMatthew G. Knepley 1834714b99b6SMatthew G. Knepley if (dim != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "We only support 2D edges right now"); 183506e2781eSMatthew G. Knepley normal[0] = -PetscRealPart(coords[1] - tmp[1]); 183606e2781eSMatthew G. Knepley normal[1] = PetscRealPart(coords[0] - tmp[0]); 1837714b99b6SMatthew G. Knepley norm = DMPlex_NormD_Internal(dim, normal); 1838714b99b6SMatthew G. Knepley for (d = 0; d < dim; ++d) normal[d] /= norm; 1839cc08537eSMatthew G. Knepley } 1840cc08537eSMatthew G. Knepley if (vol) { 1841714b99b6SMatthew G. Knepley *vol = 0.0; 1842714b99b6SMatthew G. Knepley for (d = 0; d < dim; ++d) *vol += PetscSqr(PetscRealPart(coords[d] - tmp[d])); 1843714b99b6SMatthew G. Knepley *vol = PetscSqrtReal(*vol); 1844cc08537eSMatthew G. Knepley } 1845cc08537eSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 1846cc08537eSMatthew G. Knepley PetscFunctionReturn(0); 1847cc08537eSMatthew G. Knepley } 1848cc08537eSMatthew G. Knepley 1849cc08537eSMatthew G. Knepley /* Centroid_i = (\sum_n A_n Cn_i ) / A */ 1850011ea5d8SMatthew G. Knepley static PetscErrorCode DMPlexComputeGeometryFVM_2D_Internal(DM dm, PetscInt dim, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 1851cc08537eSMatthew G. Knepley { 1852793a2a13SMatthew G. Knepley DMLabel depth; 1853cc08537eSMatthew G. Knepley PetscSection coordSection; 1854cc08537eSMatthew G. Knepley Vec coordinates; 1855cc08537eSMatthew G. Knepley PetscScalar *coords = NULL; 18560a1d6728SMatthew G. Knepley PetscReal vsum = 0.0, csum[3] = {0.0, 0.0, 0.0}, vtmp, ctmp[4], v0[3], R[9]; 1857793a2a13SMatthew G. Knepley PetscBool isHybrid = PETSC_FALSE; 1858793a2a13SMatthew G. Knepley PetscInt fv[4] = {0, 1, 2, 3}; 1859d80ece95SMatthew G. Knepley PetscInt pEndInterior[4], cdepth, tdim = 2, coordSize, numCorners, p, d, e; 1860cc08537eSMatthew G. Knepley PetscErrorCode ierr; 1861cc08537eSMatthew G. Knepley 1862cc08537eSMatthew G. Knepley PetscFunctionBegin; 1863793a2a13SMatthew G. Knepley /* Must check for hybrid cells because prisms have a different orientation scheme */ 1864793a2a13SMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr); 1865793a2a13SMatthew G. Knepley ierr = DMLabelGetValue(depth, cell, &cdepth);CHKERRQ(ierr); 1866d80ece95SMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &pEndInterior[3], &pEndInterior[2], &pEndInterior[1], &pEndInterior[0]);CHKERRQ(ierr); 1867d80ece95SMatthew G. Knepley if ((pEndInterior[cdepth]) >=0 && (cell >= pEndInterior[cdepth])) isHybrid = PETSC_TRUE; 1868cc08537eSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 18690a1d6728SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cell, &numCorners);CHKERRQ(ierr); 187069d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 1871cc08537eSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 18720bce18caSMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1873793a2a13SMatthew G. Knepley /* Side faces for hybrid cells are are stored as tensor products */ 1874793a2a13SMatthew G. Knepley if (isHybrid && numCorners == 4) {fv[2] = 3; fv[3] = 2;} 1875793a2a13SMatthew G. Knepley 1876ceee4971SMatthew G. Knepley if (dim > 2 && centroid) { 1877ceee4971SMatthew G. Knepley v0[0] = PetscRealPart(coords[0]); 1878ceee4971SMatthew G. Knepley v0[1] = PetscRealPart(coords[1]); 1879ceee4971SMatthew G. Knepley v0[2] = PetscRealPart(coords[2]); 1880ceee4971SMatthew G. Knepley } 1881011ea5d8SMatthew G. Knepley if (normal) { 1882011ea5d8SMatthew G. Knepley if (dim > 2) { 1883793a2a13SMatthew G. Knepley const PetscReal x0 = PetscRealPart(coords[dim*fv[1]+0] - coords[0]), x1 = PetscRealPart(coords[dim*fv[2]+0] - coords[0]); 1884793a2a13SMatthew G. Knepley const PetscReal y0 = PetscRealPart(coords[dim*fv[1]+1] - coords[1]), y1 = PetscRealPart(coords[dim*fv[2]+1] - coords[1]); 1885793a2a13SMatthew G. Knepley const PetscReal z0 = PetscRealPart(coords[dim*fv[1]+2] - coords[2]), z1 = PetscRealPart(coords[dim*fv[2]+2] - coords[2]); 18860a1d6728SMatthew G. Knepley PetscReal norm; 18870a1d6728SMatthew G. Knepley 18880a1d6728SMatthew G. Knepley normal[0] = y0*z1 - z0*y1; 18890a1d6728SMatthew G. Knepley normal[1] = z0*x1 - x0*z1; 18900a1d6728SMatthew G. Knepley normal[2] = x0*y1 - y0*x1; 18918b49ba18SBarry Smith norm = PetscSqrtReal(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]); 18920a1d6728SMatthew G. Knepley normal[0] /= norm; 18930a1d6728SMatthew G. Knepley normal[1] /= norm; 18940a1d6728SMatthew G. Knepley normal[2] /= norm; 1895011ea5d8SMatthew G. Knepley } else { 1896011ea5d8SMatthew G. Knepley for (d = 0; d < dim; ++d) normal[d] = 0.0; 1897011ea5d8SMatthew G. Knepley } 1898011ea5d8SMatthew G. Knepley } 1899741bfc07SMatthew G. Knepley if (dim == 3) {ierr = DMPlexComputeProjection3Dto2D(coordSize, coords, R);CHKERRQ(ierr);} 19000a1d6728SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 1901793a2a13SMatthew G. Knepley const PetscInt pi = p < 4 ? fv[p] : p; 1902793a2a13SMatthew G. Knepley const PetscInt pin = p < 3 ? fv[(p+1)%numCorners] : (p+1)%numCorners; 19030a1d6728SMatthew G. Knepley /* Need to do this copy to get types right */ 19040a1d6728SMatthew G. Knepley for (d = 0; d < tdim; ++d) { 1905793a2a13SMatthew G. Knepley ctmp[d] = PetscRealPart(coords[pi*tdim+d]); 1906793a2a13SMatthew G. Knepley ctmp[tdim+d] = PetscRealPart(coords[pin*tdim+d]); 19070a1d6728SMatthew G. Knepley } 19080a1d6728SMatthew G. Knepley Volume_Triangle_Origin_Internal(&vtmp, ctmp); 19090a1d6728SMatthew G. Knepley vsum += vtmp; 19100a1d6728SMatthew G. Knepley for (d = 0; d < tdim; ++d) { 19110a1d6728SMatthew G. Knepley csum[d] += (ctmp[d] + ctmp[tdim+d])*vtmp; 19120a1d6728SMatthew G. Knepley } 19130a1d6728SMatthew G. Knepley } 19140a1d6728SMatthew G. Knepley for (d = 0; d < tdim; ++d) { 19150a1d6728SMatthew G. Knepley csum[d] /= (tdim+1)*vsum; 19160a1d6728SMatthew G. Knepley } 19170a1d6728SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 1918ee6bbdb2SSatish Balay if (vol) *vol = PetscAbsReal(vsum); 19190a1d6728SMatthew G. Knepley if (centroid) { 19200a1d6728SMatthew G. Knepley if (dim > 2) { 19210a1d6728SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19220a1d6728SMatthew G. Knepley centroid[d] = v0[d]; 19230a1d6728SMatthew G. Knepley for (e = 0; e < dim; ++e) { 19240a1d6728SMatthew G. Knepley centroid[d] += R[d*dim+e]*csum[e]; 19250a1d6728SMatthew G. Knepley } 19260a1d6728SMatthew G. Knepley } 19270a1d6728SMatthew G. Knepley } else for (d = 0; d < dim; ++d) centroid[d] = csum[d]; 19280a1d6728SMatthew G. Knepley } 1929cc08537eSMatthew G. Knepley PetscFunctionReturn(0); 1930cc08537eSMatthew G. Knepley } 1931cc08537eSMatthew G. Knepley 19320ec8681fSMatthew G. Knepley /* Centroid_i = (\sum_n V_n Cn_i ) / V */ 1933011ea5d8SMatthew G. Knepley static PetscErrorCode DMPlexComputeGeometryFVM_3D_Internal(DM dm, PetscInt dim, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 19340ec8681fSMatthew G. Knepley { 1935793a2a13SMatthew G. Knepley DMLabel depth; 19360ec8681fSMatthew G. Knepley PetscSection coordSection; 19370ec8681fSMatthew G. Knepley Vec coordinates; 19380ec8681fSMatthew G. Knepley PetscScalar *coords = NULL; 193986623015SMatthew G. Knepley PetscReal vsum = 0.0, vtmp, coordsTmp[3*3]; 1940a7df9edeSMatthew G. Knepley const PetscInt *faces, *facesO; 1941793a2a13SMatthew G. Knepley PetscBool isHybrid = PETSC_FALSE; 1942793a2a13SMatthew G. Knepley PetscInt pEndInterior[4], cdepth, numFaces, f, coordSize, numCorners, p, d; 19430ec8681fSMatthew G. Knepley PetscErrorCode ierr; 19440ec8681fSMatthew G. Knepley 19450ec8681fSMatthew G. Knepley PetscFunctionBegin; 1946f6dae198SJed Brown if (PetscUnlikely(dim > 3)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"No support for dim %D > 3",dim); 1947793a2a13SMatthew G. Knepley /* Must check for hybrid cells because prisms have a different orientation scheme */ 1948793a2a13SMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr); 1949793a2a13SMatthew G. Knepley ierr = DMLabelGetValue(depth, cell, &cdepth);CHKERRQ(ierr); 19502b2dc32bSSatish Balay ierr = DMPlexGetHybridBounds(dm, &pEndInterior[3], &pEndInterior[2], &pEndInterior[1], &pEndInterior[0]);CHKERRQ(ierr); 1951793a2a13SMatthew G. Knepley if ((pEndInterior[cdepth]) >=0 && (cell >= pEndInterior[cdepth])) isHybrid = PETSC_TRUE; 1952793a2a13SMatthew G. Knepley 19530ec8681fSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 195469d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 19550ec8681fSMatthew G. Knepley 1956d9a81ebdSMatthew G. Knepley if (centroid) for (d = 0; d < dim; ++d) centroid[d] = 0.0; 19570ec8681fSMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cell, &numFaces);CHKERRQ(ierr); 19580ec8681fSMatthew G. Knepley ierr = DMPlexGetCone(dm, cell, &faces);CHKERRQ(ierr); 1959a7df9edeSMatthew G. Knepley ierr = DMPlexGetConeOrientation(dm, cell, &facesO);CHKERRQ(ierr); 19600ec8681fSMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 1961793a2a13SMatthew G. Knepley PetscBool flip = isHybrid && f == 0 ? PETSC_TRUE : PETSC_FALSE; /* The first hybrid face is reversed */ 1962793a2a13SMatthew G. Knepley 1963011ea5d8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, faces[f], &coordSize, &coords);CHKERRQ(ierr); 19640ec8681fSMatthew G. Knepley numCorners = coordSize/dim; 19650ec8681fSMatthew G. Knepley switch (numCorners) { 19660ec8681fSMatthew G. Knepley case 3: 19670ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 19681ee9d5ecSMatthew G. Knepley coordsTmp[0*dim+d] = PetscRealPart(coords[0*dim+d]); 19691ee9d5ecSMatthew G. Knepley coordsTmp[1*dim+d] = PetscRealPart(coords[1*dim+d]); 19701ee9d5ecSMatthew G. Knepley coordsTmp[2*dim+d] = PetscRealPart(coords[2*dim+d]); 19710ec8681fSMatthew G. Knepley } 19720ec8681fSMatthew G. Knepley Volume_Tetrahedron_Origin_Internal(&vtmp, coordsTmp); 1973793a2a13SMatthew G. Knepley if (facesO[f] < 0 || flip) vtmp = -vtmp; 19740ec8681fSMatthew G. Knepley vsum += vtmp; 19754f25033aSJed Brown if (centroid) { /* Centroid of OABC = (a+b+c)/4 */ 19760ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 19771ee9d5ecSMatthew G. Knepley for (p = 0; p < 3; ++p) centroid[d] += coordsTmp[p*dim+d]*vtmp; 19780ec8681fSMatthew G. Knepley } 19790ec8681fSMatthew G. Knepley } 19800ec8681fSMatthew G. Knepley break; 19810ec8681fSMatthew G. Knepley case 4: 1982793a2a13SMatthew G. Knepley { 1983793a2a13SMatthew G. Knepley PetscInt fv[4] = {0, 1, 2, 3}; 1984793a2a13SMatthew G. Knepley 1985793a2a13SMatthew G. Knepley /* Side faces for hybrid cells are are stored as tensor products */ 1986793a2a13SMatthew G. Knepley if (isHybrid && f > 1) {fv[2] = 3; fv[3] = 2;} 19870ec8681fSMatthew G. Knepley /* DO FOR PYRAMID */ 19880ec8681fSMatthew G. Knepley /* First tet */ 19890ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 1990793a2a13SMatthew G. Knepley coordsTmp[0*dim+d] = PetscRealPart(coords[fv[0]*dim+d]); 1991793a2a13SMatthew G. Knepley coordsTmp[1*dim+d] = PetscRealPart(coords[fv[1]*dim+d]); 1992793a2a13SMatthew G. Knepley coordsTmp[2*dim+d] = PetscRealPart(coords[fv[3]*dim+d]); 19930ec8681fSMatthew G. Knepley } 19940ec8681fSMatthew G. Knepley Volume_Tetrahedron_Origin_Internal(&vtmp, coordsTmp); 1995793a2a13SMatthew G. Knepley if (facesO[f] < 0 || flip) vtmp = -vtmp; 19960ec8681fSMatthew G. Knepley vsum += vtmp; 19970ec8681fSMatthew G. Knepley if (centroid) { 19980ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 19990ec8681fSMatthew G. Knepley for (p = 0; p < 3; ++p) centroid[d] += coordsTmp[p*dim+d]*vtmp; 20000ec8681fSMatthew G. Knepley } 20010ec8681fSMatthew G. Knepley } 20020ec8681fSMatthew G. Knepley /* Second tet */ 20030ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 2004793a2a13SMatthew G. Knepley coordsTmp[0*dim+d] = PetscRealPart(coords[fv[1]*dim+d]); 2005793a2a13SMatthew G. Knepley coordsTmp[1*dim+d] = PetscRealPart(coords[fv[2]*dim+d]); 2006793a2a13SMatthew G. Knepley coordsTmp[2*dim+d] = PetscRealPart(coords[fv[3]*dim+d]); 20070ec8681fSMatthew G. Knepley } 20080ec8681fSMatthew G. Knepley Volume_Tetrahedron_Origin_Internal(&vtmp, coordsTmp); 2009793a2a13SMatthew G. Knepley if (facesO[f] < 0 || flip) vtmp = -vtmp; 20100ec8681fSMatthew G. Knepley vsum += vtmp; 20110ec8681fSMatthew G. Knepley if (centroid) { 20120ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 20130ec8681fSMatthew G. Knepley for (p = 0; p < 3; ++p) centroid[d] += coordsTmp[p*dim+d]*vtmp; 20140ec8681fSMatthew G. Knepley } 20150ec8681fSMatthew G. Knepley } 20160ec8681fSMatthew G. Knepley break; 2017793a2a13SMatthew G. Knepley } 20180ec8681fSMatthew G. Knepley default: 2019796f034aSJed Brown SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle faces with %D vertices", numCorners); 20200ec8681fSMatthew G. Knepley } 20214f25033aSJed Brown ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, faces[f], &coordSize, &coords);CHKERRQ(ierr); 20220ec8681fSMatthew G. Knepley } 20238763be8eSMatthew G. Knepley if (vol) *vol = PetscAbsReal(vsum); 20240ec8681fSMatthew G. Knepley if (normal) for (d = 0; d < dim; ++d) normal[d] = 0.0; 2025d9a81ebdSMatthew G. Knepley if (centroid) for (d = 0; d < dim; ++d) centroid[d] /= (vsum*4); 20260ec8681fSMatthew G. Knepley PetscFunctionReturn(0); 20270ec8681fSMatthew G. Knepley } 20280ec8681fSMatthew G. Knepley 2029834e62ceSMatthew G. Knepley /*@C 2030834e62ceSMatthew G. Knepley DMPlexComputeCellGeometryFVM - Compute the volume for a given cell 2031834e62ceSMatthew G. Knepley 2032d083f849SBarry Smith Collective on dm 2033834e62ceSMatthew G. Knepley 2034834e62ceSMatthew G. Knepley Input Arguments: 2035834e62ceSMatthew G. Knepley + dm - the DM 2036834e62ceSMatthew G. Knepley - cell - the cell 2037834e62ceSMatthew G. Knepley 2038834e62ceSMatthew G. Knepley Output Arguments: 2039834e62ceSMatthew G. Knepley + volume - the cell volume 2040cc08537eSMatthew G. Knepley . centroid - the cell centroid 2041cc08537eSMatthew G. Knepley - normal - the cell normal, if appropriate 2042834e62ceSMatthew G. Knepley 2043834e62ceSMatthew G. Knepley Level: advanced 2044834e62ceSMatthew G. Knepley 2045834e62ceSMatthew G. Knepley Fortran Notes: 2046834e62ceSMatthew G. Knepley Since it returns arrays, this routine is only available in Fortran 90, and you must 2047834e62ceSMatthew G. Knepley include petsc.h90 in your code. 2048834e62ceSMatthew G. Knepley 2049e8964c0aSStefano Zampini .seealso: DMGetCoordinateSection(), DMGetCoordinates() 2050834e62ceSMatthew G. Knepley @*/ 2051cc08537eSMatthew G. Knepley PetscErrorCode DMPlexComputeCellGeometryFVM(DM dm, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 2052834e62ceSMatthew G. Knepley { 20530ec8681fSMatthew G. Knepley PetscInt depth, dim; 2054834e62ceSMatthew G. Knepley PetscErrorCode ierr; 2055834e62ceSMatthew G. Knepley 2056834e62ceSMatthew G. Knepley PetscFunctionBegin; 2057834e62ceSMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2058c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2059834e62ceSMatthew G. Knepley if (depth != dim) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh must be interpolated"); 2060834e62ceSMatthew G. Knepley /* We need to keep a pointer to the depth label */ 2061c58f1c22SToby Isaac ierr = DMGetLabelValue(dm, "depth", cell, &depth);CHKERRQ(ierr); 2062834e62ceSMatthew G. Knepley /* Cone size is now the number of faces */ 2063011ea5d8SMatthew G. Knepley switch (depth) { 2064cc08537eSMatthew G. Knepley case 1: 2065011ea5d8SMatthew G. Knepley ierr = DMPlexComputeGeometryFVM_1D_Internal(dm, dim, cell, vol, centroid, normal);CHKERRQ(ierr); 2066cc08537eSMatthew G. Knepley break; 2067834e62ceSMatthew G. Knepley case 2: 2068011ea5d8SMatthew G. Knepley ierr = DMPlexComputeGeometryFVM_2D_Internal(dm, dim, cell, vol, centroid, normal);CHKERRQ(ierr); 2069834e62ceSMatthew G. Knepley break; 2070834e62ceSMatthew G. Knepley case 3: 2071011ea5d8SMatthew G. Knepley ierr = DMPlexComputeGeometryFVM_3D_Internal(dm, dim, cell, vol, centroid, normal);CHKERRQ(ierr); 2072834e62ceSMatthew G. Knepley break; 2073834e62ceSMatthew G. Knepley default: 2074b81cf158SMatthew G. Knepley SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D (depth %D) for element geometry computation", dim, depth); 2075834e62ceSMatthew G. Knepley } 2076834e62ceSMatthew G. Knepley PetscFunctionReturn(0); 2077834e62ceSMatthew G. Knepley } 2078113c68e6SMatthew G. Knepley 2079c501906fSMatthew G. Knepley /*@ 2080c501906fSMatthew G. Knepley DMPlexComputeGeometryFEM - Precompute cell geometry for the entire mesh 2081c501906fSMatthew G. Knepley 2082c501906fSMatthew G. Knepley Collective on dm 2083c501906fSMatthew G. Knepley 2084c501906fSMatthew G. Knepley Input Parameter: 2085c501906fSMatthew G. Knepley . dm - The DMPlex 2086c501906fSMatthew G. Knepley 2087c501906fSMatthew G. Knepley Output Parameter: 2088c501906fSMatthew G. Knepley . cellgeom - A vector with the cell geometry data for each cell 2089c501906fSMatthew G. Knepley 2090c501906fSMatthew G. Knepley Level: beginner 2091c501906fSMatthew G. Knepley 2092c501906fSMatthew G. Knepley @*/ 2093c0d900a5SMatthew G. Knepley PetscErrorCode DMPlexComputeGeometryFEM(DM dm, Vec *cellgeom) 2094c0d900a5SMatthew G. Knepley { 2095c0d900a5SMatthew G. Knepley DM dmCell; 2096c0d900a5SMatthew G. Knepley Vec coordinates; 2097c0d900a5SMatthew G. Knepley PetscSection coordSection, sectionCell; 2098c0d900a5SMatthew G. Knepley PetscScalar *cgeom; 2099c0d900a5SMatthew G. Knepley PetscInt cStart, cEnd, cMax, c; 2100c0d900a5SMatthew G. Knepley PetscErrorCode ierr; 2101c0d900a5SMatthew G. Knepley 2102c0d900a5SMatthew G. Knepley PetscFunctionBegin; 2103c0d900a5SMatthew G. Knepley ierr = DMClone(dm, &dmCell);CHKERRQ(ierr); 2104c0d900a5SMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 2105c0d900a5SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 2106c0d900a5SMatthew G. Knepley ierr = DMSetCoordinateSection(dmCell, PETSC_DETERMINE, coordSection);CHKERRQ(ierr); 2107c0d900a5SMatthew G. Knepley ierr = DMSetCoordinatesLocal(dmCell, coordinates);CHKERRQ(ierr); 2108c0d900a5SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ionCell);CHKERRQ(ierr); 2109c0d900a5SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2110c0d900a5SMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 2111c0d900a5SMatthew G. Knepley cEnd = cMax < 0 ? cEnd : cMax; 2112c0d900a5SMatthew G. Knepley ierr = PetscSectionSetChart(sectionCell, cStart, cEnd);CHKERRQ(ierr); 2113c0d900a5SMatthew G. Knepley /* TODO This needs to be multiplied by Nq for non-affine */ 2114cf0b7c11SKarl Rupp for (c = cStart; c < cEnd; ++c) {ierr = PetscSectionSetDof(sectionCell, c, (PetscInt) PetscCeilReal(((PetscReal) sizeof(PetscFEGeom))/sizeof(PetscScalar)));CHKERRQ(ierr);} 2115c0d900a5SMatthew G. Knepley ierr = PetscSectionSetUp(sectionCell);CHKERRQ(ierr); 211692fd8e1eSJed Brown ierr = DMSetLocalSection(dmCell, sectionCell);CHKERRQ(ierr); 2117c0d900a5SMatthew G. Knepley ierr = PetscSectionDestroy(§ionCell);CHKERRQ(ierr); 2118c0d900a5SMatthew G. Knepley ierr = DMCreateLocalVector(dmCell, cellgeom);CHKERRQ(ierr); 2119c0d900a5SMatthew G. Knepley ierr = VecGetArray(*cellgeom, &cgeom);CHKERRQ(ierr); 2120c0d900a5SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 2121cf0b7c11SKarl Rupp PetscFEGeom *cg; 2122c0d900a5SMatthew G. Knepley 2123c0d900a5SMatthew G. Knepley ierr = DMPlexPointLocalRef(dmCell, c, cgeom, &cg);CHKERRQ(ierr); 2124580bdb30SBarry Smith ierr = PetscArrayzero(cg, 1);CHKERRQ(ierr); 2125cf0b7c11SKarl Rupp ierr = DMPlexComputeCellGeometryFEM(dmCell, c, NULL, cg->v, cg->J, cg->invJ, cg->detJ);CHKERRQ(ierr); 2126087ef6b2SMatthew G. Knepley if (*cg->detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double) *cg->detJ, c); 2127c0d900a5SMatthew G. Knepley } 2128c0d900a5SMatthew G. Knepley PetscFunctionReturn(0); 2129c0d900a5SMatthew G. Knepley } 2130c0d900a5SMatthew G. Knepley 2131891a9168SMatthew G. Knepley /*@ 2132891a9168SMatthew G. Knepley DMPlexComputeGeometryFVM - Computes the cell and face geometry for a finite volume method 2133891a9168SMatthew G. Knepley 2134891a9168SMatthew G. Knepley Input Parameter: 2135891a9168SMatthew G. Knepley . dm - The DM 2136891a9168SMatthew G. Knepley 2137891a9168SMatthew G. Knepley Output Parameters: 2138891a9168SMatthew G. Knepley + cellgeom - A Vec of PetscFVCellGeom data 2139a2b725a8SWilliam Gropp - facegeom - A Vec of PetscFVFaceGeom data 2140891a9168SMatthew G. Knepley 2141891a9168SMatthew G. Knepley Level: developer 2142891a9168SMatthew G. Knepley 2143891a9168SMatthew G. Knepley .seealso: PetscFVFaceGeom, PetscFVCellGeom, DMPlexComputeGeometryFEM() 2144891a9168SMatthew G. Knepley @*/ 2145113c68e6SMatthew G. Knepley PetscErrorCode DMPlexComputeGeometryFVM(DM dm, Vec *cellgeom, Vec *facegeom) 2146113c68e6SMatthew G. Knepley { 2147113c68e6SMatthew G. Knepley DM dmFace, dmCell; 2148113c68e6SMatthew G. Knepley DMLabel ghostLabel; 2149113c68e6SMatthew G. Knepley PetscSection sectionFace, sectionCell; 2150113c68e6SMatthew G. Knepley PetscSection coordSection; 2151113c68e6SMatthew G. Knepley Vec coordinates; 2152113c68e6SMatthew G. Knepley PetscScalar *fgeom, *cgeom; 2153113c68e6SMatthew G. Knepley PetscReal minradius, gminradius; 2154113c68e6SMatthew G. Knepley PetscInt dim, cStart, cEnd, cEndInterior, c, fStart, fEnd, f; 2155113c68e6SMatthew G. Knepley PetscErrorCode ierr; 2156113c68e6SMatthew G. Knepley 2157113c68e6SMatthew G. Knepley PetscFunctionBegin; 2158113c68e6SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2159113c68e6SMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 2160113c68e6SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 2161113c68e6SMatthew G. Knepley /* Make cell centroids and volumes */ 2162113c68e6SMatthew G. Knepley ierr = DMClone(dm, &dmCell);CHKERRQ(ierr); 2163113c68e6SMatthew G. Knepley ierr = DMSetCoordinateSection(dmCell, PETSC_DETERMINE, coordSection);CHKERRQ(ierr); 2164113c68e6SMatthew G. Knepley ierr = DMSetCoordinatesLocal(dmCell, coordinates);CHKERRQ(ierr); 2165113c68e6SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ionCell);CHKERRQ(ierr); 2166113c68e6SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2167485ad865SMatthew G. Knepley ierr = DMPlexGetGhostCellStratum(dm, &cEndInterior, NULL);CHKERRQ(ierr); 2168113c68e6SMatthew G. Knepley ierr = PetscSectionSetChart(sectionCell, cStart, cEnd);CHKERRQ(ierr); 21699e5edeeeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {ierr = PetscSectionSetDof(sectionCell, c, (PetscInt) PetscCeilReal(((PetscReal) sizeof(PetscFVCellGeom))/sizeof(PetscScalar)));CHKERRQ(ierr);} 2170113c68e6SMatthew G. Knepley ierr = PetscSectionSetUp(sectionCell);CHKERRQ(ierr); 217192fd8e1eSJed Brown ierr = DMSetLocalSection(dmCell, sectionCell);CHKERRQ(ierr); 2172113c68e6SMatthew G. Knepley ierr = PetscSectionDestroy(§ionCell);CHKERRQ(ierr); 2173113c68e6SMatthew G. Knepley ierr = DMCreateLocalVector(dmCell, cellgeom);CHKERRQ(ierr); 2174485ad865SMatthew G. Knepley if (cEndInterior < 0) cEndInterior = cEnd; 2175113c68e6SMatthew G. Knepley ierr = VecGetArray(*cellgeom, &cgeom);CHKERRQ(ierr); 2176113c68e6SMatthew G. Knepley for (c = cStart; c < cEndInterior; ++c) { 2177113c68e6SMatthew G. Knepley PetscFVCellGeom *cg; 2178113c68e6SMatthew G. Knepley 2179113c68e6SMatthew G. Knepley ierr = DMPlexPointLocalRef(dmCell, c, cgeom, &cg);CHKERRQ(ierr); 2180580bdb30SBarry Smith ierr = PetscArrayzero(cg, 1);CHKERRQ(ierr); 2181113c68e6SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFVM(dmCell, c, &cg->volume, cg->centroid, NULL);CHKERRQ(ierr); 2182113c68e6SMatthew G. Knepley } 2183113c68e6SMatthew G. Knepley /* Compute face normals and minimum cell radius */ 2184113c68e6SMatthew G. Knepley ierr = DMClone(dm, &dmFace);CHKERRQ(ierr); 2185113c68e6SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ionFace);CHKERRQ(ierr); 2186113c68e6SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 2187113c68e6SMatthew G. Knepley ierr = PetscSectionSetChart(sectionFace, fStart, fEnd);CHKERRQ(ierr); 21889e5edeeeSMatthew G. Knepley for (f = fStart; f < fEnd; ++f) {ierr = PetscSectionSetDof(sectionFace, f, (PetscInt) PetscCeilReal(((PetscReal) sizeof(PetscFVFaceGeom))/sizeof(PetscScalar)));CHKERRQ(ierr);} 2189113c68e6SMatthew G. Knepley ierr = PetscSectionSetUp(sectionFace);CHKERRQ(ierr); 219092fd8e1eSJed Brown ierr = DMSetLocalSection(dmFace, sectionFace);CHKERRQ(ierr); 2191113c68e6SMatthew G. Knepley ierr = PetscSectionDestroy(§ionFace);CHKERRQ(ierr); 2192113c68e6SMatthew G. Knepley ierr = DMCreateLocalVector(dmFace, facegeom);CHKERRQ(ierr); 2193113c68e6SMatthew G. Knepley ierr = VecGetArray(*facegeom, &fgeom);CHKERRQ(ierr); 2194c58f1c22SToby Isaac ierr = DMGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr); 2195113c68e6SMatthew G. Knepley minradius = PETSC_MAX_REAL; 2196113c68e6SMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 2197113c68e6SMatthew G. Knepley PetscFVFaceGeom *fg; 2198113c68e6SMatthew G. Knepley PetscReal area; 219950d63984SToby Isaac PetscInt ghost = -1, d, numChildren; 2200113c68e6SMatthew G. Knepley 22019ac3fadcSMatthew G. Knepley if (ghostLabel) {ierr = DMLabelGetValue(ghostLabel, f, &ghost);CHKERRQ(ierr);} 220250d63984SToby Isaac ierr = DMPlexGetTreeChildren(dm,f,&numChildren,NULL);CHKERRQ(ierr); 220350d63984SToby Isaac if (ghost >= 0 || numChildren) continue; 2204113c68e6SMatthew G. Knepley ierr = DMPlexPointLocalRef(dmFace, f, fgeom, &fg);CHKERRQ(ierr); 2205113c68e6SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFVM(dm, f, &area, fg->centroid, fg->normal);CHKERRQ(ierr); 2206113c68e6SMatthew G. Knepley for (d = 0; d < dim; ++d) fg->normal[d] *= area; 2207113c68e6SMatthew G. Knepley /* Flip face orientation if necessary to match ordering in support, and Update minimum radius */ 2208113c68e6SMatthew G. Knepley { 2209113c68e6SMatthew G. Knepley PetscFVCellGeom *cL, *cR; 221006348e87SToby Isaac PetscInt ncells; 2211113c68e6SMatthew G. Knepley const PetscInt *cells; 2212113c68e6SMatthew G. Knepley PetscReal *lcentroid, *rcentroid; 22130453c0cdSMatthew G. Knepley PetscReal l[3], r[3], v[3]; 2214113c68e6SMatthew G. Knepley 2215113c68e6SMatthew G. Knepley ierr = DMPlexGetSupport(dm, f, &cells);CHKERRQ(ierr); 221606348e87SToby Isaac ierr = DMPlexGetSupportSize(dm, f, &ncells);CHKERRQ(ierr); 2217113c68e6SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmCell, cells[0], cgeom, &cL);CHKERRQ(ierr); 2218113c68e6SMatthew G. Knepley lcentroid = cells[0] >= cEndInterior ? fg->centroid : cL->centroid; 221906348e87SToby Isaac if (ncells > 1) { 222006348e87SToby Isaac ierr = DMPlexPointLocalRead(dmCell, cells[1], cgeom, &cR);CHKERRQ(ierr); 2221113c68e6SMatthew G. Knepley rcentroid = cells[1] >= cEndInterior ? fg->centroid : cR->centroid; 222206348e87SToby Isaac } 222306348e87SToby Isaac else { 222406348e87SToby Isaac rcentroid = fg->centroid; 222506348e87SToby Isaac } 22262e17dfb7SMatthew G. Knepley ierr = DMLocalizeCoordinateReal_Internal(dm, dim, fg->centroid, lcentroid, l);CHKERRQ(ierr); 22272e17dfb7SMatthew G. Knepley ierr = DMLocalizeCoordinateReal_Internal(dm, dim, fg->centroid, rcentroid, r);CHKERRQ(ierr); 22280453c0cdSMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, l, r, v); 2229113c68e6SMatthew G. Knepley if (DMPlex_DotRealD_Internal(dim, fg->normal, v) < 0) { 2230113c68e6SMatthew G. Knepley for (d = 0; d < dim; ++d) fg->normal[d] = -fg->normal[d]; 2231113c68e6SMatthew G. Knepley } 2232113c68e6SMatthew G. Knepley if (DMPlex_DotRealD_Internal(dim, fg->normal, v) <= 0) { 2233113c68e6SMatthew G. Knepley if (dim == 2) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Direction for face %d could not be fixed, normal (%g,%g) v (%g,%g)", f, (double) fg->normal[0], (double) fg->normal[1], (double) v[0], (double) v[1]); 2234113c68e6SMatthew G. Knepley if (dim == 3) SETERRQ7(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Direction for face %d could not be fixed, normal (%g,%g,%g) v (%g,%g,%g)", f, (double) fg->normal[0], (double) fg->normal[1], (double) fg->normal[2], (double) v[0], (double) v[1], (double) v[2]); 2235113c68e6SMatthew G. Knepley SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Direction for face %d could not be fixed", f); 2236113c68e6SMatthew G. Knepley } 2237113c68e6SMatthew G. Knepley if (cells[0] < cEndInterior) { 2238113c68e6SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, fg->centroid, cL->centroid, v); 2239113c68e6SMatthew G. Knepley minradius = PetscMin(minradius, DMPlex_NormD_Internal(dim, v)); 2240113c68e6SMatthew G. Knepley } 224106348e87SToby Isaac if (ncells > 1 && cells[1] < cEndInterior) { 2242113c68e6SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, fg->centroid, cR->centroid, v); 2243113c68e6SMatthew G. Knepley minradius = PetscMin(minradius, DMPlex_NormD_Internal(dim, v)); 2244113c68e6SMatthew G. Knepley } 2245113c68e6SMatthew G. Knepley } 2246113c68e6SMatthew G. Knepley } 2247b2566f29SBarry Smith ierr = MPIU_Allreduce(&minradius, &gminradius, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 2248113c68e6SMatthew G. Knepley ierr = DMPlexSetMinRadius(dm, gminradius);CHKERRQ(ierr); 2249113c68e6SMatthew G. Knepley /* Compute centroids of ghost cells */ 2250113c68e6SMatthew G. Knepley for (c = cEndInterior; c < cEnd; ++c) { 2251113c68e6SMatthew G. Knepley PetscFVFaceGeom *fg; 2252113c68e6SMatthew G. Knepley const PetscInt *cone, *support; 2253113c68e6SMatthew G. Knepley PetscInt coneSize, supportSize, s; 2254113c68e6SMatthew G. Knepley 2255113c68e6SMatthew G. Knepley ierr = DMPlexGetConeSize(dmCell, c, &coneSize);CHKERRQ(ierr); 2256113c68e6SMatthew G. Knepley if (coneSize != 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Ghost cell %d has cone size %d != 1", c, coneSize); 2257113c68e6SMatthew G. Knepley ierr = DMPlexGetCone(dmCell, c, &cone);CHKERRQ(ierr); 2258113c68e6SMatthew G. Knepley ierr = DMPlexGetSupportSize(dmCell, cone[0], &supportSize);CHKERRQ(ierr); 225950d63984SToby Isaac if (supportSize != 2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d has support size %d != 2", cone[0], supportSize); 2260113c68e6SMatthew G. Knepley ierr = DMPlexGetSupport(dmCell, cone[0], &support);CHKERRQ(ierr); 2261113c68e6SMatthew G. Knepley ierr = DMPlexPointLocalRef(dmFace, cone[0], fgeom, &fg);CHKERRQ(ierr); 2262113c68e6SMatthew G. Knepley for (s = 0; s < 2; ++s) { 2263113c68e6SMatthew G. Knepley /* Reflect ghost centroid across plane of face */ 2264113c68e6SMatthew G. Knepley if (support[s] == c) { 2265640bce14SSatish Balay PetscFVCellGeom *ci; 2266113c68e6SMatthew G. Knepley PetscFVCellGeom *cg; 2267113c68e6SMatthew G. Knepley PetscReal c2f[3], a; 2268113c68e6SMatthew G. Knepley 2269113c68e6SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmCell, support[(s+1)%2], cgeom, &ci);CHKERRQ(ierr); 2270113c68e6SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, ci->centroid, fg->centroid, c2f); /* cell to face centroid */ 2271113c68e6SMatthew G. Knepley a = DMPlex_DotRealD_Internal(dim, c2f, fg->normal)/DMPlex_DotRealD_Internal(dim, fg->normal, fg->normal); 2272113c68e6SMatthew G. Knepley ierr = DMPlexPointLocalRef(dmCell, support[s], cgeom, &cg);CHKERRQ(ierr); 2273113c68e6SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, 2*a, fg->normal, ci->centroid, cg->centroid); 2274113c68e6SMatthew G. Knepley cg->volume = ci->volume; 2275113c68e6SMatthew G. Knepley } 2276113c68e6SMatthew G. Knepley } 2277113c68e6SMatthew G. Knepley } 2278113c68e6SMatthew G. Knepley ierr = VecRestoreArray(*facegeom, &fgeom);CHKERRQ(ierr); 2279113c68e6SMatthew G. Knepley ierr = VecRestoreArray(*cellgeom, &cgeom);CHKERRQ(ierr); 2280113c68e6SMatthew G. Knepley ierr = DMDestroy(&dmCell);CHKERRQ(ierr); 2281113c68e6SMatthew G. Knepley ierr = DMDestroy(&dmFace);CHKERRQ(ierr); 2282113c68e6SMatthew G. Knepley PetscFunctionReturn(0); 2283113c68e6SMatthew G. Knepley } 2284113c68e6SMatthew G. Knepley 2285113c68e6SMatthew G. Knepley /*@C 2286113c68e6SMatthew G. Knepley DMPlexGetMinRadius - Returns the minimum distance from any cell centroid to a face 2287113c68e6SMatthew G. Knepley 2288113c68e6SMatthew G. Knepley Not collective 2289113c68e6SMatthew G. Knepley 2290113c68e6SMatthew G. Knepley Input Argument: 2291113c68e6SMatthew G. Knepley . dm - the DM 2292113c68e6SMatthew G. Knepley 2293113c68e6SMatthew G. Knepley Output Argument: 2294113c68e6SMatthew G. Knepley . minradius - the minium cell radius 2295113c68e6SMatthew G. Knepley 2296113c68e6SMatthew G. Knepley Level: developer 2297113c68e6SMatthew G. Knepley 2298113c68e6SMatthew G. Knepley .seealso: DMGetCoordinates() 2299113c68e6SMatthew G. Knepley @*/ 2300113c68e6SMatthew G. Knepley PetscErrorCode DMPlexGetMinRadius(DM dm, PetscReal *minradius) 2301113c68e6SMatthew G. Knepley { 2302113c68e6SMatthew G. Knepley PetscFunctionBegin; 2303113c68e6SMatthew G. Knepley PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2304113c68e6SMatthew G. Knepley PetscValidPointer(minradius,2); 2305113c68e6SMatthew G. Knepley *minradius = ((DM_Plex*) dm->data)->minradius; 2306113c68e6SMatthew G. Knepley PetscFunctionReturn(0); 2307113c68e6SMatthew G. Knepley } 2308113c68e6SMatthew G. Knepley 2309113c68e6SMatthew G. Knepley /*@C 2310113c68e6SMatthew G. Knepley DMPlexSetMinRadius - Sets the minimum distance from the cell centroid to a face 2311113c68e6SMatthew G. Knepley 2312113c68e6SMatthew G. Knepley Logically collective 2313113c68e6SMatthew G. Knepley 2314113c68e6SMatthew G. Knepley Input Arguments: 2315113c68e6SMatthew G. Knepley + dm - the DM 2316113c68e6SMatthew G. Knepley - minradius - the minium cell radius 2317113c68e6SMatthew G. Knepley 2318113c68e6SMatthew G. Knepley Level: developer 2319113c68e6SMatthew G. Knepley 2320113c68e6SMatthew G. Knepley .seealso: DMSetCoordinates() 2321113c68e6SMatthew G. Knepley @*/ 2322113c68e6SMatthew G. Knepley PetscErrorCode DMPlexSetMinRadius(DM dm, PetscReal minradius) 2323113c68e6SMatthew G. Knepley { 2324113c68e6SMatthew G. Knepley PetscFunctionBegin; 2325113c68e6SMatthew G. Knepley PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2326113c68e6SMatthew G. Knepley ((DM_Plex*) dm->data)->minradius = minradius; 2327113c68e6SMatthew G. Knepley PetscFunctionReturn(0); 2328113c68e6SMatthew G. Knepley } 2329856ac710SMatthew G. Knepley 2330856ac710SMatthew G. Knepley static PetscErrorCode BuildGradientReconstruction_Internal(DM dm, PetscFV fvm, DM dmFace, PetscScalar *fgeom, DM dmCell, PetscScalar *cgeom) 2331856ac710SMatthew G. Knepley { 2332856ac710SMatthew G. Knepley DMLabel ghostLabel; 2333856ac710SMatthew G. Knepley PetscScalar *dx, *grad, **gref; 2334856ac710SMatthew G. Knepley PetscInt dim, cStart, cEnd, c, cEndInterior, maxNumFaces; 2335856ac710SMatthew G. Knepley PetscErrorCode ierr; 2336856ac710SMatthew G. Knepley 2337856ac710SMatthew G. Knepley PetscFunctionBegin; 2338856ac710SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2339856ac710SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2340485ad865SMatthew G. Knepley ierr = DMPlexGetGhostCellStratum(dm, &cEndInterior, NULL);CHKERRQ(ierr); 2341856ac710SMatthew G. Knepley ierr = DMPlexGetMaxSizes(dm, &maxNumFaces, NULL);CHKERRQ(ierr); 2342856ac710SMatthew G. Knepley ierr = PetscFVLeastSquaresSetMaxFaces(fvm, maxNumFaces);CHKERRQ(ierr); 2343c58f1c22SToby Isaac ierr = DMGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr); 2344856ac710SMatthew G. Knepley ierr = PetscMalloc3(maxNumFaces*dim, &dx, maxNumFaces*dim, &grad, maxNumFaces, &gref);CHKERRQ(ierr); 2345856ac710SMatthew G. Knepley for (c = cStart; c < cEndInterior; c++) { 2346856ac710SMatthew G. Knepley const PetscInt *faces; 2347856ac710SMatthew G. Knepley PetscInt numFaces, usedFaces, f, d; 2348640bce14SSatish Balay PetscFVCellGeom *cg; 2349856ac710SMatthew G. Knepley PetscBool boundary; 2350856ac710SMatthew G. Knepley PetscInt ghost; 2351856ac710SMatthew G. Knepley 2352856ac710SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmCell, c, cgeom, &cg);CHKERRQ(ierr); 2353856ac710SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &numFaces);CHKERRQ(ierr); 2354856ac710SMatthew G. Knepley ierr = DMPlexGetCone(dm, c, &faces);CHKERRQ(ierr); 2355856ac710SMatthew G. Knepley if (numFaces < dim) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cell %D has only %D faces, not enough for gradient reconstruction", c, numFaces); 2356856ac710SMatthew G. Knepley for (f = 0, usedFaces = 0; f < numFaces; ++f) { 2357640bce14SSatish Balay PetscFVCellGeom *cg1; 2358856ac710SMatthew G. Knepley PetscFVFaceGeom *fg; 2359856ac710SMatthew G. Knepley const PetscInt *fcells; 2360856ac710SMatthew G. Knepley PetscInt ncell, side; 2361856ac710SMatthew G. Knepley 2362856ac710SMatthew G. Knepley ierr = DMLabelGetValue(ghostLabel, faces[f], &ghost);CHKERRQ(ierr); 2363a6ba4734SToby Isaac ierr = DMIsBoundaryPoint(dm, faces[f], &boundary);CHKERRQ(ierr); 2364856ac710SMatthew G. Knepley if ((ghost >= 0) || boundary) continue; 2365856ac710SMatthew G. Knepley ierr = DMPlexGetSupport(dm, faces[f], &fcells);CHKERRQ(ierr); 2366856ac710SMatthew G. Knepley side = (c != fcells[0]); /* c is on left=0 or right=1 of face */ 2367856ac710SMatthew G. Knepley ncell = fcells[!side]; /* the neighbor */ 2368856ac710SMatthew G. Knepley ierr = DMPlexPointLocalRef(dmFace, faces[f], fgeom, &fg);CHKERRQ(ierr); 2369856ac710SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmCell, ncell, cgeom, &cg1);CHKERRQ(ierr); 2370856ac710SMatthew G. Knepley for (d = 0; d < dim; ++d) dx[usedFaces*dim+d] = cg1->centroid[d] - cg->centroid[d]; 2371856ac710SMatthew G. Knepley gref[usedFaces++] = fg->grad[side]; /* Gradient reconstruction term will go here */ 2372856ac710SMatthew G. Knepley } 2373856ac710SMatthew G. Knepley if (!usedFaces) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Mesh contains isolated cell (no neighbors). Is it intentional?"); 2374856ac710SMatthew G. Knepley ierr = PetscFVComputeGradient(fvm, usedFaces, dx, grad);CHKERRQ(ierr); 2375856ac710SMatthew G. Knepley for (f = 0, usedFaces = 0; f < numFaces; ++f) { 2376856ac710SMatthew G. Knepley ierr = DMLabelGetValue(ghostLabel, faces[f], &ghost);CHKERRQ(ierr); 2377a6ba4734SToby Isaac ierr = DMIsBoundaryPoint(dm, faces[f], &boundary);CHKERRQ(ierr); 2378856ac710SMatthew G. Knepley if ((ghost >= 0) || boundary) continue; 2379856ac710SMatthew G. Knepley for (d = 0; d < dim; ++d) gref[usedFaces][d] = grad[usedFaces*dim+d]; 2380856ac710SMatthew G. Knepley ++usedFaces; 2381856ac710SMatthew G. Knepley } 2382856ac710SMatthew G. Knepley } 2383856ac710SMatthew G. Knepley ierr = PetscFree3(dx, grad, gref);CHKERRQ(ierr); 2384856ac710SMatthew G. Knepley PetscFunctionReturn(0); 2385856ac710SMatthew G. Knepley } 2386856ac710SMatthew G. Knepley 2387b81db932SToby Isaac static PetscErrorCode BuildGradientReconstruction_Internal_Tree(DM dm, PetscFV fvm, DM dmFace, PetscScalar *fgeom, DM dmCell, PetscScalar *cgeom) 2388b81db932SToby Isaac { 2389b81db932SToby Isaac DMLabel ghostLabel; 2390b81db932SToby Isaac PetscScalar *dx, *grad, **gref; 2391b81db932SToby Isaac PetscInt dim, cStart, cEnd, c, cEndInterior, fStart, fEnd, f, nStart, nEnd, maxNumFaces = 0; 2392b81db932SToby Isaac PetscSection neighSec; 2393b81db932SToby Isaac PetscInt (*neighbors)[2]; 2394b81db932SToby Isaac PetscInt *counter; 2395b81db932SToby Isaac PetscErrorCode ierr; 2396b81db932SToby Isaac 2397b81db932SToby Isaac PetscFunctionBegin; 2398b81db932SToby Isaac ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2399b81db932SToby Isaac ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2400485ad865SMatthew G. Knepley ierr = DMPlexGetGhostCellStratum(dm, &cEndInterior, NULL);CHKERRQ(ierr); 2401485ad865SMatthew G. Knepley if (cEndInterior < 0) cEndInterior = cEnd; 2402b81db932SToby Isaac ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&neighSec);CHKERRQ(ierr); 2403b81db932SToby Isaac ierr = PetscSectionSetChart(neighSec,cStart,cEndInterior);CHKERRQ(ierr); 2404b81db932SToby Isaac ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 2405c58f1c22SToby Isaac ierr = DMGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr); 2406b81db932SToby Isaac for (f = fStart; f < fEnd; f++) { 2407b81db932SToby Isaac const PetscInt *fcells; 2408b81db932SToby Isaac PetscBool boundary; 24095bc680faSToby Isaac PetscInt ghost = -1; 2410b81db932SToby Isaac PetscInt numChildren, numCells, c; 2411b81db932SToby Isaac 241206348e87SToby Isaac if (ghostLabel) {ierr = DMLabelGetValue(ghostLabel, f, &ghost);CHKERRQ(ierr);} 2413a6ba4734SToby Isaac ierr = DMIsBoundaryPoint(dm, f, &boundary);CHKERRQ(ierr); 2414b81db932SToby Isaac ierr = DMPlexGetTreeChildren(dm, f, &numChildren, NULL);CHKERRQ(ierr); 2415b81db932SToby Isaac if ((ghost >= 0) || boundary || numChildren) continue; 2416b81db932SToby Isaac ierr = DMPlexGetSupportSize(dm, f, &numCells);CHKERRQ(ierr); 241706348e87SToby Isaac if (numCells == 2) { 2418b81db932SToby Isaac ierr = DMPlexGetSupport(dm, f, &fcells);CHKERRQ(ierr); 2419b81db932SToby Isaac for (c = 0; c < 2; c++) { 2420b81db932SToby Isaac PetscInt cell = fcells[c]; 2421b81db932SToby Isaac 2422e6885bbbSToby Isaac if (cell >= cStart && cell < cEndInterior) { 2423b81db932SToby Isaac ierr = PetscSectionAddDof(neighSec,cell,1);CHKERRQ(ierr); 2424b81db932SToby Isaac } 2425b81db932SToby Isaac } 2426b81db932SToby Isaac } 242706348e87SToby Isaac } 2428b81db932SToby Isaac ierr = PetscSectionSetUp(neighSec);CHKERRQ(ierr); 2429b81db932SToby Isaac ierr = PetscSectionGetMaxDof(neighSec,&maxNumFaces);CHKERRQ(ierr); 2430b81db932SToby Isaac ierr = PetscFVLeastSquaresSetMaxFaces(fvm, maxNumFaces);CHKERRQ(ierr); 2431b81db932SToby Isaac nStart = 0; 2432b81db932SToby Isaac ierr = PetscSectionGetStorageSize(neighSec,&nEnd);CHKERRQ(ierr); 2433b81db932SToby Isaac ierr = PetscMalloc1((nEnd-nStart),&neighbors);CHKERRQ(ierr); 2434b81db932SToby Isaac ierr = PetscCalloc1((cEndInterior-cStart),&counter);CHKERRQ(ierr); 2435b81db932SToby Isaac for (f = fStart; f < fEnd; f++) { 2436b81db932SToby Isaac const PetscInt *fcells; 2437b81db932SToby Isaac PetscBool boundary; 24385bc680faSToby Isaac PetscInt ghost = -1; 2439b81db932SToby Isaac PetscInt numChildren, numCells, c; 2440b81db932SToby Isaac 244106348e87SToby Isaac if (ghostLabel) {ierr = DMLabelGetValue(ghostLabel, f, &ghost);CHKERRQ(ierr);} 2442a6ba4734SToby Isaac ierr = DMIsBoundaryPoint(dm, f, &boundary);CHKERRQ(ierr); 2443b81db932SToby Isaac ierr = DMPlexGetTreeChildren(dm, f, &numChildren, NULL);CHKERRQ(ierr); 2444b81db932SToby Isaac if ((ghost >= 0) || boundary || numChildren) continue; 2445b81db932SToby Isaac ierr = DMPlexGetSupportSize(dm, f, &numCells);CHKERRQ(ierr); 244606348e87SToby Isaac if (numCells == 2) { 2447b81db932SToby Isaac ierr = DMPlexGetSupport(dm, f, &fcells);CHKERRQ(ierr); 2448b81db932SToby Isaac for (c = 0; c < 2; c++) { 2449b81db932SToby Isaac PetscInt cell = fcells[c], off; 2450b81db932SToby Isaac 2451e6885bbbSToby Isaac if (cell >= cStart && cell < cEndInterior) { 2452b81db932SToby Isaac ierr = PetscSectionGetOffset(neighSec,cell,&off);CHKERRQ(ierr); 2453b81db932SToby Isaac off += counter[cell - cStart]++; 2454b81db932SToby Isaac neighbors[off][0] = f; 2455b81db932SToby Isaac neighbors[off][1] = fcells[1 - c]; 2456b81db932SToby Isaac } 2457b81db932SToby Isaac } 2458b81db932SToby Isaac } 245906348e87SToby Isaac } 2460b81db932SToby Isaac ierr = PetscFree(counter);CHKERRQ(ierr); 2461b81db932SToby Isaac ierr = PetscMalloc3(maxNumFaces*dim, &dx, maxNumFaces*dim, &grad, maxNumFaces, &gref);CHKERRQ(ierr); 2462b81db932SToby Isaac for (c = cStart; c < cEndInterior; c++) { 2463317218b9SToby Isaac PetscInt numFaces, f, d, off, ghost = -1; 2464640bce14SSatish Balay PetscFVCellGeom *cg; 2465b81db932SToby Isaac 2466b81db932SToby Isaac ierr = DMPlexPointLocalRead(dmCell, c, cgeom, &cg);CHKERRQ(ierr); 2467b81db932SToby Isaac ierr = PetscSectionGetDof(neighSec, c, &numFaces);CHKERRQ(ierr); 2468b81db932SToby Isaac ierr = PetscSectionGetOffset(neighSec, c, &off);CHKERRQ(ierr); 2469317218b9SToby Isaac if (ghostLabel) {ierr = DMLabelGetValue(ghostLabel, c, &ghost);CHKERRQ(ierr);} 2470317218b9SToby Isaac if (ghost < 0 && numFaces < dim) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cell %D has only %D faces, not enough for gradient reconstruction", c, numFaces); 2471b81db932SToby Isaac for (f = 0; f < numFaces; ++f) { 2472640bce14SSatish Balay PetscFVCellGeom *cg1; 2473b81db932SToby Isaac PetscFVFaceGeom *fg; 2474b81db932SToby Isaac const PetscInt *fcells; 2475b81db932SToby Isaac PetscInt ncell, side, nface; 2476b81db932SToby Isaac 2477b81db932SToby Isaac nface = neighbors[off + f][0]; 2478b81db932SToby Isaac ncell = neighbors[off + f][1]; 2479b81db932SToby Isaac ierr = DMPlexGetSupport(dm,nface,&fcells);CHKERRQ(ierr); 2480b81db932SToby Isaac side = (c != fcells[0]); 2481b81db932SToby Isaac ierr = DMPlexPointLocalRef(dmFace, nface, fgeom, &fg);CHKERRQ(ierr); 2482b81db932SToby Isaac ierr = DMPlexPointLocalRead(dmCell, ncell, cgeom, &cg1);CHKERRQ(ierr); 2483b81db932SToby Isaac for (d = 0; d < dim; ++d) dx[f*dim+d] = cg1->centroid[d] - cg->centroid[d]; 2484b81db932SToby Isaac gref[f] = fg->grad[side]; /* Gradient reconstruction term will go here */ 2485b81db932SToby Isaac } 2486b81db932SToby Isaac ierr = PetscFVComputeGradient(fvm, numFaces, dx, grad);CHKERRQ(ierr); 2487b81db932SToby Isaac for (f = 0; f < numFaces; ++f) { 2488b81db932SToby Isaac for (d = 0; d < dim; ++d) gref[f][d] = grad[f*dim+d]; 2489b81db932SToby Isaac } 2490b81db932SToby Isaac } 2491b81db932SToby Isaac ierr = PetscFree3(dx, grad, gref);CHKERRQ(ierr); 24925fe94518SToby Isaac ierr = PetscSectionDestroy(&neighSec);CHKERRQ(ierr); 2493b81db932SToby Isaac ierr = PetscFree(neighbors);CHKERRQ(ierr); 2494b81db932SToby Isaac PetscFunctionReturn(0); 2495b81db932SToby Isaac } 2496b81db932SToby Isaac 2497856ac710SMatthew G. Knepley /*@ 2498856ac710SMatthew G. Knepley DMPlexComputeGradientFVM - Compute geometric factors for gradient reconstruction, which are stored in the geometry data, and compute layout for gradient data 2499856ac710SMatthew G. Knepley 2500d083f849SBarry Smith Collective on dm 2501856ac710SMatthew G. Knepley 2502856ac710SMatthew G. Knepley Input Arguments: 2503856ac710SMatthew G. Knepley + dm - The DM 2504856ac710SMatthew G. Knepley . fvm - The PetscFV 25058f9f38e3SMatthew G. Knepley . faceGeometry - The face geometry from DMPlexComputeFaceGeometryFVM() 25068f9f38e3SMatthew G. Knepley - cellGeometry - The face geometry from DMPlexComputeCellGeometryFVM() 2507856ac710SMatthew G. Knepley 2508856ac710SMatthew G. Knepley Output Parameters: 2509856ac710SMatthew G. Knepley + faceGeometry - The geometric factors for gradient calculation are inserted 2510856ac710SMatthew G. Knepley - dmGrad - The DM describing the layout of gradient data 2511856ac710SMatthew G. Knepley 2512856ac710SMatthew G. Knepley Level: developer 2513856ac710SMatthew G. Knepley 2514856ac710SMatthew G. Knepley .seealso: DMPlexGetFaceGeometryFVM(), DMPlexGetCellGeometryFVM() 2515856ac710SMatthew G. Knepley @*/ 2516856ac710SMatthew G. Knepley PetscErrorCode DMPlexComputeGradientFVM(DM dm, PetscFV fvm, Vec faceGeometry, Vec cellGeometry, DM *dmGrad) 2517856ac710SMatthew G. Knepley { 2518856ac710SMatthew G. Knepley DM dmFace, dmCell; 2519856ac710SMatthew G. Knepley PetscScalar *fgeom, *cgeom; 2520b81db932SToby Isaac PetscSection sectionGrad, parentSection; 2521856ac710SMatthew G. Knepley PetscInt dim, pdim, cStart, cEnd, cEndInterior, c; 2522856ac710SMatthew G. Knepley PetscErrorCode ierr; 2523856ac710SMatthew G. Knepley 2524856ac710SMatthew G. Knepley PetscFunctionBegin; 2525856ac710SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2526856ac710SMatthew G. Knepley ierr = PetscFVGetNumComponents(fvm, &pdim);CHKERRQ(ierr); 2527856ac710SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2528485ad865SMatthew G. Knepley ierr = DMPlexGetGhostCellStratum(dm, &cEndInterior, NULL);CHKERRQ(ierr); 2529856ac710SMatthew G. Knepley /* Construct the interpolant corresponding to each face from the least-square solution over the cell neighborhood */ 2530856ac710SMatthew G. Knepley ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr); 2531856ac710SMatthew G. Knepley ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr); 2532856ac710SMatthew G. Knepley ierr = VecGetArray(faceGeometry, &fgeom);CHKERRQ(ierr); 2533856ac710SMatthew G. Knepley ierr = VecGetArray(cellGeometry, &cgeom);CHKERRQ(ierr); 2534b81db932SToby Isaac ierr = DMPlexGetTree(dm,&parentSection,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 2535b81db932SToby Isaac if (!parentSection) { 2536856ac710SMatthew G. Knepley ierr = BuildGradientReconstruction_Internal(dm, fvm, dmFace, fgeom, dmCell, cgeom);CHKERRQ(ierr); 2537b5a3613cSMatthew G. Knepley } else { 2538b81db932SToby Isaac ierr = BuildGradientReconstruction_Internal_Tree(dm, fvm, dmFace, fgeom, dmCell, cgeom);CHKERRQ(ierr); 2539b81db932SToby Isaac } 2540856ac710SMatthew G. Knepley ierr = VecRestoreArray(faceGeometry, &fgeom);CHKERRQ(ierr); 2541856ac710SMatthew G. Knepley ierr = VecRestoreArray(cellGeometry, &cgeom);CHKERRQ(ierr); 2542856ac710SMatthew G. Knepley /* Create storage for gradients */ 2543856ac710SMatthew G. Knepley ierr = DMClone(dm, dmGrad);CHKERRQ(ierr); 2544856ac710SMatthew G. Knepley ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), §ionGrad);CHKERRQ(ierr); 2545856ac710SMatthew G. Knepley ierr = PetscSectionSetChart(sectionGrad, cStart, cEnd);CHKERRQ(ierr); 2546856ac710SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {ierr = PetscSectionSetDof(sectionGrad, c, pdim*dim);CHKERRQ(ierr);} 2547856ac710SMatthew G. Knepley ierr = PetscSectionSetUp(sectionGrad);CHKERRQ(ierr); 254892fd8e1eSJed Brown ierr = DMSetLocalSection(*dmGrad, sectionGrad);CHKERRQ(ierr); 2549856ac710SMatthew G. Knepley ierr = PetscSectionDestroy(§ionGrad);CHKERRQ(ierr); 2550856ac710SMatthew G. Knepley PetscFunctionReturn(0); 2551856ac710SMatthew G. Knepley } 2552b27d5b9eSToby Isaac 2553c501906fSMatthew G. Knepley /*@ 2554c501906fSMatthew G. Knepley DMPlexGetDataFVM - Retrieve precomputed cell geometry 2555c501906fSMatthew G. Knepley 2556d083f849SBarry Smith Collective on dm 2557c501906fSMatthew G. Knepley 2558c501906fSMatthew G. Knepley Input Arguments: 2559c501906fSMatthew G. Knepley + dm - The DM 2560c501906fSMatthew G. Knepley - fvm - The PetscFV 2561c501906fSMatthew G. Knepley 2562c501906fSMatthew G. Knepley Output Parameters: 2563c501906fSMatthew G. Knepley + cellGeometry - The cell geometry 2564c501906fSMatthew G. Knepley . faceGeometry - The face geometry 2565c501906fSMatthew G. Knepley - dmGrad - The gradient matrices 2566c501906fSMatthew G. Knepley 2567c501906fSMatthew G. Knepley Level: developer 2568c501906fSMatthew G. Knepley 2569c501906fSMatthew G. Knepley .seealso: DMPlexComputeGeometryFVM() 2570c501906fSMatthew G. Knepley @*/ 2571b27d5b9eSToby Isaac PetscErrorCode DMPlexGetDataFVM(DM dm, PetscFV fv, Vec *cellgeom, Vec *facegeom, DM *gradDM) 2572b27d5b9eSToby Isaac { 2573b27d5b9eSToby Isaac PetscObject cellgeomobj, facegeomobj; 2574b27d5b9eSToby Isaac PetscErrorCode ierr; 2575b27d5b9eSToby Isaac 2576b27d5b9eSToby Isaac PetscFunctionBegin; 2577b27d5b9eSToby Isaac ierr = PetscObjectQuery((PetscObject) dm, "DMPlex_cellgeom_fvm", &cellgeomobj);CHKERRQ(ierr); 2578b27d5b9eSToby Isaac if (!cellgeomobj) { 2579b27d5b9eSToby Isaac Vec cellgeomInt, facegeomInt; 2580b27d5b9eSToby Isaac 2581b27d5b9eSToby Isaac ierr = DMPlexComputeGeometryFVM(dm, &cellgeomInt, &facegeomInt);CHKERRQ(ierr); 2582b27d5b9eSToby Isaac ierr = PetscObjectCompose((PetscObject) dm, "DMPlex_cellgeom_fvm",(PetscObject)cellgeomInt);CHKERRQ(ierr); 2583b27d5b9eSToby Isaac ierr = PetscObjectCompose((PetscObject) dm, "DMPlex_facegeom_fvm",(PetscObject)facegeomInt);CHKERRQ(ierr); 2584b27d5b9eSToby Isaac ierr = VecDestroy(&cellgeomInt);CHKERRQ(ierr); 2585b27d5b9eSToby Isaac ierr = VecDestroy(&facegeomInt);CHKERRQ(ierr); 2586b27d5b9eSToby Isaac ierr = PetscObjectQuery((PetscObject) dm, "DMPlex_cellgeom_fvm", &cellgeomobj);CHKERRQ(ierr); 2587b27d5b9eSToby Isaac } 2588b27d5b9eSToby Isaac ierr = PetscObjectQuery((PetscObject) dm, "DMPlex_facegeom_fvm", &facegeomobj);CHKERRQ(ierr); 2589b27d5b9eSToby Isaac if (cellgeom) *cellgeom = (Vec) cellgeomobj; 2590b27d5b9eSToby Isaac if (facegeom) *facegeom = (Vec) facegeomobj; 2591b27d5b9eSToby Isaac if (gradDM) { 2592b27d5b9eSToby Isaac PetscObject gradobj; 2593b27d5b9eSToby Isaac PetscBool computeGradients; 2594b27d5b9eSToby Isaac 2595b27d5b9eSToby Isaac ierr = PetscFVGetComputeGradients(fv,&computeGradients);CHKERRQ(ierr); 2596b27d5b9eSToby Isaac if (!computeGradients) { 2597b27d5b9eSToby Isaac *gradDM = NULL; 2598b27d5b9eSToby Isaac PetscFunctionReturn(0); 2599b27d5b9eSToby Isaac } 2600b27d5b9eSToby Isaac ierr = PetscObjectQuery((PetscObject) dm, "DMPlex_dmgrad_fvm", &gradobj);CHKERRQ(ierr); 2601b27d5b9eSToby Isaac if (!gradobj) { 2602b27d5b9eSToby Isaac DM dmGradInt; 2603b27d5b9eSToby Isaac 2604b27d5b9eSToby Isaac ierr = DMPlexComputeGradientFVM(dm,fv,(Vec) facegeomobj,(Vec) cellgeomobj,&dmGradInt);CHKERRQ(ierr); 2605b27d5b9eSToby Isaac ierr = PetscObjectCompose((PetscObject) dm, "DMPlex_dmgrad_fvm", (PetscObject)dmGradInt);CHKERRQ(ierr); 2606b27d5b9eSToby Isaac ierr = DMDestroy(&dmGradInt);CHKERRQ(ierr); 2607b27d5b9eSToby Isaac ierr = PetscObjectQuery((PetscObject) dm, "DMPlex_dmgrad_fvm", &gradobj);CHKERRQ(ierr); 2608b27d5b9eSToby Isaac } 2609b27d5b9eSToby Isaac *gradDM = (DM) gradobj; 2610b27d5b9eSToby Isaac } 2611b27d5b9eSToby Isaac PetscFunctionReturn(0); 2612b27d5b9eSToby Isaac } 2613d6143a4eSToby Isaac 26149d150b73SToby Isaac static PetscErrorCode DMPlexCoordinatesToReference_NewtonUpdate(PetscInt dimC, PetscInt dimR, PetscScalar *J, PetscScalar *invJ, PetscScalar *work, PetscReal *resNeg, PetscReal *guess) 26159d150b73SToby Isaac { 26169d150b73SToby Isaac PetscInt l, m; 26179d150b73SToby Isaac 2618cd345991SToby Isaac PetscFunctionBeginHot; 26199d150b73SToby Isaac if (dimC == dimR && dimR <= 3) { 26209d150b73SToby Isaac /* invert Jacobian, multiply */ 26219d150b73SToby Isaac PetscScalar det, idet; 26229d150b73SToby Isaac 26239d150b73SToby Isaac switch (dimR) { 26249d150b73SToby Isaac case 1: 26259d150b73SToby Isaac invJ[0] = 1./ J[0]; 26269d150b73SToby Isaac break; 26279d150b73SToby Isaac case 2: 26289d150b73SToby Isaac det = J[0] * J[3] - J[1] * J[2]; 26299d150b73SToby Isaac idet = 1./det; 26309d150b73SToby Isaac invJ[0] = J[3] * idet; 26319d150b73SToby Isaac invJ[1] = -J[1] * idet; 26329d150b73SToby Isaac invJ[2] = -J[2] * idet; 26339d150b73SToby Isaac invJ[3] = J[0] * idet; 26349d150b73SToby Isaac break; 26359d150b73SToby Isaac case 3: 26369d150b73SToby Isaac { 26379d150b73SToby Isaac invJ[0] = J[4] * J[8] - J[5] * J[7]; 26389d150b73SToby Isaac invJ[1] = J[2] * J[7] - J[1] * J[8]; 26399d150b73SToby Isaac invJ[2] = J[1] * J[5] - J[2] * J[4]; 26409d150b73SToby Isaac det = invJ[0] * J[0] + invJ[1] * J[3] + invJ[2] * J[6]; 26419d150b73SToby Isaac idet = 1./det; 26429d150b73SToby Isaac invJ[0] *= idet; 26439d150b73SToby Isaac invJ[1] *= idet; 26449d150b73SToby Isaac invJ[2] *= idet; 26459d150b73SToby Isaac invJ[3] = idet * (J[5] * J[6] - J[3] * J[8]); 26469d150b73SToby Isaac invJ[4] = idet * (J[0] * J[8] - J[2] * J[6]); 26479d150b73SToby Isaac invJ[5] = idet * (J[2] * J[3] - J[0] * J[5]); 26489d150b73SToby Isaac invJ[6] = idet * (J[3] * J[7] - J[4] * J[6]); 26499d150b73SToby Isaac invJ[7] = idet * (J[1] * J[6] - J[0] * J[7]); 26509d150b73SToby Isaac invJ[8] = idet * (J[0] * J[4] - J[1] * J[3]); 26519d150b73SToby Isaac } 26529d150b73SToby Isaac break; 26539d150b73SToby Isaac } 26549d150b73SToby Isaac for (l = 0; l < dimR; l++) { 26559d150b73SToby Isaac for (m = 0; m < dimC; m++) { 2656c6e120d1SToby Isaac guess[l] += PetscRealPart(invJ[l * dimC + m]) * resNeg[m]; 26579d150b73SToby Isaac } 26589d150b73SToby Isaac } 26599d150b73SToby Isaac } else { 26609d150b73SToby Isaac #if defined(PETSC_USE_COMPLEX) 26619d150b73SToby Isaac char transpose = 'C'; 26629d150b73SToby Isaac #else 26639d150b73SToby Isaac char transpose = 'T'; 26649d150b73SToby Isaac #endif 26659d150b73SToby Isaac PetscBLASInt m = dimR; 26669d150b73SToby Isaac PetscBLASInt n = dimC; 26679d150b73SToby Isaac PetscBLASInt one = 1; 26689d150b73SToby Isaac PetscBLASInt worksize = dimR * dimC, info; 26699d150b73SToby Isaac 26709d150b73SToby Isaac for (l = 0; l < dimC; l++) {invJ[l] = resNeg[l];} 26719d150b73SToby Isaac 26729d150b73SToby Isaac PetscStackCallBLAS("LAPACKgels",LAPACKgels_(&transpose,&m,&n,&one,J,&m,invJ,&n,work,&worksize, &info)); 26739d150b73SToby Isaac if (info != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to GELS"); 26749d150b73SToby Isaac 2675c6e120d1SToby Isaac for (l = 0; l < dimR; l++) {guess[l] += PetscRealPart(invJ[l]);} 26769d150b73SToby Isaac } 26779d150b73SToby Isaac PetscFunctionReturn(0); 26789d150b73SToby Isaac } 26799d150b73SToby Isaac 26809d150b73SToby Isaac static PetscErrorCode DMPlexCoordinatesToReference_Tensor(DM dm, PetscInt cell, PetscInt numPoints, const PetscReal realCoords[], PetscReal refCoords[], Vec coords, PetscInt dimC, PetscInt dimR) 26819d150b73SToby Isaac { 2682c0cbe899SToby Isaac PetscInt coordSize, i, j, k, l, m, maxIts = 7, numV = (1 << dimR); 26839d150b73SToby Isaac PetscScalar *coordsScalar = NULL; 26849d150b73SToby Isaac PetscReal *cellData, *cellCoords, *cellCoeffs, *extJ, *resNeg; 26859d150b73SToby Isaac PetscScalar *J, *invJ, *work; 26869d150b73SToby Isaac PetscErrorCode ierr; 26879d150b73SToby Isaac 26889d150b73SToby Isaac PetscFunctionBegin; 26899d150b73SToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 26909d150b73SToby Isaac ierr = DMPlexVecGetClosure(dm, NULL, coords, cell, &coordSize, &coordsScalar);CHKERRQ(ierr); 269113903a91SSatish Balay if (coordSize < dimC * numV) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expecting at least %D coordinates, got %D",dimC * (1 << dimR), coordSize); 269269291d52SBarry Smith ierr = DMGetWorkArray(dm, 2 * coordSize + dimR + dimC, MPIU_REAL, &cellData);CHKERRQ(ierr); 269369291d52SBarry Smith ierr = DMGetWorkArray(dm, 3 * dimR * dimC, MPIU_SCALAR, &J);CHKERRQ(ierr); 26949d150b73SToby Isaac cellCoords = &cellData[0]; 26959d150b73SToby Isaac cellCoeffs = &cellData[coordSize]; 26969d150b73SToby Isaac extJ = &cellData[2 * coordSize]; 26979d150b73SToby Isaac resNeg = &cellData[2 * coordSize + dimR]; 26989d150b73SToby Isaac invJ = &J[dimR * dimC]; 26999d150b73SToby Isaac work = &J[2 * dimR * dimC]; 27009d150b73SToby Isaac if (dimR == 2) { 27019d150b73SToby Isaac const PetscInt zToPlex[4] = {0, 1, 3, 2}; 27029d150b73SToby Isaac 27039d150b73SToby Isaac for (i = 0; i < 4; i++) { 27049d150b73SToby Isaac PetscInt plexI = zToPlex[i]; 27059d150b73SToby Isaac 27069d150b73SToby Isaac for (j = 0; j < dimC; j++) { 27079d150b73SToby Isaac cellCoords[dimC * i + j] = PetscRealPart(coordsScalar[dimC * plexI + j]); 27089d150b73SToby Isaac } 27099d150b73SToby Isaac } 27109d150b73SToby Isaac } else if (dimR == 3) { 27119d150b73SToby Isaac const PetscInt zToPlex[8] = {0, 3, 1, 2, 4, 5, 7, 6}; 27129d150b73SToby Isaac 27139d150b73SToby Isaac for (i = 0; i < 8; i++) { 27149d150b73SToby Isaac PetscInt plexI = zToPlex[i]; 27159d150b73SToby Isaac 27169d150b73SToby Isaac for (j = 0; j < dimC; j++) { 27179d150b73SToby Isaac cellCoords[dimC * i + j] = PetscRealPart(coordsScalar[dimC * plexI + j]); 27189d150b73SToby Isaac } 27199d150b73SToby Isaac } 27209d150b73SToby Isaac } else { 27219d150b73SToby Isaac for (i = 0; i < coordSize; i++) {cellCoords[i] = PetscRealPart(coordsScalar[i]);} 27229d150b73SToby Isaac } 27239d150b73SToby Isaac /* Perform the shuffling transform that converts values at the corners of [-1,1]^d to coefficients */ 27249d150b73SToby Isaac for (i = 0; i < dimR; i++) { 27259d150b73SToby Isaac PetscReal *swap; 27269d150b73SToby Isaac 27279d150b73SToby Isaac for (j = 0; j < (numV / 2); j++) { 27289d150b73SToby Isaac for (k = 0; k < dimC; k++) { 27299d150b73SToby Isaac cellCoeffs[dimC * j + k] = 0.5 * (cellCoords[dimC * (2 * j + 1) + k] + cellCoords[dimC * 2 * j + k]); 27309d150b73SToby Isaac cellCoeffs[dimC * (j + (numV / 2)) + k] = 0.5 * (cellCoords[dimC * (2 * j + 1) + k] - cellCoords[dimC * 2 * j + k]); 27319d150b73SToby Isaac } 27329d150b73SToby Isaac } 27339d150b73SToby Isaac 27349d150b73SToby Isaac if (i < dimR - 1) { 27359d150b73SToby Isaac swap = cellCoeffs; 27369d150b73SToby Isaac cellCoeffs = cellCoords; 27379d150b73SToby Isaac cellCoords = swap; 27389d150b73SToby Isaac } 27399d150b73SToby Isaac } 2740580bdb30SBarry Smith ierr = PetscArrayzero(refCoords,numPoints * dimR);CHKERRQ(ierr); 27419d150b73SToby Isaac for (j = 0; j < numPoints; j++) { 27429d150b73SToby Isaac for (i = 0; i < maxIts; i++) { 27439d150b73SToby Isaac PetscReal *guess = &refCoords[dimR * j]; 27449d150b73SToby Isaac 27459d150b73SToby Isaac /* compute -residual and Jacobian */ 27469d150b73SToby Isaac for (k = 0; k < dimC; k++) {resNeg[k] = realCoords[dimC * j + k];} 27479d150b73SToby Isaac for (k = 0; k < dimC * dimR; k++) {J[k] = 0.;} 27489d150b73SToby Isaac for (k = 0; k < numV; k++) { 27499d150b73SToby Isaac PetscReal extCoord = 1.; 27509d150b73SToby Isaac for (l = 0; l < dimR; l++) { 27519d150b73SToby Isaac PetscReal coord = guess[l]; 27529d150b73SToby Isaac PetscInt dep = (k & (1 << l)) >> l; 27539d150b73SToby Isaac 27549d150b73SToby Isaac extCoord *= dep * coord + !dep; 27559d150b73SToby Isaac extJ[l] = dep; 27569d150b73SToby Isaac 27579d150b73SToby Isaac for (m = 0; m < dimR; m++) { 27589d150b73SToby Isaac PetscReal coord = guess[m]; 27599d150b73SToby Isaac PetscInt dep = ((k & (1 << m)) >> m) && (m != l); 27609d150b73SToby Isaac PetscReal mult = dep * coord + !dep; 27619d150b73SToby Isaac 27629d150b73SToby Isaac extJ[l] *= mult; 27639d150b73SToby Isaac } 27649d150b73SToby Isaac } 27659d150b73SToby Isaac for (l = 0; l < dimC; l++) { 27669d150b73SToby Isaac PetscReal coeff = cellCoeffs[dimC * k + l]; 27679d150b73SToby Isaac 27689d150b73SToby Isaac resNeg[l] -= coeff * extCoord; 27699d150b73SToby Isaac for (m = 0; m < dimR; m++) { 27709d150b73SToby Isaac J[dimR * l + m] += coeff * extJ[m]; 27719d150b73SToby Isaac } 27729d150b73SToby Isaac } 27739d150b73SToby Isaac } 27740611203eSToby Isaac #if 0 && defined(PETSC_USE_DEBUG) 27750611203eSToby Isaac { 27760611203eSToby Isaac PetscReal maxAbs = 0.; 27770611203eSToby Isaac 27780611203eSToby Isaac for (l = 0; l < dimC; l++) { 27790611203eSToby Isaac maxAbs = PetscMax(maxAbs,PetscAbsReal(resNeg[l])); 27800611203eSToby Isaac } 2781087ef6b2SMatthew G. Knepley ierr = PetscInfo4(dm,"cell %D, point %D, iter %D: res %g\n",cell,j,i,(double) maxAbs);CHKERRQ(ierr); 27820611203eSToby Isaac } 27830611203eSToby Isaac #endif 27849d150b73SToby Isaac 27859d150b73SToby Isaac ierr = DMPlexCoordinatesToReference_NewtonUpdate(dimC,dimR,J,invJ,work,resNeg,guess);CHKERRQ(ierr); 27869d150b73SToby Isaac } 27879d150b73SToby Isaac } 278869291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 3 * dimR * dimC, MPIU_SCALAR, &J);CHKERRQ(ierr); 278969291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 2 * coordSize + dimR + dimC, MPIU_REAL, &cellData);CHKERRQ(ierr); 27909d150b73SToby Isaac ierr = DMPlexVecRestoreClosure(dm, NULL, coords, cell, &coordSize, &coordsScalar);CHKERRQ(ierr); 27919d150b73SToby Isaac PetscFunctionReturn(0); 27929d150b73SToby Isaac } 27939d150b73SToby Isaac 27949d150b73SToby Isaac static PetscErrorCode DMPlexReferenceToCoordinates_Tensor(DM dm, PetscInt cell, PetscInt numPoints, const PetscReal refCoords[], PetscReal realCoords[], Vec coords, PetscInt dimC, PetscInt dimR) 27959d150b73SToby Isaac { 27969d150b73SToby Isaac PetscInt coordSize, i, j, k, l, numV = (1 << dimR); 27979d150b73SToby Isaac PetscScalar *coordsScalar = NULL; 27989d150b73SToby Isaac PetscReal *cellData, *cellCoords, *cellCoeffs; 27999d150b73SToby Isaac PetscErrorCode ierr; 28009d150b73SToby Isaac 28019d150b73SToby Isaac PetscFunctionBegin; 28029d150b73SToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 28039d150b73SToby Isaac ierr = DMPlexVecGetClosure(dm, NULL, coords, cell, &coordSize, &coordsScalar);CHKERRQ(ierr); 280413903a91SSatish Balay if (coordSize < dimC * numV) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expecting at least %D coordinates, got %D",dimC * (1 << dimR), coordSize); 280569291d52SBarry Smith ierr = DMGetWorkArray(dm, 2 * coordSize, MPIU_REAL, &cellData);CHKERRQ(ierr); 28069d150b73SToby Isaac cellCoords = &cellData[0]; 28079d150b73SToby Isaac cellCoeffs = &cellData[coordSize]; 28089d150b73SToby Isaac if (dimR == 2) { 28099d150b73SToby Isaac const PetscInt zToPlex[4] = {0, 1, 3, 2}; 28109d150b73SToby Isaac 28119d150b73SToby Isaac for (i = 0; i < 4; i++) { 28129d150b73SToby Isaac PetscInt plexI = zToPlex[i]; 28139d150b73SToby Isaac 28149d150b73SToby Isaac for (j = 0; j < dimC; j++) { 28159d150b73SToby Isaac cellCoords[dimC * i + j] = PetscRealPart(coordsScalar[dimC * plexI + j]); 28169d150b73SToby Isaac } 28179d150b73SToby Isaac } 28189d150b73SToby Isaac } else if (dimR == 3) { 28199d150b73SToby Isaac const PetscInt zToPlex[8] = {0, 3, 1, 2, 4, 5, 7, 6}; 28209d150b73SToby Isaac 28219d150b73SToby Isaac for (i = 0; i < 8; i++) { 28229d150b73SToby Isaac PetscInt plexI = zToPlex[i]; 28239d150b73SToby Isaac 28249d150b73SToby Isaac for (j = 0; j < dimC; j++) { 28259d150b73SToby Isaac cellCoords[dimC * i + j] = PetscRealPart(coordsScalar[dimC * plexI + j]); 28269d150b73SToby Isaac } 28279d150b73SToby Isaac } 28289d150b73SToby Isaac } else { 28299d150b73SToby Isaac for (i = 0; i < coordSize; i++) {cellCoords[i] = PetscRealPart(coordsScalar[i]);} 28309d150b73SToby Isaac } 28319d150b73SToby Isaac /* Perform the shuffling transform that converts values at the corners of [-1,1]^d to coefficients */ 28329d150b73SToby Isaac for (i = 0; i < dimR; i++) { 28339d150b73SToby Isaac PetscReal *swap; 28349d150b73SToby Isaac 28359d150b73SToby Isaac for (j = 0; j < (numV / 2); j++) { 28369d150b73SToby Isaac for (k = 0; k < dimC; k++) { 28379d150b73SToby Isaac cellCoeffs[dimC * j + k] = 0.5 * (cellCoords[dimC * (2 * j + 1) + k] + cellCoords[dimC * 2 * j + k]); 28389d150b73SToby Isaac cellCoeffs[dimC * (j + (numV / 2)) + k] = 0.5 * (cellCoords[dimC * (2 * j + 1) + k] - cellCoords[dimC * 2 * j + k]); 28399d150b73SToby Isaac } 28409d150b73SToby Isaac } 28419d150b73SToby Isaac 28429d150b73SToby Isaac if (i < dimR - 1) { 28439d150b73SToby Isaac swap = cellCoeffs; 28449d150b73SToby Isaac cellCoeffs = cellCoords; 28459d150b73SToby Isaac cellCoords = swap; 28469d150b73SToby Isaac } 28479d150b73SToby Isaac } 2848580bdb30SBarry Smith ierr = PetscArrayzero(realCoords,numPoints * dimC);CHKERRQ(ierr); 28499d150b73SToby Isaac for (j = 0; j < numPoints; j++) { 28509d150b73SToby Isaac const PetscReal *guess = &refCoords[dimR * j]; 28519d150b73SToby Isaac PetscReal *mapped = &realCoords[dimC * j]; 28529d150b73SToby Isaac 28539d150b73SToby Isaac for (k = 0; k < numV; k++) { 28549d150b73SToby Isaac PetscReal extCoord = 1.; 28559d150b73SToby Isaac for (l = 0; l < dimR; l++) { 28569d150b73SToby Isaac PetscReal coord = guess[l]; 28579d150b73SToby Isaac PetscInt dep = (k & (1 << l)) >> l; 28589d150b73SToby Isaac 28599d150b73SToby Isaac extCoord *= dep * coord + !dep; 28609d150b73SToby Isaac } 28619d150b73SToby Isaac for (l = 0; l < dimC; l++) { 28629d150b73SToby Isaac PetscReal coeff = cellCoeffs[dimC * k + l]; 28639d150b73SToby Isaac 28649d150b73SToby Isaac mapped[l] += coeff * extCoord; 28659d150b73SToby Isaac } 28669d150b73SToby Isaac } 28679d150b73SToby Isaac } 286869291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 2 * coordSize, MPIU_REAL, &cellData);CHKERRQ(ierr); 28699d150b73SToby Isaac ierr = DMPlexVecRestoreClosure(dm, NULL, coords, cell, &coordSize, &coordsScalar);CHKERRQ(ierr); 28709d150b73SToby Isaac PetscFunctionReturn(0); 28719d150b73SToby Isaac } 28729d150b73SToby Isaac 28739c3cf19fSMatthew G. Knepley /* TODO: TOBY please fix this for Nc > 1 */ 28749c3cf19fSMatthew G. Knepley static PetscErrorCode DMPlexCoordinatesToReference_FE(DM dm, PetscFE fe, PetscInt cell, PetscInt numPoints, const PetscReal realCoords[], PetscReal refCoords[], Vec coords, PetscInt Nc, PetscInt dimR) 28759d150b73SToby Isaac { 28769c3cf19fSMatthew G. Knepley PetscInt numComp, pdim, i, j, k, l, m, maxIter = 7, coordSize; 2877c6e120d1SToby Isaac PetscScalar *nodes = NULL; 2878c6e120d1SToby Isaac PetscReal *invV, *modes; 2879c6e120d1SToby Isaac PetscReal *B, *D, *resNeg; 2880c6e120d1SToby Isaac PetscScalar *J, *invJ, *work; 28819d150b73SToby Isaac PetscErrorCode ierr; 28829d150b73SToby Isaac 28839d150b73SToby Isaac PetscFunctionBegin; 28849c3cf19fSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &pdim);CHKERRQ(ierr); 28859d150b73SToby Isaac ierr = PetscFEGetNumComponents(fe, &numComp);CHKERRQ(ierr); 28869c3cf19fSMatthew G. Knepley if (numComp != Nc) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"coordinate discretization must have as many components (%D) as embedding dimension (!= %D)",numComp,Nc); 28879d150b73SToby Isaac ierr = DMPlexVecGetClosure(dm, NULL, coords, cell, &coordSize, &nodes);CHKERRQ(ierr); 28889d150b73SToby Isaac /* convert nodes to values in the stable evaluation basis */ 288969291d52SBarry Smith ierr = DMGetWorkArray(dm,pdim,MPIU_REAL,&modes);CHKERRQ(ierr); 28909d150b73SToby Isaac invV = fe->invV; 2891012b7cc6SMatthew G. Knepley for (i = 0; i < pdim; ++i) { 2892012b7cc6SMatthew G. Knepley modes[i] = 0.; 2893012b7cc6SMatthew G. Knepley for (j = 0; j < pdim; ++j) { 2894012b7cc6SMatthew G. Knepley modes[i] += invV[i * pdim + j] * PetscRealPart(nodes[j]); 28959d150b73SToby Isaac } 28969d150b73SToby Isaac } 289769291d52SBarry Smith ierr = DMGetWorkArray(dm,pdim * Nc + pdim * Nc * dimR + Nc,MPIU_REAL,&B);CHKERRQ(ierr); 28989c3cf19fSMatthew G. Knepley D = &B[pdim*Nc]; 28999c3cf19fSMatthew G. Knepley resNeg = &D[pdim*Nc * dimR]; 290069291d52SBarry Smith ierr = DMGetWorkArray(dm,3 * Nc * dimR,MPIU_SCALAR,&J);CHKERRQ(ierr); 29019c3cf19fSMatthew G. Knepley invJ = &J[Nc * dimR]; 29029c3cf19fSMatthew G. Knepley work = &invJ[Nc * dimR]; 29039d150b73SToby Isaac for (i = 0; i < numPoints * dimR; i++) {refCoords[i] = 0.;} 29049d150b73SToby Isaac for (j = 0; j < numPoints; j++) { 29059b1f03cbSToby Isaac for (i = 0; i < maxIter; i++) { /* we could batch this so that we're not making big B and D arrays all the time */ 29069d150b73SToby Isaac PetscReal *guess = &refCoords[j * dimR]; 29079d150b73SToby Isaac ierr = PetscSpaceEvaluate(fe->basisSpace, 1, guess, B, D, NULL);CHKERRQ(ierr); 29089c3cf19fSMatthew G. Knepley for (k = 0; k < Nc; k++) {resNeg[k] = realCoords[j * Nc + k];} 29099c3cf19fSMatthew G. Knepley for (k = 0; k < Nc * dimR; k++) {J[k] = 0.;} 29109c3cf19fSMatthew G. Knepley for (k = 0; k < pdim; k++) { 29119c3cf19fSMatthew G. Knepley for (l = 0; l < Nc; l++) { 2912012b7cc6SMatthew G. Knepley resNeg[l] -= modes[k] * B[k * Nc + l]; 29139d150b73SToby Isaac for (m = 0; m < dimR; m++) { 2914012b7cc6SMatthew G. Knepley J[l * dimR + m] += modes[k] * D[(k * Nc + l) * dimR + m]; 29159d150b73SToby Isaac } 29169d150b73SToby Isaac } 29179d150b73SToby Isaac } 29180611203eSToby Isaac #if 0 && defined(PETSC_USE_DEBUG) 29190611203eSToby Isaac { 29200611203eSToby Isaac PetscReal maxAbs = 0.; 29210611203eSToby Isaac 29229c3cf19fSMatthew G. Knepley for (l = 0; l < Nc; l++) { 29230611203eSToby Isaac maxAbs = PetscMax(maxAbs,PetscAbsReal(resNeg[l])); 29240611203eSToby Isaac } 2925087ef6b2SMatthew G. Knepley ierr = PetscInfo4(dm,"cell %D, point %D, iter %D: res %g\n",cell,j,i,(double) maxAbs);CHKERRQ(ierr); 29260611203eSToby Isaac } 29270611203eSToby Isaac #endif 29289c3cf19fSMatthew G. Knepley ierr = DMPlexCoordinatesToReference_NewtonUpdate(Nc,dimR,J,invJ,work,resNeg,guess);CHKERRQ(ierr); 29299d150b73SToby Isaac } 29309d150b73SToby Isaac } 293169291d52SBarry Smith ierr = DMRestoreWorkArray(dm,3 * Nc * dimR,MPIU_SCALAR,&J);CHKERRQ(ierr); 293269291d52SBarry Smith ierr = DMRestoreWorkArray(dm,pdim * Nc + pdim * Nc * dimR + Nc,MPIU_REAL,&B);CHKERRQ(ierr); 293369291d52SBarry Smith ierr = DMRestoreWorkArray(dm,pdim,MPIU_REAL,&modes);CHKERRQ(ierr); 29349d150b73SToby Isaac ierr = DMPlexVecRestoreClosure(dm, NULL, coords, cell, &coordSize, &nodes);CHKERRQ(ierr); 29359d150b73SToby Isaac PetscFunctionReturn(0); 29369d150b73SToby Isaac } 29379d150b73SToby Isaac 29389c3cf19fSMatthew G. Knepley /* TODO: TOBY please fix this for Nc > 1 */ 29399c3cf19fSMatthew G. Knepley static PetscErrorCode DMPlexReferenceToCoordinates_FE(DM dm, PetscFE fe, PetscInt cell, PetscInt numPoints, const PetscReal refCoords[], PetscReal realCoords[], Vec coords, PetscInt Nc, PetscInt dimR) 29409d150b73SToby Isaac { 29419c3cf19fSMatthew G. Knepley PetscInt numComp, pdim, i, j, k, l, coordSize; 2942c6e120d1SToby Isaac PetscScalar *nodes = NULL; 2943c6e120d1SToby Isaac PetscReal *invV, *modes; 29449d150b73SToby Isaac PetscReal *B; 29459d150b73SToby Isaac PetscErrorCode ierr; 29469d150b73SToby Isaac 29479d150b73SToby Isaac PetscFunctionBegin; 29489c3cf19fSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &pdim);CHKERRQ(ierr); 29499d150b73SToby Isaac ierr = PetscFEGetNumComponents(fe, &numComp);CHKERRQ(ierr); 29509c3cf19fSMatthew G. Knepley if (numComp != Nc) SETERRQ2(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"coordinate discretization must have as many components (%D) as embedding dimension (!= %D)",numComp,Nc); 29519d150b73SToby Isaac ierr = DMPlexVecGetClosure(dm, NULL, coords, cell, &coordSize, &nodes);CHKERRQ(ierr); 29529d150b73SToby Isaac /* convert nodes to values in the stable evaluation basis */ 295369291d52SBarry Smith ierr = DMGetWorkArray(dm,pdim,MPIU_REAL,&modes);CHKERRQ(ierr); 29549d150b73SToby Isaac invV = fe->invV; 2955012b7cc6SMatthew G. Knepley for (i = 0; i < pdim; ++i) { 2956012b7cc6SMatthew G. Knepley modes[i] = 0.; 2957012b7cc6SMatthew G. Knepley for (j = 0; j < pdim; ++j) { 2958012b7cc6SMatthew G. Knepley modes[i] += invV[i * pdim + j] * PetscRealPart(nodes[j]); 29599d150b73SToby Isaac } 29609d150b73SToby Isaac } 296169291d52SBarry Smith ierr = DMGetWorkArray(dm,numPoints * pdim * Nc,MPIU_REAL,&B);CHKERRQ(ierr); 2962012b7cc6SMatthew G. Knepley ierr = PetscSpaceEvaluate(fe->basisSpace, numPoints, refCoords, B, NULL, NULL);CHKERRQ(ierr); 29639c3cf19fSMatthew G. Knepley for (i = 0; i < numPoints * Nc; i++) {realCoords[i] = 0.;} 29649d150b73SToby Isaac for (j = 0; j < numPoints; j++) { 29659c3cf19fSMatthew G. Knepley PetscReal *mapped = &realCoords[j * Nc]; 29669d150b73SToby Isaac 29679c3cf19fSMatthew G. Knepley for (k = 0; k < pdim; k++) { 29689c3cf19fSMatthew G. Knepley for (l = 0; l < Nc; l++) { 296940cf36b3SToby Isaac mapped[l] += modes[k] * B[(j * pdim + k) * Nc + l]; 29709d150b73SToby Isaac } 29719d150b73SToby Isaac } 29729d150b73SToby Isaac } 297369291d52SBarry Smith ierr = DMRestoreWorkArray(dm,numPoints * pdim * Nc,MPIU_REAL,&B);CHKERRQ(ierr); 297469291d52SBarry Smith ierr = DMRestoreWorkArray(dm,pdim,MPIU_REAL,&modes);CHKERRQ(ierr); 29759d150b73SToby Isaac ierr = DMPlexVecRestoreClosure(dm, NULL, coords, cell, &coordSize, &nodes);CHKERRQ(ierr); 29769d150b73SToby Isaac PetscFunctionReturn(0); 29779d150b73SToby Isaac } 29789d150b73SToby Isaac 2979d6143a4eSToby Isaac /*@ 2980d6143a4eSToby Isaac DMPlexCoordinatesToReference - Pull coordinates back from the mesh to the reference element using a single element 2981d6143a4eSToby Isaac map. This inversion will be accurate inside the reference element, but may be inaccurate for mappings that do not 2982d6143a4eSToby Isaac extend uniquely outside the reference cell (e.g, most non-affine maps) 2983d6143a4eSToby Isaac 2984d6143a4eSToby Isaac Not collective 2985d6143a4eSToby Isaac 2986d6143a4eSToby Isaac Input Parameters: 2987d6143a4eSToby Isaac + dm - The mesh, with coordinate maps defined either by a PetscDS for the coordinate DM (see DMGetCoordinateDM()) or 2988d6143a4eSToby Isaac implicitly by the coordinates of the corner vertices of the cell: as an affine map for simplicial elements, or 2989d6143a4eSToby Isaac as a multilinear map for tensor-product elements 2990d6143a4eSToby Isaac . cell - the cell whose map is used. 2991d6143a4eSToby Isaac . numPoints - the number of points to locate 29921b266c99SBarry Smith - realCoords - (numPoints x coordinate dimension) array of coordinates (see DMGetCoordinateDim()) 2993d6143a4eSToby Isaac 2994d6143a4eSToby Isaac Output Parameters: 2995d6143a4eSToby Isaac . refCoords - (numPoints x dimension) array of reference coordinates (see DMGetDimension()) 29961b266c99SBarry Smith 29971b266c99SBarry Smith Level: intermediate 299873c9229bSMatthew Knepley 299973c9229bSMatthew Knepley .seealso: DMPlexReferenceToCoordinates() 3000d6143a4eSToby Isaac @*/ 3001d6143a4eSToby Isaac PetscErrorCode DMPlexCoordinatesToReference(DM dm, PetscInt cell, PetscInt numPoints, const PetscReal realCoords[], PetscReal refCoords[]) 3002d6143a4eSToby Isaac { 3003485ad865SMatthew G. Knepley PetscInt dimC, dimR, depth, cStart, cEnd, i; 30049d150b73SToby Isaac DM coordDM = NULL; 30059d150b73SToby Isaac Vec coords; 30069d150b73SToby Isaac PetscFE fe = NULL; 30079d150b73SToby Isaac PetscErrorCode ierr; 30089d150b73SToby Isaac 3009d6143a4eSToby Isaac PetscFunctionBegin; 30109d150b73SToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 30119d150b73SToby Isaac ierr = DMGetDimension(dm,&dimR);CHKERRQ(ierr); 30129d150b73SToby Isaac ierr = DMGetCoordinateDim(dm,&dimC);CHKERRQ(ierr); 30139d150b73SToby Isaac if (dimR <= 0 || dimC <= 0 || numPoints <= 0) PetscFunctionReturn(0); 30149d150b73SToby Isaac ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 30159d150b73SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coords);CHKERRQ(ierr); 30169d150b73SToby Isaac ierr = DMGetCoordinateDM(dm,&coordDM);CHKERRQ(ierr); 30179d150b73SToby Isaac if (coordDM) { 30189d150b73SToby Isaac PetscInt coordFields; 30199d150b73SToby Isaac 30209d150b73SToby Isaac ierr = DMGetNumFields(coordDM,&coordFields);CHKERRQ(ierr); 30219d150b73SToby Isaac if (coordFields) { 30229d150b73SToby Isaac PetscClassId id; 30239d150b73SToby Isaac PetscObject disc; 30249d150b73SToby Isaac 302544a7f3ddSMatthew G. Knepley ierr = DMGetField(coordDM,0,NULL,&disc);CHKERRQ(ierr); 30269d150b73SToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 30279d150b73SToby Isaac if (id == PETSCFE_CLASSID) { 30289d150b73SToby Isaac fe = (PetscFE) disc; 30299d150b73SToby Isaac } 30309d150b73SToby Isaac } 30319d150b73SToby Isaac } 3032485ad865SMatthew G. Knepley ierr = DMPlexGetInteriorCellStratum(dm,&cStart,&cEnd);CHKERRQ(ierr); 303313903a91SSatish Balay if (cell < cStart || cell >= cEnd) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"point %D not in cell range [%D,%D)",cell,cStart,cEnd); 30349d150b73SToby Isaac if (!fe) { /* implicit discretization: affine or multilinear */ 30359d150b73SToby Isaac PetscInt coneSize; 30369d150b73SToby Isaac PetscBool isSimplex, isTensor; 30379d150b73SToby Isaac 30389d150b73SToby Isaac ierr = DMPlexGetConeSize(dm,cell,&coneSize);CHKERRQ(ierr); 30399d150b73SToby Isaac isSimplex = (coneSize == (dimR + 1)) ? PETSC_TRUE : PETSC_FALSE; 30409d150b73SToby Isaac isTensor = (coneSize == ((depth == 1) ? (1 << dimR) : (2 * dimR))) ? PETSC_TRUE : PETSC_FALSE; 30419d150b73SToby Isaac if (isSimplex) { 30429d150b73SToby Isaac PetscReal detJ, *v0, *J, *invJ; 30439d150b73SToby Isaac 304469291d52SBarry Smith ierr = DMGetWorkArray(dm,dimC + 2 * dimC * dimC, MPIU_REAL, &v0);CHKERRQ(ierr); 30459d150b73SToby Isaac J = &v0[dimC]; 30469d150b73SToby Isaac invJ = &J[dimC * dimC]; 30479d150b73SToby Isaac ierr = DMPlexComputeCellGeometryAffineFEM(dm, cell, v0, J, invJ, &detJ);CHKERRQ(ierr); 30489d150b73SToby Isaac for (i = 0; i < numPoints; i++) { /* Apply the inverse affine transformation for each point */ 3049c330f8ffSToby Isaac const PetscReal x0[3] = {-1.,-1.,-1.}; 3050c330f8ffSToby Isaac 3051c330f8ffSToby Isaac CoordinatesRealToRef(dimC, dimR, x0, v0, invJ, &realCoords[dimC * i], &refCoords[dimR * i]); 30529d150b73SToby Isaac } 305369291d52SBarry Smith ierr = DMRestoreWorkArray(dm,dimC + 2 * dimC * dimC, MPIU_REAL, &v0);CHKERRQ(ierr); 30549d150b73SToby Isaac } else if (isTensor) { 30559d150b73SToby Isaac ierr = DMPlexCoordinatesToReference_Tensor(coordDM, cell, numPoints, realCoords, refCoords, coords, dimC, dimR);CHKERRQ(ierr); 30569d150b73SToby Isaac } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unrecognized cone size %D",coneSize); 30579d150b73SToby Isaac } else { 30589d150b73SToby Isaac ierr = DMPlexCoordinatesToReference_FE(coordDM, fe, cell, numPoints, realCoords, refCoords, coords, dimC, dimR);CHKERRQ(ierr); 30599d150b73SToby Isaac } 30609d150b73SToby Isaac PetscFunctionReturn(0); 30619d150b73SToby Isaac } 30629d150b73SToby Isaac 30639d150b73SToby Isaac /*@ 30649d150b73SToby Isaac DMPlexReferenceToCoordinates - Map references coordinates to coordinates in the the mesh for a single element map. 30659d150b73SToby Isaac 30669d150b73SToby Isaac Not collective 30679d150b73SToby Isaac 30689d150b73SToby Isaac Input Parameters: 30699d150b73SToby Isaac + dm - The mesh, with coordinate maps defined either by a PetscDS for the coordinate DM (see DMGetCoordinateDM()) or 30709d150b73SToby Isaac implicitly by the coordinates of the corner vertices of the cell: as an affine map for simplicial elements, or 30719d150b73SToby Isaac as a multilinear map for tensor-product elements 30729d150b73SToby Isaac . cell - the cell whose map is used. 30739d150b73SToby Isaac . numPoints - the number of points to locate 3074a2b725a8SWilliam Gropp - refCoords - (numPoints x dimension) array of reference coordinates (see DMGetDimension()) 30759d150b73SToby Isaac 30769d150b73SToby Isaac Output Parameters: 30779d150b73SToby Isaac . realCoords - (numPoints x coordinate dimension) array of coordinates (see DMGetCoordinateDim()) 30781b266c99SBarry Smith 30791b266c99SBarry Smith Level: intermediate 308073c9229bSMatthew Knepley 308173c9229bSMatthew Knepley .seealso: DMPlexCoordinatesToReference() 30829d150b73SToby Isaac @*/ 30839d150b73SToby Isaac PetscErrorCode DMPlexReferenceToCoordinates(DM dm, PetscInt cell, PetscInt numPoints, const PetscReal refCoords[], PetscReal realCoords[]) 30849d150b73SToby Isaac { 3085485ad865SMatthew G. Knepley PetscInt dimC, dimR, depth, cStart, cEnd, i; 30869d150b73SToby Isaac DM coordDM = NULL; 30879d150b73SToby Isaac Vec coords; 30889d150b73SToby Isaac PetscFE fe = NULL; 30899d150b73SToby Isaac PetscErrorCode ierr; 30909d150b73SToby Isaac 30919d150b73SToby Isaac PetscFunctionBegin; 30929d150b73SToby Isaac PetscValidHeaderSpecific(dm,DM_CLASSID,1); 30939d150b73SToby Isaac ierr = DMGetDimension(dm,&dimR);CHKERRQ(ierr); 30949d150b73SToby Isaac ierr = DMGetCoordinateDim(dm,&dimC);CHKERRQ(ierr); 30959d150b73SToby Isaac if (dimR <= 0 || dimC <= 0 || numPoints <= 0) PetscFunctionReturn(0); 30969d150b73SToby Isaac ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 30979d150b73SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coords);CHKERRQ(ierr); 30989d150b73SToby Isaac ierr = DMGetCoordinateDM(dm,&coordDM);CHKERRQ(ierr); 30999d150b73SToby Isaac if (coordDM) { 31009d150b73SToby Isaac PetscInt coordFields; 31019d150b73SToby Isaac 31029d150b73SToby Isaac ierr = DMGetNumFields(coordDM,&coordFields);CHKERRQ(ierr); 31039d150b73SToby Isaac if (coordFields) { 31049d150b73SToby Isaac PetscClassId id; 31059d150b73SToby Isaac PetscObject disc; 31069d150b73SToby Isaac 310744a7f3ddSMatthew G. Knepley ierr = DMGetField(coordDM,0,NULL,&disc);CHKERRQ(ierr); 31089d150b73SToby Isaac ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr); 31099d150b73SToby Isaac if (id == PETSCFE_CLASSID) { 31109d150b73SToby Isaac fe = (PetscFE) disc; 31119d150b73SToby Isaac } 31129d150b73SToby Isaac } 31139d150b73SToby Isaac } 3114485ad865SMatthew G. Knepley ierr = DMPlexGetInteriorCellStratum(dm,&cStart,&cEnd);CHKERRQ(ierr); 311513903a91SSatish Balay if (cell < cStart || cell >= cEnd) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"point %D not in cell range [%D,%D)",cell,cStart,cEnd); 31169d150b73SToby Isaac if (!fe) { /* implicit discretization: affine or multilinear */ 31179d150b73SToby Isaac PetscInt coneSize; 31189d150b73SToby Isaac PetscBool isSimplex, isTensor; 31199d150b73SToby Isaac 31209d150b73SToby Isaac ierr = DMPlexGetConeSize(dm,cell,&coneSize);CHKERRQ(ierr); 31219d150b73SToby Isaac isSimplex = (coneSize == (dimR + 1)) ? PETSC_TRUE : PETSC_FALSE; 31229d150b73SToby Isaac isTensor = (coneSize == ((depth == 1) ? (1 << dimR) : (2 * dimR))) ? PETSC_TRUE : PETSC_FALSE; 31239d150b73SToby Isaac if (isSimplex) { 31249d150b73SToby Isaac PetscReal detJ, *v0, *J; 31259d150b73SToby Isaac 312669291d52SBarry Smith ierr = DMGetWorkArray(dm,dimC + 2 * dimC * dimC, MPIU_REAL, &v0);CHKERRQ(ierr); 31279d150b73SToby Isaac J = &v0[dimC]; 31289d150b73SToby Isaac ierr = DMPlexComputeCellGeometryAffineFEM(dm, cell, v0, J, NULL, &detJ);CHKERRQ(ierr); 3129c330f8ffSToby Isaac for (i = 0; i < numPoints; i++) { /* Apply the affine transformation for each point */ 3130c330f8ffSToby Isaac const PetscReal xi0[3] = {-1.,-1.,-1.}; 3131c330f8ffSToby Isaac 3132c330f8ffSToby Isaac CoordinatesRefToReal(dimC, dimR, xi0, v0, J, &refCoords[dimR * i], &realCoords[dimC * i]); 31339d150b73SToby Isaac } 313469291d52SBarry Smith ierr = DMRestoreWorkArray(dm,dimC + 2 * dimC * dimC, MPIU_REAL, &v0);CHKERRQ(ierr); 31359d150b73SToby Isaac } else if (isTensor) { 31369d150b73SToby Isaac ierr = DMPlexReferenceToCoordinates_Tensor(coordDM, cell, numPoints, refCoords, realCoords, coords, dimC, dimR);CHKERRQ(ierr); 31379d150b73SToby Isaac } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unrecognized cone size %D",coneSize); 31389d150b73SToby Isaac } else { 31399d150b73SToby Isaac ierr = DMPlexReferenceToCoordinates_FE(coordDM, fe, cell, numPoints, refCoords, realCoords, coords, dimC, dimR);CHKERRQ(ierr); 31409d150b73SToby Isaac } 3141d6143a4eSToby Isaac PetscFunctionReturn(0); 3142d6143a4eSToby Isaac } 31430139fca9SMatthew G. Knepley 31440139fca9SMatthew G. Knepley /*@C 31450139fca9SMatthew G. Knepley DMPlexRemapGeometry - This function maps the original DM coordinates to new coordinates. 31460139fca9SMatthew G. Knepley 31470139fca9SMatthew G. Knepley Not collective 31480139fca9SMatthew G. Knepley 31490139fca9SMatthew G. Knepley Input Parameters: 31500139fca9SMatthew G. Knepley + dm - The DM 31510139fca9SMatthew G. Knepley . time - The time 31520139fca9SMatthew G. Knepley - func - The function transforming current coordinates to new coordaintes 31530139fca9SMatthew G. Knepley 31540139fca9SMatthew G. Knepley Calling sequence of func: 31550139fca9SMatthew G. Knepley $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 31560139fca9SMatthew G. Knepley $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 31570139fca9SMatthew G. Knepley $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 31580139fca9SMatthew G. Knepley $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 31590139fca9SMatthew G. Knepley 31600139fca9SMatthew G. Knepley + dim - The spatial dimension 31610139fca9SMatthew G. Knepley . Nf - The number of input fields (here 1) 31620139fca9SMatthew G. Knepley . NfAux - The number of input auxiliary fields 31630139fca9SMatthew G. Knepley . uOff - The offset of the coordinates in u[] (here 0) 31640139fca9SMatthew G. Knepley . uOff_x - The offset of the coordinates in u_x[] (here 0) 31650139fca9SMatthew G. Knepley . u - The coordinate values at this point in space 31660139fca9SMatthew G. Knepley . u_t - The coordinate time derivative at this point in space (here NULL) 31670139fca9SMatthew G. Knepley . u_x - The coordinate derivatives at this point in space 31680139fca9SMatthew G. Knepley . aOff - The offset of each auxiliary field in u[] 31690139fca9SMatthew G. Knepley . aOff_x - The offset of each auxiliary field in u_x[] 31700139fca9SMatthew G. Knepley . a - The auxiliary field values at this point in space 31710139fca9SMatthew G. Knepley . a_t - The auxiliary field time derivative at this point in space (or NULL) 31720139fca9SMatthew G. Knepley . a_x - The auxiliary field derivatives at this point in space 31730139fca9SMatthew G. Knepley . t - The current time 31740139fca9SMatthew G. Knepley . x - The coordinates of this point (here not used) 31750139fca9SMatthew G. Knepley . numConstants - The number of constants 31760139fca9SMatthew G. Knepley . constants - The value of each constant 31770139fca9SMatthew G. Knepley - f - The new coordinates at this point in space 31780139fca9SMatthew G. Knepley 31790139fca9SMatthew G. Knepley Level: intermediate 31800139fca9SMatthew G. Knepley 31810139fca9SMatthew G. Knepley .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMProjectFieldLocal(), DMProjectFieldLabelLocal() 31820139fca9SMatthew G. Knepley @*/ 31830139fca9SMatthew G. Knepley PetscErrorCode DMPlexRemapGeometry(DM dm, PetscReal time, 31840139fca9SMatthew G. Knepley void (*func)(PetscInt, PetscInt, PetscInt, 31850139fca9SMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 31860139fca9SMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 31870139fca9SMatthew G. Knepley PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[])) 31880139fca9SMatthew G. Knepley { 31890139fca9SMatthew G. Knepley DM cdm; 31900139fca9SMatthew G. Knepley Vec lCoords, tmpCoords; 31910139fca9SMatthew G. Knepley PetscErrorCode ierr; 31920139fca9SMatthew G. Knepley 31930139fca9SMatthew G. Knepley PetscFunctionBegin; 31940139fca9SMatthew G. Knepley ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 31950139fca9SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &lCoords);CHKERRQ(ierr); 31960139fca9SMatthew G. Knepley ierr = DMGetLocalVector(cdm, &tmpCoords);CHKERRQ(ierr); 31970139fca9SMatthew G. Knepley ierr = VecCopy(lCoords, tmpCoords);CHKERRQ(ierr); 31980139fca9SMatthew G. Knepley ierr = DMProjectFieldLocal(cdm, time, tmpCoords, &func, INSERT_VALUES, lCoords);CHKERRQ(ierr); 31990139fca9SMatthew G. Knepley ierr = DMRestoreLocalVector(cdm, &tmpCoords);CHKERRQ(ierr); 32000139fca9SMatthew G. Knepley PetscFunctionReturn(0); 32010139fca9SMatthew G. Knepley } 32020139fca9SMatthew G. Knepley 32030139fca9SMatthew G. Knepley /* Shear applies the transformation, assuming we fix z, 32040139fca9SMatthew G. Knepley / 1 0 m_0 \ 32050139fca9SMatthew G. Knepley | 0 1 m_1 | 32060139fca9SMatthew G. Knepley \ 0 0 1 / 32070139fca9SMatthew G. Knepley */ 32080139fca9SMatthew G. Knepley static void f0_shear(PetscInt dim, PetscInt Nf, PetscInt NfAux, 32090139fca9SMatthew G. Knepley const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 32100139fca9SMatthew G. Knepley const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 32110139fca9SMatthew G. Knepley PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar coords[]) 32120139fca9SMatthew G. Knepley { 32130139fca9SMatthew G. Knepley const PetscInt Nc = uOff[1]-uOff[0]; 3214c1f1bd54SMatthew G. Knepley const PetscInt ax = (PetscInt) PetscRealPart(constants[0]); 32150139fca9SMatthew G. Knepley PetscInt c; 32160139fca9SMatthew G. Knepley 32170139fca9SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 32180139fca9SMatthew G. Knepley coords[c] = u[c] + constants[c+1]*u[ax]; 32190139fca9SMatthew G. Knepley } 32200139fca9SMatthew G. Knepley } 32210139fca9SMatthew G. Knepley 32220139fca9SMatthew G. Knepley /*@C 32230139fca9SMatthew G. Knepley DMPlexShearGeometry - This shears the domain, meaning adds a multiple of the shear coordinate to all other coordinates. 32240139fca9SMatthew G. Knepley 32250139fca9SMatthew G. Knepley Not collective 32260139fca9SMatthew G. Knepley 32270139fca9SMatthew G. Knepley Input Parameters: 32280139fca9SMatthew G. Knepley + dm - The DM 32293ee9839eSMatthew G. Knepley . direction - The shear coordinate direction, e.g. 0 is the x-axis 32300139fca9SMatthew G. Knepley - multipliers - The multiplier m for each direction which is not the shear direction 32310139fca9SMatthew G. Knepley 32320139fca9SMatthew G. Knepley Level: intermediate 32330139fca9SMatthew G. Knepley 32340139fca9SMatthew G. Knepley .seealso: DMPlexRemapGeometry() 32350139fca9SMatthew G. Knepley @*/ 32363ee9839eSMatthew G. Knepley PetscErrorCode DMPlexShearGeometry(DM dm, DMDirection direction, PetscReal multipliers[]) 32370139fca9SMatthew G. Knepley { 32380139fca9SMatthew G. Knepley DM cdm; 32390139fca9SMatthew G. Knepley PetscDS cds; 32400139fca9SMatthew G. Knepley PetscObject obj; 32410139fca9SMatthew G. Knepley PetscClassId id; 32420139fca9SMatthew G. Knepley PetscScalar *moduli; 32433ee9839eSMatthew G. Knepley const PetscInt dir = (PetscInt) direction; 32440139fca9SMatthew G. Knepley PetscInt dE, d, e; 32450139fca9SMatthew G. Knepley PetscErrorCode ierr; 32460139fca9SMatthew G. Knepley 32470139fca9SMatthew G. Knepley PetscFunctionBegin; 32480139fca9SMatthew G. Knepley ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 32490139fca9SMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 32500139fca9SMatthew G. Knepley ierr = PetscMalloc1(dE+1, &moduli);CHKERRQ(ierr); 32510139fca9SMatthew G. Knepley moduli[0] = dir; 32520139fca9SMatthew G. Knepley for (d = 0, e = 0; d < dE; ++d) moduli[d] = d == dir ? 0.0 : (multipliers ? multipliers[e++] : 1.0); 32530139fca9SMatthew G. Knepley ierr = DMGetDS(cdm, &cds);CHKERRQ(ierr); 32540139fca9SMatthew G. Knepley ierr = PetscDSGetDiscretization(cds, 0, &obj);CHKERRQ(ierr); 32550139fca9SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 32560139fca9SMatthew G. Knepley if (id != PETSCFE_CLASSID) { 32570139fca9SMatthew G. Knepley Vec lCoords; 32580139fca9SMatthew G. Knepley PetscSection cSection; 32590139fca9SMatthew G. Knepley PetscScalar *coords; 32600139fca9SMatthew G. Knepley PetscInt vStart, vEnd, v; 32610139fca9SMatthew G. Knepley 32620139fca9SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 32630139fca9SMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 32640139fca9SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &lCoords);CHKERRQ(ierr); 32650139fca9SMatthew G. Knepley ierr = VecGetArray(lCoords, &coords);CHKERRQ(ierr); 32660139fca9SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 32670139fca9SMatthew G. Knepley PetscReal ds; 32680139fca9SMatthew G. Knepley PetscInt off, c; 32690139fca9SMatthew G. Knepley 32700139fca9SMatthew G. Knepley ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 32710139fca9SMatthew G. Knepley ds = PetscRealPart(coords[off+dir]); 32720139fca9SMatthew G. Knepley for (c = 0; c < dE; ++c) coords[off+c] += moduli[c]*ds; 32730139fca9SMatthew G. Knepley } 32740139fca9SMatthew G. Knepley ierr = VecRestoreArray(lCoords, &coords);CHKERRQ(ierr); 32750139fca9SMatthew G. Knepley } else { 32760139fca9SMatthew G. Knepley ierr = PetscDSSetConstants(cds, dE+1, moduli);CHKERRQ(ierr); 32770139fca9SMatthew G. Knepley ierr = DMPlexRemapGeometry(dm, 0.0, f0_shear);CHKERRQ(ierr); 32780139fca9SMatthew G. Knepley } 32790139fca9SMatthew G. Knepley ierr = PetscFree(moduli);CHKERRQ(ierr); 32800139fca9SMatthew G. Knepley PetscFunctionReturn(0); 32810139fca9SMatthew G. Knepley } 3282