xref: /petsc/src/dm/impls/moab/dmmbfem.cxx (revision 181f196bb05221f9cb8a491d0f5b553e3598268c)
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 */
763d025dbSVijay Mahadevan static inline PetscReal DMatrix_Determinant_2x2_Internal ( const PetscReal inmat[2 * 2] )
863d025dbSVijay Mahadevan {
963d025dbSVijay Mahadevan   return  inmat[0] * inmat[3] - inmat[1] * inmat[2];
1063d025dbSVijay Mahadevan }
1163d025dbSVijay Mahadevan 
12*181f196bSVijay Mahadevan #undef __FUNCT__
13*181f196bSVijay Mahadevan #define __FUNCT__ "DMatrix_Invert_2x2_Internal"
1463d025dbSVijay Mahadevan static inline PetscErrorCode DMatrix_Invert_2x2_Internal (const PetscReal *inmat, PetscReal *outmat, PetscReal *determinant)
1563d025dbSVijay Mahadevan {
1663d025dbSVijay Mahadevan   if (!inmat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_POINTER, "Invalid input matrix specified for 2x2 inversion.");
1763d025dbSVijay Mahadevan   PetscReal det = DMatrix_Determinant_2x2_Internal(inmat);
1863d025dbSVijay Mahadevan   if (outmat) {
1963d025dbSVijay Mahadevan     outmat[0] = inmat[3] / det;
2063d025dbSVijay Mahadevan     outmat[1] = -inmat[1] / det;
2163d025dbSVijay Mahadevan     outmat[2] = -inmat[2] / det;
2263d025dbSVijay Mahadevan     outmat[3] = inmat[0] / det;
2363d025dbSVijay Mahadevan   }
2463d025dbSVijay Mahadevan   if (determinant) *determinant = det;
2563d025dbSVijay Mahadevan   PetscFunctionReturn(0);
2663d025dbSVijay Mahadevan }
2763d025dbSVijay Mahadevan 
28*181f196bSVijay Mahadevan static inline PetscReal DMatrix_Determinant_3x3_Internal ( const PetscReal inmat[3 * 3] )
2963d025dbSVijay Mahadevan {
3063d025dbSVijay Mahadevan   return   inmat[0] * (inmat[8] * inmat[4] - inmat[7] * inmat[5])
3163d025dbSVijay Mahadevan            - inmat[3] * (inmat[8] * inmat[1] - inmat[7] * inmat[2])
3263d025dbSVijay Mahadevan            + inmat[6] * (inmat[5] * inmat[1] - inmat[4] * inmat[2]);
3363d025dbSVijay Mahadevan }
3463d025dbSVijay Mahadevan 
35*181f196bSVijay Mahadevan #undef __FUNCT__
36*181f196bSVijay Mahadevan #define __FUNCT__ "DMatrix_Invert_3x3_Internal"
3763d025dbSVijay Mahadevan static inline PetscErrorCode DMatrix_Invert_3x3_Internal (const PetscReal *inmat, PetscReal *outmat, PetscScalar *determinant)
3863d025dbSVijay Mahadevan {
3963d025dbSVijay Mahadevan   if (!inmat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_POINTER, "Invalid input matrix specified for 3x3 inversion.");
40*181f196bSVijay Mahadevan   PetscReal det = DMatrix_Determinant_3x3_Internal(inmat);
4163d025dbSVijay Mahadevan   if (outmat) {
4263d025dbSVijay Mahadevan     outmat[0] = (inmat[8] * inmat[4] - inmat[7] * inmat[5]) / det;
4363d025dbSVijay Mahadevan     outmat[1] = -(inmat[8] * inmat[1] - inmat[7] * inmat[2]) / det;
4463d025dbSVijay Mahadevan     outmat[2] = (inmat[5] * inmat[1] - inmat[4] * inmat[2]) / det;
4563d025dbSVijay Mahadevan     outmat[3] = -(inmat[8] * inmat[3] - inmat[6] * inmat[5]) / det;
4663d025dbSVijay Mahadevan     outmat[4] = (inmat[8] * inmat[0] - inmat[6] * inmat[2]) / det;
4763d025dbSVijay Mahadevan     outmat[5] = -(inmat[5] * inmat[0] - inmat[3] * inmat[2]) / det;
4863d025dbSVijay Mahadevan     outmat[6] = (inmat[7] * inmat[3] - inmat[6] * inmat[4]) / det;
4963d025dbSVijay Mahadevan     outmat[7] = -(inmat[7] * inmat[0] - inmat[6] * inmat[1]) / det;
5063d025dbSVijay Mahadevan     outmat[8] = (inmat[4] * inmat[0] - inmat[3] * inmat[1]) / det;
5163d025dbSVijay Mahadevan   }
5263d025dbSVijay Mahadevan   if (determinant) *determinant = det;
5363d025dbSVijay Mahadevan   PetscFunctionReturn(0);
5463d025dbSVijay Mahadevan }
5563d025dbSVijay Mahadevan 
56*181f196bSVijay Mahadevan inline PetscReal DMatrix_Determinant_4x4_Internal ( PetscReal inmat[4 * 4] )
57*181f196bSVijay Mahadevan {
58*181f196bSVijay Mahadevan   return
59*181f196bSVijay Mahadevan     inmat[0 + 0 * 4] * (
60*181f196bSVijay Mahadevan       inmat[1 + 1 * 4] * ( inmat[2 + 2 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 2 * 4] )
61*181f196bSVijay Mahadevan       - inmat[1 + 2 * 4] * ( inmat[2 + 1 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 1 * 4] )
62*181f196bSVijay Mahadevan       + inmat[1 + 3 * 4] * ( inmat[2 + 1 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 1 * 4] ) )
63*181f196bSVijay Mahadevan     - inmat[0 + 1 * 4] * (
64*181f196bSVijay Mahadevan       inmat[1 + 0 * 4] * ( inmat[2 + 2 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 2 * 4] )
65*181f196bSVijay Mahadevan       - inmat[1 + 2 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 0 * 4] )
66*181f196bSVijay Mahadevan       + inmat[1 + 3 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 0 * 4] ) )
67*181f196bSVijay Mahadevan     + inmat[0 + 2 * 4] * (
68*181f196bSVijay Mahadevan       inmat[1 + 0 * 4] * ( inmat[2 + 1 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 1 * 4] )
69*181f196bSVijay Mahadevan       - inmat[1 + 1 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 0 * 4] )
70*181f196bSVijay Mahadevan       + inmat[1 + 3 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 1 * 4] - inmat[2 + 1 * 4] * inmat[3 + 0 * 4] ) )
71*181f196bSVijay Mahadevan     - inmat[0 + 3 * 4] * (
72*181f196bSVijay Mahadevan       inmat[1 + 0 * 4] * ( inmat[2 + 1 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 1 * 4] )
73*181f196bSVijay Mahadevan       - inmat[1 + 1 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 0 * 4] )
74*181f196bSVijay Mahadevan       + inmat[1 + 2 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 1 * 4] - inmat[2 + 1 * 4] * inmat[3 + 0 * 4] ) );
75*181f196bSVijay Mahadevan }
76*181f196bSVijay Mahadevan 
77*181f196bSVijay Mahadevan #undef __FUNCT__
78*181f196bSVijay Mahadevan #define __FUNCT__ "DMatrix_Invert_4x4_Internal"
79*181f196bSVijay Mahadevan inline PetscErrorCode DMatrix_Invert_4x4_Internal (PetscReal *inmat, PetscReal *outmat, PetscScalar *determinant)
80*181f196bSVijay Mahadevan {
81*181f196bSVijay Mahadevan   if (!inmat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_POINTER, "Invalid input matrix specified for 4x4 inversion.");
82*181f196bSVijay Mahadevan   PetscReal det = DMatrix_Determinant_4x4_Internal(inmat);
83*181f196bSVijay Mahadevan   if (outmat) {
84*181f196bSVijay 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;
85*181f196bSVijay 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;
86*181f196bSVijay 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;
87*181f196bSVijay 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;
88*181f196bSVijay 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;
89*181f196bSVijay 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;
90*181f196bSVijay 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;
91*181f196bSVijay 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;
92*181f196bSVijay 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;
93*181f196bSVijay 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;
94*181f196bSVijay 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;
95*181f196bSVijay 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;
96*181f196bSVijay 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;
97*181f196bSVijay 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;
98*181f196bSVijay 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;
99*181f196bSVijay 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;
100*181f196bSVijay Mahadevan   }
101*181f196bSVijay Mahadevan   if (determinant) *determinant = det;
102*181f196bSVijay Mahadevan   PetscFunctionReturn(0);
103*181f196bSVijay Mahadevan }
104*181f196bSVijay Mahadevan 
10563d025dbSVijay Mahadevan 
10663d025dbSVijay Mahadevan /*@
10763d025dbSVijay Mahadevan   Compute_Lagrange_Basis_1D_Internal: Evaluate bases and derivatives at quadrature points for a EDGE2 or EDGE3 element.
10863d025dbSVijay Mahadevan 
10963d025dbSVijay Mahadevan   The routine is given the coordinates of the vertices of a linear or quadratic edge element.
11063d025dbSVijay Mahadevan 
11163d025dbSVijay Mahadevan   The routine evaluates the basis functions associated with each quadrature point provided,
11263d025dbSVijay Mahadevan   and their derivatives with respect to X.
11363d025dbSVijay Mahadevan 
11463d025dbSVijay Mahadevan   Notes:
11563d025dbSVijay Mahadevan 
11663d025dbSVijay Mahadevan   Example Physical Element
11763d025dbSVijay Mahadevan 
11863d025dbSVijay Mahadevan     1-------2        1----3----2
11963d025dbSVijay Mahadevan       EDGE2             EDGE3
12063d025dbSVijay Mahadevan 
12163d025dbSVijay Mahadevan   Input Parameter:
12263d025dbSVijay Mahadevan 
12363d025dbSVijay Mahadevan .  PetscInt  nverts,           the number of element vertices
12463d025dbSVijay Mahadevan .  PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering)
12563d025dbSVijay Mahadevan .  PetscInt  npts,             the number of evaluation points (quadrature points)
12663d025dbSVijay Mahadevan .  PetscReal quad[3*npts],     the evaluation points (quadrature points) in the reference space
12763d025dbSVijay Mahadevan 
12863d025dbSVijay Mahadevan   Output Parameter:
12963d025dbSVijay Mahadevan .  PetscReal phypts[3*npts],   the evaluation points (quadrature points) transformed to the physical space
13063d025dbSVijay Mahadevan .  PetscReal jxw[npts],        the jacobian determinant * quadrature weight necessary for assembling discrete contributions
13163d025dbSVijay Mahadevan .  PetscReal phi[npts],        the bases evaluated at the specified quadrature points
13263d025dbSVijay Mahadevan .  PetscReal dphidx[npts],     the derivative of the bases wrt X-direction evaluated at the specified quadrature points
13363d025dbSVijay Mahadevan 
13463d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 1-D
13563d025dbSVijay Mahadevan @*/
13663d025dbSVijay Mahadevan #undef __FUNCT__
13763d025dbSVijay Mahadevan #define __FUNCT__ "Compute_Lagrange_Basis_1D_Internal"
13863d025dbSVijay Mahadevan PetscErrorCode Compute_Lagrange_Basis_1D_Internal ( const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts,
139*181f196bSVijay Mahadevan     PetscReal *jxw, PetscReal *phi, PetscReal *dphidx,
140*181f196bSVijay Mahadevan     PetscReal *jacobian, PetscReal *ijacobian, PetscReal *volume)
14163d025dbSVijay Mahadevan {
14263d025dbSVijay Mahadevan   int i, j;
14363d025dbSVijay Mahadevan   PetscErrorCode  ierr;
14463d025dbSVijay Mahadevan 
145*181f196bSVijay Mahadevan   PetscFunctionBegin;
146*181f196bSVijay Mahadevan   PetscValidPointer(jacobian, 9);
147*181f196bSVijay Mahadevan   PetscValidPointer(ijacobian, 10);
148*181f196bSVijay Mahadevan   PetscValidPointer(volume, 11);
149*181f196bSVijay Mahadevan   if (phypts) {
15063d025dbSVijay Mahadevan     ierr = PetscMemzero(phypts, npts * 3 * sizeof(PetscReal));CHKERRQ(ierr);
151*181f196bSVijay Mahadevan   }
15263d025dbSVijay Mahadevan   if (dphidx) { /* Reset arrays. */
15363d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidx, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
15463d025dbSVijay Mahadevan   }
15563d025dbSVijay Mahadevan   if (nverts == 2) { /* Linear Edge */
15663d025dbSVijay Mahadevan 
15763d025dbSVijay Mahadevan     for (j = 0; j < npts; j++)
15863d025dbSVijay Mahadevan     {
15963d025dbSVijay Mahadevan       const int offset = j * nverts;
160*181f196bSVijay Mahadevan       const PetscReal r = quad[j];
16163d025dbSVijay Mahadevan 
162*181f196bSVijay Mahadevan       phi[0 + offset] = ( 1.0 - r );
163*181f196bSVijay Mahadevan       phi[1 + offset] = (       r );
16463d025dbSVijay Mahadevan 
165*181f196bSVijay Mahadevan       const PetscReal dNi_dxi[2]  = { -1.0, 1.0 };
16663d025dbSVijay Mahadevan 
167*181f196bSVijay Mahadevan       jacobian[0] = ijacobian[0] = volume[0] = 0.0;
16863d025dbSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
169*181f196bSVijay Mahadevan         const PetscReal* vertices = coords + i * 3;
170*181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i] * vertices[0];
171*181f196bSVijay Mahadevan         if (phypts) {
172*181f196bSVijay Mahadevan           phypts[3 * j + 0] += phi[i + offset] * vertices[0];
173*181f196bSVijay Mahadevan         }
17463d025dbSVijay Mahadevan       }
17563d025dbSVijay Mahadevan 
17663d025dbSVijay Mahadevan       /* invert the jacobian */
177*181f196bSVijay Mahadevan       *volume = jacobian[0];
178*181f196bSVijay Mahadevan       ijacobian[0] = 1.0 / jacobian[0];
179*181f196bSVijay Mahadevan       jxw[j] *= *volume;
18063d025dbSVijay Mahadevan 
18163d025dbSVijay Mahadevan       /*  Divide by element jacobian. */
18263d025dbSVijay Mahadevan       for ( i = 0; i < nverts; i++ ) {
183*181f196bSVijay Mahadevan         if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[0];
18463d025dbSVijay Mahadevan       }
18563d025dbSVijay Mahadevan 
18663d025dbSVijay Mahadevan     }
18763d025dbSVijay Mahadevan   }
18863d025dbSVijay Mahadevan   else if (nverts == 3) { /* Quadratic Edge */
18963d025dbSVijay Mahadevan 
19063d025dbSVijay Mahadevan     for (j = 0; j < npts; j++)
19163d025dbSVijay Mahadevan     {
19263d025dbSVijay Mahadevan       const int offset = j * nverts;
193*181f196bSVijay Mahadevan       const PetscReal r = quad[j];
19463d025dbSVijay Mahadevan 
195*181f196bSVijay Mahadevan       phi[0 + offset] = 1.0 + r * ( 2.0 * r - 3.0 );
196*181f196bSVijay Mahadevan       phi[1 + offset] = 4.0 * r * ( 1.0 - r );
197*181f196bSVijay Mahadevan       phi[2 + offset] = r * ( 2.0 * r - 1.0 );
19863d025dbSVijay Mahadevan 
199*181f196bSVijay Mahadevan       const PetscReal dNi_dxi[3]  = { 4 * r - 3.0, 4 * ( 1.0 - 2.0 * r ), 4.0 * r - 1.0};
20063d025dbSVijay Mahadevan 
201*181f196bSVijay Mahadevan       jacobian[0] = ijacobian[0] = volume[0] = 0.0;
20263d025dbSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
203*181f196bSVijay Mahadevan         const PetscReal* vertices = coords + i * 3;
204*181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i] * vertices[0];
205*181f196bSVijay Mahadevan         if (phypts) {
206*181f196bSVijay Mahadevan           phypts[3 * j + 0] += phi[i + offset] * vertices[0];
207*181f196bSVijay Mahadevan         }
20863d025dbSVijay Mahadevan       }
20963d025dbSVijay Mahadevan 
21063d025dbSVijay Mahadevan       /* invert the jacobian */
211*181f196bSVijay Mahadevan       *volume = jacobian[0];
212*181f196bSVijay Mahadevan       ijacobian[0] = 1.0 / jacobian[0];
213*181f196bSVijay Mahadevan       if (jxw) jxw[j] *= *volume;
21463d025dbSVijay Mahadevan 
21563d025dbSVijay Mahadevan       /*  Divide by element jacobian. */
21663d025dbSVijay Mahadevan       for ( i = 0; i < nverts; i++ ) {
217*181f196bSVijay Mahadevan         if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[0];
21863d025dbSVijay Mahadevan       }
21963d025dbSVijay Mahadevan     }
22063d025dbSVijay Mahadevan   }
22163d025dbSVijay Mahadevan   else {
22263d025dbSVijay 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);
22363d025dbSVijay Mahadevan   }
22463d025dbSVijay Mahadevan #if 0
22563d025dbSVijay Mahadevan   /* verify if the computed basis functions are consistent */
22663d025dbSVijay Mahadevan   for ( j = 0; j < npts; j++ ) {
22763d025dbSVijay Mahadevan     PetscScalar phisum = 0, dphixsum = 0;
22863d025dbSVijay Mahadevan     for ( i = 0; i < nverts; i++ ) {
22963d025dbSVijay Mahadevan       phisum += phi[i + j * nverts];
23063d025dbSVijay Mahadevan       if (dphidx) dphixsum += dphidx[i + j * nverts];
23163d025dbSVijay Mahadevan     }
23263d025dbSVijay Mahadevan     PetscPrintf(PETSC_COMM_WORLD, "Sum of basis at quadrature point %D = %g, %g, %g\n", j, phisum, dphixsum);
23363d025dbSVijay Mahadevan   }
23463d025dbSVijay Mahadevan #endif
23563d025dbSVijay Mahadevan   PetscFunctionReturn(0);
23663d025dbSVijay Mahadevan }
23763d025dbSVijay Mahadevan 
23863d025dbSVijay Mahadevan 
23963d025dbSVijay Mahadevan /*@
24063d025dbSVijay Mahadevan   Compute_Lagrange_Basis_2D_Internal: Evaluate bases and derivatives at quadrature points for a QUAD4 or TRI3 element.
24163d025dbSVijay Mahadevan 
24263d025dbSVijay Mahadevan   The routine is given the coordinates of the vertices of a quadrangle or triangle.
24363d025dbSVijay Mahadevan 
24463d025dbSVijay Mahadevan   The routine evaluates the basis functions associated with each quadrature point provided,
24563d025dbSVijay Mahadevan   and their derivatives with respect to X and Y.
24663d025dbSVijay Mahadevan 
24763d025dbSVijay Mahadevan   Notes:
24863d025dbSVijay Mahadevan 
24963d025dbSVijay Mahadevan   Example Physical Element (QUAD4)
25063d025dbSVijay Mahadevan 
25163d025dbSVijay Mahadevan     4------3        s
25263d025dbSVijay Mahadevan     |      |        |
25363d025dbSVijay Mahadevan     |      |        |
25463d025dbSVijay Mahadevan     |      |        |
25563d025dbSVijay Mahadevan     1------2        0-------r
25663d025dbSVijay Mahadevan 
25763d025dbSVijay Mahadevan   Input Parameter:
25863d025dbSVijay Mahadevan 
25963d025dbSVijay Mahadevan .  PetscInt  nverts,           the number of element vertices
26063d025dbSVijay Mahadevan .  PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering)
26163d025dbSVijay Mahadevan .  PetscInt  npts,             the number of evaluation points (quadrature points)
26263d025dbSVijay Mahadevan .  PetscReal quad[3*npts],     the evaluation points (quadrature points) in the reference space
26363d025dbSVijay Mahadevan 
26463d025dbSVijay Mahadevan   Output Parameter:
26563d025dbSVijay Mahadevan .  PetscReal phypts[3*npts],   the evaluation points (quadrature points) transformed to the physical space
26663d025dbSVijay Mahadevan .  PetscReal jxw[npts],        the jacobian determinant * quadrature weight necessary for assembling discrete contributions
26763d025dbSVijay Mahadevan .  PetscReal phi[npts],        the bases evaluated at the specified quadrature points
26863d025dbSVijay Mahadevan .  PetscReal dphidx[npts],     the derivative of the bases wrt X-direction evaluated at the specified quadrature points
26963d025dbSVijay Mahadevan .  PetscReal dphidy[npts],     the derivative of the bases wrt Y-direction evaluated at the specified quadrature points
27063d025dbSVijay Mahadevan 
27163d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 2-D
27263d025dbSVijay Mahadevan @*/
27363d025dbSVijay Mahadevan #undef __FUNCT__
27463d025dbSVijay Mahadevan #define __FUNCT__ "Compute_Lagrange_Basis_2D_Internal"
27563d025dbSVijay Mahadevan PetscErrorCode Compute_Lagrange_Basis_2D_Internal ( const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts,
276*181f196bSVijay Mahadevan     PetscReal *jxw, PetscReal *phi, PetscReal *dphidx, PetscReal *dphidy,
277*181f196bSVijay Mahadevan     PetscReal *jacobian, PetscReal *ijacobian, PetscReal *volume)
27863d025dbSVijay Mahadevan {
27963d025dbSVijay Mahadevan   int i, j;
28063d025dbSVijay Mahadevan   PetscErrorCode   ierr;
28163d025dbSVijay Mahadevan 
28263d025dbSVijay Mahadevan   PetscFunctionBegin;
283*181f196bSVijay Mahadevan   PetscValidPointer(jacobian, 10);
284*181f196bSVijay Mahadevan   PetscValidPointer(ijacobian, 11);
285*181f196bSVijay Mahadevan   PetscValidPointer(volume, 12);
28663d025dbSVijay Mahadevan   ierr = PetscMemzero(phi, npts * sizeof(PetscReal));CHKERRQ(ierr);
287*181f196bSVijay Mahadevan   if (phypts) {
28863d025dbSVijay Mahadevan     ierr = PetscMemzero(phypts, npts * 3 * sizeof(PetscReal));CHKERRQ(ierr);
289*181f196bSVijay Mahadevan   }
29063d025dbSVijay Mahadevan   if (dphidx) { /* Reset arrays. */
29163d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidx, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
29263d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidy, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
29363d025dbSVijay Mahadevan   }
29463d025dbSVijay Mahadevan   if (nverts == 4) { /* Linear Quadrangle */
29563d025dbSVijay Mahadevan 
29663d025dbSVijay Mahadevan     for (j = 0; j < npts; j++)
29763d025dbSVijay Mahadevan     {
29863d025dbSVijay Mahadevan       const int offset = j * nverts;
299*181f196bSVijay Mahadevan       const PetscReal r = quad[0 + j * 2];
300*181f196bSVijay Mahadevan       const PetscReal s = quad[1 + j * 2];
30163d025dbSVijay Mahadevan 
30263d025dbSVijay Mahadevan       phi[0 + offset] = ( 1.0 - r ) * ( 1.0 - s );
30363d025dbSVijay Mahadevan       phi[1 + offset] =         r   * ( 1.0 - s );
30463d025dbSVijay Mahadevan       phi[2 + offset] =         r   *         s;
30563d025dbSVijay Mahadevan       phi[3 + offset] = ( 1.0 - r ) *         s;
30663d025dbSVijay Mahadevan 
307*181f196bSVijay Mahadevan       const PetscReal dNi_dxi[4]  = { -1.0 + s, 1.0 - s, s, -s };
308*181f196bSVijay Mahadevan       const PetscReal dNi_deta[4] = { -1.0 + r, -r, r, 1.0 - r };
30963d025dbSVijay Mahadevan 
31063d025dbSVijay Mahadevan       ierr = PetscMemzero(jacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr);
31163d025dbSVijay Mahadevan       ierr = PetscMemzero(ijacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr);
31263d025dbSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
313*181f196bSVijay Mahadevan         const PetscReal* vertices = coords + i * 3;
31463d025dbSVijay Mahadevan         jacobian[0] += dNi_dxi[i] * vertices[0];
31563d025dbSVijay Mahadevan         jacobian[2] += dNi_dxi[i] * vertices[1];
31663d025dbSVijay Mahadevan         jacobian[1] += dNi_deta[i] * vertices[0];
31763d025dbSVijay Mahadevan         jacobian[3] += dNi_deta[i] * vertices[1];
318*181f196bSVijay Mahadevan         if (phypts) {
319*181f196bSVijay Mahadevan           phypts[3 * j + 0] += phi[i + offset] * vertices[0];
320*181f196bSVijay Mahadevan           phypts[3 * j + 1] += phi[i + offset] * vertices[1];
321*181f196bSVijay Mahadevan           phypts[3 * j + 2] += phi[i + offset] * vertices[2];
322*181f196bSVijay Mahadevan         }
32363d025dbSVijay Mahadevan       }
32463d025dbSVijay Mahadevan 
32563d025dbSVijay Mahadevan       /* invert the jacobian */
326*181f196bSVijay Mahadevan       ierr = DMatrix_Invert_2x2_Internal(jacobian, ijacobian, volume);CHKERRQ(ierr);
327*181f196bSVijay Mahadevan       if ( *volume < 1e-12 ) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Quadrangular element has zero volume: %g. Degenerate element or invalid connectivity\n", *volume);
32863d025dbSVijay Mahadevan 
329*181f196bSVijay Mahadevan       if (jxw) jxw[j] *= *volume;
33063d025dbSVijay Mahadevan 
331*181f196bSVijay Mahadevan       /*  Let us compute the bases derivatives by scaling with inverse jacobian. */
332*181f196bSVijay Mahadevan       if (dphidx) {
33363d025dbSVijay Mahadevan         for ( i = 0; i < nverts; i++ ) {
33463d025dbSVijay Mahadevan           for (int k = 0; k < 2; ++k) {
33563d025dbSVijay Mahadevan             if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[k * 2 + 0];
33663d025dbSVijay Mahadevan             if (dphidy) dphidy[i + offset] += dNi_deta[i] * ijacobian[k * 2 + 1];
337*181f196bSVijay Mahadevan           } /* for k=[0..2) */
338*181f196bSVijay Mahadevan         } /* for i=[0..nverts) */
339*181f196bSVijay Mahadevan       } /* if (dphidx) */
34063d025dbSVijay Mahadevan     }
34163d025dbSVijay Mahadevan   }
34263d025dbSVijay Mahadevan   else if (nverts == 3) { /* Linear triangle */
34363d025dbSVijay Mahadevan 
34463d025dbSVijay Mahadevan     ierr = PetscMemzero(jacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr);
34563d025dbSVijay Mahadevan     ierr = PetscMemzero(ijacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr);
34663d025dbSVijay Mahadevan 
347*181f196bSVijay Mahadevan     const PetscReal x2 = coords[2 * 3 + 0], y2 = coords[2 * 3 + 1];
348*181f196bSVijay Mahadevan 
34963d025dbSVijay Mahadevan     /* Jacobian is constant */
350*181f196bSVijay Mahadevan     jacobian[0] = (coords[0 * 3 + 0] - x2); jacobian[1] = (coords[1 * 3 + 0] - x2);
351*181f196bSVijay Mahadevan     jacobian[2] = (coords[0 * 3 + 1] - y2); jacobian[3] = (coords[1 * 3 + 1] - y2);
35263d025dbSVijay Mahadevan 
35363d025dbSVijay Mahadevan     /* invert the jacobian */
354*181f196bSVijay Mahadevan     ierr = DMatrix_Invert_2x2_Internal(jacobian, ijacobian, volume);CHKERRQ(ierr);
355*181f196bSVijay Mahadevan     if ( *volume < 1e-12 ) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Triangular element has zero volume: %g. Degenerate element or invalid connectivity\n", *volume);
356*181f196bSVijay Mahadevan 
357*181f196bSVijay Mahadevan     const PetscReal Dx[3] = { ijacobian[0], ijacobian[2], - ijacobian[0] - ijacobian[2] };
358*181f196bSVijay Mahadevan     const PetscReal Dy[3] = { ijacobian[1], ijacobian[3], - ijacobian[1] - ijacobian[3] };
35963d025dbSVijay Mahadevan 
36063d025dbSVijay Mahadevan     for (j = 0; j < npts; j++)
36163d025dbSVijay Mahadevan     {
36263d025dbSVijay Mahadevan       const int offset = j * nverts;
363*181f196bSVijay Mahadevan       const PetscReal r = quad[0 + j * 2];
364*181f196bSVijay Mahadevan       const PetscReal s = quad[1 + j * 2];
36563d025dbSVijay Mahadevan 
366*181f196bSVijay Mahadevan       if (jxw) jxw[j] *= 0.5;
36763d025dbSVijay Mahadevan 
368*181f196bSVijay Mahadevan       /* const PetscReal Ni[3]  = { r, s, 1.0 - r - s }; */
369*181f196bSVijay Mahadevan       const PetscReal phipts_x = coords[2 * 3 + 0] + jacobian[0] * r + jacobian[1] * s;
370*181f196bSVijay Mahadevan       const PetscReal phipts_y = coords[2 * 3 + 1] + jacobian[2] * r + jacobian[3] * s;
371*181f196bSVijay Mahadevan       if (phypts) {
372*181f196bSVijay Mahadevan         phypts[offset + 0] = phipts_x;
373*181f196bSVijay Mahadevan         phypts[offset + 1] = phipts_y;
374*181f196bSVijay Mahadevan       }
37563d025dbSVijay Mahadevan 
376*181f196bSVijay Mahadevan       /* \phi_0 = (b.y − c.y) x + (b.x − c.x) y + c.x b.y − b.x c.y */
377*181f196bSVijay Mahadevan       phi[0 + offset] = (  ijacobian[0] * (phipts_x - x2) + ijacobian[1] * (phipts_y - y2) );
378*181f196bSVijay Mahadevan       /* \phi_1 = (c.y − a.y) x + (a.x − c.x) y + c.x a.y − a.x c.y */
379*181f196bSVijay Mahadevan       phi[1 + offset] = (  ijacobian[2] * (phipts_x - x2) + ijacobian[3] * (phipts_y - y2) );
38063d025dbSVijay Mahadevan       phi[2 + offset] = 1.0 - phi[0 + offset] - phi[1 + offset];
38163d025dbSVijay Mahadevan 
38263d025dbSVijay Mahadevan       if (dphidx) {
383*181f196bSVijay Mahadevan         dphidx[0 + offset] = Dx[0];
384*181f196bSVijay Mahadevan         dphidx[1 + offset] = Dx[1];
385*181f196bSVijay Mahadevan         dphidx[2 + offset] = Dx[2];
38663d025dbSVijay Mahadevan       }
38763d025dbSVijay Mahadevan 
38863d025dbSVijay Mahadevan       if (dphidy) {
389*181f196bSVijay Mahadevan         dphidy[0 + offset] = Dy[0];
390*181f196bSVijay Mahadevan         dphidy[1 + offset] = Dy[1];
391*181f196bSVijay Mahadevan         dphidy[2 + offset] = Dy[2];
39263d025dbSVijay Mahadevan       }
39363d025dbSVijay Mahadevan 
39463d025dbSVijay Mahadevan     }
39563d025dbSVijay Mahadevan   }
39663d025dbSVijay Mahadevan   else {
39763d025dbSVijay 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);
39863d025dbSVijay Mahadevan   }
39963d025dbSVijay Mahadevan #if 0
40063d025dbSVijay Mahadevan   /* verify if the computed basis functions are consistent */
40163d025dbSVijay Mahadevan   for ( j = 0; j < npts; j++ ) {
40263d025dbSVijay Mahadevan     PetscScalar phisum = 0, dphixsum = 0, dphiysum = 0;
40363d025dbSVijay Mahadevan     for ( i = 0; i < nverts; i++ ) {
40463d025dbSVijay Mahadevan       phisum += phi[i + j * nverts];
40563d025dbSVijay Mahadevan       if (dphidx) dphixsum += dphidx[i + j * nverts];
40663d025dbSVijay Mahadevan       if (dphidy) dphiysum += dphidy[i + j * nverts];
40763d025dbSVijay Mahadevan     }
40863d025dbSVijay Mahadevan     PetscPrintf(PETSC_COMM_WORLD, "Sum of basis at quadrature point %D = %g, %g, %g\n", j, phisum, dphixsum, dphiysum);
40963d025dbSVijay Mahadevan   }
41063d025dbSVijay Mahadevan #endif
41163d025dbSVijay Mahadevan   PetscFunctionReturn(0);
41263d025dbSVijay Mahadevan }
41363d025dbSVijay Mahadevan 
41463d025dbSVijay Mahadevan 
41563d025dbSVijay Mahadevan /*@
41663d025dbSVijay Mahadevan   Compute_Lagrange_Basis_3D_Internal: Evaluate bases and derivatives at quadrature points for a HEX8 or TET4 element.
41763d025dbSVijay Mahadevan 
41863d025dbSVijay Mahadevan   The routine is given the coordinates of the vertices of a hexahedra or tetrahedra.
41963d025dbSVijay Mahadevan 
42063d025dbSVijay Mahadevan   The routine evaluates the basis functions associated with each quadrature point provided,
42163d025dbSVijay Mahadevan   and their derivatives with respect to X, Y and Z.
42263d025dbSVijay Mahadevan 
42363d025dbSVijay Mahadevan   Notes:
42463d025dbSVijay Mahadevan 
42563d025dbSVijay Mahadevan   Example Physical Element (HEX8)
42663d025dbSVijay Mahadevan 
42763d025dbSVijay Mahadevan       8------7
42863d025dbSVijay Mahadevan      /|     /|        t  s
42963d025dbSVijay Mahadevan     5------6 |        | /
43063d025dbSVijay Mahadevan     | |    | |        |/
43163d025dbSVijay Mahadevan     | 4----|-3        0-------r
43263d025dbSVijay Mahadevan     |/     |/
43363d025dbSVijay Mahadevan     1------2
43463d025dbSVijay Mahadevan 
43563d025dbSVijay Mahadevan   Input Parameter:
43663d025dbSVijay Mahadevan 
43763d025dbSVijay Mahadevan .  PetscInt  nverts,           the number of element vertices
43863d025dbSVijay Mahadevan .  PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering)
43963d025dbSVijay Mahadevan .  PetscInt  npts,             the number of evaluation points (quadrature points)
44063d025dbSVijay Mahadevan .  PetscReal quad[3*npts],     the evaluation points (quadrature points) in the reference space
44163d025dbSVijay Mahadevan 
44263d025dbSVijay Mahadevan   Output Parameter:
44363d025dbSVijay Mahadevan .  PetscReal phypts[3*npts],   the evaluation points (quadrature points) transformed to the physical space
44463d025dbSVijay Mahadevan .  PetscReal jxw[npts],        the jacobian determinant * quadrature weight necessary for assembling discrete contributions
44563d025dbSVijay Mahadevan .  PetscReal phi[npts],        the bases evaluated at the specified quadrature points
44663d025dbSVijay Mahadevan .  PetscReal dphidx[npts],     the derivative of the bases wrt X-direction evaluated at the specified quadrature points
44763d025dbSVijay Mahadevan .  PetscReal dphidy[npts],     the derivative of the bases wrt Y-direction evaluated at the specified quadrature points
44863d025dbSVijay Mahadevan .  PetscReal dphidz[npts],     the derivative of the bases wrt Z-direction evaluated at the specified quadrature points
44963d025dbSVijay Mahadevan 
45063d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 3-D
45163d025dbSVijay Mahadevan @*/
45263d025dbSVijay Mahadevan #undef __FUNCT__
45363d025dbSVijay Mahadevan #define __FUNCT__ "Compute_Lagrange_Basis_3D_Internal"
45463d025dbSVijay Mahadevan PetscErrorCode Compute_Lagrange_Basis_3D_Internal ( const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts,
455*181f196bSVijay Mahadevan     PetscReal *jxw, PetscReal *phi, PetscReal *dphidx, PetscReal *dphidy, PetscReal *dphidz,
456*181f196bSVijay Mahadevan     PetscReal *jacobian, PetscReal *ijacobian, PetscReal *volume)
45763d025dbSVijay Mahadevan {
45863d025dbSVijay Mahadevan   int i, j;
45963d025dbSVijay Mahadevan   PetscErrorCode ierr;
46063d025dbSVijay Mahadevan 
46163d025dbSVijay Mahadevan   PetscFunctionBegin;
462*181f196bSVijay Mahadevan   PetscValidPointer(jacobian, 11);
463*181f196bSVijay Mahadevan   PetscValidPointer(ijacobian, 12);
464*181f196bSVijay Mahadevan   PetscValidPointer(volume, 13);
46563d025dbSVijay Mahadevan   /* Reset arrays. */
46663d025dbSVijay Mahadevan   ierr = PetscMemzero(phi, npts * sizeof(PetscReal));CHKERRQ(ierr);
467*181f196bSVijay Mahadevan   if (phypts) {
46863d025dbSVijay Mahadevan     ierr = PetscMemzero(phypts, npts * 3 * sizeof(PetscReal));CHKERRQ(ierr);
469*181f196bSVijay Mahadevan   }
47063d025dbSVijay Mahadevan   if (dphidx) {
47163d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidx, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
47263d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidy, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
47363d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidz, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
47463d025dbSVijay Mahadevan   }
47563d025dbSVijay Mahadevan 
47663d025dbSVijay Mahadevan   if (nverts == 8) { /* Linear Hexahedra */
47763d025dbSVijay Mahadevan 
47863d025dbSVijay Mahadevan     for (j = 0; j < npts; j++)
47963d025dbSVijay Mahadevan     {
48063d025dbSVijay Mahadevan       const int offset = j * nverts;
481*181f196bSVijay Mahadevan       const PetscReal& r = quad[j * 3 + 0];
482*181f196bSVijay Mahadevan       const PetscReal& s = quad[j * 3 + 1];
483*181f196bSVijay Mahadevan       const PetscReal& t = quad[j * 3 + 2];
48463d025dbSVijay Mahadevan 
48563d025dbSVijay Mahadevan       phi[offset + 0] = ( 1.0 - r ) * ( 1.0 - s ) * ( 1.0 - t ) / 8;
48663d025dbSVijay Mahadevan       phi[offset + 1] = ( 1.0 + r ) * ( 1.0 - s ) * ( 1.0 - t ) / 8;
48763d025dbSVijay Mahadevan       phi[offset + 2] = ( 1.0 + r ) * ( 1.0 + s ) * ( 1.0 - t ) / 8;
48863d025dbSVijay Mahadevan       phi[offset + 3] = ( 1.0 - r ) * ( 1.0 + s ) * ( 1.0 - t ) / 8;
48963d025dbSVijay Mahadevan       phi[offset + 4] = ( 1.0 - r ) * ( 1.0 - s ) * ( 1.0 + t ) / 8;
49063d025dbSVijay Mahadevan       phi[offset + 5] = ( 1.0 + r ) * ( 1.0 - s ) * ( 1.0 + t ) / 8;
49163d025dbSVijay Mahadevan       phi[offset + 6] = ( 1.0 + r ) * ( 1.0 + s ) * ( 1.0 + t ) / 8;
49263d025dbSVijay Mahadevan       phi[offset + 7] = ( 1.0 - r ) * ( 1.0 + s ) * ( 1.0 + t ) / 8;
49363d025dbSVijay Mahadevan 
494*181f196bSVijay Mahadevan       const PetscReal dNi_dxi[8]  = { - ( 1.0 - s ) * ( 1.0 - t ),
49563d025dbSVijay Mahadevan                                      ( 1.0 - s ) * ( 1.0 - t ),
49663d025dbSVijay Mahadevan                                      ( 1.0 + s ) * ( 1.0 - t ),
49763d025dbSVijay Mahadevan                                      - ( 1.0 + s ) * ( 1.0 - t ),
49863d025dbSVijay Mahadevan                                      - ( 1.0 - s ) * ( 1.0 + t ),
49963d025dbSVijay Mahadevan                                      ( 1.0 - s ) * ( 1.0 + t ),
50063d025dbSVijay Mahadevan                                      ( 1.0 + s ) * ( 1.0 + t ),
50163d025dbSVijay Mahadevan                                      - ( 1.0 + s ) * ( 1.0 + t )
50263d025dbSVijay Mahadevan                                    };
50363d025dbSVijay Mahadevan 
504*181f196bSVijay Mahadevan       const PetscReal dNi_deta[8]  = { - ( 1.0 - r ) * ( 1.0 - t ),
50563d025dbSVijay Mahadevan                                       - ( 1.0 + r ) * ( 1.0 - t ),
50663d025dbSVijay Mahadevan                                       ( 1.0 + r ) * ( 1.0 - t ),
50763d025dbSVijay Mahadevan                                       ( 1.0 - r ) * ( 1.0 - t ),
50863d025dbSVijay Mahadevan                                       - ( 1.0 - r ) * ( 1.0 + t ),
50963d025dbSVijay Mahadevan                                       - ( 1.0 + r ) * ( 1.0 + t ),
51063d025dbSVijay Mahadevan                                       ( 1.0 + r ) * ( 1.0 + t ),
51163d025dbSVijay Mahadevan                                       ( 1.0 - r ) * ( 1.0 + t )
51263d025dbSVijay Mahadevan                                     };
51363d025dbSVijay Mahadevan 
514*181f196bSVijay Mahadevan       const PetscReal dNi_dzeta[8]  = { - ( 1.0 - r ) * ( 1.0 - s ),
51563d025dbSVijay Mahadevan                                        - ( 1.0 + r ) * ( 1.0 - s ),
51663d025dbSVijay Mahadevan                                        - ( 1.0 + r ) * ( 1.0 + s ),
51763d025dbSVijay Mahadevan                                        - ( 1.0 - r ) * ( 1.0 + s ),
51863d025dbSVijay Mahadevan                                        ( 1.0 - r ) * ( 1.0 - s ),
51963d025dbSVijay Mahadevan                                        ( 1.0 + r ) * ( 1.0 - s ),
52063d025dbSVijay Mahadevan                                        ( 1.0 + r ) * ( 1.0 + s ),
52163d025dbSVijay Mahadevan                                        ( 1.0 - r ) * ( 1.0 + s )
52263d025dbSVijay Mahadevan                                      };
52363d025dbSVijay Mahadevan 
52463d025dbSVijay Mahadevan       ierr = PetscMemzero(jacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr);
52563d025dbSVijay Mahadevan       ierr = PetscMemzero(ijacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr);
52663d025dbSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
527*181f196bSVijay Mahadevan         const PetscReal* vertex = coords + i * 3;
52863d025dbSVijay Mahadevan         jacobian[0] += dNi_dxi[i]   * vertex[0];
52963d025dbSVijay Mahadevan         jacobian[3] += dNi_dxi[i]   * vertex[1];
53063d025dbSVijay Mahadevan         jacobian[6] += dNi_dxi[i]   * vertex[2];
53163d025dbSVijay Mahadevan         jacobian[1] += dNi_deta[i]  * vertex[0];
53263d025dbSVijay Mahadevan         jacobian[4] += dNi_deta[i]  * vertex[1];
53363d025dbSVijay Mahadevan         jacobian[7] += dNi_deta[i]  * vertex[2];
53463d025dbSVijay Mahadevan         jacobian[2] += dNi_dzeta[i] * vertex[0];
53563d025dbSVijay Mahadevan         jacobian[5] += dNi_dzeta[i] * vertex[1];
53663d025dbSVijay Mahadevan         jacobian[8] += dNi_dzeta[i] * vertex[2];
537*181f196bSVijay Mahadevan         if (phypts) {
538*181f196bSVijay Mahadevan           phypts[3 * j + 0] += phi[i + offset] * vertex[0];
539*181f196bSVijay Mahadevan           phypts[3 * j + 1] += phi[i + offset] * vertex[1];
540*181f196bSVijay Mahadevan           phypts[3 * j + 2] += phi[i + offset] * vertex[2];
541*181f196bSVijay Mahadevan         }
54263d025dbSVijay Mahadevan       }
54363d025dbSVijay Mahadevan 
54463d025dbSVijay Mahadevan       /* invert the jacobian */
545*181f196bSVijay Mahadevan       ierr = DMatrix_Invert_3x3_Internal(jacobian, ijacobian, volume);CHKERRQ(ierr);
546*181f196bSVijay Mahadevan       if ( *volume < 1e-8 ) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Hexahedral element has zero volume: %g. Degenerate element or invalid connectivity\n", volume);
54763d025dbSVijay Mahadevan 
548*181f196bSVijay Mahadevan       const PetscReal factor = 1.0 / 8; /* Our basis is defined on [-1 to 1]^3 */
549*181f196bSVijay Mahadevan       if (jxw) jxw[j] *= factor * (*volume);
55063d025dbSVijay Mahadevan 
55163d025dbSVijay Mahadevan       /*  Divide by element jacobian. */
55263d025dbSVijay Mahadevan       for ( i = 0; i < nverts; ++i ) {
55363d025dbSVijay Mahadevan         for (int k = 0; k < 3; ++k) {
55463d025dbSVijay Mahadevan           if (dphidx) dphidx[i + offset] += dNi_dxi[i]   * ijacobian[0 * 3 + k];
55563d025dbSVijay Mahadevan           if (dphidy) dphidy[i + offset] += dNi_deta[i]  * ijacobian[1 * 3 + k];
55663d025dbSVijay Mahadevan           if (dphidz) dphidz[i + offset] += dNi_dzeta[i] * ijacobian[2 * 3 + k];
55763d025dbSVijay Mahadevan         }
55863d025dbSVijay Mahadevan       }
55963d025dbSVijay Mahadevan     }
56063d025dbSVijay Mahadevan   }
56163d025dbSVijay Mahadevan   else if (nverts == 4) { /* Linear Tetrahedra */
56263d025dbSVijay Mahadevan 
56363d025dbSVijay Mahadevan     ierr = PetscMemzero(jacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr);
56463d025dbSVijay Mahadevan     ierr = PetscMemzero(ijacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr);
56563d025dbSVijay Mahadevan 
566*181f196bSVijay Mahadevan     const PetscReal x0 = coords[/*0 * 3 +*/ 0], y0 = coords[/*0 * 3 +*/ 1], z0 = coords[/*0 * 3 +*/ 2];
567*181f196bSVijay Mahadevan 
568*181f196bSVijay Mahadevan     /* compute the jacobian */
569*181f196bSVijay Mahadevan     jacobian[0] = coords[1 * 3 + 0] - x0;  jacobian[1] = coords[2 * 3 + 0] - x0; jacobian[2] = coords[3 * 3 + 0] - x0;
570*181f196bSVijay Mahadevan     jacobian[3] = coords[1 * 3 + 1] - y0;  jacobian[4] = coords[2 * 3 + 1] - y0; jacobian[5] = coords[3 * 3 + 1] - y0;
571*181f196bSVijay Mahadevan     jacobian[6] = coords[1 * 3 + 2] - z0;  jacobian[7] = coords[2 * 3 + 2] - z0; jacobian[8] = coords[3 * 3 + 2] - z0;
57263d025dbSVijay Mahadevan 
57363d025dbSVijay Mahadevan     /* invert the jacobian */
574*181f196bSVijay Mahadevan     ierr = DMatrix_Invert_3x3_Internal(jacobian, ijacobian, volume);CHKERRQ(ierr);
575*181f196bSVijay 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);
57663d025dbSVijay Mahadevan 
577*181f196bSVijay Mahadevan     // const PetscReal Dx[4] = { ijacobian[0], ijacobian[3], ijacobian[6], - ijacobian[0] - ijacobian[3] - ijacobian[6] };
578*181f196bSVijay Mahadevan     // const PetscReal Dy[4] = { ijacobian[1], ijacobian[4], ijacobian[7], - ijacobian[1] - ijacobian[4] - ijacobian[7] };
579*181f196bSVijay Mahadevan     // const PetscReal Dz[4] = { ijacobian[2], ijacobian[5], ijacobian[8], - ijacobian[2] - ijacobian[5] - ijacobian[8] };
580*181f196bSVijay Mahadevan     PetscReal Dx[4], Dy[4], Dz[4];
581*181f196bSVijay Mahadevan     if (dphidx) {
582*181f196bSVijay Mahadevan       Dx[0] =   ( coords[1 + 2 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] )
583*181f196bSVijay Mahadevan                  - coords[1 + 1 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] )
584*181f196bSVijay Mahadevan                  - coords[1 + 3 * 3] * ( coords[2 + 1 * 3] - coords[2 + 2 * 3] )
585*181f196bSVijay Mahadevan                 ) / *volume;
586*181f196bSVijay Mahadevan       Dx[1] = - ( coords[1 + 2 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] )
587*181f196bSVijay Mahadevan                  - coords[1 + 0 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] )
588*181f196bSVijay Mahadevan                  - coords[1 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 2 * 3] )
589*181f196bSVijay Mahadevan                 ) / *volume;
590*181f196bSVijay Mahadevan       Dx[2] =   ( coords[1 + 1 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] )
591*181f196bSVijay Mahadevan                  - coords[1 + 0 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] )
592*181f196bSVijay Mahadevan                  - coords[1 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 1 * 3] )
593*181f196bSVijay Mahadevan                 ) / *volume;
594*181f196bSVijay Mahadevan       Dx[3] =  - ( Dx[0] + Dx[1] + Dx[2] );
595*181f196bSVijay Mahadevan       Dy[0] =   ( coords[0 + 1 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] )
596*181f196bSVijay Mahadevan                  - coords[0 + 2 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] )
597*181f196bSVijay Mahadevan                  + coords[0 + 3 * 3] * ( coords[2 + 1 * 3] - coords[2 + 2 * 3] )
598*181f196bSVijay Mahadevan                 ) / *volume;
599*181f196bSVijay Mahadevan       Dy[1] = - ( coords[0 + 0 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] )
600*181f196bSVijay Mahadevan                  - coords[0 + 2 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] )
601*181f196bSVijay Mahadevan                  + coords[0 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 2 * 3] )
602*181f196bSVijay Mahadevan                 ) / *volume;
603*181f196bSVijay Mahadevan       Dy[2] =   ( coords[0 + 0 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] )
604*181f196bSVijay Mahadevan                  - coords[0 + 1 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] )
605*181f196bSVijay Mahadevan                  + coords[0 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 1 * 3] )
606*181f196bSVijay Mahadevan                 ) / *volume;
607*181f196bSVijay Mahadevan       Dy[3] =  - ( Dy[0] + Dy[1] + Dy[2] );
608*181f196bSVijay Mahadevan       Dz[0] =   ( coords[0 + 1 * 3] * (coords[1 + 3 * 3] - coords[1 + 2 * 3] )
609*181f196bSVijay Mahadevan                  - coords[0 + 2 * 3] * (coords[1 + 3 * 3] - coords[1 + 1 * 3] )
610*181f196bSVijay Mahadevan                  + coords[0 + 3 * 3] * (coords[1 + 2 * 3] - coords[1 + 1 * 3] )
611*181f196bSVijay Mahadevan                 ) / *volume;
612*181f196bSVijay Mahadevan       Dz[1] = - ( coords[0 + 0 * 3] * (coords[1 + 3 * 3] - coords[1 + 2 * 3] )
613*181f196bSVijay Mahadevan                   + coords[0 + 2 * 3] * (coords[1 + 0 * 3] - coords[1 + 3 * 3] )
614*181f196bSVijay Mahadevan                   - coords[0 + 3 * 3] * (coords[1 + 0 * 3] - coords[1 + 2 * 3] )
615*181f196bSVijay Mahadevan                 ) / *volume;
616*181f196bSVijay Mahadevan       Dz[2] =   ( coords[0 + 0 * 3] * (coords[1 + 3 * 3] - coords[1 + 1 * 3] )
617*181f196bSVijay Mahadevan                  + coords[0 + 1 * 3] * (coords[1 + 0 * 3] - coords[1 + 3 * 3] )
618*181f196bSVijay Mahadevan                  - coords[0 + 3 * 3] * (coords[1 + 0 * 3] - coords[1 + 1 * 3] )
619*181f196bSVijay Mahadevan                 ) / *volume;
620*181f196bSVijay Mahadevan       Dz[3] =  - ( Dz[0] + Dz[1] + Dz[2] );
621*181f196bSVijay Mahadevan     }
62263d025dbSVijay Mahadevan 
62363d025dbSVijay Mahadevan     for ( j = 0; j < npts; j++ )
62463d025dbSVijay Mahadevan     {
62563d025dbSVijay Mahadevan       const int offset = j * nverts;
626*181f196bSVijay Mahadevan       const PetscReal& r = quad[j * 3 + 0];
627*181f196bSVijay Mahadevan       const PetscReal& s = quad[j * 3 + 1];
628*181f196bSVijay Mahadevan       const PetscReal& t = quad[j * 3 + 2];
62963d025dbSVijay Mahadevan 
630*181f196bSVijay Mahadevan       if (jxw) jxw[j] *= *volume;
63163d025dbSVijay Mahadevan 
63263d025dbSVijay Mahadevan       phi[offset + 0] = 1.0 - r - s - t;
63363d025dbSVijay Mahadevan       phi[offset + 1] = r;
63463d025dbSVijay Mahadevan       phi[offset + 2] = s;
63563d025dbSVijay Mahadevan       phi[offset + 3] = t;
63663d025dbSVijay Mahadevan 
637*181f196bSVijay Mahadevan       if (phypts) {
638*181f196bSVijay Mahadevan         for (i = 0; i < nverts; ++i) {
639*181f196bSVijay Mahadevan           const PetscScalar* vertices = coords + i * 3;
640*181f196bSVijay Mahadevan           phypts[3 * j + 0] += phi[i + offset] * vertices[0];
641*181f196bSVijay Mahadevan           phypts[3 * j + 1] += phi[i + offset] * vertices[1];
642*181f196bSVijay Mahadevan           phypts[3 * j + 2] += phi[i + offset] * vertices[2];
643*181f196bSVijay Mahadevan         }
644*181f196bSVijay Mahadevan       }
645*181f196bSVijay Mahadevan 
646*181f196bSVijay Mahadevan       /* Now set the derivatives */
64763d025dbSVijay Mahadevan       if (dphidx) {
648*181f196bSVijay Mahadevan         dphidx[0 + offset] = Dx[0];
649*181f196bSVijay Mahadevan         dphidx[1 + offset] = Dx[1];
650*181f196bSVijay Mahadevan         dphidx[2 + offset] = Dx[2];
651*181f196bSVijay Mahadevan         dphidx[3 + offset] = Dx[3];
65263d025dbSVijay Mahadevan       }
65363d025dbSVijay Mahadevan 
65463d025dbSVijay Mahadevan       if (dphidy) {
655*181f196bSVijay Mahadevan         dphidy[0 + offset] = Dy[0];
656*181f196bSVijay Mahadevan         dphidy[1 + offset] = Dy[1];
657*181f196bSVijay Mahadevan         dphidy[2 + offset] = Dy[2];
658*181f196bSVijay Mahadevan         dphidy[3 + offset] = Dy[3];
65963d025dbSVijay Mahadevan       }
66063d025dbSVijay Mahadevan 
66163d025dbSVijay Mahadevan       if (dphidz) {
662*181f196bSVijay Mahadevan         dphidz[0 + offset] = Dz[0];
663*181f196bSVijay Mahadevan         dphidz[1 + offset] = Dz[1];
664*181f196bSVijay Mahadevan         dphidz[2 + offset] = Dz[2];
665*181f196bSVijay Mahadevan         dphidz[3 + offset] = Dz[3];
66663d025dbSVijay Mahadevan       }
66763d025dbSVijay Mahadevan 
66863d025dbSVijay Mahadevan     } /* Tetrahedra -- ends */
66963d025dbSVijay Mahadevan   }
67063d025dbSVijay Mahadevan   else
67163d025dbSVijay Mahadevan   {
67263d025dbSVijay 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);
67363d025dbSVijay Mahadevan   }
67463d025dbSVijay Mahadevan #if 0
67563d025dbSVijay Mahadevan   /* verify if the computed basis functions are consistent */
67663d025dbSVijay Mahadevan   for ( j = 0; j < npts; j++ ) {
67763d025dbSVijay Mahadevan     PetscScalar phisum = 0, dphixsum = 0, dphiysum = 0, dphizsum = 0;
67863d025dbSVijay Mahadevan     const int offset = j * nverts;
67963d025dbSVijay Mahadevan     for ( i = 0; i < nverts; i++ ) {
68063d025dbSVijay Mahadevan       phisum += phi[i + offset];
68163d025dbSVijay Mahadevan       if (dphidx) dphixsum += dphidx[i + offset];
68263d025dbSVijay Mahadevan       if (dphidy) dphiysum += dphidy[i + offset];
68363d025dbSVijay Mahadevan       if (dphidz) dphizsum += dphidz[i + offset];
68463d025dbSVijay 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]);
68563d025dbSVijay Mahadevan     }
68663d025dbSVijay 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);
68763d025dbSVijay Mahadevan   }
68863d025dbSVijay Mahadevan #endif
68963d025dbSVijay Mahadevan   PetscFunctionReturn(0);
69063d025dbSVijay Mahadevan }
69163d025dbSVijay Mahadevan 
69263d025dbSVijay Mahadevan 
69363d025dbSVijay Mahadevan 
69463d025dbSVijay Mahadevan /*@
69563d025dbSVijay Mahadevan   DMMoabFEMComputeBasis: Evaluate bases and derivatives at quadrature points for a linear EDGE/QUAD/TRI/HEX/TET element.
69663d025dbSVijay Mahadevan 
69763d025dbSVijay Mahadevan   The routine takes the coordinates of the vertices of an element and computes basis functions associated with
69863d025dbSVijay Mahadevan   each quadrature point provided, and their derivatives with respect to X, Y and Z as appropriate.
69963d025dbSVijay Mahadevan 
70063d025dbSVijay Mahadevan   Input Parameter:
70163d025dbSVijay Mahadevan 
70263d025dbSVijay Mahadevan .  PetscInt  nverts,           the number of element vertices
70363d025dbSVijay Mahadevan .  PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering)
70463d025dbSVijay Mahadevan .  PetscInt  npts,             the number of evaluation points (quadrature points)
70563d025dbSVijay Mahadevan .  PetscReal quad[3*npts],     the evaluation points (quadrature points) in the reference space
70663d025dbSVijay Mahadevan 
70763d025dbSVijay Mahadevan   Output Parameter:
70863d025dbSVijay Mahadevan .  PetscReal phypts[3*npts],   the evaluation points (quadrature points) transformed to the physical space
70963d025dbSVijay Mahadevan .  PetscReal jxw[npts],        the jacobian determinant * quadrature weight necessary for assembling discrete contributions
71063d025dbSVijay Mahadevan .  PetscReal fe_basis[npts],        the bases values evaluated at the specified quadrature points
71163d025dbSVijay 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
71263d025dbSVijay Mahadevan 
71363d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 3-D
71463d025dbSVijay Mahadevan @*/
71563d025dbSVijay Mahadevan #undef __FUNCT__
71663d025dbSVijay Mahadevan #define __FUNCT__ "DMMoabFEMComputeBasis"
717*181f196bSVijay Mahadevan PetscErrorCode DMMoabFEMComputeBasis ( const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscQuadrature quadrature,
718*181f196bSVijay Mahadevan                                        PetscReal *phypts, PetscReal *jacobian_quadrature_weight_product,
719*181f196bSVijay Mahadevan                                        PetscReal *fe_basis, PetscReal **fe_basis_derivatives)
72063d025dbSVijay Mahadevan {
72163d025dbSVijay Mahadevan   PetscErrorCode  ierr;
72263d025dbSVijay Mahadevan   PetscInt        npoints;
72363d025dbSVijay Mahadevan   bool            compute_der;
72463d025dbSVijay Mahadevan   const PetscReal *quadpts, *quadwts;
725*181f196bSVijay Mahadevan   PetscReal       jacobian[9], ijacobian[9], volume;
72663d025dbSVijay Mahadevan 
72763d025dbSVijay Mahadevan   PetscFunctionBegin;
72863d025dbSVijay Mahadevan   PetscValidPointer(coordinates, 3);
72963d025dbSVijay Mahadevan   PetscValidHeaderSpecific(quadrature, PETSC_OBJECT_CLASSID, 4);
73063d025dbSVijay Mahadevan   PetscValidPointer(fe_basis, 7);
73163d025dbSVijay Mahadevan   compute_der = (fe_basis_derivatives != NULL);
73263d025dbSVijay Mahadevan 
73363d025dbSVijay Mahadevan   /* Get the quadrature points and weights for the given quadrature rule */
73463d025dbSVijay Mahadevan   ierr = PetscQuadratureGetData(quadrature, NULL, &npoints, &quadpts, &quadwts);CHKERRQ(ierr);
735*181f196bSVijay Mahadevan   if (jacobian_quadrature_weight_product) {
73663d025dbSVijay Mahadevan     ierr = PetscMemcpy(jacobian_quadrature_weight_product, quadwts, npoints * sizeof(PetscReal));CHKERRQ(ierr);
737*181f196bSVijay Mahadevan   }
73863d025dbSVijay Mahadevan 
73963d025dbSVijay Mahadevan   switch (dim) {
74063d025dbSVijay Mahadevan   case 1:
74163d025dbSVijay Mahadevan     ierr = Compute_Lagrange_Basis_1D_Internal(nverts, coordinates, npoints, quadpts, phypts,
74263d025dbSVijay Mahadevan            jacobian_quadrature_weight_product, fe_basis,
743*181f196bSVijay Mahadevan            (compute_der ? fe_basis_derivatives[0] : NULL),
744*181f196bSVijay Mahadevan            jacobian, ijacobian, &volume);CHKERRQ(ierr);
74563d025dbSVijay Mahadevan     break;
74663d025dbSVijay Mahadevan   case 2:
74763d025dbSVijay Mahadevan     ierr = Compute_Lagrange_Basis_2D_Internal(nverts, coordinates, npoints, quadpts, phypts,
74863d025dbSVijay Mahadevan            jacobian_quadrature_weight_product, fe_basis,
74963d025dbSVijay Mahadevan            (compute_der ? fe_basis_derivatives[0] : NULL),
750*181f196bSVijay Mahadevan            (compute_der ? fe_basis_derivatives[1] : NULL),
751*181f196bSVijay Mahadevan            jacobian, ijacobian, &volume);CHKERRQ(ierr);
75263d025dbSVijay Mahadevan     break;
75363d025dbSVijay Mahadevan   case 3:
75463d025dbSVijay Mahadevan     ierr = Compute_Lagrange_Basis_3D_Internal(nverts, coordinates, npoints, quadpts, phypts,
75563d025dbSVijay Mahadevan            jacobian_quadrature_weight_product, fe_basis,
75663d025dbSVijay Mahadevan            (compute_der ? fe_basis_derivatives[0] : NULL),
75763d025dbSVijay Mahadevan            (compute_der ? fe_basis_derivatives[1] : NULL),
758*181f196bSVijay Mahadevan            (compute_der ? fe_basis_derivatives[2] : NULL),
759*181f196bSVijay Mahadevan            jacobian, ijacobian, &volume);CHKERRQ(ierr);
76063d025dbSVijay Mahadevan     break;
76163d025dbSVijay Mahadevan   default:
76263d025dbSVijay Mahadevan     SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %D", dim);
76363d025dbSVijay Mahadevan   }
76463d025dbSVijay Mahadevan   PetscFunctionReturn(0);
76563d025dbSVijay Mahadevan }
76663d025dbSVijay Mahadevan 
76763d025dbSVijay Mahadevan 
76863d025dbSVijay Mahadevan 
76963d025dbSVijay Mahadevan /*@
77063d025dbSVijay Mahadevan   DMMoabFEMCreateQuadratureDefault: Create default quadrature rules for integration over an element with a given
77163d025dbSVijay Mahadevan   dimension and polynomial order (deciphered from number of element vertices).
77263d025dbSVijay Mahadevan 
77363d025dbSVijay Mahadevan   Input Parameter:
77463d025dbSVijay Mahadevan 
77563d025dbSVijay Mahadevan .  PetscInt  dim,           the element dimension (1=EDGE, 2=QUAD/TRI, 3=HEX/TET)
77663d025dbSVijay Mahadevan .  PetscInt nverts,      the number of vertices in the physical element
77763d025dbSVijay Mahadevan 
77863d025dbSVijay Mahadevan   Output Parameter:
77963d025dbSVijay Mahadevan .  PetscQuadrature quadrature,  the quadrature object with default settings to integrate polynomials defined over the element
78063d025dbSVijay Mahadevan 
78163d025dbSVijay Mahadevan .keywords: DMMoab, Quadrature, PetscDT
78263d025dbSVijay Mahadevan @*/
78363d025dbSVijay Mahadevan #undef __FUNCT__
78463d025dbSVijay Mahadevan #define __FUNCT__ "DMMoabFEMCreateQuadratureDefault"
785*181f196bSVijay Mahadevan PetscErrorCode DMMoabFEMCreateQuadratureDefault ( const PetscInt dim, const PetscInt nverts, PetscQuadrature *quadrature )
78663d025dbSVijay Mahadevan {
78763d025dbSVijay Mahadevan   PetscReal *w, *x;
78863d025dbSVijay Mahadevan   PetscErrorCode  ierr;
78963d025dbSVijay Mahadevan 
79063d025dbSVijay Mahadevan   PetscFunctionBegin;
79163d025dbSVijay Mahadevan   /* Create an appropriate quadrature rule to sample basis */
79263d025dbSVijay Mahadevan   switch (dim)
79363d025dbSVijay Mahadevan   {
79463d025dbSVijay Mahadevan   case 1:
79563d025dbSVijay Mahadevan     /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */
796*181f196bSVijay Mahadevan     ierr = PetscDTGaussJacobiQuadrature(1, nverts, 0, 1.0, quadrature);CHKERRQ(ierr);
79763d025dbSVijay Mahadevan     break;
79863d025dbSVijay Mahadevan   case 2:
79963d025dbSVijay Mahadevan     /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */
80063d025dbSVijay Mahadevan     if (nverts == 3) {
80163d025dbSVijay Mahadevan       const int order = 2;
80263d025dbSVijay Mahadevan       const int npoints = (order == 2 ? 3 : 6);
80363d025dbSVijay Mahadevan       ierr = PetscMalloc2(npoints * 2, &x, npoints, &w);CHKERRQ(ierr);
804*181f196bSVijay Mahadevan       if (npoints == 3) {
80563d025dbSVijay Mahadevan         x[0] = x[1] = x[2] = x[5] = 1.0 / 6.0;
80663d025dbSVijay Mahadevan         x[3] = x[4] = 2.0 / 3.0;
80763d025dbSVijay Mahadevan         w[0] = w[1] = w[2] = 1.0 / 3.0;
808*181f196bSVijay Mahadevan       }
809*181f196bSVijay Mahadevan       else if (npoints == 6) {
81063d025dbSVijay Mahadevan         x[0] = x[1] = x[2] = 0.44594849091597;
81163d025dbSVijay Mahadevan         x[3] = x[4] = 0.10810301816807;
81263d025dbSVijay Mahadevan         x[5] = 0.44594849091597;
81363d025dbSVijay Mahadevan         x[6] = x[7] = x[8] = 0.09157621350977;
81463d025dbSVijay Mahadevan         x[9] = x[10] = 0.81684757298046;
81563d025dbSVijay Mahadevan         x[11] = 0.09157621350977;
81663d025dbSVijay Mahadevan         w[0] = w[1] = w[2] = 0.22338158967801;
817*181f196bSVijay Mahadevan         w[3] = w[4] = w[5] = 0.10995174365532;
818*181f196bSVijay Mahadevan       }
819*181f196bSVijay Mahadevan       else {
820*181f196bSVijay Mahadevan         SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Triangle quadrature rules for points 3 and 6 supported; npoints : %D", npoints);
82163d025dbSVijay Mahadevan       }
82263d025dbSVijay Mahadevan       ierr = PetscQuadratureCreate(PETSC_COMM_SELF, quadrature);CHKERRQ(ierr);
82363d025dbSVijay Mahadevan       ierr = PetscQuadratureSetOrder(*quadrature, order);CHKERRQ(ierr);
824*181f196bSVijay Mahadevan       ierr = PetscQuadratureSetData(*quadrature, dim, npoints, x, w);CHKERRQ(ierr);
825*181f196bSVijay Mahadevan       /* ierr = PetscDTGaussJacobiQuadrature(dim, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr); */
82663d025dbSVijay Mahadevan     }
82763d025dbSVijay Mahadevan     else {
82863d025dbSVijay Mahadevan       ierr = PetscDTGaussTensorQuadrature(dim, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr);
82963d025dbSVijay Mahadevan     }
83063d025dbSVijay Mahadevan     break;
83163d025dbSVijay Mahadevan   case 3:
83263d025dbSVijay Mahadevan     /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */
83363d025dbSVijay Mahadevan     if (nverts == 4) {
834*181f196bSVijay Mahadevan       int order;
835*181f196bSVijay Mahadevan       const int npoints = 4; // Choose between 4 and 10
836*181f196bSVijay Mahadevan       ierr = PetscMalloc2(npoints * 3, &x, npoints, &w);CHKERRQ(ierr);
837*181f196bSVijay Mahadevan       if (npoints == 4) { /*  KEAST1, K1,  N=4, O=4 */
838*181f196bSVijay Mahadevan         const PetscReal x_4[12] = { 0.5854101966249685, 0.1381966011250105, 0.1381966011250105,
839*181f196bSVijay Mahadevan                                     0.1381966011250105, 0.1381966011250105, 0.1381966011250105,
840*181f196bSVijay Mahadevan                                     0.1381966011250105, 0.1381966011250105, 0.5854101966249685,
841*181f196bSVijay Mahadevan                                     0.1381966011250105, 0.5854101966249685, 0.1381966011250105
842*181f196bSVijay Mahadevan                                   };
843*181f196bSVijay Mahadevan         ierr = PetscMemcpy(x, x_4, 12 * sizeof(PetscReal));CHKERRQ(ierr);
844*181f196bSVijay Mahadevan 
845*181f196bSVijay Mahadevan         w[0] = w[1] = w[2] = w[3] = 1.0 / 24.0;
846*181f196bSVijay Mahadevan         order = 4;
847*181f196bSVijay Mahadevan       }
848*181f196bSVijay Mahadevan       else if (npoints == 10) { /*  KEAST3, K3  N=10, O=10 */
849*181f196bSVijay Mahadevan         const PetscReal x_10[30] = { 0.5684305841968444, 0.1438564719343852, 0.1438564719343852,
850*181f196bSVijay Mahadevan                                      0.1438564719343852, 0.1438564719343852, 0.1438564719343852,
851*181f196bSVijay Mahadevan                                      0.1438564719343852, 0.1438564719343852, 0.5684305841968444,
852*181f196bSVijay Mahadevan                                      0.1438564719343852, 0.5684305841968444, 0.1438564719343852,
853*181f196bSVijay Mahadevan                                      0.0000000000000000, 0.5000000000000000, 0.5000000000000000,
854*181f196bSVijay Mahadevan                                      0.5000000000000000, 0.0000000000000000, 0.5000000000000000,
855*181f196bSVijay Mahadevan                                      0.5000000000000000, 0.5000000000000000, 0.0000000000000000,
856*181f196bSVijay Mahadevan                                      0.5000000000000000, 0.0000000000000000, 0.0000000000000000,
857*181f196bSVijay Mahadevan                                      0.0000000000000000, 0.5000000000000000, 0.0000000000000000,
858*181f196bSVijay Mahadevan                                      0.0000000000000000, 0.0000000000000000, 0.5000000000000000
859*181f196bSVijay Mahadevan                                    };
860*181f196bSVijay Mahadevan         ierr = PetscMemcpy(x, x_10, 30 * sizeof(PetscReal));CHKERRQ(ierr);
861*181f196bSVijay Mahadevan 
862*181f196bSVijay Mahadevan         w[0] = w[1] = w[2] = w[3] = 0.2177650698804054;
863*181f196bSVijay Mahadevan         w[4] = w[5] = w[6] = w[7] = w[8] = w[9] = 0.0214899534130631;
864*181f196bSVijay Mahadevan         order = 10;
865*181f196bSVijay Mahadevan       }
866*181f196bSVijay Mahadevan       else {
867*181f196bSVijay Mahadevan         SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Tetrahedral quadrature rules for points 4 and 10 supported; npoints : %D", npoints);
868*181f196bSVijay Mahadevan       }
869*181f196bSVijay Mahadevan       ierr = PetscQuadratureCreate(PETSC_COMM_SELF, quadrature);CHKERRQ(ierr);
870*181f196bSVijay Mahadevan       ierr = PetscQuadratureSetOrder(*quadrature, order);CHKERRQ(ierr);
871*181f196bSVijay Mahadevan       ierr = PetscQuadratureSetData(*quadrature, dim, npoints, x, w);CHKERRQ(ierr);
872*181f196bSVijay Mahadevan       /* ierr = PetscDTGaussJacobiQuadrature(dim, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr); */
87363d025dbSVijay Mahadevan     }
87463d025dbSVijay Mahadevan     else {
87563d025dbSVijay Mahadevan       ierr = PetscDTGaussTensorQuadrature(dim, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr);
87663d025dbSVijay Mahadevan     }
87763d025dbSVijay Mahadevan     break;
87863d025dbSVijay Mahadevan   default:
87963d025dbSVijay Mahadevan     SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %D", dim);
88063d025dbSVijay Mahadevan   }
88163d025dbSVijay Mahadevan   PetscFunctionReturn(0);
88263d025dbSVijay Mahadevan }
88363d025dbSVijay Mahadevan 
884*181f196bSVijay Mahadevan /* Compute Jacobians */
885*181f196bSVijay Mahadevan #undef __FUNCT__
886*181f196bSVijay Mahadevan #define __FUNCT__ "ComputeJacobian_Internal"
887*181f196bSVijay Mahadevan PetscErrorCode ComputeJacobian_Internal ( const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscReal *quad, PetscReal *phypts,
888*181f196bSVijay Mahadevan   PetscReal *jacobian, PetscReal *ijacobian, PetscReal* volume)
889*181f196bSVijay Mahadevan {
890*181f196bSVijay Mahadevan   int i;
891*181f196bSVijay Mahadevan   PetscErrorCode ierr;
892*181f196bSVijay Mahadevan 
893*181f196bSVijay Mahadevan   PetscFunctionBegin;
894*181f196bSVijay Mahadevan   PetscValidPointer(coordinates, 3);
895*181f196bSVijay Mahadevan   PetscValidPointer(quad, 4);
896*181f196bSVijay Mahadevan   PetscValidPointer(jacobian, 5);
897*181f196bSVijay Mahadevan   ierr = PetscMemzero(jacobian, dim * dim * sizeof(PetscReal));CHKERRQ(ierr);
898*181f196bSVijay Mahadevan   if (ijacobian) {
899*181f196bSVijay Mahadevan     ierr = PetscMemzero(ijacobian, dim * dim * sizeof(PetscReal));CHKERRQ(ierr);
900*181f196bSVijay Mahadevan   }
901*181f196bSVijay Mahadevan   if (phypts) {
902*181f196bSVijay Mahadevan     ierr = PetscMemzero(phypts, /*npts=1 * */ 3 * sizeof(PetscReal));CHKERRQ(ierr);
903*181f196bSVijay Mahadevan   }
904*181f196bSVijay Mahadevan 
905*181f196bSVijay Mahadevan   if (dim == 1) {
906*181f196bSVijay Mahadevan 
907*181f196bSVijay Mahadevan     const PetscReal& r = quad[0];
908*181f196bSVijay Mahadevan     if (nverts == 2) { /* Linear Edge */
909*181f196bSVijay Mahadevan       const PetscReal dNi_dxi[2]  = { -1.0, 1.0 };
910*181f196bSVijay Mahadevan 
911*181f196bSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
912*181f196bSVijay Mahadevan         const PetscReal* vertices = coordinates + i * 3;
913*181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i] * vertices[0];
914*181f196bSVijay Mahadevan       }
915*181f196bSVijay Mahadevan     }
916*181f196bSVijay Mahadevan     else if (nverts == 3) { /* Quadratic Edge */
917*181f196bSVijay Mahadevan       const PetscReal dNi_dxi[3]  = { 4 * r - 3.0, 4 * ( 1.0 - 2.0 * r ), 4.0 * r - 1.0};
918*181f196bSVijay Mahadevan 
919*181f196bSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
920*181f196bSVijay Mahadevan         const PetscReal* vertices = coordinates + i * 3;
921*181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i] * vertices[0];
922*181f196bSVijay Mahadevan       }
923*181f196bSVijay Mahadevan     }
924*181f196bSVijay Mahadevan     else {
925*181f196bSVijay Mahadevan       SETERRQ1(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 : %D", nverts);
926*181f196bSVijay Mahadevan     }
927*181f196bSVijay Mahadevan 
928*181f196bSVijay Mahadevan     if (ijacobian) {
929*181f196bSVijay Mahadevan       /* invert the jacobian */
930*181f196bSVijay Mahadevan       ijacobian[0] = 1.0 / jacobian[0];
931*181f196bSVijay Mahadevan     }
932*181f196bSVijay Mahadevan 
933*181f196bSVijay Mahadevan   }
934*181f196bSVijay Mahadevan   else if (dim == 2) {
935*181f196bSVijay Mahadevan 
936*181f196bSVijay Mahadevan     if (nverts == 4) { /* Linear Quadrangle */
937*181f196bSVijay Mahadevan       const PetscReal& r = quad[0];
938*181f196bSVijay Mahadevan       const PetscReal& s = quad[1];
939*181f196bSVijay Mahadevan 
940*181f196bSVijay Mahadevan       const PetscReal dNi_dxi[4]  = { -1.0 + s, 1.0 - s, s, -s };
941*181f196bSVijay Mahadevan       const PetscReal dNi_deta[4] = { -1.0 + r, -r, r, 1.0 - r };
942*181f196bSVijay Mahadevan 
943*181f196bSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
944*181f196bSVijay Mahadevan         const PetscReal* vertices = coordinates + i * 3;
945*181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i]  * vertices[0];
946*181f196bSVijay Mahadevan         jacobian[2] += dNi_dxi[i]  * vertices[1];
947*181f196bSVijay Mahadevan         jacobian[1] += dNi_deta[i] * vertices[0];
948*181f196bSVijay Mahadevan         jacobian[3] += dNi_deta[i] * vertices[1];
949*181f196bSVijay Mahadevan       }
950*181f196bSVijay Mahadevan     }
951*181f196bSVijay Mahadevan     else if (nverts == 3) { /* Linear triangle */
952*181f196bSVijay Mahadevan       const PetscReal x2 = coordinates[2 * 3 + 0], y2 = coordinates[2 * 3 + 1];
953*181f196bSVijay Mahadevan 
954*181f196bSVijay Mahadevan       /* Jacobian is constant */
955*181f196bSVijay Mahadevan       jacobian[0] = (coordinates[0 * 3 + 0] - x2); jacobian[1] = (coordinates[1 * 3 + 0] - x2);
956*181f196bSVijay Mahadevan       jacobian[2] = (coordinates[0 * 3 + 1] - y2); jacobian[3] = (coordinates[1 * 3 + 1] - y2);
957*181f196bSVijay Mahadevan     }
958*181f196bSVijay Mahadevan     else {
959*181f196bSVijay Mahadevan       SETERRQ1(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 : %D", nverts);
960*181f196bSVijay Mahadevan     }
961*181f196bSVijay Mahadevan 
962*181f196bSVijay Mahadevan     /* invert the jacobian */
963*181f196bSVijay Mahadevan     if (ijacobian) {
964*181f196bSVijay Mahadevan       ierr = DMatrix_Invert_2x2_Internal(jacobian, ijacobian, volume);CHKERRQ(ierr);
965*181f196bSVijay Mahadevan     }
966*181f196bSVijay Mahadevan 
967*181f196bSVijay Mahadevan   }
968*181f196bSVijay Mahadevan   else {
969*181f196bSVijay Mahadevan 
970*181f196bSVijay Mahadevan     if (nverts == 8) { /* Linear Hexahedra */
971*181f196bSVijay Mahadevan       const PetscReal& r = quad[0];
972*181f196bSVijay Mahadevan       const PetscReal& s = quad[1];
973*181f196bSVijay Mahadevan       const PetscReal& t = quad[2];
974*181f196bSVijay Mahadevan       const PetscReal dNi_dxi[8]  = { - ( 1.0 - s ) * ( 1.0 - t ),
975*181f196bSVijay Mahadevan                                      ( 1.0 - s ) * ( 1.0 - t ),
976*181f196bSVijay Mahadevan                                      ( 1.0 + s ) * ( 1.0 - t ),
977*181f196bSVijay Mahadevan                                      - ( 1.0 + s ) * ( 1.0 - t ),
978*181f196bSVijay Mahadevan                                      - ( 1.0 - s ) * ( 1.0 + t ),
979*181f196bSVijay Mahadevan                                      ( 1.0 - s ) * ( 1.0 + t ),
980*181f196bSVijay Mahadevan                                      ( 1.0 + s ) * ( 1.0 + t ),
981*181f196bSVijay Mahadevan                                      - ( 1.0 + s ) * ( 1.0 + t )
982*181f196bSVijay Mahadevan                                    };
983*181f196bSVijay Mahadevan 
984*181f196bSVijay Mahadevan       const PetscReal dNi_deta[8]  = { - ( 1.0 - r ) * ( 1.0 - t ),
985*181f196bSVijay Mahadevan                                       - ( 1.0 + r ) * ( 1.0 - t ),
986*181f196bSVijay Mahadevan                                       ( 1.0 + r ) * ( 1.0 - t ),
987*181f196bSVijay Mahadevan                                       ( 1.0 - r ) * ( 1.0 - t ),
988*181f196bSVijay Mahadevan                                       - ( 1.0 - r ) * ( 1.0 + t ),
989*181f196bSVijay Mahadevan                                       - ( 1.0 + r ) * ( 1.0 + t ),
990*181f196bSVijay Mahadevan                                       ( 1.0 + r ) * ( 1.0 + t ),
991*181f196bSVijay Mahadevan                                       ( 1.0 - r ) * ( 1.0 + t )
992*181f196bSVijay Mahadevan                                     };
993*181f196bSVijay Mahadevan 
994*181f196bSVijay Mahadevan       const PetscReal dNi_dzeta[8]  = { - ( 1.0 - r ) * ( 1.0 - s ),
995*181f196bSVijay Mahadevan                                        - ( 1.0 + r ) * ( 1.0 - s ),
996*181f196bSVijay Mahadevan                                        - ( 1.0 + r ) * ( 1.0 + s ),
997*181f196bSVijay Mahadevan                                        - ( 1.0 - r ) * ( 1.0 + s ),
998*181f196bSVijay Mahadevan                                        ( 1.0 - r ) * ( 1.0 - s ),
999*181f196bSVijay Mahadevan                                        ( 1.0 + r ) * ( 1.0 - s ),
1000*181f196bSVijay Mahadevan                                        ( 1.0 + r ) * ( 1.0 + s ),
1001*181f196bSVijay Mahadevan                                        ( 1.0 - r ) * ( 1.0 + s )
1002*181f196bSVijay Mahadevan                                      };
1003*181f196bSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
1004*181f196bSVijay Mahadevan         const PetscReal* vertex = coordinates + i * 3;
1005*181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i]   * vertex[0];
1006*181f196bSVijay Mahadevan         jacobian[3] += dNi_dxi[i]   * vertex[1];
1007*181f196bSVijay Mahadevan         jacobian[6] += dNi_dxi[i]   * vertex[2];
1008*181f196bSVijay Mahadevan         jacobian[1] += dNi_deta[i]  * vertex[0];
1009*181f196bSVijay Mahadevan         jacobian[4] += dNi_deta[i]  * vertex[1];
1010*181f196bSVijay Mahadevan         jacobian[7] += dNi_deta[i]  * vertex[2];
1011*181f196bSVijay Mahadevan         jacobian[2] += dNi_dzeta[i] * vertex[0];
1012*181f196bSVijay Mahadevan         jacobian[5] += dNi_dzeta[i] * vertex[1];
1013*181f196bSVijay Mahadevan         jacobian[8] += dNi_dzeta[i] * vertex[2];
1014*181f196bSVijay Mahadevan       }
1015*181f196bSVijay Mahadevan 
1016*181f196bSVijay Mahadevan     }
1017*181f196bSVijay Mahadevan     else if (nverts == 4) { /* Linear Tetrahedra */
1018*181f196bSVijay Mahadevan       const PetscReal x0 = coordinates[/*0 * 3 +*/ 0], y0 = coordinates[/*0 * 3 +*/ 1], z0 = coordinates[/*0 * 3 +*/ 2];
1019*181f196bSVijay Mahadevan 
1020*181f196bSVijay Mahadevan       /* compute the jacobian */
1021*181f196bSVijay Mahadevan       jacobian[0] = coordinates[1 * 3 + 0] - x0;  jacobian[1] = coordinates[2 * 3 + 0] - x0; jacobian[2] = coordinates[3 * 3 + 0] - x0;
1022*181f196bSVijay Mahadevan       jacobian[3] = coordinates[1 * 3 + 1] - y0;  jacobian[4] = coordinates[2 * 3 + 1] - y0; jacobian[5] = coordinates[3 * 3 + 1] - y0;
1023*181f196bSVijay Mahadevan       jacobian[6] = coordinates[1 * 3 + 2] - z0;  jacobian[7] = coordinates[2 * 3 + 2] - z0; jacobian[8] = coordinates[3 * 3 + 2] - z0;
1024*181f196bSVijay Mahadevan     } /* Tetrahedra -- ends */
1025*181f196bSVijay Mahadevan     else
1026*181f196bSVijay Mahadevan     {
1027*181f196bSVijay Mahadevan       SETERRQ1(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 : %D", nverts);
1028*181f196bSVijay Mahadevan     }
1029*181f196bSVijay Mahadevan 
1030*181f196bSVijay Mahadevan     if (ijacobian) {
1031*181f196bSVijay Mahadevan       /* invert the jacobian */
1032*181f196bSVijay Mahadevan       ierr = DMatrix_Invert_3x3_Internal(jacobian, ijacobian, volume);CHKERRQ(ierr);
1033*181f196bSVijay Mahadevan     }
1034*181f196bSVijay Mahadevan 
1035*181f196bSVijay Mahadevan   }
1036*181f196bSVijay Mahadevan   if ( volume && *volume < 1e-12 ) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Element has zero volume: %g. Degenerate element or invalid connectivity\n", volume);
1037*181f196bSVijay Mahadevan   PetscFunctionReturn(0);
1038*181f196bSVijay Mahadevan }
1039*181f196bSVijay Mahadevan 
1040*181f196bSVijay Mahadevan 
1041*181f196bSVijay Mahadevan #undef __FUNCT__
1042*181f196bSVijay Mahadevan #define __FUNCT__ "FEMComputeBasis_JandF"
1043*181f196bSVijay Mahadevan PetscErrorCode FEMComputeBasis_JandF ( const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscReal *quadrature, PetscReal *phypts,
1044*181f196bSVijay Mahadevan                                        PetscReal *phibasis, PetscReal *jacobian, PetscReal *ijacobian, PetscReal* volume  )
1045*181f196bSVijay Mahadevan {
1046*181f196bSVijay Mahadevan   PetscErrorCode  ierr;
1047*181f196bSVijay Mahadevan 
1048*181f196bSVijay Mahadevan   PetscFunctionBegin;
1049*181f196bSVijay Mahadevan 
1050*181f196bSVijay Mahadevan   switch (dim) {
1051*181f196bSVijay Mahadevan   case 1:
1052*181f196bSVijay Mahadevan     ierr = Compute_Lagrange_Basis_1D_Internal(nverts, coordinates, 1, quadrature, phypts,
1053*181f196bSVijay Mahadevan            NULL, phibasis, NULL, jacobian, ijacobian, volume);CHKERRQ(ierr);
1054*181f196bSVijay Mahadevan     break;
1055*181f196bSVijay Mahadevan   case 2:
1056*181f196bSVijay Mahadevan     ierr = Compute_Lagrange_Basis_2D_Internal(nverts, coordinates, 1, quadrature, phypts,
1057*181f196bSVijay Mahadevan            NULL, phibasis, NULL, NULL, jacobian, ijacobian, volume);CHKERRQ(ierr);
1058*181f196bSVijay Mahadevan     break;
1059*181f196bSVijay Mahadevan   case 3:
1060*181f196bSVijay Mahadevan     ierr = Compute_Lagrange_Basis_3D_Internal(nverts, coordinates, 1, quadrature, phypts,
1061*181f196bSVijay Mahadevan            NULL, phibasis, NULL, NULL, NULL, jacobian, ijacobian, volume);CHKERRQ(ierr);
1062*181f196bSVijay Mahadevan     break;
1063*181f196bSVijay Mahadevan   default:
1064*181f196bSVijay Mahadevan     SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %D", dim);
1065*181f196bSVijay Mahadevan   }
1066*181f196bSVijay Mahadevan   PetscFunctionReturn(0);
1067*181f196bSVijay Mahadevan }
1068*181f196bSVijay Mahadevan 
1069*181f196bSVijay Mahadevan 
1070*181f196bSVijay Mahadevan 
1071*181f196bSVijay Mahadevan #undef __FUNCT__
1072*181f196bSVijay Mahadevan #define __FUNCT__ "DMMoabPToRMapping"
1073*181f196bSVijay Mahadevan PetscErrorCode DMMoabPToRMapping( const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscReal* xphy, PetscReal* natparam, PetscReal* phi)
1074*181f196bSVijay Mahadevan {
1075*181f196bSVijay Mahadevan   // Perform inverse evaluation for the mapping with use of Newton Raphson iteration
1076*181f196bSVijay Mahadevan   const PetscReal tol = 1.0e-10;
1077*181f196bSVijay Mahadevan   const PetscInt max_iterations = 10;
1078*181f196bSVijay Mahadevan   const PetscReal error_tol_sqr = tol*tol;
1079*181f196bSVijay Mahadevan   PetscReal phibasis[8], jacobian[9], ijacobian[9], volume;
1080*181f196bSVijay Mahadevan   PetscReal phypts[3] = {0.0, 0.0, 0.0};
1081*181f196bSVijay Mahadevan   PetscReal delta[3] = {0.0, 0.0, 0.0};
1082*181f196bSVijay Mahadevan   PetscErrorCode  ierr;
1083*181f196bSVijay Mahadevan   PetscInt iters=0;
1084*181f196bSVijay Mahadevan   PetscReal error=1.0;
1085*181f196bSVijay Mahadevan 
1086*181f196bSVijay Mahadevan   PetscFunctionBegin;
1087*181f196bSVijay Mahadevan   PetscValidPointer(coordinates, 3);
1088*181f196bSVijay Mahadevan   PetscValidPointer(xphy, 4);
1089*181f196bSVijay Mahadevan   PetscValidPointer(natparam, 5);
1090*181f196bSVijay Mahadevan 
1091*181f196bSVijay Mahadevan   ierr = PetscMemzero(natparam, 3 * sizeof(PetscReal));CHKERRQ(ierr);
1092*181f196bSVijay Mahadevan   ierr = PetscMemzero(jacobian, dim * dim * sizeof(PetscReal));CHKERRQ(ierr);
1093*181f196bSVijay Mahadevan   ierr = PetscMemzero(ijacobian, dim * dim * sizeof(PetscReal));CHKERRQ(ierr);
1094*181f196bSVijay Mahadevan   ierr = PetscMemzero(phibasis, nverts * sizeof(PetscReal));CHKERRQ(ierr);
1095*181f196bSVijay Mahadevan 
1096*181f196bSVijay Mahadevan   /* Compute delta = evaluate( xi ) - x */
1097*181f196bSVijay Mahadevan   ierr = FEMComputeBasis_JandF ( dim, nverts, coordinates, natparam, phypts, phi, jacobian, ijacobian, &volume );CHKERRQ(ierr);
1098*181f196bSVijay Mahadevan 
1099*181f196bSVijay Mahadevan   delta[0] = phypts[0] - xphy[0];
1100*181f196bSVijay Mahadevan   delta[1] = phypts[1] - xphy[1];
1101*181f196bSVijay Mahadevan   delta[2] = phypts[2] - xphy[2];
1102*181f196bSVijay Mahadevan   error = (delta[0]*delta[0] + delta[1]*delta[1] + delta[2]*delta[2]);
1103*181f196bSVijay Mahadevan 
1104*181f196bSVijay Mahadevan   while (error > error_tol_sqr) {
1105*181f196bSVijay Mahadevan 
1106*181f196bSVijay Mahadevan     if(++iters > max_iterations)
1107*181f196bSVijay Mahadevan       SETERRQ3(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]);
1108*181f196bSVijay Mahadevan 
1109*181f196bSVijay Mahadevan     /* Compute natparam -= J.inverse() * delta */
1110*181f196bSVijay Mahadevan     switch(dim) {
1111*181f196bSVijay Mahadevan       case 1:
1112*181f196bSVijay Mahadevan         natparam[0] -= ijacobian[0] * delta[0];
1113*181f196bSVijay Mahadevan         break;
1114*181f196bSVijay Mahadevan       case 2:
1115*181f196bSVijay Mahadevan         natparam[0] -= ijacobian[0] * delta[0] + ijacobian[1] * delta[1];
1116*181f196bSVijay Mahadevan         natparam[1] -= ijacobian[2] * delta[0] + ijacobian[3] * delta[1];
1117*181f196bSVijay Mahadevan         break;
1118*181f196bSVijay Mahadevan       case 3:
1119*181f196bSVijay Mahadevan         natparam[0] -= ijacobian[0] * delta[0] + ijacobian[1] * delta[1] + ijacobian[2] * delta[2];
1120*181f196bSVijay Mahadevan         natparam[1] -= ijacobian[3] * delta[0] + ijacobian[4] * delta[1] + ijacobian[5] * delta[2];
1121*181f196bSVijay Mahadevan         natparam[2] -= ijacobian[6] * delta[0] + ijacobian[7] * delta[1] + ijacobian[8] * delta[2];
1122*181f196bSVijay Mahadevan         break;
1123*181f196bSVijay Mahadevan     }
1124*181f196bSVijay Mahadevan 
1125*181f196bSVijay Mahadevan     /* Compute delta = evaluate( xi ) - x */
1126*181f196bSVijay Mahadevan     ierr = FEMComputeBasis_JandF ( dim, nverts, coordinates, natparam, phypts, phi, jacobian, ijacobian, &volume );CHKERRQ(ierr);
1127*181f196bSVijay Mahadevan 
1128*181f196bSVijay Mahadevan     delta[0] = phypts[0] - xphy[0];
1129*181f196bSVijay Mahadevan     delta[1] = phypts[1] - xphy[1];
1130*181f196bSVijay Mahadevan     delta[2] = phypts[2] - xphy[2];
1131*181f196bSVijay Mahadevan     error = (delta[0]*delta[0] + delta[1]*delta[1] + delta[2]*delta[2]);
1132*181f196bSVijay Mahadevan   }
1133*181f196bSVijay Mahadevan   if (phi) {
1134*181f196bSVijay Mahadevan     ierr = PetscMemcpy(phi, phibasis, nverts * sizeof(PetscReal));CHKERRQ(ierr);
1135*181f196bSVijay Mahadevan   }
1136*181f196bSVijay Mahadevan   PetscFunctionReturn(0);
1137*181f196bSVijay Mahadevan }
1138*181f196bSVijay Mahadevan 
1139