Actual source code: dspacesimple.c
1: #include <petsc/private/petscfeimpl.h>
2: #include <petscdmplex.h>
4: static PetscErrorCode PetscDualSpaceSetUp_Simple(PetscDualSpace sp)
5: {
6: PetscDualSpace_Simple *s = (PetscDualSpace_Simple *)sp->data;
7: DM dm = sp->dm;
8: PetscInt dim, pStart, pEnd;
9: PetscSection section;
11: PetscFunctionBegin;
12: PetscCall(DMGetDimension(dm, &dim));
13: PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
14: PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ion));
15: PetscCall(PetscSectionSetChart(section, pStart, pEnd));
16: PetscCall(PetscSectionSetDof(section, pStart, s->dim));
17: PetscCall(PetscSectionSetUp(section));
18: sp->pointSection = section;
19: PetscFunctionReturn(PETSC_SUCCESS);
20: }
22: static PetscErrorCode PetscDualSpaceDestroy_Simple(PetscDualSpace sp)
23: {
24: PetscDualSpace_Simple *s = (PetscDualSpace_Simple *)sp->data;
26: PetscFunctionBegin;
27: PetscCall(PetscFree(s->numDof));
28: PetscCall(PetscFree(s));
29: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscDualSpaceSimpleSetDimension_C", NULL));
30: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscDualSpaceSimpleSetFunctional_C", NULL));
31: PetscFunctionReturn(PETSC_SUCCESS);
32: }
34: static PetscErrorCode PetscDualSpaceDuplicate_Simple(PetscDualSpace sp, PetscDualSpace spNew)
35: {
36: PetscInt dim, d;
38: PetscFunctionBegin;
39: PetscCall(PetscDualSpaceGetDimension(sp, &dim));
40: PetscCall(PetscDualSpaceSimpleSetDimension(spNew, dim));
41: for (d = 0; d < dim; ++d) {
42: PetscQuadrature q;
44: PetscCall(PetscDualSpaceGetFunctional(sp, d, &q));
45: PetscCall(PetscDualSpaceSimpleSetFunctional(spNew, d, q));
46: }
47: PetscFunctionReturn(PETSC_SUCCESS);
48: }
50: static PetscErrorCode PetscDualSpaceSetFromOptions_Simple(PetscDualSpace sp, PetscOptionItems *PetscOptionsObject)
51: {
52: PetscFunctionBegin;
53: PetscFunctionReturn(PETSC_SUCCESS);
54: }
56: static PetscErrorCode PetscDualSpaceSimpleSetDimension_Simple(PetscDualSpace sp, const PetscInt dim)
57: {
58: PetscDualSpace_Simple *s = (PetscDualSpace_Simple *)sp->data;
59: DM dm;
60: PetscInt spatialDim, f;
62: PetscFunctionBegin;
63: for (f = 0; f < s->dim; ++f) PetscCall(PetscQuadratureDestroy(&sp->functional[f]));
64: PetscCall(PetscFree(sp->functional));
65: s->dim = dim;
66: PetscCall(PetscCalloc1(s->dim, &sp->functional));
67: PetscCall(PetscFree(s->numDof));
68: PetscCall(PetscDualSpaceGetDM(sp, &dm));
69: PetscCall(DMGetCoordinateDim(dm, &spatialDim));
70: PetscCall(PetscCalloc1(spatialDim + 1, &s->numDof));
71: s->numDof[spatialDim] = dim;
72: PetscFunctionReturn(PETSC_SUCCESS);
73: }
75: static PetscErrorCode PetscDualSpaceSimpleSetFunctional_Simple(PetscDualSpace sp, PetscInt f, PetscQuadrature q)
76: {
77: PetscDualSpace_Simple *s = (PetscDualSpace_Simple *)sp->data;
78: PetscReal *weights;
79: PetscInt Nc, c, Nq, p;
81: PetscFunctionBegin;
82: PetscCheck(!(f < 0) && !(f >= s->dim), PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Basis index %" PetscInt_FMT " not in [0, %" PetscInt_FMT ")", f, s->dim);
83: PetscCall(PetscQuadratureDuplicate(q, &sp->functional[f]));
84: /* Reweight so that it has unit volume: Do we want to do this for Nc > 1? */
85: PetscCall(PetscQuadratureGetData(sp->functional[f], NULL, &Nc, &Nq, NULL, (const PetscReal **)&weights));
86: for (c = 0; c < Nc; ++c) {
87: PetscReal vol = 0.0;
89: for (p = 0; p < Nq; ++p) vol += weights[p * Nc + c];
90: for (p = 0; p < Nq; ++p) weights[p * Nc + c] /= (vol == 0.0 ? 1.0 : vol);
91: }
92: PetscFunctionReturn(PETSC_SUCCESS);
93: }
95: /*@
96: PetscDualSpaceSimpleSetDimension - Set the number of functionals in the dual space basis
98: Logically Collective
100: Input Parameters:
101: + sp - the `PetscDualSpace`
102: - dim - the basis dimension
104: Level: intermediate
106: .seealso: `PETSCDUALSPACESIMPLE`, `PetscDualSpace`, `PetscDualSpaceSimpleSetFunctional()`
107: @*/
108: PetscErrorCode PetscDualSpaceSimpleSetDimension(PetscDualSpace sp, PetscInt dim)
109: {
110: PetscFunctionBegin;
113: PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change dimension after dual space is set up");
114: PetscTryMethod(sp, "PetscDualSpaceSimpleSetDimension_C", (PetscDualSpace, PetscInt), (sp, dim));
115: PetscFunctionReturn(PETSC_SUCCESS);
116: }
118: /*@
119: PetscDualSpaceSimpleSetFunctional - Set the given basis functional for this dual space
121: Not Collective
123: Input Parameters:
124: + sp - the `PetscDualSpace`
125: . func - the basis index
126: - q - the basis functional
128: Level: intermediate
130: Note:
131: The quadrature will be reweighted so that it has unit volume.
133: .seealso: `PETSCDUALSPACESIMPLE`, `PetscDualSpace`, `PetscDualSpaceSimpleSetDimension()`
134: @*/
135: PetscErrorCode PetscDualSpaceSimpleSetFunctional(PetscDualSpace sp, PetscInt func, PetscQuadrature q)
136: {
137: PetscFunctionBegin;
139: PetscTryMethod(sp, "PetscDualSpaceSimpleSetFunctional_C", (PetscDualSpace, PetscInt, PetscQuadrature), (sp, func, q));
140: PetscFunctionReturn(PETSC_SUCCESS);
141: }
143: static PetscErrorCode PetscDualSpaceInitialize_Simple(PetscDualSpace sp)
144: {
145: PetscFunctionBegin;
146: sp->ops->setfromoptions = PetscDualSpaceSetFromOptions_Simple;
147: sp->ops->setup = PetscDualSpaceSetUp_Simple;
148: sp->ops->view = NULL;
149: sp->ops->destroy = PetscDualSpaceDestroy_Simple;
150: sp->ops->duplicate = PetscDualSpaceDuplicate_Simple;
151: sp->ops->createheightsubspace = NULL;
152: sp->ops->createpointsubspace = NULL;
153: sp->ops->getsymmetries = NULL;
154: sp->ops->apply = PetscDualSpaceApplyDefault;
155: sp->ops->applyall = PetscDualSpaceApplyAllDefault;
156: sp->ops->applyint = PetscDualSpaceApplyInteriorDefault;
157: sp->ops->createalldata = PetscDualSpaceCreateAllDataDefault;
158: sp->ops->createintdata = PetscDualSpaceCreateInteriorDataDefault;
159: PetscFunctionReturn(PETSC_SUCCESS);
160: }
162: /*MC
163: PETSCDUALSPACESIMPLE = "simple" - A `PetscDualSpaceType` that encapsulates a dual space of functionals provided with `PetscDualSpaceSimpleSetFunctional()`
165: Level: intermediate
167: Developer Note:
168: It is not clear this has a good name
170: .seealso: `PetscDualSpace`, `PetscDualSpaceSimpleSetFunctional()`, `PetscDualSpaceType`, `PetscDualSpaceCreate()`, `PetscDualSpaceSetType()`
171: M*/
173: PETSC_EXTERN PetscErrorCode PetscDualSpaceCreate_Simple(PetscDualSpace sp)
174: {
175: PetscDualSpace_Simple *s;
177: PetscFunctionBegin;
179: PetscCall(PetscNew(&s));
180: sp->data = s;
182: s->dim = 0;
183: s->numDof = NULL;
185: PetscCall(PetscDualSpaceInitialize_Simple(sp));
186: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscDualSpaceSimpleSetDimension_C", PetscDualSpaceSimpleSetDimension_Simple));
187: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscDualSpaceSimpleSetFunctional_C", PetscDualSpaceSimpleSetFunctional_Simple));
188: PetscFunctionReturn(PETSC_SUCCESS);
189: }