xref: /petsc/src/dm/dt/fe/interface/fe.c (revision d083f849a86f1f43e18d534ee43954e2786cb29a)
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 
5320cf1dd8SToby Isaac PetscFunctionList PetscFEList              = NULL;
5420cf1dd8SToby Isaac PetscBool         PetscFERegisterAllCalled = PETSC_FALSE;
5520cf1dd8SToby Isaac 
5620cf1dd8SToby Isaac /*@C
5720cf1dd8SToby Isaac   PetscFERegister - Adds a new PetscFE implementation
5820cf1dd8SToby Isaac 
5920cf1dd8SToby Isaac   Not Collective
6020cf1dd8SToby Isaac 
6120cf1dd8SToby Isaac   Input Parameters:
6220cf1dd8SToby Isaac + name        - The name of a new user-defined creation routine
6320cf1dd8SToby Isaac - create_func - The creation routine itself
6420cf1dd8SToby Isaac 
6520cf1dd8SToby Isaac   Notes:
6620cf1dd8SToby Isaac   PetscFERegister() may be called multiple times to add several user-defined PetscFEs
6720cf1dd8SToby Isaac 
6820cf1dd8SToby Isaac   Sample usage:
6920cf1dd8SToby Isaac .vb
7020cf1dd8SToby Isaac     PetscFERegister("my_fe", MyPetscFECreate);
7120cf1dd8SToby Isaac .ve
7220cf1dd8SToby Isaac 
7320cf1dd8SToby Isaac   Then, your PetscFE type can be chosen with the procedural interface via
7420cf1dd8SToby Isaac .vb
7520cf1dd8SToby Isaac     PetscFECreate(MPI_Comm, PetscFE *);
7620cf1dd8SToby Isaac     PetscFESetType(PetscFE, "my_fe");
7720cf1dd8SToby Isaac .ve
7820cf1dd8SToby Isaac    or at runtime via the option
7920cf1dd8SToby Isaac .vb
8020cf1dd8SToby Isaac     -petscfe_type my_fe
8120cf1dd8SToby Isaac .ve
8220cf1dd8SToby Isaac 
8320cf1dd8SToby Isaac   Level: advanced
8420cf1dd8SToby Isaac 
8520cf1dd8SToby Isaac .seealso: PetscFERegisterAll(), PetscFERegisterDestroy()
8620cf1dd8SToby Isaac 
8720cf1dd8SToby Isaac @*/
8820cf1dd8SToby Isaac PetscErrorCode PetscFERegister(const char sname[], PetscErrorCode (*function)(PetscFE))
8920cf1dd8SToby Isaac {
9020cf1dd8SToby Isaac   PetscErrorCode ierr;
9120cf1dd8SToby Isaac 
9220cf1dd8SToby Isaac   PetscFunctionBegin;
9320cf1dd8SToby Isaac   ierr = PetscFunctionListAdd(&PetscFEList, sname, function);CHKERRQ(ierr);
9420cf1dd8SToby Isaac   PetscFunctionReturn(0);
9520cf1dd8SToby Isaac }
9620cf1dd8SToby Isaac 
9720cf1dd8SToby Isaac /*@C
9820cf1dd8SToby Isaac   PetscFESetType - Builds a particular PetscFE
9920cf1dd8SToby Isaac 
100*d083f849SBarry Smith   Collective on fem
10120cf1dd8SToby Isaac 
10220cf1dd8SToby Isaac   Input Parameters:
10320cf1dd8SToby Isaac + fem  - The PetscFE object
10420cf1dd8SToby Isaac - name - The kind of FEM space
10520cf1dd8SToby Isaac 
10620cf1dd8SToby Isaac   Options Database Key:
10720cf1dd8SToby Isaac . -petscfe_type <type> - Sets the PetscFE type; use -help for a list of available types
10820cf1dd8SToby Isaac 
10920cf1dd8SToby Isaac   Level: intermediate
11020cf1dd8SToby Isaac 
11120cf1dd8SToby Isaac .seealso: PetscFEGetType(), PetscFECreate()
11220cf1dd8SToby Isaac @*/
11320cf1dd8SToby Isaac PetscErrorCode PetscFESetType(PetscFE fem, PetscFEType name)
11420cf1dd8SToby Isaac {
11520cf1dd8SToby Isaac   PetscErrorCode (*r)(PetscFE);
11620cf1dd8SToby Isaac   PetscBool      match;
11720cf1dd8SToby Isaac   PetscErrorCode ierr;
11820cf1dd8SToby Isaac 
11920cf1dd8SToby Isaac   PetscFunctionBegin;
12020cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
12120cf1dd8SToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) fem, name, &match);CHKERRQ(ierr);
12220cf1dd8SToby Isaac   if (match) PetscFunctionReturn(0);
12320cf1dd8SToby Isaac 
12420cf1dd8SToby Isaac   if (!PetscFERegisterAllCalled) {ierr = PetscFERegisterAll();CHKERRQ(ierr);}
12520cf1dd8SToby Isaac   ierr = PetscFunctionListFind(PetscFEList, name, &r);CHKERRQ(ierr);
12620cf1dd8SToby Isaac   if (!r) SETERRQ1(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscFE type: %s", name);
12720cf1dd8SToby Isaac 
12820cf1dd8SToby Isaac   if (fem->ops->destroy) {
12920cf1dd8SToby Isaac     ierr              = (*fem->ops->destroy)(fem);CHKERRQ(ierr);
13020cf1dd8SToby Isaac     fem->ops->destroy = NULL;
13120cf1dd8SToby Isaac   }
13220cf1dd8SToby Isaac   ierr = (*r)(fem);CHKERRQ(ierr);
13320cf1dd8SToby Isaac   ierr = PetscObjectChangeTypeName((PetscObject) fem, name);CHKERRQ(ierr);
13420cf1dd8SToby Isaac   PetscFunctionReturn(0);
13520cf1dd8SToby Isaac }
13620cf1dd8SToby Isaac 
13720cf1dd8SToby Isaac /*@C
13820cf1dd8SToby Isaac   PetscFEGetType - Gets the PetscFE type name (as a string) from the object.
13920cf1dd8SToby Isaac 
14020cf1dd8SToby Isaac   Not Collective
14120cf1dd8SToby Isaac 
14220cf1dd8SToby Isaac   Input Parameter:
14320cf1dd8SToby Isaac . fem  - The PetscFE
14420cf1dd8SToby Isaac 
14520cf1dd8SToby Isaac   Output Parameter:
14620cf1dd8SToby Isaac . name - The PetscFE type name
14720cf1dd8SToby Isaac 
14820cf1dd8SToby Isaac   Level: intermediate
14920cf1dd8SToby Isaac 
15020cf1dd8SToby Isaac .seealso: PetscFESetType(), PetscFECreate()
15120cf1dd8SToby Isaac @*/
15220cf1dd8SToby Isaac PetscErrorCode PetscFEGetType(PetscFE fem, PetscFEType *name)
15320cf1dd8SToby Isaac {
15420cf1dd8SToby Isaac   PetscErrorCode ierr;
15520cf1dd8SToby Isaac 
15620cf1dd8SToby Isaac   PetscFunctionBegin;
15720cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
15820cf1dd8SToby Isaac   PetscValidPointer(name, 2);
15920cf1dd8SToby Isaac   if (!PetscFERegisterAllCalled) {
16020cf1dd8SToby Isaac     ierr = PetscFERegisterAll();CHKERRQ(ierr);
16120cf1dd8SToby Isaac   }
16220cf1dd8SToby Isaac   *name = ((PetscObject) fem)->type_name;
16320cf1dd8SToby Isaac   PetscFunctionReturn(0);
16420cf1dd8SToby Isaac }
16520cf1dd8SToby Isaac 
16620cf1dd8SToby Isaac /*@C
16720cf1dd8SToby Isaac   PetscFEView - Views a PetscFE
16820cf1dd8SToby Isaac 
169*d083f849SBarry Smith   Collective on fem
17020cf1dd8SToby Isaac 
17120cf1dd8SToby Isaac   Input Parameter:
17220cf1dd8SToby Isaac + fem - the PetscFE object to view
173d9bac1caSLisandro Dalcin - viewer   - the viewer
17420cf1dd8SToby Isaac 
17520cf1dd8SToby Isaac   Level: developer
17620cf1dd8SToby Isaac 
17720cf1dd8SToby Isaac .seealso PetscFEDestroy()
17820cf1dd8SToby Isaac @*/
179d9bac1caSLisandro Dalcin PetscErrorCode PetscFEView(PetscFE fem, PetscViewer viewer)
18020cf1dd8SToby Isaac {
181d9bac1caSLisandro Dalcin   PetscBool      iascii;
18220cf1dd8SToby Isaac   PetscErrorCode ierr;
18320cf1dd8SToby Isaac 
18420cf1dd8SToby Isaac   PetscFunctionBegin;
18520cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
186d9bac1caSLisandro Dalcin   if (viewer) PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
187d9bac1caSLisandro Dalcin   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) fem), &viewer);CHKERRQ(ierr);}
188d9bac1caSLisandro Dalcin   ierr = PetscObjectPrintClassNamePrefixType((PetscObject)fem, viewer);CHKERRQ(ierr);
189d9bac1caSLisandro Dalcin   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
190d9bac1caSLisandro Dalcin   if (fem->ops->view) {ierr = (*fem->ops->view)(fem, viewer);CHKERRQ(ierr);}
19120cf1dd8SToby Isaac   PetscFunctionReturn(0);
19220cf1dd8SToby Isaac }
19320cf1dd8SToby Isaac 
19420cf1dd8SToby Isaac /*@
19520cf1dd8SToby Isaac   PetscFESetFromOptions - sets parameters in a PetscFE from the options database
19620cf1dd8SToby Isaac 
197*d083f849SBarry Smith   Collective on fem
19820cf1dd8SToby Isaac 
19920cf1dd8SToby Isaac   Input Parameter:
20020cf1dd8SToby Isaac . fem - the PetscFE object to set options for
20120cf1dd8SToby Isaac 
20220cf1dd8SToby Isaac   Options Database:
20320cf1dd8SToby Isaac . -petscfe_num_blocks  the number of cell blocks to integrate concurrently
20420cf1dd8SToby Isaac . -petscfe_num_batches the number of cell batches to integrate serially
20520cf1dd8SToby Isaac 
20620cf1dd8SToby Isaac   Level: developer
20720cf1dd8SToby Isaac 
20820cf1dd8SToby Isaac .seealso PetscFEView()
20920cf1dd8SToby Isaac @*/
21020cf1dd8SToby Isaac PetscErrorCode PetscFESetFromOptions(PetscFE fem)
21120cf1dd8SToby Isaac {
21220cf1dd8SToby Isaac   const char    *defaultType;
21320cf1dd8SToby Isaac   char           name[256];
21420cf1dd8SToby Isaac   PetscBool      flg;
21520cf1dd8SToby Isaac   PetscErrorCode ierr;
21620cf1dd8SToby Isaac 
21720cf1dd8SToby Isaac   PetscFunctionBegin;
21820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
21920cf1dd8SToby Isaac   if (!((PetscObject) fem)->type_name) {
22020cf1dd8SToby Isaac     defaultType = PETSCFEBASIC;
22120cf1dd8SToby Isaac   } else {
22220cf1dd8SToby Isaac     defaultType = ((PetscObject) fem)->type_name;
22320cf1dd8SToby Isaac   }
22420cf1dd8SToby Isaac   if (!PetscFERegisterAllCalled) {ierr = PetscFERegisterAll();CHKERRQ(ierr);}
22520cf1dd8SToby Isaac 
22620cf1dd8SToby Isaac   ierr = PetscObjectOptionsBegin((PetscObject) fem);CHKERRQ(ierr);
22720cf1dd8SToby Isaac   ierr = PetscOptionsFList("-petscfe_type", "Finite element space", "PetscFESetType", PetscFEList, defaultType, name, 256, &flg);CHKERRQ(ierr);
22820cf1dd8SToby Isaac   if (flg) {
22920cf1dd8SToby Isaac     ierr = PetscFESetType(fem, name);CHKERRQ(ierr);
23020cf1dd8SToby Isaac   } else if (!((PetscObject) fem)->type_name) {
23120cf1dd8SToby Isaac     ierr = PetscFESetType(fem, defaultType);CHKERRQ(ierr);
23220cf1dd8SToby Isaac   }
23320cf1dd8SToby Isaac   ierr = PetscOptionsInt("-petscfe_num_blocks", "The number of cell blocks to integrate concurrently", "PetscSpaceSetTileSizes", fem->numBlocks, &fem->numBlocks, NULL);CHKERRQ(ierr);
23420cf1dd8SToby Isaac   ierr = PetscOptionsInt("-petscfe_num_batches", "The number of cell batches to integrate serially", "PetscSpaceSetTileSizes", fem->numBatches, &fem->numBatches, NULL);CHKERRQ(ierr);
23520cf1dd8SToby Isaac   if (fem->ops->setfromoptions) {
23620cf1dd8SToby Isaac     ierr = (*fem->ops->setfromoptions)(PetscOptionsObject,fem);CHKERRQ(ierr);
23720cf1dd8SToby Isaac   }
23820cf1dd8SToby Isaac   /* process any options handlers added with PetscObjectAddOptionsHandler() */
23920cf1dd8SToby Isaac   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) fem);CHKERRQ(ierr);
24020cf1dd8SToby Isaac   ierr = PetscOptionsEnd();CHKERRQ(ierr);
24120cf1dd8SToby Isaac   ierr = PetscFEViewFromOptions(fem, NULL, "-petscfe_view");CHKERRQ(ierr);
24220cf1dd8SToby Isaac   PetscFunctionReturn(0);
24320cf1dd8SToby Isaac }
24420cf1dd8SToby Isaac 
24520cf1dd8SToby Isaac /*@C
24620cf1dd8SToby Isaac   PetscFESetUp - Construct data structures for the PetscFE
24720cf1dd8SToby Isaac 
248*d083f849SBarry Smith   Collective on fem
24920cf1dd8SToby Isaac 
25020cf1dd8SToby Isaac   Input Parameter:
25120cf1dd8SToby Isaac . fem - the PetscFE object to setup
25220cf1dd8SToby Isaac 
25320cf1dd8SToby Isaac   Level: developer
25420cf1dd8SToby Isaac 
25520cf1dd8SToby Isaac .seealso PetscFEView(), PetscFEDestroy()
25620cf1dd8SToby Isaac @*/
25720cf1dd8SToby Isaac PetscErrorCode PetscFESetUp(PetscFE fem)
25820cf1dd8SToby Isaac {
25920cf1dd8SToby Isaac   PetscErrorCode ierr;
26020cf1dd8SToby Isaac 
26120cf1dd8SToby Isaac   PetscFunctionBegin;
26220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
26320cf1dd8SToby Isaac   if (fem->setupcalled) PetscFunctionReturn(0);
26420cf1dd8SToby Isaac   fem->setupcalled = PETSC_TRUE;
26520cf1dd8SToby Isaac   if (fem->ops->setup) {ierr = (*fem->ops->setup)(fem);CHKERRQ(ierr);}
26620cf1dd8SToby Isaac   PetscFunctionReturn(0);
26720cf1dd8SToby Isaac }
26820cf1dd8SToby Isaac 
26920cf1dd8SToby Isaac /*@
27020cf1dd8SToby Isaac   PetscFEDestroy - Destroys a PetscFE object
27120cf1dd8SToby Isaac 
272*d083f849SBarry Smith   Collective on fem
27320cf1dd8SToby Isaac 
27420cf1dd8SToby Isaac   Input Parameter:
27520cf1dd8SToby Isaac . fem - the PetscFE object to destroy
27620cf1dd8SToby Isaac 
27720cf1dd8SToby Isaac   Level: developer
27820cf1dd8SToby Isaac 
27920cf1dd8SToby Isaac .seealso PetscFEView()
28020cf1dd8SToby Isaac @*/
28120cf1dd8SToby Isaac PetscErrorCode PetscFEDestroy(PetscFE *fem)
28220cf1dd8SToby Isaac {
28320cf1dd8SToby Isaac   PetscErrorCode ierr;
28420cf1dd8SToby Isaac 
28520cf1dd8SToby Isaac   PetscFunctionBegin;
28620cf1dd8SToby Isaac   if (!*fem) PetscFunctionReturn(0);
28720cf1dd8SToby Isaac   PetscValidHeaderSpecific((*fem), PETSCFE_CLASSID, 1);
28820cf1dd8SToby Isaac 
28920cf1dd8SToby Isaac   if (--((PetscObject)(*fem))->refct > 0) {*fem = 0; PetscFunctionReturn(0);}
29020cf1dd8SToby Isaac   ((PetscObject) (*fem))->refct = 0;
29120cf1dd8SToby Isaac 
29220cf1dd8SToby Isaac   if ((*fem)->subspaces) {
29320cf1dd8SToby Isaac     PetscInt dim, d;
29420cf1dd8SToby Isaac 
29520cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDimension((*fem)->dualSpace, &dim);CHKERRQ(ierr);
29620cf1dd8SToby Isaac     for (d = 0; d < dim; ++d) {ierr = PetscFEDestroy(&(*fem)->subspaces[d]);CHKERRQ(ierr);}
29720cf1dd8SToby Isaac   }
29820cf1dd8SToby Isaac   ierr = PetscFree((*fem)->subspaces);CHKERRQ(ierr);
29920cf1dd8SToby Isaac   ierr = PetscFree((*fem)->invV);CHKERRQ(ierr);
30020cf1dd8SToby Isaac   ierr = PetscFERestoreTabulation((*fem), 0, NULL, &(*fem)->B, &(*fem)->D, NULL /*&(*fem)->H*/);CHKERRQ(ierr);
30120cf1dd8SToby Isaac   ierr = PetscFERestoreTabulation((*fem), 0, NULL, &(*fem)->Bf, &(*fem)->Df, NULL /*&(*fem)->Hf*/);CHKERRQ(ierr);
30220cf1dd8SToby Isaac   ierr = PetscFERestoreTabulation((*fem), 0, NULL, &(*fem)->F, NULL, NULL);CHKERRQ(ierr);
30320cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&(*fem)->basisSpace);CHKERRQ(ierr);
30420cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&(*fem)->dualSpace);CHKERRQ(ierr);
30520cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&(*fem)->quadrature);CHKERRQ(ierr);
30620cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&(*fem)->faceQuadrature);CHKERRQ(ierr);
30720cf1dd8SToby Isaac 
30820cf1dd8SToby Isaac   if ((*fem)->ops->destroy) {ierr = (*(*fem)->ops->destroy)(*fem);CHKERRQ(ierr);}
30920cf1dd8SToby Isaac   ierr = PetscHeaderDestroy(fem);CHKERRQ(ierr);
31020cf1dd8SToby Isaac   PetscFunctionReturn(0);
31120cf1dd8SToby Isaac }
31220cf1dd8SToby Isaac 
31320cf1dd8SToby Isaac /*@
31420cf1dd8SToby Isaac   PetscFECreate - Creates an empty PetscFE object. The type can then be set with PetscFESetType().
31520cf1dd8SToby Isaac 
316*d083f849SBarry Smith   Collective
31720cf1dd8SToby Isaac 
31820cf1dd8SToby Isaac   Input Parameter:
31920cf1dd8SToby Isaac . comm - The communicator for the PetscFE object
32020cf1dd8SToby Isaac 
32120cf1dd8SToby Isaac   Output Parameter:
32220cf1dd8SToby Isaac . fem - The PetscFE object
32320cf1dd8SToby Isaac 
32420cf1dd8SToby Isaac   Level: beginner
32520cf1dd8SToby Isaac 
32620cf1dd8SToby Isaac .seealso: PetscFESetType(), PETSCFEGALERKIN
32720cf1dd8SToby Isaac @*/
32820cf1dd8SToby Isaac PetscErrorCode PetscFECreate(MPI_Comm comm, PetscFE *fem)
32920cf1dd8SToby Isaac {
33020cf1dd8SToby Isaac   PetscFE        f;
33120cf1dd8SToby Isaac   PetscErrorCode ierr;
33220cf1dd8SToby Isaac 
33320cf1dd8SToby Isaac   PetscFunctionBegin;
33420cf1dd8SToby Isaac   PetscValidPointer(fem, 2);
33520cf1dd8SToby Isaac   ierr = PetscCitationsRegister(FECitation,&FEcite);CHKERRQ(ierr);
33620cf1dd8SToby Isaac   *fem = NULL;
33720cf1dd8SToby Isaac   ierr = PetscFEInitializePackage();CHKERRQ(ierr);
33820cf1dd8SToby Isaac 
33920cf1dd8SToby Isaac   ierr = PetscHeaderCreate(f, PETSCFE_CLASSID, "PetscFE", "Finite Element", "PetscFE", comm, PetscFEDestroy, PetscFEView);CHKERRQ(ierr);
34020cf1dd8SToby Isaac 
34120cf1dd8SToby Isaac   f->basisSpace    = NULL;
34220cf1dd8SToby Isaac   f->dualSpace     = NULL;
34320cf1dd8SToby Isaac   f->numComponents = 1;
34420cf1dd8SToby Isaac   f->subspaces     = NULL;
34520cf1dd8SToby Isaac   f->invV          = NULL;
34620cf1dd8SToby Isaac   f->B             = NULL;
34720cf1dd8SToby Isaac   f->D             = NULL;
34820cf1dd8SToby Isaac   f->H             = NULL;
34920cf1dd8SToby Isaac   f->Bf            = NULL;
35020cf1dd8SToby Isaac   f->Df            = NULL;
35120cf1dd8SToby Isaac   f->Hf            = NULL;
35220cf1dd8SToby Isaac   ierr = PetscMemzero(&f->quadrature, sizeof(PetscQuadrature));CHKERRQ(ierr);
35320cf1dd8SToby Isaac   ierr = PetscMemzero(&f->faceQuadrature, sizeof(PetscQuadrature));CHKERRQ(ierr);
35420cf1dd8SToby Isaac   f->blockSize     = 0;
35520cf1dd8SToby Isaac   f->numBlocks     = 1;
35620cf1dd8SToby Isaac   f->batchSize     = 0;
35720cf1dd8SToby Isaac   f->numBatches    = 1;
35820cf1dd8SToby Isaac 
35920cf1dd8SToby Isaac   *fem = f;
36020cf1dd8SToby Isaac   PetscFunctionReturn(0);
36120cf1dd8SToby Isaac }
36220cf1dd8SToby Isaac 
36320cf1dd8SToby Isaac /*@
36420cf1dd8SToby Isaac   PetscFEGetSpatialDimension - Returns the spatial dimension of the element
36520cf1dd8SToby Isaac 
36620cf1dd8SToby Isaac   Not collective
36720cf1dd8SToby Isaac 
36820cf1dd8SToby Isaac   Input Parameter:
36920cf1dd8SToby Isaac . fem - The PetscFE object
37020cf1dd8SToby Isaac 
37120cf1dd8SToby Isaac   Output Parameter:
37220cf1dd8SToby Isaac . dim - The spatial dimension
37320cf1dd8SToby Isaac 
37420cf1dd8SToby Isaac   Level: intermediate
37520cf1dd8SToby Isaac 
37620cf1dd8SToby Isaac .seealso: PetscFECreate()
37720cf1dd8SToby Isaac @*/
37820cf1dd8SToby Isaac PetscErrorCode PetscFEGetSpatialDimension(PetscFE fem, PetscInt *dim)
37920cf1dd8SToby Isaac {
38020cf1dd8SToby Isaac   DM             dm;
38120cf1dd8SToby Isaac   PetscErrorCode ierr;
38220cf1dd8SToby Isaac 
38320cf1dd8SToby Isaac   PetscFunctionBegin;
38420cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
38520cf1dd8SToby Isaac   PetscValidPointer(dim, 2);
38620cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr);
38720cf1dd8SToby Isaac   ierr = DMGetDimension(dm, dim);CHKERRQ(ierr);
38820cf1dd8SToby Isaac   PetscFunctionReturn(0);
38920cf1dd8SToby Isaac }
39020cf1dd8SToby Isaac 
39120cf1dd8SToby Isaac /*@
39220cf1dd8SToby Isaac   PetscFESetNumComponents - Sets the number of components in the element
39320cf1dd8SToby Isaac 
39420cf1dd8SToby Isaac   Not collective
39520cf1dd8SToby Isaac 
39620cf1dd8SToby Isaac   Input Parameters:
39720cf1dd8SToby Isaac + fem - The PetscFE object
39820cf1dd8SToby Isaac - comp - The number of field components
39920cf1dd8SToby Isaac 
40020cf1dd8SToby Isaac   Level: intermediate
40120cf1dd8SToby Isaac 
40220cf1dd8SToby Isaac .seealso: PetscFECreate()
40320cf1dd8SToby Isaac @*/
40420cf1dd8SToby Isaac PetscErrorCode PetscFESetNumComponents(PetscFE fem, PetscInt comp)
40520cf1dd8SToby Isaac {
40620cf1dd8SToby Isaac   PetscFunctionBegin;
40720cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
40820cf1dd8SToby Isaac   fem->numComponents = comp;
40920cf1dd8SToby Isaac   PetscFunctionReturn(0);
41020cf1dd8SToby Isaac }
41120cf1dd8SToby Isaac 
41220cf1dd8SToby Isaac /*@
41320cf1dd8SToby Isaac   PetscFEGetNumComponents - Returns the number of components in the element
41420cf1dd8SToby Isaac 
41520cf1dd8SToby Isaac   Not collective
41620cf1dd8SToby Isaac 
41720cf1dd8SToby Isaac   Input Parameter:
41820cf1dd8SToby Isaac . fem - The PetscFE object
41920cf1dd8SToby Isaac 
42020cf1dd8SToby Isaac   Output Parameter:
42120cf1dd8SToby Isaac . comp - The number of field components
42220cf1dd8SToby Isaac 
42320cf1dd8SToby Isaac   Level: intermediate
42420cf1dd8SToby Isaac 
42520cf1dd8SToby Isaac .seealso: PetscFECreate()
42620cf1dd8SToby Isaac @*/
42720cf1dd8SToby Isaac PetscErrorCode PetscFEGetNumComponents(PetscFE fem, PetscInt *comp)
42820cf1dd8SToby Isaac {
42920cf1dd8SToby Isaac   PetscFunctionBegin;
43020cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
43120cf1dd8SToby Isaac   PetscValidPointer(comp, 2);
43220cf1dd8SToby Isaac   *comp = fem->numComponents;
43320cf1dd8SToby Isaac   PetscFunctionReturn(0);
43420cf1dd8SToby Isaac }
43520cf1dd8SToby Isaac 
43620cf1dd8SToby Isaac /*@
43720cf1dd8SToby Isaac   PetscFESetTileSizes - Sets the tile sizes for evaluation
43820cf1dd8SToby Isaac 
43920cf1dd8SToby Isaac   Not collective
44020cf1dd8SToby Isaac 
44120cf1dd8SToby Isaac   Input Parameters:
44220cf1dd8SToby Isaac + fem - The PetscFE object
44320cf1dd8SToby Isaac . blockSize - The number of elements in a block
44420cf1dd8SToby Isaac . numBlocks - The number of blocks in a batch
44520cf1dd8SToby Isaac . batchSize - The number of elements in a batch
44620cf1dd8SToby Isaac - numBatches - The number of batches in a chunk
44720cf1dd8SToby Isaac 
44820cf1dd8SToby Isaac   Level: intermediate
44920cf1dd8SToby Isaac 
45020cf1dd8SToby Isaac .seealso: PetscFECreate()
45120cf1dd8SToby Isaac @*/
45220cf1dd8SToby Isaac PetscErrorCode PetscFESetTileSizes(PetscFE fem, PetscInt blockSize, PetscInt numBlocks, PetscInt batchSize, PetscInt numBatches)
45320cf1dd8SToby Isaac {
45420cf1dd8SToby Isaac   PetscFunctionBegin;
45520cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
45620cf1dd8SToby Isaac   fem->blockSize  = blockSize;
45720cf1dd8SToby Isaac   fem->numBlocks  = numBlocks;
45820cf1dd8SToby Isaac   fem->batchSize  = batchSize;
45920cf1dd8SToby Isaac   fem->numBatches = numBatches;
46020cf1dd8SToby Isaac   PetscFunctionReturn(0);
46120cf1dd8SToby Isaac }
46220cf1dd8SToby Isaac 
46320cf1dd8SToby Isaac /*@
46420cf1dd8SToby Isaac   PetscFEGetTileSizes - Returns the tile sizes for evaluation
46520cf1dd8SToby Isaac 
46620cf1dd8SToby Isaac   Not collective
46720cf1dd8SToby Isaac 
46820cf1dd8SToby Isaac   Input Parameter:
46920cf1dd8SToby Isaac . fem - The PetscFE object
47020cf1dd8SToby Isaac 
47120cf1dd8SToby Isaac   Output Parameters:
47220cf1dd8SToby Isaac + blockSize - The number of elements in a block
47320cf1dd8SToby Isaac . numBlocks - The number of blocks in a batch
47420cf1dd8SToby Isaac . batchSize - The number of elements in a batch
47520cf1dd8SToby Isaac - numBatches - The number of batches in a chunk
47620cf1dd8SToby Isaac 
47720cf1dd8SToby Isaac   Level: intermediate
47820cf1dd8SToby Isaac 
47920cf1dd8SToby Isaac .seealso: PetscFECreate()
48020cf1dd8SToby Isaac @*/
48120cf1dd8SToby Isaac PetscErrorCode PetscFEGetTileSizes(PetscFE fem, PetscInt *blockSize, PetscInt *numBlocks, PetscInt *batchSize, PetscInt *numBatches)
48220cf1dd8SToby Isaac {
48320cf1dd8SToby Isaac   PetscFunctionBegin;
48420cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
48520cf1dd8SToby Isaac   if (blockSize)  PetscValidPointer(blockSize,  2);
48620cf1dd8SToby Isaac   if (numBlocks)  PetscValidPointer(numBlocks,  3);
48720cf1dd8SToby Isaac   if (batchSize)  PetscValidPointer(batchSize,  4);
48820cf1dd8SToby Isaac   if (numBatches) PetscValidPointer(numBatches, 5);
48920cf1dd8SToby Isaac   if (blockSize)  *blockSize  = fem->blockSize;
49020cf1dd8SToby Isaac   if (numBlocks)  *numBlocks  = fem->numBlocks;
49120cf1dd8SToby Isaac   if (batchSize)  *batchSize  = fem->batchSize;
49220cf1dd8SToby Isaac   if (numBatches) *numBatches = fem->numBatches;
49320cf1dd8SToby Isaac   PetscFunctionReturn(0);
49420cf1dd8SToby Isaac }
49520cf1dd8SToby Isaac 
49620cf1dd8SToby Isaac /*@
49720cf1dd8SToby Isaac   PetscFEGetBasisSpace - Returns the PetscSpace used for approximation of the solution
49820cf1dd8SToby Isaac 
49920cf1dd8SToby Isaac   Not collective
50020cf1dd8SToby Isaac 
50120cf1dd8SToby Isaac   Input Parameter:
50220cf1dd8SToby Isaac . fem - The PetscFE object
50320cf1dd8SToby Isaac 
50420cf1dd8SToby Isaac   Output Parameter:
50520cf1dd8SToby Isaac . sp - The PetscSpace object
50620cf1dd8SToby Isaac 
50720cf1dd8SToby Isaac   Level: intermediate
50820cf1dd8SToby Isaac 
50920cf1dd8SToby Isaac .seealso: PetscFECreate()
51020cf1dd8SToby Isaac @*/
51120cf1dd8SToby Isaac PetscErrorCode PetscFEGetBasisSpace(PetscFE fem, PetscSpace *sp)
51220cf1dd8SToby Isaac {
51320cf1dd8SToby Isaac   PetscFunctionBegin;
51420cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
51520cf1dd8SToby Isaac   PetscValidPointer(sp, 2);
51620cf1dd8SToby Isaac   *sp = fem->basisSpace;
51720cf1dd8SToby Isaac   PetscFunctionReturn(0);
51820cf1dd8SToby Isaac }
51920cf1dd8SToby Isaac 
52020cf1dd8SToby Isaac /*@
52120cf1dd8SToby Isaac   PetscFESetBasisSpace - Sets the PetscSpace used for approximation of the solution
52220cf1dd8SToby Isaac 
52320cf1dd8SToby Isaac   Not collective
52420cf1dd8SToby Isaac 
52520cf1dd8SToby Isaac   Input Parameters:
52620cf1dd8SToby Isaac + fem - The PetscFE object
52720cf1dd8SToby Isaac - sp - The PetscSpace object
52820cf1dd8SToby Isaac 
52920cf1dd8SToby Isaac   Level: intermediate
53020cf1dd8SToby Isaac 
53120cf1dd8SToby Isaac .seealso: PetscFECreate()
53220cf1dd8SToby Isaac @*/
53320cf1dd8SToby Isaac PetscErrorCode PetscFESetBasisSpace(PetscFE fem, PetscSpace sp)
53420cf1dd8SToby Isaac {
53520cf1dd8SToby Isaac   PetscErrorCode ierr;
53620cf1dd8SToby Isaac 
53720cf1dd8SToby Isaac   PetscFunctionBegin;
53820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
53920cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCSPACE_CLASSID, 2);
54020cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&fem->basisSpace);CHKERRQ(ierr);
54120cf1dd8SToby Isaac   fem->basisSpace = sp;
54220cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) fem->basisSpace);CHKERRQ(ierr);
54320cf1dd8SToby Isaac   PetscFunctionReturn(0);
54420cf1dd8SToby Isaac }
54520cf1dd8SToby Isaac 
54620cf1dd8SToby Isaac /*@
54720cf1dd8SToby Isaac   PetscFEGetDualSpace - Returns the PetscDualSpace used to define the inner product
54820cf1dd8SToby Isaac 
54920cf1dd8SToby Isaac   Not collective
55020cf1dd8SToby Isaac 
55120cf1dd8SToby Isaac   Input Parameter:
55220cf1dd8SToby Isaac . fem - The PetscFE object
55320cf1dd8SToby Isaac 
55420cf1dd8SToby Isaac   Output Parameter:
55520cf1dd8SToby Isaac . sp - The PetscDualSpace object
55620cf1dd8SToby Isaac 
55720cf1dd8SToby Isaac   Level: intermediate
55820cf1dd8SToby Isaac 
55920cf1dd8SToby Isaac .seealso: PetscFECreate()
56020cf1dd8SToby Isaac @*/
56120cf1dd8SToby Isaac PetscErrorCode PetscFEGetDualSpace(PetscFE fem, PetscDualSpace *sp)
56220cf1dd8SToby Isaac {
56320cf1dd8SToby Isaac   PetscFunctionBegin;
56420cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
56520cf1dd8SToby Isaac   PetscValidPointer(sp, 2);
56620cf1dd8SToby Isaac   *sp = fem->dualSpace;
56720cf1dd8SToby Isaac   PetscFunctionReturn(0);
56820cf1dd8SToby Isaac }
56920cf1dd8SToby Isaac 
57020cf1dd8SToby Isaac /*@
57120cf1dd8SToby Isaac   PetscFESetDualSpace - Sets the PetscDualSpace used to define the inner product
57220cf1dd8SToby Isaac 
57320cf1dd8SToby Isaac   Not collective
57420cf1dd8SToby Isaac 
57520cf1dd8SToby Isaac   Input Parameters:
57620cf1dd8SToby Isaac + fem - The PetscFE object
57720cf1dd8SToby Isaac - sp - The PetscDualSpace object
57820cf1dd8SToby Isaac 
57920cf1dd8SToby Isaac   Level: intermediate
58020cf1dd8SToby Isaac 
58120cf1dd8SToby Isaac .seealso: PetscFECreate()
58220cf1dd8SToby Isaac @*/
58320cf1dd8SToby Isaac PetscErrorCode PetscFESetDualSpace(PetscFE fem, PetscDualSpace sp)
58420cf1dd8SToby Isaac {
58520cf1dd8SToby Isaac   PetscErrorCode ierr;
58620cf1dd8SToby Isaac 
58720cf1dd8SToby Isaac   PetscFunctionBegin;
58820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
58920cf1dd8SToby Isaac   PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 2);
59020cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&fem->dualSpace);CHKERRQ(ierr);
59120cf1dd8SToby Isaac   fem->dualSpace = sp;
59220cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) fem->dualSpace);CHKERRQ(ierr);
59320cf1dd8SToby Isaac   PetscFunctionReturn(0);
59420cf1dd8SToby Isaac }
59520cf1dd8SToby Isaac 
59620cf1dd8SToby Isaac /*@
59720cf1dd8SToby Isaac   PetscFEGetQuadrature - Returns the PetscQuadrature used to calculate inner products
59820cf1dd8SToby Isaac 
59920cf1dd8SToby Isaac   Not collective
60020cf1dd8SToby Isaac 
60120cf1dd8SToby Isaac   Input Parameter:
60220cf1dd8SToby Isaac . fem - The PetscFE object
60320cf1dd8SToby Isaac 
60420cf1dd8SToby Isaac   Output Parameter:
60520cf1dd8SToby Isaac . q - The PetscQuadrature object
60620cf1dd8SToby Isaac 
60720cf1dd8SToby Isaac   Level: intermediate
60820cf1dd8SToby Isaac 
60920cf1dd8SToby Isaac .seealso: PetscFECreate()
61020cf1dd8SToby Isaac @*/
61120cf1dd8SToby Isaac PetscErrorCode PetscFEGetQuadrature(PetscFE fem, PetscQuadrature *q)
61220cf1dd8SToby Isaac {
61320cf1dd8SToby Isaac   PetscFunctionBegin;
61420cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
61520cf1dd8SToby Isaac   PetscValidPointer(q, 2);
61620cf1dd8SToby Isaac   *q = fem->quadrature;
61720cf1dd8SToby Isaac   PetscFunctionReturn(0);
61820cf1dd8SToby Isaac }
61920cf1dd8SToby Isaac 
62020cf1dd8SToby Isaac /*@
62120cf1dd8SToby Isaac   PetscFESetQuadrature - Sets the PetscQuadrature used to calculate inner products
62220cf1dd8SToby Isaac 
62320cf1dd8SToby Isaac   Not collective
62420cf1dd8SToby Isaac 
62520cf1dd8SToby Isaac   Input Parameters:
62620cf1dd8SToby Isaac + fem - The PetscFE object
62720cf1dd8SToby Isaac - q - The PetscQuadrature object
62820cf1dd8SToby Isaac 
62920cf1dd8SToby Isaac   Level: intermediate
63020cf1dd8SToby Isaac 
63120cf1dd8SToby Isaac .seealso: PetscFECreate()
63220cf1dd8SToby Isaac @*/
63320cf1dd8SToby Isaac PetscErrorCode PetscFESetQuadrature(PetscFE fem, PetscQuadrature q)
63420cf1dd8SToby Isaac {
63520cf1dd8SToby Isaac   PetscInt       Nc, qNc;
63620cf1dd8SToby Isaac   PetscErrorCode ierr;
63720cf1dd8SToby Isaac 
63820cf1dd8SToby Isaac   PetscFunctionBegin;
63920cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
64020cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fem, &Nc);CHKERRQ(ierr);
64120cf1dd8SToby Isaac   ierr = PetscQuadratureGetNumComponents(q, &qNc);CHKERRQ(ierr);
64220cf1dd8SToby 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);
64320cf1dd8SToby Isaac   ierr = PetscFERestoreTabulation(fem, 0, NULL, &fem->B, &fem->D, NULL /*&(*fem)->H*/);CHKERRQ(ierr);
64420cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&fem->quadrature);CHKERRQ(ierr);
64520cf1dd8SToby Isaac   fem->quadrature = q;
64620cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr);
64720cf1dd8SToby Isaac   PetscFunctionReturn(0);
64820cf1dd8SToby Isaac }
64920cf1dd8SToby Isaac 
65020cf1dd8SToby Isaac /*@
65120cf1dd8SToby Isaac   PetscFEGetFaceQuadrature - Returns the PetscQuadrature used to calculate inner products on faces
65220cf1dd8SToby Isaac 
65320cf1dd8SToby Isaac   Not collective
65420cf1dd8SToby Isaac 
65520cf1dd8SToby Isaac   Input Parameter:
65620cf1dd8SToby Isaac . fem - The PetscFE object
65720cf1dd8SToby Isaac 
65820cf1dd8SToby Isaac   Output Parameter:
65920cf1dd8SToby Isaac . q - The PetscQuadrature object
66020cf1dd8SToby Isaac 
66120cf1dd8SToby Isaac   Level: intermediate
66220cf1dd8SToby Isaac 
66320cf1dd8SToby Isaac .seealso: PetscFECreate()
66420cf1dd8SToby Isaac @*/
66520cf1dd8SToby Isaac PetscErrorCode PetscFEGetFaceQuadrature(PetscFE fem, PetscQuadrature *q)
66620cf1dd8SToby Isaac {
66720cf1dd8SToby Isaac   PetscFunctionBegin;
66820cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
66920cf1dd8SToby Isaac   PetscValidPointer(q, 2);
67020cf1dd8SToby Isaac   *q = fem->faceQuadrature;
67120cf1dd8SToby Isaac   PetscFunctionReturn(0);
67220cf1dd8SToby Isaac }
67320cf1dd8SToby Isaac 
67420cf1dd8SToby Isaac /*@
67520cf1dd8SToby Isaac   PetscFESetFaceQuadrature - Sets the PetscQuadrature used to calculate inner products on faces
67620cf1dd8SToby Isaac 
67720cf1dd8SToby Isaac   Not collective
67820cf1dd8SToby Isaac 
67920cf1dd8SToby Isaac   Input Parameters:
68020cf1dd8SToby Isaac + fem - The PetscFE object
68120cf1dd8SToby Isaac - q - The PetscQuadrature object
68220cf1dd8SToby Isaac 
68320cf1dd8SToby Isaac   Level: intermediate
68420cf1dd8SToby Isaac 
68520cf1dd8SToby Isaac .seealso: PetscFECreate()
68620cf1dd8SToby Isaac @*/
68720cf1dd8SToby Isaac PetscErrorCode PetscFESetFaceQuadrature(PetscFE fem, PetscQuadrature q)
68820cf1dd8SToby Isaac {
68920cf1dd8SToby Isaac   PetscErrorCode ierr;
69020cf1dd8SToby Isaac 
69120cf1dd8SToby Isaac   PetscFunctionBegin;
69220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
69320cf1dd8SToby Isaac   ierr = PetscFERestoreTabulation(fem, 0, NULL, &fem->Bf, &fem->Df, NULL /*&(*fem)->Hf*/);CHKERRQ(ierr);
69420cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&fem->faceQuadrature);CHKERRQ(ierr);
69520cf1dd8SToby Isaac   fem->faceQuadrature = q;
69620cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) q);CHKERRQ(ierr);
69720cf1dd8SToby Isaac   PetscFunctionReturn(0);
69820cf1dd8SToby Isaac }
69920cf1dd8SToby Isaac 
70020cf1dd8SToby Isaac /*@C
70120cf1dd8SToby Isaac   PetscFEGetNumDof - Returns the number of dofs (dual basis vectors) associated to mesh points on the reference cell of a given dimension
70220cf1dd8SToby Isaac 
70320cf1dd8SToby Isaac   Not collective
70420cf1dd8SToby Isaac 
70520cf1dd8SToby Isaac   Input Parameter:
70620cf1dd8SToby Isaac . fem - The PetscFE object
70720cf1dd8SToby Isaac 
70820cf1dd8SToby Isaac   Output Parameter:
70920cf1dd8SToby Isaac . numDof - Array with the number of dofs per dimension
71020cf1dd8SToby Isaac 
71120cf1dd8SToby Isaac   Level: intermediate
71220cf1dd8SToby Isaac 
71320cf1dd8SToby Isaac .seealso: PetscFECreate()
71420cf1dd8SToby Isaac @*/
71520cf1dd8SToby Isaac PetscErrorCode PetscFEGetNumDof(PetscFE fem, const PetscInt **numDof)
71620cf1dd8SToby Isaac {
71720cf1dd8SToby Isaac   PetscErrorCode ierr;
71820cf1dd8SToby Isaac 
71920cf1dd8SToby Isaac   PetscFunctionBegin;
72020cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
72120cf1dd8SToby Isaac   PetscValidPointer(numDof, 2);
72220cf1dd8SToby Isaac   ierr = PetscDualSpaceGetNumDof(fem->dualSpace, numDof);CHKERRQ(ierr);
72320cf1dd8SToby Isaac   PetscFunctionReturn(0);
72420cf1dd8SToby Isaac }
72520cf1dd8SToby Isaac 
72620cf1dd8SToby Isaac /*@C
72720cf1dd8SToby Isaac   PetscFEGetDefaultTabulation - Returns the tabulation of the basis functions at the quadrature points
72820cf1dd8SToby Isaac 
72920cf1dd8SToby Isaac   Not collective
73020cf1dd8SToby Isaac 
73120cf1dd8SToby Isaac   Input Parameter:
73220cf1dd8SToby Isaac . fem - The PetscFE object
73320cf1dd8SToby Isaac 
73420cf1dd8SToby Isaac   Output Parameters:
73520cf1dd8SToby Isaac + B - The basis function values at quadrature points
73620cf1dd8SToby Isaac . D - The basis function derivatives at quadrature points
73720cf1dd8SToby Isaac - H - The basis function second derivatives at quadrature points
73820cf1dd8SToby Isaac 
73920cf1dd8SToby Isaac   Note:
74020cf1dd8SToby Isaac $ B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
74120cf1dd8SToby Isaac $ D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d
74220cf1dd8SToby Isaac $ 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
74320cf1dd8SToby Isaac 
74420cf1dd8SToby Isaac   Level: intermediate
74520cf1dd8SToby Isaac 
74620cf1dd8SToby Isaac .seealso: PetscFEGetTabulation(), PetscFERestoreTabulation()
74720cf1dd8SToby Isaac @*/
74820cf1dd8SToby Isaac PetscErrorCode PetscFEGetDefaultTabulation(PetscFE fem, PetscReal **B, PetscReal **D, PetscReal **H)
74920cf1dd8SToby Isaac {
75020cf1dd8SToby Isaac   PetscInt         npoints;
75120cf1dd8SToby Isaac   const PetscReal *points;
75220cf1dd8SToby Isaac   PetscErrorCode   ierr;
75320cf1dd8SToby Isaac 
75420cf1dd8SToby Isaac   PetscFunctionBegin;
75520cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
75620cf1dd8SToby Isaac   if (B) PetscValidPointer(B, 2);
75720cf1dd8SToby Isaac   if (D) PetscValidPointer(D, 3);
75820cf1dd8SToby Isaac   if (H) PetscValidPointer(H, 4);
75920cf1dd8SToby Isaac   ierr = PetscQuadratureGetData(fem->quadrature, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr);
76020cf1dd8SToby Isaac   if (!fem->B) {ierr = PetscFEGetTabulation(fem, npoints, points, &fem->B, &fem->D, NULL/*&fem->H*/);CHKERRQ(ierr);}
76120cf1dd8SToby Isaac   if (B) *B = fem->B;
76220cf1dd8SToby Isaac   if (D) *D = fem->D;
76320cf1dd8SToby Isaac   if (H) *H = fem->H;
76420cf1dd8SToby Isaac   PetscFunctionReturn(0);
76520cf1dd8SToby Isaac }
76620cf1dd8SToby Isaac 
76720cf1dd8SToby Isaac PetscErrorCode PetscFEGetFaceTabulation(PetscFE fem, PetscReal **Bf, PetscReal **Df, PetscReal **Hf)
76820cf1dd8SToby Isaac {
76920cf1dd8SToby Isaac   PetscErrorCode   ierr;
77020cf1dd8SToby Isaac 
77120cf1dd8SToby Isaac   PetscFunctionBegin;
77220cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
77320cf1dd8SToby Isaac   if (Bf) PetscValidPointer(Bf, 2);
77420cf1dd8SToby Isaac   if (Df) PetscValidPointer(Df, 3);
77520cf1dd8SToby Isaac   if (Hf) PetscValidPointer(Hf, 4);
77620cf1dd8SToby Isaac   if (!fem->Bf) {
77720cf1dd8SToby Isaac     const PetscReal  xi0[3] = {-1., -1., -1.};
77820cf1dd8SToby Isaac     PetscReal        v0[3], J[9], detJ;
77920cf1dd8SToby Isaac     PetscQuadrature  fq;
78020cf1dd8SToby Isaac     PetscDualSpace   sp;
78120cf1dd8SToby Isaac     DM               dm;
78220cf1dd8SToby Isaac     const PetscInt  *faces;
78320cf1dd8SToby Isaac     PetscInt         dim, numFaces, f, npoints, q;
78420cf1dd8SToby Isaac     const PetscReal *points;
78520cf1dd8SToby Isaac     PetscReal       *facePoints;
78620cf1dd8SToby Isaac 
78720cf1dd8SToby Isaac     ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr);
78820cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr);
78920cf1dd8SToby Isaac     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
79020cf1dd8SToby Isaac     ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr);
79120cf1dd8SToby Isaac     ierr = DMPlexGetCone(dm, 0, &faces);CHKERRQ(ierr);
79220cf1dd8SToby Isaac     ierr = PetscFEGetFaceQuadrature(fem, &fq);CHKERRQ(ierr);
79320cf1dd8SToby Isaac     if (fq) {
79420cf1dd8SToby Isaac       ierr = PetscQuadratureGetData(fq, NULL, NULL, &npoints, &points, NULL);CHKERRQ(ierr);
79520cf1dd8SToby Isaac       ierr = PetscMalloc1(numFaces*npoints*dim, &facePoints);CHKERRQ(ierr);
79620cf1dd8SToby Isaac       for (f = 0; f < numFaces; ++f) {
79720cf1dd8SToby Isaac         ierr = DMPlexComputeCellGeometryFEM(dm, faces[f], NULL, v0, J, NULL, &detJ);CHKERRQ(ierr);
79820cf1dd8SToby Isaac         for (q = 0; q < npoints; ++q) CoordinatesRefToReal(dim, dim-1, xi0, v0, J, &points[q*(dim-1)], &facePoints[(f*npoints+q)*dim]);
79920cf1dd8SToby Isaac       }
80020cf1dd8SToby Isaac       ierr = PetscFEGetTabulation(fem, numFaces*npoints, facePoints, &fem->Bf, &fem->Df, NULL/*&fem->Hf*/);CHKERRQ(ierr);
80120cf1dd8SToby Isaac       ierr = PetscFree(facePoints);CHKERRQ(ierr);
80220cf1dd8SToby Isaac     }
80320cf1dd8SToby Isaac   }
80420cf1dd8SToby Isaac   if (Bf) *Bf = fem->Bf;
80520cf1dd8SToby Isaac   if (Df) *Df = fem->Df;
80620cf1dd8SToby Isaac   if (Hf) *Hf = fem->Hf;
80720cf1dd8SToby Isaac   PetscFunctionReturn(0);
80820cf1dd8SToby Isaac }
80920cf1dd8SToby Isaac 
81020cf1dd8SToby Isaac PetscErrorCode PetscFEGetFaceCentroidTabulation(PetscFE fem, PetscReal **F)
81120cf1dd8SToby Isaac {
81220cf1dd8SToby Isaac   PetscErrorCode   ierr;
81320cf1dd8SToby Isaac 
81420cf1dd8SToby Isaac   PetscFunctionBegin;
81520cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
81620cf1dd8SToby Isaac   PetscValidPointer(F, 2);
81720cf1dd8SToby Isaac   if (!fem->F) {
81820cf1dd8SToby Isaac     PetscDualSpace  sp;
81920cf1dd8SToby Isaac     DM              dm;
82020cf1dd8SToby Isaac     const PetscInt *cone;
82120cf1dd8SToby Isaac     PetscReal      *centroids;
82220cf1dd8SToby Isaac     PetscInt        dim, numFaces, f;
82320cf1dd8SToby Isaac 
82420cf1dd8SToby Isaac     ierr = PetscFEGetDualSpace(fem, &sp);CHKERRQ(ierr);
82520cf1dd8SToby Isaac     ierr = PetscDualSpaceGetDM(sp, &dm);CHKERRQ(ierr);
82620cf1dd8SToby Isaac     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
82720cf1dd8SToby Isaac     ierr = DMPlexGetConeSize(dm, 0, &numFaces);CHKERRQ(ierr);
82820cf1dd8SToby Isaac     ierr = DMPlexGetCone(dm, 0, &cone);CHKERRQ(ierr);
82920cf1dd8SToby Isaac     ierr = PetscMalloc1(numFaces*dim, &centroids);CHKERRQ(ierr);
83020cf1dd8SToby Isaac     for (f = 0; f < numFaces; ++f) {ierr = DMPlexComputeCellGeometryFVM(dm, cone[f], NULL, &centroids[f*dim], NULL);CHKERRQ(ierr);}
83120cf1dd8SToby Isaac     ierr = PetscFEGetTabulation(fem, numFaces, centroids, &fem->F, NULL, NULL);CHKERRQ(ierr);
83220cf1dd8SToby Isaac     ierr = PetscFree(centroids);CHKERRQ(ierr);
83320cf1dd8SToby Isaac   }
83420cf1dd8SToby Isaac   *F = fem->F;
83520cf1dd8SToby Isaac   PetscFunctionReturn(0);
83620cf1dd8SToby Isaac }
83720cf1dd8SToby Isaac 
83820cf1dd8SToby Isaac /*@C
83920cf1dd8SToby Isaac   PetscFEGetTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
84020cf1dd8SToby Isaac 
84120cf1dd8SToby Isaac   Not collective
84220cf1dd8SToby Isaac 
84320cf1dd8SToby Isaac   Input Parameters:
84420cf1dd8SToby Isaac + fem     - The PetscFE object
84520cf1dd8SToby Isaac . npoints - The number of tabulation points
84620cf1dd8SToby Isaac - points  - The tabulation point coordinates
84720cf1dd8SToby Isaac 
84820cf1dd8SToby Isaac   Output Parameters:
84920cf1dd8SToby Isaac + B - The basis function values at tabulation points
85020cf1dd8SToby Isaac . D - The basis function derivatives at tabulation points
85120cf1dd8SToby Isaac - H - The basis function second derivatives at tabulation points
85220cf1dd8SToby Isaac 
85320cf1dd8SToby Isaac   Note:
85420cf1dd8SToby Isaac $ B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
85520cf1dd8SToby Isaac $ D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d
85620cf1dd8SToby Isaac $ 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
85720cf1dd8SToby Isaac 
85820cf1dd8SToby Isaac   Level: intermediate
85920cf1dd8SToby Isaac 
86020cf1dd8SToby Isaac .seealso: PetscFERestoreTabulation(), PetscFEGetDefaultTabulation()
86120cf1dd8SToby Isaac @*/
86220cf1dd8SToby Isaac PetscErrorCode PetscFEGetTabulation(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscReal **B, PetscReal **D, PetscReal **H)
86320cf1dd8SToby Isaac {
86420cf1dd8SToby Isaac   DM               dm;
86520cf1dd8SToby Isaac   PetscInt         pdim; /* Dimension of FE space P */
86620cf1dd8SToby Isaac   PetscInt         dim;  /* Spatial dimension */
86720cf1dd8SToby Isaac   PetscInt         comp; /* Field components */
86820cf1dd8SToby Isaac   PetscErrorCode   ierr;
86920cf1dd8SToby Isaac 
87020cf1dd8SToby Isaac   PetscFunctionBegin;
87120cf1dd8SToby Isaac   if (!npoints) {
87220cf1dd8SToby Isaac     if (B) *B = NULL;
87320cf1dd8SToby Isaac     if (D) *D = NULL;
87420cf1dd8SToby Isaac     if (H) *H = NULL;
87520cf1dd8SToby Isaac     PetscFunctionReturn(0);
87620cf1dd8SToby Isaac   }
87720cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
87820cf1dd8SToby Isaac   PetscValidPointer(points, 3);
87920cf1dd8SToby Isaac   if (B) PetscValidPointer(B, 4);
88020cf1dd8SToby Isaac   if (D) PetscValidPointer(D, 5);
88120cf1dd8SToby Isaac   if (H) PetscValidPointer(H, 6);
88220cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr);
88320cf1dd8SToby Isaac   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
88420cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr);
88520cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fem, &comp);CHKERRQ(ierr);
88620cf1dd8SToby Isaac   if (B) {ierr = DMGetWorkArray(dm, npoints*pdim*comp, MPIU_REAL, B);CHKERRQ(ierr);}
88720cf1dd8SToby Isaac   if (!dim) {
88820cf1dd8SToby Isaac     if (D) *D = NULL;
88920cf1dd8SToby Isaac     if (H) *H = NULL;
89020cf1dd8SToby Isaac   } else {
89120cf1dd8SToby Isaac     if (D) {ierr = DMGetWorkArray(dm, npoints*pdim*comp*dim, MPIU_REAL, D);CHKERRQ(ierr);}
89220cf1dd8SToby Isaac     if (H) {ierr = DMGetWorkArray(dm, npoints*pdim*comp*dim*dim, MPIU_REAL, H);CHKERRQ(ierr);}
89320cf1dd8SToby Isaac   }
89420cf1dd8SToby Isaac   ierr = (*fem->ops->gettabulation)(fem, npoints, points, B ? *B : NULL, D ? *D : NULL, H ? *H : NULL);CHKERRQ(ierr);
89520cf1dd8SToby Isaac   PetscFunctionReturn(0);
89620cf1dd8SToby Isaac }
89720cf1dd8SToby Isaac 
89820cf1dd8SToby Isaac PetscErrorCode PetscFERestoreTabulation(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscReal **B, PetscReal **D, PetscReal **H)
89920cf1dd8SToby Isaac {
90020cf1dd8SToby Isaac   DM             dm;
90120cf1dd8SToby Isaac   PetscErrorCode ierr;
90220cf1dd8SToby Isaac 
90320cf1dd8SToby Isaac   PetscFunctionBegin;
90420cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
90520cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr);
90620cf1dd8SToby Isaac   if (B && *B) {ierr = DMRestoreWorkArray(dm, 0, MPIU_REAL, B);CHKERRQ(ierr);}
90720cf1dd8SToby Isaac   if (D && *D) {ierr = DMRestoreWorkArray(dm, 0, MPIU_REAL, D);CHKERRQ(ierr);}
90820cf1dd8SToby Isaac   if (H && *H) {ierr = DMRestoreWorkArray(dm, 0, MPIU_REAL, H);CHKERRQ(ierr);}
90920cf1dd8SToby Isaac   PetscFunctionReturn(0);
91020cf1dd8SToby Isaac }
91120cf1dd8SToby Isaac 
91220cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode PetscFECreatePointTrace(PetscFE fe, PetscInt refPoint, PetscFE *trFE)
91320cf1dd8SToby Isaac {
91420cf1dd8SToby Isaac   PetscSpace     bsp, bsubsp;
91520cf1dd8SToby Isaac   PetscDualSpace dsp, dsubsp;
91620cf1dd8SToby Isaac   PetscInt       dim, depth, numComp, i, j, coneSize, order;
91720cf1dd8SToby Isaac   PetscFEType    type;
91820cf1dd8SToby Isaac   DM             dm;
91920cf1dd8SToby Isaac   DMLabel        label;
92020cf1dd8SToby Isaac   PetscReal      *xi, *v, *J, detJ;
921db11e2ebSMatthew G. Knepley   const char     *name;
92220cf1dd8SToby Isaac   PetscQuadrature origin, fullQuad, subQuad;
92320cf1dd8SToby Isaac   PetscErrorCode ierr;
92420cf1dd8SToby Isaac 
92520cf1dd8SToby Isaac   PetscFunctionBegin;
92620cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1);
92720cf1dd8SToby Isaac   PetscValidPointer(trFE,3);
92820cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe,&bsp);CHKERRQ(ierr);
92920cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr);
93020cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr);
93120cf1dd8SToby Isaac   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
93220cf1dd8SToby Isaac   ierr = DMPlexGetDepthLabel(dm,&label);CHKERRQ(ierr);
93320cf1dd8SToby Isaac   ierr = DMLabelGetValue(label,refPoint,&depth);CHKERRQ(ierr);
93420cf1dd8SToby Isaac   ierr = PetscCalloc1(depth,&xi);CHKERRQ(ierr);
93520cf1dd8SToby Isaac   ierr = PetscMalloc1(dim,&v);CHKERRQ(ierr);
93620cf1dd8SToby Isaac   ierr = PetscMalloc1(dim*dim,&J);CHKERRQ(ierr);
93720cf1dd8SToby Isaac   for (i = 0; i < depth; i++) xi[i] = 0.;
93820cf1dd8SToby Isaac   ierr = PetscQuadratureCreate(PETSC_COMM_SELF,&origin);CHKERRQ(ierr);
93920cf1dd8SToby Isaac   ierr = PetscQuadratureSetData(origin,depth,0,1,xi,NULL);CHKERRQ(ierr);
94020cf1dd8SToby Isaac   ierr = DMPlexComputeCellGeometryFEM(dm,refPoint,origin,v,J,NULL,&detJ);CHKERRQ(ierr);
94120cf1dd8SToby Isaac   /* CellGeometryFEM computes the expanded Jacobian, we want the true jacobian */
94220cf1dd8SToby Isaac   for (i = 1; i < dim; i++) {
94320cf1dd8SToby Isaac     for (j = 0; j < depth; j++) {
94420cf1dd8SToby Isaac       J[i * depth + j] = J[i * dim + j];
94520cf1dd8SToby Isaac     }
94620cf1dd8SToby Isaac   }
94720cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&origin);CHKERRQ(ierr);
94820cf1dd8SToby Isaac   ierr = PetscDualSpaceGetPointSubspace(dsp,refPoint,&dsubsp);CHKERRQ(ierr);
94920cf1dd8SToby Isaac   ierr = PetscSpaceCreateSubspace(bsp,dsubsp,v,J,NULL,NULL,PETSC_OWN_POINTER,&bsubsp);CHKERRQ(ierr);
95020cf1dd8SToby Isaac   ierr = PetscSpaceSetUp(bsubsp);CHKERRQ(ierr);
95120cf1dd8SToby Isaac   ierr = PetscFECreate(PetscObjectComm((PetscObject)fe),trFE);CHKERRQ(ierr);
95220cf1dd8SToby Isaac   ierr = PetscFEGetType(fe,&type);CHKERRQ(ierr);
95320cf1dd8SToby Isaac   ierr = PetscFESetType(*trFE,type);CHKERRQ(ierr);
95420cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe,&numComp);CHKERRQ(ierr);
95520cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*trFE,numComp);CHKERRQ(ierr);
95620cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*trFE,bsubsp);CHKERRQ(ierr);
95720cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*trFE,dsubsp);CHKERRQ(ierr);
958db11e2ebSMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr);
959db11e2ebSMatthew G. Knepley   if (name) {ierr = PetscFESetName(*trFE, name);CHKERRQ(ierr);}
96020cf1dd8SToby Isaac   ierr = PetscFEGetQuadrature(fe,&fullQuad);CHKERRQ(ierr);
96120cf1dd8SToby Isaac   ierr = PetscQuadratureGetOrder(fullQuad,&order);CHKERRQ(ierr);
96220cf1dd8SToby Isaac   ierr = DMPlexGetConeSize(dm,refPoint,&coneSize);CHKERRQ(ierr);
96320cf1dd8SToby Isaac   if (coneSize == 2 * depth) {
96420cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr);
96520cf1dd8SToby Isaac   } else {
96620cf1dd8SToby Isaac     ierr = PetscDTGaussJacobiQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);CHKERRQ(ierr);
96720cf1dd8SToby Isaac   }
96820cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*trFE,subQuad);CHKERRQ(ierr);
96920cf1dd8SToby Isaac   ierr = PetscFESetUp(*trFE);CHKERRQ(ierr);
97020cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&subQuad);CHKERRQ(ierr);
97120cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&bsubsp);CHKERRQ(ierr);
97220cf1dd8SToby Isaac   PetscFunctionReturn(0);
97320cf1dd8SToby Isaac }
97420cf1dd8SToby Isaac 
97520cf1dd8SToby Isaac PetscErrorCode PetscFECreateHeightTrace(PetscFE fe, PetscInt height, PetscFE *trFE)
97620cf1dd8SToby Isaac {
97720cf1dd8SToby Isaac   PetscInt       hStart, hEnd;
97820cf1dd8SToby Isaac   PetscDualSpace dsp;
97920cf1dd8SToby Isaac   DM             dm;
98020cf1dd8SToby Isaac   PetscErrorCode ierr;
98120cf1dd8SToby Isaac 
98220cf1dd8SToby Isaac   PetscFunctionBegin;
98320cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe,PETSCFE_CLASSID,1);
98420cf1dd8SToby Isaac   PetscValidPointer(trFE,3);
98520cf1dd8SToby Isaac   *trFE = NULL;
98620cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe,&dsp);CHKERRQ(ierr);
98720cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(dsp,&dm);CHKERRQ(ierr);
98820cf1dd8SToby Isaac   ierr = DMPlexGetHeightStratum(dm,height,&hStart,&hEnd);CHKERRQ(ierr);
98920cf1dd8SToby Isaac   if (hEnd <= hStart) PetscFunctionReturn(0);
99020cf1dd8SToby Isaac   ierr = PetscFECreatePointTrace(fe,hStart,trFE);CHKERRQ(ierr);
99120cf1dd8SToby Isaac   PetscFunctionReturn(0);
99220cf1dd8SToby Isaac }
99320cf1dd8SToby Isaac 
99420cf1dd8SToby Isaac 
99520cf1dd8SToby Isaac /*@
99620cf1dd8SToby Isaac   PetscFEGetDimension - Get the dimension of the finite element space on a cell
99720cf1dd8SToby Isaac 
99820cf1dd8SToby Isaac   Not collective
99920cf1dd8SToby Isaac 
100020cf1dd8SToby Isaac   Input Parameter:
100120cf1dd8SToby Isaac . fe - The PetscFE
100220cf1dd8SToby Isaac 
100320cf1dd8SToby Isaac   Output Parameter:
100420cf1dd8SToby Isaac . dim - The dimension
100520cf1dd8SToby Isaac 
100620cf1dd8SToby Isaac   Level: intermediate
100720cf1dd8SToby Isaac 
100820cf1dd8SToby Isaac .seealso: PetscFECreate(), PetscSpaceGetDimension(), PetscDualSpaceGetDimension()
100920cf1dd8SToby Isaac @*/
101020cf1dd8SToby Isaac PetscErrorCode PetscFEGetDimension(PetscFE fem, PetscInt *dim)
101120cf1dd8SToby Isaac {
101220cf1dd8SToby Isaac   PetscErrorCode ierr;
101320cf1dd8SToby Isaac 
101420cf1dd8SToby Isaac   PetscFunctionBegin;
101520cf1dd8SToby Isaac   PetscValidHeaderSpecific(fem, PETSCFE_CLASSID, 1);
101620cf1dd8SToby Isaac   PetscValidPointer(dim, 2);
101720cf1dd8SToby Isaac   if (fem->ops->getdimension) {ierr = (*fem->ops->getdimension)(fem, dim);CHKERRQ(ierr);}
101820cf1dd8SToby Isaac   PetscFunctionReturn(0);
101920cf1dd8SToby Isaac }
102020cf1dd8SToby Isaac 
10214bee2e38SMatthew G. Knepley /*@C
10224bee2e38SMatthew G. Knepley   PetscFEPushforward - Map the reference element function to real space
10234bee2e38SMatthew G. Knepley 
10244bee2e38SMatthew G. Knepley   Input Parameters:
10254bee2e38SMatthew G. Knepley + fe     - The PetscFE
10264bee2e38SMatthew G. Knepley . fegeom - The cell geometry
10274bee2e38SMatthew G. Knepley . Nv     - The number of function values
10284bee2e38SMatthew G. Knepley - vals   - The function values
10294bee2e38SMatthew G. Knepley 
10304bee2e38SMatthew G. Knepley   Output Parameter:
10314bee2e38SMatthew G. Knepley . vals   - The transformed function values
10324bee2e38SMatthew G. Knepley 
10334bee2e38SMatthew G. Knepley   Level: advanced
10344bee2e38SMatthew G. Knepley 
10354bee2e38SMatthew G. Knepley   Note: This just forwards the call onto PetscDualSpacePushforward().
10364bee2e38SMatthew G. Knepley 
10374bee2e38SMatthew G. Knepley .seealso: PetscDualSpacePushforward()
10384bee2e38SMatthew G. Knepley @*/
10394bee2e38SMatthew G. Knepley PetscErrorCode PetscFEPushforward(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
10404bee2e38SMatthew G. Knepley {
10414bee2e38SMatthew G. Knepley   PetscErrorCode ierr;
10424bee2e38SMatthew G. Knepley 
10432ae266adSMatthew G. Knepley   PetscFunctionBeginHot;
10442ae266adSMatthew G. Knepley   ierr = PetscDualSpacePushforward(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr);
10454bee2e38SMatthew G. Knepley   PetscFunctionReturn(0);
10464bee2e38SMatthew G. Knepley }
10474bee2e38SMatthew G. Knepley 
10484bee2e38SMatthew G. Knepley /*@C
10494bee2e38SMatthew G. Knepley   PetscFEPushforwardGradient - Map the reference element function gradient to real space
10504bee2e38SMatthew G. Knepley 
10514bee2e38SMatthew G. Knepley   Input Parameters:
10524bee2e38SMatthew G. Knepley + fe     - The PetscFE
10534bee2e38SMatthew G. Knepley . fegeom - The cell geometry
10544bee2e38SMatthew G. Knepley . Nv     - The number of function gradient values
10554bee2e38SMatthew G. Knepley - vals   - The function gradient values
10564bee2e38SMatthew G. Knepley 
10574bee2e38SMatthew G. Knepley   Output Parameter:
10584bee2e38SMatthew G. Knepley . vals   - The transformed function gradient values
10594bee2e38SMatthew G. Knepley 
10604bee2e38SMatthew G. Knepley   Level: advanced
10614bee2e38SMatthew G. Knepley 
10624bee2e38SMatthew G. Knepley   Note: This just forwards the call onto PetscDualSpacePushforwardGradient().
10634bee2e38SMatthew G. Knepley 
10644bee2e38SMatthew G. Knepley .seealso: PetscFEPushforward(), PetscDualSpacePushforwardGradient(), PetscDualSpacePushforward()
10654bee2e38SMatthew G. Knepley @*/
10664bee2e38SMatthew G. Knepley PetscErrorCode PetscFEPushforwardGradient(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
10674bee2e38SMatthew G. Knepley {
10684bee2e38SMatthew G. Knepley   PetscErrorCode ierr;
10694bee2e38SMatthew G. Knepley 
10702ae266adSMatthew G. Knepley   PetscFunctionBeginHot;
10712ae266adSMatthew G. Knepley   ierr = PetscDualSpacePushforwardGradient(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);CHKERRQ(ierr);
10724bee2e38SMatthew G. Knepley   PetscFunctionReturn(0);
10734bee2e38SMatthew G. Knepley }
10744bee2e38SMatthew G. Knepley 
107520cf1dd8SToby Isaac /*
107620cf1dd8SToby Isaac Purpose: Compute element vector for chunk of elements
107720cf1dd8SToby Isaac 
107820cf1dd8SToby Isaac Input:
107920cf1dd8SToby Isaac   Sizes:
108020cf1dd8SToby Isaac      Ne:  number of elements
108120cf1dd8SToby Isaac      Nf:  number of fields
108220cf1dd8SToby Isaac      PetscFE
108320cf1dd8SToby Isaac        dim: spatial dimension
108420cf1dd8SToby Isaac        Nb:  number of basis functions
108520cf1dd8SToby Isaac        Nc:  number of field components
108620cf1dd8SToby Isaac        PetscQuadrature
108720cf1dd8SToby Isaac          Nq:  number of quadrature points
108820cf1dd8SToby Isaac 
108920cf1dd8SToby Isaac   Geometry:
109020cf1dd8SToby Isaac      PetscFEGeom[Ne] possibly *Nq
109120cf1dd8SToby Isaac        PetscReal v0s[dim]
109220cf1dd8SToby Isaac        PetscReal n[dim]
109320cf1dd8SToby Isaac        PetscReal jacobians[dim*dim]
109420cf1dd8SToby Isaac        PetscReal jacobianInverses[dim*dim]
109520cf1dd8SToby Isaac        PetscReal jacobianDeterminants
109620cf1dd8SToby Isaac   FEM:
109720cf1dd8SToby Isaac      PetscFE
109820cf1dd8SToby Isaac        PetscQuadrature
109920cf1dd8SToby Isaac          PetscReal   quadPoints[Nq*dim]
110020cf1dd8SToby Isaac          PetscReal   quadWeights[Nq]
110120cf1dd8SToby Isaac        PetscReal   basis[Nq*Nb*Nc]
110220cf1dd8SToby Isaac        PetscReal   basisDer[Nq*Nb*Nc*dim]
110320cf1dd8SToby Isaac      PetscScalar coefficients[Ne*Nb*Nc]
110420cf1dd8SToby Isaac      PetscScalar elemVec[Ne*Nb*Nc]
110520cf1dd8SToby Isaac 
110620cf1dd8SToby Isaac   Problem:
110720cf1dd8SToby Isaac      PetscInt f: the active field
110820cf1dd8SToby Isaac      f0, f1
110920cf1dd8SToby Isaac 
111020cf1dd8SToby Isaac   Work Space:
111120cf1dd8SToby Isaac      PetscFE
111220cf1dd8SToby Isaac        PetscScalar f0[Nq*dim];
111320cf1dd8SToby Isaac        PetscScalar f1[Nq*dim*dim];
111420cf1dd8SToby Isaac        PetscScalar u[Nc];
111520cf1dd8SToby Isaac        PetscScalar gradU[Nc*dim];
111620cf1dd8SToby Isaac        PetscReal   x[dim];
111720cf1dd8SToby Isaac        PetscScalar realSpaceDer[dim];
111820cf1dd8SToby Isaac 
111920cf1dd8SToby Isaac Purpose: Compute element vector for N_cb batches of elements
112020cf1dd8SToby Isaac 
112120cf1dd8SToby Isaac Input:
112220cf1dd8SToby Isaac   Sizes:
112320cf1dd8SToby Isaac      N_cb: Number of serial cell batches
112420cf1dd8SToby Isaac 
112520cf1dd8SToby Isaac   Geometry:
112620cf1dd8SToby Isaac      PetscReal v0s[Ne*dim]
112720cf1dd8SToby Isaac      PetscReal jacobians[Ne*dim*dim]        possibly *Nq
112820cf1dd8SToby Isaac      PetscReal jacobianInverses[Ne*dim*dim] possibly *Nq
112920cf1dd8SToby Isaac      PetscReal jacobianDeterminants[Ne]     possibly *Nq
113020cf1dd8SToby Isaac   FEM:
113120cf1dd8SToby Isaac      static PetscReal   quadPoints[Nq*dim]
113220cf1dd8SToby Isaac      static PetscReal   quadWeights[Nq]
113320cf1dd8SToby Isaac      static PetscReal   basis[Nq*Nb*Nc]
113420cf1dd8SToby Isaac      static PetscReal   basisDer[Nq*Nb*Nc*dim]
113520cf1dd8SToby Isaac      PetscScalar coefficients[Ne*Nb*Nc]
113620cf1dd8SToby Isaac      PetscScalar elemVec[Ne*Nb*Nc]
113720cf1dd8SToby Isaac 
113820cf1dd8SToby Isaac ex62.c:
113920cf1dd8SToby Isaac   PetscErrorCode PetscFEIntegrateResidualBatch(PetscInt Ne, PetscInt numFields, PetscInt field, PetscQuadrature quad[], const PetscScalar coefficients[],
114020cf1dd8SToby Isaac                                                const PetscReal v0s[], const PetscReal jacobians[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[],
114120cf1dd8SToby Isaac                                                void (*f0_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]),
114220cf1dd8SToby Isaac                                                void (*f1_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]), PetscScalar elemVec[])
114320cf1dd8SToby Isaac 
114420cf1dd8SToby Isaac ex52.c:
114520cf1dd8SToby 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)
114620cf1dd8SToby 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)
114720cf1dd8SToby Isaac 
114820cf1dd8SToby Isaac ex52_integrateElement.cu
114920cf1dd8SToby Isaac __global__ void integrateElementQuadrature(int N_cb, realType *coefficients, realType *jacobianInverses, realType *jacobianDeterminants, realType *elemVec)
115020cf1dd8SToby Isaac 
115120cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt Nbl, const PetscScalar coefficients[],
115220cf1dd8SToby Isaac                                                      const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[],
115320cf1dd8SToby Isaac                                                      PetscLogEvent event, PetscInt debug, PetscInt pde_op)
115420cf1dd8SToby Isaac 
115520cf1dd8SToby Isaac ex52_integrateElementOpenCL.c:
115620cf1dd8SToby Isaac PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt N_bl, const PetscScalar coefficients[],
115720cf1dd8SToby Isaac                                                      const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[],
115820cf1dd8SToby Isaac                                                      PetscLogEvent event, PetscInt debug, PetscInt pde_op)
115920cf1dd8SToby Isaac 
116020cf1dd8SToby Isaac __kernel void integrateElementQuadrature(int N_cb, __global float *coefficients, __global float *jacobianInverses, __global float *jacobianDeterminants, __global float *elemVec)
116120cf1dd8SToby Isaac */
116220cf1dd8SToby Isaac 
116320cf1dd8SToby Isaac /*@C
116420cf1dd8SToby Isaac   PetscFEIntegrate - Produce the integral for the given field for a chunk of elements by quadrature integration
116520cf1dd8SToby Isaac 
116620cf1dd8SToby Isaac   Not collective
116720cf1dd8SToby Isaac 
116820cf1dd8SToby Isaac   Input Parameters:
116920cf1dd8SToby Isaac + fem          - The PetscFE object for the field being integrated
117020cf1dd8SToby Isaac . prob         - The PetscDS specifying the discretizations and continuum functions
117120cf1dd8SToby Isaac . field        - The field being integrated
117220cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
117320cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
117420cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
117520cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
117620cf1dd8SToby Isaac - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
117720cf1dd8SToby Isaac 
117820cf1dd8SToby Isaac   Output Parameter
117920cf1dd8SToby Isaac . integral     - the integral for this field
118020cf1dd8SToby Isaac 
118120cf1dd8SToby Isaac   Level: developer
118220cf1dd8SToby Isaac 
118320cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
118420cf1dd8SToby Isaac @*/
11854bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrate(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom,
118620cf1dd8SToby Isaac                                 const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
118720cf1dd8SToby Isaac {
11884bee2e38SMatthew G. Knepley   PetscFE        fe;
118920cf1dd8SToby Isaac   PetscErrorCode ierr;
119020cf1dd8SToby Isaac 
119120cf1dd8SToby Isaac   PetscFunctionBegin;
11924bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
11934bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
11944bee2e38SMatthew G. Knepley   if (fe->ops->integrate) {ierr = (*fe->ops->integrate)(prob, field, Ne, cgeom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);}
119520cf1dd8SToby Isaac   PetscFunctionReturn(0);
119620cf1dd8SToby Isaac }
119720cf1dd8SToby Isaac 
119820cf1dd8SToby Isaac /*@C
1199afe6d6adSToby Isaac   PetscFEIntegrateBd - Produce the integral for the given field for a chunk of elements by quadrature integration
1200afe6d6adSToby Isaac 
1201afe6d6adSToby Isaac   Not collective
1202afe6d6adSToby Isaac 
1203afe6d6adSToby Isaac   Input Parameters:
1204afe6d6adSToby Isaac + fem          - The PetscFE object for the field being integrated
1205afe6d6adSToby Isaac . prob         - The PetscDS specifying the discretizations and continuum functions
1206afe6d6adSToby Isaac . field        - The field being integrated
1207afe6d6adSToby Isaac . obj_func     - The function to be integrated
1208afe6d6adSToby Isaac . Ne           - The number of elements in the chunk
1209afe6d6adSToby Isaac . fgeom        - The face geometry for each face in the chunk
1210afe6d6adSToby Isaac . coefficients - The array of FEM basis coefficients for the elements
1211afe6d6adSToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
1212afe6d6adSToby Isaac - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1213afe6d6adSToby Isaac 
1214afe6d6adSToby Isaac   Output Parameter
1215afe6d6adSToby Isaac . integral     - the integral for this field
1216afe6d6adSToby Isaac 
1217afe6d6adSToby Isaac   Level: developer
1218afe6d6adSToby Isaac 
1219afe6d6adSToby Isaac .seealso: PetscFEIntegrateResidual()
1220afe6d6adSToby Isaac @*/
12214bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBd(PetscDS prob, PetscInt field,
1222afe6d6adSToby Isaac                                   void (*obj_func)(PetscInt, PetscInt, PetscInt,
1223afe6d6adSToby Isaac                                                    const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
1224afe6d6adSToby Isaac                                                    const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
1225afe6d6adSToby Isaac                                                    PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
1226afe6d6adSToby Isaac                                   PetscInt Ne, PetscFEGeom *geom, const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
1227afe6d6adSToby Isaac {
12284bee2e38SMatthew G. Knepley   PetscFE        fe;
1229afe6d6adSToby Isaac   PetscErrorCode ierr;
1230afe6d6adSToby Isaac 
1231afe6d6adSToby Isaac   PetscFunctionBegin;
12324bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
12334bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
12344bee2e38SMatthew G. Knepley   if (fe->ops->integratebd) {ierr = (*fe->ops->integratebd)(prob, field, obj_func, Ne, geom, coefficients, probAux, coefficientsAux, integral);CHKERRQ(ierr);}
1235afe6d6adSToby Isaac   PetscFunctionReturn(0);
1236afe6d6adSToby Isaac }
1237afe6d6adSToby Isaac 
1238afe6d6adSToby Isaac /*@C
123920cf1dd8SToby Isaac   PetscFEIntegrateResidual - Produce the element residual vector for a chunk of elements by quadrature integration
124020cf1dd8SToby Isaac 
124120cf1dd8SToby Isaac   Not collective
124220cf1dd8SToby Isaac 
124320cf1dd8SToby Isaac   Input Parameters:
124420cf1dd8SToby Isaac + fem          - The PetscFE object for the field being integrated
124520cf1dd8SToby Isaac . prob         - The PetscDS specifying the discretizations and continuum functions
124620cf1dd8SToby Isaac . field        - The field being integrated
124720cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
124820cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
124920cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
125020cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
125120cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
125220cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
125320cf1dd8SToby Isaac - t            - The time
125420cf1dd8SToby Isaac 
125520cf1dd8SToby Isaac   Output Parameter
125620cf1dd8SToby Isaac . elemVec      - the element residual vectors from each element
125720cf1dd8SToby Isaac 
125820cf1dd8SToby Isaac   Note:
125920cf1dd8SToby Isaac $ Loop over batch of elements (e):
126020cf1dd8SToby Isaac $   Loop over quadrature points (q):
126120cf1dd8SToby Isaac $     Make u_q and gradU_q (loops over fields,Nb,Ncomp) and x_q
126220cf1dd8SToby Isaac $     Call f_0 and f_1
126320cf1dd8SToby Isaac $   Loop over element vector entries (f,fc --> i):
126420cf1dd8SToby Isaac $     elemVec[i] += \psi^{fc}_f(q) f0_{fc}(u, \nabla u) + \nabla\psi^{fc}_f(q) \cdot f1_{fc,df}(u, \nabla u)
126520cf1dd8SToby Isaac 
126620cf1dd8SToby Isaac   Level: developer
126720cf1dd8SToby Isaac 
126820cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
126920cf1dd8SToby Isaac @*/
12704bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateResidual(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom,
127120cf1dd8SToby Isaac                                         const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
127220cf1dd8SToby Isaac {
12734bee2e38SMatthew G. Knepley   PetscFE        fe;
127420cf1dd8SToby Isaac   PetscErrorCode ierr;
127520cf1dd8SToby Isaac 
127620cf1dd8SToby Isaac   PetscFunctionBegin;
12774bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
12784bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
12794bee2e38SMatthew G. Knepley   if (fe->ops->integrateresidual) {ierr = (*fe->ops->integrateresidual)(prob, field, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
128020cf1dd8SToby Isaac   PetscFunctionReturn(0);
128120cf1dd8SToby Isaac }
128220cf1dd8SToby Isaac 
128320cf1dd8SToby Isaac /*@C
128420cf1dd8SToby Isaac   PetscFEIntegrateBdResidual - Produce the element residual vector for a chunk of elements by quadrature integration over a boundary
128520cf1dd8SToby Isaac 
128620cf1dd8SToby Isaac   Not collective
128720cf1dd8SToby Isaac 
128820cf1dd8SToby Isaac   Input Parameters:
128920cf1dd8SToby Isaac + fem          - The PetscFE object for the field being integrated
129020cf1dd8SToby Isaac . prob         - The PetscDS specifying the discretizations and continuum functions
129120cf1dd8SToby Isaac . field        - The field being integrated
129220cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
129320cf1dd8SToby Isaac . fgeom        - The face geometry for each cell in the chunk
129420cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements
129520cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
129620cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
129720cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
129820cf1dd8SToby Isaac - t            - The time
129920cf1dd8SToby Isaac 
130020cf1dd8SToby Isaac   Output Parameter
130120cf1dd8SToby Isaac . elemVec      - the element residual vectors from each element
130220cf1dd8SToby Isaac 
130320cf1dd8SToby Isaac   Level: developer
130420cf1dd8SToby Isaac 
130520cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
130620cf1dd8SToby Isaac @*/
13074bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBdResidual(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom,
130820cf1dd8SToby Isaac                                           const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
130920cf1dd8SToby Isaac {
13104bee2e38SMatthew G. Knepley   PetscFE        fe;
131120cf1dd8SToby Isaac   PetscErrorCode ierr;
131220cf1dd8SToby Isaac 
131320cf1dd8SToby Isaac   PetscFunctionBegin;
13144bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
13154bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
13164bee2e38SMatthew G. Knepley   if (fe->ops->integratebdresidual) {ierr = (*fe->ops->integratebdresidual)(prob, field, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);CHKERRQ(ierr);}
131720cf1dd8SToby Isaac   PetscFunctionReturn(0);
131820cf1dd8SToby Isaac }
131920cf1dd8SToby Isaac 
132020cf1dd8SToby Isaac /*@C
132120cf1dd8SToby Isaac   PetscFEIntegrateJacobian - Produce the element Jacobian for a chunk of elements by quadrature integration
132220cf1dd8SToby Isaac 
132320cf1dd8SToby Isaac   Not collective
132420cf1dd8SToby Isaac 
132520cf1dd8SToby Isaac   Input Parameters:
132620cf1dd8SToby Isaac + fem          - The PetscFE object for the field being integrated
132720cf1dd8SToby Isaac . prob         - The PetscDS specifying the discretizations and continuum functions
132820cf1dd8SToby Isaac . jtype        - The type of matrix pointwise functions that should be used
132920cf1dd8SToby Isaac . fieldI       - The test field being integrated
133020cf1dd8SToby Isaac . fieldJ       - The basis field being integrated
133120cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
133220cf1dd8SToby Isaac . cgeom        - The cell geometry for each cell in the chunk
133320cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
133420cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
133520cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
133620cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
133720cf1dd8SToby Isaac . t            - The time
133820cf1dd8SToby Isaac - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
133920cf1dd8SToby Isaac 
134020cf1dd8SToby Isaac   Output Parameter
134120cf1dd8SToby Isaac . elemMat      - the element matrices for the Jacobian from each element
134220cf1dd8SToby Isaac 
134320cf1dd8SToby Isaac   Note:
134420cf1dd8SToby Isaac $ Loop over batch of elements (e):
134520cf1dd8SToby Isaac $   Loop over element matrix entries (f,fc,g,gc --> i,j):
134620cf1dd8SToby Isaac $     Loop over quadrature points (q):
134720cf1dd8SToby Isaac $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
134820cf1dd8SToby Isaac $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
134920cf1dd8SToby Isaac $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
135020cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
135120cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
135220cf1dd8SToby Isaac   Level: developer
135320cf1dd8SToby Isaac 
135420cf1dd8SToby Isaac .seealso: PetscFEIntegrateResidual()
135520cf1dd8SToby Isaac @*/
13564bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateJacobian(PetscDS prob, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *cgeom,
135720cf1dd8SToby Isaac                                         const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
135820cf1dd8SToby Isaac {
13594bee2e38SMatthew G. Knepley   PetscFE        fe;
136020cf1dd8SToby Isaac   PetscErrorCode ierr;
136120cf1dd8SToby Isaac 
136220cf1dd8SToby Isaac   PetscFunctionBegin;
13634bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
13644bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
13654bee2e38SMatthew G. Knepley   if (fe->ops->integratejacobian) {ierr = (*fe->ops->integratejacobian)(prob, jtype, fieldI, fieldJ, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);CHKERRQ(ierr);}
136620cf1dd8SToby Isaac   PetscFunctionReturn(0);
136720cf1dd8SToby Isaac }
136820cf1dd8SToby Isaac 
136920cf1dd8SToby Isaac /*@C
137020cf1dd8SToby Isaac   PetscFEIntegrateBdJacobian - Produce the boundary element Jacobian for a chunk of elements by quadrature integration
137120cf1dd8SToby Isaac 
137220cf1dd8SToby Isaac   Not collective
137320cf1dd8SToby Isaac 
137420cf1dd8SToby Isaac   Input Parameters:
137520cf1dd8SToby Isaac . prob         - The PetscDS specifying the discretizations and continuum functions
137620cf1dd8SToby Isaac . fieldI       - The test field being integrated
137720cf1dd8SToby Isaac . fieldJ       - The basis field being integrated
137820cf1dd8SToby Isaac . Ne           - The number of elements in the chunk
137920cf1dd8SToby Isaac . fgeom        - The face geometry for each cell in the chunk
138020cf1dd8SToby Isaac . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
138120cf1dd8SToby Isaac . coefficients_t - The array of FEM basis time derivative coefficients for the elements
138220cf1dd8SToby Isaac . probAux      - The PetscDS specifying the auxiliary discretizations
138320cf1dd8SToby Isaac . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
138420cf1dd8SToby Isaac . t            - The time
138520cf1dd8SToby Isaac - u_tShift     - A multiplier for the dF/du_t term (as opposed to the dF/du term)
138620cf1dd8SToby Isaac 
138720cf1dd8SToby Isaac   Output Parameter
138820cf1dd8SToby Isaac . elemMat              - the element matrices for the Jacobian from each element
138920cf1dd8SToby Isaac 
139020cf1dd8SToby Isaac   Note:
139120cf1dd8SToby Isaac $ Loop over batch of elements (e):
139220cf1dd8SToby Isaac $   Loop over element matrix entries (f,fc,g,gc --> i,j):
139320cf1dd8SToby Isaac $     Loop over quadrature points (q):
139420cf1dd8SToby Isaac $       Make u_q and gradU_q (loops over fields,Nb,Ncomp)
139520cf1dd8SToby Isaac $         elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
139620cf1dd8SToby Isaac $                      + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
139720cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
139820cf1dd8SToby Isaac $                      + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
139920cf1dd8SToby Isaac   Level: developer
140020cf1dd8SToby Isaac 
140120cf1dd8SToby Isaac .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual()
140220cf1dd8SToby Isaac @*/
14034bee2e38SMatthew G. Knepley PetscErrorCode PetscFEIntegrateBdJacobian(PetscDS prob, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
140420cf1dd8SToby Isaac                                           const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
140520cf1dd8SToby Isaac {
14064bee2e38SMatthew G. Knepley   PetscFE        fe;
140720cf1dd8SToby Isaac   PetscErrorCode ierr;
140820cf1dd8SToby Isaac 
140920cf1dd8SToby Isaac   PetscFunctionBegin;
14104bee2e38SMatthew G. Knepley   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
14114bee2e38SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr);
14124bee2e38SMatthew 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);}
141320cf1dd8SToby Isaac   PetscFunctionReturn(0);
141420cf1dd8SToby Isaac }
141520cf1dd8SToby Isaac 
141620cf1dd8SToby Isaac PetscErrorCode PetscFEGetHeightSubspace(PetscFE fe, PetscInt height, PetscFE *subfe)
141720cf1dd8SToby Isaac {
141820cf1dd8SToby Isaac   PetscSpace      P, subP;
141920cf1dd8SToby Isaac   PetscDualSpace  Q, subQ;
142020cf1dd8SToby Isaac   PetscQuadrature subq;
142120cf1dd8SToby Isaac   PetscFEType     fetype;
142220cf1dd8SToby Isaac   PetscInt        dim, Nc;
142320cf1dd8SToby Isaac   PetscErrorCode  ierr;
142420cf1dd8SToby Isaac 
142520cf1dd8SToby Isaac   PetscFunctionBegin;
142620cf1dd8SToby Isaac   PetscValidHeaderSpecific(fe, PETSCFE_CLASSID, 1);
142720cf1dd8SToby Isaac   PetscValidPointer(subfe, 3);
142820cf1dd8SToby Isaac   if (height == 0) {
142920cf1dd8SToby Isaac     *subfe = fe;
143020cf1dd8SToby Isaac     PetscFunctionReturn(0);
143120cf1dd8SToby Isaac   }
143220cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
143320cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
143420cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr);
143520cf1dd8SToby Isaac   ierr = PetscFEGetFaceQuadrature(fe, &subq);CHKERRQ(ierr);
143620cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDimension(Q, &dim);CHKERRQ(ierr);
143720cf1dd8SToby Isaac   if (height > dim || height < 0) {SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Asked for space at height %D for dimension %D space", height, dim);}
143820cf1dd8SToby Isaac   if (!fe->subspaces) {ierr = PetscCalloc1(dim, &fe->subspaces);CHKERRQ(ierr);}
143920cf1dd8SToby Isaac   if (height <= dim) {
144020cf1dd8SToby Isaac     if (!fe->subspaces[height-1]) {
144120cf1dd8SToby Isaac       PetscFE     sub;
14423f6b16c7SMatthew G. Knepley       const char *name;
144320cf1dd8SToby Isaac 
144420cf1dd8SToby Isaac       ierr = PetscSpaceGetHeightSubspace(P, height, &subP);CHKERRQ(ierr);
144520cf1dd8SToby Isaac       ierr = PetscDualSpaceGetHeightSubspace(Q, height, &subQ);CHKERRQ(ierr);
144620cf1dd8SToby Isaac       ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), &sub);CHKERRQ(ierr);
14473f6b16c7SMatthew G. Knepley       ierr = PetscObjectGetName((PetscObject) fe,  &name);CHKERRQ(ierr);
14483f6b16c7SMatthew G. Knepley       ierr = PetscObjectSetName((PetscObject) sub,  name);CHKERRQ(ierr);
144920cf1dd8SToby Isaac       ierr = PetscFEGetType(fe, &fetype);CHKERRQ(ierr);
145020cf1dd8SToby Isaac       ierr = PetscFESetType(sub, fetype);CHKERRQ(ierr);
145120cf1dd8SToby Isaac       ierr = PetscFESetBasisSpace(sub, subP);CHKERRQ(ierr);
145220cf1dd8SToby Isaac       ierr = PetscFESetDualSpace(sub, subQ);CHKERRQ(ierr);
145320cf1dd8SToby Isaac       ierr = PetscFESetNumComponents(sub, Nc);CHKERRQ(ierr);
145420cf1dd8SToby Isaac       ierr = PetscFESetUp(sub);CHKERRQ(ierr);
145520cf1dd8SToby Isaac       ierr = PetscFESetQuadrature(sub, subq);CHKERRQ(ierr);
145620cf1dd8SToby Isaac       fe->subspaces[height-1] = sub;
145720cf1dd8SToby Isaac     }
145820cf1dd8SToby Isaac     *subfe = fe->subspaces[height-1];
145920cf1dd8SToby Isaac   } else {
146020cf1dd8SToby Isaac     *subfe = NULL;
146120cf1dd8SToby Isaac   }
146220cf1dd8SToby Isaac   PetscFunctionReturn(0);
146320cf1dd8SToby Isaac }
146420cf1dd8SToby Isaac 
146520cf1dd8SToby Isaac /*@
146620cf1dd8SToby Isaac   PetscFERefine - Create a "refined" PetscFE object that refines the reference cell into smaller copies. This is typically used
146720cf1dd8SToby Isaac   to precondition a higher order method with a lower order method on a refined mesh having the same number of dofs (but more
146820cf1dd8SToby Isaac   sparsity). It is also used to create an interpolation between regularly refined meshes.
146920cf1dd8SToby Isaac 
1470*d083f849SBarry Smith   Collective on fem
147120cf1dd8SToby Isaac 
147220cf1dd8SToby Isaac   Input Parameter:
147320cf1dd8SToby Isaac . fe - The initial PetscFE
147420cf1dd8SToby Isaac 
147520cf1dd8SToby Isaac   Output Parameter:
147620cf1dd8SToby Isaac . feRef - The refined PetscFE
147720cf1dd8SToby Isaac 
147820cf1dd8SToby Isaac   Level: developer
147920cf1dd8SToby Isaac 
148020cf1dd8SToby Isaac .seealso: PetscFEType, PetscFECreate(), PetscFESetType()
148120cf1dd8SToby Isaac @*/
148220cf1dd8SToby Isaac PetscErrorCode PetscFERefine(PetscFE fe, PetscFE *feRef)
148320cf1dd8SToby Isaac {
148420cf1dd8SToby Isaac   PetscSpace       P, Pref;
148520cf1dd8SToby Isaac   PetscDualSpace   Q, Qref;
148620cf1dd8SToby Isaac   DM               K, Kref;
148720cf1dd8SToby Isaac   PetscQuadrature  q, qref;
148820cf1dd8SToby Isaac   const PetscReal *v0, *jac;
148920cf1dd8SToby Isaac   PetscInt         numComp, numSubelements;
149020cf1dd8SToby Isaac   PetscErrorCode   ierr;
149120cf1dd8SToby Isaac 
149220cf1dd8SToby Isaac   PetscFunctionBegin;
149320cf1dd8SToby Isaac   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
149420cf1dd8SToby Isaac   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
149520cf1dd8SToby Isaac   ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr);
149620cf1dd8SToby Isaac   ierr = PetscDualSpaceGetDM(Q, &K);CHKERRQ(ierr);
149720cf1dd8SToby Isaac   /* Create space */
149820cf1dd8SToby Isaac   ierr = PetscObjectReference((PetscObject) P);CHKERRQ(ierr);
149920cf1dd8SToby Isaac   Pref = P;
150020cf1dd8SToby Isaac   /* Create dual space */
150120cf1dd8SToby Isaac   ierr = PetscDualSpaceDuplicate(Q, &Qref);CHKERRQ(ierr);
150220cf1dd8SToby Isaac   ierr = DMRefine(K, PetscObjectComm((PetscObject) fe), &Kref);CHKERRQ(ierr);
150320cf1dd8SToby Isaac   ierr = PetscDualSpaceSetDM(Qref, Kref);CHKERRQ(ierr);
150420cf1dd8SToby Isaac   ierr = DMDestroy(&Kref);CHKERRQ(ierr);
150520cf1dd8SToby Isaac   ierr = PetscDualSpaceSetUp(Qref);CHKERRQ(ierr);
150620cf1dd8SToby Isaac   /* Create element */
150720cf1dd8SToby Isaac   ierr = PetscFECreate(PetscObjectComm((PetscObject) fe), feRef);CHKERRQ(ierr);
150820cf1dd8SToby Isaac   ierr = PetscFESetType(*feRef, PETSCFECOMPOSITE);CHKERRQ(ierr);
150920cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*feRef, Pref);CHKERRQ(ierr);
151020cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*feRef, Qref);CHKERRQ(ierr);
151120cf1dd8SToby Isaac   ierr = PetscFEGetNumComponents(fe,    &numComp);CHKERRQ(ierr);
151220cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*feRef, numComp);CHKERRQ(ierr);
151320cf1dd8SToby Isaac   ierr = PetscFESetUp(*feRef);CHKERRQ(ierr);
151420cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&Pref);CHKERRQ(ierr);
151520cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&Qref);CHKERRQ(ierr);
151620cf1dd8SToby Isaac   /* Create quadrature */
151720cf1dd8SToby Isaac   ierr = PetscFECompositeGetMapping(*feRef, &numSubelements, &v0, &jac, NULL);CHKERRQ(ierr);
151820cf1dd8SToby Isaac   ierr = PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref);CHKERRQ(ierr);
151920cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*feRef, qref);CHKERRQ(ierr);
152020cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&qref);CHKERRQ(ierr);
152120cf1dd8SToby Isaac   PetscFunctionReturn(0);
152220cf1dd8SToby Isaac }
152320cf1dd8SToby Isaac 
152420cf1dd8SToby Isaac /*@C
152520cf1dd8SToby Isaac   PetscFECreateDefault - Create a PetscFE for basic FEM computation
152620cf1dd8SToby Isaac 
1527*d083f849SBarry Smith   Collective
152820cf1dd8SToby Isaac 
152920cf1dd8SToby Isaac   Input Parameters:
15307be5e748SToby Isaac + comm      - The MPI comm
153120cf1dd8SToby Isaac . dim       - The spatial dimension
153220cf1dd8SToby Isaac . Nc        - The number of components
153320cf1dd8SToby Isaac . isSimplex - Flag for simplex reference cell, otherwise its a tensor product
153420cf1dd8SToby Isaac . prefix    - The options prefix, or NULL
153520cf1dd8SToby Isaac - qorder    - The quadrature order
153620cf1dd8SToby Isaac 
153720cf1dd8SToby Isaac   Output Parameter:
153820cf1dd8SToby Isaac . fem - The PetscFE object
153920cf1dd8SToby Isaac 
154020cf1dd8SToby Isaac   Level: beginner
154120cf1dd8SToby Isaac 
154220cf1dd8SToby Isaac .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
154320cf1dd8SToby Isaac @*/
15447be5e748SToby Isaac PetscErrorCode PetscFECreateDefault(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, const char prefix[], PetscInt qorder, PetscFE *fem)
154520cf1dd8SToby Isaac {
154620cf1dd8SToby Isaac   PetscQuadrature q, fq;
154720cf1dd8SToby Isaac   DM              K;
154820cf1dd8SToby Isaac   PetscSpace      P;
154920cf1dd8SToby Isaac   PetscDualSpace  Q;
155020cf1dd8SToby Isaac   PetscInt        order, quadPointsPerEdge;
155120cf1dd8SToby Isaac   PetscBool       tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
155220cf1dd8SToby Isaac   PetscErrorCode  ierr;
155320cf1dd8SToby Isaac 
155420cf1dd8SToby Isaac   PetscFunctionBegin;
155520cf1dd8SToby Isaac   /* Create space */
15567be5e748SToby Isaac   ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr);
155720cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix);CHKERRQ(ierr);
155820cf1dd8SToby Isaac   ierr = PetscSpacePolynomialSetTensor(P, tensor);CHKERRQ(ierr);
155920cf1dd8SToby Isaac   ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr);
156020cf1dd8SToby Isaac   ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr);
1561028afddaSToby Isaac   ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr);
156220cf1dd8SToby Isaac   ierr = PetscSpaceSetUp(P);CHKERRQ(ierr);
156320cf1dd8SToby Isaac   ierr = PetscSpaceGetDegree(P, &order, NULL);CHKERRQ(ierr);
156420cf1dd8SToby Isaac   ierr = PetscSpacePolynomialGetTensor(P, &tensor);CHKERRQ(ierr);
156520cf1dd8SToby Isaac   /* Create dual space */
15667be5e748SToby Isaac   ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr);
156720cf1dd8SToby Isaac   ierr = PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE);CHKERRQ(ierr);
156820cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);CHKERRQ(ierr);
156920cf1dd8SToby Isaac   ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr);
157020cf1dd8SToby Isaac   ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr);
157120cf1dd8SToby Isaac   ierr = DMDestroy(&K);CHKERRQ(ierr);
157220cf1dd8SToby Isaac   ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr);
157320cf1dd8SToby Isaac   ierr = PetscDualSpaceSetOrder(Q, order);CHKERRQ(ierr);
157420cf1dd8SToby Isaac   ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor);CHKERRQ(ierr);
157520cf1dd8SToby Isaac   ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr);
157620cf1dd8SToby Isaac   ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr);
157720cf1dd8SToby Isaac   /* Create element */
15787be5e748SToby Isaac   ierr = PetscFECreate(comm, fem);CHKERRQ(ierr);
157920cf1dd8SToby Isaac   ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);CHKERRQ(ierr);
158020cf1dd8SToby Isaac   ierr = PetscFESetFromOptions(*fem);CHKERRQ(ierr);
158120cf1dd8SToby Isaac   ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr);
158220cf1dd8SToby Isaac   ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr);
158320cf1dd8SToby Isaac   ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr);
158420cf1dd8SToby Isaac   ierr = PetscFESetUp(*fem);CHKERRQ(ierr);
158520cf1dd8SToby Isaac   ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr);
158620cf1dd8SToby Isaac   ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr);
158720cf1dd8SToby Isaac   /* Create quadrature (with specified order if given) */
158820cf1dd8SToby Isaac   qorder = qorder >= 0 ? qorder : order;
158920cf1dd8SToby Isaac   ierr = PetscObjectOptionsBegin((PetscObject)*fem);CHKERRQ(ierr);
159020cf1dd8SToby Isaac   ierr = PetscOptionsInt("-petscfe_default_quadrature_order","Quadrature order is one less than quadture points per edge","PetscFECreateDefault",qorder,&qorder,NULL);CHKERRQ(ierr);
159120cf1dd8SToby Isaac   ierr = PetscOptionsEnd();CHKERRQ(ierr);
159220cf1dd8SToby Isaac   quadPointsPerEdge = PetscMax(qorder + 1,1);
159320cf1dd8SToby Isaac   if (isSimplex) {
159420cf1dd8SToby Isaac     ierr = PetscDTGaussJacobiQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
159520cf1dd8SToby Isaac     ierr = PetscDTGaussJacobiQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
15964ccfa306SStefano Zampini   } else {
159720cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);CHKERRQ(ierr);
159820cf1dd8SToby Isaac     ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);CHKERRQ(ierr);
159920cf1dd8SToby Isaac   }
160020cf1dd8SToby Isaac   ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr);
160120cf1dd8SToby Isaac   ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr);
160220cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr);
160320cf1dd8SToby Isaac   ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr);
160420cf1dd8SToby Isaac   PetscFunctionReturn(0);
160520cf1dd8SToby Isaac }
16063f6b16c7SMatthew G. Knepley 
16073f6b16c7SMatthew G. Knepley /*@C
16083f6b16c7SMatthew G. Knepley   PetscFESetName - Names the FE and its subobjects
16093f6b16c7SMatthew G. Knepley 
16103f6b16c7SMatthew G. Knepley   Not collective
16113f6b16c7SMatthew G. Knepley 
16123f6b16c7SMatthew G. Knepley   Input Parameters:
16133f6b16c7SMatthew G. Knepley + fe   - The PetscFE
16143f6b16c7SMatthew G. Knepley - name - The name
16153f6b16c7SMatthew G. Knepley 
16163f6b16c7SMatthew G. Knepley   Level: beginner
16173f6b16c7SMatthew G. Knepley 
16183f6b16c7SMatthew G. Knepley .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
16193f6b16c7SMatthew G. Knepley @*/
16203f6b16c7SMatthew G. Knepley PetscErrorCode PetscFESetName(PetscFE fe, const char name[])
16213f6b16c7SMatthew G. Knepley {
16223f6b16c7SMatthew G. Knepley   PetscSpace     P;
16233f6b16c7SMatthew G. Knepley   PetscDualSpace Q;
16243f6b16c7SMatthew G. Knepley   PetscErrorCode ierr;
16253f6b16c7SMatthew G. Knepley 
16263f6b16c7SMatthew G. Knepley   PetscFunctionBegin;
16273f6b16c7SMatthew G. Knepley   ierr = PetscFEGetBasisSpace(fe, &P);CHKERRQ(ierr);
16283f6b16c7SMatthew G. Knepley   ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr);
16293f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) fe, name);CHKERRQ(ierr);
16303f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) P,  name);CHKERRQ(ierr);
16313f6b16c7SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) Q,  name);CHKERRQ(ierr);
16323f6b16c7SMatthew G. Knepley   PetscFunctionReturn(0);
16333f6b16c7SMatthew G. Knepley }
1634a8f1f9e5SMatthew G. Knepley 
1635a8f1f9e5SMatthew G. Knepley PetscErrorCode PetscFEEvaluateFieldJets_Internal(PetscDS ds, PetscInt dim, PetscInt Nf, const PetscInt Nb[], const PetscInt Nc[], PetscInt q, PetscReal *basisField[], PetscReal *basisFieldDer[], PetscFEGeom *fegeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscScalar u[], PetscScalar u_x[], PetscScalar u_t[])
1636a8f1f9e5SMatthew G. Knepley {
1637a8f1f9e5SMatthew G. Knepley   PetscInt       dOffset = 0, fOffset = 0, f;
1638a8f1f9e5SMatthew G. Knepley   PetscErrorCode ierr;
1639a8f1f9e5SMatthew G. Knepley 
1640a8f1f9e5SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
1641a8f1f9e5SMatthew G. Knepley     PetscFE          fe;
1642a8f1f9e5SMatthew G. Knepley     const PetscInt   Nbf = Nb[f], Ncf = Nc[f];
1643a8f1f9e5SMatthew G. Knepley     const PetscReal *Bq = &basisField[f][q*Nbf*Ncf];
1644a8f1f9e5SMatthew G. Knepley     const PetscReal *Dq = &basisFieldDer[f][q*Nbf*Ncf*dim];
1645a8f1f9e5SMatthew G. Knepley     PetscInt         b, c, d;
1646a8f1f9e5SMatthew G. Knepley 
1647a8f1f9e5SMatthew G. Knepley     ierr = PetscDSGetDiscretization(ds, f, (PetscObject *) &fe);CHKERRQ(ierr);
1648a8f1f9e5SMatthew G. Knepley     for (c = 0; c < Ncf; ++c)     u[fOffset+c] = 0.0;
1649a8f1f9e5SMatthew G. Knepley     for (d = 0; d < dim*Ncf; ++d) u_x[fOffset*dim+d] = 0.0;
1650a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nbf; ++b) {
1651a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) {
1652a8f1f9e5SMatthew G. Knepley         const PetscInt cidx = b*Ncf+c;
1653a8f1f9e5SMatthew G. Knepley 
1654a8f1f9e5SMatthew G. Knepley         u[fOffset+c] += Bq[cidx]*coefficients[dOffset+b];
1655a8f1f9e5SMatthew G. Knepley         for (d = 0; d < dim; ++d) u_x[(fOffset+c)*dim+d] += Dq[cidx*dim+d]*coefficients[dOffset+b];
1656a8f1f9e5SMatthew G. Knepley       }
1657a8f1f9e5SMatthew G. Knepley     }
1658a8f1f9e5SMatthew G. Knepley     ierr = PetscFEPushforward(fe, fegeom, 1, &u[fOffset]);CHKERRQ(ierr);
1659a8f1f9e5SMatthew G. Knepley     ierr = PetscFEPushforwardGradient(fe, fegeom, 1, &u_x[fOffset*dim]);CHKERRQ(ierr);
1660a8f1f9e5SMatthew G. Knepley     if (u_t) {
1661a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Ncf; ++c) u_t[fOffset+c] = 0.0;
1662a8f1f9e5SMatthew G. Knepley       for (b = 0; b < Nbf; ++b) {
1663a8f1f9e5SMatthew G. Knepley         for (c = 0; c < Ncf; ++c) {
1664a8f1f9e5SMatthew G. Knepley           const PetscInt cidx = b*Ncf+c;
1665a8f1f9e5SMatthew G. Knepley 
1666a8f1f9e5SMatthew G. Knepley           u_t[fOffset+c] += Bq[cidx]*coefficients_t[dOffset+b];
1667a8f1f9e5SMatthew G. Knepley         }
1668a8f1f9e5SMatthew G. Knepley       }
1669a8f1f9e5SMatthew G. Knepley       ierr = PetscFEPushforward(fe, fegeom, 1, &u_t[fOffset]);CHKERRQ(ierr);
1670a8f1f9e5SMatthew G. Knepley     }
1671a8f1f9e5SMatthew G. Knepley     fOffset += Ncf;
1672a8f1f9e5SMatthew G. Knepley     dOffset += Nbf;
1673a8f1f9e5SMatthew G. Knepley   }
1674a8f1f9e5SMatthew G. Knepley   return 0;
1675a8f1f9e5SMatthew G. Knepley }
1676a8f1f9e5SMatthew G. Knepley 
1677a8f1f9e5SMatthew G. Knepley PetscErrorCode PetscFEEvaluateFaceFields_Internal(PetscDS prob, PetscInt field, PetscInt faceLoc, const PetscScalar coefficients[], PetscScalar u[])
1678a8f1f9e5SMatthew G. Knepley {
1679a8f1f9e5SMatthew G. Knepley   PetscFE        fe;
1680a8f1f9e5SMatthew G. Knepley   PetscReal     *faceBasis;
1681a8f1f9e5SMatthew G. Knepley   PetscInt       Nb, Nc, b, c;
1682a8f1f9e5SMatthew G. Knepley   PetscErrorCode ierr;
1683a8f1f9e5SMatthew G. Knepley 
1684a8f1f9e5SMatthew G. Knepley   if (!prob) return 0;
1685a8f1f9e5SMatthew G. Knepley   ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr);
1686a8f1f9e5SMatthew G. Knepley   ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
1687a8f1f9e5SMatthew G. Knepley   ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr);
1688a8f1f9e5SMatthew G. Knepley   ierr = PetscFEGetFaceCentroidTabulation(fe, &faceBasis);CHKERRQ(ierr);
1689a8f1f9e5SMatthew G. Knepley   for (c = 0; c < Nc; ++c) {u[c] = 0.0;}
1690a8f1f9e5SMatthew G. Knepley   for (b = 0; b < Nb; ++b) {
1691a8f1f9e5SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
1692a8f1f9e5SMatthew G. Knepley       const PetscInt cidx = b*Nc+c;
1693a8f1f9e5SMatthew G. Knepley 
1694a8f1f9e5SMatthew G. Knepley       u[c] += coefficients[cidx]*faceBasis[faceLoc*Nb*Nc+cidx];
1695a8f1f9e5SMatthew G. Knepley     }
1696a8f1f9e5SMatthew G. Knepley   }
1697a8f1f9e5SMatthew G. Knepley   return 0;
1698a8f1f9e5SMatthew G. Knepley }
1699a8f1f9e5SMatthew G. Knepley 
17006142fa51SMatthew G. Knepley PetscErrorCode PetscFEUpdateElementVec_Internal(PetscFE fe, PetscInt dim, PetscInt Nq, PetscInt Nb, PetscInt Nc, PetscReal basis[], PetscReal basisDer[], PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[])
1701a8f1f9e5SMatthew G. Knepley {
1702a8f1f9e5SMatthew G. Knepley   PetscInt       q, b, c, d;
1703a8f1f9e5SMatthew G. Knepley   PetscErrorCode ierr;
1704a8f1f9e5SMatthew G. Knepley 
1705a8f1f9e5SMatthew G. Knepley   for (b = 0; b < Nb; ++b) elemVec[b] = 0.0;
1706a8f1f9e5SMatthew G. Knepley   for (q = 0; q < Nq; ++q) {
1707a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
1708a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
1709a8f1f9e5SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
1710a8f1f9e5SMatthew G. Knepley 
1711a8f1f9e5SMatthew G. Knepley         tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx];
1712a8f1f9e5SMatthew G. Knepley         for (d = 0; d < dim; ++d) tmpBasisDer[bcidx*dim+d] = basisDer[q*Nb*Nc*dim+bcidx*dim+d];
1713a8f1f9e5SMatthew G. Knepley       }
1714a8f1f9e5SMatthew G. Knepley     }
1715a8f1f9e5SMatthew G. Knepley     ierr = PetscFEPushforward(fe, fegeom, Nb, tmpBasis);CHKERRQ(ierr);
1716a8f1f9e5SMatthew G. Knepley     ierr = PetscFEPushforwardGradient(fe, fegeom, Nb, tmpBasisDer);CHKERRQ(ierr);
1717a8f1f9e5SMatthew G. Knepley     for (b = 0; b < Nb; ++b) {
1718a8f1f9e5SMatthew G. Knepley       for (c = 0; c < Nc; ++c) {
1719a8f1f9e5SMatthew G. Knepley         const PetscInt bcidx = b*Nc+c;
1720a8f1f9e5SMatthew G. Knepley         const PetscInt qcidx = q*Nc+c;
1721a8f1f9e5SMatthew G. Knepley 
1722a8f1f9e5SMatthew G. Knepley         elemVec[b] += tmpBasis[bcidx]*f0[qcidx];
1723a8f1f9e5SMatthew G. Knepley         for (d = 0; d < dim; ++d) elemVec[b] += tmpBasisDer[bcidx*dim+d]*f1[qcidx*dim+d];
1724a8f1f9e5SMatthew G. Knepley       }
1725a8f1f9e5SMatthew G. Knepley     }
1726a8f1f9e5SMatthew G. Knepley   }
1727a8f1f9e5SMatthew G. Knepley   return(0);
1728a8f1f9e5SMatthew G. Knepley }
1729a8f1f9e5SMatthew G. Knepley 
17306142fa51SMatthew G. Knepley PetscErrorCode PetscFEUpdateElementMat_Internal(PetscFE feI, PetscFE feJ, PetscInt dim, PetscInt NbI, PetscInt NcI, const PetscReal basisI[], const PetscReal basisDerI[], PetscScalar tmpBasisI[], PetscScalar tmpBasisDerI[], PetscInt NbJ, PetscInt NcJ, const PetscReal basisJ[], const PetscReal basisDerJ[], 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[])
1731a8f1f9e5SMatthew G. Knepley {
1732a8f1f9e5SMatthew G. Knepley   PetscInt       f, fc, g, gc, df, dg;
1733a8f1f9e5SMatthew G. Knepley   PetscErrorCode ierr;
1734a8f1f9e5SMatthew G. Knepley 
1735a8f1f9e5SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
1736a8f1f9e5SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
1737a8f1f9e5SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
1738a8f1f9e5SMatthew G. Knepley 
1739a8f1f9e5SMatthew G. Knepley       tmpBasisI[fidx] = basisI[fidx];
1740a8f1f9e5SMatthew G. Knepley       for (df = 0; df < dim; ++df) tmpBasisDerI[fidx*dim+df] = basisDerI[fidx*dim+df];
1741a8f1f9e5SMatthew G. Knepley     }
1742a8f1f9e5SMatthew G. Knepley   }
1743a8f1f9e5SMatthew G. Knepley   ierr = PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);CHKERRQ(ierr);
1744a8f1f9e5SMatthew G. Knepley   ierr = PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);CHKERRQ(ierr);
1745a8f1f9e5SMatthew G. Knepley   for (g = 0; g < NbJ; ++g) {
1746a8f1f9e5SMatthew G. Knepley     for (gc = 0; gc < NcJ; ++gc) {
1747a8f1f9e5SMatthew G. Knepley       const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
1748a8f1f9e5SMatthew G. Knepley 
1749a8f1f9e5SMatthew G. Knepley       tmpBasisJ[gidx] = basisJ[gidx];
1750a8f1f9e5SMatthew G. Knepley       for (dg = 0; dg < dim; ++dg) tmpBasisDerJ[gidx*dim+dg] = basisDerJ[gidx*dim+dg];
1751a8f1f9e5SMatthew G. Knepley     }
1752a8f1f9e5SMatthew G. Knepley   }
1753a8f1f9e5SMatthew G. Knepley   ierr = PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);CHKERRQ(ierr);
1754a8f1f9e5SMatthew G. Knepley   ierr = PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);CHKERRQ(ierr);
1755a8f1f9e5SMatthew G. Knepley   for (f = 0; f < NbI; ++f) {
1756a8f1f9e5SMatthew G. Knepley     for (fc = 0; fc < NcI; ++fc) {
1757a8f1f9e5SMatthew G. Knepley       const PetscInt fidx = f*NcI+fc; /* Test function basis index */
1758a8f1f9e5SMatthew G. Knepley       const PetscInt i    = offsetI+f; /* Element matrix row */
1759a8f1f9e5SMatthew G. Knepley       for (g = 0; g < NbJ; ++g) {
1760a8f1f9e5SMatthew G. Knepley         for (gc = 0; gc < NcJ; ++gc) {
1761a8f1f9e5SMatthew G. Knepley           const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
1762a8f1f9e5SMatthew G. Knepley           const PetscInt j    = offsetJ+g; /* Element matrix column */
1763a8f1f9e5SMatthew G. Knepley           const PetscInt fOff = eOffset+i*totDim+j;
1764a8f1f9e5SMatthew G. Knepley 
1765a8f1f9e5SMatthew G. Knepley           elemMat[fOff] += tmpBasisI[fidx]*g0[fc*NcJ+gc]*tmpBasisJ[gidx];
1766a8f1f9e5SMatthew G. Knepley           for (df = 0; df < dim; ++df) {
1767a8f1f9e5SMatthew G. Knepley             elemMat[fOff] += tmpBasisI[fidx]*g1[(fc*NcJ+gc)*dim+df]*tmpBasisDerJ[gidx*dim+df];
1768a8f1f9e5SMatthew G. Knepley             elemMat[fOff] += tmpBasisDerI[fidx*dim+df]*g2[(fc*NcJ+gc)*dim+df]*tmpBasisJ[gidx];
1769a8f1f9e5SMatthew G. Knepley             for (dg = 0; dg < dim; ++dg) {
1770a8f1f9e5SMatthew G. Knepley               elemMat[fOff] += tmpBasisDerI[fidx*dim+df]*g3[((fc*NcJ+gc)*dim+df)*dim+dg]*tmpBasisDerJ[gidx*dim+dg];
1771a8f1f9e5SMatthew G. Knepley             }
1772a8f1f9e5SMatthew G. Knepley           }
1773a8f1f9e5SMatthew G. Knepley         }
1774a8f1f9e5SMatthew G. Knepley       }
1775a8f1f9e5SMatthew G. Knepley     }
1776a8f1f9e5SMatthew G. Knepley   }
1777a8f1f9e5SMatthew G. Knepley   return(0);
1778a8f1f9e5SMatthew G. Knepley }
1779