1*63d025dbSVijay Mahadevan 2*63d025dbSVijay Mahadevan #include <petscconf.h> 3*63d025dbSVijay Mahadevan #include <petscdt.h> /*I "petscdt.h" I*/ 4*63d025dbSVijay Mahadevan #include <petsc/private/dmmbimpl.h> /*I "petscdmmoab.h" I*/ 5*63d025dbSVijay Mahadevan 6*63d025dbSVijay Mahadevan /* Utility functions */ 7*63d025dbSVijay Mahadevan static inline PetscReal DMatrix_Determinant_2x2_Internal ( const PetscReal inmat[2 * 2] ) 8*63d025dbSVijay Mahadevan { 9*63d025dbSVijay Mahadevan return inmat[0] * inmat[3] - inmat[1] * inmat[2]; 10*63d025dbSVijay Mahadevan } 11*63d025dbSVijay Mahadevan 12*63d025dbSVijay Mahadevan static inline PetscErrorCode DMatrix_Invert_2x2_Internal (const PetscReal *inmat, PetscReal *outmat, PetscReal *determinant) 13*63d025dbSVijay Mahadevan { 14*63d025dbSVijay Mahadevan if (!inmat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_POINTER, "Invalid input matrix specified for 2x2 inversion."); 15*63d025dbSVijay Mahadevan PetscReal det = DMatrix_Determinant_2x2_Internal(inmat); 16*63d025dbSVijay Mahadevan if (outmat) { 17*63d025dbSVijay Mahadevan outmat[0] = inmat[3] / det; 18*63d025dbSVijay Mahadevan outmat[1] = -inmat[1] / det; 19*63d025dbSVijay Mahadevan outmat[2] = -inmat[2] / det; 20*63d025dbSVijay Mahadevan outmat[3] = inmat[0] / det; 21*63d025dbSVijay Mahadevan } 22*63d025dbSVijay Mahadevan if (determinant) *determinant = det; 23*63d025dbSVijay Mahadevan PetscFunctionReturn(0); 24*63d025dbSVijay Mahadevan } 25*63d025dbSVijay Mahadevan 26*63d025dbSVijay Mahadevan static inline double DMatrix_Determinant_3x3_Internal ( const PetscReal inmat[3 * 3] ) 27*63d025dbSVijay Mahadevan { 28*63d025dbSVijay Mahadevan return inmat[0] * (inmat[8] * inmat[4] - inmat[7] * inmat[5]) 29*63d025dbSVijay Mahadevan - inmat[3] * (inmat[8] * inmat[1] - inmat[7] * inmat[2]) 30*63d025dbSVijay Mahadevan + inmat[6] * (inmat[5] * inmat[1] - inmat[4] * inmat[2]); 31*63d025dbSVijay Mahadevan } 32*63d025dbSVijay Mahadevan 33*63d025dbSVijay Mahadevan static inline PetscErrorCode DMatrix_Invert_3x3_Internal (const PetscReal *inmat, PetscReal *outmat, PetscScalar *determinant) 34*63d025dbSVijay Mahadevan { 35*63d025dbSVijay Mahadevan if (!inmat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_POINTER, "Invalid input matrix specified for 3x3 inversion."); 36*63d025dbSVijay Mahadevan double det = DMatrix_Determinant_3x3_Internal(inmat); 37*63d025dbSVijay Mahadevan if (outmat) { 38*63d025dbSVijay Mahadevan outmat[0] = (inmat[8] * inmat[4] - inmat[7] * inmat[5]) / det; 39*63d025dbSVijay Mahadevan outmat[1] = -(inmat[8] * inmat[1] - inmat[7] * inmat[2]) / det; 40*63d025dbSVijay Mahadevan outmat[2] = (inmat[5] * inmat[1] - inmat[4] * inmat[2]) / det; 41*63d025dbSVijay Mahadevan outmat[3] = -(inmat[8] * inmat[3] - inmat[6] * inmat[5]) / det; 42*63d025dbSVijay Mahadevan outmat[4] = (inmat[8] * inmat[0] - inmat[6] * inmat[2]) / det; 43*63d025dbSVijay Mahadevan outmat[5] = -(inmat[5] * inmat[0] - inmat[3] * inmat[2]) / det; 44*63d025dbSVijay Mahadevan outmat[6] = (inmat[7] * inmat[3] - inmat[6] * inmat[4]) / det; 45*63d025dbSVijay Mahadevan outmat[7] = -(inmat[7] * inmat[0] - inmat[6] * inmat[1]) / det; 46*63d025dbSVijay Mahadevan outmat[8] = (inmat[4] * inmat[0] - inmat[3] * inmat[1]) / det; 47*63d025dbSVijay Mahadevan } 48*63d025dbSVijay Mahadevan if (determinant) *determinant = det; 49*63d025dbSVijay Mahadevan PetscFunctionReturn(0); 50*63d025dbSVijay Mahadevan } 51*63d025dbSVijay Mahadevan 52*63d025dbSVijay Mahadevan 53*63d025dbSVijay Mahadevan /*@ 54*63d025dbSVijay Mahadevan Compute_Lagrange_Basis_1D_Internal: Evaluate bases and derivatives at quadrature points for a EDGE2 or EDGE3 element. 55*63d025dbSVijay Mahadevan 56*63d025dbSVijay Mahadevan The routine is given the coordinates of the vertices of a linear or quadratic edge element. 57*63d025dbSVijay Mahadevan 58*63d025dbSVijay Mahadevan The routine evaluates the basis functions associated with each quadrature point provided, 59*63d025dbSVijay Mahadevan and their derivatives with respect to X. 60*63d025dbSVijay Mahadevan 61*63d025dbSVijay Mahadevan Notes: 62*63d025dbSVijay Mahadevan 63*63d025dbSVijay Mahadevan Example Physical Element 64*63d025dbSVijay Mahadevan 65*63d025dbSVijay Mahadevan 1-------2 1----3----2 66*63d025dbSVijay Mahadevan EDGE2 EDGE3 67*63d025dbSVijay Mahadevan 68*63d025dbSVijay Mahadevan Input Parameter: 69*63d025dbSVijay Mahadevan 70*63d025dbSVijay Mahadevan . PetscInt nverts, the number of element vertices 71*63d025dbSVijay Mahadevan . PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering) 72*63d025dbSVijay Mahadevan . PetscInt npts, the number of evaluation points (quadrature points) 73*63d025dbSVijay Mahadevan . PetscReal quad[3*npts], the evaluation points (quadrature points) in the reference space 74*63d025dbSVijay Mahadevan 75*63d025dbSVijay Mahadevan Output Parameter: 76*63d025dbSVijay Mahadevan . PetscReal phypts[3*npts], the evaluation points (quadrature points) transformed to the physical space 77*63d025dbSVijay Mahadevan . PetscReal jxw[npts], the jacobian determinant * quadrature weight necessary for assembling discrete contributions 78*63d025dbSVijay Mahadevan . PetscReal phi[npts], the bases evaluated at the specified quadrature points 79*63d025dbSVijay Mahadevan . PetscReal dphidx[npts], the derivative of the bases wrt X-direction evaluated at the specified quadrature points 80*63d025dbSVijay Mahadevan 81*63d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 1-D 82*63d025dbSVijay Mahadevan @*/ 83*63d025dbSVijay Mahadevan #undef __FUNCT__ 84*63d025dbSVijay Mahadevan #define __FUNCT__ "Compute_Lagrange_Basis_1D_Internal" 85*63d025dbSVijay Mahadevan PetscErrorCode Compute_Lagrange_Basis_1D_Internal ( const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts, 86*63d025dbSVijay Mahadevan PetscReal *jxw, PetscReal *phi, PetscReal *dphidx) 87*63d025dbSVijay Mahadevan { 88*63d025dbSVijay Mahadevan int i, j; 89*63d025dbSVijay Mahadevan PetscReal jacobian, ijacobian; 90*63d025dbSVijay Mahadevan PetscErrorCode ierr; 91*63d025dbSVijay Mahadevan PetscFunctionBegin; 92*63d025dbSVijay Mahadevan 93*63d025dbSVijay Mahadevan ierr = PetscMemzero(phypts, npts * 3 * sizeof(PetscReal));CHKERRQ(ierr); 94*63d025dbSVijay Mahadevan if (dphidx) { /* Reset arrays. */ 95*63d025dbSVijay Mahadevan ierr = PetscMemzero(dphidx, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr); 96*63d025dbSVijay Mahadevan } 97*63d025dbSVijay Mahadevan if (nverts == 2) { /* Linear Edge */ 98*63d025dbSVijay Mahadevan 99*63d025dbSVijay Mahadevan for (j = 0; j < npts; j++) 100*63d025dbSVijay Mahadevan { 101*63d025dbSVijay Mahadevan const int offset = j * nverts; 102*63d025dbSVijay Mahadevan const double r = quad[j]; 103*63d025dbSVijay Mahadevan 104*63d025dbSVijay Mahadevan phi[0 + offset] = 0.5 * ( 1.0 - r ); 105*63d025dbSVijay Mahadevan phi[1 + offset] = 0.5 * ( 1.0 + r ); 106*63d025dbSVijay Mahadevan 107*63d025dbSVijay Mahadevan const double dNi_dxi[2] = { -0.5, 0.5 }; 108*63d025dbSVijay Mahadevan 109*63d025dbSVijay Mahadevan jacobian = ijacobian = 0.0; 110*63d025dbSVijay Mahadevan for (i = 0; i < nverts; ++i) { 111*63d025dbSVijay Mahadevan const PetscScalar* vertices = coords + i * 3; 112*63d025dbSVijay Mahadevan jacobian += dNi_dxi[i] * vertices[0]; 113*63d025dbSVijay Mahadevan for (int k = 0; k < 3; ++k) 114*63d025dbSVijay Mahadevan phypts[3 * j + k] += phi[i + offset] * vertices[k]; 115*63d025dbSVijay Mahadevan } 116*63d025dbSVijay Mahadevan 117*63d025dbSVijay Mahadevan /* invert the jacobian */ 118*63d025dbSVijay Mahadevan ijacobian = 1.0 / jacobian; 119*63d025dbSVijay Mahadevan 120*63d025dbSVijay Mahadevan jxw[j] *= jacobian; 121*63d025dbSVijay Mahadevan 122*63d025dbSVijay Mahadevan /* Divide by element jacobian. */ 123*63d025dbSVijay Mahadevan for ( i = 0; i < nverts; i++ ) { 124*63d025dbSVijay Mahadevan if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian; 125*63d025dbSVijay Mahadevan } 126*63d025dbSVijay Mahadevan 127*63d025dbSVijay Mahadevan } 128*63d025dbSVijay Mahadevan } 129*63d025dbSVijay Mahadevan else if (nverts == 3) { /* Quadratic Edge */ 130*63d025dbSVijay Mahadevan 131*63d025dbSVijay Mahadevan for (j = 0; j < npts; j++) 132*63d025dbSVijay Mahadevan { 133*63d025dbSVijay Mahadevan const int offset = j * nverts; 134*63d025dbSVijay Mahadevan const double r = quad[j]; 135*63d025dbSVijay Mahadevan 136*63d025dbSVijay Mahadevan phi[0 + offset] = 0.5 * r * (r - 1.0); 137*63d025dbSVijay Mahadevan phi[1 + offset] = 0.5 * r * (r + 1.0); 138*63d025dbSVijay Mahadevan phi[2 + offset] = ( 1.0 - r * r ); 139*63d025dbSVijay Mahadevan 140*63d025dbSVijay Mahadevan const double dNi_dxi[3] = { r - 0.5, r + 0.5, -2.0 * r}; 141*63d025dbSVijay Mahadevan 142*63d025dbSVijay Mahadevan jacobian = ijacobian = 0.0; 143*63d025dbSVijay Mahadevan for (i = 0; i < nverts; ++i) { 144*63d025dbSVijay Mahadevan const PetscScalar* vertices = coords + i * 3; 145*63d025dbSVijay Mahadevan jacobian += dNi_dxi[i] * vertices[0]; 146*63d025dbSVijay Mahadevan for (int k = 0; k < 3; ++k) 147*63d025dbSVijay Mahadevan phypts[3 * j + k] += phi[i + offset] * vertices[k]; 148*63d025dbSVijay Mahadevan } 149*63d025dbSVijay Mahadevan 150*63d025dbSVijay Mahadevan /* invert the jacobian */ 151*63d025dbSVijay Mahadevan ijacobian = 1.0 / jacobian; 152*63d025dbSVijay Mahadevan 153*63d025dbSVijay Mahadevan jxw[j] *= jacobian; 154*63d025dbSVijay Mahadevan 155*63d025dbSVijay Mahadevan /* Divide by element jacobian. */ 156*63d025dbSVijay Mahadevan for ( i = 0; i < nverts; i++ ) { 157*63d025dbSVijay Mahadevan if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian; 158*63d025dbSVijay Mahadevan } 159*63d025dbSVijay Mahadevan 160*63d025dbSVijay Mahadevan } 161*63d025dbSVijay Mahadevan 162*63d025dbSVijay Mahadevan } 163*63d025dbSVijay Mahadevan else { 164*63d025dbSVijay Mahadevan SETERRQ1(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 : %D", nverts); 165*63d025dbSVijay Mahadevan } 166*63d025dbSVijay Mahadevan #if 0 167*63d025dbSVijay Mahadevan /* verify if the computed basis functions are consistent */ 168*63d025dbSVijay Mahadevan for ( j = 0; j < npts; j++ ) { 169*63d025dbSVijay Mahadevan PetscScalar phisum = 0, dphixsum = 0; 170*63d025dbSVijay Mahadevan for ( i = 0; i < nverts; i++ ) { 171*63d025dbSVijay Mahadevan phisum += phi[i + j * nverts]; 172*63d025dbSVijay Mahadevan if (dphidx) dphixsum += dphidx[i + j * nverts]; 173*63d025dbSVijay Mahadevan } 174*63d025dbSVijay Mahadevan PetscPrintf(PETSC_COMM_WORLD, "Sum of basis at quadrature point %D = %g, %g, %g\n", j, phisum, dphixsum); 175*63d025dbSVijay Mahadevan } 176*63d025dbSVijay Mahadevan #endif 177*63d025dbSVijay Mahadevan PetscFunctionReturn(0); 178*63d025dbSVijay Mahadevan } 179*63d025dbSVijay Mahadevan 180*63d025dbSVijay Mahadevan 181*63d025dbSVijay Mahadevan /*@ 182*63d025dbSVijay Mahadevan Compute_Lagrange_Basis_2D_Internal: Evaluate bases and derivatives at quadrature points for a QUAD4 or TRI3 element. 183*63d025dbSVijay Mahadevan 184*63d025dbSVijay Mahadevan The routine is given the coordinates of the vertices of a quadrangle or triangle. 185*63d025dbSVijay Mahadevan 186*63d025dbSVijay Mahadevan The routine evaluates the basis functions associated with each quadrature point provided, 187*63d025dbSVijay Mahadevan and their derivatives with respect to X and Y. 188*63d025dbSVijay Mahadevan 189*63d025dbSVijay Mahadevan Notes: 190*63d025dbSVijay Mahadevan 191*63d025dbSVijay Mahadevan Example Physical Element (QUAD4) 192*63d025dbSVijay Mahadevan 193*63d025dbSVijay Mahadevan 4------3 s 194*63d025dbSVijay Mahadevan | | | 195*63d025dbSVijay Mahadevan | | | 196*63d025dbSVijay Mahadevan | | | 197*63d025dbSVijay Mahadevan 1------2 0-------r 198*63d025dbSVijay Mahadevan 199*63d025dbSVijay Mahadevan Input Parameter: 200*63d025dbSVijay Mahadevan 201*63d025dbSVijay Mahadevan . PetscInt nverts, the number of element vertices 202*63d025dbSVijay Mahadevan . PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering) 203*63d025dbSVijay Mahadevan . PetscInt npts, the number of evaluation points (quadrature points) 204*63d025dbSVijay Mahadevan . PetscReal quad[3*npts], the evaluation points (quadrature points) in the reference space 205*63d025dbSVijay Mahadevan 206*63d025dbSVijay Mahadevan Output Parameter: 207*63d025dbSVijay Mahadevan . PetscReal phypts[3*npts], the evaluation points (quadrature points) transformed to the physical space 208*63d025dbSVijay Mahadevan . PetscReal jxw[npts], the jacobian determinant * quadrature weight necessary for assembling discrete contributions 209*63d025dbSVijay Mahadevan . PetscReal phi[npts], the bases evaluated at the specified quadrature points 210*63d025dbSVijay Mahadevan . PetscReal dphidx[npts], the derivative of the bases wrt X-direction evaluated at the specified quadrature points 211*63d025dbSVijay Mahadevan . PetscReal dphidy[npts], the derivative of the bases wrt Y-direction evaluated at the specified quadrature points 212*63d025dbSVijay Mahadevan 213*63d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 2-D 214*63d025dbSVijay Mahadevan @*/ 215*63d025dbSVijay Mahadevan #undef __FUNCT__ 216*63d025dbSVijay Mahadevan #define __FUNCT__ "Compute_Lagrange_Basis_2D_Internal" 217*63d025dbSVijay Mahadevan PetscErrorCode Compute_Lagrange_Basis_2D_Internal ( const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts, 218*63d025dbSVijay Mahadevan PetscReal *jxw, PetscReal *phi, PetscReal *dphidx, PetscReal *dphidy) 219*63d025dbSVijay Mahadevan { 220*63d025dbSVijay Mahadevan int i, j; 221*63d025dbSVijay Mahadevan PetscReal jacobian[4], ijacobian[4]; 222*63d025dbSVijay Mahadevan double jacobiandet; 223*63d025dbSVijay Mahadevan PetscErrorCode ierr; 224*63d025dbSVijay Mahadevan 225*63d025dbSVijay Mahadevan PetscFunctionBegin; 226*63d025dbSVijay Mahadevan ierr = PetscMemzero(phi, npts * sizeof(PetscReal));CHKERRQ(ierr); 227*63d025dbSVijay Mahadevan ierr = PetscMemzero(phypts, npts * 3 * sizeof(PetscReal));CHKERRQ(ierr); 228*63d025dbSVijay Mahadevan if (dphidx) { /* Reset arrays. */ 229*63d025dbSVijay Mahadevan ierr = PetscMemzero(dphidx, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr); 230*63d025dbSVijay Mahadevan ierr = PetscMemzero(dphidy, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr); 231*63d025dbSVijay Mahadevan } 232*63d025dbSVijay Mahadevan if (nverts == 4) { /* Linear Quadrangle */ 233*63d025dbSVijay Mahadevan 234*63d025dbSVijay Mahadevan for (j = 0; j < npts; j++) 235*63d025dbSVijay Mahadevan { 236*63d025dbSVijay Mahadevan const int offset = j * nverts; 237*63d025dbSVijay Mahadevan const double r = quad[0 + j * 2]; 238*63d025dbSVijay Mahadevan const double s = quad[1 + j * 2]; 239*63d025dbSVijay Mahadevan 240*63d025dbSVijay Mahadevan phi[0 + offset] = ( 1.0 - r ) * ( 1.0 - s ); 241*63d025dbSVijay Mahadevan phi[1 + offset] = r * ( 1.0 - s ); 242*63d025dbSVijay Mahadevan phi[2 + offset] = r * s; 243*63d025dbSVijay Mahadevan phi[3 + offset] = ( 1.0 - r ) * s; 244*63d025dbSVijay Mahadevan 245*63d025dbSVijay Mahadevan const double dNi_dxi[4] = { -1.0 + s, 1.0 - s, s, -s }; 246*63d025dbSVijay Mahadevan const double dNi_deta[4] = { -1.0 + r, -r, r, 1.0 - r }; 247*63d025dbSVijay Mahadevan 248*63d025dbSVijay Mahadevan ierr = PetscMemzero(jacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr); 249*63d025dbSVijay Mahadevan ierr = PetscMemzero(ijacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr); 250*63d025dbSVijay Mahadevan for (i = 0; i < nverts; ++i) { 251*63d025dbSVijay Mahadevan const PetscScalar* vertices = coords + i * 3; 252*63d025dbSVijay Mahadevan jacobian[0] += dNi_dxi[i] * vertices[0]; 253*63d025dbSVijay Mahadevan jacobian[2] += dNi_dxi[i] * vertices[1]; 254*63d025dbSVijay Mahadevan jacobian[1] += dNi_deta[i] * vertices[0]; 255*63d025dbSVijay Mahadevan jacobian[3] += dNi_deta[i] * vertices[1]; 256*63d025dbSVijay Mahadevan for (int k = 0; k < 3; ++k) 257*63d025dbSVijay Mahadevan phypts[3 * j + k] += phi[i + offset] * vertices[k]; 258*63d025dbSVijay Mahadevan } 259*63d025dbSVijay Mahadevan 260*63d025dbSVijay Mahadevan /* invert the jacobian */ 261*63d025dbSVijay Mahadevan ierr = DMatrix_Invert_2x2_Internal(jacobian, ijacobian, &jacobiandet);CHKERRQ(ierr); 262*63d025dbSVijay Mahadevan 263*63d025dbSVijay Mahadevan jxw[j] *= jacobiandet; 264*63d025dbSVijay Mahadevan 265*63d025dbSVijay Mahadevan /* Divide by element jacobian. */ 266*63d025dbSVijay Mahadevan for ( i = 0; i < nverts; i++ ) { 267*63d025dbSVijay Mahadevan for (int k = 0; k < 2; ++k) { 268*63d025dbSVijay Mahadevan if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[k * 2 + 0]; 269*63d025dbSVijay Mahadevan if (dphidy) dphidy[i + offset] += dNi_deta[i] * ijacobian[k * 2 + 1]; 270*63d025dbSVijay Mahadevan } 271*63d025dbSVijay Mahadevan } 272*63d025dbSVijay Mahadevan 273*63d025dbSVijay Mahadevan } 274*63d025dbSVijay Mahadevan } 275*63d025dbSVijay Mahadevan else if (nverts == 3) { /* Linear triangle */ 276*63d025dbSVijay Mahadevan 277*63d025dbSVijay Mahadevan ierr = PetscMemzero(jacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr); 278*63d025dbSVijay Mahadevan ierr = PetscMemzero(ijacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr); 279*63d025dbSVijay Mahadevan 280*63d025dbSVijay Mahadevan /* Jacobian is constant */ 281*63d025dbSVijay Mahadevan jacobian[0] = (coords[0 * 3 + 0] - coords[2 * 3 + 0]); jacobian[1] = (coords[1 * 3 + 0] - coords[2 * 3 + 0]); 282*63d025dbSVijay Mahadevan jacobian[2] = (coords[0 * 3 + 1] - coords[2 * 3 + 1]); jacobian[3] = (coords[1 * 3 + 1] - coords[2 * 3 + 1]); 283*63d025dbSVijay Mahadevan 284*63d025dbSVijay Mahadevan /* invert the jacobian */ 285*63d025dbSVijay Mahadevan ierr = DMatrix_Invert_2x2_Internal(jacobian, ijacobian, &jacobiandet);CHKERRQ(ierr); 286*63d025dbSVijay Mahadevan // std::cout << "Triangle area = " << jacobiandet << "\n"; 287*63d025dbSVijay Mahadevan if ( jacobiandet < 1e-8 ) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Triangular element has zero volume: %g. Degenerate element or invalid connectivity\n", jacobiandet); 288*63d025dbSVijay Mahadevan 289*63d025dbSVijay Mahadevan for (j = 0; j < npts; j++) 290*63d025dbSVijay Mahadevan { 291*63d025dbSVijay Mahadevan const int offset = j * nverts; 292*63d025dbSVijay Mahadevan const double r = quad[0 + j * 2]; 293*63d025dbSVijay Mahadevan const double s = quad[1 + j * 2]; 294*63d025dbSVijay Mahadevan 295*63d025dbSVijay Mahadevan jxw[j] *= 0.5; 296*63d025dbSVijay Mahadevan 297*63d025dbSVijay Mahadevan // const double Ni[3] = { r, s, 1.0 - r - s }; 298*63d025dbSVijay Mahadevan // for (i = 0; i < nverts; ++i) { 299*63d025dbSVijay Mahadevan // const PetscScalar* vertices = coords+i*3; 300*63d025dbSVijay Mahadevan // for (int k = 0; k < 3; ++k) 301*63d025dbSVijay Mahadevan // phypts[offset+k] += Ni[i] * vertices[k]; 302*63d025dbSVijay Mahadevan // } 303*63d025dbSVijay Mahadevan phypts[offset + 0] = coords[2 * 3 + 0] + jacobian[0] * r + jacobian[1] * s; 304*63d025dbSVijay Mahadevan phypts[offset + 1] = coords[2 * 3 + 1] + jacobian[2] * r + jacobian[3] * s; 305*63d025dbSVijay Mahadevan 306*63d025dbSVijay Mahadevan phi[0 + offset] = ( jacobian[3] * (phypts[offset + 0] - coords[2 * 3 + 0]) - jacobian[1] * (phypts[offset + 1] - coords[2 * 3 + 1]) ) / jacobiandet; // (b.y − c.y) x + (b.x − c.x) y + c.x b.y − b.x c.y 307*63d025dbSVijay Mahadevan phi[1 + offset] = ( -jacobian[2] * (phypts[offset + 0] - coords[2 * 3 + 0]) + jacobian[0] * (phypts[offset + 1] - coords[2 * 3 + 1]) ) / jacobiandet; // (c.y − a.y) x + (a.x − c.x) y + c.x a.y − a.x c.y 308*63d025dbSVijay Mahadevan phi[2 + offset] = 1.0 - phi[0 + offset] - phi[1 + offset]; 309*63d025dbSVijay Mahadevan 310*63d025dbSVijay Mahadevan if (dphidx) { 311*63d025dbSVijay Mahadevan dphidx[0 + offset] = jacobian[3] / jacobiandet; 312*63d025dbSVijay Mahadevan dphidx[1 + offset] = -jacobian[2] / jacobiandet; 313*63d025dbSVijay Mahadevan dphidx[2 + offset] = -dphidx[0 + offset] - dphidx[1 + offset]; 314*63d025dbSVijay Mahadevan } 315*63d025dbSVijay Mahadevan 316*63d025dbSVijay Mahadevan if (dphidy) { 317*63d025dbSVijay Mahadevan dphidy[0 + offset] = -jacobian[1] / jacobiandet; 318*63d025dbSVijay Mahadevan dphidy[1 + offset] = jacobian[0] / jacobiandet; 319*63d025dbSVijay Mahadevan dphidy[2 + offset] = -dphidy[0 + offset] - dphidy[1 + offset]; 320*63d025dbSVijay Mahadevan } 321*63d025dbSVijay Mahadevan 322*63d025dbSVijay Mahadevan 323*63d025dbSVijay Mahadevan } 324*63d025dbSVijay Mahadevan } 325*63d025dbSVijay Mahadevan else { 326*63d025dbSVijay Mahadevan SETERRQ1(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 : %D", nverts); 327*63d025dbSVijay Mahadevan } 328*63d025dbSVijay Mahadevan #if 0 329*63d025dbSVijay Mahadevan /* verify if the computed basis functions are consistent */ 330*63d025dbSVijay Mahadevan for ( j = 0; j < npts; j++ ) { 331*63d025dbSVijay Mahadevan PetscScalar phisum = 0, dphixsum = 0, dphiysum = 0; 332*63d025dbSVijay Mahadevan for ( i = 0; i < nverts; i++ ) { 333*63d025dbSVijay Mahadevan phisum += phi[i + j * nverts]; 334*63d025dbSVijay Mahadevan if (dphidx) dphixsum += dphidx[i + j * nverts]; 335*63d025dbSVijay Mahadevan if (dphidy) dphiysum += dphidy[i + j * nverts]; 336*63d025dbSVijay Mahadevan } 337*63d025dbSVijay Mahadevan PetscPrintf(PETSC_COMM_WORLD, "Sum of basis at quadrature point %D = %g, %g, %g\n", j, phisum, dphixsum, dphiysum); 338*63d025dbSVijay Mahadevan } 339*63d025dbSVijay Mahadevan #endif 340*63d025dbSVijay Mahadevan PetscFunctionReturn(0); 341*63d025dbSVijay Mahadevan } 342*63d025dbSVijay Mahadevan 343*63d025dbSVijay Mahadevan 344*63d025dbSVijay Mahadevan /*@ 345*63d025dbSVijay Mahadevan Compute_Lagrange_Basis_3D_Internal: Evaluate bases and derivatives at quadrature points for a HEX8 or TET4 element. 346*63d025dbSVijay Mahadevan 347*63d025dbSVijay Mahadevan The routine is given the coordinates of the vertices of a hexahedra or tetrahedra. 348*63d025dbSVijay Mahadevan 349*63d025dbSVijay Mahadevan The routine evaluates the basis functions associated with each quadrature point provided, 350*63d025dbSVijay Mahadevan and their derivatives with respect to X, Y and Z. 351*63d025dbSVijay Mahadevan 352*63d025dbSVijay Mahadevan Notes: 353*63d025dbSVijay Mahadevan 354*63d025dbSVijay Mahadevan Example Physical Element (HEX8) 355*63d025dbSVijay Mahadevan 356*63d025dbSVijay Mahadevan 8------7 357*63d025dbSVijay Mahadevan /| /| t s 358*63d025dbSVijay Mahadevan 5------6 | | / 359*63d025dbSVijay Mahadevan | | | | |/ 360*63d025dbSVijay Mahadevan | 4----|-3 0-------r 361*63d025dbSVijay Mahadevan |/ |/ 362*63d025dbSVijay Mahadevan 1------2 363*63d025dbSVijay Mahadevan 364*63d025dbSVijay Mahadevan Input Parameter: 365*63d025dbSVijay Mahadevan 366*63d025dbSVijay Mahadevan . PetscInt nverts, the number of element vertices 367*63d025dbSVijay Mahadevan . PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering) 368*63d025dbSVijay Mahadevan . PetscInt npts, the number of evaluation points (quadrature points) 369*63d025dbSVijay Mahadevan . PetscReal quad[3*npts], the evaluation points (quadrature points) in the reference space 370*63d025dbSVijay Mahadevan 371*63d025dbSVijay Mahadevan Output Parameter: 372*63d025dbSVijay Mahadevan . PetscReal phypts[3*npts], the evaluation points (quadrature points) transformed to the physical space 373*63d025dbSVijay Mahadevan . PetscReal jxw[npts], the jacobian determinant * quadrature weight necessary for assembling discrete contributions 374*63d025dbSVijay Mahadevan . PetscReal phi[npts], the bases evaluated at the specified quadrature points 375*63d025dbSVijay Mahadevan . PetscReal dphidx[npts], the derivative of the bases wrt X-direction evaluated at the specified quadrature points 376*63d025dbSVijay Mahadevan . PetscReal dphidy[npts], the derivative of the bases wrt Y-direction evaluated at the specified quadrature points 377*63d025dbSVijay Mahadevan . PetscReal dphidz[npts], the derivative of the bases wrt Z-direction evaluated at the specified quadrature points 378*63d025dbSVijay Mahadevan 379*63d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 3-D 380*63d025dbSVijay Mahadevan @*/ 381*63d025dbSVijay Mahadevan #undef __FUNCT__ 382*63d025dbSVijay Mahadevan #define __FUNCT__ "Compute_Lagrange_Basis_3D_Internal" 383*63d025dbSVijay Mahadevan PetscErrorCode Compute_Lagrange_Basis_3D_Internal ( const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts, 384*63d025dbSVijay Mahadevan PetscReal *jxw, PetscReal *phi, PetscReal *dphidx, PetscReal *dphidy, PetscReal *dphidz) 385*63d025dbSVijay Mahadevan { 386*63d025dbSVijay Mahadevan PetscReal volume; 387*63d025dbSVijay Mahadevan int i, j; 388*63d025dbSVijay Mahadevan PetscReal jacobian[9], ijacobian[9]; 389*63d025dbSVijay Mahadevan PetscErrorCode ierr; 390*63d025dbSVijay Mahadevan 391*63d025dbSVijay Mahadevan PetscFunctionBegin; 392*63d025dbSVijay Mahadevan /* Reset arrays. */ 393*63d025dbSVijay Mahadevan ierr = PetscMemzero(phi, npts * sizeof(PetscReal));CHKERRQ(ierr); 394*63d025dbSVijay Mahadevan ierr = PetscMemzero(phypts, npts * 3 * sizeof(PetscReal));CHKERRQ(ierr); 395*63d025dbSVijay Mahadevan if (dphidx) { 396*63d025dbSVijay Mahadevan ierr = PetscMemzero(dphidx, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr); 397*63d025dbSVijay Mahadevan ierr = PetscMemzero(dphidy, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr); 398*63d025dbSVijay Mahadevan ierr = PetscMemzero(dphidz, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr); 399*63d025dbSVijay Mahadevan } 400*63d025dbSVijay Mahadevan 401*63d025dbSVijay Mahadevan if (nverts == 8) { /* Linear Hexahedra */ 402*63d025dbSVijay Mahadevan 403*63d025dbSVijay Mahadevan for (j = 0; j < npts; j++) 404*63d025dbSVijay Mahadevan { 405*63d025dbSVijay Mahadevan const int offset = j * nverts; 406*63d025dbSVijay Mahadevan const double& r = quad[j * 3 + 0]; 407*63d025dbSVijay Mahadevan const double& s = quad[j * 3 + 1]; 408*63d025dbSVijay Mahadevan const double& t = quad[j * 3 + 2]; 409*63d025dbSVijay Mahadevan 410*63d025dbSVijay Mahadevan phi[offset + 0] = ( 1.0 - r ) * ( 1.0 - s ) * ( 1.0 - t ) / 8; 411*63d025dbSVijay Mahadevan phi[offset + 1] = ( 1.0 + r ) * ( 1.0 - s ) * ( 1.0 - t ) / 8; 412*63d025dbSVijay Mahadevan phi[offset + 2] = ( 1.0 + r ) * ( 1.0 + s ) * ( 1.0 - t ) / 8; 413*63d025dbSVijay Mahadevan phi[offset + 3] = ( 1.0 - r ) * ( 1.0 + s ) * ( 1.0 - t ) / 8; 414*63d025dbSVijay Mahadevan phi[offset + 4] = ( 1.0 - r ) * ( 1.0 - s ) * ( 1.0 + t ) / 8; 415*63d025dbSVijay Mahadevan phi[offset + 5] = ( 1.0 + r ) * ( 1.0 - s ) * ( 1.0 + t ) / 8; 416*63d025dbSVijay Mahadevan phi[offset + 6] = ( 1.0 + r ) * ( 1.0 + s ) * ( 1.0 + t ) / 8; 417*63d025dbSVijay Mahadevan phi[offset + 7] = ( 1.0 - r ) * ( 1.0 + s ) * ( 1.0 + t ) / 8; 418*63d025dbSVijay Mahadevan 419*63d025dbSVijay Mahadevan const double dNi_dxi[8] = { - ( 1.0 - s ) * ( 1.0 - t ), 420*63d025dbSVijay Mahadevan ( 1.0 - s ) * ( 1.0 - t ), 421*63d025dbSVijay Mahadevan ( 1.0 + s ) * ( 1.0 - t ), 422*63d025dbSVijay Mahadevan - ( 1.0 + s ) * ( 1.0 - t ), 423*63d025dbSVijay Mahadevan - ( 1.0 - s ) * ( 1.0 + t ), 424*63d025dbSVijay Mahadevan ( 1.0 - s ) * ( 1.0 + t ), 425*63d025dbSVijay Mahadevan ( 1.0 + s ) * ( 1.0 + t ), 426*63d025dbSVijay Mahadevan - ( 1.0 + s ) * ( 1.0 + t ) 427*63d025dbSVijay Mahadevan }; 428*63d025dbSVijay Mahadevan 429*63d025dbSVijay Mahadevan const double dNi_deta[8] = { - ( 1.0 - r ) * ( 1.0 - t ), 430*63d025dbSVijay Mahadevan - ( 1.0 + r ) * ( 1.0 - t ), 431*63d025dbSVijay Mahadevan ( 1.0 + r ) * ( 1.0 - t ), 432*63d025dbSVijay Mahadevan ( 1.0 - r ) * ( 1.0 - t ), 433*63d025dbSVijay Mahadevan - ( 1.0 - r ) * ( 1.0 + t ), 434*63d025dbSVijay Mahadevan - ( 1.0 + r ) * ( 1.0 + t ), 435*63d025dbSVijay Mahadevan ( 1.0 + r ) * ( 1.0 + t ), 436*63d025dbSVijay Mahadevan ( 1.0 - r ) * ( 1.0 + t ) 437*63d025dbSVijay Mahadevan }; 438*63d025dbSVijay Mahadevan 439*63d025dbSVijay Mahadevan const double dNi_dzeta[8] = { - ( 1.0 - r ) * ( 1.0 - s ), 440*63d025dbSVijay Mahadevan - ( 1.0 + r ) * ( 1.0 - s ), 441*63d025dbSVijay Mahadevan - ( 1.0 + r ) * ( 1.0 + s ), 442*63d025dbSVijay Mahadevan - ( 1.0 - r ) * ( 1.0 + s ), 443*63d025dbSVijay Mahadevan ( 1.0 - r ) * ( 1.0 - s ), 444*63d025dbSVijay Mahadevan ( 1.0 + r ) * ( 1.0 - s ), 445*63d025dbSVijay Mahadevan ( 1.0 + r ) * ( 1.0 + s ), 446*63d025dbSVijay Mahadevan ( 1.0 - r ) * ( 1.0 + s ) 447*63d025dbSVijay Mahadevan }; 448*63d025dbSVijay Mahadevan 449*63d025dbSVijay Mahadevan ierr = PetscMemzero(jacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr); 450*63d025dbSVijay Mahadevan ierr = PetscMemzero(ijacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr); 451*63d025dbSVijay Mahadevan double factor = 1.0 / 8; 452*63d025dbSVijay Mahadevan for (i = 0; i < nverts; ++i) { 453*63d025dbSVijay Mahadevan const PetscScalar* vertex = coords + i * 3; 454*63d025dbSVijay Mahadevan jacobian[0] += dNi_dxi[i] * vertex[0]; 455*63d025dbSVijay Mahadevan jacobian[3] += dNi_dxi[i] * vertex[1]; 456*63d025dbSVijay Mahadevan jacobian[6] += dNi_dxi[i] * vertex[2]; 457*63d025dbSVijay Mahadevan jacobian[1] += dNi_deta[i] * vertex[0]; 458*63d025dbSVijay Mahadevan jacobian[4] += dNi_deta[i] * vertex[1]; 459*63d025dbSVijay Mahadevan jacobian[7] += dNi_deta[i] * vertex[2]; 460*63d025dbSVijay Mahadevan jacobian[2] += dNi_dzeta[i] * vertex[0]; 461*63d025dbSVijay Mahadevan jacobian[5] += dNi_dzeta[i] * vertex[1]; 462*63d025dbSVijay Mahadevan jacobian[8] += dNi_dzeta[i] * vertex[2]; 463*63d025dbSVijay Mahadevan } 464*63d025dbSVijay Mahadevan 465*63d025dbSVijay Mahadevan /* invert the jacobian */ 466*63d025dbSVijay Mahadevan ierr = DMatrix_Invert_3x3_Internal(jacobian, ijacobian, &volume);CHKERRQ(ierr); 467*63d025dbSVijay Mahadevan 468*63d025dbSVijay Mahadevan jxw[j] *= factor * volume; 469*63d025dbSVijay Mahadevan 470*63d025dbSVijay Mahadevan /* Divide by element jacobian. */ 471*63d025dbSVijay Mahadevan for ( i = 0; i < nverts; ++i ) { 472*63d025dbSVijay Mahadevan const PetscScalar* vertex = coords + i * 3; 473*63d025dbSVijay Mahadevan for (int k = 0; k < 3; ++k) { 474*63d025dbSVijay Mahadevan phypts[3 * j + k] += phi[i + offset] * vertex[k]; 475*63d025dbSVijay Mahadevan if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[0 * 3 + k]; 476*63d025dbSVijay Mahadevan if (dphidy) dphidy[i + offset] += dNi_deta[i] * ijacobian[1 * 3 + k]; 477*63d025dbSVijay Mahadevan if (dphidz) dphidz[i + offset] += dNi_dzeta[i] * ijacobian[2 * 3 + k]; 478*63d025dbSVijay Mahadevan } 479*63d025dbSVijay Mahadevan } 480*63d025dbSVijay Mahadevan } 481*63d025dbSVijay Mahadevan } 482*63d025dbSVijay Mahadevan else if (nverts == 4) { /* Linear Tetrahedra */ 483*63d025dbSVijay Mahadevan 484*63d025dbSVijay Mahadevan ierr = PetscMemzero(jacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr); 485*63d025dbSVijay Mahadevan ierr = PetscMemzero(ijacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr); 486*63d025dbSVijay Mahadevan 487*63d025dbSVijay Mahadevan jacobian[0] = coords[1 * 3 + 0] - coords[0 * 3 + 0]; jacobian[1] = coords[2 * 3 + 0] - coords[0 * 3 + 0]; jacobian[2] = coords[3 * 3 + 0] - coords[0 * 3 + 0]; 488*63d025dbSVijay Mahadevan jacobian[3] = coords[1 * 3 + 1] - coords[0 * 3 + 1]; jacobian[4] = coords[2 * 3 + 1] - coords[0 * 3 + 1]; jacobian[5] = coords[3 * 3 + 1] - coords[0 * 3 + 1]; 489*63d025dbSVijay Mahadevan jacobian[6] = coords[1 * 3 + 2] - coords[0 * 3 + 2]; jacobian[7] = coords[2 * 3 + 2] - coords[0 * 3 + 2]; jacobian[8] = coords[3 * 3 + 2] - coords[0 * 3 + 2]; 490*63d025dbSVijay Mahadevan 491*63d025dbSVijay Mahadevan /* invert the jacobian */ 492*63d025dbSVijay Mahadevan ierr = DMatrix_Invert_3x3_Internal(jacobian, ijacobian, &volume);CHKERRQ(ierr); 493*63d025dbSVijay Mahadevan 494*63d025dbSVijay Mahadevan if ( volume < 1e-8 ) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Tetrahedral element has zero volume: %g. Degenerate element or invalid connectivity\n", volume); 495*63d025dbSVijay Mahadevan 496*63d025dbSVijay Mahadevan for ( j = 0; j < npts; j++ ) 497*63d025dbSVijay Mahadevan { 498*63d025dbSVijay Mahadevan const int offset = j * nverts; 499*63d025dbSVijay Mahadevan const double factor = 1.0 / 6; 500*63d025dbSVijay Mahadevan const double& r = quad[j * 3 + 0]; 501*63d025dbSVijay Mahadevan const double& s = quad[j * 3 + 1]; 502*63d025dbSVijay Mahadevan const double& t = quad[j * 3 + 2]; 503*63d025dbSVijay Mahadevan 504*63d025dbSVijay Mahadevan jxw[j] *= factor * volume; 505*63d025dbSVijay Mahadevan 506*63d025dbSVijay Mahadevan phi[offset + 0] = 1.0 - r - s - t; 507*63d025dbSVijay Mahadevan phi[offset + 1] = r; 508*63d025dbSVijay Mahadevan phi[offset + 2] = s; 509*63d025dbSVijay Mahadevan phi[offset + 3] = t; 510*63d025dbSVijay Mahadevan 511*63d025dbSVijay Mahadevan if (dphidx) { 512*63d025dbSVijay Mahadevan dphidx[0 + offset] = ( coords[1 + 2 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] ) 513*63d025dbSVijay Mahadevan - coords[1 + 1 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] ) 514*63d025dbSVijay Mahadevan - coords[1 + 3 * 3] * ( coords[2 + 1 * 3] - coords[2 + 2 * 3] ) 515*63d025dbSVijay Mahadevan ) / volume; 516*63d025dbSVijay Mahadevan dphidx[1 + offset] = -( coords[1 + 2 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] ) 517*63d025dbSVijay Mahadevan - coords[1 + 0 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] ) 518*63d025dbSVijay Mahadevan - coords[1 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 2 * 3] ) 519*63d025dbSVijay Mahadevan ) / volume; 520*63d025dbSVijay Mahadevan dphidx[2 + offset] = ( coords[1 + 1 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] ) 521*63d025dbSVijay Mahadevan - coords[1 + 0 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] ) 522*63d025dbSVijay Mahadevan - coords[1 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 1 * 3] ) 523*63d025dbSVijay Mahadevan ) / volume; 524*63d025dbSVijay Mahadevan dphidx[3 + offset] = -dphidx[0 + offset] - dphidx[1 + offset] - dphidx[2 + offset]; 525*63d025dbSVijay Mahadevan } 526*63d025dbSVijay Mahadevan 527*63d025dbSVijay Mahadevan if (dphidy) { 528*63d025dbSVijay Mahadevan dphidy[0 + offset] = ( coords[0 + 1 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] ) 529*63d025dbSVijay Mahadevan - coords[0 + 2 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] ) 530*63d025dbSVijay Mahadevan + coords[0 + 3 * 3] * ( coords[2 + 1 * 3] - coords[2 + 2 * 3] ) 531*63d025dbSVijay Mahadevan ) / volume; 532*63d025dbSVijay Mahadevan dphidy[1 + offset] = -( coords[0 + 0 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] ) 533*63d025dbSVijay Mahadevan - coords[0 + 2 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] ) 534*63d025dbSVijay Mahadevan + coords[0 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 2 * 3] ) 535*63d025dbSVijay Mahadevan ) / volume; 536*63d025dbSVijay Mahadevan dphidy[2 + offset] = ( coords[0 + 0 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] ) 537*63d025dbSVijay Mahadevan - coords[0 + 1 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] ) 538*63d025dbSVijay Mahadevan + coords[0 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 1 * 3] ) 539*63d025dbSVijay Mahadevan ) / volume; 540*63d025dbSVijay Mahadevan dphidy[3 + offset] = -dphidy[0 + offset] - dphidy[1 + offset] - dphidy[2 + offset]; 541*63d025dbSVijay Mahadevan } 542*63d025dbSVijay Mahadevan 543*63d025dbSVijay Mahadevan 544*63d025dbSVijay Mahadevan if (dphidz) { 545*63d025dbSVijay Mahadevan dphidz[0 + offset] = ( coords[0 + 1 * 3] * (coords[1 + 3 * 3] - coords[1 + 2 * 3]) 546*63d025dbSVijay Mahadevan - coords[0 + 2 * 3] * (coords[1 + 3 * 3] - coords[1 + 1 * 3]) 547*63d025dbSVijay Mahadevan + coords[0 + 3 * 3] * (coords[1 + 2 * 3] - coords[1 + 1 * 3]) 548*63d025dbSVijay Mahadevan ) / volume; 549*63d025dbSVijay Mahadevan dphidz[1 + offset] = -( coords[0 + 0 * 3] * (coords[1 + 3 * 3] - coords[1 + 2 * 3]) 550*63d025dbSVijay Mahadevan + coords[0 + 2 * 3] * (coords[1 + 0 * 3] - coords[1 + 3 * 3]) 551*63d025dbSVijay Mahadevan - coords[0 + 3 * 3] * (coords[1 + 0 * 3] - coords[1 + 2 * 3]) 552*63d025dbSVijay Mahadevan ) / volume; 553*63d025dbSVijay Mahadevan dphidz[2 + offset] = ( coords[0 + 0 * 3] * (coords[1 + 3 * 3] - coords[1 + 1 * 3]) 554*63d025dbSVijay Mahadevan + coords[0 + 1 * 3] * (coords[1 + 0 * 3] - coords[1 + 3 * 3]) 555*63d025dbSVijay Mahadevan - coords[0 + 3 * 3] * (coords[1 + 0 * 3] - coords[1 + 1 * 3]) 556*63d025dbSVijay Mahadevan ) / volume; 557*63d025dbSVijay Mahadevan dphidz[3 + offset] = -dphidz[0 + offset] - dphidz[1 + offset] - dphidz[2 + offset]; 558*63d025dbSVijay Mahadevan } 559*63d025dbSVijay Mahadevan 560*63d025dbSVijay Mahadevan for (i = 0; i < nverts; ++i) { 561*63d025dbSVijay Mahadevan const PetscScalar* vertices = coords + i * 3; 562*63d025dbSVijay Mahadevan for (int k = 0; k < 3; ++k) 563*63d025dbSVijay Mahadevan phypts[3 * j + k] += phi[i + offset] * vertices[k]; 564*63d025dbSVijay Mahadevan } 565*63d025dbSVijay Mahadevan } /* Tetrahedra -- ends */ 566*63d025dbSVijay Mahadevan } 567*63d025dbSVijay Mahadevan else 568*63d025dbSVijay Mahadevan { 569*63d025dbSVijay Mahadevan SETERRQ1(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 : %D", nverts); 570*63d025dbSVijay Mahadevan } 571*63d025dbSVijay Mahadevan #if 0 572*63d025dbSVijay Mahadevan /* verify if the computed basis functions are consistent */ 573*63d025dbSVijay Mahadevan for ( j = 0; j < npts; j++ ) { 574*63d025dbSVijay Mahadevan PetscScalar phisum = 0, dphixsum = 0, dphiysum = 0, dphizsum = 0; 575*63d025dbSVijay Mahadevan const int offset = j * nverts; 576*63d025dbSVijay Mahadevan for ( i = 0; i < nverts; i++ ) { 577*63d025dbSVijay Mahadevan phisum += phi[i + offset]; 578*63d025dbSVijay Mahadevan if (dphidx) dphixsum += dphidx[i + offset]; 579*63d025dbSVijay Mahadevan if (dphidy) dphiysum += dphidy[i + offset]; 580*63d025dbSVijay Mahadevan if (dphidz) dphizsum += dphidz[i + offset]; 581*63d025dbSVijay Mahadevan if (dphidx) PetscPrintf(PETSC_COMM_WORLD, "\t Values [%d]: [JxW] [phi, dphidx, dphidy, dphidz] = %g, %g, %g, %g, %g\n", j, jxw[j], phi[i + offset], dphidx[i + offset], dphidy[i + offset], dphidz[i + offset]); 582*63d025dbSVijay Mahadevan } 583*63d025dbSVijay Mahadevan if (dphidx) PetscPrintf(PETSC_COMM_WORLD, "Sum of basis at quadrature point %D (%g, %g, %g) = %g, %g, %g, %g\n", j, quad[3 * j + 0], quad[3 * j + 1], quad[3 * j + 2], phisum, dphixsum, dphiysum, dphizsum); 584*63d025dbSVijay Mahadevan } 585*63d025dbSVijay Mahadevan #endif 586*63d025dbSVijay Mahadevan PetscFunctionReturn(0); 587*63d025dbSVijay Mahadevan } 588*63d025dbSVijay Mahadevan 589*63d025dbSVijay Mahadevan 590*63d025dbSVijay Mahadevan 591*63d025dbSVijay Mahadevan /*@ 592*63d025dbSVijay Mahadevan DMMoabFEMComputeBasis: Evaluate bases and derivatives at quadrature points for a linear EDGE/QUAD/TRI/HEX/TET element. 593*63d025dbSVijay Mahadevan 594*63d025dbSVijay Mahadevan The routine takes the coordinates of the vertices of an element and computes basis functions associated with 595*63d025dbSVijay Mahadevan each quadrature point provided, and their derivatives with respect to X, Y and Z as appropriate. 596*63d025dbSVijay Mahadevan 597*63d025dbSVijay Mahadevan Input Parameter: 598*63d025dbSVijay Mahadevan 599*63d025dbSVijay Mahadevan . PetscInt nverts, the number of element vertices 600*63d025dbSVijay Mahadevan . PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering) 601*63d025dbSVijay Mahadevan . PetscInt npts, the number of evaluation points (quadrature points) 602*63d025dbSVijay Mahadevan . PetscReal quad[3*npts], the evaluation points (quadrature points) in the reference space 603*63d025dbSVijay Mahadevan 604*63d025dbSVijay Mahadevan Output Parameter: 605*63d025dbSVijay Mahadevan . PetscReal phypts[3*npts], the evaluation points (quadrature points) transformed to the physical space 606*63d025dbSVijay Mahadevan . PetscReal jxw[npts], the jacobian determinant * quadrature weight necessary for assembling discrete contributions 607*63d025dbSVijay Mahadevan . PetscReal fe_basis[npts], the bases values evaluated at the specified quadrature points 608*63d025dbSVijay Mahadevan . 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 609*63d025dbSVijay Mahadevan 610*63d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 3-D 611*63d025dbSVijay Mahadevan @*/ 612*63d025dbSVijay Mahadevan #undef __FUNCT__ 613*63d025dbSVijay Mahadevan #define __FUNCT__ "DMMoabFEMComputeBasis" 614*63d025dbSVijay Mahadevan PetscErrorCode DMMoabFEMComputeBasis ( PetscInt dim, PetscInt nverts, PetscReal *coordinates, PetscQuadrature quadrature, PetscReal *phypts, 615*63d025dbSVijay Mahadevan PetscReal *jacobian_quadrature_weight_product, PetscReal *fe_basis, PetscReal **fe_basis_derivatives) 616*63d025dbSVijay Mahadevan { 617*63d025dbSVijay Mahadevan PetscErrorCode ierr; 618*63d025dbSVijay Mahadevan PetscInt npoints; 619*63d025dbSVijay Mahadevan bool compute_der; 620*63d025dbSVijay Mahadevan const PetscReal *quadpts, *quadwts; 621*63d025dbSVijay Mahadevan 622*63d025dbSVijay Mahadevan PetscFunctionBegin; 623*63d025dbSVijay Mahadevan PetscValidPointer(coordinates, 3); 624*63d025dbSVijay Mahadevan PetscValidHeaderSpecific(quadrature, PETSC_OBJECT_CLASSID, 4); 625*63d025dbSVijay Mahadevan PetscValidPointer(phypts, 5); 626*63d025dbSVijay Mahadevan PetscValidPointer(jacobian_quadrature_weight_product, 6); 627*63d025dbSVijay Mahadevan PetscValidPointer(fe_basis, 7); 628*63d025dbSVijay Mahadevan compute_der = (fe_basis_derivatives != NULL); 629*63d025dbSVijay Mahadevan 630*63d025dbSVijay Mahadevan /* Get the quadrature points and weights for the given quadrature rule */ 631*63d025dbSVijay Mahadevan ierr = PetscQuadratureGetData(quadrature, NULL, &npoints, &quadpts, &quadwts);CHKERRQ(ierr); 632*63d025dbSVijay Mahadevan ierr = PetscMemcpy(jacobian_quadrature_weight_product, quadwts, npoints * sizeof(PetscReal));CHKERRQ(ierr); 633*63d025dbSVijay Mahadevan 634*63d025dbSVijay Mahadevan switch (dim) { 635*63d025dbSVijay Mahadevan case 1: 636*63d025dbSVijay Mahadevan ierr = Compute_Lagrange_Basis_1D_Internal(nverts, coordinates, npoints, quadpts, phypts, 637*63d025dbSVijay Mahadevan jacobian_quadrature_weight_product, fe_basis, 638*63d025dbSVijay Mahadevan (compute_der ? fe_basis_derivatives[0] : NULL));CHKERRQ(ierr); 639*63d025dbSVijay Mahadevan break; 640*63d025dbSVijay Mahadevan case 2: 641*63d025dbSVijay Mahadevan ierr = Compute_Lagrange_Basis_2D_Internal(nverts, coordinates, npoints, quadpts, phypts, 642*63d025dbSVijay Mahadevan jacobian_quadrature_weight_product, fe_basis, 643*63d025dbSVijay Mahadevan (compute_der ? fe_basis_derivatives[0] : NULL), 644*63d025dbSVijay Mahadevan (compute_der ? fe_basis_derivatives[1] : NULL));CHKERRQ(ierr); 645*63d025dbSVijay Mahadevan break; 646*63d025dbSVijay Mahadevan case 3: 647*63d025dbSVijay Mahadevan ierr = Compute_Lagrange_Basis_3D_Internal(nverts, coordinates, npoints, quadpts, phypts, 648*63d025dbSVijay Mahadevan jacobian_quadrature_weight_product, fe_basis, 649*63d025dbSVijay Mahadevan (compute_der ? fe_basis_derivatives[0] : NULL), 650*63d025dbSVijay Mahadevan (compute_der ? fe_basis_derivatives[1] : NULL), 651*63d025dbSVijay Mahadevan (compute_der ? fe_basis_derivatives[2] : NULL));CHKERRQ(ierr); 652*63d025dbSVijay Mahadevan break; 653*63d025dbSVijay Mahadevan default: 654*63d025dbSVijay Mahadevan SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %D", dim); 655*63d025dbSVijay Mahadevan } 656*63d025dbSVijay Mahadevan PetscFunctionReturn(0); 657*63d025dbSVijay Mahadevan } 658*63d025dbSVijay Mahadevan 659*63d025dbSVijay Mahadevan 660*63d025dbSVijay Mahadevan 661*63d025dbSVijay Mahadevan /*@ 662*63d025dbSVijay Mahadevan DMMoabFEMCreateQuadratureDefault: Create default quadrature rules for integration over an element with a given 663*63d025dbSVijay Mahadevan dimension and polynomial order (deciphered from number of element vertices). 664*63d025dbSVijay Mahadevan 665*63d025dbSVijay Mahadevan Input Parameter: 666*63d025dbSVijay Mahadevan 667*63d025dbSVijay Mahadevan . PetscInt dim, the element dimension (1=EDGE, 2=QUAD/TRI, 3=HEX/TET) 668*63d025dbSVijay Mahadevan . PetscInt nverts, the number of vertices in the physical element 669*63d025dbSVijay Mahadevan 670*63d025dbSVijay Mahadevan Output Parameter: 671*63d025dbSVijay Mahadevan . PetscQuadrature quadrature, the quadrature object with default settings to integrate polynomials defined over the element 672*63d025dbSVijay Mahadevan 673*63d025dbSVijay Mahadevan .keywords: DMMoab, Quadrature, PetscDT 674*63d025dbSVijay Mahadevan @*/ 675*63d025dbSVijay Mahadevan #undef __FUNCT__ 676*63d025dbSVijay Mahadevan #define __FUNCT__ "DMMoabFEMCreateQuadratureDefault" 677*63d025dbSVijay Mahadevan PetscErrorCode DMMoabFEMCreateQuadratureDefault ( PetscInt dim, PetscInt nverts, PetscQuadrature *quadrature ) 678*63d025dbSVijay Mahadevan { 679*63d025dbSVijay Mahadevan PetscReal *w, *x; 680*63d025dbSVijay Mahadevan PetscErrorCode ierr; 681*63d025dbSVijay Mahadevan 682*63d025dbSVijay Mahadevan PetscFunctionBegin; 683*63d025dbSVijay Mahadevan /* Create an appropriate quadrature rule to sample basis */ 684*63d025dbSVijay Mahadevan switch (dim) 685*63d025dbSVijay Mahadevan { 686*63d025dbSVijay Mahadevan case 1: 687*63d025dbSVijay Mahadevan /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */ 688*63d025dbSVijay Mahadevan ierr = PetscDTGaussJacobiQuadrature(1, nverts, -1.0, 1.0, quadrature);CHKERRQ(ierr); 689*63d025dbSVijay Mahadevan break; 690*63d025dbSVijay Mahadevan case 2: 691*63d025dbSVijay Mahadevan /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */ 692*63d025dbSVijay Mahadevan if (nverts == 3) { 693*63d025dbSVijay Mahadevan const int order = 2; 694*63d025dbSVijay Mahadevan const int npoints = (order == 2 ? 3 : 6); 695*63d025dbSVijay Mahadevan ierr = PetscMalloc2(npoints * 2, &x, npoints, &w);CHKERRQ(ierr); 696*63d025dbSVijay Mahadevan switch (npoints) { 697*63d025dbSVijay Mahadevan case 3: 698*63d025dbSVijay Mahadevan x[0] = x[1] = x[2] = x[5] = 1.0 / 6.0; 699*63d025dbSVijay Mahadevan x[3] = x[4] = 2.0 / 3.0; 700*63d025dbSVijay Mahadevan w[0] = w[1] = w[2] = 1.0 / 3.0; 701*63d025dbSVijay Mahadevan break; 702*63d025dbSVijay Mahadevan case 6: 703*63d025dbSVijay Mahadevan x[0] = x[1] = x[2] = 0.44594849091597; 704*63d025dbSVijay Mahadevan x[3] = x[4] = 0.10810301816807; 705*63d025dbSVijay Mahadevan x[5] = 0.44594849091597; 706*63d025dbSVijay Mahadevan x[6] = x[7] = x[8] = 0.09157621350977; 707*63d025dbSVijay Mahadevan x[9] = x[10] = 0.81684757298046; 708*63d025dbSVijay Mahadevan x[11] = 0.09157621350977; 709*63d025dbSVijay Mahadevan w[0] = w[1] = w[2] = 0.22338158967801; 710*63d025dbSVijay Mahadevan w[0] = w[1] = w[2] = 0.10995174365532; 711*63d025dbSVijay Mahadevan break; 712*63d025dbSVijay Mahadevan } 713*63d025dbSVijay Mahadevan ierr = PetscQuadratureCreate(PETSC_COMM_SELF, quadrature);CHKERRQ(ierr); 714*63d025dbSVijay Mahadevan ierr = PetscQuadratureSetOrder(*quadrature, order);CHKERRQ(ierr); 715*63d025dbSVijay Mahadevan ierr = PetscQuadratureSetData(*quadrature, 2, npoints, x, w);CHKERRQ(ierr); 716*63d025dbSVijay Mahadevan //ierr = PetscDTGaussJacobiQuadrature(dim, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr); 717*63d025dbSVijay Mahadevan } 718*63d025dbSVijay Mahadevan else { 719*63d025dbSVijay Mahadevan ierr = PetscDTGaussTensorQuadrature(dim, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr); 720*63d025dbSVijay Mahadevan } 721*63d025dbSVijay Mahadevan break; 722*63d025dbSVijay Mahadevan case 3: 723*63d025dbSVijay Mahadevan /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */ 724*63d025dbSVijay Mahadevan if (nverts == 4) { 725*63d025dbSVijay Mahadevan ierr = PetscDTGaussJacobiQuadrature(dim, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr); 726*63d025dbSVijay Mahadevan } 727*63d025dbSVijay Mahadevan else { 728*63d025dbSVijay Mahadevan ierr = PetscDTGaussTensorQuadrature(dim, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr); 729*63d025dbSVijay Mahadevan } 730*63d025dbSVijay Mahadevan break; 731*63d025dbSVijay Mahadevan default: 732*63d025dbSVijay Mahadevan SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %D", dim); 733*63d025dbSVijay Mahadevan } 734*63d025dbSVijay Mahadevan PetscFunctionReturn(0); 735*63d025dbSVijay Mahadevan } 736*63d025dbSVijay Mahadevan 737