1ccd2543fSMatthew G Knepley #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2ccd2543fSMatthew G Knepley 3ccd2543fSMatthew G Knepley #undef __FUNCT__ 4ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D_Internal" 5ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexLocatePoint_Simplex_2D_Internal(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 6ccd2543fSMatthew G Knepley { 7ccd2543fSMatthew G Knepley const PetscInt embedDim = 2; 8ccd2543fSMatthew G Knepley PetscReal x = PetscRealPart(point[0]); 9ccd2543fSMatthew G Knepley PetscReal y = PetscRealPart(point[1]); 10ccd2543fSMatthew G Knepley PetscReal v0[2], J[4], invJ[4], detJ; 11ccd2543fSMatthew G Knepley PetscReal xi, eta; 12ccd2543fSMatthew G Knepley PetscErrorCode ierr; 13ccd2543fSMatthew G Knepley 14ccd2543fSMatthew G Knepley PetscFunctionBegin; 15ccd2543fSMatthew G Knepley ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 16ccd2543fSMatthew G Knepley xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]); 17ccd2543fSMatthew G Knepley eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]); 18ccd2543fSMatthew G Knepley 19ccd2543fSMatthew G Knepley if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) *cell = c; 20ccd2543fSMatthew G Knepley else *cell = -1; 21ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 22ccd2543fSMatthew G Knepley } 23ccd2543fSMatthew G Knepley 24ccd2543fSMatthew G Knepley #undef __FUNCT__ 25ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexLocatePoint_General_2D_Internal" 26ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexLocatePoint_General_2D_Internal(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 27ccd2543fSMatthew G Knepley { 28ccd2543fSMatthew G Knepley PetscSection coordSection; 29ccd2543fSMatthew G Knepley Vec coordsLocal; 30a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 31ccd2543fSMatthew G Knepley const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 32ccd2543fSMatthew G Knepley PetscReal x = PetscRealPart(point[0]); 33ccd2543fSMatthew G Knepley PetscReal y = PetscRealPart(point[1]); 34ccd2543fSMatthew G Knepley PetscInt crossings = 0, f; 35ccd2543fSMatthew G Knepley PetscErrorCode ierr; 36ccd2543fSMatthew G Knepley 37ccd2543fSMatthew G Knepley PetscFunctionBegin; 38ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 39*69d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 40ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 41ccd2543fSMatthew G Knepley for (f = 0; f < 4; ++f) { 42ccd2543fSMatthew G Knepley PetscReal x_i = PetscRealPart(coords[faces[2*f+0]*2+0]); 43ccd2543fSMatthew G Knepley PetscReal y_i = PetscRealPart(coords[faces[2*f+0]*2+1]); 44ccd2543fSMatthew G Knepley PetscReal x_j = PetscRealPart(coords[faces[2*f+1]*2+0]); 45ccd2543fSMatthew G Knepley PetscReal y_j = PetscRealPart(coords[faces[2*f+1]*2+1]); 46ccd2543fSMatthew G Knepley PetscReal slope = (y_j - y_i) / (x_j - x_i); 47ccd2543fSMatthew G Knepley PetscBool cond1 = (x_i <= x) && (x < x_j) ? PETSC_TRUE : PETSC_FALSE; 48ccd2543fSMatthew G Knepley PetscBool cond2 = (x_j <= x) && (x < x_i) ? PETSC_TRUE : PETSC_FALSE; 49ccd2543fSMatthew G Knepley PetscBool above = (y < slope * (x - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 50ccd2543fSMatthew G Knepley if ((cond1 || cond2) && above) ++crossings; 51ccd2543fSMatthew G Knepley } 52ccd2543fSMatthew G Knepley if (crossings % 2) *cell = c; 53ccd2543fSMatthew G Knepley else *cell = -1; 54ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 55ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 56ccd2543fSMatthew G Knepley } 57ccd2543fSMatthew G Knepley 58ccd2543fSMatthew G Knepley #undef __FUNCT__ 59ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D_Internal" 60ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexLocatePoint_Simplex_3D_Internal(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 61ccd2543fSMatthew G Knepley { 62ccd2543fSMatthew G Knepley const PetscInt embedDim = 3; 63ccd2543fSMatthew G Knepley PetscReal v0[3], J[9], invJ[9], detJ; 64ccd2543fSMatthew G Knepley PetscReal x = PetscRealPart(point[0]); 65ccd2543fSMatthew G Knepley PetscReal y = PetscRealPart(point[1]); 66ccd2543fSMatthew G Knepley PetscReal z = PetscRealPart(point[2]); 67ccd2543fSMatthew G Knepley PetscReal xi, eta, zeta; 68ccd2543fSMatthew G Knepley PetscErrorCode ierr; 69ccd2543fSMatthew G Knepley 70ccd2543fSMatthew G Knepley PetscFunctionBegin; 71ccd2543fSMatthew G Knepley ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 72ccd2543fSMatthew G Knepley xi = invJ[0*embedDim+0]*(x - v0[0]) + invJ[0*embedDim+1]*(y - v0[1]) + invJ[0*embedDim+2]*(z - v0[2]); 73ccd2543fSMatthew G Knepley eta = invJ[1*embedDim+0]*(x - v0[0]) + invJ[1*embedDim+1]*(y - v0[1]) + invJ[1*embedDim+2]*(z - v0[2]); 74ccd2543fSMatthew G Knepley zeta = invJ[2*embedDim+0]*(x - v0[0]) + invJ[2*embedDim+1]*(y - v0[1]) + invJ[2*embedDim+2]*(z - v0[2]); 75ccd2543fSMatthew G Knepley 76ccd2543fSMatthew G Knepley if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) *cell = c; 77ccd2543fSMatthew G Knepley else *cell = -1; 78ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 79ccd2543fSMatthew G Knepley } 80ccd2543fSMatthew G Knepley 81ccd2543fSMatthew G Knepley #undef __FUNCT__ 82ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexLocatePoint_General_3D_Internal" 83ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexLocatePoint_General_3D_Internal(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 84ccd2543fSMatthew G Knepley { 85ccd2543fSMatthew G Knepley PetscSection coordSection; 86ccd2543fSMatthew G Knepley Vec coordsLocal; 877c1f9639SMatthew G Knepley PetscScalar *coords; 88fb150da6SMatthew G. Knepley const PetscInt faces[24] = {0, 3, 2, 1, 5, 4, 7, 6, 3, 0, 4, 5, 89fb150da6SMatthew G. Knepley 1, 2, 6, 7, 3, 5, 6, 2, 0, 1, 7, 4}; 90ccd2543fSMatthew G Knepley PetscBool found = PETSC_TRUE; 91ccd2543fSMatthew G Knepley PetscInt f; 92ccd2543fSMatthew G Knepley PetscErrorCode ierr; 93ccd2543fSMatthew G Knepley 94ccd2543fSMatthew G Knepley PetscFunctionBegin; 95ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 96*69d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 97ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 98ccd2543fSMatthew G Knepley for (f = 0; f < 6; ++f) { 99ccd2543fSMatthew G Knepley /* Check the point is under plane */ 100ccd2543fSMatthew G Knepley /* Get face normal */ 101ccd2543fSMatthew G Knepley PetscReal v_i[3]; 102ccd2543fSMatthew G Knepley PetscReal v_j[3]; 103ccd2543fSMatthew G Knepley PetscReal normal[3]; 104ccd2543fSMatthew G Knepley PetscReal pp[3]; 105ccd2543fSMatthew G Knepley PetscReal dot; 106ccd2543fSMatthew G Knepley 107ccd2543fSMatthew G Knepley v_i[0] = PetscRealPart(coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0]); 108ccd2543fSMatthew G Knepley v_i[1] = PetscRealPart(coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1]); 109ccd2543fSMatthew G Knepley v_i[2] = PetscRealPart(coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]); 110ccd2543fSMatthew G Knepley v_j[0] = PetscRealPart(coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0]); 111ccd2543fSMatthew G Knepley v_j[1] = PetscRealPart(coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1]); 112ccd2543fSMatthew G Knepley v_j[2] = PetscRealPart(coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]); 113ccd2543fSMatthew G Knepley normal[0] = v_i[1]*v_j[2] - v_i[2]*v_j[1]; 114ccd2543fSMatthew G Knepley normal[1] = v_i[2]*v_j[0] - v_i[0]*v_j[2]; 115ccd2543fSMatthew G Knepley normal[2] = v_i[0]*v_j[1] - v_i[1]*v_j[0]; 116ccd2543fSMatthew G Knepley pp[0] = PetscRealPart(coords[faces[f*4+0]*3+0] - point[0]); 117ccd2543fSMatthew G Knepley pp[1] = PetscRealPart(coords[faces[f*4+0]*3+1] - point[1]); 118ccd2543fSMatthew G Knepley pp[2] = PetscRealPart(coords[faces[f*4+0]*3+2] - point[2]); 119ccd2543fSMatthew G Knepley dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 120ccd2543fSMatthew G Knepley 121ccd2543fSMatthew G Knepley /* Check that projected point is in face (2D location problem) */ 122ccd2543fSMatthew G Knepley if (dot < 0.0) { 123ccd2543fSMatthew G Knepley found = PETSC_FALSE; 124ccd2543fSMatthew G Knepley break; 125ccd2543fSMatthew G Knepley } 126ccd2543fSMatthew G Knepley } 127ccd2543fSMatthew G Knepley if (found) *cell = c; 128ccd2543fSMatthew G Knepley else *cell = -1; 129ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, NULL, &coords);CHKERRQ(ierr); 130ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 131ccd2543fSMatthew G Knepley } 132ccd2543fSMatthew G Knepley 133ccd2543fSMatthew G Knepley #undef __FUNCT__ 134ccd2543fSMatthew G Knepley #define __FUNCT__ "DMLocatePoints_Plex" 135ccd2543fSMatthew G Knepley /* 136ccd2543fSMatthew G Knepley Need to implement using the guess 137ccd2543fSMatthew G Knepley */ 138ccd2543fSMatthew G Knepley PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 139ccd2543fSMatthew G Knepley { 140ccd2543fSMatthew G Knepley PetscInt cell = -1 /*, guess = -1*/; 141ccd2543fSMatthew G Knepley PetscInt bs, numPoints, p; 142ccd2543fSMatthew G Knepley PetscInt dim, cStart, cEnd, cMax, c, coneSize; 143ccd2543fSMatthew G Knepley PetscInt *cells; 144ccd2543fSMatthew G Knepley PetscScalar *a; 145ccd2543fSMatthew G Knepley PetscErrorCode ierr; 146ccd2543fSMatthew G Knepley 147ccd2543fSMatthew G Knepley PetscFunctionBegin; 148ccd2543fSMatthew G Knepley ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 149ccd2543fSMatthew G Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 150ccd2543fSMatthew G Knepley ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 151ccd2543fSMatthew G Knepley if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 152ccd2543fSMatthew G Knepley ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 153ccd2543fSMatthew G Knepley ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 154ccd2543fSMatthew G Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 155ccd2543fSMatthew 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); 156ccd2543fSMatthew G Knepley numPoints /= bs; 157785e854fSJed Brown ierr = PetscMalloc1(numPoints, &cells);CHKERRQ(ierr); 158ccd2543fSMatthew G Knepley for (p = 0; p < numPoints; ++p) { 159ccd2543fSMatthew G Knepley const PetscScalar *point = &a[p*bs]; 160ccd2543fSMatthew G Knepley 161ccd2543fSMatthew G Knepley switch (dim) { 162ccd2543fSMatthew G Knepley case 2: 163ccd2543fSMatthew G Knepley for (c = cStart; c < cEnd; ++c) { 164ccd2543fSMatthew G Knepley ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 165ccd2543fSMatthew G Knepley switch (coneSize) { 166ccd2543fSMatthew G Knepley case 3: 167ccd2543fSMatthew G Knepley ierr = DMPlexLocatePoint_Simplex_2D_Internal(dm, point, c, &cell);CHKERRQ(ierr); 168ccd2543fSMatthew G Knepley break; 169ccd2543fSMatthew G Knepley case 4: 170ccd2543fSMatthew G Knepley ierr = DMPlexLocatePoint_General_2D_Internal(dm, point, c, &cell);CHKERRQ(ierr); 171ccd2543fSMatthew G Knepley break; 172ccd2543fSMatthew G Knepley default: 173ccd2543fSMatthew G Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 174ccd2543fSMatthew G Knepley } 175ccd2543fSMatthew G Knepley if (cell >= 0) break; 176ccd2543fSMatthew G Knepley } 177ccd2543fSMatthew G Knepley break; 178ccd2543fSMatthew G Knepley case 3: 179ccd2543fSMatthew G Knepley for (c = cStart; c < cEnd; ++c) { 180ccd2543fSMatthew G Knepley ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 181ccd2543fSMatthew G Knepley switch (coneSize) { 182ccd2543fSMatthew G Knepley case 4: 183ccd2543fSMatthew G Knepley ierr = DMPlexLocatePoint_Simplex_3D_Internal(dm, point, c, &cell);CHKERRQ(ierr); 184ccd2543fSMatthew G Knepley break; 18535953a02SMatthew G. Knepley case 6: 186ccd2543fSMatthew G Knepley ierr = DMPlexLocatePoint_General_3D_Internal(dm, point, c, &cell);CHKERRQ(ierr); 187ccd2543fSMatthew G Knepley break; 188ccd2543fSMatthew G Knepley default: 189ccd2543fSMatthew G Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 190ccd2543fSMatthew G Knepley } 191ccd2543fSMatthew G Knepley if (cell >= 0) break; 192ccd2543fSMatthew G Knepley } 193ccd2543fSMatthew G Knepley break; 194ccd2543fSMatthew G Knepley default: 195ccd2543fSMatthew G Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 196ccd2543fSMatthew G Knepley } 197ccd2543fSMatthew G Knepley cells[p] = cell; 198ccd2543fSMatthew G Knepley } 199ccd2543fSMatthew G Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 200ccd2543fSMatthew G Knepley ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 201ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 202ccd2543fSMatthew G Knepley } 203ccd2543fSMatthew G Knepley 204ccd2543fSMatthew G Knepley #undef __FUNCT__ 20517fe8556SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeProjection2Dto1D_Internal" 20617fe8556SMatthew G. Knepley /* 20717fe8556SMatthew G. Knepley DMPlexComputeProjection2Dto1D_Internal - Rewrite coordinates to be the 1D projection of the 2D 20817fe8556SMatthew G. Knepley */ 2097f07f362SMatthew G. Knepley static PetscErrorCode DMPlexComputeProjection2Dto1D_Internal(PetscScalar coords[], PetscReal R[]) 21017fe8556SMatthew G. Knepley { 21117fe8556SMatthew G. Knepley const PetscReal x = PetscRealPart(coords[2] - coords[0]); 21217fe8556SMatthew G. Knepley const PetscReal y = PetscRealPart(coords[3] - coords[1]); 2137f07f362SMatthew G. Knepley const PetscReal r = sqrt(x*x + y*y), c = x/r, s = y/r; 21417fe8556SMatthew G. Knepley 21517fe8556SMatthew G. Knepley PetscFunctionBegin; 2161c99cf0cSGeoffrey Irving R[0] = c; R[1] = -s; 2171c99cf0cSGeoffrey Irving R[2] = s; R[3] = c; 21817fe8556SMatthew G. Knepley coords[0] = 0.0; 2197f07f362SMatthew G. Knepley coords[1] = r; 22017fe8556SMatthew G. Knepley PetscFunctionReturn(0); 22117fe8556SMatthew G. Knepley } 22217fe8556SMatthew G. Knepley 22317fe8556SMatthew G. Knepley #undef __FUNCT__ 224ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeProjection3Dto2D_Internal" 225ccd2543fSMatthew G Knepley /* 226ccd2543fSMatthew G Knepley DMPlexComputeProjection3Dto2D_Internal - Rewrite coordinates to be the 2D projection of the 3D 227ccd2543fSMatthew G Knepley */ 22899dec3a6SMatthew G. Knepley static PetscErrorCode DMPlexComputeProjection3Dto2D_Internal(PetscInt coordSize, PetscScalar coords[], PetscReal R[]) 229ccd2543fSMatthew G Knepley { 2301ee9d5ecSMatthew G. Knepley PetscReal x1[3], x2[3], n[3], norm; 23199dec3a6SMatthew G. Knepley PetscReal x1p[3], x2p[3], xnp[3]; 2324a217a95SMatthew G. Knepley PetscReal sqrtz, alpha; 233ccd2543fSMatthew G Knepley const PetscInt dim = 3; 23499dec3a6SMatthew G. Knepley PetscInt d, e, p; 235ccd2543fSMatthew G Knepley 236ccd2543fSMatthew G Knepley PetscFunctionBegin; 237ccd2543fSMatthew G Knepley /* 0) Calculate normal vector */ 238ccd2543fSMatthew G Knepley for (d = 0; d < dim; ++d) { 2391ee9d5ecSMatthew G. Knepley x1[d] = PetscRealPart(coords[1*dim+d] - coords[0*dim+d]); 2401ee9d5ecSMatthew G. Knepley x2[d] = PetscRealPart(coords[2*dim+d] - coords[0*dim+d]); 241ccd2543fSMatthew G Knepley } 242ccd2543fSMatthew G Knepley n[0] = x1[1]*x2[2] - x1[2]*x2[1]; 243ccd2543fSMatthew G Knepley n[1] = x1[2]*x2[0] - x1[0]*x2[2]; 244ccd2543fSMatthew G Knepley n[2] = x1[0]*x2[1] - x1[1]*x2[0]; 245ccd2543fSMatthew G Knepley norm = sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]); 246ccd2543fSMatthew G Knepley n[0] /= norm; 247ccd2543fSMatthew G Knepley n[1] /= norm; 248ccd2543fSMatthew G Knepley n[2] /= norm; 249ccd2543fSMatthew G Knepley /* 1) Take the normal vector and rotate until it is \hat z 250ccd2543fSMatthew G Knepley 251ccd2543fSMatthew G Knepley Let the normal vector be <nx, ny, nz> and alpha = 1/sqrt(1 - nz^2), then 252ccd2543fSMatthew G Knepley 253ccd2543fSMatthew G Knepley R = / alpha nx nz alpha ny nz -1/alpha \ 254ccd2543fSMatthew G Knepley | -alpha ny alpha nx 0 | 255ccd2543fSMatthew G Knepley \ nx ny nz / 256ccd2543fSMatthew G Knepley 257ccd2543fSMatthew G Knepley will rotate the normal vector to \hat z 258ccd2543fSMatthew G Knepley */ 2598763be8eSMatthew G. Knepley sqrtz = sqrt(1.0 - n[2]*n[2]); 26073868372SMatthew G. Knepley /* Check for n = z */ 26173868372SMatthew G. Knepley if (sqrtz < 1.0e-10) { 2621ee9d5ecSMatthew G. Knepley if (n[2] < 0.0) { 26399dec3a6SMatthew G. Knepley if (coordSize > 9) { 26499dec3a6SMatthew G. Knepley coords[2] = PetscRealPart(coords[3*dim+0] - coords[0*dim+0]); 26599dec3a6SMatthew G. Knepley coords[3] = PetscRealPart(coords[3*dim+0] - coords[0*dim+0]); 26699dec3a6SMatthew G. Knepley coords[4] = x2[0]; 26799dec3a6SMatthew G. Knepley coords[5] = x2[1]; 26899dec3a6SMatthew G. Knepley coords[6] = x1[0]; 26999dec3a6SMatthew G. Knepley coords[7] = x1[1]; 27099dec3a6SMatthew G. Knepley } else { 27173868372SMatthew G. Knepley coords[2] = x2[0]; 27273868372SMatthew G. Knepley coords[3] = x2[1]; 27373868372SMatthew G. Knepley coords[4] = x1[0]; 27473868372SMatthew G. Knepley coords[5] = x1[1]; 27599dec3a6SMatthew G. Knepley } 276b7ad821dSMatthew G. Knepley R[0] = 1.0; R[1] = 0.0; R[2] = 0.0; 277b7ad821dSMatthew G. Knepley R[3] = 0.0; R[4] = 1.0; R[5] = 0.0; 278b7ad821dSMatthew G. Knepley R[6] = 0.0; R[7] = 0.0; R[8] = -1.0; 27973868372SMatthew G. Knepley } else { 28099dec3a6SMatthew G. Knepley for (p = 3; p < coordSize/3; ++p) { 28199dec3a6SMatthew G. Knepley coords[p*2+0] = PetscRealPart(coords[p*dim+0] - coords[0*dim+0]); 28299dec3a6SMatthew G. Knepley coords[p*2+1] = PetscRealPart(coords[p*dim+1] - coords[0*dim+1]); 28399dec3a6SMatthew G. Knepley } 28473868372SMatthew G. Knepley coords[2] = x1[0]; 28573868372SMatthew G. Knepley coords[3] = x1[1]; 28673868372SMatthew G. Knepley coords[4] = x2[0]; 28773868372SMatthew G. Knepley coords[5] = x2[1]; 288b7ad821dSMatthew G. Knepley R[0] = 1.0; R[1] = 0.0; R[2] = 0.0; 289b7ad821dSMatthew G. Knepley R[3] = 0.0; R[4] = 1.0; R[5] = 0.0; 290b7ad821dSMatthew G. Knepley R[6] = 0.0; R[7] = 0.0; R[8] = 1.0; 29173868372SMatthew G. Knepley } 29299dec3a6SMatthew G. Knepley coords[0] = 0.0; 29399dec3a6SMatthew G. Knepley coords[1] = 0.0; 29473868372SMatthew G. Knepley PetscFunctionReturn(0); 29573868372SMatthew G. Knepley } 296da18b5e6SMatthew G Knepley alpha = 1.0/sqrtz; 297ccd2543fSMatthew G Knepley R[0] = alpha*n[0]*n[2]; R[1] = alpha*n[1]*n[2]; R[2] = -sqrtz; 298ccd2543fSMatthew G Knepley R[3] = -alpha*n[1]; R[4] = alpha*n[0]; R[5] = 0.0; 299ccd2543fSMatthew G Knepley R[6] = n[0]; R[7] = n[1]; R[8] = n[2]; 300ccd2543fSMatthew G Knepley for (d = 0; d < dim; ++d) { 301ccd2543fSMatthew G Knepley x1p[d] = 0.0; 302ccd2543fSMatthew G Knepley x2p[d] = 0.0; 303ccd2543fSMatthew G Knepley for (e = 0; e < dim; ++e) { 304ccd2543fSMatthew G Knepley x1p[d] += R[d*dim+e]*x1[e]; 305ccd2543fSMatthew G Knepley x2p[d] += R[d*dim+e]*x2[e]; 306ccd2543fSMatthew G Knepley } 307ccd2543fSMatthew G Knepley } 3088763be8eSMatthew G. Knepley if (PetscAbsReal(x1p[2]) > 1.0e-9) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid rotation calculated"); 3098763be8eSMatthew G. Knepley if (PetscAbsReal(x2p[2]) > 1.0e-9) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid rotation calculated"); 310ccd2543fSMatthew G Knepley /* 2) Project to (x, y) */ 31199dec3a6SMatthew G. Knepley for (p = 3; p < coordSize/3; ++p) { 31299dec3a6SMatthew G. Knepley for (d = 0; d < dim; ++d) { 31399dec3a6SMatthew G. Knepley xnp[d] = 0.0; 31499dec3a6SMatthew G. Knepley for (e = 0; e < dim; ++e) { 31599dec3a6SMatthew G. Knepley xnp[d] += R[d*dim+e]*PetscRealPart(coords[p*dim+e] - coords[0*dim+e]); 31699dec3a6SMatthew G. Knepley } 31799dec3a6SMatthew G. Knepley if (d < dim-1) coords[p*2+d] = xnp[d]; 31899dec3a6SMatthew G. Knepley } 31999dec3a6SMatthew G. Knepley } 320ccd2543fSMatthew G Knepley coords[0] = 0.0; 321ccd2543fSMatthew G Knepley coords[1] = 0.0; 322ccd2543fSMatthew G Knepley coords[2] = x1p[0]; 323ccd2543fSMatthew G Knepley coords[3] = x1p[1]; 324ccd2543fSMatthew G Knepley coords[4] = x2p[0]; 325ccd2543fSMatthew G Knepley coords[5] = x2p[1]; 3267f07f362SMatthew G. Knepley /* Output R^T which rotates \hat z to the input normal */ 3277f07f362SMatthew G. Knepley for (d = 0; d < dim; ++d) { 3287f07f362SMatthew G. Knepley for (e = d+1; e < dim; ++e) { 3297f07f362SMatthew G. Knepley PetscReal tmp; 3307f07f362SMatthew G. Knepley 3317f07f362SMatthew G. Knepley tmp = R[d*dim+e]; 3327f07f362SMatthew G. Knepley R[d*dim+e] = R[e*dim+d]; 3337f07f362SMatthew G. Knepley R[e*dim+d] = tmp; 3347f07f362SMatthew G. Knepley } 3357f07f362SMatthew G. Knepley } 336ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 337ccd2543fSMatthew G Knepley } 338ccd2543fSMatthew G Knepley 339ccd2543fSMatthew G Knepley #undef __FUNCT__ 3407f07f362SMatthew G. Knepley #define __FUNCT__ "Invert2D_Internal" 3417f07f362SMatthew G. Knepley PETSC_STATIC_INLINE void Invert2D_Internal(PetscReal invJ[], PetscReal J[], PetscReal detJ) 3427f07f362SMatthew G. Knepley { 3437f07f362SMatthew G. Knepley const PetscReal invDet = 1.0/detJ; 3447f07f362SMatthew G. Knepley 3457f07f362SMatthew G. Knepley invJ[0] = invDet*J[3]; 3467f07f362SMatthew G. Knepley invJ[1] = -invDet*J[1]; 3477f07f362SMatthew G. Knepley invJ[2] = -invDet*J[2]; 3487f07f362SMatthew G. Knepley invJ[3] = invDet*J[0]; 3497f07f362SMatthew G. Knepley PetscLogFlops(5.0); 3507f07f362SMatthew G. Knepley } 3517f07f362SMatthew G. Knepley 3527f07f362SMatthew G. Knepley #undef __FUNCT__ 3537f07f362SMatthew G. Knepley #define __FUNCT__ "Invert3D_Internal" 3547f07f362SMatthew G. Knepley PETSC_STATIC_INLINE void Invert3D_Internal(PetscReal invJ[], PetscReal J[], PetscReal detJ) 3557f07f362SMatthew G. Knepley { 3567f07f362SMatthew G. Knepley const PetscReal invDet = 1.0/detJ; 3577f07f362SMatthew G. Knepley 3587f07f362SMatthew G. Knepley invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 3597f07f362SMatthew G. Knepley invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 3607f07f362SMatthew G. Knepley invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 3617f07f362SMatthew G. Knepley invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 3627f07f362SMatthew G. Knepley invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 3637f07f362SMatthew G. Knepley invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 3647f07f362SMatthew G. Knepley invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 3657f07f362SMatthew G. Knepley invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 3667f07f362SMatthew G. Knepley invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 3677f07f362SMatthew G. Knepley PetscLogFlops(37.0); 3687f07f362SMatthew G. Knepley } 3697f07f362SMatthew G. Knepley 3707f07f362SMatthew G. Knepley #undef __FUNCT__ 3717f07f362SMatthew G. Knepley #define __FUNCT__ "Det2D_Internal" 3727f07f362SMatthew G. Knepley PETSC_STATIC_INLINE void Det2D_Internal(PetscReal *detJ, PetscReal J[]) 3737f07f362SMatthew G. Knepley { 3747f07f362SMatthew G. Knepley *detJ = J[0]*J[3] - J[1]*J[2]; 3757f07f362SMatthew G. Knepley PetscLogFlops(3.0); 3767f07f362SMatthew G. Knepley } 3777f07f362SMatthew G. Knepley 3787f07f362SMatthew G. Knepley #undef __FUNCT__ 3797f07f362SMatthew G. Knepley #define __FUNCT__ "Det3D_Internal" 3807f07f362SMatthew G. Knepley PETSC_STATIC_INLINE void Det3D_Internal(PetscReal *detJ, PetscReal J[]) 3817f07f362SMatthew G. Knepley { 382b7ad821dSMatthew G. Knepley *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 383b7ad821dSMatthew G. Knepley J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 384b7ad821dSMatthew G. Knepley J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 3857f07f362SMatthew G. Knepley PetscLogFlops(12.0); 3867f07f362SMatthew G. Knepley } 3877f07f362SMatthew G. Knepley 3887f07f362SMatthew G. Knepley #undef __FUNCT__ 389834e62ceSMatthew G. Knepley #define __FUNCT__ "Volume_Triangle_Internal" 390834e62ceSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Triangle_Internal(PetscReal *vol, PetscReal coords[]) 391834e62ceSMatthew G. Knepley { 392834e62ceSMatthew G. Knepley /* Signed volume is 1/2 the determinant 393834e62ceSMatthew G. Knepley 394834e62ceSMatthew G. Knepley | 1 1 1 | 395834e62ceSMatthew G. Knepley | x0 x1 x2 | 396834e62ceSMatthew G. Knepley | y0 y1 y2 | 397834e62ceSMatthew G. Knepley 398834e62ceSMatthew G. Knepley but if x0,y0 is the origin, we have 399834e62ceSMatthew G. Knepley 400834e62ceSMatthew G. Knepley | x1 x2 | 401834e62ceSMatthew G. Knepley | y1 y2 | 402834e62ceSMatthew G. Knepley */ 403834e62ceSMatthew G. Knepley const PetscReal x1 = coords[2] - coords[0], y1 = coords[3] - coords[1]; 404834e62ceSMatthew G. Knepley const PetscReal x2 = coords[4] - coords[0], y2 = coords[5] - coords[1]; 405834e62ceSMatthew G. Knepley PetscReal M[4], detM; 406834e62ceSMatthew G. Knepley M[0] = x1; M[1] = x2; 40786623015SMatthew G. Knepley M[2] = y1; M[3] = y2; 408834e62ceSMatthew G. Knepley Det2D_Internal(&detM, M); 409834e62ceSMatthew G. Knepley *vol = 0.5*detM; 410834e62ceSMatthew G. Knepley PetscLogFlops(5.0); 411834e62ceSMatthew G. Knepley } 412834e62ceSMatthew G. Knepley 413834e62ceSMatthew G. Knepley #undef __FUNCT__ 414834e62ceSMatthew G. Knepley #define __FUNCT__ "Volume_Triangle_Origin_Internal" 415834e62ceSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Triangle_Origin_Internal(PetscReal *vol, PetscReal coords[]) 416834e62ceSMatthew G. Knepley { 417834e62ceSMatthew G. Knepley Det2D_Internal(vol, coords); 418834e62ceSMatthew G. Knepley *vol *= 0.5; 419834e62ceSMatthew G. Knepley } 420834e62ceSMatthew G. Knepley 421834e62ceSMatthew G. Knepley #undef __FUNCT__ 422834e62ceSMatthew G. Knepley #define __FUNCT__ "Volume_Tetrahedron_Internal" 423834e62ceSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Tetrahedron_Internal(PetscReal *vol, PetscReal coords[]) 424834e62ceSMatthew G. Knepley { 425834e62ceSMatthew G. Knepley /* Signed volume is 1/6th of the determinant 426834e62ceSMatthew G. Knepley 427834e62ceSMatthew G. Knepley | 1 1 1 1 | 428834e62ceSMatthew G. Knepley | x0 x1 x2 x3 | 429834e62ceSMatthew G. Knepley | y0 y1 y2 y3 | 430834e62ceSMatthew G. Knepley | z0 z1 z2 z3 | 431834e62ceSMatthew G. Knepley 432834e62ceSMatthew G. Knepley but if x0,y0,z0 is the origin, we have 433834e62ceSMatthew G. Knepley 434834e62ceSMatthew G. Knepley | x1 x2 x3 | 435834e62ceSMatthew G. Knepley | y1 y2 y3 | 436834e62ceSMatthew G. Knepley | z1 z2 z3 | 437834e62ceSMatthew G. Knepley */ 438834e62ceSMatthew G. Knepley const PetscReal x1 = coords[3] - coords[0], y1 = coords[4] - coords[1], z1 = coords[5] - coords[2]; 439834e62ceSMatthew G. Knepley const PetscReal x2 = coords[6] - coords[0], y2 = coords[7] - coords[1], z2 = coords[8] - coords[2]; 440834e62ceSMatthew G. Knepley const PetscReal x3 = coords[9] - coords[0], y3 = coords[10] - coords[1], z3 = coords[11] - coords[2]; 441834e62ceSMatthew G. Knepley PetscReal M[9], detM; 442834e62ceSMatthew G. Knepley M[0] = x1; M[1] = x2; M[2] = x3; 443834e62ceSMatthew G. Knepley M[3] = y1; M[4] = y2; M[5] = y3; 444834e62ceSMatthew G. Knepley M[6] = z1; M[7] = z2; M[8] = z3; 445834e62ceSMatthew G. Knepley Det3D_Internal(&detM, M); 446b7ad821dSMatthew G. Knepley *vol = -0.16666666666666666666666*detM; 447834e62ceSMatthew G. Knepley PetscLogFlops(10.0); 448834e62ceSMatthew G. Knepley } 449834e62ceSMatthew G. Knepley 450834e62ceSMatthew G. Knepley #undef __FUNCT__ 4510ec8681fSMatthew G. Knepley #define __FUNCT__ "Volume_Tetrahedron_Origin_Internal" 4520ec8681fSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Tetrahedron_Origin_Internal(PetscReal *vol, PetscReal coords[]) 4530ec8681fSMatthew G. Knepley { 4540ec8681fSMatthew G. Knepley Det3D_Internal(vol, coords); 455b7ad821dSMatthew G. Knepley *vol *= -0.16666666666666666666666; 4560ec8681fSMatthew G. Knepley } 4570ec8681fSMatthew G. Knepley 4580ec8681fSMatthew G. Knepley #undef __FUNCT__ 45917fe8556SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeLineGeometry_Internal" 46017fe8556SMatthew G. Knepley static PetscErrorCode DMPlexComputeLineGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 46117fe8556SMatthew G. Knepley { 46217fe8556SMatthew G. Knepley PetscSection coordSection; 46317fe8556SMatthew G. Knepley Vec coordinates; 464a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 4657f07f362SMatthew G. Knepley PetscInt numCoords, d; 46617fe8556SMatthew G. Knepley PetscErrorCode ierr; 46717fe8556SMatthew G. Knepley 46817fe8556SMatthew G. Knepley PetscFunctionBegin; 46917fe8556SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 470*69d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 47117fe8556SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 4727f07f362SMatthew G. Knepley *detJ = 0.0; 47317fe8556SMatthew G. Knepley if (numCoords == 4) { 4747f07f362SMatthew G. Knepley const PetscInt dim = 2; 4757f07f362SMatthew G. Knepley PetscReal R[4], J0; 4767f07f362SMatthew G. Knepley 4777f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 4787f07f362SMatthew G. Knepley ierr = DMPlexComputeProjection2Dto1D_Internal(coords, R);CHKERRQ(ierr); 47917fe8556SMatthew G. Knepley if (J) { 4807f07f362SMatthew G. Knepley J0 = 0.5*PetscRealPart(coords[1]); 4817f07f362SMatthew G. Knepley J[0] = R[0]*J0; J[1] = R[1]; 4827f07f362SMatthew G. Knepley J[2] = R[2]*J0; J[3] = R[3]; 4837f07f362SMatthew G. Knepley Det2D_Internal(detJ, J); 48417fe8556SMatthew G. Knepley } 4857f07f362SMatthew G. Knepley if (invJ) {Invert2D_Internal(invJ, J, *detJ);} 4867f07f362SMatthew G. Knepley } else if (numCoords == 2) { 4877f07f362SMatthew G. Knepley const PetscInt dim = 1; 4887f07f362SMatthew G. Knepley 4897f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 4907f07f362SMatthew G. Knepley if (J) { 4917f07f362SMatthew G. Knepley J[0] = 0.5*(PetscRealPart(coords[1]) - PetscRealPart(coords[0])); 49217fe8556SMatthew G. Knepley *detJ = J[0]; 49317fe8556SMatthew G. Knepley PetscLogFlops(2.0); 49417fe8556SMatthew G. Knepley } 4957f07f362SMatthew G. Knepley if (invJ) {invJ[0] = 1.0/J[0]; PetscLogFlops(1.0);} 4967f07f362SMatthew G. Knepley } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of coordinates for this segment is %d != 2", numCoords); 49717fe8556SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 49817fe8556SMatthew G. Knepley PetscFunctionReturn(0); 49917fe8556SMatthew G. Knepley } 50017fe8556SMatthew G. Knepley 50117fe8556SMatthew G. Knepley #undef __FUNCT__ 502ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeTriangleGeometry_Internal" 503ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexComputeTriangleGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 504ccd2543fSMatthew G Knepley { 505ccd2543fSMatthew G Knepley PetscSection coordSection; 506ccd2543fSMatthew G Knepley Vec coordinates; 507a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 5087f07f362SMatthew G. Knepley PetscInt numCoords, d, f, g; 509ccd2543fSMatthew G Knepley PetscErrorCode ierr; 510ccd2543fSMatthew G Knepley 511ccd2543fSMatthew G Knepley PetscFunctionBegin; 512ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 513*69d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 514ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 5157f07f362SMatthew G. Knepley *detJ = 0.0; 516ccd2543fSMatthew G Knepley if (numCoords == 9) { 5177f07f362SMatthew G. Knepley const PetscInt dim = 3; 5187f07f362SMatthew 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}; 5197f07f362SMatthew G. Knepley 5207f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 52199dec3a6SMatthew G. Knepley ierr = DMPlexComputeProjection3Dto2D_Internal(numCoords, coords, R);CHKERRQ(ierr); 5227f07f362SMatthew G. Knepley if (J) { 523b7ad821dSMatthew G. Knepley const PetscInt pdim = 2; 524b7ad821dSMatthew G. Knepley 525b7ad821dSMatthew G. Knepley for (d = 0; d < pdim; d++) { 526b7ad821dSMatthew G. Knepley for (f = 0; f < pdim; f++) { 527b7ad821dSMatthew G. Knepley J0[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*pdim+d]) - PetscRealPart(coords[0*pdim+d])); 528ccd2543fSMatthew G Knepley } 5297f07f362SMatthew G. Knepley } 5307f07f362SMatthew G. Knepley PetscLogFlops(8.0); 53187d60e71SMatthew G. Knepley Det3D_Internal(detJ, J0); 5327f07f362SMatthew G. Knepley for (d = 0; d < dim; d++) { 5337f07f362SMatthew G. Knepley for (f = 0; f < dim; f++) { 5347f07f362SMatthew G. Knepley J[d*dim+f] = 0.0; 5357f07f362SMatthew G. Knepley for (g = 0; g < dim; g++) { 5367f07f362SMatthew G. Knepley J[d*dim+f] += R[d*dim+g]*J0[g*dim+f]; 5377f07f362SMatthew G. Knepley } 5387f07f362SMatthew G. Knepley } 5397f07f362SMatthew G. Knepley } 5407f07f362SMatthew G. Knepley PetscLogFlops(18.0); 5417f07f362SMatthew G. Knepley } 5427f07f362SMatthew G. Knepley if (invJ) {Invert3D_Internal(invJ, J, *detJ);} 5437f07f362SMatthew G. Knepley } else if (numCoords == 6) { 5447f07f362SMatthew G. Knepley const PetscInt dim = 2; 5457f07f362SMatthew G. Knepley 5467f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 547ccd2543fSMatthew G Knepley if (J) { 548ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 549ccd2543fSMatthew G Knepley for (f = 0; f < dim; f++) { 550ccd2543fSMatthew G Knepley J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 551ccd2543fSMatthew G Knepley } 552ccd2543fSMatthew G Knepley } 5537f07f362SMatthew G. Knepley PetscLogFlops(8.0); 5547f07f362SMatthew G. Knepley Det2D_Internal(detJ, J); 555ccd2543fSMatthew G Knepley } 5567f07f362SMatthew G. Knepley if (invJ) {Invert2D_Internal(invJ, J, *detJ);} 5577f07f362SMatthew G. Knepley } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of coordinates for this triangle is %d != 6", numCoords); 558ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 559ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 560ccd2543fSMatthew G Knepley } 561ccd2543fSMatthew G Knepley 562ccd2543fSMatthew G Knepley #undef __FUNCT__ 563ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeRectangleGeometry_Internal" 564ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexComputeRectangleGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 565ccd2543fSMatthew G Knepley { 566ccd2543fSMatthew G Knepley PetscSection coordSection; 567ccd2543fSMatthew G Knepley Vec coordinates; 568a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 56999dec3a6SMatthew G. Knepley PetscInt numCoords, d, f, g; 570ccd2543fSMatthew G Knepley PetscErrorCode ierr; 571ccd2543fSMatthew G Knepley 572ccd2543fSMatthew G Knepley PetscFunctionBegin; 573ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 574*69d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 57599dec3a6SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 5767f07f362SMatthew G. Knepley *detJ = 0.0; 57799dec3a6SMatthew G. Knepley if (numCoords == 12) { 57899dec3a6SMatthew G. Knepley const PetscInt dim = 3; 57999dec3a6SMatthew 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}; 58099dec3a6SMatthew G. Knepley 58199dec3a6SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 58299dec3a6SMatthew G. Knepley ierr = DMPlexComputeProjection3Dto2D_Internal(numCoords, coords, R);CHKERRQ(ierr); 58399dec3a6SMatthew G. Knepley if (J) { 58499dec3a6SMatthew G. Knepley const PetscInt pdim = 2; 58599dec3a6SMatthew G. Knepley 58699dec3a6SMatthew G. Knepley for (d = 0; d < pdim; d++) { 58799dec3a6SMatthew G. Knepley J0[d*dim+0] = 0.5*(PetscRealPart(coords[1*pdim+d]) - PetscRealPart(coords[0*pdim+d])); 58899dec3a6SMatthew G. Knepley J0[d*dim+1] = 0.5*(PetscRealPart(coords[3*pdim+d]) - PetscRealPart(coords[0*pdim+d])); 58999dec3a6SMatthew G. Knepley } 59099dec3a6SMatthew G. Knepley PetscLogFlops(8.0); 59199dec3a6SMatthew G. Knepley Det3D_Internal(detJ, J0); 59299dec3a6SMatthew G. Knepley for (d = 0; d < dim; d++) { 59399dec3a6SMatthew G. Knepley for (f = 0; f < dim; f++) { 59499dec3a6SMatthew G. Knepley J[d*dim+f] = 0.0; 59599dec3a6SMatthew G. Knepley for (g = 0; g < dim; g++) { 59699dec3a6SMatthew G. Knepley J[d*dim+f] += R[d*dim+g]*J0[g*dim+f]; 59799dec3a6SMatthew G. Knepley } 59899dec3a6SMatthew G. Knepley } 59999dec3a6SMatthew G. Knepley } 60099dec3a6SMatthew G. Knepley PetscLogFlops(18.0); 60199dec3a6SMatthew G. Knepley } 60299dec3a6SMatthew G. Knepley if (invJ) {Invert3D_Internal(invJ, J, *detJ);} 60399dec3a6SMatthew G. Knepley } else if (numCoords == 8) { 60499dec3a6SMatthew G. Knepley const PetscInt dim = 2; 60599dec3a6SMatthew G. Knepley 6067f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 607ccd2543fSMatthew G Knepley if (J) { 608ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 60999dec3a6SMatthew G. Knepley J[d*dim+0] = 0.5*(PetscRealPart(coords[1*dim+d]) - PetscRealPart(coords[0*dim+d])); 61099dec3a6SMatthew G. Knepley J[d*dim+1] = 0.5*(PetscRealPart(coords[3*dim+d]) - PetscRealPart(coords[0*dim+d])); 611ccd2543fSMatthew G Knepley } 6127f07f362SMatthew G. Knepley PetscLogFlops(8.0); 6137f07f362SMatthew G. Knepley Det2D_Internal(detJ, J); 614ccd2543fSMatthew G Knepley } 6157f07f362SMatthew G. Knepley if (invJ) {Invert2D_Internal(invJ, J, *detJ);} 61699dec3a6SMatthew G. Knepley } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of coordinates for this quadrilateral is %d != 6", numCoords); 61799dec3a6SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 618ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 619ccd2543fSMatthew G Knepley } 620ccd2543fSMatthew G Knepley 621ccd2543fSMatthew G Knepley #undef __FUNCT__ 622ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_Internal" 623ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexComputeTetrahedronGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 624ccd2543fSMatthew G Knepley { 625ccd2543fSMatthew G Knepley PetscSection coordSection; 626ccd2543fSMatthew G Knepley Vec coordinates; 627a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 628ccd2543fSMatthew G Knepley const PetscInt dim = 3; 62999dec3a6SMatthew G. Knepley PetscInt d; 630ccd2543fSMatthew G Knepley PetscErrorCode ierr; 631ccd2543fSMatthew G Knepley 632ccd2543fSMatthew G Knepley PetscFunctionBegin; 633ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 634*69d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 635ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 6367f07f362SMatthew G. Knepley *detJ = 0.0; 6377f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 638ccd2543fSMatthew G Knepley if (J) { 639ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 640f0df753eSMatthew G. Knepley /* I orient with outward face normals */ 641f0df753eSMatthew G. Knepley J[d*dim+0] = 0.5*(PetscRealPart(coords[2*dim+d]) - PetscRealPart(coords[0*dim+d])); 642f0df753eSMatthew G. Knepley J[d*dim+1] = 0.5*(PetscRealPart(coords[1*dim+d]) - PetscRealPart(coords[0*dim+d])); 643f0df753eSMatthew G. Knepley J[d*dim+2] = 0.5*(PetscRealPart(coords[3*dim+d]) - PetscRealPart(coords[0*dim+d])); 644ccd2543fSMatthew G Knepley } 6457f07f362SMatthew G. Knepley PetscLogFlops(18.0); 6467f07f362SMatthew G. Knepley Det3D_Internal(detJ, J); 647ccd2543fSMatthew G Knepley } 648f0df753eSMatthew G. Knepley if (invJ) {Invert3D_Internal(invJ, J, *detJ);} 649ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 650ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 651ccd2543fSMatthew G Knepley } 652ccd2543fSMatthew G Knepley 653ccd2543fSMatthew G Knepley #undef __FUNCT__ 654ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeHexahedronGeometry_Internal" 655ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexComputeHexahedronGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 656ccd2543fSMatthew G Knepley { 657ccd2543fSMatthew G Knepley PetscSection coordSection; 658ccd2543fSMatthew G Knepley Vec coordinates; 659a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 660ccd2543fSMatthew G Knepley const PetscInt dim = 3; 661ccd2543fSMatthew G Knepley PetscInt d; 662ccd2543fSMatthew G Knepley PetscErrorCode ierr; 663ccd2543fSMatthew G Knepley 664ccd2543fSMatthew G Knepley PetscFunctionBegin; 665ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 666*69d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 667ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 6687f07f362SMatthew G. Knepley *detJ = 0.0; 6697f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 670ccd2543fSMatthew G Knepley if (J) { 671ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 672f0df753eSMatthew G. Knepley J[d*dim+0] = 0.5*(PetscRealPart(coords[3*dim+d]) - PetscRealPart(coords[0*dim+d])); 673f0df753eSMatthew G. Knepley J[d*dim+1] = 0.5*(PetscRealPart(coords[1*dim+d]) - PetscRealPart(coords[0*dim+d])); 674f0df753eSMatthew G. Knepley J[d*dim+2] = 0.5*(PetscRealPart(coords[4*dim+d]) - PetscRealPart(coords[0*dim+d])); 675ccd2543fSMatthew G Knepley } 6767f07f362SMatthew G. Knepley PetscLogFlops(18.0); 6777f07f362SMatthew G. Knepley Det3D_Internal(detJ, J); 678ccd2543fSMatthew G Knepley } 6797f07f362SMatthew G. Knepley if (invJ) {Invert3D_Internal(invJ, J, *detJ);} 680ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 681ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 682ccd2543fSMatthew G Knepley } 683ccd2543fSMatthew G Knepley 684ccd2543fSMatthew G Knepley #undef __FUNCT__ 685ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeCellGeometry" 686ccd2543fSMatthew G Knepley /*@C 687ccd2543fSMatthew G Knepley DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 688ccd2543fSMatthew G Knepley 689ccd2543fSMatthew G Knepley Collective on DM 690ccd2543fSMatthew G Knepley 691ccd2543fSMatthew G Knepley Input Arguments: 692ccd2543fSMatthew G Knepley + dm - the DM 693ccd2543fSMatthew G Knepley - cell - the cell 694ccd2543fSMatthew G Knepley 695ccd2543fSMatthew G Knepley Output Arguments: 696ccd2543fSMatthew G Knepley + v0 - the translation part of this affine transform 697ccd2543fSMatthew G Knepley . J - the Jacobian of the transform from the reference element 698ccd2543fSMatthew G Knepley . invJ - the inverse of the Jacobian 699ccd2543fSMatthew G Knepley - detJ - the Jacobian determinant 700ccd2543fSMatthew G Knepley 701ccd2543fSMatthew G Knepley Level: advanced 702ccd2543fSMatthew G Knepley 703ccd2543fSMatthew G Knepley Fortran Notes: 704ccd2543fSMatthew G Knepley Since it returns arrays, this routine is only available in Fortran 90, and you must 705ccd2543fSMatthew G Knepley include petsc.h90 in your code. 706ccd2543fSMatthew G Knepley 707*69d8a9ceSMatthew G. Knepley .seealso: DMGetCoordinateSection(), DMGetCoordinateVec() 708ccd2543fSMatthew G Knepley @*/ 709ccd2543fSMatthew G Knepley PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 710ccd2543fSMatthew G Knepley { 71149dc4407SMatthew G. Knepley PetscInt depth, dim, coneSize; 712ccd2543fSMatthew G Knepley PetscErrorCode ierr; 713ccd2543fSMatthew G Knepley 714ccd2543fSMatthew G Knepley PetscFunctionBegin; 715139a35ccSMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 716ccd2543fSMatthew G Knepley ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 71749dc4407SMatthew G. Knepley if (depth == 1) { 7185743f1d7SMatthew G. Knepley ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 719ccd2543fSMatthew G Knepley switch (dim) { 72017fe8556SMatthew G. Knepley case 1: 72117fe8556SMatthew G. Knepley ierr = DMPlexComputeLineGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 72217fe8556SMatthew G. Knepley break; 723ccd2543fSMatthew G Knepley case 2: 724ccd2543fSMatthew G Knepley switch (coneSize) { 725ccd2543fSMatthew G Knepley case 3: 726ccd2543fSMatthew G Knepley ierr = DMPlexComputeTriangleGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 727ccd2543fSMatthew G Knepley break; 728ccd2543fSMatthew G Knepley case 4: 729ccd2543fSMatthew G Knepley ierr = DMPlexComputeRectangleGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 730ccd2543fSMatthew G Knepley break; 731ccd2543fSMatthew G Knepley default: 732ccd2543fSMatthew G Knepley SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 733ccd2543fSMatthew G Knepley } 734ccd2543fSMatthew G Knepley break; 735ccd2543fSMatthew G Knepley case 3: 736ccd2543fSMatthew G Knepley switch (coneSize) { 737ccd2543fSMatthew G Knepley case 4: 738ccd2543fSMatthew G Knepley ierr = DMPlexComputeTetrahedronGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 739ccd2543fSMatthew G Knepley break; 740ccd2543fSMatthew G Knepley case 8: 741ccd2543fSMatthew G Knepley ierr = DMPlexComputeHexahedronGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 742ccd2543fSMatthew G Knepley break; 743ccd2543fSMatthew G Knepley default: 744ccd2543fSMatthew G Knepley SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 745ccd2543fSMatthew G Knepley } 746ccd2543fSMatthew G Knepley break; 747ccd2543fSMatthew G Knepley default: 748ccd2543fSMatthew G Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 749ccd2543fSMatthew G Knepley } 75049dc4407SMatthew G. Knepley } else { 7515743f1d7SMatthew G. Knepley /* We need to keep a pointer to the depth label */ 7525743f1d7SMatthew G. Knepley ierr = DMPlexGetLabelValue(dm, "depth", cell, &dim);CHKERRQ(ierr); 75349dc4407SMatthew G. Knepley /* Cone size is now the number of faces */ 75449dc4407SMatthew G. Knepley switch (dim) { 75517fe8556SMatthew G. Knepley case 1: 75617fe8556SMatthew G. Knepley ierr = DMPlexComputeLineGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 75717fe8556SMatthew G. Knepley break; 75849dc4407SMatthew G. Knepley case 2: 75949dc4407SMatthew G. Knepley switch (coneSize) { 76049dc4407SMatthew G. Knepley case 3: 76149dc4407SMatthew G. Knepley ierr = DMPlexComputeTriangleGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 76249dc4407SMatthew G. Knepley break; 76349dc4407SMatthew G. Knepley case 4: 76449dc4407SMatthew G. Knepley ierr = DMPlexComputeRectangleGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 76549dc4407SMatthew G. Knepley break; 76649dc4407SMatthew G. Knepley default: 76749dc4407SMatthew G. Knepley SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 76849dc4407SMatthew G. Knepley } 76949dc4407SMatthew G. Knepley break; 77049dc4407SMatthew G. Knepley case 3: 77149dc4407SMatthew G. Knepley switch (coneSize) { 77249dc4407SMatthew G. Knepley case 4: 77349dc4407SMatthew G. Knepley ierr = DMPlexComputeTetrahedronGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 77449dc4407SMatthew G. Knepley break; 77549dc4407SMatthew G. Knepley case 6: 77649dc4407SMatthew G. Knepley ierr = DMPlexComputeHexahedronGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 77749dc4407SMatthew G. Knepley break; 77849dc4407SMatthew G. Knepley default: 77949dc4407SMatthew G. Knepley SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 78049dc4407SMatthew G. Knepley } 78149dc4407SMatthew G. Knepley break; 78249dc4407SMatthew G. Knepley default: 78349dc4407SMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 78449dc4407SMatthew G. Knepley } 78549dc4407SMatthew G. Knepley } 786ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 787ccd2543fSMatthew G Knepley } 788834e62ceSMatthew G. Knepley 789834e62ceSMatthew G. Knepley #undef __FUNCT__ 790cc08537eSMatthew G. Knepley #define __FUNCT__ "DMPlexComputeGeometryFVM_1D_Internal" 791011ea5d8SMatthew G. Knepley static PetscErrorCode DMPlexComputeGeometryFVM_1D_Internal(DM dm, PetscInt dim, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 792cc08537eSMatthew G. Knepley { 793cc08537eSMatthew G. Knepley PetscSection coordSection; 794cc08537eSMatthew G. Knepley Vec coordinates; 795a1e44745SMatthew G. Knepley PetscScalar *coords = NULL; 796cc08537eSMatthew G. Knepley PetscInt coordSize; 797cc08537eSMatthew G. Knepley PetscErrorCode ierr; 798cc08537eSMatthew G. Knepley 799cc08537eSMatthew G. Knepley PetscFunctionBegin; 800cc08537eSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 801*69d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 802cc08537eSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 803011ea5d8SMatthew G. Knepley if (dim != 2) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support 2D edges right now"); 804cc08537eSMatthew G. Knepley if (centroid) { 8051ee9d5ecSMatthew G. Knepley centroid[0] = 0.5*PetscRealPart(coords[0] + coords[dim+0]); 8061ee9d5ecSMatthew G. Knepley centroid[1] = 0.5*PetscRealPart(coords[1] + coords[dim+1]); 807cc08537eSMatthew G. Knepley } 808cc08537eSMatthew G. Knepley if (normal) { 809a60a936bSMatthew G. Knepley PetscReal norm; 810a60a936bSMatthew G. Knepley 8110194f449SMatthew G. Knepley normal[0] = -PetscRealPart(coords[1] - coords[dim+1]); 8120194f449SMatthew G. Knepley normal[1] = PetscRealPart(coords[0] - coords[dim+0]); 813a60a936bSMatthew G. Knepley norm = PetscSqrtReal(normal[0]*normal[0] + normal[1]*normal[1]); 814a60a936bSMatthew G. Knepley normal[0] /= norm; 815a60a936bSMatthew G. Knepley normal[1] /= norm; 816cc08537eSMatthew G. Knepley } 817cc08537eSMatthew G. Knepley if (vol) { 8181ee9d5ecSMatthew G. Knepley *vol = sqrt(PetscSqr(PetscRealPart(coords[0] - coords[dim+0])) + PetscSqr(PetscRealPart(coords[1] - coords[dim+1]))); 819cc08537eSMatthew G. Knepley } 820cc08537eSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 821cc08537eSMatthew G. Knepley PetscFunctionReturn(0); 822cc08537eSMatthew G. Knepley } 823cc08537eSMatthew G. Knepley 824cc08537eSMatthew G. Knepley #undef __FUNCT__ 825cc08537eSMatthew G. Knepley #define __FUNCT__ "DMPlexComputeGeometryFVM_2D_Internal" 826cc08537eSMatthew G. Knepley /* Centroid_i = (\sum_n A_n Cn_i ) / A */ 827011ea5d8SMatthew G. Knepley static PetscErrorCode DMPlexComputeGeometryFVM_2D_Internal(DM dm, PetscInt dim, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 828cc08537eSMatthew G. Knepley { 829cc08537eSMatthew G. Knepley PetscSection coordSection; 830cc08537eSMatthew G. Knepley Vec coordinates; 831cc08537eSMatthew G. Knepley PetscScalar *coords = NULL; 8320a1d6728SMatthew G. Knepley PetscReal vsum = 0.0, csum[3] = {0.0, 0.0, 0.0}, vtmp, ctmp[4], v0[3], R[9]; 8330a1d6728SMatthew G. Knepley PetscInt tdim = 2, coordSize, numCorners, p, d, e; 834cc08537eSMatthew G. Knepley PetscErrorCode ierr; 835cc08537eSMatthew G. Knepley 836cc08537eSMatthew G. Knepley PetscFunctionBegin; 837cc08537eSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8380a1d6728SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cell, &numCorners);CHKERRQ(ierr); 839*69d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 840cc08537eSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 8410a1d6728SMatthew G. Knepley dim = coordSize/numCorners; 842011ea5d8SMatthew G. Knepley if (normal) { 843011ea5d8SMatthew G. Knepley if (dim > 2) { 8441ee9d5ecSMatthew G. Knepley const PetscReal x0 = PetscRealPart(coords[dim+0] - coords[0]), x1 = PetscRealPart(coords[dim*2+0] - coords[0]); 8451ee9d5ecSMatthew G. Knepley const PetscReal y0 = PetscRealPart(coords[dim+1] - coords[1]), y1 = PetscRealPart(coords[dim*2+1] - coords[1]); 8461ee9d5ecSMatthew G. Knepley const PetscReal z0 = PetscRealPart(coords[dim+2] - coords[2]), z1 = PetscRealPart(coords[dim*2+2] - coords[2]); 8470a1d6728SMatthew G. Knepley PetscReal norm; 8480a1d6728SMatthew G. Knepley 8491ee9d5ecSMatthew G. Knepley v0[0] = PetscRealPart(coords[0]); 8501ee9d5ecSMatthew G. Knepley v0[1] = PetscRealPart(coords[1]); 8511ee9d5ecSMatthew G. Knepley v0[2] = PetscRealPart(coords[2]); 8520a1d6728SMatthew G. Knepley normal[0] = y0*z1 - z0*y1; 8530a1d6728SMatthew G. Knepley normal[1] = z0*x1 - x0*z1; 8540a1d6728SMatthew G. Knepley normal[2] = x0*y1 - y0*x1; 8550a1d6728SMatthew G. Knepley norm = sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]); 8560a1d6728SMatthew G. Knepley normal[0] /= norm; 8570a1d6728SMatthew G. Knepley normal[1] /= norm; 8580a1d6728SMatthew G. Knepley normal[2] /= norm; 859011ea5d8SMatthew G. Knepley } else { 860011ea5d8SMatthew G. Knepley for (d = 0; d < dim; ++d) normal[d] = 0.0; 861011ea5d8SMatthew G. Knepley } 862011ea5d8SMatthew G. Knepley } 86399dec3a6SMatthew G. Knepley if (dim == 3) {ierr = DMPlexComputeProjection3Dto2D_Internal(coordSize, coords, R);CHKERRQ(ierr);} 8640a1d6728SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 8650a1d6728SMatthew G. Knepley /* Need to do this copy to get types right */ 8660a1d6728SMatthew G. Knepley for (d = 0; d < tdim; ++d) { 8671ee9d5ecSMatthew G. Knepley ctmp[d] = PetscRealPart(coords[p*tdim+d]); 8681ee9d5ecSMatthew G. Knepley ctmp[tdim+d] = PetscRealPart(coords[((p+1)%numCorners)*tdim+d]); 8690a1d6728SMatthew G. Knepley } 8700a1d6728SMatthew G. Knepley Volume_Triangle_Origin_Internal(&vtmp, ctmp); 8710a1d6728SMatthew G. Knepley vsum += vtmp; 8720a1d6728SMatthew G. Knepley for (d = 0; d < tdim; ++d) { 8730a1d6728SMatthew G. Knepley csum[d] += (ctmp[d] + ctmp[tdim+d])*vtmp; 8740a1d6728SMatthew G. Knepley } 8750a1d6728SMatthew G. Knepley } 8760a1d6728SMatthew G. Knepley for (d = 0; d < tdim; ++d) { 8770a1d6728SMatthew G. Knepley csum[d] /= (tdim+1)*vsum; 8780a1d6728SMatthew G. Knepley } 8790a1d6728SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 880ee6bbdb2SSatish Balay if (vol) *vol = PetscAbsReal(vsum); 8810a1d6728SMatthew G. Knepley if (centroid) { 8820a1d6728SMatthew G. Knepley if (dim > 2) { 8830a1d6728SMatthew G. Knepley for (d = 0; d < dim; ++d) { 8840a1d6728SMatthew G. Knepley centroid[d] = v0[d]; 8850a1d6728SMatthew G. Knepley for (e = 0; e < dim; ++e) { 8860a1d6728SMatthew G. Knepley centroid[d] += R[d*dim+e]*csum[e]; 8870a1d6728SMatthew G. Knepley } 8880a1d6728SMatthew G. Knepley } 8890a1d6728SMatthew G. Knepley } else for (d = 0; d < dim; ++d) centroid[d] = csum[d]; 8900a1d6728SMatthew G. Knepley } 891cc08537eSMatthew G. Knepley PetscFunctionReturn(0); 892cc08537eSMatthew G. Knepley } 893cc08537eSMatthew G. Knepley 894cc08537eSMatthew G. Knepley #undef __FUNCT__ 8950ec8681fSMatthew G. Knepley #define __FUNCT__ "DMPlexComputeGeometryFVM_3D_Internal" 8960ec8681fSMatthew G. Knepley /* Centroid_i = (\sum_n V_n Cn_i ) / V */ 897011ea5d8SMatthew G. Knepley static PetscErrorCode DMPlexComputeGeometryFVM_3D_Internal(DM dm, PetscInt dim, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 8980ec8681fSMatthew G. Knepley { 8990ec8681fSMatthew G. Knepley PetscSection coordSection; 9000ec8681fSMatthew G. Knepley Vec coordinates; 9010ec8681fSMatthew G. Knepley PetscScalar *coords = NULL; 90286623015SMatthew G. Knepley PetscReal vsum = 0.0, vtmp, coordsTmp[3*3]; 903a7df9edeSMatthew G. Knepley const PetscInt *faces, *facesO; 9040ec8681fSMatthew G. Knepley PetscInt numFaces, f, coordSize, numCorners, p, d; 9050ec8681fSMatthew G. Knepley PetscErrorCode ierr; 9060ec8681fSMatthew G. Knepley 9070ec8681fSMatthew G. Knepley PetscFunctionBegin; 9080ec8681fSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 909*69d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9100ec8681fSMatthew G. Knepley 911d9a81ebdSMatthew G. Knepley if (centroid) for (d = 0; d < dim; ++d) centroid[d] = 0.0; 9120ec8681fSMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cell, &numFaces);CHKERRQ(ierr); 9130ec8681fSMatthew G. Knepley ierr = DMPlexGetCone(dm, cell, &faces);CHKERRQ(ierr); 914a7df9edeSMatthew G. Knepley ierr = DMPlexGetConeOrientation(dm, cell, &facesO);CHKERRQ(ierr); 9150ec8681fSMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 916011ea5d8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, faces[f], &coordSize, &coords);CHKERRQ(ierr); 9170ec8681fSMatthew G. Knepley numCorners = coordSize/dim; 9180ec8681fSMatthew G. Knepley switch (numCorners) { 9190ec8681fSMatthew G. Knepley case 3: 9200ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 9211ee9d5ecSMatthew G. Knepley coordsTmp[0*dim+d] = PetscRealPart(coords[0*dim+d]); 9221ee9d5ecSMatthew G. Knepley coordsTmp[1*dim+d] = PetscRealPart(coords[1*dim+d]); 9231ee9d5ecSMatthew G. Knepley coordsTmp[2*dim+d] = PetscRealPart(coords[2*dim+d]); 9240ec8681fSMatthew G. Knepley } 9250ec8681fSMatthew G. Knepley Volume_Tetrahedron_Origin_Internal(&vtmp, coordsTmp); 926a7df9edeSMatthew G. Knepley if (facesO[f] < 0) vtmp = -vtmp; 9270ec8681fSMatthew G. Knepley vsum += vtmp; 9284f25033aSJed Brown if (centroid) { /* Centroid of OABC = (a+b+c)/4 */ 9290ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 9301ee9d5ecSMatthew G. Knepley for (p = 0; p < 3; ++p) centroid[d] += coordsTmp[p*dim+d]*vtmp; 9310ec8681fSMatthew G. Knepley } 9320ec8681fSMatthew G. Knepley } 9330ec8681fSMatthew G. Knepley break; 9340ec8681fSMatthew G. Knepley case 4: 9350ec8681fSMatthew G. Knepley /* DO FOR PYRAMID */ 9360ec8681fSMatthew G. Knepley /* First tet */ 9370ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 9381ee9d5ecSMatthew G. Knepley coordsTmp[0*dim+d] = PetscRealPart(coords[0*dim+d]); 9391ee9d5ecSMatthew G. Knepley coordsTmp[1*dim+d] = PetscRealPart(coords[1*dim+d]); 9401ee9d5ecSMatthew G. Knepley coordsTmp[2*dim+d] = PetscRealPart(coords[3*dim+d]); 9410ec8681fSMatthew G. Knepley } 9420ec8681fSMatthew G. Knepley Volume_Tetrahedron_Origin_Internal(&vtmp, coordsTmp); 943a7df9edeSMatthew G. Knepley if (facesO[f] < 0) vtmp = -vtmp; 9440ec8681fSMatthew G. Knepley vsum += vtmp; 9450ec8681fSMatthew G. Knepley if (centroid) { 9460ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 9470ec8681fSMatthew G. Knepley for (p = 0; p < 3; ++p) centroid[d] += coordsTmp[p*dim+d]*vtmp; 9480ec8681fSMatthew G. Knepley } 9490ec8681fSMatthew G. Knepley } 9500ec8681fSMatthew G. Knepley /* Second tet */ 9510ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 9521ee9d5ecSMatthew G. Knepley coordsTmp[0*dim+d] = PetscRealPart(coords[1*dim+d]); 9531ee9d5ecSMatthew G. Knepley coordsTmp[1*dim+d] = PetscRealPart(coords[2*dim+d]); 9541ee9d5ecSMatthew G. Knepley coordsTmp[2*dim+d] = PetscRealPart(coords[3*dim+d]); 9550ec8681fSMatthew G. Knepley } 9560ec8681fSMatthew G. Knepley Volume_Tetrahedron_Origin_Internal(&vtmp, coordsTmp); 957a7df9edeSMatthew G. Knepley if (facesO[f] < 0) vtmp = -vtmp; 9580ec8681fSMatthew G. Knepley vsum += vtmp; 9590ec8681fSMatthew G. Knepley if (centroid) { 9600ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 9610ec8681fSMatthew G. Knepley for (p = 0; p < 3; ++p) centroid[d] += coordsTmp[p*dim+d]*vtmp; 9620ec8681fSMatthew G. Knepley } 9630ec8681fSMatthew G. Knepley } 9640ec8681fSMatthew G. Knepley break; 9650ec8681fSMatthew G. Knepley default: 9660ec8681fSMatthew G. Knepley SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle faces with %d vertices", numCorners); 9670ec8681fSMatthew G. Knepley } 9684f25033aSJed Brown ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, faces[f], &coordSize, &coords);CHKERRQ(ierr); 9690ec8681fSMatthew G. Knepley } 9708763be8eSMatthew G. Knepley if (vol) *vol = PetscAbsReal(vsum); 9710ec8681fSMatthew G. Knepley if (normal) for (d = 0; d < dim; ++d) normal[d] = 0.0; 972d9a81ebdSMatthew G. Knepley if (centroid) for (d = 0; d < dim; ++d) centroid[d] /= (vsum*4); 9730ec8681fSMatthew G. Knepley PetscFunctionReturn(0); 9740ec8681fSMatthew G. Knepley } 9750ec8681fSMatthew G. Knepley 9760ec8681fSMatthew G. Knepley #undef __FUNCT__ 977834e62ceSMatthew G. Knepley #define __FUNCT__ "DMPlexComputeCellGeometryFVM" 978834e62ceSMatthew G. Knepley /*@C 979834e62ceSMatthew G. Knepley DMPlexComputeCellGeometryFVM - Compute the volume for a given cell 980834e62ceSMatthew G. Knepley 981834e62ceSMatthew G. Knepley Collective on DM 982834e62ceSMatthew G. Knepley 983834e62ceSMatthew G. Knepley Input Arguments: 984834e62ceSMatthew G. Knepley + dm - the DM 985834e62ceSMatthew G. Knepley - cell - the cell 986834e62ceSMatthew G. Knepley 987834e62ceSMatthew G. Knepley Output Arguments: 988834e62ceSMatthew G. Knepley + volume - the cell volume 989cc08537eSMatthew G. Knepley . centroid - the cell centroid 990cc08537eSMatthew G. Knepley - normal - the cell normal, if appropriate 991834e62ceSMatthew G. Knepley 992834e62ceSMatthew G. Knepley Level: advanced 993834e62ceSMatthew G. Knepley 994834e62ceSMatthew G. Knepley Fortran Notes: 995834e62ceSMatthew G. Knepley Since it returns arrays, this routine is only available in Fortran 90, and you must 996834e62ceSMatthew G. Knepley include petsc.h90 in your code. 997834e62ceSMatthew G. Knepley 998*69d8a9ceSMatthew G. Knepley .seealso: DMGetCoordinateSection(), DMGetCoordinateVec() 999834e62ceSMatthew G. Knepley @*/ 1000cc08537eSMatthew G. Knepley PetscErrorCode DMPlexComputeCellGeometryFVM(DM dm, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 1001834e62ceSMatthew G. Knepley { 10020ec8681fSMatthew G. Knepley PetscInt depth, dim; 1003834e62ceSMatthew G. Knepley PetscErrorCode ierr; 1004834e62ceSMatthew G. Knepley 1005834e62ceSMatthew G. Knepley PetscFunctionBegin; 1006834e62ceSMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1007834e62ceSMatthew G. Knepley ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1008834e62ceSMatthew G. Knepley if (depth != dim) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh must be interpolated"); 1009834e62ceSMatthew G. Knepley /* We need to keep a pointer to the depth label */ 1010011ea5d8SMatthew G. Knepley ierr = DMPlexGetLabelValue(dm, "depth", cell, &depth);CHKERRQ(ierr); 1011834e62ceSMatthew G. Knepley /* Cone size is now the number of faces */ 1012011ea5d8SMatthew G. Knepley switch (depth) { 1013cc08537eSMatthew G. Knepley case 1: 1014011ea5d8SMatthew G. Knepley ierr = DMPlexComputeGeometryFVM_1D_Internal(dm, dim, cell, vol, centroid, normal);CHKERRQ(ierr); 1015cc08537eSMatthew G. Knepley break; 1016834e62ceSMatthew G. Knepley case 2: 1017011ea5d8SMatthew G. Knepley ierr = DMPlexComputeGeometryFVM_2D_Internal(dm, dim, cell, vol, centroid, normal);CHKERRQ(ierr); 1018834e62ceSMatthew G. Knepley break; 1019834e62ceSMatthew G. Knepley case 3: 1020011ea5d8SMatthew G. Knepley ierr = DMPlexComputeGeometryFVM_3D_Internal(dm, dim, cell, vol, centroid, normal);CHKERRQ(ierr); 1021834e62ceSMatthew G. Knepley break; 1022834e62ceSMatthew G. Knepley default: 1023834e62ceSMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 1024834e62ceSMatthew G. Knepley } 1025834e62ceSMatthew G. Knepley PetscFunctionReturn(0); 1026834e62ceSMatthew G. Knepley } 1027