xref: /petsc/src/dm/dt/dualspace/impls/refined/dualspacerefined.c (revision c3b5f7ba6bc5ce25a01a67bb37ba5d34b02bbbd7)
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 on PetscDualSpace
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: PetscFERefine()
22 @*/
23 PetscErrorCode PetscDualSpaceRefinedSetCellSpaces(PetscDualSpace sp, const PetscDualSpace cellSpaces[])
24 {
25   PetscFunctionBegin;
26   PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
27   PetscValidPointer(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(0);
31 }
32 
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) {
44 
45     PetscCall(PetscCalloc1(pEnd-pStart,&(sp->pointSpaces)));
46   }
47   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
48   for (c = 0; c < cEnd - cStart; c++) {
49     PetscCall(PetscObjectReference((PetscObject)cellSpaces[c]));
50     PetscCall(PetscDualSpaceDestroy(&(sp->pointSpaces[c + cStart - pStart])));
51     sp->pointSpaces[c+cStart-pStart] = cellSpaces[c];
52   }
53   PetscFunctionReturn(0);
54 }
55 
56 static PetscErrorCode PetscDualSpaceDestroy_Refined(PetscDualSpace sp)
57 {
58   PetscDualSpace_Refined *ref = (PetscDualSpace_Refined *) sp->data;
59 
60   PetscFunctionBegin;
61   PetscCall(PetscObjectComposeFunction((PetscObject) sp, "PetscDualSpaceRefinedSetCellSpaces_C", NULL));
62   PetscCall(PetscFree(ref));
63   PetscFunctionReturn(0);
64 }
65 
66 static PetscErrorCode PetscDualSpaceSetUp_Refined(PetscDualSpace sp)
67 {
68   PetscInt pStart, pEnd, depth;
69   PetscInt cStart, cEnd, c, spdim;
70   PetscInt h;
71   DM dm;
72   PetscSection   section;
73 
74   PetscFunctionBegin;
75   PetscCall(PetscDualSpaceGetDM(sp, &dm));
76   PetscCall(DMPlexGetDepth(dm, &depth));
77   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
78   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
79   for (c = cStart; c < cEnd; c++) {
80     if (sp->pointSpaces[c-pStart]) {
81       PetscInt ccStart, ccEnd;
82       PetscCheckFalse(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");
83       PetscCheckFalse(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");
84       PetscCall(DMPlexGetHeightStratum(sp->pointSpaces[c-pStart]->dm, 0, &ccStart, &ccEnd));
85       PetscCheckFalse(ccEnd - ccStart != 1,PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_INCOMP, "All cell spaces must have a single cell themselves");
86     }
87   }
88   for (c = cStart; c < cEnd; c++) {
89     if (sp->pointSpaces[c-pStart]) {
90       PetscBool cUniform;
91 
92       PetscCall(PetscDualSpaceGetUniform(sp->pointSpaces[c-pStart],&cUniform));
93       if (!cUniform) break;
94     }
95     if ((c > cStart) && sp->pointSpaces[c-pStart] != sp->pointSpaces[c-1-pStart]) break;
96   }
97   if (c < cEnd) sp->uniform = PETSC_FALSE;
98   for (h = 0; h < depth; h++) {
99     PetscInt hStart, hEnd;
100 
101     PetscCall(DMPlexGetHeightStratum(dm, h, &hStart, &hEnd));
102     for (c = hStart; c < hEnd; c++) {
103       PetscInt coneSize, e;
104       PetscDualSpace cspace = sp->pointSpaces[c-pStart];
105       const PetscInt *cone;
106       const PetscInt *refCone;
107 
108       if (!cspace) continue;
109       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
110       PetscCall(DMPlexGetCone(dm, c, &cone));
111       PetscCall(DMPlexGetCone(cspace->dm, 0, &refCone));
112       for (e = 0; e < coneSize; e++) {
113         PetscInt point = cone[e];
114         PetscInt refpoint = refCone[e];
115         PetscDualSpace espace;
116 
117         PetscCall(PetscDualSpaceGetPointSubspace(cspace,refpoint,&espace));
118         if (sp->pointSpaces[point-pStart] == NULL) {
119           PetscCall(PetscObjectReference((PetscObject)espace));
120           sp->pointSpaces[point-pStart] = espace;
121         }
122       }
123     }
124   }
125   PetscCall(PetscDualSpaceGetSection(sp, &section));
126   PetscCall(PetscDualSpaceGetDimension(sp, &spdim));
127   PetscCall(PetscMalloc1(spdim, &(sp->functional)));
128   PetscCall(PetscDualSpacePushForwardSubspaces_Internal(sp, pStart, pEnd));
129   PetscFunctionReturn(0);
130 }
131 
132 static PetscErrorCode PetscDualSpaceRefinedView_Ascii(PetscDualSpace sp, PetscViewer viewer)
133 {
134   PetscFunctionBegin;
135   if (sp->dm && sp->pointSpaces) {
136     PetscInt pStart, pEnd;
137     PetscInt cStart, cEnd, c;
138 
139     PetscCall(DMPlexGetChart(sp->dm, &pStart, &pEnd));
140     PetscCall(DMPlexGetHeightStratum(sp->dm, 0, &cStart, &cEnd));
141     PetscCall(PetscViewerASCIIPrintf(viewer, "Refined dual space:\n"));
142     PetscCall(PetscViewerASCIIPushTab(viewer));
143     for (c = cStart; c < cEnd; c++) {
144       if (!sp->pointSpaces[c-pStart]) {
145         PetscCall(PetscViewerASCIIPrintf(viewer, "Cell space %D not set yet\n", c));
146       } else {
147         PetscCall(PetscViewerASCIIPrintf(viewer, "Cell space %D:ot set yet\n", c));
148         PetscCall(PetscViewerASCIIPushTab(viewer));
149         PetscCall(PetscDualSpaceView(sp->pointSpaces[c-pStart],viewer));
150         PetscCall(PetscViewerASCIIPopTab(viewer));
151       }
152     }
153     PetscCall(PetscViewerASCIIPopTab(viewer));
154   } else {
155     PetscCall(PetscViewerASCIIPrintf(viewer, "Refined dual space: (cell spaces not set yet)\n"));
156   }
157   PetscFunctionReturn(0);
158 }
159 
160 static PetscErrorCode PetscDualSpaceView_Refined(PetscDualSpace sp, PetscViewer viewer)
161 {
162   PetscBool      iascii;
163 
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
166   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
167   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii));
168   if (iascii) PetscCall(PetscDualSpaceRefinedView_Ascii(sp, viewer));
169   PetscFunctionReturn(0);
170 }
171 
172 static PetscErrorCode PetscDualSpaceInitialize_Refined(PetscDualSpace sp)
173 {
174   PetscFunctionBegin;
175   sp->ops->destroy              = PetscDualSpaceDestroy_Refined;
176   sp->ops->view                 = PetscDualSpaceView_Refined;
177   sp->ops->setfromoptions       = NULL;
178   sp->ops->duplicate            = NULL;
179   sp->ops->setup                = PetscDualSpaceSetUp_Refined;
180   sp->ops->createheightsubspace = NULL;
181   sp->ops->createpointsubspace  = NULL;
182   sp->ops->getsymmetries        = NULL;
183   sp->ops->apply                = PetscDualSpaceApplyDefault;
184   sp->ops->applyall             = PetscDualSpaceApplyAllDefault;
185   sp->ops->applyint             = PetscDualSpaceApplyInteriorDefault;
186   sp->ops->createalldata        = PetscDualSpaceCreateAllDataDefault;
187   sp->ops->createintdata        = PetscDualSpaceCreateInteriorDataDefault;
188   PetscFunctionReturn(0);
189 }
190 
191 /*MC
192   PETSCDUALSPACEREFINED = "refined" - A PetscDualSpace object that defines the joint dual space of a group of cells, usually refined from one larger cell
193 
194   Level: intermediate
195 
196 .seealso: PetscDualSpaceType, PetscDualSpaceCreate(), PetscDualSpaceSetType()
197 M*/
198 PETSC_EXTERN PetscErrorCode PetscDualSpaceCreate_Refined(PetscDualSpace sp)
199 {
200   PetscDualSpace_Refined *ref;
201 
202   PetscFunctionBegin;
203   PetscValidHeaderSpecific(sp, PETSCDUALSPACE_CLASSID, 1);
204   PetscCall(PetscNewLog(sp,&ref));
205   sp->data = ref;
206 
207   PetscCall(PetscDualSpaceInitialize_Refined(sp));
208   PetscCall(PetscObjectComposeFunction((PetscObject) sp, "PetscDualSpaceRefinedSetCellSpaces_C", PetscDualSpaceRefinedSetCellSpaces_Refined));
209   PetscFunctionReturn(0);
210 }
211