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