120cf1dd8SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/ 220cf1dd8SToby Isaac #include <petscblaslapack.h> 320cf1dd8SToby Isaac 4d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFEDestroy_Basic(PetscFE fem) 5d71ae5a4SJacob Faibussowitsch { 620cf1dd8SToby Isaac PetscFE_Basic *b = (PetscFE_Basic *)fem->data; 720cf1dd8SToby Isaac 820cf1dd8SToby Isaac PetscFunctionBegin; 99566063dSJacob Faibussowitsch PetscCall(PetscFree(b)); 103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1120cf1dd8SToby Isaac } 1220cf1dd8SToby Isaac 13d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFEView_Basic_Ascii(PetscFE fe, PetscViewer v) 14d71ae5a4SJacob Faibussowitsch { 15d9bac1caSLisandro Dalcin PetscInt dim, Nc; 16d9bac1caSLisandro Dalcin PetscSpace basis = NULL; 17d9bac1caSLisandro Dalcin PetscDualSpace dual = NULL; 18d9bac1caSLisandro Dalcin PetscQuadrature quad = NULL; 1920cf1dd8SToby Isaac 2020cf1dd8SToby Isaac PetscFunctionBegin; 219566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(fe, &dim)); 229566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc)); 239566063dSJacob Faibussowitsch PetscCall(PetscFEGetBasisSpace(fe, &basis)); 249566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dual)); 259566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quad)); 269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(v)); 2763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(v, "Basic Finite Element in %" PetscInt_FMT " dimensions with %" PetscInt_FMT " components\n", dim, Nc)); 289566063dSJacob Faibussowitsch if (basis) PetscCall(PetscSpaceView(basis, v)); 299566063dSJacob Faibussowitsch if (dual) PetscCall(PetscDualSpaceView(dual, v)); 309566063dSJacob Faibussowitsch if (quad) PetscCall(PetscQuadratureView(quad, v)); 319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(v)); 323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3320cf1dd8SToby Isaac } 3420cf1dd8SToby Isaac 35d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFEView_Basic(PetscFE fe, PetscViewer v) 36d71ae5a4SJacob Faibussowitsch { 3720cf1dd8SToby Isaac PetscBool iascii; 3820cf1dd8SToby Isaac 3920cf1dd8SToby Isaac PetscFunctionBegin; 409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii)); 419566063dSJacob Faibussowitsch if (iascii) PetscCall(PetscFEView_Basic_Ascii(fe, v)); 423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4320cf1dd8SToby Isaac } 4420cf1dd8SToby Isaac 4520cf1dd8SToby Isaac /* Construct the change of basis from prime basis to nodal basis */ 46d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscFESetUp_Basic(PetscFE fem) 47d71ae5a4SJacob Faibussowitsch { 48b9d4cb8dSJed Brown PetscReal *work; 4920cf1dd8SToby Isaac PetscBLASInt *pivots; 5020cf1dd8SToby Isaac PetscBLASInt n, info; 5120cf1dd8SToby Isaac PetscInt pdim, j; 5220cf1dd8SToby Isaac 5320cf1dd8SToby Isaac PetscFunctionBegin; 549566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(fem->dualSpace, &pdim)); 559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pdim * pdim, &fem->invV)); 5620cf1dd8SToby Isaac for (j = 0; j < pdim; ++j) { 5720cf1dd8SToby Isaac PetscReal *Bf; 5820cf1dd8SToby Isaac PetscQuadrature f; 5920cf1dd8SToby Isaac const PetscReal *points, *weights; 6020cf1dd8SToby Isaac PetscInt Nc, Nq, q, k, c; 6120cf1dd8SToby Isaac 629566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(fem->dualSpace, j, &f)); 639566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(f, NULL, &Nc, &Nq, &points, &weights)); 649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nc * Nq * pdim, &Bf)); 659566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(fem->basisSpace, Nq, points, Bf, NULL, NULL)); 6620cf1dd8SToby Isaac for (k = 0; k < pdim; ++k) { 6720cf1dd8SToby Isaac /* V_{jk} = n_j(\phi_k) = \int \phi_k(x) n_j(x) dx */ 68b9d4cb8dSJed Brown fem->invV[j * pdim + k] = 0.0; 6920cf1dd8SToby Isaac 7020cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 71b9d4cb8dSJed Brown for (c = 0; c < Nc; ++c) fem->invV[j * pdim + k] += Bf[(q * pdim + k) * Nc + c] * weights[q * Nc + c]; 7220cf1dd8SToby Isaac } 7320cf1dd8SToby Isaac } 749566063dSJacob Faibussowitsch PetscCall(PetscFree(Bf)); 7520cf1dd8SToby Isaac } 76ea2bdf6dSBarry Smith 779566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pdim, &pivots, pdim, &work)); 786497c311SBarry Smith PetscCall(PetscBLASIntCast(pdim, &n)); 79792fecdfSBarry Smith PetscCallBLAS("LAPACKgetrf", LAPACKREALgetrf_(&n, &n, fem->invV, &n, pivots, &info)); 80835f2295SStefano Zampini PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error returned from LAPACKgetrf %" PetscBLASInt_FMT, info); 81792fecdfSBarry Smith PetscCallBLAS("LAPACKgetri", LAPACKREALgetri_(&n, fem->invV, &n, pivots, work, &n, &info)); 82835f2295SStefano Zampini PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error returned from LAPACKgetri %" PetscBLASInt_FMT, info); 839566063dSJacob Faibussowitsch PetscCall(PetscFree2(pivots, work)); 843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8520cf1dd8SToby Isaac } 8620cf1dd8SToby Isaac 87d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEGetDimension_Basic(PetscFE fem, PetscInt *dim) 88d71ae5a4SJacob Faibussowitsch { 8920cf1dd8SToby Isaac PetscFunctionBegin; 909566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(fem->dualSpace, dim)); 913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9220cf1dd8SToby Isaac } 9320cf1dd8SToby Isaac 94b9d4cb8dSJed Brown /* Tensor contraction on the middle index, 95b9d4cb8dSJed Brown * C[m,n,p] = A[m,k,p] * B[k,n] 96b9d4cb8dSJed Brown * where all matrices use C-style ordering. 97b9d4cb8dSJed Brown */ 98d71ae5a4SJacob Faibussowitsch static PetscErrorCode TensorContract_Private(PetscInt m, PetscInt n, PetscInt p, PetscInt k, const PetscReal *A, const PetscReal *B, PetscReal *C) 99d71ae5a4SJacob Faibussowitsch { 100b9d4cb8dSJed Brown PetscInt i; 101b9d4cb8dSJed Brown 102b9d4cb8dSJed Brown PetscFunctionBegin; 103aa9788aaSMatthew G. Knepley PetscCheck(n && p, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Empty tensor is not allowed %" PetscInt_FMT " %" PetscInt_FMT, n, p); 104b9d4cb8dSJed Brown for (i = 0; i < m; i++) { 105b9d4cb8dSJed Brown PetscBLASInt n_, p_, k_, lda, ldb, ldc; 106b9d4cb8dSJed Brown PetscReal one = 1, zero = 0; 107b9d4cb8dSJed Brown /* Taking contiguous submatrices, we wish to comput c[n,p] = a[k,p] * B[k,n] 108b9d4cb8dSJed Brown * or, in Fortran ordering, c(p,n) = a(p,k) * B(n,k) 109b9d4cb8dSJed Brown */ 1109566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(n, &n_)); 1119566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(p, &p_)); 1129566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(k, &k_)); 113b9d4cb8dSJed Brown lda = p_; 114b9d4cb8dSJed Brown ldb = n_; 115b9d4cb8dSJed Brown ldc = p_; 116792fecdfSBarry Smith PetscCallBLAS("BLASgemm", BLASREALgemm_("N", "T", &p_, &n_, &k_, &one, A + i * k * p, &lda, B, &ldb, &zero, C + i * n * p, &ldc)); 117b9d4cb8dSJed Brown } 1189566063dSJacob Faibussowitsch PetscCall(PetscLogFlops(2. * m * n * p * k)); 1193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 120b9d4cb8dSJed Brown } 121b9d4cb8dSJed Brown 122ce78bad3SBarry Smith PETSC_INTERN PetscErrorCode PetscFEComputeTabulation_Basic(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation T) 123d71ae5a4SJacob Faibussowitsch { 12420cf1dd8SToby Isaac DM dm; 12520cf1dd8SToby Isaac PetscInt pdim; /* Dimension of FE space P */ 12620cf1dd8SToby Isaac PetscInt dim; /* Spatial dimension */ 12720cf1dd8SToby Isaac PetscInt Nc; /* Field components */ 128ef0bb6c7SMatthew G. Knepley PetscReal *B = K >= 0 ? T->T[0] : NULL; 129ef0bb6c7SMatthew G. Knepley PetscReal *D = K >= 1 ? T->T[1] : NULL; 130ef0bb6c7SMatthew G. Knepley PetscReal *H = K >= 2 ? T->T[2] : NULL; 131ef0bb6c7SMatthew G. Knepley PetscReal *tmpB = NULL, *tmpD = NULL, *tmpH = NULL; 13220cf1dd8SToby Isaac 13320cf1dd8SToby Isaac PetscFunctionBegin; 1349566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDM(fem->dualSpace, &dm)); 1359566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 1369566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(fem->dualSpace, &pdim)); 1379566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fem, &Nc)); 13820cf1dd8SToby Isaac /* Evaluate the prime basis functions at all points */ 1399566063dSJacob Faibussowitsch if (K >= 0) PetscCall(DMGetWorkArray(dm, npoints * pdim * Nc, MPIU_REAL, &tmpB)); 1409566063dSJacob Faibussowitsch if (K >= 1) PetscCall(DMGetWorkArray(dm, npoints * pdim * Nc * dim, MPIU_REAL, &tmpD)); 1419566063dSJacob Faibussowitsch if (K >= 2) PetscCall(DMGetWorkArray(dm, npoints * pdim * Nc * dim * dim, MPIU_REAL, &tmpH)); 1429566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(fem->basisSpace, npoints, points, tmpB, tmpD, tmpH)); 143b9d4cb8dSJed Brown /* Translate from prime to nodal basis */ 14420cf1dd8SToby Isaac if (B) { 145b9d4cb8dSJed Brown /* B[npoints, nodes, Nc] = tmpB[npoints, prime, Nc] * invV[prime, nodes] */ 1469566063dSJacob Faibussowitsch PetscCall(TensorContract_Private(npoints, pdim, Nc, pdim, tmpB, fem->invV, B)); 14720cf1dd8SToby Isaac } 148aa9788aaSMatthew G. Knepley if (D && dim) { 149b9d4cb8dSJed Brown /* D[npoints, nodes, Nc, dim] = tmpD[npoints, prime, Nc, dim] * invV[prime, nodes] */ 1509566063dSJacob Faibussowitsch PetscCall(TensorContract_Private(npoints, pdim, Nc * dim, pdim, tmpD, fem->invV, D)); 15120cf1dd8SToby Isaac } 152aa9788aaSMatthew G. Knepley if (H && dim) { 153b9d4cb8dSJed Brown /* H[npoints, nodes, Nc, dim, dim] = tmpH[npoints, prime, Nc, dim, dim] * invV[prime, nodes] */ 1549566063dSJacob Faibussowitsch PetscCall(TensorContract_Private(npoints, pdim, Nc * dim * dim, pdim, tmpH, fem->invV, H)); 15520cf1dd8SToby Isaac } 1569566063dSJacob Faibussowitsch if (K >= 0) PetscCall(DMRestoreWorkArray(dm, npoints * pdim * Nc, MPIU_REAL, &tmpB)); 1579566063dSJacob Faibussowitsch if (K >= 1) PetscCall(DMRestoreWorkArray(dm, npoints * pdim * Nc * dim, MPIU_REAL, &tmpD)); 1589566063dSJacob Faibussowitsch if (K >= 2) PetscCall(DMRestoreWorkArray(dm, npoints * pdim * Nc * dim * dim, MPIU_REAL, &tmpH)); 1593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16020cf1dd8SToby Isaac } 16120cf1dd8SToby Isaac 1622dce792eSToby Isaac PETSC_INTERN PetscErrorCode PetscFEIntegrate_Basic(PetscDS ds, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom, const PetscScalar coefficients[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscScalar integral[]) 163d71ae5a4SJacob Faibussowitsch { 164b2deab97SMatthew G. Knepley const PetscInt debug = ds->printIntegrate; 1654bee2e38SMatthew G. Knepley PetscFE fe; 166*2192575eSBarry Smith PetscPointFn *obj_func; 16720cf1dd8SToby Isaac PetscQuadrature quad; 168ef0bb6c7SMatthew G. Knepley PetscTabulation *T, *TAux = NULL; 1694bee2e38SMatthew G. Knepley PetscScalar *u, *u_x, *a, *a_x; 17020cf1dd8SToby Isaac const PetscScalar *constants; 17187510d7dSMatthew G. Knepley PetscReal *x, cellScale; 172ef0bb6c7SMatthew G. Knepley PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL; 17320cf1dd8SToby Isaac PetscInt dim, dE, Np, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, e; 17420cf1dd8SToby Isaac PetscBool isAffine; 17520cf1dd8SToby Isaac const PetscReal *quadPoints, *quadWeights; 17620cf1dd8SToby Isaac PetscInt qNc, Nq, q; 17720cf1dd8SToby Isaac 17820cf1dd8SToby Isaac PetscFunctionBegin; 1799566063dSJacob Faibussowitsch PetscCall(PetscDSGetObjective(ds, field, &obj_func)); 1803ba16761SJacob Faibussowitsch if (!obj_func) PetscFunctionReturn(PETSC_SUCCESS); 1819566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, field, (PetscObject *)&fe)); 1829566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(fe, &dim)); 18387510d7dSMatthew G. Knepley cellScale = (PetscReal)PetscPowInt(2, dim); 1849566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quad)); 1859566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 1869566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim)); 1879566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(ds, &uOff)); 1889566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(ds, &uOff_x)); 1899566063dSJacob Faibussowitsch PetscCall(PetscDSGetTabulation(ds, &T)); 1909566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(ds, &u, NULL, &u_x)); 1919566063dSJacob Faibussowitsch PetscCall(PetscDSGetWorkspace(ds, &x, NULL, NULL, NULL, NULL)); 19287510d7dSMatthew G. Knepley PetscCall(PetscDSSetIntegrationParameters(ds, field, PETSC_DETERMINE)); 1939566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 1944bee2e38SMatthew G. Knepley if (dsAux) { 1959566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(dsAux, &NfAux)); 1969566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux)); 1979566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff)); 1989566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x)); 1999566063dSJacob Faibussowitsch PetscCall(PetscDSGetTabulation(dsAux, &TAux)); 2009566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x)); 20163a3b9bcSJacob Faibussowitsch PetscCheck(T[0]->Np == TAux[0]->Np, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of tabulation points %" PetscInt_FMT " != %" PetscInt_FMT " number of auxiliary tabulation points", T[0]->Np, TAux[0]->Np); 20220cf1dd8SToby Isaac } 2039566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights)); 20463a3b9bcSJacob Faibussowitsch PetscCheck(qNc == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %" PetscInt_FMT " components", qNc); 20520cf1dd8SToby Isaac Np = cgeom->numPoints; 20620cf1dd8SToby Isaac dE = cgeom->dimEmbed; 20720cf1dd8SToby Isaac isAffine = cgeom->isAffine; 20820cf1dd8SToby Isaac for (e = 0; e < Ne; ++e) { 2094bee2e38SMatthew G. Knepley PetscFEGeom fegeom; 21020cf1dd8SToby Isaac 21127f02ce8SMatthew G. Knepley fegeom.dim = cgeom->dim; 21227f02ce8SMatthew G. Knepley fegeom.dimEmbed = cgeom->dimEmbed; 21320cf1dd8SToby Isaac if (isAffine) { 2144bee2e38SMatthew G. Knepley fegeom.v = x; 2154bee2e38SMatthew G. Knepley fegeom.xi = cgeom->xi; 2167132c3f7SMatthew G. Knepley fegeom.J = &cgeom->J[e * Np * dE * dE]; 2177132c3f7SMatthew G. Knepley fegeom.invJ = &cgeom->invJ[e * Np * dE * dE]; 2187132c3f7SMatthew G. Knepley fegeom.detJ = &cgeom->detJ[e * Np]; 21920cf1dd8SToby Isaac } 2204bee2e38SMatthew G. Knepley for (q = 0; q < Nq; ++q) { 221d627b919SMatthew G. Knepley PetscScalar integrand = 0.; 2224bee2e38SMatthew G. Knepley PetscReal w; 2234bee2e38SMatthew G. Knepley 2244bee2e38SMatthew G. Knepley if (isAffine) { 2257132c3f7SMatthew G. Knepley CoordinatesRefToReal(dE, dim, fegeom.xi, &cgeom->v[e * Np * dE], fegeom.J, &quadPoints[q * dim], x); 2264bee2e38SMatthew G. Knepley } else { 2274bee2e38SMatthew G. Knepley fegeom.v = &cgeom->v[(e * Np + q) * dE]; 2284bee2e38SMatthew G. Knepley fegeom.J = &cgeom->J[(e * Np + q) * dE * dE]; 2294bee2e38SMatthew G. Knepley fegeom.invJ = &cgeom->invJ[(e * Np + q) * dE * dE]; 2304bee2e38SMatthew G. Knepley fegeom.detJ = &cgeom->detJ[e * Np + q]; 2314bee2e38SMatthew G. Knepley } 23287510d7dSMatthew G. Knepley PetscCall(PetscDSSetCellParameters(ds, fegeom.detJ[0] * cellScale)); 2334bee2e38SMatthew G. Knepley w = fegeom.detJ[0] * quadWeights[q]; 23420cf1dd8SToby Isaac if (debug > 1 && q < Np) { 23563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " detJ: %g\n", (double)fegeom.detJ[0])); 2367be5e748SToby Isaac #if !defined(PETSC_USE_COMPLEX) 2379566063dSJacob Faibussowitsch PetscCall(DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ)); 23820cf1dd8SToby Isaac #endif 23920cf1dd8SToby Isaac } 24063a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(PETSC_COMM_SELF, " quad point %" PetscInt_FMT "\n", q)); 2419566063dSJacob Faibussowitsch PetscCall(PetscFEEvaluateFieldJets_Internal(ds, Nf, 0, q, T, &fegeom, &coefficients[cOffset], NULL, u, u_x, NULL)); 2429566063dSJacob Faibussowitsch if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL)); 2434bee2e38SMatthew 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); 2444bee2e38SMatthew G. Knepley integrand *= w; 24520cf1dd8SToby Isaac integral[e * Nf + field] += integrand; 24620cf1dd8SToby Isaac } 247699b48e5SStefano Zampini if (debug > 1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Element Field %" PetscInt_FMT " integral: %g\n", Nf, (double)PetscRealPart(integral[e * Nf + field]))); 24820cf1dd8SToby Isaac cOffset += totDim; 24920cf1dd8SToby Isaac cOffsetAux += totDimAux; 25020cf1dd8SToby Isaac } 2513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25220cf1dd8SToby Isaac } 25320cf1dd8SToby Isaac 254*2192575eSBarry Smith PETSC_INTERN PetscErrorCode PetscFEIntegrateBd_Basic(PetscDS ds, PetscInt field, PetscBdPointFn *obj_func, PetscInt Ne, PetscFEGeom *fgeom, const PetscScalar coefficients[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscScalar integral[]) 255d71ae5a4SJacob Faibussowitsch { 256b2deab97SMatthew G. Knepley const PetscInt debug = ds->printIntegrate; 2574bee2e38SMatthew G. Knepley PetscFE fe; 258afe6d6adSToby Isaac PetscQuadrature quad; 259ef0bb6c7SMatthew G. Knepley PetscTabulation *Tf, *TfAux = NULL; 2604bee2e38SMatthew G. Knepley PetscScalar *u, *u_x, *a, *a_x, *basisReal, *basisDerReal; 261afe6d6adSToby Isaac const PetscScalar *constants; 26287510d7dSMatthew G. Knepley PetscReal *x, cellScale; 263ef0bb6c7SMatthew G. Knepley PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL; 264afe6d6adSToby Isaac PetscBool isAffine, auxOnBd; 265afe6d6adSToby Isaac const PetscReal *quadPoints, *quadWeights; 266afe6d6adSToby Isaac PetscInt qNc, Nq, q, Np, dE; 267afe6d6adSToby Isaac PetscInt dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, e; 268afe6d6adSToby Isaac 269afe6d6adSToby Isaac PetscFunctionBegin; 2703ba16761SJacob Faibussowitsch if (!obj_func) PetscFunctionReturn(PETSC_SUCCESS); 2719566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, field, (PetscObject *)&fe)); 2729566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(fe, &dim)); 27387510d7dSMatthew G. Knepley cellScale = (PetscReal)PetscPowInt(2, dim); 2749566063dSJacob Faibussowitsch PetscCall(PetscFEGetFaceQuadrature(fe, &quad)); 2759566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 2769566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim)); 2779566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(ds, &uOff)); 2789566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(ds, &uOff_x)); 2799566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(ds, &u, NULL, &u_x)); 2809566063dSJacob Faibussowitsch PetscCall(PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL)); 2819566063dSJacob Faibussowitsch PetscCall(PetscDSGetFaceTabulation(ds, &Tf)); 28287510d7dSMatthew G. Knepley PetscCall(PetscDSSetIntegrationParameters(ds, field, PETSC_DETERMINE)); 2839566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 2844bee2e38SMatthew G. Knepley if (dsAux) { 2859566063dSJacob Faibussowitsch PetscCall(PetscDSGetSpatialDimension(dsAux, &dimAux)); 2869566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(dsAux, &NfAux)); 2879566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux)); 2889566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff)); 2899566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x)); 2909566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x)); 291afe6d6adSToby Isaac auxOnBd = dimAux < dim ? PETSC_TRUE : PETSC_FALSE; 2929566063dSJacob Faibussowitsch if (auxOnBd) PetscCall(PetscDSGetTabulation(dsAux, &TfAux)); 2939566063dSJacob Faibussowitsch else PetscCall(PetscDSGetFaceTabulation(dsAux, &TfAux)); 29463a3b9bcSJacob Faibussowitsch PetscCheck(Tf[0]->Np == TfAux[0]->Np, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of tabulation points %" PetscInt_FMT " != %" PetscInt_FMT " number of auxiliary tabulation points", Tf[0]->Np, TfAux[0]->Np); 295afe6d6adSToby Isaac } 2969566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights)); 29763a3b9bcSJacob Faibussowitsch PetscCheck(qNc == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %" PetscInt_FMT " components", qNc); 29879ab67a3SMatthew G. Knepley if (debug > 1) PetscCall(PetscPrintf(PETSC_COMM_SELF, "Field: %" PetscInt_FMT " Nface: %" PetscInt_FMT " Nq: %" PetscInt_FMT "\n", field, Ne, Nq)); 299afe6d6adSToby Isaac Np = fgeom->numPoints; 300afe6d6adSToby Isaac dE = fgeom->dimEmbed; 301afe6d6adSToby Isaac isAffine = fgeom->isAffine; 302afe6d6adSToby Isaac for (e = 0; e < Ne; ++e) { 3039f209ee4SMatthew G. Knepley PetscFEGeom fegeom, cgeom; 304afe6d6adSToby Isaac const PetscInt face = fgeom->face[e][0]; /* Local face number in cell */ 305ea78f98cSLisandro Dalcin fegeom.n = NULL; 306ea78f98cSLisandro Dalcin fegeom.v = NULL; 307ea78f98cSLisandro Dalcin fegeom.J = NULL; 308b2deab97SMatthew G. Knepley fegeom.invJ = NULL; 309ea78f98cSLisandro Dalcin fegeom.detJ = NULL; 31027f02ce8SMatthew G. Knepley fegeom.dim = fgeom->dim; 31127f02ce8SMatthew G. Knepley fegeom.dimEmbed = fgeom->dimEmbed; 31227f02ce8SMatthew G. Knepley cgeom.dim = fgeom->dim; 31327f02ce8SMatthew G. Knepley cgeom.dimEmbed = fgeom->dimEmbed; 3144bee2e38SMatthew G. Knepley if (isAffine) { 3154bee2e38SMatthew G. Knepley fegeom.v = x; 3164bee2e38SMatthew G. Knepley fegeom.xi = fgeom->xi; 3177132c3f7SMatthew G. Knepley fegeom.J = &fgeom->J[e * Np * dE * dE]; 3187132c3f7SMatthew G. Knepley fegeom.invJ = &fgeom->invJ[e * Np * dE * dE]; 3197132c3f7SMatthew G. Knepley fegeom.detJ = &fgeom->detJ[e * Np]; 3207132c3f7SMatthew G. Knepley fegeom.n = &fgeom->n[e * Np * dE]; 3219f209ee4SMatthew G. Knepley 3227132c3f7SMatthew G. Knepley cgeom.J = &fgeom->suppJ[0][e * Np * dE * dE]; 3237132c3f7SMatthew G. Knepley cgeom.invJ = &fgeom->suppInvJ[0][e * Np * dE * dE]; 3247132c3f7SMatthew G. Knepley cgeom.detJ = &fgeom->suppDetJ[0][e * Np]; 3254bee2e38SMatthew G. Knepley } 326afe6d6adSToby Isaac for (q = 0; q < Nq; ++q) { 32779ab67a3SMatthew G. Knepley PetscScalar integrand = 0.; 3284bee2e38SMatthew G. Knepley PetscReal w; 329afe6d6adSToby Isaac 330afe6d6adSToby Isaac if (isAffine) { 3317132c3f7SMatthew G. Knepley CoordinatesRefToReal(dE, dim - 1, fegeom.xi, &fgeom->v[e * Np * dE], fegeom.J, &quadPoints[q * (dim - 1)], x); 332afe6d6adSToby Isaac } else { 3333fe841f2SMatthew G. Knepley fegeom.v = &fgeom->v[(e * Np + q) * dE]; 3349f209ee4SMatthew G. Knepley fegeom.J = &fgeom->J[(e * Np + q) * dE * dE]; 3359f209ee4SMatthew G. Knepley fegeom.invJ = &fgeom->invJ[(e * Np + q) * dE * dE]; 3364bee2e38SMatthew G. Knepley fegeom.detJ = &fgeom->detJ[e * Np + q]; 3374bee2e38SMatthew G. Knepley fegeom.n = &fgeom->n[(e * Np + q) * dE]; 3389f209ee4SMatthew G. Knepley 3399f209ee4SMatthew G. Knepley cgeom.J = &fgeom->suppJ[0][(e * Np + q) * dE * dE]; 3409f209ee4SMatthew G. Knepley cgeom.invJ = &fgeom->suppInvJ[0][(e * Np + q) * dE * dE]; 3419f209ee4SMatthew G. Knepley cgeom.detJ = &fgeom->suppDetJ[0][e * Np + q]; 342afe6d6adSToby Isaac } 34387510d7dSMatthew G. Knepley PetscCall(PetscDSSetCellParameters(ds, fegeom.detJ[0] * cellScale)); 3444bee2e38SMatthew G. Knepley w = fegeom.detJ[0] * quadWeights[q]; 345afe6d6adSToby Isaac if (debug > 1 && q < Np) { 34663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " detJ: %g\n", (double)fegeom.detJ[0])); 347afe6d6adSToby Isaac #ifndef PETSC_USE_COMPLEX 3489566063dSJacob Faibussowitsch PetscCall(DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ)); 349afe6d6adSToby Isaac #endif 350afe6d6adSToby Isaac } 35163a3b9bcSJacob Faibussowitsch if (debug > 1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " quad point %" PetscInt_FMT "\n", q)); 35279ab67a3SMatthew G. Knepley if (debug > 3) { 35379ab67a3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, " x_q (")); 35479ab67a3SMatthew G. Knepley for (PetscInt d = 0; d < dE; ++d) { 35579ab67a3SMatthew G. Knepley if (d) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); 35679ab67a3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", (double)fegeom.v[d])); 35779ab67a3SMatthew G. Knepley } 35879ab67a3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n")); 35979ab67a3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, " n_q (")); 36079ab67a3SMatthew G. Knepley for (PetscInt d = 0; d < dE; ++d) { 36179ab67a3SMatthew G. Knepley if (d) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); 36279ab67a3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", (double)fegeom.n[d])); 36379ab67a3SMatthew G. Knepley } 36479ab67a3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n")); 36579ab67a3SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 36679ab67a3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, " u_%" PetscInt_FMT " (", f)); 36779ab67a3SMatthew G. Knepley for (PetscInt c = 0; c < uOff[f + 1] - uOff[f]; ++c) { 36879ab67a3SMatthew G. Knepley if (c) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", ")); 36979ab67a3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", (double)PetscRealPart(u[uOff[f] + c]))); 37079ab67a3SMatthew G. Knepley } 37179ab67a3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, ")\n")); 37279ab67a3SMatthew G. Knepley } 37379ab67a3SMatthew G. Knepley } 3749566063dSJacob Faibussowitsch PetscCall(PetscFEEvaluateFieldJets_Internal(ds, Nf, face, q, Tf, &cgeom, &coefficients[cOffset], NULL, u, u_x, NULL)); 3759566063dSJacob Faibussowitsch if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, face, q, TfAux, &cgeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL)); 3764bee2e38SMatthew 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); 3774bee2e38SMatthew G. Knepley integrand *= w; 378afe6d6adSToby Isaac integral[e * Nf + field] += integrand; 37979ab67a3SMatthew G. Knepley if (debug > 1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " int: %g tot: %g\n", (double)PetscRealPart(integrand), (double)PetscRealPart(integral[e * Nf + field]))); 380afe6d6adSToby Isaac } 381afe6d6adSToby Isaac cOffset += totDim; 382afe6d6adSToby Isaac cOffsetAux += totDimAux; 383afe6d6adSToby Isaac } 3843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 385afe6d6adSToby Isaac } 386afe6d6adSToby Isaac 387d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEIntegrateResidual_Basic(PetscDS ds, PetscFormKey key, PetscInt Ne, PetscFEGeom *cgeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[]) 388d71ae5a4SJacob Faibussowitsch { 389b2deab97SMatthew G. Knepley const PetscInt debug = ds->printIntegrate; 3906528b96dSMatthew G. Knepley const PetscInt field = key.field; 3914bee2e38SMatthew G. Knepley PetscFE fe; 3926528b96dSMatthew G. Knepley PetscWeakForm wf; 3936528b96dSMatthew G. Knepley PetscInt n0, n1, i; 394*2192575eSBarry Smith PetscPointFn **f0_func, **f1_func; 39520cf1dd8SToby Isaac PetscQuadrature quad; 396ef0bb6c7SMatthew G. Knepley PetscTabulation *T, *TAux = NULL; 3974bee2e38SMatthew G. Knepley PetscScalar *f0, *f1, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal; 39820cf1dd8SToby Isaac const PetscScalar *constants; 39987510d7dSMatthew G. Knepley PetscReal *x, cellScale; 400ef0bb6c7SMatthew G. Knepley PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL; 401ef0bb6c7SMatthew G. Knepley PetscInt dim, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, fOffset, e; 40220cf1dd8SToby Isaac const PetscReal *quadPoints, *quadWeights; 4036587ee25SMatthew G. Knepley PetscInt qdim, qNc, Nq, q, dE; 40420cf1dd8SToby Isaac 40520cf1dd8SToby Isaac PetscFunctionBegin; 4069566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, field, (PetscObject *)&fe)); 4079566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(fe, &dim)); 40887510d7dSMatthew G. Knepley cellScale = (PetscReal)PetscPowInt(2, dim); 4099566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quad)); 4109566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 4119566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim)); 4129566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(ds, &uOff)); 4139566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(ds, &uOff_x)); 4149566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffset(ds, field, &fOffset)); 4159566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 4169566063dSJacob Faibussowitsch PetscCall(PetscWeakFormGetResidual(wf, key.label, key.value, key.field, key.part, &n0, &f0_func, &n1, &f1_func)); 4173ba16761SJacob Faibussowitsch if (!n0 && !n1) PetscFunctionReturn(PETSC_SUCCESS); 4189566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x)); 4199566063dSJacob Faibussowitsch PetscCall(PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL)); 4209566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakFormArrays(ds, &f0, &f1, NULL, NULL, NULL, NULL)); 4219566063dSJacob Faibussowitsch PetscCall(PetscDSGetTabulation(ds, &T)); 42287510d7dSMatthew G. Knepley PetscCall(PetscDSSetIntegrationParameters(ds, field, PETSC_DETERMINE)); 4239566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 4244bee2e38SMatthew G. Knepley if (dsAux) { 4259566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(dsAux, &NfAux)); 4269566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux)); 4279566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff)); 4289566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x)); 4299566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x)); 4309566063dSJacob Faibussowitsch PetscCall(PetscDSGetTabulation(dsAux, &TAux)); 43163a3b9bcSJacob Faibussowitsch PetscCheck(T[0]->Np == TAux[0]->Np, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of tabulation points %" PetscInt_FMT " != %" PetscInt_FMT " number of auxiliary tabulation points", T[0]->Np, TAux[0]->Np); 43220cf1dd8SToby Isaac } 4339566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, &qdim, &qNc, &Nq, &quadPoints, &quadWeights)); 43463a3b9bcSJacob Faibussowitsch PetscCheck(qNc == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %" PetscInt_FMT " components", qNc); 43520cf1dd8SToby Isaac dE = cgeom->dimEmbed; 43663a3b9bcSJacob Faibussowitsch PetscCheck(cgeom->dim == qdim, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "FEGeom dim %" PetscInt_FMT " != %" PetscInt_FMT " quadrature dim", cgeom->dim, qdim); 43720cf1dd8SToby Isaac for (e = 0; e < Ne; ++e) { 4384bee2e38SMatthew G. Knepley PetscFEGeom fegeom; 43920cf1dd8SToby Isaac 4406587ee25SMatthew G. Knepley fegeom.v = x; /* workspace */ 4419566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(f0, Nq * T[field]->Nc)); 4429566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(f1, Nq * T[field]->Nc * dE)); 44320cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 4444bee2e38SMatthew G. Knepley PetscReal w; 4454bee2e38SMatthew G. Knepley PetscInt c, d; 44620cf1dd8SToby Isaac 4479566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetPoint(cgeom, e, q, &quadPoints[q * cgeom->dim], &fegeom)); 44887510d7dSMatthew G. Knepley PetscCall(PetscDSSetCellParameters(ds, fegeom.detJ[0] * cellScale)); 4494bee2e38SMatthew G. Knepley w = fegeom.detJ[0] * quadWeights[q]; 4506587ee25SMatthew G. Knepley if (debug > 1 && q < cgeom->numPoints) { 45163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " detJ: %g\n", (double)fegeom.detJ[0])); 4527be5e748SToby Isaac #if !defined(PETSC_USE_COMPLEX) 453ac9d17c7SMatthew G. Knepley PetscCall(DMPrintCellMatrix(e, "invJ", dE, dE, fegeom.invJ)); 45420cf1dd8SToby Isaac #endif 45520cf1dd8SToby Isaac } 45616cd844bSPierre Jolivet PetscCall(PetscFEEvaluateFieldJets_Internal(ds, Nf, 0, q, T, &fegeom, &coefficients[cOffset], PetscSafePointerPlusOffset(coefficients_t, cOffset), u, u_x, u_t)); 4579566063dSJacob Faibussowitsch if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL)); 458ac9d17c7SMatthew G. Knepley for (i = 0; i < n0; ++i) f0_func[i](dE, 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]); 459ef0bb6c7SMatthew G. Knepley for (c = 0; c < T[field]->Nc; ++c) f0[q * T[field]->Nc + c] *= w; 460ac9d17c7SMatthew G. Knepley for (i = 0; i < n1; ++i) f1_func[i](dE, 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 * dE]); 4619371c9d4SSatish Balay for (c = 0; c < T[field]->Nc; ++c) 462ac9d17c7SMatthew G. Knepley for (d = 0; d < dE; ++d) f1[(q * T[field]->Nc + c) * dE + d] *= w; 463b8025e53SMatthew G. Knepley if (debug) { 464e8e188d2SZach Atkins // LCOV_EXCL_START 465e8e188d2SZach Atkins PetscCall(PetscPrintf(PETSC_COMM_SELF, " quad point %" PetscInt_FMT " wt %g x:", q, (double)quadWeights[q])); 466e8e188d2SZach Atkins for (c = 0; c < dE; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %g", (double)fegeom.v[c])); 467e8e188d2SZach Atkins PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 468b8025e53SMatthew G. Knepley if (debug > 2) { 46963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " field %" PetscInt_FMT ":", field)); 47063a3b9bcSJacob Faibussowitsch for (c = 0; c < T[field]->Nc; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %g", (double)PetscRealPart(u[uOff[field] + c]))); 4719566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 472e8e188d2SZach Atkins PetscCall(PetscPrintf(PETSC_COMM_SELF, " field der %" PetscInt_FMT ":", field)); 473e8e188d2SZach Atkins for (c = 0; c < T[field]->Nc * dE; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %g", (double)PetscRealPart(u_x[uOff[field] + c]))); 474e8e188d2SZach Atkins PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 47563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " resid %" PetscInt_FMT ":", field)); 47663a3b9bcSJacob Faibussowitsch for (c = 0; c < T[field]->Nc; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %g", (double)PetscRealPart(f0[q * T[field]->Nc + c]))); 4779566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 478e8e188d2SZach Atkins PetscCall(PetscPrintf(PETSC_COMM_SELF, " res der %" PetscInt_FMT ":", field)); 479e8e188d2SZach Atkins for (c = 0; c < T[field]->Nc; ++c) { 480ac9d17c7SMatthew G. Knepley for (d = 0; d < dE; ++d) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %g", (double)PetscRealPart(f1[(q * T[field]->Nc + c) * dE + d]))); 481b8025e53SMatthew G. Knepley } 482e8e188d2SZach Atkins PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 483e8e188d2SZach Atkins } 484e8e188d2SZach Atkins // LCOV_EXCL_STOP 485b8025e53SMatthew G. Knepley } 48620cf1dd8SToby Isaac } 4879566063dSJacob Faibussowitsch PetscCall(PetscFEUpdateElementVec_Internal(fe, T[field], 0, basisReal, basisDerReal, e, cgeom, f0, f1, &elemVec[cOffset + fOffset])); 48820cf1dd8SToby Isaac cOffset += totDim; 48920cf1dd8SToby Isaac cOffsetAux += totDimAux; 49020cf1dd8SToby Isaac } 4913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49220cf1dd8SToby Isaac } 49320cf1dd8SToby Isaac 494d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEIntegrateBdResidual_Basic(PetscDS ds, PetscWeakForm wf, PetscFormKey key, PetscInt Ne, PetscFEGeom *fgeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[]) 495d71ae5a4SJacob Faibussowitsch { 496b2deab97SMatthew G. Knepley const PetscInt debug = ds->printIntegrate; 49706d8a0d3SMatthew G. Knepley const PetscInt field = key.field; 4984bee2e38SMatthew G. Knepley PetscFE fe; 49906d8a0d3SMatthew G. Knepley PetscInt n0, n1, i; 500*2192575eSBarry Smith PetscBdPointFn **f0_func, **f1_func; 50120cf1dd8SToby Isaac PetscQuadrature quad; 502ef0bb6c7SMatthew G. Knepley PetscTabulation *Tf, *TfAux = NULL; 5034bee2e38SMatthew G. Knepley PetscScalar *f0, *f1, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal; 50420cf1dd8SToby Isaac const PetscScalar *constants; 50587510d7dSMatthew G. Knepley PetscReal *x, cellScale; 506ef0bb6c7SMatthew G. Knepley PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL; 507ef0bb6c7SMatthew G. Knepley PetscInt dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimAux = 0, cOffset = 0, cOffsetAux = 0, fOffset, e, NcI; 5086587ee25SMatthew G. Knepley PetscBool auxOnBd = PETSC_FALSE; 50920cf1dd8SToby Isaac const PetscReal *quadPoints, *quadWeights; 5106587ee25SMatthew G. Knepley PetscInt qdim, qNc, Nq, q, dE; 51120cf1dd8SToby Isaac 51220cf1dd8SToby Isaac PetscFunctionBegin; 5139566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, field, (PetscObject *)&fe)); 5149566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(fe, &dim)); 51587510d7dSMatthew G. Knepley cellScale = (PetscReal)PetscPowInt(2, dim); 5169566063dSJacob Faibussowitsch PetscCall(PetscFEGetFaceQuadrature(fe, &quad)); 5179566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 5189566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim)); 5199566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(ds, &uOff)); 5209566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(ds, &uOff_x)); 5219566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffset(ds, field, &fOffset)); 5229566063dSJacob Faibussowitsch PetscCall(PetscWeakFormGetBdResidual(wf, key.label, key.value, key.field, key.part, &n0, &f0_func, &n1, &f1_func)); 5233ba16761SJacob Faibussowitsch if (!n0 && !n1) PetscFunctionReturn(PETSC_SUCCESS); 5249566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x)); 5259566063dSJacob Faibussowitsch PetscCall(PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL)); 5269566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakFormArrays(ds, &f0, &f1, NULL, NULL, NULL, NULL)); 5279566063dSJacob Faibussowitsch PetscCall(PetscDSGetFaceTabulation(ds, &Tf)); 52887510d7dSMatthew G. Knepley PetscCall(PetscDSSetIntegrationParameters(ds, field, PETSC_DETERMINE)); 5299566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 5304bee2e38SMatthew G. Knepley if (dsAux) { 5319566063dSJacob Faibussowitsch PetscCall(PetscDSGetSpatialDimension(dsAux, &dimAux)); 5329566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(dsAux, &NfAux)); 5339566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux)); 5349566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff)); 5359566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x)); 5369566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x)); 5377be5e748SToby Isaac auxOnBd = dimAux < dim ? PETSC_TRUE : PETSC_FALSE; 5389566063dSJacob Faibussowitsch if (auxOnBd) PetscCall(PetscDSGetTabulation(dsAux, &TfAux)); 5399566063dSJacob Faibussowitsch else PetscCall(PetscDSGetFaceTabulation(dsAux, &TfAux)); 54063a3b9bcSJacob Faibussowitsch PetscCheck(Tf[0]->Np == TfAux[0]->Np, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of tabulation points %" PetscInt_FMT " != %" PetscInt_FMT " number of auxiliary tabulation points", Tf[0]->Np, TfAux[0]->Np); 54120cf1dd8SToby Isaac } 542ef0bb6c7SMatthew G. Knepley NcI = Tf[field]->Nc; 5439566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, &qdim, &qNc, &Nq, &quadPoints, &quadWeights)); 54463a3b9bcSJacob Faibussowitsch PetscCheck(qNc == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %" PetscInt_FMT " components", qNc); 54520cf1dd8SToby Isaac dE = fgeom->dimEmbed; 5466587ee25SMatthew G. Knepley /* TODO FIX THIS */ 5476587ee25SMatthew G. Knepley fgeom->dim = dim - 1; 54863a3b9bcSJacob Faibussowitsch PetscCheck(fgeom->dim == qdim, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "FEGeom dim %" PetscInt_FMT " != %" PetscInt_FMT " quadrature dim", fgeom->dim, qdim); 54920cf1dd8SToby Isaac for (e = 0; e < Ne; ++e) { 5509f209ee4SMatthew G. Knepley PetscFEGeom fegeom, cgeom; 55120cf1dd8SToby Isaac const PetscInt face = fgeom->face[e][0]; 5529f209ee4SMatthew G. Knepley 5536587ee25SMatthew G. Knepley fegeom.v = x; /* Workspace */ 5549566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(f0, Nq * NcI)); 5559566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(f1, Nq * NcI * dE)); 55620cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 5574bee2e38SMatthew G. Knepley PetscReal w; 5584bee2e38SMatthew G. Knepley PetscInt c, d; 5594bee2e38SMatthew G. Knepley 5609566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetPoint(fgeom, e, q, &quadPoints[q * fgeom->dim], &fegeom)); 5619566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetCellPoint(fgeom, e, q, &cgeom)); 56287510d7dSMatthew G. Knepley PetscCall(PetscDSSetCellParameters(ds, fegeom.detJ[0] * cellScale)); 5634bee2e38SMatthew G. Knepley w = fegeom.detJ[0] * quadWeights[q]; 56462bd480fSMatthew G. Knepley if (debug > 1) { 5656587ee25SMatthew G. Knepley if ((fgeom->isAffine && q == 0) || (!fgeom->isAffine)) { 56663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " detJ: %g\n", (double)fegeom.detJ[0])); 5677be5e748SToby Isaac #if !defined(PETSC_USE_COMPLEX) 5689566063dSJacob Faibussowitsch PetscCall(DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ)); 5699566063dSJacob Faibussowitsch PetscCall(DMPrintCellVector(e, "n", dim, fegeom.n)); 57020cf1dd8SToby Isaac #endif 57120cf1dd8SToby Isaac } 57262bd480fSMatthew G. Knepley } 5738e3a54c0SPierre Jolivet PetscCall(PetscFEEvaluateFieldJets_Internal(ds, Nf, face, q, Tf, &cgeom, &coefficients[cOffset], PetscSafePointerPlusOffset(coefficients_t, cOffset), u, u_x, u_t)); 5749566063dSJacob Faibussowitsch if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, auxOnBd ? 0 : face, q, TfAux, &cgeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL)); 575ac9d17c7SMatthew G. Knepley for (i = 0; i < n0; ++i) f0_func[i](dE, 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]); 5764bee2e38SMatthew G. Knepley for (c = 0; c < NcI; ++c) f0[q * NcI + c] *= w; 577ac9d17c7SMatthew G. Knepley for (i = 0; i < n1; ++i) f1_func[i](dE, 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 * dE]); 5789371c9d4SSatish Balay for (c = 0; c < NcI; ++c) 579ac9d17c7SMatthew G. Knepley for (d = 0; d < dE; ++d) f1[(q * NcI + c) * dE + d] *= w; 58062bd480fSMatthew G. Knepley if (debug) { 58163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " elem %" PetscInt_FMT " quad point %" PetscInt_FMT "\n", e, q)); 58262bd480fSMatthew G. Knepley for (c = 0; c < NcI; ++c) { 58363a3b9bcSJacob Faibussowitsch if (n0) PetscCall(PetscPrintf(PETSC_COMM_SELF, " f0[%" PetscInt_FMT "] %g\n", c, (double)PetscRealPart(f0[q * NcI + c]))); 58462bd480fSMatthew G. Knepley if (n1) { 58563a3b9bcSJacob Faibussowitsch for (d = 0; d < dim; ++d) PetscCall(PetscPrintf(PETSC_COMM_SELF, " f1[%" PetscInt_FMT ",%" PetscInt_FMT "] %g", c, d, (double)PetscRealPart(f1[(q * NcI + c) * dim + d]))); 5869566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 58762bd480fSMatthew G. Knepley } 58862bd480fSMatthew G. Knepley } 58962bd480fSMatthew G. Knepley } 59020cf1dd8SToby Isaac } 5919566063dSJacob Faibussowitsch PetscCall(PetscFEUpdateElementVec_Internal(fe, Tf[field], face, basisReal, basisDerReal, e, fgeom, f0, f1, &elemVec[cOffset + fOffset])); 59220cf1dd8SToby Isaac cOffset += totDim; 59320cf1dd8SToby Isaac cOffsetAux += totDimAux; 59420cf1dd8SToby Isaac } 5953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59620cf1dd8SToby Isaac } 59720cf1dd8SToby Isaac 59827f02ce8SMatthew G. Knepley /* 59927f02ce8SMatthew 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 60027f02ce8SMatthew G. Knepley all transforms operate in the full space and are square. 60127f02ce8SMatthew G. Knepley 60227f02ce8SMatthew G. Knepley HybridIntegral: The discretization is lower dimensional. That means the transforms are non-square. 60327f02ce8SMatthew G. Knepley 1) DMPlexGetCellFields() retrieves from the hybrid cell, so it gets fields from both faces 60427f02ce8SMatthew G. Knepley 2) We need to assume that the orientation is 0 for both 60527f02ce8SMatthew 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() 60627f02ce8SMatthew G. Knepley */ 607989fa639SBrad Aagaard PETSC_INTERN PetscErrorCode PetscFEIntegrateHybridResidual_Basic(PetscDS ds, PetscDS dsIn, PetscFormKey key, PetscInt s, PetscInt Ne, PetscFEGeom *fgeom, PetscFEGeom *nbrgeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[]) 608d71ae5a4SJacob Faibussowitsch { 609b2deab97SMatthew G. Knepley const PetscInt debug = ds->printIntegrate; 6106528b96dSMatthew G. Knepley const PetscInt field = key.field; 61127f02ce8SMatthew G. Knepley PetscFE fe; 6126528b96dSMatthew G. Knepley PetscWeakForm wf; 6136528b96dSMatthew G. Knepley PetscInt n0, n1, i; 614*2192575eSBarry Smith PetscBdPointFn **f0_func, **f1_func; 61527f02ce8SMatthew G. Knepley PetscQuadrature quad; 6160e18dc48SMatthew G. Knepley DMPolytopeType ct; 61707218a29SMatthew G. Knepley PetscTabulation *Tf, *TfIn, *TfAux = NULL; 61827f02ce8SMatthew G. Knepley PetscScalar *f0, *f1, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal; 61927f02ce8SMatthew G. Knepley const PetscScalar *constants; 62027f02ce8SMatthew G. Knepley PetscReal *x; 621665f567fSMatthew G. Knepley PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL; 62207218a29SMatthew G. Knepley PetscInt dim, dimAux, numConstants, Nf, NfAux = 0, totDim, totDimIn, totDimAux = 0, cOffset = 0, cOffsetIn = 0, cOffsetAux = 0, fOffset, e, NcI, NcS; 6236587ee25SMatthew G. Knepley PetscBool isCohesiveField, auxOnBd = PETSC_FALSE; 62427f02ce8SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 6256587ee25SMatthew G. Knepley PetscInt qdim, qNc, Nq, q, dE; 62627f02ce8SMatthew G. Knepley 62727f02ce8SMatthew G. Knepley PetscFunctionBegin; 62827f02ce8SMatthew G. Knepley /* Hybrid discretization is posed directly on faces */ 6299566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, field, (PetscObject *)&fe)); 6309566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(fe, &dim)); 6319566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quad)); 6329566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 6339566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim)); 63407218a29SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsIn, &totDimIn)); 635429ebbe4SMatthew G. Knepley PetscCall(PetscDSGetComponentOffsetsCohesive(dsIn, 0, &uOff)); // Change 0 to s for one-sided offsets 63607218a29SMatthew G. Knepley PetscCall(PetscDSGetComponentDerivativeOffsetsCohesive(dsIn, s, &uOff_x)); 6379566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffsetCohesive(ds, field, &fOffset)); 6389566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 6399566063dSJacob Faibussowitsch PetscCall(PetscWeakFormGetBdResidual(wf, key.label, key.value, key.field, key.part, &n0, &f0_func, &n1, &f1_func)); 6403ba16761SJacob Faibussowitsch if (!n0 && !n1) PetscFunctionReturn(PETSC_SUCCESS); 6419566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x)); 6429566063dSJacob Faibussowitsch PetscCall(PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, NULL, NULL)); 6439566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakFormArrays(ds, &f0, &f1, NULL, NULL, NULL, NULL)); 64427f02ce8SMatthew G. Knepley /* NOTE This is a bulk tabulation because the DS is a face discretization */ 6459566063dSJacob Faibussowitsch PetscCall(PetscDSGetTabulation(ds, &Tf)); 64607218a29SMatthew G. Knepley PetscCall(PetscDSGetFaceTabulation(dsIn, &TfIn)); 64787510d7dSMatthew G. Knepley PetscCall(PetscDSSetIntegrationParameters(ds, field, PETSC_DETERMINE)); 6489566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 64927f02ce8SMatthew G. Knepley if (dsAux) { 6509566063dSJacob Faibussowitsch PetscCall(PetscDSGetSpatialDimension(dsAux, &dimAux)); 6519566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(dsAux, &NfAux)); 6529566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux)); 6539566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff)); 6549566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x)); 6559566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x)); 65601907d53SMatthew G. Knepley auxOnBd = dimAux == dim ? PETSC_TRUE : PETSC_FALSE; 6579566063dSJacob Faibussowitsch if (auxOnBd) PetscCall(PetscDSGetTabulation(dsAux, &TfAux)); 6589566063dSJacob Faibussowitsch else PetscCall(PetscDSGetFaceTabulation(dsAux, &TfAux)); 65963a3b9bcSJacob Faibussowitsch PetscCheck(Tf[0]->Np == TfAux[0]->Np, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of tabulation points %" PetscInt_FMT " != %" PetscInt_FMT " number of auxiliary tabulation points", Tf[0]->Np, TfAux[0]->Np); 66027f02ce8SMatthew G. Knepley } 6619566063dSJacob Faibussowitsch PetscCall(PetscDSGetCohesive(ds, field, &isCohesiveField)); 662665f567fSMatthew G. Knepley NcI = Tf[field]->Nc; 663c2b7495fSMatthew G. Knepley NcS = NcI; 6640abb75b6SMatthew G. Knepley if (!isCohesiveField && s == 2) { 6650abb75b6SMatthew G. Knepley // If we are integrating over a cohesive cell (s = 2) for a non-cohesive fields, we use both sides 6660abb75b6SMatthew G. Knepley NcS *= 2; 6670abb75b6SMatthew G. Knepley } 6689566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, &qdim, &qNc, &Nq, &quadPoints, &quadWeights)); 6690e18dc48SMatthew G. Knepley PetscCall(PetscQuadratureGetCellType(quad, &ct)); 67063a3b9bcSJacob Faibussowitsch PetscCheck(qNc == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %" PetscInt_FMT " components", qNc); 67127f02ce8SMatthew G. Knepley dE = fgeom->dimEmbed; 67263a3b9bcSJacob Faibussowitsch PetscCheck(fgeom->dim == qdim, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "FEGeom dim %" PetscInt_FMT " != %" PetscInt_FMT " quadrature dim", fgeom->dim, qdim); 67327f02ce8SMatthew G. Knepley for (e = 0; e < Ne; ++e) { 674989fa639SBrad Aagaard // In order for the face information to be correct, the support of endcap faces _must_ be correctly oriented 675989fa639SBrad Aagaard PetscFEGeom fegeom, fegeomN[2]; 6760e18dc48SMatthew G. Knepley const PetscInt face[2] = {fgeom->face[e * 2 + 0][0], fgeom->face[e * 2 + 1][2]}; 6770e18dc48SMatthew G. Knepley const PetscInt ornt[2] = {fgeom->face[e * 2 + 0][1], fgeom->face[e * 2 + 1][3]}; 6784e913f38SMatthew G. Knepley const PetscInt cornt[2] = {fgeom->face[e * 2 + 0][3], fgeom->face[e * 2 + 1][1]}; 67927f02ce8SMatthew G. Knepley 6806587ee25SMatthew G. Knepley fegeom.v = x; /* Workspace */ 6819566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(f0, Nq * NcS)); 6829566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(f1, Nq * NcS * dE)); 68327f02ce8SMatthew G. Knepley for (q = 0; q < Nq; ++q) { 6840e18dc48SMatthew G. Knepley PetscInt qpt[2]; 68527f02ce8SMatthew G. Knepley PetscReal w; 68627f02ce8SMatthew G. Knepley PetscInt c, d; 68727f02ce8SMatthew G. Knepley 6884e913f38SMatthew G. Knepley PetscCall(PetscDSPermuteQuadPoint(ds, DMPolytopeTypeComposeOrientationInv(ct, cornt[0], ornt[0]), field, q, &qpt[0])); 6894e913f38SMatthew G. Knepley PetscCall(PetscDSPermuteQuadPoint(ds, DMPolytopeTypeComposeOrientationInv(ct, ornt[1], cornt[1]), field, q, &qpt[1])); 69007218a29SMatthew G. Knepley PetscCall(PetscFEGeomGetPoint(fgeom, e * 2, q, &quadPoints[q * fgeom->dim], &fegeom)); 691989fa639SBrad Aagaard PetscCall(PetscFEGeomGetPoint(nbrgeom, e * 2, q, NULL, &fegeomN[0])); 692989fa639SBrad Aagaard PetscCall(PetscFEGeomGetPoint(nbrgeom, e * 2 + 1, q, NULL, &fegeomN[1])); 69327f02ce8SMatthew G. Knepley w = fegeom.detJ[0] * quadWeights[q]; 6946587ee25SMatthew G. Knepley if (debug > 1 && q < fgeom->numPoints) { 69563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " detJ: %g\n", (double)fegeom.detJ[0])); 69627f02ce8SMatthew G. Knepley #if !defined(PETSC_USE_COMPLEX) 6979566063dSJacob Faibussowitsch PetscCall(DMPrintCellMatrix(e, "invJ", dim, dE, fegeom.invJ)); 69827f02ce8SMatthew G. Knepley #endif 69927f02ce8SMatthew G. Knepley } 700a4158a15SMatthew G. Knepley if (debug) PetscCall(PetscPrintf(PETSC_COMM_SELF, " quad point %" PetscInt_FMT " weight %g detJ %g\n", q, (double)quadWeights[q], (double)fegeom.detJ[0])); 70127f02ce8SMatthew G. Knepley /* TODO Is this cell or face quadrature, meaning should we use 'q' or 'face*Nq+q' */ 702989fa639SBrad Aagaard PetscCall(PetscFEEvaluateFieldJets_Hybrid_Internal(dsIn, Nf, 0, q, Tf, face, qpt, TfIn, &fegeom, fegeomN, &coefficients[cOffsetIn], PetscSafePointerPlusOffset(coefficients_t, cOffsetIn), u, u_x, u_t)); 70307218a29SMatthew G. Knepley if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, auxOnBd ? 0 : face[s], auxOnBd ? q : qpt[s], TfAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL)); 704ac9d17c7SMatthew G. Knepley for (i = 0; i < n0; ++i) f0_func[i](dE, 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]); 70527f02ce8SMatthew G. Knepley for (c = 0; c < NcS; ++c) f0[q * NcS + c] *= w; 706ac9d17c7SMatthew G. Knepley for (i = 0; i < n1; ++i) f1_func[i](dE, 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 * dE]); 7079371c9d4SSatish Balay for (c = 0; c < NcS; ++c) 7089371c9d4SSatish Balay for (d = 0; d < dE; ++d) f1[(q * NcS + c) * dE + d] *= w; 70988409cc3SMatthew G. Knepley if (debug) { 71088409cc3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, " elem %" PetscInt_FMT " quad point %" PetscInt_FMT " field %" PetscInt_FMT " side %" PetscInt_FMT "\n", e, q, field, s)); 71188409cc3SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 71288409cc3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, " Field %" PetscInt_FMT ":", f)); 71388409cc3SMatthew G. Knepley for (PetscInt c = uOff[f]; c < uOff[f + 1]; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %g", (double)PetscRealPart(u[c]))); 71488409cc3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 71588409cc3SMatthew G. Knepley } 71688409cc3SMatthew G. Knepley for (c = 0; c < NcS; ++c) { 71788409cc3SMatthew G. Knepley if (n0) PetscCall(PetscPrintf(PETSC_COMM_SELF, " f0[%" PetscInt_FMT "] %g\n", c, (double)PetscRealPart(f0[q * NcS + c]))); 71888409cc3SMatthew G. Knepley if (n1) { 71988409cc3SMatthew G. Knepley for (d = 0; d < dE; ++d) PetscCall(PetscPrintf(PETSC_COMM_SELF, " f1[%" PetscInt_FMT ",%" PetscInt_FMT "] %g", c, d, (double)PetscRealPart(f1[(q * NcS + c) * dE + d]))); 72088409cc3SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 72188409cc3SMatthew G. Knepley } 72288409cc3SMatthew G. Knepley } 72388409cc3SMatthew G. Knepley } 72427f02ce8SMatthew G. Knepley } 7259371c9d4SSatish Balay if (isCohesiveField) { 7263ba16761SJacob Faibussowitsch PetscCall(PetscFEUpdateElementVec_Internal(fe, Tf[field], 0, basisReal, basisDerReal, e, fgeom, f0, f1, &elemVec[cOffset + fOffset])); 7279371c9d4SSatish Balay } else { 7283ba16761SJacob Faibussowitsch PetscCall(PetscFEUpdateElementVec_Hybrid_Internal(fe, Tf[field], 0, s, basisReal, basisDerReal, fgeom, f0, f1, &elemVec[cOffset + fOffset])); 7299371c9d4SSatish Balay } 73027f02ce8SMatthew G. Knepley cOffset += totDim; 73107218a29SMatthew G. Knepley cOffsetIn += totDimIn; 73227f02ce8SMatthew G. Knepley cOffsetAux += totDimAux; 73327f02ce8SMatthew G. Knepley } 7343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 73527f02ce8SMatthew G. Knepley } 73627f02ce8SMatthew G. Knepley 737d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFEIntegrateJacobian_Basic(PetscDS ds, PetscFEJacobianType jtype, PetscFormKey key, PetscInt Ne, PetscFEGeom *cgeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[]) 738d71ae5a4SJacob Faibussowitsch { 739b2deab97SMatthew G. Knepley const PetscInt debug = ds->printIntegrate; 7404bee2e38SMatthew G. Knepley PetscFE feI, feJ; 7416528b96dSMatthew G. Knepley PetscWeakForm wf; 742*2192575eSBarry Smith PetscPointJacFn **g0_func, **g1_func, **g2_func, **g3_func; 7436528b96dSMatthew G. Knepley PetscInt n0, n1, n2, n3, i; 74420cf1dd8SToby Isaac PetscInt cOffset = 0; /* Offset into coefficients[] for element e */ 74520cf1dd8SToby Isaac PetscInt cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */ 74620cf1dd8SToby Isaac PetscInt eOffset = 0; /* Offset into elemMat[] for element e */ 74720cf1dd8SToby Isaac PetscInt offsetI = 0; /* Offset into an element vector for fieldI */ 74820cf1dd8SToby Isaac PetscInt offsetJ = 0; /* Offset into an element vector for fieldJ */ 74920cf1dd8SToby Isaac PetscQuadrature quad; 750ef0bb6c7SMatthew G. Knepley PetscTabulation *T, *TAux = NULL; 7511a768569SStefano Zampini PetscScalar *g0 = NULL, *g1 = NULL, *g2 = NULL, *g3 = NULL, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal; 75220cf1dd8SToby Isaac const PetscScalar *constants; 75387510d7dSMatthew G. Knepley PetscReal *x, cellScale; 754ef0bb6c7SMatthew G. Knepley PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL; 755ef0bb6c7SMatthew G. Knepley PetscInt NcI = 0, NcJ = 0; 7566528b96dSMatthew G. Knepley PetscInt dim, numConstants, Nf, fieldI, fieldJ, NfAux = 0, totDim, totDimAux = 0, e; 75720cf1dd8SToby Isaac PetscInt dE, Np; 75820cf1dd8SToby Isaac PetscBool isAffine; 75920cf1dd8SToby Isaac const PetscReal *quadPoints, *quadWeights; 76020cf1dd8SToby Isaac PetscInt qNc, Nq, q; 76120cf1dd8SToby Isaac 76220cf1dd8SToby Isaac PetscFunctionBegin; 7639566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 7646528b96dSMatthew G. Knepley fieldI = key.field / Nf; 7656528b96dSMatthew G. Knepley fieldJ = key.field % Nf; 7669566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, fieldI, (PetscObject *)&feI)); 7679566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, fieldJ, (PetscObject *)&feJ)); 7689566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(feI, &dim)); 76987510d7dSMatthew G. Knepley cellScale = (PetscReal)PetscPowInt(2, dim); 7709566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(feI, &quad)); 7719566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim)); 7729566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(ds, &uOff)); 7739566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(ds, &uOff_x)); 7749566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 77520cf1dd8SToby Isaac switch (jtype) { 776d71ae5a4SJacob Faibussowitsch case PETSCFE_JACOBIAN_DYN: 777d71ae5a4SJacob Faibussowitsch PetscCall(PetscWeakFormGetDynamicJacobian(wf, key.label, key.value, fieldI, fieldJ, key.part, &n0, &g0_func, &n1, &g1_func, &n2, &g2_func, &n3, &g3_func)); 778d71ae5a4SJacob Faibussowitsch break; 779d71ae5a4SJacob Faibussowitsch case PETSCFE_JACOBIAN_PRE: 780d71ae5a4SJacob Faibussowitsch PetscCall(PetscWeakFormGetJacobianPreconditioner(wf, key.label, key.value, fieldI, fieldJ, key.part, &n0, &g0_func, &n1, &g1_func, &n2, &g2_func, &n3, &g3_func)); 781d71ae5a4SJacob Faibussowitsch break; 782d71ae5a4SJacob Faibussowitsch case PETSCFE_JACOBIAN: 783d71ae5a4SJacob Faibussowitsch PetscCall(PetscWeakFormGetJacobian(wf, key.label, key.value, fieldI, fieldJ, key.part, &n0, &g0_func, &n1, &g1_func, &n2, &g2_func, &n3, &g3_func)); 784d71ae5a4SJacob Faibussowitsch break; 78520cf1dd8SToby Isaac } 7863ba16761SJacob Faibussowitsch if (!n0 && !n1 && !n2 && !n3) PetscFunctionReturn(PETSC_SUCCESS); 7879566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x)); 7889566063dSJacob Faibussowitsch PetscCall(PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal)); 7891a768569SStefano Zampini PetscCall(PetscDSGetWeakFormArrays(ds, NULL, NULL, n0 ? &g0 : NULL, n1 ? &g1 : NULL, n2 ? &g2 : NULL, n3 ? &g3 : NULL)); 7901a768569SStefano Zampini 7919566063dSJacob Faibussowitsch PetscCall(PetscDSGetTabulation(ds, &T)); 7929566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffset(ds, fieldI, &offsetI)); 7939566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffset(ds, fieldJ, &offsetJ)); 794a102dd69SStefano Zampini PetscCall(PetscDSSetIntegrationParameters(ds, fieldI, fieldJ)); 7959566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 7964bee2e38SMatthew G. Knepley if (dsAux) { 7979566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(dsAux, &NfAux)); 7989566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux)); 7999566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff)); 8009566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x)); 8019566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x)); 8029566063dSJacob Faibussowitsch PetscCall(PetscDSGetTabulation(dsAux, &TAux)); 80363a3b9bcSJacob Faibussowitsch PetscCheck(T[0]->Np == TAux[0]->Np, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of tabulation points %" PetscInt_FMT " != %" PetscInt_FMT " number of auxiliary tabulation points", T[0]->Np, TAux[0]->Np); 80420cf1dd8SToby Isaac } 80527f02ce8SMatthew G. Knepley NcI = T[fieldI]->Nc; 80627f02ce8SMatthew G. Knepley NcJ = T[fieldJ]->Nc; 8074bee2e38SMatthew G. Knepley Np = cgeom->numPoints; 8084bee2e38SMatthew G. Knepley dE = cgeom->dimEmbed; 8094bee2e38SMatthew G. Knepley isAffine = cgeom->isAffine; 8109566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights)); 81163a3b9bcSJacob Faibussowitsch PetscCheck(qNc == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %" PetscInt_FMT " components", qNc); 8121a768569SStefano Zampini 8134bee2e38SMatthew G. Knepley for (e = 0; e < Ne; ++e) { 8144bee2e38SMatthew G. Knepley PetscFEGeom fegeom; 8154bee2e38SMatthew G. Knepley 81627f02ce8SMatthew G. Knepley fegeom.dim = cgeom->dim; 81727f02ce8SMatthew G. Knepley fegeom.dimEmbed = cgeom->dimEmbed; 8184bee2e38SMatthew G. Knepley if (isAffine) { 8194bee2e38SMatthew G. Knepley fegeom.v = x; 8204bee2e38SMatthew G. Knepley fegeom.xi = cgeom->xi; 8217132c3f7SMatthew G. Knepley fegeom.J = &cgeom->J[e * Np * dE * dE]; 8227132c3f7SMatthew G. Knepley fegeom.invJ = &cgeom->invJ[e * Np * dE * dE]; 8237132c3f7SMatthew G. Knepley fegeom.detJ = &cgeom->detJ[e * Np]; 8244bee2e38SMatthew G. Knepley } 82520cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 82620cf1dd8SToby Isaac PetscReal w; 8274bee2e38SMatthew G. Knepley PetscInt c; 82820cf1dd8SToby Isaac 82920cf1dd8SToby Isaac if (isAffine) { 8307132c3f7SMatthew G. Knepley CoordinatesRefToReal(dE, dim, fegeom.xi, &cgeom->v[e * Np * dE], fegeom.J, &quadPoints[q * dim], x); 83120cf1dd8SToby Isaac } else { 8324bee2e38SMatthew G. Knepley fegeom.v = &cgeom->v[(e * Np + q) * dE]; 8334bee2e38SMatthew G. Knepley fegeom.J = &cgeom->J[(e * Np + q) * dE * dE]; 8344bee2e38SMatthew G. Knepley fegeom.invJ = &cgeom->invJ[(e * Np + q) * dE * dE]; 8354bee2e38SMatthew G. Knepley fegeom.detJ = &cgeom->detJ[e * Np + q]; 83620cf1dd8SToby Isaac } 83787510d7dSMatthew G. Knepley PetscCall(PetscDSSetCellParameters(ds, fegeom.detJ[0] * cellScale)); 8389566063dSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(PETSC_COMM_SELF, " quad point %" PetscInt_FMT " weight %g detJ %g\n", q, (double)quadWeights[q], (double)fegeom.detJ[0])); 8394bee2e38SMatthew G. Knepley w = fegeom.detJ[0] * quadWeights[q]; 84016cd844bSPierre Jolivet if (coefficients) PetscCall(PetscFEEvaluateFieldJets_Internal(ds, Nf, 0, q, T, &fegeom, &coefficients[cOffset], PetscSafePointerPlusOffset(coefficients_t, cOffset), u, u_x, u_t)); 8419566063dSJacob Faibussowitsch if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, q, TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL)); 842ea672e62SMatthew G. Knepley if (n0) { 8439566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g0, NcI * NcJ)); 844ac9d17c7SMatthew G. Knepley for (i = 0; i < n0; ++i) g0_func[i](dE, 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); 84520cf1dd8SToby Isaac for (c = 0; c < NcI * NcJ; ++c) g0[c] *= w; 84620cf1dd8SToby Isaac } 847ea672e62SMatthew G. Knepley if (n1) { 8489566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g1, NcI * NcJ * dE)); 849ac9d17c7SMatthew G. Knepley for (i = 0; i < n1; ++i) g1_func[i](dE, 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); 8509b529ac9SStefano Zampini for (c = 0; c < NcI * NcJ * dE; ++c) g1[c] *= w; 85120cf1dd8SToby Isaac } 852ea672e62SMatthew G. Knepley if (n2) { 8539566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g2, NcI * NcJ * dE)); 854ac9d17c7SMatthew G. Knepley for (i = 0; i < n2; ++i) g2_func[i](dE, 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); 8559b529ac9SStefano Zampini for (c = 0; c < NcI * NcJ * dE; ++c) g2[c] *= w; 85620cf1dd8SToby Isaac } 857ea672e62SMatthew G. Knepley if (n3) { 8589566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g3, NcI * NcJ * dE * dE)); 859ac9d17c7SMatthew G. Knepley for (i = 0; i < n3; ++i) g3_func[i](dE, 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); 8609b529ac9SStefano Zampini for (c = 0; c < NcI * NcJ * dE * dE; ++c) g3[c] *= w; 86120cf1dd8SToby Isaac } 86220cf1dd8SToby Isaac 8631a768569SStefano Zampini PetscCall(PetscFEUpdateElementMat_Internal(feI, feJ, 0, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, g0, g1, g2, g3, totDim, offsetI, offsetJ, elemMat + eOffset)); 86420cf1dd8SToby Isaac } 86520cf1dd8SToby Isaac if (debug > 1) { 866699b48e5SStefano Zampini PetscInt f, g; 86720cf1dd8SToby Isaac 86863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %" PetscInt_FMT " and %" PetscInt_FMT "\n", fieldI, fieldJ)); 869ef0bb6c7SMatthew G. Knepley for (f = 0; f < T[fieldI]->Nb; ++f) { 870699b48e5SStefano Zampini const PetscInt i = offsetI + f; 871ef0bb6c7SMatthew G. Knepley for (g = 0; g < T[fieldJ]->Nb; ++g) { 872699b48e5SStefano Zampini const PetscInt j = offsetJ + g; 873699b48e5SStefano Zampini PetscCall(PetscPrintf(PETSC_COMM_SELF, " elemMat[%" PetscInt_FMT ", %" PetscInt_FMT "]: %g\n", f, g, (double)PetscRealPart(elemMat[eOffset + i * totDim + j]))); 87420cf1dd8SToby Isaac } 8759566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 87620cf1dd8SToby Isaac } 87720cf1dd8SToby Isaac } 87820cf1dd8SToby Isaac cOffset += totDim; 87920cf1dd8SToby Isaac cOffsetAux += totDimAux; 88020cf1dd8SToby Isaac eOffset += PetscSqr(totDim); 88120cf1dd8SToby Isaac } 8823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 88320cf1dd8SToby Isaac } 88420cf1dd8SToby Isaac 885e3d591f2SMatthew G. Knepley PETSC_INTERN PetscErrorCode PetscFEIntegrateBdJacobian_Basic(PetscDS ds, PetscWeakForm wf, PetscFEJacobianType jtype, PetscFormKey key, PetscInt Ne, PetscFEGeom *fgeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[]) 886d71ae5a4SJacob Faibussowitsch { 887b2deab97SMatthew G. Knepley const PetscInt debug = ds->printIntegrate; 8884bee2e38SMatthew G. Knepley PetscFE feI, feJ; 889*2192575eSBarry Smith PetscBdPointJacFn **g0_func, **g1_func, **g2_func, **g3_func; 89045480ffeSMatthew G. Knepley PetscInt n0, n1, n2, n3, i; 89120cf1dd8SToby Isaac PetscInt cOffset = 0; /* Offset into coefficients[] for element e */ 89220cf1dd8SToby Isaac PetscInt cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */ 89320cf1dd8SToby Isaac PetscInt eOffset = 0; /* Offset into elemMat[] for element e */ 89420cf1dd8SToby Isaac PetscInt offsetI = 0; /* Offset into an element vector for fieldI */ 89520cf1dd8SToby Isaac PetscInt offsetJ = 0; /* Offset into an element vector for fieldJ */ 89620cf1dd8SToby Isaac PetscQuadrature quad; 897ef0bb6c7SMatthew G. Knepley PetscTabulation *T, *TAux = NULL; 8984bee2e38SMatthew G. Knepley PetscScalar *g0, *g1, *g2, *g3, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal; 89920cf1dd8SToby Isaac const PetscScalar *constants; 90087510d7dSMatthew G. Knepley PetscReal *x, cellScale; 901ef0bb6c7SMatthew G. Knepley PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL; 902ef0bb6c7SMatthew G. Knepley PetscInt NcI = 0, NcJ = 0; 90345480ffeSMatthew G. Knepley PetscInt dim, numConstants, Nf, fieldI, fieldJ, NfAux = 0, totDim, totDimAux = 0, e; 90420cf1dd8SToby Isaac PetscBool isAffine; 90520cf1dd8SToby Isaac const PetscReal *quadPoints, *quadWeights; 90620cf1dd8SToby Isaac PetscInt qNc, Nq, q, Np, dE; 90720cf1dd8SToby Isaac 90820cf1dd8SToby Isaac PetscFunctionBegin; 9099566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 91045480ffeSMatthew G. Knepley fieldI = key.field / Nf; 91145480ffeSMatthew G. Knepley fieldJ = key.field % Nf; 9129566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, fieldI, (PetscObject *)&feI)); 9139566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, fieldJ, (PetscObject *)&feJ)); 9149566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(feI, &dim)); 91587510d7dSMatthew G. Knepley cellScale = (PetscReal)PetscPowInt(2, dim); 9169566063dSJacob Faibussowitsch PetscCall(PetscFEGetFaceQuadrature(feI, &quad)); 9179566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim)); 9189566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(ds, &uOff)); 9199566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(ds, &uOff_x)); 9209566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffset(ds, fieldI, &offsetI)); 9219566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffset(ds, fieldJ, &offsetJ)); 922e3d591f2SMatthew G. Knepley switch (jtype) { 923e3d591f2SMatthew G. Knepley case PETSCFE_JACOBIAN_PRE: 924e3d591f2SMatthew G. Knepley PetscCall(PetscWeakFormGetBdJacobianPreconditioner(wf, key.label, key.value, fieldI, fieldJ, key.part, &n0, &g0_func, &n1, &g1_func, &n2, &g2_func, &n3, &g3_func)); 925e3d591f2SMatthew G. Knepley break; 926e3d591f2SMatthew G. Knepley case PETSCFE_JACOBIAN: 9279566063dSJacob Faibussowitsch PetscCall(PetscWeakFormGetBdJacobian(wf, key.label, key.value, fieldI, fieldJ, key.part, &n0, &g0_func, &n1, &g1_func, &n2, &g2_func, &n3, &g3_func)); 928e3d591f2SMatthew G. Knepley break; 929e3d591f2SMatthew G. Knepley case PETSCFE_JACOBIAN_DYN: 930e3d591f2SMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "PETSCFE_JACOBIAN_DYN is not supported for PetscFEIntegrateBdJacobian()"); 931e3d591f2SMatthew G. Knepley } 9323ba16761SJacob Faibussowitsch if (!n0 && !n1 && !n2 && !n3) PetscFunctionReturn(PETSC_SUCCESS); 9339566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x)); 9349566063dSJacob Faibussowitsch PetscCall(PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal)); 9359566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakFormArrays(ds, NULL, NULL, &g0, &g1, &g2, &g3)); 9369566063dSJacob Faibussowitsch PetscCall(PetscDSGetFaceTabulation(ds, &T)); 93787510d7dSMatthew G. Knepley PetscCall(PetscDSSetIntegrationParameters(ds, fieldI, fieldJ)); 9389566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 9394bee2e38SMatthew G. Knepley if (dsAux) { 9409566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(dsAux, &NfAux)); 9419566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux)); 9429566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff)); 9439566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x)); 9449566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x)); 9459566063dSJacob Faibussowitsch PetscCall(PetscDSGetFaceTabulation(dsAux, &TAux)); 94620cf1dd8SToby Isaac } 947ef0bb6c7SMatthew G. Knepley NcI = T[fieldI]->Nc, NcJ = T[fieldJ]->Nc; 94820cf1dd8SToby Isaac Np = fgeom->numPoints; 94920cf1dd8SToby Isaac dE = fgeom->dimEmbed; 95020cf1dd8SToby Isaac isAffine = fgeom->isAffine; 95127f02ce8SMatthew G. Knepley /* Initialize here in case the function is not defined */ 9529566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g0, NcI * NcJ)); 9539566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g1, NcI * NcJ * dE)); 9549566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g2, NcI * NcJ * dE)); 9559566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g3, NcI * NcJ * dE * dE)); 9569566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights)); 95763a3b9bcSJacob Faibussowitsch PetscCheck(qNc == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %" PetscInt_FMT " components", qNc); 95820cf1dd8SToby Isaac for (e = 0; e < Ne; ++e) { 9599f209ee4SMatthew G. Knepley PetscFEGeom fegeom, cgeom; 96020cf1dd8SToby Isaac const PetscInt face = fgeom->face[e][0]; 961ea78f98cSLisandro Dalcin fegeom.n = NULL; 962ea78f98cSLisandro Dalcin fegeom.v = NULL; 963ea78f98cSLisandro Dalcin fegeom.J = NULL; 964ea78f98cSLisandro Dalcin fegeom.detJ = NULL; 96527f02ce8SMatthew G. Knepley fegeom.dim = fgeom->dim; 96627f02ce8SMatthew G. Knepley fegeom.dimEmbed = fgeom->dimEmbed; 96727f02ce8SMatthew G. Knepley cgeom.dim = fgeom->dim; 96827f02ce8SMatthew G. Knepley cgeom.dimEmbed = fgeom->dimEmbed; 9694bee2e38SMatthew G. Knepley if (isAffine) { 9704bee2e38SMatthew G. Knepley fegeom.v = x; 9714bee2e38SMatthew G. Knepley fegeom.xi = fgeom->xi; 9727132c3f7SMatthew G. Knepley fegeom.J = &fgeom->J[e * Np * dE * dE]; 9737132c3f7SMatthew G. Knepley fegeom.invJ = &fgeom->invJ[e * Np * dE * dE]; 9747132c3f7SMatthew G. Knepley fegeom.detJ = &fgeom->detJ[e * Np]; 9757132c3f7SMatthew G. Knepley fegeom.n = &fgeom->n[e * Np * dE]; 9769f209ee4SMatthew G. Knepley 9777132c3f7SMatthew G. Knepley cgeom.J = &fgeom->suppJ[0][e * Np * dE * dE]; 9787132c3f7SMatthew G. Knepley cgeom.invJ = &fgeom->suppInvJ[0][e * Np * dE * dE]; 9797132c3f7SMatthew G. Knepley cgeom.detJ = &fgeom->suppDetJ[0][e * Np]; 9804bee2e38SMatthew G. Knepley } 98120cf1dd8SToby Isaac for (q = 0; q < Nq; ++q) { 98220cf1dd8SToby Isaac PetscReal w; 9834bee2e38SMatthew G. Knepley PetscInt c; 98420cf1dd8SToby Isaac 98563a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(PETSC_COMM_SELF, " quad point %" PetscInt_FMT "\n", q)); 98620cf1dd8SToby Isaac if (isAffine) { 9877132c3f7SMatthew G. Knepley CoordinatesRefToReal(dE, dim - 1, fegeom.xi, &fgeom->v[e * Np * dE], fegeom.J, &quadPoints[q * (dim - 1)], x); 98820cf1dd8SToby Isaac } else { 9893fe841f2SMatthew G. Knepley fegeom.v = &fgeom->v[(e * Np + q) * dE]; 9909f209ee4SMatthew G. Knepley fegeom.J = &fgeom->J[(e * Np + q) * dE * dE]; 9919f209ee4SMatthew G. Knepley fegeom.invJ = &fgeom->invJ[(e * Np + q) * dE * dE]; 9924bee2e38SMatthew G. Knepley fegeom.detJ = &fgeom->detJ[e * Np + q]; 9934bee2e38SMatthew G. Knepley fegeom.n = &fgeom->n[(e * Np + q) * dE]; 9949f209ee4SMatthew G. Knepley 9959f209ee4SMatthew G. Knepley cgeom.J = &fgeom->suppJ[0][(e * Np + q) * dE * dE]; 9969f209ee4SMatthew G. Knepley cgeom.invJ = &fgeom->suppInvJ[0][(e * Np + q) * dE * dE]; 9979f209ee4SMatthew G. Knepley cgeom.detJ = &fgeom->suppDetJ[0][e * Np + q]; 99820cf1dd8SToby Isaac } 99987510d7dSMatthew G. Knepley PetscCall(PetscDSSetCellParameters(ds, fegeom.detJ[0] * cellScale)); 10004bee2e38SMatthew G. Knepley w = fegeom.detJ[0] * quadWeights[q]; 10019566063dSJacob Faibussowitsch if (coefficients) PetscCall(PetscFEEvaluateFieldJets_Internal(ds, Nf, face, q, T, &cgeom, &coefficients[cOffset], &coefficients_t[cOffset], u, u_x, u_t)); 10029566063dSJacob Faibussowitsch if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, face, q, TAux, &cgeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL)); 1003ea672e62SMatthew G. Knepley if (n0) { 10049566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g0, NcI * NcJ)); 1005ac9d17c7SMatthew G. Knepley for (i = 0; i < n0; ++i) g0_func[i](dE, 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); 100620cf1dd8SToby Isaac for (c = 0; c < NcI * NcJ; ++c) g0[c] *= w; 100720cf1dd8SToby Isaac } 1008ea672e62SMatthew G. Knepley if (n1) { 10099566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g1, NcI * NcJ * dE)); 1010ac9d17c7SMatthew G. Knepley for (i = 0; i < n1; ++i) g1_func[i](dE, 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); 10114bee2e38SMatthew G. Knepley for (c = 0; c < NcI * NcJ * dim; ++c) g1[c] *= w; 101220cf1dd8SToby Isaac } 1013ea672e62SMatthew G. Knepley if (n2) { 10149566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g2, NcI * NcJ * dE)); 1015ac9d17c7SMatthew G. Knepley for (i = 0; i < n2; ++i) g2_func[i](dE, 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); 10164bee2e38SMatthew G. Knepley for (c = 0; c < NcI * NcJ * dim; ++c) g2[c] *= w; 101720cf1dd8SToby Isaac } 1018ea672e62SMatthew G. Knepley if (n3) { 10199566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g3, NcI * NcJ * dE * dE)); 1020ac9d17c7SMatthew G. Knepley for (i = 0; i < n3; ++i) g3_func[i](dE, 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); 10214bee2e38SMatthew G. Knepley for (c = 0; c < NcI * NcJ * dim * dim; ++c) g3[c] *= w; 102220cf1dd8SToby Isaac } 102320cf1dd8SToby Isaac 10241a768569SStefano Zampini PetscCall(PetscFEUpdateElementMat_Internal(feI, feJ, face, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &cgeom, g0, g1, g2, g3, totDim, offsetI, offsetJ, elemMat + eOffset)); 102520cf1dd8SToby Isaac } 102620cf1dd8SToby Isaac if (debug > 1) { 102720cf1dd8SToby Isaac PetscInt fc, f, gc, g; 102820cf1dd8SToby Isaac 102963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %" PetscInt_FMT " and %" PetscInt_FMT "\n", fieldI, fieldJ)); 1030ef0bb6c7SMatthew G. Knepley for (fc = 0; fc < T[fieldI]->Nc; ++fc) { 1031ef0bb6c7SMatthew G. Knepley for (f = 0; f < T[fieldI]->Nb; ++f) { 1032ef0bb6c7SMatthew G. Knepley const PetscInt i = offsetI + f * T[fieldI]->Nc + fc; 1033ef0bb6c7SMatthew G. Knepley for (gc = 0; gc < T[fieldJ]->Nc; ++gc) { 1034ef0bb6c7SMatthew G. Knepley for (g = 0; g < T[fieldJ]->Nb; ++g) { 1035ef0bb6c7SMatthew G. Knepley const PetscInt j = offsetJ + g * T[fieldJ]->Nc + gc; 103663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " elemMat[%" PetscInt_FMT ",%" PetscInt_FMT ",%" PetscInt_FMT ",%" PetscInt_FMT "]: %g\n", f, fc, g, gc, (double)PetscRealPart(elemMat[eOffset + i * totDim + j]))); 103720cf1dd8SToby Isaac } 103820cf1dd8SToby Isaac } 10399566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 104020cf1dd8SToby Isaac } 104120cf1dd8SToby Isaac } 104220cf1dd8SToby Isaac } 104320cf1dd8SToby Isaac cOffset += totDim; 104420cf1dd8SToby Isaac cOffsetAux += totDimAux; 104520cf1dd8SToby Isaac eOffset += PetscSqr(totDim); 104620cf1dd8SToby Isaac } 10473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 104820cf1dd8SToby Isaac } 104920cf1dd8SToby Isaac 1050989fa639SBrad Aagaard PETSC_INTERN PetscErrorCode PetscFEIntegrateHybridJacobian_Basic(PetscDS ds, PetscDS dsIn, PetscFEJacobianType jtype, PetscFormKey key, PetscInt s, PetscInt Ne, PetscFEGeom *fgeom, PetscFEGeom *nbrgeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS dsAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[]) 1051d71ae5a4SJacob Faibussowitsch { 1052b2deab97SMatthew G. Knepley const PetscInt debug = ds->printIntegrate; 105327f02ce8SMatthew G. Knepley PetscFE feI, feJ; 1054148442b3SMatthew G. Knepley PetscWeakForm wf; 1055*2192575eSBarry Smith PetscBdPointJacFn **g0_func, **g1_func, **g2_func, **g3_func; 1056148442b3SMatthew G. Knepley PetscInt n0, n1, n2, n3, i; 105727f02ce8SMatthew G. Knepley PetscInt cOffset = 0; /* Offset into coefficients[] for element e */ 105827f02ce8SMatthew G. Knepley PetscInt cOffsetAux = 0; /* Offset into coefficientsAux[] for element e */ 105927f02ce8SMatthew G. Knepley PetscInt eOffset = 0; /* Offset into elemMat[] for element e */ 106027f02ce8SMatthew G. Knepley PetscInt offsetI = 0; /* Offset into an element vector for fieldI */ 106127f02ce8SMatthew G. Knepley PetscInt offsetJ = 0; /* Offset into an element vector for fieldJ */ 1062665f567fSMatthew G. Knepley PetscQuadrature quad; 10630e18dc48SMatthew G. Knepley DMPolytopeType ct; 106407218a29SMatthew G. Knepley PetscTabulation *T, *TfIn, *TAux = NULL; 106527f02ce8SMatthew G. Knepley PetscScalar *g0, *g1, *g2, *g3, *u, *u_t = NULL, *u_x, *a, *a_x, *basisReal, *basisDerReal, *testReal, *testDerReal; 106627f02ce8SMatthew G. Knepley const PetscScalar *constants; 106727f02ce8SMatthew G. Knepley PetscReal *x; 1068665f567fSMatthew G. Knepley PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL; 1069665f567fSMatthew G. Knepley PetscInt NcI = 0, NcJ = 0, NcS, NcT; 107045480ffeSMatthew G. Knepley PetscInt dim, dimAux, numConstants, Nf, fieldI, fieldJ, NfAux = 0, totDim, totDimAux = 0, e; 107107218a29SMatthew G. Knepley PetscBool isCohesiveFieldI, isCohesiveFieldJ, auxOnBd = PETSC_FALSE; 107227f02ce8SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 10730563a546SMatthew G. Knepley PetscInt qNc, Nq, q, dE; 107427f02ce8SMatthew G. Knepley 107527f02ce8SMatthew G. Knepley PetscFunctionBegin; 10769566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 107745480ffeSMatthew G. Knepley fieldI = key.field / Nf; 107845480ffeSMatthew G. Knepley fieldJ = key.field % Nf; 107927f02ce8SMatthew G. Knepley /* Hybrid discretization is posed directly on faces */ 10809566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, fieldI, (PetscObject *)&feI)); 10819566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, fieldJ, (PetscObject *)&feJ)); 10829566063dSJacob Faibussowitsch PetscCall(PetscFEGetSpatialDimension(feI, &dim)); 10839566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(feI, &quad)); 10849566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim)); 1085429ebbe4SMatthew G. Knepley PetscCall(PetscDSGetComponentOffsetsCohesive(ds, 0, &uOff)); // Change 0 to s for one-sided offsets 10869566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsetsCohesive(ds, s, &uOff_x)); 10879566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 108827f02ce8SMatthew G. Knepley switch (jtype) { 1089d71ae5a4SJacob Faibussowitsch case PETSCFE_JACOBIAN_PRE: 1090d71ae5a4SJacob Faibussowitsch PetscCall(PetscWeakFormGetBdJacobianPreconditioner(wf, key.label, key.value, fieldI, fieldJ, key.part, &n0, &g0_func, &n1, &g1_func, &n2, &g2_func, &n3, &g3_func)); 1091d71ae5a4SJacob Faibussowitsch break; 1092d71ae5a4SJacob Faibussowitsch case PETSCFE_JACOBIAN: 1093d71ae5a4SJacob Faibussowitsch PetscCall(PetscWeakFormGetBdJacobian(wf, key.label, key.value, fieldI, fieldJ, key.part, &n0, &g0_func, &n1, &g1_func, &n2, &g2_func, &n3, &g3_func)); 1094d71ae5a4SJacob Faibussowitsch break; 1095d71ae5a4SJacob Faibussowitsch case PETSCFE_JACOBIAN_DYN: 1096d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No boundary hybrid Jacobians :)"); 109727f02ce8SMatthew G. Knepley } 10983ba16761SJacob Faibussowitsch if (!n0 && !n1 && !n2 && !n3) PetscFunctionReturn(PETSC_SUCCESS); 10999566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(ds, &u, coefficients_t ? &u_t : NULL, &u_x)); 11009566063dSJacob Faibussowitsch PetscCall(PetscDSGetWorkspace(ds, &x, &basisReal, &basisDerReal, &testReal, &testDerReal)); 11019566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakFormArrays(ds, NULL, NULL, &g0, &g1, &g2, &g3)); 11029566063dSJacob Faibussowitsch PetscCall(PetscDSGetTabulation(ds, &T)); 110307218a29SMatthew G. Knepley PetscCall(PetscDSGetFaceTabulation(dsIn, &TfIn)); 11049566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffsetCohesive(ds, fieldI, &offsetI)); 11059566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffsetCohesive(ds, fieldJ, &offsetJ)); 110687510d7dSMatthew G. Knepley PetscCall(PetscDSSetIntegrationParameters(ds, fieldI, fieldJ)); 11079566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 110827f02ce8SMatthew G. Knepley if (dsAux) { 11099566063dSJacob Faibussowitsch PetscCall(PetscDSGetSpatialDimension(dsAux, &dimAux)); 11109566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(dsAux, &NfAux)); 11119566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux)); 11129566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(dsAux, &aOff)); 11139566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x)); 11149566063dSJacob Faibussowitsch PetscCall(PetscDSGetEvaluationArrays(dsAux, &a, NULL, &a_x)); 111501907d53SMatthew G. Knepley auxOnBd = dimAux == dim ? PETSC_TRUE : PETSC_FALSE; 11169566063dSJacob Faibussowitsch if (auxOnBd) PetscCall(PetscDSGetTabulation(dsAux, &TAux)); 11179566063dSJacob Faibussowitsch else PetscCall(PetscDSGetFaceTabulation(dsAux, &TAux)); 111863a3b9bcSJacob Faibussowitsch PetscCheck(T[0]->Np == TAux[0]->Np, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of tabulation points %" PetscInt_FMT " != %" PetscInt_FMT " number of auxiliary tabulation points", T[0]->Np, TAux[0]->Np); 111927f02ce8SMatthew G. Knepley } 11209566063dSJacob Faibussowitsch PetscCall(PetscDSGetCohesive(ds, fieldI, &isCohesiveFieldI)); 11219566063dSJacob Faibussowitsch PetscCall(PetscDSGetCohesive(ds, fieldJ, &isCohesiveFieldJ)); 11220563a546SMatthew G. Knepley dE = fgeom->dimEmbed; 1123665f567fSMatthew G. Knepley NcI = T[fieldI]->Nc; 1124665f567fSMatthew G. Knepley NcJ = T[fieldJ]->Nc; 112527f02ce8SMatthew G. Knepley NcS = isCohesiveFieldI ? NcI : 2 * NcI; 112627f02ce8SMatthew G. Knepley NcT = isCohesiveFieldJ ? NcJ : 2 * NcJ; 11270abb75b6SMatthew G. Knepley if (!isCohesiveFieldI && s == 2) { 11280abb75b6SMatthew G. Knepley // If we are integrating over a cohesive cell (s = 2) for a non-cohesive fields, we use both sides 11290abb75b6SMatthew G. Knepley NcS *= 2; 11300abb75b6SMatthew G. Knepley } 11310abb75b6SMatthew G. Knepley if (!isCohesiveFieldJ && s == 2) { 11320abb75b6SMatthew G. Knepley // If we are integrating over a cohesive cell (s = 2) for a non-cohesive fields, we use both sides 11330abb75b6SMatthew G. Knepley NcT *= 2; 11340abb75b6SMatthew G. Knepley } 11350502970dSMatthew G. Knepley // The derivatives are constrained to be along the cell, so there are dim, not dE, components, even though 11360502970dSMatthew G. Knepley // the coordinates are in dE dimensions 11379566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g0, NcS * NcT)); 11380502970dSMatthew G. Knepley PetscCall(PetscArrayzero(g1, NcS * NcT * dim)); 11390502970dSMatthew G. Knepley PetscCall(PetscArrayzero(g2, NcS * NcT * dim)); 11400502970dSMatthew G. Knepley PetscCall(PetscArrayzero(g3, NcS * NcT * dim * dim)); 11419566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights)); 11420e18dc48SMatthew G. Knepley PetscCall(PetscQuadratureGetCellType(quad, &ct)); 114363a3b9bcSJacob Faibussowitsch PetscCheck(qNc == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supports scalar quadrature, not %" PetscInt_FMT " components", qNc); 114427f02ce8SMatthew G. Knepley for (e = 0; e < Ne; ++e) { 1145989fa639SBrad Aagaard PetscFEGeom fegeom, fegeomN[2]; 11460e18dc48SMatthew G. Knepley const PetscInt face[2] = {fgeom->face[e * 2 + 0][0], fgeom->face[e * 2 + 1][2]}; 11470e18dc48SMatthew G. Knepley const PetscInt ornt[2] = {fgeom->face[e * 2 + 0][1], fgeom->face[e * 2 + 1][3]}; 11484e913f38SMatthew G. Knepley const PetscInt cornt[2] = {fgeom->face[e * 2 + 0][3], fgeom->face[e * 2 + 1][1]}; 114927f02ce8SMatthew G. Knepley 115007218a29SMatthew G. Knepley fegeom.v = x; /* Workspace */ 115127f02ce8SMatthew G. Knepley for (q = 0; q < Nq; ++q) { 11520e18dc48SMatthew G. Knepley PetscInt qpt[2]; 115327f02ce8SMatthew G. Knepley PetscReal w; 115427f02ce8SMatthew G. Knepley PetscInt c; 115527f02ce8SMatthew G. Knepley 11564e913f38SMatthew G. Knepley PetscCall(PetscDSPermuteQuadPoint(ds, DMPolytopeTypeComposeOrientationInv(ct, cornt[0], ornt[0]), fieldI, q, &qpt[0])); 11574e913f38SMatthew G. Knepley PetscCall(PetscDSPermuteQuadPoint(ds, DMPolytopeTypeComposeOrientationInv(ct, ornt[1], cornt[1]), fieldI, q, &qpt[1])); 115807218a29SMatthew G. Knepley PetscCall(PetscFEGeomGetPoint(fgeom, e * 2, q, &quadPoints[q * fgeom->dim], &fegeom)); 1159989fa639SBrad Aagaard PetscCall(PetscFEGeomGetPoint(nbrgeom, e * 2, q, NULL, &fegeomN[0])); 1160989fa639SBrad Aagaard PetscCall(PetscFEGeomGetPoint(nbrgeom, e * 2 + 1, q, NULL, &fegeomN[1])); 116127f02ce8SMatthew G. Knepley w = fegeom.detJ[0] * quadWeights[q]; 116207218a29SMatthew G. Knepley if (debug > 1 && q < fgeom->numPoints) { 116363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " detJ: %g\n", (double)fegeom.detJ[0])); 116427f02ce8SMatthew G. Knepley #if !defined(PETSC_USE_COMPLEX) 11659566063dSJacob Faibussowitsch PetscCall(DMPrintCellMatrix(e, "invJ", dim, dim, fegeom.invJ)); 116627f02ce8SMatthew G. Knepley #endif 116727f02ce8SMatthew G. Knepley } 116863a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(PETSC_COMM_SELF, " quad point %" PetscInt_FMT "\n", q)); 1169989fa639SBrad Aagaard if (coefficients) PetscCall(PetscFEEvaluateFieldJets_Hybrid_Internal(dsIn, Nf, 0, q, T, face, qpt, TfIn, &fegeom, fegeomN, &coefficients[cOffset], PetscSafePointerPlusOffset(coefficients_t, cOffset), u, u_x, u_t)); 117007218a29SMatthew G. Knepley if (dsAux) PetscCall(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, auxOnBd ? 0 : face[s], auxOnBd ? q : qpt[s], TAux, &fegeom, &coefficientsAux[cOffsetAux], NULL, a, a_x, NULL)); 1171ea672e62SMatthew G. Knepley if (n0) { 11729566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(g0, NcS * NcT)); 11730563a546SMatthew G. Knepley for (i = 0; i < n0; ++i) g0_func[i](dE, 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); 117427f02ce8SMatthew G. Knepley for (c = 0; c < NcS * NcT; ++c) g0[c] *= w; 117527f02ce8SMatthew G. Knepley } 1176ea672e62SMatthew G. Knepley if (n1) { 11770502970dSMatthew G. Knepley PetscCall(PetscArrayzero(g1, NcS * NcT * dim)); 11780563a546SMatthew G. Knepley for (i = 0; i < n1; ++i) g1_func[i](dE, 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); 11790502970dSMatthew G. Knepley for (c = 0; c < NcS * NcT * dim; ++c) g1[c] *= w; 118027f02ce8SMatthew G. Knepley } 1181ea672e62SMatthew G. Knepley if (n2) { 11820502970dSMatthew G. Knepley PetscCall(PetscArrayzero(g2, NcS * NcT * dim)); 11830563a546SMatthew G. Knepley for (i = 0; i < n2; ++i) g2_func[i](dE, 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); 11840502970dSMatthew G. Knepley for (c = 0; c < NcS * NcT * dim; ++c) g2[c] *= w; 118527f02ce8SMatthew G. Knepley } 1186ea672e62SMatthew G. Knepley if (n3) { 11870502970dSMatthew G. Knepley PetscCall(PetscArrayzero(g3, NcS * NcT * dim * dim)); 11880563a546SMatthew G. Knepley for (i = 0; i < n3; ++i) g3_func[i](dE, 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); 11890502970dSMatthew G. Knepley for (c = 0; c < NcS * NcT * dim * dim; ++c) g3[c] *= w; 119027f02ce8SMatthew G. Knepley } 119127f02ce8SMatthew G. Knepley 11925fedec97SMatthew G. Knepley if (isCohesiveFieldI) { 11935fedec97SMatthew G. Knepley if (isCohesiveFieldJ) { 1194989fa639SBrad Aagaard //PetscCall(PetscFEUpdateElementMat_Internal(feI, feJ, 0, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, g0, g1, g2, g3, totDim, offsetI, offsetJ, elemMat + eOffset)); 1195989fa639SBrad Aagaard PetscCall(PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, 0, 0, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, g0, g1, g2, g3, eOffset, totDim, offsetI, offsetJ, elemMat)); 119627f02ce8SMatthew G. Knepley } else { 11970abb75b6SMatthew G. Knepley PetscCall(PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, 0, 0, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, g0, g1, g2, g3, eOffset, totDim, offsetI, offsetJ, elemMat)); 11980abb75b6SMatthew G. Knepley PetscCall(PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, 1, 1, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, &g0[NcI * NcJ], &g1[NcI * NcJ * dim], &g2[NcI * NcJ * dim], &g3[NcI * NcJ * dim * dim], eOffset, totDim, offsetI, offsetJ, elemMat)); 11990abb75b6SMatthew G. Knepley } 12000abb75b6SMatthew G. Knepley } else { 12010abb75b6SMatthew G. Knepley if (s == 2) { 12020abb75b6SMatthew G. Knepley if (isCohesiveFieldJ) { 12030abb75b6SMatthew G. Knepley PetscCall(PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, 0, 0, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, g0, g1, g2, g3, eOffset, totDim, offsetI, offsetJ, elemMat)); 12040abb75b6SMatthew G. Knepley PetscCall(PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, 1, 1, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, &g0[NcI * NcJ], &g1[NcI * NcJ * dim], &g2[NcI * NcJ * dim], &g3[NcI * NcJ * dim * dim], eOffset, totDim, offsetI, offsetJ, elemMat)); 12050abb75b6SMatthew G. Knepley } else { 12060abb75b6SMatthew G. Knepley PetscCall(PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, 0, 0, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, g0, g1, g2, g3, eOffset, totDim, offsetI, offsetJ, elemMat)); 12070abb75b6SMatthew G. Knepley PetscCall(PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, 0, 1, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, &g0[NcI * NcJ], &g1[NcI * NcJ * dim], &g2[NcI * NcJ * dim], &g3[NcI * NcJ * dim * dim], eOffset, totDim, offsetI, offsetJ, elemMat)); 12080abb75b6SMatthew G. Knepley PetscCall(PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, 1, 0, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, &g0[NcI * NcJ * 2], &g1[NcI * NcJ * dim * 2], &g2[NcI * NcJ * dim * 2], &g3[NcI * NcJ * dim * dim * 2], eOffset, totDim, offsetI, offsetJ, elemMat)); 12090abb75b6SMatthew G. Knepley PetscCall(PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, 1, 1, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, &g0[NcI * NcJ * 3], &g1[NcI * NcJ * dim * 3], &g2[NcI * NcJ * dim * 3], &g3[NcI * NcJ * dim * dim * 3], eOffset, totDim, offsetI, offsetJ, elemMat)); 12105fedec97SMatthew G. Knepley } 12119371c9d4SSatish Balay } else 12120abb75b6SMatthew G. Knepley PetscCall(PetscFEUpdateElementMat_Hybrid_Internal(feI, isCohesiveFieldI, feJ, isCohesiveFieldJ, 0, s, s, q, T[fieldI], basisReal, basisDerReal, T[fieldJ], testReal, testDerReal, &fegeom, g0, g1, g2, g3, eOffset, totDim, offsetI, offsetJ, elemMat)); 12130abb75b6SMatthew G. Knepley } 121427f02ce8SMatthew G. Knepley } 121527f02ce8SMatthew G. Knepley if (debug > 1) { 12164e913f38SMatthew G. Knepley const PetscInt fS = 0 + (isCohesiveFieldI ? 0 : (s == 2 ? 0 : s * T[fieldI]->Nb)); 12174e913f38SMatthew G. Knepley const PetscInt fE = T[fieldI]->Nb + (isCohesiveFieldI ? 0 : (s == 2 ? T[fieldI]->Nb : s * T[fieldI]->Nb)); 12184e913f38SMatthew G. Knepley const PetscInt gS = 0 + (isCohesiveFieldJ ? 0 : (s == 2 ? 0 : s * T[fieldJ]->Nb)); 12194e913f38SMatthew G. Knepley const PetscInt gE = T[fieldJ]->Nb + (isCohesiveFieldJ ? 0 : (s == 2 ? T[fieldJ]->Nb : s * T[fieldJ]->Nb)); 12204e913f38SMatthew G. Knepley PetscInt f, g; 122127f02ce8SMatthew G. Knepley 12224e913f38SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, "Element matrix for fields %" PetscInt_FMT " and %" PetscInt_FMT " s %s totDim %" PetscInt_FMT " offsets (%" PetscInt_FMT ", %" PetscInt_FMT ", %" PetscInt_FMT ")\n", fieldI, fieldJ, s ? (s > 1 ? "Coh" : "Pos") : "Neg", totDim, eOffset, offsetI, offsetJ)); 12234e913f38SMatthew G. Knepley for (f = fS; f < fE; ++f) { 12244e913f38SMatthew G. Knepley const PetscInt i = offsetI + f; 12254e913f38SMatthew G. Knepley for (g = gS; g < gE; ++g) { 12264e913f38SMatthew G. Knepley const PetscInt j = offsetJ + g; 1227e978a55eSPierre Jolivet PetscCheck(i < totDim && j < totDim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fuck up %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, f, i, g, j); 12284e913f38SMatthew G. Knepley PetscCall(PetscPrintf(PETSC_COMM_SELF, " elemMat[%" PetscInt_FMT ",%" PetscInt_FMT ",%" PetscInt_FMT ",%" PetscInt_FMT "]: %g\n", f / NcI, f % NcI, g / NcJ, g % NcJ, (double)PetscRealPart(elemMat[eOffset + i * totDim + j]))); 122927f02ce8SMatthew G. Knepley } 12309566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 123127f02ce8SMatthew G. Knepley } 123227f02ce8SMatthew G. Knepley } 123327f02ce8SMatthew G. Knepley cOffset += totDim; 123427f02ce8SMatthew G. Knepley cOffsetAux += totDimAux; 123527f02ce8SMatthew G. Knepley eOffset += PetscSqr(totDim); 123627f02ce8SMatthew G. Knepley } 12373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 123827f02ce8SMatthew G. Knepley } 123927f02ce8SMatthew G. Knepley 1240d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscFEInitialize_Basic(PetscFE fem) 1241d71ae5a4SJacob Faibussowitsch { 124220cf1dd8SToby Isaac PetscFunctionBegin; 124320cf1dd8SToby Isaac fem->ops->setfromoptions = NULL; 124420cf1dd8SToby Isaac fem->ops->setup = PetscFESetUp_Basic; 124520cf1dd8SToby Isaac fem->ops->view = PetscFEView_Basic; 124620cf1dd8SToby Isaac fem->ops->destroy = PetscFEDestroy_Basic; 124720cf1dd8SToby Isaac fem->ops->getdimension = PetscFEGetDimension_Basic; 1248ce78bad3SBarry Smith fem->ops->computetabulation = PetscFEComputeTabulation_Basic; 124920cf1dd8SToby Isaac fem->ops->integrate = PetscFEIntegrate_Basic; 1250afe6d6adSToby Isaac fem->ops->integratebd = PetscFEIntegrateBd_Basic; 125120cf1dd8SToby Isaac fem->ops->integrateresidual = PetscFEIntegrateResidual_Basic; 125220cf1dd8SToby Isaac fem->ops->integratebdresidual = PetscFEIntegrateBdResidual_Basic; 125327f02ce8SMatthew G. Knepley fem->ops->integratehybridresidual = PetscFEIntegrateHybridResidual_Basic; 125420cf1dd8SToby Isaac fem->ops->integratejacobianaction = NULL /* PetscFEIntegrateJacobianAction_Basic */; 125520cf1dd8SToby Isaac fem->ops->integratejacobian = PetscFEIntegrateJacobian_Basic; 125620cf1dd8SToby Isaac fem->ops->integratebdjacobian = PetscFEIntegrateBdJacobian_Basic; 125727f02ce8SMatthew G. Knepley fem->ops->integratehybridjacobian = PetscFEIntegrateHybridJacobian_Basic; 12583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 125920cf1dd8SToby Isaac } 126020cf1dd8SToby Isaac 126120cf1dd8SToby Isaac /*MC 1262dce8aebaSBarry Smith PETSCFEBASIC = "basic" - A `PetscFE` object that integrates with basic tiling and no vectorization 126320cf1dd8SToby Isaac 126420cf1dd8SToby Isaac Level: intermediate 126520cf1dd8SToby Isaac 1266dce8aebaSBarry Smith .seealso: `PetscFE`, `PetscFEType`, `PetscFECreate()`, `PetscFESetType()` 126720cf1dd8SToby Isaac M*/ 126820cf1dd8SToby Isaac 1269d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscFECreate_Basic(PetscFE fem) 1270d71ae5a4SJacob Faibussowitsch { 127120cf1dd8SToby Isaac PetscFE_Basic *b; 127220cf1dd8SToby Isaac 127320cf1dd8SToby Isaac PetscFunctionBegin; 127420cf1dd8SToby Isaac PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1); 12754dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&b)); 127620cf1dd8SToby Isaac fem->data = b; 127720cf1dd8SToby Isaac 12789566063dSJacob Faibussowitsch PetscCall(PetscFEInitialize_Basic(fem)); 12793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 128020cf1dd8SToby Isaac } 1281