xref: /petsc/src/dm/dt/fe/impls/basic/febasic.c (revision 665f567fbb66b540ec875154af897510965f64fc)
120cf1dd8SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
220cf1dd8SToby Isaac #include <petscblaslapack.h>
320cf1dd8SToby Isaac 
42b99622eSMatthew G. Knepley static PetscErrorCode PetscFEDestroy_Basic(PetscFE fem)
520cf1dd8SToby Isaac {
620cf1dd8SToby Isaac   PetscFE_Basic *b = (PetscFE_Basic *) fem->data;
720cf1dd8SToby Isaac   PetscErrorCode ierr;
820cf1dd8SToby Isaac 
920cf1dd8SToby Isaac   PetscFunctionBegin;
1020cf1dd8SToby Isaac   ierr = PetscFree(b);CHKERRQ(ierr);
1120cf1dd8SToby Isaac   PetscFunctionReturn(0);
1220cf1dd8SToby Isaac }
1320cf1dd8SToby Isaac 
142b99622eSMatthew G. Knepley static PetscErrorCode PetscFEView_Basic_Ascii(PetscFE fe, PetscViewer v)
1520cf1dd8SToby Isaac {
16d9bac1caSLisandro Dalcin   PetscInt          dim, Nc;
17d9bac1caSLisandro Dalcin   PetscSpace        basis = NULL;
18d9bac1caSLisandro Dalcin   PetscDualSpace    dual = NULL;
19d9bac1caSLisandro Dalcin   PetscQuadrature   quad = NULL;
2020cf1dd8SToby Isaac   PetscErrorCode    ierr;
2120cf1dd8SToby Isaac 
2220cf1dd8SToby Isaac   PetscFunctionBegin;
23d9bac1caSLisandro Dalcin   ierr = PetscFEGetSpatialDimension(fe, &dim);CHKERRQ(ierr);
24d9bac1caSLisandro Dalcin   ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr);
2520cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe, &basis);CHKERRQ(ierr);
2620cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe, &dual);CHKERRQ(ierr);
27d9bac1caSLisandro Dalcin   ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr);
28d9bac1caSLisandro Dalcin   ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
29d9bac1caSLisandro Dalcin   ierr = PetscViewerASCIIPrintf(v, "Basic Finite Element in %D dimensions with %D components\n",dim,Nc);CHKERRQ(ierr);
30d9bac1caSLisandro Dalcin   if (basis) {ierr = PetscSpaceView(basis, v);CHKERRQ(ierr);}
31d9bac1caSLisandro Dalcin   if (dual)  {ierr = PetscDualSpaceView(dual, v);CHKERRQ(ierr);}
32d9bac1caSLisandro Dalcin   if (quad)  {ierr = PetscQuadratureView(quad, v);CHKERRQ(ierr);}
33d9bac1caSLisandro Dalcin   ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
3420cf1dd8SToby Isaac   PetscFunctionReturn(0);
3520cf1dd8SToby Isaac }
3620cf1dd8SToby Isaac 
372b99622eSMatthew G. Knepley static PetscErrorCode PetscFEView_Basic(PetscFE fe, PetscViewer v)
3820cf1dd8SToby Isaac {
3920cf1dd8SToby Isaac   PetscBool      iascii;
4020cf1dd8SToby Isaac   PetscErrorCode ierr;
4120cf1dd8SToby Isaac 
4220cf1dd8SToby Isaac   PetscFunctionBegin;
43d9bac1caSLisandro Dalcin   ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
44d9bac1caSLisandro Dalcin   if (iascii) {ierr = PetscFEView_Basic_Ascii(fe, v);CHKERRQ(ierr);}
4520cf1dd8SToby Isaac   PetscFunctionReturn(0);
4620cf1dd8SToby Isaac }
4720cf1dd8SToby Isaac 
4820cf1dd8SToby Isaac /* Construct the change of basis from prime basis to nodal basis */
4915310ec5SMatthew G. Knepley PetscErrorCode PetscFESetUp_Basic(PetscFE fem)
5020cf1dd8SToby Isaac {
51b9d4cb8dSJed Brown   PetscReal     *work;
5220cf1dd8SToby Isaac   PetscBLASInt  *pivots;
5320cf1dd8SToby Isaac   PetscBLASInt   n, info;
5420cf1dd8SToby Isaac   PetscInt       pdim, j;
5520cf1dd8SToby Isaac   PetscErrorCode ierr;
5620cf1dd8SToby Isaac 
5720cf1dd8SToby Isaac   PetscFunctionBegin;
5820cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr);
5920cf1dd8SToby Isaac   ierr = PetscMalloc1(pdim*pdim,&fem->invV);CHKERRQ(ierr);
6020cf1dd8SToby Isaac   for (j = 0; j < pdim; ++j) {
6120cf1dd8SToby Isaac     PetscReal       *Bf;
6220cf1dd8SToby Isaac     PetscQuadrature  f;
6320cf1dd8SToby Isaac     const PetscReal *points, *weights;
6420cf1dd8SToby Isaac     PetscInt         Nc, Nq, q, k, c;
6520cf1dd8SToby Isaac 
6620cf1dd8SToby Isaac     ierr = PetscDualSpaceGetFunctional(fem->dualSpace, j, &f);CHKERRQ(ierr);
6720cf1dd8SToby Isaac     ierr = PetscQuadratureGetData(f, NULL, &Nc, &Nq, &points, &weights);CHKERRQ(ierr);
6820cf1dd8SToby Isaac     ierr = PetscMalloc1(Nc*Nq*pdim,&Bf);CHKERRQ(ierr);
6920cf1dd8SToby Isaac     ierr = PetscSpaceEvaluate(fem->basisSpace, Nq, points, Bf, NULL, NULL);CHKERRQ(ierr);
7020cf1dd8SToby Isaac     for (k = 0; k < pdim; ++k) {
7120cf1dd8SToby Isaac       /* V_{jk} = n_j(\phi_k) = \int \phi_k(x) n_j(x) dx */
72b9d4cb8dSJed Brown       fem->invV[j*pdim+k] = 0.0;
7320cf1dd8SToby Isaac 
7420cf1dd8SToby Isaac       for (q = 0; q < Nq; ++q) {
75b9d4cb8dSJed Brown         for (c = 0; c < Nc; ++c) fem->invV[j*pdim+k] += Bf[(q*pdim + k)*Nc + c]*weights[q*Nc + c];
7620cf1dd8SToby Isaac       }
7720cf1dd8SToby Isaac     }
7820cf1dd8SToby Isaac     ierr = PetscFree(Bf);CHKERRQ(ierr);
7920cf1dd8SToby Isaac   }
80ea2bdf6dSBarry Smith 
8120cf1dd8SToby Isaac   ierr = PetscMalloc2(pdim,&pivots,pdim,&work);CHKERRQ(ierr);
8220cf1dd8SToby Isaac   n = pdim;
83b9d4cb8dSJed Brown   PetscStackCallBLAS("LAPACKgetrf", LAPACKREALgetrf_(&n, &n, fem->invV, &n, pivots, &info));
84ea2bdf6dSBarry Smith   if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error returned from LAPACKgetrf %D",(PetscInt)info);
85b9d4cb8dSJed Brown   PetscStackCallBLAS("LAPACKgetri", LAPACKREALgetri_(&n, fem->invV, &n, pivots, work, &n, &info));
86ea2bdf6dSBarry Smith   if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error returned from LAPACKgetri %D",(PetscInt)info);
8720cf1dd8SToby Isaac   ierr = PetscFree2(pivots,work);CHKERRQ(ierr);
8820cf1dd8SToby Isaac   PetscFunctionReturn(0);
8920cf1dd8SToby Isaac }
9020cf1dd8SToby Isaac 
9120cf1dd8SToby Isaac PetscErrorCode PetscFEGetDimension_Basic(PetscFE fem, PetscInt *dim)
9220cf1dd8SToby Isaac {
9320cf1dd8SToby Isaac   PetscErrorCode ierr;
9420cf1dd8SToby Isaac 
9520cf1dd8SToby Isaac   PetscFunctionBegin;
9620cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDimension(fem->dualSpace, dim);CHKERRQ(ierr);
9720cf1dd8SToby Isaac   PetscFunctionReturn(0);
9820cf1dd8SToby Isaac }
9920cf1dd8SToby Isaac 
100b9d4cb8dSJed Brown /* Tensor contraction on the middle index,
101b9d4cb8dSJed Brown  *    C[m,n,p] = A[m,k,p] * B[k,n]
102b9d4cb8dSJed Brown  * where all matrices use C-style ordering.
103b9d4cb8dSJed Brown  */
104b9d4cb8dSJed Brown static PetscErrorCode TensorContract_Private(PetscInt m,PetscInt n,PetscInt p,PetscInt k,const PetscReal *A,const PetscReal *B,PetscReal *C) {
105b9d4cb8dSJed Brown   PetscErrorCode ierr;
106b9d4cb8dSJed Brown   PetscInt i;
107b9d4cb8dSJed Brown 
108b9d4cb8dSJed Brown   PetscFunctionBegin;
109b9d4cb8dSJed Brown   for (i=0; i<m; i++) {
110b9d4cb8dSJed Brown     PetscBLASInt n_,p_,k_,lda,ldb,ldc;
111b9d4cb8dSJed Brown     PetscReal one = 1, zero = 0;
112b9d4cb8dSJed Brown     /* Taking contiguous submatrices, we wish to comput c[n,p] = a[k,p] * B[k,n]
113b9d4cb8dSJed Brown      * or, in Fortran ordering, c(p,n) = a(p,k) * B(n,k)
114b9d4cb8dSJed Brown      */
115b9d4cb8dSJed Brown     ierr = PetscBLASIntCast(n,&n_);CHKERRQ(ierr);
116b9d4cb8dSJed Brown     ierr = PetscBLASIntCast(p,&p_);CHKERRQ(ierr);
117b9d4cb8dSJed Brown     ierr = PetscBLASIntCast(k,&k_);CHKERRQ(ierr);
118b9d4cb8dSJed Brown     lda = p_;
119b9d4cb8dSJed Brown     ldb = n_;
120b9d4cb8dSJed Brown     ldc = p_;
121b9d4cb8dSJed Brown     PetscStackCallBLAS("BLASgemm",BLASREALgemm_("N","T",&p_,&n_,&k_,&one,A+i*k*p,&lda,B,&ldb,&zero,C+i*n*p,&ldc));
122b9d4cb8dSJed Brown   }
1236485a3bbSJed Brown   ierr = PetscLogFlops(2.*m*n*p*k);CHKERRQ(ierr);
124b9d4cb8dSJed Brown   PetscFunctionReturn(0);
125b9d4cb8dSJed Brown }
126b9d4cb8dSJed Brown 
127ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFECreateTabulation_Basic(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation T)
12820cf1dd8SToby Isaac {
12920cf1dd8SToby Isaac   DM               dm;
13020cf1dd8SToby Isaac   PetscInt         pdim; /* Dimension of FE space P */
13120cf1dd8SToby Isaac   PetscInt         dim;  /* Spatial dimension */
13220cf1dd8SToby Isaac   PetscInt         Nc;   /* Field components */
133ef0bb6c7SMatthew G. Knepley   PetscReal       *B = K >= 0 ? T->T[0] : NULL;
134ef0bb6c7SMatthew G. Knepley   PetscReal       *D = K >= 1 ? T->T[1] : NULL;
135ef0bb6c7SMatthew G. Knepley   PetscReal       *H = K >= 2 ? T->T[2] : NULL;
136ef0bb6c7SMatthew G. Knepley   PetscReal       *tmpB = NULL, *tmpD = NULL, *tmpH = NULL;
13720cf1dd8SToby Isaac   PetscErrorCode   ierr;
13820cf1dd8SToby Isaac 
13920cf1dd8SToby Isaac   PetscFunctionBegin;
14020cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr);
14120cf1dd8SToby Isaac   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
14220cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr);
14320cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
14420cf1dd8SToby Isaac   /* Evaluate the prime basis functions at all points */
145ef0bb6c7SMatthew G. Knepley   if (K >= 0) {ierr = DMGetWorkArray(dm, npoints*pdim*Nc, MPIU_REAL, &tmpB);CHKERRQ(ierr);}
146ef0bb6c7SMatthew G. Knepley   if (K >= 1) {ierr = DMGetWorkArray(dm, npoints*pdim*Nc*dim, MPIU_REAL, &tmpD);CHKERRQ(ierr);}
147ef0bb6c7SMatthew G. Knepley   if (K >= 2) {ierr = DMGetWorkArray(dm, npoints*pdim*Nc*dim*dim, MPIU_REAL, &tmpH);CHKERRQ(ierr);}
148ef0bb6c7SMatthew G. Knepley   ierr = PetscSpaceEvaluate(fem->basisSpace, npoints, points, tmpB, tmpD, tmpH);CHKERRQ(ierr);
149b9d4cb8dSJed Brown   /* Translate from prime to nodal basis */
15020cf1dd8SToby Isaac   if (B) {
151b9d4cb8dSJed Brown     /* B[npoints, nodes, Nc] = tmpB[npoints, prime, Nc] * invV[prime, nodes] */
152b9d4cb8dSJed Brown     ierr = TensorContract_Private(npoints, pdim, Nc, pdim, tmpB, fem->invV, B);CHKERRQ(ierr);
15320cf1dd8SToby Isaac   }
15420cf1dd8SToby Isaac   if (D) {
155b9d4cb8dSJed Brown     /* D[npoints, nodes, Nc, dim] = tmpD[npoints, prime, Nc, dim] * invV[prime, nodes] */
156b9d4cb8dSJed Brown     ierr = TensorContract_Private(npoints, pdim, Nc*dim, pdim, tmpD, fem->invV, D);CHKERRQ(ierr);
15720cf1dd8SToby Isaac   }
15820cf1dd8SToby Isaac   if (H) {
159b9d4cb8dSJed Brown     /* H[npoints, nodes, Nc, dim, dim] = tmpH[npoints, prime, Nc, dim, dim] * invV[prime, nodes] */
160b9d4cb8dSJed Brown     ierr = TensorContract_Private(npoints, pdim, Nc*dim*dim, pdim, tmpH, fem->invV, H);CHKERRQ(ierr);
16120cf1dd8SToby Isaac   }
162ef0bb6c7SMatthew G. Knepley   if (K >= 0) {ierr = DMRestoreWorkArray(dm, npoints*pdim*Nc, MPIU_REAL, &tmpB);CHKERRQ(ierr);}
163ef0bb6c7SMatthew G. Knepley   if (K >= 1) {ierr = DMRestoreWorkArray(dm, npoints*pdim*Nc*dim, MPIU_REAL, &tmpD);CHKERRQ(ierr);}
164ef0bb6c7SMatthew G. Knepley   if (K >= 2) {ierr = DMRestoreWorkArray(dm, npoints*pdim*Nc*dim*dim, MPIU_REAL, &tmpH);CHKERRQ(ierr);}
16520cf1dd8SToby Isaac   PetscFunctionReturn(0);
16620cf1dd8SToby Isaac }
16720cf1dd8SToby Isaac 
1682b99622eSMatthew G. Knepley static PetscErrorCode PetscFEIntegrate_Basic(PetscDS ds, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom,
1694bee2e38SMatthew G. Knepley                                              const PetscScalar coefficients[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
17020cf1dd8SToby Isaac {
17120cf1dd8SToby Isaac   const PetscInt     debug = 0;
1724bee2e38SMatthew G. Knepley   PetscFE            fe;
17320cf1dd8SToby Isaac   PetscPointFunc     obj_func;
17420cf1dd8SToby Isaac   PetscQuadrature    quad;
175ef0bb6c7SMatthew G. Knepley   PetscTabulation   *T, *TAux = NULL;
1764bee2e38SMatthew G. Knepley   PetscScalar       *u, *u_x, *a, *a_x;
17720cf1dd8SToby Isaac   const PetscScalar *constants;
17820cf1dd8SToby Isaac   PetscReal         *x;
179ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
18020cf1dd8SToby Isaac   PetscInt           dim, dE, Np, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, e;
18120cf1dd8SToby Isaac   PetscBool          isAffine;
18220cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
18320cf1dd8SToby Isaac   PetscInt           qNc, Nq, q;
18420cf1dd8SToby Isaac   PetscErrorCode     ierr;
18520cf1dd8SToby Isaac 
18620cf1dd8SToby Isaac   PetscFunctionBegin;
1874bee2e38SMatthew G. Knepley   ierr = PetscDSGetObjective(ds, field, &obj_func);CHKERRQ(ierr);
18820cf1dd8SToby Isaac   if (!obj_func) PetscFunctionReturn(0);
1894bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
1904bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(fe, &dim);CHKERRQ(ierr);
1914bee2e38SMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr);
1924bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
1934bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
1944bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
1954bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
196ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetTabulation(ds, &T);CHKERRQ(ierr);
1974bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, NULL, &u_x);CHKERRQ(ierr);
1984bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
1994bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
2004bee2e38SMatthew G. Knepley   if (dsAux) {
2014bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
2024bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
2034bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
2044bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
205ef0bb6c7SMatthew G. Knepley     ierr = PetscDSGetTabulation(dsAux, &TAux);CHKERRQ(ierr);
2064bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
20720cf1dd8SToby Isaac   }
20820cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
2094bee2e38SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
21020cf1dd8SToby Isaac   Np = cgeom->numPoints;
21120cf1dd8SToby Isaac   dE = cgeom->dimEmbed;
21220cf1dd8SToby Isaac   isAffine = cgeom->isAffine;
21320cf1dd8SToby Isaac   for (e = 0; e < Ne; ++e) {
2144bee2e38SMatthew G. Knepley     PetscFEGeom fegeom;
21520cf1dd8SToby Isaac 
21627f02ce8SMatthew G. Knepley     fegeom.dim      = cgeom->dim;
21727f02ce8SMatthew G. Knepley     fegeom.dimEmbed = cgeom->dimEmbed;
21820cf1dd8SToby Isaac     if (isAffine) {
2194bee2e38SMatthew G. Knepley       fegeom.v    = x;
2204bee2e38SMatthew G. Knepley       fegeom.xi   = cgeom->xi;
2217132c3f7SMatthew G. Knepley       fegeom.J    = &cgeom->J[e*Np*dE*dE];
2227132c3f7SMatthew G. Knepley       fegeom.invJ = &cgeom->invJ[e*Np*dE*dE];
2237132c3f7SMatthew G. Knepley       fegeom.detJ = &cgeom->detJ[e*Np];
22420cf1dd8SToby Isaac     }
2254bee2e38SMatthew G. Knepley     for (q = 0; q < Nq; ++q) {
2264bee2e38SMatthew G. Knepley       PetscScalar integrand;
2274bee2e38SMatthew G. Knepley       PetscReal   w;
2284bee2e38SMatthew G. Knepley 
2294bee2e38SMatthew G. Knepley       if (isAffine) {
2307132c3f7SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &cgeom->v[e*Np*dE], fegeom.J, &quadPoints[q*dim], x);
2314bee2e38SMatthew G. Knepley       } else {
2324bee2e38SMatthew G. Knepley         fegeom.v    = &cgeom->v[(e*Np+q)*dE];
2334bee2e38SMatthew G. Knepley         fegeom.J    = &cgeom->J[(e*Np+q)*dE*dE];
2344bee2e38SMatthew G. Knepley         fegeom.invJ = &cgeom->invJ[(e*Np+q)*dE*dE];
2354bee2e38SMatthew G. Knepley         fegeom.detJ = &cgeom->detJ[e*Np+q];
2364bee2e38SMatthew G. Knepley       }
2374bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
23820cf1dd8SToby Isaac       if (debug > 1 && q < Np) {
2394bee2e38SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
2407be5e748SToby Isaac #if !defined(PETSC_USE_COMPLEX)
2414bee2e38SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ);CHKERRQ(ierr);
24220cf1dd8SToby Isaac #endif
24320cf1dd8SToby Isaac       }
24420cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
245ef0bb6c7SMatthew G. Knepley       ierr = PetscFEEvaluateFieldJets_Internal(ds, Nf, 0, q, T, &fegeom, &coefficients[cOffset], NULL, u, u_x, NULL);CHKERRQ(ierr);
246ef0bb6c7SMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
2474bee2e38SMatthew G. Knepley       obj_func(dim, Nf, NfAux, uOff, uOff_x, u, NULL, u_x, aOff, aOff_x, a, NULL, a_x, 0.0, fegeom.v, numConstants, constants, &integrand);
2484bee2e38SMatthew G. Knepley       integrand *= w;
24920cf1dd8SToby Isaac       integral[e*Nf+field] += integrand;
25020cf1dd8SToby Isaac       if (debug > 1) {ierr = PetscPrintf(PETSC_COMM_SELF, "    int: %g %g\n", (double) PetscRealPart(integrand), (double) PetscRealPart(integral[field]));CHKERRQ(ierr);}
25120cf1dd8SToby Isaac     }
25220cf1dd8SToby Isaac     cOffset    += totDim;
25320cf1dd8SToby Isaac     cOffsetAux += totDimAux;
25420cf1dd8SToby Isaac   }
25520cf1dd8SToby Isaac   PetscFunctionReturn(0);
25620cf1dd8SToby Isaac }
25720cf1dd8SToby Isaac 
2582b99622eSMatthew G. Knepley static PetscErrorCode PetscFEIntegrateBd_Basic(PetscDS ds, PetscInt field,
259afe6d6adSToby Isaac                                                PetscBdPointFunc obj_func,
2604bee2e38SMatthew G. Knepley                                                PetscInt Ne, PetscFEGeom *fgeom, const PetscScalar coefficients[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
261afe6d6adSToby Isaac {
262afe6d6adSToby Isaac   const PetscInt     debug = 0;
2634bee2e38SMatthew G. Knepley   PetscFE            fe;
264afe6d6adSToby Isaac   PetscQuadrature    quad;
265ef0bb6c7SMatthew G. Knepley   PetscTabulation   *Tf, *TfAux = NULL;
2664bee2e38SMatthew G. Knepley   PetscScalar       *u, *u_x, *a, *a_x, *basisReal, *basisDerReal;
267afe6d6adSToby Isaac   const PetscScalar *constants;
268afe6d6adSToby Isaac   PetscReal         *x;
269ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
270afe6d6adSToby Isaac   PetscBool          isAffine, auxOnBd;
271afe6d6adSToby Isaac   const PetscReal   *quadPoints, *quadWeights;
272afe6d6adSToby Isaac   PetscInt           qNc, Nq, q, Np, dE;
273afe6d6adSToby Isaac   PetscInt           dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, e;
274afe6d6adSToby Isaac   PetscErrorCode     ierr;
275afe6d6adSToby Isaac 
276afe6d6adSToby Isaac   PetscFunctionBegin;
277afe6d6adSToby Isaac   if (!obj_func) PetscFunctionReturn(0);
2784bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
2794bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(fe, &dim);CHKERRQ(ierr);
2804bee2e38SMatthew G. Knepley   ierr = PetscFEGetFaceQuadrature(fe, &quad);CHKERRQ(ierr);
2814bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
2824bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
2834bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
2844bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
2854bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, NULL, &u_x);CHKERRQ(ierr);
2864bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL);CHKERRQ(ierr);
287ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetFaceTabulation(ds, &Tf);CHKERRQ(ierr);
2884bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
2894bee2e38SMatthew G. Knepley   if (dsAux) {
2904bee2e38SMatthew G. Knepley     ierr = PetscDSGetSpatialDimension(dsAux, &dimAux);CHKERRQ(ierr);
2914bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
2924bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
2934bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
2944bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
2954bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
296afe6d6adSToby Isaac     auxOnBd = dimAux < dim ? PETSC_TRUE : PETSC_FALSE;
297ef0bb6c7SMatthew G. Knepley     if (auxOnBd) {ierr = PetscDSGetTabulation(dsAux, &TfAux);CHKERRQ(ierr);}
298ef0bb6c7SMatthew G. Knepley     else         {ierr = PetscDSGetFaceTabulation(dsAux, &TfAux);CHKERRQ(ierr);}
299afe6d6adSToby Isaac   }
300afe6d6adSToby Isaac   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
301afe6d6adSToby Isaac   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
302afe6d6adSToby Isaac   Np = fgeom->numPoints;
303afe6d6adSToby Isaac   dE = fgeom->dimEmbed;
304afe6d6adSToby Isaac   isAffine = fgeom->isAffine;
305afe6d6adSToby Isaac   for (e = 0; e < Ne; ++e) {
3069f209ee4SMatthew G. Knepley     PetscFEGeom    fegeom, cgeom;
307afe6d6adSToby Isaac     const PetscInt face = fgeom->face[e][0]; /* Local face number in cell */
3084dcf62a8SSatish Balay     fegeom.n = 0;
3094dcf62a8SSatish Balay     fegeom.v = 0;
3104dcf62a8SSatish Balay     fegeom.J = 0;
3114dcf62a8SSatish Balay     fegeom.detJ = 0;
31227f02ce8SMatthew G. Knepley     fegeom.dim      = fgeom->dim;
31327f02ce8SMatthew G. Knepley     fegeom.dimEmbed = fgeom->dimEmbed;
31427f02ce8SMatthew G. Knepley     cgeom.dim       = fgeom->dim;
31527f02ce8SMatthew G. Knepley     cgeom.dimEmbed  = fgeom->dimEmbed;
3164bee2e38SMatthew G. Knepley     if (isAffine) {
3174bee2e38SMatthew G. Knepley       fegeom.v    = x;
3184bee2e38SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
3197132c3f7SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*Np*dE*dE];
3207132c3f7SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*Np*dE*dE];
3217132c3f7SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e*Np];
3227132c3f7SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*Np*dE];
3239f209ee4SMatthew G. Knepley 
3247132c3f7SMatthew G. Knepley       cgeom.J     = &fgeom->suppJ[0][e*Np*dE*dE];
3257132c3f7SMatthew G. Knepley       cgeom.invJ  = &fgeom->suppInvJ[0][e*Np*dE*dE];
3267132c3f7SMatthew G. Knepley       cgeom.detJ  = &fgeom->suppDetJ[0][e*Np];
3274bee2e38SMatthew G. Knepley     }
328afe6d6adSToby Isaac     for (q = 0; q < Nq; ++q) {
329afe6d6adSToby Isaac       PetscScalar integrand;
3304bee2e38SMatthew G. Knepley       PetscReal   w;
331afe6d6adSToby Isaac 
332afe6d6adSToby Isaac       if (isAffine) {
3337132c3f7SMatthew G. Knepley         CoordinatesRefToReal(dE, dim-1, fegeom.xi, &fgeom->v[e*Np*dE], fegeom.J, &quadPoints[q*(dim-1)], x);
334afe6d6adSToby Isaac       } else {
3353fe841f2SMatthew G. Knepley         fegeom.v    = &fgeom->v[(e*Np+q)*dE];
3369f209ee4SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
3379f209ee4SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
3384bee2e38SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
3394bee2e38SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
3409f209ee4SMatthew G. Knepley 
3419f209ee4SMatthew G. Knepley         cgeom.J     = &fgeom->suppJ[0][(e*Np+q)*dE*dE];
3429f209ee4SMatthew G. Knepley         cgeom.invJ  = &fgeom->suppInvJ[0][(e*Np+q)*dE*dE];
3439f209ee4SMatthew G. Knepley         cgeom.detJ  = &fgeom->suppDetJ[0][e*Np+q];
344afe6d6adSToby Isaac       }
3454bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
346afe6d6adSToby Isaac       if (debug > 1 && q < Np) {
3474bee2e38SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
348afe6d6adSToby Isaac #ifndef PETSC_USE_COMPLEX
3494bee2e38SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ);CHKERRQ(ierr);
350afe6d6adSToby Isaac #endif
351afe6d6adSToby Isaac       }
352afe6d6adSToby Isaac       if (debug > 1) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
353ef0bb6c7SMatthew G. Knepley       ierr = PetscFEEvaluateFieldJets_Internal(ds, Nf, face, q, Tf, &cgeom, &coefficients[cOffset], NULL, u, u_x, NULL);CHKERRQ(ierr);
354ef0bb6c7SMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, face, q, TfAux, &cgeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
3554bee2e38SMatthew G. Knepley       obj_func(dim, Nf, NfAux, uOff, uOff_x, u, NULL, u_x, aOff, aOff_x, a, NULL, a_x, 0.0, fegeom.v, fegeom.n, numConstants, constants, &integrand);
3564bee2e38SMatthew G. Knepley       integrand *= w;
357afe6d6adSToby Isaac       integral[e*Nf+field] += integrand;
358afe6d6adSToby Isaac       if (debug > 1) {ierr = PetscPrintf(PETSC_COMM_SELF, "    int: %g %g\n", (double) PetscRealPart(integrand), (double) PetscRealPart(integral[e*Nf+field]));CHKERRQ(ierr);}
359afe6d6adSToby Isaac     }
360afe6d6adSToby Isaac     cOffset    += totDim;
361afe6d6adSToby Isaac     cOffsetAux += totDimAux;
362afe6d6adSToby Isaac   }
363afe6d6adSToby Isaac   PetscFunctionReturn(0);
364afe6d6adSToby Isaac }
365afe6d6adSToby Isaac 
3664bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateResidual_Basic(PetscDS ds, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom,
3674bee2e38SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
36820cf1dd8SToby Isaac {
36920cf1dd8SToby Isaac   const PetscInt     debug = 0;
3704bee2e38SMatthew G. Knepley   PetscFE            fe;
37120cf1dd8SToby Isaac   PetscPointFunc     f0_func;
37220cf1dd8SToby Isaac   PetscPointFunc     f1_func;
37320cf1dd8SToby Isaac   PetscQuadrature    quad;
374ef0bb6c7SMatthew G. Knepley   PetscTabulation   *T, *TAux = NULL;
3754bee2e38SMatthew G. Knepley   PetscScalar       *f0, *f1, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal;
37620cf1dd8SToby Isaac   const PetscScalar *constants;
37720cf1dd8SToby Isaac   PetscReal         *x;
378ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
379ef0bb6c7SMatthew G. Knepley   PetscInt           dim, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, fOffset, e;
38020cf1dd8SToby Isaac   PetscBool          isAffine;
38120cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
3824bee2e38SMatthew G. Knepley   PetscInt           qNc, Nq, q, Np, dE;
38320cf1dd8SToby Isaac   PetscErrorCode     ierr;
38420cf1dd8SToby Isaac 
38520cf1dd8SToby Isaac   PetscFunctionBegin;
3864bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
3874bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(fe, &dim);CHKERRQ(ierr);
3884bee2e38SMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr);
3894bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
3904bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
3914bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
3924bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
3934bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, field, &fOffset);CHKERRQ(ierr);
3944bee2e38SMatthew G. Knepley   ierr = PetscDSGetResidual(ds, field, &f0_func, &f1_func);CHKERRQ(ierr);
3954bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
3964bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL);CHKERRQ(ierr);
3974bee2e38SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, &f0, &f1, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
3984bee2e38SMatthew G. Knepley   if (!f0_func && !f1_func) PetscFunctionReturn(0);
399ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetTabulation(ds, &T);CHKERRQ(ierr);
4004bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
4014bee2e38SMatthew G. Knepley   if (dsAux) {
4024bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
4034bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
4044bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
4054bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
4064bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
407ef0bb6c7SMatthew G. Knepley     ierr = PetscDSGetTabulation(dsAux, &TAux);CHKERRQ(ierr);
40820cf1dd8SToby Isaac   }
40920cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
4104bee2e38SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
41120cf1dd8SToby Isaac   Np = cgeom->numPoints;
41220cf1dd8SToby Isaac   dE = cgeom->dimEmbed;
41320cf1dd8SToby Isaac   isAffine = cgeom->isAffine;
41420cf1dd8SToby Isaac   for (e = 0; e < Ne; ++e) {
4154bee2e38SMatthew G. Knepley     PetscFEGeom fegeom;
41620cf1dd8SToby Isaac 
41727f02ce8SMatthew G. Knepley     fegeom.dim      = cgeom->dim;
41827f02ce8SMatthew G. Knepley     fegeom.dimEmbed = cgeom->dimEmbed;
4194bee2e38SMatthew G. Knepley     if (isAffine) {
4204bee2e38SMatthew G. Knepley       fegeom.v    = x;
4214bee2e38SMatthew G. Knepley       fegeom.xi   = cgeom->xi;
4227132c3f7SMatthew G. Knepley       fegeom.J    = &cgeom->J[e*Np*dE*dE];
4237132c3f7SMatthew G. Knepley       fegeom.invJ = &cgeom->invJ[e*Np*dE*dE];
4247132c3f7SMatthew G. Knepley       fegeom.detJ = &cgeom->detJ[e*Np];
4254bee2e38SMatthew G. Knepley     }
426ef0bb6c7SMatthew G. Knepley     ierr = PetscArrayzero(f0, Nq*T[field]->Nc);CHKERRQ(ierr);
42727f02ce8SMatthew G. Knepley     ierr = PetscArrayzero(f1, Nq*T[field]->Nc*dE);CHKERRQ(ierr);
42820cf1dd8SToby Isaac     for (q = 0; q < Nq; ++q) {
4294bee2e38SMatthew G. Knepley       PetscReal w;
4304bee2e38SMatthew G. Knepley       PetscInt  c, d;
43120cf1dd8SToby Isaac 
43220cf1dd8SToby Isaac       if (isAffine) {
4337132c3f7SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &cgeom->v[e*Np*dE], fegeom.J, &quadPoints[q*dim], x);
43420cf1dd8SToby Isaac       } else {
4354bee2e38SMatthew G. Knepley         fegeom.v    = &cgeom->v[(e*Np+q)*dE];
4364bee2e38SMatthew G. Knepley         fegeom.J    = &cgeom->J[(e*Np+q)*dE*dE];
4374bee2e38SMatthew G. Knepley         fegeom.invJ = &cgeom->invJ[(e*Np+q)*dE*dE];
4384bee2e38SMatthew G. Knepley         fegeom.detJ = &cgeom->detJ[e*Np+q];
43920cf1dd8SToby Isaac       }
4404bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
44120cf1dd8SToby Isaac       if (debug > 1 && q < Np) {
4424bee2e38SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
4437be5e748SToby Isaac #if !defined(PETSC_USE_COMPLEX)
4444bee2e38SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ);CHKERRQ(ierr);
44520cf1dd8SToby Isaac #endif
44620cf1dd8SToby Isaac       }
44720cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
448ef0bb6c7SMatthew G. Knepley       ierr = PetscFEEvaluateFieldJets_Internal(ds, Nf, 0, q, T, &fegeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t);CHKERRQ(ierr);
449ef0bb6c7SMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
4504bee2e38SMatthew G. Knepley       if (f0_func) {
451ef0bb6c7SMatthew G. Knepley         f0_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, fegeom.v, numConstants, constants, &f0[q*T[field]->Nc]);
452ef0bb6c7SMatthew G. Knepley         for (c = 0; c < T[field]->Nc; ++c) f0[q*T[field]->Nc+c] *= w;
4534bee2e38SMatthew G. Knepley       }
45420cf1dd8SToby Isaac       if (f1_func) {
455ef0bb6c7SMatthew G. Knepley         f1_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, fegeom.v, numConstants, constants, &f1[q*T[field]->Nc*dim]);
456ef0bb6c7SMatthew G. Knepley         for (c = 0; c < T[field]->Nc; ++c) for (d = 0; d < dim; ++d) f1[(q*T[field]->Nc+c)*dim+d] *= w;
45720cf1dd8SToby Isaac       }
45820cf1dd8SToby Isaac     }
459ef0bb6c7SMatthew G. Knepley     ierr = PetscFEUpdateElementVec_Internal(fe, T[field], 0, basisReal, basisDerReal, &fegeom, f0, f1, &elemVec[cOffset+fOffset]);CHKERRQ(ierr);
46020cf1dd8SToby Isaac     cOffset    += totDim;
46120cf1dd8SToby Isaac     cOffsetAux += totDimAux;
46220cf1dd8SToby Isaac   }
46320cf1dd8SToby Isaac   PetscFunctionReturn(0);
46420cf1dd8SToby Isaac }
46520cf1dd8SToby Isaac 
4664bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBdResidual_Basic(PetscDS ds, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom,
4674bee2e38SMatthew G. Knepley                                                 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
46820cf1dd8SToby Isaac {
46920cf1dd8SToby Isaac   const PetscInt     debug = 0;
4704bee2e38SMatthew G. Knepley   PetscFE            fe;
47120cf1dd8SToby Isaac   PetscBdPointFunc   f0_func;
47220cf1dd8SToby Isaac   PetscBdPointFunc   f1_func;
47320cf1dd8SToby Isaac   PetscQuadrature    quad;
474ef0bb6c7SMatthew G. Knepley   PetscTabulation   *Tf, *TfAux = NULL;
4754bee2e38SMatthew G. Knepley   PetscScalar       *f0, *f1, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal;
47620cf1dd8SToby Isaac   const PetscScalar *constants;
47720cf1dd8SToby Isaac   PetscReal         *x;
478ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
479ef0bb6c7SMatthew G. Knepley   PetscInt           dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, fOffset, e, NcI;
480b07bd890SMatthew G. Knepley   PetscBool          isAffine, auxOnBd = PETSC_FALSE;
48120cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
48220cf1dd8SToby Isaac   PetscInt           qNc, Nq, q, Np, dE;
48320cf1dd8SToby Isaac   PetscErrorCode     ierr;
48420cf1dd8SToby Isaac 
48520cf1dd8SToby Isaac   PetscFunctionBegin;
4864bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
4874bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(fe, &dim);CHKERRQ(ierr);
4884bee2e38SMatthew G. Knepley   ierr = PetscFEGetFaceQuadrature(fe, &quad);CHKERRQ(ierr);
4894bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
4904bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
4914bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
4924bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
4934bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, field, &fOffset);CHKERRQ(ierr);
4944bee2e38SMatthew G. Knepley   ierr = PetscDSGetBdResidual(ds, field, &f0_func, &f1_func);CHKERRQ(ierr);
49520cf1dd8SToby Isaac   if (!f0_func && !f1_func) PetscFunctionReturn(0);
4964bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
4974bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL);CHKERRQ(ierr);
4984bee2e38SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, &f0, &f1, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
499ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetFaceTabulation(ds, &Tf);CHKERRQ(ierr);
5004bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
5014bee2e38SMatthew G. Knepley   if (dsAux) {
5024bee2e38SMatthew G. Knepley     ierr = PetscDSGetSpatialDimension(dsAux, &dimAux);CHKERRQ(ierr);
5034bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
5044bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
5054bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
5064bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
5074bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
5087be5e748SToby Isaac     auxOnBd = dimAux < dim ? PETSC_TRUE : PETSC_FALSE;
509ef0bb6c7SMatthew G. Knepley     if (auxOnBd) {ierr = PetscDSGetTabulation(dsAux, &TfAux);CHKERRQ(ierr);}
510ef0bb6c7SMatthew G. Knepley     else         {ierr = PetscDSGetFaceTabulation(dsAux, &TfAux);CHKERRQ(ierr);}
51120cf1dd8SToby Isaac   }
512ef0bb6c7SMatthew G. Knepley   NcI = Tf[field]->Nc;
51320cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
514afe6d6adSToby Isaac   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
51520cf1dd8SToby Isaac   Np = fgeom->numPoints;
51620cf1dd8SToby Isaac   dE = fgeom->dimEmbed;
51720cf1dd8SToby Isaac   isAffine = fgeom->isAffine;
51820cf1dd8SToby Isaac   for (e = 0; e < Ne; ++e) {
5199f209ee4SMatthew G. Knepley     PetscFEGeom    fegeom, cgeom;
52020cf1dd8SToby Isaac     const PetscInt face = fgeom->face[e][0];
5214dcf62a8SSatish Balay     fegeom.n = 0;
5224dcf62a8SSatish Balay     fegeom.v = 0;
5234dcf62a8SSatish Balay     fegeom.J = 0;
5244dcf62a8SSatish Balay     fegeom.detJ = 0;
52527f02ce8SMatthew G. Knepley     fegeom.dim      = fgeom->dim;
52627f02ce8SMatthew G. Knepley     fegeom.dimEmbed = fgeom->dimEmbed;
52727f02ce8SMatthew G. Knepley     cgeom.dim       = fgeom->dim;
52827f02ce8SMatthew G. Knepley     cgeom.dimEmbed  = fgeom->dimEmbed;
5294bee2e38SMatthew G. Knepley     if (isAffine) {
5304bee2e38SMatthew G. Knepley       fegeom.v    = x;
5314bee2e38SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
5327132c3f7SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*Np*dE*dE];
5337132c3f7SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*Np*dE*dE];
5347132c3f7SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e*Np];
5357132c3f7SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*Np*dE];
5369f209ee4SMatthew G. Knepley 
5377132c3f7SMatthew G. Knepley       cgeom.J     = &fgeom->suppJ[0][e*Np*dE*dE];
5387132c3f7SMatthew G. Knepley       cgeom.invJ  = &fgeom->suppInvJ[0][e*Np*dE*dE];
5397132c3f7SMatthew G. Knepley       cgeom.detJ  = &fgeom->suppDetJ[0][e*Np];
5404bee2e38SMatthew G. Knepley     }
541580bdb30SBarry Smith     ierr = PetscArrayzero(f0, Nq*NcI);CHKERRQ(ierr);
54227f02ce8SMatthew G. Knepley     ierr = PetscArrayzero(f1, Nq*NcI*dE);CHKERRQ(ierr);
54320cf1dd8SToby Isaac     for (q = 0; q < Nq; ++q) {
5444bee2e38SMatthew G. Knepley       PetscReal w;
5454bee2e38SMatthew G. Knepley       PetscInt  c, d;
5464bee2e38SMatthew G. Knepley 
54720cf1dd8SToby Isaac       if (isAffine) {
5487132c3f7SMatthew G. Knepley         CoordinatesRefToReal(dE, dim-1, fegeom.xi, &fgeom->v[e*Np*dE], fegeom.J, &quadPoints[q*(dim-1)], x);
54920cf1dd8SToby Isaac       } else {
5503fe841f2SMatthew G. Knepley         fegeom.v    = &fgeom->v[(e*Np+q)*dE];
5519f209ee4SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
5529f209ee4SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
5534bee2e38SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
5544bee2e38SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
5559f209ee4SMatthew G. Knepley 
5569f209ee4SMatthew G. Knepley         cgeom.J     = &fgeom->suppJ[0][(e*Np+q)*dE*dE];
5579f209ee4SMatthew G. Knepley         cgeom.invJ  = &fgeom->suppInvJ[0][(e*Np+q)*dE*dE];
5589f209ee4SMatthew G. Knepley         cgeom.detJ  = &fgeom->suppDetJ[0][e*Np+q];
55920cf1dd8SToby Isaac       }
5604bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
56120cf1dd8SToby Isaac       if (debug > 1 && q < Np) {
5624bee2e38SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
5637be5e748SToby Isaac #if !defined(PETSC_USE_COMPLEX)
5644bee2e38SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ);CHKERRQ(ierr);
56520cf1dd8SToby Isaac #endif
56620cf1dd8SToby Isaac       }
56720cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
568ef0bb6c7SMatthew G. Knepley       ierr = PetscFEEvaluateFieldJets_Internal(ds, Nf, face, q, Tf, &cgeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t);CHKERRQ(ierr);
569ef0bb6c7SMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, auxOnBd ? 0 : face, q, TfAux, &cgeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
5704bee2e38SMatthew G. Knepley       if (f0_func) {
5714bee2e38SMatthew G. Knepley         f0_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, fegeom.v, fegeom.n, numConstants, constants, &f0[q*NcI]);
5724bee2e38SMatthew G. Knepley         for (c = 0; c < NcI; ++c) f0[q*NcI+c] *= w;
5734bee2e38SMatthew G. Knepley       }
57420cf1dd8SToby Isaac       if (f1_func) {
5754bee2e38SMatthew G. Knepley         f1_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, fegeom.v, fegeom.n, numConstants, constants, &f1[q*NcI*dim]);
5764bee2e38SMatthew G. Knepley         for (c = 0; c < NcI; ++c) for (d = 0; d < dim; ++d) f1[(q*NcI+c)*dim+d] *= w;
57720cf1dd8SToby Isaac       }
57820cf1dd8SToby Isaac     }
579ef0bb6c7SMatthew G. Knepley     ierr = PetscFEUpdateElementVec_Internal(fe, Tf[field], face, basisReal, basisDerReal, &cgeom, f0, f1, &elemVec[cOffset+fOffset]);CHKERRQ(ierr);
58020cf1dd8SToby Isaac     cOffset    += totDim;
58120cf1dd8SToby Isaac     cOffsetAux += totDimAux;
58220cf1dd8SToby Isaac   }
58320cf1dd8SToby Isaac   PetscFunctionReturn(0);
58420cf1dd8SToby Isaac }
58520cf1dd8SToby Isaac 
58627f02ce8SMatthew G. Knepley /*
58727f02ce8SMatthew G. Knepley   BdIntegral: Operates completely in the embedding dimension. The trick is to have special "face quadrature" so we only integrate over the face, but
58827f02ce8SMatthew G. Knepley               all transforms operate in the full space and are square.
58927f02ce8SMatthew G. Knepley 
59027f02ce8SMatthew G. Knepley   HybridIntegral: The discretization is lower dimensional. That means the transforms are non-square.
59127f02ce8SMatthew G. Knepley     1) DMPlexGetCellFields() retrieves from the hybrid cell, so it gets fields from both faces
59227f02ce8SMatthew G. Knepley     2) We need to assume that the orientation is 0 for both
59327f02ce8SMatthew G. Knepley     3) TODO We need to use a non-square Jacobian for the derivative maps, meaning the embedding dimension has to go to EvaluateFieldJets() and UpdateElementVec()
59427f02ce8SMatthew G. Knepley */
59527f02ce8SMatthew G. Knepley static PetscErrorCode PetscFEIntegrateHybridResidual_Basic(PetscDS ds, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom,
59627f02ce8SMatthew G. Knepley                                                            const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
59727f02ce8SMatthew G. Knepley {
59827f02ce8SMatthew G. Knepley   const PetscInt     debug = 0;
59927f02ce8SMatthew G. Knepley   PetscFE            fe;
60027f02ce8SMatthew G. Knepley   PetscBdPointFunc   f0_func;
60127f02ce8SMatthew G. Knepley   PetscBdPointFunc   f1_func;
60227f02ce8SMatthew G. Knepley   PetscQuadrature    quad;
603*665f567fSMatthew G. Knepley   PetscTabulation   *Tf, *TfAux = NULL;
60427f02ce8SMatthew G. Knepley   PetscScalar       *f0, *f1, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal;
60527f02ce8SMatthew G. Knepley   const PetscScalar *constants;
60627f02ce8SMatthew G. Knepley   PetscReal         *x;
607*665f567fSMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
608*665f567fSMatthew G. Knepley   PetscInt           dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, fOffset, e, NcI, NcS;
609*665f567fSMatthew G. Knepley   PetscBool          isCohesiveField, isAffine, auxOnBd = PETSC_FALSE;
61027f02ce8SMatthew G. Knepley   const PetscReal   *quadPoints, *quadWeights;
61127f02ce8SMatthew G. Knepley   PetscInt           qNc, Nq, q, Np, dE;
61227f02ce8SMatthew G. Knepley   PetscErrorCode     ierr;
61327f02ce8SMatthew G. Knepley 
61427f02ce8SMatthew G. Knepley   PetscFunctionBegin;
61527f02ce8SMatthew G. Knepley   /* Hybrid discretization is posed directly on faces */
61627f02ce8SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
61727f02ce8SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(fe, &dim);CHKERRQ(ierr);
61827f02ce8SMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr);
61927f02ce8SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
62027f02ce8SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
62127f02ce8SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
62227f02ce8SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
62327f02ce8SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, field, &fOffset);CHKERRQ(ierr);
62427f02ce8SMatthew G. Knepley   ierr = PetscDSGetBdResidual(ds, field, &f0_func, &f1_func);CHKERRQ(ierr);
62527f02ce8SMatthew G. Knepley   if (!f0_func && !f1_func) PetscFunctionReturn(0);
62627f02ce8SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
62727f02ce8SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL);CHKERRQ(ierr);
62827f02ce8SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, &f0, &f1, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
62927f02ce8SMatthew G. Knepley   /* NOTE This is a bulk tabulation because the DS is a face discretization */
630*665f567fSMatthew G. Knepley   ierr = PetscDSGetTabulation(ds, &Tf);CHKERRQ(ierr);
63127f02ce8SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
63227f02ce8SMatthew G. Knepley   if (dsAux) {
63327f02ce8SMatthew G. Knepley     ierr = PetscDSGetSpatialDimension(dsAux, &dimAux);CHKERRQ(ierr);
63427f02ce8SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
63527f02ce8SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
63627f02ce8SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
63727f02ce8SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
63827f02ce8SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
63927f02ce8SMatthew G. Knepley     auxOnBd = dimAux < dim ? PETSC_TRUE : PETSC_FALSE;
640*665f567fSMatthew G. Knepley     if (auxOnBd) {ierr = PetscDSGetTabulation(dsAux, &TfAux);CHKERRQ(ierr);}
641*665f567fSMatthew G. Knepley     else         {ierr = PetscDSGetFaceTabulation(dsAux, &TfAux);CHKERRQ(ierr);}
64227f02ce8SMatthew G. Knepley   }
64327f02ce8SMatthew G. Knepley   isCohesiveField = field == Nf-1 ? PETSC_TRUE : PETSC_FALSE;
644*665f567fSMatthew G. Knepley   NcI = Tf[field]->Nc;
64527f02ce8SMatthew G. Knepley   NcS = isCohesiveField ? NcI : 2*NcI;
64627f02ce8SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
64727f02ce8SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
64827f02ce8SMatthew G. Knepley   Np = fgeom->numPoints;
64927f02ce8SMatthew G. Knepley   dE = fgeom->dimEmbed;
65027f02ce8SMatthew G. Knepley   isAffine = fgeom->isAffine;
65127f02ce8SMatthew G. Knepley   for (e = 0; e < Ne; ++e) {
65227f02ce8SMatthew G. Knepley     PetscFEGeom    fegeom;
65327f02ce8SMatthew G. Knepley     const PetscInt face = fgeom->face[e][0];
65427f02ce8SMatthew G. Knepley 
65527f02ce8SMatthew G. Knepley     fegeom.dim      = fgeom->dim;
65627f02ce8SMatthew G. Knepley     fegeom.dimEmbed = fgeom->dimEmbed;
65727f02ce8SMatthew G. Knepley     if (isAffine) {
65827f02ce8SMatthew G. Knepley       fegeom.v    = x;
65927f02ce8SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
66027f02ce8SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*dE*dE];
66127f02ce8SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*dE*dE];
66227f02ce8SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e];
66327f02ce8SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*dE];
66427f02ce8SMatthew G. Knepley     }
66527f02ce8SMatthew G. Knepley     ierr = PetscArrayzero(f0, Nq*NcS);CHKERRQ(ierr);
66627f02ce8SMatthew G. Knepley     ierr = PetscArrayzero(f1, Nq*NcS*dE);CHKERRQ(ierr);
66727f02ce8SMatthew G. Knepley     for (q = 0; q < Nq; ++q) {
66827f02ce8SMatthew G. Knepley       PetscReal w;
66927f02ce8SMatthew G. Knepley       PetscInt  c, d;
67027f02ce8SMatthew G. Knepley 
67127f02ce8SMatthew G. Knepley       if (isAffine) {
67227f02ce8SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &fgeom->v[e*dE], fegeom.J, &quadPoints[q*dim], x);
67327f02ce8SMatthew G. Knepley       } else {
67427f02ce8SMatthew G. Knepley         fegeom.v    = &fgeom->v[(e*Np+q)*dE];
67527f02ce8SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
67627f02ce8SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
67727f02ce8SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
67827f02ce8SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
67927f02ce8SMatthew G. Knepley       }
68027f02ce8SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
68127f02ce8SMatthew G. Knepley       if (debug > 1 && q < Np) {
68227f02ce8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
68327f02ce8SMatthew G. Knepley #if !defined(PETSC_USE_COMPLEX)
68427f02ce8SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dE, fegeom.invJ);CHKERRQ(ierr);
68527f02ce8SMatthew G. Knepley #endif
68627f02ce8SMatthew G. Knepley       }
68727f02ce8SMatthew G. Knepley       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
68827f02ce8SMatthew G. Knepley       /* TODO Is this cell or face quadrature, meaning should we use 'q' or 'face*Nq+q' */
689*665f567fSMatthew G. Knepley       ierr = PetscFEEvaluateFieldJets_Hybrid_Internal(ds, Nf, 0, q, Tf, &fegeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t);CHKERRQ(ierr);
690*665f567fSMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Hybrid_Internal(dsAux, NfAux, 0, auxOnBd ? q : face*Nq+q, TfAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
69127f02ce8SMatthew G. Knepley       if (f0_func) {
69227f02ce8SMatthew G. Knepley         f0_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, fegeom.v, fegeom.n, numConstants, constants, &f0[q*NcS]);
69327f02ce8SMatthew G. Knepley         for (c = 0; c < NcS; ++c) f0[q*NcS+c] *= w;
69427f02ce8SMatthew G. Knepley       }
69527f02ce8SMatthew G. Knepley       if (f1_func) {
69627f02ce8SMatthew G. Knepley         f1_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, fegeom.v, fegeom.n, numConstants, constants, &f1[q*NcS*dim]);
69727f02ce8SMatthew G. Knepley         for (c = 0; c < NcS; ++c) for (d = 0; d < dim; ++d) f1[(q*NcS+c)*dim+d] *= w;
69827f02ce8SMatthew G. Knepley       }
69927f02ce8SMatthew G. Knepley     }
700*665f567fSMatthew G. Knepley     if (isCohesiveField) {PetscFEUpdateElementVec_Internal(fe, Tf[field], 0, basisReal, basisDerReal, &fegeom, f0, f1, &elemVec[cOffset+fOffset*2]);}
701*665f567fSMatthew G. Knepley     else                 {PetscFEUpdateElementVec_Hybrid_Internal(fe, Tf[field], 0, basisReal, basisDerReal, &fegeom, f0, f1, &elemVec[cOffset+fOffset*2]);}
70227f02ce8SMatthew G. Knepley     cOffset    += totDim;
70327f02ce8SMatthew G. Knepley     cOffsetAux += totDimAux;
70427f02ce8SMatthew G. Knepley   }
70527f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
70627f02ce8SMatthew G. Knepley }
70727f02ce8SMatthew G. Knepley 
7084bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateJacobian_Basic(PetscDS ds, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *cgeom,
7094bee2e38SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
71020cf1dd8SToby Isaac {
71120cf1dd8SToby Isaac   const PetscInt     debug      = 0;
7124bee2e38SMatthew G. Knepley   PetscFE            feI, feJ;
7134bee2e38SMatthew G. Knepley   PetscPointJac      g0_func, g1_func, g2_func, g3_func;
71420cf1dd8SToby Isaac   PetscInt           cOffset    = 0; /* Offset into coefficients[] for element e */
71520cf1dd8SToby Isaac   PetscInt           cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */
71620cf1dd8SToby Isaac   PetscInt           eOffset    = 0; /* Offset into elemMat[] for element e */
71720cf1dd8SToby Isaac   PetscInt           offsetI    = 0; /* Offset into an element vector for fieldI */
71820cf1dd8SToby Isaac   PetscInt           offsetJ    = 0; /* Offset into an element vector for fieldJ */
71920cf1dd8SToby Isaac   PetscQuadrature    quad;
720ef0bb6c7SMatthew G. Knepley   PetscTabulation   *T, *TAux = NULL;
7214bee2e38SMatthew G. Knepley   PetscScalar       *g0, *g1, *g2, *g3, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal;
72220cf1dd8SToby Isaac   const PetscScalar *constants;
72320cf1dd8SToby Isaac   PetscReal         *x;
724ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
725ef0bb6c7SMatthew G. Knepley   PetscInt           NcI = 0, NcJ = 0;
72620cf1dd8SToby Isaac   PetscInt           dim, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, e;
72720cf1dd8SToby Isaac   PetscInt           dE, Np;
72820cf1dd8SToby Isaac   PetscBool          isAffine;
72920cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
73020cf1dd8SToby Isaac   PetscInt           qNc, Nq, q;
73120cf1dd8SToby Isaac   PetscErrorCode     ierr;
73220cf1dd8SToby Isaac 
73320cf1dd8SToby Isaac   PetscFunctionBegin;
7344bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldI, (PetscObject *) &feI);CHKERRQ(ierr);
7354bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldJ, (PetscObject *) &feJ);CHKERRQ(ierr);
7364bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(feI, &dim);CHKERRQ(ierr);
7374bee2e38SMatthew G. Knepley   ierr = PetscFEGetQuadrature(feI, &quad);CHKERRQ(ierr);
7384bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
7394bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
7404bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
7414bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
74220cf1dd8SToby Isaac   switch(jtype) {
7434bee2e38SMatthew G. Knepley   case PETSCFE_JACOBIAN_DYN: ierr = PetscDSGetDynamicJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
7444bee2e38SMatthew G. Knepley   case PETSCFE_JACOBIAN_PRE: ierr = PetscDSGetJacobianPreconditioner(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
7454bee2e38SMatthew G. Knepley   case PETSCFE_JACOBIAN:     ierr = PetscDSGetJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
74620cf1dd8SToby Isaac   }
74720cf1dd8SToby Isaac   if (!g0_func && !g1_func && !g2_func && !g3_func) PetscFunctionReturn(0);
7484bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
7494bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal);CHKERRQ(ierr);
7504bee2e38SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, NULL, NULL, &g0, &g1, &g2, &g3);CHKERRQ(ierr);
751ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetTabulation(ds, &T);CHKERRQ(ierr);
7524bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldI, &offsetI);CHKERRQ(ierr);
7534bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldJ, &offsetJ);CHKERRQ(ierr);
7544bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
7554bee2e38SMatthew G. Knepley   if (dsAux) {
7564bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
7574bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
7584bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
7594bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
7604bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
761ef0bb6c7SMatthew G. Knepley     ierr = PetscDSGetTabulation(dsAux, &TAux);CHKERRQ(ierr);
76220cf1dd8SToby Isaac   }
76327f02ce8SMatthew G. Knepley   NcI = T[fieldI]->Nc;
76427f02ce8SMatthew G. Knepley   NcJ = T[fieldJ]->Nc;
7654bee2e38SMatthew G. Knepley   Np  = cgeom->numPoints;
7664bee2e38SMatthew G. Knepley   dE  = cgeom->dimEmbed;
7674bee2e38SMatthew G. Knepley   isAffine = cgeom->isAffine;
76827f02ce8SMatthew G. Knepley   /* Initialize here in case the function is not defined */
76927f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
77027f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g1, NcI*NcJ*dE);CHKERRQ(ierr);
77127f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g2, NcI*NcJ*dE);CHKERRQ(ierr);
77227f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g3, NcI*NcJ*dE*dE);CHKERRQ(ierr);
77327f02ce8SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
77427f02ce8SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
7754bee2e38SMatthew G. Knepley   for (e = 0; e < Ne; ++e) {
7764bee2e38SMatthew G. Knepley     PetscFEGeom fegeom;
7774bee2e38SMatthew G. Knepley 
77827f02ce8SMatthew G. Knepley     fegeom.dim      = cgeom->dim;
77927f02ce8SMatthew G. Knepley     fegeom.dimEmbed = cgeom->dimEmbed;
7804bee2e38SMatthew G. Knepley     if (isAffine) {
7814bee2e38SMatthew G. Knepley       fegeom.v    = x;
7824bee2e38SMatthew G. Knepley       fegeom.xi   = cgeom->xi;
7837132c3f7SMatthew G. Knepley       fegeom.J    = &cgeom->J[e*Np*dE*dE];
7847132c3f7SMatthew G. Knepley       fegeom.invJ = &cgeom->invJ[e*Np*dE*dE];
7857132c3f7SMatthew G. Knepley       fegeom.detJ = &cgeom->detJ[e*Np];
7864bee2e38SMatthew G. Knepley     }
78720cf1dd8SToby Isaac     for (q = 0; q < Nq; ++q) {
78820cf1dd8SToby Isaac       PetscReal w;
7894bee2e38SMatthew G. Knepley       PetscInt  c;
79020cf1dd8SToby Isaac 
79120cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
79220cf1dd8SToby Isaac       if (isAffine) {
7937132c3f7SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &cgeom->v[e*Np*dE], fegeom.J, &quadPoints[q*dim], x);
79420cf1dd8SToby Isaac       } else {
7954bee2e38SMatthew G. Knepley         fegeom.v    = &cgeom->v[(e*Np+q)*dE];
7964bee2e38SMatthew G. Knepley         fegeom.J    = &cgeom->J[(e*Np+q)*dE*dE];
7974bee2e38SMatthew G. Knepley         fegeom.invJ = &cgeom->invJ[(e*Np+q)*dE*dE];
7984bee2e38SMatthew G. Knepley         fegeom.detJ = &cgeom->detJ[e*Np+q];
79920cf1dd8SToby Isaac       }
8004bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
801ef0bb6c7SMatthew G. Knepley       if (coefficients) {ierr = PetscFEEvaluateFieldJets_Internal(ds, Nf, 0, q, T, &fegeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t);CHKERRQ(ierr);}
802ef0bb6c7SMatthew G. Knepley       if (dsAux)        {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
80320cf1dd8SToby Isaac       if (g0_func) {
804580bdb30SBarry Smith         ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
8054bee2e38SMatthew G. Knepley         g0_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, numConstants, constants, g0);
80620cf1dd8SToby Isaac         for (c = 0; c < NcI*NcJ; ++c) g0[c] *= w;
80720cf1dd8SToby Isaac       }
80820cf1dd8SToby Isaac       if (g1_func) {
80927f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g1, NcI*NcJ*dE);CHKERRQ(ierr);
8104bee2e38SMatthew G. Knepley         g1_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, numConstants, constants, g1);
8114bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g1[c] *= w;
81220cf1dd8SToby Isaac       }
81320cf1dd8SToby Isaac       if (g2_func) {
81427f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g2, NcI*NcJ*dE);CHKERRQ(ierr);
8154bee2e38SMatthew G. Knepley         g2_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, numConstants, constants, g2);
8164bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g2[c] *= w;
81720cf1dd8SToby Isaac       }
81820cf1dd8SToby Isaac       if (g3_func) {
81927f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g3, NcI*NcJ*dE*dE);CHKERRQ(ierr);
8204bee2e38SMatthew G. Knepley         g3_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, numConstants, constants, g3);
8214bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim*dim; ++c) g3[c] *= w;
82220cf1dd8SToby Isaac       }
82320cf1dd8SToby Isaac 
824ef0bb6c7SMatthew G. Knepley       ierr = PetscFEUpdateElementMat_Internal(feI, feJ, 0, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, g0, g1, g2, g3, eOffset, totDim, offsetI, offsetJ, elemMat);CHKERRQ(ierr);
82520cf1dd8SToby Isaac     }
82620cf1dd8SToby Isaac     if (debug > 1) {
82720cf1dd8SToby Isaac       PetscInt fc, f, gc, g;
82820cf1dd8SToby Isaac 
82920cf1dd8SToby Isaac       ierr = PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %d and %d\n", fieldI, fieldJ);CHKERRQ(ierr);
830ef0bb6c7SMatthew G. Knepley       for (fc = 0; fc < T[fieldI]->Nc; ++fc) {
831ef0bb6c7SMatthew G. Knepley         for (f = 0; f < T[fieldI]->Nb; ++f) {
832ef0bb6c7SMatthew G. Knepley           const PetscInt i = offsetI + f*T[fieldI]->Nc+fc;
833ef0bb6c7SMatthew G. Knepley           for (gc = 0; gc < T[fieldJ]->Nc; ++gc) {
834ef0bb6c7SMatthew G. Knepley             for (g = 0; g < T[fieldJ]->Nb; ++g) {
835ef0bb6c7SMatthew G. Knepley               const PetscInt j = offsetJ + g*T[fieldJ]->Nc+gc;
83620cf1dd8SToby Isaac               ierr = PetscPrintf(PETSC_COMM_SELF, "    elemMat[%d,%d,%d,%d]: %g\n", f, fc, g, gc, PetscRealPart(elemMat[eOffset+i*totDim+j]));CHKERRQ(ierr);
83720cf1dd8SToby Isaac             }
83820cf1dd8SToby Isaac           }
83920cf1dd8SToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
84020cf1dd8SToby Isaac         }
84120cf1dd8SToby Isaac       }
84220cf1dd8SToby Isaac     }
84320cf1dd8SToby Isaac     cOffset    += totDim;
84420cf1dd8SToby Isaac     cOffsetAux += totDimAux;
84520cf1dd8SToby Isaac     eOffset    += PetscSqr(totDim);
84620cf1dd8SToby Isaac   }
84720cf1dd8SToby Isaac   PetscFunctionReturn(0);
84820cf1dd8SToby Isaac }
84920cf1dd8SToby Isaac 
8502b99622eSMatthew G. Knepley static PetscErrorCode PetscFEIntegrateBdJacobian_Basic(PetscDS ds, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
8514bee2e38SMatthew G. Knepley                                                        const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
85220cf1dd8SToby Isaac {
85320cf1dd8SToby Isaac   const PetscInt     debug      = 0;
8544bee2e38SMatthew G. Knepley   PetscFE            feI, feJ;
8554bee2e38SMatthew G. Knepley   PetscBdPointJac    g0_func, g1_func, g2_func, g3_func;
85620cf1dd8SToby Isaac   PetscInt           cOffset    = 0; /* Offset into coefficients[] for element e */
85720cf1dd8SToby Isaac   PetscInt           cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */
85820cf1dd8SToby Isaac   PetscInt           eOffset    = 0; /* Offset into elemMat[] for element e */
85920cf1dd8SToby Isaac   PetscInt           offsetI    = 0; /* Offset into an element vector for fieldI */
86020cf1dd8SToby Isaac   PetscInt           offsetJ    = 0; /* Offset into an element vector for fieldJ */
86120cf1dd8SToby Isaac   PetscQuadrature    quad;
862ef0bb6c7SMatthew G. Knepley   PetscTabulation   *T, *TAux = NULL;
8634bee2e38SMatthew G. Knepley   PetscScalar       *g0, *g1, *g2, *g3, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal;
86420cf1dd8SToby Isaac   const PetscScalar *constants;
86520cf1dd8SToby Isaac   PetscReal         *x;
866ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
867ef0bb6c7SMatthew G. Knepley   PetscInt           NcI = 0, NcJ = 0;
86820cf1dd8SToby Isaac   PetscInt           dim, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, e;
86920cf1dd8SToby Isaac   PetscBool          isAffine;
87020cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
87120cf1dd8SToby Isaac   PetscInt           qNc, Nq, q, Np, dE;
87220cf1dd8SToby Isaac   PetscErrorCode     ierr;
87320cf1dd8SToby Isaac 
87420cf1dd8SToby Isaac   PetscFunctionBegin;
8754bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldI, (PetscObject *) &feI);CHKERRQ(ierr);
8764bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldJ, (PetscObject *) &feJ);CHKERRQ(ierr);
8774bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(feI, &dim);CHKERRQ(ierr);
8784bee2e38SMatthew G. Knepley   ierr = PetscFEGetFaceQuadrature(feI, &quad);CHKERRQ(ierr);
8794bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
8804bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
8814bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
8824bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
8834bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldI, &offsetI);CHKERRQ(ierr);
8844bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldJ, &offsetJ);CHKERRQ(ierr);
8854bee2e38SMatthew G. Knepley   ierr = PetscDSGetBdJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);
88631f073d7SMatthew G. Knepley   if (!g0_func && !g1_func && !g2_func && !g3_func) PetscFunctionReturn(0);
8874bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
8884bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal);CHKERRQ(ierr);
8894bee2e38SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, NULL, NULL, &g0, &g1, &g2, &g3);CHKERRQ(ierr);
890ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetFaceTabulation(ds, &T);CHKERRQ(ierr);
8914bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
8924bee2e38SMatthew G. Knepley   if (dsAux) {
8934bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
8944bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
8954bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
8964bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
8974bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
898ef0bb6c7SMatthew G. Knepley     ierr = PetscDSGetFaceTabulation(dsAux, &TAux);CHKERRQ(ierr);
89920cf1dd8SToby Isaac   }
900ef0bb6c7SMatthew G. Knepley   NcI = T[fieldI]->Nc, NcJ = T[fieldJ]->Nc;
90120cf1dd8SToby Isaac   Np = fgeom->numPoints;
90220cf1dd8SToby Isaac   dE = fgeom->dimEmbed;
90320cf1dd8SToby Isaac   isAffine = fgeom->isAffine;
90427f02ce8SMatthew G. Knepley   /* Initialize here in case the function is not defined */
90531f073d7SMatthew G. Knepley   ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
90627f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g1, NcI*NcJ*dE);CHKERRQ(ierr);
90727f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g2, NcI*NcJ*dE);CHKERRQ(ierr);
90827f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g3, NcI*NcJ*dE*dE);CHKERRQ(ierr);
90927f02ce8SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
91027f02ce8SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
91120cf1dd8SToby Isaac   for (e = 0; e < Ne; ++e) {
9129f209ee4SMatthew G. Knepley     PetscFEGeom    fegeom, cgeom;
91320cf1dd8SToby Isaac     const PetscInt face = fgeom->face[e][0];
9144dcf62a8SSatish Balay     fegeom.n = 0;
9154dcf62a8SSatish Balay     fegeom.v = 0;
9164dcf62a8SSatish Balay     fegeom.J = 0;
9174dcf62a8SSatish Balay     fegeom.detJ = 0;
91827f02ce8SMatthew G. Knepley     fegeom.dim      = fgeom->dim;
91927f02ce8SMatthew G. Knepley     fegeom.dimEmbed = fgeom->dimEmbed;
92027f02ce8SMatthew G. Knepley     cgeom.dim       = fgeom->dim;
92127f02ce8SMatthew G. Knepley     cgeom.dimEmbed  = fgeom->dimEmbed;
9224bee2e38SMatthew G. Knepley     if (isAffine) {
9234bee2e38SMatthew G. Knepley       fegeom.v    = x;
9244bee2e38SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
9257132c3f7SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*Np*dE*dE];
9267132c3f7SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*Np*dE*dE];
9277132c3f7SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e*Np];
9287132c3f7SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*Np*dE];
9299f209ee4SMatthew G. Knepley 
9307132c3f7SMatthew G. Knepley       cgeom.J     = &fgeom->suppJ[0][e*Np*dE*dE];
9317132c3f7SMatthew G. Knepley       cgeom.invJ  = &fgeom->suppInvJ[0][e*Np*dE*dE];
9327132c3f7SMatthew G. Knepley       cgeom.detJ  = &fgeom->suppDetJ[0][e*Np];
9334bee2e38SMatthew G. Knepley     }
93420cf1dd8SToby Isaac     for (q = 0; q < Nq; ++q) {
93520cf1dd8SToby Isaac       PetscReal w;
9364bee2e38SMatthew G. Knepley       PetscInt  c;
93720cf1dd8SToby Isaac 
93820cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
93920cf1dd8SToby Isaac       if (isAffine) {
9407132c3f7SMatthew G. Knepley         CoordinatesRefToReal(dE, dim-1, fegeom.xi, &fgeom->v[e*Np*dE], fegeom.J, &quadPoints[q*(dim-1)], x);
94120cf1dd8SToby Isaac       } else {
9423fe841f2SMatthew G. Knepley         fegeom.v    = &fgeom->v[(e*Np+q)*dE];
9439f209ee4SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
9449f209ee4SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
9454bee2e38SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
9464bee2e38SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
9479f209ee4SMatthew G. Knepley 
9489f209ee4SMatthew G. Knepley         cgeom.J     = &fgeom->suppJ[0][(e*Np+q)*dE*dE];
9499f209ee4SMatthew G. Knepley         cgeom.invJ  = &fgeom->suppInvJ[0][(e*Np+q)*dE*dE];
9509f209ee4SMatthew G. Knepley         cgeom.detJ  = &fgeom->suppDetJ[0][e*Np+q];
95120cf1dd8SToby Isaac       }
9524bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
953ef0bb6c7SMatthew G. Knepley       if (coefficients) {ierr = PetscFEEvaluateFieldJets_Internal(ds, Nf, face, q, T, &cgeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t);CHKERRQ(ierr);}
954ef0bb6c7SMatthew G. Knepley       if (dsAux)        {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, face, q, TAux, &cgeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
95520cf1dd8SToby Isaac       if (g0_func) {
956580bdb30SBarry Smith         ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
9574bee2e38SMatthew G. Knepley         g0_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, fegeom.n, numConstants, constants, g0);
95820cf1dd8SToby Isaac         for (c = 0; c < NcI*NcJ; ++c) g0[c] *= w;
95920cf1dd8SToby Isaac       }
96020cf1dd8SToby Isaac       if (g1_func) {
96127f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g1, NcI*NcJ*dE);CHKERRQ(ierr);
9624bee2e38SMatthew G. Knepley         g1_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, fegeom.n, numConstants, constants, g1);
9634bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g1[c] *= w;
96420cf1dd8SToby Isaac       }
96520cf1dd8SToby Isaac       if (g2_func) {
96627f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g2, NcI*NcJ*dE);CHKERRQ(ierr);
9674bee2e38SMatthew G. Knepley         g2_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, fegeom.n, numConstants, constants, g2);
9684bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g2[c] *= w;
96920cf1dd8SToby Isaac       }
97020cf1dd8SToby Isaac       if (g3_func) {
97127f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g3, NcI*NcJ*dE*dE);CHKERRQ(ierr);
9724bee2e38SMatthew G. Knepley         g3_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, fegeom.n, numConstants, constants, g3);
9734bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim*dim; ++c) g3[c] *= w;
97420cf1dd8SToby Isaac       }
97520cf1dd8SToby Isaac 
976ef0bb6c7SMatthew G. Knepley       ierr = PetscFEUpdateElementMat_Internal(feI, feJ, face, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &cgeom, g0, g1, g2, g3, eOffset, totDim, offsetI, offsetJ, elemMat);CHKERRQ(ierr);
97720cf1dd8SToby Isaac     }
97820cf1dd8SToby Isaac     if (debug > 1) {
97920cf1dd8SToby Isaac       PetscInt fc, f, gc, g;
98020cf1dd8SToby Isaac 
98120cf1dd8SToby Isaac       ierr = PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %d and %d\n", fieldI, fieldJ);CHKERRQ(ierr);
982ef0bb6c7SMatthew G. Knepley       for (fc = 0; fc < T[fieldI]->Nc; ++fc) {
983ef0bb6c7SMatthew G. Knepley         for (f = 0; f < T[fieldI]->Nb; ++f) {
984ef0bb6c7SMatthew G. Knepley           const PetscInt i = offsetI + f*T[fieldI]->Nc+fc;
985ef0bb6c7SMatthew G. Knepley           for (gc = 0; gc < T[fieldJ]->Nc; ++gc) {
986ef0bb6c7SMatthew G. Knepley             for (g = 0; g < T[fieldJ]->Nb; ++g) {
987ef0bb6c7SMatthew G. Knepley               const PetscInt j = offsetJ + g*T[fieldJ]->Nc+gc;
98820cf1dd8SToby Isaac               ierr = PetscPrintf(PETSC_COMM_SELF, "    elemMat[%d,%d,%d,%d]: %g\n", f, fc, g, gc, PetscRealPart(elemMat[eOffset+i*totDim+j]));CHKERRQ(ierr);
98920cf1dd8SToby Isaac             }
99020cf1dd8SToby Isaac           }
99120cf1dd8SToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
99220cf1dd8SToby Isaac         }
99320cf1dd8SToby Isaac       }
99420cf1dd8SToby Isaac     }
99520cf1dd8SToby Isaac     cOffset    += totDim;
99620cf1dd8SToby Isaac     cOffsetAux += totDimAux;
99720cf1dd8SToby Isaac     eOffset    += PetscSqr(totDim);
99820cf1dd8SToby Isaac   }
99920cf1dd8SToby Isaac   PetscFunctionReturn(0);
100020cf1dd8SToby Isaac }
100120cf1dd8SToby Isaac 
100227f02ce8SMatthew G. Knepley PetscErrorCode PetscFEIntegrateHybridJacobian_Basic(PetscDS ds, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
100327f02ce8SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
100427f02ce8SMatthew G. Knepley {
100527f02ce8SMatthew G. Knepley   const PetscInt     debug      = 0;
100627f02ce8SMatthew G. Knepley   PetscFE            feI, feJ;
1007*665f567fSMatthew G. Knepley   PetscBdPointJac    g0_func, g1_func, g2_func, g3_func;
100827f02ce8SMatthew G. Knepley   PetscInt           cOffset    = 0; /* Offset into coefficients[] for element e */
100927f02ce8SMatthew G. Knepley   PetscInt           cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */
101027f02ce8SMatthew G. Knepley   PetscInt           eOffset    = 0; /* Offset into elemMat[] for element e */
101127f02ce8SMatthew G. Knepley   PetscInt           offsetI    = 0; /* Offset into an element vector for fieldI */
101227f02ce8SMatthew G. Knepley   PetscInt           offsetJ    = 0; /* Offset into an element vector for fieldJ */
1013*665f567fSMatthew G. Knepley   PetscQuadrature    quad;
1014*665f567fSMatthew G. Knepley   PetscTabulation   *T, *TAux = NULL;
101527f02ce8SMatthew G. Knepley   PetscScalar       *g0, *g1, *g2, *g3, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal;
101627f02ce8SMatthew G. Knepley   const PetscScalar *constants;
101727f02ce8SMatthew G. Knepley   PetscReal         *x;
1018*665f567fSMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
1019*665f567fSMatthew G. Knepley   PetscInt           NcI = 0, NcJ = 0, NcS, NcT;
102027f02ce8SMatthew G. Knepley   PetscInt           dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, e;
1021*665f567fSMatthew G. Knepley   PetscBool          isCohesiveFieldI, isCohesiveFieldJ, isAffine, auxOnBd = PETSC_FALSE;
102227f02ce8SMatthew G. Knepley   const PetscReal   *quadPoints, *quadWeights;
102327f02ce8SMatthew G. Knepley   PetscInt           qNc, Nq, q, Np, dE;
102427f02ce8SMatthew G. Knepley   PetscErrorCode     ierr;
102527f02ce8SMatthew G. Knepley 
102627f02ce8SMatthew G. Knepley   PetscFunctionBegin;
102727f02ce8SMatthew G. Knepley   /* Hybrid discretization is posed directly on faces */
102827f02ce8SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldI, (PetscObject *) &feI);CHKERRQ(ierr);
102927f02ce8SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldJ, (PetscObject *) &feJ);CHKERRQ(ierr);
103027f02ce8SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(feI, &dim);CHKERRQ(ierr);
103127f02ce8SMatthew G. Knepley   ierr = PetscFEGetQuadrature(feI, &quad);CHKERRQ(ierr);
103227f02ce8SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
103327f02ce8SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
103427f02ce8SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
103527f02ce8SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
103627f02ce8SMatthew G. Knepley   switch(jtype) {
103727f02ce8SMatthew G. Knepley   case PETSCFE_JACOBIAN_PRE: ierr = PetscDSGetBdJacobianPreconditioner(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
103827f02ce8SMatthew G. Knepley   case PETSCFE_JACOBIAN:     ierr = PetscDSGetBdJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
1039*665f567fSMatthew G. Knepley   case PETSCFE_JACOBIAN_DYN: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No boundary hybrid Jacobians :)");
104027f02ce8SMatthew G. Knepley   }
104127f02ce8SMatthew G. Knepley   if (!g0_func && !g1_func && !g2_func && !g3_func) PetscFunctionReturn(0);
104227f02ce8SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
104327f02ce8SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal);CHKERRQ(ierr);
104427f02ce8SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, NULL, NULL, &g0, &g1, &g2, &g3);CHKERRQ(ierr);
1045*665f567fSMatthew G. Knepley   ierr = PetscDSGetTabulation(ds, &T);CHKERRQ(ierr);
1046*665f567fSMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldI, &offsetI);CHKERRQ(ierr);
1047*665f567fSMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldJ, &offsetJ);CHKERRQ(ierr);
104827f02ce8SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
104927f02ce8SMatthew G. Knepley   if (dsAux) {
105027f02ce8SMatthew G. Knepley     ierr = PetscDSGetSpatialDimension(dsAux, &dimAux);CHKERRQ(ierr);
105127f02ce8SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
105227f02ce8SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
105327f02ce8SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
105427f02ce8SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
105527f02ce8SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
105627f02ce8SMatthew G. Knepley     auxOnBd = dimAux < dim ? PETSC_TRUE : PETSC_FALSE;
1057*665f567fSMatthew G. Knepley     if (auxOnBd) {ierr = PetscDSGetTabulation(dsAux, &TAux);CHKERRQ(ierr);}
1058*665f567fSMatthew G. Knepley     else         {ierr = PetscDSGetFaceTabulation(dsAux, &TAux);CHKERRQ(ierr);}
105927f02ce8SMatthew G. Knepley   }
106027f02ce8SMatthew G. Knepley   isCohesiveFieldI = fieldI == Nf-1 ? PETSC_TRUE : PETSC_FALSE;
106127f02ce8SMatthew G. Knepley   isCohesiveFieldJ = fieldJ == Nf-1 ? PETSC_TRUE : PETSC_FALSE;
1062*665f567fSMatthew G. Knepley   NcI = T[fieldI]->Nc;
1063*665f567fSMatthew G. Knepley   NcJ = T[fieldJ]->Nc;
106427f02ce8SMatthew G. Knepley   NcS = isCohesiveFieldI ? NcI : 2*NcI;
106527f02ce8SMatthew G. Knepley   NcT = isCohesiveFieldJ ? NcJ : 2*NcJ;
106627f02ce8SMatthew G. Knepley   Np = fgeom->numPoints;
106727f02ce8SMatthew G. Knepley   dE = fgeom->dimEmbed;
106827f02ce8SMatthew G. Knepley   isAffine = fgeom->isAffine;
106927f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g0, NcS*NcT);CHKERRQ(ierr);
107027f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g1, NcS*NcT*dE);CHKERRQ(ierr);
107127f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g2, NcS*NcT*dE);CHKERRQ(ierr);
107227f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g3, NcS*NcT*dE*dE);CHKERRQ(ierr);
1073*665f567fSMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
1074*665f567fSMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
107527f02ce8SMatthew G. Knepley   for (e = 0; e < Ne; ++e) {
107627f02ce8SMatthew G. Knepley     PetscFEGeom    fegeom;
107727f02ce8SMatthew G. Knepley     const PetscInt face = fgeom->face[e][0];
107827f02ce8SMatthew G. Knepley 
107927f02ce8SMatthew G. Knepley     fegeom.dim      = fgeom->dim;
108027f02ce8SMatthew G. Knepley     fegeom.dimEmbed = fgeom->dimEmbed;
108127f02ce8SMatthew G. Knepley     if (isAffine) {
108227f02ce8SMatthew G. Knepley       fegeom.v    = x;
108327f02ce8SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
108427f02ce8SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*dE*dE];
108527f02ce8SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*dE*dE];
108627f02ce8SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e];
108727f02ce8SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*dE];
108827f02ce8SMatthew G. Knepley     }
108927f02ce8SMatthew G. Knepley     for (q = 0; q < Nq; ++q) {
109027f02ce8SMatthew G. Knepley       PetscReal w;
109127f02ce8SMatthew G. Knepley       PetscInt  c;
109227f02ce8SMatthew G. Knepley 
109327f02ce8SMatthew G. Knepley       if (isAffine) {
109427f02ce8SMatthew G. Knepley         /* TODO Is it correct to have 'dim' here, or should it be 'dim-1'? */
109527f02ce8SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &fgeom->v[e*dE], fegeom.J, &quadPoints[q*dim], x);
109627f02ce8SMatthew G. Knepley       } else {
109727f02ce8SMatthew G. Knepley         fegeom.v    = &fegeom.v[(e*Np+q)*dE];
109827f02ce8SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
109927f02ce8SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
110027f02ce8SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
110127f02ce8SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
110227f02ce8SMatthew G. Knepley       }
110327f02ce8SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
110427f02ce8SMatthew G. Knepley       if (debug > 1 && q < Np) {
110527f02ce8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
110627f02ce8SMatthew G. Knepley #if !defined(PETSC_USE_COMPLEX)
110727f02ce8SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ);CHKERRQ(ierr);
110827f02ce8SMatthew G. Knepley #endif
110927f02ce8SMatthew G. Knepley       }
111027f02ce8SMatthew G. Knepley       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
1111*665f567fSMatthew G. Knepley       if (coefficients) {ierr = PetscFEEvaluateFieldJets_Hybrid_Internal(ds, Nf, 0, q, T, &fegeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t);CHKERRQ(ierr);}
1112*665f567fSMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Hybrid_Internal(dsAux, NfAux, 0, auxOnBd ? q : face*Nq+q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
111327f02ce8SMatthew G. Knepley       if (g0_func) {
111427f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g0, NcS*NcT);CHKERRQ(ierr);
111527f02ce8SMatthew G. Knepley         g0_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, fegeom.n, numConstants, constants, g0);
111627f02ce8SMatthew G. Knepley         for (c = 0; c < NcS*NcT; ++c) g0[c] *= w;
111727f02ce8SMatthew G. Knepley       }
111827f02ce8SMatthew G. Knepley       if (g1_func) {
111927f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g1, NcS*NcT*dE);CHKERRQ(ierr);
112027f02ce8SMatthew G. Knepley         g1_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, fegeom.n, numConstants, constants, g1);
112127f02ce8SMatthew G. Knepley         for (c = 0; c < NcS*NcT*dE; ++c) g1[c] *= w;
112227f02ce8SMatthew G. Knepley       }
112327f02ce8SMatthew G. Knepley       if (g2_func) {
112427f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g2, NcS*NcT*dE);CHKERRQ(ierr);
112527f02ce8SMatthew G. Knepley         g2_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, fegeom.n, numConstants, constants, g2);
112627f02ce8SMatthew G. Knepley         for (c = 0; c < NcS*NcT*dE; ++c) g2[c] *= w;
112727f02ce8SMatthew G. Knepley       }
112827f02ce8SMatthew G. Knepley       if (g3_func) {
112927f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g3, NcS*NcT*dE*dE);CHKERRQ(ierr);
113027f02ce8SMatthew G. Knepley         g3_func(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, NULL, a_x, t, u_tshift, fegeom.v, fegeom.n, numConstants, constants, g3);
113127f02ce8SMatthew G. Knepley         for (c = 0; c < NcS*NcT*dE*dE; ++c) g3[c] *= w;
113227f02ce8SMatthew G. Knepley       }
113327f02ce8SMatthew G. Knepley 
113427f02ce8SMatthew G. Knepley       if (isCohesiveFieldI && isCohesiveFieldJ) {
1135*665f567fSMatthew G. Knepley         ierr = PetscFEUpdateElementMat_Internal(feI, feJ, 0, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, g0, g1, g2, g3, eOffset, totDim, offsetI*2, offsetJ*2, elemMat);CHKERRQ(ierr);
113627f02ce8SMatthew G. Knepley       } else {
1137*665f567fSMatthew G. Knepley         ierr = PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, g0, g1, g2, g3, eOffset, totDim, offsetI*2, offsetJ*2, elemMat);CHKERRQ(ierr);
113827f02ce8SMatthew G. Knepley       }
113927f02ce8SMatthew G. Knepley     }
114027f02ce8SMatthew G. Knepley     if (debug > 1) {
114127f02ce8SMatthew G. Knepley       PetscInt fc, f, gc, g;
114227f02ce8SMatthew G. Knepley 
114327f02ce8SMatthew G. Knepley       ierr = PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %d and %d\n", fieldI, fieldJ);CHKERRQ(ierr);
114427f02ce8SMatthew G. Knepley       for (fc = 0; fc < NcI; ++fc) {
1145*665f567fSMatthew G. Knepley         for (f = 0; f < T[fieldI]->Nb; ++f) {
114627f02ce8SMatthew G. Knepley           const PetscInt i = offsetI + f*NcI+fc;
114727f02ce8SMatthew G. Knepley           for (gc = 0; gc < NcJ; ++gc) {
1148*665f567fSMatthew G. Knepley             for (g = 0; g < T[fieldJ]->Nb; ++g) {
114927f02ce8SMatthew G. Knepley               const PetscInt j = offsetJ + g*NcJ+gc;
115027f02ce8SMatthew G. Knepley               ierr = PetscPrintf(PETSC_COMM_SELF, "    elemMat[%d,%d,%d,%d]: %g\n", f, fc, g, gc, PetscRealPart(elemMat[eOffset+i*totDim+j]));CHKERRQ(ierr);
115127f02ce8SMatthew G. Knepley             }
115227f02ce8SMatthew G. Knepley           }
115327f02ce8SMatthew G. Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
115427f02ce8SMatthew G. Knepley         }
115527f02ce8SMatthew G. Knepley       }
115627f02ce8SMatthew G. Knepley     }
115727f02ce8SMatthew G. Knepley     cOffset    += totDim;
115827f02ce8SMatthew G. Knepley     cOffsetAux += totDimAux;
115927f02ce8SMatthew G. Knepley     eOffset    += PetscSqr(totDim);
116027f02ce8SMatthew G. Knepley   }
116127f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
116227f02ce8SMatthew G. Knepley }
116327f02ce8SMatthew G. Knepley 
11642b99622eSMatthew G. Knepley static PetscErrorCode PetscFEInitialize_Basic(PetscFE fem)
116520cf1dd8SToby Isaac {
116620cf1dd8SToby Isaac   PetscFunctionBegin;
116720cf1dd8SToby Isaac   fem->ops->setfromoptions          = NULL;
116820cf1dd8SToby Isaac   fem->ops->setup                   = PetscFESetUp_Basic;
116920cf1dd8SToby Isaac   fem->ops->view                    = PetscFEView_Basic;
117020cf1dd8SToby Isaac   fem->ops->destroy                 = PetscFEDestroy_Basic;
117120cf1dd8SToby Isaac   fem->ops->getdimension            = PetscFEGetDimension_Basic;
1172ef0bb6c7SMatthew G. Knepley   fem->ops->createtabulation        = PetscFECreateTabulation_Basic;
117320cf1dd8SToby Isaac   fem->ops->integrate               = PetscFEIntegrate_Basic;
1174afe6d6adSToby Isaac   fem->ops->integratebd             = PetscFEIntegrateBd_Basic;
117520cf1dd8SToby Isaac   fem->ops->integrateresidual       = PetscFEIntegrateResidual_Basic;
117620cf1dd8SToby Isaac   fem->ops->integratebdresidual     = PetscFEIntegrateBdResidual_Basic;
117727f02ce8SMatthew G. Knepley   fem->ops->integratehybridresidual = PetscFEIntegrateHybridResidual_Basic;
117820cf1dd8SToby Isaac   fem->ops->integratejacobianaction = NULL/* PetscFEIntegrateJacobianAction_Basic */;
117920cf1dd8SToby Isaac   fem->ops->integratejacobian       = PetscFEIntegrateJacobian_Basic;
118020cf1dd8SToby Isaac   fem->ops->integratebdjacobian     = PetscFEIntegrateBdJacobian_Basic;
118127f02ce8SMatthew G. Knepley   fem->ops->integratehybridjacobian = PetscFEIntegrateHybridJacobian_Basic;
118220cf1dd8SToby Isaac   PetscFunctionReturn(0);
118320cf1dd8SToby Isaac }
118420cf1dd8SToby Isaac 
118520cf1dd8SToby Isaac /*MC
118620cf1dd8SToby Isaac   PETSCFEBASIC = "basic" - A PetscFE object that integrates with basic tiling and no vectorization
118720cf1dd8SToby Isaac 
118820cf1dd8SToby Isaac   Level: intermediate
118920cf1dd8SToby Isaac 
119020cf1dd8SToby Isaac .seealso: PetscFEType, PetscFECreate(), PetscFESetType()
119120cf1dd8SToby Isaac M*/
119220cf1dd8SToby Isaac 
119320cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode PetscFECreate_Basic(PetscFE fem)
119420cf1dd8SToby Isaac {
119520cf1dd8SToby Isaac   PetscFE_Basic *b;
119620cf1dd8SToby Isaac   PetscErrorCode ierr;
119720cf1dd8SToby Isaac 
119820cf1dd8SToby Isaac   PetscFunctionBegin;
119920cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
120020cf1dd8SToby Isaac   ierr      = PetscNewLog(fem,&b);CHKERRQ(ierr);
120120cf1dd8SToby Isaac   fem->data = b;
120220cf1dd8SToby Isaac 
120320cf1dd8SToby Isaac   ierr = PetscFEInitialize_Basic(fem);CHKERRQ(ierr);
120420cf1dd8SToby Isaac   PetscFunctionReturn(0);
120520cf1dd8SToby Isaac }
1206