xref: /petsc/src/dm/dt/dualspace/impls/refined/dualspacerefined.c (revision bcda9346efad4e5ba2d553af84eb238771ba1e25)
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, &section));
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