163d025dbSVijay Mahadevan 263d025dbSVijay Mahadevan #include <petscconf.h> 363d025dbSVijay Mahadevan #include <petscdt.h> /*I "petscdt.h" I*/ 463d025dbSVijay Mahadevan #include <petsc/private/dmmbimpl.h> /*I "petscdmmoab.h" I*/ 563d025dbSVijay Mahadevan 663d025dbSVijay Mahadevan /* Utility functions */ 7d71ae5a4SJacob Faibussowitsch static inline PetscReal DMatrix_Determinant_2x2_Internal(const PetscReal inmat[2 * 2]) 8d71ae5a4SJacob Faibussowitsch { 963d025dbSVijay Mahadevan return inmat[0] * inmat[3] - inmat[1] * inmat[2]; 1063d025dbSVijay Mahadevan } 1163d025dbSVijay Mahadevan 12d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMatrix_Invert_2x2_Internal(const PetscReal *inmat, PetscReal *outmat, PetscReal *determinant) 13d71ae5a4SJacob Faibussowitsch { 1463d025dbSVijay Mahadevan PetscReal det = DMatrix_Determinant_2x2_Internal(inmat); 1563d025dbSVijay Mahadevan if (outmat) { 1663d025dbSVijay Mahadevan outmat[0] = inmat[3] / det; 1763d025dbSVijay Mahadevan outmat[1] = -inmat[1] / det; 1863d025dbSVijay Mahadevan outmat[2] = -inmat[2] / det; 1963d025dbSVijay Mahadevan outmat[3] = inmat[0] / det; 2063d025dbSVijay Mahadevan } 2163d025dbSVijay Mahadevan if (determinant) *determinant = det; 22*3ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 2363d025dbSVijay Mahadevan } 2463d025dbSVijay Mahadevan 25d71ae5a4SJacob Faibussowitsch static inline PetscReal DMatrix_Determinant_3x3_Internal(const PetscReal inmat[3 * 3]) 26d71ae5a4SJacob Faibussowitsch { 279371c9d4SSatish Balay return inmat[0] * (inmat[8] * inmat[4] - inmat[7] * inmat[5]) - inmat[3] * (inmat[8] * inmat[1] - inmat[7] * inmat[2]) + inmat[6] * (inmat[5] * inmat[1] - inmat[4] * inmat[2]); 2863d025dbSVijay Mahadevan } 2963d025dbSVijay Mahadevan 30d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMatrix_Invert_3x3_Internal(const PetscReal *inmat, PetscReal *outmat, PetscScalar *determinant) 31d71ae5a4SJacob Faibussowitsch { 32181f196bSVijay Mahadevan PetscReal det = DMatrix_Determinant_3x3_Internal(inmat); 3363d025dbSVijay Mahadevan if (outmat) { 3463d025dbSVijay Mahadevan outmat[0] = (inmat[8] * inmat[4] - inmat[7] * inmat[5]) / det; 3563d025dbSVijay Mahadevan outmat[1] = -(inmat[8] * inmat[1] - inmat[7] * inmat[2]) / det; 3663d025dbSVijay Mahadevan outmat[2] = (inmat[5] * inmat[1] - inmat[4] * inmat[2]) / det; 3763d025dbSVijay Mahadevan outmat[3] = -(inmat[8] * inmat[3] - inmat[6] * inmat[5]) / det; 3863d025dbSVijay Mahadevan outmat[4] = (inmat[8] * inmat[0] - inmat[6] * inmat[2]) / det; 3963d025dbSVijay Mahadevan outmat[5] = -(inmat[5] * inmat[0] - inmat[3] * inmat[2]) / det; 4063d025dbSVijay Mahadevan outmat[6] = (inmat[7] * inmat[3] - inmat[6] * inmat[4]) / det; 4163d025dbSVijay Mahadevan outmat[7] = -(inmat[7] * inmat[0] - inmat[6] * inmat[1]) / det; 4263d025dbSVijay Mahadevan outmat[8] = (inmat[4] * inmat[0] - inmat[3] * inmat[1]) / det; 4363d025dbSVijay Mahadevan } 4463d025dbSVijay Mahadevan if (determinant) *determinant = det; 45*3ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 4663d025dbSVijay Mahadevan } 4763d025dbSVijay Mahadevan 48d71ae5a4SJacob Faibussowitsch inline PetscReal DMatrix_Determinant_4x4_Internal(PetscReal inmat[4 * 4]) 49d71ae5a4SJacob Faibussowitsch { 509371c9d4SSatish Balay return inmat[0 + 0 * 4] * (inmat[1 + 1 * 4] * (inmat[2 + 2 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 2 * 4]) - inmat[1 + 2 * 4] * (inmat[2 + 1 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 1 * 4]) + inmat[1 + 3 * 4] * (inmat[2 + 1 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 1 * 4])) - inmat[0 + 1 * 4] * (inmat[1 + 0 * 4] * (inmat[2 + 2 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 2 * 4]) - inmat[1 + 2 * 4] * (inmat[2 + 0 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 0 * 4]) + inmat[1 + 3 * 4] * (inmat[2 + 0 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 0 * 4])) + inmat[0 + 2 * 4] * (inmat[1 + 0 * 4] * (inmat[2 + 1 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 1 * 4]) - inmat[1 + 1 * 4] * (inmat[2 + 0 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 0 * 4]) + inmat[1 + 3 * 4] * (inmat[2 + 0 * 4] * inmat[3 + 1 * 4] - inmat[2 + 1 * 4] * inmat[3 + 0 * 4])) - inmat[0 + 3 * 4] * (inmat[1 + 0 * 4] * (inmat[2 + 1 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 1 * 4]) - inmat[1 + 1 * 4] * (inmat[2 + 0 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 0 * 4]) + inmat[1 + 2 * 4] * (inmat[2 + 0 * 4] * inmat[3 + 1 * 4] - inmat[2 + 1 * 4] * inmat[3 + 0 * 4])); 51181f196bSVijay Mahadevan } 52181f196bSVijay Mahadevan 53d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DMatrix_Invert_4x4_Internal(PetscReal *inmat, PetscReal *outmat, PetscScalar *determinant) 54d71ae5a4SJacob Faibussowitsch { 55181f196bSVijay Mahadevan PetscReal det = DMatrix_Determinant_4x4_Internal(inmat); 56181f196bSVijay Mahadevan if (outmat) { 57181f196bSVijay Mahadevan outmat[0] = (inmat[5] * inmat[10] * inmat[15] + inmat[6] * inmat[11] * inmat[13] + inmat[7] * inmat[9] * inmat[14] - inmat[5] * inmat[11] * inmat[14] - inmat[6] * inmat[9] * inmat[15] - inmat[7] * inmat[10] * inmat[13]) / det; 58181f196bSVijay Mahadevan outmat[1] = (inmat[1] * inmat[11] * inmat[14] + inmat[2] * inmat[9] * inmat[15] + inmat[3] * inmat[10] * inmat[13] - inmat[1] * inmat[10] * inmat[15] - inmat[2] * inmat[11] * inmat[13] - inmat[3] * inmat[9] * inmat[14]) / det; 59181f196bSVijay Mahadevan outmat[2] = (inmat[1] * inmat[6] * inmat[15] + inmat[2] * inmat[7] * inmat[13] + inmat[3] * inmat[5] * inmat[14] - inmat[1] * inmat[7] * inmat[14] - inmat[2] * inmat[5] * inmat[15] - inmat[3] * inmat[6] * inmat[13]) / det; 60181f196bSVijay Mahadevan outmat[3] = (inmat[1] * inmat[7] * inmat[10] + inmat[2] * inmat[5] * inmat[11] + inmat[3] * inmat[6] * inmat[9] - inmat[1] * inmat[6] * inmat[11] - inmat[2] * inmat[7] * inmat[9] - inmat[3] * inmat[5] * inmat[10]) / det; 61181f196bSVijay Mahadevan outmat[4] = (inmat[4] * inmat[11] * inmat[14] + inmat[6] * inmat[8] * inmat[15] + inmat[7] * inmat[10] * inmat[12] - inmat[4] * inmat[10] * inmat[15] - inmat[6] * inmat[11] * inmat[12] - inmat[7] * inmat[8] * inmat[14]) / det; 62181f196bSVijay Mahadevan outmat[5] = (inmat[0] * inmat[10] * inmat[15] + inmat[2] * inmat[11] * inmat[12] + inmat[3] * inmat[8] * inmat[14] - inmat[0] * inmat[11] * inmat[14] - inmat[2] * inmat[8] * inmat[15] - inmat[3] * inmat[10] * inmat[12]) / det; 63181f196bSVijay Mahadevan outmat[6] = (inmat[0] * inmat[7] * inmat[14] + inmat[2] * inmat[4] * inmat[15] + inmat[3] * inmat[6] * inmat[12] - inmat[0] * inmat[6] * inmat[15] - inmat[2] * inmat[7] * inmat[12] - inmat[3] * inmat[4] * inmat[14]) / det; 64181f196bSVijay Mahadevan outmat[7] = (inmat[0] * inmat[6] * inmat[11] + inmat[2] * inmat[7] * inmat[8] + inmat[3] * inmat[4] * inmat[10] - inmat[0] * inmat[7] * inmat[10] - inmat[2] * inmat[4] * inmat[11] - inmat[3] * inmat[6] * inmat[8]) / det; 65181f196bSVijay Mahadevan outmat[8] = (inmat[4] * inmat[9] * inmat[15] + inmat[5] * inmat[11] * inmat[12] + inmat[7] * inmat[8] * inmat[13] - inmat[4] * inmat[11] * inmat[13] - inmat[5] * inmat[8] * inmat[15] - inmat[7] * inmat[9] * inmat[12]) / det; 66181f196bSVijay Mahadevan outmat[9] = (inmat[0] * inmat[11] * inmat[13] + inmat[1] * inmat[8] * inmat[15] + inmat[3] * inmat[9] * inmat[12] - inmat[0] * inmat[9] * inmat[15] - inmat[1] * inmat[11] * inmat[12] - inmat[3] * inmat[8] * inmat[13]) / det; 67181f196bSVijay Mahadevan outmat[10] = (inmat[0] * inmat[5] * inmat[15] + inmat[1] * inmat[7] * inmat[12] + inmat[3] * inmat[4] * inmat[13] - inmat[0] * inmat[7] * inmat[13] - inmat[1] * inmat[4] * inmat[15] - inmat[3] * inmat[5] * inmat[12]) / det; 68181f196bSVijay Mahadevan outmat[11] = (inmat[0] * inmat[7] * inmat[9] + inmat[1] * inmat[4] * inmat[11] + inmat[3] * inmat[5] * inmat[8] - inmat[0] * inmat[5] * inmat[11] - inmat[1] * inmat[7] * inmat[8] - inmat[3] * inmat[4] * inmat[9]) / det; 69181f196bSVijay Mahadevan outmat[12] = (inmat[4] * inmat[10] * inmat[13] + inmat[5] * inmat[8] * inmat[14] + inmat[6] * inmat[9] * inmat[12] - inmat[4] * inmat[9] * inmat[14] - inmat[5] * inmat[10] * inmat[12] - inmat[6] * inmat[8] * inmat[13]) / det; 70181f196bSVijay Mahadevan outmat[13] = (inmat[0] * inmat[9] * inmat[14] + inmat[1] * inmat[10] * inmat[12] + inmat[2] * inmat[8] * inmat[13] - inmat[0] * inmat[10] * inmat[13] - inmat[1] * inmat[8] * inmat[14] - inmat[2] * inmat[9] * inmat[12]) / det; 71181f196bSVijay Mahadevan outmat[14] = (inmat[0] * inmat[6] * inmat[13] + inmat[1] * inmat[4] * inmat[14] + inmat[2] * inmat[5] * inmat[12] - inmat[0] * inmat[5] * inmat[14] - inmat[1] * inmat[6] * inmat[12] - inmat[2] * inmat[4] * inmat[13]) / det; 72181f196bSVijay Mahadevan outmat[15] = (inmat[0] * inmat[5] * inmat[10] + inmat[1] * inmat[6] * inmat[8] + inmat[2] * inmat[4] * inmat[9] - inmat[0] * inmat[6] * inmat[9] - inmat[1] * inmat[4] * inmat[10] - inmat[2] * inmat[5] * inmat[8]) / det; 73181f196bSVijay Mahadevan } 74181f196bSVijay Mahadevan if (determinant) *determinant = det; 75*3ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 76181f196bSVijay Mahadevan } 77181f196bSVijay Mahadevan 78cab5ea25SPierre Jolivet /*@C 7997b73a88SSatish Balay Compute_Lagrange_Basis_1D_Internal - Evaluate bases and derivatives at quadrature points for a EDGE2 or EDGE3 element. 8063d025dbSVijay Mahadevan 8163d025dbSVijay Mahadevan The routine is given the coordinates of the vertices of a linear or quadratic edge element. 8263d025dbSVijay Mahadevan 8363d025dbSVijay Mahadevan The routine evaluates the basis functions associated with each quadrature point provided, 8463d025dbSVijay Mahadevan and their derivatives with respect to X. 8563d025dbSVijay Mahadevan 8663d025dbSVijay Mahadevan Notes: 8763d025dbSVijay Mahadevan 8863d025dbSVijay Mahadevan Example Physical Element 89a2b725a8SWilliam Gropp .vb 9063d025dbSVijay Mahadevan 1-------2 1----3----2 9163d025dbSVijay Mahadevan EDGE2 EDGE3 92a2b725a8SWilliam Gropp .ve 9363d025dbSVijay Mahadevan 94d8d19677SJose E. Roman Input Parameters: 95a2b725a8SWilliam Gropp + PetscInt nverts - the number of element vertices 96a2b725a8SWilliam Gropp . PetscReal coords[3*nverts] - the physical coordinates of the vertices (in canonical numbering) 97a2b725a8SWilliam Gropp . PetscInt npts - the number of evaluation points (quadrature points) 98a2b725a8SWilliam Gropp - PetscReal quad[3*npts] - the evaluation points (quadrature points) in the reference space 9963d025dbSVijay Mahadevan 100d8d19677SJose E. Roman Output Parameters: 101a2b725a8SWilliam Gropp + PetscReal phypts[3*npts] - the evaluation points (quadrature points) transformed to the physical space 102a2b725a8SWilliam Gropp . PetscReal jxw[npts] - the jacobian determinant * quadrature weight necessary for assembling discrete contributions 103a2b725a8SWilliam Gropp . PetscReal phi[npts] - the bases evaluated at the specified quadrature points 1046b867d5aSJose E. Roman . PetscReal dphidx[npts] - the derivative of the bases wrt X-direction evaluated at the specified quadrature points 10567b8a455SSatish Balay . jacobian - jacobian 10667b8a455SSatish Balay . ijacobian - ijacobian 10767b8a455SSatish Balay - volume - volume 10863d025dbSVijay Mahadevan 109edc382c3SSatish Balay Level: advanced 110edc382c3SSatish Balay 11163d025dbSVijay Mahadevan @*/ 112d71ae5a4SJacob Faibussowitsch PetscErrorCode Compute_Lagrange_Basis_1D_Internal(const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts, PetscReal *jxw, PetscReal *phi, PetscReal *dphidx, PetscReal *jacobian, PetscReal *ijacobian, PetscReal *volume) 113d71ae5a4SJacob Faibussowitsch { 11463d025dbSVijay Mahadevan int i, j; 11563d025dbSVijay Mahadevan 116181f196bSVijay Mahadevan PetscFunctionBegin; 117181f196bSVijay Mahadevan PetscValidPointer(jacobian, 9); 118181f196bSVijay Mahadevan PetscValidPointer(ijacobian, 10); 119181f196bSVijay Mahadevan PetscValidPointer(volume, 11); 12048a46eb9SPierre Jolivet if (phypts) PetscCall(PetscArrayzero(phypts, npts * 3)); 12163d025dbSVijay Mahadevan if (dphidx) { /* Reset arrays. */ 1229566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dphidx, npts * nverts)); 12363d025dbSVijay Mahadevan } 12463d025dbSVijay Mahadevan if (nverts == 2) { /* Linear Edge */ 12563d025dbSVijay Mahadevan 1262da392ccSBarry Smith for (j = 0; j < npts; j++) { 127a86ed394SVijay Mahadevan const PetscInt offset = j * nverts; 128181f196bSVijay Mahadevan const PetscReal r = quad[j]; 12963d025dbSVijay Mahadevan 130181f196bSVijay Mahadevan phi[0 + offset] = (1.0 - r); 131181f196bSVijay Mahadevan phi[1 + offset] = (r); 13263d025dbSVijay Mahadevan 133181f196bSVijay Mahadevan const PetscReal dNi_dxi[2] = {-1.0, 1.0}; 13463d025dbSVijay Mahadevan 135181f196bSVijay Mahadevan jacobian[0] = ijacobian[0] = volume[0] = 0.0; 13663d025dbSVijay Mahadevan for (i = 0; i < nverts; ++i) { 137181f196bSVijay Mahadevan const PetscReal *vertices = coords + i * 3; 138181f196bSVijay Mahadevan jacobian[0] += dNi_dxi[i] * vertices[0]; 139ad540459SPierre Jolivet if (phypts) phypts[3 * j + 0] += phi[i + offset] * vertices[0]; 14063d025dbSVijay Mahadevan } 14163d025dbSVijay Mahadevan 14263d025dbSVijay Mahadevan /* invert the jacobian */ 143181f196bSVijay Mahadevan *volume = jacobian[0]; 144181f196bSVijay Mahadevan ijacobian[0] = 1.0 / jacobian[0]; 145181f196bSVijay Mahadevan jxw[j] *= *volume; 14663d025dbSVijay Mahadevan 14763d025dbSVijay Mahadevan /* Divide by element jacobian. */ 14863d025dbSVijay Mahadevan for (i = 0; i < nverts; i++) { 149181f196bSVijay Mahadevan if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[0]; 15063d025dbSVijay Mahadevan } 15163d025dbSVijay Mahadevan } 1522da392ccSBarry Smith } else if (nverts == 3) { /* Quadratic Edge */ 15363d025dbSVijay Mahadevan 1542da392ccSBarry Smith for (j = 0; j < npts; j++) { 155a86ed394SVijay Mahadevan const PetscInt offset = j * nverts; 156181f196bSVijay Mahadevan const PetscReal r = quad[j]; 15763d025dbSVijay Mahadevan 158181f196bSVijay Mahadevan phi[0 + offset] = 1.0 + r * (2.0 * r - 3.0); 159181f196bSVijay Mahadevan phi[1 + offset] = 4.0 * r * (1.0 - r); 160181f196bSVijay Mahadevan phi[2 + offset] = r * (2.0 * r - 1.0); 16163d025dbSVijay Mahadevan 162181f196bSVijay Mahadevan const PetscReal dNi_dxi[3] = {4 * r - 3.0, 4 * (1.0 - 2.0 * r), 4.0 * r - 1.0}; 16363d025dbSVijay Mahadevan 164181f196bSVijay Mahadevan jacobian[0] = ijacobian[0] = volume[0] = 0.0; 16563d025dbSVijay Mahadevan for (i = 0; i < nverts; ++i) { 166181f196bSVijay Mahadevan const PetscReal *vertices = coords + i * 3; 167181f196bSVijay Mahadevan jacobian[0] += dNi_dxi[i] * vertices[0]; 168ad540459SPierre Jolivet if (phypts) phypts[3 * j + 0] += phi[i + offset] * vertices[0]; 16963d025dbSVijay Mahadevan } 17063d025dbSVijay Mahadevan 17163d025dbSVijay Mahadevan /* invert the jacobian */ 172181f196bSVijay Mahadevan *volume = jacobian[0]; 173181f196bSVijay Mahadevan ijacobian[0] = 1.0 / jacobian[0]; 174181f196bSVijay Mahadevan if (jxw) jxw[j] *= *volume; 17563d025dbSVijay Mahadevan 17663d025dbSVijay Mahadevan /* Divide by element jacobian. */ 17763d025dbSVijay Mahadevan for (i = 0; i < nverts; i++) { 178181f196bSVijay Mahadevan if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[0]; 17963d025dbSVijay Mahadevan } 18063d025dbSVijay Mahadevan } 18163a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "The number of entity vertices are invalid. Currently only support EDGE2 and EDGE3 basis evaluations in 1-D : %" PetscInt_FMT, nverts); 182*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18363d025dbSVijay Mahadevan } 18463d025dbSVijay Mahadevan 185cab5ea25SPierre Jolivet /*@C 18697b73a88SSatish Balay Compute_Lagrange_Basis_2D_Internal - Evaluate bases and derivatives at quadrature points for a QUAD4 or TRI3 element. 18763d025dbSVijay Mahadevan 18863d025dbSVijay Mahadevan The routine is given the coordinates of the vertices of a quadrangle or triangle. 18963d025dbSVijay Mahadevan 19063d025dbSVijay Mahadevan The routine evaluates the basis functions associated with each quadrature point provided, 19163d025dbSVijay Mahadevan and their derivatives with respect to X and Y. 19263d025dbSVijay Mahadevan 19363d025dbSVijay Mahadevan Notes: 19463d025dbSVijay Mahadevan 19563d025dbSVijay Mahadevan Example Physical Element (QUAD4) 196a2b725a8SWilliam Gropp .vb 19763d025dbSVijay Mahadevan 4------3 s 19863d025dbSVijay Mahadevan | | | 19963d025dbSVijay Mahadevan | | | 20063d025dbSVijay Mahadevan | | | 20163d025dbSVijay Mahadevan 1------2 0-------r 202a2b725a8SWilliam Gropp .ve 20363d025dbSVijay Mahadevan 204d8d19677SJose E. Roman Input Parameters: 205a2b725a8SWilliam Gropp + PetscInt nverts - the number of element vertices 206a2b725a8SWilliam Gropp . PetscReal coords[3*nverts] - the physical coordinates of the vertices (in canonical numbering) 207a2b725a8SWilliam Gropp . PetscInt npts - the number of evaluation points (quadrature points) 208a2b725a8SWilliam Gropp - PetscReal quad[3*npts] - the evaluation points (quadrature points) in the reference space 20963d025dbSVijay Mahadevan 210d8d19677SJose E. Roman Output Parameters: 211a2b725a8SWilliam Gropp + PetscReal phypts[3*npts] - the evaluation points (quadrature points) transformed to the physical space 212a2b725a8SWilliam Gropp . PetscReal jxw[npts] - the jacobian determinant * quadrature weight necessary for assembling discrete contributions 213a2b725a8SWilliam Gropp . PetscReal phi[npts] - the bases evaluated at the specified quadrature points 214a2b725a8SWilliam Gropp . PetscReal dphidx[npts] - the derivative of the bases wrt X-direction evaluated at the specified quadrature points 2156b867d5aSJose E. Roman . PetscReal dphidy[npts] - the derivative of the bases wrt Y-direction evaluated at the specified quadrature points 21667b8a455SSatish Balay . jacobian - jacobian 21767b8a455SSatish Balay . ijacobian - ijacobian 21867b8a455SSatish Balay - volume - volume 21963d025dbSVijay Mahadevan 220edc382c3SSatish Balay Level: advanced 221edc382c3SSatish Balay 22263d025dbSVijay Mahadevan @*/ 223d71ae5a4SJacob Faibussowitsch PetscErrorCode Compute_Lagrange_Basis_2D_Internal(const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts, PetscReal *jxw, PetscReal *phi, PetscReal *dphidx, PetscReal *dphidy, PetscReal *jacobian, PetscReal *ijacobian, PetscReal *volume) 224d71ae5a4SJacob Faibussowitsch { 225a86ed394SVijay Mahadevan PetscInt i, j, k; 22663d025dbSVijay Mahadevan 22763d025dbSVijay Mahadevan PetscFunctionBegin; 228181f196bSVijay Mahadevan PetscValidPointer(jacobian, 10); 229181f196bSVijay Mahadevan PetscValidPointer(ijacobian, 11); 230181f196bSVijay Mahadevan PetscValidPointer(volume, 12); 2319566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(phi, npts)); 23248a46eb9SPierre Jolivet if (phypts) PetscCall(PetscArrayzero(phypts, npts * 3)); 23363d025dbSVijay Mahadevan if (dphidx) { /* Reset arrays. */ 2349566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dphidx, npts * nverts)); 2359566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dphidy, npts * nverts)); 23663d025dbSVijay Mahadevan } 23763d025dbSVijay Mahadevan if (nverts == 4) { /* Linear Quadrangle */ 23863d025dbSVijay Mahadevan 2399371c9d4SSatish Balay for (j = 0; j < npts; j++) { 240a86ed394SVijay Mahadevan const PetscInt offset = j * nverts; 241181f196bSVijay Mahadevan const PetscReal r = quad[0 + j * 2]; 242181f196bSVijay Mahadevan const PetscReal s = quad[1 + j * 2]; 24363d025dbSVijay Mahadevan 24463d025dbSVijay Mahadevan phi[0 + offset] = (1.0 - r) * (1.0 - s); 24563d025dbSVijay Mahadevan phi[1 + offset] = r * (1.0 - s); 24663d025dbSVijay Mahadevan phi[2 + offset] = r * s; 24763d025dbSVijay Mahadevan phi[3 + offset] = (1.0 - r) * s; 24863d025dbSVijay Mahadevan 249181f196bSVijay Mahadevan const PetscReal dNi_dxi[4] = {-1.0 + s, 1.0 - s, s, -s}; 250181f196bSVijay Mahadevan const PetscReal dNi_deta[4] = {-1.0 + r, -r, r, 1.0 - r}; 25163d025dbSVijay Mahadevan 2529566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(jacobian, 4)); 2539566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ijacobian, 4)); 25463d025dbSVijay Mahadevan for (i = 0; i < nverts; ++i) { 255181f196bSVijay Mahadevan const PetscReal *vertices = coords + i * 3; 25663d025dbSVijay Mahadevan jacobian[0] += dNi_dxi[i] * vertices[0]; 25763d025dbSVijay Mahadevan jacobian[2] += dNi_dxi[i] * vertices[1]; 25863d025dbSVijay Mahadevan jacobian[1] += dNi_deta[i] * vertices[0]; 25963d025dbSVijay Mahadevan jacobian[3] += dNi_deta[i] * vertices[1]; 260181f196bSVijay Mahadevan if (phypts) { 261181f196bSVijay Mahadevan phypts[3 * j + 0] += phi[i + offset] * vertices[0]; 262181f196bSVijay Mahadevan phypts[3 * j + 1] += phi[i + offset] * vertices[1]; 263181f196bSVijay Mahadevan phypts[3 * j + 2] += phi[i + offset] * vertices[2]; 264181f196bSVijay Mahadevan } 26563d025dbSVijay Mahadevan } 26663d025dbSVijay Mahadevan 26763d025dbSVijay Mahadevan /* invert the jacobian */ 2689566063dSJacob Faibussowitsch PetscCall(DMatrix_Invert_2x2_Internal(jacobian, ijacobian, volume)); 26908401ef6SPierre Jolivet PetscCheck(*volume >= 1e-12, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Quadrangular element has zero volume: %g. Degenerate element or invalid connectivity", *volume); 27063d025dbSVijay Mahadevan 271181f196bSVijay Mahadevan if (jxw) jxw[j] *= *volume; 27263d025dbSVijay Mahadevan 273181f196bSVijay Mahadevan /* Let us compute the bases derivatives by scaling with inverse jacobian. */ 274181f196bSVijay Mahadevan if (dphidx) { 27563d025dbSVijay Mahadevan for (i = 0; i < nverts; i++) { 276a86ed394SVijay Mahadevan for (k = 0; k < 2; ++k) { 27763d025dbSVijay Mahadevan if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[k * 2 + 0]; 27863d025dbSVijay Mahadevan if (dphidy) dphidy[i + offset] += dNi_deta[i] * ijacobian[k * 2 + 1]; 279181f196bSVijay Mahadevan } /* for k=[0..2) */ 280181f196bSVijay Mahadevan } /* for i=[0..nverts) */ 281181f196bSVijay Mahadevan } /* if (dphidx) */ 28263d025dbSVijay Mahadevan } 2832da392ccSBarry Smith } else if (nverts == 3) { /* Linear triangle */ 2842da392ccSBarry Smith const PetscReal x2 = coords[2 * 3 + 0], y2 = coords[2 * 3 + 1]; 28563d025dbSVijay Mahadevan 2869566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(jacobian, 4)); 2879566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ijacobian, 4)); 28863d025dbSVijay Mahadevan 28963d025dbSVijay Mahadevan /* Jacobian is constant */ 2909371c9d4SSatish Balay jacobian[0] = (coords[0 * 3 + 0] - x2); 2919371c9d4SSatish Balay jacobian[1] = (coords[1 * 3 + 0] - x2); 2929371c9d4SSatish Balay jacobian[2] = (coords[0 * 3 + 1] - y2); 2939371c9d4SSatish Balay jacobian[3] = (coords[1 * 3 + 1] - y2); 29463d025dbSVijay Mahadevan 29563d025dbSVijay Mahadevan /* invert the jacobian */ 2969566063dSJacob Faibussowitsch PetscCall(DMatrix_Invert_2x2_Internal(jacobian, ijacobian, volume)); 29708401ef6SPierre Jolivet PetscCheck(*volume >= 1e-12, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Triangular element has zero volume: %g. Degenerate element or invalid connectivity", (double)*volume); 298181f196bSVijay Mahadevan 299181f196bSVijay Mahadevan const PetscReal Dx[3] = {ijacobian[0], ijacobian[2], -ijacobian[0] - ijacobian[2]}; 300181f196bSVijay Mahadevan const PetscReal Dy[3] = {ijacobian[1], ijacobian[3], -ijacobian[1] - ijacobian[3]}; 30163d025dbSVijay Mahadevan 3022da392ccSBarry Smith for (j = 0; j < npts; j++) { 303a86ed394SVijay Mahadevan const PetscInt offset = j * nverts; 304181f196bSVijay Mahadevan const PetscReal r = quad[0 + j * 2]; 305181f196bSVijay Mahadevan const PetscReal s = quad[1 + j * 2]; 30663d025dbSVijay Mahadevan 307181f196bSVijay Mahadevan if (jxw) jxw[j] *= 0.5; 30863d025dbSVijay Mahadevan 309181f196bSVijay Mahadevan /* const PetscReal Ni[3] = { r, s, 1.0 - r - s }; */ 310181f196bSVijay Mahadevan const PetscReal phipts_x = coords[2 * 3 + 0] + jacobian[0] * r + jacobian[1] * s; 311181f196bSVijay Mahadevan const PetscReal phipts_y = coords[2 * 3 + 1] + jacobian[2] * r + jacobian[3] * s; 312181f196bSVijay Mahadevan if (phypts) { 313181f196bSVijay Mahadevan phypts[offset + 0] = phipts_x; 314181f196bSVijay Mahadevan phypts[offset + 1] = phipts_y; 315181f196bSVijay Mahadevan } 31663d025dbSVijay Mahadevan 317110fc3b0SBarry Smith /* \phi_0 = (b.y - c.y) x + (b.x - c.x) y + c.x b.y - b.x c.y */ 318181f196bSVijay Mahadevan phi[0 + offset] = (ijacobian[0] * (phipts_x - x2) + ijacobian[1] * (phipts_y - y2)); 319110fc3b0SBarry Smith /* \phi_1 = (c.y - a.y) x + (a.x - c.x) y + c.x a.y - a.x c.y */ 320181f196bSVijay Mahadevan phi[1 + offset] = (ijacobian[2] * (phipts_x - x2) + ijacobian[3] * (phipts_y - y2)); 32163d025dbSVijay Mahadevan phi[2 + offset] = 1.0 - phi[0 + offset] - phi[1 + offset]; 32263d025dbSVijay Mahadevan 32363d025dbSVijay Mahadevan if (dphidx) { 324181f196bSVijay Mahadevan dphidx[0 + offset] = Dx[0]; 325181f196bSVijay Mahadevan dphidx[1 + offset] = Dx[1]; 326181f196bSVijay Mahadevan dphidx[2 + offset] = Dx[2]; 32763d025dbSVijay Mahadevan } 32863d025dbSVijay Mahadevan 32963d025dbSVijay Mahadevan if (dphidy) { 330181f196bSVijay Mahadevan dphidy[0 + offset] = Dy[0]; 331181f196bSVijay Mahadevan dphidy[1 + offset] = Dy[1]; 332181f196bSVijay Mahadevan dphidy[2 + offset] = Dy[2]; 33363d025dbSVijay Mahadevan } 33463d025dbSVijay Mahadevan } 33563a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "The number of entity vertices are invalid. Currently only support QUAD4 and TRI3 basis evaluations in 2-D : %" PetscInt_FMT, nverts); 336*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33763d025dbSVijay Mahadevan } 33863d025dbSVijay Mahadevan 339cab5ea25SPierre Jolivet /*@C 34097b73a88SSatish Balay Compute_Lagrange_Basis_3D_Internal - Evaluate bases and derivatives at quadrature points for a HEX8 or TET4 element. 34163d025dbSVijay Mahadevan 34263d025dbSVijay Mahadevan The routine is given the coordinates of the vertices of a hexahedra or tetrahedra. 34363d025dbSVijay Mahadevan 34463d025dbSVijay Mahadevan The routine evaluates the basis functions associated with each quadrature point provided, 34563d025dbSVijay Mahadevan and their derivatives with respect to X, Y and Z. 34663d025dbSVijay Mahadevan 34763d025dbSVijay Mahadevan Notes: 34863d025dbSVijay Mahadevan 34963d025dbSVijay Mahadevan Example Physical Element (HEX8) 350a2b725a8SWilliam Gropp .vb 35163d025dbSVijay Mahadevan 8------7 35263d025dbSVijay Mahadevan /| /| t s 35363d025dbSVijay Mahadevan 5------6 | | / 35463d025dbSVijay Mahadevan | | | | |/ 35563d025dbSVijay Mahadevan | 4----|-3 0-------r 35663d025dbSVijay Mahadevan |/ |/ 35763d025dbSVijay Mahadevan 1------2 358a2b725a8SWilliam Gropp .ve 35963d025dbSVijay Mahadevan 360d8d19677SJose E. Roman Input Parameters: 361a2b725a8SWilliam Gropp + PetscInt nverts - the number of element vertices 362a2b725a8SWilliam Gropp . PetscReal coords[3*nverts] - the physical coordinates of the vertices (in canonical numbering) 363a2b725a8SWilliam Gropp . PetscInt npts - the number of evaluation points (quadrature points) 364a2b725a8SWilliam Gropp - PetscReal quad[3*npts] - the evaluation points (quadrature points) in the reference space 36563d025dbSVijay Mahadevan 366d8d19677SJose E. Roman Output Parameters: 367a2b725a8SWilliam Gropp + PetscReal phypts[3*npts] - the evaluation points (quadrature points) transformed to the physical space 368a2b725a8SWilliam Gropp . PetscReal jxw[npts] - the jacobian determinant * quadrature weight necessary for assembling discrete contributions 369a2b725a8SWilliam Gropp . PetscReal phi[npts] - the bases evaluated at the specified quadrature points 370a2b725a8SWilliam Gropp . PetscReal dphidx[npts] - the derivative of the bases wrt X-direction evaluated at the specified quadrature points 371a2b725a8SWilliam Gropp . PetscReal dphidy[npts] - the derivative of the bases wrt Y-direction evaluated at the specified quadrature points 3726b867d5aSJose E. Roman . PetscReal dphidz[npts] - the derivative of the bases wrt Z-direction evaluated at the specified quadrature points 37367b8a455SSatish Balay . jacobian - jacobian 37467b8a455SSatish Balay . ijacobian - ijacobian 37567b8a455SSatish Balay - volume - volume 37663d025dbSVijay Mahadevan 377edc382c3SSatish Balay Level: advanced 378edc382c3SSatish Balay 37963d025dbSVijay Mahadevan @*/ 380d71ae5a4SJacob Faibussowitsch PetscErrorCode Compute_Lagrange_Basis_3D_Internal(const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts, PetscReal *jxw, PetscReal *phi, PetscReal *dphidx, PetscReal *dphidy, PetscReal *dphidz, PetscReal *jacobian, PetscReal *ijacobian, PetscReal *volume) 381d71ae5a4SJacob Faibussowitsch { 382a86ed394SVijay Mahadevan PetscInt i, j, k; 38363d025dbSVijay Mahadevan 38463d025dbSVijay Mahadevan PetscFunctionBegin; 385181f196bSVijay Mahadevan PetscValidPointer(jacobian, 11); 386181f196bSVijay Mahadevan PetscValidPointer(ijacobian, 12); 387181f196bSVijay Mahadevan PetscValidPointer(volume, 13); 3882da392ccSBarry Smith 3899566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(phi, npts)); 39048a46eb9SPierre Jolivet if (phypts) PetscCall(PetscArrayzero(phypts, npts * 3)); 39163d025dbSVijay Mahadevan if (dphidx) { 3929566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dphidx, npts * nverts)); 3939566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dphidy, npts * nverts)); 3949566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dphidz, npts * nverts)); 39563d025dbSVijay Mahadevan } 39663d025dbSVijay Mahadevan 39763d025dbSVijay Mahadevan if (nverts == 8) { /* Linear Hexahedra */ 39863d025dbSVijay Mahadevan 3992da392ccSBarry Smith for (j = 0; j < npts; j++) { 400a86ed394SVijay Mahadevan const PetscInt offset = j * nverts; 401181f196bSVijay Mahadevan const PetscReal &r = quad[j * 3 + 0]; 402181f196bSVijay Mahadevan const PetscReal &s = quad[j * 3 + 1]; 403181f196bSVijay Mahadevan const PetscReal &t = quad[j * 3 + 2]; 40463d025dbSVijay Mahadevan 405a86ed394SVijay Mahadevan phi[offset + 0] = (1.0 - r) * (1.0 - s) * (1.0 - t); /* 0,0,0 */ 406a86ed394SVijay Mahadevan phi[offset + 1] = (r) * (1.0 - s) * (1.0 - t); /* 1,0,0 */ 407a86ed394SVijay Mahadevan phi[offset + 2] = (r) * (s) * (1.0 - t); /* 1,1,0 */ 408a86ed394SVijay Mahadevan phi[offset + 3] = (1.0 - r) * (s) * (1.0 - t); /* 0,1,0 */ 409a86ed394SVijay Mahadevan phi[offset + 4] = (1.0 - r) * (1.0 - s) * (t); /* 0,0,1 */ 410a86ed394SVijay Mahadevan phi[offset + 5] = (r) * (1.0 - s) * (t); /* 1,0,1 */ 411a86ed394SVijay Mahadevan phi[offset + 6] = (r) * (s) * (t); /* 1,1,1 */ 412a86ed394SVijay Mahadevan phi[offset + 7] = (1.0 - r) * (s) * (t); /* 0,1,1 */ 41363d025dbSVijay Mahadevan 4149371c9d4SSatish Balay const PetscReal dNi_dxi[8] = {-(1.0 - s) * (1.0 - t), (1.0 - s) * (1.0 - t), (s) * (1.0 - t), -(s) * (1.0 - t), -(1.0 - s) * (t), (1.0 - s) * (t), (s) * (t), -(s) * (t)}; 41563d025dbSVijay Mahadevan 4169371c9d4SSatish Balay const PetscReal dNi_deta[8] = {-(1.0 - r) * (1.0 - t), -(r) * (1.0 - t), (r) * (1.0 - t), (1.0 - r) * (1.0 - t), -(1.0 - r) * (t), -(r) * (t), (r) * (t), (1.0 - r) * (t)}; 41763d025dbSVijay Mahadevan 4189371c9d4SSatish Balay const PetscReal dNi_dzeta[8] = {-(1.0 - r) * (1.0 - s), -(r) * (1.0 - s), -(r) * (s), -(1.0 - r) * (s), (1.0 - r) * (1.0 - s), (r) * (1.0 - s), (r) * (s), (1.0 - r) * (s)}; 41963d025dbSVijay Mahadevan 4209566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(jacobian, 9)); 4219566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ijacobian, 9)); 42263d025dbSVijay Mahadevan for (i = 0; i < nverts; ++i) { 423181f196bSVijay Mahadevan const PetscReal *vertex = coords + i * 3; 42463d025dbSVijay Mahadevan jacobian[0] += dNi_dxi[i] * vertex[0]; 42563d025dbSVijay Mahadevan jacobian[3] += dNi_dxi[i] * vertex[1]; 42663d025dbSVijay Mahadevan jacobian[6] += dNi_dxi[i] * vertex[2]; 42763d025dbSVijay Mahadevan jacobian[1] += dNi_deta[i] * vertex[0]; 42863d025dbSVijay Mahadevan jacobian[4] += dNi_deta[i] * vertex[1]; 42963d025dbSVijay Mahadevan jacobian[7] += dNi_deta[i] * vertex[2]; 43063d025dbSVijay Mahadevan jacobian[2] += dNi_dzeta[i] * vertex[0]; 43163d025dbSVijay Mahadevan jacobian[5] += dNi_dzeta[i] * vertex[1]; 43263d025dbSVijay Mahadevan jacobian[8] += dNi_dzeta[i] * vertex[2]; 433181f196bSVijay Mahadevan if (phypts) { 434181f196bSVijay Mahadevan phypts[3 * j + 0] += phi[i + offset] * vertex[0]; 435181f196bSVijay Mahadevan phypts[3 * j + 1] += phi[i + offset] * vertex[1]; 436181f196bSVijay Mahadevan phypts[3 * j + 2] += phi[i + offset] * vertex[2]; 437181f196bSVijay Mahadevan } 43863d025dbSVijay Mahadevan } 43963d025dbSVijay Mahadevan 44063d025dbSVijay Mahadevan /* invert the jacobian */ 4419566063dSJacob Faibussowitsch PetscCall(DMatrix_Invert_3x3_Internal(jacobian, ijacobian, volume)); 44208401ef6SPierre Jolivet PetscCheck(*volume >= 1e-8, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Hexahedral element has zero volume: %g. Degenerate element or invalid connectivity", *volume); 44363d025dbSVijay Mahadevan 444a86ed394SVijay Mahadevan if (jxw) jxw[j] *= (*volume); 44563d025dbSVijay Mahadevan 44663d025dbSVijay Mahadevan /* Divide by element jacobian. */ 44763d025dbSVijay Mahadevan for (i = 0; i < nverts; ++i) { 448a86ed394SVijay Mahadevan for (k = 0; k < 3; ++k) { 44963d025dbSVijay Mahadevan if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[0 * 3 + k]; 45063d025dbSVijay Mahadevan if (dphidy) dphidy[i + offset] += dNi_deta[i] * ijacobian[1 * 3 + k]; 45163d025dbSVijay Mahadevan if (dphidz) dphidz[i + offset] += dNi_dzeta[i] * ijacobian[2 * 3 + k]; 45263d025dbSVijay Mahadevan } 45363d025dbSVijay Mahadevan } 45463d025dbSVijay Mahadevan } 4552da392ccSBarry Smith } else if (nverts == 4) { /* Linear Tetrahedra */ 4562da392ccSBarry Smith PetscReal Dx[4] = {0, 0, 0, 0}, Dy[4] = {0, 0, 0, 0}, Dz[4] = {0, 0, 0, 0}; 4572da392ccSBarry Smith const PetscReal x0 = coords[/*0 * 3 +*/ 0], y0 = coords[/*0 * 3 +*/ 1], z0 = coords[/*0 * 3 +*/ 2]; 45863d025dbSVijay Mahadevan 4599566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(jacobian, 9)); 4609566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ijacobian, 9)); 46163d025dbSVijay Mahadevan 462181f196bSVijay Mahadevan /* compute the jacobian */ 4639371c9d4SSatish Balay jacobian[0] = coords[1 * 3 + 0] - x0; 4649371c9d4SSatish Balay jacobian[1] = coords[2 * 3 + 0] - x0; 4659371c9d4SSatish Balay jacobian[2] = coords[3 * 3 + 0] - x0; 4669371c9d4SSatish Balay jacobian[3] = coords[1 * 3 + 1] - y0; 4679371c9d4SSatish Balay jacobian[4] = coords[2 * 3 + 1] - y0; 4689371c9d4SSatish Balay jacobian[5] = coords[3 * 3 + 1] - y0; 4699371c9d4SSatish Balay jacobian[6] = coords[1 * 3 + 2] - z0; 4709371c9d4SSatish Balay jacobian[7] = coords[2 * 3 + 2] - z0; 4719371c9d4SSatish Balay jacobian[8] = coords[3 * 3 + 2] - z0; 47263d025dbSVijay Mahadevan 47363d025dbSVijay Mahadevan /* invert the jacobian */ 4749566063dSJacob Faibussowitsch PetscCall(DMatrix_Invert_3x3_Internal(jacobian, ijacobian, volume)); 47508401ef6SPierre Jolivet PetscCheck(*volume >= 1e-8, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Tetrahedral element has zero volume: %g. Degenerate element or invalid connectivity", (double)*volume); 47663d025dbSVijay Mahadevan 477181f196bSVijay Mahadevan if (dphidx) { 4789371c9d4SSatish Balay Dx[0] = (coords[1 + 2 * 3] * (coords[2 + 1 * 3] - coords[2 + 3 * 3]) - coords[1 + 1 * 3] * (coords[2 + 2 * 3] - coords[2 + 3 * 3]) - coords[1 + 3 * 3] * (coords[2 + 1 * 3] - coords[2 + 2 * 3])) / *volume; 4799371c9d4SSatish Balay Dx[1] = -(coords[1 + 2 * 3] * (coords[2 + 0 * 3] - coords[2 + 3 * 3]) - coords[1 + 0 * 3] * (coords[2 + 2 * 3] - coords[2 + 3 * 3]) - coords[1 + 3 * 3] * (coords[2 + 0 * 3] - coords[2 + 2 * 3])) / *volume; 4809371c9d4SSatish Balay Dx[2] = (coords[1 + 1 * 3] * (coords[2 + 0 * 3] - coords[2 + 3 * 3]) - coords[1 + 0 * 3] * (coords[2 + 1 * 3] - coords[2 + 3 * 3]) - coords[1 + 3 * 3] * (coords[2 + 0 * 3] - coords[2 + 1 * 3])) / *volume; 481181f196bSVijay Mahadevan Dx[3] = -(Dx[0] + Dx[1] + Dx[2]); 4829371c9d4SSatish Balay Dy[0] = (coords[0 + 1 * 3] * (coords[2 + 2 * 3] - coords[2 + 3 * 3]) - coords[0 + 2 * 3] * (coords[2 + 1 * 3] - coords[2 + 3 * 3]) + coords[0 + 3 * 3] * (coords[2 + 1 * 3] - coords[2 + 2 * 3])) / *volume; 4839371c9d4SSatish Balay Dy[1] = -(coords[0 + 0 * 3] * (coords[2 + 2 * 3] - coords[2 + 3 * 3]) - coords[0 + 2 * 3] * (coords[2 + 0 * 3] - coords[2 + 3 * 3]) + coords[0 + 3 * 3] * (coords[2 + 0 * 3] - coords[2 + 2 * 3])) / *volume; 4849371c9d4SSatish Balay Dy[2] = (coords[0 + 0 * 3] * (coords[2 + 1 * 3] - coords[2 + 3 * 3]) - coords[0 + 1 * 3] * (coords[2 + 0 * 3] - coords[2 + 3 * 3]) + coords[0 + 3 * 3] * (coords[2 + 0 * 3] - coords[2 + 1 * 3])) / *volume; 485181f196bSVijay Mahadevan Dy[3] = -(Dy[0] + Dy[1] + Dy[2]); 4869371c9d4SSatish Balay Dz[0] = (coords[0 + 1 * 3] * (coords[1 + 3 * 3] - coords[1 + 2 * 3]) - coords[0 + 2 * 3] * (coords[1 + 3 * 3] - coords[1 + 1 * 3]) + coords[0 + 3 * 3] * (coords[1 + 2 * 3] - coords[1 + 1 * 3])) / *volume; 4879371c9d4SSatish Balay Dz[1] = -(coords[0 + 0 * 3] * (coords[1 + 3 * 3] - coords[1 + 2 * 3]) + coords[0 + 2 * 3] * (coords[1 + 0 * 3] - coords[1 + 3 * 3]) - coords[0 + 3 * 3] * (coords[1 + 0 * 3] - coords[1 + 2 * 3])) / *volume; 4889371c9d4SSatish Balay Dz[2] = (coords[0 + 0 * 3] * (coords[1 + 3 * 3] - coords[1 + 1 * 3]) + coords[0 + 1 * 3] * (coords[1 + 0 * 3] - coords[1 + 3 * 3]) - coords[0 + 3 * 3] * (coords[1 + 0 * 3] - coords[1 + 1 * 3])) / *volume; 489181f196bSVijay Mahadevan Dz[3] = -(Dz[0] + Dz[1] + Dz[2]); 490181f196bSVijay Mahadevan } 49163d025dbSVijay Mahadevan 4922da392ccSBarry Smith for (j = 0; j < npts; j++) { 493a86ed394SVijay Mahadevan const PetscInt offset = j * nverts; 494181f196bSVijay Mahadevan const PetscReal &r = quad[j * 3 + 0]; 495181f196bSVijay Mahadevan const PetscReal &s = quad[j * 3 + 1]; 496181f196bSVijay Mahadevan const PetscReal &t = quad[j * 3 + 2]; 49763d025dbSVijay Mahadevan 498181f196bSVijay Mahadevan if (jxw) jxw[j] *= *volume; 49963d025dbSVijay Mahadevan 50063d025dbSVijay Mahadevan phi[offset + 0] = 1.0 - r - s - t; 50163d025dbSVijay Mahadevan phi[offset + 1] = r; 50263d025dbSVijay Mahadevan phi[offset + 2] = s; 50363d025dbSVijay Mahadevan phi[offset + 3] = t; 50463d025dbSVijay Mahadevan 505181f196bSVijay Mahadevan if (phypts) { 506181f196bSVijay Mahadevan for (i = 0; i < nverts; ++i) { 507181f196bSVijay Mahadevan const PetscScalar *vertices = coords + i * 3; 508181f196bSVijay Mahadevan phypts[3 * j + 0] += phi[i + offset] * vertices[0]; 509181f196bSVijay Mahadevan phypts[3 * j + 1] += phi[i + offset] * vertices[1]; 510181f196bSVijay Mahadevan phypts[3 * j + 2] += phi[i + offset] * vertices[2]; 511181f196bSVijay Mahadevan } 512181f196bSVijay Mahadevan } 513181f196bSVijay Mahadevan 514181f196bSVijay Mahadevan /* Now set the derivatives */ 51563d025dbSVijay Mahadevan if (dphidx) { 516181f196bSVijay Mahadevan dphidx[0 + offset] = Dx[0]; 517181f196bSVijay Mahadevan dphidx[1 + offset] = Dx[1]; 518181f196bSVijay Mahadevan dphidx[2 + offset] = Dx[2]; 519181f196bSVijay Mahadevan dphidx[3 + offset] = Dx[3]; 52063d025dbSVijay Mahadevan 521181f196bSVijay Mahadevan dphidy[0 + offset] = Dy[0]; 522181f196bSVijay Mahadevan dphidy[1 + offset] = Dy[1]; 523181f196bSVijay Mahadevan dphidy[2 + offset] = Dy[2]; 524181f196bSVijay Mahadevan dphidy[3 + offset] = Dy[3]; 52563d025dbSVijay Mahadevan 526181f196bSVijay Mahadevan dphidz[0 + offset] = Dz[0]; 527181f196bSVijay Mahadevan dphidz[1 + offset] = Dz[1]; 528181f196bSVijay Mahadevan dphidz[2 + offset] = Dz[2]; 529181f196bSVijay Mahadevan dphidz[3 + offset] = Dz[3]; 53063d025dbSVijay Mahadevan } 53163d025dbSVijay Mahadevan 53263d025dbSVijay Mahadevan } /* Tetrahedra -- ends */ 53363a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "The number of entity vertices are invalid. Currently only support HEX8 and TET4 basis evaluations in 3-D : %" PetscInt_FMT, nverts); 534*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 53563d025dbSVijay Mahadevan } 53663d025dbSVijay Mahadevan 537cab5ea25SPierre Jolivet /*@C 53897b73a88SSatish Balay DMMoabFEMComputeBasis - Evaluate bases and derivatives at quadrature points for a linear EDGE/QUAD/TRI/HEX/TET element. 53963d025dbSVijay Mahadevan 54063d025dbSVijay Mahadevan The routine takes the coordinates of the vertices of an element and computes basis functions associated with 54163d025dbSVijay Mahadevan each quadrature point provided, and their derivatives with respect to X, Y and Z as appropriate. 54263d025dbSVijay Mahadevan 543d8d19677SJose E. Roman Input Parameters: 54467b8a455SSatish Balay + PetscInt nverts - the number of element vertices 54567b8a455SSatish Balay . PetscReal coords[3*nverts] - the physical coordinates of the vertices (in canonical numbering) 54667b8a455SSatish Balay . PetscInt npts - the number of evaluation points (quadrature points) 54767b8a455SSatish Balay - PetscReal quad[3*npts] - the evaluation points (quadrature points) in the reference space 54863d025dbSVijay Mahadevan 549d8d19677SJose E. Roman Output Parameters: 55067b8a455SSatish Balay + PetscReal phypts[3*npts] - the evaluation points (quadrature points) transformed to the physical space 55167b8a455SSatish Balay . PetscReal jxw[npts] - the jacobian determinant * quadrature weight necessary for assembling discrete contributions 55267b8a455SSatish Balay . PetscReal fe_basis[npts] - the bases values evaluated at the specified quadrature points 55367b8a455SSatish Balay - PetscReal fe_basis_derivatives[dim][npts] - the derivative of the bases wrt (X,Y,Z)-directions (depending on the dimension) evaluated at the specified quadrature points 55463d025dbSVijay Mahadevan 555edc382c3SSatish Balay Level: advanced 556edc382c3SSatish Balay 55763d025dbSVijay Mahadevan @*/ 558d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMoabFEMComputeBasis(const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscQuadrature quadrature, PetscReal *phypts, PetscReal *jacobian_quadrature_weight_product, PetscReal *fe_basis, PetscReal **fe_basis_derivatives) 559d71ae5a4SJacob Faibussowitsch { 560b21a1e88SVijay Mahadevan PetscInt npoints, idim; 56163d025dbSVijay Mahadevan bool compute_der; 56263d025dbSVijay Mahadevan const PetscReal *quadpts, *quadwts; 563181f196bSVijay Mahadevan PetscReal jacobian[9], ijacobian[9], volume; 56463d025dbSVijay Mahadevan 56563d025dbSVijay Mahadevan PetscFunctionBegin; 56663d025dbSVijay Mahadevan PetscValidPointer(coordinates, 3); 56778dc7ee3SMatthew G. Knepley PetscValidHeaderSpecific(quadrature, PETSCQUADRATURE_CLASSID, 4); 56863d025dbSVijay Mahadevan PetscValidPointer(fe_basis, 7); 56963d025dbSVijay Mahadevan compute_der = (fe_basis_derivatives != NULL); 57063d025dbSVijay Mahadevan 57163d025dbSVijay Mahadevan /* Get the quadrature points and weights for the given quadrature rule */ 5729566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quadrature, &idim, NULL, &npoints, &quadpts, &quadwts)); 57363a3b9bcSJacob Faibussowitsch PetscCheck(idim == dim, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Dimension mismatch: provided (%" PetscInt_FMT ") vs quadrature (%" PetscInt_FMT ")", idim, dim); 57448a46eb9SPierre Jolivet if (jacobian_quadrature_weight_product) PetscCall(PetscArraycpy(jacobian_quadrature_weight_product, quadwts, npoints)); 57563d025dbSVijay Mahadevan 57663d025dbSVijay Mahadevan switch (dim) { 577d71ae5a4SJacob Faibussowitsch case 1: 578d71ae5a4SJacob Faibussowitsch PetscCall(Compute_Lagrange_Basis_1D_Internal(nverts, coordinates, npoints, quadpts, phypts, jacobian_quadrature_weight_product, fe_basis, (compute_der ? fe_basis_derivatives[0] : NULL), jacobian, ijacobian, &volume)); 579d71ae5a4SJacob Faibussowitsch break; 58063d025dbSVijay Mahadevan case 2: 5819371c9d4SSatish Balay PetscCall(Compute_Lagrange_Basis_2D_Internal(nverts, coordinates, npoints, quadpts, phypts, jacobian_quadrature_weight_product, fe_basis, (compute_der ? fe_basis_derivatives[0] : NULL), (compute_der ? fe_basis_derivatives[1] : NULL), jacobian, ijacobian, &volume)); 58263d025dbSVijay Mahadevan break; 58363d025dbSVijay Mahadevan case 3: 5849371c9d4SSatish Balay PetscCall(Compute_Lagrange_Basis_3D_Internal(nverts, coordinates, npoints, quadpts, phypts, jacobian_quadrature_weight_product, fe_basis, (compute_der ? fe_basis_derivatives[0] : NULL), (compute_der ? fe_basis_derivatives[1] : NULL), (compute_der ? fe_basis_derivatives[2] : NULL), jacobian, ijacobian, &volume)); 58563d025dbSVijay Mahadevan break; 586d71ae5a4SJacob Faibussowitsch default: 587d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %" PetscInt_FMT, dim); 58863d025dbSVijay Mahadevan } 589*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59063d025dbSVijay Mahadevan } 59163d025dbSVijay Mahadevan 592cab5ea25SPierre Jolivet /*@C 59397b73a88SSatish Balay DMMoabFEMCreateQuadratureDefault - Create default quadrature rules for integration over an element with a given 59463d025dbSVijay Mahadevan dimension and polynomial order (deciphered from number of element vertices). 59563d025dbSVijay Mahadevan 596d8d19677SJose E. Roman Input Parameters: 59763d025dbSVijay Mahadevan 598a2b725a8SWilliam Gropp + PetscInt dim - the element dimension (1=EDGE, 2=QUAD/TRI, 3=HEX/TET) 599a2b725a8SWilliam Gropp - PetscInt nverts - the number of vertices in the physical element 60063d025dbSVijay Mahadevan 60163d025dbSVijay Mahadevan Output Parameter: 602a2b725a8SWilliam Gropp . PetscQuadrature quadrature - the quadrature object with default settings to integrate polynomials defined over the element 60363d025dbSVijay Mahadevan 604edc382c3SSatish Balay Level: advanced 605edc382c3SSatish Balay 60663d025dbSVijay Mahadevan @*/ 607d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMoabFEMCreateQuadratureDefault(const PetscInt dim, const PetscInt nverts, PetscQuadrature *quadrature) 608d71ae5a4SJacob Faibussowitsch { 60963d025dbSVijay Mahadevan PetscReal *w, *x; 610b21a1e88SVijay Mahadevan PetscInt nc = 1; 61163d025dbSVijay Mahadevan 61263d025dbSVijay Mahadevan PetscFunctionBegin; 61363d025dbSVijay Mahadevan /* Create an appropriate quadrature rule to sample basis */ 6149371c9d4SSatish Balay switch (dim) { 61563d025dbSVijay Mahadevan case 1: 61663d025dbSVijay Mahadevan /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */ 6179566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(1, nc, nverts, 0, 1.0, quadrature)); 61863d025dbSVijay Mahadevan break; 61963d025dbSVijay Mahadevan case 2: 62063d025dbSVijay Mahadevan /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */ 62163d025dbSVijay Mahadevan if (nverts == 3) { 622a86ed394SVijay Mahadevan const PetscInt order = 2; 623a86ed394SVijay Mahadevan const PetscInt npoints = (order == 2 ? 3 : 6); 6249566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(npoints * 2, &x, npoints, &w)); 625181f196bSVijay Mahadevan if (npoints == 3) { 62663d025dbSVijay Mahadevan x[0] = x[1] = x[2] = x[5] = 1.0 / 6.0; 62763d025dbSVijay Mahadevan x[3] = x[4] = 2.0 / 3.0; 62863d025dbSVijay Mahadevan w[0] = w[1] = w[2] = 1.0 / 3.0; 6292da392ccSBarry Smith } else if (npoints == 6) { 63063d025dbSVijay Mahadevan x[0] = x[1] = x[2] = 0.44594849091597; 63163d025dbSVijay Mahadevan x[3] = x[4] = 0.10810301816807; 63263d025dbSVijay Mahadevan x[5] = 0.44594849091597; 63363d025dbSVijay Mahadevan x[6] = x[7] = x[8] = 0.09157621350977; 63463d025dbSVijay Mahadevan x[9] = x[10] = 0.81684757298046; 63563d025dbSVijay Mahadevan x[11] = 0.09157621350977; 63663d025dbSVijay Mahadevan w[0] = w[1] = w[2] = 0.22338158967801; 637181f196bSVijay Mahadevan w[3] = w[4] = w[5] = 0.10995174365532; 63863a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Triangle quadrature rules for points 3 and 6 supported; npoints : %" PetscInt_FMT, npoints); 6399566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, quadrature)); 6409566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetOrder(*quadrature, order)); 6419566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*quadrature, dim, nc, npoints, x, w)); 6429566063dSJacob Faibussowitsch /* PetscCall(PetscDTStroudConicalQuadrature(dim, nc, nverts, 0.0, 1.0, quadrature)); */ 6431baa6e33SBarry Smith } else PetscCall(PetscDTGaussTensorQuadrature(dim, nc, nverts, 0.0, 1.0, quadrature)); 64463d025dbSVijay Mahadevan break; 64563d025dbSVijay Mahadevan case 3: 64663d025dbSVijay Mahadevan /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */ 64763d025dbSVijay Mahadevan if (nverts == 4) { 648a86ed394SVijay Mahadevan PetscInt order; 649a86ed394SVijay Mahadevan const PetscInt npoints = 4; // Choose between 4 and 10 6509566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(npoints * 3, &x, npoints, &w)); 651181f196bSVijay Mahadevan if (npoints == 4) { /* KEAST1, K1, N=4, O=4 */ 6529371c9d4SSatish Balay const PetscReal x_4[12] = {0.5854101966249685, 0.1381966011250105, 0.1381966011250105, 0.1381966011250105, 0.1381966011250105, 0.1381966011250105, 6539371c9d4SSatish Balay 0.1381966011250105, 0.1381966011250105, 0.5854101966249685, 0.1381966011250105, 0.5854101966249685, 0.1381966011250105}; 6549566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(x, x_4, 12)); 655181f196bSVijay Mahadevan 656181f196bSVijay Mahadevan w[0] = w[1] = w[2] = w[3] = 1.0 / 24.0; 657181f196bSVijay Mahadevan order = 4; 6582da392ccSBarry Smith } else if (npoints == 10) { /* KEAST3, K3 N=10, O=10 */ 6599371c9d4SSatish Balay const PetscReal x_10[30] = {0.5684305841968444, 0.1438564719343852, 0.1438564719343852, 0.1438564719343852, 0.1438564719343852, 0.1438564719343852, 0.1438564719343852, 0.1438564719343852, 0.5684305841968444, 0.1438564719343852, 6609371c9d4SSatish Balay 0.5684305841968444, 0.1438564719343852, 0.0000000000000000, 0.5000000000000000, 0.5000000000000000, 0.5000000000000000, 0.0000000000000000, 0.5000000000000000, 0.5000000000000000, 0.5000000000000000, 6619371c9d4SSatish Balay 0.0000000000000000, 0.5000000000000000, 0.0000000000000000, 0.0000000000000000, 0.0000000000000000, 0.5000000000000000, 0.0000000000000000, 0.0000000000000000, 0.0000000000000000, 0.5000000000000000}; 6629566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(x, x_10, 30)); 663181f196bSVijay Mahadevan 664181f196bSVijay Mahadevan w[0] = w[1] = w[2] = w[3] = 0.2177650698804054; 665181f196bSVijay Mahadevan w[4] = w[5] = w[6] = w[7] = w[8] = w[9] = 0.0214899534130631; 666181f196bSVijay Mahadevan order = 10; 66763a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Tetrahedral quadrature rules for points 4 and 10 supported; npoints : %" PetscInt_FMT, npoints); 6689566063dSJacob Faibussowitsch PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, quadrature)); 6699566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetOrder(*quadrature, order)); 6709566063dSJacob Faibussowitsch PetscCall(PetscQuadratureSetData(*quadrature, dim, nc, npoints, x, w)); 6719566063dSJacob Faibussowitsch /* PetscCall(PetscDTStroudConicalQuadrature(dim, nc, nverts, 0.0, 1.0, quadrature)); */ 6721baa6e33SBarry Smith } else PetscCall(PetscDTGaussTensorQuadrature(dim, nc, nverts, 0.0, 1.0, quadrature)); 67363d025dbSVijay Mahadevan break; 674d71ae5a4SJacob Faibussowitsch default: 675d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %" PetscInt_FMT, dim); 67663d025dbSVijay Mahadevan } 677*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 67863d025dbSVijay Mahadevan } 67963d025dbSVijay Mahadevan 680181f196bSVijay Mahadevan /* Compute Jacobians */ 681d71ae5a4SJacob Faibussowitsch PetscErrorCode ComputeJacobian_Internal(const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscReal *quad, PetscReal *phypts, PetscReal *jacobian, PetscReal *ijacobian, PetscReal *dvolume) 682d71ae5a4SJacob Faibussowitsch { 683a86ed394SVijay Mahadevan PetscInt i; 6842417220eSVijay Mahadevan PetscReal volume = 1.0; 685181f196bSVijay Mahadevan 686181f196bSVijay Mahadevan PetscFunctionBegin; 687181f196bSVijay Mahadevan PetscValidPointer(coordinates, 3); 688181f196bSVijay Mahadevan PetscValidPointer(quad, 4); 689181f196bSVijay Mahadevan PetscValidPointer(jacobian, 5); 6909566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(jacobian, dim * dim)); 69148a46eb9SPierre Jolivet if (ijacobian) PetscCall(PetscArrayzero(ijacobian, dim * dim)); 69248a46eb9SPierre Jolivet if (phypts) PetscCall(PetscArrayzero(phypts, /*npts=1 * */ 3)); 693181f196bSVijay Mahadevan 694181f196bSVijay Mahadevan if (dim == 1) { 695181f196bSVijay Mahadevan const PetscReal &r = quad[0]; 696181f196bSVijay Mahadevan if (nverts == 2) { /* Linear Edge */ 697181f196bSVijay Mahadevan const PetscReal dNi_dxi[2] = {-1.0, 1.0}; 698181f196bSVijay Mahadevan 699181f196bSVijay Mahadevan for (i = 0; i < nverts; ++i) { 700181f196bSVijay Mahadevan const PetscReal *vertices = coordinates + i * 3; 701181f196bSVijay Mahadevan jacobian[0] += dNi_dxi[i] * vertices[0]; 702181f196bSVijay Mahadevan } 7032da392ccSBarry Smith } else if (nverts == 3) { /* Quadratic Edge */ 704181f196bSVijay Mahadevan const PetscReal dNi_dxi[3] = {4 * r - 3.0, 4 * (1.0 - 2.0 * r), 4.0 * r - 1.0}; 705181f196bSVijay Mahadevan 706181f196bSVijay Mahadevan for (i = 0; i < nverts; ++i) { 707181f196bSVijay Mahadevan const PetscReal *vertices = coordinates + i * 3; 708181f196bSVijay Mahadevan jacobian[0] += dNi_dxi[i] * vertices[0]; 709181f196bSVijay Mahadevan } 7101baa6e33SBarry Smith } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "The number of 1-D entity vertices are invalid. Currently only support EDGE2 and EDGE3 basis evaluations in 1-D : %" PetscInt_FMT, nverts); 711181f196bSVijay Mahadevan 712181f196bSVijay Mahadevan if (ijacobian) { 713181f196bSVijay Mahadevan /* invert the jacobian */ 714181f196bSVijay Mahadevan ijacobian[0] = 1.0 / jacobian[0]; 715181f196bSVijay Mahadevan } 7162da392ccSBarry Smith } else if (dim == 2) { 717181f196bSVijay Mahadevan if (nverts == 4) { /* Linear Quadrangle */ 718181f196bSVijay Mahadevan const PetscReal &r = quad[0]; 719181f196bSVijay Mahadevan const PetscReal &s = quad[1]; 720181f196bSVijay Mahadevan 721181f196bSVijay Mahadevan const PetscReal dNi_dxi[4] = {-1.0 + s, 1.0 - s, s, -s}; 722181f196bSVijay Mahadevan const PetscReal dNi_deta[4] = {-1.0 + r, -r, r, 1.0 - r}; 723181f196bSVijay Mahadevan 724181f196bSVijay Mahadevan for (i = 0; i < nverts; ++i) { 725181f196bSVijay Mahadevan const PetscReal *vertices = coordinates + i * 3; 726181f196bSVijay Mahadevan jacobian[0] += dNi_dxi[i] * vertices[0]; 727181f196bSVijay Mahadevan jacobian[2] += dNi_dxi[i] * vertices[1]; 728181f196bSVijay Mahadevan jacobian[1] += dNi_deta[i] * vertices[0]; 729181f196bSVijay Mahadevan jacobian[3] += dNi_deta[i] * vertices[1]; 730181f196bSVijay Mahadevan } 7312da392ccSBarry Smith } else if (nverts == 3) { /* Linear triangle */ 732181f196bSVijay Mahadevan const PetscReal x2 = coordinates[2 * 3 + 0], y2 = coordinates[2 * 3 + 1]; 733181f196bSVijay Mahadevan 734181f196bSVijay Mahadevan /* Jacobian is constant */ 7359371c9d4SSatish Balay jacobian[0] = (coordinates[0 * 3 + 0] - x2); 7369371c9d4SSatish Balay jacobian[1] = (coordinates[1 * 3 + 0] - x2); 7379371c9d4SSatish Balay jacobian[2] = (coordinates[0 * 3 + 1] - y2); 7389371c9d4SSatish Balay jacobian[3] = (coordinates[1 * 3 + 1] - y2); 73963a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "The number of 2-D entity vertices are invalid. Currently only support QUAD4 and TRI3 basis evaluations in 2-D : %" PetscInt_FMT, nverts); 740181f196bSVijay Mahadevan 741181f196bSVijay Mahadevan /* invert the jacobian */ 74248a46eb9SPierre Jolivet if (ijacobian) PetscCall(DMatrix_Invert_2x2_Internal(jacobian, ijacobian, &volume)); 7432da392ccSBarry Smith } else { 744181f196bSVijay Mahadevan if (nverts == 8) { /* Linear Hexahedra */ 745181f196bSVijay Mahadevan const PetscReal &r = quad[0]; 746181f196bSVijay Mahadevan const PetscReal &s = quad[1]; 747181f196bSVijay Mahadevan const PetscReal &t = quad[2]; 7489371c9d4SSatish Balay const PetscReal dNi_dxi[8] = {-(1.0 - s) * (1.0 - t), (1.0 - s) * (1.0 - t), (s) * (1.0 - t), -(s) * (1.0 - t), -(1.0 - s) * (t), (1.0 - s) * (t), (s) * (t), -(s) * (t)}; 749181f196bSVijay Mahadevan 7509371c9d4SSatish Balay const PetscReal dNi_deta[8] = {-(1.0 - r) * (1.0 - t), -(r) * (1.0 - t), (r) * (1.0 - t), (1.0 - r) * (1.0 - t), -(1.0 - r) * (t), -(r) * (t), (r) * (t), (1.0 - r) * (t)}; 751181f196bSVijay Mahadevan 7529371c9d4SSatish Balay const PetscReal dNi_dzeta[8] = {-(1.0 - r) * (1.0 - s), -(r) * (1.0 - s), -(r) * (s), -(1.0 - r) * (s), (1.0 - r) * (1.0 - s), (r) * (1.0 - s), (r) * (s), (1.0 - r) * (s)}; 753a86ed394SVijay Mahadevan 754181f196bSVijay Mahadevan for (i = 0; i < nverts; ++i) { 755181f196bSVijay Mahadevan const PetscReal *vertex = coordinates + i * 3; 756181f196bSVijay Mahadevan jacobian[0] += dNi_dxi[i] * vertex[0]; 757181f196bSVijay Mahadevan jacobian[3] += dNi_dxi[i] * vertex[1]; 758181f196bSVijay Mahadevan jacobian[6] += dNi_dxi[i] * vertex[2]; 759181f196bSVijay Mahadevan jacobian[1] += dNi_deta[i] * vertex[0]; 760181f196bSVijay Mahadevan jacobian[4] += dNi_deta[i] * vertex[1]; 761181f196bSVijay Mahadevan jacobian[7] += dNi_deta[i] * vertex[2]; 762181f196bSVijay Mahadevan jacobian[2] += dNi_dzeta[i] * vertex[0]; 763181f196bSVijay Mahadevan jacobian[5] += dNi_dzeta[i] * vertex[1]; 764181f196bSVijay Mahadevan jacobian[8] += dNi_dzeta[i] * vertex[2]; 765181f196bSVijay Mahadevan } 7662da392ccSBarry Smith } else if (nverts == 4) { /* Linear Tetrahedra */ 767181f196bSVijay Mahadevan const PetscReal x0 = coordinates[/*0 * 3 +*/ 0], y0 = coordinates[/*0 * 3 +*/ 1], z0 = coordinates[/*0 * 3 +*/ 2]; 768181f196bSVijay Mahadevan 769181f196bSVijay Mahadevan /* compute the jacobian */ 7709371c9d4SSatish Balay jacobian[0] = coordinates[1 * 3 + 0] - x0; 7719371c9d4SSatish Balay jacobian[1] = coordinates[2 * 3 + 0] - x0; 7729371c9d4SSatish Balay jacobian[2] = coordinates[3 * 3 + 0] - x0; 7739371c9d4SSatish Balay jacobian[3] = coordinates[1 * 3 + 1] - y0; 7749371c9d4SSatish Balay jacobian[4] = coordinates[2 * 3 + 1] - y0; 7759371c9d4SSatish Balay jacobian[5] = coordinates[3 * 3 + 1] - y0; 7769371c9d4SSatish Balay jacobian[6] = coordinates[1 * 3 + 2] - z0; 7779371c9d4SSatish Balay jacobian[7] = coordinates[2 * 3 + 2] - z0; 7789371c9d4SSatish Balay jacobian[8] = coordinates[3 * 3 + 2] - z0; 77963a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "The number of 3-D entity vertices are invalid. Currently only support HEX8 and TET4 basis evaluations in 3-D : %" PetscInt_FMT, nverts); 780181f196bSVijay Mahadevan 781181f196bSVijay Mahadevan if (ijacobian) { 782181f196bSVijay Mahadevan /* invert the jacobian */ 7839566063dSJacob Faibussowitsch PetscCall(DMatrix_Invert_3x3_Internal(jacobian, ijacobian, &volume)); 784181f196bSVijay Mahadevan } 785181f196bSVijay Mahadevan } 78608401ef6SPierre Jolivet PetscCheck(volume >= 1e-12, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Element has zero volume: %g. Degenerate element or invalid connectivity", volume); 787a86ed394SVijay Mahadevan if (dvolume) *dvolume = volume; 788*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 789181f196bSVijay Mahadevan } 790181f196bSVijay Mahadevan 791d71ae5a4SJacob Faibussowitsch PetscErrorCode FEMComputeBasis_JandF(const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscReal *quadrature, PetscReal *phypts, PetscReal *phibasis, PetscReal *jacobian, PetscReal *ijacobian, PetscReal *volume) 792d71ae5a4SJacob Faibussowitsch { 793181f196bSVijay Mahadevan PetscFunctionBegin; 794181f196bSVijay Mahadevan switch (dim) { 795d71ae5a4SJacob Faibussowitsch case 1: 796d71ae5a4SJacob Faibussowitsch PetscCall(Compute_Lagrange_Basis_1D_Internal(nverts, coordinates, 1, quadrature, phypts, NULL, phibasis, NULL, jacobian, ijacobian, volume)); 797d71ae5a4SJacob Faibussowitsch break; 798d71ae5a4SJacob Faibussowitsch case 2: 799d71ae5a4SJacob Faibussowitsch PetscCall(Compute_Lagrange_Basis_2D_Internal(nverts, coordinates, 1, quadrature, phypts, NULL, phibasis, NULL, NULL, jacobian, ijacobian, volume)); 800d71ae5a4SJacob Faibussowitsch break; 801d71ae5a4SJacob Faibussowitsch case 3: 802d71ae5a4SJacob Faibussowitsch PetscCall(Compute_Lagrange_Basis_3D_Internal(nverts, coordinates, 1, quadrature, phypts, NULL, phibasis, NULL, NULL, NULL, jacobian, ijacobian, volume)); 803d71ae5a4SJacob Faibussowitsch break; 804d71ae5a4SJacob Faibussowitsch default: 805d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %" PetscInt_FMT, dim); 806181f196bSVijay Mahadevan } 807*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 808181f196bSVijay Mahadevan } 809181f196bSVijay Mahadevan 810cab5ea25SPierre Jolivet /*@C 81197b73a88SSatish Balay DMMoabPToRMapping - Compute the mapping from the physical coordinate system for a given element to the 812a86ed394SVijay Mahadevan canonical reference element. In addition to finding the inverse mapping evaluation through Newton iteration, 813a86ed394SVijay Mahadevan the basis function at the parametric point is also evaluated optionally. 814a86ed394SVijay Mahadevan 815d8d19677SJose E. Roman Input Parameters: 816a2b725a8SWilliam Gropp + PetscInt dim - the element dimension (1=EDGE, 2=QUAD/TRI, 3=HEX/TET) 817a2b725a8SWilliam Gropp . PetscInt nverts - the number of vertices in the physical element 818a2b725a8SWilliam Gropp . PetscReal coordinates - the coordinates of vertices in the physical element 819a2b725a8SWilliam Gropp - PetscReal[3] xphy - the coordinates of physical point for which natural coordinates (in reference frame) are sought 820a86ed394SVijay Mahadevan 821d8d19677SJose E. Roman Output Parameters: 822a2b725a8SWilliam Gropp + PetscReal[3] natparam - the natural coordinates (in reference frame) corresponding to xphy 823a2b725a8SWilliam Gropp - PetscReal[nverts] phi - the basis functions evaluated at the natural coordinates (natparam) 824a86ed394SVijay Mahadevan 825edc382c3SSatish Balay Level: advanced 826edc382c3SSatish Balay 827a86ed394SVijay Mahadevan @*/ 828d71ae5a4SJacob Faibussowitsch PetscErrorCode DMMoabPToRMapping(const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscReal *xphy, PetscReal *natparam, PetscReal *phi) 829d71ae5a4SJacob Faibussowitsch { 830a86ed394SVijay Mahadevan /* Perform inverse evaluation for the mapping with use of Newton Raphson iteration */ 831181f196bSVijay Mahadevan const PetscReal tol = 1.0e-10; 832181f196bSVijay Mahadevan const PetscInt max_iterations = 10; 833181f196bSVijay Mahadevan const PetscReal error_tol_sqr = tol * tol; 834181f196bSVijay Mahadevan PetscReal phibasis[8], jacobian[9], ijacobian[9], volume; 835181f196bSVijay Mahadevan PetscReal phypts[3] = {0.0, 0.0, 0.0}; 836181f196bSVijay Mahadevan PetscReal delta[3] = {0.0, 0.0, 0.0}; 837181f196bSVijay Mahadevan PetscInt iters = 0; 838181f196bSVijay Mahadevan PetscReal error = 1.0; 839181f196bSVijay Mahadevan 840181f196bSVijay Mahadevan PetscFunctionBegin; 841181f196bSVijay Mahadevan PetscValidPointer(coordinates, 3); 842181f196bSVijay Mahadevan PetscValidPointer(xphy, 4); 843181f196bSVijay Mahadevan PetscValidPointer(natparam, 5); 844181f196bSVijay Mahadevan 8459566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(jacobian, dim * dim)); 8469566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ijacobian, dim * dim)); 8479566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(phibasis, nverts)); 848181f196bSVijay Mahadevan 849a86ed394SVijay Mahadevan /* zero initial guess */ 850a86ed394SVijay Mahadevan natparam[0] = natparam[1] = natparam[2] = 0.0; 851181f196bSVijay Mahadevan 852a86ed394SVijay Mahadevan /* Compute delta = evaluate( xi) - x */ 8539566063dSJacob Faibussowitsch PetscCall(FEMComputeBasis_JandF(dim, nverts, coordinates, natparam, phypts, phibasis, jacobian, ijacobian, &volume)); 854a86ed394SVijay Mahadevan 855a86ed394SVijay Mahadevan error = 0.0; 856a86ed394SVijay Mahadevan switch (dim) { 857d71ae5a4SJacob Faibussowitsch case 3: 858d71ae5a4SJacob Faibussowitsch delta[2] = phypts[2] - xphy[2]; 859d71ae5a4SJacob Faibussowitsch error += (delta[2] * delta[2]); 860d71ae5a4SJacob Faibussowitsch case 2: 861d71ae5a4SJacob Faibussowitsch delta[1] = phypts[1] - xphy[1]; 862d71ae5a4SJacob Faibussowitsch error += (delta[1] * delta[1]); 863a86ed394SVijay Mahadevan case 1: 864a86ed394SVijay Mahadevan delta[0] = phypts[0] - xphy[0]; 865a86ed394SVijay Mahadevan error += (delta[0] * delta[0]); 866a86ed394SVijay Mahadevan break; 867a86ed394SVijay Mahadevan } 868a86ed394SVijay Mahadevan 869181f196bSVijay Mahadevan while (error > error_tol_sqr) { 8707a46b595SBarry Smith PetscCheck(++iters <= max_iterations, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Maximum Newton iterations (10) reached. Current point in reference space : (%g, %g, %g)", natparam[0], natparam[1], natparam[2]); 871181f196bSVijay Mahadevan 872181f196bSVijay Mahadevan /* Compute natparam -= J.inverse() * delta */ 873181f196bSVijay Mahadevan switch (dim) { 874d71ae5a4SJacob Faibussowitsch case 1: 875d71ae5a4SJacob Faibussowitsch natparam[0] -= ijacobian[0] * delta[0]; 876d71ae5a4SJacob Faibussowitsch break; 877181f196bSVijay Mahadevan case 2: 878181f196bSVijay Mahadevan natparam[0] -= ijacobian[0] * delta[0] + ijacobian[1] * delta[1]; 879181f196bSVijay Mahadevan natparam[1] -= ijacobian[2] * delta[0] + ijacobian[3] * delta[1]; 880181f196bSVijay Mahadevan break; 881181f196bSVijay Mahadevan case 3: 882181f196bSVijay Mahadevan natparam[0] -= ijacobian[0] * delta[0] + ijacobian[1] * delta[1] + ijacobian[2] * delta[2]; 883181f196bSVijay Mahadevan natparam[1] -= ijacobian[3] * delta[0] + ijacobian[4] * delta[1] + ijacobian[5] * delta[2]; 884181f196bSVijay Mahadevan natparam[2] -= ijacobian[6] * delta[0] + ijacobian[7] * delta[1] + ijacobian[8] * delta[2]; 885181f196bSVijay Mahadevan break; 886181f196bSVijay Mahadevan } 887181f196bSVijay Mahadevan 888181f196bSVijay Mahadevan /* Compute delta = evaluate( xi) - x */ 8899566063dSJacob Faibussowitsch PetscCall(FEMComputeBasis_JandF(dim, nverts, coordinates, natparam, phypts, phibasis, jacobian, ijacobian, &volume)); 890181f196bSVijay Mahadevan 891a86ed394SVijay Mahadevan error = 0.0; 892a86ed394SVijay Mahadevan switch (dim) { 893d71ae5a4SJacob Faibussowitsch case 3: 894d71ae5a4SJacob Faibussowitsch delta[2] = phypts[2] - xphy[2]; 895d71ae5a4SJacob Faibussowitsch error += (delta[2] * delta[2]); 896d71ae5a4SJacob Faibussowitsch case 2: 897d71ae5a4SJacob Faibussowitsch delta[1] = phypts[1] - xphy[1]; 898d71ae5a4SJacob Faibussowitsch error += (delta[1] * delta[1]); 899a86ed394SVijay Mahadevan case 1: 900a86ed394SVijay Mahadevan delta[0] = phypts[0] - xphy[0]; 901a86ed394SVijay Mahadevan error += (delta[0] * delta[0]); 902a86ed394SVijay Mahadevan break; 903a86ed394SVijay Mahadevan } 904181f196bSVijay Mahadevan } 90548a46eb9SPierre Jolivet if (phi) PetscCall(PetscArraycpy(phi, phibasis, nverts)); 906*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 907181f196bSVijay Mahadevan } 908