xref: /petsc/src/dm/dt/fe/interface/fe.c (revision 6528b96d098a3a0d8b5eec2f1c205a3c25c0d721)
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 
316ea78f98cSLisandro Dalcin   if (--((PetscObject)(*fem))->refct > 0) {*fem = NULL; PetscFunctionReturn(0);}
31720cf1dd8SToby Isaac   ((PetscObject) (*fem))->refct = 0;
31820cf1dd8SToby Isaac 
31920cf1dd8SToby Isaac   if ((*fem)->subspaces) {
32020cf1dd8SToby Isaac     PetscInt dim, d;
32120cf1dd8SToby Isaac 
32220cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDimension((*fem)->dualSpace, &dim);CHKERRQ(ierr);
32320cf1dd8SToby Isaac     for (d = 0; d < dim; ++d) {ierr = PetscFEDestroy(&(*fem)->subspaces[d]);CHKERRQ(ierr);}
32420cf1dd8SToby Isaac   }
32520cf1dd8SToby Isaac   ierr = PetscFree((*fem)->subspaces);CHKERRQ(ierr);
32620cf1dd8SToby Isaac   ierr = PetscFree((*fem)->invV);CHKERRQ(ierr);
327ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&(*fem)->T);CHKERRQ(ierr);
328ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&(*fem)->Tf);CHKERRQ(ierr);
329ef0bb6c7SMatthew G. Knepley   ierr = PetscTabulationDestroy(&(*fem)->Tc);CHKERRQ(ierr);
33020cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&(*fem)->basisSpace);CHKERRQ(ierr);
33120cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&(*fem)->dualSpace);CHKERRQ(ierr);
33220cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&(*fem)->quadrature);CHKERRQ(ierr);
33320cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&(*fem)->faceQuadrature);CHKERRQ(ierr);
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:
790f9244615SMatthew G. Knepley + fem - The PetscFE object
791f9244615SMatthew G. Knepley - k   - The highest derivative we need to tabulate, very often 1
79220cf1dd8SToby Isaac 
793ef0bb6c7SMatthew G. Knepley   Output Parameter:
794ef0bb6c7SMatthew G. Knepley . T - The basis function values and derivatives at quadrature points
79520cf1dd8SToby Isaac 
79620cf1dd8SToby Isaac   Note:
797ef0bb6c7SMatthew G. Knepley $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
798ef0bb6c7SMatthew 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
799ef0bb6c7SMatthew 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
80020cf1dd8SToby Isaac 
80120cf1dd8SToby Isaac   Level: intermediate
80220cf1dd8SToby Isaac 
803ef0bb6c7SMatthew G. Knepley .seealso: PetscFECreateTabulation(), PetscTabulationDestroy()
80420cf1dd8SToby Isaac @*/
805f9244615SMatthew G. Knepley PetscErrorCode PetscFEGetCellTabulation(PetscFE fem, PetscInt k, PetscTabulation *T)
80620cf1dd8SToby Isaac {
80720cf1dd8SToby Isaac   PetscInt         npoints;
80820cf1dd8SToby Isaac   const PetscReal *points;
80920cf1dd8SToby Isaac   PetscErrorCode   ierr;
81020cf1dd8SToby Isaac 
81120cf1dd8SToby Isaac   PetscFunctionBegin;
81220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
813ef0bb6c7SMatthew G. Knepley   PetscValidPointer(T, 2);
81420cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(fem->quadrature, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr);
815f9244615SMatthew G. Knepley   if (!fem->T) {ierr = PetscFECreateTabulation(fem, 1, npoints, points, k, &fem->T);CHKERRQ(ierr);}
816f9244615SMatthew G. Knepley   if (fem->T && k > fem->T->K) SETERRQ2(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_OUTOFRANGE, "Requested %D derivatives, but only tabulated %D", k, fem->T->K);
817ef0bb6c7SMatthew G. Knepley   *T = fem->T;
81820cf1dd8SToby Isaac   PetscFunctionReturn(0);
81920cf1dd8SToby Isaac }
82020cf1dd8SToby Isaac 
8212b99622eSMatthew G. Knepley /*@C
822ef0bb6c7SMatthew G. Knepley   PetscFEGetFaceTabulation - Returns the tabulation of the basis functions at the face quadrature points for each face of the reference cell
8232b99622eSMatthew G. Knepley 
8242b99622eSMatthew G. Knepley   Not collective
8252b99622eSMatthew G. Knepley 
8262b99622eSMatthew G. Knepley   Input Parameter:
827f9244615SMatthew G. Knepley + fem - The PetscFE object
828f9244615SMatthew G. Knepley - k   - The highest derivative we need to tabulate, very often 1
8292b99622eSMatthew G. Knepley 
8302b99622eSMatthew G. Knepley   Output Parameters:
831ef0bb6c7SMatthew G. Knepley . Tf - The basis function values and derviatives at face quadrature points
8322b99622eSMatthew G. Knepley 
8332b99622eSMatthew G. Knepley   Note:
834ef0bb6c7SMatthew 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
835ef0bb6c7SMatthew 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
836ef0bb6c7SMatthew 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
8372b99622eSMatthew G. Knepley 
8382b99622eSMatthew G. Knepley   Level: intermediate
8392b99622eSMatthew G. Knepley 
840ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetCellTabulation(), PetscFECreateTabulation(), PetscTabulationDestroy()
8412b99622eSMatthew G. Knepley @*/
842f9244615SMatthew G. Knepley PetscErrorCode PetscFEGetFaceTabulation(PetscFE fem, PetscInt k, PetscTabulation *Tf)
84320cf1dd8SToby Isaac {
84420cf1dd8SToby Isaac   PetscErrorCode   ierr;
84520cf1dd8SToby Isaac 
84620cf1dd8SToby Isaac   PetscFunctionBegin;
84720cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
848ef0bb6c7SMatthew G. Knepley   PetscValidPointer(Tf, 2);
849ef0bb6c7SMatthew G. Knepley   if (!fem->Tf) {
85020cf1dd8SToby Isaac     const PetscReal  xi0[3] = {-1., -1., -1.};
85120cf1dd8SToby Isaac     PetscReal        v0[3], J[9], detJ;
85220cf1dd8SToby Isaac     PetscQuadrature  fq;
85320cf1dd8SToby Isaac     PetscDualSpace   sp;
85420cf1dd8SToby Isaac     DM               dm;
85520cf1dd8SToby Isaac     const PetscInt  *faces;
85620cf1dd8SToby Isaac     PetscInt         dim, numFaces, f, npoints, q;
85720cf1dd8SToby Isaac     const PetscReal *points;
85820cf1dd8SToby Isaac     PetscReal       *facePoints;
85920cf1dd8SToby Isaac 
86020cf1dd8SToby Isaac     ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr);
86120cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr);
86220cf1dd8SToby Isaac     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
86320cf1dd8SToby Isaac     ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr);
86420cf1dd8SToby Isaac     ierr = DMPlexGetCone(dm, 0, &faces);CHKERRQ(ierr);
86520cf1dd8SToby Isaac     ierr = PetscFEGetFaceQuadrature(fem, &fq);CHKERRQ(ierr);
86620cf1dd8SToby Isaac     if (fq) {
86720cf1dd8SToby Isaac       ierr = PetscQuadratureGetData(fq, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr);
86820cf1dd8SToby Isaac       ierr = PetscMalloc1(numFaces*npoints*dim, &facePoints);CHKERRQ(ierr);
86920cf1dd8SToby Isaac       for (f = 0; f < numFaces; ++f) {
87020cf1dd8SToby Isaac         ierr = DMPlexComputeCellGeometryFEM(dm, faces[f], NULL, v0, J, NULL, &detJ);CHKERRQ(ierr);
87120cf1dd8SToby Isaac         for (q = 0; q < npoints; ++q) CoordinatesRefToReal(dim, dim-1, xi0, v0, J, &points[q*(dim-1)], &facePoints[(f*npoints+q)*dim]);
87220cf1dd8SToby Isaac       }
873f9244615SMatthew G. Knepley       ierr = PetscFECreateTabulation(fem, numFaces, npoints, facePoints, k, &fem->Tf);CHKERRQ(ierr);
87420cf1dd8SToby Isaac       ierr = PetscFree(facePoints);CHKERRQ(ierr);
87520cf1dd8SToby Isaac     }
87620cf1dd8SToby Isaac   }
877f9244615SMatthew G. Knepley   if (fem->Tf && k > fem->Tf->K) SETERRQ2(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_OUTOFRANGE, "Requested %D derivatives, but only tabulated %D", k, fem->Tf->K);
878ef0bb6c7SMatthew G. Knepley   *Tf = fem->Tf;
87920cf1dd8SToby Isaac   PetscFunctionReturn(0);
88020cf1dd8SToby Isaac }
88120cf1dd8SToby Isaac 
8822b99622eSMatthew G. Knepley /*@C
883ef0bb6c7SMatthew G. Knepley   PetscFEGetFaceCentroidTabulation - Returns the tabulation of the basis functions at the face centroid points
8842b99622eSMatthew G. Knepley 
8852b99622eSMatthew G. Knepley   Not collective
8862b99622eSMatthew G. Knepley 
8872b99622eSMatthew G. Knepley   Input Parameter:
8882b99622eSMatthew G. Knepley . fem - The PetscFE object
8892b99622eSMatthew G. Knepley 
8902b99622eSMatthew G. Knepley   Output Parameters:
891ef0bb6c7SMatthew G. Knepley . Tc - The basis function values at face centroid points
8922b99622eSMatthew G. Knepley 
8932b99622eSMatthew G. Knepley   Note:
894ef0bb6c7SMatthew G. Knepley $ T->T[0] = Bf[(f*pdim + i)*Nc + c] is the value at point f for basis function i and component c
8952b99622eSMatthew G. Knepley 
8962b99622eSMatthew G. Knepley   Level: intermediate
8972b99622eSMatthew G. Knepley 
898ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetFaceTabulation(), PetscFEGetCellTabulation(), PetscFECreateTabulation(), PetscTabulationDestroy()
8992b99622eSMatthew G. Knepley @*/
900ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEGetFaceCentroidTabulation(PetscFE fem, PetscTabulation *Tc)
90120cf1dd8SToby Isaac {
90220cf1dd8SToby Isaac   PetscErrorCode   ierr;
90320cf1dd8SToby Isaac 
90420cf1dd8SToby Isaac   PetscFunctionBegin;
90520cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
906ef0bb6c7SMatthew G. Knepley   PetscValidPointer(Tc, 2);
907ef0bb6c7SMatthew G. Knepley   if (!fem->Tc) {
90820cf1dd8SToby Isaac     PetscDualSpace  sp;
90920cf1dd8SToby Isaac     DM              dm;
91020cf1dd8SToby Isaac     const PetscInt *cone;
91120cf1dd8SToby Isaac     PetscReal      *centroids;
91220cf1dd8SToby Isaac     PetscInt        dim, numFaces, f;
91320cf1dd8SToby Isaac 
91420cf1dd8SToby Isaac     ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr);
91520cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr);
91620cf1dd8SToby Isaac     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
91720cf1dd8SToby Isaac     ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr);
91820cf1dd8SToby Isaac     ierr = DMPlexGetCone(dm, 0, &cone);CHKERRQ(ierr);
91920cf1dd8SToby Isaac     ierr = PetscMalloc1(numFaces*dim, &centroids);CHKERRQ(ierr);
92020cf1dd8SToby Isaac     for (f = 0; f < numFaces; ++f) {ierr = DMPlexComputeCellGeometryFVM(dm, cone[f], NULL, &centroids[f*dim], NULL);CHKERRQ(ierr);}
921ef0bb6c7SMatthew G. Knepley     ierr = PetscFECreateTabulation(fem, 1, numFaces, centroids, 0, &fem->Tc);CHKERRQ(ierr);
92220cf1dd8SToby Isaac     ierr = PetscFree(centroids);CHKERRQ(ierr);
92320cf1dd8SToby Isaac   }
924ef0bb6c7SMatthew G. Knepley   *Tc = fem->Tc;
92520cf1dd8SToby Isaac   PetscFunctionReturn(0);
92620cf1dd8SToby Isaac }
92720cf1dd8SToby Isaac 
92820cf1dd8SToby Isaac /*@C
929ef0bb6c7SMatthew G. Knepley   PetscFECreateTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
93020cf1dd8SToby Isaac 
93120cf1dd8SToby Isaac   Not collective
93220cf1dd8SToby Isaac 
93320cf1dd8SToby Isaac   Input Parameters:
93420cf1dd8SToby Isaac + fem     - The PetscFE object
935ef0bb6c7SMatthew G. Knepley . nrepl   - The number of replicas
936ef0bb6c7SMatthew G. Knepley . npoints - The number of tabulation points in a replica
937ef0bb6c7SMatthew G. Knepley . points  - The tabulation point coordinates
938ef0bb6c7SMatthew G. Knepley - K       - The number of derivatives calculated
93920cf1dd8SToby Isaac 
940ef0bb6c7SMatthew G. Knepley   Output Parameter:
941ef0bb6c7SMatthew G. Knepley . T - The basis function values and derivatives at tabulation points
94220cf1dd8SToby Isaac 
94320cf1dd8SToby Isaac   Note:
944ef0bb6c7SMatthew G. Knepley $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
945ef0bb6c7SMatthew 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
946ef0bb6c7SMatthew 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
94720cf1dd8SToby Isaac 
94820cf1dd8SToby Isaac   Level: intermediate
94920cf1dd8SToby Isaac 
950ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetCellTabulation(), PetscTabulationDestroy()
95120cf1dd8SToby Isaac @*/
952ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFECreateTabulation(PetscFE fem, PetscInt nrepl, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation *T)
95320cf1dd8SToby Isaac {
95420cf1dd8SToby Isaac   DM               dm;
955ef0bb6c7SMatthew G. Knepley   PetscDualSpace   Q;
956ef0bb6c7SMatthew G. Knepley   PetscInt         Nb;   /* Dimension of FE space P */
957ef0bb6c7SMatthew G. Knepley   PetscInt         Nc;   /* Field components */
958ef0bb6c7SMatthew G. Knepley   PetscInt         cdim; /* Reference coordinate dimension */
959ef0bb6c7SMatthew G. Knepley   PetscInt         k;
96020cf1dd8SToby Isaac   PetscErrorCode   ierr;
96120cf1dd8SToby Isaac 
96220cf1dd8SToby Isaac   PetscFunctionBegin;
963ef0bb6c7SMatthew G. Knepley   if (!npoints || !fem->dualSpace || K < 0) {
964ef0bb6c7SMatthew G. Knepley     *T = NULL;
96520cf1dd8SToby Isaac     PetscFunctionReturn(0);
96620cf1dd8SToby Isaac   }
96720cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
96840a2aa30SMatthew G. Knepley   PetscValidPointer(points, 4);
96940a2aa30SMatthew G. Knepley   PetscValidPointer(T, 6);
970ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetDualSpace(fem, &Q);CHKERRQ(ierr);
971ef0bb6c7SMatthew G. Knepley   ierr = PetscDualSpaceGetDM(Q, &dm);CHKERRQ(ierr);
972ef0bb6c7SMatthew G. Knepley   ierr = DMGetDimension(dm, &cdim);CHKERRQ(ierr);
973ef0bb6c7SMatthew G. Knepley   ierr = PetscDualSpaceGetDimension(Q, &Nb);CHKERRQ(ierr);
974ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
975ef0bb6c7SMatthew G. Knepley   ierr = PetscMalloc1(1, T);CHKERRQ(ierr);
976ef0bb6c7SMatthew G. Knepley   (*T)->K    = !cdim ? 0 : K;
977ef0bb6c7SMatthew G. Knepley   (*T)->Nr   = nrepl;
978ef0bb6c7SMatthew G. Knepley   (*T)->Np   = npoints;
979ef0bb6c7SMatthew G. Knepley   (*T)->Nb   = Nb;
980ef0bb6c7SMatthew G. Knepley   (*T)->Nc   = Nc;
981ef0bb6c7SMatthew G. Knepley   (*T)->cdim = cdim;
982ef0bb6c7SMatthew G. Knepley   ierr = PetscMalloc1((*T)->K+1, &(*T)->T);CHKERRQ(ierr);
983ef0bb6c7SMatthew G. Knepley   for (k = 0; k <= (*T)->K; ++k) {
984ef0bb6c7SMatthew G. Knepley     ierr = PetscMalloc1(nrepl*npoints*Nb*Nc*PetscPowInt(cdim, k), &(*T)->T[k]);CHKERRQ(ierr);
98520cf1dd8SToby Isaac   }
986ef0bb6c7SMatthew G. Knepley   ierr = (*fem->ops->createtabulation)(fem, nrepl*npoints, points, K, *T);CHKERRQ(ierr);
98720cf1dd8SToby Isaac   PetscFunctionReturn(0);
98820cf1dd8SToby Isaac }
98920cf1dd8SToby Isaac 
9902b99622eSMatthew G. Knepley /*@C
991ef0bb6c7SMatthew G. Knepley   PetscFEComputeTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
9922b99622eSMatthew G. Knepley 
9932b99622eSMatthew G. Knepley   Not collective
9942b99622eSMatthew G. Knepley 
9952b99622eSMatthew G. Knepley   Input Parameters:
9962b99622eSMatthew G. Knepley + fem     - The PetscFE object
9972b99622eSMatthew G. Knepley . npoints - The number of tabulation points
9982b99622eSMatthew G. Knepley . points  - The tabulation point coordinates
999ef0bb6c7SMatthew G. Knepley . K       - The number of derivatives calculated
1000ef0bb6c7SMatthew G. Knepley - T       - An existing tabulation object with enough allocated space
1001ef0bb6c7SMatthew G. Knepley 
1002ef0bb6c7SMatthew G. Knepley   Output Parameter:
1003ef0bb6c7SMatthew G. Knepley . T - The basis function values and derivatives at tabulation points
10042b99622eSMatthew G. Knepley 
10052b99622eSMatthew G. Knepley   Note:
1006ef0bb6c7SMatthew G. Knepley $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1007ef0bb6c7SMatthew 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
1008ef0bb6c7SMatthew 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
10092b99622eSMatthew G. Knepley 
10102b99622eSMatthew G. Knepley   Level: intermediate
10112b99622eSMatthew G. Knepley 
1012ef0bb6c7SMatthew G. Knepley .seealso: PetscFEGetCellTabulation(), PetscTabulationDestroy()
10132b99622eSMatthew G. Knepley @*/
1014ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEComputeTabulation(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation T)
1015ef0bb6c7SMatthew G. Knepley {
1016ef0bb6c7SMatthew G. Knepley   PetscErrorCode ierr;
1017ef0bb6c7SMatthew G. Knepley 
1018ef0bb6c7SMatthew G. Knepley   PetscFunctionBeginHot;
1019ef0bb6c7SMatthew G. Knepley   if (!npoints || !fem->dualSpace || K < 0) PetscFunctionReturn(0);
1020ef0bb6c7SMatthew G. Knepley   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
1021ef0bb6c7SMatthew G. Knepley   PetscValidPointer(points, 3);
1022ef0bb6c7SMatthew G. Knepley   PetscValidPointer(T, 5);
102376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
102420cf1dd8SToby Isaac     DM               dm;
1025ef0bb6c7SMatthew G. Knepley     PetscDualSpace   Q;
1026ef0bb6c7SMatthew G. Knepley     PetscInt         Nb;   /* Dimension of FE space P */
1027ef0bb6c7SMatthew G. Knepley     PetscInt         Nc;   /* Field components */
1028ef0bb6c7SMatthew G. Knepley     PetscInt         cdim; /* Reference coordinate dimension */
1029ef0bb6c7SMatthew G. Knepley 
1030ef0bb6c7SMatthew G. Knepley     ierr = PetscFEGetDualSpace(fem, &Q);CHKERRQ(ierr);
1031ef0bb6c7SMatthew G. Knepley     ierr = PetscDualSpaceGetDM(Q, &dm);CHKERRQ(ierr);
1032ef0bb6c7SMatthew G. Knepley     ierr = DMGetDimension(dm, &cdim);CHKERRQ(ierr);
1033ef0bb6c7SMatthew G. Knepley     ierr = PetscDualSpaceGetDimension(Q, &Nb);CHKERRQ(ierr);
1034ef0bb6c7SMatthew G. Knepley     ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
1035ef0bb6c7SMatthew 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);
1036ef0bb6c7SMatthew 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);
1037ef0bb6c7SMatthew 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);
1038ef0bb6c7SMatthew 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);
1039ef0bb6c7SMatthew G. Knepley   }
1040ef0bb6c7SMatthew G. Knepley   T->Nr = 1;
1041ef0bb6c7SMatthew G. Knepley   T->Np = npoints;
1042ef0bb6c7SMatthew G. Knepley   ierr = (*fem->ops->createtabulation)(fem, npoints, points, K, T);CHKERRQ(ierr);
1043ef0bb6c7SMatthew G. Knepley   PetscFunctionReturn(0);
1044ef0bb6c7SMatthew G. Knepley }
1045ef0bb6c7SMatthew G. Knepley 
1046ef0bb6c7SMatthew G. Knepley /*@C
1047ef0bb6c7SMatthew G. Knepley   PetscTabulationDestroy - Frees memory from the associated tabulation.
1048ef0bb6c7SMatthew G. Knepley 
1049ef0bb6c7SMatthew G. Knepley   Not collective
1050ef0bb6c7SMatthew G. Knepley 
1051ef0bb6c7SMatthew G. Knepley   Input Parameter:
1052ef0bb6c7SMatthew G. Knepley . T - The tabulation
1053ef0bb6c7SMatthew G. Knepley 
1054ef0bb6c7SMatthew G. Knepley   Level: intermediate
1055ef0bb6c7SMatthew G. Knepley 
1056ef0bb6c7SMatthew G. Knepley .seealso: PetscFECreateTabulation(), PetscFEGetCellTabulation()
1057ef0bb6c7SMatthew G. Knepley @*/
1058ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscTabulationDestroy(PetscTabulation *T)
1059ef0bb6c7SMatthew G. Knepley {
1060ef0bb6c7SMatthew G. Knepley   PetscInt       k;
106120cf1dd8SToby Isaac   PetscErrorCode ierr;
106220cf1dd8SToby Isaac 
106320cf1dd8SToby Isaac   PetscFunctionBegin;
1064ef0bb6c7SMatthew G. Knepley   PetscValidPointer(T, 1);
1065ef0bb6c7SMatthew G. Knepley   if (!T || !(*T)) PetscFunctionReturn(0);
1066ef0bb6c7SMatthew G. Knepley   for (k = 0; k <= (*T)->K; ++k) {ierr = PetscFree((*T)->T[k]);CHKERRQ(ierr);}
1067ef0bb6c7SMatthew G. Knepley   ierr = PetscFree((*T)->T);CHKERRQ(ierr);
1068ef0bb6c7SMatthew G. Knepley   ierr = PetscFree(*T);CHKERRQ(ierr);
1069ef0bb6c7SMatthew G. Knepley   *T = NULL;
107020cf1dd8SToby Isaac   PetscFunctionReturn(0);
107120cf1dd8SToby Isaac }
107220cf1dd8SToby Isaac 
107320cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode PetscFECreatePointTrace(PetscFE fe, PetscInt refPoint, PetscFE *trFE)
107420cf1dd8SToby Isaac {
107520cf1dd8SToby Isaac   PetscSpace     bsp, bsubsp;
107620cf1dd8SToby Isaac   PetscDualSpace dsp, dsubsp;
107720cf1dd8SToby Isaac   PetscInt       dim, depth, numComp, i, j, coneSize, order;
107820cf1dd8SToby Isaac   PetscFEType    type;
107920cf1dd8SToby Isaac   DM             dm;
108020cf1dd8SToby Isaac   DMLabel        label;
108120cf1dd8SToby Isaac   PetscReal      *xi, *v, *J, detJ;
1082db11e2ebSMatthew G. Knepley   const char     *name;
108320cf1dd8SToby Isaac   PetscQuadrature origin, fullQuad, subQuad;
108420cf1dd8SToby Isaac   PetscErrorCode ierr;
108520cf1dd8SToby Isaac 
108620cf1dd8SToby Isaac   PetscFunctionBegin;
108720cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1);
108820cf1dd8SToby Isaac   PetscValidPointer(trFE,3);
108920cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe,&bsp);CHKERRQ(ierr);
109020cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr);
109120cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr);
109220cf1dd8SToby Isaac   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
109320cf1dd8SToby Isaac   ierr = DMPlexGetDepthLabel(dm,&label);CHKERRQ(ierr);
109420cf1dd8SToby Isaac   ierr = DMLabelGetValue(label,refPoint,&depth);CHKERRQ(ierr);
109520cf1dd8SToby Isaac   ierr = PetscCalloc1(depth,&xi);CHKERRQ(ierr);
109620cf1dd8SToby Isaac   ierr = PetscMalloc1(dim,&v);CHKERRQ(ierr);
109720cf1dd8SToby Isaac   ierr = PetscMalloc1(dim*dim,&J);CHKERRQ(ierr);
109820cf1dd8SToby Isaac   for (i = 0; i < depth; i++) xi[i] = 0.;
109920cf1dd8SToby Isaac   ierr = PetscQuadratureCreate(PETSC_COMM_SELF,&origin);CHKERRQ(ierr);
110020cf1dd8SToby Isaac   ierr = PetscQuadratureSetData(origin,depth,0,1,xi,NULL);CHKERRQ(ierr);
110120cf1dd8SToby Isaac   ierr = DMPlexComputeCellGeometryFEM(dm,refPoint,origin,v,J,NULL,&detJ);CHKERRQ(ierr);
110220cf1dd8SToby Isaac   /* CellGeometryFEM computes the expanded Jacobian, we want the true jacobian */
110320cf1dd8SToby Isaac   for (i = 1; i < dim; i++) {
110420cf1dd8SToby Isaac     for (j = 0; j < depth; j++) {
110520cf1dd8SToby Isaac       J[i * depth + j] = J[i * dim + j];
110620cf1dd8SToby Isaac     }
110720cf1dd8SToby Isaac   }
110820cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&origin);CHKERRQ(ierr);
110920cf1dd8SToby Isaac   ierr = PetscDualSpaceGetPointSubspace(dsp,refPoint,&dsubsp);CHKERRQ(ierr);
111020cf1dd8SToby Isaac   ierr = PetscSpaceCreateSubspace(bsp,dsubsp,v,J,NULL,NULL,PETSC_OWN_POINTER,&bsubsp);CHKERRQ(ierr);
111120cf1dd8SToby Isaac   ierr = PetscSpaceSetUp(bsubsp);CHKERRQ(ierr);
111220cf1dd8SToby Isaac   ierr = PetscFECreate(PetscObjectComm((PetscObject)fe),trFE);CHKERRQ(ierr);
111320cf1dd8SToby Isaac   ierr = PetscFEGetType(fe,&type);CHKERRQ(ierr);
111420cf1dd8SToby Isaac   ierr = PetscFESetType(*trFE,type);CHKERRQ(ierr);
111520cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe,&numComp);CHKERRQ(ierr);
111620cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*trFE,numComp);CHKERRQ(ierr);
111720cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*trFE,bsubsp);CHKERRQ(ierr);
111820cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*trFE,dsubsp);CHKERRQ(ierr);
1119db11e2ebSMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr);
1120db11e2ebSMatthew G. Knepley   if (name) {ierr = PetscFESetName(*trFE, name);CHKERRQ(ierr);}
112120cf1dd8SToby Isaac   ierr = PetscFEGetQuadrature(fe,&fullQuad);CHKERRQ(ierr);
112220cf1dd8SToby Isaac   ierr = PetscQuadratureGetOrder(fullQuad,&order);CHKERRQ(ierr);
112320cf1dd8SToby Isaac   ierr = DMPlexGetConeSize(dm,refPoint,&coneSize);CHKERRQ(ierr);
112420cf1dd8SToby Isaac   if (coneSize == 2 * depth) {
112520cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr);
112620cf1dd8SToby Isaac   } else {
1127e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr);
112820cf1dd8SToby Isaac   }
112920cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*trFE,subQuad);CHKERRQ(ierr);
113020cf1dd8SToby Isaac   ierr = PetscFESetUp(*trFE);CHKERRQ(ierr);
113120cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&subQuad);CHKERRQ(ierr);
113220cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&bsubsp);CHKERRQ(ierr);
113320cf1dd8SToby Isaac   PetscFunctionReturn(0);
113420cf1dd8SToby Isaac }
113520cf1dd8SToby Isaac 
113620cf1dd8SToby Isaac PetscErrorCode PetscFECreateHeightTrace(PetscFE fe, PetscInt height, PetscFE *trFE)
113720cf1dd8SToby Isaac {
113820cf1dd8SToby Isaac   PetscInt       hStart, hEnd;
113920cf1dd8SToby Isaac   PetscDualSpace dsp;
114020cf1dd8SToby Isaac   DM             dm;
114120cf1dd8SToby Isaac   PetscErrorCode ierr;
114220cf1dd8SToby Isaac 
114320cf1dd8SToby Isaac   PetscFunctionBegin;
114420cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1);
114520cf1dd8SToby Isaac   PetscValidPointer(trFE,3);
114620cf1dd8SToby Isaac   *trFE = NULL;
114720cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr);
114820cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr);
114920cf1dd8SToby Isaac   ierr = DMPlexGetHeightStratum(dm,height,&hStart,&hEnd);CHKERRQ(ierr);
115020cf1dd8SToby Isaac   if (hEnd <= hStart) PetscFunctionReturn(0);
115120cf1dd8SToby Isaac   ierr = PetscFECreatePointTrace(fe,hStart,trFE);CHKERRQ(ierr);
115220cf1dd8SToby Isaac   PetscFunctionReturn(0);
115320cf1dd8SToby Isaac }
115420cf1dd8SToby Isaac 
115520cf1dd8SToby Isaac 
115620cf1dd8SToby Isaac /*@
115720cf1dd8SToby Isaac   PetscFEGetDimension - Get the dimension of the finite element space on a cell
115820cf1dd8SToby Isaac 
115920cf1dd8SToby Isaac   Not collective
116020cf1dd8SToby Isaac 
116120cf1dd8SToby Isaac   Input Parameter:
116220cf1dd8SToby Isaac . fe - The PetscFE
116320cf1dd8SToby Isaac 
116420cf1dd8SToby Isaac   Output Parameter:
116520cf1dd8SToby Isaac . dim - The dimension
116620cf1dd8SToby Isaac 
116720cf1dd8SToby Isaac   Level: intermediate
116820cf1dd8SToby Isaac 
116920cf1dd8SToby Isaac .seealso: PetscFECreate(), PetscSpaceGetDimension(), PetscDualSpaceGetDimension()
117020cf1dd8SToby Isaac @*/
117120cf1dd8SToby Isaac PetscErrorCode PetscFEGetDimension(PetscFE fem, PetscInt *dim)
117220cf1dd8SToby Isaac {
117320cf1dd8SToby Isaac   PetscErrorCode ierr;
117420cf1dd8SToby Isaac 
117520cf1dd8SToby Isaac   PetscFunctionBegin;
117620cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
117720cf1dd8SToby Isaac   PetscValidPointer(dim, 2);
117820cf1dd8SToby Isaac   if (fem->ops->getdimension) {ierr = (*fem->ops->getdimension)(fem, dim);CHKERRQ(ierr);}
117920cf1dd8SToby Isaac   PetscFunctionReturn(0);
118020cf1dd8SToby Isaac }
118120cf1dd8SToby Isaac 
11824bee2e38SMatthew G. Knepley /*@C
11834bee2e38SMatthew G. Knepley   PetscFEPushforward - Map the reference element function to real space
11844bee2e38SMatthew G. Knepley 
11854bee2e38SMatthew G. Knepley   Input Parameters:
11864bee2e38SMatthew G. Knepley + fe     - The PetscFE
11874bee2e38SMatthew G. Knepley . fegeom - The cell geometry
11884bee2e38SMatthew G. Knepley . Nv     - The number of function values
11894bee2e38SMatthew G. Knepley - vals   - The function values
11904bee2e38SMatthew G. Knepley 
11914bee2e38SMatthew G. Knepley   Output Parameter:
11924bee2e38SMatthew G. Knepley . vals   - The transformed function values
11934bee2e38SMatthew G. Knepley 
11944bee2e38SMatthew G. Knepley   Level: advanced
11954bee2e38SMatthew G. Knepley 
11964bee2e38SMatthew G. Knepley   Note: This just forwards the call onto PetscDualSpacePushforward().
11974bee2e38SMatthew G. Knepley 
1198f9244615SMatthew G. Knepley   Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
11992edcad52SToby Isaac 
12004bee2e38SMatthew G. Knepley .seealso: PetscDualSpacePushforward()
12014bee2e38SMatthew G. Knepley @*/
12022edcad52SToby Isaac PetscErrorCode PetscFEPushforward(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
12034bee2e38SMatthew G. Knepley {
12044bee2e38SMatthew G. Knepley   PetscErrorCode ierr;
12054bee2e38SMatthew G. Knepley 
12062ae266adSMatthew G. Knepley   PetscFunctionBeginHot;
12072edcad52SToby Isaac   ierr = PetscDualSpacePushforward(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr);
12084bee2e38SMatthew G. Knepley   PetscFunctionReturn(0);
12094bee2e38SMatthew G. Knepley }
12104bee2e38SMatthew G. Knepley 
12114bee2e38SMatthew G. Knepley /*@C
12124bee2e38SMatthew G. Knepley   PetscFEPushforwardGradient - Map the reference element function gradient to real space
12134bee2e38SMatthew G. Knepley 
12144bee2e38SMatthew G. Knepley   Input Parameters:
12154bee2e38SMatthew G. Knepley + fe     - The PetscFE
12164bee2e38SMatthew G. Knepley . fegeom - The cell geometry
12174bee2e38SMatthew G. Knepley . Nv     - The number of function gradient values
12184bee2e38SMatthew G. Knepley - vals   - The function gradient values
12194bee2e38SMatthew G. Knepley 
12204bee2e38SMatthew G. Knepley   Output Parameter:
12214bee2e38SMatthew G. Knepley . vals   - The transformed function gradient values
12224bee2e38SMatthew G. Knepley 
12234bee2e38SMatthew G. Knepley   Level: advanced
12244bee2e38SMatthew G. Knepley 
12254bee2e38SMatthew G. Knepley   Note: This just forwards the call onto PetscDualSpacePushforwardGradient().
12264bee2e38SMatthew G. Knepley 
1227f9244615SMatthew G. Knepley   Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
12282edcad52SToby Isaac 
12294bee2e38SMatthew G. Knepley .seealso: PetscFEPushforward(), PetscDualSpacePushforwardGradient(), PetscDualSpacePushforward()
12304bee2e38SMatthew G. Knepley @*/
12312edcad52SToby Isaac PetscErrorCode PetscFEPushforwardGradient(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
12324bee2e38SMatthew G. Knepley {
12334bee2e38SMatthew G. Knepley   PetscErrorCode ierr;
12344bee2e38SMatthew G. Knepley 
12352ae266adSMatthew G. Knepley   PetscFunctionBeginHot;
12362edcad52SToby Isaac   ierr = PetscDualSpacePushforwardGradient(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr);
12374bee2e38SMatthew G. Knepley   PetscFunctionReturn(0);
12384bee2e38SMatthew G. Knepley }
12394bee2e38SMatthew G. Knepley 
1240f9244615SMatthew G. Knepley /*@C
1241f9244615SMatthew G. Knepley   PetscFEPushforwardHessian - Map the reference element function Hessian to real space
1242f9244615SMatthew G. Knepley 
1243f9244615SMatthew G. Knepley   Input Parameters:
1244f9244615SMatthew G. Knepley + fe     - The PetscFE
1245f9244615SMatthew G. Knepley . fegeom - The cell geometry
1246f9244615SMatthew G. Knepley . Nv     - The number of function Hessian values
1247f9244615SMatthew G. Knepley - vals   - The function Hessian values
1248f9244615SMatthew G. Knepley 
1249f9244615SMatthew G. Knepley   Output Parameter:
1250f9244615SMatthew G. Knepley . vals   - The transformed function Hessian values
1251f9244615SMatthew G. Knepley 
1252f9244615SMatthew G. Knepley   Level: advanced
1253f9244615SMatthew G. Knepley 
1254f9244615SMatthew G. Knepley   Note: This just forwards the call onto PetscDualSpacePushforwardHessian().
1255f9244615SMatthew G. Knepley 
1256f9244615SMatthew G. Knepley   Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
1257f9244615SMatthew G. Knepley 
1258f9244615SMatthew G. Knepley .seealso: PetscFEPushforward(), PetscDualSpacePushforwardHessian(), PetscDualSpacePushforward()
1259f9244615SMatthew G. Knepley @*/
1260f9244615SMatthew G. Knepley PetscErrorCode PetscFEPushforwardHessian(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
1261f9244615SMatthew G. Knepley {
1262f9244615SMatthew G. Knepley   PetscErrorCode ierr;
1263f9244615SMatthew G. Knepley 
1264f9244615SMatthew G. Knepley   PetscFunctionBeginHot;
1265f9244615SMatthew G. Knepley   ierr = PetscDualSpacePushforwardHessian(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr);
1266f9244615SMatthew G. Knepley   PetscFunctionReturn(0);
1267f9244615SMatthew G. Knepley }
1268f9244615SMatthew G. Knepley 
126920cf1dd8SToby Isaac /*
127020cf1dd8SToby Isaac Purpose: Compute element vector for chunk of elements
127120cf1dd8SToby Isaac 
127220cf1dd8SToby Isaac Input:
127320cf1dd8SToby Isaac   Sizes:
127420cf1dd8SToby Isaac      Ne:  number of elements
127520cf1dd8SToby Isaac      Nf:  number of fields
127620cf1dd8SToby Isaac      PetscFE
127720cf1dd8SToby Isaac        dim: spatial dimension
127820cf1dd8SToby Isaac        Nb:  number of basis functions
127920cf1dd8SToby Isaac        Nc:  number of field components
128020cf1dd8SToby Isaac        PetscQuadrature
128120cf1dd8SToby Isaac          Nq:  number of quadrature points
128220cf1dd8SToby Isaac 
128320cf1dd8SToby Isaac   Geometry:
128420cf1dd8SToby Isaac      PetscFEGeom[Ne] possibly *Nq
128520cf1dd8SToby Isaac        PetscReal v0s[dim]
128620cf1dd8SToby Isaac        PetscReal n[dim]
128720cf1dd8SToby Isaac        PetscReal jacobians[dim*dim]
128820cf1dd8SToby Isaac        PetscReal jacobianInverses[dim*dim]
128920cf1dd8SToby Isaac        PetscReal jacobianDeterminants
129020cf1dd8SToby Isaac   FEM:
129120cf1dd8SToby Isaac      PetscFE
129220cf1dd8SToby Isaac        PetscQuadrature
129320cf1dd8SToby Isaac          PetscReal   quadPoints[Nq*dim]
129420cf1dd8SToby Isaac          PetscReal   quadWeights[Nq]
129520cf1dd8SToby Isaac        PetscReal   basis[Nq*Nb*Nc]
129620cf1dd8SToby Isaac        PetscReal   basisDer[Nq*Nb*Nc*dim]
129720cf1dd8SToby Isaac      PetscScalar coefficients[Ne*Nb*Nc]
129820cf1dd8SToby Isaac      PetscScalar elemVec[Ne*Nb*Nc]
129920cf1dd8SToby Isaac 
130020cf1dd8SToby Isaac   Problem:
130120cf1dd8SToby Isaac      PetscInt f: the active field
130220cf1dd8SToby Isaac      f0, f1
130320cf1dd8SToby Isaac 
130420cf1dd8SToby Isaac   Work Space:
130520cf1dd8SToby Isaac      PetscFE
130620cf1dd8SToby Isaac        PetscScalar f0[Nq*dim];
130720cf1dd8SToby Isaac        PetscScalar f1[Nq*dim*dim];
130820cf1dd8SToby Isaac        PetscScalar u[Nc];
130920cf1dd8SToby Isaac        PetscScalar gradU[Nc*dim];
131020cf1dd8SToby Isaac        PetscReal   x[dim];
131120cf1dd8SToby Isaac        PetscScalar realSpaceDer[dim];
131220cf1dd8SToby Isaac 
131320cf1dd8SToby Isaac Purpose: Compute element vector for N_cb batches of elements
131420cf1dd8SToby Isaac 
131520cf1dd8SToby Isaac Input:
131620cf1dd8SToby Isaac   Sizes:
131720cf1dd8SToby Isaac      N_cb: Number of serial cell batches
131820cf1dd8SToby Isaac 
131920cf1dd8SToby Isaac   Geometry:
132020cf1dd8SToby Isaac      PetscReal v0s[Ne*dim]
132120cf1dd8SToby Isaac      PetscReal jacobians[Ne*dim*dim]        possibly *Nq
132220cf1dd8SToby Isaac      PetscReal jacobianInverses[Ne*dim*dim] possibly *Nq
132320cf1dd8SToby Isaac      PetscReal jacobianDeterminants[Ne]     possibly *Nq
132420cf1dd8SToby Isaac   FEM:
132520cf1dd8SToby Isaac      static PetscReal   quadPoints[Nq*dim]
132620cf1dd8SToby Isaac      static PetscReal   quadWeights[Nq]
132720cf1dd8SToby Isaac      static PetscReal   basis[Nq*Nb*Nc]
132820cf1dd8SToby Isaac      static PetscReal   basisDer[Nq*Nb*Nc*dim]
132920cf1dd8SToby Isaac      PetscScalar coefficients[Ne*Nb*Nc]
133020cf1dd8SToby Isaac      PetscScalar elemVec[Ne*Nb*Nc]
133120cf1dd8SToby Isaac 
133220cf1dd8SToby Isaac ex62.c:
133320cf1dd8SToby Isaac   PetscErrorCode PetscFEIntegrateResidualBatch(PetscInt Ne, PetscInt numFields, PetscInt field, PetscQuadrature quad[], const PetscScalar coefficients[],
133420cf1dd8SToby Isaac                                                const PetscReal v0s[], const PetscReal jacobians[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[],
133520cf1dd8SToby Isaac                                                void (*f0_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]),
133620cf1dd8SToby Isaac                                                void (*f1_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]), PetscScalar elemVec[])
133720cf1dd8SToby Isaac 
133820cf1dd8SToby Isaac ex52.c:
133920cf1dd8SToby 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)
134020cf1dd8SToby 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)
134120cf1dd8SToby Isaac 
134220cf1dd8SToby Isaac ex52_integrateElement.cu
134320cf1dd8SToby Isaac __global__ void integrateElementQuadrature(int N_cb, realType *coefficients, realType *jacobianInverses, realType *jacobianDeterminants, realType *elemVec)
134420cf1dd8SToby Isaac 
134520cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt Nbl, const PetscScalar coefficients[],
134620cf1dd8SToby Isaac                                                      const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[],
134720cf1dd8SToby Isaac                                                      PetscLogEvent event, PetscInt debug, PetscInt pde_op)
134820cf1dd8SToby Isaac 
134920cf1dd8SToby Isaac ex52_integrateElementOpenCL.c:
135020cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt N_bl, const PetscScalar coefficients[],
135120cf1dd8SToby Isaac                                                      const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[],
135220cf1dd8SToby Isaac                                                      PetscLogEvent event, PetscInt debug, PetscInt pde_op)
135320cf1dd8SToby Isaac 
135420cf1dd8SToby Isaac __kernel void integrateElementQuadrature(int N_cb, __global float *coefficients, __global float *jacobianInverses, __global float *jacobianDeterminants, __global float *elemVec)
135520cf1dd8SToby Isaac */
135620cf1dd8SToby Isaac 
135720cf1dd8SToby Isaac /*@C
135820cf1dd8SToby Isaac   PetscFEIntegrate - Produce the integral for the given field for a chunk of elements by quadrature integration
135920cf1dd8SToby Isaac 
136020cf1dd8SToby Isaac   Not collective
136120cf1dd8SToby Isaac 
136220cf1dd8SToby Isaac   Input Parameters:
1363360cf244SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
136420cf1dd8SToby Isaac . field        - The field being integrated
136520cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
136620cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
136720cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
136820cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
136920cf1dd8SToby Isaac - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
137020cf1dd8SToby Isaac 
13717a7aea1fSJed Brown   Output Parameter:
137220cf1dd8SToby Isaac . integral     - the integral for this field
137320cf1dd8SToby Isaac 
13742b99622eSMatthew G. Knepley   Level: intermediate
137520cf1dd8SToby Isaac 
137620cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
137720cf1dd8SToby Isaac @*/
13784bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrate(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom,
137920cf1dd8SToby Isaac                                 const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
138020cf1dd8SToby Isaac {
13814bee2e38SMatthew G. Knepley   PetscFE        fe;
138220cf1dd8SToby Isaac   PetscErrorCode ierr;
138320cf1dd8SToby Isaac 
138420cf1dd8SToby Isaac   PetscFunctionBegin;
13854bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
13864bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
13874bee2e38SMatthew G. Knepley   if (fe->ops->integrate) {ierr = (*fe->ops->integrate)(prob, field, Ne, cgeom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);}
138820cf1dd8SToby Isaac   PetscFunctionReturn(0);
138920cf1dd8SToby Isaac }
139020cf1dd8SToby Isaac 
139120cf1dd8SToby Isaac /*@C
1392afe6d6adSToby Isaac   PetscFEIntegrateBd - Produce the integral for the given field for a chunk of elements by quadrature integration
1393afe6d6adSToby Isaac 
1394afe6d6adSToby Isaac   Not collective
1395afe6d6adSToby Isaac 
1396afe6d6adSToby Isaac   Input Parameters:
1397360cf244SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
1398afe6d6adSToby Isaac . field        - The field being integrated
1399afe6d6adSToby Isaac . obj_func     - The function to be integrated
1400afe6d6adSToby Isaac . Ne           - The number of elements in the chunk
1401afe6d6adSToby Isaac . fgeom        - The face geometry for each face in the chunk
1402afe6d6adSToby Isaac . coefficients - The array of FEM basis coefficients for the elements
1403afe6d6adSToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
1404afe6d6adSToby Isaac - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1405afe6d6adSToby Isaac 
14067a7aea1fSJed Brown   Output Parameter:
1407afe6d6adSToby Isaac . integral     - the integral for this field
1408afe6d6adSToby Isaac 
14092b99622eSMatthew G. Knepley   Level: intermediate
1410afe6d6adSToby Isaac 
1411afe6d6adSToby Isaac .seealso: PetscFEIntegrateResidual()
1412afe6d6adSToby Isaac @*/
14134bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBd(PetscDS prob, PetscInt field,
1414afe6d6adSToby Isaac                                   void (*obj_func)(PetscInt, PetscInt, PetscInt,
1415afe6d6adSToby Isaac                                                    const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
1416afe6d6adSToby Isaac                                                    const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
1417afe6d6adSToby Isaac                                                    PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
1418afe6d6adSToby Isaac                                   PetscInt Ne, PetscFEGeom *geom, const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
1419afe6d6adSToby Isaac {
14204bee2e38SMatthew G. Knepley   PetscFE        fe;
1421afe6d6adSToby Isaac   PetscErrorCode ierr;
1422afe6d6adSToby Isaac 
1423afe6d6adSToby Isaac   PetscFunctionBegin;
14244bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
14254bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
14264bee2e38SMatthew G. Knepley   if (fe->ops->integratebd) {ierr = (*fe->ops->integratebd)(prob, field, obj_func, Ne, geom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);}
1427afe6d6adSToby Isaac   PetscFunctionReturn(0);
1428afe6d6adSToby Isaac }
1429afe6d6adSToby Isaac 
1430afe6d6adSToby Isaac /*@C
143120cf1dd8SToby Isaac   PetscFEIntegrateResidual - Produce the element residual vector for a chunk of elements by quadrature integration
143220cf1dd8SToby Isaac 
143320cf1dd8SToby Isaac   Not collective
143420cf1dd8SToby Isaac 
143520cf1dd8SToby Isaac   Input Parameters:
1436*6528b96dSMatthew G. Knepley + ds           - The PetscDS specifying the discretizations and continuum functions
1437*6528b96dSMatthew G. Knepley . key          - The (label+value, field) being integrated
143820cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
143920cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
144020cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
144120cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
144220cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
144320cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
144420cf1dd8SToby Isaac - t            - The time
144520cf1dd8SToby Isaac 
14467a7aea1fSJed Brown   Output Parameter:
144720cf1dd8SToby Isaac . elemVec      - the element residual vectors from each element
144820cf1dd8SToby Isaac 
144920cf1dd8SToby Isaac   Note:
145020cf1dd8SToby Isaac $ Loop over batch of elements (e):
145120cf1dd8SToby Isaac $   Loop over quadrature points (q):
145220cf1dd8SToby Isaac $     Make u_q and gradU_q (loops over fields,Nb,Ncomp) and x_q
145320cf1dd8SToby Isaac $     Call f_0 and f_1
145420cf1dd8SToby Isaac $   Loop over element vector entries (f,fc --> i):
145520cf1dd8SToby Isaac $     elemVec[i] += \psi^{fc}_f(q) f0_{fc}(u, \nabla u) + \nabla\psi^{fc}_f(q) \cdot f1_{fc,df}(u, \nabla u)
145620cf1dd8SToby Isaac 
14572b99622eSMatthew G. Knepley   Level: intermediate
145820cf1dd8SToby Isaac 
145920cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
146020cf1dd8SToby Isaac @*/
1461*6528b96dSMatthew G. Knepley PetscErrorCode PetscFEIntegrateResidual(PetscDS ds, PetscHashFormKey key, PetscInt Ne, PetscFEGeom *cgeom,
146220cf1dd8SToby Isaac                                         const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
146320cf1dd8SToby Isaac {
14644bee2e38SMatthew G. Knepley   PetscFE        fe;
146520cf1dd8SToby Isaac   PetscErrorCode ierr;
146620cf1dd8SToby Isaac 
1467*6528b96dSMatthew G. Knepley   PetscFunctionBeginHot;
1468*6528b96dSMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1469*6528b96dSMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, key.field, (PetscObject *) &fe);CHKERRQ(ierr);
1470*6528b96dSMatthew G. Knepley   if (fe->ops->integrateresidual) {ierr = (*fe->ops->integrateresidual)(ds, key, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
147120cf1dd8SToby Isaac   PetscFunctionReturn(0);
147220cf1dd8SToby Isaac }
147320cf1dd8SToby Isaac 
147420cf1dd8SToby Isaac /*@C
147520cf1dd8SToby Isaac   PetscFEIntegrateBdResidual - Produce the element residual vector for a chunk of elements by quadrature integration over a boundary
147620cf1dd8SToby Isaac 
147720cf1dd8SToby Isaac   Not collective
147820cf1dd8SToby Isaac 
147920cf1dd8SToby Isaac   Input Parameters:
1480360cf244SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
148120cf1dd8SToby Isaac . field        - The field being integrated
148220cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
148320cf1dd8SToby Isaac . fgeom        - The face geometry for each cell in the chunk
148420cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
148520cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
148620cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
148720cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
148820cf1dd8SToby Isaac - t            - The time
148920cf1dd8SToby Isaac 
14907a7aea1fSJed Brown   Output Parameter:
149120cf1dd8SToby Isaac . elemVec      - the element residual vectors from each element
149220cf1dd8SToby Isaac 
14932b99622eSMatthew G. Knepley   Level: intermediate
149420cf1dd8SToby Isaac 
149520cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
149620cf1dd8SToby Isaac @*/
14974bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBdResidual(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom,
149820cf1dd8SToby Isaac                                           const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
149920cf1dd8SToby Isaac {
15004bee2e38SMatthew G. Knepley   PetscFE        fe;
150120cf1dd8SToby Isaac   PetscErrorCode ierr;
150220cf1dd8SToby Isaac 
150320cf1dd8SToby Isaac   PetscFunctionBegin;
15044bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
15054bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
15064bee2e38SMatthew G. Knepley   if (fe->ops->integratebdresidual) {ierr = (*fe->ops->integratebdresidual)(prob, field, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
150720cf1dd8SToby Isaac   PetscFunctionReturn(0);
150820cf1dd8SToby Isaac }
150920cf1dd8SToby Isaac 
151020cf1dd8SToby Isaac /*@C
151127f02ce8SMatthew G. Knepley   PetscFEIntegrateHybridResidual - Produce the element residual vector for a chunk of hybrid element faces by quadrature integration
151227f02ce8SMatthew G. Knepley 
151327f02ce8SMatthew G. Knepley   Not collective
151427f02ce8SMatthew G. Knepley 
151527f02ce8SMatthew G. Knepley   Input Parameters:
151627f02ce8SMatthew G. Knepley + prob         - The PetscDS specifying the discretizations and continuum functions
1517*6528b96dSMatthew G. Knepley . key          - The (label+value, field) being integrated
151827f02ce8SMatthew G. Knepley . Ne           - The number of elements in the chunk
151927f02ce8SMatthew G. Knepley . fgeom        - The face geometry for each cell in the chunk
152027f02ce8SMatthew G. Knepley . coefficients - The array of FEM basis coefficients for the elements
152127f02ce8SMatthew G. Knepley . coefficients_t - The array of FEM basis time derivative coefficients for the elements
152227f02ce8SMatthew G. Knepley . probAux      - The PetscDS specifying the auxiliary discretizations
152327f02ce8SMatthew G. Knepley . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
152427f02ce8SMatthew G. Knepley - t            - The time
152527f02ce8SMatthew G. Knepley 
152627f02ce8SMatthew G. Knepley   Output Parameter
152727f02ce8SMatthew G. Knepley . elemVec      - the element residual vectors from each element
152827f02ce8SMatthew G. Knepley 
152927f02ce8SMatthew G. Knepley   Level: developer
153027f02ce8SMatthew G. Knepley 
153127f02ce8SMatthew G. Knepley .seealso: PetscFEIntegrateResidual()
153227f02ce8SMatthew G. Knepley @*/
1533*6528b96dSMatthew G. Knepley PetscErrorCode PetscFEIntegrateHybridResidual(PetscDS prob, PetscHashFormKey key, PetscInt Ne, PetscFEGeom *fgeom,
153427f02ce8SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
153527f02ce8SMatthew G. Knepley {
153627f02ce8SMatthew G. Knepley   PetscFE        fe;
153727f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
153827f02ce8SMatthew G. Knepley 
153927f02ce8SMatthew G. Knepley   PetscFunctionBegin;
154027f02ce8SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1541*6528b96dSMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, key.field, (PetscObject *) &fe);CHKERRQ(ierr);
1542*6528b96dSMatthew G. Knepley   if (fe->ops->integratehybridresidual) {ierr = (*fe->ops->integratehybridresidual)(prob, key, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
154327f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
154427f02ce8SMatthew G. Knepley }
154527f02ce8SMatthew G. Knepley 
154627f02ce8SMatthew G. Knepley /*@C
154720cf1dd8SToby Isaac   PetscFEIntegrateJacobian - Produce the element Jacobian for a chunk of elements by quadrature integration
154820cf1dd8SToby Isaac 
154920cf1dd8SToby Isaac   Not collective
155020cf1dd8SToby Isaac 
155120cf1dd8SToby Isaac   Input Parameters:
1552*6528b96dSMatthew G. Knepley + ds           - The PetscDS specifying the discretizations and continuum functions
155320cf1dd8SToby Isaac . jtype        - The type of matrix pointwise functions that should be used
1554*6528b96dSMatthew G. Knepley . key          - The (label+value, fieldI*Nf + fieldJ) being integrated
155520cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
155620cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
155720cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
155820cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
155920cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
156020cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
156120cf1dd8SToby Isaac . t            - The time
156220cf1dd8SToby Isaac - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
156320cf1dd8SToby Isaac 
15647a7aea1fSJed Brown   Output Parameter:
156520cf1dd8SToby Isaac . elemMat      - the element matrices for the Jacobian from each element
156620cf1dd8SToby Isaac 
156720cf1dd8SToby Isaac   Note:
156820cf1dd8SToby Isaac $ Loop over batch of elements (e):
156920cf1dd8SToby Isaac $   Loop over element matrix entries (f,fc,g,gc --> i,j):
157020cf1dd8SToby Isaac $     Loop over quadrature points (q):
157120cf1dd8SToby Isaac $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
157220cf1dd8SToby Isaac $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
157320cf1dd8SToby Isaac $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
157420cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
157520cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
15762b99622eSMatthew G. Knepley   Level: intermediate
157720cf1dd8SToby Isaac 
157820cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
157920cf1dd8SToby Isaac @*/
1580*6528b96dSMatthew G. Knepley PetscErrorCode PetscFEIntegrateJacobian(PetscDS ds, PetscFEJacobianType jtype, PetscHashFormKey key, PetscInt Ne, PetscFEGeom *cgeom,
158120cf1dd8SToby Isaac                                         const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
158220cf1dd8SToby Isaac {
15834bee2e38SMatthew G. Knepley   PetscFE        fe;
1584*6528b96dSMatthew G. Knepley   PetscInt       Nf;
158520cf1dd8SToby Isaac   PetscErrorCode ierr;
158620cf1dd8SToby Isaac 
158720cf1dd8SToby Isaac   PetscFunctionBegin;
1588*6528b96dSMatthew G. Knepley   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1589*6528b96dSMatthew G. Knepley   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
1590*6528b96dSMatthew G. Knepley   ierr = PetscDSGetDiscretization(ds, key.field / Nf, (PetscObject *) &fe);CHKERRQ(ierr);
1591*6528b96dSMatthew G. Knepley   if (fe->ops->integratejacobian) {ierr = (*fe->ops->integratejacobian)(ds, jtype, key, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);}
159220cf1dd8SToby Isaac   PetscFunctionReturn(0);
159320cf1dd8SToby Isaac }
159420cf1dd8SToby Isaac 
159520cf1dd8SToby Isaac /*@C
159620cf1dd8SToby Isaac   PetscFEIntegrateBdJacobian - Produce the boundary element Jacobian for a chunk of elements by quadrature integration
159720cf1dd8SToby Isaac 
159820cf1dd8SToby Isaac   Not collective
159920cf1dd8SToby Isaac 
160020cf1dd8SToby Isaac   Input Parameters:
1601f0fc11ceSJed Brown + prob         - The PetscDS specifying the discretizations and continuum functions
160220cf1dd8SToby Isaac . fieldI       - The test field being integrated
160320cf1dd8SToby Isaac . fieldJ       - The basis field being integrated
160420cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
160520cf1dd8SToby Isaac . fgeom        - The face geometry for each cell in the chunk
160620cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
160720cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
160820cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
160920cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
161020cf1dd8SToby Isaac . t            - The time
161120cf1dd8SToby Isaac - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
161220cf1dd8SToby Isaac 
16137a7aea1fSJed Brown   Output Parameter:
161420cf1dd8SToby Isaac . elemMat              - the element matrices for the Jacobian from each element
161520cf1dd8SToby Isaac 
161620cf1dd8SToby Isaac   Note:
161720cf1dd8SToby Isaac $ Loop over batch of elements (e):
161820cf1dd8SToby Isaac $   Loop over element matrix entries (f,fc,g,gc --> i,j):
161920cf1dd8SToby Isaac $     Loop over quadrature points (q):
162020cf1dd8SToby Isaac $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
162120cf1dd8SToby Isaac $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
162220cf1dd8SToby Isaac $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
162320cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
162420cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
16252b99622eSMatthew G. Knepley   Level: intermediate
162620cf1dd8SToby Isaac 
162720cf1dd8SToby Isaac .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual()
162820cf1dd8SToby Isaac @*/
16294bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBdJacobian(PetscDS prob, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
163020cf1dd8SToby Isaac                                           const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
163120cf1dd8SToby Isaac {
16324bee2e38SMatthew G. Knepley   PetscFE        fe;
163320cf1dd8SToby Isaac   PetscErrorCode ierr;
163420cf1dd8SToby Isaac 
163520cf1dd8SToby Isaac   PetscFunctionBegin;
16364bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
16374bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
16384bee2e38SMatthew 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);}
163920cf1dd8SToby Isaac   PetscFunctionReturn(0);
164020cf1dd8SToby Isaac }
164120cf1dd8SToby Isaac 
164227f02ce8SMatthew G. Knepley /*@C
164327f02ce8SMatthew G. Knepley   PetscFEIntegrateHybridJacobian - Produce the boundary element Jacobian for a chunk of hybrid elements by quadrature integration
164427f02ce8SMatthew G. Knepley 
164527f02ce8SMatthew G. Knepley   Not collective
164627f02ce8SMatthew G. Knepley 
164727f02ce8SMatthew G. Knepley   Input Parameters:
1648ee300463SSatish Balay + prob         - The PetscDS specifying the discretizations and continuum functions
164927f02ce8SMatthew G. Knepley . jtype        - The type of matrix pointwise functions that should be used
165027f02ce8SMatthew G. Knepley . fieldI       - The test field being integrated
165127f02ce8SMatthew G. Knepley . fieldJ       - The basis field being integrated
165227f02ce8SMatthew G. Knepley . Ne           - The number of elements in the chunk
165327f02ce8SMatthew G. Knepley . fgeom        - The face geometry for each cell in the chunk
165427f02ce8SMatthew G. Knepley . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
165527f02ce8SMatthew G. Knepley . coefficients_t - The array of FEM basis time derivative coefficients for the elements
165627f02ce8SMatthew G. Knepley . probAux      - The PetscDS specifying the auxiliary discretizations
165727f02ce8SMatthew G. Knepley . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
165827f02ce8SMatthew G. Knepley . t            - The time
165927f02ce8SMatthew G. Knepley - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
166027f02ce8SMatthew G. Knepley 
166127f02ce8SMatthew G. Knepley   Output Parameter
166227f02ce8SMatthew G. Knepley . elemMat              - the element matrices for the Jacobian from each element
166327f02ce8SMatthew G. Knepley 
166427f02ce8SMatthew G. Knepley   Note:
166527f02ce8SMatthew G. Knepley $ Loop over batch of elements (e):
166627f02ce8SMatthew G. Knepley $   Loop over element matrix entries (f,fc,g,gc --> i,j):
166727f02ce8SMatthew G. Knepley $     Loop over quadrature points (q):
166827f02ce8SMatthew G. Knepley $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
166927f02ce8SMatthew G. Knepley $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
167027f02ce8SMatthew G. Knepley $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
167127f02ce8SMatthew G. Knepley $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
167227f02ce8SMatthew G. Knepley $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
167327f02ce8SMatthew G. Knepley   Level: developer
167427f02ce8SMatthew G. Knepley 
167527f02ce8SMatthew G. Knepley .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual()
167627f02ce8SMatthew G. Knepley @*/
167727f02ce8SMatthew G. Knepley PetscErrorCode PetscFEIntegrateHybridJacobian(PetscDS prob, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
167827f02ce8SMatthew G. Knepley                                               const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
167927f02ce8SMatthew G. Knepley {
168027f02ce8SMatthew G. Knepley   PetscFE        fe;
168127f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
168227f02ce8SMatthew G. Knepley 
168327f02ce8SMatthew G. Knepley   PetscFunctionBegin;
168427f02ce8SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
168527f02ce8SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
168627f02ce8SMatthew 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);}
168727f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
168827f02ce8SMatthew G. Knepley }
168927f02ce8SMatthew G. Knepley 
16902b99622eSMatthew G. Knepley /*@
16912b99622eSMatthew G. Knepley   PetscFEGetHeightSubspace - Get the subspace of this space for a mesh point of a given height
16922b99622eSMatthew G. Knepley 
16932b99622eSMatthew G. Knepley   Input Parameters:
16942b99622eSMatthew G. Knepley + fe     - The finite element space
16952b99622eSMatthew G. Knepley - height - The height of the Plex point
16962b99622eSMatthew G. Knepley 
16972b99622eSMatthew G. Knepley   Output Parameter:
16982b99622eSMatthew G. Knepley . subfe  - The subspace of this FE space
16992b99622eSMatthew G. Knepley 
17002b99622eSMatthew G. Knepley   Note: For example, if we want the subspace of this space for a face, we would choose height = 1.
17012b99622eSMatthew G. Knepley 
17022b99622eSMatthew G. Knepley   Level: advanced
17032b99622eSMatthew G. Knepley 
17042b99622eSMatthew G. Knepley .seealso: PetscFECreateDefault()
17052b99622eSMatthew G. Knepley @*/
170620cf1dd8SToby Isaac PetscErrorCode PetscFEGetHeightSubspace(PetscFE fe, PetscInt height, PetscFE *subfe)
170720cf1dd8SToby Isaac {
170820cf1dd8SToby Isaac   PetscSpace      P, subP;
170920cf1dd8SToby Isaac   PetscDualSpace  Q, subQ;
171020cf1dd8SToby Isaac   PetscQuadrature subq;
171120cf1dd8SToby Isaac   PetscFEType     fetype;
171220cf1dd8SToby Isaac   PetscInt        dim, Nc;
171320cf1dd8SToby Isaac   PetscErrorCode  ierr;
171420cf1dd8SToby Isaac 
171520cf1dd8SToby Isaac   PetscFunctionBegin;
171620cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe, PETSCFE_CLASSID, 1);
171720cf1dd8SToby Isaac   PetscValidPointer(subfe, 3);
171820cf1dd8SToby Isaac   if (height == 0) {
171920cf1dd8SToby Isaac     *subfe = fe;
172020cf1dd8SToby Isaac     PetscFunctionReturn(0);
172120cf1dd8SToby Isaac   }
172220cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
172320cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
172420cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr);
172520cf1dd8SToby Isaac   ierr = PetscFEGetFaceQuadrature(fe, &subq);CHKERRQ(ierr);
172620cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDimension(Q, &dim);CHKERRQ(ierr);
17272da392ccSBarry Smith   if (height > dim || height < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Asked for space at height %D for dimension %D space", height, dim);
172820cf1dd8SToby Isaac   if (!fe->subspaces) {ierr = PetscCalloc1(dim, &fe->subspaces);CHKERRQ(ierr);}
172920cf1dd8SToby Isaac   if (height <= dim) {
173020cf1dd8SToby Isaac     if (!fe->subspaces[height-1]) {
1731665f567fSMatthew G. Knepley       PetscFE     sub = NULL;
17323f6b16c7SMatthew G. Knepley       const char *name;
173320cf1dd8SToby Isaac 
173420cf1dd8SToby Isaac       ierr = PetscSpaceGetHeightSubspace(P, height, &subP);CHKERRQ(ierr);
173520cf1dd8SToby Isaac       ierr = PetscDualSpaceGetHeightSubspace(Q, height, &subQ);CHKERRQ(ierr);
1736665f567fSMatthew G. Knepley       if (subQ) {
173720cf1dd8SToby Isaac         ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), &sub);CHKERRQ(ierr);
17383f6b16c7SMatthew G. Knepley         ierr = PetscObjectGetName((PetscObject) fe,  &name);CHKERRQ(ierr);
17393f6b16c7SMatthew G. Knepley         ierr = PetscObjectSetName((PetscObject) sub,  name);CHKERRQ(ierr);
174020cf1dd8SToby Isaac         ierr = PetscFEGetType(fe, &fetype);CHKERRQ(ierr);
174120cf1dd8SToby Isaac         ierr = PetscFESetType(sub, fetype);CHKERRQ(ierr);
174220cf1dd8SToby Isaac         ierr = PetscFESetBasisSpace(sub, subP);CHKERRQ(ierr);
174320cf1dd8SToby Isaac         ierr = PetscFESetDualSpace(sub, subQ);CHKERRQ(ierr);
174420cf1dd8SToby Isaac         ierr = PetscFESetNumComponents(sub, Nc);CHKERRQ(ierr);
174520cf1dd8SToby Isaac         ierr = PetscFESetUp(sub);CHKERRQ(ierr);
174620cf1dd8SToby Isaac         ierr = PetscFESetQuadrature(sub, subq);CHKERRQ(ierr);
1747665f567fSMatthew G. Knepley       }
174820cf1dd8SToby Isaac       fe->subspaces[height-1] = sub;
174920cf1dd8SToby Isaac     }
175020cf1dd8SToby Isaac     *subfe = fe->subspaces[height-1];
175120cf1dd8SToby Isaac   } else {
175220cf1dd8SToby Isaac     *subfe = NULL;
175320cf1dd8SToby Isaac   }
175420cf1dd8SToby Isaac   PetscFunctionReturn(0);
175520cf1dd8SToby Isaac }
175620cf1dd8SToby Isaac 
175720cf1dd8SToby Isaac /*@
175820cf1dd8SToby Isaac   PetscFERefine - Create a "refined" PetscFE object that refines the reference cell into smaller copies. This is typically used
175920cf1dd8SToby Isaac   to precondition a higher order method with a lower order method on a refined mesh having the same number of dofs (but more
176020cf1dd8SToby Isaac   sparsity). It is also used to create an interpolation between regularly refined meshes.
176120cf1dd8SToby Isaac 
1762d083f849SBarry Smith   Collective on fem
176320cf1dd8SToby Isaac 
176420cf1dd8SToby Isaac   Input Parameter:
176520cf1dd8SToby Isaac . fe - The initial PetscFE
176620cf1dd8SToby Isaac 
176720cf1dd8SToby Isaac   Output Parameter:
176820cf1dd8SToby Isaac . feRef - The refined PetscFE
176920cf1dd8SToby Isaac 
17702b99622eSMatthew G. Knepley   Level: advanced
177120cf1dd8SToby Isaac 
177220cf1dd8SToby Isaac .seealso: PetscFEType, PetscFECreate(), PetscFESetType()
177320cf1dd8SToby Isaac @*/
177420cf1dd8SToby Isaac PetscErrorCode PetscFERefine(PetscFE fe, PetscFE *feRef)
177520cf1dd8SToby Isaac {
177620cf1dd8SToby Isaac   PetscSpace       P, Pref;
177720cf1dd8SToby Isaac   PetscDualSpace   Q, Qref;
177820cf1dd8SToby Isaac   DM               K, Kref;
177920cf1dd8SToby Isaac   PetscQuadrature  q, qref;
178020cf1dd8SToby Isaac   const PetscReal *v0, *jac;
178120cf1dd8SToby Isaac   PetscInt         numComp, numSubelements;
17821ac17e89SToby Isaac   PetscInt         cStart, cEnd, c;
17831ac17e89SToby Isaac   PetscDualSpace  *cellSpaces;
178420cf1dd8SToby Isaac   PetscErrorCode   ierr;
178520cf1dd8SToby Isaac 
178620cf1dd8SToby Isaac   PetscFunctionBegin;
178720cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
178820cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
178920cf1dd8SToby Isaac   ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr);
179020cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(Q, &K);CHKERRQ(ierr);
179120cf1dd8SToby Isaac   /* Create space */
179220cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) P);CHKERRQ(ierr);
179320cf1dd8SToby Isaac   Pref = P;
179420cf1dd8SToby Isaac   /* Create dual space */
179520cf1dd8SToby Isaac   ierr = PetscDualSpaceDuplicate(Q, &Qref);CHKERRQ(ierr);
17961ac17e89SToby Isaac   ierr = PetscDualSpaceSetType(Qref, PETSCDUALSPACEREFINED);CHKERRQ(ierr);
179720cf1dd8SToby Isaac   ierr = DMRefine(K, PetscObjectComm((PetscObject) fe), &Kref);CHKERRQ(ierr);
179820cf1dd8SToby Isaac   ierr = PetscDualSpaceSetDM(Qref, Kref);CHKERRQ(ierr);
17991ac17e89SToby Isaac   ierr = DMPlexGetHeightStratum(Kref, 0, &cStart, &cEnd);CHKERRQ(ierr);
18001ac17e89SToby Isaac   ierr = PetscMalloc1(cEnd - cStart, &cellSpaces);CHKERRQ(ierr);
18011ac17e89SToby Isaac   /* TODO: fix for non-uniform refinement */
18021ac17e89SToby Isaac   for (c = 0; c < cEnd - cStart; c++) cellSpaces[c] = Q;
18031ac17e89SToby Isaac   ierr = PetscDualSpaceRefinedSetCellSpaces(Qref, cellSpaces);CHKERRQ(ierr);
18041ac17e89SToby Isaac   ierr = PetscFree(cellSpaces);CHKERRQ(ierr);
180520cf1dd8SToby Isaac   ierr = DMDestroy(&Kref);CHKERRQ(ierr);
180620cf1dd8SToby Isaac   ierr = PetscDualSpaceSetUp(Qref);CHKERRQ(ierr);
180720cf1dd8SToby Isaac   /* Create element */
180820cf1dd8SToby Isaac   ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), feRef);CHKERRQ(ierr);
180920cf1dd8SToby Isaac   ierr = PetscFESetType(*feRef, PETSCFECOMPOSITE);CHKERRQ(ierr);
181020cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*feRef, Pref);CHKERRQ(ierr);
181120cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*feRef, Qref);CHKERRQ(ierr);
181220cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe,    &numComp);CHKERRQ(ierr);
181320cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*feRef, numComp);CHKERRQ(ierr);
181420cf1dd8SToby Isaac   ierr = PetscFESetUp(*feRef);CHKERRQ(ierr);
181520cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&Pref);CHKERRQ(ierr);
181620cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&Qref);CHKERRQ(ierr);
181720cf1dd8SToby Isaac   /* Create quadrature */
181820cf1dd8SToby Isaac   ierr = PetscFECompositeGetMapping(*feRef, &numSubelements, &v0, &jac, NULL);CHKERRQ(ierr);
181920cf1dd8SToby Isaac   ierr = PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref);CHKERRQ(ierr);
182020cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*feRef, qref);CHKERRQ(ierr);
182120cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&qref);CHKERRQ(ierr);
182220cf1dd8SToby Isaac   PetscFunctionReturn(0);
182320cf1dd8SToby Isaac }
182420cf1dd8SToby Isaac 
182520cf1dd8SToby Isaac /*@C
182620cf1dd8SToby Isaac   PetscFECreateDefault - Create a PetscFE for basic FEM computation
182720cf1dd8SToby Isaac 
1828d083f849SBarry Smith   Collective
182920cf1dd8SToby Isaac 
183020cf1dd8SToby Isaac   Input Parameters:
18317be5e748SToby Isaac + comm      - The MPI comm
183220cf1dd8SToby Isaac . dim       - The spatial dimension
183320cf1dd8SToby Isaac . Nc        - The number of components
183420cf1dd8SToby Isaac . isSimplex - Flag for simplex reference cell, otherwise its a tensor product
183520cf1dd8SToby Isaac . prefix    - The options prefix, or NULL
1836727cddd5SJacob Faibussowitsch - qorder    - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree
183720cf1dd8SToby Isaac 
183820cf1dd8SToby Isaac   Output Parameter:
183920cf1dd8SToby Isaac . fem - The PetscFE object
184020cf1dd8SToby Isaac 
1841e703855dSMatthew G. Knepley   Note:
1842e703855dSMatthew G. Knepley   Each object is SetFromOption() during creation, so that the object may be customized from the command line.
1843e703855dSMatthew G. Knepley 
184420cf1dd8SToby Isaac   Level: beginner
184520cf1dd8SToby Isaac 
184620cf1dd8SToby Isaac .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
184720cf1dd8SToby Isaac @*/
18487be5e748SToby Isaac PetscErrorCode PetscFECreateDefault(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, const char prefix[], PetscInt qorder, PetscFE *fem)
184920cf1dd8SToby Isaac {
185020cf1dd8SToby Isaac   PetscQuadrature q, fq;
185120cf1dd8SToby Isaac   DM              K;
185220cf1dd8SToby Isaac   PetscSpace      P;
185320cf1dd8SToby Isaac   PetscDualSpace  Q;
185420cf1dd8SToby Isaac   PetscInt        order, quadPointsPerEdge;
185520cf1dd8SToby Isaac   PetscBool       tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
185620cf1dd8SToby Isaac   PetscErrorCode  ierr;
185720cf1dd8SToby Isaac 
185820cf1dd8SToby Isaac   PetscFunctionBegin;
185920cf1dd8SToby Isaac   /* Create space */
18607be5e748SToby Isaac   ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr);
186120cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix);CHKERRQ(ierr);
186220cf1dd8SToby Isaac   ierr = PetscSpacePolynomialSetTensor(P, tensor);CHKERRQ(ierr);
186320cf1dd8SToby Isaac   ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr);
186420cf1dd8SToby Isaac   ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr);
1865028afddaSToby Isaac   ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr);
186620cf1dd8SToby Isaac   ierr = PetscSpaceSetUp(P);CHKERRQ(ierr);
186720cf1dd8SToby Isaac   ierr = PetscSpaceGetDegree(P, &order, NULL);CHKERRQ(ierr);
186820cf1dd8SToby Isaac   ierr = PetscSpacePolynomialGetTensor(P, &tensor);CHKERRQ(ierr);
186920cf1dd8SToby Isaac   /* Create dual space */
18707be5e748SToby Isaac   ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr);
187120cf1dd8SToby Isaac   ierr = PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
187220cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);CHKERRQ(ierr);
187320cf1dd8SToby Isaac   ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr);
187420cf1dd8SToby Isaac   ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr);
187520cf1dd8SToby Isaac   ierr = DMDestroy(&K);CHKERRQ(ierr);
187620cf1dd8SToby Isaac   ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr);
187720cf1dd8SToby Isaac   ierr = PetscDualSpaceSetOrder(Q, order);CHKERRQ(ierr);
187820cf1dd8SToby Isaac   ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor);CHKERRQ(ierr);
187920cf1dd8SToby Isaac   ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr);
188020cf1dd8SToby Isaac   ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr);
188120cf1dd8SToby Isaac   /* Create element */
18827be5e748SToby Isaac   ierr = PetscFECreate(comm, fem);CHKERRQ(ierr);
188320cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);CHKERRQ(ierr);
188420cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr);
188520cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr);
188620cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr);
188791e89cf0SMatthew G. Knepley   ierr = PetscFESetFromOptions(*fem);CHKERRQ(ierr);
188820cf1dd8SToby Isaac   ierr = PetscFESetUp(*fem);CHKERRQ(ierr);
188920cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr);
189020cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr);
189120cf1dd8SToby Isaac   /* Create quadrature (with specified order if given) */
189220cf1dd8SToby Isaac   qorder = qorder >= 0 ? qorder : order;
189320cf1dd8SToby Isaac   ierr = PetscObjectOptionsBegin((PetscObject)*fem);CHKERRQ(ierr);
18945a856986SBarry Smith   ierr = PetscOptionsBoundedInt("-petscfe_default_quadrature_order","Quadrature order is one less than quadrature points per edge","PetscFECreateDefault",qorder,&qorder,NULL,0);CHKERRQ(ierr);
189520cf1dd8SToby Isaac   ierr = PetscOptionsEnd();CHKERRQ(ierr);
189620cf1dd8SToby Isaac   quadPointsPerEdge = PetscMax(qorder + 1,1);
189720cf1dd8SToby Isaac   if (isSimplex) {
1898e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
1899e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
19004ccfa306SStefano Zampini   } else {
190120cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
190220cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
190320cf1dd8SToby Isaac   }
190420cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr);
190520cf1dd8SToby Isaac   ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr);
190620cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr);
190720cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr);
190820cf1dd8SToby Isaac   PetscFunctionReturn(0);
190920cf1dd8SToby Isaac }
19103f6b16c7SMatthew G. Knepley 
1911e703855dSMatthew G. Knepley /*@
1912e703855dSMatthew G. Knepley   PetscFECreateLagrange - Create a PetscFE for the basic Lagrange space of degree k
1913e703855dSMatthew G. Knepley 
1914e703855dSMatthew G. Knepley   Collective
1915e703855dSMatthew G. Knepley 
1916e703855dSMatthew G. Knepley   Input Parameters:
1917e703855dSMatthew G. Knepley + comm      - The MPI comm
1918e703855dSMatthew G. Knepley . dim       - The spatial dimension
1919e703855dSMatthew G. Knepley . Nc        - The number of components
1920e703855dSMatthew G. Knepley . isSimplex - Flag for simplex reference cell, otherwise its a tensor product
1921e703855dSMatthew G. Knepley . k         - The degree k of the space
1922e703855dSMatthew G. Knepley - qorder    - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree
1923e703855dSMatthew G. Knepley 
1924e703855dSMatthew G. Knepley   Output Parameter:
1925e703855dSMatthew G. Knepley . fem       - The PetscFE object
1926e703855dSMatthew G. Knepley 
1927e703855dSMatthew G. Knepley   Level: beginner
1928e703855dSMatthew G. Knepley 
1929e703855dSMatthew G. Knepley   Notes:
1930e703855dSMatthew 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.
1931e703855dSMatthew G. Knepley 
1932e703855dSMatthew G. Knepley .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
1933e703855dSMatthew G. Knepley @*/
1934e703855dSMatthew G. Knepley PetscErrorCode PetscFECreateLagrange(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, PetscInt k, PetscInt qorder, PetscFE *fem)
1935e703855dSMatthew G. Knepley {
1936e703855dSMatthew G. Knepley   PetscQuadrature q, fq;
1937e703855dSMatthew G. Knepley   DM              K;
1938e703855dSMatthew G. Knepley   PetscSpace      P;
1939e703855dSMatthew G. Knepley   PetscDualSpace  Q;
1940e703855dSMatthew G. Knepley   PetscInt        quadPointsPerEdge;
1941e703855dSMatthew G. Knepley   PetscBool       tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1942e703855dSMatthew G. Knepley   char            name[64];
1943e703855dSMatthew G. Knepley   PetscErrorCode  ierr;
1944e703855dSMatthew G. Knepley 
1945e703855dSMatthew G. Knepley   PetscFunctionBegin;
1946e703855dSMatthew G. Knepley   /* Create space */
1947e703855dSMatthew G. Knepley   ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr);
1948e703855dSMatthew G. Knepley   ierr = PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr);
1949e703855dSMatthew G. Knepley   ierr = PetscSpacePolynomialSetTensor(P, tensor);CHKERRQ(ierr);
1950e703855dSMatthew G. Knepley   ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr);
1951e703855dSMatthew G. Knepley   ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr);
1952e703855dSMatthew G. Knepley   ierr = PetscSpaceSetDegree(P, k, PETSC_DETERMINE);CHKERRQ(ierr);
1953e703855dSMatthew G. Knepley   ierr = PetscSpaceSetUp(P);CHKERRQ(ierr);
1954e703855dSMatthew G. Knepley   /* Create dual space */
1955e703855dSMatthew G. Knepley   ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr);
1956e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
1957e703855dSMatthew G. Knepley   ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr);
1958e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr);
1959e703855dSMatthew G. Knepley   ierr = DMDestroy(&K);CHKERRQ(ierr);
1960e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr);
1961e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetOrder(Q, k);CHKERRQ(ierr);
1962e703855dSMatthew G. Knepley   ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor);CHKERRQ(ierr);
1963e703855dSMatthew G. Knepley   ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr);
1964849618d6SLisandro Dalcin   /* Create finite element */
1965e703855dSMatthew G. Knepley   ierr = PetscFECreate(comm, fem);CHKERRQ(ierr);
196635e85c11SLisandro Dalcin   ierr = PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);CHKERRQ(ierr);
196735e85c11SLisandro Dalcin   ierr = PetscObjectSetName((PetscObject) *fem, name);CHKERRQ(ierr);
1968e703855dSMatthew G. Knepley   ierr = PetscFESetType(*fem, PETSCFEBASIC);CHKERRQ(ierr);
1969e703855dSMatthew G. Knepley   ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr);
1970e703855dSMatthew G. Knepley   ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr);
1971e703855dSMatthew G. Knepley   ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr);
1972e703855dSMatthew G. Knepley   ierr = PetscFESetUp(*fem);CHKERRQ(ierr);
1973e703855dSMatthew G. Knepley   ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr);
1974e703855dSMatthew G. Knepley   ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr);
1975e703855dSMatthew G. Knepley   /* Create quadrature (with specified order if given) */
1976e703855dSMatthew G. Knepley   qorder = qorder >= 0 ? qorder : k;
1977e703855dSMatthew G. Knepley   quadPointsPerEdge = PetscMax(qorder + 1,1);
1978e703855dSMatthew G. Knepley   if (isSimplex) {
1979e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
1980e6a796c3SToby Isaac     ierr = PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
1981e703855dSMatthew G. Knepley   } else {
1982e703855dSMatthew G. Knepley     ierr = PetscDTGaussTensorQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
1983e703855dSMatthew G. Knepley     ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
1984e703855dSMatthew G. Knepley   }
1985e703855dSMatthew G. Knepley   ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr);
1986e703855dSMatthew G. Knepley   ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr);
1987e703855dSMatthew G. Knepley   ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr);
1988e703855dSMatthew G. Knepley   ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr);
1989849618d6SLisandro Dalcin   /* Set finite element name */
1990849618d6SLisandro Dalcin   ierr = PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);CHKERRQ(ierr);
1991849618d6SLisandro Dalcin   ierr = PetscFESetName(*fem, name);CHKERRQ(ierr);
1992e703855dSMatthew G. Knepley   PetscFunctionReturn(0);
1993e703855dSMatthew G. Knepley }
1994e703855dSMatthew G. Knepley 
19953f6b16c7SMatthew G. Knepley /*@C
19963f6b16c7SMatthew G. Knepley   PetscFESetName - Names the FE and its subobjects
19973f6b16c7SMatthew G. Knepley 
19983f6b16c7SMatthew G. Knepley   Not collective
19993f6b16c7SMatthew G. Knepley 
20003f6b16c7SMatthew G. Knepley   Input Parameters:
20013f6b16c7SMatthew G. Knepley + fe   - The PetscFE
20023f6b16c7SMatthew G. Knepley - name - The name
20033f6b16c7SMatthew G. Knepley 
20042b99622eSMatthew G. Knepley   Level: intermediate
20053f6b16c7SMatthew G. Knepley 
20063f6b16c7SMatthew G. Knepley .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
20073f6b16c7SMatthew G. Knepley @*/
20083f6b16c7SMatthew G. Knepley PetscErrorCode PetscFESetName(PetscFE fe, const char name[])
20093f6b16c7SMatthew G. Knepley {
20103f6b16c7SMatthew G. Knepley   PetscSpace     P;
20113f6b16c7SMatthew G. Knepley   PetscDualSpace Q;
20123f6b16c7SMatthew G. Knepley   PetscErrorCode ierr;
20133f6b16c7SMatthew G. Knepley 
20143f6b16c7SMatthew G. Knepley   PetscFunctionBegin;
20153f6b16c7SMatthew G. Knepley   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
20163f6b16c7SMatthew G. Knepley   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
20173f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) fe, name);CHKERRQ(ierr);
20183f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) P,  name);CHKERRQ(ierr);
20193f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) Q,  name);CHKERRQ(ierr);
20203f6b16c7SMatthew G. Knepley   PetscFunctionReturn(0);
20213f6b16c7SMatthew G. Knepley }
2022a8f1f9e5SMatthew G. Knepley 
2023ef0bb6c7SMatthew 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[])
2024a8f1f9e5SMatthew G. Knepley {
2025f9244615SMatthew G. Knepley   PetscInt       dOffset = 0, fOffset = 0, f, g;
2026a8f1f9e5SMatthew G. Knepley   PetscErrorCode ierr;
2027a8f1f9e5SMatthew G. Knepley 
2028a8f1f9e5SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
2029a8f1f9e5SMatthew G. Knepley     PetscFE          fe;
2030f9244615SMatthew G. Knepley     const PetscInt   k    = ds->jetDegree[f];
2031ef0bb6c7SMatthew G. Knepley     const PetscInt   cdim = T[f]->cdim;
2032ef0bb6c7SMatthew G. Knepley     const PetscInt   Nq   = T[f]->Np;
2033ef0bb6c7SMatthew G. Knepley     const PetscInt   Nbf  = T[f]->Nb;
2034ef0bb6c7SMatthew G. Knepley     const PetscInt   Ncf  = T[f]->Nc;
2035ef0bb6c7SMatthew G. Knepley     const PetscReal *Bq   = &T[f]->T[0][(r*Nq+q)*Nbf*Ncf];
2036ef0bb6c7SMatthew G. Knepley     const PetscReal *Dq   = &T[f]->T[1][(r*Nq+q)*Nbf*Ncf*cdim];
2037f9244615SMatthew G. Knepley     const PetscReal *Hq   = k > 1 ? &T[f]->T[2][(r*Nq+q)*Nbf*Ncf*cdim*cdim] : NULL;
2038f9244615SMatthew G. Knepley     PetscInt         hOffset = 0, b, c, d;
2039a8f1f9e5SMatthew G. Knepley 
2040a8f1f9e5SMatthew G. Knepley     ierr = PetscDSGetDiscretization(ds, f, (PetscObject *) &fe);CHKERRQ(ierr);
2041a8f1f9e5SMatthew G. Knepley     for (c = 0; c < Ncf; ++c) u[fOffset+c] = 0.0;
2042ef0bb6c7SMatthew G. Knepley     for (d = 0; d < cdim*Ncf; ++d) u_x[fOffset*cdim+d] = 0.0;
2043a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nbf; ++b) {
2044a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) {
2045a8f1f9e5SMatthew G. Knepley         const PetscInt cidx = b*Ncf+c;
2046a8f1f9e5SMatthew G. Knepley 
2047a8f1f9e5SMatthew G. Knepley         u[fOffset+c] += Bq[cidx]*coefficients[dOffset+b];
2048ef0bb6c7SMatthew G. Knepley         for (d = 0; d < cdim; ++d) u_x[(fOffset+c)*cdim+d] += Dq[cidx*cdim+d]*coefficients[dOffset+b];
2049a8f1f9e5SMatthew G. Knepley       }
2050a8f1f9e5SMatthew G. Knepley     }
2051f9244615SMatthew G. Knepley     if (k > 1) {
2052f9244615SMatthew G. Knepley       for (g = 0; g < Nf; ++g) hOffset += T[g]->Nc*cdim;
2053f9244615SMatthew G. Knepley       for (d = 0; d < cdim*cdim*Ncf; ++d) u_x[hOffset+fOffset*cdim*cdim+d] = 0.0;
2054f9244615SMatthew G. Knepley       for (b = 0; b < Nbf; ++b) {
2055f9244615SMatthew G. Knepley         for (c = 0; c < Ncf; ++c) {
2056f9244615SMatthew G. Knepley           const PetscInt cidx = b*Ncf+c;
2057f9244615SMatthew G. Knepley 
2058f9244615SMatthew G. Knepley           for (d = 0; d < cdim*cdim; ++d) u_x[hOffset+(fOffset+c)*cdim*cdim+d] += Hq[cidx*cdim*cdim+d]*coefficients[dOffset+b];
2059f9244615SMatthew G. Knepley         }
2060f9244615SMatthew G. Knepley       }
2061f9244615SMatthew G. Knepley       ierr = PetscFEPushforwardHessian(fe, fegeom, 1, &u_x[hOffset+fOffset*cdim*cdim]);CHKERRQ(ierr);
2062f9244615SMatthew G. Knepley     }
20632edcad52SToby Isaac     ierr = PetscFEPushforward(fe, fegeom, 1, &u[fOffset]);CHKERRQ(ierr);
20642edcad52SToby Isaac     ierr = PetscFEPushforwardGradient(fe, fegeom, 1, &u_x[fOffset*cdim]);CHKERRQ(ierr);
2065a8f1f9e5SMatthew G. Knepley     if (u_t) {
2066a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) u_t[fOffset+c] = 0.0;
2067a8f1f9e5SMatthew G. Knepley       for (b = 0; b < Nbf; ++b) {
2068a8f1f9e5SMatthew G. Knepley         for (c = 0; c < Ncf; ++c) {
2069a8f1f9e5SMatthew G. Knepley           const PetscInt cidx = b*Ncf+c;
2070a8f1f9e5SMatthew G. Knepley 
2071a8f1f9e5SMatthew G. Knepley           u_t[fOffset+c] += Bq[cidx]*coefficients_t[dOffset+b];
2072a8f1f9e5SMatthew G. Knepley         }
2073a8f1f9e5SMatthew G. Knepley       }
20742edcad52SToby Isaac       ierr = PetscFEPushforward(fe, fegeom, 1, &u_t[fOffset]);CHKERRQ(ierr);
2075a8f1f9e5SMatthew G. Knepley     }
2076a8f1f9e5SMatthew G. Knepley     fOffset += Ncf;
2077a8f1f9e5SMatthew G. Knepley     dOffset += Nbf;
2078a8f1f9e5SMatthew G. Knepley   }
2079a8f1f9e5SMatthew G. Knepley   return 0;
2080a8f1f9e5SMatthew G. Knepley }
2081a8f1f9e5SMatthew G. Knepley 
2082665f567fSMatthew 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[])
208327f02ce8SMatthew G. Knepley {
208427f02ce8SMatthew G. Knepley   PetscInt       dOffset = 0, fOffset = 0, g;
208527f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
208627f02ce8SMatthew G. Knepley 
208727f02ce8SMatthew G. Knepley   for (g = 0; g < 2*Nf-1; ++g) {
2088665f567fSMatthew G. Knepley     if (!T[g/2]) continue;
2089665f567fSMatthew G. Knepley     {
209027f02ce8SMatthew G. Knepley     PetscFE          fe;
209127f02ce8SMatthew G. Knepley     const PetscInt   f   = g/2;
2092665f567fSMatthew G. Knepley     const PetscInt   cdim = T[f]->cdim;
2093665f567fSMatthew G. Knepley     const PetscInt   Nq   = T[f]->Np;
2094665f567fSMatthew G. Knepley     const PetscInt   Nbf  = T[f]->Nb;
2095665f567fSMatthew G. Knepley     const PetscInt   Ncf  = T[f]->Nc;
2096665f567fSMatthew G. Knepley     const PetscReal *Bq   = &T[f]->T[0][(r*Nq+q)*Nbf*Ncf];
2097665f567fSMatthew G. Knepley     const PetscReal *Dq   = &T[f]->T[1][(r*Nq+q)*Nbf*Ncf*cdim];
209827f02ce8SMatthew G. Knepley     PetscInt         b, c, d;
209927f02ce8SMatthew G. Knepley 
210027f02ce8SMatthew G. Knepley     fe = (PetscFE) ds->disc[f];
210127f02ce8SMatthew G. Knepley     for (c = 0; c < Ncf; ++c)      u[fOffset+c] = 0.0;
2102665f567fSMatthew G. Knepley     for (d = 0; d < cdim*Ncf; ++d) u_x[fOffset*cdim+d] = 0.0;
210327f02ce8SMatthew G. Knepley     for (b = 0; b < Nbf; ++b) {
210427f02ce8SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) {
210527f02ce8SMatthew G. Knepley         const PetscInt cidx = b*Ncf+c;
210627f02ce8SMatthew G. Knepley 
210727f02ce8SMatthew G. Knepley         u[fOffset+c] += Bq[cidx]*coefficients[dOffset+b];
2108665f567fSMatthew G. Knepley         for (d = 0; d < cdim; ++d) u_x[(fOffset+c)*cdim+d] += Dq[cidx*cdim+d]*coefficients[dOffset+b];
210927f02ce8SMatthew G. Knepley       }
211027f02ce8SMatthew G. Knepley     }
211127f02ce8SMatthew G. Knepley     ierr = PetscFEPushforward(fe, fegeom, 1, &u[fOffset]);CHKERRQ(ierr);
2112665f567fSMatthew G. Knepley     ierr = PetscFEPushforwardGradient(fe, fegeom, 1, &u_x[fOffset*cdim]);CHKERRQ(ierr);
211327f02ce8SMatthew G. Knepley     if (u_t) {
211427f02ce8SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) u_t[fOffset+c] = 0.0;
211527f02ce8SMatthew G. Knepley       for (b = 0; b < Nbf; ++b) {
211627f02ce8SMatthew G. Knepley         for (c = 0; c < Ncf; ++c) {
211727f02ce8SMatthew G. Knepley           const PetscInt cidx = b*Ncf+c;
211827f02ce8SMatthew G. Knepley 
211927f02ce8SMatthew G. Knepley           u_t[fOffset+c] += Bq[cidx]*coefficients_t[dOffset+b];
212027f02ce8SMatthew G. Knepley         }
212127f02ce8SMatthew G. Knepley       }
212227f02ce8SMatthew G. Knepley       ierr = PetscFEPushforward(fe, fegeom, 1, &u_t[fOffset]);CHKERRQ(ierr);
212327f02ce8SMatthew G. Knepley     }
212427f02ce8SMatthew G. Knepley     fOffset += Ncf;
212527f02ce8SMatthew G. Knepley     dOffset += Nbf;
212627f02ce8SMatthew G. Knepley   }
2127665f567fSMatthew G. Knepley   }
212827f02ce8SMatthew G. Knepley   return 0;
212927f02ce8SMatthew G. Knepley }
213027f02ce8SMatthew G. Knepley 
2131a8f1f9e5SMatthew G. Knepley PetscErrorCode PetscFEEvaluateFaceFields_Internal(PetscDS prob, PetscInt field, PetscInt faceLoc, const PetscScalar coefficients[], PetscScalar u[])
2132a8f1f9e5SMatthew G. Knepley {
2133a8f1f9e5SMatthew G. Knepley   PetscFE         fe;
2134ef0bb6c7SMatthew G. Knepley   PetscTabulation Tc;
2135ef0bb6c7SMatthew G. Knepley   PetscInt        b, c;
2136a8f1f9e5SMatthew G. Knepley   PetscErrorCode  ierr;
2137a8f1f9e5SMatthew G. Knepley 
2138a8f1f9e5SMatthew G. Knepley   if (!prob) return 0;
2139a8f1f9e5SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
2140ef0bb6c7SMatthew G. Knepley   ierr = PetscFEGetFaceCentroidTabulation(fe, &Tc);CHKERRQ(ierr);
2141ef0bb6c7SMatthew G. Knepley   {
2142ef0bb6c7SMatthew G. Knepley     const PetscReal *faceBasis = Tc->T[0];
2143ef0bb6c7SMatthew G. Knepley     const PetscInt   Nb        = Tc->Nb;
2144ef0bb6c7SMatthew G. Knepley     const PetscInt   Nc        = Tc->Nc;
2145ef0bb6c7SMatthew G. Knepley 
2146a8f1f9e5SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {u[c] = 0.0;}
2147a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
2148a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
2149813a933aSJed Brown         u[c] += coefficients[b] * faceBasis[(faceLoc*Nb + b)*Nc + c];
2150a8f1f9e5SMatthew G. Knepley       }
2151a8f1f9e5SMatthew G. Knepley     }
2152ef0bb6c7SMatthew G. Knepley   }
2153a8f1f9e5SMatthew G. Knepley   return 0;
2154a8f1f9e5SMatthew G. Knepley }
2155a8f1f9e5SMatthew G. Knepley 
2156ef0bb6c7SMatthew G. Knepley PetscErrorCode PetscFEUpdateElementVec_Internal(PetscFE fe, PetscTabulation T, PetscInt r, PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[])
2157a8f1f9e5SMatthew G. Knepley {
215827f02ce8SMatthew G. Knepley   const PetscInt   dE       = T->cdim; /* fegeom->dimEmbed */
2159ef0bb6c7SMatthew G. Knepley   const PetscInt   Nq       = T->Np;
2160ef0bb6c7SMatthew G. Knepley   const PetscInt   Nb       = T->Nb;
2161ef0bb6c7SMatthew G. Knepley   const PetscInt   Nc       = T->Nc;
2162ef0bb6c7SMatthew G. Knepley   const PetscReal *basis    = &T->T[0][r*Nq*Nb*Nc];
2163665f567fSMatthew G. Knepley   const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dE];
2164a8f1f9e5SMatthew G. Knepley   PetscInt         q, b, c, d;
2165a8f1f9e5SMatthew G. Knepley   PetscErrorCode   ierr;
2166a8f1f9e5SMatthew G. Knepley 
2167a8f1f9e5SMatthew G. Knepley   for (b = 0; b < Nb; ++b) elemVec[b] = 0.0;
2168a8f1f9e5SMatthew G. Knepley   for (q = 0; q < Nq; ++q) {
2169a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
2170a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
2171a8f1f9e5SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
2172a8f1f9e5SMatthew G. Knepley 
2173a8f1f9e5SMatthew G. Knepley         tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx];
217427f02ce8SMatthew G. Knepley         for (d = 0; d < dE; ++d) tmpBasisDer[bcidx*dE+d] = basisDer[q*Nb*Nc*dE+bcidx*dE+d];
2175a8f1f9e5SMatthew G. Knepley       }
2176a8f1f9e5SMatthew G. Knepley     }
21772edcad52SToby Isaac     ierr = PetscFEPushforward(fe, fegeom, Nb, tmpBasis);CHKERRQ(ierr);
21782edcad52SToby Isaac     ierr = PetscFEPushforwardGradient(fe, fegeom, Nb, tmpBasisDer);CHKERRQ(ierr);
2179a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
2180a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
2181a8f1f9e5SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
2182a8f1f9e5SMatthew G. Knepley         const PetscInt qcidx = q*Nc+c;
2183a8f1f9e5SMatthew G. Knepley 
2184a8f1f9e5SMatthew G. Knepley         elemVec[b] += tmpBasis[bcidx]*f0[qcidx];
218527f02ce8SMatthew G. Knepley         for (d = 0; d < dE; ++d) elemVec[b] += tmpBasisDer[bcidx*dE+d]*f1[qcidx*dE+d];
218627f02ce8SMatthew G. Knepley       }
218727f02ce8SMatthew G. Knepley     }
218827f02ce8SMatthew G. Knepley   }
218927f02ce8SMatthew G. Knepley   return(0);
219027f02ce8SMatthew G. Knepley }
219127f02ce8SMatthew G. Knepley 
219227f02ce8SMatthew G. Knepley PetscErrorCode PetscFEUpdateElementVec_Hybrid_Internal(PetscFE fe, PetscTabulation T, PetscInt r, PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[])
219327f02ce8SMatthew G. Knepley {
219427f02ce8SMatthew G. Knepley   const PetscInt   dE       = T->cdim;
219527f02ce8SMatthew G. Knepley   const PetscInt   Nq       = T->Np;
219627f02ce8SMatthew G. Knepley   const PetscInt   Nb       = T->Nb;
219727f02ce8SMatthew G. Knepley   const PetscInt   Nc       = T->Nc;
219827f02ce8SMatthew G. Knepley   const PetscReal *basis    = &T->T[0][r*Nq*Nb*Nc];
219927f02ce8SMatthew G. Knepley   const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dE];
220027f02ce8SMatthew G. Knepley   PetscInt         q, b, c, d, s;
220127f02ce8SMatthew G. Knepley   PetscErrorCode   ierr;
220227f02ce8SMatthew G. Knepley 
220327f02ce8SMatthew G. Knepley   for (b = 0; b < Nb*2; ++b) elemVec[b] = 0.0;
220427f02ce8SMatthew G. Knepley   for (q = 0; q < Nq; ++q) {
220527f02ce8SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
220627f02ce8SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
220727f02ce8SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
220827f02ce8SMatthew G. Knepley 
220927f02ce8SMatthew G. Knepley         tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx];
221027f02ce8SMatthew G. Knepley         for (d = 0; d < dE; ++d) tmpBasisDer[bcidx*dE+d] = basisDer[q*Nb*Nc*dE+bcidx*dE+d];
221127f02ce8SMatthew G. Knepley       }
221227f02ce8SMatthew G. Knepley     }
221327f02ce8SMatthew G. Knepley     ierr = PetscFEPushforward(fe, fegeom, Nb, tmpBasis);CHKERRQ(ierr);
221427f02ce8SMatthew G. Knepley     ierr = PetscFEPushforwardGradient(fe, fegeom, Nb, tmpBasisDer);CHKERRQ(ierr);
221527f02ce8SMatthew G. Knepley     for (s = 0; s < 2; ++s) {
221627f02ce8SMatthew G. Knepley       for (b = 0; b < Nb; ++b) {
221727f02ce8SMatthew G. Knepley         for (c = 0; c < Nc; ++c) {
221827f02ce8SMatthew G. Knepley           const PetscInt bcidx = b*Nc+c;
221927f02ce8SMatthew G. Knepley           const PetscInt qcidx = (q*2+s)*Nc+c;
222027f02ce8SMatthew G. Knepley 
222127f02ce8SMatthew G. Knepley           elemVec[Nb*s+b] += tmpBasis[bcidx]*f0[qcidx];
222227f02ce8SMatthew G. Knepley           for (d = 0; d < dE; ++d) elemVec[Nb*s+b] += tmpBasisDer[bcidx*dE+d]*f1[qcidx*dE+d];
222327f02ce8SMatthew G. Knepley         }
2224a8f1f9e5SMatthew G. Knepley       }
2225a8f1f9e5SMatthew G. Knepley     }
2226a8f1f9e5SMatthew G. Knepley   }
2227a8f1f9e5SMatthew G. Knepley   return(0);
2228a8f1f9e5SMatthew G. Knepley }
2229a8f1f9e5SMatthew G. Knepley 
2230ef0bb6c7SMatthew 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[])
2231a8f1f9e5SMatthew G. Knepley {
223227f02ce8SMatthew G. Knepley   const PetscInt   dE        = TI->cdim;
2233ef0bb6c7SMatthew G. Knepley   const PetscInt   NqI       = TI->Np;
2234ef0bb6c7SMatthew G. Knepley   const PetscInt   NbI       = TI->Nb;
2235ef0bb6c7SMatthew G. Knepley   const PetscInt   NcI       = TI->Nc;
2236ef0bb6c7SMatthew G. Knepley   const PetscReal *basisI    = &TI->T[0][(r*NqI+q)*NbI*NcI];
2237665f567fSMatthew G. Knepley   const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dE];
2238ef0bb6c7SMatthew G. Knepley   const PetscInt   NqJ       = TJ->Np;
2239ef0bb6c7SMatthew G. Knepley   const PetscInt   NbJ       = TJ->Nb;
2240ef0bb6c7SMatthew G. Knepley   const PetscInt   NcJ       = TJ->Nc;
2241ef0bb6c7SMatthew G. Knepley   const PetscReal *basisJ    = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ];
2242665f567fSMatthew G. Knepley   const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dE];
2243a8f1f9e5SMatthew G. Knepley   PetscInt         f, fc, g, gc, df, dg;
2244a8f1f9e5SMatthew G. Knepley   PetscErrorCode   ierr;
2245a8f1f9e5SMatthew G. Knepley 
2246a8f1f9e5SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
2247a8f1f9e5SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
2248a8f1f9e5SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
2249a8f1f9e5SMatthew G. Knepley 
2250a8f1f9e5SMatthew G. Knepley       tmpBasisI[fidx] = basisI[fidx];
225127f02ce8SMatthew G. Knepley       for (df = 0; df < dE; ++df) tmpBasisDerI[fidx*dE+df] = basisDerI[fidx*dE+df];
2252a8f1f9e5SMatthew G. Knepley     }
2253a8f1f9e5SMatthew G. Knepley   }
22542edcad52SToby Isaac   ierr = PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);CHKERRQ(ierr);
22552edcad52SToby Isaac   ierr = PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);CHKERRQ(ierr);
2256a8f1f9e5SMatthew G. Knepley   for (g = 0; g < NbJ; ++g) {
2257a8f1f9e5SMatthew G. Knepley     for (gc = 0; gc < NcJ; ++gc) {
2258a8f1f9e5SMatthew G. Knepley       const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
2259a8f1f9e5SMatthew G. Knepley 
2260a8f1f9e5SMatthew G. Knepley       tmpBasisJ[gidx] = basisJ[gidx];
226127f02ce8SMatthew G. Knepley       for (dg = 0; dg < dE; ++dg) tmpBasisDerJ[gidx*dE+dg] = basisDerJ[gidx*dE+dg];
2262a8f1f9e5SMatthew G. Knepley     }
2263a8f1f9e5SMatthew G. Knepley   }
22642edcad52SToby Isaac   ierr = PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);CHKERRQ(ierr);
22652edcad52SToby Isaac   ierr = PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);CHKERRQ(ierr);
2266a8f1f9e5SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
2267a8f1f9e5SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
2268a8f1f9e5SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
2269a8f1f9e5SMatthew G. Knepley       const PetscInt i    = offsetI+f; /* Element matrix row */
2270a8f1f9e5SMatthew G. Knepley       for (g = 0; g < NbJ; ++g) {
2271a8f1f9e5SMatthew G. Knepley         for (gc = 0; gc < NcJ; ++gc) {
2272a8f1f9e5SMatthew G. Knepley           const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
2273a8f1f9e5SMatthew G. Knepley           const PetscInt j    = offsetJ+g; /* Element matrix column */
2274a8f1f9e5SMatthew G. Knepley           const PetscInt fOff = eOffset+i*totDim+j;
2275a8f1f9e5SMatthew G. Knepley 
2276a8f1f9e5SMatthew G. Knepley           elemMat[fOff] += tmpBasisI[fidx]*g0[fc*NcJ+gc]*tmpBasisJ[gidx];
227727f02ce8SMatthew G. Knepley           for (df = 0; df < dE; ++df) {
227827f02ce8SMatthew G. Knepley             elemMat[fOff] += tmpBasisI[fidx]*g1[(fc*NcJ+gc)*dE+df]*tmpBasisDerJ[gidx*dE+df];
227927f02ce8SMatthew G. Knepley             elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g2[(fc*NcJ+gc)*dE+df]*tmpBasisJ[gidx];
228027f02ce8SMatthew G. Knepley             for (dg = 0; dg < dE; ++dg) {
228127f02ce8SMatthew G. Knepley               elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g3[((fc*NcJ+gc)*dE+df)*dE+dg]*tmpBasisDerJ[gidx*dE+dg];
228227f02ce8SMatthew G. Knepley             }
228327f02ce8SMatthew G. Knepley           }
228427f02ce8SMatthew G. Knepley         }
228527f02ce8SMatthew G. Knepley       }
228627f02ce8SMatthew G. Knepley     }
228727f02ce8SMatthew G. Knepley   }
228827f02ce8SMatthew G. Knepley   return(0);
228927f02ce8SMatthew G. Knepley }
229027f02ce8SMatthew G. Knepley 
2291665f567fSMatthew 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[])
229227f02ce8SMatthew G. Knepley {
2293665f567fSMatthew G. Knepley   const PetscInt   dE        = TI->cdim;
2294665f567fSMatthew G. Knepley   const PetscInt   NqI       = TI->Np;
2295665f567fSMatthew G. Knepley   const PetscInt   NbI       = TI->Nb;
2296665f567fSMatthew G. Knepley   const PetscInt   NcI       = TI->Nc;
2297665f567fSMatthew G. Knepley   const PetscReal *basisI    = &TI->T[0][(r*NqI+q)*NbI*NcI];
2298665f567fSMatthew G. Knepley   const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dE];
2299665f567fSMatthew G. Knepley   const PetscInt   NqJ       = TJ->Np;
2300665f567fSMatthew G. Knepley   const PetscInt   NbJ       = TJ->Nb;
2301665f567fSMatthew G. Knepley   const PetscInt   NcJ       = TJ->Nc;
2302665f567fSMatthew G. Knepley   const PetscReal *basisJ    = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ];
2303665f567fSMatthew G. Knepley   const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dE];
230427f02ce8SMatthew G. Knepley   const PetscInt   Ns = isHybridI ? 1 : 2;
230527f02ce8SMatthew G. Knepley   const PetscInt   Nt = isHybridJ ? 1 : 2;
230627f02ce8SMatthew G. Knepley   PetscInt         f, fc, g, gc, df, dg, s, t;
230727f02ce8SMatthew G. Knepley   PetscErrorCode   ierr;
230827f02ce8SMatthew G. Knepley 
230927f02ce8SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
231027f02ce8SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
231127f02ce8SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
231227f02ce8SMatthew G. Knepley 
231327f02ce8SMatthew G. Knepley       tmpBasisI[fidx] = basisI[fidx];
2314665f567fSMatthew G. Knepley       for (df = 0; df < dE; ++df) tmpBasisDerI[fidx*dE+df] = basisDerI[fidx*dE+df];
231527f02ce8SMatthew G. Knepley     }
231627f02ce8SMatthew G. Knepley   }
231727f02ce8SMatthew G. Knepley   ierr = PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);CHKERRQ(ierr);
231827f02ce8SMatthew G. Knepley   ierr = PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);CHKERRQ(ierr);
231927f02ce8SMatthew G. Knepley   for (g = 0; g < NbJ; ++g) {
232027f02ce8SMatthew G. Knepley     for (gc = 0; gc < NcJ; ++gc) {
232127f02ce8SMatthew G. Knepley       const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
232227f02ce8SMatthew G. Knepley 
232327f02ce8SMatthew G. Knepley       tmpBasisJ[gidx] = basisJ[gidx];
2324665f567fSMatthew G. Knepley       for (dg = 0; dg < dE; ++dg) tmpBasisDerJ[gidx*dE+dg] = basisDerJ[gidx*dE+dg];
232527f02ce8SMatthew G. Knepley     }
232627f02ce8SMatthew G. Knepley   }
232727f02ce8SMatthew G. Knepley   ierr = PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);CHKERRQ(ierr);
232827f02ce8SMatthew G. Knepley   ierr = PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);CHKERRQ(ierr);
232927f02ce8SMatthew G. Knepley   for (s = 0; s < Ns; ++s) {
233027f02ce8SMatthew G. Knepley     for (f = 0; f < NbI; ++f) {
233127f02ce8SMatthew G. Knepley       for (fc = 0; fc < NcI; ++fc) {
233227f02ce8SMatthew G. Knepley         const PetscInt sc   = NcI*s+fc;  /* components from each side of the surface */
233327f02ce8SMatthew G. Knepley         const PetscInt fidx = f*NcI+fc;  /* Test function basis index */
233427f02ce8SMatthew G. Knepley         const PetscInt i    = offsetI+NbI*s+f; /* Element matrix row */
233527f02ce8SMatthew G. Knepley         for (t = 0; t < Nt; ++t) {
233627f02ce8SMatthew G. Knepley           for (g = 0; g < NbJ; ++g) {
233727f02ce8SMatthew G. Knepley             for (gc = 0; gc < NcJ; ++gc) {
233827f02ce8SMatthew G. Knepley               const PetscInt tc   = NcJ*t+gc;  /* components from each side of the surface */
233927f02ce8SMatthew G. Knepley               const PetscInt gidx = g*NcJ+gc;  /* Trial function basis index */
234027f02ce8SMatthew G. Knepley               const PetscInt j    = offsetJ+NbJ*t+g; /* Element matrix column */
234127f02ce8SMatthew G. Knepley               const PetscInt fOff = eOffset+i*totDim+j;
234227f02ce8SMatthew G. Knepley 
234327f02ce8SMatthew G. Knepley               elemMat[fOff] += tmpBasisI[fidx]*g0[sc*NcJ*Nt+tc]*tmpBasisJ[gidx];
234427f02ce8SMatthew G. Knepley               for (df = 0; df < dE; ++df) {
234527f02ce8SMatthew G. Knepley                 elemMat[fOff] += tmpBasisI[fidx]*g1[(sc*NcJ*Nt+tc)*dE+df]*tmpBasisDerJ[gidx*dE+df];
234627f02ce8SMatthew G. Knepley                 elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g2[(sc*NcJ*Nt+tc)*dE+df]*tmpBasisJ[gidx];
234727f02ce8SMatthew G. Knepley                 for (dg = 0; dg < dE; ++dg) {
234827f02ce8SMatthew G. Knepley                   elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g3[((sc*NcJ*Nt+tc)*dE+df)*dE+dg]*tmpBasisDerJ[gidx*dE+dg];
234927f02ce8SMatthew G. Knepley                 }
235027f02ce8SMatthew G. Knepley               }
2351a8f1f9e5SMatthew G. Knepley             }
2352a8f1f9e5SMatthew G. Knepley           }
2353a8f1f9e5SMatthew G. Knepley         }
2354a8f1f9e5SMatthew G. Knepley       }
2355a8f1f9e5SMatthew G. Knepley     }
2356a8f1f9e5SMatthew G. Knepley   }
2357a8f1f9e5SMatthew G. Knepley   return(0);
2358a8f1f9e5SMatthew G. Knepley }
2359c9ba7969SMatthew G. Knepley 
2360c9ba7969SMatthew G. Knepley PetscErrorCode PetscFECreateCellGeometry(PetscFE fe, PetscQuadrature quad, PetscFEGeom *cgeom)
2361c9ba7969SMatthew G. Knepley {
2362c9ba7969SMatthew G. Knepley   PetscDualSpace  dsp;
2363c9ba7969SMatthew G. Knepley   DM              dm;
2364c9ba7969SMatthew G. Knepley   PetscQuadrature quadDef;
2365c9ba7969SMatthew G. Knepley   PetscInt        dim, cdim, Nq;
2366c9ba7969SMatthew G. Knepley   PetscErrorCode  ierr;
2367c9ba7969SMatthew G. Knepley 
2368c9ba7969SMatthew G. Knepley   PetscFunctionBegin;
2369c9ba7969SMatthew G. Knepley   ierr = PetscFEGetDualSpace(fe, &dsp);CHKERRQ(ierr);
2370c9ba7969SMatthew G. Knepley   ierr = PetscDualSpaceGetDM(dsp, &dm);CHKERRQ(ierr);
2371c9ba7969SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
2372c9ba7969SMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
2373c9ba7969SMatthew G. Knepley   ierr = PetscFEGetQuadrature(fe, &quadDef);CHKERRQ(ierr);
2374c9ba7969SMatthew G. Knepley   quad = quad ? quad : quadDef;
2375c9ba7969SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);
2376c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq*cdim,      &cgeom->v);CHKERRQ(ierr);
2377c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq*cdim*cdim, &cgeom->J);CHKERRQ(ierr);
2378c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq*cdim*cdim, &cgeom->invJ);CHKERRQ(ierr);
2379c9ba7969SMatthew G. Knepley   ierr = PetscMalloc1(Nq,           &cgeom->detJ);CHKERRQ(ierr);
2380c9ba7969SMatthew G. Knepley   cgeom->dim       = dim;
2381c9ba7969SMatthew G. Knepley   cgeom->dimEmbed  = cdim;
2382c9ba7969SMatthew G. Knepley   cgeom->numCells  = 1;
2383c9ba7969SMatthew G. Knepley   cgeom->numPoints = Nq;
2384c9ba7969SMatthew G. Knepley   ierr = DMPlexComputeCellGeometryFEM(dm, 0, quad, cgeom->v, cgeom->J, cgeom->invJ, cgeom->detJ);CHKERRQ(ierr);
2385c9ba7969SMatthew G. Knepley   PetscFunctionReturn(0);
2386c9ba7969SMatthew G. Knepley }
2387c9ba7969SMatthew G. Knepley 
2388c9ba7969SMatthew G. Knepley PetscErrorCode PetscFEDestroyCellGeometry(PetscFE fe, PetscFEGeom *cgeom)
2389c9ba7969SMatthew G. Knepley {
2390c9ba7969SMatthew G. Knepley   PetscErrorCode ierr;
2391c9ba7969SMatthew G. Knepley 
2392c9ba7969SMatthew G. Knepley   PetscFunctionBegin;
2393c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->v);CHKERRQ(ierr);
2394c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->J);CHKERRQ(ierr);
2395c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->invJ);CHKERRQ(ierr);
2396c9ba7969SMatthew G. Knepley   ierr = PetscFree(cgeom->detJ);CHKERRQ(ierr);
2397c9ba7969SMatthew G. Knepley   PetscFunctionReturn(0);
2398c9ba7969SMatthew G. Knepley }
2399