xref: /petsc/src/dm/dt/fe/impls/basic/febasic.c (revision 27f02ce888cd6d83c79d307cd15e2865fe9f0ab4)
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 
216*27f02ce8SMatthew G. Knepley     fegeom.dim      = cgeom->dim;
217*27f02ce8SMatthew 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;
312*27f02ce8SMatthew G. Knepley     fegeom.dim      = fgeom->dim;
313*27f02ce8SMatthew G. Knepley     fegeom.dimEmbed = fgeom->dimEmbed;
314*27f02ce8SMatthew G. Knepley     cgeom.dim       = fgeom->dim;
315*27f02ce8SMatthew 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 
417*27f02ce8SMatthew G. Knepley     fegeom.dim      = cgeom->dim;
418*27f02ce8SMatthew 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);
427*27f02ce8SMatthew 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;
525*27f02ce8SMatthew G. Knepley     fegeom.dim      = fgeom->dim;
526*27f02ce8SMatthew G. Knepley     fegeom.dimEmbed = fgeom->dimEmbed;
527*27f02ce8SMatthew G. Knepley     cgeom.dim       = fgeom->dim;
528*27f02ce8SMatthew 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);
542*27f02ce8SMatthew 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 
586*27f02ce8SMatthew G. Knepley /*
587*27f02ce8SMatthew 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
588*27f02ce8SMatthew G. Knepley               all transforms operate in the full space and are square.
589*27f02ce8SMatthew G. Knepley 
590*27f02ce8SMatthew G. Knepley   HybridIntegral: The discretization is lower dimensional. That means the transforms are non-square.
591*27f02ce8SMatthew G. Knepley     1) DMPlexGetCellFields() retrieves from the hybrid cell, so it gets fields from both faces
592*27f02ce8SMatthew G. Knepley     2) We need to assume that the orientation is 0 for both
593*27f02ce8SMatthew 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()
594*27f02ce8SMatthew G. Knepley */
595*27f02ce8SMatthew G. Knepley static PetscErrorCode PetscFEIntegrateHybridResidual_Basic(PetscDS ds, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom,
596*27f02ce8SMatthew G. Knepley                                                            const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
597*27f02ce8SMatthew G. Knepley {
598*27f02ce8SMatthew G. Knepley   const PetscInt     debug = 0;
599*27f02ce8SMatthew G. Knepley   PetscFE            fe;
600*27f02ce8SMatthew G. Knepley   PetscBdPointFunc   f0_func;
601*27f02ce8SMatthew G. Knepley   PetscBdPointFunc   f1_func;
602*27f02ce8SMatthew G. Knepley   PetscQuadrature    quad;
603*27f02ce8SMatthew G. Knepley   PetscScalar       *f0, *f1, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal;
604*27f02ce8SMatthew G. Knepley   const PetscScalar *constants;
605*27f02ce8SMatthew G. Knepley   PetscReal         *x;
606*27f02ce8SMatthew G. Knepley   PetscReal        **B, **D, **BAux = NULL, **DAux = NULL, *BI, *DI;
607*27f02ce8SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL, *Nb, *Nc, *NbAux = NULL, *NcAux = NULL;
608*27f02ce8SMatthew G. Knepley   PetscInt           dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, fOffset, e, NbI, NcI, NcS;
609*27f02ce8SMatthew G. Knepley   PetscBool          isCohesiveField, isAffine, auxOnBd;
610*27f02ce8SMatthew G. Knepley   const PetscReal   *quadPoints, *quadWeights;
611*27f02ce8SMatthew G. Knepley   PetscInt           qNc, Nq, q, Np, dE;
612*27f02ce8SMatthew G. Knepley   PetscErrorCode     ierr;
613*27f02ce8SMatthew G. Knepley 
614*27f02ce8SMatthew G. Knepley   PetscFunctionBegin;
615*27f02ce8SMatthew G. Knepley   /* Hybrid discretization is posed directly on faces */
616*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
617*27f02ce8SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(fe, &dim);CHKERRQ(ierr);
618*27f02ce8SMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr);
619*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
620*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
621*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetDimensions(ds, &Nb);CHKERRQ(ierr);
622*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetComponents(ds, &Nc);CHKERRQ(ierr);
623*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
624*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
625*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, field, &fOffset);CHKERRQ(ierr);
626*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetBdResidual(ds, field, &f0_func, &f1_func);CHKERRQ(ierr);
627*27f02ce8SMatthew G. Knepley   if (!f0_func && !f1_func) PetscFunctionReturn(0);
628*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
629*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL);CHKERRQ(ierr);
630*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, &f0, &f1, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
631*27f02ce8SMatthew G. Knepley   /* NOTE This is a bulk tabulation because the DS is a face discretization */
632*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetTabulation(ds, &B, &D);CHKERRQ(ierr);
633*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
634*27f02ce8SMatthew G. Knepley   if (dsAux) {
635*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetSpatialDimension(dsAux, &dimAux);CHKERRQ(ierr);
636*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
637*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
638*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetDimensions(dsAux, &NbAux);CHKERRQ(ierr);
639*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetComponents(dsAux, &NcAux);CHKERRQ(ierr);
640*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
641*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
642*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
643*27f02ce8SMatthew G. Knepley     auxOnBd = dimAux < dim ? PETSC_TRUE : PETSC_FALSE;
644*27f02ce8SMatthew G. Knepley     if (auxOnBd) {ierr = PetscDSGetTabulation(dsAux, &BAux, &DAux);CHKERRQ(ierr);}
645*27f02ce8SMatthew G. Knepley     else         {ierr = PetscDSGetFaceTabulation(dsAux, &BAux, &DAux);CHKERRQ(ierr);}
646*27f02ce8SMatthew G. Knepley   }
647*27f02ce8SMatthew G. Knepley   isCohesiveField = field == Nf-1 ? PETSC_TRUE : PETSC_FALSE;
648*27f02ce8SMatthew G. Knepley   NbI = Nb[field];
649*27f02ce8SMatthew G. Knepley   NcI = Nc[field];
650*27f02ce8SMatthew G. Knepley   NcS = isCohesiveField ? NcI : 2*NcI;
651*27f02ce8SMatthew G. Knepley   BI  = B[field];
652*27f02ce8SMatthew G. Knepley   DI  = D[field];
653*27f02ce8SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
654*27f02ce8SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
655*27f02ce8SMatthew G. Knepley   Np = fgeom->numPoints;
656*27f02ce8SMatthew G. Knepley   dE = fgeom->dimEmbed;
657*27f02ce8SMatthew G. Knepley   isAffine = fgeom->isAffine;
658*27f02ce8SMatthew G. Knepley   for (e = 0; e < Ne; ++e) {
659*27f02ce8SMatthew G. Knepley     PetscFEGeom    fegeom;
660*27f02ce8SMatthew G. Knepley     const PetscInt face = fgeom->face[e][0];
661*27f02ce8SMatthew G. Knepley 
662*27f02ce8SMatthew G. Knepley     fegeom.dim      = fgeom->dim;
663*27f02ce8SMatthew G. Knepley     fegeom.dimEmbed = fgeom->dimEmbed;
664*27f02ce8SMatthew G. Knepley     if (isAffine) {
665*27f02ce8SMatthew G. Knepley       fegeom.v    = x;
666*27f02ce8SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
667*27f02ce8SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*dE*dE];
668*27f02ce8SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*dE*dE];
669*27f02ce8SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e];
670*27f02ce8SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*dE];
671*27f02ce8SMatthew G. Knepley     }
672*27f02ce8SMatthew G. Knepley     ierr = PetscArrayzero(f0, Nq*NcS);CHKERRQ(ierr);
673*27f02ce8SMatthew G. Knepley     ierr = PetscArrayzero(f1, Nq*NcS*dE);CHKERRQ(ierr);
674*27f02ce8SMatthew G. Knepley     for (q = 0; q < Nq; ++q) {
675*27f02ce8SMatthew G. Knepley       PetscReal w;
676*27f02ce8SMatthew G. Knepley       PetscInt  c, d;
677*27f02ce8SMatthew G. Knepley 
678*27f02ce8SMatthew G. Knepley       if (isAffine) {
679*27f02ce8SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &fgeom->v[e*dE], fegeom.J, &quadPoints[q*dim], x);
680*27f02ce8SMatthew G. Knepley       } else {
681*27f02ce8SMatthew G. Knepley         fegeom.v    = &fgeom->v[(e*Np+q)*dE];
682*27f02ce8SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
683*27f02ce8SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
684*27f02ce8SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
685*27f02ce8SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
686*27f02ce8SMatthew G. Knepley       }
687*27f02ce8SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
688*27f02ce8SMatthew G. Knepley       if (debug > 1 && q < Np) {
689*27f02ce8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
690*27f02ce8SMatthew G. Knepley #if !defined(PETSC_USE_COMPLEX)
691*27f02ce8SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dE, fegeom.invJ);CHKERRQ(ierr);
692*27f02ce8SMatthew G. Knepley #endif
693*27f02ce8SMatthew G. Knepley       }
694*27f02ce8SMatthew G. Knepley       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
695*27f02ce8SMatthew G. Knepley       /* TODO Is this cell or face quadrature, meaning should we use 'q' or 'face*Nq+q' */
696*27f02ce8SMatthew G. Knepley       ierr = PetscFEEvaluateFieldJets_Hybrid_Internal(ds, dim, Nf, Nb, Nc, q, B, D, &fegeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t);CHKERRQ(ierr);
697*27f02ce8SMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Hybrid_Internal(dsAux, dimAux, NfAux, NbAux, NcAux, auxOnBd ? q : face*Nq+q, BAux, DAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
698*27f02ce8SMatthew G. Knepley       if (f0_func) {
699*27f02ce8SMatthew 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]);
700*27f02ce8SMatthew G. Knepley         for (c = 0; c < NcS; ++c) f0[q*NcS+c] *= w;
701*27f02ce8SMatthew G. Knepley       }
702*27f02ce8SMatthew G. Knepley       if (f1_func) {
703*27f02ce8SMatthew 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]);
704*27f02ce8SMatthew G. Knepley         for (c = 0; c < NcS; ++c) for (d = 0; d < dim; ++d) f1[(q*NcS+c)*dim+d] *= w;
705*27f02ce8SMatthew G. Knepley       }
706*27f02ce8SMatthew G. Knepley     }
707*27f02ce8SMatthew G. Knepley     /* TODO These are tabulations. Shouldn;t they be face tabulations? &BI[face*Nq*NbI*NcI], &DI[face*Nq*NbI*NcI*dim] */
708*27f02ce8SMatthew G. Knepley     if (isCohesiveField) {PetscFEUpdateElementVec_Internal(fe, dim, Nq, NbI, NcI, BI, DI, basisReal, basisDerReal, &fegeom, f0, f1, &elemVec[cOffset+fOffset*2]);}
709*27f02ce8SMatthew G. Knepley     else                 {PetscFEUpdateElementVec_Hybrid_Internal(fe, dim, Nq, NbI, NcI, BI, DI, basisReal, basisDerReal, &fegeom, f0, f1, &elemVec[cOffset+fOffset*2]);}
710*27f02ce8SMatthew G. Knepley     cOffset    += totDim;
711*27f02ce8SMatthew G. Knepley     cOffsetAux += totDimAux;
712*27f02ce8SMatthew G. Knepley   }
713*27f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
714*27f02ce8SMatthew G. Knepley }
715*27f02ce8SMatthew G. Knepley 
7164bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateJacobian_Basic(PetscDS ds, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *cgeom,
7174bee2e38SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
71820cf1dd8SToby Isaac {
71920cf1dd8SToby Isaac   const PetscInt     debug      = 0;
7204bee2e38SMatthew G. Knepley   PetscFE            feI, feJ;
7214bee2e38SMatthew G. Knepley   PetscPointJac      g0_func, g1_func, g2_func, g3_func;
72220cf1dd8SToby Isaac   PetscInt           cOffset    = 0; /* Offset into coefficients[] for element e */
72320cf1dd8SToby Isaac   PetscInt           cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */
72420cf1dd8SToby Isaac   PetscInt           eOffset    = 0; /* Offset into elemMat[] for element e */
72520cf1dd8SToby Isaac   PetscInt           offsetI    = 0; /* Offset into an element vector for fieldI */
72620cf1dd8SToby Isaac   PetscInt           offsetJ    = 0; /* Offset into an element vector for fieldJ */
72720cf1dd8SToby Isaac   PetscQuadrature    quad;
728ef0bb6c7SMatthew G. Knepley   PetscTabulation   *T, *TAux = NULL;
7294bee2e38SMatthew G. Knepley   PetscScalar       *g0, *g1, *g2, *g3, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal;
73020cf1dd8SToby Isaac   const PetscScalar *constants;
73120cf1dd8SToby Isaac   PetscReal         *x;
732ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
733ef0bb6c7SMatthew G. Knepley   PetscInt           NcI = 0, NcJ = 0;
73420cf1dd8SToby Isaac   PetscInt           dim, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, e;
73520cf1dd8SToby Isaac   PetscInt           dE, Np;
73620cf1dd8SToby Isaac   PetscBool          isAffine;
73720cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
73820cf1dd8SToby Isaac   PetscInt           qNc, Nq, q;
73920cf1dd8SToby Isaac   PetscErrorCode     ierr;
74020cf1dd8SToby Isaac 
74120cf1dd8SToby Isaac   PetscFunctionBegin;
7424bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldI, (PetscObject *) &feI);CHKERRQ(ierr);
7434bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldJ, (PetscObject *) &feJ);CHKERRQ(ierr);
7444bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(feI, &dim);CHKERRQ(ierr);
7454bee2e38SMatthew G. Knepley   ierr = PetscFEGetQuadrature(feI, &quad);CHKERRQ(ierr);
7464bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
7474bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
7484bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
7494bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
75020cf1dd8SToby Isaac   switch(jtype) {
7514bee2e38SMatthew G. Knepley   case PETSCFE_JACOBIAN_DYN: ierr = PetscDSGetDynamicJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
7524bee2e38SMatthew G. Knepley   case PETSCFE_JACOBIAN_PRE: ierr = PetscDSGetJacobianPreconditioner(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
7534bee2e38SMatthew G. Knepley   case PETSCFE_JACOBIAN:     ierr = PetscDSGetJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
75420cf1dd8SToby Isaac   }
75520cf1dd8SToby Isaac   if (!g0_func && !g1_func && !g2_func && !g3_func) PetscFunctionReturn(0);
7564bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
7574bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal);CHKERRQ(ierr);
7584bee2e38SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, NULL, NULL, &g0, &g1, &g2, &g3);CHKERRQ(ierr);
759ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetTabulation(ds, &T);CHKERRQ(ierr);
7604bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldI, &offsetI);CHKERRQ(ierr);
7614bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldJ, &offsetJ);CHKERRQ(ierr);
7624bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
7634bee2e38SMatthew G. Knepley   if (dsAux) {
7644bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
7654bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
7664bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
7674bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
7684bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
769ef0bb6c7SMatthew G. Knepley     ierr = PetscDSGetTabulation(dsAux, &TAux);CHKERRQ(ierr);
77020cf1dd8SToby Isaac   }
771*27f02ce8SMatthew G. Knepley   NcI = T[fieldI]->Nc;
772*27f02ce8SMatthew G. Knepley   NcJ = T[fieldJ]->Nc;
7734bee2e38SMatthew G. Knepley   Np  = cgeom->numPoints;
7744bee2e38SMatthew G. Knepley   dE  = cgeom->dimEmbed;
7754bee2e38SMatthew G. Knepley   isAffine = cgeom->isAffine;
776*27f02ce8SMatthew G. Knepley   /* Initialize here in case the function is not defined */
777*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
778*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g1, NcI*NcJ*dE);CHKERRQ(ierr);
779*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g2, NcI*NcJ*dE);CHKERRQ(ierr);
780*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g3, NcI*NcJ*dE*dE);CHKERRQ(ierr);
781*27f02ce8SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
782*27f02ce8SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
7834bee2e38SMatthew G. Knepley   for (e = 0; e < Ne; ++e) {
7844bee2e38SMatthew G. Knepley     PetscFEGeom fegeom;
7854bee2e38SMatthew G. Knepley 
786*27f02ce8SMatthew G. Knepley     fegeom.dim      = cgeom->dim;
787*27f02ce8SMatthew G. Knepley     fegeom.dimEmbed = cgeom->dimEmbed;
7884bee2e38SMatthew G. Knepley     if (isAffine) {
7894bee2e38SMatthew G. Knepley       fegeom.v    = x;
7904bee2e38SMatthew G. Knepley       fegeom.xi   = cgeom->xi;
7917132c3f7SMatthew G. Knepley       fegeom.J    = &cgeom->J[e*Np*dE*dE];
7927132c3f7SMatthew G. Knepley       fegeom.invJ = &cgeom->invJ[e*Np*dE*dE];
7937132c3f7SMatthew G. Knepley       fegeom.detJ = &cgeom->detJ[e*Np];
7944bee2e38SMatthew G. Knepley     }
79520cf1dd8SToby Isaac     for (q = 0; q < Nq; ++q) {
79620cf1dd8SToby Isaac       PetscReal w;
7974bee2e38SMatthew G. Knepley       PetscInt  c;
79820cf1dd8SToby Isaac 
79920cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
80020cf1dd8SToby Isaac       if (isAffine) {
8017132c3f7SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &cgeom->v[e*Np*dE], fegeom.J, &quadPoints[q*dim], x);
80220cf1dd8SToby Isaac       } else {
8034bee2e38SMatthew G. Knepley         fegeom.v    = &cgeom->v[(e*Np+q)*dE];
8044bee2e38SMatthew G. Knepley         fegeom.J    = &cgeom->J[(e*Np+q)*dE*dE];
8054bee2e38SMatthew G. Knepley         fegeom.invJ = &cgeom->invJ[(e*Np+q)*dE*dE];
8064bee2e38SMatthew G. Knepley         fegeom.detJ = &cgeom->detJ[e*Np+q];
80720cf1dd8SToby Isaac       }
8084bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
809ef0bb6c7SMatthew 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);}
810ef0bb6c7SMatthew G. Knepley       if (dsAux)        {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
81120cf1dd8SToby Isaac       if (g0_func) {
812580bdb30SBarry Smith         ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
8134bee2e38SMatthew 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);
81420cf1dd8SToby Isaac         for (c = 0; c < NcI*NcJ; ++c) g0[c] *= w;
81520cf1dd8SToby Isaac       }
81620cf1dd8SToby Isaac       if (g1_func) {
817*27f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g1, NcI*NcJ*dE);CHKERRQ(ierr);
8184bee2e38SMatthew 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);
8194bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g1[c] *= w;
82020cf1dd8SToby Isaac       }
82120cf1dd8SToby Isaac       if (g2_func) {
822*27f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g2, NcI*NcJ*dE);CHKERRQ(ierr);
8234bee2e38SMatthew 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);
8244bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g2[c] *= w;
82520cf1dd8SToby Isaac       }
82620cf1dd8SToby Isaac       if (g3_func) {
827*27f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g3, NcI*NcJ*dE*dE);CHKERRQ(ierr);
8284bee2e38SMatthew 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);
8294bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim*dim; ++c) g3[c] *= w;
83020cf1dd8SToby Isaac       }
83120cf1dd8SToby Isaac 
832ef0bb6c7SMatthew 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);
83320cf1dd8SToby Isaac     }
83420cf1dd8SToby Isaac     if (debug > 1) {
83520cf1dd8SToby Isaac       PetscInt fc, f, gc, g;
83620cf1dd8SToby Isaac 
83720cf1dd8SToby Isaac       ierr = PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %d and %d\n", fieldI, fieldJ);CHKERRQ(ierr);
838ef0bb6c7SMatthew G. Knepley       for (fc = 0; fc < T[fieldI]->Nc; ++fc) {
839ef0bb6c7SMatthew G. Knepley         for (f = 0; f < T[fieldI]->Nb; ++f) {
840ef0bb6c7SMatthew G. Knepley           const PetscInt i = offsetI + f*T[fieldI]->Nc+fc;
841ef0bb6c7SMatthew G. Knepley           for (gc = 0; gc < T[fieldJ]->Nc; ++gc) {
842ef0bb6c7SMatthew G. Knepley             for (g = 0; g < T[fieldJ]->Nb; ++g) {
843ef0bb6c7SMatthew G. Knepley               const PetscInt j = offsetJ + g*T[fieldJ]->Nc+gc;
84420cf1dd8SToby 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);
84520cf1dd8SToby Isaac             }
84620cf1dd8SToby Isaac           }
84720cf1dd8SToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
84820cf1dd8SToby Isaac         }
84920cf1dd8SToby Isaac       }
85020cf1dd8SToby Isaac     }
85120cf1dd8SToby Isaac     cOffset    += totDim;
85220cf1dd8SToby Isaac     cOffsetAux += totDimAux;
85320cf1dd8SToby Isaac     eOffset    += PetscSqr(totDim);
85420cf1dd8SToby Isaac   }
85520cf1dd8SToby Isaac   PetscFunctionReturn(0);
85620cf1dd8SToby Isaac }
85720cf1dd8SToby Isaac 
8582b99622eSMatthew G. Knepley static PetscErrorCode PetscFEIntegrateBdJacobian_Basic(PetscDS ds, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
8594bee2e38SMatthew G. Knepley                                                        const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
86020cf1dd8SToby Isaac {
86120cf1dd8SToby Isaac   const PetscInt     debug      = 0;
8624bee2e38SMatthew G. Knepley   PetscFE            feI, feJ;
8634bee2e38SMatthew G. Knepley   PetscBdPointJac    g0_func, g1_func, g2_func, g3_func;
86420cf1dd8SToby Isaac   PetscInt           cOffset    = 0; /* Offset into coefficients[] for element e */
86520cf1dd8SToby Isaac   PetscInt           cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */
86620cf1dd8SToby Isaac   PetscInt           eOffset    = 0; /* Offset into elemMat[] for element e */
86720cf1dd8SToby Isaac   PetscInt           offsetI    = 0; /* Offset into an element vector for fieldI */
86820cf1dd8SToby Isaac   PetscInt           offsetJ    = 0; /* Offset into an element vector for fieldJ */
86920cf1dd8SToby Isaac   PetscQuadrature    quad;
870ef0bb6c7SMatthew G. Knepley   PetscTabulation   *T, *TAux = NULL;
8714bee2e38SMatthew G. Knepley   PetscScalar       *g0, *g1, *g2, *g3, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal;
87220cf1dd8SToby Isaac   const PetscScalar *constants;
87320cf1dd8SToby Isaac   PetscReal         *x;
874ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
875ef0bb6c7SMatthew G. Knepley   PetscInt           NcI = 0, NcJ = 0;
87620cf1dd8SToby Isaac   PetscInt           dim, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, e;
87720cf1dd8SToby Isaac   PetscBool          isAffine;
87820cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
87920cf1dd8SToby Isaac   PetscInt           qNc, Nq, q, Np, dE;
88020cf1dd8SToby Isaac   PetscErrorCode     ierr;
88120cf1dd8SToby Isaac 
88220cf1dd8SToby Isaac   PetscFunctionBegin;
8834bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldI, (PetscObject *) &feI);CHKERRQ(ierr);
8844bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldJ, (PetscObject *) &feJ);CHKERRQ(ierr);
8854bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(feI, &dim);CHKERRQ(ierr);
8864bee2e38SMatthew G. Knepley   ierr = PetscFEGetFaceQuadrature(feI, &quad);CHKERRQ(ierr);
8874bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
8884bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
8894bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
8904bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
8914bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldI, &offsetI);CHKERRQ(ierr);
8924bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldJ, &offsetJ);CHKERRQ(ierr);
8934bee2e38SMatthew G. Knepley   ierr = PetscDSGetBdJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);
89431f073d7SMatthew G. Knepley   if (!g0_func && !g1_func && !g2_func && !g3_func) PetscFunctionReturn(0);
8954bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
8964bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal);CHKERRQ(ierr);
8974bee2e38SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, NULL, NULL, &g0, &g1, &g2, &g3);CHKERRQ(ierr);
898ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetFaceTabulation(ds, &T);CHKERRQ(ierr);
8994bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
9004bee2e38SMatthew G. Knepley   if (dsAux) {
9014bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
9024bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
9034bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
9044bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
9054bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
906ef0bb6c7SMatthew G. Knepley     ierr = PetscDSGetFaceTabulation(dsAux, &TAux);CHKERRQ(ierr);
90720cf1dd8SToby Isaac   }
908ef0bb6c7SMatthew G. Knepley   NcI = T[fieldI]->Nc, NcJ = T[fieldJ]->Nc;
90920cf1dd8SToby Isaac   Np = fgeom->numPoints;
91020cf1dd8SToby Isaac   dE = fgeom->dimEmbed;
91120cf1dd8SToby Isaac   isAffine = fgeom->isAffine;
912*27f02ce8SMatthew G. Knepley   /* Initialize here in case the function is not defined */
91331f073d7SMatthew G. Knepley   ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
914*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g1, NcI*NcJ*dE);CHKERRQ(ierr);
915*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g2, NcI*NcJ*dE);CHKERRQ(ierr);
916*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g3, NcI*NcJ*dE*dE);CHKERRQ(ierr);
917*27f02ce8SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
918*27f02ce8SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
91920cf1dd8SToby Isaac   for (e = 0; e < Ne; ++e) {
9209f209ee4SMatthew G. Knepley     PetscFEGeom    fegeom, cgeom;
92120cf1dd8SToby Isaac     const PetscInt face = fgeom->face[e][0];
9224dcf62a8SSatish Balay     fegeom.n = 0;
9234dcf62a8SSatish Balay     fegeom.v = 0;
9244dcf62a8SSatish Balay     fegeom.J = 0;
9254dcf62a8SSatish Balay     fegeom.detJ = 0;
926*27f02ce8SMatthew G. Knepley     fegeom.dim      = fgeom->dim;
927*27f02ce8SMatthew G. Knepley     fegeom.dimEmbed = fgeom->dimEmbed;
928*27f02ce8SMatthew G. Knepley     cgeom.dim       = fgeom->dim;
929*27f02ce8SMatthew G. Knepley     cgeom.dimEmbed  = fgeom->dimEmbed;
9304bee2e38SMatthew G. Knepley     if (isAffine) {
9314bee2e38SMatthew G. Knepley       fegeom.v    = x;
9324bee2e38SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
9337132c3f7SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*Np*dE*dE];
9347132c3f7SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*Np*dE*dE];
9357132c3f7SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e*Np];
9367132c3f7SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*Np*dE];
9379f209ee4SMatthew G. Knepley 
9387132c3f7SMatthew G. Knepley       cgeom.J     = &fgeom->suppJ[0][e*Np*dE*dE];
9397132c3f7SMatthew G. Knepley       cgeom.invJ  = &fgeom->suppInvJ[0][e*Np*dE*dE];
9407132c3f7SMatthew G. Knepley       cgeom.detJ  = &fgeom->suppDetJ[0][e*Np];
9414bee2e38SMatthew G. Knepley     }
94220cf1dd8SToby Isaac     for (q = 0; q < Nq; ++q) {
94320cf1dd8SToby Isaac       PetscReal w;
9444bee2e38SMatthew G. Knepley       PetscInt  c;
94520cf1dd8SToby Isaac 
94620cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
94720cf1dd8SToby Isaac       if (isAffine) {
9487132c3f7SMatthew G. Knepley         CoordinatesRefToReal(dE, dim-1, fegeom.xi, &fgeom->v[e*Np*dE], fegeom.J, &quadPoints[q*(dim-1)], x);
94920cf1dd8SToby Isaac       } else {
9503fe841f2SMatthew G. Knepley         fegeom.v    = &fgeom->v[(e*Np+q)*dE];
9519f209ee4SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
9529f209ee4SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
9534bee2e38SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
9544bee2e38SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
9559f209ee4SMatthew G. Knepley 
9569f209ee4SMatthew G. Knepley         cgeom.J     = &fgeom->suppJ[0][(e*Np+q)*dE*dE];
9579f209ee4SMatthew G. Knepley         cgeom.invJ  = &fgeom->suppInvJ[0][(e*Np+q)*dE*dE];
9589f209ee4SMatthew G. Knepley         cgeom.detJ  = &fgeom->suppDetJ[0][e*Np+q];
95920cf1dd8SToby Isaac       }
9604bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
961ef0bb6c7SMatthew 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);}
962ef0bb6c7SMatthew G. Knepley       if (dsAux)        {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, face, q, TAux, &cgeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
96320cf1dd8SToby Isaac       if (g0_func) {
964580bdb30SBarry Smith         ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
9654bee2e38SMatthew 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);
96620cf1dd8SToby Isaac         for (c = 0; c < NcI*NcJ; ++c) g0[c] *= w;
96720cf1dd8SToby Isaac       }
96820cf1dd8SToby Isaac       if (g1_func) {
969*27f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g1, NcI*NcJ*dE);CHKERRQ(ierr);
9704bee2e38SMatthew 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);
9714bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g1[c] *= w;
97220cf1dd8SToby Isaac       }
97320cf1dd8SToby Isaac       if (g2_func) {
974*27f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g2, NcI*NcJ*dE);CHKERRQ(ierr);
9754bee2e38SMatthew 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);
9764bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g2[c] *= w;
97720cf1dd8SToby Isaac       }
97820cf1dd8SToby Isaac       if (g3_func) {
979*27f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g3, NcI*NcJ*dE*dE);CHKERRQ(ierr);
9804bee2e38SMatthew 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);
9814bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim*dim; ++c) g3[c] *= w;
98220cf1dd8SToby Isaac       }
98320cf1dd8SToby Isaac 
984ef0bb6c7SMatthew 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);
98520cf1dd8SToby Isaac     }
98620cf1dd8SToby Isaac     if (debug > 1) {
98720cf1dd8SToby Isaac       PetscInt fc, f, gc, g;
98820cf1dd8SToby Isaac 
98920cf1dd8SToby Isaac       ierr = PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %d and %d\n", fieldI, fieldJ);CHKERRQ(ierr);
990ef0bb6c7SMatthew G. Knepley       for (fc = 0; fc < T[fieldI]->Nc; ++fc) {
991ef0bb6c7SMatthew G. Knepley         for (f = 0; f < T[fieldI]->Nb; ++f) {
992ef0bb6c7SMatthew G. Knepley           const PetscInt i = offsetI + f*T[fieldI]->Nc+fc;
993ef0bb6c7SMatthew G. Knepley           for (gc = 0; gc < T[fieldJ]->Nc; ++gc) {
994ef0bb6c7SMatthew G. Knepley             for (g = 0; g < T[fieldJ]->Nb; ++g) {
995ef0bb6c7SMatthew G. Knepley               const PetscInt j = offsetJ + g*T[fieldJ]->Nc+gc;
99620cf1dd8SToby 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);
99720cf1dd8SToby Isaac             }
99820cf1dd8SToby Isaac           }
99920cf1dd8SToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
100020cf1dd8SToby Isaac         }
100120cf1dd8SToby Isaac       }
100220cf1dd8SToby Isaac     }
100320cf1dd8SToby Isaac     cOffset    += totDim;
100420cf1dd8SToby Isaac     cOffsetAux += totDimAux;
100520cf1dd8SToby Isaac     eOffset    += PetscSqr(totDim);
100620cf1dd8SToby Isaac   }
100720cf1dd8SToby Isaac   PetscFunctionReturn(0);
100820cf1dd8SToby Isaac }
100920cf1dd8SToby Isaac 
1010*27f02ce8SMatthew G. Knepley PetscErrorCode PetscFEIntegrateHybridJacobian_Basic(PetscDS ds, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
1011*27f02ce8SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
1012*27f02ce8SMatthew G. Knepley {
1013*27f02ce8SMatthew G. Knepley   const PetscInt     debug      = 0;
1014*27f02ce8SMatthew G. Knepley   PetscFE            feI, feJ;
1015*27f02ce8SMatthew G. Knepley   PetscBdPointJac    g0_func;
1016*27f02ce8SMatthew G. Knepley   PetscBdPointJac    g1_func;
1017*27f02ce8SMatthew G. Knepley   PetscBdPointJac    g2_func;
1018*27f02ce8SMatthew G. Knepley   PetscBdPointJac    g3_func;
1019*27f02ce8SMatthew G. Knepley   PetscQuadrature    quad;
1020*27f02ce8SMatthew G. Knepley   PetscInt           cOffset    = 0; /* Offset into coefficients[] for element e */
1021*27f02ce8SMatthew G. Knepley   PetscInt           cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */
1022*27f02ce8SMatthew G. Knepley   PetscInt           eOffset    = 0; /* Offset into elemMat[] for element e */
1023*27f02ce8SMatthew G. Knepley   PetscInt           offsetI    = 0; /* Offset into an element vector for fieldI */
1024*27f02ce8SMatthew G. Knepley   PetscInt           offsetJ    = 0; /* Offset into an element vector for fieldJ */
1025*27f02ce8SMatthew G. Knepley   PetscScalar       *g0, *g1, *g2, *g3, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal;
1026*27f02ce8SMatthew G. Knepley   const PetscScalar *constants;
1027*27f02ce8SMatthew G. Knepley   PetscReal         *x;
1028*27f02ce8SMatthew G. Knepley   PetscReal        **B, **D, **BAux = NULL, **DAux = NULL, *BI, *DI, *BJ, *DJ;
1029*27f02ce8SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL, *Nb, *Nc, *NbAux = NULL, *NcAux = NULL;
1030*27f02ce8SMatthew G. Knepley   PetscInt           NbI = 0, NcI = 0, NbJ = 0, NcJ = 0, NcS, NcT;
1031*27f02ce8SMatthew G. Knepley   PetscInt           dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, e;
1032*27f02ce8SMatthew G. Knepley   PetscBool          isCohesiveFieldI, isCohesiveFieldJ, isAffine, auxOnBd;
1033*27f02ce8SMatthew G. Knepley   const PetscReal   *quadPoints, *quadWeights;
1034*27f02ce8SMatthew G. Knepley   PetscInt           qNc, Nq, q, Np, dE;
1035*27f02ce8SMatthew G. Knepley   PetscErrorCode     ierr;
1036*27f02ce8SMatthew G. Knepley 
1037*27f02ce8SMatthew G. Knepley   PetscFunctionBegin;
1038*27f02ce8SMatthew G. Knepley   /* Hybrid discretization is posed directly on faces */
1039*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldI, (PetscObject *) &feI);CHKERRQ(ierr);
1040*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldJ, (PetscObject *) &feJ);CHKERRQ(ierr);
1041*27f02ce8SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(feI, &dim);CHKERRQ(ierr);
1042*27f02ce8SMatthew G. Knepley   ierr = PetscFEGetQuadrature(feI, &quad);CHKERRQ(ierr);
1043*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
1044*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
1045*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetDimensions(ds, &Nb);CHKERRQ(ierr);
1046*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetComponents(ds, &Nc);CHKERRQ(ierr);
1047*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
1048*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
1049*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldI, &offsetI);CHKERRQ(ierr);
1050*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldJ, &offsetJ);CHKERRQ(ierr);
1051*27f02ce8SMatthew G. Knepley   switch(jtype) {
1052*27f02ce8SMatthew G. Knepley   case PETSCFE_JACOBIAN_PRE: ierr = PetscDSGetBdJacobianPreconditioner(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
1053*27f02ce8SMatthew G. Knepley   case PETSCFE_JACOBIAN:     ierr = PetscDSGetBdJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
1054*27f02ce8SMatthew G. Knepley   case PETSCFE_JACOBIAN_DYN: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No dynamic boundary hybrid Jacobians :)");
1055*27f02ce8SMatthew G. Knepley   }
1056*27f02ce8SMatthew G. Knepley   if (!g0_func && !g1_func && !g2_func && !g3_func) PetscFunctionReturn(0);
1057*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
1058*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal);CHKERRQ(ierr);
1059*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, NULL, NULL, &g0, &g1, &g2, &g3);CHKERRQ(ierr);
1060*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetTabulation(ds, &B, &D);CHKERRQ(ierr);
1061*27f02ce8SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
1062*27f02ce8SMatthew G. Knepley   if (dsAux) {
1063*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetSpatialDimension(dsAux, &dimAux);CHKERRQ(ierr);
1064*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
1065*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
1066*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetDimensions(dsAux, &NbAux);CHKERRQ(ierr);
1067*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetComponents(dsAux, &NcAux);CHKERRQ(ierr);
1068*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
1069*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
1070*27f02ce8SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
1071*27f02ce8SMatthew G. Knepley     auxOnBd = dimAux < dim ? PETSC_TRUE : PETSC_FALSE;
1072*27f02ce8SMatthew G. Knepley     if (auxOnBd) {ierr = PetscDSGetTabulation(dsAux, &BAux, &DAux);CHKERRQ(ierr);}
1073*27f02ce8SMatthew G. Knepley     else         {ierr = PetscDSGetFaceTabulation(dsAux, &BAux, &DAux);CHKERRQ(ierr);}
1074*27f02ce8SMatthew G. Knepley   }
1075*27f02ce8SMatthew G. Knepley   isCohesiveFieldI = fieldI == Nf-1 ? PETSC_TRUE : PETSC_FALSE;
1076*27f02ce8SMatthew G. Knepley   isCohesiveFieldJ = fieldJ == Nf-1 ? PETSC_TRUE : PETSC_FALSE;
1077*27f02ce8SMatthew G. Knepley   NbI = Nb[fieldI], NbJ = Nb[fieldJ];
1078*27f02ce8SMatthew G. Knepley   NcI = Nc[fieldI], NcJ = Nc[fieldJ];
1079*27f02ce8SMatthew G. Knepley   NcS = isCohesiveFieldI ? NcI : 2*NcI;
1080*27f02ce8SMatthew G. Knepley   NcT = isCohesiveFieldJ ? NcJ : 2*NcJ;
1081*27f02ce8SMatthew G. Knepley   BI  = B[fieldI],  BJ  = B[fieldJ];
1082*27f02ce8SMatthew G. Knepley   DI  = D[fieldI],  DJ  = D[fieldJ];
1083*27f02ce8SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
1084*27f02ce8SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
1085*27f02ce8SMatthew G. Knepley   Np = fgeom->numPoints;
1086*27f02ce8SMatthew G. Knepley   dE = fgeom->dimEmbed;
1087*27f02ce8SMatthew G. Knepley   isAffine = fgeom->isAffine;
1088*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g0, NcS*NcT);CHKERRQ(ierr);
1089*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g1, NcS*NcT*dE);CHKERRQ(ierr);
1090*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g2, NcS*NcT*dE);CHKERRQ(ierr);
1091*27f02ce8SMatthew G. Knepley   ierr = PetscArrayzero(g3, NcS*NcT*dE*dE);CHKERRQ(ierr);
1092*27f02ce8SMatthew G. Knepley   for (e = 0; e < Ne; ++e) {
1093*27f02ce8SMatthew G. Knepley     PetscFEGeom    fegeom;
1094*27f02ce8SMatthew G. Knepley     const PetscInt face = fgeom->face[e][0];
1095*27f02ce8SMatthew G. Knepley 
1096*27f02ce8SMatthew G. Knepley     fegeom.dim      = fgeom->dim;
1097*27f02ce8SMatthew G. Knepley     fegeom.dimEmbed = fgeom->dimEmbed;
1098*27f02ce8SMatthew G. Knepley     if (isAffine) {
1099*27f02ce8SMatthew G. Knepley       fegeom.v    = x;
1100*27f02ce8SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
1101*27f02ce8SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*dE*dE];
1102*27f02ce8SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*dE*dE];
1103*27f02ce8SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e];
1104*27f02ce8SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*dE];
1105*27f02ce8SMatthew G. Knepley     }
1106*27f02ce8SMatthew G. Knepley     for (q = 0; q < Nq; ++q) {
1107*27f02ce8SMatthew G. Knepley       const PetscReal *BIq = &BI[q*NbI*NcI], *BJq = &BJ[q*NbJ*NcJ];
1108*27f02ce8SMatthew G. Knepley       const PetscReal *DIq = &DI[q*NbI*NcI*dim], *DJq = &DJ[q*NbJ*NcJ*dim];
1109*27f02ce8SMatthew G. Knepley       PetscReal        w;
1110*27f02ce8SMatthew G. Knepley       PetscInt         c;
1111*27f02ce8SMatthew G. Knepley 
1112*27f02ce8SMatthew G. Knepley       if (isAffine) {
1113*27f02ce8SMatthew G. Knepley         /* TODO Is it correct to have 'dim' here, or should it be 'dim-1'? */
1114*27f02ce8SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &fgeom->v[e*dE], fegeom.J, &quadPoints[q*dim], x);
1115*27f02ce8SMatthew G. Knepley       } else {
1116*27f02ce8SMatthew G. Knepley         fegeom.v    = &fegeom.v[(e*Np+q)*dE];
1117*27f02ce8SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
1118*27f02ce8SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
1119*27f02ce8SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
1120*27f02ce8SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
1121*27f02ce8SMatthew G. Knepley       }
1122*27f02ce8SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
1123*27f02ce8SMatthew G. Knepley       if (debug > 1 && q < Np) {
1124*27f02ce8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
1125*27f02ce8SMatthew G. Knepley #if !defined(PETSC_USE_COMPLEX)
1126*27f02ce8SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ);CHKERRQ(ierr);
1127*27f02ce8SMatthew G. Knepley #endif
1128*27f02ce8SMatthew G. Knepley       }
1129*27f02ce8SMatthew G. Knepley       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
1130*27f02ce8SMatthew G. Knepley       if (coefficients) {ierr = PetscFEEvaluateFieldJets_Hybrid_Internal(ds, dim, Nf, Nb, Nc, q, B, D, &fegeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t);CHKERRQ(ierr);}
1131*27f02ce8SMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Hybrid_Internal(dsAux, dimAux, NfAux, NbAux, NcAux, auxOnBd ? q : face*Nq+q, BAux, DAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
1132*27f02ce8SMatthew G. Knepley       if (g0_func) {
1133*27f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g0, NcS*NcT);CHKERRQ(ierr);
1134*27f02ce8SMatthew 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);
1135*27f02ce8SMatthew G. Knepley         for (c = 0; c < NcS*NcT; ++c) g0[c] *= w;
1136*27f02ce8SMatthew G. Knepley       }
1137*27f02ce8SMatthew G. Knepley       if (g1_func) {
1138*27f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g1, NcS*NcT*dE);CHKERRQ(ierr);
1139*27f02ce8SMatthew 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);
1140*27f02ce8SMatthew G. Knepley         for (c = 0; c < NcS*NcT*dE; ++c) g1[c] *= w;
1141*27f02ce8SMatthew G. Knepley       }
1142*27f02ce8SMatthew G. Knepley       if (g2_func) {
1143*27f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g2, NcS*NcT*dE);CHKERRQ(ierr);
1144*27f02ce8SMatthew 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);
1145*27f02ce8SMatthew G. Knepley         for (c = 0; c < NcS*NcT*dE; ++c) g2[c] *= w;
1146*27f02ce8SMatthew G. Knepley       }
1147*27f02ce8SMatthew G. Knepley       if (g3_func) {
1148*27f02ce8SMatthew G. Knepley         ierr = PetscArrayzero(g3, NcS*NcT*dE*dE);CHKERRQ(ierr);
1149*27f02ce8SMatthew 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);
1150*27f02ce8SMatthew G. Knepley         for (c = 0; c < NcS*NcT*dE*dE; ++c) g3[c] *= w;
1151*27f02ce8SMatthew G. Knepley       }
1152*27f02ce8SMatthew G. Knepley 
1153*27f02ce8SMatthew G. Knepley       if (isCohesiveFieldI && isCohesiveFieldJ) {
1154*27f02ce8SMatthew G. Knepley         ierr = PetscFEUpdateElementMat_Internal(feI, feJ, dim, NbI, NcI, BIq, DIq, basisReal, basisDerReal, NbJ, NcJ, BJq, DJq, testReal, testDerReal, &fegeom, g0, g1, g2, g3, eOffset, totDim, offsetI*2, offsetJ*2, elemMat);CHKERRQ(ierr);
1155*27f02ce8SMatthew G. Knepley       } else {
1156*27f02ce8SMatthew G. Knepley         ierr = PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, dim, NbI, NcI, BIq, DIq, basisReal, basisDerReal, NbJ, NcJ, BJq, DJq, testReal, testDerReal, &fegeom, g0, g1, g2, g3, eOffset, totDim, offsetI*2, offsetJ*2, elemMat);CHKERRQ(ierr);
1157*27f02ce8SMatthew G. Knepley       }
1158*27f02ce8SMatthew G. Knepley     }
1159*27f02ce8SMatthew G. Knepley     if (debug > 1) {
1160*27f02ce8SMatthew G. Knepley       PetscInt fc, f, gc, g;
1161*27f02ce8SMatthew G. Knepley 
1162*27f02ce8SMatthew G. Knepley       ierr = PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %d and %d\n", fieldI, fieldJ);CHKERRQ(ierr);
1163*27f02ce8SMatthew G. Knepley       for (fc = 0; fc < NcI; ++fc) {
1164*27f02ce8SMatthew G. Knepley         for (f = 0; f < NbI; ++f) {
1165*27f02ce8SMatthew G. Knepley           const PetscInt i = offsetI + f*NcI+fc;
1166*27f02ce8SMatthew G. Knepley           for (gc = 0; gc < NcJ; ++gc) {
1167*27f02ce8SMatthew G. Knepley             for (g = 0; g < NbJ; ++g) {
1168*27f02ce8SMatthew G. Knepley               const PetscInt j = offsetJ + g*NcJ+gc;
1169*27f02ce8SMatthew 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);
1170*27f02ce8SMatthew G. Knepley             }
1171*27f02ce8SMatthew G. Knepley           }
1172*27f02ce8SMatthew G. Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
1173*27f02ce8SMatthew G. Knepley         }
1174*27f02ce8SMatthew G. Knepley       }
1175*27f02ce8SMatthew G. Knepley     }
1176*27f02ce8SMatthew G. Knepley     cOffset    += totDim;
1177*27f02ce8SMatthew G. Knepley     cOffsetAux += totDimAux;
1178*27f02ce8SMatthew G. Knepley     eOffset    += PetscSqr(totDim);
1179*27f02ce8SMatthew G. Knepley   }
1180*27f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
1181*27f02ce8SMatthew G. Knepley }
1182*27f02ce8SMatthew G. Knepley 
11832b99622eSMatthew G. Knepley static PetscErrorCode PetscFEInitialize_Basic(PetscFE fem)
118420cf1dd8SToby Isaac {
118520cf1dd8SToby Isaac   PetscFunctionBegin;
118620cf1dd8SToby Isaac   fem->ops->setfromoptions          = NULL;
118720cf1dd8SToby Isaac   fem->ops->setup                   = PetscFESetUp_Basic;
118820cf1dd8SToby Isaac   fem->ops->view                    = PetscFEView_Basic;
118920cf1dd8SToby Isaac   fem->ops->destroy                 = PetscFEDestroy_Basic;
119020cf1dd8SToby Isaac   fem->ops->getdimension            = PetscFEGetDimension_Basic;
1191ef0bb6c7SMatthew G. Knepley   fem->ops->createtabulation        = PetscFECreateTabulation_Basic;
119220cf1dd8SToby Isaac   fem->ops->integrate               = PetscFEIntegrate_Basic;
1193afe6d6adSToby Isaac   fem->ops->integratebd             = PetscFEIntegrateBd_Basic;
119420cf1dd8SToby Isaac   fem->ops->integrateresidual       = PetscFEIntegrateResidual_Basic;
119520cf1dd8SToby Isaac   fem->ops->integratebdresidual     = PetscFEIntegrateBdResidual_Basic;
1196*27f02ce8SMatthew G. Knepley   fem->ops->integratehybridresidual = PetscFEIntegrateHybridResidual_Basic;
119720cf1dd8SToby Isaac   fem->ops->integratejacobianaction = NULL/* PetscFEIntegrateJacobianAction_Basic */;
119820cf1dd8SToby Isaac   fem->ops->integratejacobian       = PetscFEIntegrateJacobian_Basic;
119920cf1dd8SToby Isaac   fem->ops->integratebdjacobian     = PetscFEIntegrateBdJacobian_Basic;
1200*27f02ce8SMatthew G. Knepley   fem->ops->integratehybridjacobian = PetscFEIntegrateHybridJacobian_Basic;
120120cf1dd8SToby Isaac   PetscFunctionReturn(0);
120220cf1dd8SToby Isaac }
120320cf1dd8SToby Isaac 
120420cf1dd8SToby Isaac /*MC
120520cf1dd8SToby Isaac   PETSCFEBASIC = "basic" - A PetscFE object that integrates with basic tiling and no vectorization
120620cf1dd8SToby Isaac 
120720cf1dd8SToby Isaac   Level: intermediate
120820cf1dd8SToby Isaac 
120920cf1dd8SToby Isaac .seealso: PetscFEType, PetscFECreate(), PetscFESetType()
121020cf1dd8SToby Isaac M*/
121120cf1dd8SToby Isaac 
121220cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode PetscFECreate_Basic(PetscFE fem)
121320cf1dd8SToby Isaac {
121420cf1dd8SToby Isaac   PetscFE_Basic *b;
121520cf1dd8SToby Isaac   PetscErrorCode ierr;
121620cf1dd8SToby Isaac 
121720cf1dd8SToby Isaac   PetscFunctionBegin;
121820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
121920cf1dd8SToby Isaac   ierr      = PetscNewLog(fem,&b);CHKERRQ(ierr);
122020cf1dd8SToby Isaac   fem->data = b;
122120cf1dd8SToby Isaac 
122220cf1dd8SToby Isaac   ierr = PetscFEInitialize_Basic(fem);CHKERRQ(ierr);
122320cf1dd8SToby Isaac   PetscFunctionReturn(0);
122420cf1dd8SToby Isaac }
1225