xref: /petsc/src/dm/dt/fe/impls/composite/fecomposite.c (revision 412e9a14abbdcfab8bb1cbfb40875fcde8c4ce26)
120cf1dd8SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
220cf1dd8SToby Isaac #include <petsc/private/dtimpl.h> /*I "petscdt.h" I*/
320cf1dd8SToby Isaac #include <petscblaslapack.h>
420cf1dd8SToby Isaac 
52b99622eSMatthew G. Knepley static PetscErrorCode PetscFEDestroy_Composite(PetscFE fem)
620cf1dd8SToby Isaac {
720cf1dd8SToby Isaac   PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data;
820cf1dd8SToby Isaac   PetscErrorCode     ierr;
920cf1dd8SToby Isaac 
1020cf1dd8SToby Isaac   PetscFunctionBegin;
1120cf1dd8SToby Isaac   ierr = PetscFree(cmp->embedding);CHKERRQ(ierr);
1220cf1dd8SToby Isaac   ierr = PetscFree(cmp);CHKERRQ(ierr);
1320cf1dd8SToby Isaac   PetscFunctionReturn(0);
1420cf1dd8SToby Isaac }
1520cf1dd8SToby Isaac 
162b99622eSMatthew G. Knepley static PetscErrorCode PetscFESetUp_Composite(PetscFE fem)
1720cf1dd8SToby Isaac {
1820cf1dd8SToby Isaac   PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data;
1920cf1dd8SToby Isaac   DM                 K;
20*412e9a14SMatthew G. Knepley   DMPolytopeType     ct;
21*412e9a14SMatthew G. Knepley   DMPlexCellRefiner  cr;
2220cf1dd8SToby Isaac   PetscReal         *subpoint;
2320cf1dd8SToby Isaac   PetscBLASInt      *pivots;
2420cf1dd8SToby Isaac   PetscBLASInt       n, info;
2520cf1dd8SToby Isaac   PetscScalar       *work, *invVscalar;
2620cf1dd8SToby Isaac   PetscInt           dim, pdim, spdim, j, s;
2720cf1dd8SToby Isaac   PetscErrorCode     ierr;
2820cf1dd8SToby Isaac 
2920cf1dd8SToby Isaac   PetscFunctionBegin;
3020cf1dd8SToby Isaac   /* Get affine mapping from reference cell to each subcell */
3120cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(fem->dualSpace, &K);CHKERRQ(ierr);
3220cf1dd8SToby Isaac   ierr = DMGetDimension(K, &dim);CHKERRQ(ierr);
33*412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellType(K, 0, &ct);CHKERRQ(ierr);
34*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerCreate(K, &cr);CHKERRQ(ierr);
35*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &cmp->numSubelements, &cmp->v0, &cmp->jac, &cmp->invjac);CHKERRQ(ierr);
36*412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
3720cf1dd8SToby Isaac   /* Determine dof embedding into subelements */
3820cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr);
3920cf1dd8SToby Isaac   ierr = PetscSpaceGetDimension(fem->basisSpace, &spdim);CHKERRQ(ierr);
4020cf1dd8SToby Isaac   ierr = PetscMalloc1(cmp->numSubelements*spdim,&cmp->embedding);CHKERRQ(ierr);
4120cf1dd8SToby Isaac   ierr = DMGetWorkArray(K, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr);
4220cf1dd8SToby Isaac   for (s = 0; s < cmp->numSubelements; ++s) {
4320cf1dd8SToby Isaac     PetscInt sd = 0;
4420cf1dd8SToby Isaac 
4520cf1dd8SToby Isaac     for (j = 0; j < pdim; ++j) {
4620cf1dd8SToby Isaac       PetscBool       inside;
4720cf1dd8SToby Isaac       PetscQuadrature f;
4820cf1dd8SToby Isaac       PetscInt        d, e;
4920cf1dd8SToby Isaac 
5020cf1dd8SToby Isaac       ierr = PetscDualSpaceGetFunctional(fem->dualSpace, j, &f);CHKERRQ(ierr);
5120cf1dd8SToby Isaac       /* Apply transform to first point, and check that point is inside subcell */
5220cf1dd8SToby Isaac       for (d = 0; d < dim; ++d) {
5320cf1dd8SToby Isaac         subpoint[d] = -1.0;
5420cf1dd8SToby Isaac         for (e = 0; e < dim; ++e) subpoint[d] += cmp->invjac[(s*dim + d)*dim+e]*(f->points[e] - cmp->v0[s*dim+e]);
5520cf1dd8SToby Isaac       }
56*412e9a14SMatthew G. Knepley       ierr = CellRefinerInCellTest_Internal(ct, subpoint, &inside);CHKERRQ(ierr);
5720cf1dd8SToby Isaac       if (inside) {cmp->embedding[s*spdim+sd++] = j;}
5820cf1dd8SToby Isaac     }
5920cf1dd8SToby Isaac     if (sd != spdim) SETERRQ3(PetscObjectComm((PetscObject) fem), PETSC_ERR_PLIB, "Subelement %d has %d dual basis vectors != %d", s, sd, spdim);
6020cf1dd8SToby Isaac   }
6120cf1dd8SToby Isaac   ierr = DMRestoreWorkArray(K, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr);
6220cf1dd8SToby Isaac   /* Construct the change of basis from prime basis to nodal basis for each subelement */
6320cf1dd8SToby Isaac   ierr = PetscMalloc1(cmp->numSubelements*spdim*spdim,&fem->invV);CHKERRQ(ierr);
6420cf1dd8SToby Isaac   ierr = PetscMalloc2(spdim,&pivots,spdim,&work);CHKERRQ(ierr);
6520cf1dd8SToby Isaac #if defined(PETSC_USE_COMPLEX)
6620cf1dd8SToby Isaac   ierr = PetscMalloc1(cmp->numSubelements*spdim*spdim,&invVscalar);CHKERRQ(ierr);
6720cf1dd8SToby Isaac #else
6820cf1dd8SToby Isaac   invVscalar = fem->invV;
6920cf1dd8SToby Isaac #endif
7020cf1dd8SToby Isaac   for (s = 0; s < cmp->numSubelements; ++s) {
7120cf1dd8SToby Isaac     for (j = 0; j < spdim; ++j) {
7220cf1dd8SToby Isaac       PetscReal       *Bf;
7320cf1dd8SToby Isaac       PetscQuadrature  f;
7420cf1dd8SToby Isaac       const PetscReal *points, *weights;
7520cf1dd8SToby Isaac       PetscInt         Nc, Nq, q, k;
7620cf1dd8SToby Isaac 
7720cf1dd8SToby Isaac       ierr = PetscDualSpaceGetFunctional(fem->dualSpace, cmp->embedding[s*spdim+j], &f);CHKERRQ(ierr);
7820cf1dd8SToby Isaac       ierr = PetscQuadratureGetData(f, NULL, &Nc, &Nq, &points, &weights);CHKERRQ(ierr);
7920cf1dd8SToby Isaac       ierr = PetscMalloc1(f->numPoints*spdim*Nc,&Bf);CHKERRQ(ierr);
8020cf1dd8SToby Isaac       ierr = PetscSpaceEvaluate(fem->basisSpace, Nq, points, Bf, NULL, NULL);CHKERRQ(ierr);
8120cf1dd8SToby Isaac       for (k = 0; k < spdim; ++k) {
8220cf1dd8SToby Isaac         /* n_j \cdot \phi_k */
8320cf1dd8SToby Isaac         invVscalar[(s*spdim + j)*spdim+k] = 0.0;
8420cf1dd8SToby Isaac         for (q = 0; q < Nq; ++q) {
8520cf1dd8SToby Isaac           invVscalar[(s*spdim + j)*spdim+k] += Bf[q*spdim+k]*weights[q];
8620cf1dd8SToby Isaac         }
8720cf1dd8SToby Isaac       }
8820cf1dd8SToby Isaac       ierr = PetscFree(Bf);CHKERRQ(ierr);
8920cf1dd8SToby Isaac     }
9020cf1dd8SToby Isaac     n = spdim;
9120cf1dd8SToby Isaac     PetscStackCallBLAS("LAPACKgetrf", LAPACKgetrf_(&n, &n, &invVscalar[s*spdim*spdim], &n, pivots, &info));
9220cf1dd8SToby Isaac     PetscStackCallBLAS("LAPACKgetri", LAPACKgetri_(&n, &invVscalar[s*spdim*spdim], &n, pivots, work, &n, &info));
9320cf1dd8SToby Isaac   }
9420cf1dd8SToby Isaac #if defined(PETSC_USE_COMPLEX)
9520cf1dd8SToby Isaac   for (s = 0; s <cmp->numSubelements*spdim*spdim; s++) fem->invV[s] = PetscRealPart(invVscalar[s]);
9620cf1dd8SToby Isaac   ierr = PetscFree(invVscalar);CHKERRQ(ierr);
9720cf1dd8SToby Isaac #endif
9820cf1dd8SToby Isaac   ierr = PetscFree2(pivots,work);CHKERRQ(ierr);
9920cf1dd8SToby Isaac   PetscFunctionReturn(0);
10020cf1dd8SToby Isaac }
10120cf1dd8SToby Isaac 
102ef0bb6c7SMatthew G. Knepley static PetscErrorCode PetscFECreateTabulation_Composite(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation T)
10320cf1dd8SToby Isaac {
10420cf1dd8SToby Isaac   PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data;
10520cf1dd8SToby Isaac   DM                 dm;
106*412e9a14SMatthew G. Knepley   DMPolytopeType     ct;
10720cf1dd8SToby Isaac   PetscInt           pdim;  /* Dimension of FE space P */
10820cf1dd8SToby Isaac   PetscInt           spdim; /* Dimension of subelement FE space P */
10920cf1dd8SToby Isaac   PetscInt           dim;   /* Spatial dimension */
11020cf1dd8SToby Isaac   PetscInt           comp;  /* Field components */
11120cf1dd8SToby Isaac   PetscInt          *subpoints;
112ef0bb6c7SMatthew G. Knepley   PetscReal         *B = K >= 0 ? T->T[0] : NULL;
113ef0bb6c7SMatthew G. Knepley   PetscReal         *D = K >= 1 ? T->T[1] : NULL;
114ef0bb6c7SMatthew G. Knepley   PetscReal         *H = K >= 2 ? T->T[2] : NULL;
115ef0bb6c7SMatthew G. Knepley   PetscReal         *tmpB = NULL, *tmpD = NULL, *tmpH = NULL, *subpoint;
11620cf1dd8SToby Isaac   PetscInt           p, s, d, e, j, k;
11720cf1dd8SToby Isaac   PetscErrorCode     ierr;
11820cf1dd8SToby Isaac 
11920cf1dd8SToby Isaac   PetscFunctionBegin;
12020cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr);
12120cf1dd8SToby Isaac   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
122*412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellType(dm, 0, &ct);CHKERRQ(ierr);
12320cf1dd8SToby Isaac   ierr = PetscSpaceGetDimension(fem->basisSpace, &spdim);CHKERRQ(ierr);
12420cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr);
12520cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fem, &comp);CHKERRQ(ierr);
12620cf1dd8SToby Isaac   /* Divide points into subelements */
12720cf1dd8SToby Isaac   ierr = DMGetWorkArray(dm, npoints, MPIU_INT, &subpoints);CHKERRQ(ierr);
12820cf1dd8SToby Isaac   ierr = DMGetWorkArray(dm, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr);
12920cf1dd8SToby Isaac   for (p = 0; p < npoints; ++p) {
13020cf1dd8SToby Isaac     for (s = 0; s < cmp->numSubelements; ++s) {
13120cf1dd8SToby Isaac       PetscBool inside;
13220cf1dd8SToby Isaac 
13320cf1dd8SToby Isaac       /* Apply transform, and check that point is inside cell */
13420cf1dd8SToby Isaac       for (d = 0; d < dim; ++d) {
13520cf1dd8SToby Isaac         subpoint[d] = -1.0;
13620cf1dd8SToby Isaac         for (e = 0; e < dim; ++e) subpoint[d] += cmp->invjac[(s*dim + d)*dim+e]*(points[p*dim+e] - cmp->v0[s*dim+e]);
13720cf1dd8SToby Isaac       }
138*412e9a14SMatthew G. Knepley       ierr = CellRefinerInCellTest_Internal(ct, subpoint, &inside);CHKERRQ(ierr);
13920cf1dd8SToby Isaac       if (inside) {subpoints[p] = s; break;}
14020cf1dd8SToby Isaac     }
14120cf1dd8SToby Isaac     if (s >= cmp->numSubelements) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %d was not found in any subelement", p);
14220cf1dd8SToby Isaac   }
14320cf1dd8SToby Isaac   ierr = DMRestoreWorkArray(dm, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr);
14420cf1dd8SToby Isaac   /* Evaluate the prime basis functions at all points */
145ef0bb6c7SMatthew G. Knepley   if (K >= 0) {ierr = DMGetWorkArray(dm, npoints*spdim, MPIU_REAL, &tmpB);CHKERRQ(ierr);}
146ef0bb6c7SMatthew G. Knepley   if (K >= 1) {ierr = DMGetWorkArray(dm, npoints*spdim*dim, MPIU_REAL, &tmpD);CHKERRQ(ierr);}
147ef0bb6c7SMatthew G. Knepley   if (K >= 2) {ierr = DMGetWorkArray(dm, npoints*spdim*dim*dim, MPIU_REAL, &tmpH);CHKERRQ(ierr);}
148ef0bb6c7SMatthew G. Knepley   ierr = PetscSpaceEvaluate(fem->basisSpace, npoints, points, tmpB, tmpD, tmpH);CHKERRQ(ierr);
14920cf1dd8SToby Isaac   /* Translate to the nodal basis */
150ef0bb6c7SMatthew G. Knepley   if (K >= 0) {ierr = PetscArrayzero(B, npoints*pdim*comp);CHKERRQ(ierr);}
151ef0bb6c7SMatthew G. Knepley   if (K >= 1) {ierr = PetscArrayzero(D, npoints*pdim*comp*dim);CHKERRQ(ierr);}
152ef0bb6c7SMatthew G. Knepley   if (K >= 2) {ierr = PetscArrayzero(H, npoints*pdim*comp*dim*dim);CHKERRQ(ierr);}
15320cf1dd8SToby Isaac   for (p = 0; p < npoints; ++p) {
15420cf1dd8SToby Isaac     const PetscInt s = subpoints[p];
15520cf1dd8SToby Isaac 
15620cf1dd8SToby Isaac     if (B) {
15720cf1dd8SToby Isaac       /* Multiply by V^{-1} (spdim x spdim) */
15820cf1dd8SToby Isaac       for (j = 0; j < spdim; ++j) {
15920cf1dd8SToby Isaac         const PetscInt i = (p*pdim + cmp->embedding[s*spdim+j])*comp;
16020cf1dd8SToby Isaac 
16120cf1dd8SToby Isaac         B[i] = 0.0;
16220cf1dd8SToby Isaac         for (k = 0; k < spdim; ++k) {
16320cf1dd8SToby Isaac           B[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpB[p*spdim + k];
16420cf1dd8SToby Isaac         }
16520cf1dd8SToby Isaac       }
16620cf1dd8SToby Isaac     }
16720cf1dd8SToby Isaac     if (D) {
16820cf1dd8SToby Isaac       /* Multiply by V^{-1} (spdim x spdim) */
16920cf1dd8SToby Isaac       for (j = 0; j < spdim; ++j) {
17020cf1dd8SToby Isaac         for (d = 0; d < dim; ++d) {
17120cf1dd8SToby Isaac           const PetscInt i = ((p*pdim + cmp->embedding[s*spdim+j])*comp + 0)*dim + d;
17220cf1dd8SToby Isaac 
17320cf1dd8SToby Isaac           D[i] = 0.0;
17420cf1dd8SToby Isaac           for (k = 0; k < spdim; ++k) {
17520cf1dd8SToby Isaac             D[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpD[(p*spdim + k)*dim + d];
17620cf1dd8SToby Isaac           }
17720cf1dd8SToby Isaac         }
17820cf1dd8SToby Isaac       }
17920cf1dd8SToby Isaac     }
18020cf1dd8SToby Isaac     if (H) {
18120cf1dd8SToby Isaac       /* Multiply by V^{-1} (pdim x pdim) */
18220cf1dd8SToby Isaac       for (j = 0; j < spdim; ++j) {
18320cf1dd8SToby Isaac         for (d = 0; d < dim*dim; ++d) {
18420cf1dd8SToby Isaac           const PetscInt i = ((p*pdim + cmp->embedding[s*spdim+j])*comp + 0)*dim*dim + d;
18520cf1dd8SToby Isaac 
18620cf1dd8SToby Isaac           H[i] = 0.0;
18720cf1dd8SToby Isaac           for (k = 0; k < spdim; ++k) {
18820cf1dd8SToby Isaac             H[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpH[(p*spdim + k)*dim*dim + d];
18920cf1dd8SToby Isaac           }
19020cf1dd8SToby Isaac         }
19120cf1dd8SToby Isaac       }
19220cf1dd8SToby Isaac     }
19320cf1dd8SToby Isaac   }
19420cf1dd8SToby Isaac   ierr = DMRestoreWorkArray(dm, npoints, MPIU_INT, &subpoints);CHKERRQ(ierr);
195ef0bb6c7SMatthew G. Knepley   if (K >= 0) {ierr = DMRestoreWorkArray(dm, npoints*spdim, MPIU_REAL, &tmpB);CHKERRQ(ierr);}
196ef0bb6c7SMatthew G. Knepley   if (K >= 1) {ierr = DMRestoreWorkArray(dm, npoints*spdim*dim, MPIU_REAL, &tmpD);CHKERRQ(ierr);}
197ef0bb6c7SMatthew G. Knepley   if (K >= 2) {ierr = DMRestoreWorkArray(dm, npoints*spdim*dim*dim, MPIU_REAL, &tmpH);CHKERRQ(ierr);}
19820cf1dd8SToby Isaac   PetscFunctionReturn(0);
19920cf1dd8SToby Isaac }
20020cf1dd8SToby Isaac 
2012b99622eSMatthew G. Knepley static PetscErrorCode PetscFEInitialize_Composite(PetscFE fem)
20220cf1dd8SToby Isaac {
20320cf1dd8SToby Isaac   PetscFunctionBegin;
20420cf1dd8SToby Isaac   fem->ops->setfromoptions          = NULL;
20520cf1dd8SToby Isaac   fem->ops->setup                   = PetscFESetUp_Composite;
20620cf1dd8SToby Isaac   fem->ops->view                    = NULL;
20720cf1dd8SToby Isaac   fem->ops->destroy                 = PetscFEDestroy_Composite;
20820cf1dd8SToby Isaac   fem->ops->getdimension            = PetscFEGetDimension_Basic;
209ef0bb6c7SMatthew G. Knepley   fem->ops->createtabulation        = PetscFECreateTabulation_Composite;
21020cf1dd8SToby Isaac   fem->ops->integrateresidual       = PetscFEIntegrateResidual_Basic;
21120cf1dd8SToby Isaac   fem->ops->integratebdresidual     = PetscFEIntegrateBdResidual_Basic;
21220cf1dd8SToby Isaac   fem->ops->integratejacobianaction = NULL/* PetscFEIntegrateJacobianAction_Basic */;
21320cf1dd8SToby Isaac   fem->ops->integratejacobian       = PetscFEIntegrateJacobian_Basic;
21420cf1dd8SToby Isaac   PetscFunctionReturn(0);
21520cf1dd8SToby Isaac }
21620cf1dd8SToby Isaac 
21720cf1dd8SToby Isaac /*MC
21820cf1dd8SToby Isaac   PETSCFECOMPOSITE = "composite" - A PetscFE object that represents a composite element
21920cf1dd8SToby Isaac 
22020cf1dd8SToby Isaac   Level: intermediate
22120cf1dd8SToby Isaac 
22220cf1dd8SToby Isaac .seealso: PetscFEType, PetscFECreate(), PetscFESetType()
22320cf1dd8SToby Isaac M*/
22420cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode PetscFECreate_Composite(PetscFE fem)
22520cf1dd8SToby Isaac {
22620cf1dd8SToby Isaac   PetscFE_Composite *cmp;
22720cf1dd8SToby Isaac   PetscErrorCode     ierr;
22820cf1dd8SToby Isaac 
22920cf1dd8SToby Isaac   PetscFunctionBegin;
23020cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
23120cf1dd8SToby Isaac   ierr      = PetscNewLog(fem, &cmp);CHKERRQ(ierr);
23220cf1dd8SToby Isaac   fem->data = cmp;
23320cf1dd8SToby Isaac 
23420cf1dd8SToby Isaac   cmp->numSubelements = -1;
23520cf1dd8SToby Isaac   cmp->v0             = NULL;
23620cf1dd8SToby Isaac   cmp->jac            = NULL;
23720cf1dd8SToby Isaac 
23820cf1dd8SToby Isaac   ierr = PetscFEInitialize_Composite(fem);CHKERRQ(ierr);
23920cf1dd8SToby Isaac   PetscFunctionReturn(0);
24020cf1dd8SToby Isaac }
24120cf1dd8SToby Isaac 
24220cf1dd8SToby Isaac /*@C
24320cf1dd8SToby Isaac   PetscFECompositeGetMapping - Returns the mappings from the reference element to each subelement
24420cf1dd8SToby Isaac 
24520cf1dd8SToby Isaac   Not collective
24620cf1dd8SToby Isaac 
24720cf1dd8SToby Isaac   Input Parameter:
24820cf1dd8SToby Isaac . fem - The PetscFE object
24920cf1dd8SToby Isaac 
25020cf1dd8SToby Isaac   Output Parameters:
25120cf1dd8SToby Isaac + blockSize - The number of elements in a block
25220cf1dd8SToby Isaac . numBlocks - The number of blocks in a batch
25320cf1dd8SToby Isaac . batchSize - The number of elements in a batch
25420cf1dd8SToby Isaac - numBatches - The number of batches in a chunk
25520cf1dd8SToby Isaac 
25620cf1dd8SToby Isaac   Level: intermediate
25720cf1dd8SToby Isaac 
25820cf1dd8SToby Isaac .seealso: PetscFECreate()
25920cf1dd8SToby Isaac @*/
26020cf1dd8SToby Isaac PetscErrorCode PetscFECompositeGetMapping(PetscFE fem, PetscInt *numSubelements, const PetscReal *v0[], const PetscReal *jac[], const PetscReal *invjac[])
26120cf1dd8SToby Isaac {
26220cf1dd8SToby Isaac   PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data;
26320cf1dd8SToby Isaac 
26420cf1dd8SToby Isaac   PetscFunctionBegin;
26520cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
26620cf1dd8SToby Isaac   if (numSubelements) {PetscValidPointer(numSubelements, 2); *numSubelements = cmp->numSubelements;}
26720cf1dd8SToby Isaac   if (v0)             {PetscValidPointer(v0, 3);             *v0             = cmp->v0;}
26820cf1dd8SToby Isaac   if (jac)            {PetscValidPointer(jac, 4);            *jac            = cmp->jac;}
26920cf1dd8SToby Isaac   if (invjac)         {PetscValidPointer(invjac, 5);         *invjac         = cmp->invjac;}
27020cf1dd8SToby Isaac   PetscFunctionReturn(0);
27120cf1dd8SToby Isaac }
272