xref: /petsc/src/dm/dt/fe/interface/fe.c (revision ea78f98c112368f404cd6d4fff6d4dfe73e5a1e7)
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 
19620cf1dd8SToby Isaac   Input Parameter:
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 
316*ea78f98cSLisandro 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);
33420cf1dd8SToby Isaac 
33520cf1dd8SToby Isaac   if ((*fem)->ops->destroy) {ierr = (*(*fem)->ops->destroy)(*fem);CHKERRQ(ierr);}
33620cf1dd8SToby Isaac   ierr = PetscHeaderDestroy(fem);CHKERRQ(ierr);
33720cf1dd8SToby Isaac   PetscFunctionReturn(0);
33820cf1dd8SToby Isaac }
33920cf1dd8SToby Isaac 
34020cf1dd8SToby Isaac /*@
34120cf1dd8SToby Isaac   PetscFECreate - Creates an empty PetscFE object. The type can then be set with PetscFESetType().
34220cf1dd8SToby Isaac 
343d083f849SBarry Smith   Collective
34420cf1dd8SToby Isaac 
34520cf1dd8SToby Isaac   Input Parameter:
34620cf1dd8SToby Isaac . comm - The communicator for the PetscFE object
34720cf1dd8SToby Isaac 
34820cf1dd8SToby Isaac   Output Parameter:
34920cf1dd8SToby Isaac . fem - The PetscFE object
35020cf1dd8SToby Isaac 
35120cf1dd8SToby Isaac   Level: beginner
35220cf1dd8SToby Isaac 
35320cf1dd8SToby Isaac .seealso: PetscFESetType(), PETSCFEGALERKIN
35420cf1dd8SToby Isaac @*/
35520cf1dd8SToby Isaac PetscErrorCode PetscFECreate(MPI_Comm comm, PetscFE *fem)
35620cf1dd8SToby Isaac {
35720cf1dd8SToby Isaac   PetscFE        f;
35820cf1dd8SToby Isaac   PetscErrorCode ierr;
35920cf1dd8SToby Isaac 
36020cf1dd8SToby Isaac   PetscFunctionBegin;
36120cf1dd8SToby Isaac   PetscValidPointer(fem, 2);
36220cf1dd8SToby Isaac   ierr = PetscCitationsRegister(FECitation,&FEcite);CHKERRQ(ierr);
36320cf1dd8SToby Isaac   *fem = NULL;
36420cf1dd8SToby Isaac   ierr = PetscFEInitializePackage();CHKERRQ(ierr);
36520cf1dd8SToby Isaac 
36620cf1dd8SToby Isaac   ierr = PetscHeaderCreate(f, PETSCFE_CLASSID, "PetscFE", "Finite Element", "PetscFE", comm, PetscFEDestroy, PetscFEView);CHKERRQ(ierr);
36720cf1dd8SToby Isaac 
36820cf1dd8SToby Isaac   f->basisSpace    = NULL;
36920cf1dd8SToby Isaac   f->dualSpace     = NULL;
37020cf1dd8SToby Isaac   f->numComponents = 1;
37120cf1dd8SToby Isaac   f->subspaces     = NULL;
37220cf1dd8SToby Isaac   f->invV          = NULL;
373ef0bb6c7SMatthew G. Knepley   f->T             = NULL;
374ef0bb6c7SMatthew G. Knepley   f->Tf            = NULL;
375ef0bb6c7SMatthew G. Knepley   f->Tc            = NULL;
376580bdb30SBarry Smith   ierr = PetscArrayzero(&f->quadrature, 1);CHKERRQ(ierr);
377580bdb30SBarry Smith   ierr = PetscArrayzero(&f->faceQuadrature, 1);CHKERRQ(ierr);
37820cf1dd8SToby Isaac   f->blockSize     = 0;
37920cf1dd8SToby Isaac   f->numBlocks     = 1;
38020cf1dd8SToby Isaac   f->batchSize     = 0;
38120cf1dd8SToby Isaac   f->numBatches    = 1;
38220cf1dd8SToby Isaac 
38320cf1dd8SToby Isaac   *fem = f;
38420cf1dd8SToby Isaac   PetscFunctionReturn(0);
38520cf1dd8SToby Isaac }
38620cf1dd8SToby Isaac 
38720cf1dd8SToby Isaac /*@
38820cf1dd8SToby Isaac   PetscFEGetSpatialDimension - Returns the spatial dimension of the element
38920cf1dd8SToby Isaac 
39020cf1dd8SToby Isaac   Not collective
39120cf1dd8SToby Isaac 
39220cf1dd8SToby Isaac   Input Parameter:
39320cf1dd8SToby Isaac . fem - The PetscFE object
39420cf1dd8SToby Isaac 
39520cf1dd8SToby Isaac   Output Parameter:
39620cf1dd8SToby Isaac . dim - The spatial dimension
39720cf1dd8SToby Isaac 
39820cf1dd8SToby Isaac   Level: intermediate
39920cf1dd8SToby Isaac 
40020cf1dd8SToby Isaac .seealso: PetscFECreate()
40120cf1dd8SToby Isaac @*/
40220cf1dd8SToby Isaac PetscErrorCode PetscFEGetSpatialDimension(PetscFE fem, PetscInt *dim)
40320cf1dd8SToby Isaac {
40420cf1dd8SToby Isaac   DM             dm;
40520cf1dd8SToby Isaac   PetscErrorCode ierr;
40620cf1dd8SToby Isaac 
40720cf1dd8SToby Isaac   PetscFunctionBegin;
40820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
40920cf1dd8SToby Isaac   PetscValidPointer(dim, 2);
41020cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr);
41120cf1dd8SToby Isaac   ierr = DMGetDimension(dm, dim);CHKERRQ(ierr);
41220cf1dd8SToby Isaac   PetscFunctionReturn(0);
41320cf1dd8SToby Isaac }
41420cf1dd8SToby Isaac 
41520cf1dd8SToby Isaac /*@
41620cf1dd8SToby Isaac   PetscFESetNumComponents - Sets the number of components in the element
41720cf1dd8SToby Isaac 
41820cf1dd8SToby Isaac   Not collective
41920cf1dd8SToby Isaac 
42020cf1dd8SToby Isaac   Input Parameters:
42120cf1dd8SToby Isaac + fem - The PetscFE object
42220cf1dd8SToby Isaac - comp - The number of field components
42320cf1dd8SToby Isaac 
42420cf1dd8SToby Isaac   Level: intermediate
42520cf1dd8SToby Isaac 
42620cf1dd8SToby Isaac .seealso: PetscFECreate()
42720cf1dd8SToby Isaac @*/
42820cf1dd8SToby Isaac PetscErrorCode PetscFESetNumComponents(PetscFE fem, PetscInt comp)
42920cf1dd8SToby Isaac {
43020cf1dd8SToby Isaac   PetscFunctionBegin;
43120cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
43220cf1dd8SToby Isaac   fem->numComponents = comp;
43320cf1dd8SToby Isaac   PetscFunctionReturn(0);
43420cf1dd8SToby Isaac }
43520cf1dd8SToby Isaac 
43620cf1dd8SToby Isaac /*@
43720cf1dd8SToby Isaac   PetscFEGetNumComponents - Returns the number of components in the element
43820cf1dd8SToby Isaac 
43920cf1dd8SToby Isaac   Not collective
44020cf1dd8SToby Isaac 
44120cf1dd8SToby Isaac   Input Parameter:
44220cf1dd8SToby Isaac . fem - The PetscFE object
44320cf1dd8SToby Isaac 
44420cf1dd8SToby Isaac   Output Parameter:
44520cf1dd8SToby Isaac . comp - The number of field components
44620cf1dd8SToby Isaac 
44720cf1dd8SToby Isaac   Level: intermediate
44820cf1dd8SToby Isaac 
44920cf1dd8SToby Isaac .seealso: PetscFECreate()
45020cf1dd8SToby Isaac @*/
45120cf1dd8SToby Isaac PetscErrorCode PetscFEGetNumComponents(PetscFE fem, PetscInt *comp)
45220cf1dd8SToby Isaac {
45320cf1dd8SToby Isaac   PetscFunctionBegin;
45420cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
45520cf1dd8SToby Isaac   PetscValidPointer(comp, 2);
45620cf1dd8SToby Isaac   *comp = fem->numComponents;
45720cf1dd8SToby Isaac   PetscFunctionReturn(0);
45820cf1dd8SToby Isaac }
45920cf1dd8SToby Isaac 
46020cf1dd8SToby Isaac /*@
46120cf1dd8SToby Isaac   PetscFESetTileSizes - Sets the tile sizes for evaluation
46220cf1dd8SToby Isaac 
46320cf1dd8SToby Isaac   Not collective
46420cf1dd8SToby Isaac 
46520cf1dd8SToby Isaac   Input Parameters:
46620cf1dd8SToby Isaac + fem - The PetscFE object
46720cf1dd8SToby Isaac . blockSize - The number of elements in a block
46820cf1dd8SToby Isaac . numBlocks - The number of blocks in a batch
46920cf1dd8SToby Isaac . batchSize - The number of elements in a batch
47020cf1dd8SToby Isaac - numBatches - The number of batches in a chunk
47120cf1dd8SToby Isaac 
47220cf1dd8SToby Isaac   Level: intermediate
47320cf1dd8SToby Isaac 
47420cf1dd8SToby Isaac .seealso: PetscFECreate()
47520cf1dd8SToby Isaac @*/
47620cf1dd8SToby Isaac PetscErrorCode PetscFESetTileSizes(PetscFE fem, PetscInt blockSize, PetscInt numBlocks, PetscInt batchSize, PetscInt numBatches)
47720cf1dd8SToby Isaac {
47820cf1dd8SToby Isaac   PetscFunctionBegin;
47920cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
48020cf1dd8SToby Isaac   fem->blockSize  = blockSize;
48120cf1dd8SToby Isaac   fem->numBlocks  = numBlocks;
48220cf1dd8SToby Isaac   fem->batchSize  = batchSize;
48320cf1dd8SToby Isaac   fem->numBatches = numBatches;
48420cf1dd8SToby Isaac   PetscFunctionReturn(0);
48520cf1dd8SToby Isaac }
48620cf1dd8SToby Isaac 
48720cf1dd8SToby Isaac /*@
48820cf1dd8SToby Isaac   PetscFEGetTileSizes - Returns the tile sizes for evaluation
48920cf1dd8SToby Isaac 
49020cf1dd8SToby Isaac   Not collective
49120cf1dd8SToby Isaac 
49220cf1dd8SToby Isaac   Input Parameter:
49320cf1dd8SToby Isaac . fem - The PetscFE object
49420cf1dd8SToby Isaac 
49520cf1dd8SToby Isaac   Output Parameters:
49620cf1dd8SToby Isaac + blockSize - The number of elements in a block
49720cf1dd8SToby Isaac . numBlocks - The number of blocks in a batch
49820cf1dd8SToby Isaac . batchSize - The number of elements in a batch
49920cf1dd8SToby Isaac - numBatches - The number of batches in a chunk
50020cf1dd8SToby Isaac 
50120cf1dd8SToby Isaac   Level: intermediate
50220cf1dd8SToby Isaac 
50320cf1dd8SToby Isaac .seealso: PetscFECreate()
50420cf1dd8SToby Isaac @*/
50520cf1dd8SToby Isaac PetscErrorCode PetscFEGetTileSizes(PetscFE fem, PetscInt *blockSize, PetscInt *numBlocks, PetscInt *batchSize, PetscInt *numBatches)
50620cf1dd8SToby Isaac {
50720cf1dd8SToby Isaac   PetscFunctionBegin;
50820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
50920cf1dd8SToby Isaac   if (blockSize)  PetscValidPointer(blockSize,  2);
51020cf1dd8SToby Isaac   if (numBlocks)  PetscValidPointer(numBlocks,  3);
51120cf1dd8SToby Isaac   if (batchSize)  PetscValidPointer(batchSize,  4);
51220cf1dd8SToby Isaac   if (numBatches) PetscValidPointer(numBatches, 5);
51320cf1dd8SToby Isaac   if (blockSize)  *blockSize  = fem->blockSize;
51420cf1dd8SToby Isaac   if (numBlocks)  *numBlocks  = fem->numBlocks;
51520cf1dd8SToby Isaac   if (batchSize)  *batchSize  = fem->batchSize;
51620cf1dd8SToby Isaac   if (numBatches) *numBatches = fem->numBatches;
51720cf1dd8SToby Isaac   PetscFunctionReturn(0);
51820cf1dd8SToby Isaac }
51920cf1dd8SToby Isaac 
52020cf1dd8SToby Isaac /*@
52120cf1dd8SToby Isaac   PetscFEGetBasisSpace - Returns the PetscSpace used for approximation of the solution
52220cf1dd8SToby Isaac 
52320cf1dd8SToby Isaac   Not collective
52420cf1dd8SToby Isaac 
52520cf1dd8SToby Isaac   Input Parameter:
52620cf1dd8SToby Isaac . fem - The PetscFE object
52720cf1dd8SToby Isaac 
52820cf1dd8SToby Isaac   Output Parameter:
52920cf1dd8SToby Isaac . sp - The PetscSpace object
53020cf1dd8SToby Isaac 
53120cf1dd8SToby Isaac   Level: intermediate
53220cf1dd8SToby Isaac 
53320cf1dd8SToby Isaac .seealso: PetscFECreate()
53420cf1dd8SToby Isaac @*/
53520cf1dd8SToby Isaac PetscErrorCode PetscFEGetBasisSpace(PetscFE fem, PetscSpace *sp)
53620cf1dd8SToby Isaac {
53720cf1dd8SToby Isaac   PetscFunctionBegin;
53820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
53920cf1dd8SToby Isaac   PetscValidPointer(sp, 2);
54020cf1dd8SToby Isaac   *sp = fem->basisSpace;
54120cf1dd8SToby Isaac   PetscFunctionReturn(0);
54220cf1dd8SToby Isaac }
54320cf1dd8SToby Isaac 
54420cf1dd8SToby Isaac /*@
54520cf1dd8SToby Isaac   PetscFESetBasisSpace - Sets the PetscSpace used for approximation of the solution
54620cf1dd8SToby Isaac 
54720cf1dd8SToby Isaac   Not collective
54820cf1dd8SToby Isaac 
54920cf1dd8SToby Isaac   Input Parameters:
55020cf1dd8SToby Isaac + fem - The PetscFE object
55120cf1dd8SToby Isaac - sp - The PetscSpace object
55220cf1dd8SToby Isaac 
55320cf1dd8SToby Isaac   Level: intermediate
55420cf1dd8SToby Isaac 
55520cf1dd8SToby Isaac .seealso: PetscFECreate()
55620cf1dd8SToby Isaac @*/
55720cf1dd8SToby Isaac PetscErrorCode PetscFESetBasisSpace(PetscFE fem, PetscSpace sp)
55820cf1dd8SToby Isaac {
55920cf1dd8SToby Isaac   PetscErrorCode ierr;
56020cf1dd8SToby Isaac 
56120cf1dd8SToby Isaac   PetscFunctionBegin;
56220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
56320cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 2);
56420cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&fem->basisSpace);CHKERRQ(ierr);
56520cf1dd8SToby Isaac   fem->basisSpace = sp;
56620cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) fem->basisSpace);CHKERRQ(ierr);
56720cf1dd8SToby Isaac   PetscFunctionReturn(0);
56820cf1dd8SToby Isaac }
56920cf1dd8SToby Isaac 
57020cf1dd8SToby Isaac /*@
57120cf1dd8SToby Isaac   PetscFEGetDualSpace - Returns the PetscDualSpace used to define the inner product
57220cf1dd8SToby Isaac 
57320cf1dd8SToby Isaac   Not collective
57420cf1dd8SToby Isaac 
57520cf1dd8SToby Isaac   Input Parameter:
57620cf1dd8SToby Isaac . fem - The PetscFE object
57720cf1dd8SToby Isaac 
57820cf1dd8SToby Isaac   Output Parameter:
57920cf1dd8SToby Isaac . sp - The PetscDualSpace object
58020cf1dd8SToby Isaac 
58120cf1dd8SToby Isaac   Level: intermediate
58220cf1dd8SToby Isaac 
58320cf1dd8SToby Isaac .seealso: PetscFECreate()
58420cf1dd8SToby Isaac @*/
58520cf1dd8SToby Isaac PetscErrorCode PetscFEGetDualSpace(PetscFE fem, PetscDualSpace *sp)
58620cf1dd8SToby Isaac {
58720cf1dd8SToby Isaac   PetscFunctionBegin;
58820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
58920cf1dd8SToby Isaac   PetscValidPointer(sp, 2);
59020cf1dd8SToby Isaac   *sp = fem->dualSpace;
59120cf1dd8SToby Isaac   PetscFunctionReturn(0);
59220cf1dd8SToby Isaac }
59320cf1dd8SToby Isaac 
59420cf1dd8SToby Isaac /*@
59520cf1dd8SToby Isaac   PetscFESetDualSpace - Sets the PetscDualSpace used to define the inner product
59620cf1dd8SToby Isaac 
59720cf1dd8SToby Isaac   Not collective
59820cf1dd8SToby Isaac 
59920cf1dd8SToby Isaac   Input Parameters:
60020cf1dd8SToby Isaac + fem - The PetscFE object
60120cf1dd8SToby Isaac - sp - The PetscDualSpace object
60220cf1dd8SToby Isaac 
60320cf1dd8SToby Isaac   Level: intermediate
60420cf1dd8SToby Isaac 
60520cf1dd8SToby Isaac .seealso: PetscFECreate()
60620cf1dd8SToby Isaac @*/
60720cf1dd8SToby Isaac PetscErrorCode PetscFESetDualSpace(PetscFE fem, PetscDualSpace sp)
60820cf1dd8SToby Isaac {
60920cf1dd8SToby Isaac   PetscErrorCode ierr;
61020cf1dd8SToby Isaac 
61120cf1dd8SToby Isaac   PetscFunctionBegin;
61220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
61320cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 2);
61420cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&fem->dualSpace);CHKERRQ(ierr);
61520cf1dd8SToby Isaac   fem->dualSpace = sp;
61620cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) fem->dualSpace);CHKERRQ(ierr);
61720cf1dd8SToby Isaac   PetscFunctionReturn(0);
61820cf1dd8SToby Isaac }
61920cf1dd8SToby Isaac 
62020cf1dd8SToby Isaac /*@
62120cf1dd8SToby Isaac   PetscFEGetQuadrature - Returns the PetscQuadrature used to calculate inner products
62220cf1dd8SToby Isaac 
62320cf1dd8SToby Isaac   Not collective
62420cf1dd8SToby Isaac 
62520cf1dd8SToby Isaac   Input Parameter:
62620cf1dd8SToby Isaac . fem - The PetscFE object
62720cf1dd8SToby Isaac 
62820cf1dd8SToby Isaac   Output Parameter:
62920cf1dd8SToby Isaac . q - The PetscQuadrature object
63020cf1dd8SToby Isaac 
63120cf1dd8SToby Isaac   Level: intermediate
63220cf1dd8SToby Isaac 
63320cf1dd8SToby Isaac .seealso: PetscFECreate()
63420cf1dd8SToby Isaac @*/
63520cf1dd8SToby Isaac PetscErrorCode PetscFEGetQuadrature(PetscFE fem, PetscQuadrature *q)
63620cf1dd8SToby Isaac {
63720cf1dd8SToby Isaac   PetscFunctionBegin;
63820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
63920cf1dd8SToby Isaac   PetscValidPointer(q, 2);
64020cf1dd8SToby Isaac   *q = fem->quadrature;
64120cf1dd8SToby Isaac   PetscFunctionReturn(0);
64220cf1dd8SToby Isaac }
64320cf1dd8SToby Isaac 
64420cf1dd8SToby Isaac /*@
64520cf1dd8SToby Isaac   PetscFESetQuadrature - Sets the PetscQuadrature used to calculate inner products
64620cf1dd8SToby Isaac 
64720cf1dd8SToby Isaac   Not collective
64820cf1dd8SToby Isaac 
64920cf1dd8SToby Isaac   Input Parameters:
65020cf1dd8SToby Isaac + fem - The PetscFE object
65120cf1dd8SToby Isaac - q - The PetscQuadrature object
65220cf1dd8SToby Isaac 
65320cf1dd8SToby Isaac   Level: intermediate
65420cf1dd8SToby Isaac 
65520cf1dd8SToby Isaac .seealso: PetscFECreate()
65620cf1dd8SToby Isaac @*/
65720cf1dd8SToby Isaac PetscErrorCode PetscFESetQuadrature(PetscFE fem, PetscQuadrature q)
65820cf1dd8SToby Isaac {
65920cf1dd8SToby Isaac   PetscInt       Nc, qNc;
66020cf1dd8SToby Isaac   PetscErrorCode ierr;
66120cf1dd8SToby Isaac 
66220cf1dd8SToby Isaac   PetscFunctionBegin;
66320cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
664fd2fdbddSMatthew G. Knepley   if (q == fem->quadrature) PetscFunctionReturn(0);
66520cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
66620cf1dd8SToby Isaac   ierr = PetscQuadratureGetNumComponents(q, &qNc);CHKERRQ(ierr);
66720cf1dd8SToby 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);
668ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&fem->T);CHKERRQ(ierr);
669ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&fem->Tc);CHKERRQ(ierr);
670fd2fdbddSMatthew G. Knepley   ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr);
67120cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&fem->quadrature);CHKERRQ(ierr);
67220cf1dd8SToby Isaac   fem->quadrature = q;
67320cf1dd8SToby Isaac   PetscFunctionReturn(0);
67420cf1dd8SToby Isaac }
67520cf1dd8SToby Isaac 
67620cf1dd8SToby Isaac /*@
67720cf1dd8SToby Isaac   PetscFEGetFaceQuadrature - Returns the PetscQuadrature used to calculate inner products on faces
67820cf1dd8SToby Isaac 
67920cf1dd8SToby Isaac   Not collective
68020cf1dd8SToby Isaac 
68120cf1dd8SToby Isaac   Input Parameter:
68220cf1dd8SToby Isaac . fem - The PetscFE object
68320cf1dd8SToby Isaac 
68420cf1dd8SToby Isaac   Output Parameter:
68520cf1dd8SToby Isaac . q - The PetscQuadrature object
68620cf1dd8SToby Isaac 
68720cf1dd8SToby Isaac   Level: intermediate
68820cf1dd8SToby Isaac 
68920cf1dd8SToby Isaac .seealso: PetscFECreate()
69020cf1dd8SToby Isaac @*/
69120cf1dd8SToby Isaac PetscErrorCode PetscFEGetFaceQuadrature(PetscFE fem, PetscQuadrature *q)
69220cf1dd8SToby Isaac {
69320cf1dd8SToby Isaac   PetscFunctionBegin;
69420cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
69520cf1dd8SToby Isaac   PetscValidPointer(q, 2);
69620cf1dd8SToby Isaac   *q = fem->faceQuadrature;
69720cf1dd8SToby Isaac   PetscFunctionReturn(0);
69820cf1dd8SToby Isaac }
69920cf1dd8SToby Isaac 
70020cf1dd8SToby Isaac /*@
70120cf1dd8SToby Isaac   PetscFESetFaceQuadrature - Sets the PetscQuadrature used to calculate inner products on faces
70220cf1dd8SToby Isaac 
70320cf1dd8SToby Isaac   Not collective
70420cf1dd8SToby Isaac 
70520cf1dd8SToby Isaac   Input Parameters:
70620cf1dd8SToby Isaac + fem - The PetscFE object
70720cf1dd8SToby Isaac - q - The PetscQuadrature object
70820cf1dd8SToby Isaac 
70920cf1dd8SToby Isaac   Level: intermediate
71020cf1dd8SToby Isaac 
71120cf1dd8SToby Isaac .seealso: PetscFECreate()
71220cf1dd8SToby Isaac @*/
71320cf1dd8SToby Isaac PetscErrorCode PetscFESetFaceQuadrature(PetscFE fem, PetscQuadrature q)
71420cf1dd8SToby Isaac {
715ef0bb6c7SMatthew G. Knepley   PetscInt       Nc, qNc;
71620cf1dd8SToby Isaac   PetscErrorCode ierr;
71720cf1dd8SToby Isaac 
71820cf1dd8SToby Isaac   PetscFunctionBegin;
71920cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
720ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
721ef0bb6c7SMatthew G. Knepley   ierr = PetscQuadratureGetNumComponents(q, &qNc);CHKERRQ(ierr);
722ef0bb6c7SMatthew 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);
723ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&fem->Tf);CHKERRQ(ierr);
72420cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&fem->faceQuadrature);CHKERRQ(ierr);
72520cf1dd8SToby Isaac   fem->faceQuadrature = q;
72620cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr);
72720cf1dd8SToby Isaac   PetscFunctionReturn(0);
72820cf1dd8SToby Isaac }
72920cf1dd8SToby Isaac 
7305dc5c000SMatthew G. Knepley /*@
7315dc5c000SMatthew G. Knepley   PetscFECopyQuadrature - Copy both volumetric and surface quadrature
7325dc5c000SMatthew G. Knepley 
7335dc5c000SMatthew G. Knepley   Not collective
7345dc5c000SMatthew G. Knepley 
7355dc5c000SMatthew G. Knepley   Input Parameters:
7365dc5c000SMatthew G. Knepley + sfe - The PetscFE source for the quadratures
7375dc5c000SMatthew G. Knepley - tfe - The PetscFE target for the quadratures
7385dc5c000SMatthew G. Knepley 
7395dc5c000SMatthew G. Knepley   Level: intermediate
7405dc5c000SMatthew G. Knepley 
7415dc5c000SMatthew G. Knepley .seealso: PetscFECreate(), PetscFESetQuadrature(), PetscFESetFaceQuadrature()
7425dc5c000SMatthew G. Knepley @*/
7435dc5c000SMatthew G. Knepley PetscErrorCode PetscFECopyQuadrature(PetscFE sfe, PetscFE tfe)
7445dc5c000SMatthew G. Knepley {
7455dc5c000SMatthew G. Knepley   PetscQuadrature q;
7465dc5c000SMatthew G. Knepley   PetscErrorCode  ierr;
7475dc5c000SMatthew G. Knepley 
7485dc5c000SMatthew G. Knepley   PetscFunctionBegin;
7495dc5c000SMatthew G. Knepley   PetscValidHeaderSpecific(sfe, PETSCFE_CLASSID, 1);
7505dc5c000SMatthew G. Knepley   PetscValidHeaderSpecific(tfe, PETSCFE_CLASSID, 2);
7515dc5c000SMatthew G. Knepley   ierr = PetscFEGetQuadrature(sfe, &q);CHKERRQ(ierr);
7525dc5c000SMatthew G. Knepley   ierr = PetscFESetQuadrature(tfe,  q);CHKERRQ(ierr);
7535dc5c000SMatthew G. Knepley   ierr = PetscFEGetFaceQuadrature(sfe, &q);CHKERRQ(ierr);
7545dc5c000SMatthew G. Knepley   ierr = PetscFESetFaceQuadrature(tfe,  q);CHKERRQ(ierr);
7555dc5c000SMatthew G. Knepley   PetscFunctionReturn(0);
7565dc5c000SMatthew G. Knepley }
7575dc5c000SMatthew G. Knepley 
75820cf1dd8SToby Isaac /*@C
75920cf1dd8SToby Isaac   PetscFEGetNumDof - Returns the number of dofs (dual basis vectors) associated to mesh points on the reference cell of a given dimension
76020cf1dd8SToby Isaac 
76120cf1dd8SToby Isaac   Not collective
76220cf1dd8SToby Isaac 
76320cf1dd8SToby Isaac   Input Parameter:
76420cf1dd8SToby Isaac . fem - The PetscFE object
76520cf1dd8SToby Isaac 
76620cf1dd8SToby Isaac   Output Parameter:
76720cf1dd8SToby Isaac . numDof - Array with the number of dofs per dimension
76820cf1dd8SToby Isaac 
76920cf1dd8SToby Isaac   Level: intermediate
77020cf1dd8SToby Isaac 
77120cf1dd8SToby Isaac .seealso: PetscFECreate()
77220cf1dd8SToby Isaac @*/
77320cf1dd8SToby Isaac PetscErrorCode PetscFEGetNumDof(PetscFE fem, const PetscInt **numDof)
77420cf1dd8SToby Isaac {
77520cf1dd8SToby Isaac   PetscErrorCode ierr;
77620cf1dd8SToby Isaac 
77720cf1dd8SToby Isaac   PetscFunctionBegin;
77820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
77920cf1dd8SToby Isaac   PetscValidPointer(numDof, 2);
78020cf1dd8SToby Isaac   ierr = PetscDualSpaceGetNumDof(fem->dualSpace, numDof);CHKERRQ(ierr);
78120cf1dd8SToby Isaac   PetscFunctionReturn(0);
78220cf1dd8SToby Isaac }
78320cf1dd8SToby Isaac 
78420cf1dd8SToby Isaac /*@C
785ef0bb6c7SMatthew G. Knepley   PetscFEGetCellTabulation - Returns the tabulation of the basis functions at the quadrature points on the reference cell
78620cf1dd8SToby Isaac 
78720cf1dd8SToby Isaac   Not collective
78820cf1dd8SToby Isaac 
78920cf1dd8SToby Isaac   Input Parameter:
79020cf1dd8SToby Isaac . fem - The PetscFE object
79120cf1dd8SToby Isaac 
792ef0bb6c7SMatthew G. Knepley   Output Parameter:
793ef0bb6c7SMatthew G. Knepley . T - The basis function values and derivatives at quadrature points
79420cf1dd8SToby Isaac 
79520cf1dd8SToby Isaac   Note:
796ef0bb6c7SMatthew G. Knepley $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
797ef0bb6c7SMatthew 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
798ef0bb6c7SMatthew 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
79920cf1dd8SToby Isaac 
80020cf1dd8SToby Isaac   Level: intermediate
80120cf1dd8SToby Isaac 
802ef0bb6c7SMatthew G. Knepley .seealso: PetscFECreateTabulation(), PetscTabulationDestroy()
80320cf1dd8SToby Isaac @*/
804ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEGetCellTabulation(PetscFE fem, PetscTabulation *T)
80520cf1dd8SToby Isaac {
80620cf1dd8SToby Isaac   PetscInt         npoints;
80720cf1dd8SToby Isaac   const PetscReal *points;
80820cf1dd8SToby Isaac   PetscErrorCode   ierr;
80920cf1dd8SToby Isaac 
81020cf1dd8SToby Isaac   PetscFunctionBegin;
81120cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
812ef0bb6c7SMatthew G. Knepley   PetscValidPointer(T, 2);
81320cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(fem->quadrature, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr);
814ef0bb6c7SMatthew G. Knepley   if (!fem->T) {ierr = PetscFECreateTabulation(fem, 1, npoints, points, 1, &fem->T);CHKERRQ(ierr);}
815ef0bb6c7SMatthew G. Knepley   *T = fem->T;
81620cf1dd8SToby Isaac   PetscFunctionReturn(0);
81720cf1dd8SToby Isaac }
81820cf1dd8SToby Isaac 
8192b99622eSMatthew G. Knepley /*@C
820ef0bb6c7SMatthew G. Knepley   PetscFEGetFaceTabulation - Returns the tabulation of the basis functions at the face quadrature points for each face of the reference cell
8212b99622eSMatthew G. Knepley 
8222b99622eSMatthew G. Knepley   Not collective
8232b99622eSMatthew G. Knepley 
8242b99622eSMatthew G. Knepley   Input Parameter:
8252b99622eSMatthew G. Knepley . fem - The PetscFE object
8262b99622eSMatthew G. Knepley 
8272b99622eSMatthew G. Knepley   Output Parameters:
828ef0bb6c7SMatthew G. Knepley . Tf - The basis function values and derviatives at face quadrature points
8292b99622eSMatthew G. Knepley 
8302b99622eSMatthew G. Knepley   Note:
831ef0bb6c7SMatthew 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
832ef0bb6c7SMatthew 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
833ef0bb6c7SMatthew 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
8342b99622eSMatthew G. Knepley 
8352b99622eSMatthew G. Knepley   Level: intermediate
8362b99622eSMatthew G. Knepley 
837ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetCellTabulation(), PetscFECreateTabulation(), PetscTabulationDestroy()
8382b99622eSMatthew G. Knepley @*/
839ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEGetFaceTabulation(PetscFE fem, PetscTabulation *Tf)
84020cf1dd8SToby Isaac {
84120cf1dd8SToby Isaac   PetscErrorCode   ierr;
84220cf1dd8SToby Isaac 
84320cf1dd8SToby Isaac   PetscFunctionBegin;
84420cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
845ef0bb6c7SMatthew G. Knepley   PetscValidPointer(Tf, 2);
846ef0bb6c7SMatthew G. Knepley   if (!fem->Tf) {
84720cf1dd8SToby Isaac     const PetscReal  xi0[3] = {-1., -1., -1.};
84820cf1dd8SToby Isaac     PetscReal        v0[3], J[9], detJ;
84920cf1dd8SToby Isaac     PetscQuadrature  fq;
85020cf1dd8SToby Isaac     PetscDualSpace   sp;
85120cf1dd8SToby Isaac     DM               dm;
85220cf1dd8SToby Isaac     const PetscInt  *faces;
85320cf1dd8SToby Isaac     PetscInt         dim, numFaces, f, npoints, q;
85420cf1dd8SToby Isaac     const PetscReal *points;
85520cf1dd8SToby Isaac     PetscReal       *facePoints;
85620cf1dd8SToby Isaac 
85720cf1dd8SToby Isaac     ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr);
85820cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr);
85920cf1dd8SToby Isaac     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
86020cf1dd8SToby Isaac     ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr);
86120cf1dd8SToby Isaac     ierr = DMPlexGetCone(dm, 0, &faces);CHKERRQ(ierr);
86220cf1dd8SToby Isaac     ierr = PetscFEGetFaceQuadrature(fem, &fq);CHKERRQ(ierr);
86320cf1dd8SToby Isaac     if (fq) {
86420cf1dd8SToby Isaac       ierr = PetscQuadratureGetData(fq, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr);
86520cf1dd8SToby Isaac       ierr = PetscMalloc1(numFaces*npoints*dim, &facePoints);CHKERRQ(ierr);
86620cf1dd8SToby Isaac       for (f = 0; f < numFaces; ++f) {
86720cf1dd8SToby Isaac         ierr = DMPlexComputeCellGeometryFEM(dm, faces[f], NULL, v0, J, NULL, &detJ);CHKERRQ(ierr);
86820cf1dd8SToby Isaac         for (q = 0; q < npoints; ++q) CoordinatesRefToReal(dim, dim-1, xi0, v0, J, &points[q*(dim-1)], &facePoints[(f*npoints+q)*dim]);
86920cf1dd8SToby Isaac       }
870ef0bb6c7SMatthew G. Knepley       ierr = PetscFECreateTabulation(fem, numFaces, npoints, facePoints, 1, &fem->Tf);CHKERRQ(ierr);
87120cf1dd8SToby Isaac       ierr = PetscFree(facePoints);CHKERRQ(ierr);
87220cf1dd8SToby Isaac     }
87320cf1dd8SToby Isaac   }
874ef0bb6c7SMatthew G. Knepley   *Tf = fem->Tf;
87520cf1dd8SToby Isaac   PetscFunctionReturn(0);
87620cf1dd8SToby Isaac }
87720cf1dd8SToby Isaac 
8782b99622eSMatthew G. Knepley /*@C
879ef0bb6c7SMatthew G. Knepley   PetscFEGetFaceCentroidTabulation - Returns the tabulation of the basis functions at the face centroid points
8802b99622eSMatthew G. Knepley 
8812b99622eSMatthew G. Knepley   Not collective
8822b99622eSMatthew G. Knepley 
8832b99622eSMatthew G. Knepley   Input Parameter:
8842b99622eSMatthew G. Knepley . fem - The PetscFE object
8852b99622eSMatthew G. Knepley 
8862b99622eSMatthew G. Knepley   Output Parameters:
887ef0bb6c7SMatthew G. Knepley . Tc - The basis function values at face centroid points
8882b99622eSMatthew G. Knepley 
8892b99622eSMatthew G. Knepley   Note:
890ef0bb6c7SMatthew G. Knepley $ T->T[0] = Bf[(f*pdim + i)*Nc + c] is the value at point f for basis function i and component c
8912b99622eSMatthew G. Knepley 
8922b99622eSMatthew G. Knepley   Level: intermediate
8932b99622eSMatthew G. Knepley 
894ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetFaceTabulation(), PetscFEGetCellTabulation(), PetscFECreateTabulation(), PetscTabulationDestroy()
8952b99622eSMatthew G. Knepley @*/
896ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEGetFaceCentroidTabulation(PetscFE fem, PetscTabulation *Tc)
89720cf1dd8SToby Isaac {
89820cf1dd8SToby Isaac   PetscErrorCode   ierr;
89920cf1dd8SToby Isaac 
90020cf1dd8SToby Isaac   PetscFunctionBegin;
90120cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
902ef0bb6c7SMatthew G. Knepley   PetscValidPointer(Tc, 2);
903ef0bb6c7SMatthew G. Knepley   if (!fem->Tc) {
90420cf1dd8SToby Isaac     PetscDualSpace  sp;
90520cf1dd8SToby Isaac     DM              dm;
90620cf1dd8SToby Isaac     const PetscInt *cone;
90720cf1dd8SToby Isaac     PetscReal      *centroids;
90820cf1dd8SToby Isaac     PetscInt        dim, numFaces, f;
90920cf1dd8SToby Isaac 
91020cf1dd8SToby Isaac     ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr);
91120cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr);
91220cf1dd8SToby Isaac     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
91320cf1dd8SToby Isaac     ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr);
91420cf1dd8SToby Isaac     ierr = DMPlexGetCone(dm, 0, &cone);CHKERRQ(ierr);
91520cf1dd8SToby Isaac     ierr = PetscMalloc1(numFaces*dim, &centroids);CHKERRQ(ierr);
91620cf1dd8SToby Isaac     for (f = 0; f < numFaces; ++f) {ierr = DMPlexComputeCellGeometryFVM(dm, cone[f], NULL, &centroids[f*dim], NULL);CHKERRQ(ierr);}
917ef0bb6c7SMatthew G. Knepley     ierr = PetscFECreateTabulation(fem, 1, numFaces, centroids, 0, &fem->Tc);CHKERRQ(ierr);
91820cf1dd8SToby Isaac     ierr = PetscFree(centroids);CHKERRQ(ierr);
91920cf1dd8SToby Isaac   }
920ef0bb6c7SMatthew G. Knepley   *Tc = fem->Tc;
92120cf1dd8SToby Isaac   PetscFunctionReturn(0);
92220cf1dd8SToby Isaac }
92320cf1dd8SToby Isaac 
92420cf1dd8SToby Isaac /*@C
925ef0bb6c7SMatthew G. Knepley   PetscFECreateTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
92620cf1dd8SToby Isaac 
92720cf1dd8SToby Isaac   Not collective
92820cf1dd8SToby Isaac 
92920cf1dd8SToby Isaac   Input Parameters:
93020cf1dd8SToby Isaac + fem     - The PetscFE object
931ef0bb6c7SMatthew G. Knepley . nrepl   - The number of replicas
932ef0bb6c7SMatthew G. Knepley . npoints - The number of tabulation points in a replica
933ef0bb6c7SMatthew G. Knepley . points  - The tabulation point coordinates
934ef0bb6c7SMatthew G. Knepley - K       - The number of derivatives calculated
93520cf1dd8SToby Isaac 
936ef0bb6c7SMatthew G. Knepley   Output Parameter:
937ef0bb6c7SMatthew G. Knepley . T - The basis function values and derivatives at tabulation points
93820cf1dd8SToby Isaac 
93920cf1dd8SToby Isaac   Note:
940ef0bb6c7SMatthew G. Knepley $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
941ef0bb6c7SMatthew 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
942ef0bb6c7SMatthew 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
94320cf1dd8SToby Isaac 
94420cf1dd8SToby Isaac   Level: intermediate
94520cf1dd8SToby Isaac 
946ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetCellTabulation(), PetscTabulationDestroy()
94720cf1dd8SToby Isaac @*/
948ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFECreateTabulation(PetscFE fem, PetscInt nrepl, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation *T)
94920cf1dd8SToby Isaac {
95020cf1dd8SToby Isaac   DM               dm;
951ef0bb6c7SMatthew G. Knepley   PetscDualSpace   Q;
952ef0bb6c7SMatthew G. Knepley   PetscInt         Nb;   /* Dimension of FE space P */
953ef0bb6c7SMatthew G. Knepley   PetscInt         Nc;   /* Field components */
954ef0bb6c7SMatthew G. Knepley   PetscInt         cdim; /* Reference coordinate dimension */
955ef0bb6c7SMatthew G. Knepley   PetscInt         k;
95620cf1dd8SToby Isaac   PetscErrorCode   ierr;
95720cf1dd8SToby Isaac 
95820cf1dd8SToby Isaac   PetscFunctionBegin;
959ef0bb6c7SMatthew G. Knepley   if (!npoints || !fem->dualSpace || K < 0) {
960ef0bb6c7SMatthew G. Knepley     *T = NULL;
96120cf1dd8SToby Isaac     PetscFunctionReturn(0);
96220cf1dd8SToby Isaac   }
96320cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
96440a2aa30SMatthew G. Knepley   PetscValidPointer(points, 4);
96540a2aa30SMatthew G. Knepley   PetscValidPointer(T, 6);
966ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetDualSpace(fem, &Q);CHKERRQ(ierr);
967ef0bb6c7SMatthew G. Knepley   ierr = PetscDualSpaceGetDM(Q, &dm);CHKERRQ(ierr);
968ef0bb6c7SMatthew G. Knepley   ierr = DMGetDimension(dm, &cdim);CHKERRQ(ierr);
969ef0bb6c7SMatthew G. Knepley   ierr = PetscDualSpaceGetDimension(Q, &Nb);CHKERRQ(ierr);
970ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
971ef0bb6c7SMatthew G. Knepley   ierr = PetscMalloc1(1, T);CHKERRQ(ierr);
972ef0bb6c7SMatthew G. Knepley   (*T)->K    = !cdim ? 0 : K;
973ef0bb6c7SMatthew G. Knepley   (*T)->Nr   = nrepl;
974ef0bb6c7SMatthew G. Knepley   (*T)->Np   = npoints;
975ef0bb6c7SMatthew G. Knepley   (*T)->Nb   = Nb;
976ef0bb6c7SMatthew G. Knepley   (*T)->Nc   = Nc;
977ef0bb6c7SMatthew G. Knepley   (*T)->cdim = cdim;
978ef0bb6c7SMatthew G. Knepley   ierr = PetscMalloc1((*T)->K+1, &(*T)->T);CHKERRQ(ierr);
979ef0bb6c7SMatthew G. Knepley   for (k = 0; k <= (*T)->K; ++k) {
980ef0bb6c7SMatthew G. Knepley     ierr = PetscMalloc1(nrepl*npoints*Nb*Nc*PetscPowInt(cdim, k), &(*T)->T[k]);CHKERRQ(ierr);
98120cf1dd8SToby Isaac   }
982ef0bb6c7SMatthew G. Knepley   ierr = (*fem->ops->createtabulation)(fem, nrepl*npoints, points, K, *T);CHKERRQ(ierr);
98320cf1dd8SToby Isaac   PetscFunctionReturn(0);
98420cf1dd8SToby Isaac }
98520cf1dd8SToby Isaac 
9862b99622eSMatthew G. Knepley /*@C
987ef0bb6c7SMatthew G. Knepley   PetscFEComputeTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
9882b99622eSMatthew G. Knepley 
9892b99622eSMatthew G. Knepley   Not collective
9902b99622eSMatthew G. Knepley 
9912b99622eSMatthew G. Knepley   Input Parameters:
9922b99622eSMatthew G. Knepley + fem     - The PetscFE object
9932b99622eSMatthew G. Knepley . npoints - The number of tabulation points
9942b99622eSMatthew G. Knepley . points  - The tabulation point coordinates
995ef0bb6c7SMatthew G. Knepley . K       - The number of derivatives calculated
996ef0bb6c7SMatthew G. Knepley - T       - An existing tabulation object with enough allocated space
997ef0bb6c7SMatthew G. Knepley 
998ef0bb6c7SMatthew G. Knepley   Output Parameter:
999ef0bb6c7SMatthew G. Knepley . T - The basis function values and derivatives at tabulation points
10002b99622eSMatthew G. Knepley 
10012b99622eSMatthew G. Knepley   Note:
1002ef0bb6c7SMatthew G. Knepley $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1003ef0bb6c7SMatthew 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
1004ef0bb6c7SMatthew 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
10052b99622eSMatthew G. Knepley 
10062b99622eSMatthew G. Knepley   Level: intermediate
10072b99622eSMatthew G. Knepley 
1008ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetCellTabulation(), PetscTabulationDestroy()
10092b99622eSMatthew G. Knepley @*/
1010ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEComputeTabulation(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation T)
1011ef0bb6c7SMatthew G. Knepley {
1012ef0bb6c7SMatthew G. Knepley   PetscErrorCode ierr;
1013ef0bb6c7SMatthew G. Knepley 
1014ef0bb6c7SMatthew G. Knepley   PetscFunctionBeginHot;
1015ef0bb6c7SMatthew G. Knepley   if (!npoints || !fem->dualSpace || K < 0) PetscFunctionReturn(0);
1016ef0bb6c7SMatthew G. Knepley   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
1017ef0bb6c7SMatthew G. Knepley   PetscValidPointer(points, 3);
1018ef0bb6c7SMatthew G. Knepley   PetscValidPointer(T, 5);
101976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
102020cf1dd8SToby Isaac     DM               dm;
1021ef0bb6c7SMatthew G. Knepley     PetscDualSpace   Q;
1022ef0bb6c7SMatthew G. Knepley     PetscInt         Nb;   /* Dimension of FE space P */
1023ef0bb6c7SMatthew G. Knepley     PetscInt         Nc;   /* Field components */
1024ef0bb6c7SMatthew G. Knepley     PetscInt         cdim; /* Reference coordinate dimension */
1025ef0bb6c7SMatthew G. Knepley 
1026ef0bb6c7SMatthew G. Knepley     ierr = PetscFEGetDualSpace(fem, &Q);CHKERRQ(ierr);
1027ef0bb6c7SMatthew G. Knepley     ierr = PetscDualSpaceGetDM(Q, &dm);CHKERRQ(ierr);
1028ef0bb6c7SMatthew G. Knepley     ierr = DMGetDimension(dm, &cdim);CHKERRQ(ierr);
1029ef0bb6c7SMatthew G. Knepley     ierr = PetscDualSpaceGetDimension(Q, &Nb);CHKERRQ(ierr);
1030ef0bb6c7SMatthew G. Knepley     ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
1031ef0bb6c7SMatthew 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);
1032ef0bb6c7SMatthew 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);
1033ef0bb6c7SMatthew 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);
1034ef0bb6c7SMatthew 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);
1035ef0bb6c7SMatthew G. Knepley   }
1036ef0bb6c7SMatthew G. Knepley   T->Nr = 1;
1037ef0bb6c7SMatthew G. Knepley   T->Np = npoints;
1038ef0bb6c7SMatthew G. Knepley   ierr = (*fem->ops->createtabulation)(fem, npoints, points, K, T);CHKERRQ(ierr);
1039ef0bb6c7SMatthew G. Knepley   PetscFunctionReturn(0);
1040ef0bb6c7SMatthew G. Knepley }
1041ef0bb6c7SMatthew G. Knepley 
1042ef0bb6c7SMatthew G. Knepley /*@C
1043ef0bb6c7SMatthew G. Knepley   PetscTabulationDestroy - Frees memory from the associated tabulation.
1044ef0bb6c7SMatthew G. Knepley 
1045ef0bb6c7SMatthew G. Knepley   Not collective
1046ef0bb6c7SMatthew G. Knepley 
1047ef0bb6c7SMatthew G. Knepley   Input Parameter:
1048ef0bb6c7SMatthew G. Knepley . T - The tabulation
1049ef0bb6c7SMatthew G. Knepley 
1050ef0bb6c7SMatthew G. Knepley   Level: intermediate
1051ef0bb6c7SMatthew G. Knepley 
1052ef0bb6c7SMatthew G. Knepley .seealso: PetscFECreateTabulation(), PetscFEGetCellTabulation()
1053ef0bb6c7SMatthew G. Knepley @*/
1054ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscTabulationDestroy(PetscTabulation *T)
1055ef0bb6c7SMatthew G. Knepley {
1056ef0bb6c7SMatthew G. Knepley   PetscInt       k;
105720cf1dd8SToby Isaac   PetscErrorCode ierr;
105820cf1dd8SToby Isaac 
105920cf1dd8SToby Isaac   PetscFunctionBegin;
1060ef0bb6c7SMatthew G. Knepley   PetscValidPointer(T, 1);
1061ef0bb6c7SMatthew G. Knepley   if (!T || !(*T)) PetscFunctionReturn(0);
1062ef0bb6c7SMatthew G. Knepley   for (k = 0; k <= (*T)->K; ++k) {ierr = PetscFree((*T)->T[k]);CHKERRQ(ierr);}
1063ef0bb6c7SMatthew G. Knepley   ierr = PetscFree((*T)->T);CHKERRQ(ierr);
1064ef0bb6c7SMatthew G. Knepley   ierr = PetscFree(*T);CHKERRQ(ierr);
1065ef0bb6c7SMatthew G. Knepley   *T = NULL;
106620cf1dd8SToby Isaac   PetscFunctionReturn(0);
106720cf1dd8SToby Isaac }
106820cf1dd8SToby Isaac 
106920cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode PetscFECreatePointTrace(PetscFE fe, PetscInt refPoint, PetscFE *trFE)
107020cf1dd8SToby Isaac {
107120cf1dd8SToby Isaac   PetscSpace     bsp, bsubsp;
107220cf1dd8SToby Isaac   PetscDualSpace dsp, dsubsp;
107320cf1dd8SToby Isaac   PetscInt       dim, depth, numComp, i, j, coneSize, order;
107420cf1dd8SToby Isaac   PetscFEType    type;
107520cf1dd8SToby Isaac   DM             dm;
107620cf1dd8SToby Isaac   DMLabel        label;
107720cf1dd8SToby Isaac   PetscReal      *xi, *v, *J, detJ;
1078db11e2ebSMatthew G. Knepley   const char     *name;
107920cf1dd8SToby Isaac   PetscQuadrature origin, fullQuad, subQuad;
108020cf1dd8SToby Isaac   PetscErrorCode ierr;
108120cf1dd8SToby Isaac 
108220cf1dd8SToby Isaac   PetscFunctionBegin;
108320cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1);
108420cf1dd8SToby Isaac   PetscValidPointer(trFE,3);
108520cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe,&bsp);CHKERRQ(ierr);
108620cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr);
108720cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr);
108820cf1dd8SToby Isaac   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
108920cf1dd8SToby Isaac   ierr = DMPlexGetDepthLabel(dm,&label);CHKERRQ(ierr);
109020cf1dd8SToby Isaac   ierr = DMLabelGetValue(label,refPoint,&depth);CHKERRQ(ierr);
109120cf1dd8SToby Isaac   ierr = PetscCalloc1(depth,&xi);CHKERRQ(ierr);
109220cf1dd8SToby Isaac   ierr = PetscMalloc1(dim,&v);CHKERRQ(ierr);
109320cf1dd8SToby Isaac   ierr = PetscMalloc1(dim*dim,&J);CHKERRQ(ierr);
109420cf1dd8SToby Isaac   for (i = 0; i < depth; i++) xi[i] = 0.;
109520cf1dd8SToby Isaac   ierr = PetscQuadratureCreate(PETSC_COMM_SELF,&origin);CHKERRQ(ierr);
109620cf1dd8SToby Isaac   ierr = PetscQuadratureSetData(origin,depth,0,1,xi,NULL);CHKERRQ(ierr);
109720cf1dd8SToby Isaac   ierr = DMPlexComputeCellGeometryFEM(dm,refPoint,origin,v,J,NULL,&detJ);CHKERRQ(ierr);
109820cf1dd8SToby Isaac   /* CellGeometryFEM computes the expanded Jacobian, we want the true jacobian */
109920cf1dd8SToby Isaac   for (i = 1; i < dim; i++) {
110020cf1dd8SToby Isaac     for (j = 0; j < depth; j++) {
110120cf1dd8SToby Isaac       J[i * depth + j] = J[i * dim + j];
110220cf1dd8SToby Isaac     }
110320cf1dd8SToby Isaac   }
110420cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&origin);CHKERRQ(ierr);
110520cf1dd8SToby Isaac   ierr = PetscDualSpaceGetPointSubspace(dsp,refPoint,&dsubsp);CHKERRQ(ierr);
110620cf1dd8SToby Isaac   ierr = PetscSpaceCreateSubspace(bsp,dsubsp,v,J,NULL,NULL,PETSC_OWN_POINTER,&bsubsp);CHKERRQ(ierr);
110720cf1dd8SToby Isaac   ierr = PetscSpaceSetUp(bsubsp);CHKERRQ(ierr);
110820cf1dd8SToby Isaac   ierr = PetscFECreate(PetscObjectComm((PetscObject)fe),trFE);CHKERRQ(ierr);
110920cf1dd8SToby Isaac   ierr = PetscFEGetType(fe,&type);CHKERRQ(ierr);
111020cf1dd8SToby Isaac   ierr = PetscFESetType(*trFE,type);CHKERRQ(ierr);
111120cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe,&numComp);CHKERRQ(ierr);
111220cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*trFE,numComp);CHKERRQ(ierr);
111320cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*trFE,bsubsp);CHKERRQ(ierr);
111420cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*trFE,dsubsp);CHKERRQ(ierr);
1115db11e2ebSMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr);
1116db11e2ebSMatthew G. Knepley   if (name) {ierr = PetscFESetName(*trFE, name);CHKERRQ(ierr);}
111720cf1dd8SToby Isaac   ierr = PetscFEGetQuadrature(fe,&fullQuad);CHKERRQ(ierr);
111820cf1dd8SToby Isaac   ierr = PetscQuadratureGetOrder(fullQuad,&order);CHKERRQ(ierr);
111920cf1dd8SToby Isaac   ierr = DMPlexGetConeSize(dm,refPoint,&coneSize);CHKERRQ(ierr);
112020cf1dd8SToby Isaac   if (coneSize == 2 * depth) {
112120cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr);
112220cf1dd8SToby Isaac   } else {
1123e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr);
112420cf1dd8SToby Isaac   }
112520cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*trFE,subQuad);CHKERRQ(ierr);
112620cf1dd8SToby Isaac   ierr = PetscFESetUp(*trFE);CHKERRQ(ierr);
112720cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&subQuad);CHKERRQ(ierr);
112820cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&bsubsp);CHKERRQ(ierr);
112920cf1dd8SToby Isaac   PetscFunctionReturn(0);
113020cf1dd8SToby Isaac }
113120cf1dd8SToby Isaac 
113220cf1dd8SToby Isaac PetscErrorCode PetscFECreateHeightTrace(PetscFE fe, PetscInt height, PetscFE *trFE)
113320cf1dd8SToby Isaac {
113420cf1dd8SToby Isaac   PetscInt       hStart, hEnd;
113520cf1dd8SToby Isaac   PetscDualSpace dsp;
113620cf1dd8SToby Isaac   DM             dm;
113720cf1dd8SToby Isaac   PetscErrorCode ierr;
113820cf1dd8SToby Isaac 
113920cf1dd8SToby Isaac   PetscFunctionBegin;
114020cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1);
114120cf1dd8SToby Isaac   PetscValidPointer(trFE,3);
114220cf1dd8SToby Isaac   *trFE = NULL;
114320cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr);
114420cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr);
114520cf1dd8SToby Isaac   ierr = DMPlexGetHeightStratum(dm,height,&hStart,&hEnd);CHKERRQ(ierr);
114620cf1dd8SToby Isaac   if (hEnd <= hStart) PetscFunctionReturn(0);
114720cf1dd8SToby Isaac   ierr = PetscFECreatePointTrace(fe,hStart,trFE);CHKERRQ(ierr);
114820cf1dd8SToby Isaac   PetscFunctionReturn(0);
114920cf1dd8SToby Isaac }
115020cf1dd8SToby Isaac 
115120cf1dd8SToby Isaac 
115220cf1dd8SToby Isaac /*@
115320cf1dd8SToby Isaac   PetscFEGetDimension - Get the dimension of the finite element space on a cell
115420cf1dd8SToby Isaac 
115520cf1dd8SToby Isaac   Not collective
115620cf1dd8SToby Isaac 
115720cf1dd8SToby Isaac   Input Parameter:
115820cf1dd8SToby Isaac . fe - The PetscFE
115920cf1dd8SToby Isaac 
116020cf1dd8SToby Isaac   Output Parameter:
116120cf1dd8SToby Isaac . dim - The dimension
116220cf1dd8SToby Isaac 
116320cf1dd8SToby Isaac   Level: intermediate
116420cf1dd8SToby Isaac 
116520cf1dd8SToby Isaac .seealso: PetscFECreate(), PetscSpaceGetDimension(), PetscDualSpaceGetDimension()
116620cf1dd8SToby Isaac @*/
116720cf1dd8SToby Isaac PetscErrorCode PetscFEGetDimension(PetscFE fem, PetscInt *dim)
116820cf1dd8SToby Isaac {
116920cf1dd8SToby Isaac   PetscErrorCode ierr;
117020cf1dd8SToby Isaac 
117120cf1dd8SToby Isaac   PetscFunctionBegin;
117220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
117320cf1dd8SToby Isaac   PetscValidPointer(dim, 2);
117420cf1dd8SToby Isaac   if (fem->ops->getdimension) {ierr = (*fem->ops->getdimension)(fem, dim);CHKERRQ(ierr);}
117520cf1dd8SToby Isaac   PetscFunctionReturn(0);
117620cf1dd8SToby Isaac }
117720cf1dd8SToby Isaac 
11784bee2e38SMatthew G. Knepley /*@C
11794bee2e38SMatthew G. Knepley   PetscFEPushforward - Map the reference element function to real space
11804bee2e38SMatthew G. Knepley 
11814bee2e38SMatthew G. Knepley   Input Parameters:
11824bee2e38SMatthew G. Knepley + fe     - The PetscFE
11834bee2e38SMatthew G. Knepley . fegeom - The cell geometry
11844bee2e38SMatthew G. Knepley . Nv     - The number of function values
11854bee2e38SMatthew G. Knepley - vals   - The function values
11864bee2e38SMatthew G. Knepley 
11874bee2e38SMatthew G. Knepley   Output Parameter:
11884bee2e38SMatthew G. Knepley . vals   - The transformed function values
11894bee2e38SMatthew G. Knepley 
11904bee2e38SMatthew G. Knepley   Level: advanced
11914bee2e38SMatthew G. Knepley 
11924bee2e38SMatthew G. Knepley   Note: This just forwards the call onto PetscDualSpacePushforward().
11934bee2e38SMatthew G. Knepley 
11942edcad52SToby Isaac   Note: This only handles tranformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
11952edcad52SToby Isaac 
11964bee2e38SMatthew G. Knepley .seealso: PetscDualSpacePushforward()
11974bee2e38SMatthew G. Knepley @*/
11982edcad52SToby Isaac PetscErrorCode PetscFEPushforward(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
11994bee2e38SMatthew G. Knepley {
12004bee2e38SMatthew G. Knepley   PetscErrorCode ierr;
12014bee2e38SMatthew G. Knepley 
12022ae266adSMatthew G. Knepley   PetscFunctionBeginHot;
12032edcad52SToby Isaac   ierr = PetscDualSpacePushforward(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr);
12044bee2e38SMatthew G. Knepley   PetscFunctionReturn(0);
12054bee2e38SMatthew G. Knepley }
12064bee2e38SMatthew G. Knepley 
12074bee2e38SMatthew G. Knepley /*@C
12084bee2e38SMatthew G. Knepley   PetscFEPushforwardGradient - Map the reference element function gradient to real space
12094bee2e38SMatthew G. Knepley 
12104bee2e38SMatthew G. Knepley   Input Parameters:
12114bee2e38SMatthew G. Knepley + fe     - The PetscFE
12124bee2e38SMatthew G. Knepley . fegeom - The cell geometry
12134bee2e38SMatthew G. Knepley . Nv     - The number of function gradient values
12144bee2e38SMatthew G. Knepley - vals   - The function gradient values
12154bee2e38SMatthew G. Knepley 
12164bee2e38SMatthew G. Knepley   Output Parameter:
12174bee2e38SMatthew G. Knepley . vals   - The transformed function gradient values
12184bee2e38SMatthew G. Knepley 
12194bee2e38SMatthew G. Knepley   Level: advanced
12204bee2e38SMatthew G. Knepley 
12214bee2e38SMatthew G. Knepley   Note: This just forwards the call onto PetscDualSpacePushforwardGradient().
12224bee2e38SMatthew G. Knepley 
12232edcad52SToby Isaac   Note: This only handles tranformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
12242edcad52SToby Isaac 
12254bee2e38SMatthew G. Knepley .seealso: PetscFEPushforward(), PetscDualSpacePushforwardGradient(), PetscDualSpacePushforward()
12264bee2e38SMatthew G. Knepley @*/
12272edcad52SToby Isaac PetscErrorCode PetscFEPushforwardGradient(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
12284bee2e38SMatthew G. Knepley {
12294bee2e38SMatthew G. Knepley   PetscErrorCode ierr;
12304bee2e38SMatthew G. Knepley 
12312ae266adSMatthew G. Knepley   PetscFunctionBeginHot;
12322edcad52SToby Isaac   ierr = PetscDualSpacePushforwardGradient(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr);
12334bee2e38SMatthew G. Knepley   PetscFunctionReturn(0);
12344bee2e38SMatthew G. Knepley }
12354bee2e38SMatthew G. Knepley 
123620cf1dd8SToby Isaac /*
123720cf1dd8SToby Isaac Purpose: Compute element vector for chunk of elements
123820cf1dd8SToby Isaac 
123920cf1dd8SToby Isaac Input:
124020cf1dd8SToby Isaac   Sizes:
124120cf1dd8SToby Isaac      Ne:  number of elements
124220cf1dd8SToby Isaac      Nf:  number of fields
124320cf1dd8SToby Isaac      PetscFE
124420cf1dd8SToby Isaac        dim: spatial dimension
124520cf1dd8SToby Isaac        Nb:  number of basis functions
124620cf1dd8SToby Isaac        Nc:  number of field components
124720cf1dd8SToby Isaac        PetscQuadrature
124820cf1dd8SToby Isaac          Nq:  number of quadrature points
124920cf1dd8SToby Isaac 
125020cf1dd8SToby Isaac   Geometry:
125120cf1dd8SToby Isaac      PetscFEGeom[Ne] possibly *Nq
125220cf1dd8SToby Isaac        PetscReal v0s[dim]
125320cf1dd8SToby Isaac        PetscReal n[dim]
125420cf1dd8SToby Isaac        PetscReal jacobians[dim*dim]
125520cf1dd8SToby Isaac        PetscReal jacobianInverses[dim*dim]
125620cf1dd8SToby Isaac        PetscReal jacobianDeterminants
125720cf1dd8SToby Isaac   FEM:
125820cf1dd8SToby Isaac      PetscFE
125920cf1dd8SToby Isaac        PetscQuadrature
126020cf1dd8SToby Isaac          PetscReal   quadPoints[Nq*dim]
126120cf1dd8SToby Isaac          PetscReal   quadWeights[Nq]
126220cf1dd8SToby Isaac        PetscReal   basis[Nq*Nb*Nc]
126320cf1dd8SToby Isaac        PetscReal   basisDer[Nq*Nb*Nc*dim]
126420cf1dd8SToby Isaac      PetscScalar coefficients[Ne*Nb*Nc]
126520cf1dd8SToby Isaac      PetscScalar elemVec[Ne*Nb*Nc]
126620cf1dd8SToby Isaac 
126720cf1dd8SToby Isaac   Problem:
126820cf1dd8SToby Isaac      PetscInt f: the active field
126920cf1dd8SToby Isaac      f0, f1
127020cf1dd8SToby Isaac 
127120cf1dd8SToby Isaac   Work Space:
127220cf1dd8SToby Isaac      PetscFE
127320cf1dd8SToby Isaac        PetscScalar f0[Nq*dim];
127420cf1dd8SToby Isaac        PetscScalar f1[Nq*dim*dim];
127520cf1dd8SToby Isaac        PetscScalar u[Nc];
127620cf1dd8SToby Isaac        PetscScalar gradU[Nc*dim];
127720cf1dd8SToby Isaac        PetscReal   x[dim];
127820cf1dd8SToby Isaac        PetscScalar realSpaceDer[dim];
127920cf1dd8SToby Isaac 
128020cf1dd8SToby Isaac Purpose: Compute element vector for N_cb batches of elements
128120cf1dd8SToby Isaac 
128220cf1dd8SToby Isaac Input:
128320cf1dd8SToby Isaac   Sizes:
128420cf1dd8SToby Isaac      N_cb: Number of serial cell batches
128520cf1dd8SToby Isaac 
128620cf1dd8SToby Isaac   Geometry:
128720cf1dd8SToby Isaac      PetscReal v0s[Ne*dim]
128820cf1dd8SToby Isaac      PetscReal jacobians[Ne*dim*dim]        possibly *Nq
128920cf1dd8SToby Isaac      PetscReal jacobianInverses[Ne*dim*dim] possibly *Nq
129020cf1dd8SToby Isaac      PetscReal jacobianDeterminants[Ne]     possibly *Nq
129120cf1dd8SToby Isaac   FEM:
129220cf1dd8SToby Isaac      static PetscReal   quadPoints[Nq*dim]
129320cf1dd8SToby Isaac      static PetscReal   quadWeights[Nq]
129420cf1dd8SToby Isaac      static PetscReal   basis[Nq*Nb*Nc]
129520cf1dd8SToby Isaac      static PetscReal   basisDer[Nq*Nb*Nc*dim]
129620cf1dd8SToby Isaac      PetscScalar coefficients[Ne*Nb*Nc]
129720cf1dd8SToby Isaac      PetscScalar elemVec[Ne*Nb*Nc]
129820cf1dd8SToby Isaac 
129920cf1dd8SToby Isaac ex62.c:
130020cf1dd8SToby Isaac   PetscErrorCode PetscFEIntegrateResidualBatch(PetscInt Ne, PetscInt numFields, PetscInt field, PetscQuadrature quad[], const PetscScalar coefficients[],
130120cf1dd8SToby Isaac                                                const PetscReal v0s[], const PetscReal jacobians[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[],
130220cf1dd8SToby Isaac                                                void (*f0_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]),
130320cf1dd8SToby Isaac                                                void (*f1_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]), PetscScalar elemVec[])
130420cf1dd8SToby Isaac 
130520cf1dd8SToby Isaac ex52.c:
130620cf1dd8SToby 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)
130720cf1dd8SToby 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)
130820cf1dd8SToby Isaac 
130920cf1dd8SToby Isaac ex52_integrateElement.cu
131020cf1dd8SToby Isaac __global__ void integrateElementQuadrature(int N_cb, realType *coefficients, realType *jacobianInverses, realType *jacobianDeterminants, realType *elemVec)
131120cf1dd8SToby Isaac 
131220cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt Nbl, const PetscScalar coefficients[],
131320cf1dd8SToby Isaac                                                      const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[],
131420cf1dd8SToby Isaac                                                      PetscLogEvent event, PetscInt debug, PetscInt pde_op)
131520cf1dd8SToby Isaac 
131620cf1dd8SToby Isaac ex52_integrateElementOpenCL.c:
131720cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt N_bl, const PetscScalar coefficients[],
131820cf1dd8SToby Isaac                                                      const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[],
131920cf1dd8SToby Isaac                                                      PetscLogEvent event, PetscInt debug, PetscInt pde_op)
132020cf1dd8SToby Isaac 
132120cf1dd8SToby Isaac __kernel void integrateElementQuadrature(int N_cb, __global float *coefficients, __global float *jacobianInverses, __global float *jacobianDeterminants, __global float *elemVec)
132220cf1dd8SToby Isaac */
132320cf1dd8SToby Isaac 
132420cf1dd8SToby Isaac /*@C
132520cf1dd8SToby Isaac   PetscFEIntegrate - Produce the integral for the given field for a chunk of elements by quadrature integration
132620cf1dd8SToby Isaac 
132720cf1dd8SToby Isaac   Not collective
132820cf1dd8SToby Isaac 
132920cf1dd8SToby Isaac   Input Parameters:
1330360cf244SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
133120cf1dd8SToby Isaac . field        - The field being integrated
133220cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
133320cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
133420cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
133520cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
133620cf1dd8SToby Isaac - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
133720cf1dd8SToby Isaac 
13387a7aea1fSJed Brown   Output Parameter:
133920cf1dd8SToby Isaac . integral     - the integral for this field
134020cf1dd8SToby Isaac 
13412b99622eSMatthew G. Knepley   Level: intermediate
134220cf1dd8SToby Isaac 
134320cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
134420cf1dd8SToby Isaac @*/
13454bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrate(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom,
134620cf1dd8SToby Isaac                                 const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
134720cf1dd8SToby Isaac {
13484bee2e38SMatthew G. Knepley   PetscFE        fe;
134920cf1dd8SToby Isaac   PetscErrorCode ierr;
135020cf1dd8SToby Isaac 
135120cf1dd8SToby Isaac   PetscFunctionBegin;
13524bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
13534bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
13544bee2e38SMatthew G. Knepley   if (fe->ops->integrate) {ierr = (*fe->ops->integrate)(prob, field, Ne, cgeom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);}
135520cf1dd8SToby Isaac   PetscFunctionReturn(0);
135620cf1dd8SToby Isaac }
135720cf1dd8SToby Isaac 
135820cf1dd8SToby Isaac /*@C
1359afe6d6adSToby Isaac   PetscFEIntegrateBd - Produce the integral for the given field for a chunk of elements by quadrature integration
1360afe6d6adSToby Isaac 
1361afe6d6adSToby Isaac   Not collective
1362afe6d6adSToby Isaac 
1363afe6d6adSToby Isaac   Input Parameters:
1364360cf244SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
1365afe6d6adSToby Isaac . field        - The field being integrated
1366afe6d6adSToby Isaac . obj_func     - The function to be integrated
1367afe6d6adSToby Isaac . Ne           - The number of elements in the chunk
1368afe6d6adSToby Isaac . fgeom        - The face geometry for each face in the chunk
1369afe6d6adSToby Isaac . coefficients - The array of FEM basis coefficients for the elements
1370afe6d6adSToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
1371afe6d6adSToby Isaac - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1372afe6d6adSToby Isaac 
13737a7aea1fSJed Brown   Output Parameter:
1374afe6d6adSToby Isaac . integral     - the integral for this field
1375afe6d6adSToby Isaac 
13762b99622eSMatthew G. Knepley   Level: intermediate
1377afe6d6adSToby Isaac 
1378afe6d6adSToby Isaac .seealso: PetscFEIntegrateResidual()
1379afe6d6adSToby Isaac @*/
13804bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBd(PetscDS prob, PetscInt field,
1381afe6d6adSToby Isaac                                   void (*obj_func)(PetscInt, PetscInt, PetscInt,
1382afe6d6adSToby Isaac                                                    const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
1383afe6d6adSToby Isaac                                                    const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
1384afe6d6adSToby Isaac                                                    PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
1385afe6d6adSToby Isaac                                   PetscInt Ne, PetscFEGeom *geom, const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
1386afe6d6adSToby Isaac {
13874bee2e38SMatthew G. Knepley   PetscFE        fe;
1388afe6d6adSToby Isaac   PetscErrorCode ierr;
1389afe6d6adSToby Isaac 
1390afe6d6adSToby Isaac   PetscFunctionBegin;
13914bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
13924bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
13934bee2e38SMatthew G. Knepley   if (fe->ops->integratebd) {ierr = (*fe->ops->integratebd)(prob, field, obj_func, Ne, geom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);}
1394afe6d6adSToby Isaac   PetscFunctionReturn(0);
1395afe6d6adSToby Isaac }
1396afe6d6adSToby Isaac 
1397afe6d6adSToby Isaac /*@C
139820cf1dd8SToby Isaac   PetscFEIntegrateResidual - Produce the element residual vector for a chunk of elements by quadrature integration
139920cf1dd8SToby Isaac 
140020cf1dd8SToby Isaac   Not collective
140120cf1dd8SToby Isaac 
140220cf1dd8SToby Isaac   Input Parameters:
1403360cf244SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
140420cf1dd8SToby Isaac . field        - The field being integrated
140520cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
140620cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
140720cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
140820cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
140920cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
141020cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
141120cf1dd8SToby Isaac - t            - The time
141220cf1dd8SToby Isaac 
14137a7aea1fSJed Brown   Output Parameter:
141420cf1dd8SToby Isaac . elemVec      - the element residual vectors from each element
141520cf1dd8SToby Isaac 
141620cf1dd8SToby Isaac   Note:
141720cf1dd8SToby Isaac $ Loop over batch of elements (e):
141820cf1dd8SToby Isaac $   Loop over quadrature points (q):
141920cf1dd8SToby Isaac $     Make u_q and gradU_q (loops over fields,Nb,Ncomp) and x_q
142020cf1dd8SToby Isaac $     Call f_0 and f_1
142120cf1dd8SToby Isaac $   Loop over element vector entries (f,fc --> i):
142220cf1dd8SToby Isaac $     elemVec[i] += \psi^{fc}_f(q) f0_{fc}(u, \nabla u) + \nabla\psi^{fc}_f(q) \cdot f1_{fc,df}(u, \nabla u)
142320cf1dd8SToby Isaac 
14242b99622eSMatthew G. Knepley   Level: intermediate
142520cf1dd8SToby Isaac 
142620cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
142720cf1dd8SToby Isaac @*/
14284bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateResidual(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom,
142920cf1dd8SToby Isaac                                         const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
143020cf1dd8SToby Isaac {
14314bee2e38SMatthew G. Knepley   PetscFE        fe;
143220cf1dd8SToby Isaac   PetscErrorCode ierr;
143320cf1dd8SToby Isaac 
143420cf1dd8SToby Isaac   PetscFunctionBegin;
14354bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
14364bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
14374bee2e38SMatthew G. Knepley   if (fe->ops->integrateresidual) {ierr = (*fe->ops->integrateresidual)(prob, field, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
143820cf1dd8SToby Isaac   PetscFunctionReturn(0);
143920cf1dd8SToby Isaac }
144020cf1dd8SToby Isaac 
144120cf1dd8SToby Isaac /*@C
144220cf1dd8SToby Isaac   PetscFEIntegrateBdResidual - Produce the element residual vector for a chunk of elements by quadrature integration over a boundary
144320cf1dd8SToby Isaac 
144420cf1dd8SToby Isaac   Not collective
144520cf1dd8SToby Isaac 
144620cf1dd8SToby Isaac   Input Parameters:
1447360cf244SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
144820cf1dd8SToby Isaac . field        - The field being integrated
144920cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
145020cf1dd8SToby Isaac . fgeom        - The face geometry for each cell in the chunk
145120cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
145220cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
145320cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
145420cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
145520cf1dd8SToby Isaac - t            - The time
145620cf1dd8SToby Isaac 
14577a7aea1fSJed Brown   Output Parameter:
145820cf1dd8SToby Isaac . elemVec      - the element residual vectors from each element
145920cf1dd8SToby Isaac 
14602b99622eSMatthew G. Knepley   Level: intermediate
146120cf1dd8SToby Isaac 
146220cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
146320cf1dd8SToby Isaac @*/
14644bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBdResidual(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom,
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 
147020cf1dd8SToby Isaac   PetscFunctionBegin;
14714bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
14724bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
14734bee2e38SMatthew G. Knepley   if (fe->ops->integratebdresidual) {ierr = (*fe->ops->integratebdresidual)(prob, field, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
147420cf1dd8SToby Isaac   PetscFunctionReturn(0);
147520cf1dd8SToby Isaac }
147620cf1dd8SToby Isaac 
147720cf1dd8SToby Isaac /*@C
147827f02ce8SMatthew G. Knepley   PetscFEIntegrateHybridResidual - Produce the element residual vector for a chunk of hybrid element faces by quadrature integration
147927f02ce8SMatthew G. Knepley 
148027f02ce8SMatthew G. Knepley   Not collective
148127f02ce8SMatthew G. Knepley 
148227f02ce8SMatthew G. Knepley   Input Parameters:
148327f02ce8SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
148427f02ce8SMatthew G. Knepley . field        - The field being integrated
148527f02ce8SMatthew G. Knepley . Ne           - The number of elements in the chunk
148627f02ce8SMatthew G. Knepley . fgeom        - The face geometry for each cell in the chunk
148727f02ce8SMatthew G. Knepley . coefficients - The array of FEM basis coefficients for the elements
148827f02ce8SMatthew G. Knepley . coefficients_t - The array of FEM basis time derivative coefficients for the elements
148927f02ce8SMatthew G. Knepley . probAux      - The PetscDS specifying the auxiliary discretizations
149027f02ce8SMatthew G. Knepley . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
149127f02ce8SMatthew G. Knepley - t            - The time
149227f02ce8SMatthew G. Knepley 
149327f02ce8SMatthew G. Knepley   Output Parameter
149427f02ce8SMatthew G. Knepley . elemVec      - the element residual vectors from each element
149527f02ce8SMatthew G. Knepley 
149627f02ce8SMatthew G. Knepley   Level: developer
149727f02ce8SMatthew G. Knepley 
149827f02ce8SMatthew G. Knepley .seealso: PetscFEIntegrateResidual()
149927f02ce8SMatthew G. Knepley @*/
150027f02ce8SMatthew G. Knepley PetscErrorCode PetscFEIntegrateHybridResidual(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom,
150127f02ce8SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
150227f02ce8SMatthew G. Knepley {
150327f02ce8SMatthew G. Knepley   PetscFE        fe;
150427f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
150527f02ce8SMatthew G. Knepley 
150627f02ce8SMatthew G. Knepley   PetscFunctionBegin;
150727f02ce8SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
150827f02ce8SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
150927f02ce8SMatthew G. Knepley   if (fe->ops->integratehybridresidual) {ierr = (*fe->ops->integratehybridresidual)(prob, field, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
151027f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
151127f02ce8SMatthew G. Knepley }
151227f02ce8SMatthew G. Knepley 
151327f02ce8SMatthew G. Knepley /*@C
151420cf1dd8SToby Isaac   PetscFEIntegrateJacobian - Produce the element Jacobian for a chunk of elements by quadrature integration
151520cf1dd8SToby Isaac 
151620cf1dd8SToby Isaac   Not collective
151720cf1dd8SToby Isaac 
151820cf1dd8SToby Isaac   Input Parameters:
1519360cf244SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
152020cf1dd8SToby Isaac . jtype        - The type of matrix pointwise functions that should be used
152120cf1dd8SToby Isaac . fieldI       - The test field being integrated
152220cf1dd8SToby Isaac . fieldJ       - The basis field being integrated
152320cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
152420cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
152520cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
152620cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
152720cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
152820cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
152920cf1dd8SToby Isaac . t            - The time
153020cf1dd8SToby Isaac - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
153120cf1dd8SToby Isaac 
15327a7aea1fSJed Brown   Output Parameter:
153320cf1dd8SToby Isaac . elemMat      - the element matrices for the Jacobian from each element
153420cf1dd8SToby Isaac 
153520cf1dd8SToby Isaac   Note:
153620cf1dd8SToby Isaac $ Loop over batch of elements (e):
153720cf1dd8SToby Isaac $   Loop over element matrix entries (f,fc,g,gc --> i,j):
153820cf1dd8SToby Isaac $     Loop over quadrature points (q):
153920cf1dd8SToby Isaac $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
154020cf1dd8SToby Isaac $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
154120cf1dd8SToby Isaac $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
154220cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
154320cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
15442b99622eSMatthew G. Knepley   Level: intermediate
154520cf1dd8SToby Isaac 
154620cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
154720cf1dd8SToby Isaac @*/
15484bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateJacobian(PetscDS prob, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *cgeom,
154920cf1dd8SToby Isaac                                         const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
155020cf1dd8SToby Isaac {
15514bee2e38SMatthew G. Knepley   PetscFE        fe;
155220cf1dd8SToby Isaac   PetscErrorCode ierr;
155320cf1dd8SToby Isaac 
155420cf1dd8SToby Isaac   PetscFunctionBegin;
15554bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
15564bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
15574bee2e38SMatthew G. Knepley   if (fe->ops->integratejacobian) {ierr = (*fe->ops->integratejacobian)(prob, jtype, fieldI, fieldJ, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);}
155820cf1dd8SToby Isaac   PetscFunctionReturn(0);
155920cf1dd8SToby Isaac }
156020cf1dd8SToby Isaac 
156120cf1dd8SToby Isaac /*@C
156220cf1dd8SToby Isaac   PetscFEIntegrateBdJacobian - Produce the boundary element Jacobian for a chunk of elements by quadrature integration
156320cf1dd8SToby Isaac 
156420cf1dd8SToby Isaac   Not collective
156520cf1dd8SToby Isaac 
156620cf1dd8SToby Isaac   Input Parameters:
1567f0fc11ceSJed Brown + prob         - The PetscDS specifying the discretizations and continuum functions
156820cf1dd8SToby Isaac . fieldI       - The test field being integrated
156920cf1dd8SToby Isaac . fieldJ       - The basis field being integrated
157020cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
157120cf1dd8SToby Isaac . fgeom        - The face geometry for each cell in the chunk
157220cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
157320cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
157420cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
157520cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
157620cf1dd8SToby Isaac . t            - The time
157720cf1dd8SToby Isaac - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
157820cf1dd8SToby Isaac 
15797a7aea1fSJed Brown   Output Parameter:
158020cf1dd8SToby Isaac . elemMat              - the element matrices for the Jacobian from each element
158120cf1dd8SToby Isaac 
158220cf1dd8SToby Isaac   Note:
158320cf1dd8SToby Isaac $ Loop over batch of elements (e):
158420cf1dd8SToby Isaac $   Loop over element matrix entries (f,fc,g,gc --> i,j):
158520cf1dd8SToby Isaac $     Loop over quadrature points (q):
158620cf1dd8SToby Isaac $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
158720cf1dd8SToby Isaac $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
158820cf1dd8SToby Isaac $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
158920cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
159020cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
15912b99622eSMatthew G. Knepley   Level: intermediate
159220cf1dd8SToby Isaac 
159320cf1dd8SToby Isaac .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual()
159420cf1dd8SToby Isaac @*/
15954bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBdJacobian(PetscDS prob, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
159620cf1dd8SToby Isaac                                           const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
159720cf1dd8SToby Isaac {
15984bee2e38SMatthew G. Knepley   PetscFE        fe;
159920cf1dd8SToby Isaac   PetscErrorCode ierr;
160020cf1dd8SToby Isaac 
160120cf1dd8SToby Isaac   PetscFunctionBegin;
16024bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
16034bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
16044bee2e38SMatthew G. Knepley   if (fe->ops->integratebdjacobian) {ierr = (*fe->ops->integratebdjacobian)(prob, fieldI, fieldJ, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);}
160520cf1dd8SToby Isaac   PetscFunctionReturn(0);
160620cf1dd8SToby Isaac }
160720cf1dd8SToby Isaac 
160827f02ce8SMatthew G. Knepley /*@C
160927f02ce8SMatthew G. Knepley   PetscFEIntegrateHybridJacobian - Produce the boundary element Jacobian for a chunk of hybrid elements by quadrature integration
161027f02ce8SMatthew G. Knepley 
161127f02ce8SMatthew G. Knepley   Not collective
161227f02ce8SMatthew G. Knepley 
161327f02ce8SMatthew G. Knepley   Input Parameters:
161427f02ce8SMatthew G. Knepley . prob         - The PetscDS specifying the discretizations and continuum functions
161527f02ce8SMatthew G. Knepley . jtype        - The type of matrix pointwise functions that should be used
161627f02ce8SMatthew G. Knepley . fieldI       - The test field being integrated
161727f02ce8SMatthew G. Knepley . fieldJ       - The basis field being integrated
161827f02ce8SMatthew G. Knepley . Ne           - The number of elements in the chunk
161927f02ce8SMatthew G. Knepley . fgeom        - The face geometry for each cell in the chunk
162027f02ce8SMatthew G. Knepley . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
162127f02ce8SMatthew G. Knepley . coefficients_t - The array of FEM basis time derivative coefficients for the elements
162227f02ce8SMatthew G. Knepley . probAux      - The PetscDS specifying the auxiliary discretizations
162327f02ce8SMatthew G. Knepley . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
162427f02ce8SMatthew G. Knepley . t            - The time
162527f02ce8SMatthew G. Knepley - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
162627f02ce8SMatthew G. Knepley 
162727f02ce8SMatthew G. Knepley   Output Parameter
162827f02ce8SMatthew G. Knepley . elemMat              - the element matrices for the Jacobian from each element
162927f02ce8SMatthew G. Knepley 
163027f02ce8SMatthew G. Knepley   Note:
163127f02ce8SMatthew G. Knepley $ Loop over batch of elements (e):
163227f02ce8SMatthew G. Knepley $   Loop over element matrix entries (f,fc,g,gc --> i,j):
163327f02ce8SMatthew G. Knepley $     Loop over quadrature points (q):
163427f02ce8SMatthew G. Knepley $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
163527f02ce8SMatthew G. Knepley $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
163627f02ce8SMatthew G. Knepley $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
163727f02ce8SMatthew G. Knepley $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
163827f02ce8SMatthew G. Knepley $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
163927f02ce8SMatthew G. Knepley   Level: developer
164027f02ce8SMatthew G. Knepley 
164127f02ce8SMatthew G. Knepley .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual()
164227f02ce8SMatthew G. Knepley @*/
164327f02ce8SMatthew G. Knepley PetscErrorCode PetscFEIntegrateHybridJacobian(PetscDS prob, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
164427f02ce8SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
164527f02ce8SMatthew G. Knepley {
164627f02ce8SMatthew G. Knepley   PetscFE        fe;
164727f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
164827f02ce8SMatthew G. Knepley 
164927f02ce8SMatthew G. Knepley   PetscFunctionBegin;
165027f02ce8SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
165127f02ce8SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
165227f02ce8SMatthew G. Knepley   if (fe->ops->integratehybridjacobian) {ierr = (*fe->ops->integratehybridjacobian)(prob, jtype, fieldI, fieldJ, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);}
165327f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
165427f02ce8SMatthew G. Knepley }
165527f02ce8SMatthew G. Knepley 
16562b99622eSMatthew G. Knepley /*@
16572b99622eSMatthew G. Knepley   PetscFEGetHeightSubspace - Get the subspace of this space for a mesh point of a given height
16582b99622eSMatthew G. Knepley 
16592b99622eSMatthew G. Knepley   Input Parameters:
16602b99622eSMatthew G. Knepley + fe     - The finite element space
16612b99622eSMatthew G. Knepley - height - The height of the Plex point
16622b99622eSMatthew G. Knepley 
16632b99622eSMatthew G. Knepley   Output Parameter:
16642b99622eSMatthew G. Knepley . subfe  - The subspace of this FE space
16652b99622eSMatthew G. Knepley 
16662b99622eSMatthew G. Knepley   Note: For example, if we want the subspace of this space for a face, we would choose height = 1.
16672b99622eSMatthew G. Knepley 
16682b99622eSMatthew G. Knepley   Level: advanced
16692b99622eSMatthew G. Knepley 
16702b99622eSMatthew G. Knepley .seealso: PetscFECreateDefault()
16712b99622eSMatthew G. Knepley @*/
167220cf1dd8SToby Isaac PetscErrorCode PetscFEGetHeightSubspace(PetscFE fe, PetscInt height, PetscFE *subfe)
167320cf1dd8SToby Isaac {
167420cf1dd8SToby Isaac   PetscSpace      P, subP;
167520cf1dd8SToby Isaac   PetscDualSpace  Q, subQ;
167620cf1dd8SToby Isaac   PetscQuadrature subq;
167720cf1dd8SToby Isaac   PetscFEType     fetype;
167820cf1dd8SToby Isaac   PetscInt        dim, Nc;
167920cf1dd8SToby Isaac   PetscErrorCode  ierr;
168020cf1dd8SToby Isaac 
168120cf1dd8SToby Isaac   PetscFunctionBegin;
168220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe, PETSCFE_CLASSID, 1);
168320cf1dd8SToby Isaac   PetscValidPointer(subfe, 3);
168420cf1dd8SToby Isaac   if (height == 0) {
168520cf1dd8SToby Isaac     *subfe = fe;
168620cf1dd8SToby Isaac     PetscFunctionReturn(0);
168720cf1dd8SToby Isaac   }
168820cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
168920cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
169020cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr);
169120cf1dd8SToby Isaac   ierr = PetscFEGetFaceQuadrature(fe, &subq);CHKERRQ(ierr);
169220cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDimension(Q, &dim);CHKERRQ(ierr);
169320cf1dd8SToby Isaac   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);}
169420cf1dd8SToby Isaac   if (!fe->subspaces) {ierr = PetscCalloc1(dim, &fe->subspaces);CHKERRQ(ierr);}
169520cf1dd8SToby Isaac   if (height <= dim) {
169620cf1dd8SToby Isaac     if (!fe->subspaces[height-1]) {
1697665f567fSMatthew G. Knepley       PetscFE     sub = NULL;
16983f6b16c7SMatthew G. Knepley       const char *name;
169920cf1dd8SToby Isaac 
170020cf1dd8SToby Isaac       ierr = PetscSpaceGetHeightSubspace(P, height, &subP);CHKERRQ(ierr);
170120cf1dd8SToby Isaac       ierr = PetscDualSpaceGetHeightSubspace(Q, height, &subQ);CHKERRQ(ierr);
1702665f567fSMatthew G. Knepley       if (subQ) {
170320cf1dd8SToby Isaac         ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), &sub);CHKERRQ(ierr);
17043f6b16c7SMatthew G. Knepley         ierr = PetscObjectGetName((PetscObject) fe,  &name);CHKERRQ(ierr);
17053f6b16c7SMatthew G. Knepley         ierr = PetscObjectSetName((PetscObject) sub,  name);CHKERRQ(ierr);
170620cf1dd8SToby Isaac         ierr = PetscFEGetType(fe, &fetype);CHKERRQ(ierr);
170720cf1dd8SToby Isaac         ierr = PetscFESetType(sub, fetype);CHKERRQ(ierr);
170820cf1dd8SToby Isaac         ierr = PetscFESetBasisSpace(sub, subP);CHKERRQ(ierr);
170920cf1dd8SToby Isaac         ierr = PetscFESetDualSpace(sub, subQ);CHKERRQ(ierr);
171020cf1dd8SToby Isaac         ierr = PetscFESetNumComponents(sub, Nc);CHKERRQ(ierr);
171120cf1dd8SToby Isaac         ierr = PetscFESetUp(sub);CHKERRQ(ierr);
171220cf1dd8SToby Isaac         ierr = PetscFESetQuadrature(sub, subq);CHKERRQ(ierr);
1713665f567fSMatthew G. Knepley       }
171420cf1dd8SToby Isaac       fe->subspaces[height-1] = sub;
171520cf1dd8SToby Isaac     }
171620cf1dd8SToby Isaac     *subfe = fe->subspaces[height-1];
171720cf1dd8SToby Isaac   } else {
171820cf1dd8SToby Isaac     *subfe = NULL;
171920cf1dd8SToby Isaac   }
172020cf1dd8SToby Isaac   PetscFunctionReturn(0);
172120cf1dd8SToby Isaac }
172220cf1dd8SToby Isaac 
172320cf1dd8SToby Isaac /*@
172420cf1dd8SToby Isaac   PetscFERefine - Create a "refined" PetscFE object that refines the reference cell into smaller copies. This is typically used
172520cf1dd8SToby Isaac   to precondition a higher order method with a lower order method on a refined mesh having the same number of dofs (but more
172620cf1dd8SToby Isaac   sparsity). It is also used to create an interpolation between regularly refined meshes.
172720cf1dd8SToby Isaac 
1728d083f849SBarry Smith   Collective on fem
172920cf1dd8SToby Isaac 
173020cf1dd8SToby Isaac   Input Parameter:
173120cf1dd8SToby Isaac . fe - The initial PetscFE
173220cf1dd8SToby Isaac 
173320cf1dd8SToby Isaac   Output Parameter:
173420cf1dd8SToby Isaac . feRef - The refined PetscFE
173520cf1dd8SToby Isaac 
17362b99622eSMatthew G. Knepley   Level: advanced
173720cf1dd8SToby Isaac 
173820cf1dd8SToby Isaac .seealso: PetscFEType, PetscFECreate(), PetscFESetType()
173920cf1dd8SToby Isaac @*/
174020cf1dd8SToby Isaac PetscErrorCode PetscFERefine(PetscFE fe, PetscFE *feRef)
174120cf1dd8SToby Isaac {
174220cf1dd8SToby Isaac   PetscSpace       P, Pref;
174320cf1dd8SToby Isaac   PetscDualSpace   Q, Qref;
174420cf1dd8SToby Isaac   DM               K, Kref;
174520cf1dd8SToby Isaac   PetscQuadrature  q, qref;
174620cf1dd8SToby Isaac   const PetscReal *v0, *jac;
174720cf1dd8SToby Isaac   PetscInt         numComp, numSubelements;
17481ac17e89SToby Isaac   PetscInt         cStart, cEnd, c;
17491ac17e89SToby Isaac   PetscDualSpace  *cellSpaces;
175020cf1dd8SToby Isaac   PetscErrorCode   ierr;
175120cf1dd8SToby Isaac 
175220cf1dd8SToby Isaac   PetscFunctionBegin;
175320cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
175420cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
175520cf1dd8SToby Isaac   ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr);
175620cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(Q, &K);CHKERRQ(ierr);
175720cf1dd8SToby Isaac   /* Create space */
175820cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) P);CHKERRQ(ierr);
175920cf1dd8SToby Isaac   Pref = P;
176020cf1dd8SToby Isaac   /* Create dual space */
176120cf1dd8SToby Isaac   ierr = PetscDualSpaceDuplicate(Q, &Qref);CHKERRQ(ierr);
17621ac17e89SToby Isaac   ierr = PetscDualSpaceSetType(Qref, PETSCDUALSPACEREFINED);CHKERRQ(ierr);
176320cf1dd8SToby Isaac   ierr = DMRefine(K, PetscObjectComm((PetscObject) fe), &Kref);CHKERRQ(ierr);
176420cf1dd8SToby Isaac   ierr = PetscDualSpaceSetDM(Qref, Kref);CHKERRQ(ierr);
17651ac17e89SToby Isaac   ierr = DMPlexGetHeightStratum(Kref, 0, &cStart, &cEnd);CHKERRQ(ierr);
17661ac17e89SToby Isaac   ierr = PetscMalloc1(cEnd - cStart, &cellSpaces);CHKERRQ(ierr);
17671ac17e89SToby Isaac   /* TODO: fix for non-uniform refinement */
17681ac17e89SToby Isaac   for (c = 0; c < cEnd - cStart; c++) cellSpaces[c] = Q;
17691ac17e89SToby Isaac   ierr = PetscDualSpaceRefinedSetCellSpaces(Qref, cellSpaces);CHKERRQ(ierr);
17701ac17e89SToby Isaac   ierr = PetscFree(cellSpaces);CHKERRQ(ierr);
177120cf1dd8SToby Isaac   ierr = DMDestroy(&Kref);CHKERRQ(ierr);
177220cf1dd8SToby Isaac   ierr = PetscDualSpaceSetUp(Qref);CHKERRQ(ierr);
177320cf1dd8SToby Isaac   /* Create element */
177420cf1dd8SToby Isaac   ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), feRef);CHKERRQ(ierr);
177520cf1dd8SToby Isaac   ierr = PetscFESetType(*feRef, PETSCFECOMPOSITE);CHKERRQ(ierr);
177620cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*feRef, Pref);CHKERRQ(ierr);
177720cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*feRef, Qref);CHKERRQ(ierr);
177820cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe,    &numComp);CHKERRQ(ierr);
177920cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*feRef, numComp);CHKERRQ(ierr);
178020cf1dd8SToby Isaac   ierr = PetscFESetUp(*feRef);CHKERRQ(ierr);
178120cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&Pref);CHKERRQ(ierr);
178220cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&Qref);CHKERRQ(ierr);
178320cf1dd8SToby Isaac   /* Create quadrature */
178420cf1dd8SToby Isaac   ierr = PetscFECompositeGetMapping(*feRef, &numSubelements, &v0, &jac, NULL);CHKERRQ(ierr);
178520cf1dd8SToby Isaac   ierr = PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref);CHKERRQ(ierr);
178620cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*feRef, qref);CHKERRQ(ierr);
178720cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&qref);CHKERRQ(ierr);
178820cf1dd8SToby Isaac   PetscFunctionReturn(0);
178920cf1dd8SToby Isaac }
179020cf1dd8SToby Isaac 
179120cf1dd8SToby Isaac /*@C
179220cf1dd8SToby Isaac   PetscFECreateDefault - Create a PetscFE for basic FEM computation
179320cf1dd8SToby Isaac 
1794d083f849SBarry Smith   Collective
179520cf1dd8SToby Isaac 
179620cf1dd8SToby Isaac   Input Parameters:
17977be5e748SToby Isaac + comm      - The MPI comm
179820cf1dd8SToby Isaac . dim       - The spatial dimension
179920cf1dd8SToby Isaac . Nc        - The number of components
180020cf1dd8SToby Isaac . isSimplex - Flag for simplex reference cell, otherwise its a tensor product
180120cf1dd8SToby Isaac . prefix    - The options prefix, or NULL
1802727cddd5SJacob Faibussowitsch - qorder    - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree
180320cf1dd8SToby Isaac 
180420cf1dd8SToby Isaac   Output Parameter:
180520cf1dd8SToby Isaac . fem - The PetscFE object
180620cf1dd8SToby Isaac 
1807e703855dSMatthew G. Knepley   Note:
1808e703855dSMatthew G. Knepley   Each object is SetFromOption() during creation, so that the object may be customized from the command line.
1809e703855dSMatthew G. Knepley 
181020cf1dd8SToby Isaac   Level: beginner
181120cf1dd8SToby Isaac 
181220cf1dd8SToby Isaac .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
181320cf1dd8SToby Isaac @*/
18147be5e748SToby Isaac PetscErrorCode PetscFECreateDefault(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, const char prefix[], PetscInt qorder, PetscFE *fem)
181520cf1dd8SToby Isaac {
181620cf1dd8SToby Isaac   PetscQuadrature q, fq;
181720cf1dd8SToby Isaac   DM              K;
181820cf1dd8SToby Isaac   PetscSpace      P;
181920cf1dd8SToby Isaac   PetscDualSpace  Q;
182020cf1dd8SToby Isaac   PetscInt        order, quadPointsPerEdge;
182120cf1dd8SToby Isaac   PetscBool       tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
182220cf1dd8SToby Isaac   PetscErrorCode  ierr;
182320cf1dd8SToby Isaac 
182420cf1dd8SToby Isaac   PetscFunctionBegin;
182520cf1dd8SToby Isaac   /* Create space */
18267be5e748SToby Isaac   ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr);
182720cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix);CHKERRQ(ierr);
182820cf1dd8SToby Isaac   ierr = PetscSpacePolynomialSetTensor(P, tensor);CHKERRQ(ierr);
182920cf1dd8SToby Isaac   ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr);
183020cf1dd8SToby Isaac   ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr);
1831028afddaSToby Isaac   ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr);
183220cf1dd8SToby Isaac   ierr = PetscSpaceSetUp(P);CHKERRQ(ierr);
183320cf1dd8SToby Isaac   ierr = PetscSpaceGetDegree(P, &order, NULL);CHKERRQ(ierr);
183420cf1dd8SToby Isaac   ierr = PetscSpacePolynomialGetTensor(P, &tensor);CHKERRQ(ierr);
183520cf1dd8SToby Isaac   /* Create dual space */
18367be5e748SToby Isaac   ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr);
183720cf1dd8SToby Isaac   ierr = PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
183820cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);CHKERRQ(ierr);
183920cf1dd8SToby Isaac   ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr);
184020cf1dd8SToby Isaac   ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr);
184120cf1dd8SToby Isaac   ierr = DMDestroy(&K);CHKERRQ(ierr);
184220cf1dd8SToby Isaac   ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr);
184320cf1dd8SToby Isaac   ierr = PetscDualSpaceSetOrder(Q, order);CHKERRQ(ierr);
184420cf1dd8SToby Isaac   ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor);CHKERRQ(ierr);
184520cf1dd8SToby Isaac   ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr);
184620cf1dd8SToby Isaac   ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr);
184720cf1dd8SToby Isaac   /* Create element */
18487be5e748SToby Isaac   ierr = PetscFECreate(comm, fem);CHKERRQ(ierr);
184920cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);CHKERRQ(ierr);
185020cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr);
185120cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr);
185220cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr);
185391e89cf0SMatthew G. Knepley   ierr = PetscFESetFromOptions(*fem);CHKERRQ(ierr);
185420cf1dd8SToby Isaac   ierr = PetscFESetUp(*fem);CHKERRQ(ierr);
185520cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr);
185620cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr);
185720cf1dd8SToby Isaac   /* Create quadrature (with specified order if given) */
185820cf1dd8SToby Isaac   qorder = qorder >= 0 ? qorder : order;
185920cf1dd8SToby Isaac   ierr = PetscObjectOptionsBegin((PetscObject)*fem);CHKERRQ(ierr);
18605a856986SBarry Smith   ierr = PetscOptionsBoundedInt("-petscfe_default_quadrature_order","Quadrature order is one less than quadrature points per edge","PetscFECreateDefault",qorder,&qorder,NULL,0);CHKERRQ(ierr);
186120cf1dd8SToby Isaac   ierr = PetscOptionsEnd();CHKERRQ(ierr);
186220cf1dd8SToby Isaac   quadPointsPerEdge = PetscMax(qorder + 1,1);
186320cf1dd8SToby Isaac   if (isSimplex) {
1864e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
1865e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
18664ccfa306SStefano Zampini   } else {
186720cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
186820cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
186920cf1dd8SToby Isaac   }
187020cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr);
187120cf1dd8SToby Isaac   ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr);
187220cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr);
187320cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr);
187420cf1dd8SToby Isaac   PetscFunctionReturn(0);
187520cf1dd8SToby Isaac }
18763f6b16c7SMatthew G. Knepley 
1877e703855dSMatthew G. Knepley /*@
1878e703855dSMatthew G. Knepley   PetscFECreateLagrange - Create a PetscFE for the basic Lagrange space of degree k
1879e703855dSMatthew G. Knepley 
1880e703855dSMatthew G. Knepley   Collective
1881e703855dSMatthew G. Knepley 
1882e703855dSMatthew G. Knepley   Input Parameters:
1883e703855dSMatthew G. Knepley + comm      - The MPI comm
1884e703855dSMatthew G. Knepley . dim       - The spatial dimension
1885e703855dSMatthew G. Knepley . Nc        - The number of components
1886e703855dSMatthew G. Knepley . isSimplex - Flag for simplex reference cell, otherwise its a tensor product
1887e703855dSMatthew G. Knepley . k         - The degree k of the space
1888e703855dSMatthew G. Knepley - qorder    - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree
1889e703855dSMatthew G. Knepley 
1890e703855dSMatthew G. Knepley   Output Parameter:
1891e703855dSMatthew G. Knepley . fem       - The PetscFE object
1892e703855dSMatthew G. Knepley 
1893e703855dSMatthew G. Knepley   Level: beginner
1894e703855dSMatthew G. Knepley 
1895e703855dSMatthew G. Knepley   Notes:
1896e703855dSMatthew 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.
1897e703855dSMatthew G. Knepley 
1898e703855dSMatthew G. Knepley .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
1899e703855dSMatthew G. Knepley @*/
1900e703855dSMatthew G. Knepley PetscErrorCode PetscFECreateLagrange(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, PetscInt k, PetscInt qorder, PetscFE *fem)
1901e703855dSMatthew G. Knepley {
1902e703855dSMatthew G. Knepley   PetscQuadrature q, fq;
1903e703855dSMatthew G. Knepley   DM              K;
1904e703855dSMatthew G. Knepley   PetscSpace      P;
1905e703855dSMatthew G. Knepley   PetscDualSpace  Q;
1906e703855dSMatthew G. Knepley   PetscInt        quadPointsPerEdge;
1907e703855dSMatthew G. Knepley   PetscBool       tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1908e703855dSMatthew G. Knepley   char            name[64];
1909e703855dSMatthew G. Knepley   PetscErrorCode  ierr;
1910e703855dSMatthew G. Knepley 
1911e703855dSMatthew G. Knepley   PetscFunctionBegin;
1912e703855dSMatthew G. Knepley   /* Create space */
1913e703855dSMatthew G. Knepley   ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr);
1914e703855dSMatthew G. Knepley   ierr = PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr);
1915e703855dSMatthew G. Knepley   ierr = PetscSpacePolynomialSetTensor(P, tensor);CHKERRQ(ierr);
1916e703855dSMatthew G. Knepley   ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr);
1917e703855dSMatthew G. Knepley   ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr);
1918e703855dSMatthew G. Knepley   ierr = PetscSpaceSetDegree(P, k, PETSC_DETERMINE);CHKERRQ(ierr);
1919e703855dSMatthew G. Knepley   ierr = PetscSpaceSetUp(P);CHKERRQ(ierr);
1920e703855dSMatthew G. Knepley   /* Create dual space */
1921e703855dSMatthew G. Knepley   ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr);
1922e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
1923e703855dSMatthew G. Knepley   ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr);
1924e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr);
1925e703855dSMatthew G. Knepley   ierr = DMDestroy(&K);CHKERRQ(ierr);
1926e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr);
1927e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetOrder(Q, k);CHKERRQ(ierr);
1928e703855dSMatthew G. Knepley   ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor);CHKERRQ(ierr);
1929e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr);
1930849618d6SLisandro Dalcin   /* Create finite element */
1931e703855dSMatthew G. Knepley   ierr = PetscFECreate(comm, fem);CHKERRQ(ierr);
1932e703855dSMatthew G. Knepley   ierr = PetscFESetType(*fem, PETSCFEBASIC);CHKERRQ(ierr);
1933e703855dSMatthew G. Knepley   ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr);
1934e703855dSMatthew G. Knepley   ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr);
1935e703855dSMatthew G. Knepley   ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr);
1936e703855dSMatthew G. Knepley   ierr = PetscFESetUp(*fem);CHKERRQ(ierr);
1937e703855dSMatthew G. Knepley   ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr);
1938e703855dSMatthew G. Knepley   ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr);
1939e703855dSMatthew G. Knepley   /* Create quadrature (with specified order if given) */
1940e703855dSMatthew G. Knepley   qorder = qorder >= 0 ? qorder : k;
1941e703855dSMatthew G. Knepley   quadPointsPerEdge = PetscMax(qorder + 1,1);
1942e703855dSMatthew G. Knepley   if (isSimplex) {
1943e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
1944e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
1945e703855dSMatthew G. Knepley   } else {
1946e703855dSMatthew G. Knepley     ierr = PetscDTGaussTensorQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
1947e703855dSMatthew G. Knepley     ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
1948e703855dSMatthew G. Knepley   }
1949e703855dSMatthew G. Knepley   ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr);
1950e703855dSMatthew G. Knepley   ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr);
1951e703855dSMatthew G. Knepley   ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr);
1952e703855dSMatthew G. Knepley   ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr);
1953849618d6SLisandro Dalcin   /* Set finite element name */
1954849618d6SLisandro Dalcin   ierr = PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);CHKERRQ(ierr);
1955849618d6SLisandro Dalcin   ierr = PetscFESetName(*fem, name);CHKERRQ(ierr);
1956e703855dSMatthew G. Knepley   PetscFunctionReturn(0);
1957e703855dSMatthew G. Knepley }
1958e703855dSMatthew G. Knepley 
19593f6b16c7SMatthew G. Knepley /*@C
19603f6b16c7SMatthew G. Knepley   PetscFESetName - Names the FE and its subobjects
19613f6b16c7SMatthew G. Knepley 
19623f6b16c7SMatthew G. Knepley   Not collective
19633f6b16c7SMatthew G. Knepley 
19643f6b16c7SMatthew G. Knepley   Input Parameters:
19653f6b16c7SMatthew G. Knepley + fe   - The PetscFE
19663f6b16c7SMatthew G. Knepley - name - The name
19673f6b16c7SMatthew G. Knepley 
19682b99622eSMatthew G. Knepley   Level: intermediate
19693f6b16c7SMatthew G. Knepley 
19703f6b16c7SMatthew G. Knepley .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
19713f6b16c7SMatthew G. Knepley @*/
19723f6b16c7SMatthew G. Knepley PetscErrorCode PetscFESetName(PetscFE fe, const char name[])
19733f6b16c7SMatthew G. Knepley {
19743f6b16c7SMatthew G. Knepley   PetscSpace     P;
19753f6b16c7SMatthew G. Knepley   PetscDualSpace Q;
19763f6b16c7SMatthew G. Knepley   PetscErrorCode ierr;
19773f6b16c7SMatthew G. Knepley 
19783f6b16c7SMatthew G. Knepley   PetscFunctionBegin;
19793f6b16c7SMatthew G. Knepley   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
19803f6b16c7SMatthew G. Knepley   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
19813f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) fe, name);CHKERRQ(ierr);
19823f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) P,  name);CHKERRQ(ierr);
19833f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) Q,  name);CHKERRQ(ierr);
19843f6b16c7SMatthew G. Knepley   PetscFunctionReturn(0);
19853f6b16c7SMatthew G. Knepley }
1986a8f1f9e5SMatthew G. Knepley 
1987ef0bb6c7SMatthew 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[])
1988a8f1f9e5SMatthew G. Knepley {
1989a8f1f9e5SMatthew G. Knepley   PetscInt       dOffset = 0, fOffset = 0, f;
1990a8f1f9e5SMatthew G. Knepley   PetscErrorCode ierr;
1991a8f1f9e5SMatthew G. Knepley 
1992a8f1f9e5SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
1993a8f1f9e5SMatthew G. Knepley     PetscFE          fe;
1994ef0bb6c7SMatthew G. Knepley     const PetscInt   cdim = T[f]->cdim;
1995ef0bb6c7SMatthew G. Knepley     const PetscInt   Nq   = T[f]->Np;
1996ef0bb6c7SMatthew G. Knepley     const PetscInt   Nbf  = T[f]->Nb;
1997ef0bb6c7SMatthew G. Knepley     const PetscInt   Ncf  = T[f]->Nc;
1998ef0bb6c7SMatthew G. Knepley     const PetscReal *Bq   = &T[f]->T[0][(r*Nq+q)*Nbf*Ncf];
1999ef0bb6c7SMatthew G. Knepley     const PetscReal *Dq   = &T[f]->T[1][(r*Nq+q)*Nbf*Ncf*cdim];
2000a8f1f9e5SMatthew G. Knepley     PetscInt         b, c, d;
2001a8f1f9e5SMatthew G. Knepley 
2002a8f1f9e5SMatthew G. Knepley     ierr = PetscDSGetDiscretization(ds, f, (PetscObject *) &fe);CHKERRQ(ierr);
2003a8f1f9e5SMatthew G. Knepley     for (c = 0; c < Ncf; ++c) u[fOffset+c] = 0.0;
2004ef0bb6c7SMatthew G. Knepley     for (d = 0; d < cdim*Ncf; ++d) u_x[fOffset*cdim+d] = 0.0;
2005a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nbf; ++b) {
2006a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) {
2007a8f1f9e5SMatthew G. Knepley         const PetscInt cidx = b*Ncf+c;
2008a8f1f9e5SMatthew G. Knepley 
2009a8f1f9e5SMatthew G. Knepley         u[fOffset+c] += Bq[cidx]*coefficients[dOffset+b];
2010ef0bb6c7SMatthew G. Knepley         for (d = 0; d < cdim; ++d) u_x[(fOffset+c)*cdim+d] += Dq[cidx*cdim+d]*coefficients[dOffset+b];
2011a8f1f9e5SMatthew G. Knepley       }
2012a8f1f9e5SMatthew G. Knepley     }
20132edcad52SToby Isaac     ierr = PetscFEPushforward(fe, fegeom, 1, &u[fOffset]);CHKERRQ(ierr);
20142edcad52SToby Isaac     ierr = PetscFEPushforwardGradient(fe, fegeom, 1, &u_x[fOffset*cdim]);CHKERRQ(ierr);
2015a8f1f9e5SMatthew G. Knepley     if (u_t) {
2016a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) u_t[fOffset+c] = 0.0;
2017a8f1f9e5SMatthew G. Knepley       for (b = 0; b < Nbf; ++b) {
2018a8f1f9e5SMatthew G. Knepley         for (c = 0; c < Ncf; ++c) {
2019a8f1f9e5SMatthew G. Knepley           const PetscInt cidx = b*Ncf+c;
2020a8f1f9e5SMatthew G. Knepley 
2021a8f1f9e5SMatthew G. Knepley           u_t[fOffset+c] += Bq[cidx]*coefficients_t[dOffset+b];
2022a8f1f9e5SMatthew G. Knepley         }
2023a8f1f9e5SMatthew G. Knepley       }
20242edcad52SToby Isaac       ierr = PetscFEPushforward(fe, fegeom, 1, &u_t[fOffset]);CHKERRQ(ierr);
2025a8f1f9e5SMatthew G. Knepley     }
2026a8f1f9e5SMatthew G. Knepley     fOffset += Ncf;
2027a8f1f9e5SMatthew G. Knepley     dOffset += Nbf;
2028a8f1f9e5SMatthew G. Knepley   }
2029a8f1f9e5SMatthew G. Knepley   return 0;
2030a8f1f9e5SMatthew G. Knepley }
2031a8f1f9e5SMatthew G. Knepley 
2032665f567fSMatthew 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[])
203327f02ce8SMatthew G. Knepley {
203427f02ce8SMatthew G. Knepley   PetscInt       dOffset = 0, fOffset = 0, g;
203527f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
203627f02ce8SMatthew G. Knepley 
203727f02ce8SMatthew G. Knepley   for (g = 0; g < 2*Nf-1; ++g) {
2038665f567fSMatthew G. Knepley     if (!T[g/2]) continue;
2039665f567fSMatthew G. Knepley     {
204027f02ce8SMatthew G. Knepley     PetscFE          fe;
204127f02ce8SMatthew G. Knepley     const PetscInt   f   = g/2;
2042665f567fSMatthew G. Knepley     const PetscInt   cdim = T[f]->cdim;
2043665f567fSMatthew G. Knepley     const PetscInt   Nq   = T[f]->Np;
2044665f567fSMatthew G. Knepley     const PetscInt   Nbf  = T[f]->Nb;
2045665f567fSMatthew G. Knepley     const PetscInt   Ncf  = T[f]->Nc;
2046665f567fSMatthew G. Knepley     const PetscReal *Bq   = &T[f]->T[0][(r*Nq+q)*Nbf*Ncf];
2047665f567fSMatthew G. Knepley     const PetscReal *Dq   = &T[f]->T[1][(r*Nq+q)*Nbf*Ncf*cdim];
204827f02ce8SMatthew G. Knepley     PetscInt         b, c, d;
204927f02ce8SMatthew G. Knepley 
205027f02ce8SMatthew G. Knepley     fe = (PetscFE) ds->disc[f];
205127f02ce8SMatthew G. Knepley     for (c = 0; c < Ncf; ++c)      u[fOffset+c] = 0.0;
2052665f567fSMatthew G. Knepley     for (d = 0; d < cdim*Ncf; ++d) u_x[fOffset*cdim+d] = 0.0;
205327f02ce8SMatthew G. Knepley     for (b = 0; b < Nbf; ++b) {
205427f02ce8SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) {
205527f02ce8SMatthew G. Knepley         const PetscInt cidx = b*Ncf+c;
205627f02ce8SMatthew G. Knepley 
205727f02ce8SMatthew G. Knepley         u[fOffset+c] += Bq[cidx]*coefficients[dOffset+b];
2058665f567fSMatthew G. Knepley         for (d = 0; d < cdim; ++d) u_x[(fOffset+c)*cdim+d] += Dq[cidx*cdim+d]*coefficients[dOffset+b];
205927f02ce8SMatthew G. Knepley       }
206027f02ce8SMatthew G. Knepley     }
206127f02ce8SMatthew G. Knepley     ierr = PetscFEPushforward(fe, fegeom, 1, &u[fOffset]);CHKERRQ(ierr);
2062665f567fSMatthew G. Knepley     ierr = PetscFEPushforwardGradient(fe, fegeom, 1, &u_x[fOffset*cdim]);CHKERRQ(ierr);
206327f02ce8SMatthew G. Knepley     if (u_t) {
206427f02ce8SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) u_t[fOffset+c] = 0.0;
206527f02ce8SMatthew G. Knepley       for (b = 0; b < Nbf; ++b) {
206627f02ce8SMatthew G. Knepley         for (c = 0; c < Ncf; ++c) {
206727f02ce8SMatthew G. Knepley           const PetscInt cidx = b*Ncf+c;
206827f02ce8SMatthew G. Knepley 
206927f02ce8SMatthew G. Knepley           u_t[fOffset+c] += Bq[cidx]*coefficients_t[dOffset+b];
207027f02ce8SMatthew G. Knepley         }
207127f02ce8SMatthew G. Knepley       }
207227f02ce8SMatthew G. Knepley       ierr = PetscFEPushforward(fe, fegeom, 1, &u_t[fOffset]);CHKERRQ(ierr);
207327f02ce8SMatthew G. Knepley     }
207427f02ce8SMatthew G. Knepley     fOffset += Ncf;
207527f02ce8SMatthew G. Knepley     dOffset += Nbf;
207627f02ce8SMatthew G. Knepley   }
2077665f567fSMatthew G. Knepley   }
207827f02ce8SMatthew G. Knepley   return 0;
207927f02ce8SMatthew G. Knepley }
208027f02ce8SMatthew G. Knepley 
2081a8f1f9e5SMatthew G. Knepley PetscErrorCode PetscFEEvaluateFaceFields_Internal(PetscDS prob, PetscInt field, PetscInt faceLoc, const PetscScalar coefficients[], PetscScalar u[])
2082a8f1f9e5SMatthew G. Knepley {
2083a8f1f9e5SMatthew G. Knepley   PetscFE         fe;
2084ef0bb6c7SMatthew G. Knepley   PetscTabulation Tc;
2085ef0bb6c7SMatthew G. Knepley   PetscInt        b, c;
2086a8f1f9e5SMatthew G. Knepley   PetscErrorCode  ierr;
2087a8f1f9e5SMatthew G. Knepley 
2088a8f1f9e5SMatthew G. Knepley   if (!prob) return 0;
2089a8f1f9e5SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
2090ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetFaceCentroidTabulation(fe, &Tc);CHKERRQ(ierr);
2091ef0bb6c7SMatthew G. Knepley   {
2092ef0bb6c7SMatthew G. Knepley     const PetscReal *faceBasis = Tc->T[0];
2093ef0bb6c7SMatthew G. Knepley     const PetscInt   Nb        = Tc->Nb;
2094ef0bb6c7SMatthew G. Knepley     const PetscInt   Nc        = Tc->Nc;
2095ef0bb6c7SMatthew G. Knepley 
2096a8f1f9e5SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {u[c] = 0.0;}
2097a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
2098a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
2099813a933aSJed Brown         u[c] += coefficients[b] * faceBasis[(faceLoc*Nb + b)*Nc + c];
2100a8f1f9e5SMatthew G. Knepley       }
2101a8f1f9e5SMatthew G. Knepley     }
2102ef0bb6c7SMatthew G. Knepley   }
2103a8f1f9e5SMatthew G. Knepley   return 0;
2104a8f1f9e5SMatthew G. Knepley }
2105a8f1f9e5SMatthew G. Knepley 
2106ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEUpdateElementVec_Internal(PetscFE fe, PetscTabulation T, PetscInt r, PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[])
2107a8f1f9e5SMatthew G. Knepley {
210827f02ce8SMatthew G. Knepley   const PetscInt   dE       = T->cdim; /* fegeom->dimEmbed */
2109ef0bb6c7SMatthew G. Knepley   const PetscInt   Nq       = T->Np;
2110ef0bb6c7SMatthew G. Knepley   const PetscInt   Nb       = T->Nb;
2111ef0bb6c7SMatthew G. Knepley   const PetscInt   Nc       = T->Nc;
2112ef0bb6c7SMatthew G. Knepley   const PetscReal *basis    = &T->T[0][r*Nq*Nb*Nc];
2113665f567fSMatthew G. Knepley   const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dE];
2114a8f1f9e5SMatthew G. Knepley   PetscInt         q, b, c, d;
2115a8f1f9e5SMatthew G. Knepley   PetscErrorCode   ierr;
2116a8f1f9e5SMatthew G. Knepley 
2117a8f1f9e5SMatthew G. Knepley   for (b = 0; b < Nb; ++b) elemVec[b] = 0.0;
2118a8f1f9e5SMatthew G. Knepley   for (q = 0; q < Nq; ++q) {
2119a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
2120a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
2121a8f1f9e5SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
2122a8f1f9e5SMatthew G. Knepley 
2123a8f1f9e5SMatthew G. Knepley         tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx];
212427f02ce8SMatthew G. Knepley         for (d = 0; d < dE; ++d) tmpBasisDer[bcidx*dE+d] = basisDer[q*Nb*Nc*dE+bcidx*dE+d];
2125a8f1f9e5SMatthew G. Knepley       }
2126a8f1f9e5SMatthew G. Knepley     }
21272edcad52SToby Isaac     ierr = PetscFEPushforward(fe, fegeom, Nb, tmpBasis);CHKERRQ(ierr);
21282edcad52SToby Isaac     ierr = PetscFEPushforwardGradient(fe, fegeom, Nb, tmpBasisDer);CHKERRQ(ierr);
2129a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
2130a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
2131a8f1f9e5SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
2132a8f1f9e5SMatthew G. Knepley         const PetscInt qcidx = q*Nc+c;
2133a8f1f9e5SMatthew G. Knepley 
2134a8f1f9e5SMatthew G. Knepley         elemVec[b] += tmpBasis[bcidx]*f0[qcidx];
213527f02ce8SMatthew G. Knepley         for (d = 0; d < dE; ++d) elemVec[b] += tmpBasisDer[bcidx*dE+d]*f1[qcidx*dE+d];
213627f02ce8SMatthew G. Knepley       }
213727f02ce8SMatthew G. Knepley     }
213827f02ce8SMatthew G. Knepley   }
213927f02ce8SMatthew G. Knepley   return(0);
214027f02ce8SMatthew G. Knepley }
214127f02ce8SMatthew G. Knepley 
214227f02ce8SMatthew G. Knepley PetscErrorCode PetscFEUpdateElementVec_Hybrid_Internal(PetscFE fe, PetscTabulation T, PetscInt r, PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[])
214327f02ce8SMatthew G. Knepley {
214427f02ce8SMatthew G. Knepley   const PetscInt   dE       = T->cdim;
214527f02ce8SMatthew G. Knepley   const PetscInt   Nq       = T->Np;
214627f02ce8SMatthew G. Knepley   const PetscInt   Nb       = T->Nb;
214727f02ce8SMatthew G. Knepley   const PetscInt   Nc       = T->Nc;
214827f02ce8SMatthew G. Knepley   const PetscReal *basis    = &T->T[0][r*Nq*Nb*Nc];
214927f02ce8SMatthew G. Knepley   const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dE];
215027f02ce8SMatthew G. Knepley   PetscInt         q, b, c, d, s;
215127f02ce8SMatthew G. Knepley   PetscErrorCode   ierr;
215227f02ce8SMatthew G. Knepley 
215327f02ce8SMatthew G. Knepley   for (b = 0; b < Nb*2; ++b) elemVec[b] = 0.0;
215427f02ce8SMatthew G. Knepley   for (q = 0; q < Nq; ++q) {
215527f02ce8SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
215627f02ce8SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
215727f02ce8SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
215827f02ce8SMatthew G. Knepley 
215927f02ce8SMatthew G. Knepley         tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx];
216027f02ce8SMatthew G. Knepley         for (d = 0; d < dE; ++d) tmpBasisDer[bcidx*dE+d] = basisDer[q*Nb*Nc*dE+bcidx*dE+d];
216127f02ce8SMatthew G. Knepley       }
216227f02ce8SMatthew G. Knepley     }
216327f02ce8SMatthew G. Knepley     ierr = PetscFEPushforward(fe, fegeom, Nb, tmpBasis);CHKERRQ(ierr);
216427f02ce8SMatthew G. Knepley     ierr = PetscFEPushforwardGradient(fe, fegeom, Nb, tmpBasisDer);CHKERRQ(ierr);
216527f02ce8SMatthew G. Knepley     for (s = 0; s < 2; ++s) {
216627f02ce8SMatthew G. Knepley       for (b = 0; b < Nb; ++b) {
216727f02ce8SMatthew G. Knepley         for (c = 0; c < Nc; ++c) {
216827f02ce8SMatthew G. Knepley           const PetscInt bcidx = b*Nc+c;
216927f02ce8SMatthew G. Knepley           const PetscInt qcidx = (q*2+s)*Nc+c;
217027f02ce8SMatthew G. Knepley 
217127f02ce8SMatthew G. Knepley           elemVec[Nb*s+b] += tmpBasis[bcidx]*f0[qcidx];
217227f02ce8SMatthew G. Knepley           for (d = 0; d < dE; ++d) elemVec[Nb*s+b] += tmpBasisDer[bcidx*dE+d]*f1[qcidx*dE+d];
217327f02ce8SMatthew G. Knepley         }
2174a8f1f9e5SMatthew G. Knepley       }
2175a8f1f9e5SMatthew G. Knepley     }
2176a8f1f9e5SMatthew G. Knepley   }
2177a8f1f9e5SMatthew G. Knepley   return(0);
2178a8f1f9e5SMatthew G. Knepley }
2179a8f1f9e5SMatthew G. Knepley 
2180ef0bb6c7SMatthew 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[])
2181a8f1f9e5SMatthew G. Knepley {
218227f02ce8SMatthew G. Knepley   const PetscInt   dE        = TI->cdim;
2183ef0bb6c7SMatthew G. Knepley   const PetscInt   NqI       = TI->Np;
2184ef0bb6c7SMatthew G. Knepley   const PetscInt   NbI       = TI->Nb;
2185ef0bb6c7SMatthew G. Knepley   const PetscInt   NcI       = TI->Nc;
2186ef0bb6c7SMatthew G. Knepley   const PetscReal *basisI    = &TI->T[0][(r*NqI+q)*NbI*NcI];
2187665f567fSMatthew G. Knepley   const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dE];
2188ef0bb6c7SMatthew G. Knepley   const PetscInt   NqJ       = TJ->Np;
2189ef0bb6c7SMatthew G. Knepley   const PetscInt   NbJ       = TJ->Nb;
2190ef0bb6c7SMatthew G. Knepley   const PetscInt   NcJ       = TJ->Nc;
2191ef0bb6c7SMatthew G. Knepley   const PetscReal *basisJ    = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ];
2192665f567fSMatthew G. Knepley   const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dE];
2193a8f1f9e5SMatthew G. Knepley   PetscInt         f, fc, g, gc, df, dg;
2194a8f1f9e5SMatthew G. Knepley   PetscErrorCode   ierr;
2195a8f1f9e5SMatthew G. Knepley 
2196a8f1f9e5SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
2197a8f1f9e5SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
2198a8f1f9e5SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
2199a8f1f9e5SMatthew G. Knepley 
2200a8f1f9e5SMatthew G. Knepley       tmpBasisI[fidx] = basisI[fidx];
220127f02ce8SMatthew G. Knepley       for (df = 0; df < dE; ++df) tmpBasisDerI[fidx*dE+df] = basisDerI[fidx*dE+df];
2202a8f1f9e5SMatthew G. Knepley     }
2203a8f1f9e5SMatthew G. Knepley   }
22042edcad52SToby Isaac   ierr = PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);CHKERRQ(ierr);
22052edcad52SToby Isaac   ierr = PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);CHKERRQ(ierr);
2206a8f1f9e5SMatthew G. Knepley   for (g = 0; g < NbJ; ++g) {
2207a8f1f9e5SMatthew G. Knepley     for (gc = 0; gc < NcJ; ++gc) {
2208a8f1f9e5SMatthew G. Knepley       const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
2209a8f1f9e5SMatthew G. Knepley 
2210a8f1f9e5SMatthew G. Knepley       tmpBasisJ[gidx] = basisJ[gidx];
221127f02ce8SMatthew G. Knepley       for (dg = 0; dg < dE; ++dg) tmpBasisDerJ[gidx*dE+dg] = basisDerJ[gidx*dE+dg];
2212a8f1f9e5SMatthew G. Knepley     }
2213a8f1f9e5SMatthew G. Knepley   }
22142edcad52SToby Isaac   ierr = PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);CHKERRQ(ierr);
22152edcad52SToby Isaac   ierr = PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);CHKERRQ(ierr);
2216a8f1f9e5SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
2217a8f1f9e5SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
2218a8f1f9e5SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
2219a8f1f9e5SMatthew G. Knepley       const PetscInt i    = offsetI+f; /* Element matrix row */
2220a8f1f9e5SMatthew G. Knepley       for (g = 0; g < NbJ; ++g) {
2221a8f1f9e5SMatthew G. Knepley         for (gc = 0; gc < NcJ; ++gc) {
2222a8f1f9e5SMatthew G. Knepley           const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
2223a8f1f9e5SMatthew G. Knepley           const PetscInt j    = offsetJ+g; /* Element matrix column */
2224a8f1f9e5SMatthew G. Knepley           const PetscInt fOff = eOffset+i*totDim+j;
2225a8f1f9e5SMatthew G. Knepley 
2226a8f1f9e5SMatthew G. Knepley           elemMat[fOff] += tmpBasisI[fidx]*g0[fc*NcJ+gc]*tmpBasisJ[gidx];
222727f02ce8SMatthew G. Knepley           for (df = 0; df < dE; ++df) {
222827f02ce8SMatthew G. Knepley             elemMat[fOff] += tmpBasisI[fidx]*g1[(fc*NcJ+gc)*dE+df]*tmpBasisDerJ[gidx*dE+df];
222927f02ce8SMatthew G. Knepley             elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g2[(fc*NcJ+gc)*dE+df]*tmpBasisJ[gidx];
223027f02ce8SMatthew G. Knepley             for (dg = 0; dg < dE; ++dg) {
223127f02ce8SMatthew G. Knepley               elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g3[((fc*NcJ+gc)*dE+df)*dE+dg]*tmpBasisDerJ[gidx*dE+dg];
223227f02ce8SMatthew G. Knepley             }
223327f02ce8SMatthew G. Knepley           }
223427f02ce8SMatthew G. Knepley         }
223527f02ce8SMatthew G. Knepley       }
223627f02ce8SMatthew G. Knepley     }
223727f02ce8SMatthew G. Knepley   }
223827f02ce8SMatthew G. Knepley   return(0);
223927f02ce8SMatthew G. Knepley }
224027f02ce8SMatthew G. Knepley 
2241665f567fSMatthew G. Knepley PetscErrorCode PetscFEUpdateElementMat_Hybrid_Internal(PetscFE feI, PetscBool isHybridI, PetscFE feJ, PetscBool isHybridJ, 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[])
224227f02ce8SMatthew G. Knepley {
2243665f567fSMatthew G. Knepley   const PetscInt   dE        = TI->cdim;
2244665f567fSMatthew G. Knepley   const PetscInt   NqI       = TI->Np;
2245665f567fSMatthew G. Knepley   const PetscInt   NbI       = TI->Nb;
2246665f567fSMatthew G. Knepley   const PetscInt   NcI       = TI->Nc;
2247665f567fSMatthew G. Knepley   const PetscReal *basisI    = &TI->T[0][(r*NqI+q)*NbI*NcI];
2248665f567fSMatthew G. Knepley   const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dE];
2249665f567fSMatthew G. Knepley   const PetscInt   NqJ       = TJ->Np;
2250665f567fSMatthew G. Knepley   const PetscInt   NbJ       = TJ->Nb;
2251665f567fSMatthew G. Knepley   const PetscInt   NcJ       = TJ->Nc;
2252665f567fSMatthew G. Knepley   const PetscReal *basisJ    = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ];
2253665f567fSMatthew G. Knepley   const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dE];
225427f02ce8SMatthew G. Knepley   const PetscInt   Ns = isHybridI ? 1 : 2;
225527f02ce8SMatthew G. Knepley   const PetscInt   Nt = isHybridJ ? 1 : 2;
225627f02ce8SMatthew G. Knepley   PetscInt         f, fc, g, gc, df, dg, s, t;
225727f02ce8SMatthew G. Knepley   PetscErrorCode   ierr;
225827f02ce8SMatthew G. Knepley 
225927f02ce8SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
226027f02ce8SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
226127f02ce8SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
226227f02ce8SMatthew G. Knepley 
226327f02ce8SMatthew G. Knepley       tmpBasisI[fidx] = basisI[fidx];
2264665f567fSMatthew G. Knepley       for (df = 0; df < dE; ++df) tmpBasisDerI[fidx*dE+df] = basisDerI[fidx*dE+df];
226527f02ce8SMatthew G. Knepley     }
226627f02ce8SMatthew G. Knepley   }
226727f02ce8SMatthew G. Knepley   ierr = PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);CHKERRQ(ierr);
226827f02ce8SMatthew G. Knepley   ierr = PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);CHKERRQ(ierr);
226927f02ce8SMatthew G. Knepley   for (g = 0; g < NbJ; ++g) {
227027f02ce8SMatthew G. Knepley     for (gc = 0; gc < NcJ; ++gc) {
227127f02ce8SMatthew G. Knepley       const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
227227f02ce8SMatthew G. Knepley 
227327f02ce8SMatthew G. Knepley       tmpBasisJ[gidx] = basisJ[gidx];
2274665f567fSMatthew G. Knepley       for (dg = 0; dg < dE; ++dg) tmpBasisDerJ[gidx*dE+dg] = basisDerJ[gidx*dE+dg];
227527f02ce8SMatthew G. Knepley     }
227627f02ce8SMatthew G. Knepley   }
227727f02ce8SMatthew G. Knepley   ierr = PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);CHKERRQ(ierr);
227827f02ce8SMatthew G. Knepley   ierr = PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);CHKERRQ(ierr);
227927f02ce8SMatthew G. Knepley   for (s = 0; s < Ns; ++s) {
228027f02ce8SMatthew G. Knepley     for (f = 0; f < NbI; ++f) {
228127f02ce8SMatthew G. Knepley       for (fc = 0; fc < NcI; ++fc) {
228227f02ce8SMatthew G. Knepley         const PetscInt sc   = NcI*s+fc;  /* components from each side of the surface */
228327f02ce8SMatthew G. Knepley         const PetscInt fidx = f*NcI+fc;  /* Test function basis index */
228427f02ce8SMatthew G. Knepley         const PetscInt i    = offsetI+NbI*s+f; /* Element matrix row */
228527f02ce8SMatthew G. Knepley         for (t = 0; t < Nt; ++t) {
228627f02ce8SMatthew G. Knepley           for (g = 0; g < NbJ; ++g) {
228727f02ce8SMatthew G. Knepley             for (gc = 0; gc < NcJ; ++gc) {
228827f02ce8SMatthew G. Knepley               const PetscInt tc   = NcJ*t+gc;  /* components from each side of the surface */
228927f02ce8SMatthew G. Knepley               const PetscInt gidx = g*NcJ+gc;  /* Trial function basis index */
229027f02ce8SMatthew G. Knepley               const PetscInt j    = offsetJ+NbJ*t+g; /* Element matrix column */
229127f02ce8SMatthew G. Knepley               const PetscInt fOff = eOffset+i*totDim+j;
229227f02ce8SMatthew G. Knepley 
229327f02ce8SMatthew G. Knepley               elemMat[fOff] += tmpBasisI[fidx]*g0[sc*NcJ*Nt+tc]*tmpBasisJ[gidx];
229427f02ce8SMatthew G. Knepley               for (df = 0; df < dE; ++df) {
229527f02ce8SMatthew G. Knepley                 elemMat[fOff] += tmpBasisI[fidx]*g1[(sc*NcJ*Nt+tc)*dE+df]*tmpBasisDerJ[gidx*dE+df];
229627f02ce8SMatthew G. Knepley                 elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g2[(sc*NcJ*Nt+tc)*dE+df]*tmpBasisJ[gidx];
229727f02ce8SMatthew G. Knepley                 for (dg = 0; dg < dE; ++dg) {
229827f02ce8SMatthew G. Knepley                   elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g3[((sc*NcJ*Nt+tc)*dE+df)*dE+dg]*tmpBasisDerJ[gidx*dE+dg];
229927f02ce8SMatthew G. Knepley                 }
230027f02ce8SMatthew G. Knepley               }
2301a8f1f9e5SMatthew G. Knepley             }
2302a8f1f9e5SMatthew G. Knepley           }
2303a8f1f9e5SMatthew G. Knepley         }
2304a8f1f9e5SMatthew G. Knepley       }
2305a8f1f9e5SMatthew G. Knepley     }
2306a8f1f9e5SMatthew G. Knepley   }
2307a8f1f9e5SMatthew G. Knepley   return(0);
2308a8f1f9e5SMatthew G. Knepley }
2309c9ba7969SMatthew G. Knepley 
2310c9ba7969SMatthew G. Knepley PetscErrorCode PetscFECreateCellGeometry(PetscFE fe, PetscQuadrature quad, PetscFEGeom *cgeom)
2311c9ba7969SMatthew G. Knepley {
2312c9ba7969SMatthew G. Knepley   PetscDualSpace  dsp;
2313c9ba7969SMatthew G. Knepley   DM              dm;
2314c9ba7969SMatthew G. Knepley   PetscQuadrature quadDef;
2315c9ba7969SMatthew G. Knepley   PetscInt        dim, cdim, Nq;
2316c9ba7969SMatthew G. Knepley   PetscErrorCode  ierr;
2317c9ba7969SMatthew G. Knepley 
2318c9ba7969SMatthew G. Knepley   PetscFunctionBegin;
2319c9ba7969SMatthew G. Knepley   ierr = PetscFEGetDualSpace(fe, &dsp);CHKERRQ(ierr);
2320c9ba7969SMatthew G. Knepley   ierr = PetscDualSpaceGetDM(dsp, &dm);CHKERRQ(ierr);
2321c9ba7969SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
2322c9ba7969SMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
2323c9ba7969SMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &quadDef);CHKERRQ(ierr);
2324c9ba7969SMatthew G. Knepley   quad = quad ? quad : quadDef;
2325c9ba7969SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);
2326c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq*cdim,      &cgeom->v);CHKERRQ(ierr);
2327c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq*cdim*cdim, &cgeom->J);CHKERRQ(ierr);
2328c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq*cdim*cdim, &cgeom->invJ);CHKERRQ(ierr);
2329c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq,           &cgeom->detJ);CHKERRQ(ierr);
2330c9ba7969SMatthew G. Knepley   cgeom->dim       = dim;
2331c9ba7969SMatthew G. Knepley   cgeom->dimEmbed  = cdim;
2332c9ba7969SMatthew G. Knepley   cgeom->numCells  = 1;
2333c9ba7969SMatthew G. Knepley   cgeom->numPoints = Nq;
2334c9ba7969SMatthew G. Knepley   ierr = DMPlexComputeCellGeometryFEM(dm, 0, quad, cgeom->v, cgeom->J, cgeom->invJ, cgeom->detJ);CHKERRQ(ierr);
2335c9ba7969SMatthew G. Knepley   PetscFunctionReturn(0);
2336c9ba7969SMatthew G. Knepley }
2337c9ba7969SMatthew G. Knepley 
2338c9ba7969SMatthew G. Knepley PetscErrorCode PetscFEDestroyCellGeometry(PetscFE fe, PetscFEGeom *cgeom)
2339c9ba7969SMatthew G. Knepley {
2340c9ba7969SMatthew G. Knepley   PetscErrorCode ierr;
2341c9ba7969SMatthew G. Knepley 
2342c9ba7969SMatthew G. Knepley   PetscFunctionBegin;
2343c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->v);CHKERRQ(ierr);
2344c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->J);CHKERRQ(ierr);
2345c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->invJ);CHKERRQ(ierr);
2346c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->detJ);CHKERRQ(ierr);
2347c9ba7969SMatthew G. Knepley   PetscFunctionReturn(0);
2348c9ba7969SMatthew G. Knepley }
2349