xref: /petsc/src/dm/field/impls/ds/dmfieldds.c (revision 2710589c03dae5062edabba57d2c9d9ba90fb564)
151a454edSToby Isaac #include <petsc/private/dmfieldimpl.h> /*I "petscdmfield.h" I*/
251a454edSToby Isaac #include <petscfe.h>
351a454edSToby Isaac #include <petscdmplex.h>
451a454edSToby Isaac #include <petscds.h>
551a454edSToby Isaac 
651a454edSToby Isaac typedef struct _n_DMField_DS
751a454edSToby Isaac {
851a454edSToby Isaac   PetscInt    fieldNum;
951a454edSToby Isaac   Vec         vec;
1051a454edSToby Isaac   PetscInt    height;
1151a454edSToby Isaac   PetscObject *disc;
1251a454edSToby Isaac   PetscBool   multifieldVec;
1351a454edSToby Isaac }
1451a454edSToby Isaac DMField_DS;
1551a454edSToby Isaac 
1651a454edSToby Isaac static PetscErrorCode DMFieldDestroy_DS(DMField field)
1751a454edSToby Isaac {
1851a454edSToby Isaac   DMField_DS     *dsfield;
1951a454edSToby Isaac   PetscInt       i;
2051a454edSToby Isaac   PetscErrorCode ierr;
2151a454edSToby Isaac 
2251a454edSToby Isaac   PetscFunctionBegin;
2351a454edSToby Isaac   dsfield = (DMField_DS *) field->data;
2451a454edSToby Isaac   ierr = VecDestroy(&dsfield->vec);CHKERRQ(ierr);
2551a454edSToby Isaac   for (i = 0; i < dsfield->height; i++) {
2651a454edSToby Isaac     ierr = PetscObjectDereference(dsfield->disc[i]);CHKERRQ(ierr);
2751a454edSToby Isaac   }
2851a454edSToby Isaac   ierr = PetscFree(dsfield->disc);CHKERRQ(ierr);
2951a454edSToby Isaac   ierr = PetscFree(dsfield);CHKERRQ(ierr);
3051a454edSToby Isaac   PetscFunctionReturn(0);
3151a454edSToby Isaac }
3251a454edSToby Isaac 
3351a454edSToby Isaac static PetscErrorCode DMFieldView_DS(DMField field,PetscViewer viewer)
3451a454edSToby Isaac {
3551a454edSToby Isaac   DMField_DS     *dsfield = (DMField_DS *) field->data;
3651a454edSToby Isaac   PetscBool      iascii;
3751a454edSToby Isaac   PetscObject    disc;
3851a454edSToby Isaac   PetscErrorCode ierr;
3951a454edSToby Isaac 
4051a454edSToby Isaac   PetscFunctionBegin;
4151a454edSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
4251a454edSToby Isaac   disc = dsfield->disc[0];
4351a454edSToby Isaac   if (iascii) {
4451a454edSToby Isaac     PetscViewerASCIIPrintf(viewer, "PetscDS field %D\n",dsfield->fieldNum);CHKERRQ(ierr);
4551a454edSToby Isaac     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
4651a454edSToby Isaac     ierr = PetscObjectView(disc,viewer);CHKERRQ(ierr);
4751a454edSToby Isaac     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
4851a454edSToby Isaac   }
4951a454edSToby Isaac   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
5051a454edSToby Isaac   if (dsfield->multifieldVec) {
5151a454edSToby Isaac     SETERRQ(PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"View of subfield not implemented yet");
5251a454edSToby Isaac   } else {
5351a454edSToby Isaac     ierr = VecView(dsfield->vec,viewer);CHKERRQ(ierr);
5451a454edSToby Isaac   }
5551a454edSToby Isaac   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
5651a454edSToby Isaac   PetscFunctionReturn(0);
5751a454edSToby Isaac }
5851a454edSToby Isaac 
5951a454edSToby Isaac static PetscErrorCode DMFieldEvaluate_DS(DMField field, Vec points, PetscDataType datatype, void *B, void *D, void *H)
6051a454edSToby Isaac {
6151a454edSToby Isaac   PetscFunctionBegin;
6251a454edSToby Isaac   SETERRQ(PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented yet");
6351a454edSToby Isaac   PetscFunctionReturn(0);
6451a454edSToby Isaac }
6551a454edSToby Isaac 
6651a454edSToby Isaac static PetscErrorCode DMFieldDSGetHeightDisc(DMField field, PetscInt height, PetscObject *disc)
6751a454edSToby Isaac {
6851a454edSToby Isaac   DMField_DS     *dsfield = (DMField_DS *) field->data;
6951a454edSToby Isaac   PetscErrorCode ierr;
7051a454edSToby Isaac 
7151a454edSToby Isaac   PetscFunctionBegin;
7251a454edSToby Isaac   if (!dsfield->disc[height]) {
7351a454edSToby Isaac     PetscClassId   id;
7451a454edSToby Isaac 
7551a454edSToby Isaac     ierr = PetscObjectGetClassId(dsfield->disc[0],&id);CHKERRQ(ierr);
7651a454edSToby Isaac     if (id == PETSCFE_CLASSID) {
7751a454edSToby Isaac       PetscFE fe = (PetscFE) dsfield->disc[0];
7851a454edSToby Isaac 
7951a454edSToby Isaac       ierr = PetscFECreateHeightTrace(fe,height,(PetscFE *)&dsfield->disc[height]);CHKERRQ(ierr);
8051a454edSToby Isaac     }
8151a454edSToby Isaac   }
8251a454edSToby Isaac   *disc = dsfield->disc[height];
8351a454edSToby Isaac   PetscFunctionReturn(0);
8451a454edSToby Isaac }
8551a454edSToby Isaac 
8651a454edSToby Isaac #define DMFieldDSdot(y,A,b,m,n,c,cast)                                           \
8751a454edSToby Isaac   do {                                                                           \
8851a454edSToby Isaac     PetscInt _i, _j, _k;                                                         \
8951a454edSToby Isaac     for (_i = 0; _i < (m); _i++) {                                               \
9051a454edSToby Isaac       for (_k = 0; _k < (c); _k++) {                                             \
9151a454edSToby Isaac         (y)[_i * (c) + _k] = 0.;                                                 \
9251a454edSToby Isaac       }                                                                          \
9351a454edSToby Isaac       for (_j = 0; _j < (n); _j++) {                                             \
9451a454edSToby Isaac         for (_k = 0; _k < (c); _k++) {                                           \
9551a454edSToby Isaac           (y)[_i * (c) + _k] += (A)[(_i * (n) + _j) * (c) + _k] * cast((b)[_j]); \
9651a454edSToby Isaac         }                                                                        \
9751a454edSToby Isaac       }                                                                          \
9851a454edSToby Isaac     }                                                                            \
9951a454edSToby Isaac   } while (0)
10051a454edSToby Isaac 
10151a454edSToby Isaac static PetscErrorCode DMFieldEvaluateFE_DS(DMField field, IS pointIS, PetscQuadrature quad, PetscDataType type, void *B, void *D, void *H)
10251a454edSToby Isaac {
10351a454edSToby Isaac   DMField_DS      *dsfield = (DMField_DS *) field->data;
10451a454edSToby Isaac   DM              dm;
10551a454edSToby Isaac   PetscObject     disc;
10651a454edSToby Isaac   PetscClassId    classid;
10751a454edSToby Isaac   PetscInt        nq, nc, dim, meshDim, numCells;
10851a454edSToby Isaac   PetscSection    section;
10951a454edSToby Isaac   const PetscReal *qpoints;
11051a454edSToby Isaac   PetscBool       isStride;
11151a454edSToby Isaac   const PetscInt  *points = NULL;
11251a454edSToby Isaac   PetscInt        sfirst = -1, stride = -1;
11351a454edSToby Isaac   PetscErrorCode  ierr;
11451a454edSToby Isaac 
11551a454edSToby Isaac   PetscFunctionBeginHot;
11651a454edSToby Isaac   dm   = field->dm;
11751a454edSToby Isaac   nc   = field->numComponents;
11851a454edSToby Isaac   ierr = PetscQuadratureGetData(quad,&dim,NULL,&nq,&qpoints,NULL);CHKERRQ(ierr);
119f99c8401SToby Isaac   ierr = DMFieldDSGetHeightDisc(field,dsfield->height - 1 - dim,&disc);CHKERRQ(ierr);
12051a454edSToby Isaac   ierr = DMGetDimension(dm,&meshDim);CHKERRQ(ierr);
12151a454edSToby Isaac   ierr = DMGetDefaultSection(dm,&section);CHKERRQ(ierr);
12251a454edSToby Isaac   ierr = PetscSectionGetField(section,dsfield->fieldNum,&section);CHKERRQ(ierr);
12351a454edSToby Isaac   ierr = PetscObjectGetClassId(disc,&classid);CHKERRQ(ierr);
12451a454edSToby Isaac   /* TODO: batch */
12551a454edSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject)pointIS,ISSTRIDE,&isStride);CHKERRQ(ierr);
12651a454edSToby Isaac   ierr = ISGetLocalSize(pointIS,&numCells);CHKERRQ(ierr);
12751a454edSToby Isaac   if (isStride) {
12851a454edSToby Isaac     ierr = ISStrideGetInfo(pointIS,&sfirst,&stride);CHKERRQ(ierr);
12951a454edSToby Isaac   } else {
13051a454edSToby Isaac     ierr = ISGetIndices(pointIS,&points);CHKERRQ(ierr);
13151a454edSToby Isaac   }
13251a454edSToby Isaac   if (classid == PETSCFE_CLASSID) {
13351a454edSToby Isaac     PetscFE      fe = (PetscFE) disc;
13451a454edSToby Isaac     PetscInt     feDim, i;
13551a454edSToby Isaac     PetscReal    *fB = NULL, *fD = NULL, *fH = NULL;
13651a454edSToby Isaac 
13751a454edSToby Isaac     if (dim == meshDim - 1) {
13851a454edSToby Isaac       /* TODO */
13951a454edSToby Isaac     }
14051a454edSToby Isaac     ierr = PetscFEGetDimension(fe,&feDim);CHKERRQ(ierr);
14151a454edSToby Isaac     ierr = PetscFEGetTabulation(fe,nq,qpoints,B ? &fB : NULL,D ? &fD : NULL,H ? &fH : NULL);CHKERRQ(ierr);
14251a454edSToby Isaac     for (i = 0; i < numCells; i++) {
14351a454edSToby Isaac       PetscInt     c = isStride ? (sfirst + i * stride) : points[i];
144*2710589cSToby Isaac       PetscInt     closureSize;
145*2710589cSToby Isaac       PetscScalar *elem = NULL;
14651a454edSToby Isaac 
14751a454edSToby Isaac       ierr = DMPlexVecGetClosure(dm,section,dsfield->vec,c,&closureSize,&elem);CHKERRQ(ierr);
14851a454edSToby Isaac       if (B) {
14951a454edSToby Isaac         if (type == PETSC_SCALAR) {
15051a454edSToby Isaac           PetscScalar *cB = &((PetscScalar *) B)[nc * nq * i];
15151a454edSToby Isaac 
15251a454edSToby Isaac           DMFieldDSdot(cB,fB,elem,nq,feDim,nc,(PetscScalar));
15351a454edSToby Isaac         } else {
15451a454edSToby Isaac           PetscReal *cB = &((PetscReal *) B)[nc * nq * i];
15551a454edSToby Isaac 
15651a454edSToby Isaac           DMFieldDSdot(cB,fB,elem,nq,feDim,nc,PetscRealPart);
15751a454edSToby Isaac         }
15851a454edSToby Isaac       }
15951a454edSToby Isaac       if (D) {
16051a454edSToby Isaac         if (type == PETSC_SCALAR) {
16151a454edSToby Isaac           PetscScalar *cD = &((PetscScalar *) D)[nc * nq * dim * i];
16251a454edSToby Isaac 
16351a454edSToby Isaac           DMFieldDSdot(cD,fD,elem,nq,feDim,(nc * dim),(PetscScalar));
16451a454edSToby Isaac         } else {
16551a454edSToby Isaac           PetscReal *cD = &((PetscReal *) D)[nc * nq * dim * i];
16651a454edSToby Isaac 
16751a454edSToby Isaac           DMFieldDSdot(cD,fD,elem,nq,feDim,(nc * dim),PetscRealPart);
16851a454edSToby Isaac         }
16951a454edSToby Isaac       }
17051a454edSToby Isaac       if (H) {
17151a454edSToby Isaac         if (type == PETSC_SCALAR) {
17251a454edSToby Isaac           PetscScalar *cH = &((PetscScalar *) H)[nc * nq * dim * dim * i];
17351a454edSToby Isaac 
17451a454edSToby Isaac           DMFieldDSdot(cH,fH,elem,nq,feDim,(nc * dim * dim),(PetscScalar));
17551a454edSToby Isaac         } else {
17651a454edSToby Isaac           PetscReal *cH = &((PetscReal *) H)[nc * nq * dim * dim * i];
17751a454edSToby Isaac 
17851a454edSToby Isaac           DMFieldDSdot(cH,fH,elem,nq,feDim,(nc * dim * dim),PetscRealPart);
17951a454edSToby Isaac         }
18051a454edSToby Isaac       }
181*2710589cSToby Isaac       ierr = DMPlexVecRestoreClosure(dm,section,dsfield->vec,c,&closureSize,&elem);CHKERRQ(ierr);
18251a454edSToby Isaac     }
18351a454edSToby Isaac     ierr = PetscFERestoreTabulation(fe,nq,qpoints,B ? &fB : NULL,D ? &fD : NULL,H ? &fH : NULL);CHKERRQ(ierr);
18451a454edSToby Isaac   } else {SETERRQ(PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented");}
18551a454edSToby Isaac   if (!isStride) {
18651a454edSToby Isaac     ierr = ISRestoreIndices(pointIS,&points);CHKERRQ(ierr);
18751a454edSToby Isaac   }
18851a454edSToby Isaac   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
18951a454edSToby Isaac   PetscFunctionReturn(0);
19051a454edSToby Isaac }
19151a454edSToby Isaac 
19251a454edSToby Isaac static PetscErrorCode DMFieldGetFEInvariance_DS(DMField field, IS pointIS, PetscBool *isConstant, PetscBool *isAffine, PetscBool *isQuadratic)
19351a454edSToby Isaac {
19451a454edSToby Isaac   DMField_DS     *dsfield;
19551a454edSToby Isaac   PetscObject    disc;
19651a454edSToby Isaac   PetscInt       h, imin;
19751a454edSToby Isaac   PetscClassId   id;
19851a454edSToby Isaac   PetscErrorCode ierr;
19951a454edSToby Isaac 
20051a454edSToby Isaac   PetscFunctionBegin;
20151a454edSToby Isaac   dsfield = (DMField_DS *) field->data;
20251a454edSToby Isaac   ierr = ISGetMinMax(pointIS,&imin,NULL);CHKERRQ(ierr);
203f99c8401SToby Isaac   for (h = 0; h < dsfield->height; h++) {
20451a454edSToby Isaac     PetscInt hEnd;
20551a454edSToby Isaac 
20651a454edSToby Isaac     ierr = DMPlexGetHeightStratum(field->dm,h,NULL,&hEnd);CHKERRQ(ierr);
20751a454edSToby Isaac     if (imin < hEnd) break;
20851a454edSToby Isaac   }
20951a454edSToby Isaac   ierr = DMFieldDSGetHeightDisc(field,h,&disc);CHKERRQ(ierr);
21051a454edSToby Isaac   ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr);
21151a454edSToby Isaac   if (id == PETSCFE_CLASSID) {
21251a454edSToby Isaac     PetscFE    fe = (PetscFE) disc;
21351a454edSToby Isaac     PetscInt   order, maxOrder;
21451a454edSToby Isaac     PetscBool  tensor = PETSC_FALSE;
21551a454edSToby Isaac     PetscSpace sp;
21651a454edSToby Isaac 
21751a454edSToby Isaac     ierr = PetscFEGetBasisSpace(fe, &sp);CHKERRQ(ierr);
21851a454edSToby Isaac     ierr = PetscSpaceGetOrder(sp,&order);CHKERRQ(ierr);
21951a454edSToby Isaac     ierr = PetscSpacePolynomialGetTensor(sp,&tensor);CHKERRQ(ierr);
22051a454edSToby Isaac     if (tensor) {
22151a454edSToby Isaac       PetscInt dim;
22251a454edSToby Isaac 
22351a454edSToby Isaac       ierr = DMGetDimension(field->dm,&dim);CHKERRQ(ierr);
22451a454edSToby Isaac       maxOrder = order * dim;
22551a454edSToby Isaac     } else {
22651a454edSToby Isaac       maxOrder = order;
22751a454edSToby Isaac     }
22851a454edSToby Isaac     if (isConstant)  *isConstant  = (maxOrder < 1) ? PETSC_TRUE : PETSC_FALSE;
22951a454edSToby Isaac     if (isAffine)    *isAffine    = (maxOrder < 2) ? PETSC_TRUE : PETSC_FALSE;
23051a454edSToby Isaac     if (isQuadratic) *isQuadratic = (maxOrder < 3) ? PETSC_TRUE : PETSC_FALSE;
23151a454edSToby Isaac   }
23251a454edSToby Isaac   PetscFunctionReturn(0);
23351a454edSToby Isaac }
23451a454edSToby Isaac 
23551a454edSToby Isaac static PetscErrorCode DMFieldCreateDefaultQuadrature_DS(DMField field, IS pointIS, PetscQuadrature *quad)
23651a454edSToby Isaac {
23751a454edSToby Isaac   PetscInt       h, dim, imax, imin;
23851a454edSToby Isaac   DM             dm;
23951a454edSToby Isaac   DMField_DS     *dsfield;
24051a454edSToby Isaac   PetscObject    disc;
24151a454edSToby Isaac   PetscFE        fe;
24251a454edSToby Isaac   PetscClassId   id;
24351a454edSToby Isaac   PetscErrorCode ierr;
24451a454edSToby Isaac 
24551a454edSToby Isaac 
24651a454edSToby Isaac   PetscFunctionBegin;
24751a454edSToby Isaac   dm = field->dm;
24851a454edSToby Isaac   dsfield = (DMField_DS *) field->data;
24951a454edSToby Isaac   ierr = ISGetMinMax(pointIS,&imax,&imin);CHKERRQ(ierr);
25051a454edSToby Isaac   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
25151a454edSToby Isaac   for (h = 0; h <= dim; h++) {
25251a454edSToby Isaac     PetscInt hStart, hEnd;
25351a454edSToby Isaac 
25451a454edSToby Isaac     ierr = DMPlexGetHeightStratum(dm,h,&hStart,&hEnd);CHKERRQ(ierr);
25551a454edSToby Isaac     if (imin >= hStart && imax < hEnd) break;
25651a454edSToby Isaac   }
25751a454edSToby Isaac   *quad = NULL;
258f99c8401SToby Isaac   if (h < dsfield->height) {
25951a454edSToby Isaac     ierr = DMFieldDSGetHeightDisc(field,h,&disc);CHKERRQ(ierr);
26051a454edSToby Isaac     ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr);
26151a454edSToby Isaac     if (id != PETSCFE_CLASSID) PetscFunctionReturn(0);
26251a454edSToby Isaac     fe = (PetscFE) disc;
26351a454edSToby Isaac     ierr = PetscFEGetQuadrature(fe,quad);CHKERRQ(ierr);
26451a454edSToby Isaac     ierr = PetscObjectReference((PetscObject)*quad);CHKERRQ(ierr);
26551a454edSToby Isaac   }
26651a454edSToby Isaac   PetscFunctionReturn(0);
26751a454edSToby Isaac }
26851a454edSToby Isaac 
26951a454edSToby Isaac static PetscErrorCode DMFieldInitialize_DS(DMField field)
27051a454edSToby Isaac {
27151a454edSToby Isaac   PetscFunctionBegin;
27251a454edSToby Isaac   field->ops->destroy                 = DMFieldDestroy_DS;
27351a454edSToby Isaac   field->ops->evaluate                = DMFieldEvaluate_DS;
27451a454edSToby Isaac   field->ops->evaluateFE              = DMFieldEvaluateFE_DS;
27551a454edSToby Isaac   field->ops->getFEInvariance         = DMFieldGetFEInvariance_DS;
27651a454edSToby Isaac   field->ops->createDefaultQuadrature = DMFieldCreateDefaultQuadrature_DS;
27751a454edSToby Isaac   field->ops->view                    = DMFieldView_DS;
27851a454edSToby Isaac   PetscFunctionReturn(0);
27951a454edSToby Isaac }
28051a454edSToby Isaac 
28151a454edSToby Isaac PETSC_INTERN PetscErrorCode DMFieldCreate_DS(DMField field)
28251a454edSToby Isaac {
28351a454edSToby Isaac   DMField_DS     *dsfield;
28451a454edSToby Isaac   PetscErrorCode ierr;
28551a454edSToby Isaac 
28651a454edSToby Isaac   PetscFunctionBegin;
28751a454edSToby Isaac   ierr = PetscNewLog(field,&dsfield);CHKERRQ(ierr);
28851a454edSToby Isaac   field->data = dsfield;
28951a454edSToby Isaac   ierr = DMFieldInitialize_DS(field);CHKERRQ(ierr);
29051a454edSToby Isaac   PetscFunctionReturn(0);
29151a454edSToby Isaac }
29251a454edSToby Isaac 
29351a454edSToby Isaac PetscErrorCode DMFieldCreateDS(DM dm, PetscInt fieldNum, Vec vec,DMField *field)
29451a454edSToby Isaac {
29551a454edSToby Isaac   DMField        b;
29651a454edSToby Isaac   DMField_DS     *dsfield;
29751a454edSToby Isaac   PetscObject    disc = NULL;
29851a454edSToby Isaac   PetscBool      isContainer = PETSC_FALSE;
29951a454edSToby Isaac   PetscClassId   id = -1;
30051a454edSToby Isaac   PetscInt       numComponents = -1, dsNumFields;
30151a454edSToby Isaac   PetscSection   section;
30251a454edSToby Isaac   PetscErrorCode ierr;
30351a454edSToby Isaac 
30451a454edSToby Isaac   PetscFunctionBegin;
30551a454edSToby Isaac   ierr = DMGetDefaultSection(dm,&section);CHKERRQ(ierr);
30651a454edSToby Isaac   ierr = PetscSectionGetFieldComponents(section,fieldNum,&numComponents);CHKERRQ(ierr);
30751a454edSToby Isaac   ierr = DMGetNumFields(dm,&dsNumFields);CHKERRQ(ierr);
30851a454edSToby Isaac   if (dsNumFields) {ierr = DMGetField(dm,fieldNum,&disc);CHKERRQ(ierr);}
30951a454edSToby Isaac   if (disc) {
31051a454edSToby Isaac     ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr);
31151a454edSToby Isaac     isContainer = (id == PETSC_CONTAINER_CLASSID) ? PETSC_TRUE : PETSC_FALSE;
31251a454edSToby Isaac   }
31351a454edSToby Isaac   if (!disc || isContainer) {
31451a454edSToby Isaac     MPI_Comm        comm = PetscObjectComm((PetscObject) dm);
31551a454edSToby Isaac     PetscInt        cStart, cEnd, dim;
31651a454edSToby Isaac     PetscInt        localConeSize = 0, coneSize;
31751a454edSToby Isaac     PetscFE         fe;
31851a454edSToby Isaac     PetscDualSpace  Q;
31951a454edSToby Isaac     PetscSpace      P;
32051a454edSToby Isaac     DM              K;
32151a454edSToby Isaac     PetscQuadrature quad, fquad;
32251a454edSToby Isaac     PetscBool       isSimplex;
32351a454edSToby Isaac 
32451a454edSToby Isaac     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
32551a454edSToby Isaac     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
32651a454edSToby Isaac     if (cEnd > cStart) {
32751a454edSToby Isaac       ierr = DMPlexGetConeSize(dm, cStart, &localConeSize);CHKERRQ(ierr);
32851a454edSToby Isaac     }
32951a454edSToby Isaac     ierr = MPI_Allreduce(&localConeSize,&coneSize,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
33051a454edSToby Isaac     isSimplex = (coneSize == (dim + 1)) ? PETSC_TRUE : PETSC_FALSE;
33151a454edSToby Isaac     ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr);
33251a454edSToby Isaac     ierr = PetscSpaceSetOrder(P, 1);CHKERRQ(ierr);
33351a454edSToby Isaac     ierr = PetscSpaceSetNumComponents(P, numComponents);CHKERRQ(ierr);
33451a454edSToby Isaac     ierr = PetscSpaceSetType(P,PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr);
33551a454edSToby Isaac     ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr);
33651a454edSToby Isaac     ierr = PetscSpacePolynomialSetTensor(P, isSimplex ? PETSC_FALSE : PETSC_TRUE);CHKERRQ(ierr);
33751a454edSToby Isaac     ierr = PetscSpaceSetUp(P);CHKERRQ(ierr);
33851a454edSToby Isaac     ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr);
33951a454edSToby Isaac     ierr = PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
34051a454edSToby Isaac     ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr);
34151a454edSToby Isaac     ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr);
34251a454edSToby Isaac     ierr = DMDestroy(&K);CHKERRQ(ierr);
34351a454edSToby Isaac     ierr = PetscDualSpaceSetNumComponents(Q, numComponents);CHKERRQ(ierr);
34451a454edSToby Isaac     ierr = PetscDualSpaceSetOrder(Q, 1);CHKERRQ(ierr);
34551a454edSToby Isaac     ierr = PetscDualSpaceLagrangeSetTensor(Q, isSimplex ? PETSC_FALSE : PETSC_TRUE);CHKERRQ(ierr);
34651a454edSToby Isaac     ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr);
34751a454edSToby Isaac     ierr = PetscFECreate(comm, &fe);CHKERRQ(ierr);
34851a454edSToby Isaac     ierr = PetscFESetType(fe,PETSCFEBASIC);CHKERRQ(ierr);
34951a454edSToby Isaac     ierr = PetscFESetBasisSpace(fe, P);CHKERRQ(ierr);
35051a454edSToby Isaac     ierr = PetscFESetDualSpace(fe, Q);CHKERRQ(ierr);
35151a454edSToby Isaac     ierr = PetscFESetNumComponents(fe, numComponents);CHKERRQ(ierr);
35251a454edSToby Isaac     ierr = PetscFESetUp(fe);CHKERRQ(ierr);
35351a454edSToby Isaac     ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr);
35451a454edSToby Isaac     ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr);
35551a454edSToby Isaac     if (isSimplex) {
35651a454edSToby Isaac       ierr = PetscDTGaussJacobiQuadrature(dim,   1, 1, -1.0, 1.0, &quad);CHKERRQ(ierr);
35751a454edSToby Isaac       ierr = PetscDTGaussJacobiQuadrature(dim-1, 1, 1, -1.0, 1.0, &fquad);CHKERRQ(ierr);
35851a454edSToby Isaac     }
35951a454edSToby Isaac     else {
36051a454edSToby Isaac       ierr = PetscDTGaussTensorQuadrature(dim,   1, 1, -1.0, 1.0, &quad);CHKERRQ(ierr);
36151a454edSToby Isaac       ierr = PetscDTGaussTensorQuadrature(dim-1, 1, 1, -1.0, 1.0, &fquad);CHKERRQ(ierr);
36251a454edSToby Isaac     }
36351a454edSToby Isaac     ierr = PetscFESetQuadrature(fe, quad);CHKERRQ(ierr);
36451a454edSToby Isaac     ierr = PetscFESetFaceQuadrature(fe, fquad);CHKERRQ(ierr);
36551a454edSToby Isaac     ierr = PetscQuadratureDestroy(&quad);CHKERRQ(ierr);
36651a454edSToby Isaac     ierr = PetscQuadratureDestroy(&fquad);CHKERRQ(ierr);
36751a454edSToby Isaac     disc = (PetscObject) fe;
36851a454edSToby Isaac   } else {
36951a454edSToby Isaac     ierr = PetscObjectReference(disc);CHKERRQ(ierr);
37051a454edSToby Isaac   }
37151a454edSToby Isaac   ierr = PetscObjectGetClassId(disc,&id);CHKERRQ(ierr);
37251a454edSToby Isaac   if (id == PETSCFE_CLASSID) {
37351a454edSToby Isaac     PetscFE fe = (PetscFE) disc;
37451a454edSToby Isaac 
37551a454edSToby Isaac     ierr = PetscFEGetNumComponents(fe,&numComponents);CHKERRQ(ierr);
37651a454edSToby Isaac   } else {SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Not implemented");}
37751a454edSToby Isaac   ierr = DMFieldCreate(dm,numComponents,DMFIELD_VERTEX,&b);CHKERRQ(ierr);
37851a454edSToby Isaac   ierr = DMFieldSetType(b,DMFIELDDS);CHKERRQ(ierr);
37951a454edSToby Isaac   dsfield = (DMField_DS *) b->data;
38051a454edSToby Isaac   dsfield->fieldNum = fieldNum;
38151a454edSToby Isaac   ierr = DMGetDimension(dm,&dsfield->height);CHKERRQ(ierr);
382f99c8401SToby Isaac   dsfield->height++;
38351a454edSToby Isaac   ierr = PetscCalloc1(dsfield->height,&dsfield->disc);CHKERRQ(ierr);
38451a454edSToby Isaac   dsfield->disc[0] = disc;
38551a454edSToby Isaac   ierr = PetscObjectReference((PetscObject)vec);CHKERRQ(ierr);
38651a454edSToby Isaac   dsfield->vec = vec;
38751a454edSToby Isaac   *field = b;
38851a454edSToby Isaac 
38951a454edSToby Isaac   PetscFunctionReturn(0);
39051a454edSToby Isaac }
391