xref: /petsc/src/dm/impls/moab/dmmbfem.cxx (revision 97b73a88eb11698f8fb1e5916bdd90ae585b3943)
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 
1263d025dbSVijay Mahadevan static inline PetscErrorCode DMatrix_Invert_2x2_Internal (const PetscReal *inmat, PetscReal *outmat, PetscReal *determinant)
1363d025dbSVijay Mahadevan {
1463d025dbSVijay Mahadevan   if (!inmat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_POINTER, "Invalid input matrix specified for 2x2 inversion.");
1563d025dbSVijay Mahadevan   PetscReal det = DMatrix_Determinant_2x2_Internal(inmat);
1663d025dbSVijay Mahadevan   if (outmat) {
1763d025dbSVijay Mahadevan     outmat[0] = inmat[3] / det;
1863d025dbSVijay Mahadevan     outmat[1] = -inmat[1] / det;
1963d025dbSVijay Mahadevan     outmat[2] = -inmat[2] / det;
2063d025dbSVijay Mahadevan     outmat[3] = inmat[0] / det;
2163d025dbSVijay Mahadevan   }
2263d025dbSVijay Mahadevan   if (determinant) *determinant = det;
2363d025dbSVijay Mahadevan   PetscFunctionReturn(0);
2463d025dbSVijay Mahadevan }
2563d025dbSVijay Mahadevan 
26181f196bSVijay Mahadevan static inline PetscReal DMatrix_Determinant_3x3_Internal ( const PetscReal inmat[3 * 3] )
2763d025dbSVijay Mahadevan {
2863d025dbSVijay Mahadevan   return   inmat[0] * (inmat[8] * inmat[4] - inmat[7] * inmat[5])
2963d025dbSVijay Mahadevan            - inmat[3] * (inmat[8] * inmat[1] - inmat[7] * inmat[2])
3063d025dbSVijay Mahadevan            + inmat[6] * (inmat[5] * inmat[1] - inmat[4] * inmat[2]);
3163d025dbSVijay Mahadevan }
3263d025dbSVijay Mahadevan 
3363d025dbSVijay Mahadevan static inline PetscErrorCode DMatrix_Invert_3x3_Internal (const PetscReal *inmat, PetscReal *outmat, PetscScalar *determinant)
3463d025dbSVijay Mahadevan {
3563d025dbSVijay Mahadevan   if (!inmat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_POINTER, "Invalid input matrix specified for 3x3 inversion.");
36181f196bSVijay Mahadevan   PetscReal det = DMatrix_Determinant_3x3_Internal(inmat);
3763d025dbSVijay Mahadevan   if (outmat) {
3863d025dbSVijay Mahadevan     outmat[0] = (inmat[8] * inmat[4] - inmat[7] * inmat[5]) / det;
3963d025dbSVijay Mahadevan     outmat[1] = -(inmat[8] * inmat[1] - inmat[7] * inmat[2]) / det;
4063d025dbSVijay Mahadevan     outmat[2] = (inmat[5] * inmat[1] - inmat[4] * inmat[2]) / det;
4163d025dbSVijay Mahadevan     outmat[3] = -(inmat[8] * inmat[3] - inmat[6] * inmat[5]) / det;
4263d025dbSVijay Mahadevan     outmat[4] = (inmat[8] * inmat[0] - inmat[6] * inmat[2]) / det;
4363d025dbSVijay Mahadevan     outmat[5] = -(inmat[5] * inmat[0] - inmat[3] * inmat[2]) / det;
4463d025dbSVijay Mahadevan     outmat[6] = (inmat[7] * inmat[3] - inmat[6] * inmat[4]) / det;
4563d025dbSVijay Mahadevan     outmat[7] = -(inmat[7] * inmat[0] - inmat[6] * inmat[1]) / det;
4663d025dbSVijay Mahadevan     outmat[8] = (inmat[4] * inmat[0] - inmat[3] * inmat[1]) / det;
4763d025dbSVijay Mahadevan   }
4863d025dbSVijay Mahadevan   if (determinant) *determinant = det;
4963d025dbSVijay Mahadevan   PetscFunctionReturn(0);
5063d025dbSVijay Mahadevan }
5163d025dbSVijay Mahadevan 
52181f196bSVijay Mahadevan inline PetscReal DMatrix_Determinant_4x4_Internal ( PetscReal inmat[4 * 4] )
53181f196bSVijay Mahadevan {
54181f196bSVijay Mahadevan   return
55181f196bSVijay Mahadevan     inmat[0 + 0 * 4] * (
56181f196bSVijay Mahadevan       inmat[1 + 1 * 4] * ( inmat[2 + 2 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 2 * 4] )
57181f196bSVijay Mahadevan       - inmat[1 + 2 * 4] * ( inmat[2 + 1 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 1 * 4] )
58181f196bSVijay Mahadevan       + inmat[1 + 3 * 4] * ( inmat[2 + 1 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 1 * 4] ) )
59181f196bSVijay Mahadevan     - inmat[0 + 1 * 4] * (
60181f196bSVijay Mahadevan       inmat[1 + 0 * 4] * ( inmat[2 + 2 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 2 * 4] )
61181f196bSVijay Mahadevan       - inmat[1 + 2 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 0 * 4] )
62181f196bSVijay Mahadevan       + inmat[1 + 3 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 0 * 4] ) )
63181f196bSVijay Mahadevan     + inmat[0 + 2 * 4] * (
64181f196bSVijay Mahadevan       inmat[1 + 0 * 4] * ( inmat[2 + 1 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 1 * 4] )
65181f196bSVijay Mahadevan       - inmat[1 + 1 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 3 * 4] - inmat[2 + 3 * 4] * inmat[3 + 0 * 4] )
66181f196bSVijay Mahadevan       + inmat[1 + 3 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 1 * 4] - inmat[2 + 1 * 4] * inmat[3 + 0 * 4] ) )
67181f196bSVijay Mahadevan     - inmat[0 + 3 * 4] * (
68181f196bSVijay Mahadevan       inmat[1 + 0 * 4] * ( inmat[2 + 1 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 1 * 4] )
69181f196bSVijay Mahadevan       - inmat[1 + 1 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 2 * 4] - inmat[2 + 2 * 4] * inmat[3 + 0 * 4] )
70181f196bSVijay Mahadevan       + inmat[1 + 2 * 4] * ( inmat[2 + 0 * 4] * inmat[3 + 1 * 4] - inmat[2 + 1 * 4] * inmat[3 + 0 * 4] ) );
71181f196bSVijay Mahadevan }
72181f196bSVijay Mahadevan 
73181f196bSVijay Mahadevan inline PetscErrorCode DMatrix_Invert_4x4_Internal (PetscReal *inmat, PetscReal *outmat, PetscScalar *determinant)
74181f196bSVijay Mahadevan {
75181f196bSVijay Mahadevan   if (!inmat) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_POINTER, "Invalid input matrix specified for 4x4 inversion.");
76181f196bSVijay Mahadevan   PetscReal det = DMatrix_Determinant_4x4_Internal(inmat);
77181f196bSVijay Mahadevan   if (outmat) {
78181f196bSVijay 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;
79181f196bSVijay 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;
80181f196bSVijay 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;
81181f196bSVijay 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;
82181f196bSVijay 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;
83181f196bSVijay 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;
84181f196bSVijay 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;
85181f196bSVijay 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;
86181f196bSVijay 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;
87181f196bSVijay 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;
88181f196bSVijay 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;
89181f196bSVijay 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;
90181f196bSVijay 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;
91181f196bSVijay 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;
92181f196bSVijay 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;
93181f196bSVijay 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;
94181f196bSVijay Mahadevan   }
95181f196bSVijay Mahadevan   if (determinant) *determinant = det;
96181f196bSVijay Mahadevan   PetscFunctionReturn(0);
97181f196bSVijay Mahadevan }
98181f196bSVijay Mahadevan 
9963d025dbSVijay Mahadevan 
10063d025dbSVijay Mahadevan /*@
101*97b73a88SSatish Balay   Compute_Lagrange_Basis_1D_Internal - Evaluate bases and derivatives at quadrature points for a EDGE2 or EDGE3 element.
10263d025dbSVijay Mahadevan 
10363d025dbSVijay Mahadevan   The routine is given the coordinates of the vertices of a linear or quadratic edge element.
10463d025dbSVijay Mahadevan 
10563d025dbSVijay Mahadevan   The routine evaluates the basis functions associated with each quadrature point provided,
10663d025dbSVijay Mahadevan   and their derivatives with respect to X.
10763d025dbSVijay Mahadevan 
10863d025dbSVijay Mahadevan   Notes:
10963d025dbSVijay Mahadevan 
11063d025dbSVijay Mahadevan   Example Physical Element
11163d025dbSVijay Mahadevan 
11263d025dbSVijay Mahadevan     1-------2        1----3----2
11363d025dbSVijay Mahadevan       EDGE2             EDGE3
11463d025dbSVijay Mahadevan 
11563d025dbSVijay Mahadevan   Input Parameter:
11663d025dbSVijay Mahadevan 
11763d025dbSVijay Mahadevan .  PetscInt  nverts,           the number of element vertices
11863d025dbSVijay Mahadevan .  PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering)
11963d025dbSVijay Mahadevan .  PetscInt  npts,             the number of evaluation points (quadrature points)
12063d025dbSVijay Mahadevan .  PetscReal quad[3*npts],     the evaluation points (quadrature points) in the reference space
12163d025dbSVijay Mahadevan 
12263d025dbSVijay Mahadevan   Output Parameter:
12363d025dbSVijay Mahadevan .  PetscReal phypts[3*npts],   the evaluation points (quadrature points) transformed to the physical space
12463d025dbSVijay Mahadevan .  PetscReal jxw[npts],        the jacobian determinant * quadrature weight necessary for assembling discrete contributions
12563d025dbSVijay Mahadevan .  PetscReal phi[npts],        the bases evaluated at the specified quadrature points
12663d025dbSVijay Mahadevan .  PetscReal dphidx[npts],     the derivative of the bases wrt X-direction evaluated at the specified quadrature points
12763d025dbSVijay Mahadevan 
12863d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 1-D
12963d025dbSVijay Mahadevan @*/
13063d025dbSVijay Mahadevan PetscErrorCode Compute_Lagrange_Basis_1D_Internal ( const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts,
131181f196bSVijay Mahadevan     PetscReal *jxw, PetscReal *phi, PetscReal *dphidx,
132181f196bSVijay Mahadevan     PetscReal *jacobian, PetscReal *ijacobian, PetscReal *volume)
13363d025dbSVijay Mahadevan {
13463d025dbSVijay Mahadevan   int i, j;
13563d025dbSVijay Mahadevan   PetscErrorCode  ierr;
13663d025dbSVijay Mahadevan 
137181f196bSVijay Mahadevan   PetscFunctionBegin;
138181f196bSVijay Mahadevan   PetscValidPointer(jacobian, 9);
139181f196bSVijay Mahadevan   PetscValidPointer(ijacobian, 10);
140181f196bSVijay Mahadevan   PetscValidPointer(volume, 11);
141181f196bSVijay Mahadevan   if (phypts) {
14263d025dbSVijay Mahadevan     ierr = PetscMemzero(phypts, npts * 3 * sizeof(PetscReal));CHKERRQ(ierr);
143181f196bSVijay Mahadevan   }
14463d025dbSVijay Mahadevan   if (dphidx) { /* Reset arrays. */
14563d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidx, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
14663d025dbSVijay Mahadevan   }
14763d025dbSVijay Mahadevan   if (nverts == 2) { /* Linear Edge */
14863d025dbSVijay Mahadevan 
14963d025dbSVijay Mahadevan     for (j = 0; j < npts; j++)
15063d025dbSVijay Mahadevan     {
151a86ed394SVijay Mahadevan       const PetscInt offset = j * nverts;
152181f196bSVijay Mahadevan       const PetscReal r = quad[j];
15363d025dbSVijay Mahadevan 
154181f196bSVijay Mahadevan       phi[0 + offset] = ( 1.0 - r );
155181f196bSVijay Mahadevan       phi[1 + offset] = (       r );
15663d025dbSVijay Mahadevan 
157181f196bSVijay Mahadevan       const PetscReal dNi_dxi[2]  = { -1.0, 1.0 };
15863d025dbSVijay Mahadevan 
159181f196bSVijay Mahadevan       jacobian[0] = ijacobian[0] = volume[0] = 0.0;
16063d025dbSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
161181f196bSVijay Mahadevan         const PetscReal* vertices = coords + i * 3;
162181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i] * vertices[0];
163181f196bSVijay Mahadevan         if (phypts) {
164181f196bSVijay Mahadevan           phypts[3 * j + 0] += phi[i + offset] * vertices[0];
165181f196bSVijay Mahadevan         }
16663d025dbSVijay Mahadevan       }
16763d025dbSVijay Mahadevan 
16863d025dbSVijay Mahadevan       /* invert the jacobian */
169181f196bSVijay Mahadevan       *volume = jacobian[0];
170181f196bSVijay Mahadevan       ijacobian[0] = 1.0 / jacobian[0];
171181f196bSVijay Mahadevan       jxw[j] *= *volume;
17263d025dbSVijay Mahadevan 
17363d025dbSVijay Mahadevan       /*  Divide by element jacobian. */
17463d025dbSVijay Mahadevan       for ( i = 0; i < nverts; i++ ) {
175181f196bSVijay Mahadevan         if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[0];
17663d025dbSVijay Mahadevan       }
17763d025dbSVijay Mahadevan 
17863d025dbSVijay Mahadevan     }
17963d025dbSVijay Mahadevan   }
18063d025dbSVijay Mahadevan   else if (nverts == 3) { /* Quadratic Edge */
18163d025dbSVijay Mahadevan 
18263d025dbSVijay Mahadevan     for (j = 0; j < npts; j++)
18363d025dbSVijay Mahadevan     {
184a86ed394SVijay Mahadevan       const PetscInt offset = j * nverts;
185181f196bSVijay Mahadevan       const PetscReal r = quad[j];
18663d025dbSVijay Mahadevan 
187181f196bSVijay Mahadevan       phi[0 + offset] = 1.0 + r * ( 2.0 * r - 3.0 );
188181f196bSVijay Mahadevan       phi[1 + offset] = 4.0 * r * ( 1.0 - r );
189181f196bSVijay Mahadevan       phi[2 + offset] = r * ( 2.0 * r - 1.0 );
19063d025dbSVijay Mahadevan 
191181f196bSVijay Mahadevan       const PetscReal dNi_dxi[3]  = { 4 * r - 3.0, 4 * ( 1.0 - 2.0 * r ), 4.0 * r - 1.0};
19263d025dbSVijay Mahadevan 
193181f196bSVijay Mahadevan       jacobian[0] = ijacobian[0] = volume[0] = 0.0;
19463d025dbSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
195181f196bSVijay Mahadevan         const PetscReal* vertices = coords + i * 3;
196181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i] * vertices[0];
197181f196bSVijay Mahadevan         if (phypts) {
198181f196bSVijay Mahadevan           phypts[3 * j + 0] += phi[i + offset] * vertices[0];
199181f196bSVijay Mahadevan         }
20063d025dbSVijay Mahadevan       }
20163d025dbSVijay Mahadevan 
20263d025dbSVijay Mahadevan       /* invert the jacobian */
203181f196bSVijay Mahadevan       *volume = jacobian[0];
204181f196bSVijay Mahadevan       ijacobian[0] = 1.0 / jacobian[0];
205181f196bSVijay Mahadevan       if (jxw) jxw[j] *= *volume;
20663d025dbSVijay Mahadevan 
20763d025dbSVijay Mahadevan       /*  Divide by element jacobian. */
20863d025dbSVijay Mahadevan       for ( i = 0; i < nverts; i++ ) {
209181f196bSVijay Mahadevan         if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[0];
21063d025dbSVijay Mahadevan       }
21163d025dbSVijay Mahadevan     }
21263d025dbSVijay Mahadevan   }
21363d025dbSVijay Mahadevan   else {
21463d025dbSVijay 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);
21563d025dbSVijay Mahadevan   }
21663d025dbSVijay Mahadevan #if 0
21763d025dbSVijay Mahadevan   /* verify if the computed basis functions are consistent */
21863d025dbSVijay Mahadevan   for ( j = 0; j < npts; j++ ) {
21963d025dbSVijay Mahadevan     PetscScalar phisum = 0, dphixsum = 0;
22063d025dbSVijay Mahadevan     for ( i = 0; i < nverts; i++ ) {
22163d025dbSVijay Mahadevan       phisum += phi[i + j * nverts];
22263d025dbSVijay Mahadevan       if (dphidx) dphixsum += dphidx[i + j * nverts];
22363d025dbSVijay Mahadevan     }
22463d025dbSVijay Mahadevan     PetscPrintf(PETSC_COMM_WORLD, "Sum of basis at quadrature point %D = %g, %g, %g\n", j, phisum, dphixsum);
22563d025dbSVijay Mahadevan   }
22663d025dbSVijay Mahadevan #endif
22763d025dbSVijay Mahadevan   PetscFunctionReturn(0);
22863d025dbSVijay Mahadevan }
22963d025dbSVijay Mahadevan 
23063d025dbSVijay Mahadevan 
23163d025dbSVijay Mahadevan /*@
232*97b73a88SSatish Balay   Compute_Lagrange_Basis_2D_Internal - Evaluate bases and derivatives at quadrature points for a QUAD4 or TRI3 element.
23363d025dbSVijay Mahadevan 
23463d025dbSVijay Mahadevan   The routine is given the coordinates of the vertices of a quadrangle or triangle.
23563d025dbSVijay Mahadevan 
23663d025dbSVijay Mahadevan   The routine evaluates the basis functions associated with each quadrature point provided,
23763d025dbSVijay Mahadevan   and their derivatives with respect to X and Y.
23863d025dbSVijay Mahadevan 
23963d025dbSVijay Mahadevan   Notes:
24063d025dbSVijay Mahadevan 
24163d025dbSVijay Mahadevan   Example Physical Element (QUAD4)
24263d025dbSVijay Mahadevan 
24363d025dbSVijay Mahadevan     4------3        s
24463d025dbSVijay Mahadevan     |      |        |
24563d025dbSVijay Mahadevan     |      |        |
24663d025dbSVijay Mahadevan     |      |        |
24763d025dbSVijay Mahadevan     1------2        0-------r
24863d025dbSVijay Mahadevan 
24963d025dbSVijay Mahadevan   Input Parameter:
25063d025dbSVijay Mahadevan 
25163d025dbSVijay Mahadevan .  PetscInt  nverts,           the number of element vertices
25263d025dbSVijay Mahadevan .  PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering)
25363d025dbSVijay Mahadevan .  PetscInt  npts,             the number of evaluation points (quadrature points)
25463d025dbSVijay Mahadevan .  PetscReal quad[3*npts],     the evaluation points (quadrature points) in the reference space
25563d025dbSVijay Mahadevan 
25663d025dbSVijay Mahadevan   Output Parameter:
25763d025dbSVijay Mahadevan .  PetscReal phypts[3*npts],   the evaluation points (quadrature points) transformed to the physical space
25863d025dbSVijay Mahadevan .  PetscReal jxw[npts],        the jacobian determinant * quadrature weight necessary for assembling discrete contributions
25963d025dbSVijay Mahadevan .  PetscReal phi[npts],        the bases evaluated at the specified quadrature points
26063d025dbSVijay Mahadevan .  PetscReal dphidx[npts],     the derivative of the bases wrt X-direction evaluated at the specified quadrature points
26163d025dbSVijay Mahadevan .  PetscReal dphidy[npts],     the derivative of the bases wrt Y-direction evaluated at the specified quadrature points
26263d025dbSVijay Mahadevan 
26363d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 2-D
26463d025dbSVijay Mahadevan @*/
26563d025dbSVijay Mahadevan PetscErrorCode Compute_Lagrange_Basis_2D_Internal ( const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts,
266181f196bSVijay Mahadevan     PetscReal *jxw, PetscReal *phi, PetscReal *dphidx, PetscReal *dphidy,
267181f196bSVijay Mahadevan     PetscReal *jacobian, PetscReal *ijacobian, PetscReal *volume)
26863d025dbSVijay Mahadevan {
269a86ed394SVijay Mahadevan   PetscInt i, j, k;
27063d025dbSVijay Mahadevan   PetscErrorCode   ierr;
27163d025dbSVijay Mahadevan 
27263d025dbSVijay Mahadevan   PetscFunctionBegin;
273181f196bSVijay Mahadevan   PetscValidPointer(jacobian, 10);
274181f196bSVijay Mahadevan   PetscValidPointer(ijacobian, 11);
275181f196bSVijay Mahadevan   PetscValidPointer(volume, 12);
27663d025dbSVijay Mahadevan   ierr = PetscMemzero(phi, npts * sizeof(PetscReal));CHKERRQ(ierr);
277181f196bSVijay Mahadevan   if (phypts) {
27863d025dbSVijay Mahadevan     ierr = PetscMemzero(phypts, npts * 3 * sizeof(PetscReal));CHKERRQ(ierr);
279181f196bSVijay Mahadevan   }
28063d025dbSVijay Mahadevan   if (dphidx) { /* Reset arrays. */
28163d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidx, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
28263d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidy, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
28363d025dbSVijay Mahadevan   }
28463d025dbSVijay Mahadevan   if (nverts == 4) { /* Linear Quadrangle */
28563d025dbSVijay Mahadevan 
28663d025dbSVijay Mahadevan     for (j = 0; j < npts; j++)
28763d025dbSVijay Mahadevan     {
288a86ed394SVijay Mahadevan       const PetscInt offset = j * nverts;
289181f196bSVijay Mahadevan       const PetscReal r = quad[0 + j * 2];
290181f196bSVijay Mahadevan       const PetscReal s = quad[1 + j * 2];
29163d025dbSVijay Mahadevan 
29263d025dbSVijay Mahadevan       phi[0 + offset] = ( 1.0 - r ) * ( 1.0 - s );
29363d025dbSVijay Mahadevan       phi[1 + offset] =         r   * ( 1.0 - s );
29463d025dbSVijay Mahadevan       phi[2 + offset] =         r   *         s;
29563d025dbSVijay Mahadevan       phi[3 + offset] = ( 1.0 - r ) *         s;
29663d025dbSVijay Mahadevan 
297181f196bSVijay Mahadevan       const PetscReal dNi_dxi[4]  = { -1.0 + s, 1.0 - s, s, -s };
298181f196bSVijay Mahadevan       const PetscReal dNi_deta[4] = { -1.0 + r, -r, r, 1.0 - r };
29963d025dbSVijay Mahadevan 
30063d025dbSVijay Mahadevan       ierr = PetscMemzero(jacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr);
30163d025dbSVijay Mahadevan       ierr = PetscMemzero(ijacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr);
30263d025dbSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
303181f196bSVijay Mahadevan         const PetscReal* vertices = coords + i * 3;
30463d025dbSVijay Mahadevan         jacobian[0] += dNi_dxi[i] * vertices[0];
30563d025dbSVijay Mahadevan         jacobian[2] += dNi_dxi[i] * vertices[1];
30663d025dbSVijay Mahadevan         jacobian[1] += dNi_deta[i] * vertices[0];
30763d025dbSVijay Mahadevan         jacobian[3] += dNi_deta[i] * vertices[1];
308181f196bSVijay Mahadevan         if (phypts) {
309181f196bSVijay Mahadevan           phypts[3 * j + 0] += phi[i + offset] * vertices[0];
310181f196bSVijay Mahadevan           phypts[3 * j + 1] += phi[i + offset] * vertices[1];
311181f196bSVijay Mahadevan           phypts[3 * j + 2] += phi[i + offset] * vertices[2];
312181f196bSVijay Mahadevan         }
31363d025dbSVijay Mahadevan       }
31463d025dbSVijay Mahadevan 
31563d025dbSVijay Mahadevan       /* invert the jacobian */
316181f196bSVijay Mahadevan       ierr = DMatrix_Invert_2x2_Internal(jacobian, ijacobian, volume);CHKERRQ(ierr);
317181f196bSVijay 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);
31863d025dbSVijay Mahadevan 
319181f196bSVijay Mahadevan       if (jxw) jxw[j] *= *volume;
32063d025dbSVijay Mahadevan 
321181f196bSVijay Mahadevan       /*  Let us compute the bases derivatives by scaling with inverse jacobian. */
322181f196bSVijay Mahadevan       if (dphidx) {
32363d025dbSVijay Mahadevan         for ( i = 0; i < nverts; i++ ) {
324a86ed394SVijay Mahadevan           for ( k = 0; k < 2; ++k) {
32563d025dbSVijay Mahadevan             if (dphidx) dphidx[i + offset] += dNi_dxi[i] * ijacobian[k * 2 + 0];
32663d025dbSVijay Mahadevan             if (dphidy) dphidy[i + offset] += dNi_deta[i] * ijacobian[k * 2 + 1];
327181f196bSVijay Mahadevan           } /* for k=[0..2) */
328181f196bSVijay Mahadevan         } /* for i=[0..nverts) */
329181f196bSVijay Mahadevan       } /* if (dphidx) */
33063d025dbSVijay Mahadevan     }
33163d025dbSVijay Mahadevan   }
33263d025dbSVijay Mahadevan   else if (nverts == 3) { /* Linear triangle */
33363d025dbSVijay Mahadevan 
33463d025dbSVijay Mahadevan     ierr = PetscMemzero(jacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr);
33563d025dbSVijay Mahadevan     ierr = PetscMemzero(ijacobian, 4 * sizeof(PetscReal));CHKERRQ(ierr);
33663d025dbSVijay Mahadevan 
337181f196bSVijay Mahadevan     const PetscReal x2 = coords[2 * 3 + 0], y2 = coords[2 * 3 + 1];
338181f196bSVijay Mahadevan 
33963d025dbSVijay Mahadevan     /* Jacobian is constant */
340181f196bSVijay Mahadevan     jacobian[0] = (coords[0 * 3 + 0] - x2); jacobian[1] = (coords[1 * 3 + 0] - x2);
341181f196bSVijay Mahadevan     jacobian[2] = (coords[0 * 3 + 1] - y2); jacobian[3] = (coords[1 * 3 + 1] - y2);
34263d025dbSVijay Mahadevan 
34363d025dbSVijay Mahadevan     /* invert the jacobian */
344181f196bSVijay Mahadevan     ierr = DMatrix_Invert_2x2_Internal(jacobian, ijacobian, volume);CHKERRQ(ierr);
345181f196bSVijay 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);
346181f196bSVijay Mahadevan 
347181f196bSVijay Mahadevan     const PetscReal Dx[3] = { ijacobian[0], ijacobian[2], - ijacobian[0] - ijacobian[2] };
348181f196bSVijay Mahadevan     const PetscReal Dy[3] = { ijacobian[1], ijacobian[3], - ijacobian[1] - ijacobian[3] };
34963d025dbSVijay Mahadevan 
35063d025dbSVijay Mahadevan     for (j = 0; j < npts; j++)
35163d025dbSVijay Mahadevan     {
352a86ed394SVijay Mahadevan       const PetscInt offset = j * nverts;
353181f196bSVijay Mahadevan       const PetscReal r = quad[0 + j * 2];
354181f196bSVijay Mahadevan       const PetscReal s = quad[1 + j * 2];
35563d025dbSVijay Mahadevan 
356181f196bSVijay Mahadevan       if (jxw) jxw[j] *= 0.5;
35763d025dbSVijay Mahadevan 
358181f196bSVijay Mahadevan       /* const PetscReal Ni[3]  = { r, s, 1.0 - r - s }; */
359181f196bSVijay Mahadevan       const PetscReal phipts_x = coords[2 * 3 + 0] + jacobian[0] * r + jacobian[1] * s;
360181f196bSVijay Mahadevan       const PetscReal phipts_y = coords[2 * 3 + 1] + jacobian[2] * r + jacobian[3] * s;
361181f196bSVijay Mahadevan       if (phypts) {
362181f196bSVijay Mahadevan         phypts[offset + 0] = phipts_x;
363181f196bSVijay Mahadevan         phypts[offset + 1] = phipts_y;
364181f196bSVijay Mahadevan       }
36563d025dbSVijay Mahadevan 
366181f196bSVijay Mahadevan       /* \phi_0 = (b.y − c.y) x + (b.x − c.x) y + c.x b.y − b.x c.y */
367181f196bSVijay Mahadevan       phi[0 + offset] = (  ijacobian[0] * (phipts_x - x2) + ijacobian[1] * (phipts_y - y2) );
368181f196bSVijay Mahadevan       /* \phi_1 = (c.y − a.y) x + (a.x − c.x) y + c.x a.y − a.x c.y */
369181f196bSVijay Mahadevan       phi[1 + offset] = (  ijacobian[2] * (phipts_x - x2) + ijacobian[3] * (phipts_y - y2) );
37063d025dbSVijay Mahadevan       phi[2 + offset] = 1.0 - phi[0 + offset] - phi[1 + offset];
37163d025dbSVijay Mahadevan 
37263d025dbSVijay Mahadevan       if (dphidx) {
373181f196bSVijay Mahadevan         dphidx[0 + offset] = Dx[0];
374181f196bSVijay Mahadevan         dphidx[1 + offset] = Dx[1];
375181f196bSVijay Mahadevan         dphidx[2 + offset] = Dx[2];
37663d025dbSVijay Mahadevan       }
37763d025dbSVijay Mahadevan 
37863d025dbSVijay Mahadevan       if (dphidy) {
379181f196bSVijay Mahadevan         dphidy[0 + offset] = Dy[0];
380181f196bSVijay Mahadevan         dphidy[1 + offset] = Dy[1];
381181f196bSVijay Mahadevan         dphidy[2 + offset] = Dy[2];
38263d025dbSVijay Mahadevan       }
38363d025dbSVijay Mahadevan 
38463d025dbSVijay Mahadevan     }
38563d025dbSVijay Mahadevan   }
38663d025dbSVijay Mahadevan   else {
38763d025dbSVijay 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);
38863d025dbSVijay Mahadevan   }
38963d025dbSVijay Mahadevan #if 0
39063d025dbSVijay Mahadevan   /* verify if the computed basis functions are consistent */
39163d025dbSVijay Mahadevan   for ( j = 0; j < npts; j++ ) {
39263d025dbSVijay Mahadevan     PetscScalar phisum = 0, dphixsum = 0, dphiysum = 0;
39363d025dbSVijay Mahadevan     for ( i = 0; i < nverts; i++ ) {
39463d025dbSVijay Mahadevan       phisum += phi[i + j * nverts];
39563d025dbSVijay Mahadevan       if (dphidx) dphixsum += dphidx[i + j * nverts];
39663d025dbSVijay Mahadevan       if (dphidy) dphiysum += dphidy[i + j * nverts];
39763d025dbSVijay Mahadevan     }
39863d025dbSVijay Mahadevan     PetscPrintf(PETSC_COMM_WORLD, "Sum of basis at quadrature point %D = %g, %g, %g\n", j, phisum, dphixsum, dphiysum);
39963d025dbSVijay Mahadevan   }
40063d025dbSVijay Mahadevan #endif
40163d025dbSVijay Mahadevan   PetscFunctionReturn(0);
40263d025dbSVijay Mahadevan }
40363d025dbSVijay Mahadevan 
40463d025dbSVijay Mahadevan 
40563d025dbSVijay Mahadevan /*@
406*97b73a88SSatish Balay   Compute_Lagrange_Basis_3D_Internal - Evaluate bases and derivatives at quadrature points for a HEX8 or TET4 element.
40763d025dbSVijay Mahadevan 
40863d025dbSVijay Mahadevan   The routine is given the coordinates of the vertices of a hexahedra or tetrahedra.
40963d025dbSVijay Mahadevan 
41063d025dbSVijay Mahadevan   The routine evaluates the basis functions associated with each quadrature point provided,
41163d025dbSVijay Mahadevan   and their derivatives with respect to X, Y and Z.
41263d025dbSVijay Mahadevan 
41363d025dbSVijay Mahadevan   Notes:
41463d025dbSVijay Mahadevan 
41563d025dbSVijay Mahadevan   Example Physical Element (HEX8)
41663d025dbSVijay Mahadevan 
41763d025dbSVijay Mahadevan       8------7
41863d025dbSVijay Mahadevan      /|     /|        t  s
41963d025dbSVijay Mahadevan     5------6 |        | /
42063d025dbSVijay Mahadevan     | |    | |        |/
42163d025dbSVijay Mahadevan     | 4----|-3        0-------r
42263d025dbSVijay Mahadevan     |/     |/
42363d025dbSVijay Mahadevan     1------2
42463d025dbSVijay Mahadevan 
42563d025dbSVijay Mahadevan   Input Parameter:
42663d025dbSVijay Mahadevan 
42763d025dbSVijay Mahadevan .  PetscInt  nverts,           the number of element vertices
42863d025dbSVijay Mahadevan .  PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering)
42963d025dbSVijay Mahadevan .  PetscInt  npts,             the number of evaluation points (quadrature points)
43063d025dbSVijay Mahadevan .  PetscReal quad[3*npts],     the evaluation points (quadrature points) in the reference space
43163d025dbSVijay Mahadevan 
43263d025dbSVijay Mahadevan   Output Parameter:
43363d025dbSVijay Mahadevan .  PetscReal phypts[3*npts],   the evaluation points (quadrature points) transformed to the physical space
43463d025dbSVijay Mahadevan .  PetscReal jxw[npts],        the jacobian determinant * quadrature weight necessary for assembling discrete contributions
43563d025dbSVijay Mahadevan .  PetscReal phi[npts],        the bases evaluated at the specified quadrature points
43663d025dbSVijay Mahadevan .  PetscReal dphidx[npts],     the derivative of the bases wrt X-direction evaluated at the specified quadrature points
43763d025dbSVijay Mahadevan .  PetscReal dphidy[npts],     the derivative of the bases wrt Y-direction evaluated at the specified quadrature points
43863d025dbSVijay Mahadevan .  PetscReal dphidz[npts],     the derivative of the bases wrt Z-direction evaluated at the specified quadrature points
43963d025dbSVijay Mahadevan 
44063d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 3-D
44163d025dbSVijay Mahadevan @*/
44263d025dbSVijay Mahadevan PetscErrorCode Compute_Lagrange_Basis_3D_Internal ( const PetscInt nverts, const PetscReal *coords, const PetscInt npts, const PetscReal *quad, PetscReal *phypts,
443181f196bSVijay Mahadevan     PetscReal *jxw, PetscReal *phi, PetscReal *dphidx, PetscReal *dphidy, PetscReal *dphidz,
444181f196bSVijay Mahadevan     PetscReal *jacobian, PetscReal *ijacobian, PetscReal *volume)
44563d025dbSVijay Mahadevan {
446a86ed394SVijay Mahadevan   PetscInt i, j, k;
44763d025dbSVijay Mahadevan   PetscErrorCode ierr;
44863d025dbSVijay Mahadevan 
44963d025dbSVijay Mahadevan   PetscFunctionBegin;
450181f196bSVijay Mahadevan   PetscValidPointer(jacobian, 11);
451181f196bSVijay Mahadevan   PetscValidPointer(ijacobian, 12);
452181f196bSVijay Mahadevan   PetscValidPointer(volume, 13);
45363d025dbSVijay Mahadevan   /* Reset arrays. */
45463d025dbSVijay Mahadevan   ierr = PetscMemzero(phi, npts * sizeof(PetscReal));CHKERRQ(ierr);
455181f196bSVijay Mahadevan   if (phypts) {
45663d025dbSVijay Mahadevan     ierr = PetscMemzero(phypts, npts * 3 * sizeof(PetscReal));CHKERRQ(ierr);
457181f196bSVijay Mahadevan   }
45863d025dbSVijay Mahadevan   if (dphidx) {
45963d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidx, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
46063d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidy, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
46163d025dbSVijay Mahadevan     ierr = PetscMemzero(dphidz, npts * nverts * sizeof(PetscReal));CHKERRQ(ierr);
46263d025dbSVijay Mahadevan   }
46363d025dbSVijay Mahadevan 
46463d025dbSVijay Mahadevan   if (nverts == 8) { /* Linear Hexahedra */
46563d025dbSVijay Mahadevan 
46663d025dbSVijay Mahadevan     for (j = 0; j < npts; j++)
46763d025dbSVijay Mahadevan     {
468a86ed394SVijay Mahadevan       const PetscInt offset = j * nverts;
469181f196bSVijay Mahadevan       const PetscReal& r = quad[j * 3 + 0];
470181f196bSVijay Mahadevan       const PetscReal& s = quad[j * 3 + 1];
471181f196bSVijay Mahadevan       const PetscReal& t = quad[j * 3 + 2];
47263d025dbSVijay Mahadevan 
473a86ed394SVijay Mahadevan       phi[offset + 0] = ( 1.0 - r ) * ( 1.0 - s ) * ( 1.0 - t ); /* 0,0,0 */
474a86ed394SVijay Mahadevan       phi[offset + 1] = (       r ) * ( 1.0 - s ) * ( 1.0 - t ); /* 1,0,0 */
475a86ed394SVijay Mahadevan       phi[offset + 2] = (       r ) * (       s ) * ( 1.0 - t ); /* 1,1,0 */
476a86ed394SVijay Mahadevan       phi[offset + 3] = ( 1.0 - r ) * (       s ) * ( 1.0 - t ); /* 0,1,0 */
477a86ed394SVijay Mahadevan       phi[offset + 4] = ( 1.0 - r ) * ( 1.0 - s ) * (       t ); /* 0,0,1 */
478a86ed394SVijay Mahadevan       phi[offset + 5] = (       r ) * ( 1.0 - s ) * (       t ); /* 1,0,1 */
479a86ed394SVijay Mahadevan       phi[offset + 6] = (       r ) * (       s ) * (       t ); /* 1,1,1 */
480a86ed394SVijay Mahadevan       phi[offset + 7] = ( 1.0 - r ) * (       s ) * (       t ); /* 0,1,1 */
48163d025dbSVijay Mahadevan 
482181f196bSVijay Mahadevan       const PetscReal dNi_dxi[8]  = {- ( 1.0 - s ) * ( 1.0 - t ),
48363d025dbSVijay Mahadevan                                        ( 1.0 - s ) * ( 1.0 - t ),
484a86ed394SVijay Mahadevan                                        (       s ) * ( 1.0 - t ),
485a86ed394SVijay Mahadevan                                      - (       s ) * ( 1.0 - t ),
486a86ed394SVijay Mahadevan                                      - ( 1.0 - s ) * (       t ),
487a86ed394SVijay Mahadevan                                        ( 1.0 - s ) * (       t ),
488a86ed394SVijay Mahadevan                                        (       s ) * (       t ),
489a86ed394SVijay Mahadevan                                      - (       s ) * (       t )
49063d025dbSVijay Mahadevan                                     };
49163d025dbSVijay Mahadevan 
492181f196bSVijay Mahadevan       const PetscReal dNi_deta[8]  = { - ( 1.0 - r ) * ( 1.0 - t ),
493a86ed394SVijay Mahadevan                                        - (       r ) * ( 1.0 - t ),
494a86ed394SVijay Mahadevan                                          (       r ) * ( 1.0 - t ),
49563d025dbSVijay Mahadevan                                          ( 1.0 - r ) * ( 1.0 - t ),
496a86ed394SVijay Mahadevan                                        - ( 1.0 - r ) * (       t ),
497a86ed394SVijay Mahadevan                                        - (       r ) * (       t ),
498a86ed394SVijay Mahadevan                                          (       r ) * (       t ),
499a86ed394SVijay Mahadevan                                          ( 1.0 - r ) * (       t )
50063d025dbSVijay Mahadevan                                       };
50163d025dbSVijay Mahadevan 
502181f196bSVijay Mahadevan       const PetscReal dNi_dzeta[8]  = { - ( 1.0 - r ) * ( 1.0 - s ),
503a86ed394SVijay Mahadevan                                         - (       r ) * ( 1.0 - s ),
504a86ed394SVijay Mahadevan                                         - (       r ) * (       s ),
505a86ed394SVijay Mahadevan                                         - ( 1.0 - r ) * (       s ),
50663d025dbSVijay Mahadevan                                           ( 1.0 - r ) * ( 1.0 - s ),
507a86ed394SVijay Mahadevan                                           (       r ) * ( 1.0 - s ),
508a86ed394SVijay Mahadevan                                           (       r ) * (       s ),
509a86ed394SVijay Mahadevan                                           ( 1.0 - r ) * (       s )
51063d025dbSVijay Mahadevan                                      };
51163d025dbSVijay Mahadevan 
51263d025dbSVijay Mahadevan       ierr = PetscMemzero(jacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr);
51363d025dbSVijay Mahadevan       ierr = PetscMemzero(ijacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr);
51463d025dbSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
515181f196bSVijay Mahadevan         const PetscReal* vertex = coords + i * 3;
51663d025dbSVijay Mahadevan         jacobian[0] += dNi_dxi[i]   * vertex[0];
51763d025dbSVijay Mahadevan         jacobian[3] += dNi_dxi[i]   * vertex[1];
51863d025dbSVijay Mahadevan         jacobian[6] += dNi_dxi[i]   * vertex[2];
51963d025dbSVijay Mahadevan         jacobian[1] += dNi_deta[i]  * vertex[0];
52063d025dbSVijay Mahadevan         jacobian[4] += dNi_deta[i]  * vertex[1];
52163d025dbSVijay Mahadevan         jacobian[7] += dNi_deta[i]  * vertex[2];
52263d025dbSVijay Mahadevan         jacobian[2] += dNi_dzeta[i] * vertex[0];
52363d025dbSVijay Mahadevan         jacobian[5] += dNi_dzeta[i] * vertex[1];
52463d025dbSVijay Mahadevan         jacobian[8] += dNi_dzeta[i] * vertex[2];
525181f196bSVijay Mahadevan         if (phypts) {
526181f196bSVijay Mahadevan           phypts[3 * j + 0] += phi[i + offset] * vertex[0];
527181f196bSVijay Mahadevan           phypts[3 * j + 1] += phi[i + offset] * vertex[1];
528181f196bSVijay Mahadevan           phypts[3 * j + 2] += phi[i + offset] * vertex[2];
529181f196bSVijay Mahadevan         }
53063d025dbSVijay Mahadevan       }
53163d025dbSVijay Mahadevan 
53263d025dbSVijay Mahadevan       /* invert the jacobian */
533181f196bSVijay Mahadevan       ierr = DMatrix_Invert_3x3_Internal(jacobian, ijacobian, volume);CHKERRQ(ierr);
534a86ed394SVijay 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);
53563d025dbSVijay Mahadevan 
536a86ed394SVijay Mahadevan       if (jxw) jxw[j] *= (*volume);
53763d025dbSVijay Mahadevan 
53863d025dbSVijay Mahadevan       /*  Divide by element jacobian. */
53963d025dbSVijay Mahadevan       for ( i = 0; i < nverts; ++i ) {
540a86ed394SVijay Mahadevan         for ( k = 0; k < 3; ++k) {
54163d025dbSVijay Mahadevan           if (dphidx) dphidx[i + offset] += dNi_dxi[i]   * ijacobian[0 * 3 + k];
54263d025dbSVijay Mahadevan           if (dphidy) dphidy[i + offset] += dNi_deta[i]  * ijacobian[1 * 3 + k];
54363d025dbSVijay Mahadevan           if (dphidz) dphidz[i + offset] += dNi_dzeta[i] * ijacobian[2 * 3 + k];
54463d025dbSVijay Mahadevan         }
54563d025dbSVijay Mahadevan       }
54663d025dbSVijay Mahadevan     }
54763d025dbSVijay Mahadevan   }
54863d025dbSVijay Mahadevan   else if (nverts == 4) { /* Linear Tetrahedra */
54963d025dbSVijay Mahadevan 
55063d025dbSVijay Mahadevan     ierr = PetscMemzero(jacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr);
55163d025dbSVijay Mahadevan     ierr = PetscMemzero(ijacobian, 9 * sizeof(PetscReal));CHKERRQ(ierr);
55263d025dbSVijay Mahadevan 
553181f196bSVijay Mahadevan     const PetscReal x0 = coords[/*0 * 3 +*/ 0], y0 = coords[/*0 * 3 +*/ 1], z0 = coords[/*0 * 3 +*/ 2];
554181f196bSVijay Mahadevan 
555181f196bSVijay Mahadevan     /* compute the jacobian */
556181f196bSVijay Mahadevan     jacobian[0] = coords[1 * 3 + 0] - x0;  jacobian[1] = coords[2 * 3 + 0] - x0; jacobian[2] = coords[3 * 3 + 0] - x0;
557181f196bSVijay Mahadevan     jacobian[3] = coords[1 * 3 + 1] - y0;  jacobian[4] = coords[2 * 3 + 1] - y0; jacobian[5] = coords[3 * 3 + 1] - y0;
558181f196bSVijay Mahadevan     jacobian[6] = coords[1 * 3 + 2] - z0;  jacobian[7] = coords[2 * 3 + 2] - z0; jacobian[8] = coords[3 * 3 + 2] - z0;
55963d025dbSVijay Mahadevan 
56063d025dbSVijay Mahadevan     /* invert the jacobian */
561181f196bSVijay Mahadevan     ierr = DMatrix_Invert_3x3_Internal(jacobian, ijacobian, volume);CHKERRQ(ierr);
562a86ed394SVijay 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);
56363d025dbSVijay Mahadevan 
5646ea892caSVijay Mahadevan     PetscReal Dx[4]={0,0,0,0}, Dy[4]={0,0,0,0}, Dz[4]={0,0,0,0};
565181f196bSVijay Mahadevan     if (dphidx) {
566181f196bSVijay Mahadevan       Dx[0] =   ( coords[1 + 2 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] )
567181f196bSVijay Mahadevan                  - coords[1 + 1 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] )
568181f196bSVijay Mahadevan                  - coords[1 + 3 * 3] * ( coords[2 + 1 * 3] - coords[2 + 2 * 3] )
569181f196bSVijay Mahadevan                 ) / *volume;
570181f196bSVijay Mahadevan       Dx[1] = - ( coords[1 + 2 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] )
571181f196bSVijay Mahadevan                  - coords[1 + 0 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] )
572181f196bSVijay Mahadevan                  - coords[1 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 2 * 3] )
573181f196bSVijay Mahadevan                 ) / *volume;
574181f196bSVijay Mahadevan       Dx[2] =   ( coords[1 + 1 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] )
575181f196bSVijay Mahadevan                  - coords[1 + 0 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] )
576181f196bSVijay Mahadevan                  - coords[1 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 1 * 3] )
577181f196bSVijay Mahadevan                 ) / *volume;
578181f196bSVijay Mahadevan       Dx[3] =  - ( Dx[0] + Dx[1] + Dx[2] );
579181f196bSVijay Mahadevan       Dy[0] =   ( coords[0 + 1 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] )
580181f196bSVijay Mahadevan                  - coords[0 + 2 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] )
581181f196bSVijay Mahadevan                  + coords[0 + 3 * 3] * ( coords[2 + 1 * 3] - coords[2 + 2 * 3] )
582181f196bSVijay Mahadevan                 ) / *volume;
583181f196bSVijay Mahadevan       Dy[1] = - ( coords[0 + 0 * 3] * ( coords[2 + 2 * 3] - coords[2 + 3 * 3] )
584181f196bSVijay Mahadevan                  - coords[0 + 2 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] )
585181f196bSVijay Mahadevan                  + coords[0 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 2 * 3] )
586181f196bSVijay Mahadevan                 ) / *volume;
587181f196bSVijay Mahadevan       Dy[2] =   ( coords[0 + 0 * 3] * ( coords[2 + 1 * 3] - coords[2 + 3 * 3] )
588181f196bSVijay Mahadevan                  - coords[0 + 1 * 3] * ( coords[2 + 0 * 3] - coords[2 + 3 * 3] )
589181f196bSVijay Mahadevan                  + coords[0 + 3 * 3] * ( coords[2 + 0 * 3] - coords[2 + 1 * 3] )
590181f196bSVijay Mahadevan                 ) / *volume;
591181f196bSVijay Mahadevan       Dy[3] =  - ( Dy[0] + Dy[1] + Dy[2] );
592181f196bSVijay Mahadevan       Dz[0] =   ( coords[0 + 1 * 3] * (coords[1 + 3 * 3] - coords[1 + 2 * 3] )
593181f196bSVijay Mahadevan                  - coords[0 + 2 * 3] * (coords[1 + 3 * 3] - coords[1 + 1 * 3] )
594181f196bSVijay Mahadevan                  + coords[0 + 3 * 3] * (coords[1 + 2 * 3] - coords[1 + 1 * 3] )
595181f196bSVijay Mahadevan                 ) / *volume;
596181f196bSVijay Mahadevan       Dz[1] = - ( coords[0 + 0 * 3] * (coords[1 + 3 * 3] - coords[1 + 2 * 3] )
597181f196bSVijay Mahadevan                   + coords[0 + 2 * 3] * (coords[1 + 0 * 3] - coords[1 + 3 * 3] )
598181f196bSVijay Mahadevan                   - coords[0 + 3 * 3] * (coords[1 + 0 * 3] - coords[1 + 2 * 3] )
599181f196bSVijay Mahadevan                 ) / *volume;
600181f196bSVijay Mahadevan       Dz[2] =   ( coords[0 + 0 * 3] * (coords[1 + 3 * 3] - coords[1 + 1 * 3] )
601181f196bSVijay Mahadevan                  + coords[0 + 1 * 3] * (coords[1 + 0 * 3] - coords[1 + 3 * 3] )
602181f196bSVijay Mahadevan                  - coords[0 + 3 * 3] * (coords[1 + 0 * 3] - coords[1 + 1 * 3] )
603181f196bSVijay Mahadevan                 ) / *volume;
604181f196bSVijay Mahadevan       Dz[3] =  - ( Dz[0] + Dz[1] + Dz[2] );
605181f196bSVijay Mahadevan     }
60663d025dbSVijay Mahadevan 
60763d025dbSVijay Mahadevan     for ( j = 0; j < npts; j++ )
60863d025dbSVijay Mahadevan     {
609a86ed394SVijay Mahadevan       const PetscInt offset = j * nverts;
610181f196bSVijay Mahadevan       const PetscReal& r = quad[j * 3 + 0];
611181f196bSVijay Mahadevan       const PetscReal& s = quad[j * 3 + 1];
612181f196bSVijay Mahadevan       const PetscReal& t = quad[j * 3 + 2];
61363d025dbSVijay Mahadevan 
614181f196bSVijay Mahadevan       if (jxw) jxw[j] *= *volume;
61563d025dbSVijay Mahadevan 
61663d025dbSVijay Mahadevan       phi[offset + 0] = 1.0 - r - s - t;
61763d025dbSVijay Mahadevan       phi[offset + 1] = r;
61863d025dbSVijay Mahadevan       phi[offset + 2] = s;
61963d025dbSVijay Mahadevan       phi[offset + 3] = t;
62063d025dbSVijay Mahadevan 
621181f196bSVijay Mahadevan       if (phypts) {
622181f196bSVijay Mahadevan         for (i = 0; i < nverts; ++i) {
623181f196bSVijay Mahadevan           const PetscScalar* vertices = coords + i * 3;
624181f196bSVijay Mahadevan           phypts[3 * j + 0] += phi[i + offset] * vertices[0];
625181f196bSVijay Mahadevan           phypts[3 * j + 1] += phi[i + offset] * vertices[1];
626181f196bSVijay Mahadevan           phypts[3 * j + 2] += phi[i + offset] * vertices[2];
627181f196bSVijay Mahadevan         }
628181f196bSVijay Mahadevan       }
629181f196bSVijay Mahadevan 
630181f196bSVijay Mahadevan       /* Now set the derivatives */
63163d025dbSVijay Mahadevan       if (dphidx) {
632181f196bSVijay Mahadevan         dphidx[0 + offset] = Dx[0];
633181f196bSVijay Mahadevan         dphidx[1 + offset] = Dx[1];
634181f196bSVijay Mahadevan         dphidx[2 + offset] = Dx[2];
635181f196bSVijay Mahadevan         dphidx[3 + offset] = Dx[3];
63663d025dbSVijay Mahadevan 
637181f196bSVijay Mahadevan         dphidy[0 + offset] = Dy[0];
638181f196bSVijay Mahadevan         dphidy[1 + offset] = Dy[1];
639181f196bSVijay Mahadevan         dphidy[2 + offset] = Dy[2];
640181f196bSVijay Mahadevan         dphidy[3 + offset] = Dy[3];
64163d025dbSVijay Mahadevan 
642181f196bSVijay Mahadevan         dphidz[0 + offset] = Dz[0];
643181f196bSVijay Mahadevan         dphidz[1 + offset] = Dz[1];
644181f196bSVijay Mahadevan         dphidz[2 + offset] = Dz[2];
645181f196bSVijay Mahadevan         dphidz[3 + offset] = Dz[3];
64663d025dbSVijay Mahadevan       }
64763d025dbSVijay Mahadevan 
64863d025dbSVijay Mahadevan     } /* Tetrahedra -- ends */
64963d025dbSVijay Mahadevan   }
65063d025dbSVijay Mahadevan   else
65163d025dbSVijay Mahadevan   {
65263d025dbSVijay 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);
65363d025dbSVijay Mahadevan   }
65463d025dbSVijay Mahadevan #if 0
65563d025dbSVijay Mahadevan   /* verify if the computed basis functions are consistent */
65663d025dbSVijay Mahadevan   for ( j = 0; j < npts; j++ ) {
65763d025dbSVijay Mahadevan     PetscScalar phisum = 0, dphixsum = 0, dphiysum = 0, dphizsum = 0;
65863d025dbSVijay Mahadevan     const int offset = j * nverts;
65963d025dbSVijay Mahadevan     for ( i = 0; i < nverts; i++ ) {
66063d025dbSVijay Mahadevan       phisum += phi[i + offset];
66163d025dbSVijay Mahadevan       if (dphidx) dphixsum += dphidx[i + offset];
66263d025dbSVijay Mahadevan       if (dphidy) dphiysum += dphidy[i + offset];
66363d025dbSVijay Mahadevan       if (dphidz) dphizsum += dphidz[i + offset];
66463d025dbSVijay 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]);
66563d025dbSVijay Mahadevan     }
66663d025dbSVijay 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);
66763d025dbSVijay Mahadevan   }
66863d025dbSVijay Mahadevan #endif
66963d025dbSVijay Mahadevan   PetscFunctionReturn(0);
67063d025dbSVijay Mahadevan }
67163d025dbSVijay Mahadevan 
67263d025dbSVijay Mahadevan 
67363d025dbSVijay Mahadevan 
67463d025dbSVijay Mahadevan /*@
675*97b73a88SSatish Balay   DMMoabFEMComputeBasis - Evaluate bases and derivatives at quadrature points for a linear EDGE/QUAD/TRI/HEX/TET element.
67663d025dbSVijay Mahadevan 
67763d025dbSVijay Mahadevan   The routine takes the coordinates of the vertices of an element and computes basis functions associated with
67863d025dbSVijay Mahadevan   each quadrature point provided, and their derivatives with respect to X, Y and Z as appropriate.
67963d025dbSVijay Mahadevan 
68063d025dbSVijay Mahadevan   Input Parameter:
68163d025dbSVijay Mahadevan 
68263d025dbSVijay Mahadevan .  PetscInt  nverts,           the number of element vertices
68363d025dbSVijay Mahadevan .  PetscReal coords[3*nverts], the physical coordinates of the vertices (in canonical numbering)
68463d025dbSVijay Mahadevan .  PetscInt  npts,             the number of evaluation points (quadrature points)
68563d025dbSVijay Mahadevan .  PetscReal quad[3*npts],     the evaluation points (quadrature points) in the reference space
68663d025dbSVijay Mahadevan 
68763d025dbSVijay Mahadevan   Output Parameter:
68863d025dbSVijay Mahadevan .  PetscReal phypts[3*npts],   the evaluation points (quadrature points) transformed to the physical space
68963d025dbSVijay Mahadevan .  PetscReal jxw[npts],        the jacobian determinant * quadrature weight necessary for assembling discrete contributions
69063d025dbSVijay Mahadevan .  PetscReal fe_basis[npts],        the bases values evaluated at the specified quadrature points
69163d025dbSVijay 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
69263d025dbSVijay Mahadevan 
69363d025dbSVijay Mahadevan .keywords: DMMoab, FEM, 3-D
69463d025dbSVijay Mahadevan @*/
695181f196bSVijay Mahadevan PetscErrorCode DMMoabFEMComputeBasis ( const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscQuadrature quadrature,
696181f196bSVijay Mahadevan                                        PetscReal *phypts, PetscReal *jacobian_quadrature_weight_product,
697181f196bSVijay Mahadevan                                        PetscReal *fe_basis, PetscReal **fe_basis_derivatives)
69863d025dbSVijay Mahadevan {
69963d025dbSVijay Mahadevan   PetscErrorCode  ierr;
700b21a1e88SVijay Mahadevan   PetscInt        npoints,idim;
70163d025dbSVijay Mahadevan   bool            compute_der;
70263d025dbSVijay Mahadevan   const PetscReal *quadpts, *quadwts;
703181f196bSVijay Mahadevan   PetscReal       jacobian[9], ijacobian[9], volume;
70463d025dbSVijay Mahadevan 
70563d025dbSVijay Mahadevan   PetscFunctionBegin;
70663d025dbSVijay Mahadevan   PetscValidPointer(coordinates, 3);
70763d025dbSVijay Mahadevan   PetscValidHeaderSpecific(quadrature, PETSC_OBJECT_CLASSID, 4);
70863d025dbSVijay Mahadevan   PetscValidPointer(fe_basis, 7);
70963d025dbSVijay Mahadevan   compute_der = (fe_basis_derivatives != NULL);
71063d025dbSVijay Mahadevan 
71163d025dbSVijay Mahadevan   /* Get the quadrature points and weights for the given quadrature rule */
712b21a1e88SVijay Mahadevan   ierr = PetscQuadratureGetData(quadrature, &idim, NULL, &npoints, &quadpts, &quadwts);CHKERRQ(ierr);
713b21a1e88SVijay Mahadevan   if (idim != dim) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Dimension mismatch: provided (%D) vs quadrature (%D)\n",idim,dim);
714181f196bSVijay Mahadevan   if (jacobian_quadrature_weight_product) {
71563d025dbSVijay Mahadevan     ierr = PetscMemcpy(jacobian_quadrature_weight_product, quadwts, npoints * sizeof(PetscReal));CHKERRQ(ierr);
716181f196bSVijay Mahadevan   }
71763d025dbSVijay Mahadevan 
71863d025dbSVijay Mahadevan   switch (dim) {
71963d025dbSVijay Mahadevan   case 1:
72063d025dbSVijay Mahadevan     ierr = Compute_Lagrange_Basis_1D_Internal(nverts, coordinates, npoints, quadpts, phypts,
72163d025dbSVijay Mahadevan            jacobian_quadrature_weight_product, fe_basis,
722181f196bSVijay Mahadevan            (compute_der ? fe_basis_derivatives[0] : NULL),
723181f196bSVijay Mahadevan            jacobian, ijacobian, &volume);CHKERRQ(ierr);
72463d025dbSVijay Mahadevan     break;
72563d025dbSVijay Mahadevan   case 2:
72663d025dbSVijay Mahadevan     ierr = Compute_Lagrange_Basis_2D_Internal(nverts, coordinates, npoints, quadpts, phypts,
72763d025dbSVijay Mahadevan            jacobian_quadrature_weight_product, fe_basis,
72863d025dbSVijay Mahadevan            (compute_der ? fe_basis_derivatives[0] : NULL),
729181f196bSVijay Mahadevan            (compute_der ? fe_basis_derivatives[1] : NULL),
730181f196bSVijay Mahadevan            jacobian, ijacobian, &volume);CHKERRQ(ierr);
73163d025dbSVijay Mahadevan     break;
73263d025dbSVijay Mahadevan   case 3:
73363d025dbSVijay Mahadevan     ierr = Compute_Lagrange_Basis_3D_Internal(nverts, coordinates, npoints, quadpts, phypts,
73463d025dbSVijay Mahadevan            jacobian_quadrature_weight_product, fe_basis,
73563d025dbSVijay Mahadevan            (compute_der ? fe_basis_derivatives[0] : NULL),
73663d025dbSVijay Mahadevan            (compute_der ? fe_basis_derivatives[1] : NULL),
737181f196bSVijay Mahadevan            (compute_der ? fe_basis_derivatives[2] : NULL),
738181f196bSVijay Mahadevan            jacobian, ijacobian, &volume);CHKERRQ(ierr);
73963d025dbSVijay Mahadevan     break;
74063d025dbSVijay Mahadevan   default:
74163d025dbSVijay Mahadevan     SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %D", dim);
74263d025dbSVijay Mahadevan   }
74363d025dbSVijay Mahadevan   PetscFunctionReturn(0);
74463d025dbSVijay Mahadevan }
74563d025dbSVijay Mahadevan 
74663d025dbSVijay Mahadevan 
74763d025dbSVijay Mahadevan 
74863d025dbSVijay Mahadevan /*@
749*97b73a88SSatish Balay   DMMoabFEMCreateQuadratureDefault - Create default quadrature rules for integration over an element with a given
75063d025dbSVijay Mahadevan   dimension and polynomial order (deciphered from number of element vertices).
75163d025dbSVijay Mahadevan 
75263d025dbSVijay Mahadevan   Input Parameter:
75363d025dbSVijay Mahadevan 
75463d025dbSVijay Mahadevan .  PetscInt  dim,           the element dimension (1=EDGE, 2=QUAD/TRI, 3=HEX/TET)
75563d025dbSVijay Mahadevan .  PetscInt nverts,      the number of vertices in the physical element
75663d025dbSVijay Mahadevan 
75763d025dbSVijay Mahadevan   Output Parameter:
75863d025dbSVijay Mahadevan .  PetscQuadrature quadrature,  the quadrature object with default settings to integrate polynomials defined over the element
75963d025dbSVijay Mahadevan 
76063d025dbSVijay Mahadevan .keywords: DMMoab, Quadrature, PetscDT
76163d025dbSVijay Mahadevan @*/
762181f196bSVijay Mahadevan PetscErrorCode DMMoabFEMCreateQuadratureDefault ( const PetscInt dim, const PetscInt nverts, PetscQuadrature *quadrature )
76363d025dbSVijay Mahadevan {
76463d025dbSVijay Mahadevan   PetscReal *w, *x;
765b21a1e88SVijay Mahadevan   PetscInt nc=1;
76663d025dbSVijay Mahadevan   PetscErrorCode  ierr;
76763d025dbSVijay Mahadevan 
76863d025dbSVijay Mahadevan   PetscFunctionBegin;
76963d025dbSVijay Mahadevan   /* Create an appropriate quadrature rule to sample basis */
77063d025dbSVijay Mahadevan   switch (dim)
77163d025dbSVijay Mahadevan   {
77263d025dbSVijay Mahadevan   case 1:
77363d025dbSVijay Mahadevan     /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */
774b21a1e88SVijay Mahadevan     ierr = PetscDTGaussJacobiQuadrature(1, nc, nverts, 0, 1.0, quadrature);CHKERRQ(ierr);
77563d025dbSVijay Mahadevan     break;
77663d025dbSVijay Mahadevan   case 2:
77763d025dbSVijay Mahadevan     /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */
77863d025dbSVijay Mahadevan     if (nverts == 3) {
779a86ed394SVijay Mahadevan       const PetscInt order = 2;
780a86ed394SVijay Mahadevan       const PetscInt npoints = (order == 2 ? 3 : 6);
78163d025dbSVijay Mahadevan       ierr = PetscMalloc2(npoints * 2, &x, npoints, &w);CHKERRQ(ierr);
782181f196bSVijay Mahadevan       if (npoints == 3) {
78363d025dbSVijay Mahadevan         x[0] = x[1] = x[2] = x[5] = 1.0 / 6.0;
78463d025dbSVijay Mahadevan         x[3] = x[4] = 2.0 / 3.0;
78563d025dbSVijay Mahadevan         w[0] = w[1] = w[2] = 1.0 / 3.0;
786181f196bSVijay Mahadevan       }
787181f196bSVijay Mahadevan       else if (npoints == 6) {
78863d025dbSVijay Mahadevan         x[0] = x[1] = x[2] = 0.44594849091597;
78963d025dbSVijay Mahadevan         x[3] = x[4] = 0.10810301816807;
79063d025dbSVijay Mahadevan         x[5] = 0.44594849091597;
79163d025dbSVijay Mahadevan         x[6] = x[7] = x[8] = 0.09157621350977;
79263d025dbSVijay Mahadevan         x[9] = x[10] = 0.81684757298046;
79363d025dbSVijay Mahadevan         x[11] = 0.09157621350977;
79463d025dbSVijay Mahadevan         w[0] = w[1] = w[2] = 0.22338158967801;
795181f196bSVijay Mahadevan         w[3] = w[4] = w[5] = 0.10995174365532;
796181f196bSVijay Mahadevan       }
797181f196bSVijay Mahadevan       else {
798181f196bSVijay Mahadevan         SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Triangle quadrature rules for points 3 and 6 supported; npoints : %D", npoints);
79963d025dbSVijay Mahadevan       }
80063d025dbSVijay Mahadevan       ierr = PetscQuadratureCreate(PETSC_COMM_SELF, quadrature);CHKERRQ(ierr);
80163d025dbSVijay Mahadevan       ierr = PetscQuadratureSetOrder(*quadrature, order);CHKERRQ(ierr);
802b21a1e88SVijay Mahadevan       ierr = PetscQuadratureSetData(*quadrature, dim, nc, npoints, x, w);CHKERRQ(ierr);
803181f196bSVijay Mahadevan       /* ierr = PetscDTGaussJacobiQuadrature(dim, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr); */
80463d025dbSVijay Mahadevan     }
80563d025dbSVijay Mahadevan     else {
806b21a1e88SVijay Mahadevan       ierr = PetscDTGaussTensorQuadrature(dim, nc, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr);
80763d025dbSVijay Mahadevan     }
80863d025dbSVijay Mahadevan     break;
80963d025dbSVijay Mahadevan   case 3:
81063d025dbSVijay Mahadevan     /* Create Gauss quadrature rules with <order = nverts> in the span [-1, 1] */
81163d025dbSVijay Mahadevan     if (nverts == 4) {
812a86ed394SVijay Mahadevan       PetscInt order;
813a86ed394SVijay Mahadevan       const PetscInt npoints = 4; // Choose between 4 and 10
814181f196bSVijay Mahadevan       ierr = PetscMalloc2(npoints * 3, &x, npoints, &w);CHKERRQ(ierr);
815181f196bSVijay Mahadevan       if (npoints == 4) { /*  KEAST1, K1,  N=4, O=4 */
816181f196bSVijay Mahadevan         const PetscReal x_4[12] = { 0.5854101966249685, 0.1381966011250105, 0.1381966011250105,
817181f196bSVijay Mahadevan                                     0.1381966011250105, 0.1381966011250105, 0.1381966011250105,
818181f196bSVijay Mahadevan                                     0.1381966011250105, 0.1381966011250105, 0.5854101966249685,
819181f196bSVijay Mahadevan                                     0.1381966011250105, 0.5854101966249685, 0.1381966011250105
820181f196bSVijay Mahadevan                                   };
821181f196bSVijay Mahadevan         ierr = PetscMemcpy(x, x_4, 12 * sizeof(PetscReal));CHKERRQ(ierr);
822181f196bSVijay Mahadevan 
823181f196bSVijay Mahadevan         w[0] = w[1] = w[2] = w[3] = 1.0 / 24.0;
824181f196bSVijay Mahadevan         order = 4;
825181f196bSVijay Mahadevan       }
826181f196bSVijay Mahadevan       else if (npoints == 10) { /*  KEAST3, K3  N=10, O=10 */
827181f196bSVijay Mahadevan         const PetscReal x_10[30] = { 0.5684305841968444, 0.1438564719343852, 0.1438564719343852,
828181f196bSVijay Mahadevan                                      0.1438564719343852, 0.1438564719343852, 0.1438564719343852,
829181f196bSVijay Mahadevan                                      0.1438564719343852, 0.1438564719343852, 0.5684305841968444,
830181f196bSVijay Mahadevan                                      0.1438564719343852, 0.5684305841968444, 0.1438564719343852,
831181f196bSVijay Mahadevan                                      0.0000000000000000, 0.5000000000000000, 0.5000000000000000,
832181f196bSVijay Mahadevan                                      0.5000000000000000, 0.0000000000000000, 0.5000000000000000,
833181f196bSVijay Mahadevan                                      0.5000000000000000, 0.5000000000000000, 0.0000000000000000,
834181f196bSVijay Mahadevan                                      0.5000000000000000, 0.0000000000000000, 0.0000000000000000,
835181f196bSVijay Mahadevan                                      0.0000000000000000, 0.5000000000000000, 0.0000000000000000,
836181f196bSVijay Mahadevan                                      0.0000000000000000, 0.0000000000000000, 0.5000000000000000
837181f196bSVijay Mahadevan                                    };
838181f196bSVijay Mahadevan         ierr = PetscMemcpy(x, x_10, 30 * sizeof(PetscReal));CHKERRQ(ierr);
839181f196bSVijay Mahadevan 
840181f196bSVijay Mahadevan         w[0] = w[1] = w[2] = w[3] = 0.2177650698804054;
841181f196bSVijay Mahadevan         w[4] = w[5] = w[6] = w[7] = w[8] = w[9] = 0.0214899534130631;
842181f196bSVijay Mahadevan         order = 10;
843181f196bSVijay Mahadevan       }
844181f196bSVijay Mahadevan       else {
845181f196bSVijay Mahadevan         SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Tetrahedral quadrature rules for points 4 and 10 supported; npoints : %D", npoints);
846181f196bSVijay Mahadevan       }
847181f196bSVijay Mahadevan       ierr = PetscQuadratureCreate(PETSC_COMM_SELF, quadrature);CHKERRQ(ierr);
848181f196bSVijay Mahadevan       ierr = PetscQuadratureSetOrder(*quadrature, order);CHKERRQ(ierr);
849b21a1e88SVijay Mahadevan       ierr = PetscQuadratureSetData(*quadrature, dim, nc, npoints, x, w);CHKERRQ(ierr);
850181f196bSVijay Mahadevan       /* ierr = PetscDTGaussJacobiQuadrature(dim, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr); */
85163d025dbSVijay Mahadevan     }
85263d025dbSVijay Mahadevan     else {
853b21a1e88SVijay Mahadevan       ierr = PetscDTGaussTensorQuadrature(dim, nc, nverts, 0.0, 1.0, quadrature);CHKERRQ(ierr);
85463d025dbSVijay Mahadevan     }
85563d025dbSVijay Mahadevan     break;
85663d025dbSVijay Mahadevan   default:
85763d025dbSVijay Mahadevan     SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %D", dim);
85863d025dbSVijay Mahadevan   }
85963d025dbSVijay Mahadevan   PetscFunctionReturn(0);
86063d025dbSVijay Mahadevan }
86163d025dbSVijay Mahadevan 
862181f196bSVijay Mahadevan /* Compute Jacobians */
863181f196bSVijay Mahadevan PetscErrorCode ComputeJacobian_Internal ( const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscReal *quad, PetscReal *phypts,
864a86ed394SVijay Mahadevan   PetscReal *jacobian, PetscReal *ijacobian, PetscReal* dvolume)
865181f196bSVijay Mahadevan {
866a86ed394SVijay Mahadevan   PetscInt i;
8672417220eSVijay Mahadevan   PetscReal volume=1.0;
868181f196bSVijay Mahadevan   PetscErrorCode ierr;
869181f196bSVijay Mahadevan 
870181f196bSVijay Mahadevan   PetscFunctionBegin;
871181f196bSVijay Mahadevan   PetscValidPointer(coordinates, 3);
872181f196bSVijay Mahadevan   PetscValidPointer(quad, 4);
873181f196bSVijay Mahadevan   PetscValidPointer(jacobian, 5);
874181f196bSVijay Mahadevan   ierr = PetscMemzero(jacobian, dim * dim * sizeof(PetscReal));CHKERRQ(ierr);
875181f196bSVijay Mahadevan   if (ijacobian) {
876181f196bSVijay Mahadevan     ierr = PetscMemzero(ijacobian, dim * dim * sizeof(PetscReal));CHKERRQ(ierr);
877181f196bSVijay Mahadevan   }
878181f196bSVijay Mahadevan   if (phypts) {
879181f196bSVijay Mahadevan     ierr = PetscMemzero(phypts, /*npts=1 * */ 3 * sizeof(PetscReal));CHKERRQ(ierr);
880181f196bSVijay Mahadevan   }
881181f196bSVijay Mahadevan 
882181f196bSVijay Mahadevan   if (dim == 1) {
883181f196bSVijay Mahadevan 
884181f196bSVijay Mahadevan     const PetscReal& r = quad[0];
885181f196bSVijay Mahadevan     if (nverts == 2) { /* Linear Edge */
886181f196bSVijay Mahadevan       const PetscReal dNi_dxi[2]  = { -1.0, 1.0 };
887181f196bSVijay Mahadevan 
888181f196bSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
889181f196bSVijay Mahadevan         const PetscReal* vertices = coordinates + i * 3;
890181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i] * vertices[0];
891181f196bSVijay Mahadevan       }
892181f196bSVijay Mahadevan     }
893181f196bSVijay Mahadevan     else if (nverts == 3) { /* Quadratic Edge */
894181f196bSVijay Mahadevan       const PetscReal dNi_dxi[3]  = { 4 * r - 3.0, 4 * ( 1.0 - 2.0 * r ), 4.0 * r - 1.0};
895181f196bSVijay Mahadevan 
896181f196bSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
897181f196bSVijay Mahadevan         const PetscReal* vertices = coordinates + i * 3;
898181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i] * vertices[0];
899181f196bSVijay Mahadevan       }
900181f196bSVijay Mahadevan     }
901181f196bSVijay Mahadevan     else {
902181f196bSVijay 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);
903181f196bSVijay Mahadevan     }
904181f196bSVijay Mahadevan 
905181f196bSVijay Mahadevan     if (ijacobian) {
906181f196bSVijay Mahadevan       /* invert the jacobian */
907181f196bSVijay Mahadevan       ijacobian[0] = 1.0 / jacobian[0];
908181f196bSVijay Mahadevan     }
909181f196bSVijay Mahadevan 
910181f196bSVijay Mahadevan   }
911181f196bSVijay Mahadevan   else if (dim == 2) {
912181f196bSVijay Mahadevan 
913181f196bSVijay Mahadevan     if (nverts == 4) { /* Linear Quadrangle */
914181f196bSVijay Mahadevan       const PetscReal& r = quad[0];
915181f196bSVijay Mahadevan       const PetscReal& s = quad[1];
916181f196bSVijay Mahadevan 
917181f196bSVijay Mahadevan       const PetscReal dNi_dxi[4]  = { -1.0 + s, 1.0 - s, s, -s };
918181f196bSVijay Mahadevan       const PetscReal dNi_deta[4] = { -1.0 + r, -r, r, 1.0 - r };
919181f196bSVijay Mahadevan 
920181f196bSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
921181f196bSVijay Mahadevan         const PetscReal* vertices = coordinates + i * 3;
922181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i]  * vertices[0];
923181f196bSVijay Mahadevan         jacobian[2] += dNi_dxi[i]  * vertices[1];
924181f196bSVijay Mahadevan         jacobian[1] += dNi_deta[i] * vertices[0];
925181f196bSVijay Mahadevan         jacobian[3] += dNi_deta[i] * vertices[1];
926181f196bSVijay Mahadevan       }
927181f196bSVijay Mahadevan     }
928181f196bSVijay Mahadevan     else if (nverts == 3) { /* Linear triangle */
929181f196bSVijay Mahadevan       const PetscReal x2 = coordinates[2 * 3 + 0], y2 = coordinates[2 * 3 + 1];
930181f196bSVijay Mahadevan 
931181f196bSVijay Mahadevan       /* Jacobian is constant */
932181f196bSVijay Mahadevan       jacobian[0] = (coordinates[0 * 3 + 0] - x2); jacobian[1] = (coordinates[1 * 3 + 0] - x2);
933181f196bSVijay Mahadevan       jacobian[2] = (coordinates[0 * 3 + 1] - y2); jacobian[3] = (coordinates[1 * 3 + 1] - y2);
934181f196bSVijay Mahadevan     }
935181f196bSVijay Mahadevan     else {
936181f196bSVijay 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);
937181f196bSVijay Mahadevan     }
938181f196bSVijay Mahadevan 
939181f196bSVijay Mahadevan     /* invert the jacobian */
940181f196bSVijay Mahadevan     if (ijacobian) {
941a86ed394SVijay Mahadevan       ierr = DMatrix_Invert_2x2_Internal(jacobian, ijacobian, &volume);CHKERRQ(ierr);
942181f196bSVijay Mahadevan     }
943181f196bSVijay Mahadevan 
944181f196bSVijay Mahadevan   }
945181f196bSVijay Mahadevan   else {
946181f196bSVijay Mahadevan 
947181f196bSVijay Mahadevan     if (nverts == 8) { /* Linear Hexahedra */
948181f196bSVijay Mahadevan       const PetscReal& r = quad[0];
949181f196bSVijay Mahadevan       const PetscReal& s = quad[1];
950181f196bSVijay Mahadevan       const PetscReal& t = quad[2];
951181f196bSVijay Mahadevan       const PetscReal dNi_dxi[8]  = {- ( 1.0 - s ) * ( 1.0 - t ),
952181f196bSVijay Mahadevan                                        ( 1.0 - s ) * ( 1.0 - t ),
953a86ed394SVijay Mahadevan                                        (       s ) * ( 1.0 - t ),
954a86ed394SVijay Mahadevan                                      - (       s ) * ( 1.0 - t ),
955a86ed394SVijay Mahadevan                                      - ( 1.0 - s ) * (       t ),
956a86ed394SVijay Mahadevan                                        ( 1.0 - s ) * (       t ),
957a86ed394SVijay Mahadevan                                        (       s ) * (       t ),
958a86ed394SVijay Mahadevan                                      - (       s ) * (       t )
959181f196bSVijay Mahadevan                                     };
960181f196bSVijay Mahadevan 
961181f196bSVijay Mahadevan       const PetscReal dNi_deta[8]  = { - ( 1.0 - r ) * ( 1.0 - t ),
962a86ed394SVijay Mahadevan                                        - (       r ) * ( 1.0 - t ),
963a86ed394SVijay Mahadevan                                          (       r ) * ( 1.0 - t ),
964181f196bSVijay Mahadevan                                          ( 1.0 - r ) * ( 1.0 - t ),
965a86ed394SVijay Mahadevan                                        - ( 1.0 - r ) * (       t ),
966a86ed394SVijay Mahadevan                                        - (       r ) * (       t ),
967a86ed394SVijay Mahadevan                                          (       r ) * (       t ),
968a86ed394SVijay Mahadevan                                          ( 1.0 - r ) * (       t )
969181f196bSVijay Mahadevan                                       };
970181f196bSVijay Mahadevan 
971181f196bSVijay Mahadevan       const PetscReal dNi_dzeta[8]  = { - ( 1.0 - r ) * ( 1.0 - s ),
972a86ed394SVijay Mahadevan                                         - (       r ) * ( 1.0 - s ),
973a86ed394SVijay Mahadevan                                         - (       r ) * (       s ),
974a86ed394SVijay Mahadevan                                         - ( 1.0 - r ) * (       s ),
975181f196bSVijay Mahadevan                                           ( 1.0 - r ) * ( 1.0 - s ),
976a86ed394SVijay Mahadevan                                           (       r ) * ( 1.0 - s ),
977a86ed394SVijay Mahadevan                                           (       r ) * (       s ),
978a86ed394SVijay Mahadevan                                           ( 1.0 - r ) * (       s )
979181f196bSVijay Mahadevan                                      };
980a86ed394SVijay Mahadevan 
981181f196bSVijay Mahadevan       for (i = 0; i < nverts; ++i) {
982181f196bSVijay Mahadevan         const PetscReal* vertex = coordinates + i * 3;
983181f196bSVijay Mahadevan         jacobian[0] += dNi_dxi[i]   * vertex[0];
984181f196bSVijay Mahadevan         jacobian[3] += dNi_dxi[i]   * vertex[1];
985181f196bSVijay Mahadevan         jacobian[6] += dNi_dxi[i]   * vertex[2];
986181f196bSVijay Mahadevan         jacobian[1] += dNi_deta[i]  * vertex[0];
987181f196bSVijay Mahadevan         jacobian[4] += dNi_deta[i]  * vertex[1];
988181f196bSVijay Mahadevan         jacobian[7] += dNi_deta[i]  * vertex[2];
989181f196bSVijay Mahadevan         jacobian[2] += dNi_dzeta[i] * vertex[0];
990181f196bSVijay Mahadevan         jacobian[5] += dNi_dzeta[i] * vertex[1];
991181f196bSVijay Mahadevan         jacobian[8] += dNi_dzeta[i] * vertex[2];
992181f196bSVijay Mahadevan       }
993181f196bSVijay Mahadevan 
994181f196bSVijay Mahadevan     }
995181f196bSVijay Mahadevan     else if (nverts == 4) { /* Linear Tetrahedra */
996181f196bSVijay Mahadevan       const PetscReal x0 = coordinates[/*0 * 3 +*/ 0], y0 = coordinates[/*0 * 3 +*/ 1], z0 = coordinates[/*0 * 3 +*/ 2];
997181f196bSVijay Mahadevan 
998181f196bSVijay Mahadevan       /* compute the jacobian */
999181f196bSVijay Mahadevan       jacobian[0] = coordinates[1 * 3 + 0] - x0;  jacobian[1] = coordinates[2 * 3 + 0] - x0; jacobian[2] = coordinates[3 * 3 + 0] - x0;
1000181f196bSVijay Mahadevan       jacobian[3] = coordinates[1 * 3 + 1] - y0;  jacobian[4] = coordinates[2 * 3 + 1] - y0; jacobian[5] = coordinates[3 * 3 + 1] - y0;
1001181f196bSVijay Mahadevan       jacobian[6] = coordinates[1 * 3 + 2] - z0;  jacobian[7] = coordinates[2 * 3 + 2] - z0; jacobian[8] = coordinates[3 * 3 + 2] - z0;
1002181f196bSVijay Mahadevan     } /* Tetrahedra -- ends */
1003181f196bSVijay Mahadevan     else
1004181f196bSVijay Mahadevan     {
1005181f196bSVijay 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);
1006181f196bSVijay Mahadevan     }
1007181f196bSVijay Mahadevan 
1008181f196bSVijay Mahadevan     if (ijacobian) {
1009181f196bSVijay Mahadevan       /* invert the jacobian */
1010a86ed394SVijay Mahadevan       ierr = DMatrix_Invert_3x3_Internal(jacobian, ijacobian, &volume);CHKERRQ(ierr);
1011181f196bSVijay Mahadevan     }
1012181f196bSVijay Mahadevan 
1013181f196bSVijay Mahadevan   }
1014a86ed394SVijay Mahadevan   if ( volume < 1e-12 ) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Element has zero volume: %g. Degenerate element or invalid connectivity\n", volume);
1015a86ed394SVijay Mahadevan   if (dvolume) *dvolume = volume;
1016181f196bSVijay Mahadevan   PetscFunctionReturn(0);
1017181f196bSVijay Mahadevan }
1018181f196bSVijay Mahadevan 
1019181f196bSVijay Mahadevan 
1020181f196bSVijay Mahadevan PetscErrorCode FEMComputeBasis_JandF ( const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscReal *quadrature, PetscReal *phypts,
1021181f196bSVijay Mahadevan                                        PetscReal *phibasis, PetscReal *jacobian, PetscReal *ijacobian, PetscReal* volume  )
1022181f196bSVijay Mahadevan {
1023181f196bSVijay Mahadevan   PetscErrorCode  ierr;
1024181f196bSVijay Mahadevan 
1025181f196bSVijay Mahadevan   PetscFunctionBegin;
1026181f196bSVijay Mahadevan   switch (dim) {
1027181f196bSVijay Mahadevan     case 1:
1028181f196bSVijay Mahadevan       ierr = Compute_Lagrange_Basis_1D_Internal(nverts, coordinates, 1, quadrature, phypts,
1029181f196bSVijay Mahadevan             NULL, phibasis, NULL, jacobian, ijacobian, volume);CHKERRQ(ierr);
1030181f196bSVijay Mahadevan       break;
1031181f196bSVijay Mahadevan     case 2:
1032181f196bSVijay Mahadevan       ierr = Compute_Lagrange_Basis_2D_Internal(nverts, coordinates, 1, quadrature, phypts,
1033181f196bSVijay Mahadevan             NULL, phibasis, NULL, NULL, jacobian, ijacobian, volume);CHKERRQ(ierr);
1034181f196bSVijay Mahadevan       break;
1035181f196bSVijay Mahadevan     case 3:
1036181f196bSVijay Mahadevan       ierr = Compute_Lagrange_Basis_3D_Internal(nverts, coordinates, 1, quadrature, phypts,
1037181f196bSVijay Mahadevan             NULL, phibasis, NULL, NULL, NULL, jacobian, ijacobian, volume);CHKERRQ(ierr);
1038181f196bSVijay Mahadevan       break;
1039181f196bSVijay Mahadevan     default:
1040181f196bSVijay Mahadevan       SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension; should be in [1,3] : %D", dim);
1041181f196bSVijay Mahadevan   }
1042181f196bSVijay Mahadevan   PetscFunctionReturn(0);
1043181f196bSVijay Mahadevan }
1044181f196bSVijay Mahadevan 
1045181f196bSVijay Mahadevan 
1046181f196bSVijay Mahadevan 
1047a86ed394SVijay Mahadevan /*@
1048*97b73a88SSatish Balay   DMMoabPToRMapping - Compute the mapping from the physical coordinate system for a given element to the
1049a86ed394SVijay Mahadevan   canonical reference element. In addition to finding the inverse mapping evaluation through Newton iteration,
1050a86ed394SVijay Mahadevan   the basis function at the parametric point is also evaluated optionally.
1051a86ed394SVijay Mahadevan 
1052a86ed394SVijay Mahadevan   Input Parameter:
1053a86ed394SVijay Mahadevan 
1054a86ed394SVijay Mahadevan .  PetscInt  dim,          the element dimension (1=EDGE, 2=QUAD/TRI, 3=HEX/TET)
1055a86ed394SVijay Mahadevan .  PetscInt nverts,        the number of vertices in the physical element
1056a86ed394SVijay Mahadevan .  PetscReal coordinates,  the coordinates of vertices in the physical element
1057a86ed394SVijay Mahadevan .  PetscReal[3] xphy,      the coordinates of physical point for which natural coordinates (in reference frame) are sought
1058a86ed394SVijay Mahadevan 
1059a86ed394SVijay Mahadevan   Output Parameter:
1060a86ed394SVijay Mahadevan .  PetscReal[3] natparam,  the natural coordinates (in reference frame) corresponding to xphy
1061a86ed394SVijay Mahadevan .  PetscReal[nverts] phi,  the basis functions evaluated at the natural coordinates (natparam)
1062a86ed394SVijay Mahadevan 
1063a86ed394SVijay Mahadevan .keywords: DMMoab, Mapping, FEM
1064a86ed394SVijay Mahadevan @*/
1065181f196bSVijay Mahadevan PetscErrorCode DMMoabPToRMapping( const PetscInt dim, const PetscInt nverts, const PetscReal *coordinates, const PetscReal* xphy, PetscReal* natparam, PetscReal* phi)
1066181f196bSVijay Mahadevan {
1067a86ed394SVijay Mahadevan   /* Perform inverse evaluation for the mapping with use of Newton Raphson iteration */
1068181f196bSVijay Mahadevan   const PetscReal tol = 1.0e-10;
1069181f196bSVijay Mahadevan   const PetscInt max_iterations = 10;
1070181f196bSVijay Mahadevan   const PetscReal error_tol_sqr = tol*tol;
1071181f196bSVijay Mahadevan   PetscReal phibasis[8], jacobian[9], ijacobian[9], volume;
1072181f196bSVijay Mahadevan   PetscReal phypts[3] = {0.0, 0.0, 0.0};
1073181f196bSVijay Mahadevan   PetscReal delta[3] = {0.0, 0.0, 0.0};
1074181f196bSVijay Mahadevan   PetscErrorCode  ierr;
1075181f196bSVijay Mahadevan   PetscInt iters=0;
1076181f196bSVijay Mahadevan   PetscReal error=1.0;
1077181f196bSVijay Mahadevan 
1078181f196bSVijay Mahadevan   PetscFunctionBegin;
1079181f196bSVijay Mahadevan   PetscValidPointer(coordinates, 3);
1080181f196bSVijay Mahadevan   PetscValidPointer(xphy, 4);
1081181f196bSVijay Mahadevan   PetscValidPointer(natparam, 5);
1082181f196bSVijay Mahadevan 
1083181f196bSVijay Mahadevan   ierr = PetscMemzero(jacobian, dim * dim * sizeof(PetscReal));CHKERRQ(ierr);
1084181f196bSVijay Mahadevan   ierr = PetscMemzero(ijacobian, dim * dim * sizeof(PetscReal));CHKERRQ(ierr);
1085181f196bSVijay Mahadevan   ierr = PetscMemzero(phibasis, nverts * sizeof(PetscReal));CHKERRQ(ierr);
1086181f196bSVijay Mahadevan 
1087a86ed394SVijay Mahadevan   /* zero initial guess */
1088a86ed394SVijay Mahadevan   natparam[0] = natparam[1] = natparam[2] = 0.0;
1089181f196bSVijay Mahadevan 
1090a86ed394SVijay Mahadevan   /* Compute delta = evaluate( xi ) - x */
1091a86ed394SVijay Mahadevan   ierr = FEMComputeBasis_JandF ( dim, nverts, coordinates, natparam, phypts, phibasis, jacobian, ijacobian, &volume );CHKERRQ(ierr);
1092a86ed394SVijay Mahadevan 
1093a86ed394SVijay Mahadevan   error = 0.0;
1094a86ed394SVijay Mahadevan   switch(dim) {
1095a86ed394SVijay Mahadevan     case 3:
1096181f196bSVijay Mahadevan       delta[2] = phypts[2] - xphy[2];
1097a86ed394SVijay Mahadevan       error += (delta[2]*delta[2]);
1098a86ed394SVijay Mahadevan     case 2:
1099a86ed394SVijay Mahadevan       delta[1] = phypts[1] - xphy[1];
1100a86ed394SVijay Mahadevan       error += (delta[1]*delta[1]);
1101a86ed394SVijay Mahadevan     case 1:
1102a86ed394SVijay Mahadevan       delta[0] = phypts[0] - xphy[0];
1103a86ed394SVijay Mahadevan       error += (delta[0]*delta[0]);
1104a86ed394SVijay Mahadevan       break;
1105a86ed394SVijay Mahadevan   }
1106a86ed394SVijay Mahadevan 
1107a86ed394SVijay Mahadevan #if 0
1108a86ed394SVijay Mahadevan   PetscInfo4(NULL, "Current point in physical space : (%g, %g, %g) and error : %g\n", xphy[0], xphy[1], xphy[2], error);
1109a86ed394SVijay Mahadevan #endif
1110181f196bSVijay Mahadevan 
1111181f196bSVijay Mahadevan   while (error > error_tol_sqr) {
1112181f196bSVijay Mahadevan 
1113181f196bSVijay Mahadevan     if(++iters > max_iterations)
1114181f196bSVijay 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]);
1115181f196bSVijay Mahadevan 
1116181f196bSVijay Mahadevan     /* Compute natparam -= J.inverse() * delta */
1117181f196bSVijay Mahadevan     switch(dim) {
1118181f196bSVijay Mahadevan       case 1:
1119181f196bSVijay Mahadevan         natparam[0] -= ijacobian[0] * delta[0];
1120181f196bSVijay Mahadevan         break;
1121181f196bSVijay Mahadevan       case 2:
1122181f196bSVijay Mahadevan         natparam[0] -= ijacobian[0] * delta[0] + ijacobian[1] * delta[1];
1123181f196bSVijay Mahadevan         natparam[1] -= ijacobian[2] * delta[0] + ijacobian[3] * delta[1];
1124181f196bSVijay Mahadevan         break;
1125181f196bSVijay Mahadevan       case 3:
1126181f196bSVijay Mahadevan         natparam[0] -= ijacobian[0] * delta[0] + ijacobian[1] * delta[1] + ijacobian[2] * delta[2];
1127181f196bSVijay Mahadevan         natparam[1] -= ijacobian[3] * delta[0] + ijacobian[4] * delta[1] + ijacobian[5] * delta[2];
1128181f196bSVijay Mahadevan         natparam[2] -= ijacobian[6] * delta[0] + ijacobian[7] * delta[1] + ijacobian[8] * delta[2];
1129181f196bSVijay Mahadevan         break;
1130181f196bSVijay Mahadevan     }
1131181f196bSVijay Mahadevan 
1132181f196bSVijay Mahadevan     /* Compute delta = evaluate( xi ) - x */
1133a86ed394SVijay Mahadevan     ierr = FEMComputeBasis_JandF ( dim, nverts, coordinates, natparam, phypts, phibasis, jacobian, ijacobian, &volume );CHKERRQ(ierr);
1134181f196bSVijay Mahadevan 
1135a86ed394SVijay Mahadevan     error = 0.0;
1136a86ed394SVijay Mahadevan     switch(dim) {
1137a86ed394SVijay Mahadevan       case 3:
1138181f196bSVijay Mahadevan         delta[2] = phypts[2] - xphy[2];
1139a86ed394SVijay Mahadevan         error += (delta[2]*delta[2]);
1140a86ed394SVijay Mahadevan       case 2:
1141a86ed394SVijay Mahadevan         delta[1] = phypts[1] - xphy[1];
1142a86ed394SVijay Mahadevan         error += (delta[1]*delta[1]);
1143a86ed394SVijay Mahadevan       case 1:
1144a86ed394SVijay Mahadevan         delta[0] = phypts[0] - xphy[0];
1145a86ed394SVijay Mahadevan         error += (delta[0]*delta[0]);
1146a86ed394SVijay Mahadevan         break;
1147a86ed394SVijay Mahadevan     }
1148a86ed394SVijay Mahadevan #if 0
1149a86ed394SVijay Mahadevan     PetscInfo5(NULL, "Newton [%D] : Current point in reference space : (%g, %g, %g) and error : %g\n", iters, natparam[0], natparam[1], natparam[2], error);
1150a86ed394SVijay Mahadevan #endif
1151181f196bSVijay Mahadevan   }
1152181f196bSVijay Mahadevan   if (phi) {
1153181f196bSVijay Mahadevan     ierr = PetscMemcpy(phi, phibasis, nverts * sizeof(PetscReal));CHKERRQ(ierr);
1154181f196bSVijay Mahadevan   }
1155181f196bSVijay Mahadevan   PetscFunctionReturn(0);
1156181f196bSVijay Mahadevan }
1157181f196bSVijay Mahadevan 
1158