1 #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
2 #include <petscdmplex.h>
3
4 typedef struct {
5 PetscInt dummy;
6 } PetscDualSpace_Refined;
7
8 /*@
9 PetscDualSpaceRefinedSetCellSpaces - Set the dual spaces for the closures of each of the cells
10 in the multicell `DM` of a `PetscDualSpace`
11
12 Collective
13
14 Input Parameters:
15 + sp - a `PetscDualSpace`
16 - cellSpaces - one `PetscDualSpace` for each of the cells. The reference count of each cell space will be incremented,
17 so the user is still responsible for these spaces afterwards
18
19 Level: intermediate
20
21 .seealso: `PETSCDUALSPACEREFINED`, `PetscDualSpace`, `PetscFERefine()`
22 @*/
PetscDualSpaceRefinedSetCellSpaces(PetscDualSpace sp,const PetscDualSpace cellSpaces[])23 PetscErrorCode PetscDualSpaceRefinedSetCellSpaces(PetscDualSpace sp, const PetscDualSpace cellSpaces[])
24 {
25 PetscFunctionBegin;
26 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
27 PetscAssertPointer(cellSpaces, 2);
28 PetscCheck(!sp->setupcalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change cell spaces after setup is called");
29 PetscTryMethod(sp, "PetscDualSpaceRefinedSetCellSpaces_C", (PetscDualSpace, const PetscDualSpace[]), (sp, cellSpaces));
30 PetscFunctionReturn(PETSC_SUCCESS);
31 }
32
PetscDualSpaceRefinedSetCellSpaces_Refined(PetscDualSpace sp,const PetscDualSpace cellSpaces[])33 static PetscErrorCode PetscDualSpaceRefinedSetCellSpaces_Refined(PetscDualSpace sp, const PetscDualSpace cellSpaces[])
34 {
35 DM dm;
36 PetscInt pStart, pEnd;
37 PetscInt cStart, cEnd, c;
38
39 PetscFunctionBegin;
40 dm = sp->dm;
41 PetscCheck(dm, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "PetscDualSpace must have a DM (PetscDualSpaceSetDM()) before calling PetscDualSpaceRefinedSetCellSpaces");
42 PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
43 if (!sp->pointSpaces) PetscCall(PetscCalloc1(pEnd - pStart, &sp->pointSpaces));
44 PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
45 for (c = 0; c < cEnd - cStart; c++) {
46 PetscCall(PetscObjectReference((PetscObject)cellSpaces[c]));
47 PetscCall(PetscDualSpaceDestroy(&sp->pointSpaces[c + cStart - pStart]));
48 sp->pointSpaces[c + cStart - pStart] = cellSpaces[c];
49 }
50 PetscFunctionReturn(PETSC_SUCCESS);
51 }
52
PetscDualSpaceDestroy_Refined(PetscDualSpace sp)53 static PetscErrorCode PetscDualSpaceDestroy_Refined(PetscDualSpace sp)
54 {
55 PetscDualSpace_Refined *ref = (PetscDualSpace_Refined *)sp->data;
56
57 PetscFunctionBegin;
58 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscDualSpaceRefinedSetCellSpaces_C", NULL));
59 PetscCall(PetscFree(ref));
60 PetscFunctionReturn(PETSC_SUCCESS);
61 }
62
PetscDualSpaceSetUp_Refined(PetscDualSpace sp)63 static PetscErrorCode PetscDualSpaceSetUp_Refined(PetscDualSpace sp)
64 {
65 PetscInt pStart, pEnd, depth;
66 PetscInt cStart, cEnd, c, spdim;
67 PetscInt h;
68 DM dm;
69 PetscSection section;
70
71 PetscFunctionBegin;
72 PetscCall(PetscDualSpaceGetDM(sp, &dm));
73 PetscCall(DMPlexGetDepth(dm, &depth));
74 PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
75 PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
76 for (c = cStart; c < cEnd; c++) {
77 if (sp->pointSpaces[c - pStart]) {
78 PetscInt ccStart, ccEnd;
79 PetscCheck(sp->pointSpaces[c - pStart]->k == sp->k, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_INCOMP, "All cell spaces must have the same form degree as the refined dual space");
80 PetscCheck(sp->pointSpaces[c - pStart]->Nc == sp->Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_INCOMP, "All cell spaces must have the same number of components as the refined dual space");
81 PetscCall(DMPlexGetHeightStratum(sp->pointSpaces[c - pStart]->dm, 0, &ccStart, &ccEnd));
82 PetscCheck(ccEnd - ccStart == 1, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_INCOMP, "All cell spaces must have a single cell themselves");
83 }
84 }
85 for (c = cStart; c < cEnd; c++) {
86 if (sp->pointSpaces[c - pStart]) {
87 PetscBool cUniform;
88
89 PetscCall(PetscDualSpaceGetUniform(sp->pointSpaces[c - pStart], &cUniform));
90 if (!cUniform) break;
91 }
92 if ((c > cStart) && sp->pointSpaces[c - pStart] != sp->pointSpaces[c - 1 - pStart]) break;
93 }
94 if (c < cEnd) sp->uniform = PETSC_FALSE;
95 for (h = 0; h < depth; h++) {
96 PetscInt hStart, hEnd;
97
98 PetscCall(DMPlexGetHeightStratum(dm, h, &hStart, &hEnd));
99 for (c = hStart; c < hEnd; c++) {
100 PetscInt coneSize, e;
101 PetscDualSpace cspace = sp->pointSpaces[c - pStart];
102 const PetscInt *cone;
103 const PetscInt *refCone;
104
105 if (!cspace) continue;
106 PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
107 PetscCall(DMPlexGetCone(dm, c, &cone));
108 PetscCall(DMPlexGetCone(cspace->dm, 0, &refCone));
109 for (e = 0; e < coneSize; e++) {
110 PetscInt point = cone[e];
111 PetscInt refpoint = refCone[e];
112 PetscDualSpace espace;
113
114 PetscCall(PetscDualSpaceGetPointSubspace(cspace, refpoint, &espace));
115 if (sp->pointSpaces[point - pStart] == NULL) {
116 PetscCall(PetscObjectReference((PetscObject)espace));
117 sp->pointSpaces[point - pStart] = espace;
118 }
119 }
120 }
121 }
122 PetscCall(PetscDualSpaceGetSection(sp, §ion));
123 PetscCall(PetscDualSpaceGetDimension(sp, &spdim));
124 PetscCall(PetscMalloc1(spdim, &sp->functional));
125 PetscCall(PetscDualSpacePushForwardSubspaces_Internal(sp, pStart, pEnd));
126 PetscFunctionReturn(PETSC_SUCCESS);
127 }
128
PetscDualSpaceRefinedView_Ascii(PetscDualSpace sp,PetscViewer viewer)129 static PetscErrorCode PetscDualSpaceRefinedView_Ascii(PetscDualSpace sp, PetscViewer viewer)
130 {
131 PetscFunctionBegin;
132 if (sp->dm && sp->pointSpaces) {
133 PetscInt pStart, pEnd;
134 PetscInt cStart, cEnd, c;
135
136 PetscCall(DMPlexGetChart(sp->dm, &pStart, &pEnd));
137 PetscCall(DMPlexGetHeightStratum(sp->dm, 0, &cStart, &cEnd));
138 PetscCall(PetscViewerASCIIPrintf(viewer, "Refined dual space:\n"));
139 PetscCall(PetscViewerASCIIPushTab(viewer));
140 for (c = cStart; c < cEnd; c++) {
141 if (!sp->pointSpaces[c - pStart]) {
142 PetscCall(PetscViewerASCIIPrintf(viewer, "Cell space %" PetscInt_FMT " not set yet\n", c));
143 } else {
144 PetscCall(PetscViewerASCIIPrintf(viewer, "Cell space %" PetscInt_FMT ":ot set yet\n", c));
145 PetscCall(PetscViewerASCIIPushTab(viewer));
146 PetscCall(PetscDualSpaceView(sp->pointSpaces[c - pStart], viewer));
147 PetscCall(PetscViewerASCIIPopTab(viewer));
148 }
149 }
150 PetscCall(PetscViewerASCIIPopTab(viewer));
151 } else PetscCall(PetscViewerASCIIPrintf(viewer, "Refined dual space: (cell spaces not set yet)\n"));
152 PetscFunctionReturn(PETSC_SUCCESS);
153 }
154
PetscDualSpaceView_Refined(PetscDualSpace sp,PetscViewer viewer)155 static PetscErrorCode PetscDualSpaceView_Refined(PetscDualSpace sp, PetscViewer viewer)
156 {
157 PetscBool isascii;
158
159 PetscFunctionBegin;
160 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
161 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
162 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
163 if (isascii) PetscCall(PetscDualSpaceRefinedView_Ascii(sp, viewer));
164 PetscFunctionReturn(PETSC_SUCCESS);
165 }
166
PetscDualSpaceInitialize_Refined(PetscDualSpace sp)167 static PetscErrorCode PetscDualSpaceInitialize_Refined(PetscDualSpace sp)
168 {
169 PetscFunctionBegin;
170 sp->ops->destroy = PetscDualSpaceDestroy_Refined;
171 sp->ops->view = PetscDualSpaceView_Refined;
172 sp->ops->setfromoptions = NULL;
173 sp->ops->duplicate = NULL;
174 sp->ops->setup = PetscDualSpaceSetUp_Refined;
175 sp->ops->createheightsubspace = NULL;
176 sp->ops->createpointsubspace = NULL;
177 sp->ops->getsymmetries = NULL;
178 sp->ops->apply = PetscDualSpaceApplyDefault;
179 sp->ops->applyall = PetscDualSpaceApplyAllDefault;
180 sp->ops->applyint = PetscDualSpaceApplyInteriorDefault;
181 sp->ops->createalldata = PetscDualSpaceCreateAllDataDefault;
182 sp->ops->createintdata = PetscDualSpaceCreateInteriorDataDefault;
183 PetscFunctionReturn(PETSC_SUCCESS);
184 }
185
186 /*MC
187 PETSCDUALSPACEREFINED = "refined" - A `PetscDualSpaceType` that defines the joint dual space of a group of cells, usually refined from one larger cell
188
189 Level: intermediate
190
191 .seealso: `PetscDualSpace`, `PetscDualSpaceType`, `PetscDualSpaceRefinedSetCellSpaces`, `PetscDualSpaceCreate()`, `PetscDualSpaceSetType()`
192 M*/
PetscDualSpaceCreate_Refined(PetscDualSpace sp)193 PETSC_EXTERN PetscErrorCode PetscDualSpaceCreate_Refined(PetscDualSpace sp)
194 {
195 PetscDualSpace_Refined *ref;
196
197 PetscFunctionBegin;
198 PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
199 PetscCall(PetscNew(&ref));
200 sp->data = ref;
201
202 PetscCall(PetscDualSpaceInitialize_Refined(sp));
203 PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscDualSpaceRefinedSetCellSpaces_C", PetscDualSpaceRefinedSetCellSpaces_Refined));
204 PetscFunctionReturn(PETSC_SUCCESS);
205 }
206