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