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; 307c1f9639SMatthew G Knepley PetscScalar *coords; 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); 39ccd2543fSMatthew G Knepley ierr = DMPlexGetCoordinateSection(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; 88ccd2543fSMatthew G Knepley const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 89ccd2543fSMatthew G Knepley 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 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); 96ccd2543fSMatthew G Knepley ierr = DMPlexGetCoordinateSection(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; 157ccd2543fSMatthew G Knepley ierr = PetscMalloc(numPoints * sizeof(PetscInt), &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; 185ccd2543fSMatthew G Knepley case 8: 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; 2167f07f362SMatthew G. Knepley R[0] = c; R[1] = s; 2177f07f362SMatthew G. Knepley 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 */ 2287f07f362SMatthew G. Knepley static PetscErrorCode DMPlexComputeProjection3Dto2D_Internal(PetscScalar coords[], PetscReal R[]) 229ccd2543fSMatthew G Knepley { 2301ee9d5ecSMatthew G. Knepley PetscReal x1[3], x2[3], n[3], norm; 2311ee9d5ecSMatthew G. Knepley PetscReal x1p[3], x2p[3]; 2324a217a95SMatthew G. Knepley PetscReal sqrtz, alpha; 233ccd2543fSMatthew G Knepley const PetscInt dim = 3; 234ccd2543fSMatthew G Knepley PetscInt d, e; 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) { 26273868372SMatthew G. Knepley coords[0] = 0.0; 26373868372SMatthew G. Knepley coords[1] = 0.0; 2641ee9d5ecSMatthew G. Knepley if (n[2] < 0.0) { 26573868372SMatthew G. Knepley coords[2] = x2[0]; 26673868372SMatthew G. Knepley coords[3] = x2[1]; 26773868372SMatthew G. Knepley coords[4] = x1[0]; 26873868372SMatthew G. Knepley coords[5] = x1[1]; 269b7ad821dSMatthew G. Knepley R[0] = 1.0; R[1] = 0.0; R[2] = 0.0; 270b7ad821dSMatthew G. Knepley R[3] = 0.0; R[4] = 1.0; R[5] = 0.0; 271b7ad821dSMatthew G. Knepley R[6] = 0.0; R[7] = 0.0; R[8] = -1.0; 27273868372SMatthew G. Knepley } else { 27373868372SMatthew G. Knepley coords[2] = x1[0]; 27473868372SMatthew G. Knepley coords[3] = x1[1]; 27573868372SMatthew G. Knepley coords[4] = x2[0]; 27673868372SMatthew G. Knepley coords[5] = x2[1]; 277b7ad821dSMatthew G. Knepley R[0] = 1.0; R[1] = 0.0; R[2] = 0.0; 278b7ad821dSMatthew G. Knepley R[3] = 0.0; R[4] = 1.0; R[5] = 0.0; 279b7ad821dSMatthew G. Knepley R[6] = 0.0; R[7] = 0.0; R[8] = 1.0; 28073868372SMatthew G. Knepley } 28173868372SMatthew G. Knepley PetscFunctionReturn(0); 28273868372SMatthew G. Knepley } 283da18b5e6SMatthew G Knepley alpha = 1.0/sqrtz; 284ccd2543fSMatthew G Knepley R[0] = alpha*n[0]*n[2]; R[1] = alpha*n[1]*n[2]; R[2] = -sqrtz; 285ccd2543fSMatthew G Knepley R[3] = -alpha*n[1]; R[4] = alpha*n[0]; R[5] = 0.0; 286ccd2543fSMatthew G Knepley R[6] = n[0]; R[7] = n[1]; R[8] = n[2]; 287ccd2543fSMatthew G Knepley for (d = 0; d < dim; ++d) { 288ccd2543fSMatthew G Knepley x1p[d] = 0.0; 289ccd2543fSMatthew G Knepley x2p[d] = 0.0; 290ccd2543fSMatthew G Knepley for (e = 0; e < dim; ++e) { 291ccd2543fSMatthew G Knepley x1p[d] += R[d*dim+e]*x1[e]; 292ccd2543fSMatthew G Knepley x2p[d] += R[d*dim+e]*x2[e]; 293ccd2543fSMatthew G Knepley } 294ccd2543fSMatthew G Knepley } 2958763be8eSMatthew G. Knepley if (PetscAbsReal(x1p[2]) > 1.0e-9) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid rotation calculated"); 2968763be8eSMatthew G. Knepley if (PetscAbsReal(x2p[2]) > 1.0e-9) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid rotation calculated"); 297ccd2543fSMatthew G Knepley /* 2) Project to (x, y) */ 298ccd2543fSMatthew G Knepley coords[0] = 0.0; 299ccd2543fSMatthew G Knepley coords[1] = 0.0; 300ccd2543fSMatthew G Knepley coords[2] = x1p[0]; 301ccd2543fSMatthew G Knepley coords[3] = x1p[1]; 302ccd2543fSMatthew G Knepley coords[4] = x2p[0]; 303ccd2543fSMatthew G Knepley coords[5] = x2p[1]; 3047f07f362SMatthew G. Knepley /* Output R^T which rotates \hat z to the input normal */ 3057f07f362SMatthew G. Knepley for (d = 0; d < dim; ++d) { 3067f07f362SMatthew G. Knepley for (e = d+1; e < dim; ++e) { 3077f07f362SMatthew G. Knepley PetscReal tmp; 3087f07f362SMatthew G. Knepley 3097f07f362SMatthew G. Knepley tmp = R[d*dim+e]; 3107f07f362SMatthew G. Knepley R[d*dim+e] = R[e*dim+d]; 3117f07f362SMatthew G. Knepley R[e*dim+d] = tmp; 3127f07f362SMatthew G. Knepley } 3137f07f362SMatthew G. Knepley } 314ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 315ccd2543fSMatthew G Knepley } 316ccd2543fSMatthew G Knepley 317ccd2543fSMatthew G Knepley #undef __FUNCT__ 3187f07f362SMatthew G. Knepley #define __FUNCT__ "Invert2D_Internal" 3197f07f362SMatthew G. Knepley PETSC_STATIC_INLINE void Invert2D_Internal(PetscReal invJ[], PetscReal J[], PetscReal detJ) 3207f07f362SMatthew G. Knepley { 3217f07f362SMatthew G. Knepley const PetscReal invDet = 1.0/detJ; 3227f07f362SMatthew G. Knepley 3237f07f362SMatthew G. Knepley invJ[0] = invDet*J[3]; 3247f07f362SMatthew G. Knepley invJ[1] = -invDet*J[1]; 3257f07f362SMatthew G. Knepley invJ[2] = -invDet*J[2]; 3267f07f362SMatthew G. Knepley invJ[3] = invDet*J[0]; 3277f07f362SMatthew G. Knepley PetscLogFlops(5.0); 3287f07f362SMatthew G. Knepley } 3297f07f362SMatthew G. Knepley 3307f07f362SMatthew G. Knepley #undef __FUNCT__ 3317f07f362SMatthew G. Knepley #define __FUNCT__ "Invert3D_Internal" 3327f07f362SMatthew G. Knepley PETSC_STATIC_INLINE void Invert3D_Internal(PetscReal invJ[], PetscReal J[], PetscReal detJ) 3337f07f362SMatthew G. Knepley { 3347f07f362SMatthew G. Knepley const PetscReal invDet = 1.0/detJ; 3357f07f362SMatthew G. Knepley 3367f07f362SMatthew G. Knepley invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 3377f07f362SMatthew G. Knepley invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 3387f07f362SMatthew G. Knepley invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 3397f07f362SMatthew G. Knepley invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 3407f07f362SMatthew G. Knepley invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 3417f07f362SMatthew G. Knepley invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 3427f07f362SMatthew G. Knepley invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 3437f07f362SMatthew G. Knepley invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 3447f07f362SMatthew G. Knepley invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 3457f07f362SMatthew G. Knepley PetscLogFlops(37.0); 3467f07f362SMatthew G. Knepley } 3477f07f362SMatthew G. Knepley 3487f07f362SMatthew G. Knepley #undef __FUNCT__ 3497f07f362SMatthew G. Knepley #define __FUNCT__ "Det2D_Internal" 3507f07f362SMatthew G. Knepley PETSC_STATIC_INLINE void Det2D_Internal(PetscReal *detJ, PetscReal J[]) 3517f07f362SMatthew G. Knepley { 3527f07f362SMatthew G. Knepley *detJ = J[0]*J[3] - J[1]*J[2]; 3537f07f362SMatthew G. Knepley PetscLogFlops(3.0); 3547f07f362SMatthew G. Knepley } 3557f07f362SMatthew G. Knepley 3567f07f362SMatthew G. Knepley #undef __FUNCT__ 3577f07f362SMatthew G. Knepley #define __FUNCT__ "Det3D_Internal" 3587f07f362SMatthew G. Knepley PETSC_STATIC_INLINE void Det3D_Internal(PetscReal *detJ, PetscReal J[]) 3597f07f362SMatthew G. Knepley { 360b7ad821dSMatthew G. Knepley *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 361b7ad821dSMatthew G. Knepley J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 362b7ad821dSMatthew G. Knepley J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 3637f07f362SMatthew G. Knepley PetscLogFlops(12.0); 3647f07f362SMatthew G. Knepley } 3657f07f362SMatthew G. Knepley 3667f07f362SMatthew G. Knepley #undef __FUNCT__ 367834e62ceSMatthew G. Knepley #define __FUNCT__ "Volume_Triangle_Internal" 368834e62ceSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Triangle_Internal(PetscReal *vol, PetscReal coords[]) 369834e62ceSMatthew G. Knepley { 370834e62ceSMatthew G. Knepley /* Signed volume is 1/2 the determinant 371834e62ceSMatthew G. Knepley 372834e62ceSMatthew G. Knepley | 1 1 1 | 373834e62ceSMatthew G. Knepley | x0 x1 x2 | 374834e62ceSMatthew G. Knepley | y0 y1 y2 | 375834e62ceSMatthew G. Knepley 376834e62ceSMatthew G. Knepley but if x0,y0 is the origin, we have 377834e62ceSMatthew G. Knepley 378834e62ceSMatthew G. Knepley | x1 x2 | 379834e62ceSMatthew G. Knepley | y1 y2 | 380834e62ceSMatthew G. Knepley */ 381834e62ceSMatthew G. Knepley const PetscReal x1 = coords[2] - coords[0], y1 = coords[3] - coords[1]; 382834e62ceSMatthew G. Knepley const PetscReal x2 = coords[4] - coords[0], y2 = coords[5] - coords[1]; 383834e62ceSMatthew G. Knepley PetscReal M[4], detM; 384834e62ceSMatthew G. Knepley M[0] = x1; M[1] = x2; 38586623015SMatthew G. Knepley M[2] = y1; M[3] = y2; 386834e62ceSMatthew G. Knepley Det2D_Internal(&detM, M); 387834e62ceSMatthew G. Knepley *vol = 0.5*detM; 388834e62ceSMatthew G. Knepley PetscLogFlops(5.0); 389834e62ceSMatthew G. Knepley } 390834e62ceSMatthew G. Knepley 391834e62ceSMatthew G. Knepley #undef __FUNCT__ 392834e62ceSMatthew G. Knepley #define __FUNCT__ "Volume_Triangle_Origin_Internal" 393834e62ceSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Triangle_Origin_Internal(PetscReal *vol, PetscReal coords[]) 394834e62ceSMatthew G. Knepley { 395834e62ceSMatthew G. Knepley Det2D_Internal(vol, coords); 396834e62ceSMatthew G. Knepley *vol *= 0.5; 397834e62ceSMatthew G. Knepley } 398834e62ceSMatthew G. Knepley 399834e62ceSMatthew G. Knepley #undef __FUNCT__ 400834e62ceSMatthew G. Knepley #define __FUNCT__ "Volume_Tetrahedron_Internal" 401834e62ceSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Tetrahedron_Internal(PetscReal *vol, PetscReal coords[]) 402834e62ceSMatthew G. Knepley { 403834e62ceSMatthew G. Knepley /* Signed volume is 1/6th of the determinant 404834e62ceSMatthew G. Knepley 405834e62ceSMatthew G. Knepley | 1 1 1 1 | 406834e62ceSMatthew G. Knepley | x0 x1 x2 x3 | 407834e62ceSMatthew G. Knepley | y0 y1 y2 y3 | 408834e62ceSMatthew G. Knepley | z0 z1 z2 z3 | 409834e62ceSMatthew G. Knepley 410834e62ceSMatthew G. Knepley but if x0,y0,z0 is the origin, we have 411834e62ceSMatthew G. Knepley 412834e62ceSMatthew G. Knepley | x1 x2 x3 | 413834e62ceSMatthew G. Knepley | y1 y2 y3 | 414834e62ceSMatthew G. Knepley | z1 z2 z3 | 415834e62ceSMatthew G. Knepley */ 416834e62ceSMatthew G. Knepley const PetscReal x1 = coords[3] - coords[0], y1 = coords[4] - coords[1], z1 = coords[5] - coords[2]; 417834e62ceSMatthew G. Knepley const PetscReal x2 = coords[6] - coords[0], y2 = coords[7] - coords[1], z2 = coords[8] - coords[2]; 418834e62ceSMatthew G. Knepley const PetscReal x3 = coords[9] - coords[0], y3 = coords[10] - coords[1], z3 = coords[11] - coords[2]; 419834e62ceSMatthew G. Knepley PetscReal M[9], detM; 420834e62ceSMatthew G. Knepley M[0] = x1; M[1] = x2; M[2] = x3; 421834e62ceSMatthew G. Knepley M[3] = y1; M[4] = y2; M[5] = y3; 422834e62ceSMatthew G. Knepley M[6] = z1; M[7] = z2; M[8] = z3; 423834e62ceSMatthew G. Knepley Det3D_Internal(&detM, M); 424b7ad821dSMatthew G. Knepley *vol = -0.16666666666666666666666*detM; 425834e62ceSMatthew G. Knepley PetscLogFlops(10.0); 426834e62ceSMatthew G. Knepley } 427834e62ceSMatthew G. Knepley 428834e62ceSMatthew G. Knepley #undef __FUNCT__ 4290ec8681fSMatthew G. Knepley #define __FUNCT__ "Volume_Tetrahedron_Origin_Internal" 4300ec8681fSMatthew G. Knepley PETSC_STATIC_INLINE void Volume_Tetrahedron_Origin_Internal(PetscReal *vol, PetscReal coords[]) 4310ec8681fSMatthew G. Knepley { 4320ec8681fSMatthew G. Knepley Det3D_Internal(vol, coords); 433b7ad821dSMatthew G. Knepley *vol *= -0.16666666666666666666666; 4340ec8681fSMatthew G. Knepley } 4350ec8681fSMatthew G. Knepley 4360ec8681fSMatthew G. Knepley #undef __FUNCT__ 43717fe8556SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeLineGeometry_Internal" 43817fe8556SMatthew G. Knepley static PetscErrorCode DMPlexComputeLineGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 43917fe8556SMatthew G. Knepley { 44017fe8556SMatthew G. Knepley PetscSection coordSection; 44117fe8556SMatthew G. Knepley Vec coordinates; 44217fe8556SMatthew G. Knepley PetscScalar *coords; 4437f07f362SMatthew G. Knepley PetscInt numCoords, d; 44417fe8556SMatthew G. Knepley PetscErrorCode ierr; 44517fe8556SMatthew G. Knepley 44617fe8556SMatthew G. Knepley PetscFunctionBegin; 44717fe8556SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 44817fe8556SMatthew G. Knepley ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 44917fe8556SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 4507f07f362SMatthew G. Knepley *detJ = 0.0; 45117fe8556SMatthew G. Knepley if (numCoords == 4) { 4527f07f362SMatthew G. Knepley const PetscInt dim = 2; 4537f07f362SMatthew G. Knepley PetscReal R[4], J0; 4547f07f362SMatthew G. Knepley 4557f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 4567f07f362SMatthew G. Knepley ierr = DMPlexComputeProjection2Dto1D_Internal(coords, R);CHKERRQ(ierr); 45717fe8556SMatthew G. Knepley if (J) { 4587f07f362SMatthew G. Knepley J0 = 0.5*PetscRealPart(coords[1]); 4597f07f362SMatthew G. Knepley J[0] = R[0]*J0; J[1] = R[1]; 4607f07f362SMatthew G. Knepley J[2] = R[2]*J0; J[3] = R[3]; 4617f07f362SMatthew G. Knepley Det2D_Internal(detJ, J); 46217fe8556SMatthew G. Knepley } 4637f07f362SMatthew G. Knepley if (invJ) {Invert2D_Internal(invJ, J, *detJ);} 4647f07f362SMatthew G. Knepley } else if (numCoords == 2) { 4657f07f362SMatthew G. Knepley const PetscInt dim = 1; 4667f07f362SMatthew G. Knepley 4677f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 4687f07f362SMatthew G. Knepley if (J) { 4697f07f362SMatthew G. Knepley J[0] = 0.5*(PetscRealPart(coords[1]) - PetscRealPart(coords[0])); 47017fe8556SMatthew G. Knepley *detJ = J[0]; 47117fe8556SMatthew G. Knepley PetscLogFlops(2.0); 47217fe8556SMatthew G. Knepley } 4737f07f362SMatthew G. Knepley if (invJ) {invJ[0] = 1.0/J[0]; PetscLogFlops(1.0);} 4747f07f362SMatthew G. Knepley } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of coordinates for this segment is %d != 2", numCoords); 47517fe8556SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 47617fe8556SMatthew G. Knepley PetscFunctionReturn(0); 47717fe8556SMatthew G. Knepley } 47817fe8556SMatthew G. Knepley 47917fe8556SMatthew G. Knepley #undef __FUNCT__ 480ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeTriangleGeometry_Internal" 481ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexComputeTriangleGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 482ccd2543fSMatthew G Knepley { 483ccd2543fSMatthew G Knepley PetscSection coordSection; 484ccd2543fSMatthew G Knepley Vec coordinates; 4857c1f9639SMatthew G Knepley PetscScalar *coords; 4867f07f362SMatthew G. Knepley PetscInt numCoords, d, f, g; 487ccd2543fSMatthew G Knepley PetscErrorCode ierr; 488ccd2543fSMatthew G Knepley 489ccd2543fSMatthew G Knepley PetscFunctionBegin; 490ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 491ccd2543fSMatthew G Knepley ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 492ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 4937f07f362SMatthew G. Knepley *detJ = 0.0; 494ccd2543fSMatthew G Knepley if (numCoords == 9) { 4957f07f362SMatthew G. Knepley const PetscInt dim = 3; 4967f07f362SMatthew 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}; 4977f07f362SMatthew G. Knepley 4987f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 4997f07f362SMatthew G. Knepley ierr = DMPlexComputeProjection3Dto2D_Internal(coords, R);CHKERRQ(ierr); 5007f07f362SMatthew G. Knepley if (J) { 501b7ad821dSMatthew G. Knepley const PetscInt pdim = 2; 502b7ad821dSMatthew G. Knepley 503b7ad821dSMatthew G. Knepley for (d = 0; d < pdim; d++) { 504b7ad821dSMatthew G. Knepley for (f = 0; f < pdim; f++) { 505b7ad821dSMatthew G. Knepley J0[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*pdim+d]) - PetscRealPart(coords[0*pdim+d])); 506ccd2543fSMatthew G Knepley } 5077f07f362SMatthew G. Knepley } 5087f07f362SMatthew G. Knepley PetscLogFlops(8.0); 50987d60e71SMatthew G. Knepley Det3D_Internal(detJ, J0); 5107f07f362SMatthew G. Knepley for (d = 0; d < dim; d++) { 5117f07f362SMatthew G. Knepley for (f = 0; f < dim; f++) { 5127f07f362SMatthew G. Knepley J[d*dim+f] = 0.0; 5137f07f362SMatthew G. Knepley for (g = 0; g < dim; g++) { 5147f07f362SMatthew G. Knepley J[d*dim+f] += R[d*dim+g]*J0[g*dim+f]; 5157f07f362SMatthew G. Knepley } 5167f07f362SMatthew G. Knepley } 5177f07f362SMatthew G. Knepley } 5187f07f362SMatthew G. Knepley PetscLogFlops(18.0); 5197f07f362SMatthew G. Knepley } 5207f07f362SMatthew G. Knepley if (invJ) {Invert3D_Internal(invJ, J, *detJ);} 5217f07f362SMatthew G. Knepley } else if (numCoords == 6) { 5227f07f362SMatthew G. Knepley const PetscInt dim = 2; 5237f07f362SMatthew G. Knepley 5247f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 525ccd2543fSMatthew G Knepley if (J) { 526ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 527ccd2543fSMatthew G Knepley for (f = 0; f < dim; f++) { 528ccd2543fSMatthew G Knepley J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 529ccd2543fSMatthew G Knepley } 530ccd2543fSMatthew G Knepley } 5317f07f362SMatthew G. Knepley PetscLogFlops(8.0); 5327f07f362SMatthew G. Knepley Det2D_Internal(detJ, J); 533ccd2543fSMatthew G Knepley } 5347f07f362SMatthew G. Knepley if (invJ) {Invert2D_Internal(invJ, J, *detJ);} 5357f07f362SMatthew G. Knepley } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of coordinates for this triangle is %d != 6", numCoords); 536ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, &numCoords, &coords);CHKERRQ(ierr); 537ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 538ccd2543fSMatthew G Knepley } 539ccd2543fSMatthew G Knepley 540ccd2543fSMatthew G Knepley #undef __FUNCT__ 541ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeRectangleGeometry_Internal" 542ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexComputeRectangleGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 543ccd2543fSMatthew G Knepley { 544ccd2543fSMatthew G Knepley PetscSection coordSection; 545ccd2543fSMatthew G Knepley Vec coordinates; 5467c1f9639SMatthew G Knepley PetscScalar *coords; 547ccd2543fSMatthew G Knepley const PetscInt dim = 2; 548ccd2543fSMatthew G Knepley PetscInt d, f; 549ccd2543fSMatthew G Knepley PetscErrorCode ierr; 550ccd2543fSMatthew G Knepley 551ccd2543fSMatthew G Knepley PetscFunctionBegin; 552ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 553ccd2543fSMatthew G Knepley ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 554ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 5557f07f362SMatthew G. Knepley *detJ = 0.0; 5567f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 557ccd2543fSMatthew G Knepley if (J) { 558ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 559ccd2543fSMatthew G Knepley for (f = 0; f < dim; f++) { 560ccd2543fSMatthew G Knepley J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 561ccd2543fSMatthew G Knepley } 562ccd2543fSMatthew G Knepley } 5637f07f362SMatthew G. Knepley PetscLogFlops(8.0); 5647f07f362SMatthew G. Knepley Det2D_Internal(detJ, J); 565ccd2543fSMatthew G Knepley } 5667f07f362SMatthew G. Knepley if (invJ) {Invert2D_Internal(invJ, J, *detJ);} 567ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 568ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 569ccd2543fSMatthew G Knepley } 570ccd2543fSMatthew G Knepley 571ccd2543fSMatthew G Knepley #undef __FUNCT__ 572ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_Internal" 573ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexComputeTetrahedronGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 574ccd2543fSMatthew G Knepley { 575ccd2543fSMatthew G Knepley PetscSection coordSection; 576ccd2543fSMatthew G Knepley Vec coordinates; 5777c1f9639SMatthew G Knepley PetscScalar *coords; 578ccd2543fSMatthew G Knepley const PetscInt dim = 3; 579ccd2543fSMatthew G Knepley PetscInt d, f; 580ccd2543fSMatthew G Knepley PetscErrorCode ierr; 581ccd2543fSMatthew G Knepley 582ccd2543fSMatthew G Knepley PetscFunctionBegin; 583ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 584ccd2543fSMatthew G Knepley ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 585ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 5867f07f362SMatthew G. Knepley *detJ = 0.0; 5877f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 588ccd2543fSMatthew G Knepley if (J) { 589ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 590ccd2543fSMatthew G Knepley for (f = 0; f < dim; f++) { 591ccd2543fSMatthew G Knepley J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 592ccd2543fSMatthew G Knepley } 593ccd2543fSMatthew G Knepley } 5947f07f362SMatthew G. Knepley PetscLogFlops(18.0); 5957f07f362SMatthew G. Knepley Det3D_Internal(detJ, J); 596b7ad821dSMatthew G. Knepley *detJ = -*detJ; 597ccd2543fSMatthew G Knepley } 5987f07f362SMatthew G. Knepley if (invJ) {Invert3D_Internal(invJ, J, *detJ);} 599ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 600ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 601ccd2543fSMatthew G Knepley } 602ccd2543fSMatthew G Knepley 603ccd2543fSMatthew G Knepley #undef __FUNCT__ 604ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeHexahedronGeometry_Internal" 605ccd2543fSMatthew G Knepley static PetscErrorCode DMPlexComputeHexahedronGeometry_Internal(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 606ccd2543fSMatthew G Knepley { 607ccd2543fSMatthew G Knepley PetscSection coordSection; 608ccd2543fSMatthew G Knepley Vec coordinates; 6097c1f9639SMatthew G Knepley PetscScalar *coords; 610ccd2543fSMatthew G Knepley const PetscInt dim = 3; 611ccd2543fSMatthew G Knepley PetscInt d; 612ccd2543fSMatthew G Knepley PetscErrorCode ierr; 613ccd2543fSMatthew G Knepley 614ccd2543fSMatthew G Knepley PetscFunctionBegin; 615ccd2543fSMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 616ccd2543fSMatthew G Knepley ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 617ccd2543fSMatthew G Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 6187f07f362SMatthew G. Knepley *detJ = 0.0; 6197f07f362SMatthew G. Knepley if (v0) {for (d = 0; d < dim; d++) v0[d] = PetscRealPart(coords[d]);} 620ccd2543fSMatthew G Knepley if (J) { 621ccd2543fSMatthew G Knepley for (d = 0; d < dim; d++) { 622de36ddddSMatthew G. Knepley J[d*dim+0] = 0.5*(PetscRealPart(coords[(2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 623ccd2543fSMatthew G Knepley J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 624ccd2543fSMatthew G Knepley J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 625ccd2543fSMatthew G Knepley } 6267f07f362SMatthew G. Knepley PetscLogFlops(18.0); 6277f07f362SMatthew G. Knepley Det3D_Internal(detJ, J); 628b7ad821dSMatthew G. Knepley *detJ = -*detJ; 629ccd2543fSMatthew G Knepley } 6307f07f362SMatthew G. Knepley if (invJ) {Invert3D_Internal(invJ, J, *detJ);} 6317f07f362SMatthew G. Knepley *detJ *= -8.0; 632ccd2543fSMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, NULL, &coords);CHKERRQ(ierr); 633ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 634ccd2543fSMatthew G Knepley } 635ccd2543fSMatthew G Knepley 636ccd2543fSMatthew G Knepley #undef __FUNCT__ 637ccd2543fSMatthew G Knepley #define __FUNCT__ "DMPlexComputeCellGeometry" 638ccd2543fSMatthew G Knepley /*@C 639ccd2543fSMatthew G Knepley DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 640ccd2543fSMatthew G Knepley 641ccd2543fSMatthew G Knepley Collective on DM 642ccd2543fSMatthew G Knepley 643ccd2543fSMatthew G Knepley Input Arguments: 644ccd2543fSMatthew G Knepley + dm - the DM 645ccd2543fSMatthew G Knepley - cell - the cell 646ccd2543fSMatthew G Knepley 647ccd2543fSMatthew G Knepley Output Arguments: 648ccd2543fSMatthew G Knepley + v0 - the translation part of this affine transform 649ccd2543fSMatthew G Knepley . J - the Jacobian of the transform from the reference element 650ccd2543fSMatthew G Knepley . invJ - the inverse of the Jacobian 651ccd2543fSMatthew G Knepley - detJ - the Jacobian determinant 652ccd2543fSMatthew G Knepley 653ccd2543fSMatthew G Knepley Level: advanced 654ccd2543fSMatthew G Knepley 655ccd2543fSMatthew G Knepley Fortran Notes: 656ccd2543fSMatthew G Knepley Since it returns arrays, this routine is only available in Fortran 90, and you must 657ccd2543fSMatthew G Knepley include petsc.h90 in your code. 658ccd2543fSMatthew G Knepley 659ccd2543fSMatthew G Knepley .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 660ccd2543fSMatthew G Knepley @*/ 661ccd2543fSMatthew G Knepley PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) 662ccd2543fSMatthew G Knepley { 66349dc4407SMatthew G. Knepley PetscInt depth, dim, coneSize; 664ccd2543fSMatthew G Knepley PetscErrorCode ierr; 665ccd2543fSMatthew G Knepley 666ccd2543fSMatthew G Knepley PetscFunctionBegin; 667139a35ccSMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 668ccd2543fSMatthew G Knepley ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 66949dc4407SMatthew G. Knepley if (depth == 1) { 6705743f1d7SMatthew G. Knepley ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 671ccd2543fSMatthew G Knepley switch (dim) { 67217fe8556SMatthew G. Knepley case 1: 67317fe8556SMatthew G. Knepley ierr = DMPlexComputeLineGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 67417fe8556SMatthew G. Knepley break; 675ccd2543fSMatthew G Knepley case 2: 676ccd2543fSMatthew G Knepley switch (coneSize) { 677ccd2543fSMatthew G Knepley case 3: 678ccd2543fSMatthew G Knepley ierr = DMPlexComputeTriangleGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 679ccd2543fSMatthew G Knepley break; 680ccd2543fSMatthew G Knepley case 4: 681ccd2543fSMatthew G Knepley ierr = DMPlexComputeRectangleGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 682ccd2543fSMatthew G Knepley break; 683ccd2543fSMatthew G Knepley default: 684ccd2543fSMatthew G Knepley SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 685ccd2543fSMatthew G Knepley } 686ccd2543fSMatthew G Knepley break; 687ccd2543fSMatthew G Knepley case 3: 688ccd2543fSMatthew G Knepley switch (coneSize) { 689ccd2543fSMatthew G Knepley case 4: 690ccd2543fSMatthew G Knepley ierr = DMPlexComputeTetrahedronGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 691ccd2543fSMatthew G Knepley break; 692ccd2543fSMatthew G Knepley case 8: 693ccd2543fSMatthew G Knepley ierr = DMPlexComputeHexahedronGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 694ccd2543fSMatthew G Knepley break; 695ccd2543fSMatthew G Knepley default: 696ccd2543fSMatthew G Knepley SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 697ccd2543fSMatthew G Knepley } 698ccd2543fSMatthew G Knepley break; 699ccd2543fSMatthew G Knepley default: 700ccd2543fSMatthew G Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 701ccd2543fSMatthew G Knepley } 70249dc4407SMatthew G. Knepley } else { 7035743f1d7SMatthew G. Knepley /* We need to keep a pointer to the depth label */ 7045743f1d7SMatthew G. Knepley ierr = DMPlexGetLabelValue(dm, "depth", cell, &dim);CHKERRQ(ierr); 70549dc4407SMatthew G. Knepley /* Cone size is now the number of faces */ 70649dc4407SMatthew G. Knepley switch (dim) { 70717fe8556SMatthew G. Knepley case 1: 70817fe8556SMatthew G. Knepley ierr = DMPlexComputeLineGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 70917fe8556SMatthew G. Knepley break; 71049dc4407SMatthew G. Knepley case 2: 71149dc4407SMatthew G. Knepley switch (coneSize) { 71249dc4407SMatthew G. Knepley case 3: 71349dc4407SMatthew G. Knepley ierr = DMPlexComputeTriangleGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 71449dc4407SMatthew G. Knepley break; 71549dc4407SMatthew G. Knepley case 4: 71649dc4407SMatthew G. Knepley ierr = DMPlexComputeRectangleGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 71749dc4407SMatthew G. Knepley break; 71849dc4407SMatthew G. Knepley default: 71949dc4407SMatthew G. Knepley SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 72049dc4407SMatthew G. Knepley } 72149dc4407SMatthew G. Knepley break; 72249dc4407SMatthew G. Knepley case 3: 72349dc4407SMatthew G. Knepley switch (coneSize) { 72449dc4407SMatthew G. Knepley case 4: 72549dc4407SMatthew G. Knepley ierr = DMPlexComputeTetrahedronGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 72649dc4407SMatthew G. Knepley break; 72749dc4407SMatthew G. Knepley case 6: 72849dc4407SMatthew G. Knepley ierr = DMPlexComputeHexahedronGeometry_Internal(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 72949dc4407SMatthew G. Knepley break; 73049dc4407SMatthew G. Knepley default: 73149dc4407SMatthew G. Knepley SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported number of vertices %D in cell %D for element geometry computation", coneSize, cell); 73249dc4407SMatthew G. Knepley } 73349dc4407SMatthew G. Knepley break; 73449dc4407SMatthew G. Knepley default: 73549dc4407SMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 73649dc4407SMatthew G. Knepley } 73749dc4407SMatthew G. Knepley } 738ccd2543fSMatthew G Knepley PetscFunctionReturn(0); 739ccd2543fSMatthew G Knepley } 740834e62ceSMatthew G. Knepley 741834e62ceSMatthew G. Knepley #undef __FUNCT__ 742cc08537eSMatthew G. Knepley #define __FUNCT__ "DMPlexComputeGeometryFVM_1D_Internal" 743011ea5d8SMatthew G. Knepley static PetscErrorCode DMPlexComputeGeometryFVM_1D_Internal(DM dm, PetscInt dim, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 744cc08537eSMatthew G. Knepley { 745cc08537eSMatthew G. Knepley PetscSection coordSection; 746cc08537eSMatthew G. Knepley Vec coordinates; 747cc08537eSMatthew G. Knepley PetscScalar *coords; 748cc08537eSMatthew G. Knepley PetscInt coordSize; 749cc08537eSMatthew G. Knepley PetscErrorCode ierr; 750cc08537eSMatthew G. Knepley 751cc08537eSMatthew G. Knepley PetscFunctionBegin; 752cc08537eSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 753cc08537eSMatthew G. Knepley ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 754cc08537eSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 755011ea5d8SMatthew G. Knepley if (dim != 2) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support 2D edges right now"); 756cc08537eSMatthew G. Knepley if (centroid) { 7571ee9d5ecSMatthew G. Knepley centroid[0] = 0.5*PetscRealPart(coords[0] + coords[dim+0]); 7581ee9d5ecSMatthew G. Knepley centroid[1] = 0.5*PetscRealPart(coords[1] + coords[dim+1]); 759cc08537eSMatthew G. Knepley } 760cc08537eSMatthew G. Knepley if (normal) { 7611ee9d5ecSMatthew G. Knepley normal[0] = PetscRealPart(coords[1] - coords[dim+1]); 7621ee9d5ecSMatthew G. Knepley normal[1] = -PetscRealPart(coords[0] - coords[dim+0]); 763cc08537eSMatthew G. Knepley } 764cc08537eSMatthew G. Knepley if (vol) { 7651ee9d5ecSMatthew G. Knepley *vol = sqrt(PetscSqr(PetscRealPart(coords[0] - coords[dim+0])) + PetscSqr(PetscRealPart(coords[1] - coords[dim+1]))); 766cc08537eSMatthew G. Knepley } 767cc08537eSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 768cc08537eSMatthew G. Knepley PetscFunctionReturn(0); 769cc08537eSMatthew G. Knepley } 770cc08537eSMatthew G. Knepley 771cc08537eSMatthew G. Knepley #undef __FUNCT__ 772cc08537eSMatthew G. Knepley #define __FUNCT__ "DMPlexComputeGeometryFVM_2D_Internal" 773cc08537eSMatthew G. Knepley /* Centroid_i = (\sum_n A_n Cn_i ) / A */ 774011ea5d8SMatthew G. Knepley static PetscErrorCode DMPlexComputeGeometryFVM_2D_Internal(DM dm, PetscInt dim, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 775cc08537eSMatthew G. Knepley { 776cc08537eSMatthew G. Knepley PetscSection coordSection; 777cc08537eSMatthew G. Knepley Vec coordinates; 778cc08537eSMatthew G. Knepley PetscScalar *coords = NULL; 7790a1d6728SMatthew G. Knepley PetscReal vsum = 0.0, csum[3] = {0.0, 0.0, 0.0}, vtmp, ctmp[4], v0[3], R[9]; 7800a1d6728SMatthew G. Knepley PetscInt tdim = 2, coordSize, numCorners, p, d, e; 781cc08537eSMatthew G. Knepley PetscErrorCode ierr; 782cc08537eSMatthew G. Knepley 783cc08537eSMatthew G. Knepley PetscFunctionBegin; 784cc08537eSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 7850a1d6728SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cell, &numCorners);CHKERRQ(ierr); 786cc08537eSMatthew G. Knepley ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 787cc08537eSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 7880a1d6728SMatthew G. Knepley dim = coordSize/numCorners; 789011ea5d8SMatthew G. Knepley if (normal) { 790011ea5d8SMatthew G. Knepley if (dim > 2) { 7911ee9d5ecSMatthew G. Knepley const PetscReal x0 = PetscRealPart(coords[dim+0] - coords[0]), x1 = PetscRealPart(coords[dim*2+0] - coords[0]); 7921ee9d5ecSMatthew G. Knepley const PetscReal y0 = PetscRealPart(coords[dim+1] - coords[1]), y1 = PetscRealPart(coords[dim*2+1] - coords[1]); 7931ee9d5ecSMatthew G. Knepley const PetscReal z0 = PetscRealPart(coords[dim+2] - coords[2]), z1 = PetscRealPart(coords[dim*2+2] - coords[2]); 7940a1d6728SMatthew G. Knepley PetscReal norm; 7950a1d6728SMatthew G. Knepley 7961ee9d5ecSMatthew G. Knepley v0[0] = PetscRealPart(coords[0]); 7971ee9d5ecSMatthew G. Knepley v0[1] = PetscRealPart(coords[1]); 7981ee9d5ecSMatthew G. Knepley v0[2] = PetscRealPart(coords[2]); 7990a1d6728SMatthew G. Knepley normal[0] = y0*z1 - z0*y1; 8000a1d6728SMatthew G. Knepley normal[1] = z0*x1 - x0*z1; 8010a1d6728SMatthew G. Knepley normal[2] = x0*y1 - y0*x1; 8020a1d6728SMatthew G. Knepley norm = sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]); 8030a1d6728SMatthew G. Knepley normal[0] /= norm; 8040a1d6728SMatthew G. Knepley normal[1] /= norm; 8050a1d6728SMatthew G. Knepley normal[2] /= norm; 806011ea5d8SMatthew G. Knepley } else { 807011ea5d8SMatthew G. Knepley for (d = 0; d < dim; ++d) normal[d] = 0.0; 808011ea5d8SMatthew G. Knepley } 809011ea5d8SMatthew G. Knepley } 8100a1d6728SMatthew G. Knepley if (dim == 3) {ierr = DMPlexComputeProjection3Dto2D_Internal(coords, R);CHKERRQ(ierr);} 8110a1d6728SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 8120a1d6728SMatthew G. Knepley /* Need to do this copy to get types right */ 8130a1d6728SMatthew G. Knepley for (d = 0; d < tdim; ++d) { 8141ee9d5ecSMatthew G. Knepley ctmp[d] = PetscRealPart(coords[p*tdim+d]); 8151ee9d5ecSMatthew G. Knepley ctmp[tdim+d] = PetscRealPart(coords[((p+1)%numCorners)*tdim+d]); 8160a1d6728SMatthew G. Knepley } 8170a1d6728SMatthew G. Knepley Volume_Triangle_Origin_Internal(&vtmp, ctmp); 8180a1d6728SMatthew G. Knepley vsum += vtmp; 8190a1d6728SMatthew G. Knepley for (d = 0; d < tdim; ++d) { 8200a1d6728SMatthew G. Knepley csum[d] += (ctmp[d] + ctmp[tdim+d])*vtmp; 8210a1d6728SMatthew G. Knepley } 8220a1d6728SMatthew G. Knepley } 8230a1d6728SMatthew G. Knepley for (d = 0; d < tdim; ++d) { 8240a1d6728SMatthew G. Knepley csum[d] /= (tdim+1)*vsum; 8250a1d6728SMatthew G. Knepley } 8260a1d6728SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 827*ee6bbdb2SSatish Balay if (vol) *vol = PetscAbsReal(vsum); 8280a1d6728SMatthew G. Knepley if (centroid) { 8290a1d6728SMatthew G. Knepley if (dim > 2) { 8300a1d6728SMatthew G. Knepley for (d = 0; d < dim; ++d) { 8310a1d6728SMatthew G. Knepley centroid[d] = v0[d]; 8320a1d6728SMatthew G. Knepley for (e = 0; e < dim; ++e) { 8330a1d6728SMatthew G. Knepley centroid[d] += R[d*dim+e]*csum[e]; 8340a1d6728SMatthew G. Knepley } 8350a1d6728SMatthew G. Knepley } 8360a1d6728SMatthew G. Knepley } else for (d = 0; d < dim; ++d) centroid[d] = csum[d]; 8370a1d6728SMatthew G. Knepley } 838cc08537eSMatthew G. Knepley PetscFunctionReturn(0); 839cc08537eSMatthew G. Knepley } 840cc08537eSMatthew G. Knepley 841cc08537eSMatthew G. Knepley #undef __FUNCT__ 8420ec8681fSMatthew G. Knepley #define __FUNCT__ "DMPlexComputeGeometryFVM_3D_Internal" 8430ec8681fSMatthew G. Knepley /* Centroid_i = (\sum_n V_n Cn_i ) / V */ 844011ea5d8SMatthew G. Knepley static PetscErrorCode DMPlexComputeGeometryFVM_3D_Internal(DM dm, PetscInt dim, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 8450ec8681fSMatthew G. Knepley { 8460ec8681fSMatthew G. Knepley PetscSection coordSection; 8470ec8681fSMatthew G. Knepley Vec coordinates; 8480ec8681fSMatthew G. Knepley PetscScalar *coords = NULL; 84986623015SMatthew G. Knepley PetscReal vsum = 0.0, vtmp, coordsTmp[3*3]; 850011ea5d8SMatthew G. Knepley const PetscInt *faces; 8510ec8681fSMatthew G. Knepley PetscInt numFaces, f, coordSize, numCorners, p, d; 8520ec8681fSMatthew G. Knepley PetscErrorCode ierr; 8530ec8681fSMatthew G. Knepley 8540ec8681fSMatthew G. Knepley PetscFunctionBegin; 8550ec8681fSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8560ec8681fSMatthew G. Knepley ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8570ec8681fSMatthew G. Knepley 8580ec8681fSMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cell, &numFaces);CHKERRQ(ierr); 8590ec8681fSMatthew G. Knepley ierr = DMPlexGetCone(dm, cell, &faces);CHKERRQ(ierr); 8600ec8681fSMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 861011ea5d8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, faces[f], &coordSize, &coords);CHKERRQ(ierr); 8620ec8681fSMatthew G. Knepley numCorners = coordSize/dim; 8630ec8681fSMatthew G. Knepley switch (numCorners) { 8640ec8681fSMatthew G. Knepley case 3: 8650ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8661ee9d5ecSMatthew G. Knepley coordsTmp[0*dim+d] = PetscRealPart(coords[0*dim+d]); 8671ee9d5ecSMatthew G. Knepley coordsTmp[1*dim+d] = PetscRealPart(coords[1*dim+d]); 8681ee9d5ecSMatthew G. Knepley coordsTmp[2*dim+d] = PetscRealPart(coords[2*dim+d]); 8690ec8681fSMatthew G. Knepley } 8700ec8681fSMatthew G. Knepley Volume_Tetrahedron_Origin_Internal(&vtmp, coordsTmp); 8710ec8681fSMatthew G. Knepley vsum += vtmp; 8720ec8681fSMatthew G. Knepley if (centroid) { 8730ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8741ee9d5ecSMatthew G. Knepley for (p = 0; p < 3; ++p) centroid[d] += coordsTmp[p*dim+d]*vtmp; 8750ec8681fSMatthew G. Knepley } 8760ec8681fSMatthew G. Knepley } 8770ec8681fSMatthew G. Knepley break; 8780ec8681fSMatthew G. Knepley case 4: 8790ec8681fSMatthew G. Knepley /* DO FOR PYRAMID */ 8800ec8681fSMatthew G. Knepley /* First tet */ 8810ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8821ee9d5ecSMatthew G. Knepley coordsTmp[0*dim+d] = PetscRealPart(coords[0*dim+d]); 8831ee9d5ecSMatthew G. Knepley coordsTmp[1*dim+d] = PetscRealPart(coords[1*dim+d]); 8841ee9d5ecSMatthew G. Knepley coordsTmp[2*dim+d] = PetscRealPart(coords[3*dim+d]); 8850ec8681fSMatthew G. Knepley } 8860ec8681fSMatthew G. Knepley Volume_Tetrahedron_Origin_Internal(&vtmp, coordsTmp); 8870ec8681fSMatthew G. Knepley vsum += vtmp; 8880ec8681fSMatthew G. Knepley if (centroid) { 8890ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8900ec8681fSMatthew G. Knepley for (p = 0; p < 3; ++p) centroid[d] += coordsTmp[p*dim+d]*vtmp; 8910ec8681fSMatthew G. Knepley } 8920ec8681fSMatthew G. Knepley } 8930ec8681fSMatthew G. Knepley /* Second tet */ 8940ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8951ee9d5ecSMatthew G. Knepley coordsTmp[0*dim+d] = PetscRealPart(coords[1*dim+d]); 8961ee9d5ecSMatthew G. Knepley coordsTmp[1*dim+d] = PetscRealPart(coords[2*dim+d]); 8971ee9d5ecSMatthew G. Knepley coordsTmp[2*dim+d] = PetscRealPart(coords[3*dim+d]); 8980ec8681fSMatthew G. Knepley } 8990ec8681fSMatthew G. Knepley Volume_Tetrahedron_Origin_Internal(&vtmp, coordsTmp); 9000ec8681fSMatthew G. Knepley vsum += vtmp; 9010ec8681fSMatthew G. Knepley if (centroid) { 9020ec8681fSMatthew G. Knepley for (d = 0; d < dim; ++d) { 9030ec8681fSMatthew G. Knepley for (p = 0; p < 3; ++p) centroid[d] += coordsTmp[p*dim+d]*vtmp; 9040ec8681fSMatthew G. Knepley } 9050ec8681fSMatthew G. Knepley } 9060ec8681fSMatthew G. Knepley break; 9070ec8681fSMatthew G. Knepley default: 9080ec8681fSMatthew G. Knepley SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle faces with %d vertices", numCorners); 9090ec8681fSMatthew G. Knepley } 9100ec8681fSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, cell, &coordSize, &coords);CHKERRQ(ierr); 9110ec8681fSMatthew G. Knepley } 9128763be8eSMatthew G. Knepley if (vol) *vol = PetscAbsReal(vsum); 9130ec8681fSMatthew G. Knepley if (normal) for (d = 0; d < dim; ++d) normal[d] = 0.0; 9140ec8681fSMatthew G. Knepley PetscFunctionReturn(0); 9150ec8681fSMatthew G. Knepley } 9160ec8681fSMatthew G. Knepley 9170ec8681fSMatthew G. Knepley #undef __FUNCT__ 918834e62ceSMatthew G. Knepley #define __FUNCT__ "DMPlexComputeCellGeometryFVM" 919834e62ceSMatthew G. Knepley /*@C 920834e62ceSMatthew G. Knepley DMPlexComputeCellGeometryFVM - Compute the volume for a given cell 921834e62ceSMatthew G. Knepley 922834e62ceSMatthew G. Knepley Collective on DM 923834e62ceSMatthew G. Knepley 924834e62ceSMatthew G. Knepley Input Arguments: 925834e62ceSMatthew G. Knepley + dm - the DM 926834e62ceSMatthew G. Knepley - cell - the cell 927834e62ceSMatthew G. Knepley 928834e62ceSMatthew G. Knepley Output Arguments: 929834e62ceSMatthew G. Knepley + volume - the cell volume 930cc08537eSMatthew G. Knepley . centroid - the cell centroid 931cc08537eSMatthew G. Knepley - normal - the cell normal, if appropriate 932834e62ceSMatthew G. Knepley 933834e62ceSMatthew G. Knepley Level: advanced 934834e62ceSMatthew G. Knepley 935834e62ceSMatthew G. Knepley Fortran Notes: 936834e62ceSMatthew G. Knepley Since it returns arrays, this routine is only available in Fortran 90, and you must 937834e62ceSMatthew G. Knepley include petsc.h90 in your code. 938834e62ceSMatthew G. Knepley 939834e62ceSMatthew G. Knepley .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 940834e62ceSMatthew G. Knepley @*/ 941cc08537eSMatthew G. Knepley PetscErrorCode DMPlexComputeCellGeometryFVM(DM dm, PetscInt cell, PetscReal *vol, PetscReal centroid[], PetscReal normal[]) 942834e62ceSMatthew G. Knepley { 9430ec8681fSMatthew G. Knepley PetscInt depth, dim; 944834e62ceSMatthew G. Knepley PetscErrorCode ierr; 945834e62ceSMatthew G. Knepley 946834e62ceSMatthew G. Knepley PetscFunctionBegin; 947834e62ceSMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 948834e62ceSMatthew G. Knepley ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 949834e62ceSMatthew G. Knepley if (depth != dim) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh must be interpolated"); 950834e62ceSMatthew G. Knepley /* We need to keep a pointer to the depth label */ 951011ea5d8SMatthew G. Knepley ierr = DMPlexGetLabelValue(dm, "depth", cell, &depth);CHKERRQ(ierr); 952834e62ceSMatthew G. Knepley /* Cone size is now the number of faces */ 953011ea5d8SMatthew G. Knepley switch (depth) { 954cc08537eSMatthew G. Knepley case 1: 955011ea5d8SMatthew G. Knepley ierr = DMPlexComputeGeometryFVM_1D_Internal(dm, dim, cell, vol, centroid, normal);CHKERRQ(ierr); 956cc08537eSMatthew G. Knepley break; 957834e62ceSMatthew G. Knepley case 2: 958011ea5d8SMatthew G. Knepley ierr = DMPlexComputeGeometryFVM_2D_Internal(dm, dim, cell, vol, centroid, normal);CHKERRQ(ierr); 959834e62ceSMatthew G. Knepley break; 960834e62ceSMatthew G. Knepley case 3: 961011ea5d8SMatthew G. Knepley ierr = DMPlexComputeGeometryFVM_3D_Internal(dm, dim, cell, vol, centroid, normal);CHKERRQ(ierr); 962834e62ceSMatthew G. Knepley break; 963834e62ceSMatthew G. Knepley default: 964834e62ceSMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 965834e62ceSMatthew G. Knepley } 966834e62ceSMatthew G. Knepley PetscFunctionReturn(0); 967834e62ceSMatthew G. Knepley } 968