xref: /petsc/src/dm/dt/fe/impls/basic/febasic.c (revision b9d4cb8d3f91c0e61c53e13d029f5ea140787a76)
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 {
51*b9d4cb8dSJed 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 */
72*b9d4cb8dSJed Brown       fem->invV[j*pdim+k] = 0.0;
7320cf1dd8SToby Isaac 
7420cf1dd8SToby Isaac       for (q = 0; q < Nq; ++q) {
75*b9d4cb8dSJed 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;
83*b9d4cb8dSJed 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);
85*b9d4cb8dSJed 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 
100*b9d4cb8dSJed Brown /* Tensor contraction on the middle index,
101*b9d4cb8dSJed Brown  *    C[m,n,p] = A[m,k,p] * B[k,n]
102*b9d4cb8dSJed Brown  * where all matrices use C-style ordering.
103*b9d4cb8dSJed Brown  */
104*b9d4cb8dSJed Brown static PetscErrorCode TensorContract_Private(PetscInt m,PetscInt n,PetscInt p,PetscInt k,const PetscReal *A,const PetscReal *B,PetscReal *C) {
105*b9d4cb8dSJed Brown   PetscErrorCode ierr;
106*b9d4cb8dSJed Brown   PetscInt i;
107*b9d4cb8dSJed Brown 
108*b9d4cb8dSJed Brown   PetscFunctionBegin;
109*b9d4cb8dSJed Brown   for (i=0; i<m; i++) {
110*b9d4cb8dSJed Brown     PetscBLASInt n_,p_,k_,lda,ldb,ldc;
111*b9d4cb8dSJed Brown     PetscReal one = 1, zero = 0;
112*b9d4cb8dSJed Brown     /* Taking contiguous submatrices, we wish to comput c[n,p] = a[k,p] * B[k,n]
113*b9d4cb8dSJed Brown      * or, in Fortran ordering, c(p,n) = a(p,k) * B(n,k)
114*b9d4cb8dSJed Brown      */
115*b9d4cb8dSJed Brown     ierr = PetscBLASIntCast(n,&n_);CHKERRQ(ierr);
116*b9d4cb8dSJed Brown     ierr = PetscBLASIntCast(p,&p_);CHKERRQ(ierr);
117*b9d4cb8dSJed Brown     ierr = PetscBLASIntCast(k,&k_);CHKERRQ(ierr);
118*b9d4cb8dSJed Brown     lda = p_;
119*b9d4cb8dSJed Brown     ldb = n_;
120*b9d4cb8dSJed Brown     ldc = p_;
121*b9d4cb8dSJed Brown     PetscStackCallBLAS("BLASgemm",BLASREALgemm_("N","T",&p_,&n_,&k_,&one,A+i*k*p,&lda,B,&ldb,&zero,C+i*n*p,&ldc));
122*b9d4cb8dSJed Brown   }
123*b9d4cb8dSJed Brown   PetscLogFlops(2*m*n*p*k);
124*b9d4cb8dSJed Brown   PetscFunctionReturn(0);
125*b9d4cb8dSJed Brown }
126*b9d4cb8dSJed 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);
149*b9d4cb8dSJed Brown   /* Translate from prime to nodal basis */
15020cf1dd8SToby Isaac   if (B) {
151*b9d4cb8dSJed Brown     /* B[npoints, nodes, Nc] = tmpB[npoints, prime, Nc] * invV[prime, nodes] */
152*b9d4cb8dSJed Brown     ierr = TensorContract_Private(npoints, pdim, Nc, pdim, tmpB, fem->invV, B);CHKERRQ(ierr);
15320cf1dd8SToby Isaac   }
15420cf1dd8SToby Isaac   if (D) {
155*b9d4cb8dSJed Brown     /* D[npoints, nodes, Nc, dim] = tmpD[npoints, prime, Nc, dim] * invV[prime, nodes] */
156*b9d4cb8dSJed Brown     ierr = TensorContract_Private(npoints, pdim, Nc*dim, pdim, tmpD, fem->invV, D);CHKERRQ(ierr);
15720cf1dd8SToby Isaac   }
15820cf1dd8SToby Isaac   if (H) {
159*b9d4cb8dSJed Brown     /* H[npoints, nodes, Nc, dim, dim] = tmpH[npoints, prime, Nc, dim, dim] * invV[prime, nodes] */
160*b9d4cb8dSJed 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 
21620cf1dd8SToby Isaac     if (isAffine) {
2174bee2e38SMatthew G. Knepley       fegeom.v    = x;
2184bee2e38SMatthew G. Knepley       fegeom.xi   = cgeom->xi;
2194bee2e38SMatthew G. Knepley       fegeom.J    = &cgeom->J[e*dE*dE];
2204bee2e38SMatthew G. Knepley       fegeom.invJ = &cgeom->invJ[e*dE*dE];
2214bee2e38SMatthew G. Knepley       fegeom.detJ = &cgeom->detJ[e];
22220cf1dd8SToby Isaac     }
2234bee2e38SMatthew G. Knepley     for (q = 0; q < Nq; ++q) {
2244bee2e38SMatthew G. Knepley       PetscScalar integrand;
2254bee2e38SMatthew G. Knepley       PetscReal   w;
2264bee2e38SMatthew G. Knepley 
2274bee2e38SMatthew G. Knepley       if (isAffine) {
2284bee2e38SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &cgeom->v[e*dE], fegeom.J, &quadPoints[q*dim], x);
2294bee2e38SMatthew G. Knepley       } else {
2304bee2e38SMatthew G. Knepley         fegeom.v    = &cgeom->v[(e*Np+q)*dE];
2314bee2e38SMatthew G. Knepley         fegeom.J    = &cgeom->J[(e*Np+q)*dE*dE];
2324bee2e38SMatthew G. Knepley         fegeom.invJ = &cgeom->invJ[(e*Np+q)*dE*dE];
2334bee2e38SMatthew G. Knepley         fegeom.detJ = &cgeom->detJ[e*Np+q];
2344bee2e38SMatthew G. Knepley       }
2354bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
23620cf1dd8SToby Isaac       if (debug > 1 && q < Np) {
2374bee2e38SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
2387be5e748SToby Isaac #if !defined(PETSC_USE_COMPLEX)
2394bee2e38SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ);CHKERRQ(ierr);
24020cf1dd8SToby Isaac #endif
24120cf1dd8SToby Isaac       }
24220cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
243ef0bb6c7SMatthew G. Knepley       ierr = PetscFEEvaluateFieldJets_Internal(ds, Nf, 0, q, T, &fegeom, &coefficients[cOffset], NULL, u, u_x, NULL);CHKERRQ(ierr);
244ef0bb6c7SMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
2454bee2e38SMatthew 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);
2464bee2e38SMatthew G. Knepley       integrand *= w;
24720cf1dd8SToby Isaac       integral[e*Nf+field] += integrand;
24820cf1dd8SToby Isaac       if (debug > 1) {ierr = PetscPrintf(PETSC_COMM_SELF, "    int: %g %g\n", (double) PetscRealPart(integrand), (double) PetscRealPart(integral[field]));CHKERRQ(ierr);}
24920cf1dd8SToby Isaac     }
25020cf1dd8SToby Isaac     cOffset    += totDim;
25120cf1dd8SToby Isaac     cOffsetAux += totDimAux;
25220cf1dd8SToby Isaac   }
25320cf1dd8SToby Isaac   PetscFunctionReturn(0);
25420cf1dd8SToby Isaac }
25520cf1dd8SToby Isaac 
2562b99622eSMatthew G. Knepley static PetscErrorCode PetscFEIntegrateBd_Basic(PetscDS ds, PetscInt field,
257afe6d6adSToby Isaac                                                PetscBdPointFunc obj_func,
2584bee2e38SMatthew G. Knepley                                                PetscInt Ne, PetscFEGeom *fgeom, const PetscScalar coefficients[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
259afe6d6adSToby Isaac {
260afe6d6adSToby Isaac   const PetscInt     debug = 0;
2614bee2e38SMatthew G. Knepley   PetscFE            fe;
262afe6d6adSToby Isaac   PetscQuadrature    quad;
263ef0bb6c7SMatthew G. Knepley   PetscTabulation   *Tf, *TfAux = NULL;
2644bee2e38SMatthew G. Knepley   PetscScalar       *u, *u_x, *a, *a_x, *basisReal, *basisDerReal;
265afe6d6adSToby Isaac   const PetscScalar *constants;
266afe6d6adSToby Isaac   PetscReal         *x;
267ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
268afe6d6adSToby Isaac   PetscBool          isAffine, auxOnBd;
269afe6d6adSToby Isaac   const PetscReal   *quadPoints, *quadWeights;
270afe6d6adSToby Isaac   PetscInt           qNc, Nq, q, Np, dE;
271afe6d6adSToby Isaac   PetscInt           dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, e;
272afe6d6adSToby Isaac   PetscErrorCode     ierr;
273afe6d6adSToby Isaac 
274afe6d6adSToby Isaac   PetscFunctionBegin;
275afe6d6adSToby Isaac   if (!obj_func) PetscFunctionReturn(0);
2764bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
2774bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(fe, &dim);CHKERRQ(ierr);
2784bee2e38SMatthew G. Knepley   ierr = PetscFEGetFaceQuadrature(fe, &quad);CHKERRQ(ierr);
2794bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
2804bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
2814bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
2824bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
2834bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, NULL, &u_x);CHKERRQ(ierr);
2844bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL);CHKERRQ(ierr);
285ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetFaceTabulation(ds, &Tf);CHKERRQ(ierr);
2864bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
2874bee2e38SMatthew G. Knepley   if (dsAux) {
2884bee2e38SMatthew G. Knepley     ierr = PetscDSGetSpatialDimension(dsAux, &dimAux);CHKERRQ(ierr);
2894bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
2904bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
2914bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
2924bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
2934bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
294afe6d6adSToby Isaac     auxOnBd = dimAux < dim ? PETSC_TRUE : PETSC_FALSE;
295ef0bb6c7SMatthew G. Knepley     if (auxOnBd) {ierr = PetscDSGetTabulation(dsAux, &TfAux);CHKERRQ(ierr);}
296ef0bb6c7SMatthew G. Knepley     else         {ierr = PetscDSGetFaceTabulation(dsAux, &TfAux);CHKERRQ(ierr);}
297afe6d6adSToby Isaac   }
298afe6d6adSToby Isaac   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
299afe6d6adSToby Isaac   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
300afe6d6adSToby Isaac   Np = fgeom->numPoints;
301afe6d6adSToby Isaac   dE = fgeom->dimEmbed;
302afe6d6adSToby Isaac   isAffine = fgeom->isAffine;
303afe6d6adSToby Isaac   for (e = 0; e < Ne; ++e) {
3049f209ee4SMatthew G. Knepley     PetscFEGeom    fegeom, cgeom;
305afe6d6adSToby Isaac     const PetscInt face = fgeom->face[e][0]; /* Local face number in cell */
3064dcf62a8SSatish Balay     fegeom.n = 0;
3074dcf62a8SSatish Balay     fegeom.v = 0;
3084dcf62a8SSatish Balay     fegeom.J = 0;
3094dcf62a8SSatish Balay     fegeom.detJ = 0;
3104bee2e38SMatthew G. Knepley     if (isAffine) {
3114bee2e38SMatthew G. Knepley       fegeom.v    = x;
3124bee2e38SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
3134bee2e38SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*dE*dE];
3149f209ee4SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*dE*dE];
3154bee2e38SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e];
3164bee2e38SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*dE];
3179f209ee4SMatthew G. Knepley 
3189f209ee4SMatthew G. Knepley       cgeom.J     = &fgeom->suppJ[0][e*dE*dE];
3199f209ee4SMatthew G. Knepley       cgeom.invJ  = &fgeom->suppInvJ[0][e*dE*dE];
3209f209ee4SMatthew G. Knepley       cgeom.detJ  = &fgeom->suppDetJ[0][e];
3214bee2e38SMatthew G. Knepley     }
322afe6d6adSToby Isaac     for (q = 0; q < Nq; ++q) {
323afe6d6adSToby Isaac       PetscScalar integrand;
3244bee2e38SMatthew G. Knepley       PetscReal   w;
325afe6d6adSToby Isaac 
326afe6d6adSToby Isaac       if (isAffine) {
3274bee2e38SMatthew G. Knepley         CoordinatesRefToReal(dE, dim-1, fegeom.xi, &fgeom->v[e*dE], fegeom.J, &quadPoints[q*(dim-1)], x);
328afe6d6adSToby Isaac       } else {
3293fe841f2SMatthew G. Knepley         fegeom.v    = &fgeom->v[(e*Np+q)*dE];
3309f209ee4SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
3319f209ee4SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
3324bee2e38SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
3334bee2e38SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
3349f209ee4SMatthew G. Knepley 
3359f209ee4SMatthew G. Knepley         cgeom.J     = &fgeom->suppJ[0][(e*Np+q)*dE*dE];
3369f209ee4SMatthew G. Knepley         cgeom.invJ  = &fgeom->suppInvJ[0][(e*Np+q)*dE*dE];
3379f209ee4SMatthew G. Knepley         cgeom.detJ  = &fgeom->suppDetJ[0][e*Np+q];
338afe6d6adSToby Isaac       }
3394bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
340afe6d6adSToby Isaac       if (debug > 1 && q < Np) {
3414bee2e38SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
342afe6d6adSToby Isaac #ifndef PETSC_USE_COMPLEX
3434bee2e38SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ);CHKERRQ(ierr);
344afe6d6adSToby Isaac #endif
345afe6d6adSToby Isaac       }
346afe6d6adSToby Isaac       if (debug > 1) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
347ef0bb6c7SMatthew G. Knepley       ierr = PetscFEEvaluateFieldJets_Internal(ds, Nf, face, q, Tf, &cgeom, &coefficients[cOffset], NULL, u, u_x, NULL);CHKERRQ(ierr);
348ef0bb6c7SMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, face, q, TfAux, &cgeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
3494bee2e38SMatthew 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);
3504bee2e38SMatthew G. Knepley       integrand *= w;
351afe6d6adSToby Isaac       integral[e*Nf+field] += integrand;
352afe6d6adSToby Isaac       if (debug > 1) {ierr = PetscPrintf(PETSC_COMM_SELF, "    int: %g %g\n", (double) PetscRealPart(integrand), (double) PetscRealPart(integral[e*Nf+field]));CHKERRQ(ierr);}
353afe6d6adSToby Isaac     }
354afe6d6adSToby Isaac     cOffset    += totDim;
355afe6d6adSToby Isaac     cOffsetAux += totDimAux;
356afe6d6adSToby Isaac   }
357afe6d6adSToby Isaac   PetscFunctionReturn(0);
358afe6d6adSToby Isaac }
359afe6d6adSToby Isaac 
3604bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateResidual_Basic(PetscDS ds, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom,
3614bee2e38SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
36220cf1dd8SToby Isaac {
36320cf1dd8SToby Isaac   const PetscInt     debug = 0;
3644bee2e38SMatthew G. Knepley   PetscFE            fe;
36520cf1dd8SToby Isaac   PetscPointFunc     f0_func;
36620cf1dd8SToby Isaac   PetscPointFunc     f1_func;
36720cf1dd8SToby Isaac   PetscQuadrature    quad;
368ef0bb6c7SMatthew G. Knepley   PetscTabulation   *T, *TAux = NULL;
3694bee2e38SMatthew G. Knepley   PetscScalar       *f0, *f1, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal;
37020cf1dd8SToby Isaac   const PetscScalar *constants;
37120cf1dd8SToby Isaac   PetscReal         *x;
372ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
373ef0bb6c7SMatthew G. Knepley   PetscInt           dim, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, fOffset, e;
37420cf1dd8SToby Isaac   PetscBool          isAffine;
37520cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
3764bee2e38SMatthew G. Knepley   PetscInt           qNc, Nq, q, Np, dE;
37720cf1dd8SToby Isaac   PetscErrorCode     ierr;
37820cf1dd8SToby Isaac 
37920cf1dd8SToby Isaac   PetscFunctionBegin;
3804bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
3814bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(fe, &dim);CHKERRQ(ierr);
3824bee2e38SMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr);
3834bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
3844bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
3854bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
3864bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
3874bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, field, &fOffset);CHKERRQ(ierr);
3884bee2e38SMatthew G. Knepley   ierr = PetscDSGetResidual(ds, field, &f0_func, &f1_func);CHKERRQ(ierr);
3894bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
3904bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL);CHKERRQ(ierr);
3914bee2e38SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, &f0, &f1, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
3924bee2e38SMatthew G. Knepley   if (!f0_func && !f1_func) PetscFunctionReturn(0);
393ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetTabulation(ds, &T);CHKERRQ(ierr);
3944bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
3954bee2e38SMatthew G. Knepley   if (dsAux) {
3964bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
3974bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
3984bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
3994bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
4004bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
401ef0bb6c7SMatthew G. Knepley     ierr = PetscDSGetTabulation(dsAux, &TAux);CHKERRQ(ierr);
40220cf1dd8SToby Isaac   }
40320cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
4044bee2e38SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
40520cf1dd8SToby Isaac   Np = cgeom->numPoints;
40620cf1dd8SToby Isaac   dE = cgeom->dimEmbed;
40720cf1dd8SToby Isaac   isAffine = cgeom->isAffine;
40820cf1dd8SToby Isaac   for (e = 0; e < Ne; ++e) {
4094bee2e38SMatthew G. Knepley     PetscFEGeom fegeom;
41020cf1dd8SToby Isaac 
4114bee2e38SMatthew G. Knepley     if (isAffine) {
4124bee2e38SMatthew G. Knepley       fegeom.v    = x;
4134bee2e38SMatthew G. Knepley       fegeom.xi   = cgeom->xi;
4144bee2e38SMatthew G. Knepley       fegeom.J    = &cgeom->J[e*dE*dE];
4154bee2e38SMatthew G. Knepley       fegeom.invJ = &cgeom->invJ[e*dE*dE];
4164bee2e38SMatthew G. Knepley       fegeom.detJ = &cgeom->detJ[e];
4174bee2e38SMatthew G. Knepley     }
418ef0bb6c7SMatthew G. Knepley     ierr = PetscArrayzero(f0, Nq*T[field]->Nc);CHKERRQ(ierr);
419ef0bb6c7SMatthew G. Knepley     ierr = PetscArrayzero(f1, Nq*T[field]->Nc*dim);CHKERRQ(ierr);
42020cf1dd8SToby Isaac     for (q = 0; q < Nq; ++q) {
4214bee2e38SMatthew G. Knepley       PetscReal w;
4224bee2e38SMatthew G. Knepley       PetscInt  c, d;
42320cf1dd8SToby Isaac 
42420cf1dd8SToby Isaac       if (isAffine) {
4254bee2e38SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &cgeom->v[e*dE], fegeom.J, &quadPoints[q*dim], x);
42620cf1dd8SToby Isaac       } else {
4274bee2e38SMatthew G. Knepley         fegeom.v    = &cgeom->v[(e*Np+q)*dE];
4284bee2e38SMatthew G. Knepley         fegeom.J    = &cgeom->J[(e*Np+q)*dE*dE];
4294bee2e38SMatthew G. Knepley         fegeom.invJ = &cgeom->invJ[(e*Np+q)*dE*dE];
4304bee2e38SMatthew G. Knepley         fegeom.detJ = &cgeom->detJ[e*Np+q];
43120cf1dd8SToby Isaac       }
4324bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
43320cf1dd8SToby Isaac       if (debug > 1 && q < Np) {
4344bee2e38SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
4357be5e748SToby Isaac #if !defined(PETSC_USE_COMPLEX)
4364bee2e38SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ);CHKERRQ(ierr);
43720cf1dd8SToby Isaac #endif
43820cf1dd8SToby Isaac       }
43920cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
440ef0bb6c7SMatthew G. Knepley       ierr = PetscFEEvaluateFieldJets_Internal(ds, Nf, 0, q, T, &fegeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t);CHKERRQ(ierr);
441ef0bb6c7SMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
4424bee2e38SMatthew G. Knepley       if (f0_func) {
443ef0bb6c7SMatthew 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]);
444ef0bb6c7SMatthew G. Knepley         for (c = 0; c < T[field]->Nc; ++c) f0[q*T[field]->Nc+c] *= w;
4454bee2e38SMatthew G. Knepley       }
44620cf1dd8SToby Isaac       if (f1_func) {
447ef0bb6c7SMatthew 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]);
448ef0bb6c7SMatthew 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;
44920cf1dd8SToby Isaac       }
45020cf1dd8SToby Isaac     }
451ef0bb6c7SMatthew G. Knepley     ierr = PetscFEUpdateElementVec_Internal(fe, T[field], 0, basisReal, basisDerReal, &fegeom, f0, f1, &elemVec[cOffset+fOffset]);CHKERRQ(ierr);
45220cf1dd8SToby Isaac     cOffset    += totDim;
45320cf1dd8SToby Isaac     cOffsetAux += totDimAux;
45420cf1dd8SToby Isaac   }
45520cf1dd8SToby Isaac   PetscFunctionReturn(0);
45620cf1dd8SToby Isaac }
45720cf1dd8SToby Isaac 
4584bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBdResidual_Basic(PetscDS ds, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom,
4594bee2e38SMatthew G. Knepley                                                 const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
46020cf1dd8SToby Isaac {
46120cf1dd8SToby Isaac   const PetscInt     debug = 0;
4624bee2e38SMatthew G. Knepley   PetscFE            fe;
46320cf1dd8SToby Isaac   PetscBdPointFunc   f0_func;
46420cf1dd8SToby Isaac   PetscBdPointFunc   f1_func;
46520cf1dd8SToby Isaac   PetscQuadrature    quad;
466ef0bb6c7SMatthew G. Knepley   PetscTabulation   *Tf, *TfAux = NULL;
4674bee2e38SMatthew G. Knepley   PetscScalar       *f0, *f1, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal;
46820cf1dd8SToby Isaac   const PetscScalar *constants;
46920cf1dd8SToby Isaac   PetscReal         *x;
470ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
471ef0bb6c7SMatthew G. Knepley   PetscInt           dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, fOffset, e, NcI;
472b07bd890SMatthew G. Knepley   PetscBool          isAffine, auxOnBd = PETSC_FALSE;
47320cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
47420cf1dd8SToby Isaac   PetscInt           qNc, Nq, q, Np, dE;
47520cf1dd8SToby Isaac   PetscErrorCode     ierr;
47620cf1dd8SToby Isaac 
47720cf1dd8SToby Isaac   PetscFunctionBegin;
4784bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr);
4794bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(fe, &dim);CHKERRQ(ierr);
4804bee2e38SMatthew G. Knepley   ierr = PetscFEGetFaceQuadrature(fe, &quad);CHKERRQ(ierr);
4814bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
4824bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
4834bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
4844bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
4854bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, field, &fOffset);CHKERRQ(ierr);
4864bee2e38SMatthew G. Knepley   ierr = PetscDSGetBdResidual(ds, field, &f0_func, &f1_func);CHKERRQ(ierr);
48720cf1dd8SToby Isaac   if (!f0_func && !f1_func) PetscFunctionReturn(0);
4884bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
4894bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL);CHKERRQ(ierr);
4904bee2e38SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, &f0, &f1, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
491ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetFaceTabulation(ds, &Tf);CHKERRQ(ierr);
4924bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
4934bee2e38SMatthew G. Knepley   if (dsAux) {
4944bee2e38SMatthew G. Knepley     ierr = PetscDSGetSpatialDimension(dsAux, &dimAux);CHKERRQ(ierr);
4954bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
4964bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
4974bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
4984bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
4994bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
5007be5e748SToby Isaac     auxOnBd = dimAux < dim ? PETSC_TRUE : PETSC_FALSE;
501ef0bb6c7SMatthew G. Knepley     if (auxOnBd) {ierr = PetscDSGetTabulation(dsAux, &TfAux);CHKERRQ(ierr);}
502ef0bb6c7SMatthew G. Knepley     else         {ierr = PetscDSGetFaceTabulation(dsAux, &TfAux);CHKERRQ(ierr);}
50320cf1dd8SToby Isaac   }
504ef0bb6c7SMatthew G. Knepley   NcI = Tf[field]->Nc;
50520cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
506afe6d6adSToby Isaac   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
50720cf1dd8SToby Isaac   Np = fgeom->numPoints;
50820cf1dd8SToby Isaac   dE = fgeom->dimEmbed;
50920cf1dd8SToby Isaac   isAffine = fgeom->isAffine;
51020cf1dd8SToby Isaac   for (e = 0; e < Ne; ++e) {
5119f209ee4SMatthew G. Knepley     PetscFEGeom    fegeom, cgeom;
51220cf1dd8SToby Isaac     const PetscInt face = fgeom->face[e][0];
5134dcf62a8SSatish Balay     fegeom.n = 0;
5144dcf62a8SSatish Balay     fegeom.v = 0;
5154dcf62a8SSatish Balay     fegeom.J = 0;
5164dcf62a8SSatish Balay     fegeom.detJ = 0;
5174bee2e38SMatthew G. Knepley     if (isAffine) {
5184bee2e38SMatthew G. Knepley       fegeom.v    = x;
5194bee2e38SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
5204bee2e38SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*dE*dE];
5219f209ee4SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*dE*dE];
5224bee2e38SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e];
5234bee2e38SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*dE];
5249f209ee4SMatthew G. Knepley 
5259f209ee4SMatthew G. Knepley       cgeom.J     = &fgeom->suppJ[0][e*dE*dE];
5269f209ee4SMatthew G. Knepley       cgeom.invJ  = &fgeom->suppInvJ[0][e*dE*dE];
5279f209ee4SMatthew G. Knepley       cgeom.detJ  = &fgeom->suppDetJ[0][e];
5284bee2e38SMatthew G. Knepley     }
529580bdb30SBarry Smith     ierr = PetscArrayzero(f0, Nq*NcI);CHKERRQ(ierr);
530580bdb30SBarry Smith     ierr = PetscArrayzero(f1, Nq*NcI*dim);CHKERRQ(ierr);
53120cf1dd8SToby Isaac     for (q = 0; q < Nq; ++q) {
5324bee2e38SMatthew G. Knepley       PetscReal w;
5334bee2e38SMatthew G. Knepley       PetscInt  c, d;
5344bee2e38SMatthew G. Knepley 
53520cf1dd8SToby Isaac       if (isAffine) {
5364bee2e38SMatthew G. Knepley         CoordinatesRefToReal(dE, dim-1, fegeom.xi, &fgeom->v[e*dE], fegeom.J, &quadPoints[q*(dim-1)], x);
53720cf1dd8SToby Isaac       } else {
5383fe841f2SMatthew G. Knepley         fegeom.v    = &fgeom->v[(e*Np+q)*dE];
5399f209ee4SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
5409f209ee4SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
5414bee2e38SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
5424bee2e38SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
5439f209ee4SMatthew G. Knepley 
5449f209ee4SMatthew G. Knepley         cgeom.J     = &fgeom->suppJ[0][(e*Np+q)*dE*dE];
5459f209ee4SMatthew G. Knepley         cgeom.invJ  = &fgeom->suppInvJ[0][(e*Np+q)*dE*dE];
5469f209ee4SMatthew G. Knepley         cgeom.detJ  = &fgeom->suppDetJ[0][e*Np+q];
54720cf1dd8SToby Isaac       }
5484bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
54920cf1dd8SToby Isaac       if (debug > 1 && q < Np) {
5504bee2e38SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "  detJ: %g\n", fegeom.detJ[0]);CHKERRQ(ierr);
5517be5e748SToby Isaac #if !defined(PETSC_USE_COMPLEX)
5524bee2e38SMatthew G. Knepley         ierr = DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ);CHKERRQ(ierr);
55320cf1dd8SToby Isaac #endif
55420cf1dd8SToby Isaac       }
55520cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
556ef0bb6c7SMatthew G. Knepley       ierr = PetscFEEvaluateFieldJets_Internal(ds, Nf, face, q, Tf, &cgeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t);CHKERRQ(ierr);
557ef0bb6c7SMatthew G. Knepley       if (dsAux) {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, auxOnBd ? 0 : face, q, TfAux, &cgeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
5584bee2e38SMatthew G. Knepley       if (f0_func) {
5594bee2e38SMatthew 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]);
5604bee2e38SMatthew G. Knepley         for (c = 0; c < NcI; ++c) f0[q*NcI+c] *= w;
5614bee2e38SMatthew G. Knepley       }
56220cf1dd8SToby Isaac       if (f1_func) {
5634bee2e38SMatthew 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]);
5644bee2e38SMatthew G. Knepley         for (c = 0; c < NcI; ++c) for (d = 0; d < dim; ++d) f1[(q*NcI+c)*dim+d] *= w;
56520cf1dd8SToby Isaac       }
56620cf1dd8SToby Isaac     }
567ef0bb6c7SMatthew G. Knepley     ierr = PetscFEUpdateElementVec_Internal(fe, Tf[field], face, basisReal, basisDerReal, &cgeom, f0, f1, &elemVec[cOffset+fOffset]);CHKERRQ(ierr);
56820cf1dd8SToby Isaac     cOffset    += totDim;
56920cf1dd8SToby Isaac     cOffsetAux += totDimAux;
57020cf1dd8SToby Isaac   }
57120cf1dd8SToby Isaac   PetscFunctionReturn(0);
57220cf1dd8SToby Isaac }
57320cf1dd8SToby Isaac 
5744bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateJacobian_Basic(PetscDS ds, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *cgeom,
5754bee2e38SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
57620cf1dd8SToby Isaac {
57720cf1dd8SToby Isaac   const PetscInt     debug      = 0;
5784bee2e38SMatthew G. Knepley   PetscFE            feI, feJ;
5794bee2e38SMatthew G. Knepley   PetscPointJac      g0_func, g1_func, g2_func, g3_func;
58020cf1dd8SToby Isaac   PetscInt           cOffset    = 0; /* Offset into coefficients[] for element e */
58120cf1dd8SToby Isaac   PetscInt           cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */
58220cf1dd8SToby Isaac   PetscInt           eOffset    = 0; /* Offset into elemMat[] for element e */
58320cf1dd8SToby Isaac   PetscInt           offsetI    = 0; /* Offset into an element vector for fieldI */
58420cf1dd8SToby Isaac   PetscInt           offsetJ    = 0; /* Offset into an element vector for fieldJ */
58520cf1dd8SToby Isaac   PetscQuadrature    quad;
586ef0bb6c7SMatthew G. Knepley   PetscTabulation   *T, *TAux = NULL;
5874bee2e38SMatthew G. Knepley   PetscScalar       *g0, *g1, *g2, *g3, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal;
58820cf1dd8SToby Isaac   const PetscScalar *constants;
58920cf1dd8SToby Isaac   PetscReal         *x;
590ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
591ef0bb6c7SMatthew G. Knepley   PetscInt           NcI = 0, NcJ = 0;
59220cf1dd8SToby Isaac   PetscInt           dim, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, e;
59320cf1dd8SToby Isaac   PetscInt           dE, Np;
59420cf1dd8SToby Isaac   PetscBool          isAffine;
59520cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
59620cf1dd8SToby Isaac   PetscInt           qNc, Nq, q;
59720cf1dd8SToby Isaac   PetscErrorCode     ierr;
59820cf1dd8SToby Isaac 
59920cf1dd8SToby Isaac   PetscFunctionBegin;
6004bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldI, (PetscObject *) &feI);CHKERRQ(ierr);
6014bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldJ, (PetscObject *) &feJ);CHKERRQ(ierr);
6024bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(feI, &dim);CHKERRQ(ierr);
6034bee2e38SMatthew G. Knepley   ierr = PetscFEGetQuadrature(feI, &quad);CHKERRQ(ierr);
6044bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
6054bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
6064bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
6074bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
60820cf1dd8SToby Isaac   switch(jtype) {
6094bee2e38SMatthew G. Knepley   case PETSCFE_JACOBIAN_DYN: ierr = PetscDSGetDynamicJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
6104bee2e38SMatthew G. Knepley   case PETSCFE_JACOBIAN_PRE: ierr = PetscDSGetJacobianPreconditioner(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
6114bee2e38SMatthew G. Knepley   case PETSCFE_JACOBIAN:     ierr = PetscDSGetJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);break;
61220cf1dd8SToby Isaac   }
61320cf1dd8SToby Isaac   if (!g0_func && !g1_func && !g2_func && !g3_func) PetscFunctionReturn(0);
6144bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
6154bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal);CHKERRQ(ierr);
6164bee2e38SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, NULL, NULL, &g0, &g1, &g2, &g3);CHKERRQ(ierr);
617ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetTabulation(ds, &T);CHKERRQ(ierr);
6184bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldI, &offsetI);CHKERRQ(ierr);
6194bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldJ, &offsetJ);CHKERRQ(ierr);
6204bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
6214bee2e38SMatthew G. Knepley   if (dsAux) {
6224bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
6234bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
6244bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
6254bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
6264bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
627ef0bb6c7SMatthew G. Knepley     ierr = PetscDSGetTabulation(dsAux, &TAux);CHKERRQ(ierr);
62820cf1dd8SToby Isaac   }
629ef0bb6c7SMatthew G. Knepley   NcI = T[fieldI]->Nc, NcJ = T[fieldJ]->Nc;
63020cf1dd8SToby Isaac   /* Initialize here in case the function is not defined */
631580bdb30SBarry Smith   ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
632580bdb30SBarry Smith   ierr = PetscArrayzero(g1, NcI*NcJ*dim);CHKERRQ(ierr);
633580bdb30SBarry Smith   ierr = PetscArrayzero(g2, NcI*NcJ*dim);CHKERRQ(ierr);
634580bdb30SBarry Smith   ierr = PetscArrayzero(g3, NcI*NcJ*dim*dim);CHKERRQ(ierr);
63520cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
63620cf1dd8SToby Isaac   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
6374bee2e38SMatthew G. Knepley   Np = cgeom->numPoints;
6384bee2e38SMatthew G. Knepley   dE = cgeom->dimEmbed;
6394bee2e38SMatthew G. Knepley   isAffine = cgeom->isAffine;
6404bee2e38SMatthew G. Knepley   for (e = 0; e < Ne; ++e) {
6414bee2e38SMatthew G. Knepley     PetscFEGeom fegeom;
6424bee2e38SMatthew G. Knepley 
6434bee2e38SMatthew G. Knepley     if (isAffine) {
6444bee2e38SMatthew G. Knepley       fegeom.v    = x;
6454bee2e38SMatthew G. Knepley       fegeom.xi   = cgeom->xi;
6464bee2e38SMatthew G. Knepley       fegeom.J    = &cgeom->J[e*dE*dE];
6474bee2e38SMatthew G. Knepley       fegeom.invJ = &cgeom->invJ[e*dE*dE];
6484bee2e38SMatthew G. Knepley       fegeom.detJ = &cgeom->detJ[e];
6494bee2e38SMatthew G. Knepley     }
65020cf1dd8SToby Isaac     for (q = 0; q < Nq; ++q) {
65120cf1dd8SToby Isaac       PetscReal w;
6524bee2e38SMatthew G. Knepley       PetscInt  c;
65320cf1dd8SToby Isaac 
65420cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
65520cf1dd8SToby Isaac       if (isAffine) {
6564bee2e38SMatthew G. Knepley         CoordinatesRefToReal(dE, dim, fegeom.xi, &cgeom->v[e*dE], fegeom.J, &quadPoints[q*dim], x);
65720cf1dd8SToby Isaac       } else {
6584bee2e38SMatthew G. Knepley         fegeom.v    = &cgeom->v[(e*Np+q)*dE];
6594bee2e38SMatthew G. Knepley         fegeom.J    = &cgeom->J[(e*Np+q)*dE*dE];
6604bee2e38SMatthew G. Knepley         fegeom.invJ = &cgeom->invJ[(e*Np+q)*dE*dE];
6614bee2e38SMatthew G. Knepley         fegeom.detJ = &cgeom->detJ[e*Np+q];
66220cf1dd8SToby Isaac       }
6634bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
664ef0bb6c7SMatthew 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);}
665ef0bb6c7SMatthew G. Knepley       if (dsAux)        {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
66620cf1dd8SToby Isaac       if (g0_func) {
667580bdb30SBarry Smith         ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
6684bee2e38SMatthew 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);
66920cf1dd8SToby Isaac         for (c = 0; c < NcI*NcJ; ++c) g0[c] *= w;
67020cf1dd8SToby Isaac       }
67120cf1dd8SToby Isaac       if (g1_func) {
672580bdb30SBarry Smith         ierr = PetscArrayzero(g1, NcI*NcJ*dim);CHKERRQ(ierr);
6734bee2e38SMatthew 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);
6744bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g1[c] *= w;
67520cf1dd8SToby Isaac       }
67620cf1dd8SToby Isaac       if (g2_func) {
677580bdb30SBarry Smith         ierr = PetscArrayzero(g2, NcI*NcJ*dim);CHKERRQ(ierr);
6784bee2e38SMatthew 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);
6794bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g2[c] *= w;
68020cf1dd8SToby Isaac       }
68120cf1dd8SToby Isaac       if (g3_func) {
682580bdb30SBarry Smith         ierr = PetscArrayzero(g3, NcI*NcJ*dim*dim);CHKERRQ(ierr);
6834bee2e38SMatthew 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);
6844bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim*dim; ++c) g3[c] *= w;
68520cf1dd8SToby Isaac       }
68620cf1dd8SToby Isaac 
687ef0bb6c7SMatthew 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);
68820cf1dd8SToby Isaac     }
68920cf1dd8SToby Isaac     if (debug > 1) {
69020cf1dd8SToby Isaac       PetscInt fc, f, gc, g;
69120cf1dd8SToby Isaac 
69220cf1dd8SToby Isaac       ierr = PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %d and %d\n", fieldI, fieldJ);CHKERRQ(ierr);
693ef0bb6c7SMatthew G. Knepley       for (fc = 0; fc < T[fieldI]->Nc; ++fc) {
694ef0bb6c7SMatthew G. Knepley         for (f = 0; f < T[fieldI]->Nb; ++f) {
695ef0bb6c7SMatthew G. Knepley           const PetscInt i = offsetI + f*T[fieldI]->Nc+fc;
696ef0bb6c7SMatthew G. Knepley           for (gc = 0; gc < T[fieldJ]->Nc; ++gc) {
697ef0bb6c7SMatthew G. Knepley             for (g = 0; g < T[fieldJ]->Nb; ++g) {
698ef0bb6c7SMatthew G. Knepley               const PetscInt j = offsetJ + g*T[fieldJ]->Nc+gc;
69920cf1dd8SToby 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);
70020cf1dd8SToby Isaac             }
70120cf1dd8SToby Isaac           }
70220cf1dd8SToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
70320cf1dd8SToby Isaac         }
70420cf1dd8SToby Isaac       }
70520cf1dd8SToby Isaac     }
70620cf1dd8SToby Isaac     cOffset    += totDim;
70720cf1dd8SToby Isaac     cOffsetAux += totDimAux;
70820cf1dd8SToby Isaac     eOffset    += PetscSqr(totDim);
70920cf1dd8SToby Isaac   }
71020cf1dd8SToby Isaac   PetscFunctionReturn(0);
71120cf1dd8SToby Isaac }
71220cf1dd8SToby Isaac 
7132b99622eSMatthew G. Knepley static PetscErrorCode PetscFEIntegrateBdJacobian_Basic(PetscDS ds, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
7144bee2e38SMatthew G. Knepley                                                        const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
71520cf1dd8SToby Isaac {
71620cf1dd8SToby Isaac   const PetscInt     debug      = 0;
7174bee2e38SMatthew G. Knepley   PetscFE            feI, feJ;
7184bee2e38SMatthew G. Knepley   PetscBdPointJac    g0_func, g1_func, g2_func, g3_func;
71920cf1dd8SToby Isaac   PetscInt           cOffset    = 0; /* Offset into coefficients[] for element e */
72020cf1dd8SToby Isaac   PetscInt           cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */
72120cf1dd8SToby Isaac   PetscInt           eOffset    = 0; /* Offset into elemMat[] for element e */
72220cf1dd8SToby Isaac   PetscInt           offsetI    = 0; /* Offset into an element vector for fieldI */
72320cf1dd8SToby Isaac   PetscInt           offsetJ    = 0; /* Offset into an element vector for fieldJ */
72420cf1dd8SToby Isaac   PetscQuadrature    quad;
725ef0bb6c7SMatthew G. Knepley   PetscTabulation   *T, *TAux = NULL;
7264bee2e38SMatthew G. Knepley   PetscScalar       *g0, *g1, *g2, *g3, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal;
72720cf1dd8SToby Isaac   const PetscScalar *constants;
72820cf1dd8SToby Isaac   PetscReal         *x;
729ef0bb6c7SMatthew G. Knepley   PetscInt          *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL;
730ef0bb6c7SMatthew G. Knepley   PetscInt           NcI = 0, NcJ = 0;
73120cf1dd8SToby Isaac   PetscInt           dim, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, e;
73220cf1dd8SToby Isaac   PetscBool          isAffine;
73320cf1dd8SToby Isaac   const PetscReal   *quadPoints, *quadWeights;
73420cf1dd8SToby Isaac   PetscInt           qNc, Nq, q, Np, dE;
73520cf1dd8SToby Isaac   PetscErrorCode     ierr;
73620cf1dd8SToby Isaac 
73720cf1dd8SToby Isaac   PetscFunctionBegin;
7384bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldI, (PetscObject *) &feI);CHKERRQ(ierr);
7394bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, fieldJ, (PetscObject *) &feJ);CHKERRQ(ierr);
7404bee2e38SMatthew G. Knepley   ierr = PetscFEGetSpatialDimension(feI, &dim);CHKERRQ(ierr);
7414bee2e38SMatthew G. Knepley   ierr = PetscFEGetFaceQuadrature(feI, &quad);CHKERRQ(ierr);
7424bee2e38SMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
7434bee2e38SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr);
7444bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentOffsets(ds, &uOff);CHKERRQ(ierr);
7454bee2e38SMatthew G. Knepley   ierr = PetscDSGetComponentDerivativeOffsets(ds, &uOff_x);CHKERRQ(ierr);
7464bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldI, &offsetI);CHKERRQ(ierr);
7474bee2e38SMatthew G. Knepley   ierr = PetscDSGetFieldOffset(ds, fieldJ, &offsetJ);CHKERRQ(ierr);
7484bee2e38SMatthew G. Knepley   ierr = PetscDSGetBdJacobian(ds, fieldI, fieldJ, &g0_func, &g1_func, &g2_func, &g3_func);CHKERRQ(ierr);
74931f073d7SMatthew G. Knepley   if (!g0_func && !g1_func && !g2_func && !g3_func) PetscFunctionReturn(0);
7504bee2e38SMatthew G. Knepley   ierr = PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x);CHKERRQ(ierr);
7514bee2e38SMatthew G. Knepley   ierr = PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal);CHKERRQ(ierr);
7524bee2e38SMatthew G. Knepley   ierr = PetscDSGetWeakFormArrays(ds, NULL, NULL, &g0, &g1, &g2, &g3);CHKERRQ(ierr);
753ef0bb6c7SMatthew G. Knepley   ierr = PetscDSGetFaceTabulation(ds, &T);CHKERRQ(ierr);
7544bee2e38SMatthew G. Knepley   ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr);
7554bee2e38SMatthew G. Knepley   if (dsAux) {
7564bee2e38SMatthew G. Knepley     ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr);
7574bee2e38SMatthew G. Knepley     ierr = PetscDSGetTotalDimension(dsAux, &totDimAux);CHKERRQ(ierr);
7584bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentOffsets(dsAux, &aOff);CHKERRQ(ierr);
7594bee2e38SMatthew G. Knepley     ierr = PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x);CHKERRQ(ierr);
7604bee2e38SMatthew G. Knepley     ierr = PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x);CHKERRQ(ierr);
761ef0bb6c7SMatthew G. Knepley     ierr = PetscDSGetFaceTabulation(dsAux, &TAux);CHKERRQ(ierr);
76220cf1dd8SToby Isaac   }
763ef0bb6c7SMatthew G. Knepley   NcI = T[fieldI]->Nc, NcJ = T[fieldJ]->Nc;
76420cf1dd8SToby Isaac   /* Initialize here in case the function is not defined */
765580bdb30SBarry Smith   ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
766580bdb30SBarry Smith   ierr = PetscArrayzero(g1, NcI*NcJ*dim);CHKERRQ(ierr);
767580bdb30SBarry Smith   ierr = PetscArrayzero(g2, NcI*NcJ*dim);CHKERRQ(ierr);
768580bdb30SBarry Smith   ierr = PetscArrayzero(g3, NcI*NcJ*dim*dim);CHKERRQ(ierr);
76920cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr);
7704bee2e38SMatthew G. Knepley   if (qNc != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %D components\n", qNc);
77120cf1dd8SToby Isaac   Np = fgeom->numPoints;
77220cf1dd8SToby Isaac   dE = fgeom->dimEmbed;
77320cf1dd8SToby Isaac   isAffine = fgeom->isAffine;
77431f073d7SMatthew G. Knepley   ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
77531f073d7SMatthew G. Knepley   ierr = PetscArrayzero(g1, NcI*NcJ*dim);CHKERRQ(ierr);
77631f073d7SMatthew G. Knepley   ierr = PetscArrayzero(g2, NcI*NcJ*dim);CHKERRQ(ierr);
77731f073d7SMatthew G. Knepley   ierr = PetscArrayzero(g3, NcI*NcJ*dim*dim);CHKERRQ(ierr);
77820cf1dd8SToby Isaac   for (e = 0; e < Ne; ++e) {
7799f209ee4SMatthew G. Knepley     PetscFEGeom    fegeom, cgeom;
78020cf1dd8SToby Isaac     const PetscInt face = fgeom->face[e][0];
7814dcf62a8SSatish Balay     fegeom.n = 0;
7824dcf62a8SSatish Balay     fegeom.v = 0;
7834dcf62a8SSatish Balay     fegeom.J = 0;
7844dcf62a8SSatish Balay     fegeom.detJ = 0;
7854bee2e38SMatthew G. Knepley     if (isAffine) {
7864bee2e38SMatthew G. Knepley       fegeom.v    = x;
7874bee2e38SMatthew G. Knepley       fegeom.xi   = fgeom->xi;
7884bee2e38SMatthew G. Knepley       fegeom.J    = &fgeom->J[e*dE*dE];
7899f209ee4SMatthew G. Knepley       fegeom.invJ = &fgeom->invJ[e*dE*dE];
7904bee2e38SMatthew G. Knepley       fegeom.detJ = &fgeom->detJ[e];
7914bee2e38SMatthew G. Knepley       fegeom.n    = &fgeom->n[e*dE];
7929f209ee4SMatthew G. Knepley 
7939f209ee4SMatthew G. Knepley       cgeom.J     = &fgeom->suppJ[0][e*dE*dE];
7949f209ee4SMatthew G. Knepley       cgeom.invJ  = &fgeom->suppInvJ[0][e*dE*dE];
7959f209ee4SMatthew G. Knepley       cgeom.detJ  = &fgeom->suppDetJ[0][e];
7964bee2e38SMatthew G. Knepley     }
79720cf1dd8SToby Isaac     for (q = 0; q < Nq; ++q) {
79820cf1dd8SToby Isaac       PetscReal w;
7994bee2e38SMatthew G. Knepley       PetscInt  c;
80020cf1dd8SToby Isaac 
80120cf1dd8SToby Isaac       if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  quad point %d\n", q);CHKERRQ(ierr);}
80220cf1dd8SToby Isaac       if (isAffine) {
8034bee2e38SMatthew G. Knepley         CoordinatesRefToReal(dE, dim-1, fegeom.xi, &fgeom->v[e*dE], fegeom.J, &quadPoints[q*(dim-1)], x);
80420cf1dd8SToby Isaac       } else {
8053fe841f2SMatthew G. Knepley         fegeom.v    = &fgeom->v[(e*Np+q)*dE];
8069f209ee4SMatthew G. Knepley         fegeom.J    = &fgeom->J[(e*Np+q)*dE*dE];
8079f209ee4SMatthew G. Knepley         fegeom.invJ = &fgeom->invJ[(e*Np+q)*dE*dE];
8084bee2e38SMatthew G. Knepley         fegeom.detJ = &fgeom->detJ[e*Np+q];
8094bee2e38SMatthew G. Knepley         fegeom.n    = &fgeom->n[(e*Np+q)*dE];
8109f209ee4SMatthew G. Knepley 
8119f209ee4SMatthew G. Knepley         cgeom.J     = &fgeom->suppJ[0][(e*Np+q)*dE*dE];
8129f209ee4SMatthew G. Knepley         cgeom.invJ  = &fgeom->suppInvJ[0][(e*Np+q)*dE*dE];
8139f209ee4SMatthew G. Knepley         cgeom.detJ  = &fgeom->suppDetJ[0][e*Np+q];
81420cf1dd8SToby Isaac       }
8154bee2e38SMatthew G. Knepley       w = fegeom.detJ[0]*quadWeights[q];
816ef0bb6c7SMatthew 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);}
817ef0bb6c7SMatthew G. Knepley       if (dsAux)        {ierr = PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, face, q, TAux, &cgeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL);CHKERRQ(ierr);}
81820cf1dd8SToby Isaac       if (g0_func) {
819580bdb30SBarry Smith         ierr = PetscArrayzero(g0, NcI*NcJ);CHKERRQ(ierr);
8204bee2e38SMatthew 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);
82120cf1dd8SToby Isaac         for (c = 0; c < NcI*NcJ; ++c) g0[c] *= w;
82220cf1dd8SToby Isaac       }
82320cf1dd8SToby Isaac       if (g1_func) {
824580bdb30SBarry Smith         ierr = PetscArrayzero(g1, NcI*NcJ*dim);CHKERRQ(ierr);
8254bee2e38SMatthew 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);
8264bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g1[c] *= w;
82720cf1dd8SToby Isaac       }
82820cf1dd8SToby Isaac       if (g2_func) {
829580bdb30SBarry Smith         ierr = PetscArrayzero(g2, NcI*NcJ*dim);CHKERRQ(ierr);
8304bee2e38SMatthew 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);
8314bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim; ++c) g2[c] *= w;
83220cf1dd8SToby Isaac       }
83320cf1dd8SToby Isaac       if (g3_func) {
834580bdb30SBarry Smith         ierr = PetscArrayzero(g3, NcI*NcJ*dim*dim);CHKERRQ(ierr);
8354bee2e38SMatthew 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);
8364bee2e38SMatthew G. Knepley         for (c = 0; c < NcI*NcJ*dim*dim; ++c) g3[c] *= w;
83720cf1dd8SToby Isaac       }
83820cf1dd8SToby Isaac 
839ef0bb6c7SMatthew 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);
84020cf1dd8SToby Isaac     }
84120cf1dd8SToby Isaac     if (debug > 1) {
84220cf1dd8SToby Isaac       PetscInt fc, f, gc, g;
84320cf1dd8SToby Isaac 
84420cf1dd8SToby Isaac       ierr = PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %d and %d\n", fieldI, fieldJ);CHKERRQ(ierr);
845ef0bb6c7SMatthew G. Knepley       for (fc = 0; fc < T[fieldI]->Nc; ++fc) {
846ef0bb6c7SMatthew G. Knepley         for (f = 0; f < T[fieldI]->Nb; ++f) {
847ef0bb6c7SMatthew G. Knepley           const PetscInt i = offsetI + f*T[fieldI]->Nc+fc;
848ef0bb6c7SMatthew G. Knepley           for (gc = 0; gc < T[fieldJ]->Nc; ++gc) {
849ef0bb6c7SMatthew G. Knepley             for (g = 0; g < T[fieldJ]->Nb; ++g) {
850ef0bb6c7SMatthew G. Knepley               const PetscInt j = offsetJ + g*T[fieldJ]->Nc+gc;
85120cf1dd8SToby 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);
85220cf1dd8SToby Isaac             }
85320cf1dd8SToby Isaac           }
85420cf1dd8SToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
85520cf1dd8SToby Isaac         }
85620cf1dd8SToby Isaac       }
85720cf1dd8SToby Isaac     }
85820cf1dd8SToby Isaac     cOffset    += totDim;
85920cf1dd8SToby Isaac     cOffsetAux += totDimAux;
86020cf1dd8SToby Isaac     eOffset    += PetscSqr(totDim);
86120cf1dd8SToby Isaac   }
86220cf1dd8SToby Isaac   PetscFunctionReturn(0);
86320cf1dd8SToby Isaac }
86420cf1dd8SToby Isaac 
8652b99622eSMatthew G. Knepley static PetscErrorCode PetscFEInitialize_Basic(PetscFE fem)
86620cf1dd8SToby Isaac {
86720cf1dd8SToby Isaac   PetscFunctionBegin;
86820cf1dd8SToby Isaac   fem->ops->setfromoptions          = NULL;
86920cf1dd8SToby Isaac   fem->ops->setup                   = PetscFESetUp_Basic;
87020cf1dd8SToby Isaac   fem->ops->view                    = PetscFEView_Basic;
87120cf1dd8SToby Isaac   fem->ops->destroy                 = PetscFEDestroy_Basic;
87220cf1dd8SToby Isaac   fem->ops->getdimension            = PetscFEGetDimension_Basic;
873ef0bb6c7SMatthew G. Knepley   fem->ops->createtabulation        = PetscFECreateTabulation_Basic;
87420cf1dd8SToby Isaac   fem->ops->integrate               = PetscFEIntegrate_Basic;
875afe6d6adSToby Isaac   fem->ops->integratebd             = PetscFEIntegrateBd_Basic;
87620cf1dd8SToby Isaac   fem->ops->integrateresidual       = PetscFEIntegrateResidual_Basic;
87720cf1dd8SToby Isaac   fem->ops->integratebdresidual     = PetscFEIntegrateBdResidual_Basic;
87820cf1dd8SToby Isaac   fem->ops->integratejacobianaction = NULL/* PetscFEIntegrateJacobianAction_Basic */;
87920cf1dd8SToby Isaac   fem->ops->integratejacobian       = PetscFEIntegrateJacobian_Basic;
88020cf1dd8SToby Isaac   fem->ops->integratebdjacobian     = PetscFEIntegrateBdJacobian_Basic;
88120cf1dd8SToby Isaac   PetscFunctionReturn(0);
88220cf1dd8SToby Isaac }
88320cf1dd8SToby Isaac 
88420cf1dd8SToby Isaac /*MC
88520cf1dd8SToby Isaac   PETSCFEBASIC = "basic" - A PetscFE object that integrates with basic tiling and no vectorization
88620cf1dd8SToby Isaac 
88720cf1dd8SToby Isaac   Level: intermediate
88820cf1dd8SToby Isaac 
88920cf1dd8SToby Isaac .seealso: PetscFEType, PetscFECreate(), PetscFESetType()
89020cf1dd8SToby Isaac M*/
89120cf1dd8SToby Isaac 
89220cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode PetscFECreate_Basic(PetscFE fem)
89320cf1dd8SToby Isaac {
89420cf1dd8SToby Isaac   PetscFE_Basic *b;
89520cf1dd8SToby Isaac   PetscErrorCode ierr;
89620cf1dd8SToby Isaac 
89720cf1dd8SToby Isaac   PetscFunctionBegin;
89820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
89920cf1dd8SToby Isaac   ierr      = PetscNewLog(fem,&b);CHKERRQ(ierr);
90020cf1dd8SToby Isaac   fem->data = b;
90120cf1dd8SToby Isaac 
90220cf1dd8SToby Isaac   ierr = PetscFEInitialize_Basic(fem);CHKERRQ(ierr);
90320cf1dd8SToby Isaac   PetscFunctionReturn(0);
90420cf1dd8SToby Isaac }
905