xref: /petsc/src/dm/impls/moab/dmmbfem.cxx (revision 63d025db7609f1d3caad584ea351809d563b52f4)
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