xref: /petsc/src/dm/dt/fe/interface/fe.c (revision 5fedec97950c19de564efaecd0f125b1a6cb2b20)
120cf1dd8SToby Isaac /* Basis Jet Tabulation
220cf1dd8SToby Isaac 
320cf1dd8SToby Isaac We would like to tabulate the nodal basis functions and derivatives at a set of points, usually quadrature points. We
420cf1dd8SToby Isaac follow here the derviation in http://www.math.ttu.edu/~kirby/papers/fiat-toms-2004.pdf. The nodal basis $\psi_i$ can
520cf1dd8SToby Isaac be expressed in terms of a prime basis $\phi_i$ which can be stably evaluated. In PETSc, we will use the Legendre basis
620cf1dd8SToby Isaac as a prime basis.
720cf1dd8SToby Isaac 
820cf1dd8SToby Isaac   \psi_i = \sum_k \alpha_{ki} \phi_k
920cf1dd8SToby Isaac 
1020cf1dd8SToby Isaac Our nodal basis is defined in terms of the dual basis $n_j$
1120cf1dd8SToby Isaac 
1220cf1dd8SToby Isaac   n_j \cdot \psi_i = \delta_{ji}
1320cf1dd8SToby Isaac 
1420cf1dd8SToby Isaac and we may act on the first equation to obtain
1520cf1dd8SToby Isaac 
1620cf1dd8SToby Isaac   n_j \cdot \psi_i = \sum_k \alpha_{ki} n_j \cdot \phi_k
1720cf1dd8SToby Isaac        \delta_{ji} = \sum_k \alpha_{ki} V_{jk}
1820cf1dd8SToby Isaac                  I = V \alpha
1920cf1dd8SToby Isaac 
2020cf1dd8SToby Isaac so the coefficients of the nodal basis in the prime basis are
2120cf1dd8SToby Isaac 
2220cf1dd8SToby Isaac    \alpha = V^{-1}
2320cf1dd8SToby Isaac 
2420cf1dd8SToby Isaac We will define the dual basis vectors $n_j$ using a quadrature rule.
2520cf1dd8SToby Isaac 
2620cf1dd8SToby Isaac Right now, we will just use the polynomial spaces P^k. I know some elements use the space of symmetric polynomials
2720cf1dd8SToby Isaac (I think Nedelec), but we will neglect this for now. Constraints in the space, e.g. Arnold-Winther elements, can
2820cf1dd8SToby Isaac be implemented exactly as in FIAT using functionals $L_j$.
2920cf1dd8SToby Isaac 
3020cf1dd8SToby Isaac I will have to count the degrees correctly for the Legendre product when we are on simplices.
3120cf1dd8SToby Isaac 
3220cf1dd8SToby Isaac We will have three objects:
3320cf1dd8SToby Isaac  - Space, P: this just need point evaluation I think
3420cf1dd8SToby Isaac  - Dual Space, P'+K: This looks like a set of functionals that can act on members of P, each n is defined by a Q
3520cf1dd8SToby Isaac  - FEM: This keeps {P, P', Q}
3620cf1dd8SToby Isaac */
3720cf1dd8SToby Isaac #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
3820cf1dd8SToby Isaac #include <petscdmplex.h>
3920cf1dd8SToby Isaac 
4020cf1dd8SToby Isaac PetscBool FEcite = PETSC_FALSE;
4120cf1dd8SToby Isaac const char FECitation[] = "@article{kirby2004,\n"
4220cf1dd8SToby Isaac                           "  title   = {Algorithm 839: FIAT, a New Paradigm for Computing Finite Element Basis Functions},\n"
4320cf1dd8SToby Isaac                           "  journal = {ACM Transactions on Mathematical Software},\n"
4420cf1dd8SToby Isaac                           "  author  = {Robert C. Kirby},\n"
4520cf1dd8SToby Isaac                           "  volume  = {30},\n"
4620cf1dd8SToby Isaac                           "  number  = {4},\n"
4720cf1dd8SToby Isaac                           "  pages   = {502--516},\n"
4820cf1dd8SToby Isaac                           "  doi     = {10.1145/1039813.1039820},\n"
4920cf1dd8SToby Isaac                           "  year    = {2004}\n}\n";
5020cf1dd8SToby Isaac 
5120cf1dd8SToby Isaac PetscClassId PETSCFE_CLASSID = 0;
5220cf1dd8SToby Isaac 
53ead873ccSMatthew G. Knepley PetscLogEvent PETSCFE_SetUp;
54ead873ccSMatthew G. Knepley 
5520cf1dd8SToby Isaac PetscFunctionList PetscFEList              = NULL;
5620cf1dd8SToby Isaac PetscBool         PetscFERegisterAllCalled = PETSC_FALSE;
5720cf1dd8SToby Isaac 
5820cf1dd8SToby Isaac /*@C
5920cf1dd8SToby Isaac   PetscFERegister - Adds a new PetscFE implementation
6020cf1dd8SToby Isaac 
6120cf1dd8SToby Isaac   Not Collective
6220cf1dd8SToby Isaac 
6320cf1dd8SToby Isaac   Input Parameters:
6420cf1dd8SToby Isaac + name        - The name of a new user-defined creation routine
6520cf1dd8SToby Isaac - create_func - The creation routine itself
6620cf1dd8SToby Isaac 
6720cf1dd8SToby Isaac   Notes:
6820cf1dd8SToby Isaac   PetscFERegister() may be called multiple times to add several user-defined PetscFEs
6920cf1dd8SToby Isaac 
7020cf1dd8SToby Isaac   Sample usage:
7120cf1dd8SToby Isaac .vb
7220cf1dd8SToby Isaac     PetscFERegister("my_fe", MyPetscFECreate);
7320cf1dd8SToby Isaac .ve
7420cf1dd8SToby Isaac 
7520cf1dd8SToby Isaac   Then, your PetscFE type can be chosen with the procedural interface via
7620cf1dd8SToby Isaac .vb
7720cf1dd8SToby Isaac     PetscFECreate(MPI_Comm, PetscFE *);
7820cf1dd8SToby Isaac     PetscFESetType(PetscFE, "my_fe");
7920cf1dd8SToby Isaac .ve
8020cf1dd8SToby Isaac    or at runtime via the option
8120cf1dd8SToby Isaac .vb
8220cf1dd8SToby Isaac     -petscfe_type my_fe
8320cf1dd8SToby Isaac .ve
8420cf1dd8SToby Isaac 
8520cf1dd8SToby Isaac   Level: advanced
8620cf1dd8SToby Isaac 
8720cf1dd8SToby Isaac .seealso: PetscFERegisterAll(), PetscFERegisterDestroy()
8820cf1dd8SToby Isaac 
8920cf1dd8SToby Isaac @*/
9020cf1dd8SToby Isaac PetscErrorCode PetscFERegister(const char sname[], PetscErrorCode (*function)(PetscFE))
9120cf1dd8SToby Isaac {
9220cf1dd8SToby Isaac   PetscErrorCode ierr;
9320cf1dd8SToby Isaac 
9420cf1dd8SToby Isaac   PetscFunctionBegin;
9520cf1dd8SToby Isaac   ierr = PetscFunctionListAdd(&PetscFEList, sname, function);CHKERRQ(ierr);
9620cf1dd8SToby Isaac   PetscFunctionReturn(0);
9720cf1dd8SToby Isaac }
9820cf1dd8SToby Isaac 
9920cf1dd8SToby Isaac /*@C
10020cf1dd8SToby Isaac   PetscFESetType - Builds a particular PetscFE
10120cf1dd8SToby Isaac 
102d083f849SBarry Smith   Collective on fem
10320cf1dd8SToby Isaac 
10420cf1dd8SToby Isaac   Input Parameters:
10520cf1dd8SToby Isaac + fem  - The PetscFE object
10620cf1dd8SToby Isaac - name - The kind of FEM space
10720cf1dd8SToby Isaac 
10820cf1dd8SToby Isaac   Options Database Key:
10920cf1dd8SToby Isaac . -petscfe_type <type> - Sets the PetscFE type; use -help for a list of available types
11020cf1dd8SToby Isaac 
11120cf1dd8SToby Isaac   Level: intermediate
11220cf1dd8SToby Isaac 
11320cf1dd8SToby Isaac .seealso: PetscFEGetType(), PetscFECreate()
11420cf1dd8SToby Isaac @*/
11520cf1dd8SToby Isaac PetscErrorCode PetscFESetType(PetscFE fem, PetscFEType name)
11620cf1dd8SToby Isaac {
11720cf1dd8SToby Isaac   PetscErrorCode (*r)(PetscFE);
11820cf1dd8SToby Isaac   PetscBool      match;
11920cf1dd8SToby Isaac   PetscErrorCode ierr;
12020cf1dd8SToby Isaac 
12120cf1dd8SToby Isaac   PetscFunctionBegin;
12220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
12320cf1dd8SToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) fem, name, &match);CHKERRQ(ierr);
12420cf1dd8SToby Isaac   if (match) PetscFunctionReturn(0);
12520cf1dd8SToby Isaac 
12620cf1dd8SToby Isaac   if (!PetscFERegisterAllCalled) {ierr = PetscFERegisterAll();CHKERRQ(ierr);}
12720cf1dd8SToby Isaac   ierr = PetscFunctionListFind(PetscFEList, name, &r);CHKERRQ(ierr);
12820cf1dd8SToby Isaac   if (!r) SETERRQ1(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscFE type: %s", name);
12920cf1dd8SToby Isaac 
13020cf1dd8SToby Isaac   if (fem->ops->destroy) {
13120cf1dd8SToby Isaac     ierr              = (*fem->ops->destroy)(fem);CHKERRQ(ierr);
13220cf1dd8SToby Isaac     fem->ops->destroy = NULL;
13320cf1dd8SToby Isaac   }
13420cf1dd8SToby Isaac   ierr = (*r)(fem);CHKERRQ(ierr);
13520cf1dd8SToby Isaac   ierr = PetscObjectChangeTypeName((PetscObject) fem, name);CHKERRQ(ierr);
13620cf1dd8SToby Isaac   PetscFunctionReturn(0);
13720cf1dd8SToby Isaac }
13820cf1dd8SToby Isaac 
13920cf1dd8SToby Isaac /*@C
14020cf1dd8SToby Isaac   PetscFEGetType - Gets the PetscFE type name (as a string) from the object.
14120cf1dd8SToby Isaac 
14220cf1dd8SToby Isaac   Not Collective
14320cf1dd8SToby Isaac 
14420cf1dd8SToby Isaac   Input Parameter:
14520cf1dd8SToby Isaac . fem  - The PetscFE
14620cf1dd8SToby Isaac 
14720cf1dd8SToby Isaac   Output Parameter:
14820cf1dd8SToby Isaac . name - The PetscFE type name
14920cf1dd8SToby Isaac 
15020cf1dd8SToby Isaac   Level: intermediate
15120cf1dd8SToby Isaac 
15220cf1dd8SToby Isaac .seealso: PetscFESetType(), PetscFECreate()
15320cf1dd8SToby Isaac @*/
15420cf1dd8SToby Isaac PetscErrorCode PetscFEGetType(PetscFE fem, PetscFEType *name)
15520cf1dd8SToby Isaac {
15620cf1dd8SToby Isaac   PetscErrorCode ierr;
15720cf1dd8SToby Isaac 
15820cf1dd8SToby Isaac   PetscFunctionBegin;
15920cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
16020cf1dd8SToby Isaac   PetscValidPointer(name, 2);
16120cf1dd8SToby Isaac   if (!PetscFERegisterAllCalled) {
16220cf1dd8SToby Isaac     ierr = PetscFERegisterAll();CHKERRQ(ierr);
16320cf1dd8SToby Isaac   }
16420cf1dd8SToby Isaac   *name = ((PetscObject) fem)->type_name;
16520cf1dd8SToby Isaac   PetscFunctionReturn(0);
16620cf1dd8SToby Isaac }
16720cf1dd8SToby Isaac 
16820cf1dd8SToby Isaac /*@C
169fe2efc57SMark    PetscFEViewFromOptions - View from Options
170fe2efc57SMark 
171fe2efc57SMark    Collective on PetscFE
172fe2efc57SMark 
173fe2efc57SMark    Input Parameters:
174fe2efc57SMark +  A - the PetscFE object
175fe2efc57SMark .  obj - Optional object
176fe2efc57SMark -  name - command line option
177fe2efc57SMark 
178fe2efc57SMark    Level: intermediate
179fe2efc57SMark .seealso:  PetscFE(), PetscFEView(), PetscObjectViewFromOptions(), PetscFECreate()
180fe2efc57SMark @*/
181fe2efc57SMark PetscErrorCode  PetscFEViewFromOptions(PetscFE A,PetscObject obj,const char name[])
182fe2efc57SMark {
183fe2efc57SMark   PetscErrorCode ierr;
184fe2efc57SMark 
185fe2efc57SMark   PetscFunctionBegin;
186fe2efc57SMark   PetscValidHeaderSpecific(A,PETSCFE_CLASSID,1);
187fe2efc57SMark   ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr);
188fe2efc57SMark   PetscFunctionReturn(0);
189fe2efc57SMark }
190fe2efc57SMark 
191fe2efc57SMark /*@C
19220cf1dd8SToby Isaac   PetscFEView - Views a PetscFE
19320cf1dd8SToby Isaac 
194d083f849SBarry Smith   Collective on fem
19520cf1dd8SToby Isaac 
196d8d19677SJose E. Roman   Input Parameters:
19720cf1dd8SToby Isaac + fem - the PetscFE object to view
198d9bac1caSLisandro Dalcin - viewer   - the viewer
19920cf1dd8SToby Isaac 
2002b99622eSMatthew G. Knepley   Level: beginner
20120cf1dd8SToby Isaac 
20220cf1dd8SToby Isaac .seealso PetscFEDestroy()
20320cf1dd8SToby Isaac @*/
204d9bac1caSLisandro Dalcin PetscErrorCode PetscFEView(PetscFE fem, PetscViewer viewer)
20520cf1dd8SToby Isaac {
206d9bac1caSLisandro Dalcin   PetscBool      iascii;
20720cf1dd8SToby Isaac   PetscErrorCode ierr;
20820cf1dd8SToby Isaac 
20920cf1dd8SToby Isaac   PetscFunctionBegin;
21020cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
211d9bac1caSLisandro Dalcin   if (viewer) PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
212d9bac1caSLisandro Dalcin   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) fem), &viewer);CHKERRQ(ierr);}
213d9bac1caSLisandro Dalcin   ierr = PetscObjectPrintClassNamePrefixType((PetscObject)fem, viewer);CHKERRQ(ierr);
214d9bac1caSLisandro Dalcin   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
215d9bac1caSLisandro Dalcin   if (fem->ops->view) {ierr = (*fem->ops->view)(fem, viewer);CHKERRQ(ierr);}
21620cf1dd8SToby Isaac   PetscFunctionReturn(0);
21720cf1dd8SToby Isaac }
21820cf1dd8SToby Isaac 
21920cf1dd8SToby Isaac /*@
22020cf1dd8SToby Isaac   PetscFESetFromOptions - sets parameters in a PetscFE from the options database
22120cf1dd8SToby Isaac 
222d083f849SBarry Smith   Collective on fem
22320cf1dd8SToby Isaac 
22420cf1dd8SToby Isaac   Input Parameter:
22520cf1dd8SToby Isaac . fem - the PetscFE object to set options for
22620cf1dd8SToby Isaac 
22720cf1dd8SToby Isaac   Options Database:
228a2b725a8SWilliam Gropp + -petscfe_num_blocks  - the number of cell blocks to integrate concurrently
229a2b725a8SWilliam Gropp - -petscfe_num_batches - the number of cell batches to integrate serially
23020cf1dd8SToby Isaac 
2312b99622eSMatthew G. Knepley   Level: intermediate
23220cf1dd8SToby Isaac 
23320cf1dd8SToby Isaac .seealso PetscFEView()
23420cf1dd8SToby Isaac @*/
23520cf1dd8SToby Isaac PetscErrorCode PetscFESetFromOptions(PetscFE fem)
23620cf1dd8SToby Isaac {
23720cf1dd8SToby Isaac   const char    *defaultType;
23820cf1dd8SToby Isaac   char           name[256];
23920cf1dd8SToby Isaac   PetscBool      flg;
24020cf1dd8SToby Isaac   PetscErrorCode ierr;
24120cf1dd8SToby Isaac 
24220cf1dd8SToby Isaac   PetscFunctionBegin;
24320cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
24420cf1dd8SToby Isaac   if (!((PetscObject) fem)->type_name) {
24520cf1dd8SToby Isaac     defaultType = PETSCFEBASIC;
24620cf1dd8SToby Isaac   } else {
24720cf1dd8SToby Isaac     defaultType = ((PetscObject) fem)->type_name;
24820cf1dd8SToby Isaac   }
24920cf1dd8SToby Isaac   if (!PetscFERegisterAllCalled) {ierr = PetscFERegisterAll();CHKERRQ(ierr);}
25020cf1dd8SToby Isaac 
25120cf1dd8SToby Isaac   ierr = PetscObjectOptionsBegin((PetscObject) fem);CHKERRQ(ierr);
25220cf1dd8SToby Isaac   ierr = PetscOptionsFList("-petscfe_type", "Finite element space", "PetscFESetType", PetscFEList, defaultType, name, 256, &flg);CHKERRQ(ierr);
25320cf1dd8SToby Isaac   if (flg) {
25420cf1dd8SToby Isaac     ierr = PetscFESetType(fem, name);CHKERRQ(ierr);
25520cf1dd8SToby Isaac   } else if (!((PetscObject) fem)->type_name) {
25620cf1dd8SToby Isaac     ierr = PetscFESetType(fem, defaultType);CHKERRQ(ierr);
25720cf1dd8SToby Isaac   }
2585a856986SBarry Smith   ierr = PetscOptionsBoundedInt("-petscfe_num_blocks", "The number of cell blocks to integrate concurrently", "PetscSpaceSetTileSizes", fem->numBlocks, &fem->numBlocks, NULL,1);CHKERRQ(ierr);
2595a856986SBarry Smith   ierr = PetscOptionsBoundedInt("-petscfe_num_batches", "The number of cell batches to integrate serially", "PetscSpaceSetTileSizes", fem->numBatches, &fem->numBatches, NULL,1);CHKERRQ(ierr);
26020cf1dd8SToby Isaac   if (fem->ops->setfromoptions) {
26120cf1dd8SToby Isaac     ierr = (*fem->ops->setfromoptions)(PetscOptionsObject,fem);CHKERRQ(ierr);
26220cf1dd8SToby Isaac   }
26320cf1dd8SToby Isaac   /* process any options handlers added with PetscObjectAddOptionsHandler() */
26420cf1dd8SToby Isaac   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) fem);CHKERRQ(ierr);
26520cf1dd8SToby Isaac   ierr = PetscOptionsEnd();CHKERRQ(ierr);
26620cf1dd8SToby Isaac   ierr = PetscFEViewFromOptions(fem, NULL, "-petscfe_view");CHKERRQ(ierr);
26720cf1dd8SToby Isaac   PetscFunctionReturn(0);
26820cf1dd8SToby Isaac }
26920cf1dd8SToby Isaac 
27020cf1dd8SToby Isaac /*@C
27120cf1dd8SToby Isaac   PetscFESetUp - Construct data structures for the PetscFE
27220cf1dd8SToby Isaac 
273d083f849SBarry Smith   Collective on fem
27420cf1dd8SToby Isaac 
27520cf1dd8SToby Isaac   Input Parameter:
27620cf1dd8SToby Isaac . fem - the PetscFE object to setup
27720cf1dd8SToby Isaac 
2782b99622eSMatthew G. Knepley   Level: intermediate
27920cf1dd8SToby Isaac 
28020cf1dd8SToby Isaac .seealso PetscFEView(), PetscFEDestroy()
28120cf1dd8SToby Isaac @*/
28220cf1dd8SToby Isaac PetscErrorCode PetscFESetUp(PetscFE fem)
28320cf1dd8SToby Isaac {
28420cf1dd8SToby Isaac   PetscErrorCode ierr;
28520cf1dd8SToby Isaac 
28620cf1dd8SToby Isaac   PetscFunctionBegin;
28720cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
28820cf1dd8SToby Isaac   if (fem->setupcalled) PetscFunctionReturn(0);
289ead873ccSMatthew G. Knepley   ierr = PetscLogEventBegin(PETSCFE_SetUp, fem, 0, 0, 0);CHKERRQ(ierr);
29020cf1dd8SToby Isaac   fem->setupcalled = PETSC_TRUE;
29120cf1dd8SToby Isaac   if (fem->ops->setup) {ierr = (*fem->ops->setup)(fem);CHKERRQ(ierr);}
292ead873ccSMatthew G. Knepley   ierr = PetscLogEventEnd(PETSCFE_SetUp, fem, 0, 0, 0);CHKERRQ(ierr);
29320cf1dd8SToby Isaac   PetscFunctionReturn(0);
29420cf1dd8SToby Isaac }
29520cf1dd8SToby Isaac 
29620cf1dd8SToby Isaac /*@
29720cf1dd8SToby Isaac   PetscFEDestroy - Destroys a PetscFE object
29820cf1dd8SToby Isaac 
299d083f849SBarry Smith   Collective on fem
30020cf1dd8SToby Isaac 
30120cf1dd8SToby Isaac   Input Parameter:
30220cf1dd8SToby Isaac . fem - the PetscFE object to destroy
30320cf1dd8SToby Isaac 
3042b99622eSMatthew G. Knepley   Level: beginner
30520cf1dd8SToby Isaac 
30620cf1dd8SToby Isaac .seealso PetscFEView()
30720cf1dd8SToby Isaac @*/
30820cf1dd8SToby Isaac PetscErrorCode PetscFEDestroy(PetscFE *fem)
30920cf1dd8SToby Isaac {
31020cf1dd8SToby Isaac   PetscErrorCode ierr;
31120cf1dd8SToby Isaac 
31220cf1dd8SToby Isaac   PetscFunctionBegin;
31320cf1dd8SToby Isaac   if (!*fem) PetscFunctionReturn(0);
31420cf1dd8SToby Isaac   PetscValidHeaderSpecific((*fem), PETSCFE_CLASSID, 1);
31520cf1dd8SToby Isaac 
316ea78f98cSLisandro Dalcin   if (--((PetscObject)(*fem))->refct > 0) {*fem = NULL; PetscFunctionReturn(0);}
31720cf1dd8SToby Isaac   ((PetscObject) (*fem))->refct = 0;
31820cf1dd8SToby Isaac 
31920cf1dd8SToby Isaac   if ((*fem)->subspaces) {
32020cf1dd8SToby Isaac     PetscInt dim, d;
32120cf1dd8SToby Isaac 
32220cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDimension((*fem)->dualSpace, &dim);CHKERRQ(ierr);
32320cf1dd8SToby Isaac     for (d = 0; d < dim; ++d) {ierr = PetscFEDestroy(&(*fem)->subspaces[d]);CHKERRQ(ierr);}
32420cf1dd8SToby Isaac   }
32520cf1dd8SToby Isaac   ierr = PetscFree((*fem)->subspaces);CHKERRQ(ierr);
32620cf1dd8SToby Isaac   ierr = PetscFree((*fem)->invV);CHKERRQ(ierr);
327ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&(*fem)->T);CHKERRQ(ierr);
328ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&(*fem)->Tf);CHKERRQ(ierr);
329ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&(*fem)->Tc);CHKERRQ(ierr);
33020cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&(*fem)->basisSpace);CHKERRQ(ierr);
33120cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&(*fem)->dualSpace);CHKERRQ(ierr);
33220cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&(*fem)->quadrature);CHKERRQ(ierr);
33320cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&(*fem)->faceQuadrature);CHKERRQ(ierr);
334f918ec44SMatthew G. Knepley #ifdef PETSC_HAVE_LIBCEED
335f918ec44SMatthew G. Knepley   ierr = CeedBasisDestroy(&(*fem)->ceedBasis);CHKERRQ(ierr);
336f918ec44SMatthew G. Knepley   ierr = CeedDestroy(&(*fem)->ceed);CHKERRQ(ierr);
337f918ec44SMatthew G. Knepley #endif
33820cf1dd8SToby Isaac 
33920cf1dd8SToby Isaac   if ((*fem)->ops->destroy) {ierr = (*(*fem)->ops->destroy)(*fem);CHKERRQ(ierr);}
34020cf1dd8SToby Isaac   ierr = PetscHeaderDestroy(fem);CHKERRQ(ierr);
34120cf1dd8SToby Isaac   PetscFunctionReturn(0);
34220cf1dd8SToby Isaac }
34320cf1dd8SToby Isaac 
34420cf1dd8SToby Isaac /*@
34520cf1dd8SToby Isaac   PetscFECreate - Creates an empty PetscFE object. The type can then be set with PetscFESetType().
34620cf1dd8SToby Isaac 
347d083f849SBarry Smith   Collective
34820cf1dd8SToby Isaac 
34920cf1dd8SToby Isaac   Input Parameter:
35020cf1dd8SToby Isaac . comm - The communicator for the PetscFE object
35120cf1dd8SToby Isaac 
35220cf1dd8SToby Isaac   Output Parameter:
35320cf1dd8SToby Isaac . fem - The PetscFE object
35420cf1dd8SToby Isaac 
35520cf1dd8SToby Isaac   Level: beginner
35620cf1dd8SToby Isaac 
35720cf1dd8SToby Isaac .seealso: PetscFESetType(), PETSCFEGALERKIN
35820cf1dd8SToby Isaac @*/
35920cf1dd8SToby Isaac PetscErrorCode PetscFECreate(MPI_Comm comm, PetscFE *fem)
36020cf1dd8SToby Isaac {
36120cf1dd8SToby Isaac   PetscFE        f;
36220cf1dd8SToby Isaac   PetscErrorCode ierr;
36320cf1dd8SToby Isaac 
36420cf1dd8SToby Isaac   PetscFunctionBegin;
36520cf1dd8SToby Isaac   PetscValidPointer(fem, 2);
36620cf1dd8SToby Isaac   ierr = PetscCitationsRegister(FECitation,&FEcite);CHKERRQ(ierr);
36720cf1dd8SToby Isaac   *fem = NULL;
36820cf1dd8SToby Isaac   ierr = PetscFEInitializePackage();CHKERRQ(ierr);
36920cf1dd8SToby Isaac 
37020cf1dd8SToby Isaac   ierr = PetscHeaderCreate(f, PETSCFE_CLASSID, "PetscFE", "Finite Element", "PetscFE", comm, PetscFEDestroy, PetscFEView);CHKERRQ(ierr);
37120cf1dd8SToby Isaac 
37220cf1dd8SToby Isaac   f->basisSpace    = NULL;
37320cf1dd8SToby Isaac   f->dualSpace     = NULL;
37420cf1dd8SToby Isaac   f->numComponents = 1;
37520cf1dd8SToby Isaac   f->subspaces     = NULL;
37620cf1dd8SToby Isaac   f->invV          = NULL;
377ef0bb6c7SMatthew G. Knepley   f->T             = NULL;
378ef0bb6c7SMatthew G. Knepley   f->Tf            = NULL;
379ef0bb6c7SMatthew G. Knepley   f->Tc            = NULL;
380580bdb30SBarry Smith   ierr = PetscArrayzero(&f->quadrature, 1);CHKERRQ(ierr);
381580bdb30SBarry Smith   ierr = PetscArrayzero(&f->faceQuadrature, 1);CHKERRQ(ierr);
38220cf1dd8SToby Isaac   f->blockSize     = 0;
38320cf1dd8SToby Isaac   f->numBlocks     = 1;
38420cf1dd8SToby Isaac   f->batchSize     = 0;
38520cf1dd8SToby Isaac   f->numBatches    = 1;
38620cf1dd8SToby Isaac 
38720cf1dd8SToby Isaac   *fem = f;
38820cf1dd8SToby Isaac   PetscFunctionReturn(0);
38920cf1dd8SToby Isaac }
39020cf1dd8SToby Isaac 
39120cf1dd8SToby Isaac /*@
39220cf1dd8SToby Isaac   PetscFEGetSpatialDimension - Returns the spatial dimension of the element
39320cf1dd8SToby Isaac 
39420cf1dd8SToby Isaac   Not collective
39520cf1dd8SToby Isaac 
39620cf1dd8SToby Isaac   Input Parameter:
39720cf1dd8SToby Isaac . fem - The PetscFE object
39820cf1dd8SToby Isaac 
39920cf1dd8SToby Isaac   Output Parameter:
40020cf1dd8SToby Isaac . dim - The spatial dimension
40120cf1dd8SToby Isaac 
40220cf1dd8SToby Isaac   Level: intermediate
40320cf1dd8SToby Isaac 
40420cf1dd8SToby Isaac .seealso: PetscFECreate()
40520cf1dd8SToby Isaac @*/
40620cf1dd8SToby Isaac PetscErrorCode PetscFEGetSpatialDimension(PetscFE fem, PetscInt *dim)
40720cf1dd8SToby Isaac {
40820cf1dd8SToby Isaac   DM             dm;
40920cf1dd8SToby Isaac   PetscErrorCode ierr;
41020cf1dd8SToby Isaac 
41120cf1dd8SToby Isaac   PetscFunctionBegin;
41220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
41320cf1dd8SToby Isaac   PetscValidPointer(dim, 2);
41420cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr);
41520cf1dd8SToby Isaac   ierr = DMGetDimension(dm, dim);CHKERRQ(ierr);
41620cf1dd8SToby Isaac   PetscFunctionReturn(0);
41720cf1dd8SToby Isaac }
41820cf1dd8SToby Isaac 
41920cf1dd8SToby Isaac /*@
42020cf1dd8SToby Isaac   PetscFESetNumComponents - Sets the number of components in the element
42120cf1dd8SToby Isaac 
42220cf1dd8SToby Isaac   Not collective
42320cf1dd8SToby Isaac 
42420cf1dd8SToby Isaac   Input Parameters:
42520cf1dd8SToby Isaac + fem - The PetscFE object
42620cf1dd8SToby Isaac - comp - The number of field components
42720cf1dd8SToby Isaac 
42820cf1dd8SToby Isaac   Level: intermediate
42920cf1dd8SToby Isaac 
43020cf1dd8SToby Isaac .seealso: PetscFECreate()
43120cf1dd8SToby Isaac @*/
43220cf1dd8SToby Isaac PetscErrorCode PetscFESetNumComponents(PetscFE fem, PetscInt comp)
43320cf1dd8SToby Isaac {
43420cf1dd8SToby Isaac   PetscFunctionBegin;
43520cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
43620cf1dd8SToby Isaac   fem->numComponents = comp;
43720cf1dd8SToby Isaac   PetscFunctionReturn(0);
43820cf1dd8SToby Isaac }
43920cf1dd8SToby Isaac 
44020cf1dd8SToby Isaac /*@
44120cf1dd8SToby Isaac   PetscFEGetNumComponents - Returns the number of components in the element
44220cf1dd8SToby Isaac 
44320cf1dd8SToby Isaac   Not collective
44420cf1dd8SToby Isaac 
44520cf1dd8SToby Isaac   Input Parameter:
44620cf1dd8SToby Isaac . fem - The PetscFE object
44720cf1dd8SToby Isaac 
44820cf1dd8SToby Isaac   Output Parameter:
44920cf1dd8SToby Isaac . comp - The number of field components
45020cf1dd8SToby Isaac 
45120cf1dd8SToby Isaac   Level: intermediate
45220cf1dd8SToby Isaac 
45320cf1dd8SToby Isaac .seealso: PetscFECreate()
45420cf1dd8SToby Isaac @*/
45520cf1dd8SToby Isaac PetscErrorCode PetscFEGetNumComponents(PetscFE fem, PetscInt *comp)
45620cf1dd8SToby Isaac {
45720cf1dd8SToby Isaac   PetscFunctionBegin;
45820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
45920cf1dd8SToby Isaac   PetscValidPointer(comp, 2);
46020cf1dd8SToby Isaac   *comp = fem->numComponents;
46120cf1dd8SToby Isaac   PetscFunctionReturn(0);
46220cf1dd8SToby Isaac }
46320cf1dd8SToby Isaac 
46420cf1dd8SToby Isaac /*@
46520cf1dd8SToby Isaac   PetscFESetTileSizes - Sets the tile sizes for evaluation
46620cf1dd8SToby Isaac 
46720cf1dd8SToby Isaac   Not collective
46820cf1dd8SToby Isaac 
46920cf1dd8SToby Isaac   Input Parameters:
47020cf1dd8SToby Isaac + fem - The PetscFE object
47120cf1dd8SToby Isaac . blockSize - The number of elements in a block
47220cf1dd8SToby Isaac . numBlocks - The number of blocks in a batch
47320cf1dd8SToby Isaac . batchSize - The number of elements in a batch
47420cf1dd8SToby Isaac - numBatches - The number of batches in a chunk
47520cf1dd8SToby Isaac 
47620cf1dd8SToby Isaac   Level: intermediate
47720cf1dd8SToby Isaac 
47820cf1dd8SToby Isaac .seealso: PetscFECreate()
47920cf1dd8SToby Isaac @*/
48020cf1dd8SToby Isaac PetscErrorCode PetscFESetTileSizes(PetscFE fem, PetscInt blockSize, PetscInt numBlocks, PetscInt batchSize, PetscInt numBatches)
48120cf1dd8SToby Isaac {
48220cf1dd8SToby Isaac   PetscFunctionBegin;
48320cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
48420cf1dd8SToby Isaac   fem->blockSize  = blockSize;
48520cf1dd8SToby Isaac   fem->numBlocks  = numBlocks;
48620cf1dd8SToby Isaac   fem->batchSize  = batchSize;
48720cf1dd8SToby Isaac   fem->numBatches = numBatches;
48820cf1dd8SToby Isaac   PetscFunctionReturn(0);
48920cf1dd8SToby Isaac }
49020cf1dd8SToby Isaac 
49120cf1dd8SToby Isaac /*@
49220cf1dd8SToby Isaac   PetscFEGetTileSizes - Returns the tile sizes for evaluation
49320cf1dd8SToby Isaac 
49420cf1dd8SToby Isaac   Not collective
49520cf1dd8SToby Isaac 
49620cf1dd8SToby Isaac   Input Parameter:
49720cf1dd8SToby Isaac . fem - The PetscFE object
49820cf1dd8SToby Isaac 
49920cf1dd8SToby Isaac   Output Parameters:
50020cf1dd8SToby Isaac + blockSize - The number of elements in a block
50120cf1dd8SToby Isaac . numBlocks - The number of blocks in a batch
50220cf1dd8SToby Isaac . batchSize - The number of elements in a batch
50320cf1dd8SToby Isaac - numBatches - The number of batches in a chunk
50420cf1dd8SToby Isaac 
50520cf1dd8SToby Isaac   Level: intermediate
50620cf1dd8SToby Isaac 
50720cf1dd8SToby Isaac .seealso: PetscFECreate()
50820cf1dd8SToby Isaac @*/
50920cf1dd8SToby Isaac PetscErrorCode PetscFEGetTileSizes(PetscFE fem, PetscInt *blockSize, PetscInt *numBlocks, PetscInt *batchSize, PetscInt *numBatches)
51020cf1dd8SToby Isaac {
51120cf1dd8SToby Isaac   PetscFunctionBegin;
51220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
51320cf1dd8SToby Isaac   if (blockSize)  PetscValidPointer(blockSize,  2);
51420cf1dd8SToby Isaac   if (numBlocks)  PetscValidPointer(numBlocks,  3);
51520cf1dd8SToby Isaac   if (batchSize)  PetscValidPointer(batchSize,  4);
51620cf1dd8SToby Isaac   if (numBatches) PetscValidPointer(numBatches, 5);
51720cf1dd8SToby Isaac   if (blockSize)  *blockSize  = fem->blockSize;
51820cf1dd8SToby Isaac   if (numBlocks)  *numBlocks  = fem->numBlocks;
51920cf1dd8SToby Isaac   if (batchSize)  *batchSize  = fem->batchSize;
52020cf1dd8SToby Isaac   if (numBatches) *numBatches = fem->numBatches;
52120cf1dd8SToby Isaac   PetscFunctionReturn(0);
52220cf1dd8SToby Isaac }
52320cf1dd8SToby Isaac 
52420cf1dd8SToby Isaac /*@
52520cf1dd8SToby Isaac   PetscFEGetBasisSpace - Returns the PetscSpace used for approximation of the solution
52620cf1dd8SToby Isaac 
52720cf1dd8SToby Isaac   Not collective
52820cf1dd8SToby Isaac 
52920cf1dd8SToby Isaac   Input Parameter:
53020cf1dd8SToby Isaac . fem - The PetscFE object
53120cf1dd8SToby Isaac 
53220cf1dd8SToby Isaac   Output Parameter:
53320cf1dd8SToby Isaac . sp - The PetscSpace object
53420cf1dd8SToby Isaac 
53520cf1dd8SToby Isaac   Level: intermediate
53620cf1dd8SToby Isaac 
53720cf1dd8SToby Isaac .seealso: PetscFECreate()
53820cf1dd8SToby Isaac @*/
53920cf1dd8SToby Isaac PetscErrorCode PetscFEGetBasisSpace(PetscFE fem, PetscSpace *sp)
54020cf1dd8SToby Isaac {
54120cf1dd8SToby Isaac   PetscFunctionBegin;
54220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
54320cf1dd8SToby Isaac   PetscValidPointer(sp, 2);
54420cf1dd8SToby Isaac   *sp = fem->basisSpace;
54520cf1dd8SToby Isaac   PetscFunctionReturn(0);
54620cf1dd8SToby Isaac }
54720cf1dd8SToby Isaac 
54820cf1dd8SToby Isaac /*@
54920cf1dd8SToby Isaac   PetscFESetBasisSpace - Sets the PetscSpace used for approximation of the solution
55020cf1dd8SToby Isaac 
55120cf1dd8SToby Isaac   Not collective
55220cf1dd8SToby Isaac 
55320cf1dd8SToby Isaac   Input Parameters:
55420cf1dd8SToby Isaac + fem - The PetscFE object
55520cf1dd8SToby Isaac - sp - The PetscSpace object
55620cf1dd8SToby Isaac 
55720cf1dd8SToby Isaac   Level: intermediate
55820cf1dd8SToby Isaac 
55920cf1dd8SToby Isaac .seealso: PetscFECreate()
56020cf1dd8SToby Isaac @*/
56120cf1dd8SToby Isaac PetscErrorCode PetscFESetBasisSpace(PetscFE fem, PetscSpace sp)
56220cf1dd8SToby Isaac {
56320cf1dd8SToby Isaac   PetscErrorCode ierr;
56420cf1dd8SToby Isaac 
56520cf1dd8SToby Isaac   PetscFunctionBegin;
56620cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
56720cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 2);
56820cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&fem->basisSpace);CHKERRQ(ierr);
56920cf1dd8SToby Isaac   fem->basisSpace = sp;
57020cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) fem->basisSpace);CHKERRQ(ierr);
57120cf1dd8SToby Isaac   PetscFunctionReturn(0);
57220cf1dd8SToby Isaac }
57320cf1dd8SToby Isaac 
57420cf1dd8SToby Isaac /*@
57520cf1dd8SToby Isaac   PetscFEGetDualSpace - Returns the PetscDualSpace used to define the inner product
57620cf1dd8SToby Isaac 
57720cf1dd8SToby Isaac   Not collective
57820cf1dd8SToby Isaac 
57920cf1dd8SToby Isaac   Input Parameter:
58020cf1dd8SToby Isaac . fem - The PetscFE object
58120cf1dd8SToby Isaac 
58220cf1dd8SToby Isaac   Output Parameter:
58320cf1dd8SToby Isaac . sp - The PetscDualSpace object
58420cf1dd8SToby Isaac 
58520cf1dd8SToby Isaac   Level: intermediate
58620cf1dd8SToby Isaac 
58720cf1dd8SToby Isaac .seealso: PetscFECreate()
58820cf1dd8SToby Isaac @*/
58920cf1dd8SToby Isaac PetscErrorCode PetscFEGetDualSpace(PetscFE fem, PetscDualSpace *sp)
59020cf1dd8SToby Isaac {
59120cf1dd8SToby Isaac   PetscFunctionBegin;
59220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
59320cf1dd8SToby Isaac   PetscValidPointer(sp, 2);
59420cf1dd8SToby Isaac   *sp = fem->dualSpace;
59520cf1dd8SToby Isaac   PetscFunctionReturn(0);
59620cf1dd8SToby Isaac }
59720cf1dd8SToby Isaac 
59820cf1dd8SToby Isaac /*@
59920cf1dd8SToby Isaac   PetscFESetDualSpace - Sets the PetscDualSpace used to define the inner product
60020cf1dd8SToby Isaac 
60120cf1dd8SToby Isaac   Not collective
60220cf1dd8SToby Isaac 
60320cf1dd8SToby Isaac   Input Parameters:
60420cf1dd8SToby Isaac + fem - The PetscFE object
60520cf1dd8SToby Isaac - sp - The PetscDualSpace object
60620cf1dd8SToby Isaac 
60720cf1dd8SToby Isaac   Level: intermediate
60820cf1dd8SToby Isaac 
60920cf1dd8SToby Isaac .seealso: PetscFECreate()
61020cf1dd8SToby Isaac @*/
61120cf1dd8SToby Isaac PetscErrorCode PetscFESetDualSpace(PetscFE fem, PetscDualSpace sp)
61220cf1dd8SToby Isaac {
61320cf1dd8SToby Isaac   PetscErrorCode ierr;
61420cf1dd8SToby Isaac 
61520cf1dd8SToby Isaac   PetscFunctionBegin;
61620cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
61720cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 2);
61820cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&fem->dualSpace);CHKERRQ(ierr);
61920cf1dd8SToby Isaac   fem->dualSpace = sp;
62020cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) fem->dualSpace);CHKERRQ(ierr);
62120cf1dd8SToby Isaac   PetscFunctionReturn(0);
62220cf1dd8SToby Isaac }
62320cf1dd8SToby Isaac 
62420cf1dd8SToby Isaac /*@
62520cf1dd8SToby Isaac   PetscFEGetQuadrature - Returns the PetscQuadrature used to calculate inner products
62620cf1dd8SToby Isaac 
62720cf1dd8SToby Isaac   Not collective
62820cf1dd8SToby Isaac 
62920cf1dd8SToby Isaac   Input Parameter:
63020cf1dd8SToby Isaac . fem - The PetscFE object
63120cf1dd8SToby Isaac 
63220cf1dd8SToby Isaac   Output Parameter:
63320cf1dd8SToby Isaac . q - The PetscQuadrature object
63420cf1dd8SToby Isaac 
63520cf1dd8SToby Isaac   Level: intermediate
63620cf1dd8SToby Isaac 
63720cf1dd8SToby Isaac .seealso: PetscFECreate()
63820cf1dd8SToby Isaac @*/
63920cf1dd8SToby Isaac PetscErrorCode PetscFEGetQuadrature(PetscFE fem, PetscQuadrature *q)
64020cf1dd8SToby Isaac {
64120cf1dd8SToby Isaac   PetscFunctionBegin;
64220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
64320cf1dd8SToby Isaac   PetscValidPointer(q, 2);
64420cf1dd8SToby Isaac   *q = fem->quadrature;
64520cf1dd8SToby Isaac   PetscFunctionReturn(0);
64620cf1dd8SToby Isaac }
64720cf1dd8SToby Isaac 
64820cf1dd8SToby Isaac /*@
64920cf1dd8SToby Isaac   PetscFESetQuadrature - Sets the PetscQuadrature used to calculate inner products
65020cf1dd8SToby Isaac 
65120cf1dd8SToby Isaac   Not collective
65220cf1dd8SToby Isaac 
65320cf1dd8SToby Isaac   Input Parameters:
65420cf1dd8SToby Isaac + fem - The PetscFE object
65520cf1dd8SToby Isaac - q - The PetscQuadrature object
65620cf1dd8SToby Isaac 
65720cf1dd8SToby Isaac   Level: intermediate
65820cf1dd8SToby Isaac 
65920cf1dd8SToby Isaac .seealso: PetscFECreate()
66020cf1dd8SToby Isaac @*/
66120cf1dd8SToby Isaac PetscErrorCode PetscFESetQuadrature(PetscFE fem, PetscQuadrature q)
66220cf1dd8SToby Isaac {
66320cf1dd8SToby Isaac   PetscInt       Nc, qNc;
66420cf1dd8SToby Isaac   PetscErrorCode ierr;
66520cf1dd8SToby Isaac 
66620cf1dd8SToby Isaac   PetscFunctionBegin;
66720cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
668fd2fdbddSMatthew G. Knepley   if (q == fem->quadrature) PetscFunctionReturn(0);
66920cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
67020cf1dd8SToby Isaac   ierr = PetscQuadratureGetNumComponents(q, &qNc);CHKERRQ(ierr);
67120cf1dd8SToby Isaac   if ((qNc != 1) && (Nc != qNc)) SETERRQ2(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_SIZ, "FE components %D != Quadrature components %D and non-scalar quadrature", Nc, qNc);
672ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&fem->T);CHKERRQ(ierr);
673ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&fem->Tc);CHKERRQ(ierr);
674fd2fdbddSMatthew G. Knepley   ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr);
67520cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&fem->quadrature);CHKERRQ(ierr);
67620cf1dd8SToby Isaac   fem->quadrature = q;
67720cf1dd8SToby Isaac   PetscFunctionReturn(0);
67820cf1dd8SToby Isaac }
67920cf1dd8SToby Isaac 
68020cf1dd8SToby Isaac /*@
68120cf1dd8SToby Isaac   PetscFEGetFaceQuadrature - Returns the PetscQuadrature used to calculate inner products on faces
68220cf1dd8SToby Isaac 
68320cf1dd8SToby Isaac   Not collective
68420cf1dd8SToby Isaac 
68520cf1dd8SToby Isaac   Input Parameter:
68620cf1dd8SToby Isaac . fem - The PetscFE object
68720cf1dd8SToby Isaac 
68820cf1dd8SToby Isaac   Output Parameter:
68920cf1dd8SToby Isaac . q - The PetscQuadrature object
69020cf1dd8SToby Isaac 
69120cf1dd8SToby Isaac   Level: intermediate
69220cf1dd8SToby Isaac 
69320cf1dd8SToby Isaac .seealso: PetscFECreate()
69420cf1dd8SToby Isaac @*/
69520cf1dd8SToby Isaac PetscErrorCode PetscFEGetFaceQuadrature(PetscFE fem, PetscQuadrature *q)
69620cf1dd8SToby Isaac {
69720cf1dd8SToby Isaac   PetscFunctionBegin;
69820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
69920cf1dd8SToby Isaac   PetscValidPointer(q, 2);
70020cf1dd8SToby Isaac   *q = fem->faceQuadrature;
70120cf1dd8SToby Isaac   PetscFunctionReturn(0);
70220cf1dd8SToby Isaac }
70320cf1dd8SToby Isaac 
70420cf1dd8SToby Isaac /*@
70520cf1dd8SToby Isaac   PetscFESetFaceQuadrature - Sets the PetscQuadrature used to calculate inner products on faces
70620cf1dd8SToby Isaac 
70720cf1dd8SToby Isaac   Not collective
70820cf1dd8SToby Isaac 
70920cf1dd8SToby Isaac   Input Parameters:
71020cf1dd8SToby Isaac + fem - The PetscFE object
71120cf1dd8SToby Isaac - q - The PetscQuadrature object
71220cf1dd8SToby Isaac 
71320cf1dd8SToby Isaac   Level: intermediate
71420cf1dd8SToby Isaac 
71520cf1dd8SToby Isaac .seealso: PetscFECreate()
71620cf1dd8SToby Isaac @*/
71720cf1dd8SToby Isaac PetscErrorCode PetscFESetFaceQuadrature(PetscFE fem, PetscQuadrature q)
71820cf1dd8SToby Isaac {
719ef0bb6c7SMatthew G. Knepley   PetscInt       Nc, qNc;
72020cf1dd8SToby Isaac   PetscErrorCode ierr;
72120cf1dd8SToby Isaac 
72220cf1dd8SToby Isaac   PetscFunctionBegin;
72320cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
724ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
725ef0bb6c7SMatthew G. Knepley   ierr = PetscQuadratureGetNumComponents(q, &qNc);CHKERRQ(ierr);
726ef0bb6c7SMatthew G. Knepley   if ((qNc != 1) && (Nc != qNc)) SETERRQ2(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_SIZ, "FE components %D != Quadrature components %D and non-scalar quadrature", Nc, qNc);
727ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&fem->Tf);CHKERRQ(ierr);
72820cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&fem->faceQuadrature);CHKERRQ(ierr);
72920cf1dd8SToby Isaac   fem->faceQuadrature = q;
73020cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr);
73120cf1dd8SToby Isaac   PetscFunctionReturn(0);
73220cf1dd8SToby Isaac }
73320cf1dd8SToby Isaac 
7345dc5c000SMatthew G. Knepley /*@
7355dc5c000SMatthew G. Knepley   PetscFECopyQuadrature - Copy both volumetric and surface quadrature
7365dc5c000SMatthew G. Knepley 
7375dc5c000SMatthew G. Knepley   Not collective
7385dc5c000SMatthew G. Knepley 
7395dc5c000SMatthew G. Knepley   Input Parameters:
7405dc5c000SMatthew G. Knepley + sfe - The PetscFE source for the quadratures
7415dc5c000SMatthew G. Knepley - tfe - The PetscFE target for the quadratures
7425dc5c000SMatthew G. Knepley 
7435dc5c000SMatthew G. Knepley   Level: intermediate
7445dc5c000SMatthew G. Knepley 
7455dc5c000SMatthew G. Knepley .seealso: PetscFECreate(), PetscFESetQuadrature(), PetscFESetFaceQuadrature()
7465dc5c000SMatthew G. Knepley @*/
7475dc5c000SMatthew G. Knepley PetscErrorCode PetscFECopyQuadrature(PetscFE sfe, PetscFE tfe)
7485dc5c000SMatthew G. Knepley {
7495dc5c000SMatthew G. Knepley   PetscQuadrature q;
7505dc5c000SMatthew G. Knepley   PetscErrorCode  ierr;
7515dc5c000SMatthew G. Knepley 
7525dc5c000SMatthew G. Knepley   PetscFunctionBegin;
7535dc5c000SMatthew G. Knepley   PetscValidHeaderSpecific(sfe, PETSCFE_CLASSID, 1);
7545dc5c000SMatthew G. Knepley   PetscValidHeaderSpecific(tfe, PETSCFE_CLASSID, 2);
7555dc5c000SMatthew G. Knepley   ierr = PetscFEGetQuadrature(sfe, &q);CHKERRQ(ierr);
7565dc5c000SMatthew G. Knepley   ierr = PetscFESetQuadrature(tfe,  q);CHKERRQ(ierr);
7575dc5c000SMatthew G. Knepley   ierr = PetscFEGetFaceQuadrature(sfe, &q);CHKERRQ(ierr);
7585dc5c000SMatthew G. Knepley   ierr = PetscFESetFaceQuadrature(tfe,  q);CHKERRQ(ierr);
7595dc5c000SMatthew G. Knepley   PetscFunctionReturn(0);
7605dc5c000SMatthew G. Knepley }
7615dc5c000SMatthew G. Knepley 
76220cf1dd8SToby Isaac /*@C
76320cf1dd8SToby Isaac   PetscFEGetNumDof - Returns the number of dofs (dual basis vectors) associated to mesh points on the reference cell of a given dimension
76420cf1dd8SToby Isaac 
76520cf1dd8SToby Isaac   Not collective
76620cf1dd8SToby Isaac 
76720cf1dd8SToby Isaac   Input Parameter:
76820cf1dd8SToby Isaac . fem - The PetscFE object
76920cf1dd8SToby Isaac 
77020cf1dd8SToby Isaac   Output Parameter:
77120cf1dd8SToby Isaac . numDof - Array with the number of dofs per dimension
77220cf1dd8SToby Isaac 
77320cf1dd8SToby Isaac   Level: intermediate
77420cf1dd8SToby Isaac 
77520cf1dd8SToby Isaac .seealso: PetscFECreate()
77620cf1dd8SToby Isaac @*/
77720cf1dd8SToby Isaac PetscErrorCode PetscFEGetNumDof(PetscFE fem, const PetscInt **numDof)
77820cf1dd8SToby Isaac {
77920cf1dd8SToby Isaac   PetscErrorCode ierr;
78020cf1dd8SToby Isaac 
78120cf1dd8SToby Isaac   PetscFunctionBegin;
78220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
78320cf1dd8SToby Isaac   PetscValidPointer(numDof, 2);
78420cf1dd8SToby Isaac   ierr = PetscDualSpaceGetNumDof(fem->dualSpace, numDof);CHKERRQ(ierr);
78520cf1dd8SToby Isaac   PetscFunctionReturn(0);
78620cf1dd8SToby Isaac }
78720cf1dd8SToby Isaac 
78820cf1dd8SToby Isaac /*@C
789ef0bb6c7SMatthew G. Knepley   PetscFEGetCellTabulation - Returns the tabulation of the basis functions at the quadrature points on the reference cell
79020cf1dd8SToby Isaac 
79120cf1dd8SToby Isaac   Not collective
79220cf1dd8SToby Isaac 
793d8d19677SJose E. Roman   Input Parameters:
794f9244615SMatthew G. Knepley + fem - The PetscFE object
795f9244615SMatthew G. Knepley - k   - The highest derivative we need to tabulate, very often 1
79620cf1dd8SToby Isaac 
797ef0bb6c7SMatthew G. Knepley   Output Parameter:
798ef0bb6c7SMatthew G. Knepley . T - The basis function values and derivatives at quadrature points
79920cf1dd8SToby Isaac 
80020cf1dd8SToby Isaac   Note:
801ef0bb6c7SMatthew G. Knepley $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
802ef0bb6c7SMatthew G. Knepley $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d
803ef0bb6c7SMatthew G. Knepley $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e
80420cf1dd8SToby Isaac 
80520cf1dd8SToby Isaac   Level: intermediate
80620cf1dd8SToby Isaac 
807ef0bb6c7SMatthew G. Knepley .seealso: PetscFECreateTabulation(), PetscTabulationDestroy()
80820cf1dd8SToby Isaac @*/
809f9244615SMatthew G. Knepley PetscErrorCode PetscFEGetCellTabulation(PetscFE fem, PetscInt k, PetscTabulation *T)
81020cf1dd8SToby Isaac {
81120cf1dd8SToby Isaac   PetscInt         npoints;
81220cf1dd8SToby Isaac   const PetscReal *points;
81320cf1dd8SToby Isaac   PetscErrorCode   ierr;
81420cf1dd8SToby Isaac 
81520cf1dd8SToby Isaac   PetscFunctionBegin;
81620cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
817064a246eSJacob Faibussowitsch   PetscValidPointer(T, 3);
81820cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(fem->quadrature, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr);
819f9244615SMatthew G. Knepley   if (!fem->T) {ierr = PetscFECreateTabulation(fem, 1, npoints, points, k, &fem->T);CHKERRQ(ierr);}
820f9244615SMatthew G. Knepley   if (fem->T && k > fem->T->K) SETERRQ2(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_OUTOFRANGE, "Requested %D derivatives, but only tabulated %D", k, fem->T->K);
821ef0bb6c7SMatthew G. Knepley   *T = fem->T;
82220cf1dd8SToby Isaac   PetscFunctionReturn(0);
82320cf1dd8SToby Isaac }
82420cf1dd8SToby Isaac 
8252b99622eSMatthew G. Knepley /*@C
826ef0bb6c7SMatthew G. Knepley   PetscFEGetFaceTabulation - Returns the tabulation of the basis functions at the face quadrature points for each face of the reference cell
8272b99622eSMatthew G. Knepley 
8282b99622eSMatthew G. Knepley   Not collective
8292b99622eSMatthew G. Knepley 
830d8d19677SJose E. Roman   Input Parameters:
831f9244615SMatthew G. Knepley + fem - The PetscFE object
832f9244615SMatthew G. Knepley - k   - The highest derivative we need to tabulate, very often 1
8332b99622eSMatthew G. Knepley 
8342b99622eSMatthew G. Knepley   Output Parameters:
835a5b23f4aSJose E. Roman . Tf - The basis function values and derivatives at face quadrature points
8362b99622eSMatthew G. Knepley 
8372b99622eSMatthew G. Knepley   Note:
838ef0bb6c7SMatthew G. Knepley $ T->T[0] = Bf[((f*Nq + q)*pdim + i)*Nc + c] is the value at point f,q for basis function i and component c
839ef0bb6c7SMatthew G. Knepley $ T->T[1] = Df[(((f*Nq + q)*pdim + i)*Nc + c)*dim + d] is the derivative value at point f,q for basis function i, component c, in direction d
840ef0bb6c7SMatthew G. Knepley $ T->T[2] = Hf[((((f*Nq + q)*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point f,q for basis function i, component c, in directions d and e
8412b99622eSMatthew G. Knepley 
8422b99622eSMatthew G. Knepley   Level: intermediate
8432b99622eSMatthew G. Knepley 
844ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetCellTabulation(), PetscFECreateTabulation(), PetscTabulationDestroy()
8452b99622eSMatthew G. Knepley @*/
846f9244615SMatthew G. Knepley PetscErrorCode PetscFEGetFaceTabulation(PetscFE fem, PetscInt k, PetscTabulation *Tf)
84720cf1dd8SToby Isaac {
84820cf1dd8SToby Isaac   PetscErrorCode   ierr;
84920cf1dd8SToby Isaac 
85020cf1dd8SToby Isaac   PetscFunctionBegin;
85120cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
852064a246eSJacob Faibussowitsch   PetscValidPointer(Tf, 3);
853ef0bb6c7SMatthew G. Knepley   if (!fem->Tf) {
85420cf1dd8SToby Isaac     const PetscReal  xi0[3] = {-1., -1., -1.};
85520cf1dd8SToby Isaac     PetscReal        v0[3], J[9], detJ;
85620cf1dd8SToby Isaac     PetscQuadrature  fq;
85720cf1dd8SToby Isaac     PetscDualSpace   sp;
85820cf1dd8SToby Isaac     DM               dm;
85920cf1dd8SToby Isaac     const PetscInt  *faces;
86020cf1dd8SToby Isaac     PetscInt         dim, numFaces, f, npoints, q;
86120cf1dd8SToby Isaac     const PetscReal *points;
86220cf1dd8SToby Isaac     PetscReal       *facePoints;
86320cf1dd8SToby Isaac 
86420cf1dd8SToby Isaac     ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr);
86520cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr);
86620cf1dd8SToby Isaac     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
86720cf1dd8SToby Isaac     ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr);
86820cf1dd8SToby Isaac     ierr = DMPlexGetCone(dm, 0, &faces);CHKERRQ(ierr);
86920cf1dd8SToby Isaac     ierr = PetscFEGetFaceQuadrature(fem, &fq);CHKERRQ(ierr);
87020cf1dd8SToby Isaac     if (fq) {
87120cf1dd8SToby Isaac       ierr = PetscQuadratureGetData(fq, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr);
87220cf1dd8SToby Isaac       ierr = PetscMalloc1(numFaces*npoints*dim, &facePoints);CHKERRQ(ierr);
87320cf1dd8SToby Isaac       for (f = 0; f < numFaces; ++f) {
87420cf1dd8SToby Isaac         ierr = DMPlexComputeCellGeometryFEM(dm, faces[f], NULL, v0, J, NULL, &detJ);CHKERRQ(ierr);
87520cf1dd8SToby Isaac         for (q = 0; q < npoints; ++q) CoordinatesRefToReal(dim, dim-1, xi0, v0, J, &points[q*(dim-1)], &facePoints[(f*npoints+q)*dim]);
87620cf1dd8SToby Isaac       }
877f9244615SMatthew G. Knepley       ierr = PetscFECreateTabulation(fem, numFaces, npoints, facePoints, k, &fem->Tf);CHKERRQ(ierr);
87820cf1dd8SToby Isaac       ierr = PetscFree(facePoints);CHKERRQ(ierr);
87920cf1dd8SToby Isaac     }
88020cf1dd8SToby Isaac   }
881f9244615SMatthew G. Knepley   if (fem->Tf && k > fem->Tf->K) SETERRQ2(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_OUTOFRANGE, "Requested %D derivatives, but only tabulated %D", k, fem->Tf->K);
882ef0bb6c7SMatthew G. Knepley   *Tf = fem->Tf;
88320cf1dd8SToby Isaac   PetscFunctionReturn(0);
88420cf1dd8SToby Isaac }
88520cf1dd8SToby Isaac 
8862b99622eSMatthew G. Knepley /*@C
887ef0bb6c7SMatthew G. Knepley   PetscFEGetFaceCentroidTabulation - Returns the tabulation of the basis functions at the face centroid points
8882b99622eSMatthew G. Knepley 
8892b99622eSMatthew G. Knepley   Not collective
8902b99622eSMatthew G. Knepley 
8912b99622eSMatthew G. Knepley   Input Parameter:
8922b99622eSMatthew G. Knepley . fem - The PetscFE object
8932b99622eSMatthew G. Knepley 
8942b99622eSMatthew G. Knepley   Output Parameters:
895ef0bb6c7SMatthew G. Knepley . Tc - The basis function values at face centroid points
8962b99622eSMatthew G. Knepley 
8972b99622eSMatthew G. Knepley   Note:
898ef0bb6c7SMatthew G. Knepley $ T->T[0] = Bf[(f*pdim + i)*Nc + c] is the value at point f for basis function i and component c
8992b99622eSMatthew G. Knepley 
9002b99622eSMatthew G. Knepley   Level: intermediate
9012b99622eSMatthew G. Knepley 
902ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetFaceTabulation(), PetscFEGetCellTabulation(), PetscFECreateTabulation(), PetscTabulationDestroy()
9032b99622eSMatthew G. Knepley @*/
904ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEGetFaceCentroidTabulation(PetscFE fem, PetscTabulation *Tc)
90520cf1dd8SToby Isaac {
90620cf1dd8SToby Isaac   PetscErrorCode   ierr;
90720cf1dd8SToby Isaac 
90820cf1dd8SToby Isaac   PetscFunctionBegin;
90920cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
910ef0bb6c7SMatthew G. Knepley   PetscValidPointer(Tc, 2);
911ef0bb6c7SMatthew G. Knepley   if (!fem->Tc) {
91220cf1dd8SToby Isaac     PetscDualSpace  sp;
91320cf1dd8SToby Isaac     DM              dm;
91420cf1dd8SToby Isaac     const PetscInt *cone;
91520cf1dd8SToby Isaac     PetscReal      *centroids;
91620cf1dd8SToby Isaac     PetscInt        dim, numFaces, f;
91720cf1dd8SToby Isaac 
91820cf1dd8SToby Isaac     ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr);
91920cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr);
92020cf1dd8SToby Isaac     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
92120cf1dd8SToby Isaac     ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr);
92220cf1dd8SToby Isaac     ierr = DMPlexGetCone(dm, 0, &cone);CHKERRQ(ierr);
92320cf1dd8SToby Isaac     ierr = PetscMalloc1(numFaces*dim, &centroids);CHKERRQ(ierr);
92420cf1dd8SToby Isaac     for (f = 0; f < numFaces; ++f) {ierr = DMPlexComputeCellGeometryFVM(dm, cone[f], NULL, &centroids[f*dim], NULL);CHKERRQ(ierr);}
925ef0bb6c7SMatthew G. Knepley     ierr = PetscFECreateTabulation(fem, 1, numFaces, centroids, 0, &fem->Tc);CHKERRQ(ierr);
92620cf1dd8SToby Isaac     ierr = PetscFree(centroids);CHKERRQ(ierr);
92720cf1dd8SToby Isaac   }
928ef0bb6c7SMatthew G. Knepley   *Tc = fem->Tc;
92920cf1dd8SToby Isaac   PetscFunctionReturn(0);
93020cf1dd8SToby Isaac }
93120cf1dd8SToby Isaac 
93220cf1dd8SToby Isaac /*@C
933ef0bb6c7SMatthew G. Knepley   PetscFECreateTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
93420cf1dd8SToby Isaac 
93520cf1dd8SToby Isaac   Not collective
93620cf1dd8SToby Isaac 
93720cf1dd8SToby Isaac   Input Parameters:
93820cf1dd8SToby Isaac + fem     - The PetscFE object
939ef0bb6c7SMatthew G. Knepley . nrepl   - The number of replicas
940ef0bb6c7SMatthew G. Knepley . npoints - The number of tabulation points in a replica
941ef0bb6c7SMatthew G. Knepley . points  - The tabulation point coordinates
942ef0bb6c7SMatthew G. Knepley - K       - The number of derivatives calculated
94320cf1dd8SToby Isaac 
944ef0bb6c7SMatthew G. Knepley   Output Parameter:
945ef0bb6c7SMatthew G. Knepley . T - The basis function values and derivatives at tabulation points
94620cf1dd8SToby Isaac 
94720cf1dd8SToby Isaac   Note:
948ef0bb6c7SMatthew G. Knepley $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
949ef0bb6c7SMatthew G. Knepley $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d
950ef0bb6c7SMatthew G. Knepley $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e
95120cf1dd8SToby Isaac 
95220cf1dd8SToby Isaac   Level: intermediate
95320cf1dd8SToby Isaac 
954ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetCellTabulation(), PetscTabulationDestroy()
95520cf1dd8SToby Isaac @*/
956ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFECreateTabulation(PetscFE fem, PetscInt nrepl, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation *T)
95720cf1dd8SToby Isaac {
95820cf1dd8SToby Isaac   DM               dm;
959ef0bb6c7SMatthew G. Knepley   PetscDualSpace   Q;
960ef0bb6c7SMatthew G. Knepley   PetscInt         Nb;   /* Dimension of FE space P */
961ef0bb6c7SMatthew G. Knepley   PetscInt         Nc;   /* Field components */
962ef0bb6c7SMatthew G. Knepley   PetscInt         cdim; /* Reference coordinate dimension */
963ef0bb6c7SMatthew G. Knepley   PetscInt         k;
96420cf1dd8SToby Isaac   PetscErrorCode   ierr;
96520cf1dd8SToby Isaac 
96620cf1dd8SToby Isaac   PetscFunctionBegin;
967ef0bb6c7SMatthew G. Knepley   if (!npoints || !fem->dualSpace || K < 0) {
968ef0bb6c7SMatthew G. Knepley     *T = NULL;
96920cf1dd8SToby Isaac     PetscFunctionReturn(0);
97020cf1dd8SToby Isaac   }
97120cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
97240a2aa30SMatthew G. Knepley   PetscValidPointer(points, 4);
97340a2aa30SMatthew G. Knepley   PetscValidPointer(T, 6);
974ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetDualSpace(fem, &Q);CHKERRQ(ierr);
975ef0bb6c7SMatthew G. Knepley   ierr = PetscDualSpaceGetDM(Q, &dm);CHKERRQ(ierr);
976ef0bb6c7SMatthew G. Knepley   ierr = DMGetDimension(dm, &cdim);CHKERRQ(ierr);
977ef0bb6c7SMatthew G. Knepley   ierr = PetscDualSpaceGetDimension(Q, &Nb);CHKERRQ(ierr);
978ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
979ef0bb6c7SMatthew G. Knepley   ierr = PetscMalloc1(1, T);CHKERRQ(ierr);
980ef0bb6c7SMatthew G. Knepley   (*T)->K    = !cdim ? 0 : K;
981ef0bb6c7SMatthew G. Knepley   (*T)->Nr   = nrepl;
982ef0bb6c7SMatthew G. Knepley   (*T)->Np   = npoints;
983ef0bb6c7SMatthew G. Knepley   (*T)->Nb   = Nb;
984ef0bb6c7SMatthew G. Knepley   (*T)->Nc   = Nc;
985ef0bb6c7SMatthew G. Knepley   (*T)->cdim = cdim;
986ef0bb6c7SMatthew G. Knepley   ierr = PetscMalloc1((*T)->K+1, &(*T)->T);CHKERRQ(ierr);
987ef0bb6c7SMatthew G. Knepley   for (k = 0; k <= (*T)->K; ++k) {
988ef0bb6c7SMatthew G. Knepley     ierr = PetscMalloc1(nrepl*npoints*Nb*Nc*PetscPowInt(cdim, k), &(*T)->T[k]);CHKERRQ(ierr);
98920cf1dd8SToby Isaac   }
990ef0bb6c7SMatthew G. Knepley   ierr = (*fem->ops->createtabulation)(fem, nrepl*npoints, points, K, *T);CHKERRQ(ierr);
99120cf1dd8SToby Isaac   PetscFunctionReturn(0);
99220cf1dd8SToby Isaac }
99320cf1dd8SToby Isaac 
9942b99622eSMatthew G. Knepley /*@C
995ef0bb6c7SMatthew G. Knepley   PetscFEComputeTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
9962b99622eSMatthew G. Knepley 
9972b99622eSMatthew G. Knepley   Not collective
9982b99622eSMatthew G. Knepley 
9992b99622eSMatthew G. Knepley   Input Parameters:
10002b99622eSMatthew G. Knepley + fem     - The PetscFE object
10012b99622eSMatthew G. Knepley . npoints - The number of tabulation points
10022b99622eSMatthew G. Knepley . points  - The tabulation point coordinates
1003ef0bb6c7SMatthew G. Knepley . K       - The number of derivatives calculated
1004ef0bb6c7SMatthew G. Knepley - T       - An existing tabulation object with enough allocated space
1005ef0bb6c7SMatthew G. Knepley 
1006ef0bb6c7SMatthew G. Knepley   Output Parameter:
1007ef0bb6c7SMatthew G. Knepley . T - The basis function values and derivatives at tabulation points
10082b99622eSMatthew G. Knepley 
10092b99622eSMatthew G. Knepley   Note:
1010ef0bb6c7SMatthew G. Knepley $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1011ef0bb6c7SMatthew G. Knepley $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d
1012ef0bb6c7SMatthew G. Knepley $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e
10132b99622eSMatthew G. Knepley 
10142b99622eSMatthew G. Knepley   Level: intermediate
10152b99622eSMatthew G. Knepley 
1016ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetCellTabulation(), PetscTabulationDestroy()
10172b99622eSMatthew G. Knepley @*/
1018ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEComputeTabulation(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation T)
1019ef0bb6c7SMatthew G. Knepley {
1020ef0bb6c7SMatthew G. Knepley   PetscErrorCode ierr;
1021ef0bb6c7SMatthew G. Knepley 
1022ef0bb6c7SMatthew G. Knepley   PetscFunctionBeginHot;
1023ef0bb6c7SMatthew G. Knepley   if (!npoints || !fem->dualSpace || K < 0) PetscFunctionReturn(0);
1024ef0bb6c7SMatthew G. Knepley   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
1025ef0bb6c7SMatthew G. Knepley   PetscValidPointer(points, 3);
1026ef0bb6c7SMatthew G. Knepley   PetscValidPointer(T, 5);
102776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
102820cf1dd8SToby Isaac     DM               dm;
1029ef0bb6c7SMatthew G. Knepley     PetscDualSpace   Q;
1030ef0bb6c7SMatthew G. Knepley     PetscInt         Nb;   /* Dimension of FE space P */
1031ef0bb6c7SMatthew G. Knepley     PetscInt         Nc;   /* Field components */
1032ef0bb6c7SMatthew G. Knepley     PetscInt         cdim; /* Reference coordinate dimension */
1033ef0bb6c7SMatthew G. Knepley 
1034ef0bb6c7SMatthew G. Knepley     ierr = PetscFEGetDualSpace(fem, &Q);CHKERRQ(ierr);
1035ef0bb6c7SMatthew G. Knepley     ierr = PetscDualSpaceGetDM(Q, &dm);CHKERRQ(ierr);
1036ef0bb6c7SMatthew G. Knepley     ierr = DMGetDimension(dm, &cdim);CHKERRQ(ierr);
1037ef0bb6c7SMatthew G. Knepley     ierr = PetscDualSpaceGetDimension(Q, &Nb);CHKERRQ(ierr);
1038ef0bb6c7SMatthew G. Knepley     ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
1039ef0bb6c7SMatthew G. Knepley     if (T->K    != (!cdim ? 0 : K)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation K %D must match requested K %D", T->K, !cdim ? 0 : K);
1040ef0bb6c7SMatthew G. Knepley     if (T->Nb   != Nb)              SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation Nb %D must match requested Nb %D", T->Nb, Nb);
1041ef0bb6c7SMatthew G. Knepley     if (T->Nc   != Nc)              SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation Nc %D must match requested Nc %D", T->Nc, Nc);
1042ef0bb6c7SMatthew G. Knepley     if (T->cdim != cdim)            SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation cdim %D must match requested cdim %D", T->cdim, cdim);
1043ef0bb6c7SMatthew G. Knepley   }
1044ef0bb6c7SMatthew G. Knepley   T->Nr = 1;
1045ef0bb6c7SMatthew G. Knepley   T->Np = npoints;
1046ef0bb6c7SMatthew G. Knepley   ierr = (*fem->ops->createtabulation)(fem, npoints, points, K, T);CHKERRQ(ierr);
1047ef0bb6c7SMatthew G. Knepley   PetscFunctionReturn(0);
1048ef0bb6c7SMatthew G. Knepley }
1049ef0bb6c7SMatthew G. Knepley 
1050ef0bb6c7SMatthew G. Knepley /*@C
1051ef0bb6c7SMatthew G. Knepley   PetscTabulationDestroy - Frees memory from the associated tabulation.
1052ef0bb6c7SMatthew G. Knepley 
1053ef0bb6c7SMatthew G. Knepley   Not collective
1054ef0bb6c7SMatthew G. Knepley 
1055ef0bb6c7SMatthew G. Knepley   Input Parameter:
1056ef0bb6c7SMatthew G. Knepley . T - The tabulation
1057ef0bb6c7SMatthew G. Knepley 
1058ef0bb6c7SMatthew G. Knepley   Level: intermediate
1059ef0bb6c7SMatthew G. Knepley 
1060ef0bb6c7SMatthew G. Knepley .seealso: PetscFECreateTabulation(), PetscFEGetCellTabulation()
1061ef0bb6c7SMatthew G. Knepley @*/
1062ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscTabulationDestroy(PetscTabulation *T)
1063ef0bb6c7SMatthew G. Knepley {
1064ef0bb6c7SMatthew G. Knepley   PetscInt       k;
106520cf1dd8SToby Isaac   PetscErrorCode ierr;
106620cf1dd8SToby Isaac 
106720cf1dd8SToby Isaac   PetscFunctionBegin;
1068ef0bb6c7SMatthew G. Knepley   PetscValidPointer(T, 1);
1069ef0bb6c7SMatthew G. Knepley   if (!T || !(*T)) PetscFunctionReturn(0);
1070ef0bb6c7SMatthew G. Knepley   for (k = 0; k <= (*T)->K; ++k) {ierr = PetscFree((*T)->T[k]);CHKERRQ(ierr);}
1071ef0bb6c7SMatthew G. Knepley   ierr = PetscFree((*T)->T);CHKERRQ(ierr);
1072ef0bb6c7SMatthew G. Knepley   ierr = PetscFree(*T);CHKERRQ(ierr);
1073ef0bb6c7SMatthew G. Knepley   *T = NULL;
107420cf1dd8SToby Isaac   PetscFunctionReturn(0);
107520cf1dd8SToby Isaac }
107620cf1dd8SToby Isaac 
107720cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode PetscFECreatePointTrace(PetscFE fe, PetscInt refPoint, PetscFE *trFE)
107820cf1dd8SToby Isaac {
107920cf1dd8SToby Isaac   PetscSpace     bsp, bsubsp;
108020cf1dd8SToby Isaac   PetscDualSpace dsp, dsubsp;
108120cf1dd8SToby Isaac   PetscInt       dim, depth, numComp, i, j, coneSize, order;
108220cf1dd8SToby Isaac   PetscFEType    type;
108320cf1dd8SToby Isaac   DM             dm;
108420cf1dd8SToby Isaac   DMLabel        label;
108520cf1dd8SToby Isaac   PetscReal      *xi, *v, *J, detJ;
1086db11e2ebSMatthew G. Knepley   const char     *name;
108720cf1dd8SToby Isaac   PetscQuadrature origin, fullQuad, subQuad;
108820cf1dd8SToby Isaac   PetscErrorCode ierr;
108920cf1dd8SToby Isaac 
109020cf1dd8SToby Isaac   PetscFunctionBegin;
109120cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1);
109220cf1dd8SToby Isaac   PetscValidPointer(trFE,3);
109320cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe,&bsp);CHKERRQ(ierr);
109420cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr);
109520cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr);
109620cf1dd8SToby Isaac   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
109720cf1dd8SToby Isaac   ierr = DMPlexGetDepthLabel(dm,&label);CHKERRQ(ierr);
109820cf1dd8SToby Isaac   ierr = DMLabelGetValue(label,refPoint,&depth);CHKERRQ(ierr);
109920cf1dd8SToby Isaac   ierr = PetscCalloc1(depth,&xi);CHKERRQ(ierr);
110020cf1dd8SToby Isaac   ierr = PetscMalloc1(dim,&v);CHKERRQ(ierr);
110120cf1dd8SToby Isaac   ierr = PetscMalloc1(dim*dim,&J);CHKERRQ(ierr);
110220cf1dd8SToby Isaac   for (i = 0; i < depth; i++) xi[i] = 0.;
110320cf1dd8SToby Isaac   ierr = PetscQuadratureCreate(PETSC_COMM_SELF,&origin);CHKERRQ(ierr);
110420cf1dd8SToby Isaac   ierr = PetscQuadratureSetData(origin,depth,0,1,xi,NULL);CHKERRQ(ierr);
110520cf1dd8SToby Isaac   ierr = DMPlexComputeCellGeometryFEM(dm,refPoint,origin,v,J,NULL,&detJ);CHKERRQ(ierr);
110620cf1dd8SToby Isaac   /* CellGeometryFEM computes the expanded Jacobian, we want the true jacobian */
110720cf1dd8SToby Isaac   for (i = 1; i < dim; i++) {
110820cf1dd8SToby Isaac     for (j = 0; j < depth; j++) {
110920cf1dd8SToby Isaac       J[i * depth + j] = J[i * dim + j];
111020cf1dd8SToby Isaac     }
111120cf1dd8SToby Isaac   }
111220cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&origin);CHKERRQ(ierr);
111320cf1dd8SToby Isaac   ierr = PetscDualSpaceGetPointSubspace(dsp,refPoint,&dsubsp);CHKERRQ(ierr);
111420cf1dd8SToby Isaac   ierr = PetscSpaceCreateSubspace(bsp,dsubsp,v,J,NULL,NULL,PETSC_OWN_POINTER,&bsubsp);CHKERRQ(ierr);
111520cf1dd8SToby Isaac   ierr = PetscSpaceSetUp(bsubsp);CHKERRQ(ierr);
111620cf1dd8SToby Isaac   ierr = PetscFECreate(PetscObjectComm((PetscObject)fe),trFE);CHKERRQ(ierr);
111720cf1dd8SToby Isaac   ierr = PetscFEGetType(fe,&type);CHKERRQ(ierr);
111820cf1dd8SToby Isaac   ierr = PetscFESetType(*trFE,type);CHKERRQ(ierr);
111920cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe,&numComp);CHKERRQ(ierr);
112020cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*trFE,numComp);CHKERRQ(ierr);
112120cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*trFE,bsubsp);CHKERRQ(ierr);
112220cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*trFE,dsubsp);CHKERRQ(ierr);
1123db11e2ebSMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr);
1124db11e2ebSMatthew G. Knepley   if (name) {ierr = PetscFESetName(*trFE, name);CHKERRQ(ierr);}
112520cf1dd8SToby Isaac   ierr = PetscFEGetQuadrature(fe,&fullQuad);CHKERRQ(ierr);
112620cf1dd8SToby Isaac   ierr = PetscQuadratureGetOrder(fullQuad,&order);CHKERRQ(ierr);
112720cf1dd8SToby Isaac   ierr = DMPlexGetConeSize(dm,refPoint,&coneSize);CHKERRQ(ierr);
112820cf1dd8SToby Isaac   if (coneSize == 2 * depth) {
112920cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr);
113020cf1dd8SToby Isaac   } else {
1131e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr);
113220cf1dd8SToby Isaac   }
113320cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*trFE,subQuad);CHKERRQ(ierr);
113420cf1dd8SToby Isaac   ierr = PetscFESetUp(*trFE);CHKERRQ(ierr);
113520cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&subQuad);CHKERRQ(ierr);
113620cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&bsubsp);CHKERRQ(ierr);
113720cf1dd8SToby Isaac   PetscFunctionReturn(0);
113820cf1dd8SToby Isaac }
113920cf1dd8SToby Isaac 
114020cf1dd8SToby Isaac PetscErrorCode PetscFECreateHeightTrace(PetscFE fe, PetscInt height, PetscFE *trFE)
114120cf1dd8SToby Isaac {
114220cf1dd8SToby Isaac   PetscInt       hStart, hEnd;
114320cf1dd8SToby Isaac   PetscDualSpace dsp;
114420cf1dd8SToby Isaac   DM             dm;
114520cf1dd8SToby Isaac   PetscErrorCode ierr;
114620cf1dd8SToby Isaac 
114720cf1dd8SToby Isaac   PetscFunctionBegin;
114820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1);
114920cf1dd8SToby Isaac   PetscValidPointer(trFE,3);
115020cf1dd8SToby Isaac   *trFE = NULL;
115120cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr);
115220cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr);
115320cf1dd8SToby Isaac   ierr = DMPlexGetHeightStratum(dm,height,&hStart,&hEnd);CHKERRQ(ierr);
115420cf1dd8SToby Isaac   if (hEnd <= hStart) PetscFunctionReturn(0);
115520cf1dd8SToby Isaac   ierr = PetscFECreatePointTrace(fe,hStart,trFE);CHKERRQ(ierr);
115620cf1dd8SToby Isaac   PetscFunctionReturn(0);
115720cf1dd8SToby Isaac }
115820cf1dd8SToby Isaac 
115920cf1dd8SToby Isaac /*@
116020cf1dd8SToby Isaac   PetscFEGetDimension - Get the dimension of the finite element space on a cell
116120cf1dd8SToby Isaac 
116220cf1dd8SToby Isaac   Not collective
116320cf1dd8SToby Isaac 
116420cf1dd8SToby Isaac   Input Parameter:
116520cf1dd8SToby Isaac . fe - The PetscFE
116620cf1dd8SToby Isaac 
116720cf1dd8SToby Isaac   Output Parameter:
116820cf1dd8SToby Isaac . dim - The dimension
116920cf1dd8SToby Isaac 
117020cf1dd8SToby Isaac   Level: intermediate
117120cf1dd8SToby Isaac 
117220cf1dd8SToby Isaac .seealso: PetscFECreate(), PetscSpaceGetDimension(), PetscDualSpaceGetDimension()
117320cf1dd8SToby Isaac @*/
117420cf1dd8SToby Isaac PetscErrorCode PetscFEGetDimension(PetscFE fem, PetscInt *dim)
117520cf1dd8SToby Isaac {
117620cf1dd8SToby Isaac   PetscErrorCode ierr;
117720cf1dd8SToby Isaac 
117820cf1dd8SToby Isaac   PetscFunctionBegin;
117920cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
118020cf1dd8SToby Isaac   PetscValidPointer(dim, 2);
118120cf1dd8SToby Isaac   if (fem->ops->getdimension) {ierr = (*fem->ops->getdimension)(fem, dim);CHKERRQ(ierr);}
118220cf1dd8SToby Isaac   PetscFunctionReturn(0);
118320cf1dd8SToby Isaac }
118420cf1dd8SToby Isaac 
11854bee2e38SMatthew G. Knepley /*@C
11864bee2e38SMatthew G. Knepley   PetscFEPushforward - Map the reference element function to real space
11874bee2e38SMatthew G. Knepley 
11884bee2e38SMatthew G. Knepley   Input Parameters:
11894bee2e38SMatthew G. Knepley + fe     - The PetscFE
11904bee2e38SMatthew G. Knepley . fegeom - The cell geometry
11914bee2e38SMatthew G. Knepley . Nv     - The number of function values
11924bee2e38SMatthew G. Knepley - vals   - The function values
11934bee2e38SMatthew G. Knepley 
11944bee2e38SMatthew G. Knepley   Output Parameter:
11954bee2e38SMatthew G. Knepley . vals   - The transformed function values
11964bee2e38SMatthew G. Knepley 
11974bee2e38SMatthew G. Knepley   Level: advanced
11984bee2e38SMatthew G. Knepley 
11994bee2e38SMatthew G. Knepley   Note: This just forwards the call onto PetscDualSpacePushforward().
12004bee2e38SMatthew G. Knepley 
1201f9244615SMatthew G. Knepley   Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
12022edcad52SToby Isaac 
12034bee2e38SMatthew G. Knepley .seealso: PetscDualSpacePushforward()
12044bee2e38SMatthew G. Knepley @*/
12052edcad52SToby Isaac PetscErrorCode PetscFEPushforward(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
12064bee2e38SMatthew G. Knepley {
12074bee2e38SMatthew G. Knepley   PetscErrorCode ierr;
12084bee2e38SMatthew G. Knepley 
12092ae266adSMatthew G. Knepley   PetscFunctionBeginHot;
12102edcad52SToby Isaac   ierr = PetscDualSpacePushforward(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr);
12114bee2e38SMatthew G. Knepley   PetscFunctionReturn(0);
12124bee2e38SMatthew G. Knepley }
12134bee2e38SMatthew G. Knepley 
12144bee2e38SMatthew G. Knepley /*@C
12154bee2e38SMatthew G. Knepley   PetscFEPushforwardGradient - Map the reference element function gradient to real space
12164bee2e38SMatthew G. Knepley 
12174bee2e38SMatthew G. Knepley   Input Parameters:
12184bee2e38SMatthew G. Knepley + fe     - The PetscFE
12194bee2e38SMatthew G. Knepley . fegeom - The cell geometry
12204bee2e38SMatthew G. Knepley . Nv     - The number of function gradient values
12214bee2e38SMatthew G. Knepley - vals   - The function gradient values
12224bee2e38SMatthew G. Knepley 
12234bee2e38SMatthew G. Knepley   Output Parameter:
12244bee2e38SMatthew G. Knepley . vals   - The transformed function gradient values
12254bee2e38SMatthew G. Knepley 
12264bee2e38SMatthew G. Knepley   Level: advanced
12274bee2e38SMatthew G. Knepley 
12284bee2e38SMatthew G. Knepley   Note: This just forwards the call onto PetscDualSpacePushforwardGradient().
12294bee2e38SMatthew G. Knepley 
1230f9244615SMatthew G. Knepley   Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
12312edcad52SToby Isaac 
12324bee2e38SMatthew G. Knepley .seealso: PetscFEPushforward(), PetscDualSpacePushforwardGradient(), PetscDualSpacePushforward()
12334bee2e38SMatthew G. Knepley @*/
12342edcad52SToby Isaac PetscErrorCode PetscFEPushforwardGradient(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
12354bee2e38SMatthew G. Knepley {
12364bee2e38SMatthew G. Knepley   PetscErrorCode ierr;
12374bee2e38SMatthew G. Knepley 
12382ae266adSMatthew G. Knepley   PetscFunctionBeginHot;
12392edcad52SToby Isaac   ierr = PetscDualSpacePushforwardGradient(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr);
12404bee2e38SMatthew G. Knepley   PetscFunctionReturn(0);
12414bee2e38SMatthew G. Knepley }
12424bee2e38SMatthew G. Knepley 
1243f9244615SMatthew G. Knepley /*@C
1244f9244615SMatthew G. Knepley   PetscFEPushforwardHessian - Map the reference element function Hessian to real space
1245f9244615SMatthew G. Knepley 
1246f9244615SMatthew G. Knepley   Input Parameters:
1247f9244615SMatthew G. Knepley + fe     - The PetscFE
1248f9244615SMatthew G. Knepley . fegeom - The cell geometry
1249f9244615SMatthew G. Knepley . Nv     - The number of function Hessian values
1250f9244615SMatthew G. Knepley - vals   - The function Hessian values
1251f9244615SMatthew G. Knepley 
1252f9244615SMatthew G. Knepley   Output Parameter:
1253f9244615SMatthew G. Knepley . vals   - The transformed function Hessian values
1254f9244615SMatthew G. Knepley 
1255f9244615SMatthew G. Knepley   Level: advanced
1256f9244615SMatthew G. Knepley 
1257f9244615SMatthew G. Knepley   Note: This just forwards the call onto PetscDualSpacePushforwardHessian().
1258f9244615SMatthew G. Knepley 
1259f9244615SMatthew G. Knepley   Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
1260f9244615SMatthew G. Knepley 
1261f9244615SMatthew G. Knepley .seealso: PetscFEPushforward(), PetscDualSpacePushforwardHessian(), PetscDualSpacePushforward()
1262f9244615SMatthew G. Knepley @*/
1263f9244615SMatthew G. Knepley PetscErrorCode PetscFEPushforwardHessian(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
1264f9244615SMatthew G. Knepley {
1265f9244615SMatthew G. Knepley   PetscErrorCode ierr;
1266f9244615SMatthew G. Knepley 
1267f9244615SMatthew G. Knepley   PetscFunctionBeginHot;
1268f9244615SMatthew G. Knepley   ierr = PetscDualSpacePushforwardHessian(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr);
1269f9244615SMatthew G. Knepley   PetscFunctionReturn(0);
1270f9244615SMatthew G. Knepley }
1271f9244615SMatthew G. Knepley 
127220cf1dd8SToby Isaac /*
127320cf1dd8SToby Isaac Purpose: Compute element vector for chunk of elements
127420cf1dd8SToby Isaac 
127520cf1dd8SToby Isaac Input:
127620cf1dd8SToby Isaac   Sizes:
127720cf1dd8SToby Isaac      Ne:  number of elements
127820cf1dd8SToby Isaac      Nf:  number of fields
127920cf1dd8SToby Isaac      PetscFE
128020cf1dd8SToby Isaac        dim: spatial dimension
128120cf1dd8SToby Isaac        Nb:  number of basis functions
128220cf1dd8SToby Isaac        Nc:  number of field components
128320cf1dd8SToby Isaac        PetscQuadrature
128420cf1dd8SToby Isaac          Nq:  number of quadrature points
128520cf1dd8SToby Isaac 
128620cf1dd8SToby Isaac   Geometry:
128720cf1dd8SToby Isaac      PetscFEGeom[Ne] possibly *Nq
128820cf1dd8SToby Isaac        PetscReal v0s[dim]
128920cf1dd8SToby Isaac        PetscReal n[dim]
129020cf1dd8SToby Isaac        PetscReal jacobians[dim*dim]
129120cf1dd8SToby Isaac        PetscReal jacobianInverses[dim*dim]
129220cf1dd8SToby Isaac        PetscReal jacobianDeterminants
129320cf1dd8SToby Isaac   FEM:
129420cf1dd8SToby Isaac      PetscFE
129520cf1dd8SToby Isaac        PetscQuadrature
129620cf1dd8SToby Isaac          PetscReal   quadPoints[Nq*dim]
129720cf1dd8SToby Isaac          PetscReal   quadWeights[Nq]
129820cf1dd8SToby Isaac        PetscReal   basis[Nq*Nb*Nc]
129920cf1dd8SToby Isaac        PetscReal   basisDer[Nq*Nb*Nc*dim]
130020cf1dd8SToby Isaac      PetscScalar coefficients[Ne*Nb*Nc]
130120cf1dd8SToby Isaac      PetscScalar elemVec[Ne*Nb*Nc]
130220cf1dd8SToby Isaac 
130320cf1dd8SToby Isaac   Problem:
130420cf1dd8SToby Isaac      PetscInt f: the active field
130520cf1dd8SToby Isaac      f0, f1
130620cf1dd8SToby Isaac 
130720cf1dd8SToby Isaac   Work Space:
130820cf1dd8SToby Isaac      PetscFE
130920cf1dd8SToby Isaac        PetscScalar f0[Nq*dim];
131020cf1dd8SToby Isaac        PetscScalar f1[Nq*dim*dim];
131120cf1dd8SToby Isaac        PetscScalar u[Nc];
131220cf1dd8SToby Isaac        PetscScalar gradU[Nc*dim];
131320cf1dd8SToby Isaac        PetscReal   x[dim];
131420cf1dd8SToby Isaac        PetscScalar realSpaceDer[dim];
131520cf1dd8SToby Isaac 
131620cf1dd8SToby Isaac Purpose: Compute element vector for N_cb batches of elements
131720cf1dd8SToby Isaac 
131820cf1dd8SToby Isaac Input:
131920cf1dd8SToby Isaac   Sizes:
132020cf1dd8SToby Isaac      N_cb: Number of serial cell batches
132120cf1dd8SToby Isaac 
132220cf1dd8SToby Isaac   Geometry:
132320cf1dd8SToby Isaac      PetscReal v0s[Ne*dim]
132420cf1dd8SToby Isaac      PetscReal jacobians[Ne*dim*dim]        possibly *Nq
132520cf1dd8SToby Isaac      PetscReal jacobianInverses[Ne*dim*dim] possibly *Nq
132620cf1dd8SToby Isaac      PetscReal jacobianDeterminants[Ne]     possibly *Nq
132720cf1dd8SToby Isaac   FEM:
132820cf1dd8SToby Isaac      static PetscReal   quadPoints[Nq*dim]
132920cf1dd8SToby Isaac      static PetscReal   quadWeights[Nq]
133020cf1dd8SToby Isaac      static PetscReal   basis[Nq*Nb*Nc]
133120cf1dd8SToby Isaac      static PetscReal   basisDer[Nq*Nb*Nc*dim]
133220cf1dd8SToby Isaac      PetscScalar coefficients[Ne*Nb*Nc]
133320cf1dd8SToby Isaac      PetscScalar elemVec[Ne*Nb*Nc]
133420cf1dd8SToby Isaac 
133520cf1dd8SToby Isaac ex62.c:
133620cf1dd8SToby Isaac   PetscErrorCode PetscFEIntegrateResidualBatch(PetscInt Ne, PetscInt numFields, PetscInt field, PetscQuadrature quad[], const PetscScalar coefficients[],
133720cf1dd8SToby Isaac                                                const PetscReal v0s[], const PetscReal jacobians[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[],
133820cf1dd8SToby Isaac                                                void (*f0_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]),
133920cf1dd8SToby Isaac                                                void (*f1_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]), PetscScalar elemVec[])
134020cf1dd8SToby Isaac 
134120cf1dd8SToby Isaac ex52.c:
134220cf1dd8SToby Isaac   PetscErrorCode IntegrateLaplacianBatchCPU(PetscInt Ne, PetscInt Nb, const PetscScalar coefficients[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscInt Nq, const PetscReal quadPoints[], const PetscReal quadWeights[], const PetscReal basisTabulation[], const PetscReal basisDerTabulation[], PetscScalar elemVec[], AppCtx *user)
134320cf1dd8SToby Isaac   PetscErrorCode IntegrateElasticityBatchCPU(PetscInt Ne, PetscInt Nb, PetscInt Ncomp, const PetscScalar coefficients[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscInt Nq, const PetscReal quadPoints[], const PetscReal quadWeights[], const PetscReal basisTabulation[], const PetscReal basisDerTabulation[], PetscScalar elemVec[], AppCtx *user)
134420cf1dd8SToby Isaac 
134520cf1dd8SToby Isaac ex52_integrateElement.cu
134620cf1dd8SToby Isaac __global__ void integrateElementQuadrature(int N_cb, realType *coefficients, realType *jacobianInverses, realType *jacobianDeterminants, realType *elemVec)
134720cf1dd8SToby Isaac 
134820cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt Nbl, const PetscScalar coefficients[],
134920cf1dd8SToby Isaac                                                      const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[],
135020cf1dd8SToby Isaac                                                      PetscLogEvent event, PetscInt debug, PetscInt pde_op)
135120cf1dd8SToby Isaac 
135220cf1dd8SToby Isaac ex52_integrateElementOpenCL.c:
135320cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt N_bl, const PetscScalar coefficients[],
135420cf1dd8SToby Isaac                                                      const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[],
135520cf1dd8SToby Isaac                                                      PetscLogEvent event, PetscInt debug, PetscInt pde_op)
135620cf1dd8SToby Isaac 
135720cf1dd8SToby Isaac __kernel void integrateElementQuadrature(int N_cb, __global float *coefficients, __global float *jacobianInverses, __global float *jacobianDeterminants, __global float *elemVec)
135820cf1dd8SToby Isaac */
135920cf1dd8SToby Isaac 
136020cf1dd8SToby Isaac /*@C
136120cf1dd8SToby Isaac   PetscFEIntegrate - Produce the integral for the given field for a chunk of elements by quadrature integration
136220cf1dd8SToby Isaac 
136320cf1dd8SToby Isaac   Not collective
136420cf1dd8SToby Isaac 
136520cf1dd8SToby Isaac   Input Parameters:
1366360cf244SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
136720cf1dd8SToby Isaac . field        - The field being integrated
136820cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
136920cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
137020cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
137120cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
137220cf1dd8SToby Isaac - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
137320cf1dd8SToby Isaac 
13747a7aea1fSJed Brown   Output Parameter:
137520cf1dd8SToby Isaac . integral     - the integral for this field
137620cf1dd8SToby Isaac 
13772b99622eSMatthew G. Knepley   Level: intermediate
137820cf1dd8SToby Isaac 
137920cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
138020cf1dd8SToby Isaac @*/
13814bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrate(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom,
138220cf1dd8SToby Isaac                                 const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
138320cf1dd8SToby Isaac {
13844bee2e38SMatthew G. Knepley   PetscFE        fe;
138520cf1dd8SToby Isaac   PetscErrorCode ierr;
138620cf1dd8SToby Isaac 
138720cf1dd8SToby Isaac   PetscFunctionBegin;
13884bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
13894bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
13904bee2e38SMatthew G. Knepley   if (fe->ops->integrate) {ierr = (*fe->ops->integrate)(prob, field, Ne, cgeom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);}
139120cf1dd8SToby Isaac   PetscFunctionReturn(0);
139220cf1dd8SToby Isaac }
139320cf1dd8SToby Isaac 
139420cf1dd8SToby Isaac /*@C
1395afe6d6adSToby Isaac   PetscFEIntegrateBd - Produce the integral for the given field for a chunk of elements by quadrature integration
1396afe6d6adSToby Isaac 
1397afe6d6adSToby Isaac   Not collective
1398afe6d6adSToby Isaac 
1399afe6d6adSToby Isaac   Input Parameters:
1400360cf244SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
1401afe6d6adSToby Isaac . field        - The field being integrated
1402afe6d6adSToby Isaac . obj_func     - The function to be integrated
1403afe6d6adSToby Isaac . Ne           - The number of elements in the chunk
1404afe6d6adSToby Isaac . fgeom        - The face geometry for each face in the chunk
1405afe6d6adSToby Isaac . coefficients - The array of FEM basis coefficients for the elements
1406afe6d6adSToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
1407afe6d6adSToby Isaac - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1408afe6d6adSToby Isaac 
14097a7aea1fSJed Brown   Output Parameter:
1410afe6d6adSToby Isaac . integral     - the integral for this field
1411afe6d6adSToby Isaac 
14122b99622eSMatthew G. Knepley   Level: intermediate
1413afe6d6adSToby Isaac 
1414afe6d6adSToby Isaac .seealso: PetscFEIntegrateResidual()
1415afe6d6adSToby Isaac @*/
14164bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBd(PetscDS prob, PetscInt field,
1417afe6d6adSToby Isaac                                   void (*obj_func)(PetscInt, PetscInt, PetscInt,
1418afe6d6adSToby Isaac                                                    const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
1419afe6d6adSToby Isaac                                                    const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
1420afe6d6adSToby Isaac                                                    PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
1421afe6d6adSToby Isaac                                   PetscInt Ne, PetscFEGeom *geom, const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
1422afe6d6adSToby Isaac {
14234bee2e38SMatthew G. Knepley   PetscFE        fe;
1424afe6d6adSToby Isaac   PetscErrorCode ierr;
1425afe6d6adSToby Isaac 
1426afe6d6adSToby Isaac   PetscFunctionBegin;
14274bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
14284bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
14294bee2e38SMatthew G. Knepley   if (fe->ops->integratebd) {ierr = (*fe->ops->integratebd)(prob, field, obj_func, Ne, geom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);}
1430afe6d6adSToby Isaac   PetscFunctionReturn(0);
1431afe6d6adSToby Isaac }
1432afe6d6adSToby Isaac 
1433afe6d6adSToby Isaac /*@C
143420cf1dd8SToby Isaac   PetscFEIntegrateResidual - Produce the element residual vector for a chunk of elements by quadrature integration
143520cf1dd8SToby Isaac 
143620cf1dd8SToby Isaac   Not collective
143720cf1dd8SToby Isaac 
143820cf1dd8SToby Isaac   Input Parameters:
14396528b96dSMatthew G. Knepley + ds           - The PetscDS specifying the discretizations and continuum functions
14406528b96dSMatthew G. Knepley . key          - The (label+value, field) being integrated
144120cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
144220cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
144320cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
144420cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
144520cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
144620cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
144720cf1dd8SToby Isaac - t            - The time
144820cf1dd8SToby Isaac 
14497a7aea1fSJed Brown   Output Parameter:
145020cf1dd8SToby Isaac . elemVec      - the element residual vectors from each element
145120cf1dd8SToby Isaac 
145220cf1dd8SToby Isaac   Note:
145320cf1dd8SToby Isaac $ Loop over batch of elements (e):
145420cf1dd8SToby Isaac $   Loop over quadrature points (q):
145520cf1dd8SToby Isaac $     Make u_q and gradU_q (loops over fields,Nb,Ncomp) and x_q
145620cf1dd8SToby Isaac $     Call f_0 and f_1
145720cf1dd8SToby Isaac $   Loop over element vector entries (f,fc --> i):
145820cf1dd8SToby Isaac $     elemVec[i] += \psi^{fc}_f(q) f0_{fc}(u, \nabla u) + \nabla\psi^{fc}_f(q) \cdot f1_{fc,df}(u, \nabla u)
145920cf1dd8SToby Isaac 
14602b99622eSMatthew G. Knepley   Level: intermediate
146120cf1dd8SToby Isaac 
146220cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
146320cf1dd8SToby Isaac @*/
146406ad1575SMatthew G. Knepley PetscErrorCode PetscFEIntegrateResidual(PetscDS ds, PetscFormKey key, PetscInt Ne, PetscFEGeom *cgeom,
146520cf1dd8SToby Isaac                                         const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
146620cf1dd8SToby Isaac {
14674bee2e38SMatthew G. Knepley   PetscFE        fe;
146820cf1dd8SToby Isaac   PetscErrorCode ierr;
146920cf1dd8SToby Isaac 
14706528b96dSMatthew G. Knepley   PetscFunctionBeginHot;
14716528b96dSMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
14726528b96dSMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, key.field, (PetscObject *) &fe);CHKERRQ(ierr);
14736528b96dSMatthew G. Knepley   if (fe->ops->integrateresidual) {ierr = (*fe->ops->integrateresidual)(ds, key, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
147420cf1dd8SToby Isaac   PetscFunctionReturn(0);
147520cf1dd8SToby Isaac }
147620cf1dd8SToby Isaac 
147720cf1dd8SToby Isaac /*@C
147820cf1dd8SToby Isaac   PetscFEIntegrateBdResidual - Produce the element residual vector for a chunk of elements by quadrature integration over a boundary
147920cf1dd8SToby Isaac 
148020cf1dd8SToby Isaac   Not collective
148120cf1dd8SToby Isaac 
148220cf1dd8SToby Isaac   Input Parameters:
148306d8a0d3SMatthew G. Knepley + ds           - The PetscDS specifying the discretizations and continuum functions
148445480ffeSMatthew G. Knepley . wf           - The PetscWeakForm object holding the pointwise functions
148506d8a0d3SMatthew G. Knepley . key          - The (label+value, field) being integrated
148620cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
148720cf1dd8SToby Isaac . fgeom        - The face geometry for each cell in the chunk
148820cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
148920cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
149020cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
149120cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
149220cf1dd8SToby Isaac - t            - The time
149320cf1dd8SToby Isaac 
14947a7aea1fSJed Brown   Output Parameter:
149520cf1dd8SToby Isaac . elemVec      - the element residual vectors from each element
149620cf1dd8SToby Isaac 
14972b99622eSMatthew G. Knepley   Level: intermediate
149820cf1dd8SToby Isaac 
149920cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
150020cf1dd8SToby Isaac @*/
150106ad1575SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBdResidual(PetscDS ds, PetscWeakForm wf, PetscFormKey key, PetscInt Ne, PetscFEGeom *fgeom,
150220cf1dd8SToby Isaac                                           const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
150320cf1dd8SToby Isaac {
15044bee2e38SMatthew G. Knepley   PetscFE        fe;
150520cf1dd8SToby Isaac   PetscErrorCode ierr;
150620cf1dd8SToby Isaac 
150720cf1dd8SToby Isaac   PetscFunctionBegin;
150806d8a0d3SMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
150906d8a0d3SMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, key.field, (PetscObject *) &fe);CHKERRQ(ierr);
151045480ffeSMatthew G. Knepley   if (fe->ops->integratebdresidual) {ierr = (*fe->ops->integratebdresidual)(ds, wf, key, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
151120cf1dd8SToby Isaac   PetscFunctionReturn(0);
151220cf1dd8SToby Isaac }
151320cf1dd8SToby Isaac 
151420cf1dd8SToby Isaac /*@C
151527f02ce8SMatthew G. Knepley   PetscFEIntegrateHybridResidual - Produce the element residual vector for a chunk of hybrid element faces by quadrature integration
151627f02ce8SMatthew G. Knepley 
151727f02ce8SMatthew G. Knepley   Not collective
151827f02ce8SMatthew G. Knepley 
151927f02ce8SMatthew G. Knepley   Input Parameters:
152027f02ce8SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
15216528b96dSMatthew G. Knepley . key          - The (label+value, field) being integrated
1522c2b7495fSMatthew G. Knepley . s            - The side of the cell being integrated, 0 for negative and 1 for positive
152327f02ce8SMatthew G. Knepley . Ne           - The number of elements in the chunk
152427f02ce8SMatthew G. Knepley . fgeom        - The face geometry for each cell in the chunk
152527f02ce8SMatthew G. Knepley . coefficients - The array of FEM basis coefficients for the elements
152627f02ce8SMatthew G. Knepley . coefficients_t - The array of FEM basis time derivative coefficients for the elements
152727f02ce8SMatthew G. Knepley . probAux      - The PetscDS specifying the auxiliary discretizations
152827f02ce8SMatthew G. Knepley . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
152927f02ce8SMatthew G. Knepley - t            - The time
153027f02ce8SMatthew G. Knepley 
153127f02ce8SMatthew G. Knepley   Output Parameter
153227f02ce8SMatthew G. Knepley . elemVec      - the element residual vectors from each element
153327f02ce8SMatthew G. Knepley 
153427f02ce8SMatthew G. Knepley   Level: developer
153527f02ce8SMatthew G. Knepley 
153627f02ce8SMatthew G. Knepley .seealso: PetscFEIntegrateResidual()
153727f02ce8SMatthew G. Knepley @*/
1538c2b7495fSMatthew G. Knepley PetscErrorCode PetscFEIntegrateHybridResidual(PetscDS prob, PetscFormKey key, PetscInt s, PetscInt Ne, PetscFEGeom *fgeom,
153927f02ce8SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
154027f02ce8SMatthew G. Knepley {
154127f02ce8SMatthew G. Knepley   PetscFE        fe;
154227f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
154327f02ce8SMatthew G. Knepley 
154427f02ce8SMatthew G. Knepley   PetscFunctionBegin;
154527f02ce8SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
15466528b96dSMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, key.field, (PetscObject *) &fe);CHKERRQ(ierr);
1547c2b7495fSMatthew G. Knepley   if (fe->ops->integratehybridresidual) {ierr = (*fe->ops->integratehybridresidual)(prob, key, s, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
154827f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
154927f02ce8SMatthew G. Knepley }
155027f02ce8SMatthew G. Knepley 
155127f02ce8SMatthew G. Knepley /*@C
155220cf1dd8SToby Isaac   PetscFEIntegrateJacobian - Produce the element Jacobian for a chunk of elements by quadrature integration
155320cf1dd8SToby Isaac 
155420cf1dd8SToby Isaac   Not collective
155520cf1dd8SToby Isaac 
155620cf1dd8SToby Isaac   Input Parameters:
15576528b96dSMatthew G. Knepley + ds           - The PetscDS specifying the discretizations and continuum functions
155820cf1dd8SToby Isaac . jtype        - The type of matrix pointwise functions that should be used
15596528b96dSMatthew G. Knepley . key          - The (label+value, fieldI*Nf + fieldJ) being integrated
1560*5fedec97SMatthew G. Knepley . s            - The side of the cell being integrated, 0 for negative and 1 for positive
156120cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
156220cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
156320cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
156420cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
156520cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
156620cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
156720cf1dd8SToby Isaac . t            - The time
156820cf1dd8SToby Isaac - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
156920cf1dd8SToby Isaac 
15707a7aea1fSJed Brown   Output Parameter:
157120cf1dd8SToby Isaac . elemMat      - the element matrices for the Jacobian from each element
157220cf1dd8SToby Isaac 
157320cf1dd8SToby Isaac   Note:
157420cf1dd8SToby Isaac $ Loop over batch of elements (e):
157520cf1dd8SToby Isaac $   Loop over element matrix entries (f,fc,g,gc --> i,j):
157620cf1dd8SToby Isaac $     Loop over quadrature points (q):
157720cf1dd8SToby Isaac $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
157820cf1dd8SToby Isaac $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
157920cf1dd8SToby Isaac $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
158020cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
158120cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
15822b99622eSMatthew G. Knepley   Level: intermediate
158320cf1dd8SToby Isaac 
158420cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
158520cf1dd8SToby Isaac @*/
158606ad1575SMatthew G. Knepley PetscErrorCode PetscFEIntegrateJacobian(PetscDS ds, PetscFEJacobianType jtype, PetscFormKey key, PetscInt Ne, PetscFEGeom *cgeom,
158720cf1dd8SToby Isaac                                         const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
158820cf1dd8SToby Isaac {
15894bee2e38SMatthew G. Knepley   PetscFE        fe;
15906528b96dSMatthew G. Knepley   PetscInt       Nf;
159120cf1dd8SToby Isaac   PetscErrorCode ierr;
159220cf1dd8SToby Isaac 
159320cf1dd8SToby Isaac   PetscFunctionBegin;
15946528b96dSMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
15956528b96dSMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
15966528b96dSMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, key.field / Nf, (PetscObject *) &fe);CHKERRQ(ierr);
15976528b96dSMatthew G. Knepley   if (fe->ops->integratejacobian) {ierr = (*fe->ops->integratejacobian)(ds, jtype, key, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);}
159820cf1dd8SToby Isaac   PetscFunctionReturn(0);
159920cf1dd8SToby Isaac }
160020cf1dd8SToby Isaac 
160120cf1dd8SToby Isaac /*@C
160220cf1dd8SToby Isaac   PetscFEIntegrateBdJacobian - Produce the boundary element Jacobian for a chunk of elements by quadrature integration
160320cf1dd8SToby Isaac 
160420cf1dd8SToby Isaac   Not collective
160520cf1dd8SToby Isaac 
160620cf1dd8SToby Isaac   Input Parameters:
160745480ffeSMatthew G. Knepley + ds           - The PetscDS specifying the discretizations and continuum functions
160845480ffeSMatthew G. Knepley . wf           - The PetscWeakForm holding the pointwise functions
160945480ffeSMatthew G. Knepley . key          - The (label+value, fieldI*Nf + fieldJ) being integrated
161020cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
161120cf1dd8SToby Isaac . fgeom        - The face geometry for each cell in the chunk
161220cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
161320cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
161420cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
161520cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
161620cf1dd8SToby Isaac . t            - The time
161720cf1dd8SToby Isaac - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
161820cf1dd8SToby Isaac 
16197a7aea1fSJed Brown   Output Parameter:
162020cf1dd8SToby Isaac . elemMat              - the element matrices for the Jacobian from each element
162120cf1dd8SToby Isaac 
162220cf1dd8SToby Isaac   Note:
162320cf1dd8SToby Isaac $ Loop over batch of elements (e):
162420cf1dd8SToby Isaac $   Loop over element matrix entries (f,fc,g,gc --> i,j):
162520cf1dd8SToby Isaac $     Loop over quadrature points (q):
162620cf1dd8SToby Isaac $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
162720cf1dd8SToby Isaac $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
162820cf1dd8SToby Isaac $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
162920cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
163020cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
16312b99622eSMatthew G. Knepley   Level: intermediate
163220cf1dd8SToby Isaac 
163320cf1dd8SToby Isaac .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual()
163420cf1dd8SToby Isaac @*/
163506ad1575SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBdJacobian(PetscDS ds, PetscWeakForm wf, PetscFormKey key, PetscInt Ne, PetscFEGeom *fgeom,
163620cf1dd8SToby Isaac                                           const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
163720cf1dd8SToby Isaac {
16384bee2e38SMatthew G. Knepley   PetscFE        fe;
163945480ffeSMatthew G. Knepley   PetscInt       Nf;
164020cf1dd8SToby Isaac   PetscErrorCode ierr;
164120cf1dd8SToby Isaac 
164220cf1dd8SToby Isaac   PetscFunctionBegin;
164345480ffeSMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
164445480ffeSMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
164545480ffeSMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, key.field / Nf, (PetscObject *) &fe);CHKERRQ(ierr);
164645480ffeSMatthew G. Knepley   if (fe->ops->integratebdjacobian) {ierr = (*fe->ops->integratebdjacobian)(ds, wf, key, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);}
164720cf1dd8SToby Isaac   PetscFunctionReturn(0);
164820cf1dd8SToby Isaac }
164920cf1dd8SToby Isaac 
165027f02ce8SMatthew G. Knepley /*@C
165127f02ce8SMatthew G. Knepley   PetscFEIntegrateHybridJacobian - Produce the boundary element Jacobian for a chunk of hybrid elements by quadrature integration
165227f02ce8SMatthew G. Knepley 
165327f02ce8SMatthew G. Knepley   Not collective
165427f02ce8SMatthew G. Knepley 
165527f02ce8SMatthew G. Knepley   Input Parameters:
165645480ffeSMatthew G. Knepley + ds           - The PetscDS specifying the discretizations and continuum functions
165727f02ce8SMatthew G. Knepley . jtype        - The type of matrix pointwise functions that should be used
165845480ffeSMatthew G. Knepley . key          - The (label+value, fieldI*Nf + fieldJ) being integrated
1659*5fedec97SMatthew G. Knepley . s            - The side of the cell being integrated, 0 for negative and 1 for positive
166027f02ce8SMatthew G. Knepley . Ne           - The number of elements in the chunk
166127f02ce8SMatthew G. Knepley . fgeom        - The face geometry for each cell in the chunk
166227f02ce8SMatthew G. Knepley . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
166327f02ce8SMatthew G. Knepley . coefficients_t - The array of FEM basis time derivative coefficients for the elements
166427f02ce8SMatthew G. Knepley . probAux      - The PetscDS specifying the auxiliary discretizations
166527f02ce8SMatthew G. Knepley . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
166627f02ce8SMatthew G. Knepley . t            - The time
166727f02ce8SMatthew G. Knepley - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
166827f02ce8SMatthew G. Knepley 
166927f02ce8SMatthew G. Knepley   Output Parameter
167027f02ce8SMatthew G. Knepley . elemMat              - the element matrices for the Jacobian from each element
167127f02ce8SMatthew G. Knepley 
167227f02ce8SMatthew G. Knepley   Note:
167327f02ce8SMatthew G. Knepley $ Loop over batch of elements (e):
167427f02ce8SMatthew G. Knepley $   Loop over element matrix entries (f,fc,g,gc --> i,j):
167527f02ce8SMatthew G. Knepley $     Loop over quadrature points (q):
167627f02ce8SMatthew G. Knepley $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
167727f02ce8SMatthew G. Knepley $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
167827f02ce8SMatthew G. Knepley $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
167927f02ce8SMatthew G. Knepley $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
168027f02ce8SMatthew G. Knepley $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
168127f02ce8SMatthew G. Knepley   Level: developer
168227f02ce8SMatthew G. Knepley 
168327f02ce8SMatthew G. Knepley .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual()
168427f02ce8SMatthew G. Knepley @*/
1685*5fedec97SMatthew G. Knepley PetscErrorCode PetscFEIntegrateHybridJacobian(PetscDS ds, PetscFEJacobianType jtype, PetscFormKey key, PetscInt s, PetscInt Ne, PetscFEGeom *fgeom,
168627f02ce8SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
168727f02ce8SMatthew G. Knepley {
168827f02ce8SMatthew G. Knepley   PetscFE        fe;
168945480ffeSMatthew G. Knepley   PetscInt       Nf;
169027f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
169127f02ce8SMatthew G. Knepley 
169227f02ce8SMatthew G. Knepley   PetscFunctionBegin;
169345480ffeSMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
169445480ffeSMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
169545480ffeSMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, key.field / Nf, (PetscObject *) &fe);CHKERRQ(ierr);
1696*5fedec97SMatthew G. Knepley   if (fe->ops->integratehybridjacobian) {ierr = (*fe->ops->integratehybridjacobian)(ds, jtype, key, s, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);}
169727f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
169827f02ce8SMatthew G. Knepley }
169927f02ce8SMatthew G. Knepley 
17002b99622eSMatthew G. Knepley /*@
17012b99622eSMatthew G. Knepley   PetscFEGetHeightSubspace - Get the subspace of this space for a mesh point of a given height
17022b99622eSMatthew G. Knepley 
17032b99622eSMatthew G. Knepley   Input Parameters:
17042b99622eSMatthew G. Knepley + fe     - The finite element space
17052b99622eSMatthew G. Knepley - height - The height of the Plex point
17062b99622eSMatthew G. Knepley 
17072b99622eSMatthew G. Knepley   Output Parameter:
17082b99622eSMatthew G. Knepley . subfe  - The subspace of this FE space
17092b99622eSMatthew G. Knepley 
17102b99622eSMatthew G. Knepley   Note: For example, if we want the subspace of this space for a face, we would choose height = 1.
17112b99622eSMatthew G. Knepley 
17122b99622eSMatthew G. Knepley   Level: advanced
17132b99622eSMatthew G. Knepley 
17142b99622eSMatthew G. Knepley .seealso: PetscFECreateDefault()
17152b99622eSMatthew G. Knepley @*/
171620cf1dd8SToby Isaac PetscErrorCode PetscFEGetHeightSubspace(PetscFE fe, PetscInt height, PetscFE *subfe)
171720cf1dd8SToby Isaac {
171820cf1dd8SToby Isaac   PetscSpace      P, subP;
171920cf1dd8SToby Isaac   PetscDualSpace  Q, subQ;
172020cf1dd8SToby Isaac   PetscQuadrature subq;
172120cf1dd8SToby Isaac   PetscFEType     fetype;
172220cf1dd8SToby Isaac   PetscInt        dim, Nc;
172320cf1dd8SToby Isaac   PetscErrorCode  ierr;
172420cf1dd8SToby Isaac 
172520cf1dd8SToby Isaac   PetscFunctionBegin;
172620cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe, PETSCFE_CLASSID, 1);
172720cf1dd8SToby Isaac   PetscValidPointer(subfe, 3);
172820cf1dd8SToby Isaac   if (height == 0) {
172920cf1dd8SToby Isaac     *subfe = fe;
173020cf1dd8SToby Isaac     PetscFunctionReturn(0);
173120cf1dd8SToby Isaac   }
173220cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
173320cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
173420cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr);
173520cf1dd8SToby Isaac   ierr = PetscFEGetFaceQuadrature(fe, &subq);CHKERRQ(ierr);
173620cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDimension(Q, &dim);CHKERRQ(ierr);
17372da392ccSBarry Smith   if (height > dim || height < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Asked for space at height %D for dimension %D space", height, dim);
173820cf1dd8SToby Isaac   if (!fe->subspaces) {ierr = PetscCalloc1(dim, &fe->subspaces);CHKERRQ(ierr);}
173920cf1dd8SToby Isaac   if (height <= dim) {
174020cf1dd8SToby Isaac     if (!fe->subspaces[height-1]) {
1741665f567fSMatthew G. Knepley       PetscFE     sub = NULL;
17423f6b16c7SMatthew G. Knepley       const char *name;
174320cf1dd8SToby Isaac 
174420cf1dd8SToby Isaac       ierr = PetscSpaceGetHeightSubspace(P, height, &subP);CHKERRQ(ierr);
174520cf1dd8SToby Isaac       ierr = PetscDualSpaceGetHeightSubspace(Q, height, &subQ);CHKERRQ(ierr);
1746665f567fSMatthew G. Knepley       if (subQ) {
174720cf1dd8SToby Isaac         ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), &sub);CHKERRQ(ierr);
17483f6b16c7SMatthew G. Knepley         ierr = PetscObjectGetName((PetscObject) fe,  &name);CHKERRQ(ierr);
17493f6b16c7SMatthew G. Knepley         ierr = PetscObjectSetName((PetscObject) sub,  name);CHKERRQ(ierr);
175020cf1dd8SToby Isaac         ierr = PetscFEGetType(fe, &fetype);CHKERRQ(ierr);
175120cf1dd8SToby Isaac         ierr = PetscFESetType(sub, fetype);CHKERRQ(ierr);
175220cf1dd8SToby Isaac         ierr = PetscFESetBasisSpace(sub, subP);CHKERRQ(ierr);
175320cf1dd8SToby Isaac         ierr = PetscFESetDualSpace(sub, subQ);CHKERRQ(ierr);
175420cf1dd8SToby Isaac         ierr = PetscFESetNumComponents(sub, Nc);CHKERRQ(ierr);
175520cf1dd8SToby Isaac         ierr = PetscFESetUp(sub);CHKERRQ(ierr);
175620cf1dd8SToby Isaac         ierr = PetscFESetQuadrature(sub, subq);CHKERRQ(ierr);
1757665f567fSMatthew G. Knepley       }
175820cf1dd8SToby Isaac       fe->subspaces[height-1] = sub;
175920cf1dd8SToby Isaac     }
176020cf1dd8SToby Isaac     *subfe = fe->subspaces[height-1];
176120cf1dd8SToby Isaac   } else {
176220cf1dd8SToby Isaac     *subfe = NULL;
176320cf1dd8SToby Isaac   }
176420cf1dd8SToby Isaac   PetscFunctionReturn(0);
176520cf1dd8SToby Isaac }
176620cf1dd8SToby Isaac 
176720cf1dd8SToby Isaac /*@
176820cf1dd8SToby Isaac   PetscFERefine - Create a "refined" PetscFE object that refines the reference cell into smaller copies. This is typically used
176920cf1dd8SToby Isaac   to precondition a higher order method with a lower order method on a refined mesh having the same number of dofs (but more
177020cf1dd8SToby Isaac   sparsity). It is also used to create an interpolation between regularly refined meshes.
177120cf1dd8SToby Isaac 
1772d083f849SBarry Smith   Collective on fem
177320cf1dd8SToby Isaac 
177420cf1dd8SToby Isaac   Input Parameter:
177520cf1dd8SToby Isaac . fe - The initial PetscFE
177620cf1dd8SToby Isaac 
177720cf1dd8SToby Isaac   Output Parameter:
177820cf1dd8SToby Isaac . feRef - The refined PetscFE
177920cf1dd8SToby Isaac 
17802b99622eSMatthew G. Knepley   Level: advanced
178120cf1dd8SToby Isaac 
178220cf1dd8SToby Isaac .seealso: PetscFEType, PetscFECreate(), PetscFESetType()
178320cf1dd8SToby Isaac @*/
178420cf1dd8SToby Isaac PetscErrorCode PetscFERefine(PetscFE fe, PetscFE *feRef)
178520cf1dd8SToby Isaac {
178620cf1dd8SToby Isaac   PetscSpace       P, Pref;
178720cf1dd8SToby Isaac   PetscDualSpace   Q, Qref;
178820cf1dd8SToby Isaac   DM               K, Kref;
178920cf1dd8SToby Isaac   PetscQuadrature  q, qref;
179020cf1dd8SToby Isaac   const PetscReal *v0, *jac;
179120cf1dd8SToby Isaac   PetscInt         numComp, numSubelements;
17921ac17e89SToby Isaac   PetscInt         cStart, cEnd, c;
17931ac17e89SToby Isaac   PetscDualSpace  *cellSpaces;
179420cf1dd8SToby Isaac   PetscErrorCode   ierr;
179520cf1dd8SToby Isaac 
179620cf1dd8SToby Isaac   PetscFunctionBegin;
179720cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
179820cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
179920cf1dd8SToby Isaac   ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr);
180020cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(Q, &K);CHKERRQ(ierr);
180120cf1dd8SToby Isaac   /* Create space */
180220cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) P);CHKERRQ(ierr);
180320cf1dd8SToby Isaac   Pref = P;
180420cf1dd8SToby Isaac   /* Create dual space */
180520cf1dd8SToby Isaac   ierr = PetscDualSpaceDuplicate(Q, &Qref);CHKERRQ(ierr);
18061ac17e89SToby Isaac   ierr = PetscDualSpaceSetType(Qref, PETSCDUALSPACEREFINED);CHKERRQ(ierr);
180720cf1dd8SToby Isaac   ierr = DMRefine(K, PetscObjectComm((PetscObject) fe), &Kref);CHKERRQ(ierr);
180820cf1dd8SToby Isaac   ierr = PetscDualSpaceSetDM(Qref, Kref);CHKERRQ(ierr);
18091ac17e89SToby Isaac   ierr = DMPlexGetHeightStratum(Kref, 0, &cStart, &cEnd);CHKERRQ(ierr);
18101ac17e89SToby Isaac   ierr = PetscMalloc1(cEnd - cStart, &cellSpaces);CHKERRQ(ierr);
18111ac17e89SToby Isaac   /* TODO: fix for non-uniform refinement */
18121ac17e89SToby Isaac   for (c = 0; c < cEnd - cStart; c++) cellSpaces[c] = Q;
18131ac17e89SToby Isaac   ierr = PetscDualSpaceRefinedSetCellSpaces(Qref, cellSpaces);CHKERRQ(ierr);
18141ac17e89SToby Isaac   ierr = PetscFree(cellSpaces);CHKERRQ(ierr);
181520cf1dd8SToby Isaac   ierr = DMDestroy(&Kref);CHKERRQ(ierr);
181620cf1dd8SToby Isaac   ierr = PetscDualSpaceSetUp(Qref);CHKERRQ(ierr);
181720cf1dd8SToby Isaac   /* Create element */
181820cf1dd8SToby Isaac   ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), feRef);CHKERRQ(ierr);
181920cf1dd8SToby Isaac   ierr = PetscFESetType(*feRef, PETSCFECOMPOSITE);CHKERRQ(ierr);
182020cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*feRef, Pref);CHKERRQ(ierr);
182120cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*feRef, Qref);CHKERRQ(ierr);
182220cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe,    &numComp);CHKERRQ(ierr);
182320cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*feRef, numComp);CHKERRQ(ierr);
182420cf1dd8SToby Isaac   ierr = PetscFESetUp(*feRef);CHKERRQ(ierr);
182520cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&Pref);CHKERRQ(ierr);
182620cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&Qref);CHKERRQ(ierr);
182720cf1dd8SToby Isaac   /* Create quadrature */
182820cf1dd8SToby Isaac   ierr = PetscFECompositeGetMapping(*feRef, &numSubelements, &v0, &jac, NULL);CHKERRQ(ierr);
182920cf1dd8SToby Isaac   ierr = PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref);CHKERRQ(ierr);
183020cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*feRef, qref);CHKERRQ(ierr);
183120cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&qref);CHKERRQ(ierr);
183220cf1dd8SToby Isaac   PetscFunctionReturn(0);
183320cf1dd8SToby Isaac }
183420cf1dd8SToby Isaac 
183520cf1dd8SToby Isaac /*@C
183620cf1dd8SToby Isaac   PetscFECreateDefault - Create a PetscFE for basic FEM computation
183720cf1dd8SToby Isaac 
1838d083f849SBarry Smith   Collective
183920cf1dd8SToby Isaac 
184020cf1dd8SToby Isaac   Input Parameters:
18417be5e748SToby Isaac + comm      - The MPI comm
184220cf1dd8SToby Isaac . dim       - The spatial dimension
184320cf1dd8SToby Isaac . Nc        - The number of components
184420cf1dd8SToby Isaac . isSimplex - Flag for simplex reference cell, otherwise its a tensor product
184520cf1dd8SToby Isaac . prefix    - The options prefix, or NULL
1846727cddd5SJacob Faibussowitsch - qorder    - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree
184720cf1dd8SToby Isaac 
184820cf1dd8SToby Isaac   Output Parameter:
184920cf1dd8SToby Isaac . fem - The PetscFE object
185020cf1dd8SToby Isaac 
1851e703855dSMatthew G. Knepley   Note:
18528f2aacc6SMatthew G. Knepley   Each subobject is SetFromOption() during creation, so that the object may be customized from the command line, using the prefix specified above. See the links below for the particular options available.
1853e703855dSMatthew G. Knepley 
185420cf1dd8SToby Isaac   Level: beginner
185520cf1dd8SToby Isaac 
18568f2aacc6SMatthew G. Knepley .seealso: PetscSpaceSetFromOptions(), PetscDualSpaceSetFromOptions(), PetscFESetFromOptions(), PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
185720cf1dd8SToby Isaac @*/
18587be5e748SToby Isaac PetscErrorCode PetscFECreateDefault(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, const char prefix[], PetscInt qorder, PetscFE *fem)
185920cf1dd8SToby Isaac {
186020cf1dd8SToby Isaac   PetscQuadrature q, fq;
186120cf1dd8SToby Isaac   DM              K;
186220cf1dd8SToby Isaac   PetscSpace      P;
186320cf1dd8SToby Isaac   PetscDualSpace  Q;
186420cf1dd8SToby Isaac   PetscInt        order, quadPointsPerEdge;
186520cf1dd8SToby Isaac   PetscBool       tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
186620cf1dd8SToby Isaac   PetscErrorCode  ierr;
186720cf1dd8SToby Isaac 
186820cf1dd8SToby Isaac   PetscFunctionBegin;
186920cf1dd8SToby Isaac   /* Create space */
18707be5e748SToby Isaac   ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr);
187120cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix);CHKERRQ(ierr);
187220cf1dd8SToby Isaac   ierr = PetscSpacePolynomialSetTensor(P, tensor);CHKERRQ(ierr);
187320cf1dd8SToby Isaac   ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr);
187420cf1dd8SToby Isaac   ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr);
1875028afddaSToby Isaac   ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr);
187620cf1dd8SToby Isaac   ierr = PetscSpaceSetUp(P);CHKERRQ(ierr);
187720cf1dd8SToby Isaac   ierr = PetscSpaceGetDegree(P, &order, NULL);CHKERRQ(ierr);
187820cf1dd8SToby Isaac   ierr = PetscSpacePolynomialGetTensor(P, &tensor);CHKERRQ(ierr);
187920cf1dd8SToby Isaac   /* Create dual space */
18807be5e748SToby Isaac   ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr);
188120cf1dd8SToby Isaac   ierr = PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
188220cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);CHKERRQ(ierr);
188320cf1dd8SToby Isaac   ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr);
188420cf1dd8SToby Isaac   ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr);
188520cf1dd8SToby Isaac   ierr = DMDestroy(&K);CHKERRQ(ierr);
188620cf1dd8SToby Isaac   ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr);
188720cf1dd8SToby Isaac   ierr = PetscDualSpaceSetOrder(Q, order);CHKERRQ(ierr);
188820cf1dd8SToby Isaac   ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor);CHKERRQ(ierr);
188920cf1dd8SToby Isaac   ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr);
189020cf1dd8SToby Isaac   ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr);
189120cf1dd8SToby Isaac   /* Create element */
18927be5e748SToby Isaac   ierr = PetscFECreate(comm, fem);CHKERRQ(ierr);
189320cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);CHKERRQ(ierr);
189420cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr);
189520cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr);
189620cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr);
189791e89cf0SMatthew G. Knepley   ierr = PetscFESetFromOptions(*fem);CHKERRQ(ierr);
189820cf1dd8SToby Isaac   ierr = PetscFESetUp(*fem);CHKERRQ(ierr);
189920cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr);
190020cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr);
190120cf1dd8SToby Isaac   /* Create quadrature (with specified order if given) */
190220cf1dd8SToby Isaac   qorder = qorder >= 0 ? qorder : order;
190320cf1dd8SToby Isaac   ierr = PetscObjectOptionsBegin((PetscObject)*fem);CHKERRQ(ierr);
19045a856986SBarry Smith   ierr = PetscOptionsBoundedInt("-petscfe_default_quadrature_order","Quadrature order is one less than quadrature points per edge","PetscFECreateDefault",qorder,&qorder,NULL,0);CHKERRQ(ierr);
190520cf1dd8SToby Isaac   ierr = PetscOptionsEnd();CHKERRQ(ierr);
190620cf1dd8SToby Isaac   quadPointsPerEdge = PetscMax(qorder + 1,1);
190720cf1dd8SToby Isaac   if (isSimplex) {
1908e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
1909e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
19104ccfa306SStefano Zampini   } else {
191120cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
191220cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
191320cf1dd8SToby Isaac   }
191420cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr);
191520cf1dd8SToby Isaac   ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr);
191620cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr);
191720cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr);
191820cf1dd8SToby Isaac   PetscFunctionReturn(0);
191920cf1dd8SToby Isaac }
19203f6b16c7SMatthew G. Knepley 
1921e703855dSMatthew G. Knepley /*@
1922e703855dSMatthew G. Knepley   PetscFECreateLagrange - Create a PetscFE for the basic Lagrange space of degree k
1923e703855dSMatthew G. Knepley 
1924e703855dSMatthew G. Knepley   Collective
1925e703855dSMatthew G. Knepley 
1926e703855dSMatthew G. Knepley   Input Parameters:
1927e703855dSMatthew G. Knepley + comm      - The MPI comm
1928e703855dSMatthew G. Knepley . dim       - The spatial dimension
1929e703855dSMatthew G. Knepley . Nc        - The number of components
1930e703855dSMatthew G. Knepley . isSimplex - Flag for simplex reference cell, otherwise its a tensor product
1931e703855dSMatthew G. Knepley . k         - The degree k of the space
1932e703855dSMatthew G. Knepley - qorder    - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree
1933e703855dSMatthew G. Knepley 
1934e703855dSMatthew G. Knepley   Output Parameter:
1935e703855dSMatthew G. Knepley . fem       - The PetscFE object
1936e703855dSMatthew G. Knepley 
1937e703855dSMatthew G. Knepley   Level: beginner
1938e703855dSMatthew G. Knepley 
1939e703855dSMatthew G. Knepley   Notes:
1940e703855dSMatthew G. Knepley   For simplices, this element is the space of maximum polynomial degree k, otherwise it is a tensor product of 1D polynomials, each with maximal degree k.
1941e703855dSMatthew G. Knepley 
1942e703855dSMatthew G. Knepley .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
1943e703855dSMatthew G. Knepley @*/
1944e703855dSMatthew G. Knepley PetscErrorCode PetscFECreateLagrange(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, PetscInt k, PetscInt qorder, PetscFE *fem)
1945e703855dSMatthew G. Knepley {
1946e703855dSMatthew G. Knepley   PetscQuadrature q, fq;
1947e703855dSMatthew G. Knepley   DM              K;
1948e703855dSMatthew G. Knepley   PetscSpace      P;
1949e703855dSMatthew G. Knepley   PetscDualSpace  Q;
1950e703855dSMatthew G. Knepley   PetscInt        quadPointsPerEdge;
1951e703855dSMatthew G. Knepley   PetscBool       tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1952e703855dSMatthew G. Knepley   char            name[64];
1953e703855dSMatthew G. Knepley   PetscErrorCode  ierr;
1954e703855dSMatthew G. Knepley 
1955e703855dSMatthew G. Knepley   PetscFunctionBegin;
1956e703855dSMatthew G. Knepley   /* Create space */
1957e703855dSMatthew G. Knepley   ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr);
1958e703855dSMatthew G. Knepley   ierr = PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr);
1959e703855dSMatthew G. Knepley   ierr = PetscSpacePolynomialSetTensor(P, tensor);CHKERRQ(ierr);
1960e703855dSMatthew G. Knepley   ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr);
1961e703855dSMatthew G. Knepley   ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr);
1962e703855dSMatthew G. Knepley   ierr = PetscSpaceSetDegree(P, k, PETSC_DETERMINE);CHKERRQ(ierr);
1963e703855dSMatthew G. Knepley   ierr = PetscSpaceSetUp(P);CHKERRQ(ierr);
1964e703855dSMatthew G. Knepley   /* Create dual space */
1965e703855dSMatthew G. Knepley   ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr);
1966e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
1967e703855dSMatthew G. Knepley   ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr);
1968e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr);
1969e703855dSMatthew G. Knepley   ierr = DMDestroy(&K);CHKERRQ(ierr);
1970e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr);
1971e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetOrder(Q, k);CHKERRQ(ierr);
1972e703855dSMatthew G. Knepley   ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor);CHKERRQ(ierr);
1973e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr);
1974849618d6SLisandro Dalcin   /* Create finite element */
1975e703855dSMatthew G. Knepley   ierr = PetscFECreate(comm, fem);CHKERRQ(ierr);
197635e85c11SLisandro Dalcin   ierr = PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);CHKERRQ(ierr);
197735e85c11SLisandro Dalcin   ierr = PetscObjectSetName((PetscObject) *fem, name);CHKERRQ(ierr);
1978e703855dSMatthew G. Knepley   ierr = PetscFESetType(*fem, PETSCFEBASIC);CHKERRQ(ierr);
1979e703855dSMatthew G. Knepley   ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr);
1980e703855dSMatthew G. Knepley   ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr);
1981e703855dSMatthew G. Knepley   ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr);
1982e703855dSMatthew G. Knepley   ierr = PetscFESetUp(*fem);CHKERRQ(ierr);
1983e703855dSMatthew G. Knepley   ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr);
1984e703855dSMatthew G. Knepley   ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr);
1985e703855dSMatthew G. Knepley   /* Create quadrature (with specified order if given) */
1986e703855dSMatthew G. Knepley   qorder = qorder >= 0 ? qorder : k;
1987e703855dSMatthew G. Knepley   quadPointsPerEdge = PetscMax(qorder + 1,1);
1988e703855dSMatthew G. Knepley   if (isSimplex) {
1989e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
1990e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
1991e703855dSMatthew G. Knepley   } else {
1992e703855dSMatthew G. Knepley     ierr = PetscDTGaussTensorQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
1993e703855dSMatthew G. Knepley     ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
1994e703855dSMatthew G. Knepley   }
1995e703855dSMatthew G. Knepley   ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr);
1996e703855dSMatthew G. Knepley   ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr);
1997e703855dSMatthew G. Knepley   ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr);
1998e703855dSMatthew G. Knepley   ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr);
1999849618d6SLisandro Dalcin   /* Set finite element name */
2000849618d6SLisandro Dalcin   ierr = PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);CHKERRQ(ierr);
2001849618d6SLisandro Dalcin   ierr = PetscFESetName(*fem, name);CHKERRQ(ierr);
2002e703855dSMatthew G. Knepley   PetscFunctionReturn(0);
2003e703855dSMatthew G. Knepley }
2004e703855dSMatthew G. Knepley 
20053f6b16c7SMatthew G. Knepley /*@C
20063f6b16c7SMatthew G. Knepley   PetscFESetName - Names the FE and its subobjects
20073f6b16c7SMatthew G. Knepley 
20083f6b16c7SMatthew G. Knepley   Not collective
20093f6b16c7SMatthew G. Knepley 
20103f6b16c7SMatthew G. Knepley   Input Parameters:
20113f6b16c7SMatthew G. Knepley + fe   - The PetscFE
20123f6b16c7SMatthew G. Knepley - name - The name
20133f6b16c7SMatthew G. Knepley 
20142b99622eSMatthew G. Knepley   Level: intermediate
20153f6b16c7SMatthew G. Knepley 
20163f6b16c7SMatthew G. Knepley .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
20173f6b16c7SMatthew G. Knepley @*/
20183f6b16c7SMatthew G. Knepley PetscErrorCode PetscFESetName(PetscFE fe, const char name[])
20193f6b16c7SMatthew G. Knepley {
20203f6b16c7SMatthew G. Knepley   PetscSpace     P;
20213f6b16c7SMatthew G. Knepley   PetscDualSpace Q;
20223f6b16c7SMatthew G. Knepley   PetscErrorCode ierr;
20233f6b16c7SMatthew G. Knepley 
20243f6b16c7SMatthew G. Knepley   PetscFunctionBegin;
20253f6b16c7SMatthew G. Knepley   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
20263f6b16c7SMatthew G. Knepley   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
20273f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) fe, name);CHKERRQ(ierr);
20283f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) P,  name);CHKERRQ(ierr);
20293f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) Q,  name);CHKERRQ(ierr);
20303f6b16c7SMatthew G. Knepley   PetscFunctionReturn(0);
20313f6b16c7SMatthew G. Knepley }
2032a8f1f9e5SMatthew G. Knepley 
2033ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEEvaluateFieldJets_Internal(PetscDS ds, PetscInt Nf, PetscInt r, PetscInt q, PetscTabulation T[], PetscFEGeom *fegeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscScalar u[], PetscScalar u_x[], PetscScalar u_t[])
2034a8f1f9e5SMatthew G. Knepley {
2035f9244615SMatthew G. Knepley   PetscInt       dOffset = 0, fOffset = 0, f, g;
2036a8f1f9e5SMatthew G. Knepley   PetscErrorCode ierr;
2037a8f1f9e5SMatthew G. Knepley 
2038a8f1f9e5SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
2039a8f1f9e5SMatthew G. Knepley     PetscFE          fe;
2040f9244615SMatthew G. Knepley     const PetscInt   k    = ds->jetDegree[f];
2041ef0bb6c7SMatthew G. Knepley     const PetscInt   cdim = T[f]->cdim;
2042ef0bb6c7SMatthew G. Knepley     const PetscInt   Nq   = T[f]->Np;
2043ef0bb6c7SMatthew G. Knepley     const PetscInt   Nbf  = T[f]->Nb;
2044ef0bb6c7SMatthew G. Knepley     const PetscInt   Ncf  = T[f]->Nc;
2045ef0bb6c7SMatthew G. Knepley     const PetscReal *Bq   = &T[f]->T[0][(r*Nq+q)*Nbf*Ncf];
2046ef0bb6c7SMatthew G. Knepley     const PetscReal *Dq   = &T[f]->T[1][(r*Nq+q)*Nbf*Ncf*cdim];
2047f9244615SMatthew G. Knepley     const PetscReal *Hq   = k > 1 ? &T[f]->T[2][(r*Nq+q)*Nbf*Ncf*cdim*cdim] : NULL;
2048f9244615SMatthew G. Knepley     PetscInt         hOffset = 0, b, c, d;
2049a8f1f9e5SMatthew G. Knepley 
2050a8f1f9e5SMatthew G. Knepley     ierr = PetscDSGetDiscretization(ds, f, (PetscObject *) &fe);CHKERRQ(ierr);
2051a8f1f9e5SMatthew G. Knepley     for (c = 0; c < Ncf; ++c) u[fOffset+c] = 0.0;
2052ef0bb6c7SMatthew G. Knepley     for (d = 0; d < cdim*Ncf; ++d) u_x[fOffset*cdim+d] = 0.0;
2053a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nbf; ++b) {
2054a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) {
2055a8f1f9e5SMatthew G. Knepley         const PetscInt cidx = b*Ncf+c;
2056a8f1f9e5SMatthew G. Knepley 
2057a8f1f9e5SMatthew G. Knepley         u[fOffset+c] += Bq[cidx]*coefficients[dOffset+b];
2058ef0bb6c7SMatthew G. Knepley         for (d = 0; d < cdim; ++d) u_x[(fOffset+c)*cdim+d] += Dq[cidx*cdim+d]*coefficients[dOffset+b];
2059a8f1f9e5SMatthew G. Knepley       }
2060a8f1f9e5SMatthew G. Knepley     }
2061f9244615SMatthew G. Knepley     if (k > 1) {
2062f9244615SMatthew G. Knepley       for (g = 0; g < Nf; ++g) hOffset += T[g]->Nc*cdim;
2063f9244615SMatthew G. Knepley       for (d = 0; d < cdim*cdim*Ncf; ++d) u_x[hOffset+fOffset*cdim*cdim+d] = 0.0;
2064f9244615SMatthew G. Knepley       for (b = 0; b < Nbf; ++b) {
2065f9244615SMatthew G. Knepley         for (c = 0; c < Ncf; ++c) {
2066f9244615SMatthew G. Knepley           const PetscInt cidx = b*Ncf+c;
2067f9244615SMatthew G. Knepley 
2068f9244615SMatthew G. Knepley           for (d = 0; d < cdim*cdim; ++d) u_x[hOffset+(fOffset+c)*cdim*cdim+d] += Hq[cidx*cdim*cdim+d]*coefficients[dOffset+b];
2069f9244615SMatthew G. Knepley         }
2070f9244615SMatthew G. Knepley       }
2071f9244615SMatthew G. Knepley       ierr = PetscFEPushforwardHessian(fe, fegeom, 1, &u_x[hOffset+fOffset*cdim*cdim]);CHKERRQ(ierr);
2072f9244615SMatthew G. Knepley     }
20732edcad52SToby Isaac     ierr = PetscFEPushforward(fe, fegeom, 1, &u[fOffset]);CHKERRQ(ierr);
20742edcad52SToby Isaac     ierr = PetscFEPushforwardGradient(fe, fegeom, 1, &u_x[fOffset*cdim]);CHKERRQ(ierr);
2075a8f1f9e5SMatthew G. Knepley     if (u_t) {
2076a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) u_t[fOffset+c] = 0.0;
2077a8f1f9e5SMatthew G. Knepley       for (b = 0; b < Nbf; ++b) {
2078a8f1f9e5SMatthew G. Knepley         for (c = 0; c < Ncf; ++c) {
2079a8f1f9e5SMatthew G. Knepley           const PetscInt cidx = b*Ncf+c;
2080a8f1f9e5SMatthew G. Knepley 
2081a8f1f9e5SMatthew G. Knepley           u_t[fOffset+c] += Bq[cidx]*coefficients_t[dOffset+b];
2082a8f1f9e5SMatthew G. Knepley         }
2083a8f1f9e5SMatthew G. Knepley       }
20842edcad52SToby Isaac       ierr = PetscFEPushforward(fe, fegeom, 1, &u_t[fOffset]);CHKERRQ(ierr);
2085a8f1f9e5SMatthew G. Knepley     }
2086a8f1f9e5SMatthew G. Knepley     fOffset += Ncf;
2087a8f1f9e5SMatthew G. Knepley     dOffset += Nbf;
2088a8f1f9e5SMatthew G. Knepley   }
2089a8f1f9e5SMatthew G. Knepley   return 0;
2090a8f1f9e5SMatthew G. Knepley }
2091a8f1f9e5SMatthew G. Knepley 
2092665f567fSMatthew G. Knepley PetscErrorCode PetscFEEvaluateFieldJets_Hybrid_Internal(PetscDS ds, PetscInt Nf, PetscInt r, PetscInt q, PetscTabulation T[], PetscFEGeom *fegeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscScalar u[], PetscScalar u_x[], PetscScalar u_t[])
209327f02ce8SMatthew G. Knepley {
2094*5fedec97SMatthew G. Knepley   PetscInt       dOffset = 0, fOffset = 0, f, g;
209527f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
209627f02ce8SMatthew G. Knepley 
2097*5fedec97SMatthew G. Knepley   /* f is the field number in the DS, g is the field number in u[] */
2098*5fedec97SMatthew G. Knepley   for (f = 0, g = 0; f < Nf; ++f) {
2099*5fedec97SMatthew G. Knepley     PetscFE          fe   = (PetscFE) ds->disc[f];
2100665f567fSMatthew G. Knepley     const PetscInt   cdim = T[f]->cdim;
2101665f567fSMatthew G. Knepley     const PetscInt   Nq   = T[f]->Np;
2102665f567fSMatthew G. Knepley     const PetscInt   Nbf  = T[f]->Nb;
2103665f567fSMatthew G. Knepley     const PetscInt   Ncf  = T[f]->Nc;
2104665f567fSMatthew G. Knepley     const PetscReal *Bq   = &T[f]->T[0][(r*Nq+q)*Nbf*Ncf];
2105665f567fSMatthew G. Knepley     const PetscReal *Dq   = &T[f]->T[1][(r*Nq+q)*Nbf*Ncf*cdim];
2106*5fedec97SMatthew G. Knepley     PetscBool        isCohesive;
2107*5fedec97SMatthew G. Knepley     PetscInt         Ns, s;
2108*5fedec97SMatthew G. Knepley 
2109*5fedec97SMatthew G. Knepley     if (!T[f]) continue;
2110*5fedec97SMatthew G. Knepley     ierr = PetscDSGetCohesive(ds, f, &isCohesive);CHKERRQ(ierr);
2111*5fedec97SMatthew G. Knepley     Ns   = isCohesive ? 1 : 2;
2112*5fedec97SMatthew G. Knepley     for (s = 0; s < Ns; ++s, ++g) {
211327f02ce8SMatthew G. Knepley       PetscInt b, c, d;
211427f02ce8SMatthew G. Knepley 
211527f02ce8SMatthew G. Knepley       for (c = 0; c < Ncf; ++c)      u[fOffset+c] = 0.0;
2116665f567fSMatthew G. Knepley       for (d = 0; d < cdim*Ncf; ++d) u_x[fOffset*cdim+d] = 0.0;
211727f02ce8SMatthew G. Knepley       for (b = 0; b < Nbf; ++b) {
211827f02ce8SMatthew G. Knepley         for (c = 0; c < Ncf; ++c) {
211927f02ce8SMatthew G. Knepley           const PetscInt cidx = b*Ncf+c;
212027f02ce8SMatthew G. Knepley 
212127f02ce8SMatthew G. Knepley           u[fOffset+c] += Bq[cidx]*coefficients[dOffset+b];
2122665f567fSMatthew G. Knepley           for (d = 0; d < cdim; ++d) u_x[(fOffset+c)*cdim+d] += Dq[cidx*cdim+d]*coefficients[dOffset+b];
212327f02ce8SMatthew G. Knepley         }
212427f02ce8SMatthew G. Knepley       }
212527f02ce8SMatthew G. Knepley       ierr = PetscFEPushforward(fe, fegeom, 1, &u[fOffset]);CHKERRQ(ierr);
2126665f567fSMatthew G. Knepley       ierr = PetscFEPushforwardGradient(fe, fegeom, 1, &u_x[fOffset*cdim]);CHKERRQ(ierr);
212727f02ce8SMatthew G. Knepley       if (u_t) {
212827f02ce8SMatthew G. Knepley         for (c = 0; c < Ncf; ++c) u_t[fOffset+c] = 0.0;
212927f02ce8SMatthew G. Knepley         for (b = 0; b < Nbf; ++b) {
213027f02ce8SMatthew G. Knepley           for (c = 0; c < Ncf; ++c) {
213127f02ce8SMatthew G. Knepley             const PetscInt cidx = b*Ncf+c;
213227f02ce8SMatthew G. Knepley 
213327f02ce8SMatthew G. Knepley             u_t[fOffset+c] += Bq[cidx]*coefficients_t[dOffset+b];
213427f02ce8SMatthew G. Knepley           }
213527f02ce8SMatthew G. Knepley         }
213627f02ce8SMatthew G. Knepley         ierr = PetscFEPushforward(fe, fegeom, 1, &u_t[fOffset]);CHKERRQ(ierr);
213727f02ce8SMatthew G. Knepley       }
213827f02ce8SMatthew G. Knepley       fOffset += Ncf;
213927f02ce8SMatthew G. Knepley       dOffset += Nbf;
214027f02ce8SMatthew G. Knepley     }
2141665f567fSMatthew G. Knepley   }
214227f02ce8SMatthew G. Knepley   return 0;
214327f02ce8SMatthew G. Knepley }
214427f02ce8SMatthew G. Knepley 
2145a8f1f9e5SMatthew G. Knepley PetscErrorCode PetscFEEvaluateFaceFields_Internal(PetscDS prob, PetscInt field, PetscInt faceLoc, const PetscScalar coefficients[], PetscScalar u[])
2146a8f1f9e5SMatthew G. Knepley {
2147a8f1f9e5SMatthew G. Knepley   PetscFE         fe;
2148ef0bb6c7SMatthew G. Knepley   PetscTabulation Tc;
2149ef0bb6c7SMatthew G. Knepley   PetscInt        b, c;
2150a8f1f9e5SMatthew G. Knepley   PetscErrorCode  ierr;
2151a8f1f9e5SMatthew G. Knepley 
2152a8f1f9e5SMatthew G. Knepley   if (!prob) return 0;
2153a8f1f9e5SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
2154ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetFaceCentroidTabulation(fe, &Tc);CHKERRQ(ierr);
2155ef0bb6c7SMatthew G. Knepley   {
2156ef0bb6c7SMatthew G. Knepley     const PetscReal *faceBasis = Tc->T[0];
2157ef0bb6c7SMatthew G. Knepley     const PetscInt   Nb        = Tc->Nb;
2158ef0bb6c7SMatthew G. Knepley     const PetscInt   Nc        = Tc->Nc;
2159ef0bb6c7SMatthew G. Knepley 
2160a8f1f9e5SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {u[c] = 0.0;}
2161a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
2162a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
2163813a933aSJed Brown         u[c] += coefficients[b] * faceBasis[(faceLoc*Nb + b)*Nc + c];
2164a8f1f9e5SMatthew G. Knepley       }
2165a8f1f9e5SMatthew G. Knepley     }
2166ef0bb6c7SMatthew G. Knepley   }
2167a8f1f9e5SMatthew G. Knepley   return 0;
2168a8f1f9e5SMatthew G. Knepley }
2169a8f1f9e5SMatthew G. Knepley 
21706587ee25SMatthew G. Knepley PetscErrorCode PetscFEUpdateElementVec_Internal(PetscFE fe, PetscTabulation T, PetscInt r, PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscInt e, PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[])
2171a8f1f9e5SMatthew G. Knepley {
21726587ee25SMatthew G. Knepley   PetscFEGeom      pgeom;
2173bc3a64adSMatthew G. Knepley   const PetscInt   dEt      = T->cdim;
2174bc3a64adSMatthew G. Knepley   const PetscInt   dE       = fegeom->dimEmbed;
2175ef0bb6c7SMatthew G. Knepley   const PetscInt   Nq       = T->Np;
2176ef0bb6c7SMatthew G. Knepley   const PetscInt   Nb       = T->Nb;
2177ef0bb6c7SMatthew G. Knepley   const PetscInt   Nc       = T->Nc;
2178ef0bb6c7SMatthew G. Knepley   const PetscReal *basis    = &T->T[0][r*Nq*Nb*Nc];
2179bc3a64adSMatthew G. Knepley   const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dEt];
2180a8f1f9e5SMatthew G. Knepley   PetscInt         q, b, c, d;
2181a8f1f9e5SMatthew G. Knepley   PetscErrorCode   ierr;
2182a8f1f9e5SMatthew G. Knepley 
2183a8f1f9e5SMatthew G. Knepley   for (b = 0; b < Nb; ++b) elemVec[b] = 0.0;
2184a8f1f9e5SMatthew G. Knepley   for (q = 0; q < Nq; ++q) {
2185a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
2186a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
2187a8f1f9e5SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
2188a8f1f9e5SMatthew G. Knepley 
2189a8f1f9e5SMatthew G. Knepley         tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx];
2190bc3a64adSMatthew G. Knepley         for (d = 0; d < dEt; ++d) tmpBasisDer[bcidx*dE+d] = basisDer[q*Nb*Nc*dEt+bcidx*dEt+d];
2191a8f1f9e5SMatthew G. Knepley       }
2192a8f1f9e5SMatthew G. Knepley     }
21936587ee25SMatthew G. Knepley     ierr = PetscFEGeomGetCellPoint(fegeom, e, q, &pgeom);CHKERRQ(ierr);
21946587ee25SMatthew G. Knepley     ierr = PetscFEPushforward(fe, &pgeom, Nb, tmpBasis);CHKERRQ(ierr);
21956587ee25SMatthew G. Knepley     ierr = PetscFEPushforwardGradient(fe, &pgeom, Nb, tmpBasisDer);CHKERRQ(ierr);
2196a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
2197a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
2198a8f1f9e5SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
2199a8f1f9e5SMatthew G. Knepley         const PetscInt qcidx = q*Nc+c;
2200a8f1f9e5SMatthew G. Knepley 
2201a8f1f9e5SMatthew G. Knepley         elemVec[b] += tmpBasis[bcidx]*f0[qcidx];
220227f02ce8SMatthew G. Knepley         for (d = 0; d < dE; ++d) elemVec[b] += tmpBasisDer[bcidx*dE+d]*f1[qcidx*dE+d];
220327f02ce8SMatthew G. Knepley       }
220427f02ce8SMatthew G. Knepley     }
220527f02ce8SMatthew G. Knepley   }
220627f02ce8SMatthew G. Knepley   return(0);
220727f02ce8SMatthew G. Knepley }
220827f02ce8SMatthew G. Knepley 
2209c2b7495fSMatthew G. Knepley PetscErrorCode PetscFEUpdateElementVec_Hybrid_Internal(PetscFE fe, PetscTabulation T, PetscInt r, PetscInt s, PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[])
221027f02ce8SMatthew G. Knepley {
221127f02ce8SMatthew G. Knepley   const PetscInt   dE       = T->cdim;
221227f02ce8SMatthew G. Knepley   const PetscInt   Nq       = T->Np;
221327f02ce8SMatthew G. Knepley   const PetscInt   Nb       = T->Nb;
221427f02ce8SMatthew G. Knepley   const PetscInt   Nc       = T->Nc;
221527f02ce8SMatthew G. Knepley   const PetscReal *basis    = &T->T[0][r*Nq*Nb*Nc];
221627f02ce8SMatthew G. Knepley   const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dE];
2217c2b7495fSMatthew G. Knepley   PetscInt         q, b, c, d;
221827f02ce8SMatthew G. Knepley   PetscErrorCode   ierr;
221927f02ce8SMatthew G. Knepley 
2220c2b7495fSMatthew G. Knepley   for (b = 0; b < Nb; ++b) elemVec[Nb*s+b] = 0.0;
222127f02ce8SMatthew G. Knepley   for (q = 0; q < Nq; ++q) {
222227f02ce8SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
222327f02ce8SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
222427f02ce8SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
222527f02ce8SMatthew G. Knepley 
222627f02ce8SMatthew G. Knepley         tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx];
222727f02ce8SMatthew G. Knepley         for (d = 0; d < dE; ++d) tmpBasisDer[bcidx*dE+d] = basisDer[q*Nb*Nc*dE+bcidx*dE+d];
222827f02ce8SMatthew G. Knepley       }
222927f02ce8SMatthew G. Knepley     }
223027f02ce8SMatthew G. Knepley     ierr = PetscFEPushforward(fe, fegeom, Nb, tmpBasis);CHKERRQ(ierr);
223127f02ce8SMatthew G. Knepley     ierr = PetscFEPushforwardGradient(fe, fegeom, Nb, tmpBasisDer);CHKERRQ(ierr);
223227f02ce8SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
223327f02ce8SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
223427f02ce8SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
2235c2b7495fSMatthew G. Knepley         const PetscInt qcidx = q*Nc+c;
223627f02ce8SMatthew G. Knepley 
223727f02ce8SMatthew G. Knepley         elemVec[Nb*s+b] += tmpBasis[bcidx]*f0[qcidx];
223827f02ce8SMatthew G. Knepley         for (d = 0; d < dE; ++d) elemVec[Nb*s+b] += tmpBasisDer[bcidx*dE+d]*f1[qcidx*dE+d];
223927f02ce8SMatthew G. Knepley       }
2240a8f1f9e5SMatthew G. Knepley     }
2241a8f1f9e5SMatthew G. Knepley   }
2242a8f1f9e5SMatthew G. Knepley   return(0);
2243a8f1f9e5SMatthew G. Knepley }
2244a8f1f9e5SMatthew G. Knepley 
2245ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEUpdateElementMat_Internal(PetscFE feI, PetscFE feJ, PetscInt r, PetscInt q, PetscTabulation TI, PetscScalar tmpBasisI[], PetscScalar tmpBasisDerI[], PetscTabulation TJ, PetscScalar tmpBasisJ[], PetscScalar tmpBasisDerJ[], PetscFEGeom *fegeom, const PetscScalar g0[], const PetscScalar g1[], const PetscScalar g2[], const PetscScalar g3[], PetscInt eOffset, PetscInt totDim, PetscInt offsetI, PetscInt offsetJ, PetscScalar elemMat[])
2246a8f1f9e5SMatthew G. Knepley {
224727f02ce8SMatthew G. Knepley   const PetscInt   dE        = TI->cdim;
2248ef0bb6c7SMatthew G. Knepley   const PetscInt   NqI       = TI->Np;
2249ef0bb6c7SMatthew G. Knepley   const PetscInt   NbI       = TI->Nb;
2250ef0bb6c7SMatthew G. Knepley   const PetscInt   NcI       = TI->Nc;
2251ef0bb6c7SMatthew G. Knepley   const PetscReal *basisI    = &TI->T[0][(r*NqI+q)*NbI*NcI];
2252665f567fSMatthew G. Knepley   const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dE];
2253ef0bb6c7SMatthew G. Knepley   const PetscInt   NqJ       = TJ->Np;
2254ef0bb6c7SMatthew G. Knepley   const PetscInt   NbJ       = TJ->Nb;
2255ef0bb6c7SMatthew G. Knepley   const PetscInt   NcJ       = TJ->Nc;
2256ef0bb6c7SMatthew G. Knepley   const PetscReal *basisJ    = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ];
2257665f567fSMatthew G. Knepley   const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dE];
2258a8f1f9e5SMatthew G. Knepley   PetscInt         f, fc, g, gc, df, dg;
2259a8f1f9e5SMatthew G. Knepley   PetscErrorCode   ierr;
2260a8f1f9e5SMatthew G. Knepley 
2261a8f1f9e5SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
2262a8f1f9e5SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
2263a8f1f9e5SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
2264a8f1f9e5SMatthew G. Knepley 
2265a8f1f9e5SMatthew G. Knepley       tmpBasisI[fidx] = basisI[fidx];
226627f02ce8SMatthew G. Knepley       for (df = 0; df < dE; ++df) tmpBasisDerI[fidx*dE+df] = basisDerI[fidx*dE+df];
2267a8f1f9e5SMatthew G. Knepley     }
2268a8f1f9e5SMatthew G. Knepley   }
22692edcad52SToby Isaac   ierr = PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);CHKERRQ(ierr);
22702edcad52SToby Isaac   ierr = PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);CHKERRQ(ierr);
2271a8f1f9e5SMatthew G. Knepley   for (g = 0; g < NbJ; ++g) {
2272a8f1f9e5SMatthew G. Knepley     for (gc = 0; gc < NcJ; ++gc) {
2273a8f1f9e5SMatthew G. Knepley       const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
2274a8f1f9e5SMatthew G. Knepley 
2275a8f1f9e5SMatthew G. Knepley       tmpBasisJ[gidx] = basisJ[gidx];
227627f02ce8SMatthew G. Knepley       for (dg = 0; dg < dE; ++dg) tmpBasisDerJ[gidx*dE+dg] = basisDerJ[gidx*dE+dg];
2277a8f1f9e5SMatthew G. Knepley     }
2278a8f1f9e5SMatthew G. Knepley   }
22792edcad52SToby Isaac   ierr = PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);CHKERRQ(ierr);
22802edcad52SToby Isaac   ierr = PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);CHKERRQ(ierr);
2281a8f1f9e5SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
2282a8f1f9e5SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
2283a8f1f9e5SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
2284a8f1f9e5SMatthew G. Knepley       const PetscInt i    = offsetI+f; /* Element matrix row */
2285a8f1f9e5SMatthew G. Knepley       for (g = 0; g < NbJ; ++g) {
2286a8f1f9e5SMatthew G. Knepley         for (gc = 0; gc < NcJ; ++gc) {
2287a8f1f9e5SMatthew G. Knepley           const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
2288a8f1f9e5SMatthew G. Knepley           const PetscInt j    = offsetJ+g; /* Element matrix column */
2289a8f1f9e5SMatthew G. Knepley           const PetscInt fOff = eOffset+i*totDim+j;
2290a8f1f9e5SMatthew G. Knepley 
2291a8f1f9e5SMatthew G. Knepley           elemMat[fOff] += tmpBasisI[fidx]*g0[fc*NcJ+gc]*tmpBasisJ[gidx];
229227f02ce8SMatthew G. Knepley           for (df = 0; df < dE; ++df) {
229327f02ce8SMatthew G. Knepley             elemMat[fOff] += tmpBasisI[fidx]*g1[(fc*NcJ+gc)*dE+df]*tmpBasisDerJ[gidx*dE+df];
229427f02ce8SMatthew G. Knepley             elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g2[(fc*NcJ+gc)*dE+df]*tmpBasisJ[gidx];
229527f02ce8SMatthew G. Knepley             for (dg = 0; dg < dE; ++dg) {
229627f02ce8SMatthew G. Knepley               elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g3[((fc*NcJ+gc)*dE+df)*dE+dg]*tmpBasisDerJ[gidx*dE+dg];
229727f02ce8SMatthew G. Knepley             }
229827f02ce8SMatthew G. Knepley           }
229927f02ce8SMatthew G. Knepley         }
230027f02ce8SMatthew G. Knepley       }
230127f02ce8SMatthew G. Knepley     }
230227f02ce8SMatthew G. Knepley   }
230327f02ce8SMatthew G. Knepley   return(0);
230427f02ce8SMatthew G. Knepley }
230527f02ce8SMatthew G. Knepley 
2306*5fedec97SMatthew G. Knepley PetscErrorCode PetscFEUpdateElementMat_Hybrid_Internal(PetscFE feI, PetscBool isHybridI, PetscFE feJ, PetscBool isHybridJ, PetscInt r, PetscInt s, PetscInt q, PetscTabulation TI, PetscScalar tmpBasisI[], PetscScalar tmpBasisDerI[], PetscTabulation TJ, PetscScalar tmpBasisJ[], PetscScalar tmpBasisDerJ[], PetscFEGeom *fegeom, const PetscScalar g0[], const PetscScalar g1[], const PetscScalar g2[], const PetscScalar g3[], PetscInt eOffset, PetscInt totDim, PetscInt offsetI, PetscInt offsetJ, PetscScalar elemMat[])
230727f02ce8SMatthew G. Knepley {
2308665f567fSMatthew G. Knepley   const PetscInt   dE        = TI->cdim;
2309665f567fSMatthew G. Knepley   const PetscInt   NqI       = TI->Np;
2310665f567fSMatthew G. Knepley   const PetscInt   NbI       = TI->Nb;
2311665f567fSMatthew G. Knepley   const PetscInt   NcI       = TI->Nc;
2312665f567fSMatthew G. Knepley   const PetscReal *basisI    = &TI->T[0][(r*NqI+q)*NbI*NcI];
2313665f567fSMatthew G. Knepley   const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dE];
2314665f567fSMatthew G. Knepley   const PetscInt   NqJ       = TJ->Np;
2315665f567fSMatthew G. Knepley   const PetscInt   NbJ       = TJ->Nb;
2316665f567fSMatthew G. Knepley   const PetscInt   NcJ       = TJ->Nc;
2317665f567fSMatthew G. Knepley   const PetscReal *basisJ    = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ];
2318665f567fSMatthew G. Knepley   const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dE];
2319*5fedec97SMatthew G. Knepley   const PetscInt   so        = isHybridI ? 0 : s;
2320*5fedec97SMatthew G. Knepley   const PetscInt   to        = isHybridJ ? 0 : s;
2321*5fedec97SMatthew G. Knepley   PetscInt         f, fc, g, gc, df, dg;
232227f02ce8SMatthew G. Knepley   PetscErrorCode   ierr;
232327f02ce8SMatthew G. Knepley 
232427f02ce8SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
232527f02ce8SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
232627f02ce8SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
232727f02ce8SMatthew G. Knepley 
232827f02ce8SMatthew G. Knepley       tmpBasisI[fidx] = basisI[fidx];
2329665f567fSMatthew G. Knepley       for (df = 0; df < dE; ++df) tmpBasisDerI[fidx*dE+df] = basisDerI[fidx*dE+df];
233027f02ce8SMatthew G. Knepley     }
233127f02ce8SMatthew G. Knepley   }
233227f02ce8SMatthew G. Knepley   ierr = PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);CHKERRQ(ierr);
233327f02ce8SMatthew G. Knepley   ierr = PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);CHKERRQ(ierr);
233427f02ce8SMatthew G. Knepley   for (g = 0; g < NbJ; ++g) {
233527f02ce8SMatthew G. Knepley     for (gc = 0; gc < NcJ; ++gc) {
233627f02ce8SMatthew G. Knepley       const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
233727f02ce8SMatthew G. Knepley 
233827f02ce8SMatthew G. Knepley       tmpBasisJ[gidx] = basisJ[gidx];
2339665f567fSMatthew G. Knepley       for (dg = 0; dg < dE; ++dg) tmpBasisDerJ[gidx*dE+dg] = basisDerJ[gidx*dE+dg];
234027f02ce8SMatthew G. Knepley     }
234127f02ce8SMatthew G. Knepley   }
234227f02ce8SMatthew G. Knepley   ierr = PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);CHKERRQ(ierr);
234327f02ce8SMatthew G. Knepley   ierr = PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);CHKERRQ(ierr);
234427f02ce8SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
234527f02ce8SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
234627f02ce8SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc;         /* Test function basis index */
2347*5fedec97SMatthew G. Knepley       const PetscInt i    = offsetI+NbI*so+f; /* Element matrix row */
234827f02ce8SMatthew G. Knepley       for (g = 0; g < NbJ; ++g) {
234927f02ce8SMatthew G. Knepley         for (gc = 0; gc < NcJ; ++gc) {
235027f02ce8SMatthew G. Knepley           const PetscInt gidx = g*NcJ+gc;         /* Trial function basis index */
2351*5fedec97SMatthew G. Knepley           const PetscInt j    = offsetJ+NbJ*to+g; /* Element matrix column */
235227f02ce8SMatthew G. Knepley           const PetscInt fOff = eOffset+i*totDim+j;
235327f02ce8SMatthew G. Knepley 
2354*5fedec97SMatthew G. Knepley           elemMat[fOff] += tmpBasisI[fidx]*g0[fc*NcJ+gc]*tmpBasisJ[gidx];
235527f02ce8SMatthew G. Knepley           for (df = 0; df < dE; ++df) {
2356*5fedec97SMatthew G. Knepley             elemMat[fOff] += tmpBasisI[fidx]*g1[(fc*NcJ+gc)*dE+df]*tmpBasisDerJ[gidx*dE+df];
2357*5fedec97SMatthew G. Knepley             elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g2[(fc*NcJ+gc)*dE+df]*tmpBasisJ[gidx];
235827f02ce8SMatthew G. Knepley             for (dg = 0; dg < dE; ++dg) {
2359*5fedec97SMatthew G. Knepley               elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g3[((fc*NcJ+gc)*dE+df)*dE+dg]*tmpBasisDerJ[gidx*dE+dg];
2360a8f1f9e5SMatthew G. Knepley             }
2361a8f1f9e5SMatthew G. Knepley           }
2362a8f1f9e5SMatthew G. Knepley         }
2363a8f1f9e5SMatthew G. Knepley       }
2364a8f1f9e5SMatthew G. Knepley     }
2365a8f1f9e5SMatthew G. Knepley   }
2366a8f1f9e5SMatthew G. Knepley   return(0);
2367a8f1f9e5SMatthew G. Knepley }
2368c9ba7969SMatthew G. Knepley 
2369c9ba7969SMatthew G. Knepley PetscErrorCode PetscFECreateCellGeometry(PetscFE fe, PetscQuadrature quad, PetscFEGeom *cgeom)
2370c9ba7969SMatthew G. Knepley {
2371c9ba7969SMatthew G. Knepley   PetscDualSpace  dsp;
2372c9ba7969SMatthew G. Knepley   DM              dm;
2373c9ba7969SMatthew G. Knepley   PetscQuadrature quadDef;
2374c9ba7969SMatthew G. Knepley   PetscInt        dim, cdim, Nq;
2375c9ba7969SMatthew G. Knepley   PetscErrorCode  ierr;
2376c9ba7969SMatthew G. Knepley 
2377c9ba7969SMatthew G. Knepley   PetscFunctionBegin;
2378c9ba7969SMatthew G. Knepley   ierr = PetscFEGetDualSpace(fe, &dsp);CHKERRQ(ierr);
2379c9ba7969SMatthew G. Knepley   ierr = PetscDualSpaceGetDM(dsp, &dm);CHKERRQ(ierr);
2380c9ba7969SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
2381c9ba7969SMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
2382c9ba7969SMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &quadDef);CHKERRQ(ierr);
2383c9ba7969SMatthew G. Knepley   quad = quad ? quad : quadDef;
2384c9ba7969SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);
2385c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq*cdim,      &cgeom->v);CHKERRQ(ierr);
2386c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq*cdim*cdim, &cgeom->J);CHKERRQ(ierr);
2387c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq*cdim*cdim, &cgeom->invJ);CHKERRQ(ierr);
2388c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq,           &cgeom->detJ);CHKERRQ(ierr);
2389c9ba7969SMatthew G. Knepley   cgeom->dim       = dim;
2390c9ba7969SMatthew G. Knepley   cgeom->dimEmbed  = cdim;
2391c9ba7969SMatthew G. Knepley   cgeom->numCells  = 1;
2392c9ba7969SMatthew G. Knepley   cgeom->numPoints = Nq;
2393c9ba7969SMatthew G. Knepley   ierr = DMPlexComputeCellGeometryFEM(dm, 0, quad, cgeom->v, cgeom->J, cgeom->invJ, cgeom->detJ);CHKERRQ(ierr);
2394c9ba7969SMatthew G. Knepley   PetscFunctionReturn(0);
2395c9ba7969SMatthew G. Knepley }
2396c9ba7969SMatthew G. Knepley 
2397c9ba7969SMatthew G. Knepley PetscErrorCode PetscFEDestroyCellGeometry(PetscFE fe, PetscFEGeom *cgeom)
2398c9ba7969SMatthew G. Knepley {
2399c9ba7969SMatthew G. Knepley   PetscErrorCode ierr;
2400c9ba7969SMatthew G. Knepley 
2401c9ba7969SMatthew G. Knepley   PetscFunctionBegin;
2402c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->v);CHKERRQ(ierr);
2403c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->J);CHKERRQ(ierr);
2404c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->invJ);CHKERRQ(ierr);
2405c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->detJ);CHKERRQ(ierr);
2406c9ba7969SMatthew G. Knepley   PetscFunctionReturn(0);
2407c9ba7969SMatthew G. Knepley }
2408