Actual source code: fe.c
petsc-3.15.0 2021-03-30
1: /* Basis Jet Tabulation
3: We would like to tabulate the nodal basis functions and derivatives at a set of points, usually quadrature points. We
4: follow here the derviation in http://www.math.ttu.edu/~kirby/papers/fiat-toms-2004.pdf. The nodal basis $\psi_i$ can
5: be expressed in terms of a prime basis $\phi_i$ which can be stably evaluated. In PETSc, we will use the Legendre basis
6: as a prime basis.
8: \psi_i = \sum_k \alpha_{ki} \phi_k
10: Our nodal basis is defined in terms of the dual basis $n_j$
12: n_j \cdot \psi_i = \delta_{ji}
14: and we may act on the first equation to obtain
16: n_j \cdot \psi_i = \sum_k \alpha_{ki} n_j \cdot \phi_k
17: \delta_{ji} = \sum_k \alpha_{ki} V_{jk}
18: I = V \alpha
20: so the coefficients of the nodal basis in the prime basis are
22: \alpha = V^{-1}
24: We will define the dual basis vectors $n_j$ using a quadrature rule.
26: Right now, we will just use the polynomial spaces P^k. I know some elements use the space of symmetric polynomials
27: (I think Nedelec), but we will neglect this for now. Constraints in the space, e.g. Arnold-Winther elements, can
28: be implemented exactly as in FIAT using functionals $L_j$.
30: I will have to count the degrees correctly for the Legendre product when we are on simplices.
32: We will have three objects:
33: - Space, P: this just need point evaluation I think
34: - 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
35: - FEM: This keeps {P, P', Q}
36: */
37: #include <petsc/private/petscfeimpl.h>
38: #include <petscdmplex.h>
40: PetscBool FEcite = PETSC_FALSE;
41: const char FECitation[] = "@article{kirby2004,\n"
42: " title = {Algorithm 839: FIAT, a New Paradigm for Computing Finite Element Basis Functions},\n"
43: " journal = {ACM Transactions on Mathematical Software},\n"
44: " author = {Robert C. Kirby},\n"
45: " volume = {30},\n"
46: " number = {4},\n"
47: " pages = {502--516},\n"
48: " doi = {10.1145/1039813.1039820},\n"
49: " year = {2004}\n}\n";
51: PetscClassId PETSCFE_CLASSID = 0;
53: PetscLogEvent PETSCFE_SetUp;
55: PetscFunctionList PetscFEList = NULL;
56: PetscBool PetscFERegisterAllCalled = PETSC_FALSE;
58: /*@C
59: PetscFERegister - Adds a new PetscFE implementation
61: Not Collective
63: Input Parameters:
64: + name - The name of a new user-defined creation routine
65: - create_func - The creation routine itself
67: Notes:
68: PetscFERegister() may be called multiple times to add several user-defined PetscFEs
70: Sample usage:
71: .vb
72: PetscFERegister("my_fe", MyPetscFECreate);
73: .ve
75: Then, your PetscFE type can be chosen with the procedural interface via
76: .vb
77: PetscFECreate(MPI_Comm, PetscFE *);
78: PetscFESetType(PetscFE, "my_fe");
79: .ve
80: or at runtime via the option
81: .vb
82: -petscfe_type my_fe
83: .ve
85: Level: advanced
87: .seealso: PetscFERegisterAll(), PetscFERegisterDestroy()
89: @*/
90: PetscErrorCode PetscFERegister(const char sname[], PetscErrorCode (*function)(PetscFE))
91: {
95: PetscFunctionListAdd(&PetscFEList, sname, function);
96: return(0);
97: }
99: /*@C
100: PetscFESetType - Builds a particular PetscFE
102: Collective on fem
104: Input Parameters:
105: + fem - The PetscFE object
106: - name - The kind of FEM space
108: Options Database Key:
109: . -petscfe_type <type> - Sets the PetscFE type; use -help for a list of available types
111: Level: intermediate
113: .seealso: PetscFEGetType(), PetscFECreate()
114: @*/
115: PetscErrorCode PetscFESetType(PetscFE fem, PetscFEType name)
116: {
117: PetscErrorCode (*r)(PetscFE);
118: PetscBool match;
123: PetscObjectTypeCompare((PetscObject) fem, name, &match);
124: if (match) return(0);
126: if (!PetscFERegisterAllCalled) {PetscFERegisterAll();}
127: PetscFunctionListFind(PetscFEList, name, &r);
128: if (!r) SETERRQ1(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscFE type: %s", name);
130: if (fem->ops->destroy) {
131: (*fem->ops->destroy)(fem);
132: fem->ops->destroy = NULL;
133: }
134: (*r)(fem);
135: PetscObjectChangeTypeName((PetscObject) fem, name);
136: return(0);
137: }
139: /*@C
140: PetscFEGetType - Gets the PetscFE type name (as a string) from the object.
142: Not Collective
144: Input Parameter:
145: . fem - The PetscFE
147: Output Parameter:
148: . name - The PetscFE type name
150: Level: intermediate
152: .seealso: PetscFESetType(), PetscFECreate()
153: @*/
154: PetscErrorCode PetscFEGetType(PetscFE fem, PetscFEType *name)
155: {
161: if (!PetscFERegisterAllCalled) {
162: PetscFERegisterAll();
163: }
164: *name = ((PetscObject) fem)->type_name;
165: return(0);
166: }
168: /*@C
169: PetscFEViewFromOptions - View from Options
171: Collective on PetscFE
173: Input Parameters:
174: + A - the PetscFE object
175: . obj - Optional object
176: - name - command line option
178: Level: intermediate
179: .seealso: PetscFE(), PetscFEView(), PetscObjectViewFromOptions(), PetscFECreate()
180: @*/
181: PetscErrorCode PetscFEViewFromOptions(PetscFE A,PetscObject obj,const char name[])
182: {
187: PetscObjectViewFromOptions((PetscObject)A,obj,name);
188: return(0);
189: }
191: /*@C
192: PetscFEView - Views a PetscFE
194: Collective on fem
196: Input Parameter:
197: + fem - the PetscFE object to view
198: - viewer - the viewer
200: Level: beginner
202: .seealso PetscFEDestroy()
203: @*/
204: PetscErrorCode PetscFEView(PetscFE fem, PetscViewer viewer)
205: {
206: PetscBool iascii;
212: if (!viewer) {PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) fem), &viewer);}
213: PetscObjectPrintClassNamePrefixType((PetscObject)fem, viewer);
214: PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);
215: if (fem->ops->view) {(*fem->ops->view)(fem, viewer);}
216: return(0);
217: }
219: /*@
220: PetscFESetFromOptions - sets parameters in a PetscFE from the options database
222: Collective on fem
224: Input Parameter:
225: . fem - the PetscFE object to set options for
227: Options Database:
228: + -petscfe_num_blocks - the number of cell blocks to integrate concurrently
229: - -petscfe_num_batches - the number of cell batches to integrate serially
231: Level: intermediate
233: .seealso PetscFEView()
234: @*/
235: PetscErrorCode PetscFESetFromOptions(PetscFE fem)
236: {
237: const char *defaultType;
238: char name[256];
239: PetscBool flg;
244: if (!((PetscObject) fem)->type_name) {
245: defaultType = PETSCFEBASIC;
246: } else {
247: defaultType = ((PetscObject) fem)->type_name;
248: }
249: if (!PetscFERegisterAllCalled) {PetscFERegisterAll();}
251: PetscObjectOptionsBegin((PetscObject) fem);
252: PetscOptionsFList("-petscfe_type", "Finite element space", "PetscFESetType", PetscFEList, defaultType, name, 256, &flg);
253: if (flg) {
254: PetscFESetType(fem, name);
255: } else if (!((PetscObject) fem)->type_name) {
256: PetscFESetType(fem, defaultType);
257: }
258: PetscOptionsBoundedInt("-petscfe_num_blocks", "The number of cell blocks to integrate concurrently", "PetscSpaceSetTileSizes", fem->numBlocks, &fem->numBlocks, NULL,1);
259: PetscOptionsBoundedInt("-petscfe_num_batches", "The number of cell batches to integrate serially", "PetscSpaceSetTileSizes", fem->numBatches, &fem->numBatches, NULL,1);
260: if (fem->ops->setfromoptions) {
261: (*fem->ops->setfromoptions)(PetscOptionsObject,fem);
262: }
263: /* process any options handlers added with PetscObjectAddOptionsHandler() */
264: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) fem);
265: PetscOptionsEnd();
266: PetscFEViewFromOptions(fem, NULL, "-petscfe_view");
267: return(0);
268: }
270: /*@C
271: PetscFESetUp - Construct data structures for the PetscFE
273: Collective on fem
275: Input Parameter:
276: . fem - the PetscFE object to setup
278: Level: intermediate
280: .seealso PetscFEView(), PetscFEDestroy()
281: @*/
282: PetscErrorCode PetscFESetUp(PetscFE fem)
283: {
288: if (fem->setupcalled) return(0);
289: PetscLogEventBegin(PETSCFE_SetUp, fem, 0, 0, 0);
290: fem->setupcalled = PETSC_TRUE;
291: if (fem->ops->setup) {(*fem->ops->setup)(fem);}
292: PetscLogEventEnd(PETSCFE_SetUp, fem, 0, 0, 0);
293: return(0);
294: }
296: /*@
297: PetscFEDestroy - Destroys a PetscFE object
299: Collective on fem
301: Input Parameter:
302: . fem - the PetscFE object to destroy
304: Level: beginner
306: .seealso PetscFEView()
307: @*/
308: PetscErrorCode PetscFEDestroy(PetscFE *fem)
309: {
313: if (!*fem) return(0);
316: if (--((PetscObject)(*fem))->refct > 0) {*fem = NULL; return(0);}
317: ((PetscObject) (*fem))->refct = 0;
319: if ((*fem)->subspaces) {
320: PetscInt dim, d;
322: PetscDualSpaceGetDimension((*fem)->dualSpace, &dim);
323: for (d = 0; d < dim; ++d) {PetscFEDestroy(&(*fem)->subspaces[d]);}
324: }
325: PetscFree((*fem)->subspaces);
326: PetscFree((*fem)->invV);
327: PetscTabulationDestroy(&(*fem)->T);
328: PetscTabulationDestroy(&(*fem)->Tf);
329: PetscTabulationDestroy(&(*fem)->Tc);
330: PetscSpaceDestroy(&(*fem)->basisSpace);
331: PetscDualSpaceDestroy(&(*fem)->dualSpace);
332: PetscQuadratureDestroy(&(*fem)->quadrature);
333: PetscQuadratureDestroy(&(*fem)->faceQuadrature);
335: if ((*fem)->ops->destroy) {(*(*fem)->ops->destroy)(*fem);}
336: PetscHeaderDestroy(fem);
337: return(0);
338: }
340: /*@
341: PetscFECreate - Creates an empty PetscFE object. The type can then be set with PetscFESetType().
343: Collective
345: Input Parameter:
346: . comm - The communicator for the PetscFE object
348: Output Parameter:
349: . fem - The PetscFE object
351: Level: beginner
353: .seealso: PetscFESetType(), PETSCFEGALERKIN
354: @*/
355: PetscErrorCode PetscFECreate(MPI_Comm comm, PetscFE *fem)
356: {
357: PetscFE f;
362: PetscCitationsRegister(FECitation,&FEcite);
363: *fem = NULL;
364: PetscFEInitializePackage();
366: PetscHeaderCreate(f, PETSCFE_CLASSID, "PetscFE", "Finite Element", "PetscFE", comm, PetscFEDestroy, PetscFEView);
368: f->basisSpace = NULL;
369: f->dualSpace = NULL;
370: f->numComponents = 1;
371: f->subspaces = NULL;
372: f->invV = NULL;
373: f->T = NULL;
374: f->Tf = NULL;
375: f->Tc = NULL;
376: PetscArrayzero(&f->quadrature, 1);
377: PetscArrayzero(&f->faceQuadrature, 1);
378: f->blockSize = 0;
379: f->numBlocks = 1;
380: f->batchSize = 0;
381: f->numBatches = 1;
383: *fem = f;
384: return(0);
385: }
387: /*@
388: PetscFEGetSpatialDimension - Returns the spatial dimension of the element
390: Not collective
392: Input Parameter:
393: . fem - The PetscFE object
395: Output Parameter:
396: . dim - The spatial dimension
398: Level: intermediate
400: .seealso: PetscFECreate()
401: @*/
402: PetscErrorCode PetscFEGetSpatialDimension(PetscFE fem, PetscInt *dim)
403: {
404: DM dm;
410: PetscDualSpaceGetDM(fem->dualSpace, &dm);
411: DMGetDimension(dm, dim);
412: return(0);
413: }
415: /*@
416: PetscFESetNumComponents - Sets the number of components in the element
418: Not collective
420: Input Parameters:
421: + fem - The PetscFE object
422: - comp - The number of field components
424: Level: intermediate
426: .seealso: PetscFECreate()
427: @*/
428: PetscErrorCode PetscFESetNumComponents(PetscFE fem, PetscInt comp)
429: {
432: fem->numComponents = comp;
433: return(0);
434: }
436: /*@
437: PetscFEGetNumComponents - Returns the number of components in the element
439: Not collective
441: Input Parameter:
442: . fem - The PetscFE object
444: Output Parameter:
445: . comp - The number of field components
447: Level: intermediate
449: .seealso: PetscFECreate()
450: @*/
451: PetscErrorCode PetscFEGetNumComponents(PetscFE fem, PetscInt *comp)
452: {
456: *comp = fem->numComponents;
457: return(0);
458: }
460: /*@
461: PetscFESetTileSizes - Sets the tile sizes for evaluation
463: Not collective
465: Input Parameters:
466: + fem - The PetscFE object
467: . blockSize - The number of elements in a block
468: . numBlocks - The number of blocks in a batch
469: . batchSize - The number of elements in a batch
470: - numBatches - The number of batches in a chunk
472: Level: intermediate
474: .seealso: PetscFECreate()
475: @*/
476: PetscErrorCode PetscFESetTileSizes(PetscFE fem, PetscInt blockSize, PetscInt numBlocks, PetscInt batchSize, PetscInt numBatches)
477: {
480: fem->blockSize = blockSize;
481: fem->numBlocks = numBlocks;
482: fem->batchSize = batchSize;
483: fem->numBatches = numBatches;
484: return(0);
485: }
487: /*@
488: PetscFEGetTileSizes - Returns the tile sizes for evaluation
490: Not collective
492: Input Parameter:
493: . fem - The PetscFE object
495: Output Parameters:
496: + blockSize - The number of elements in a block
497: . numBlocks - The number of blocks in a batch
498: . batchSize - The number of elements in a batch
499: - numBatches - The number of batches in a chunk
501: Level: intermediate
503: .seealso: PetscFECreate()
504: @*/
505: PetscErrorCode PetscFEGetTileSizes(PetscFE fem, PetscInt *blockSize, PetscInt *numBlocks, PetscInt *batchSize, PetscInt *numBatches)
506: {
513: if (blockSize) *blockSize = fem->blockSize;
514: if (numBlocks) *numBlocks = fem->numBlocks;
515: if (batchSize) *batchSize = fem->batchSize;
516: if (numBatches) *numBatches = fem->numBatches;
517: return(0);
518: }
520: /*@
521: PetscFEGetBasisSpace - Returns the PetscSpace used for approximation of the solution
523: Not collective
525: Input Parameter:
526: . fem - The PetscFE object
528: Output Parameter:
529: . sp - The PetscSpace object
531: Level: intermediate
533: .seealso: PetscFECreate()
534: @*/
535: PetscErrorCode PetscFEGetBasisSpace(PetscFE fem, PetscSpace *sp)
536: {
540: *sp = fem->basisSpace;
541: return(0);
542: }
544: /*@
545: PetscFESetBasisSpace - Sets the PetscSpace used for approximation of the solution
547: Not collective
549: Input Parameters:
550: + fem - The PetscFE object
551: - sp - The PetscSpace object
553: Level: intermediate
555: .seealso: PetscFECreate()
556: @*/
557: PetscErrorCode PetscFESetBasisSpace(PetscFE fem, PetscSpace sp)
558: {
564: PetscSpaceDestroy(&fem->basisSpace);
565: fem->basisSpace = sp;
566: PetscObjectReference((PetscObject) fem->basisSpace);
567: return(0);
568: }
570: /*@
571: PetscFEGetDualSpace - Returns the PetscDualSpace used to define the inner product
573: Not collective
575: Input Parameter:
576: . fem - The PetscFE object
578: Output Parameter:
579: . sp - The PetscDualSpace object
581: Level: intermediate
583: .seealso: PetscFECreate()
584: @*/
585: PetscErrorCode PetscFEGetDualSpace(PetscFE fem, PetscDualSpace *sp)
586: {
590: *sp = fem->dualSpace;
591: return(0);
592: }
594: /*@
595: PetscFESetDualSpace - Sets the PetscDualSpace used to define the inner product
597: Not collective
599: Input Parameters:
600: + fem - The PetscFE object
601: - sp - The PetscDualSpace object
603: Level: intermediate
605: .seealso: PetscFECreate()
606: @*/
607: PetscErrorCode PetscFESetDualSpace(PetscFE fem, PetscDualSpace sp)
608: {
614: PetscDualSpaceDestroy(&fem->dualSpace);
615: fem->dualSpace = sp;
616: PetscObjectReference((PetscObject) fem->dualSpace);
617: return(0);
618: }
620: /*@
621: PetscFEGetQuadrature - Returns the PetscQuadrature used to calculate inner products
623: Not collective
625: Input Parameter:
626: . fem - The PetscFE object
628: Output Parameter:
629: . q - The PetscQuadrature object
631: Level: intermediate
633: .seealso: PetscFECreate()
634: @*/
635: PetscErrorCode PetscFEGetQuadrature(PetscFE fem, PetscQuadrature *q)
636: {
640: *q = fem->quadrature;
641: return(0);
642: }
644: /*@
645: PetscFESetQuadrature - Sets the PetscQuadrature used to calculate inner products
647: Not collective
649: Input Parameters:
650: + fem - The PetscFE object
651: - q - The PetscQuadrature object
653: Level: intermediate
655: .seealso: PetscFECreate()
656: @*/
657: PetscErrorCode PetscFESetQuadrature(PetscFE fem, PetscQuadrature q)
658: {
659: PetscInt Nc, qNc;
664: if (q == fem->quadrature) return(0);
665: PetscFEGetNumComponents(fem, &Nc);
666: PetscQuadratureGetNumComponents(q, &qNc);
667: 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);
668: PetscTabulationDestroy(&fem->T);
669: PetscTabulationDestroy(&fem->Tc);
670: PetscObjectReference((PetscObject) q);
671: PetscQuadratureDestroy(&fem->quadrature);
672: fem->quadrature = q;
673: return(0);
674: }
676: /*@
677: PetscFEGetFaceQuadrature - Returns the PetscQuadrature used to calculate inner products on faces
679: Not collective
681: Input Parameter:
682: . fem - The PetscFE object
684: Output Parameter:
685: . q - The PetscQuadrature object
687: Level: intermediate
689: .seealso: PetscFECreate()
690: @*/
691: PetscErrorCode PetscFEGetFaceQuadrature(PetscFE fem, PetscQuadrature *q)
692: {
696: *q = fem->faceQuadrature;
697: return(0);
698: }
700: /*@
701: PetscFESetFaceQuadrature - Sets the PetscQuadrature used to calculate inner products on faces
703: Not collective
705: Input Parameters:
706: + fem - The PetscFE object
707: - q - The PetscQuadrature object
709: Level: intermediate
711: .seealso: PetscFECreate()
712: @*/
713: PetscErrorCode PetscFESetFaceQuadrature(PetscFE fem, PetscQuadrature q)
714: {
715: PetscInt Nc, qNc;
720: PetscFEGetNumComponents(fem, &Nc);
721: PetscQuadratureGetNumComponents(q, &qNc);
722: 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);
723: PetscTabulationDestroy(&fem->Tf);
724: PetscQuadratureDestroy(&fem->faceQuadrature);
725: fem->faceQuadrature = q;
726: PetscObjectReference((PetscObject) q);
727: return(0);
728: }
730: /*@
731: PetscFECopyQuadrature - Copy both volumetric and surface quadrature
733: Not collective
735: Input Parameters:
736: + sfe - The PetscFE source for the quadratures
737: - tfe - The PetscFE target for the quadratures
739: Level: intermediate
741: .seealso: PetscFECreate(), PetscFESetQuadrature(), PetscFESetFaceQuadrature()
742: @*/
743: PetscErrorCode PetscFECopyQuadrature(PetscFE sfe, PetscFE tfe)
744: {
745: PetscQuadrature q;
746: PetscErrorCode ierr;
751: PetscFEGetQuadrature(sfe, &q);
752: PetscFESetQuadrature(tfe, q);
753: PetscFEGetFaceQuadrature(sfe, &q);
754: PetscFESetFaceQuadrature(tfe, q);
755: return(0);
756: }
758: /*@C
759: PetscFEGetNumDof - Returns the number of dofs (dual basis vectors) associated to mesh points on the reference cell of a given dimension
761: Not collective
763: Input Parameter:
764: . fem - The PetscFE object
766: Output Parameter:
767: . numDof - Array with the number of dofs per dimension
769: Level: intermediate
771: .seealso: PetscFECreate()
772: @*/
773: PetscErrorCode PetscFEGetNumDof(PetscFE fem, const PetscInt **numDof)
774: {
780: PetscDualSpaceGetNumDof(fem->dualSpace, numDof);
781: return(0);
782: }
784: /*@C
785: PetscFEGetCellTabulation - Returns the tabulation of the basis functions at the quadrature points on the reference cell
787: Not collective
789: Input Parameter:
790: + fem - The PetscFE object
791: - k - The highest derivative we need to tabulate, very often 1
793: Output Parameter:
794: . T - The basis function values and derivatives at quadrature points
796: Note:
797: $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
798: $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d
799: $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e
801: Level: intermediate
803: .seealso: PetscFECreateTabulation(), PetscTabulationDestroy()
804: @*/
805: PetscErrorCode PetscFEGetCellTabulation(PetscFE fem, PetscInt k, PetscTabulation *T)
806: {
807: PetscInt npoints;
808: const PetscReal *points;
809: PetscErrorCode ierr;
814: PetscQuadratureGetData(fem->quadrature, NULL, NULL, &npoints, &points, NULL);
815: if (!fem->T) {PetscFECreateTabulation(fem, 1, npoints, points, k, &fem->T);}
816: if (fem->T && k > fem->T->K) SETERRQ2(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_OUTOFRANGE, "Requested %D derivatives, but only tabulated %D", k, fem->T->K);
817: *T = fem->T;
818: return(0);
819: }
821: /*@C
822: PetscFEGetFaceTabulation - Returns the tabulation of the basis functions at the face quadrature points for each face of the reference cell
824: Not collective
826: Input Parameter:
827: + fem - The PetscFE object
828: - k - The highest derivative we need to tabulate, very often 1
830: Output Parameters:
831: . Tf - The basis function values and derviatives at face quadrature points
833: Note:
834: $ T->T[0] = Bf[((f*Nq + q)*pdim + i)*Nc + c] is the value at point f,q for basis function i and component c
835: $ T->T[1] = Df[(((f*Nq + q)*pdim + i)*Nc + c)*dim + d] is the derivative value at point f,q for basis function i, component c, in direction d
836: $ T->T[2] = Hf[((((f*Nq + q)*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point f,q for basis function i, component c, in directions d and e
838: Level: intermediate
840: .seealso: PetscFEGetCellTabulation(), PetscFECreateTabulation(), PetscTabulationDestroy()
841: @*/
842: PetscErrorCode PetscFEGetFaceTabulation(PetscFE fem, PetscInt k, PetscTabulation *Tf)
843: {
844: PetscErrorCode ierr;
849: if (!fem->Tf) {
850: const PetscReal xi0[3] = {-1., -1., -1.};
851: PetscReal v0[3], J[9], detJ;
852: PetscQuadrature fq;
853: PetscDualSpace sp;
854: DM dm;
855: const PetscInt *faces;
856: PetscInt dim, numFaces, f, npoints, q;
857: const PetscReal *points;
858: PetscReal *facePoints;
860: PetscFEGetDualSpace(fem, &sp);
861: PetscDualSpaceGetDM(sp, &dm);
862: DMGetDimension(dm, &dim);
863: DMPlexGetConeSize(dm, 0, &numFaces);
864: DMPlexGetCone(dm, 0, &faces);
865: PetscFEGetFaceQuadrature(fem, &fq);
866: if (fq) {
867: PetscQuadratureGetData(fq, NULL, NULL, &npoints, &points, NULL);
868: PetscMalloc1(numFaces*npoints*dim, &facePoints);
869: for (f = 0; f < numFaces; ++f) {
870: DMPlexComputeCellGeometryFEM(dm, faces[f], NULL, v0, J, NULL, &detJ);
871: for (q = 0; q < npoints; ++q) CoordinatesRefToReal(dim, dim-1, xi0, v0, J, &points[q*(dim-1)], &facePoints[(f*npoints+q)*dim]);
872: }
873: PetscFECreateTabulation(fem, numFaces, npoints, facePoints, k, &fem->Tf);
874: PetscFree(facePoints);
875: }
876: }
877: if (fem->Tf && k > fem->Tf->K) SETERRQ2(PetscObjectComm((PetscObject) fem), PETSC_ERR_ARG_OUTOFRANGE, "Requested %D derivatives, but only tabulated %D", k, fem->Tf->K);
878: *Tf = fem->Tf;
879: return(0);
880: }
882: /*@C
883: PetscFEGetFaceCentroidTabulation - Returns the tabulation of the basis functions at the face centroid points
885: Not collective
887: Input Parameter:
888: . fem - The PetscFE object
890: Output Parameters:
891: . Tc - The basis function values at face centroid points
893: Note:
894: $ T->T[0] = Bf[(f*pdim + i)*Nc + c] is the value at point f for basis function i and component c
896: Level: intermediate
898: .seealso: PetscFEGetFaceTabulation(), PetscFEGetCellTabulation(), PetscFECreateTabulation(), PetscTabulationDestroy()
899: @*/
900: PetscErrorCode PetscFEGetFaceCentroidTabulation(PetscFE fem, PetscTabulation *Tc)
901: {
902: PetscErrorCode ierr;
907: if (!fem->Tc) {
908: PetscDualSpace sp;
909: DM dm;
910: const PetscInt *cone;
911: PetscReal *centroids;
912: PetscInt dim, numFaces, f;
914: PetscFEGetDualSpace(fem, &sp);
915: PetscDualSpaceGetDM(sp, &dm);
916: DMGetDimension(dm, &dim);
917: DMPlexGetConeSize(dm, 0, &numFaces);
918: DMPlexGetCone(dm, 0, &cone);
919: PetscMalloc1(numFaces*dim, ¢roids);
920: for (f = 0; f < numFaces; ++f) {DMPlexComputeCellGeometryFVM(dm, cone[f], NULL, ¢roids[f*dim], NULL);}
921: PetscFECreateTabulation(fem, 1, numFaces, centroids, 0, &fem->Tc);
922: PetscFree(centroids);
923: }
924: *Tc = fem->Tc;
925: return(0);
926: }
928: /*@C
929: PetscFECreateTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
931: Not collective
933: Input Parameters:
934: + fem - The PetscFE object
935: . nrepl - The number of replicas
936: . npoints - The number of tabulation points in a replica
937: . points - The tabulation point coordinates
938: - K - The number of derivatives calculated
940: Output Parameter:
941: . T - The basis function values and derivatives at tabulation points
943: Note:
944: $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
945: $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d
946: $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e
948: Level: intermediate
950: .seealso: PetscFEGetCellTabulation(), PetscTabulationDestroy()
951: @*/
952: PetscErrorCode PetscFECreateTabulation(PetscFE fem, PetscInt nrepl, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation *T)
953: {
954: DM dm;
955: PetscDualSpace Q;
956: PetscInt Nb; /* Dimension of FE space P */
957: PetscInt Nc; /* Field components */
958: PetscInt cdim; /* Reference coordinate dimension */
959: PetscInt k;
960: PetscErrorCode ierr;
963: if (!npoints || !fem->dualSpace || K < 0) {
964: *T = NULL;
965: return(0);
966: }
970: PetscFEGetDualSpace(fem, &Q);
971: PetscDualSpaceGetDM(Q, &dm);
972: DMGetDimension(dm, &cdim);
973: PetscDualSpaceGetDimension(Q, &Nb);
974: PetscFEGetNumComponents(fem, &Nc);
975: PetscMalloc1(1, T);
976: (*T)->K = !cdim ? 0 : K;
977: (*T)->Nr = nrepl;
978: (*T)->Np = npoints;
979: (*T)->Nb = Nb;
980: (*T)->Nc = Nc;
981: (*T)->cdim = cdim;
982: PetscMalloc1((*T)->K+1, &(*T)->T);
983: for (k = 0; k <= (*T)->K; ++k) {
984: PetscMalloc1(nrepl*npoints*Nb*Nc*PetscPowInt(cdim, k), &(*T)->T[k]);
985: }
986: (*fem->ops->createtabulation)(fem, nrepl*npoints, points, K, *T);
987: return(0);
988: }
990: /*@C
991: PetscFEComputeTabulation - Tabulates the basis functions, and perhaps derivatives, at the points provided.
993: Not collective
995: Input Parameters:
996: + fem - The PetscFE object
997: . npoints - The number of tabulation points
998: . points - The tabulation point coordinates
999: . K - The number of derivatives calculated
1000: - T - An existing tabulation object with enough allocated space
1002: Output Parameter:
1003: . T - The basis function values and derivatives at tabulation points
1005: Note:
1006: $ T->T[0] = B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c
1007: $ T->T[1] = D[((p*pdim + i)*Nc + c)*dim + d] is the derivative value at point p for basis function i, component c, in direction d
1008: $ T->T[2] = H[(((p*pdim + i)*Nc + c)*dim + d)*dim + e] is the value at point p for basis function i, component c, in directions d and e
1010: Level: intermediate
1012: .seealso: PetscFEGetCellTabulation(), PetscTabulationDestroy()
1013: @*/
1014: PetscErrorCode PetscFEComputeTabulation(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscInt K, PetscTabulation T)
1015: {
1019: if (!npoints || !fem->dualSpace || K < 0) return(0);
1023: if (PetscDefined(USE_DEBUG)) {
1024: DM dm;
1025: PetscDualSpace Q;
1026: PetscInt Nb; /* Dimension of FE space P */
1027: PetscInt Nc; /* Field components */
1028: PetscInt cdim; /* Reference coordinate dimension */
1030: PetscFEGetDualSpace(fem, &Q);
1031: PetscDualSpaceGetDM(Q, &dm);
1032: DMGetDimension(dm, &cdim);
1033: PetscDualSpaceGetDimension(Q, &Nb);
1034: PetscFEGetNumComponents(fem, &Nc);
1035: if (T->K != (!cdim ? 0 : K)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation K %D must match requested K %D", T->K, !cdim ? 0 : K);
1036: if (T->Nb != Nb) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation Nb %D must match requested Nb %D", T->Nb, Nb);
1037: if (T->Nc != Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation Nc %D must match requested Nc %D", T->Nc, Nc);
1038: if (T->cdim != cdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Tabulation cdim %D must match requested cdim %D", T->cdim, cdim);
1039: }
1040: T->Nr = 1;
1041: T->Np = npoints;
1042: (*fem->ops->createtabulation)(fem, npoints, points, K, T);
1043: return(0);
1044: }
1046: /*@C
1047: PetscTabulationDestroy - Frees memory from the associated tabulation.
1049: Not collective
1051: Input Parameter:
1052: . T - The tabulation
1054: Level: intermediate
1056: .seealso: PetscFECreateTabulation(), PetscFEGetCellTabulation()
1057: @*/
1058: PetscErrorCode PetscTabulationDestroy(PetscTabulation *T)
1059: {
1060: PetscInt k;
1065: if (!T || !(*T)) return(0);
1066: for (k = 0; k <= (*T)->K; ++k) {PetscFree((*T)->T[k]);}
1067: PetscFree((*T)->T);
1068: PetscFree(*T);
1069: *T = NULL;
1070: return(0);
1071: }
1073: PETSC_EXTERN PetscErrorCode PetscFECreatePointTrace(PetscFE fe, PetscInt refPoint, PetscFE *trFE)
1074: {
1075: PetscSpace bsp, bsubsp;
1076: PetscDualSpace dsp, dsubsp;
1077: PetscInt dim, depth, numComp, i, j, coneSize, order;
1078: PetscFEType type;
1079: DM dm;
1080: DMLabel label;
1081: PetscReal *xi, *v, *J, detJ;
1082: const char *name;
1083: PetscQuadrature origin, fullQuad, subQuad;
1089: PetscFEGetBasisSpace(fe,&bsp);
1090: PetscFEGetDualSpace(fe,&dsp);
1091: PetscDualSpaceGetDM(dsp,&dm);
1092: DMGetDimension(dm,&dim);
1093: DMPlexGetDepthLabel(dm,&label);
1094: DMLabelGetValue(label,refPoint,&depth);
1095: PetscCalloc1(depth,&xi);
1096: PetscMalloc1(dim,&v);
1097: PetscMalloc1(dim*dim,&J);
1098: for (i = 0; i < depth; i++) xi[i] = 0.;
1099: PetscQuadratureCreate(PETSC_COMM_SELF,&origin);
1100: PetscQuadratureSetData(origin,depth,0,1,xi,NULL);
1101: DMPlexComputeCellGeometryFEM(dm,refPoint,origin,v,J,NULL,&detJ);
1102: /* CellGeometryFEM computes the expanded Jacobian, we want the true jacobian */
1103: for (i = 1; i < dim; i++) {
1104: for (j = 0; j < depth; j++) {
1105: J[i * depth + j] = J[i * dim + j];
1106: }
1107: }
1108: PetscQuadratureDestroy(&origin);
1109: PetscDualSpaceGetPointSubspace(dsp,refPoint,&dsubsp);
1110: PetscSpaceCreateSubspace(bsp,dsubsp,v,J,NULL,NULL,PETSC_OWN_POINTER,&bsubsp);
1111: PetscSpaceSetUp(bsubsp);
1112: PetscFECreate(PetscObjectComm((PetscObject)fe),trFE);
1113: PetscFEGetType(fe,&type);
1114: PetscFESetType(*trFE,type);
1115: PetscFEGetNumComponents(fe,&numComp);
1116: PetscFESetNumComponents(*trFE,numComp);
1117: PetscFESetBasisSpace(*trFE,bsubsp);
1118: PetscFESetDualSpace(*trFE,dsubsp);
1119: PetscObjectGetName((PetscObject) fe, &name);
1120: if (name) {PetscFESetName(*trFE, name);}
1121: PetscFEGetQuadrature(fe,&fullQuad);
1122: PetscQuadratureGetOrder(fullQuad,&order);
1123: DMPlexGetConeSize(dm,refPoint,&coneSize);
1124: if (coneSize == 2 * depth) {
1125: PetscDTGaussTensorQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);
1126: } else {
1127: PetscDTStroudConicalQuadrature(depth,1,(order + 1)/2,-1.,1.,&subQuad);
1128: }
1129: PetscFESetQuadrature(*trFE,subQuad);
1130: PetscFESetUp(*trFE);
1131: PetscQuadratureDestroy(&subQuad);
1132: PetscSpaceDestroy(&bsubsp);
1133: return(0);
1134: }
1136: PetscErrorCode PetscFECreateHeightTrace(PetscFE fe, PetscInt height, PetscFE *trFE)
1137: {
1138: PetscInt hStart, hEnd;
1139: PetscDualSpace dsp;
1140: DM dm;
1146: *trFE = NULL;
1147: PetscFEGetDualSpace(fe,&dsp);
1148: PetscDualSpaceGetDM(dsp,&dm);
1149: DMPlexGetHeightStratum(dm,height,&hStart,&hEnd);
1150: if (hEnd <= hStart) return(0);
1151: PetscFECreatePointTrace(fe,hStart,trFE);
1152: return(0);
1153: }
1156: /*@
1157: PetscFEGetDimension - Get the dimension of the finite element space on a cell
1159: Not collective
1161: Input Parameter:
1162: . fe - The PetscFE
1164: Output Parameter:
1165: . dim - The dimension
1167: Level: intermediate
1169: .seealso: PetscFECreate(), PetscSpaceGetDimension(), PetscDualSpaceGetDimension()
1170: @*/
1171: PetscErrorCode PetscFEGetDimension(PetscFE fem, PetscInt *dim)
1172: {
1178: if (fem->ops->getdimension) {(*fem->ops->getdimension)(fem, dim);}
1179: return(0);
1180: }
1182: /*@C
1183: PetscFEPushforward - Map the reference element function to real space
1185: Input Parameters:
1186: + fe - The PetscFE
1187: . fegeom - The cell geometry
1188: . Nv - The number of function values
1189: - vals - The function values
1191: Output Parameter:
1192: . vals - The transformed function values
1194: Level: advanced
1196: Note: This just forwards the call onto PetscDualSpacePushforward().
1198: Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
1200: .seealso: PetscDualSpacePushforward()
1201: @*/
1202: PetscErrorCode PetscFEPushforward(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
1203: {
1207: PetscDualSpacePushforward(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);
1208: return(0);
1209: }
1211: /*@C
1212: PetscFEPushforwardGradient - Map the reference element function gradient to real space
1214: Input Parameters:
1215: + fe - The PetscFE
1216: . fegeom - The cell geometry
1217: . Nv - The number of function gradient values
1218: - vals - The function gradient values
1220: Output Parameter:
1221: . vals - The transformed function gradient values
1223: Level: advanced
1225: Note: This just forwards the call onto PetscDualSpacePushforwardGradient().
1227: Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
1229: .seealso: PetscFEPushforward(), PetscDualSpacePushforwardGradient(), PetscDualSpacePushforward()
1230: @*/
1231: PetscErrorCode PetscFEPushforwardGradient(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
1232: {
1236: PetscDualSpacePushforwardGradient(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);
1237: return(0);
1238: }
1240: /*@C
1241: PetscFEPushforwardHessian - Map the reference element function Hessian to real space
1243: Input Parameters:
1244: + fe - The PetscFE
1245: . fegeom - The cell geometry
1246: . Nv - The number of function Hessian values
1247: - vals - The function Hessian values
1249: Output Parameter:
1250: . vals - The transformed function Hessian values
1252: Level: advanced
1254: Note: This just forwards the call onto PetscDualSpacePushforwardHessian().
1256: Note: This only handles transformations when the embedding dimension of the geometry in fegeom is the same as the reference dimension.
1258: .seealso: PetscFEPushforward(), PetscDualSpacePushforwardHessian(), PetscDualSpacePushforward()
1259: @*/
1260: PetscErrorCode PetscFEPushforwardHessian(PetscFE fe, PetscFEGeom *fegeom, PetscInt Nv, PetscScalar vals[])
1261: {
1265: PetscDualSpacePushforwardHessian(fe->dualSpace, fegeom, Nv, fe->numComponents, vals);
1266: return(0);
1267: }
1269: /*
1270: Purpose: Compute element vector for chunk of elements
1272: Input:
1273: Sizes:
1274: Ne: number of elements
1275: Nf: number of fields
1276: PetscFE
1277: dim: spatial dimension
1278: Nb: number of basis functions
1279: Nc: number of field components
1280: PetscQuadrature
1281: Nq: number of quadrature points
1283: Geometry:
1284: PetscFEGeom[Ne] possibly *Nq
1285: PetscReal v0s[dim]
1286: PetscReal n[dim]
1287: PetscReal jacobians[dim*dim]
1288: PetscReal jacobianInverses[dim*dim]
1289: PetscReal jacobianDeterminants
1290: FEM:
1291: PetscFE
1292: PetscQuadrature
1293: PetscReal quadPoints[Nq*dim]
1294: PetscReal quadWeights[Nq]
1295: PetscReal basis[Nq*Nb*Nc]
1296: PetscReal basisDer[Nq*Nb*Nc*dim]
1297: PetscScalar coefficients[Ne*Nb*Nc]
1298: PetscScalar elemVec[Ne*Nb*Nc]
1300: Problem:
1301: PetscInt f: the active field
1302: f0, f1
1304: Work Space:
1305: PetscFE
1306: PetscScalar f0[Nq*dim];
1307: PetscScalar f1[Nq*dim*dim];
1308: PetscScalar u[Nc];
1309: PetscScalar gradU[Nc*dim];
1310: PetscReal x[dim];
1311: PetscScalar realSpaceDer[dim];
1313: Purpose: Compute element vector for N_cb batches of elements
1315: Input:
1316: Sizes:
1317: N_cb: Number of serial cell batches
1319: Geometry:
1320: PetscReal v0s[Ne*dim]
1321: PetscReal jacobians[Ne*dim*dim] possibly *Nq
1322: PetscReal jacobianInverses[Ne*dim*dim] possibly *Nq
1323: PetscReal jacobianDeterminants[Ne] possibly *Nq
1324: FEM:
1325: static PetscReal quadPoints[Nq*dim]
1326: static PetscReal quadWeights[Nq]
1327: static PetscReal basis[Nq*Nb*Nc]
1328: static PetscReal basisDer[Nq*Nb*Nc*dim]
1329: PetscScalar coefficients[Ne*Nb*Nc]
1330: PetscScalar elemVec[Ne*Nb*Nc]
1332: ex62.c:
1333: PetscErrorCode PetscFEIntegrateResidualBatch(PetscInt Ne, PetscInt numFields, PetscInt field, PetscQuadrature quad[], const PetscScalar coefficients[],
1334: const PetscReal v0s[], const PetscReal jacobians[], const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[],
1335: void (*f0_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]),
1336: void (*f1_func)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]), PetscScalar elemVec[])
1338: ex52.c:
1339: 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)
1340: 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)
1342: ex52_integrateElement.cu
1343: __global__ void integrateElementQuadrature(int N_cb, realType *coefficients, realType *jacobianInverses, realType *jacobianDeterminants, realType *elemVec)
1345: PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt Nbl, const PetscScalar coefficients[],
1346: const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[],
1347: PetscLogEvent event, PetscInt debug, PetscInt pde_op)
1349: ex52_integrateElementOpenCL.c:
1350: PETSC_EXTERN PetscErrorCode IntegrateElementBatchGPU(PetscInt spatial_dim, PetscInt Ne, PetscInt Ncb, PetscInt Nbc, PetscInt N_bl, const PetscScalar coefficients[],
1351: const PetscReal jacobianInverses[], const PetscReal jacobianDeterminants[], PetscScalar elemVec[],
1352: PetscLogEvent event, PetscInt debug, PetscInt pde_op)
1354: __kernel void integrateElementQuadrature(int N_cb, __global float *coefficients, __global float *jacobianInverses, __global float *jacobianDeterminants, __global float *elemVec)
1355: */
1357: /*@C
1358: PetscFEIntegrate - Produce the integral for the given field for a chunk of elements by quadrature integration
1360: Not collective
1362: Input Parameters:
1363: + prob - The PetscDS specifying the discretizations and continuum functions
1364: . field - The field being integrated
1365: . Ne - The number of elements in the chunk
1366: . cgeom - The cell geometry for each cell in the chunk
1367: . coefficients - The array of FEM basis coefficients for the elements
1368: . probAux - The PetscDS specifying the auxiliary discretizations
1369: - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1371: Output Parameter:
1372: . integral - the integral for this field
1374: Level: intermediate
1376: .seealso: PetscFEIntegrateResidual()
1377: @*/
1378: PetscErrorCode PetscFEIntegrate(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *cgeom,
1379: const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
1380: {
1381: PetscFE fe;
1386: PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);
1387: if (fe->ops->integrate) {(*fe->ops->integrate)(prob, field, Ne, cgeom, coefficients, probAux, coefficientsAux, integral);}
1388: return(0);
1389: }
1391: /*@C
1392: PetscFEIntegrateBd - Produce the integral for the given field for a chunk of elements by quadrature integration
1394: Not collective
1396: Input Parameters:
1397: + prob - The PetscDS specifying the discretizations and continuum functions
1398: . field - The field being integrated
1399: . obj_func - The function to be integrated
1400: . Ne - The number of elements in the chunk
1401: . fgeom - The face geometry for each face in the chunk
1402: . coefficients - The array of FEM basis coefficients for the elements
1403: . probAux - The PetscDS specifying the auxiliary discretizations
1404: - coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1406: Output Parameter:
1407: . integral - the integral for this field
1409: Level: intermediate
1411: .seealso: PetscFEIntegrateResidual()
1412: @*/
1413: PetscErrorCode PetscFEIntegrateBd(PetscDS prob, PetscInt field,
1414: void (*obj_func)(PetscInt, PetscInt, PetscInt,
1415: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
1416: const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[],
1417: PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]),
1418: PetscInt Ne, PetscFEGeom *geom, const PetscScalar coefficients[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscScalar integral[])
1419: {
1420: PetscFE fe;
1425: PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);
1426: if (fe->ops->integratebd) {(*fe->ops->integratebd)(prob, field, obj_func, Ne, geom, coefficients, probAux, coefficientsAux, integral);}
1427: return(0);
1428: }
1430: /*@C
1431: PetscFEIntegrateResidual - Produce the element residual vector for a chunk of elements by quadrature integration
1433: Not collective
1435: Input Parameters:
1436: + ds - The PetscDS specifying the discretizations and continuum functions
1437: . key - The (label+value, field) being integrated
1438: . Ne - The number of elements in the chunk
1439: . cgeom - The cell geometry for each cell in the chunk
1440: . coefficients - The array of FEM basis coefficients for the elements
1441: . coefficients_t - The array of FEM basis time derivative coefficients for the elements
1442: . probAux - The PetscDS specifying the auxiliary discretizations
1443: . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1444: - t - The time
1446: Output Parameter:
1447: . elemVec - the element residual vectors from each element
1449: Note:
1450: $ Loop over batch of elements (e):
1451: $ Loop over quadrature points (q):
1452: $ Make u_q and gradU_q (loops over fields,Nb,Ncomp) and x_q
1453: $ Call f_0 and f_1
1454: $ Loop over element vector entries (f,fc --> i):
1455: $ elemVec[i] += \psi^{fc}_f(q) f0_{fc}(u, \nabla u) + \nabla\psi^{fc}_f(q) \cdot f1_{fc,df}(u, \nabla u)
1457: Level: intermediate
1459: .seealso: PetscFEIntegrateResidual()
1460: @*/
1461: PetscErrorCode PetscFEIntegrateResidual(PetscDS ds, PetscHashFormKey key, PetscInt Ne, PetscFEGeom *cgeom,
1462: const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
1463: {
1464: PetscFE fe;
1469: PetscDSGetDiscretization(ds, key.field, (PetscObject *) &fe);
1470: if (fe->ops->integrateresidual) {(*fe->ops->integrateresidual)(ds, key, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);}
1471: return(0);
1472: }
1474: /*@C
1475: PetscFEIntegrateBdResidual - Produce the element residual vector for a chunk of elements by quadrature integration over a boundary
1477: Not collective
1479: Input Parameters:
1480: + prob - The PetscDS specifying the discretizations and continuum functions
1481: . field - The field being integrated
1482: . Ne - The number of elements in the chunk
1483: . fgeom - The face geometry for each cell in the chunk
1484: . coefficients - The array of FEM basis coefficients for the elements
1485: . coefficients_t - The array of FEM basis time derivative coefficients for the elements
1486: . probAux - The PetscDS specifying the auxiliary discretizations
1487: . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1488: - t - The time
1490: Output Parameter:
1491: . elemVec - the element residual vectors from each element
1493: Level: intermediate
1495: .seealso: PetscFEIntegrateResidual()
1496: @*/
1497: PetscErrorCode PetscFEIntegrateBdResidual(PetscDS prob, PetscInt field, PetscInt Ne, PetscFEGeom *fgeom,
1498: const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
1499: {
1500: PetscFE fe;
1505: PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);
1506: if (fe->ops->integratebdresidual) {(*fe->ops->integratebdresidual)(prob, field, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);}
1507: return(0);
1508: }
1510: /*@C
1511: PetscFEIntegrateHybridResidual - Produce the element residual vector for a chunk of hybrid element faces by quadrature integration
1513: Not collective
1515: Input Parameters:
1516: + prob - The PetscDS specifying the discretizations and continuum functions
1517: . key - The (label+value, field) being integrated
1518: . Ne - The number of elements in the chunk
1519: . fgeom - The face geometry for each cell in the chunk
1520: . coefficients - The array of FEM basis coefficients for the elements
1521: . coefficients_t - The array of FEM basis time derivative coefficients for the elements
1522: . probAux - The PetscDS specifying the auxiliary discretizations
1523: . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1524: - t - The time
1526: Output Parameter
1527: . elemVec - the element residual vectors from each element
1529: Level: developer
1531: .seealso: PetscFEIntegrateResidual()
1532: @*/
1533: PetscErrorCode PetscFEIntegrateHybridResidual(PetscDS prob, PetscHashFormKey key, PetscInt Ne, PetscFEGeom *fgeom,
1534: const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscScalar elemVec[])
1535: {
1536: PetscFE fe;
1541: PetscDSGetDiscretization(prob, key.field, (PetscObject *) &fe);
1542: if (fe->ops->integratehybridresidual) {(*fe->ops->integratehybridresidual)(prob, key, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, elemVec);}
1543: return(0);
1544: }
1546: /*@C
1547: PetscFEIntegrateJacobian - Produce the element Jacobian for a chunk of elements by quadrature integration
1549: Not collective
1551: Input Parameters:
1552: + ds - The PetscDS specifying the discretizations and continuum functions
1553: . jtype - The type of matrix pointwise functions that should be used
1554: . key - The (label+value, fieldI*Nf + fieldJ) being integrated
1555: . Ne - The number of elements in the chunk
1556: . cgeom - The cell geometry for each cell in the chunk
1557: . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
1558: . coefficients_t - The array of FEM basis time derivative coefficients for the elements
1559: . probAux - The PetscDS specifying the auxiliary discretizations
1560: . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1561: . t - The time
1562: - u_tShift - A multiplier for the dF/du_t term (as opposed to the dF/du term)
1564: Output Parameter:
1565: . elemMat - the element matrices for the Jacobian from each element
1567: Note:
1568: $ Loop over batch of elements (e):
1569: $ Loop over element matrix entries (f,fc,g,gc --> i,j):
1570: $ Loop over quadrature points (q):
1571: $ Make u_q and gradU_q (loops over fields,Nb,Ncomp)
1572: $ elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
1573: $ + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
1574: $ + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
1575: $ + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
1576: Level: intermediate
1578: .seealso: PetscFEIntegrateResidual()
1579: @*/
1580: PetscErrorCode PetscFEIntegrateJacobian(PetscDS ds, PetscFEJacobianType jtype, PetscHashFormKey key, PetscInt Ne, PetscFEGeom *cgeom,
1581: const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
1582: {
1583: PetscFE fe;
1584: PetscInt Nf;
1589: PetscDSGetNumFields(ds, &Nf);
1590: PetscDSGetDiscretization(ds, key.field / Nf, (PetscObject *) &fe);
1591: if (fe->ops->integratejacobian) {(*fe->ops->integratejacobian)(ds, jtype, key, Ne, cgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);}
1592: return(0);
1593: }
1595: /*@C
1596: PetscFEIntegrateBdJacobian - Produce the boundary element Jacobian for a chunk of elements by quadrature integration
1598: Not collective
1600: Input Parameters:
1601: + prob - The PetscDS specifying the discretizations and continuum functions
1602: . fieldI - The test field being integrated
1603: . fieldJ - The basis field being integrated
1604: . Ne - The number of elements in the chunk
1605: . fgeom - The face geometry for each cell in the chunk
1606: . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
1607: . coefficients_t - The array of FEM basis time derivative coefficients for the elements
1608: . probAux - The PetscDS specifying the auxiliary discretizations
1609: . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1610: . t - The time
1611: - u_tShift - A multiplier for the dF/du_t term (as opposed to the dF/du term)
1613: Output Parameter:
1614: . elemMat - the element matrices for the Jacobian from each element
1616: Note:
1617: $ Loop over batch of elements (e):
1618: $ Loop over element matrix entries (f,fc,g,gc --> i,j):
1619: $ Loop over quadrature points (q):
1620: $ Make u_q and gradU_q (loops over fields,Nb,Ncomp)
1621: $ elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
1622: $ + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
1623: $ + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
1624: $ + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
1625: Level: intermediate
1627: .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual()
1628: @*/
1629: PetscErrorCode PetscFEIntegrateBdJacobian(PetscDS prob, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
1630: const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
1631: {
1632: PetscFE fe;
1637: PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);
1638: if (fe->ops->integratebdjacobian) {(*fe->ops->integratebdjacobian)(prob, fieldI, fieldJ, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);}
1639: return(0);
1640: }
1642: /*@C
1643: PetscFEIntegrateHybridJacobian - Produce the boundary element Jacobian for a chunk of hybrid elements by quadrature integration
1645: Not collective
1647: Input Parameters:
1648: + prob - The PetscDS specifying the discretizations and continuum functions
1649: . jtype - The type of matrix pointwise functions that should be used
1650: . fieldI - The test field being integrated
1651: . fieldJ - The basis field being integrated
1652: . Ne - The number of elements in the chunk
1653: . fgeom - The face geometry for each cell in the chunk
1654: . coefficients - The array of FEM basis coefficients for the elements for the Jacobian evaluation point
1655: . coefficients_t - The array of FEM basis time derivative coefficients for the elements
1656: . probAux - The PetscDS specifying the auxiliary discretizations
1657: . coefficientsAux - The array of FEM auxiliary basis coefficients for the elements
1658: . t - The time
1659: - u_tShift - A multiplier for the dF/du_t term (as opposed to the dF/du term)
1661: Output Parameter
1662: . elemMat - the element matrices for the Jacobian from each element
1664: Note:
1665: $ Loop over batch of elements (e):
1666: $ Loop over element matrix entries (f,fc,g,gc --> i,j):
1667: $ Loop over quadrature points (q):
1668: $ Make u_q and gradU_q (loops over fields,Nb,Ncomp)
1669: $ elemMat[i,j] += \psi^{fc}_f(q) g0_{fc,gc}(u, \nabla u) \phi^{gc}_g(q)
1670: $ + \psi^{fc}_f(q) \cdot g1_{fc,gc,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
1671: $ + \nabla\psi^{fc}_f(q) \cdot g2_{fc,gc,df}(u, \nabla u) \phi^{gc}_g(q)
1672: $ + \nabla\psi^{fc}_f(q) \cdot g3_{fc,gc,df,dg}(u, \nabla u) \nabla\phi^{gc}_g(q)
1673: Level: developer
1675: .seealso: PetscFEIntegrateJacobian(), PetscFEIntegrateResidual()
1676: @*/
1677: PetscErrorCode PetscFEIntegrateHybridJacobian(PetscDS prob, PetscFEJacobianType jtype, PetscInt fieldI, PetscInt fieldJ, PetscInt Ne, PetscFEGeom *fgeom,
1678: const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscDS probAux, const PetscScalar coefficientsAux[], PetscReal t, PetscReal u_tshift, PetscScalar elemMat[])
1679: {
1680: PetscFE fe;
1685: PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);
1686: if (fe->ops->integratehybridjacobian) {(*fe->ops->integratehybridjacobian)(prob, jtype, fieldI, fieldJ, Ne, fgeom, coefficients, coefficients_t, probAux, coefficientsAux, t, u_tshift, elemMat);}
1687: return(0);
1688: }
1690: /*@
1691: PetscFEGetHeightSubspace - Get the subspace of this space for a mesh point of a given height
1693: Input Parameters:
1694: + fe - The finite element space
1695: - height - The height of the Plex point
1697: Output Parameter:
1698: . subfe - The subspace of this FE space
1700: Note: For example, if we want the subspace of this space for a face, we would choose height = 1.
1702: Level: advanced
1704: .seealso: PetscFECreateDefault()
1705: @*/
1706: PetscErrorCode PetscFEGetHeightSubspace(PetscFE fe, PetscInt height, PetscFE *subfe)
1707: {
1708: PetscSpace P, subP;
1709: PetscDualSpace Q, subQ;
1710: PetscQuadrature subq;
1711: PetscFEType fetype;
1712: PetscInt dim, Nc;
1713: PetscErrorCode ierr;
1718: if (height == 0) {
1719: *subfe = fe;
1720: return(0);
1721: }
1722: PetscFEGetBasisSpace(fe, &P);
1723: PetscFEGetDualSpace(fe, &Q);
1724: PetscFEGetNumComponents(fe, &Nc);
1725: PetscFEGetFaceQuadrature(fe, &subq);
1726: PetscDualSpaceGetDimension(Q, &dim);
1727: 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);
1728: if (!fe->subspaces) {PetscCalloc1(dim, &fe->subspaces);}
1729: if (height <= dim) {
1730: if (!fe->subspaces[height-1]) {
1731: PetscFE sub = NULL;
1732: const char *name;
1734: PetscSpaceGetHeightSubspace(P, height, &subP);
1735: PetscDualSpaceGetHeightSubspace(Q, height, &subQ);
1736: if (subQ) {
1737: PetscFECreate(PetscObjectComm((PetscObject) fe), &sub);
1738: PetscObjectGetName((PetscObject) fe, &name);
1739: PetscObjectSetName((PetscObject) sub, name);
1740: PetscFEGetType(fe, &fetype);
1741: PetscFESetType(sub, fetype);
1742: PetscFESetBasisSpace(sub, subP);
1743: PetscFESetDualSpace(sub, subQ);
1744: PetscFESetNumComponents(sub, Nc);
1745: PetscFESetUp(sub);
1746: PetscFESetQuadrature(sub, subq);
1747: }
1748: fe->subspaces[height-1] = sub;
1749: }
1750: *subfe = fe->subspaces[height-1];
1751: } else {
1752: *subfe = NULL;
1753: }
1754: return(0);
1755: }
1757: /*@
1758: PetscFERefine - Create a "refined" PetscFE object that refines the reference cell into smaller copies. This is typically used
1759: to precondition a higher order method with a lower order method on a refined mesh having the same number of dofs (but more
1760: sparsity). It is also used to create an interpolation between regularly refined meshes.
1762: Collective on fem
1764: Input Parameter:
1765: . fe - The initial PetscFE
1767: Output Parameter:
1768: . feRef - The refined PetscFE
1770: Level: advanced
1772: .seealso: PetscFEType, PetscFECreate(), PetscFESetType()
1773: @*/
1774: PetscErrorCode PetscFERefine(PetscFE fe, PetscFE *feRef)
1775: {
1776: PetscSpace P, Pref;
1777: PetscDualSpace Q, Qref;
1778: DM K, Kref;
1779: PetscQuadrature q, qref;
1780: const PetscReal *v0, *jac;
1781: PetscInt numComp, numSubelements;
1782: PetscInt cStart, cEnd, c;
1783: PetscDualSpace *cellSpaces;
1784: PetscErrorCode ierr;
1787: PetscFEGetBasisSpace(fe, &P);
1788: PetscFEGetDualSpace(fe, &Q);
1789: PetscFEGetQuadrature(fe, &q);
1790: PetscDualSpaceGetDM(Q, &K);
1791: /* Create space */
1792: PetscObjectReference((PetscObject) P);
1793: Pref = P;
1794: /* Create dual space */
1795: PetscDualSpaceDuplicate(Q, &Qref);
1796: PetscDualSpaceSetType(Qref, PETSCDUALSPACEREFINED);
1797: DMRefine(K, PetscObjectComm((PetscObject) fe), &Kref);
1798: PetscDualSpaceSetDM(Qref, Kref);
1799: DMPlexGetHeightStratum(Kref, 0, &cStart, &cEnd);
1800: PetscMalloc1(cEnd - cStart, &cellSpaces);
1801: /* TODO: fix for non-uniform refinement */
1802: for (c = 0; c < cEnd - cStart; c++) cellSpaces[c] = Q;
1803: PetscDualSpaceRefinedSetCellSpaces(Qref, cellSpaces);
1804: PetscFree(cellSpaces);
1805: DMDestroy(&Kref);
1806: PetscDualSpaceSetUp(Qref);
1807: /* Create element */
1808: PetscFECreate(PetscObjectComm((PetscObject) fe), feRef);
1809: PetscFESetType(*feRef, PETSCFECOMPOSITE);
1810: PetscFESetBasisSpace(*feRef, Pref);
1811: PetscFESetDualSpace(*feRef, Qref);
1812: PetscFEGetNumComponents(fe, &numComp);
1813: PetscFESetNumComponents(*feRef, numComp);
1814: PetscFESetUp(*feRef);
1815: PetscSpaceDestroy(&Pref);
1816: PetscDualSpaceDestroy(&Qref);
1817: /* Create quadrature */
1818: PetscFECompositeGetMapping(*feRef, &numSubelements, &v0, &jac, NULL);
1819: PetscQuadratureExpandComposite(q, numSubelements, v0, jac, &qref);
1820: PetscFESetQuadrature(*feRef, qref);
1821: PetscQuadratureDestroy(&qref);
1822: return(0);
1823: }
1825: /*@C
1826: PetscFECreateDefault - Create a PetscFE for basic FEM computation
1828: Collective
1830: Input Parameters:
1831: + comm - The MPI comm
1832: . dim - The spatial dimension
1833: . Nc - The number of components
1834: . isSimplex - Flag for simplex reference cell, otherwise its a tensor product
1835: . prefix - The options prefix, or NULL
1836: - qorder - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree
1838: Output Parameter:
1839: . fem - The PetscFE object
1841: Note:
1842: Each object is SetFromOption() during creation, so that the object may be customized from the command line.
1844: Level: beginner
1846: .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
1847: @*/
1848: PetscErrorCode PetscFECreateDefault(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, const char prefix[], PetscInt qorder, PetscFE *fem)
1849: {
1850: PetscQuadrature q, fq;
1851: DM K;
1852: PetscSpace P;
1853: PetscDualSpace Q;
1854: PetscInt order, quadPointsPerEdge;
1855: PetscBool tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1856: PetscErrorCode ierr;
1859: /* Create space */
1860: PetscSpaceCreate(comm, &P);
1861: PetscObjectSetOptionsPrefix((PetscObject) P, prefix);
1862: PetscSpacePolynomialSetTensor(P, tensor);
1863: PetscSpaceSetNumComponents(P, Nc);
1864: PetscSpaceSetNumVariables(P, dim);
1865: PetscSpaceSetFromOptions(P);
1866: PetscSpaceSetUp(P);
1867: PetscSpaceGetDegree(P, &order, NULL);
1868: PetscSpacePolynomialGetTensor(P, &tensor);
1869: /* Create dual space */
1870: PetscDualSpaceCreate(comm, &Q);
1871: PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE);
1872: PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);
1873: PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);
1874: PetscDualSpaceSetDM(Q, K);
1875: DMDestroy(&K);
1876: PetscDualSpaceSetNumComponents(Q, Nc);
1877: PetscDualSpaceSetOrder(Q, order);
1878: PetscDualSpaceLagrangeSetTensor(Q, tensor);
1879: PetscDualSpaceSetFromOptions(Q);
1880: PetscDualSpaceSetUp(Q);
1881: /* Create element */
1882: PetscFECreate(comm, fem);
1883: PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);
1884: PetscFESetBasisSpace(*fem, P);
1885: PetscFESetDualSpace(*fem, Q);
1886: PetscFESetNumComponents(*fem, Nc);
1887: PetscFESetFromOptions(*fem);
1888: PetscFESetUp(*fem);
1889: PetscSpaceDestroy(&P);
1890: PetscDualSpaceDestroy(&Q);
1891: /* Create quadrature (with specified order if given) */
1892: qorder = qorder >= 0 ? qorder : order;
1893: PetscObjectOptionsBegin((PetscObject)*fem);
1894: PetscOptionsBoundedInt("-petscfe_default_quadrature_order","Quadrature order is one less than quadrature points per edge","PetscFECreateDefault",qorder,&qorder,NULL,0);
1895: PetscOptionsEnd();
1896: quadPointsPerEdge = PetscMax(qorder + 1,1);
1897: if (isSimplex) {
1898: PetscDTStroudConicalQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q);
1899: PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);
1900: } else {
1901: PetscDTGaussTensorQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q);
1902: PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);
1903: }
1904: PetscFESetQuadrature(*fem, q);
1905: PetscFESetFaceQuadrature(*fem, fq);
1906: PetscQuadratureDestroy(&q);
1907: PetscQuadratureDestroy(&fq);
1908: return(0);
1909: }
1911: /*@
1912: PetscFECreateLagrange - Create a PetscFE for the basic Lagrange space of degree k
1914: Collective
1916: Input Parameters:
1917: + comm - The MPI comm
1918: . dim - The spatial dimension
1919: . Nc - The number of components
1920: . isSimplex - Flag for simplex reference cell, otherwise its a tensor product
1921: . k - The degree k of the space
1922: - qorder - The quadrature order or PETSC_DETERMINE to use PetscSpace polynomial degree
1924: Output Parameter:
1925: . fem - The PetscFE object
1927: Level: beginner
1929: Notes:
1930: For simplices, this element is the space of maximum polynomial degree k, otherwise it is a tensor product of 1D polynomials, each with maximal degree k.
1932: .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
1933: @*/
1934: PetscErrorCode PetscFECreateLagrange(MPI_Comm comm, PetscInt dim, PetscInt Nc, PetscBool isSimplex, PetscInt k, PetscInt qorder, PetscFE *fem)
1935: {
1936: PetscQuadrature q, fq;
1937: DM K;
1938: PetscSpace P;
1939: PetscDualSpace Q;
1940: PetscInt quadPointsPerEdge;
1941: PetscBool tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
1942: char name[64];
1943: PetscErrorCode ierr;
1946: /* Create space */
1947: PetscSpaceCreate(comm, &P);
1948: PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL);
1949: PetscSpacePolynomialSetTensor(P, tensor);
1950: PetscSpaceSetNumComponents(P, Nc);
1951: PetscSpaceSetNumVariables(P, dim);
1952: PetscSpaceSetDegree(P, k, PETSC_DETERMINE);
1953: PetscSpaceSetUp(P);
1954: /* Create dual space */
1955: PetscDualSpaceCreate(comm, &Q);
1956: PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE);
1957: PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);
1958: PetscDualSpaceSetDM(Q, K);
1959: DMDestroy(&K);
1960: PetscDualSpaceSetNumComponents(Q, Nc);
1961: PetscDualSpaceSetOrder(Q, k);
1962: PetscDualSpaceLagrangeSetTensor(Q, tensor);
1963: PetscDualSpaceSetUp(Q);
1964: /* Create finite element */
1965: PetscFECreate(comm, fem);
1966: PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);
1967: PetscObjectSetName((PetscObject) *fem, name);
1968: PetscFESetType(*fem, PETSCFEBASIC);
1969: PetscFESetBasisSpace(*fem, P);
1970: PetscFESetDualSpace(*fem, Q);
1971: PetscFESetNumComponents(*fem, Nc);
1972: PetscFESetUp(*fem);
1973: PetscSpaceDestroy(&P);
1974: PetscDualSpaceDestroy(&Q);
1975: /* Create quadrature (with specified order if given) */
1976: qorder = qorder >= 0 ? qorder : k;
1977: quadPointsPerEdge = PetscMax(qorder + 1,1);
1978: if (isSimplex) {
1979: PetscDTStroudConicalQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q);
1980: PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);
1981: } else {
1982: PetscDTGaussTensorQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q);
1983: PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);
1984: }
1985: PetscFESetQuadrature(*fem, q);
1986: PetscFESetFaceQuadrature(*fem, fq);
1987: PetscQuadratureDestroy(&q);
1988: PetscQuadratureDestroy(&fq);
1989: /* Set finite element name */
1990: PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);
1991: PetscFESetName(*fem, name);
1992: return(0);
1993: }
1995: /*@C
1996: PetscFESetName - Names the FE and its subobjects
1998: Not collective
2000: Input Parameters:
2001: + fe - The PetscFE
2002: - name - The name
2004: Level: intermediate
2006: .seealso: PetscFECreate(), PetscSpaceCreate(), PetscDualSpaceCreate()
2007: @*/
2008: PetscErrorCode PetscFESetName(PetscFE fe, const char name[])
2009: {
2010: PetscSpace P;
2011: PetscDualSpace Q;
2015: PetscFEGetBasisSpace(fe, &P);
2016: PetscFEGetDualSpace(fe, &Q);
2017: PetscObjectSetName((PetscObject) fe, name);
2018: PetscObjectSetName((PetscObject) P, name);
2019: PetscObjectSetName((PetscObject) Q, name);
2020: return(0);
2021: }
2023: PetscErrorCode PetscFEEvaluateFieldJets_Internal(PetscDS ds, PetscInt Nf, PetscInt r, PetscInt q, PetscTabulation T[], PetscFEGeom *fegeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscScalar u[], PetscScalar u_x[], PetscScalar u_t[])
2024: {
2025: PetscInt dOffset = 0, fOffset = 0, f, g;
2028: for (f = 0; f < Nf; ++f) {
2029: PetscFE fe;
2030: const PetscInt k = ds->jetDegree[f];
2031: const PetscInt cdim = T[f]->cdim;
2032: const PetscInt Nq = T[f]->Np;
2033: const PetscInt Nbf = T[f]->Nb;
2034: const PetscInt Ncf = T[f]->Nc;
2035: const PetscReal *Bq = &T[f]->T[0][(r*Nq+q)*Nbf*Ncf];
2036: const PetscReal *Dq = &T[f]->T[1][(r*Nq+q)*Nbf*Ncf*cdim];
2037: const PetscReal *Hq = k > 1 ? &T[f]->T[2][(r*Nq+q)*Nbf*Ncf*cdim*cdim] : NULL;
2038: PetscInt hOffset = 0, b, c, d;
2040: PetscDSGetDiscretization(ds, f, (PetscObject *) &fe);
2041: for (c = 0; c < Ncf; ++c) u[fOffset+c] = 0.0;
2042: for (d = 0; d < cdim*Ncf; ++d) u_x[fOffset*cdim+d] = 0.0;
2043: for (b = 0; b < Nbf; ++b) {
2044: for (c = 0; c < Ncf; ++c) {
2045: const PetscInt cidx = b*Ncf+c;
2047: u[fOffset+c] += Bq[cidx]*coefficients[dOffset+b];
2048: for (d = 0; d < cdim; ++d) u_x[(fOffset+c)*cdim+d] += Dq[cidx*cdim+d]*coefficients[dOffset+b];
2049: }
2050: }
2051: if (k > 1) {
2052: for (g = 0; g < Nf; ++g) hOffset += T[g]->Nc*cdim;
2053: for (d = 0; d < cdim*cdim*Ncf; ++d) u_x[hOffset+fOffset*cdim*cdim+d] = 0.0;
2054: for (b = 0; b < Nbf; ++b) {
2055: for (c = 0; c < Ncf; ++c) {
2056: const PetscInt cidx = b*Ncf+c;
2058: for (d = 0; d < cdim*cdim; ++d) u_x[hOffset+(fOffset+c)*cdim*cdim+d] += Hq[cidx*cdim*cdim+d]*coefficients[dOffset+b];
2059: }
2060: }
2061: PetscFEPushforwardHessian(fe, fegeom, 1, &u_x[hOffset+fOffset*cdim*cdim]);
2062: }
2063: PetscFEPushforward(fe, fegeom, 1, &u[fOffset]);
2064: PetscFEPushforwardGradient(fe, fegeom, 1, &u_x[fOffset*cdim]);
2065: if (u_t) {
2066: for (c = 0; c < Ncf; ++c) u_t[fOffset+c] = 0.0;
2067: for (b = 0; b < Nbf; ++b) {
2068: for (c = 0; c < Ncf; ++c) {
2069: const PetscInt cidx = b*Ncf+c;
2071: u_t[fOffset+c] += Bq[cidx]*coefficients_t[dOffset+b];
2072: }
2073: }
2074: PetscFEPushforward(fe, fegeom, 1, &u_t[fOffset]);
2075: }
2076: fOffset += Ncf;
2077: dOffset += Nbf;
2078: }
2079: return 0;
2080: }
2082: PetscErrorCode PetscFEEvaluateFieldJets_Hybrid_Internal(PetscDS ds, PetscInt Nf, PetscInt r, PetscInt q, PetscTabulation T[], PetscFEGeom *fegeom, const PetscScalar coefficients[], const PetscScalar coefficients_t[], PetscScalar u[], PetscScalar u_x[], PetscScalar u_t[])
2083: {
2084: PetscInt dOffset = 0, fOffset = 0, g;
2087: for (g = 0; g < 2*Nf-1; ++g) {
2088: if (!T[g/2]) continue;
2089: {
2090: PetscFE fe;
2091: const PetscInt f = g/2;
2092: const PetscInt cdim = T[f]->cdim;
2093: const PetscInt Nq = T[f]->Np;
2094: const PetscInt Nbf = T[f]->Nb;
2095: const PetscInt Ncf = T[f]->Nc;
2096: const PetscReal *Bq = &T[f]->T[0][(r*Nq+q)*Nbf*Ncf];
2097: const PetscReal *Dq = &T[f]->T[1][(r*Nq+q)*Nbf*Ncf*cdim];
2098: PetscInt b, c, d;
2100: fe = (PetscFE) ds->disc[f];
2101: for (c = 0; c < Ncf; ++c) u[fOffset+c] = 0.0;
2102: for (d = 0; d < cdim*Ncf; ++d) u_x[fOffset*cdim+d] = 0.0;
2103: for (b = 0; b < Nbf; ++b) {
2104: for (c = 0; c < Ncf; ++c) {
2105: const PetscInt cidx = b*Ncf+c;
2107: u[fOffset+c] += Bq[cidx]*coefficients[dOffset+b];
2108: for (d = 0; d < cdim; ++d) u_x[(fOffset+c)*cdim+d] += Dq[cidx*cdim+d]*coefficients[dOffset+b];
2109: }
2110: }
2111: PetscFEPushforward(fe, fegeom, 1, &u[fOffset]);
2112: PetscFEPushforwardGradient(fe, fegeom, 1, &u_x[fOffset*cdim]);
2113: if (u_t) {
2114: for (c = 0; c < Ncf; ++c) u_t[fOffset+c] = 0.0;
2115: for (b = 0; b < Nbf; ++b) {
2116: for (c = 0; c < Ncf; ++c) {
2117: const PetscInt cidx = b*Ncf+c;
2119: u_t[fOffset+c] += Bq[cidx]*coefficients_t[dOffset+b];
2120: }
2121: }
2122: PetscFEPushforward(fe, fegeom, 1, &u_t[fOffset]);
2123: }
2124: fOffset += Ncf;
2125: dOffset += Nbf;
2126: }
2127: }
2128: return 0;
2129: }
2131: PetscErrorCode PetscFEEvaluateFaceFields_Internal(PetscDS prob, PetscInt field, PetscInt faceLoc, const PetscScalar coefficients[], PetscScalar u[])
2132: {
2133: PetscFE fe;
2134: PetscTabulation Tc;
2135: PetscInt b, c;
2136: PetscErrorCode ierr;
2138: if (!prob) return 0;
2139: PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);
2140: PetscFEGetFaceCentroidTabulation(fe, &Tc);
2141: {
2142: const PetscReal *faceBasis = Tc->T[0];
2143: const PetscInt Nb = Tc->Nb;
2144: const PetscInt Nc = Tc->Nc;
2146: for (c = 0; c < Nc; ++c) {u[c] = 0.0;}
2147: for (b = 0; b < Nb; ++b) {
2148: for (c = 0; c < Nc; ++c) {
2149: u[c] += coefficients[b] * faceBasis[(faceLoc*Nb + b)*Nc + c];
2150: }
2151: }
2152: }
2153: return 0;
2154: }
2156: PetscErrorCode PetscFEUpdateElementVec_Internal(PetscFE fe, PetscTabulation T, PetscInt r, PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[])
2157: {
2158: const PetscInt dE = T->cdim; /* fegeom->dimEmbed */
2159: const PetscInt Nq = T->Np;
2160: const PetscInt Nb = T->Nb;
2161: const PetscInt Nc = T->Nc;
2162: const PetscReal *basis = &T->T[0][r*Nq*Nb*Nc];
2163: const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dE];
2164: PetscInt q, b, c, d;
2165: PetscErrorCode ierr;
2167: for (b = 0; b < Nb; ++b) elemVec[b] = 0.0;
2168: for (q = 0; q < Nq; ++q) {
2169: for (b = 0; b < Nb; ++b) {
2170: for (c = 0; c < Nc; ++c) {
2171: const PetscInt bcidx = b*Nc+c;
2173: tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx];
2174: for (d = 0; d < dE; ++d) tmpBasisDer[bcidx*dE+d] = basisDer[q*Nb*Nc*dE+bcidx*dE+d];
2175: }
2176: }
2177: PetscFEPushforward(fe, fegeom, Nb, tmpBasis);
2178: PetscFEPushforwardGradient(fe, fegeom, Nb, tmpBasisDer);
2179: for (b = 0; b < Nb; ++b) {
2180: for (c = 0; c < Nc; ++c) {
2181: const PetscInt bcidx = b*Nc+c;
2182: const PetscInt qcidx = q*Nc+c;
2184: elemVec[b] += tmpBasis[bcidx]*f0[qcidx];
2185: for (d = 0; d < dE; ++d) elemVec[b] += tmpBasisDer[bcidx*dE+d]*f1[qcidx*dE+d];
2186: }
2187: }
2188: }
2189: return(0);
2190: }
2192: PetscErrorCode PetscFEUpdateElementVec_Hybrid_Internal(PetscFE fe, PetscTabulation T, PetscInt r, PetscScalar tmpBasis[], PetscScalar tmpBasisDer[], PetscFEGeom *fegeom, PetscScalar f0[], PetscScalar f1[], PetscScalar elemVec[])
2193: {
2194: const PetscInt dE = T->cdim;
2195: const PetscInt Nq = T->Np;
2196: const PetscInt Nb = T->Nb;
2197: const PetscInt Nc = T->Nc;
2198: const PetscReal *basis = &T->T[0][r*Nq*Nb*Nc];
2199: const PetscReal *basisDer = &T->T[1][r*Nq*Nb*Nc*dE];
2200: PetscInt q, b, c, d, s;
2201: PetscErrorCode ierr;
2203: for (b = 0; b < Nb*2; ++b) elemVec[b] = 0.0;
2204: for (q = 0; q < Nq; ++q) {
2205: for (b = 0; b < Nb; ++b) {
2206: for (c = 0; c < Nc; ++c) {
2207: const PetscInt bcidx = b*Nc+c;
2209: tmpBasis[bcidx] = basis[q*Nb*Nc+bcidx];
2210: for (d = 0; d < dE; ++d) tmpBasisDer[bcidx*dE+d] = basisDer[q*Nb*Nc*dE+bcidx*dE+d];
2211: }
2212: }
2213: PetscFEPushforward(fe, fegeom, Nb, tmpBasis);
2214: PetscFEPushforwardGradient(fe, fegeom, Nb, tmpBasisDer);
2215: for (s = 0; s < 2; ++s) {
2216: for (b = 0; b < Nb; ++b) {
2217: for (c = 0; c < Nc; ++c) {
2218: const PetscInt bcidx = b*Nc+c;
2219: const PetscInt qcidx = (q*2+s)*Nc+c;
2221: elemVec[Nb*s+b] += tmpBasis[bcidx]*f0[qcidx];
2222: for (d = 0; d < dE; ++d) elemVec[Nb*s+b] += tmpBasisDer[bcidx*dE+d]*f1[qcidx*dE+d];
2223: }
2224: }
2225: }
2226: }
2227: return(0);
2228: }
2230: PetscErrorCode PetscFEUpdateElementMat_Internal(PetscFE feI, PetscFE feJ, PetscInt r, PetscInt q, PetscTabulation TI, PetscScalar tmpBasisI[], PetscScalar tmpBasisDerI[], PetscTabulation TJ, PetscScalar tmpBasisJ[], PetscScalar tmpBasisDerJ[], PetscFEGeom *fegeom, const PetscScalar g0[], const PetscScalar g1[], const PetscScalar g2[], const PetscScalar g3[], PetscInt eOffset, PetscInt totDim, PetscInt offsetI, PetscInt offsetJ, PetscScalar elemMat[])
2231: {
2232: const PetscInt dE = TI->cdim;
2233: const PetscInt NqI = TI->Np;
2234: const PetscInt NbI = TI->Nb;
2235: const PetscInt NcI = TI->Nc;
2236: const PetscReal *basisI = &TI->T[0][(r*NqI+q)*NbI*NcI];
2237: const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dE];
2238: const PetscInt NqJ = TJ->Np;
2239: const PetscInt NbJ = TJ->Nb;
2240: const PetscInt NcJ = TJ->Nc;
2241: const PetscReal *basisJ = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ];
2242: const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dE];
2243: PetscInt f, fc, g, gc, df, dg;
2244: PetscErrorCode ierr;
2246: for (f = 0; f < NbI; ++f) {
2247: for (fc = 0; fc < NcI; ++fc) {
2248: const PetscInt fidx = f*NcI+fc; /* Test function basis index */
2250: tmpBasisI[fidx] = basisI[fidx];
2251: for (df = 0; df < dE; ++df) tmpBasisDerI[fidx*dE+df] = basisDerI[fidx*dE+df];
2252: }
2253: }
2254: PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);
2255: PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);
2256: for (g = 0; g < NbJ; ++g) {
2257: for (gc = 0; gc < NcJ; ++gc) {
2258: const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
2260: tmpBasisJ[gidx] = basisJ[gidx];
2261: for (dg = 0; dg < dE; ++dg) tmpBasisDerJ[gidx*dE+dg] = basisDerJ[gidx*dE+dg];
2262: }
2263: }
2264: PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);
2265: PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);
2266: for (f = 0; f < NbI; ++f) {
2267: for (fc = 0; fc < NcI; ++fc) {
2268: const PetscInt fidx = f*NcI+fc; /* Test function basis index */
2269: const PetscInt i = offsetI+f; /* Element matrix row */
2270: for (g = 0; g < NbJ; ++g) {
2271: for (gc = 0; gc < NcJ; ++gc) {
2272: const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
2273: const PetscInt j = offsetJ+g; /* Element matrix column */
2274: const PetscInt fOff = eOffset+i*totDim+j;
2276: elemMat[fOff] += tmpBasisI[fidx]*g0[fc*NcJ+gc]*tmpBasisJ[gidx];
2277: for (df = 0; df < dE; ++df) {
2278: elemMat[fOff] += tmpBasisI[fidx]*g1[(fc*NcJ+gc)*dE+df]*tmpBasisDerJ[gidx*dE+df];
2279: elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g2[(fc*NcJ+gc)*dE+df]*tmpBasisJ[gidx];
2280: for (dg = 0; dg < dE; ++dg) {
2281: elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g3[((fc*NcJ+gc)*dE+df)*dE+dg]*tmpBasisDerJ[gidx*dE+dg];
2282: }
2283: }
2284: }
2285: }
2286: }
2287: }
2288: return(0);
2289: }
2291: PetscErrorCode PetscFEUpdateElementMat_Hybrid_Internal(PetscFE feI, PetscBool isHybridI, PetscFE feJ, PetscBool isHybridJ, PetscInt r, PetscInt q, PetscTabulation TI, PetscScalar tmpBasisI[], PetscScalar tmpBasisDerI[], PetscTabulation TJ, PetscScalar tmpBasisJ[], PetscScalar tmpBasisDerJ[], PetscFEGeom *fegeom, const PetscScalar g0[], const PetscScalar g1[], const PetscScalar g2[], const PetscScalar g3[], PetscInt eOffset, PetscInt totDim, PetscInt offsetI, PetscInt offsetJ, PetscScalar elemMat[])
2292: {
2293: const PetscInt dE = TI->cdim;
2294: const PetscInt NqI = TI->Np;
2295: const PetscInt NbI = TI->Nb;
2296: const PetscInt NcI = TI->Nc;
2297: const PetscReal *basisI = &TI->T[0][(r*NqI+q)*NbI*NcI];
2298: const PetscReal *basisDerI = &TI->T[1][(r*NqI+q)*NbI*NcI*dE];
2299: const PetscInt NqJ = TJ->Np;
2300: const PetscInt NbJ = TJ->Nb;
2301: const PetscInt NcJ = TJ->Nc;
2302: const PetscReal *basisJ = &TJ->T[0][(r*NqJ+q)*NbJ*NcJ];
2303: const PetscReal *basisDerJ = &TJ->T[1][(r*NqJ+q)*NbJ*NcJ*dE];
2304: const PetscInt Ns = isHybridI ? 1 : 2;
2305: const PetscInt Nt = isHybridJ ? 1 : 2;
2306: PetscInt f, fc, g, gc, df, dg, s, t;
2307: PetscErrorCode ierr;
2309: for (f = 0; f < NbI; ++f) {
2310: for (fc = 0; fc < NcI; ++fc) {
2311: const PetscInt fidx = f*NcI+fc; /* Test function basis index */
2313: tmpBasisI[fidx] = basisI[fidx];
2314: for (df = 0; df < dE; ++df) tmpBasisDerI[fidx*dE+df] = basisDerI[fidx*dE+df];
2315: }
2316: }
2317: PetscFEPushforward(feI, fegeom, NbI, tmpBasisI);
2318: PetscFEPushforwardGradient(feI, fegeom, NbI, tmpBasisDerI);
2319: for (g = 0; g < NbJ; ++g) {
2320: for (gc = 0; gc < NcJ; ++gc) {
2321: const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
2323: tmpBasisJ[gidx] = basisJ[gidx];
2324: for (dg = 0; dg < dE; ++dg) tmpBasisDerJ[gidx*dE+dg] = basisDerJ[gidx*dE+dg];
2325: }
2326: }
2327: PetscFEPushforward(feJ, fegeom, NbJ, tmpBasisJ);
2328: PetscFEPushforwardGradient(feJ, fegeom, NbJ, tmpBasisDerJ);
2329: for (s = 0; s < Ns; ++s) {
2330: for (f = 0; f < NbI; ++f) {
2331: for (fc = 0; fc < NcI; ++fc) {
2332: const PetscInt sc = NcI*s+fc; /* components from each side of the surface */
2333: const PetscInt fidx = f*NcI+fc; /* Test function basis index */
2334: const PetscInt i = offsetI+NbI*s+f; /* Element matrix row */
2335: for (t = 0; t < Nt; ++t) {
2336: for (g = 0; g < NbJ; ++g) {
2337: for (gc = 0; gc < NcJ; ++gc) {
2338: const PetscInt tc = NcJ*t+gc; /* components from each side of the surface */
2339: const PetscInt gidx = g*NcJ+gc; /* Trial function basis index */
2340: const PetscInt j = offsetJ+NbJ*t+g; /* Element matrix column */
2341: const PetscInt fOff = eOffset+i*totDim+j;
2343: elemMat[fOff] += tmpBasisI[fidx]*g0[sc*NcJ*Nt+tc]*tmpBasisJ[gidx];
2344: for (df = 0; df < dE; ++df) {
2345: elemMat[fOff] += tmpBasisI[fidx]*g1[(sc*NcJ*Nt+tc)*dE+df]*tmpBasisDerJ[gidx*dE+df];
2346: elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g2[(sc*NcJ*Nt+tc)*dE+df]*tmpBasisJ[gidx];
2347: for (dg = 0; dg < dE; ++dg) {
2348: elemMat[fOff] += tmpBasisDerI[fidx*dE+df]*g3[((sc*NcJ*Nt+tc)*dE+df)*dE+dg]*tmpBasisDerJ[gidx*dE+dg];
2349: }
2350: }
2351: }
2352: }
2353: }
2354: }
2355: }
2356: }
2357: return(0);
2358: }
2360: PetscErrorCode PetscFECreateCellGeometry(PetscFE fe, PetscQuadrature quad, PetscFEGeom *cgeom)
2361: {
2362: PetscDualSpace dsp;
2363: DM dm;
2364: PetscQuadrature quadDef;
2365: PetscInt dim, cdim, Nq;
2366: PetscErrorCode ierr;
2369: PetscFEGetDualSpace(fe, &dsp);
2370: PetscDualSpaceGetDM(dsp, &dm);
2371: DMGetDimension(dm, &dim);
2372: DMGetCoordinateDim(dm, &cdim);
2373: PetscFEGetQuadrature(fe, &quadDef);
2374: quad = quad ? quad : quadDef;
2375: PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL);
2376: PetscMalloc1(Nq*cdim, &cgeom->v);
2377: PetscMalloc1(Nq*cdim*cdim, &cgeom->J);
2378: PetscMalloc1(Nq*cdim*cdim, &cgeom->invJ);
2379: PetscMalloc1(Nq, &cgeom->detJ);
2380: cgeom->dim = dim;
2381: cgeom->dimEmbed = cdim;
2382: cgeom->numCells = 1;
2383: cgeom->numPoints = Nq;
2384: DMPlexComputeCellGeometryFEM(dm, 0, quad, cgeom->v, cgeom->J, cgeom->invJ, cgeom->detJ);
2385: return(0);
2386: }
2388: PetscErrorCode PetscFEDestroyCellGeometry(PetscFE fe, PetscFEGeom *cgeom)
2389: {
2393: PetscFree(cgeom->v);
2394: PetscFree(cgeom->J);
2395: PetscFree(cgeom->invJ);
2396: PetscFree(cgeom->detJ);
2397: return(0);
2398: }