1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/
2af0996ceSBarry Smith #include <petsc/private/isimpl.h>
3af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h>
4d6a7ad0dSToby Isaac #include <petscsf.h>
50c37af3bSToby Isaac #include <petscds.h>
6d6a7ad0dSToby Isaac
70e3d61c9SBarry Smith /* hierarchy routines */
8d6a7ad0dSToby Isaac
9d6a7ad0dSToby Isaac /*@
10d6a7ad0dSToby Isaac DMPlexSetReferenceTree - set the reference tree for hierarchically non-conforming meshes.
11d6a7ad0dSToby Isaac
1220f4b53cSBarry Smith Not Collective
13d6a7ad0dSToby Isaac
14d6a7ad0dSToby Isaac Input Parameters:
15a1cb98faSBarry Smith + dm - The `DMPLEX` object
16a1cb98faSBarry Smith - ref - The reference tree `DMPLEX` object
17d6a7ad0dSToby Isaac
180b7167a0SToby Isaac Level: intermediate
19d6a7ad0dSToby Isaac
201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`,`DMPlexGetReferenceTree()`, `DMPlexCreateDefaultReferenceTree()`
21d6a7ad0dSToby Isaac @*/
DMPlexSetReferenceTree(DM dm,DM ref)22d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref)
23d71ae5a4SJacob Faibussowitsch {
24d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
25d6a7ad0dSToby Isaac
26d6a7ad0dSToby Isaac PetscFunctionBegin;
27d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28ad540459SPierre Jolivet if (ref) PetscValidHeaderSpecific(ref, DM_CLASSID, 2);
299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)ref));
309566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree));
31d6a7ad0dSToby Isaac mesh->referenceTree = ref;
323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
33d6a7ad0dSToby Isaac }
34d6a7ad0dSToby Isaac
35d6a7ad0dSToby Isaac /*@
36d6a7ad0dSToby Isaac DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes.
37d6a7ad0dSToby Isaac
3820f4b53cSBarry Smith Not Collective
39d6a7ad0dSToby Isaac
402fe279fdSBarry Smith Input Parameter:
41a1cb98faSBarry Smith . dm - The `DMPLEX` object
42d6a7ad0dSToby Isaac
432fe279fdSBarry Smith Output Parameter:
44a1cb98faSBarry Smith . ref - The reference tree `DMPLEX` object
45d6a7ad0dSToby Isaac
460b7167a0SToby Isaac Level: intermediate
47d6a7ad0dSToby Isaac
48d3a532e9SStefano Zampini Developer Notes:
49d3a532e9SStefano Zampini The reference tree is shallow copied during `DMClone()`, thus it is may be shared by different `DM`s.
50d3a532e9SStefano Zampini It is not a topological-only object, since some parts of the library use its local section to compute
51d3a532e9SStefano Zampini interpolation and injection matrices. This may lead to unexpected failures during those calls.
52d3a532e9SStefano Zampini
531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetReferenceTree()`, `DMPlexCreateDefaultReferenceTree()`
54d6a7ad0dSToby Isaac @*/
DMPlexGetReferenceTree(DM dm,DM * ref)55d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref)
56d71ae5a4SJacob Faibussowitsch {
57d6a7ad0dSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
58d6a7ad0dSToby Isaac
59d6a7ad0dSToby Isaac PetscFunctionBegin;
60d6a7ad0dSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
614f572ea9SToby Isaac PetscAssertPointer(ref, 2);
62d6a7ad0dSToby Isaac *ref = mesh->referenceTree;
633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
64d6a7ad0dSToby Isaac }
65d6a7ad0dSToby Isaac
DMPlexReferenceTreeGetChildSymmetry_Default(DM dm,PetscInt parent,PetscInt parentOrientA,PetscInt childOrientA,PetscInt childA,PetscInt parentOrientB,PetscInt * childOrientB,PetscInt * childB)66d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildSymmetry_Default(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB)
67d71ae5a4SJacob Faibussowitsch {
68dcbd3bf7SToby Isaac PetscInt coneSize, dStart, dEnd, dim, ABswap, oAvert, oBvert, ABswapVert;
69dcbd3bf7SToby Isaac
70dcbd3bf7SToby Isaac PetscFunctionBegin;
71dcbd3bf7SToby Isaac if (parentOrientA == parentOrientB) {
72dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = childOrientA;
73dcbd3bf7SToby Isaac if (childB) *childB = childA;
743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
75dcbd3bf7SToby Isaac }
76dcbd3bf7SToby Isaac for (dim = 0; dim < 3; dim++) {
779566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, &dStart, &dEnd));
78ad540459SPierre Jolivet if (parent >= dStart && parent <= dEnd) break;
79dcbd3bf7SToby Isaac }
8063a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot perform child symmetry for %" PetscInt_FMT "-cells", dim);
8128b400f6SJacob Faibussowitsch PetscCheck(dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "A vertex has no children");
82dcbd3bf7SToby Isaac if (childA < dStart || childA >= dEnd) {
83dcbd3bf7SToby Isaac /* this is a lower-dimensional child: bootstrap */
84dcbd3bf7SToby Isaac PetscInt size, i, sA = -1, sB, sOrientB, sConeSize;
85dcbd3bf7SToby Isaac const PetscInt *supp, *coneA, *coneB, *oA, *oB;
86dcbd3bf7SToby Isaac
879566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, childA, &size));
889566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, childA, &supp));
89dcbd3bf7SToby Isaac
90dcbd3bf7SToby Isaac /* find a point sA in supp(childA) that has the same parent */
91dcbd3bf7SToby Isaac for (i = 0; i < size; i++) {
92dcbd3bf7SToby Isaac PetscInt sParent;
93dcbd3bf7SToby Isaac
94dcbd3bf7SToby Isaac sA = supp[i];
95dcbd3bf7SToby Isaac if (sA == parent) continue;
969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, sA, &sParent, NULL));
97ad540459SPierre Jolivet if (sParent == parent) break;
98dcbd3bf7SToby Isaac }
9908401ef6SPierre Jolivet PetscCheck(i != size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "could not find support in children");
100dcbd3bf7SToby Isaac /* find out which point sB is in an equivalent position to sA under
101dcbd3bf7SToby Isaac * parentOrientB */
1029566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry_Default(dm, parent, parentOrientA, 0, sA, parentOrientB, &sOrientB, &sB));
1039566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, sA, &sConeSize));
1049566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sA, &coneA));
1059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, sB, &coneB));
1069566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sA, &oA));
1079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, sB, &oB));
108dcbd3bf7SToby Isaac /* step through the cone of sA in natural order */
109dcbd3bf7SToby Isaac for (i = 0; i < sConeSize; i++) {
110dcbd3bf7SToby Isaac if (coneA[i] == childA) {
111dcbd3bf7SToby Isaac /* if childA is at position i in coneA,
112dcbd3bf7SToby Isaac * then we want the point that is at sOrientB*i in coneB */
113dcbd3bf7SToby Isaac PetscInt j = (sOrientB >= 0) ? ((sOrientB + i) % sConeSize) : ((sConeSize - (sOrientB + 1) - i) % sConeSize);
114dcbd3bf7SToby Isaac if (childB) *childB = coneB[j];
115dcbd3bf7SToby Isaac if (childOrientB) {
116b5a892a1SMatthew G. Knepley DMPolytopeType ct;
117dcbd3bf7SToby Isaac PetscInt oBtrue;
118dcbd3bf7SToby Isaac
1199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, childA, &coneSize));
120dcbd3bf7SToby Isaac /* compose sOrientB and oB[j] */
1211dca8a05SBarry Smith PetscCheck(coneSize == 0 || coneSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected a vertex or an edge");
122b5a892a1SMatthew G. Knepley ct = coneSize ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT;
123dcbd3bf7SToby Isaac /* we may have to flip an edge */
124b5a892a1SMatthew G. Knepley oBtrue = (sOrientB >= 0) ? oB[j] : DMPolytopeTypeComposeOrientation(ct, -1, oB[j]);
125b5a892a1SMatthew G. Knepley oBtrue = DMPolytopeConvertNewOrientation_Internal(ct, oBtrue);
126b5a892a1SMatthew G. Knepley ABswap = DihedralSwap(coneSize, DMPolytopeConvertNewOrientation_Internal(ct, oA[i]), oBtrue);
127dcbd3bf7SToby Isaac *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap);
128dcbd3bf7SToby Isaac }
129dcbd3bf7SToby Isaac break;
130dcbd3bf7SToby Isaac }
131dcbd3bf7SToby Isaac }
13208401ef6SPierre Jolivet PetscCheck(i != sConeSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "support cone mismatch");
1333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
134dcbd3bf7SToby Isaac }
135dcbd3bf7SToby Isaac /* get the cone size and symmetry swap */
1369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, parent, &coneSize));
137dcbd3bf7SToby Isaac ABswap = DihedralSwap(coneSize, parentOrientA, parentOrientB);
138dcbd3bf7SToby Isaac if (dim == 2) {
139dcbd3bf7SToby Isaac /* orientations refer to cones: we want them to refer to vertices:
140dcbd3bf7SToby Isaac * if it's a rotation, they are the same, but if the order is reversed, a
141dcbd3bf7SToby Isaac * permutation that puts side i first does *not* put vertex i first */
142dcbd3bf7SToby Isaac oAvert = (parentOrientA >= 0) ? parentOrientA : -((-parentOrientA % coneSize) + 1);
143dcbd3bf7SToby Isaac oBvert = (parentOrientB >= 0) ? parentOrientB : -((-parentOrientB % coneSize) + 1);
144dcbd3bf7SToby Isaac ABswapVert = DihedralSwap(coneSize, oAvert, oBvert);
145947b95d8SBarry Smith } else {
146dcbd3bf7SToby Isaac ABswapVert = ABswap;
147dcbd3bf7SToby Isaac }
148dcbd3bf7SToby Isaac if (childB) {
149dcbd3bf7SToby Isaac /* assume that each child corresponds to a vertex, in the same order */
150dcbd3bf7SToby Isaac PetscInt p, posA = -1, numChildren, i;
151dcbd3bf7SToby Isaac const PetscInt *children;
152dcbd3bf7SToby Isaac
153dcbd3bf7SToby Isaac /* count which position the child is in */
1549566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, parent, &numChildren, &children));
155dcbd3bf7SToby Isaac for (i = 0; i < numChildren; i++) {
156dcbd3bf7SToby Isaac p = children[i];
157dcbd3bf7SToby Isaac if (p == childA) {
158dcbd3bf7SToby Isaac posA = i;
159dcbd3bf7SToby Isaac break;
160dcbd3bf7SToby Isaac }
161dcbd3bf7SToby Isaac }
162dcbd3bf7SToby Isaac if (posA >= coneSize) {
163dcbd3bf7SToby Isaac /* this is the triangle in the middle of a uniformly refined triangle: it
164dcbd3bf7SToby Isaac * is invariant */
1651dca8a05SBarry Smith PetscCheck(dim == 2 && posA == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Expected a middle triangle, got something else");
166dcbd3bf7SToby Isaac *childB = childA;
1679371c9d4SSatish Balay } else {
168dcbd3bf7SToby Isaac /* figure out position B by applying ABswapVert */
169dcbd3bf7SToby Isaac PetscInt posB;
170dcbd3bf7SToby Isaac
171dcbd3bf7SToby Isaac posB = (ABswapVert >= 0) ? ((ABswapVert + posA) % coneSize) : ((coneSize - (ABswapVert + 1) - posA) % coneSize);
172dcbd3bf7SToby Isaac if (childB) *childB = children[posB];
173dcbd3bf7SToby Isaac }
174dcbd3bf7SToby Isaac }
175dcbd3bf7SToby Isaac if (childOrientB) *childOrientB = DihedralCompose(coneSize, childOrientA, ABswap);
1763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
177dcbd3bf7SToby Isaac }
178dcbd3bf7SToby Isaac
179dcbd3bf7SToby Isaac /*@
180dcbd3bf7SToby Isaac DMPlexReferenceTreeGetChildSymmetry - Given a reference tree, transform a childid and orientation from one parent frame to another
181dcbd3bf7SToby Isaac
182dcbd3bf7SToby Isaac Input Parameters:
183a1cb98faSBarry Smith + dm - the reference tree `DMPLEX` object
184dcbd3bf7SToby Isaac . parent - the parent point
185dcbd3bf7SToby Isaac . parentOrientA - the reference orientation for describing the parent
186dcbd3bf7SToby Isaac . childOrientA - the reference orientation for describing the child
187dcbd3bf7SToby Isaac . childA - the reference childID for describing the child
188dcbd3bf7SToby Isaac - parentOrientB - the new orientation for describing the parent
189dcbd3bf7SToby Isaac
190dcbd3bf7SToby Isaac Output Parameters:
19120f4b53cSBarry Smith + childOrientB - if not `NULL`, set to the new orientation for describing the child
19220f4b53cSBarry Smith - childB - if not `NULL`, the new childID for describing the child
193dcbd3bf7SToby Isaac
194dcbd3bf7SToby Isaac Level: developer
195dcbd3bf7SToby Isaac
1961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetReferenceTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetTree()`
197dcbd3bf7SToby Isaac @*/
DMPlexReferenceTreeGetChildSymmetry(DM dm,PetscInt parent,PetscInt parentOrientA,PetscInt childOrientA,PetscInt childA,PetscInt parentOrientB,PetscInt * childOrientB,PetscInt * childB)198d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReferenceTreeGetChildSymmetry(DM dm, PetscInt parent, PetscInt parentOrientA, PetscInt childOrientA, PetscInt childA, PetscInt parentOrientB, PetscInt *childOrientB, PetscInt *childB)
199d71ae5a4SJacob Faibussowitsch {
200dcbd3bf7SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
201dcbd3bf7SToby Isaac
202dcbd3bf7SToby Isaac PetscFunctionBegin;
203dcbd3bf7SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20428b400f6SJacob Faibussowitsch PetscCheck(mesh->getchildsymmetry, PETSC_COMM_SELF, PETSC_ERR_SUP, "DMPlexReferenceTreeGetChildSymmetry not implemented");
2059566063dSJacob Faibussowitsch PetscCall(mesh->getchildsymmetry(dm, parent, parentOrientA, childOrientA, childA, parentOrientB, childOrientB, childB));
2063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
207dcbd3bf7SToby Isaac }
208dcbd3bf7SToby Isaac
209776742edSToby Isaac static PetscErrorCode DMPlexSetTree_Internal(DM, PetscSection, PetscInt *, PetscInt *, PetscBool, PetscBool);
210f9f063d4SToby Isaac
DMPlexCreateReferenceTree_SetTree(DM dm,PetscSection parentSection,PetscInt parents[],PetscInt childIDs[])211d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceTree_SetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[])
212d71ae5a4SJacob Faibussowitsch {
213f2c1aa1dSLisandro Dalcin PetscFunctionBegin;
2149566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree_Internal(dm, parentSection, parents, childIDs, PETSC_TRUE, PETSC_FALSE));
2153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
216f2c1aa1dSLisandro Dalcin }
217f2c1aa1dSLisandro Dalcin
DMPlexCreateReferenceTree_Union(DM K,DM Kref,const char * labelName,DM * ref)218d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceTree_Union(DM K, DM Kref, const char *labelName, DM *ref)
219d71ae5a4SJacob Faibussowitsch {
2200e2cc29aSToby Isaac MPI_Comm comm;
2210e2cc29aSToby Isaac PetscInt dim, p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs;
222da43764aSToby Isaac PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts;
223da43764aSToby Isaac DMLabel identity, identityRef;
22410f7e118SToby Isaac PetscSection unionSection, unionConeSection, parentSection;
225da43764aSToby Isaac PetscScalar *unionCoords;
226da43764aSToby Isaac IS perm;
227da43764aSToby Isaac
228da43764aSToby Isaac PetscFunctionBegin;
2290e2cc29aSToby Isaac comm = PetscObjectComm((PetscObject)K);
2309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(K, &dim));
2319566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &pStart, &pEnd));
2329566063dSJacob Faibussowitsch PetscCall(DMGetLabel(K, labelName, &identity));
2339566063dSJacob Faibussowitsch PetscCall(DMGetLabel(Kref, labelName, &identityRef));
2349566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(Kref, &pRefStart, &pRefEnd));
2359566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &unionSection));
2369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart)));
237da43764aSToby Isaac /* count points that will go in the union */
23848a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(PetscSectionSetDof(unionSection, p - pStart, 1));
239da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) {
240da43764aSToby Isaac PetscInt q, qSize;
2419566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, p, &q));
2429566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(identityRef, q, &qSize));
24348a46eb9SPierre Jolivet if (qSize > 1) PetscCall(PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1));
244da43764aSToby Isaac }
2459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart + pRefEnd - pRefStart, &permvals));
246da43764aSToby Isaac offset = 0;
247da43764aSToby Isaac /* stratify points in the union by topological dimension */
248da43764aSToby Isaac for (d = 0; d <= dim; d++) {
249da43764aSToby Isaac PetscInt cStart, cEnd, c;
250da43764aSToby Isaac
2519566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &cStart, &cEnd));
252ad540459SPierre Jolivet for (c = cStart; c < cEnd; c++) permvals[offset++] = c;
253da43764aSToby Isaac
2549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd));
255ad540459SPierre Jolivet for (c = cStart; c < cEnd; c++) permvals[offset++] = c + (pEnd - pStart);
256da43764aSToby Isaac }
2579566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm));
2589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetPermutation(unionSection, perm));
2599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(unionSection));
2609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(unionSection, &numUnionPoints));
2619566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numUnionPoints, &coneSizes, dim + 1, &numDimPoints));
262da43764aSToby Isaac /* count dimension points */
263da43764aSToby Isaac for (d = 0; d <= dim; d++) {
264da43764aSToby Isaac PetscInt cStart, cOff, cOff2;
2659566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &cStart, NULL));
2669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, cStart - pStart, &cOff));
267da43764aSToby Isaac if (d < dim) {
2689566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d + 1, &cStart, NULL));
2699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, cStart - pStart, &cOff2));
2709371c9d4SSatish Balay } else {
271da43764aSToby Isaac cOff2 = numUnionPoints;
272da43764aSToby Isaac }
273da43764aSToby Isaac numDimPoints[dim - d] = cOff2 - cOff;
274da43764aSToby Isaac }
2759566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &unionConeSection));
2769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(unionConeSection, 0, numUnionPoints));
277da43764aSToby Isaac /* count the cones in the union */
278da43764aSToby Isaac for (p = pStart; p < pEnd; p++) {
279da43764aSToby Isaac PetscInt dof, uOff;
280da43764aSToby Isaac
2819566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, p, &dof));
2829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pStart, &uOff));
2839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionConeSection, uOff, dof));
284da43764aSToby Isaac coneSizes[uOff] = dof;
285da43764aSToby Isaac }
286da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) {
287da43764aSToby Isaac PetscInt dof, uDof, uOff;
288da43764aSToby Isaac
2899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(Kref, p, &dof));
2909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof));
2919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff));
292da43764aSToby Isaac if (uDof) {
2939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(unionConeSection, uOff, dof));
294da43764aSToby Isaac coneSizes[uOff] = dof;
295da43764aSToby Isaac }
296da43764aSToby Isaac }
2979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(unionConeSection));
2989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(unionConeSection, &numCones));
2999566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numCones, &unionCones, numCones, &unionOrientations));
300da43764aSToby Isaac /* write the cones in the union */
301da43764aSToby Isaac for (p = pStart; p < pEnd; p++) {
302da43764aSToby Isaac PetscInt dof, uOff, c, cOff;
303da43764aSToby Isaac const PetscInt *cone, *orientation;
304da43764aSToby Isaac
3059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, p, &dof));
3069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, p, &cone));
3079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, p, &orientation));
3089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pStart, &uOff));
3099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionConeSection, uOff, &cOff));
310da43764aSToby Isaac for (c = 0; c < dof; c++) {
311da43764aSToby Isaac PetscInt e, eOff;
312da43764aSToby Isaac e = cone[c];
3139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pStart, &eOff));
314da43764aSToby Isaac unionCones[cOff + c] = eOff;
315da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c];
316da43764aSToby Isaac }
317da43764aSToby Isaac }
318da43764aSToby Isaac for (p = pRefStart; p < pRefEnd; p++) {
319da43764aSToby Isaac PetscInt dof, uDof, uOff, c, cOff;
320da43764aSToby Isaac const PetscInt *cone, *orientation;
321da43764aSToby Isaac
3229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(Kref, p, &dof));
3239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(Kref, p, &cone));
3249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(Kref, p, &orientation));
3259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof));
3269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff));
327da43764aSToby Isaac if (uDof) {
3289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionConeSection, uOff, &cOff));
329da43764aSToby Isaac for (c = 0; c < dof; c++) {
330da43764aSToby Isaac PetscInt e, eOff, eDof;
331da43764aSToby Isaac
332da43764aSToby Isaac e = cone[c];
3339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart), &eDof));
334da43764aSToby Isaac if (eDof) {
3359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff));
3369371c9d4SSatish Balay } else {
3379566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, e, &e));
3389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, e - pStart, &eOff));
339da43764aSToby Isaac }
340da43764aSToby Isaac unionCones[cOff + c] = eOff;
341da43764aSToby Isaac unionOrientations[cOff + c] = orientation[c];
342da43764aSToby Isaac }
343da43764aSToby Isaac }
344da43764aSToby Isaac }
345da43764aSToby Isaac /* get the coordinates */
346da43764aSToby Isaac {
347da43764aSToby Isaac PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff;
348da43764aSToby Isaac PetscSection KcoordsSec, KrefCoordsSec;
349da43764aSToby Isaac Vec KcoordsVec, KrefCoordsVec;
350da43764aSToby Isaac PetscScalar *Kcoords;
351da43764aSToby Isaac
3529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &KcoordsSec));
3539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &KcoordsVec));
3549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(Kref, &KrefCoordsSec));
3559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(Kref, &KrefCoordsVec));
356da43764aSToby Isaac
357da43764aSToby Isaac numVerts = numDimPoints[0];
3589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVerts * dim, &unionCoords));
3599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K, 0, &vStart, &vEnd));
360da43764aSToby Isaac
361da43764aSToby Isaac offset = 0;
362da43764aSToby Isaac for (v = vStart; v < vEnd; v++) {
3639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, v - pStart, &vOff));
3649566063dSJacob Faibussowitsch PetscCall(VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords));
365ad540459SPierre Jolivet for (d = 0; d < dim; d++) unionCoords[offset * dim + d] = Kcoords[d];
366da43764aSToby Isaac offset++;
367da43764aSToby Isaac }
3689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(Kref, 0, &vRefStart, &vRefEnd));
369da43764aSToby Isaac for (v = vRefStart; v < vRefEnd; v++) {
3709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, v - pRefStart + (pEnd - pStart), &vDof));
3719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, v - pRefStart + (pEnd - pStart), &vOff));
3729566063dSJacob Faibussowitsch PetscCall(VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords));
373da43764aSToby Isaac if (vDof) {
374ad540459SPierre Jolivet for (d = 0; d < dim; d++) unionCoords[offset * dim + d] = Kcoords[d];
375da43764aSToby Isaac offset++;
376da43764aSToby Isaac }
377da43764aSToby Isaac }
378da43764aSToby Isaac }
3799566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, ref));
3809566063dSJacob Faibussowitsch PetscCall(DMSetType(*ref, DMPLEX));
3819566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ref, dim));
3829566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ref, dim, numDimPoints, coneSizes, unionCones, unionOrientations, unionCoords));
38310f7e118SToby Isaac /* set the tree */
3849566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(comm, &parentSection));
3859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, 0, numUnionPoints));
38610f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) {
38710f7e118SToby Isaac PetscInt uDof, uOff;
38810f7e118SToby Isaac
3899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof));
3909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff));
3911baa6e33SBarry Smith if (uDof) PetscCall(PetscSectionSetDof(parentSection, uOff, 1));
39210f7e118SToby Isaac }
3939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection));
3949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &parentSize));
3959566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(parentSize, &parents, parentSize, &childIDs));
39610f7e118SToby Isaac for (p = pRefStart; p < pRefEnd; p++) {
39710f7e118SToby Isaac PetscInt uDof, uOff;
39810f7e118SToby Isaac
3999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart), &uDof));
4009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart), &uOff));
40110f7e118SToby Isaac if (uDof) {
40210f7e118SToby Isaac PetscInt pOff, parent, parentU;
4039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection, uOff, &pOff));
4049566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(identityRef, p, &parent));
4059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(unionSection, parent - pStart, &parentU));
40610f7e118SToby Isaac parents[pOff] = parentU;
40710f7e118SToby Isaac childIDs[pOff] = uOff;
40810f7e118SToby Isaac }
40910f7e118SToby Isaac }
4109566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_SetTree(*ref, parentSection, parents, childIDs));
4119566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection));
4129566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents, childIDs));
41310f7e118SToby Isaac
414da43764aSToby Isaac /* clean up */
4159566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&unionSection));
4169566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&unionConeSection));
4179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm));
4189566063dSJacob Faibussowitsch PetscCall(PetscFree(unionCoords));
4199566063dSJacob Faibussowitsch PetscCall(PetscFree2(unionCones, unionOrientations));
4209566063dSJacob Faibussowitsch PetscCall(PetscFree2(coneSizes, numDimPoints));
4213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4220e2cc29aSToby Isaac }
4230e2cc29aSToby Isaac
4240e2cc29aSToby Isaac /*@
4250e2cc29aSToby Isaac DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement.
4260e2cc29aSToby Isaac
427d083f849SBarry Smith Collective
4280e2cc29aSToby Isaac
4290e2cc29aSToby Isaac Input Parameters:
4300e2cc29aSToby Isaac + comm - the MPI communicator
4310e2cc29aSToby Isaac . dim - the spatial dimension
4320e2cc29aSToby Isaac - simplex - Flag for simplex, otherwise use a tensor-product cell
4330e2cc29aSToby Isaac
4342fe279fdSBarry Smith Output Parameter:
435a1cb98faSBarry Smith . ref - the reference tree `DMPLEX` object
4360e2cc29aSToby Isaac
4370e2cc29aSToby Isaac Level: intermediate
4380e2cc29aSToby Isaac
439db781477SPatrick Sanan .seealso: `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()`
4400e2cc29aSToby Isaac @*/
DMPlexCreateDefaultReferenceTree(MPI_Comm comm,PetscInt dim,PetscBool simplex,DM * ref)441d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref)
442d71ae5a4SJacob Faibussowitsch {
4430e2cc29aSToby Isaac DM_Plex *mesh;
4440e2cc29aSToby Isaac DM K, Kref;
4450e2cc29aSToby Isaac PetscInt p, pStart, pEnd;
4460e2cc29aSToby Isaac DMLabel identity;
4470e2cc29aSToby Isaac
4480e2cc29aSToby Isaac PetscFunctionBegin;
4490e2cc29aSToby Isaac #if 1
4500e2cc29aSToby Isaac comm = PETSC_COMM_SELF;
4510e2cc29aSToby Isaac #endif
4520e2cc29aSToby Isaac /* create a reference element */
4539566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(comm, DMPolytopeTypeSimpleShape(dim, simplex), &K));
4549566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(K, "identity"));
4559566063dSJacob Faibussowitsch PetscCall(DMGetLabel(K, "identity", &identity));
4569566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &pStart, &pEnd));
45748a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMLabelSetValue(identity, p, p));
4580e2cc29aSToby Isaac /* refine it */
4599566063dSJacob Faibussowitsch PetscCall(DMRefine(K, comm, &Kref));
4600e2cc29aSToby Isaac
4610e2cc29aSToby Isaac /* the reference tree is the union of these two, without duplicating
4620e2cc29aSToby Isaac * points that appear in both */
4639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceTree_Union(K, Kref, "identity", ref));
4640e2cc29aSToby Isaac mesh = (DM_Plex *)(*ref)->data;
4650e2cc29aSToby Isaac mesh->getchildsymmetry = DMPlexReferenceTreeGetChildSymmetry_Default;
4669566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K));
4679566063dSJacob Faibussowitsch PetscCall(DMDestroy(&Kref));
4683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
469da43764aSToby Isaac }
470da43764aSToby Isaac
DMPlexTreeSymmetrize(DM dm)471d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTreeSymmetrize(DM dm)
472d71ae5a4SJacob Faibussowitsch {
473878b19aaSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
474878b19aaSToby Isaac PetscSection childSec, pSec;
4751690c2aeSBarry Smith PetscInt p, pSize, cSize, parMax = PETSC_INT_MIN, parMin = PETSC_INT_MAX;
476878b19aaSToby Isaac PetscInt *offsets, *children, pStart, pEnd;
477878b19aaSToby Isaac
478878b19aaSToby Isaac PetscFunctionBegin;
479878b19aaSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4809566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection));
4819566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children));
482878b19aaSToby Isaac pSec = mesh->parentSection;
4833ba16761SJacob Faibussowitsch if (!pSec) PetscFunctionReturn(PETSC_SUCCESS);
4849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(pSec, &pSize));
485878b19aaSToby Isaac for (p = 0; p < pSize; p++) {
486878b19aaSToby Isaac PetscInt par = mesh->parents[p];
487878b19aaSToby Isaac
488878b19aaSToby Isaac parMax = PetscMax(parMax, par + 1);
489878b19aaSToby Isaac parMin = PetscMin(parMin, par);
490878b19aaSToby Isaac }
491878b19aaSToby Isaac if (parMin > parMax) {
492878b19aaSToby Isaac parMin = -1;
493878b19aaSToby Isaac parMax = -1;
494878b19aaSToby Isaac }
4959566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)pSec), &childSec));
4969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(childSec, parMin, parMax));
497878b19aaSToby Isaac for (p = 0; p < pSize; p++) {
498878b19aaSToby Isaac PetscInt par = mesh->parents[p];
499878b19aaSToby Isaac
5009566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(childSec, par, 1));
501878b19aaSToby Isaac }
5029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(childSec));
5039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(childSec, &cSize));
5049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cSize, &children));
5059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(parMax - parMin, &offsets));
5069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pSec, &pStart, &pEnd));
507878b19aaSToby Isaac for (p = pStart; p < pEnd; p++) {
508878b19aaSToby Isaac PetscInt dof, off, i;
509878b19aaSToby Isaac
5109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, p, &dof));
5119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec, p, &off));
512878b19aaSToby Isaac for (i = 0; i < dof; i++) {
513878b19aaSToby Isaac PetscInt par = mesh->parents[off + i], cOff;
514878b19aaSToby Isaac
5159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(childSec, par, &cOff));
516878b19aaSToby Isaac children[cOff + offsets[par - parMin]++] = p;
517878b19aaSToby Isaac }
518878b19aaSToby Isaac }
519878b19aaSToby Isaac mesh->childSection = childSec;
520878b19aaSToby Isaac mesh->children = children;
5219566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets));
5223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
523878b19aaSToby Isaac }
524878b19aaSToby Isaac
AnchorsFlatten(PetscSection section,IS is,PetscSection * sectionNew,IS * isNew)525d71ae5a4SJacob Faibussowitsch static PetscErrorCode AnchorsFlatten(PetscSection section, IS is, PetscSection *sectionNew, IS *isNew)
526d71ae5a4SJacob Faibussowitsch {
5276dd5a8c8SToby Isaac PetscInt pStart, pEnd, size, sizeNew, i, p, *valsNew = NULL;
5286dd5a8c8SToby Isaac const PetscInt *vals;
5296dd5a8c8SToby Isaac PetscSection secNew;
5306dd5a8c8SToby Isaac PetscBool anyNew, globalAnyNew;
5316dd5a8c8SToby Isaac PetscBool compress;
5326dd5a8c8SToby Isaac
5336dd5a8c8SToby Isaac PetscFunctionBegin;
5349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
5359566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &size));
5369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &vals));
5379566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), &secNew));
5389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(secNew, pStart, pEnd));
5396dd5a8c8SToby Isaac for (i = 0; i < size; i++) {
5406dd5a8c8SToby Isaac PetscInt dof;
5416dd5a8c8SToby Isaac
5426dd5a8c8SToby Isaac p = vals[i];
5436dd5a8c8SToby Isaac if (p < pStart || p >= pEnd) continue;
5449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof));
5456dd5a8c8SToby Isaac if (dof) break;
5466dd5a8c8SToby Isaac }
5476dd5a8c8SToby Isaac if (i == size) {
5489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secNew));
5496dd5a8c8SToby Isaac anyNew = PETSC_FALSE;
5506dd5a8c8SToby Isaac compress = PETSC_FALSE;
5516dd5a8c8SToby Isaac sizeNew = 0;
5529371c9d4SSatish Balay } else {
5536dd5a8c8SToby Isaac anyNew = PETSC_TRUE;
5546dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) {
5556dd5a8c8SToby Isaac PetscInt dof, off;
5566dd5a8c8SToby Isaac
5579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof));
5589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off));
5596dd5a8c8SToby Isaac for (i = 0; i < dof; i++) {
5606dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0;
5616dd5a8c8SToby Isaac
56248a46eb9SPierre Jolivet if (q >= pStart && q < pEnd) PetscCall(PetscSectionGetDof(section, q, &qDof));
5631baa6e33SBarry Smith if (qDof) PetscCall(PetscSectionAddDof(secNew, p, qDof));
56448a46eb9SPierre Jolivet else PetscCall(PetscSectionAddDof(secNew, p, 1));
5656dd5a8c8SToby Isaac }
5666dd5a8c8SToby Isaac }
5679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secNew));
5689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(secNew, &sizeNew));
5699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sizeNew, &valsNew));
5706dd5a8c8SToby Isaac compress = PETSC_FALSE;
5716dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) {
5726dd5a8c8SToby Isaac PetscInt dof, off, count, offNew, dofNew;
5736dd5a8c8SToby Isaac
5749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof));
5759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &off));
5769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dofNew));
5779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secNew, p, &offNew));
5786dd5a8c8SToby Isaac count = 0;
5796dd5a8c8SToby Isaac for (i = 0; i < dof; i++) {
5806dd5a8c8SToby Isaac PetscInt q = vals[off + i], qDof = 0, qOff = 0, j;
5816dd5a8c8SToby Isaac
5826dd5a8c8SToby Isaac if (q >= pStart && q < pEnd) {
5839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &qDof));
5849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &qOff));
5856dd5a8c8SToby Isaac }
5866dd5a8c8SToby Isaac if (qDof) {
5876dd5a8c8SToby Isaac PetscInt oldCount = count;
5886dd5a8c8SToby Isaac
5896dd5a8c8SToby Isaac for (j = 0; j < qDof; j++) {
5906dd5a8c8SToby Isaac PetscInt k, r = vals[qOff + j];
5916dd5a8c8SToby Isaac
5926dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) {
593ad540459SPierre Jolivet if (valsNew[offNew + k] == r) break;
5946dd5a8c8SToby Isaac }
595ad540459SPierre Jolivet if (k == oldCount) valsNew[offNew + count++] = r;
5966dd5a8c8SToby Isaac }
5979371c9d4SSatish Balay } else {
5986dd5a8c8SToby Isaac PetscInt k, oldCount = count;
5996dd5a8c8SToby Isaac
6006dd5a8c8SToby Isaac for (k = 0; k < oldCount; k++) {
601ad540459SPierre Jolivet if (valsNew[offNew + k] == q) break;
6026dd5a8c8SToby Isaac }
603ad540459SPierre Jolivet if (k == oldCount) valsNew[offNew + count++] = q;
6046dd5a8c8SToby Isaac }
6056dd5a8c8SToby Isaac }
6066dd5a8c8SToby Isaac if (count < dofNew) {
6079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(secNew, p, count));
6086dd5a8c8SToby Isaac compress = PETSC_TRUE;
6096dd5a8c8SToby Isaac }
6106dd5a8c8SToby Isaac }
6116dd5a8c8SToby Isaac }
6129566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &vals));
613*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&anyNew, &globalAnyNew, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)secNew)));
6146dd5a8c8SToby Isaac if (!globalAnyNew) {
6159566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secNew));
6166dd5a8c8SToby Isaac *sectionNew = NULL;
6176dd5a8c8SToby Isaac *isNew = NULL;
6189371c9d4SSatish Balay } else {
6196dd5a8c8SToby Isaac if (compress) {
6206dd5a8c8SToby Isaac PetscSection secComp;
6216dd5a8c8SToby Isaac PetscInt *valsComp = NULL;
6226dd5a8c8SToby Isaac
6239566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)section), &secComp));
6249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(secComp, pStart, pEnd));
6256dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) {
6266dd5a8c8SToby Isaac PetscInt dof;
6276dd5a8c8SToby Isaac
6289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dof));
6299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(secComp, p, dof));
6306dd5a8c8SToby Isaac }
6319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(secComp));
6329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(secComp, &sizeNew));
6339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(sizeNew, &valsComp));
6346dd5a8c8SToby Isaac for (p = pStart; p < pEnd; p++) {
6356dd5a8c8SToby Isaac PetscInt dof, off, offNew, j;
6366dd5a8c8SToby Isaac
6379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(secNew, p, &dof));
6389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secNew, p, &off));
6399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(secComp, p, &offNew));
640ad540459SPierre Jolivet for (j = 0; j < dof; j++) valsComp[offNew + j] = valsNew[off + j];
6416dd5a8c8SToby Isaac }
6429566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&secNew));
6436dd5a8c8SToby Isaac secNew = secComp;
6449566063dSJacob Faibussowitsch PetscCall(PetscFree(valsNew));
6456dd5a8c8SToby Isaac valsNew = valsComp;
6466dd5a8c8SToby Isaac }
6479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is), sizeNew, valsNew, PETSC_OWN_POINTER, isNew));
6486dd5a8c8SToby Isaac }
6493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
6506dd5a8c8SToby Isaac }
6516dd5a8c8SToby Isaac
DMPlexCreateAnchors_Tree(DM dm)652d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateAnchors_Tree(DM dm)
653d71ae5a4SJacob Faibussowitsch {
65466af876cSToby Isaac PetscInt p, pStart, pEnd, *anchors, size;
6551690c2aeSBarry Smith PetscInt aMin = PETSC_INT_MAX, aMax = PETSC_INT_MIN;
65666af876cSToby Isaac PetscSection aSec;
657f9f063d4SToby Isaac DMLabel canonLabel;
65866af876cSToby Isaac IS aIS;
65966af876cSToby Isaac
66066af876cSToby Isaac PetscFunctionBegin;
66166af876cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6629566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
6639566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "canonical", &canonLabel));
66466af876cSToby Isaac for (p = pStart; p < pEnd; p++) {
66566af876cSToby Isaac PetscInt parent;
66666af876cSToby Isaac
667f9f063d4SToby Isaac if (canonLabel) {
668f9f063d4SToby Isaac PetscInt canon;
669f9f063d4SToby Isaac
6709566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon));
671f9f063d4SToby Isaac if (p != canon) continue;
672f9f063d4SToby Isaac }
6739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL));
67466af876cSToby Isaac if (parent != p) {
67566af876cSToby Isaac aMin = PetscMin(aMin, p);
67666af876cSToby Isaac aMax = PetscMax(aMax, p + 1);
67766af876cSToby Isaac }
67866af876cSToby Isaac }
67966af876cSToby Isaac if (aMin > aMax) {
68066af876cSToby Isaac aMin = -1;
68166af876cSToby Isaac aMax = -1;
68266af876cSToby Isaac }
6839566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &aSec));
6849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(aSec, aMin, aMax));
68566af876cSToby Isaac for (p = aMin; p < aMax; p++) {
68666af876cSToby Isaac PetscInt parent, ancestor = p;
68766af876cSToby Isaac
688f9f063d4SToby Isaac if (canonLabel) {
689f9f063d4SToby Isaac PetscInt canon;
690f9f063d4SToby Isaac
6919566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon));
692f9f063d4SToby Isaac if (p != canon) continue;
693f9f063d4SToby Isaac }
6949566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL));
69566af876cSToby Isaac while (parent != ancestor) {
69666af876cSToby Isaac ancestor = parent;
6979566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, ancestor, &parent, NULL));
69866af876cSToby Isaac }
69966af876cSToby Isaac if (ancestor != p) {
70066af876cSToby Isaac PetscInt closureSize, *closure = NULL;
70166af876cSToby Isaac
7029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure));
7039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(aSec, p, closureSize));
7049566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure));
70566af876cSToby Isaac }
70666af876cSToby Isaac }
7079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(aSec));
7089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(aSec, &size));
7099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &anchors));
71066af876cSToby Isaac for (p = aMin; p < aMax; p++) {
71166af876cSToby Isaac PetscInt parent, ancestor = p;
71266af876cSToby Isaac
713f9f063d4SToby Isaac if (canonLabel) {
714f9f063d4SToby Isaac PetscInt canon;
715f9f063d4SToby Isaac
7169566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, p, &canon));
717f9f063d4SToby Isaac if (p != canon) continue;
718f9f063d4SToby Isaac }
7199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &parent, NULL));
72066af876cSToby Isaac while (parent != ancestor) {
72166af876cSToby Isaac ancestor = parent;
7229566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, ancestor, &parent, NULL));
72366af876cSToby Isaac }
72466af876cSToby Isaac if (ancestor != p) {
72566af876cSToby Isaac PetscInt j, closureSize, *closure = NULL, aOff;
72666af876cSToby Isaac
7279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff));
72866af876cSToby Isaac
7299566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure));
730ad540459SPierre Jolivet for (j = 0; j < closureSize; j++) anchors[aOff + j] = closure[2 * j];
7319566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, ancestor, PETSC_TRUE, &closureSize, &closure));
73266af876cSToby Isaac }
73366af876cSToby Isaac }
7349566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, anchors, PETSC_OWN_POINTER, &aIS));
7356dd5a8c8SToby Isaac {
7366dd5a8c8SToby Isaac PetscSection aSecNew = aSec;
7376dd5a8c8SToby Isaac IS aISNew = aIS;
7386dd5a8c8SToby Isaac
7399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)aSec));
7409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)aIS));
7416dd5a8c8SToby Isaac while (aSecNew) {
7429566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&aSec));
7439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&aIS));
7446dd5a8c8SToby Isaac aSec = aSecNew;
7456dd5a8c8SToby Isaac aIS = aISNew;
7466dd5a8c8SToby Isaac aSecNew = NULL;
7476dd5a8c8SToby Isaac aISNew = NULL;
7489566063dSJacob Faibussowitsch PetscCall(AnchorsFlatten(aSec, aIS, &aSecNew, &aISNew));
7496dd5a8c8SToby Isaac }
7506dd5a8c8SToby Isaac }
7519566063dSJacob Faibussowitsch PetscCall(DMPlexSetAnchors(dm, aSec, aIS));
7529566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&aSec));
7539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&aIS));
7543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
75566af876cSToby Isaac }
75666af876cSToby Isaac
DMPlexGetTrueSupportSize(DM dm,PetscInt p,PetscInt * dof,PetscInt * numTrueSupp)757d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTrueSupportSize(DM dm, PetscInt p, PetscInt *dof, PetscInt *numTrueSupp)
758d71ae5a4SJacob Faibussowitsch {
7596461c1adSToby Isaac PetscFunctionBegin;
7606461c1adSToby Isaac if (numTrueSupp[p] == -1) {
7616461c1adSToby Isaac PetscInt i, alldof;
7626461c1adSToby Isaac const PetscInt *supp;
7636461c1adSToby Isaac PetscInt count = 0;
7646461c1adSToby Isaac
7659566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &alldof));
7669566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &supp));
7676461c1adSToby Isaac for (i = 0; i < alldof; i++) {
7686461c1adSToby Isaac PetscInt q = supp[i], numCones, j;
7696461c1adSToby Isaac const PetscInt *cone;
7706461c1adSToby Isaac
7719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &numCones));
7729566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &cone));
7736461c1adSToby Isaac for (j = 0; j < numCones; j++) {
7746461c1adSToby Isaac if (cone[j] == p) break;
7756461c1adSToby Isaac }
7766461c1adSToby Isaac if (j < numCones) count++;
7776461c1adSToby Isaac }
7786461c1adSToby Isaac numTrueSupp[p] = count;
7796461c1adSToby Isaac }
7806461c1adSToby Isaac *dof = numTrueSupp[p];
7813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
7826461c1adSToby Isaac }
7836461c1adSToby Isaac
DMPlexTreeExchangeSupports(DM dm)784d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTreeExchangeSupports(DM dm)
785d71ae5a4SJacob Faibussowitsch {
786776742edSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
787776742edSToby Isaac PetscSection newSupportSection;
788776742edSToby Isaac PetscInt newSize, *newSupports, pStart, pEnd, p, d, depth;
7896461c1adSToby Isaac PetscInt *numTrueSupp;
790776742edSToby Isaac PetscInt *offsets;
791776742edSToby Isaac
792776742edSToby Isaac PetscFunctionBegin;
793776742edSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
794776742edSToby Isaac /* symmetrize the hierarchy */
7959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth));
796f4f49eeaSPierre Jolivet PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)mesh->supportSection), &newSupportSection));
7979566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
7989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newSupportSection, pStart, pEnd));
7999566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd, &offsets));
8009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd, &numTrueSupp));
8016461c1adSToby Isaac for (p = 0; p < pEnd; p++) numTrueSupp[p] = -1;
8026461c1adSToby Isaac /* if a point is in the (true) support of q, it should be in the support of
803776742edSToby Isaac * parent(q) */
804776742edSToby Isaac for (d = 0; d <= depth; d++) {
8059566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pStart, &pEnd));
806776742edSToby Isaac for (p = pStart; p < pEnd; ++p) {
807776742edSToby Isaac PetscInt dof, q, qdof, parent;
808776742edSToby Isaac
8099566063dSJacob Faibussowitsch PetscCall(DMPlexGetTrueSupportSize(dm, p, &dof, numTrueSupp));
8109566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, p, dof));
811776742edSToby Isaac q = p;
8129566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL));
813776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) {
814776742edSToby Isaac q = parent;
815776742edSToby Isaac
8169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTrueSupportSize(dm, q, &qdof, numTrueSupp));
8179566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, p, qdof));
8189566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(newSupportSection, q, dof));
8199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL));
820776742edSToby Isaac }
821776742edSToby Isaac }
822776742edSToby Isaac }
8239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newSupportSection));
8249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newSupportSection, &newSize));
8259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newSize, &newSupports));
826776742edSToby Isaac for (d = 0; d <= depth; d++) {
8279566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pStart, &pEnd));
828776742edSToby Isaac for (p = pStart; p < pEnd; p++) {
829776742edSToby Isaac PetscInt dof, off, q, qdof, qoff, newDof, newOff, newqOff, i, parent;
830776742edSToby Isaac
8319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
8329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
8339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(newSupportSection, p, &newDof));
8349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newSupportSection, p, &newOff));
835776742edSToby Isaac for (i = 0; i < dof; i++) {
8366461c1adSToby Isaac PetscInt numCones, j;
8376461c1adSToby Isaac const PetscInt *cone;
8386461c1adSToby Isaac PetscInt q = mesh->supports[off + i];
8396461c1adSToby Isaac
8409566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, q, &numCones));
8419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, q, &cone));
8426461c1adSToby Isaac for (j = 0; j < numCones; j++) {
8436461c1adSToby Isaac if (cone[j] == p) break;
8446461c1adSToby Isaac }
8456461c1adSToby Isaac if (j < numCones) newSupports[newOff + offsets[p]++] = q;
846776742edSToby Isaac }
847776742edSToby Isaac
848776742edSToby Isaac q = p;
8499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL));
850776742edSToby Isaac while (parent != q && parent >= pStart && parent < pEnd) {
851776742edSToby Isaac q = parent;
8529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, q, &qdof));
8539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &qoff));
8549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newSupportSection, q, &newqOff));
855776742edSToby Isaac for (i = 0; i < qdof; i++) {
8566461c1adSToby Isaac PetscInt numCones, j;
8576461c1adSToby Isaac const PetscInt *cone;
8586461c1adSToby Isaac PetscInt r = mesh->supports[qoff + i];
8596461c1adSToby Isaac
8609566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, r, &numCones));
8619566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, r, &cone));
8626461c1adSToby Isaac for (j = 0; j < numCones; j++) {
8636461c1adSToby Isaac if (cone[j] == q) break;
8646461c1adSToby Isaac }
8656461c1adSToby Isaac if (j < numCones) newSupports[newOff + offsets[p]++] = r;
866776742edSToby Isaac }
867776742edSToby Isaac for (i = 0; i < dof; i++) {
8686461c1adSToby Isaac PetscInt numCones, j;
8696461c1adSToby Isaac const PetscInt *cone;
8706461c1adSToby Isaac PetscInt r = mesh->supports[off + i];
8716461c1adSToby Isaac
8729566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, r, &numCones));
8739566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, r, &cone));
8746461c1adSToby Isaac for (j = 0; j < numCones; j++) {
8756461c1adSToby Isaac if (cone[j] == p) break;
8766461c1adSToby Isaac }
8776461c1adSToby Isaac if (j < numCones) newSupports[newqOff + offsets[q]++] = r;
878776742edSToby Isaac }
8799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, q, &parent, NULL));
880776742edSToby Isaac }
881776742edSToby Isaac }
882776742edSToby Isaac }
8839566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection));
884776742edSToby Isaac mesh->supportSection = newSupportSection;
8859566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports));
886776742edSToby Isaac mesh->supports = newSupports;
8879566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets));
8889566063dSJacob Faibussowitsch PetscCall(PetscFree(numTrueSupp));
8893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
890776742edSToby Isaac }
891776742edSToby Isaac
892f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM, PetscSection, PetscSection, Mat);
893f7c74593SToby Isaac static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM, PetscSection, PetscSection, Mat);
894f7c74593SToby Isaac
DMPlexSetTree_Internal(DM dm,PetscSection parentSection,PetscInt * parents,PetscInt * childIDs,PetscBool computeCanonical,PetscBool exchangeSupports)895d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSetTree_Internal(DM dm, PetscSection parentSection, PetscInt *parents, PetscInt *childIDs, PetscBool computeCanonical, PetscBool exchangeSupports)
896d71ae5a4SJacob Faibussowitsch {
897f9f063d4SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
898f9f063d4SToby Isaac DM refTree;
899f9f063d4SToby Isaac PetscInt size;
900f9f063d4SToby Isaac
901f9f063d4SToby Isaac PetscFunctionBegin;
902f9f063d4SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
903f9f063d4SToby Isaac PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2);
9049566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)parentSection));
9059566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection));
906f9f063d4SToby Isaac mesh->parentSection = parentSection;
9079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &size));
908f9f063d4SToby Isaac if (parents != mesh->parents) {
9099566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents));
9109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->parents));
9119566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mesh->parents, parents, size));
912f9f063d4SToby Isaac }
913f9f063d4SToby Isaac if (childIDs != mesh->childIDs) {
9149566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs));
9159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->childIDs));
9169566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mesh->childIDs, childIDs, size));
917f9f063d4SToby Isaac }
9189566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree));
919f9f063d4SToby Isaac if (refTree) {
920f9f063d4SToby Isaac DMLabel canonLabel;
921f9f063d4SToby Isaac
9229566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonLabel));
923f9f063d4SToby Isaac if (canonLabel) {
924f9f063d4SToby Isaac PetscInt i;
925f9f063d4SToby Isaac
926f9f063d4SToby Isaac for (i = 0; i < size; i++) {
927f9f063d4SToby Isaac PetscInt canon;
9289566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonLabel, mesh->childIDs[i], &canon));
929ad540459SPierre Jolivet if (canon >= 0) mesh->childIDs[i] = canon;
930f9f063d4SToby Isaac }
931f9f063d4SToby Isaac }
932f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_FromReference;
9336e0288c8SStefano Zampini } else {
934f7c74593SToby Isaac mesh->computeanchormatrix = DMPlexComputeAnchorMatrix_Tree_Direct;
935f9f063d4SToby Isaac }
9369566063dSJacob Faibussowitsch PetscCall(DMPlexTreeSymmetrize(dm));
937f9f063d4SToby Isaac if (computeCanonical) {
938f9f063d4SToby Isaac PetscInt d, dim;
939f9f063d4SToby Isaac
940f9f063d4SToby Isaac /* add the canonical label */
9419566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
9429566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "canonical"));
943f9f063d4SToby Isaac for (d = 0; d <= dim; d++) {
944f9f063d4SToby Isaac PetscInt p, dStart, dEnd, canon = -1, cNumChildren;
945f9f063d4SToby Isaac const PetscInt *cChildren;
946f9f063d4SToby Isaac
9479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd));
948f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) {
9499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, p, &cNumChildren, &cChildren));
950f9f063d4SToby Isaac if (cNumChildren) {
951f9f063d4SToby Isaac canon = p;
952f9f063d4SToby Isaac break;
953f9f063d4SToby Isaac }
954f9f063d4SToby Isaac }
955f9f063d4SToby Isaac if (canon == -1) continue;
956f9f063d4SToby Isaac for (p = dStart; p < dEnd; p++) {
957f9f063d4SToby Isaac PetscInt numChildren, i;
958f9f063d4SToby Isaac const PetscInt *children;
959f9f063d4SToby Isaac
9609566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, p, &numChildren, &children));
961f9f063d4SToby Isaac if (numChildren) {
96263a3b9bcSJacob Faibussowitsch PetscCheck(numChildren == cNumChildren, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "All parent points in a stratum should have the same number of children: %" PetscInt_FMT " != %" PetscInt_FMT, numChildren, cNumChildren);
9639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "canonical", p, canon));
96448a46eb9SPierre Jolivet for (i = 0; i < numChildren; i++) PetscCall(DMSetLabelValue(dm, "canonical", children[i], cChildren[i]));
965f9f063d4SToby Isaac }
966f9f063d4SToby Isaac }
967f9f063d4SToby Isaac }
968f9f063d4SToby Isaac }
9691baa6e33SBarry Smith if (exchangeSupports) PetscCall(DMPlexTreeExchangeSupports(dm));
970f7c74593SToby Isaac mesh->createanchors = DMPlexCreateAnchors_Tree;
971f7c74593SToby Isaac /* reset anchors */
9729566063dSJacob Faibussowitsch PetscCall(DMPlexSetAnchors(dm, NULL, NULL));
9733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
974f9f063d4SToby Isaac }
975f9f063d4SToby Isaac
9760b7167a0SToby Isaac /*@
9770b7167a0SToby Isaac DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates
978aaa8cc7dSPierre Jolivet the point-to-point constraints determined by the tree: a point is constrained to the points in the closure of its
9790b7167a0SToby Isaac tree root.
9800b7167a0SToby Isaac
98120f4b53cSBarry Smith Collective
9820b7167a0SToby Isaac
9830b7167a0SToby Isaac Input Parameters:
984a1cb98faSBarry Smith + dm - the `DMPLEX` object
9850b7167a0SToby Isaac . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section
9860b7167a0SToby Isaac offset indexes the parent and childID list; the reference count of parentSection is incremented
9870b7167a0SToby Isaac . parents - a list of the point parents; copied, can be destroyed
9880b7167a0SToby Isaac - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then
9890b7167a0SToby Isaac the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed
9900b7167a0SToby Isaac
9910b7167a0SToby Isaac Level: intermediate
9920b7167a0SToby Isaac
9931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()`
9940b7167a0SToby Isaac @*/
DMPlexSetTree(DM dm,PetscSection parentSection,PetscInt parents[],PetscInt childIDs[])995d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[])
996d71ae5a4SJacob Faibussowitsch {
9970b7167a0SToby Isaac PetscFunctionBegin;
9989566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree_Internal(dm, parentSection, parents, childIDs, PETSC_FALSE, PETSC_TRUE));
9993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
10000b7167a0SToby Isaac }
10010b7167a0SToby Isaac
1002b2f41788SToby Isaac /*@
1003b2f41788SToby Isaac DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points.
100420f4b53cSBarry Smith Collective
1005b2f41788SToby Isaac
1006f899ff85SJose E. Roman Input Parameter:
1007a1cb98faSBarry Smith . dm - the `DMPLEX` object
1008b2f41788SToby Isaac
1009b2f41788SToby Isaac Output Parameters:
1010b2f41788SToby Isaac + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section
1011b2f41788SToby Isaac offset indexes the parent and childID list
1012b2f41788SToby Isaac . parents - a list of the point parents
1013b2f41788SToby Isaac . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then
1014b2f41788SToby Isaac the child corresponds to the point in the reference tree with index childID
1015b2f41788SToby Isaac . childSection - the inverse of the parent section
1016b2f41788SToby Isaac - children - a list of the point children
1017b2f41788SToby Isaac
1018b2f41788SToby Isaac Level: intermediate
1019b2f41788SToby Isaac
10201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`,`DMPlexSetTree()`, `DMPlexSetReferenceTree()`, `DMPlexSetAnchors()`, `DMPlexGetTreeParent()`, `DMPlexGetTreeChildren()`
1021b2f41788SToby Isaac @*/
DMPlexGetTree(DM dm,PetscSection * parentSection,PetscInt * parents[],PetscInt * childIDs[],PetscSection * childSection,PetscInt * children[])1022d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[])
1023d71ae5a4SJacob Faibussowitsch {
1024b2f41788SToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
1025b2f41788SToby Isaac
1026b2f41788SToby Isaac PetscFunctionBegin;
1027b2f41788SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1028b2f41788SToby Isaac if (parentSection) *parentSection = mesh->parentSection;
1029b2f41788SToby Isaac if (parents) *parents = mesh->parents;
1030b2f41788SToby Isaac if (childIDs) *childIDs = mesh->childIDs;
1031b2f41788SToby Isaac if (childSection) *childSection = mesh->childSection;
1032b2f41788SToby Isaac if (children) *children = mesh->children;
10333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1034b2f41788SToby Isaac }
1035b2f41788SToby Isaac
1036d961a43aSToby Isaac /*@
1037eaf898f9SPatrick Sanan DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the DAG)
1038d961a43aSToby Isaac
1039d961a43aSToby Isaac Input Parameters:
1040a1cb98faSBarry Smith + dm - the `DMPLEX` object
1041d961a43aSToby Isaac - point - the query point
1042d961a43aSToby Isaac
1043d961a43aSToby Isaac Output Parameters:
104420f4b53cSBarry Smith + parent - if not `NULL`, set to the parent of the point, or the point itself if the point does not have a parent
104520f4b53cSBarry Smith - childID - if not `NULL`, set to the child ID of the point with respect to its parent, or 0 if the point
1046d961a43aSToby Isaac does not have a parent
1047d961a43aSToby Isaac
1048d961a43aSToby Isaac Level: intermediate
1049d961a43aSToby Isaac
10501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeChildren()`
1051d961a43aSToby Isaac @*/
DMPlexGetTreeParent(DM dm,PetscInt point,PetscInt * parent,PetscInt * childID)1052d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID)
1053d71ae5a4SJacob Faibussowitsch {
1054d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
1055d961a43aSToby Isaac PetscSection pSec;
1056d961a43aSToby Isaac
1057d961a43aSToby Isaac PetscFunctionBegin;
1058d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1059d961a43aSToby Isaac pSec = mesh->parentSection;
1060d961a43aSToby Isaac if (pSec && point >= pSec->pStart && point < pSec->pEnd) {
1061d961a43aSToby Isaac PetscInt dof;
1062d961a43aSToby Isaac
10639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, point, &dof));
1064d961a43aSToby Isaac if (dof) {
1065d961a43aSToby Isaac PetscInt off;
1066d961a43aSToby Isaac
10679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec, point, &off));
1068d961a43aSToby Isaac if (parent) *parent = mesh->parents[off];
1069d961a43aSToby Isaac if (childID) *childID = mesh->childIDs[off];
10703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1071d961a43aSToby Isaac }
1072d961a43aSToby Isaac }
1073ad540459SPierre Jolivet if (parent) *parent = point;
1074ad540459SPierre Jolivet if (childID) *childID = 0;
10753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1076d961a43aSToby Isaac }
1077d961a43aSToby Isaac
1078d961a43aSToby Isaac /*@C
1079eaf898f9SPatrick Sanan DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the DAG)
1080d961a43aSToby Isaac
1081d961a43aSToby Isaac Input Parameters:
1082a1cb98faSBarry Smith + dm - the `DMPLEX` object
1083d961a43aSToby Isaac - point - the query point
1084d961a43aSToby Isaac
1085d961a43aSToby Isaac Output Parameters:
108620f4b53cSBarry Smith + numChildren - if not `NULL`, set to the number of children
108720f4b53cSBarry Smith - children - if not `NULL`, set to a list children, or set to `NULL` if the point has no children
1088d961a43aSToby Isaac
1089d961a43aSToby Isaac Level: intermediate
1090d961a43aSToby Isaac
10911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetTree()`, `DMPlexGetTree()`, `DMPlexGetTreeParent()`
1092d961a43aSToby Isaac @*/
DMPlexGetTreeChildren(DM dm,PetscInt point,PetscInt * numChildren,const PetscInt * children[])1093d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[])
1094d71ae5a4SJacob Faibussowitsch {
1095d961a43aSToby Isaac DM_Plex *mesh = (DM_Plex *)dm->data;
1096d961a43aSToby Isaac PetscSection childSec;
1097d961a43aSToby Isaac PetscInt dof = 0;
1098d961a43aSToby Isaac
1099d961a43aSToby Isaac PetscFunctionBegin;
1100d961a43aSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1101d961a43aSToby Isaac childSec = mesh->childSection;
110248a46eb9SPierre Jolivet if (childSec && point >= childSec->pStart && point < childSec->pEnd) PetscCall(PetscSectionGetDof(childSec, point, &dof));
1103d961a43aSToby Isaac if (numChildren) *numChildren = dof;
1104d961a43aSToby Isaac if (children) {
1105d961a43aSToby Isaac if (dof) {
1106d961a43aSToby Isaac PetscInt off;
1107d961a43aSToby Isaac
11089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(childSec, point, &off));
1109d961a43aSToby Isaac *children = &mesh->children[off];
11109371c9d4SSatish Balay } else {
1111d961a43aSToby Isaac *children = NULL;
1112d961a43aSToby Isaac }
1113d961a43aSToby Isaac }
11143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1115d961a43aSToby Isaac }
11160c37af3bSToby Isaac
EvaluateBasis(PetscSpace space,PetscInt nBasis,PetscInt nFunctionals,PetscInt nComps,PetscInt nPoints,const PetscInt * pointsPerFn,const PetscReal * points,const PetscReal * weights,PetscReal * work,Mat basisAtPoints)1117d71ae5a4SJacob Faibussowitsch static PetscErrorCode EvaluateBasis(PetscSpace space, PetscInt nBasis, PetscInt nFunctionals, PetscInt nComps, PetscInt nPoints, const PetscInt *pointsPerFn, const PetscReal *points, const PetscReal *weights, PetscReal *work, Mat basisAtPoints)
1118d71ae5a4SJacob Faibussowitsch {
111952a3aeb4SToby Isaac PetscInt f, b, p, c, offset, qPoints;
1120b3a4bf2aSToby Isaac
1121b3a4bf2aSToby Isaac PetscFunctionBegin;
11229566063dSJacob Faibussowitsch PetscCall(PetscSpaceEvaluate(space, nPoints, points, work, NULL, NULL));
112352a3aeb4SToby Isaac for (f = 0, offset = 0; f < nFunctionals; f++) {
112452a3aeb4SToby Isaac qPoints = pointsPerFn[f];
112552a3aeb4SToby Isaac for (b = 0; b < nBasis; b++) {
1126b3a4bf2aSToby Isaac PetscScalar val = 0.;
1127b3a4bf2aSToby Isaac
112852a3aeb4SToby Isaac for (p = 0; p < qPoints; p++) {
1129ad540459SPierre Jolivet for (c = 0; c < nComps; c++) val += work[((offset + p) * nBasis + b) * nComps + c] * weights[(offset + p) * nComps + c];
113052a3aeb4SToby Isaac }
11319566063dSJacob Faibussowitsch PetscCall(MatSetValue(basisAtPoints, b, f, val, INSERT_VALUES));
1132b3a4bf2aSToby Isaac }
1133b3a4bf2aSToby Isaac offset += qPoints;
1134b3a4bf2aSToby Isaac }
11359566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(basisAtPoints, MAT_FINAL_ASSEMBLY));
11369566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(basisAtPoints, MAT_FINAL_ASSEMBLY));
11373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1138b3a4bf2aSToby Isaac }
1139b3a4bf2aSToby Isaac
DMPlexComputeAnchorMatrix_Tree_Direct(DM dm,PetscSection section,PetscSection cSec,Mat cMat)1140d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_Direct(DM dm, PetscSection section, PetscSection cSec, Mat cMat)
1141d71ae5a4SJacob Faibussowitsch {
11420c37af3bSToby Isaac PetscDS ds;
11430c37af3bSToby Isaac PetscInt spdim;
11440c37af3bSToby Isaac PetscInt numFields, f, c, cStart, cEnd, pStart, pEnd, conStart, conEnd;
11450c37af3bSToby Isaac const PetscInt *anchors;
1146f7c74593SToby Isaac PetscSection aSec;
11470c37af3bSToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJparent, detJ, detJparent;
11480c37af3bSToby Isaac IS aIS;
11490c37af3bSToby Isaac
11500c37af3bSToby Isaac PetscFunctionBegin;
11519566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
11529566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds));
11539566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields));
11549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
11559566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
11569566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors));
11579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &conStart, &conEnd));
11589566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &spdim));
11599566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(spdim, &v0, spdim, &v0parent, spdim, &vtmp, spdim * spdim, &J, spdim * spdim, &Jparent, spdim * spdim, &invJparent));
11600c37af3bSToby Isaac
11610c37af3bSToby Isaac for (f = 0; f < numFields; f++) {
11620dd1b1feSToby Isaac PetscObject disc;
11630dd1b1feSToby Isaac PetscClassId id;
1164b3a4bf2aSToby Isaac PetscSpace bspace;
1165b3a4bf2aSToby Isaac PetscDualSpace dspace;
11669c3cf19fSMatthew G. Knepley PetscInt i, j, k, nPoints, Nc, offset;
116752a3aeb4SToby Isaac PetscInt fSize, maxDof;
1168b3a4bf2aSToby Isaac PetscReal *weights, *pointsRef, *pointsReal, *work;
11691683a169SBarry Smith PetscScalar *scwork;
11701683a169SBarry Smith const PetscScalar *X;
11712c44ad04SToby Isaac PetscInt *sizes, *workIndRow, *workIndCol;
11720c37af3bSToby Isaac Mat Amat, Bmat, Xmat;
11732c44ad04SToby Isaac const PetscInt *numDof = NULL;
1174085f0adfSToby Isaac const PetscInt ***perms = NULL;
1175085f0adfSToby Isaac const PetscScalar ***flips = NULL;
11760c37af3bSToby Isaac
11779566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc));
11789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &id));
11790dd1b1feSToby Isaac if (id == PETSCFE_CLASSID) {
1180b3a4bf2aSToby Isaac PetscFE fe = (PetscFE)disc;
1181b3a4bf2aSToby Isaac
11829566063dSJacob Faibussowitsch PetscCall(PetscFEGetBasisSpace(fe, &bspace));
11839566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dspace));
11849566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace, &fSize));
11859566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc));
11869371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) {
1187b3a4bf2aSToby Isaac PetscFV fv = (PetscFV)disc;
1188b3a4bf2aSToby Isaac
11899566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc));
11909566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)fv), &bspace));
11919566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(bspace, PETSCSPACEPOLYNOMIAL));
11929566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(bspace, 0, PETSC_DETERMINE));
11939566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(bspace, Nc));
11949566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(bspace, spdim));
11959566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(bspace));
11969566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fv, &dspace));
11979566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dspace, &fSize));
11989371c9d4SSatish Balay } else SETERRQ(PetscObjectComm(disc), PETSC_ERR_ARG_UNKNOWN_TYPE, "PetscDS discretization id %d not recognized.", id);
11999566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dspace, &numDof));
1200ad540459SPierre Jolivet for (i = 0, maxDof = 0; i <= spdim; i++) maxDof = PetscMax(maxDof, numDof[i]);
12019566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dspace, &perms, &flips));
12020dd1b1feSToby Isaac
12039566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &Amat));
12049566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Amat, fSize, fSize, fSize, fSize));
12059566063dSJacob Faibussowitsch PetscCall(MatSetType(Amat, MATSEQDENSE));
12069566063dSJacob Faibussowitsch PetscCall(MatSetUp(Amat));
12079566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat, MAT_DO_NOT_COPY_VALUES, &Bmat));
12089566063dSJacob Faibussowitsch PetscCall(MatDuplicate(Amat, MAT_DO_NOT_COPY_VALUES, &Xmat));
12090c37af3bSToby Isaac nPoints = 0;
12100c37af3bSToby Isaac for (i = 0; i < fSize; i++) {
121152a3aeb4SToby Isaac PetscInt qPoints, thisNc;
12120c37af3bSToby Isaac PetscQuadrature quad;
12130c37af3bSToby Isaac
12149566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace, i, &quad));
12159566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &thisNc, &qPoints, NULL, NULL));
121663a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc);
12170c37af3bSToby Isaac nPoints += qPoints;
12180c37af3bSToby Isaac }
12199566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(fSize, &sizes, nPoints * Nc, &weights, spdim * nPoints, &pointsRef, spdim * nPoints, &pointsReal, nPoints * fSize * Nc, &work, maxDof, &workIndRow, maxDof, &workIndCol));
12209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &scwork));
12210c37af3bSToby Isaac offset = 0;
12220c37af3bSToby Isaac for (i = 0; i < fSize; i++) {
12230c37af3bSToby Isaac PetscInt qPoints;
12240c37af3bSToby Isaac const PetscReal *p, *w;
12250c37af3bSToby Isaac PetscQuadrature quad;
12260c37af3bSToby Isaac
12279566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dspace, i, &quad));
12289566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &qPoints, &p, &w));
12299566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(weights + Nc * offset, w, Nc * qPoints));
12309566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pointsRef + spdim * offset, p, spdim * qPoints));
1231b3a4bf2aSToby Isaac sizes[i] = qPoints;
12320c37af3bSToby Isaac offset += qPoints;
12330c37af3bSToby Isaac }
12349566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace, fSize, fSize, Nc, nPoints, sizes, pointsRef, weights, work, Amat));
12359566063dSJacob Faibussowitsch PetscCall(MatLUFactor(Amat, NULL, NULL, NULL));
12360c37af3bSToby Isaac for (c = cStart; c < cEnd; c++) {
12370c37af3bSToby Isaac PetscInt parent;
12380c37af3bSToby Isaac PetscInt closureSize, closureSizeP, *closure = NULL, *closureP = NULL;
12390c37af3bSToby Isaac PetscInt *childOffsets, *parentOffsets;
12400c37af3bSToby Isaac
12419566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, c, &parent, NULL));
12420c37af3bSToby Isaac if (parent == c) continue;
12439566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
12440c37af3bSToby Isaac for (i = 0; i < closureSize; i++) {
12450c37af3bSToby Isaac PetscInt p = closure[2 * i];
12460c37af3bSToby Isaac PetscInt conDof;
12470c37af3bSToby Isaac
12480c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue;
1249085f0adfSToby Isaac if (numFields) {
12509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &conDof));
12519371c9d4SSatish Balay } else {
12529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &conDof));
12530c37af3bSToby Isaac }
12540c37af3bSToby Isaac if (conDof) break;
12550c37af3bSToby Isaac }
12560c37af3bSToby Isaac if (i == closureSize) {
12579566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
12580c37af3bSToby Isaac continue;
12590c37af3bSToby Isaac }
12600c37af3bSToby Isaac
12619566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, NULL, &detJ));
12629566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, parent, NULL, v0parent, Jparent, invJparent, &detJparent));
12630c37af3bSToby Isaac for (i = 0; i < nPoints; i++) {
1264c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.};
1265c330f8ffSToby Isaac
1266c330f8ffSToby Isaac CoordinatesRefToReal(spdim, spdim, xi0, v0, J, &pointsRef[i * spdim], vtmp);
1267c330f8ffSToby Isaac CoordinatesRealToRef(spdim, spdim, xi0, v0parent, invJparent, vtmp, &pointsReal[i * spdim]);
12680c37af3bSToby Isaac }
12699566063dSJacob Faibussowitsch PetscCall(EvaluateBasis(bspace, fSize, fSize, Nc, nPoints, sizes, pointsReal, weights, work, Bmat));
12709566063dSJacob Faibussowitsch PetscCall(MatMatSolve(Amat, Bmat, Xmat));
12719566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Xmat, &X));
12729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSizeP, &closureP));
12739566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(closureSize + 1, &childOffsets, closureSizeP + 1, &parentOffsets));
12740c37af3bSToby Isaac childOffsets[0] = 0;
12750c37af3bSToby Isaac for (i = 0; i < closureSize; i++) {
12760c37af3bSToby Isaac PetscInt p = closure[2 * i];
12770c37af3bSToby Isaac PetscInt dof;
12780c37af3bSToby Isaac
1279085f0adfSToby Isaac if (numFields) {
12809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
12819371c9d4SSatish Balay } else {
12829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof));
12830c37af3bSToby Isaac }
128452a3aeb4SToby Isaac childOffsets[i + 1] = childOffsets[i] + dof;
12850c37af3bSToby Isaac }
12860c37af3bSToby Isaac parentOffsets[0] = 0;
12870c37af3bSToby Isaac for (i = 0; i < closureSizeP; i++) {
12880c37af3bSToby Isaac PetscInt p = closureP[2 * i];
12890c37af3bSToby Isaac PetscInt dof;
12900c37af3bSToby Isaac
1291085f0adfSToby Isaac if (numFields) {
12929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
12939371c9d4SSatish Balay } else {
12949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof));
12950c37af3bSToby Isaac }
129652a3aeb4SToby Isaac parentOffsets[i + 1] = parentOffsets[i] + dof;
12970c37af3bSToby Isaac }
12980c37af3bSToby Isaac for (i = 0; i < closureSize; i++) {
12992c44ad04SToby Isaac PetscInt conDof, conOff, aDof, aOff, nWork;
13000c37af3bSToby Isaac PetscInt p = closure[2 * i];
13010c37af3bSToby Isaac PetscInt o = closure[2 * i + 1];
1302085f0adfSToby Isaac const PetscInt *perm;
1303085f0adfSToby Isaac const PetscScalar *flip;
13040c37af3bSToby Isaac
13050c37af3bSToby Isaac if (p < conStart || p >= conEnd) continue;
1306085f0adfSToby Isaac if (numFields) {
13079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &conDof));
13089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &conOff));
13099371c9d4SSatish Balay } else {
13109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &conDof));
13119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &conOff));
13120c37af3bSToby Isaac }
13130c37af3bSToby Isaac if (!conDof) continue;
1314085f0adfSToby Isaac perm = (perms && perms[i]) ? perms[i][o] : NULL;
1315085f0adfSToby Isaac flip = (flips && flips[i]) ? flips[i][o] : NULL;
13169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof));
13179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff));
13182c44ad04SToby Isaac nWork = childOffsets[i + 1] - childOffsets[i];
13190c37af3bSToby Isaac for (k = 0; k < aDof; k++) {
13200c37af3bSToby Isaac PetscInt a = anchors[aOff + k];
13210c37af3bSToby Isaac PetscInt aSecDof, aSecOff;
13220c37af3bSToby Isaac
1323085f0adfSToby Isaac if (numFields) {
13249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aSecDof));
13259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aSecOff));
13269371c9d4SSatish Balay } else {
13279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aSecDof));
13289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aSecOff));
13290c37af3bSToby Isaac }
13300c37af3bSToby Isaac if (!aSecDof) continue;
13310c37af3bSToby Isaac
13320c37af3bSToby Isaac for (j = 0; j < closureSizeP; j++) {
13330c37af3bSToby Isaac PetscInt q = closureP[2 * j];
13340c37af3bSToby Isaac PetscInt oq = closureP[2 * j + 1];
13352c44ad04SToby Isaac
13362c44ad04SToby Isaac if (q == a) {
133752a3aeb4SToby Isaac PetscInt r, s, nWorkP;
1338085f0adfSToby Isaac const PetscInt *permP;
1339085f0adfSToby Isaac const PetscScalar *flipP;
1340085f0adfSToby Isaac
1341085f0adfSToby Isaac permP = (perms && perms[j]) ? perms[j][oq] : NULL;
1342085f0adfSToby Isaac flipP = (flips && flips[j]) ? flips[j][oq] : NULL;
13432c44ad04SToby Isaac nWorkP = parentOffsets[j + 1] - parentOffsets[j];
13442c44ad04SToby Isaac /* get a copy of the child-to-anchor portion of the matrix, and transpose so that rows correspond to the
13451683a169SBarry Smith * child and columns correspond to the anchor: BUT the maxrix returned by MatDenseGetArrayRead() is
13462c44ad04SToby Isaac * column-major, so transpose-transpose = do nothing */
13472c44ad04SToby Isaac for (r = 0; r < nWork; r++) {
1348ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] = X[fSize * (r + childOffsets[i]) + (s + parentOffsets[j])];
13492c44ad04SToby Isaac }
1350ad540459SPierre Jolivet for (r = 0; r < nWork; r++) workIndRow[perm ? perm[r] : r] = conOff + r;
1351ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) workIndCol[permP ? permP[s] : s] = aSecOff + s;
13522c44ad04SToby Isaac if (flip) {
13532c44ad04SToby Isaac for (r = 0; r < nWork; r++) {
1354ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] *= flip[r];
13552c44ad04SToby Isaac }
13562c44ad04SToby Isaac }
13572c44ad04SToby Isaac if (flipP) {
13582c44ad04SToby Isaac for (r = 0; r < nWork; r++) {
1359ad540459SPierre Jolivet for (s = 0; s < nWorkP; s++) scwork[r * nWorkP + s] *= flipP[s];
13602c44ad04SToby Isaac }
13612c44ad04SToby Isaac }
13629566063dSJacob Faibussowitsch PetscCall(MatSetValues(cMat, nWork, workIndRow, nWorkP, workIndCol, scwork, INSERT_VALUES));
13632c44ad04SToby Isaac break;
13640c37af3bSToby Isaac }
13650c37af3bSToby Isaac }
13660c37af3bSToby Isaac }
13670c37af3bSToby Isaac }
13689566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Xmat, &X));
13699566063dSJacob Faibussowitsch PetscCall(PetscFree2(childOffsets, parentOffsets));
13709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
13719566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSizeP, &closureP));
13720c37af3bSToby Isaac }
13739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Amat));
13749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bmat));
13759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Xmat));
13769566063dSJacob Faibussowitsch PetscCall(PetscFree(scwork));
13779566063dSJacob Faibussowitsch PetscCall(PetscFree7(sizes, weights, pointsRef, pointsReal, work, workIndRow, workIndCol));
137848a46eb9SPierre Jolivet if (id == PETSCFV_CLASSID) PetscCall(PetscSpaceDestroy(&bspace));
13790c37af3bSToby Isaac }
13809566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY));
13819566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY));
13829566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJparent));
13839566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors));
13843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
13850c37af3bSToby Isaac }
138695a0b26dSToby Isaac
DMPlexReferenceTreeGetChildrenMatrices(DM refTree,PetscScalar **** childrenMats,PetscInt *** childrenN)1387d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN)
1388d71ae5a4SJacob Faibussowitsch {
1389f7c74593SToby Isaac Mat refCmat;
139021968bf8SToby Isaac PetscDS ds;
1391085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof, maxAnDof, **refPointFieldN;
139221968bf8SToby Isaac PetscScalar ***refPointFieldMats;
139321968bf8SToby Isaac PetscSection refConSec, refAnSec, refSection;
139421968bf8SToby Isaac IS refAnIS;
139521968bf8SToby Isaac const PetscInt *refAnchors;
1396085f0adfSToby Isaac const PetscInt **perms;
1397085f0adfSToby Isaac const PetscScalar **flips;
139895a0b26dSToby Isaac
139995a0b26dSToby Isaac PetscFunctionBegin;
14009566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds));
14019566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields));
1402085f0adfSToby Isaac maxFields = PetscMax(1, numFields);
14039566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL));
14049566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS));
14059566063dSJacob Faibussowitsch PetscCall(ISGetIndices(refAnIS, &refAnchors));
14069566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection));
14079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd));
14089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats));
14099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldN));
14109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof));
14119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof));
14129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows));
14139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxAnDof, &cols));
141495a0b26dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) {
141595a0b26dSToby Isaac PetscInt parent, closureSize, *closure = NULL, pDof;
141695a0b26dSToby Isaac
14179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL));
14189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof));
141995a0b26dSToby Isaac if (!pDof || parent == p) continue;
142095a0b26dSToby Isaac
14219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxFields, &refPointFieldMats[p - pRefStart]));
14229566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxFields, &refPointFieldN[p - pRefStart]));
14239566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parent, PETSC_TRUE, &closureSize, &closure));
1424085f0adfSToby Isaac for (f = 0; f < maxFields; f++) {
1425085f0adfSToby Isaac PetscInt cDof, cOff, numCols, r, i;
142695a0b26dSToby Isaac
1427085f0adfSToby Isaac if (f < numFields) {
14289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof));
14299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff));
14309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(refSection, f, closureSize, closure, &perms, &flips));
1431085f0adfSToby Isaac } else {
14329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof));
14339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff));
14349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(refSection, closureSize, closure, &perms, &flips));
143595a0b26dSToby Isaac }
143695a0b26dSToby Isaac
1437ad540459SPierre Jolivet for (r = 0; r < cDof; r++) rows[r] = cOff + r;
143895a0b26dSToby Isaac numCols = 0;
143995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) {
144095a0b26dSToby Isaac PetscInt q = closure[2 * i];
144195a0b26dSToby Isaac PetscInt aDof, aOff, j;
1442085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL;
144395a0b26dSToby Isaac
1444085f0adfSToby Isaac if (numFields) {
14459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, q, f, &aDof));
14469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, q, f, &aOff));
14479371c9d4SSatish Balay } else {
14489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, q, &aDof));
14499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, q, &aOff));
145095a0b26dSToby Isaac }
145195a0b26dSToby Isaac
1452ad540459SPierre Jolivet for (j = 0; j < aDof; j++) cols[numCols++] = aOff + (perm ? perm[j] : j);
145395a0b26dSToby Isaac }
145495a0b26dSToby Isaac refPointFieldN[p - pRefStart][f] = numCols;
14559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f]));
14569566063dSJacob Faibussowitsch PetscCall(MatGetValues(refCmat, cDof, rows, numCols, cols, refPointFieldMats[p - pRefStart][f]));
1457085f0adfSToby Isaac if (flips) {
1458085f0adfSToby Isaac PetscInt colOff = 0;
1459085f0adfSToby Isaac
1460085f0adfSToby Isaac for (i = 0; i < closureSize; i++) {
1461085f0adfSToby Isaac PetscInt q = closure[2 * i];
1462085f0adfSToby Isaac PetscInt aDof, aOff, j;
1463085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL;
1464085f0adfSToby Isaac
1465085f0adfSToby Isaac if (numFields) {
14669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, q, f, &aDof));
14679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, q, f, &aOff));
14689371c9d4SSatish Balay } else {
14699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, q, &aDof));
14709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, q, &aOff));
1471085f0adfSToby Isaac }
1472085f0adfSToby Isaac if (flip) {
1473085f0adfSToby Isaac PetscInt k;
1474085f0adfSToby Isaac for (k = 0; k < cDof; k++) {
1475ad540459SPierre Jolivet for (j = 0; j < aDof; j++) refPointFieldMats[p - pRefStart][f][k * numCols + colOff + j] *= flip[j];
1476085f0adfSToby Isaac }
1477085f0adfSToby Isaac }
1478085f0adfSToby Isaac colOff += aDof;
1479085f0adfSToby Isaac }
1480085f0adfSToby Isaac }
1481085f0adfSToby Isaac if (numFields) {
14829566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(refSection, f, closureSize, closure, &perms, &flips));
1483085f0adfSToby Isaac } else {
14849566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(refSection, closureSize, closure, &perms, &flips));
1485085f0adfSToby Isaac }
148695a0b26dSToby Isaac }
14879566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parent, PETSC_TRUE, &closureSize, &closure));
148895a0b26dSToby Isaac }
148921968bf8SToby Isaac *childrenMats = refPointFieldMats;
149021968bf8SToby Isaac *childrenN = refPointFieldN;
14919566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(refAnIS, &refAnchors));
14929566063dSJacob Faibussowitsch PetscCall(PetscFree(rows));
14939566063dSJacob Faibussowitsch PetscCall(PetscFree(cols));
14943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
149521968bf8SToby Isaac }
149621968bf8SToby Isaac
DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree,PetscScalar **** childrenMats,PetscInt *** childrenN)1497d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices(DM refTree, PetscScalar ****childrenMats, PetscInt ***childrenN)
1498d71ae5a4SJacob Faibussowitsch {
149921968bf8SToby Isaac PetscDS ds;
150021968bf8SToby Isaac PetscInt **refPointFieldN;
150121968bf8SToby Isaac PetscScalar ***refPointFieldMats;
1502085f0adfSToby Isaac PetscInt numFields, maxFields, pRefStart, pRefEnd, p, f;
150321968bf8SToby Isaac PetscSection refConSec;
150421968bf8SToby Isaac
150521968bf8SToby Isaac PetscFunctionBegin;
150621968bf8SToby Isaac refPointFieldN = *childrenN;
150721968bf8SToby Isaac *childrenN = NULL;
150821968bf8SToby Isaac refPointFieldMats = *childrenMats;
150921968bf8SToby Isaac *childrenMats = NULL;
15109566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds));
15119566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields));
1512367003a6SStefano Zampini maxFields = PetscMax(1, numFields);
15139566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL));
15149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd));
151521968bf8SToby Isaac for (p = pRefStart; p < pRefEnd; p++) {
151621968bf8SToby Isaac PetscInt parent, pDof;
151721968bf8SToby Isaac
15189566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL));
15199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof));
152021968bf8SToby Isaac if (!pDof || parent == p) continue;
152121968bf8SToby Isaac
1522085f0adfSToby Isaac for (f = 0; f < maxFields; f++) {
152321968bf8SToby Isaac PetscInt cDof;
152421968bf8SToby Isaac
1525085f0adfSToby Isaac if (numFields) {
15269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof));
15279371c9d4SSatish Balay } else {
15289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof));
152921968bf8SToby Isaac }
153021968bf8SToby Isaac
15319566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f]));
153221968bf8SToby Isaac }
15339566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart]));
15349566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN[p - pRefStart]));
153521968bf8SToby Isaac }
15369566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats));
15379566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldN));
15383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
153921968bf8SToby Isaac }
154021968bf8SToby Isaac
DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm,PetscSection section,PetscSection conSec,Mat cMat)1541d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexComputeAnchorMatrix_Tree_FromReference(DM dm, PetscSection section, PetscSection conSec, Mat cMat)
1542d71ae5a4SJacob Faibussowitsch {
154321968bf8SToby Isaac DM refTree;
154421968bf8SToby Isaac PetscDS ds;
154521968bf8SToby Isaac Mat refCmat;
1546085f0adfSToby Isaac PetscInt numFields, maxFields, f, pRefStart, pRefEnd, p, maxDof, maxAnDof, *perm, *iperm, pStart, pEnd, conStart, conEnd, **refPointFieldN;
154721968bf8SToby Isaac PetscScalar ***refPointFieldMats, *pointWork;
154821968bf8SToby Isaac PetscSection refConSec, refAnSec, anSec;
154921968bf8SToby Isaac IS refAnIS, anIS;
155021968bf8SToby Isaac const PetscInt *anchors;
155121968bf8SToby Isaac
155221968bf8SToby Isaac PetscFunctionBegin;
155321968bf8SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
15549566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds));
15559566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields));
1556085f0adfSToby Isaac maxFields = PetscMax(1, numFields);
15579566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree));
15589566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, refTree));
1559c77c71ffSToby Isaac PetscCall(DMSetLocalSection(refTree, NULL));
1560c77c71ffSToby Isaac PetscCall(DMSetDefaultConstraints(refTree, NULL, NULL, NULL));
15619566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, &refCmat, NULL));
15629566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, &refAnIS));
15639566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anSec, &anIS));
15649566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anIS, &anchors));
15659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd));
15669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(conSec, &conStart, &conEnd));
15679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof));
15689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refAnSec, &maxAnDof));
15699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof * maxAnDof, &pointWork));
157021968bf8SToby Isaac
157121968bf8SToby Isaac /* step 1: get submats for every constrained point in the reference tree */
15729566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN));
157395a0b26dSToby Isaac
157495a0b26dSToby Isaac /* step 2: compute the preorder */
15759566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
15769566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &perm, pEnd - pStart, &iperm));
157795a0b26dSToby Isaac for (p = pStart; p < pEnd; p++) {
157895a0b26dSToby Isaac perm[p - pStart] = p;
157995a0b26dSToby Isaac iperm[p - pStart] = p - pStart;
158095a0b26dSToby Isaac }
158195a0b26dSToby Isaac for (p = 0; p < pEnd - pStart;) {
158295a0b26dSToby Isaac PetscInt point = perm[p];
158395a0b26dSToby Isaac PetscInt parent;
158495a0b26dSToby Isaac
15859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, NULL));
158695a0b26dSToby Isaac if (parent == point) {
158795a0b26dSToby Isaac p++;
15889371c9d4SSatish Balay } else {
158995a0b26dSToby Isaac PetscInt size, closureSize, *closure = NULL, i;
159095a0b26dSToby Isaac
15919566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure));
159295a0b26dSToby Isaac for (i = 0; i < closureSize; i++) {
159395a0b26dSToby Isaac PetscInt q = closure[2 * i];
159495a0b26dSToby Isaac if (iperm[q - pStart] > iperm[point - pStart]) {
159595a0b26dSToby Isaac /* swap */
159695a0b26dSToby Isaac perm[p] = q;
159795a0b26dSToby Isaac perm[iperm[q - pStart]] = point;
159895a0b26dSToby Isaac iperm[point - pStart] = iperm[q - pStart];
159995a0b26dSToby Isaac iperm[q - pStart] = p;
160095a0b26dSToby Isaac break;
160195a0b26dSToby Isaac }
160295a0b26dSToby Isaac }
160395a0b26dSToby Isaac size = closureSize;
16049566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure));
1605ad540459SPierre Jolivet if (i == size) p++;
160695a0b26dSToby Isaac }
160795a0b26dSToby Isaac }
160895a0b26dSToby Isaac
160995a0b26dSToby Isaac /* step 3: fill the constraint matrix */
161095a0b26dSToby Isaac /* we are going to use a preorder progressive fill strategy. Mat doesn't
161195a0b26dSToby Isaac * allow progressive fill without assembly, so we are going to set up the
161295a0b26dSToby Isaac * values outside of the Mat first.
161395a0b26dSToby Isaac */
161495a0b26dSToby Isaac {
161595a0b26dSToby Isaac PetscInt nRows, row, nnz;
161695a0b26dSToby Isaac PetscBool done;
1617cd6fc93eSToby Isaac PetscInt secStart, secEnd;
161895a0b26dSToby Isaac const PetscInt *ia, *ja;
161995a0b26dSToby Isaac PetscScalar *vals;
162095a0b26dSToby Isaac
1621cd6fc93eSToby Isaac PetscCall(PetscSectionGetChart(section, &secStart, &secEnd));
16229566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done));
162328b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not get RowIJ of constraint matrix");
162495a0b26dSToby Isaac nnz = ia[nRows];
162595a0b26dSToby Isaac /* malloc and then zero rows right before we fill them: this way valgrind
162695a0b26dSToby Isaac * can tell if we are doing progressive fill in the wrong order */
16279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &vals));
162895a0b26dSToby Isaac for (p = 0; p < pEnd - pStart; p++) {
162995a0b26dSToby Isaac PetscInt parent, childid, closureSize, *closure = NULL;
163095a0b26dSToby Isaac PetscInt point = perm[p], pointDof;
163195a0b26dSToby Isaac
16329566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, point, &parent, &childid));
163395a0b26dSToby Isaac if ((point < conStart) || (point >= conEnd) || (parent == point)) continue;
16349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &pointDof));
163595a0b26dSToby Isaac if (!pointDof) continue;
16369566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure));
1637085f0adfSToby Isaac for (f = 0; f < maxFields; f++) {
1638085f0adfSToby Isaac PetscInt cDof, cOff, numCols, numFillCols, i, r, matOffset, offset;
163995a0b26dSToby Isaac PetscScalar *pointMat;
1640085f0adfSToby Isaac const PetscInt **perms;
1641085f0adfSToby Isaac const PetscScalar **flips;
164295a0b26dSToby Isaac
1643085f0adfSToby Isaac if (numFields) {
16449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, point, f, &cDof));
16459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, point, f, &cOff));
16469371c9d4SSatish Balay } else {
16479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, point, &cDof));
16489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, point, &cOff));
164995a0b26dSToby Isaac }
165095a0b26dSToby Isaac if (!cDof) continue;
16519566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(section, f, closureSize, closure, &perms, &flips));
16529566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, closureSize, closure, &perms, &flips));
165395a0b26dSToby Isaac
165495a0b26dSToby Isaac /* make sure that every row for this point is the same size */
165576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) {
165695a0b26dSToby Isaac for (r = 0; r < cDof; r++) {
165795a0b26dSToby Isaac if (cDof > 1 && r) {
165857508eceSPierre Jolivet PetscCheck((ia[cOff + r + 1] - ia[cOff + r]) == (ia[cOff + r] - ia[cOff + r - 1]), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two point rows have different nnz: %" PetscInt_FMT " vs. %" PetscInt_FMT, ia[cOff + r + 1] - ia[cOff + r], ia[cOff + r] - ia[cOff + r - 1]);
165995a0b26dSToby Isaac }
166095a0b26dSToby Isaac }
166176bd3646SJed Brown }
166295a0b26dSToby Isaac /* zero rows */
1663ad540459SPierre Jolivet for (i = ia[cOff]; i < ia[cOff + cDof]; i++) vals[i] = 0.;
166495a0b26dSToby Isaac matOffset = ia[cOff];
166595a0b26dSToby Isaac numFillCols = ia[cOff + 1] - matOffset;
166695a0b26dSToby Isaac pointMat = refPointFieldMats[childid - pRefStart][f];
166795a0b26dSToby Isaac numCols = refPointFieldN[childid - pRefStart][f];
166895a0b26dSToby Isaac offset = 0;
166995a0b26dSToby Isaac for (i = 0; i < closureSize; i++) {
167095a0b26dSToby Isaac PetscInt q = closure[2 * i];
167195a0b26dSToby Isaac PetscInt aDof, aOff, j, k, qConDof, qConOff;
1672085f0adfSToby Isaac const PetscInt *perm = perms ? perms[i] : NULL;
1673085f0adfSToby Isaac const PetscScalar *flip = flips ? flips[i] : NULL;
167495a0b26dSToby Isaac
167595a0b26dSToby Isaac qConDof = qConOff = 0;
1676cd6fc93eSToby Isaac if (q < secStart || q >= secEnd) continue;
1677085f0adfSToby Isaac if (numFields) {
16789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, q, f, &aDof));
16799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, q, f, &aOff));
168095a0b26dSToby Isaac if (q >= conStart && q < conEnd) {
16819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(conSec, q, f, &qConDof));
16829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(conSec, q, f, &qConOff));
168395a0b26dSToby Isaac }
16849371c9d4SSatish Balay } else {
16859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, q, &aDof));
16869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, q, &aOff));
168795a0b26dSToby Isaac if (q >= conStart && q < conEnd) {
16889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(conSec, q, &qConDof));
16899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(conSec, q, &qConOff));
169095a0b26dSToby Isaac }
169195a0b26dSToby Isaac }
169295a0b26dSToby Isaac if (!aDof) continue;
169395a0b26dSToby Isaac if (qConDof) {
169495a0b26dSToby Isaac /* this point has anchors: its rows of the matrix should already
169595a0b26dSToby Isaac * be filled, thanks to preordering */
169695a0b26dSToby Isaac /* first multiply into pointWork, then set in matrix */
169795a0b26dSToby Isaac PetscInt aMatOffset = ia[qConOff];
169895a0b26dSToby Isaac PetscInt aNumFillCols = ia[qConOff + 1] - aMatOffset;
169995a0b26dSToby Isaac for (r = 0; r < cDof; r++) {
170095a0b26dSToby Isaac for (j = 0; j < aNumFillCols; j++) {
170195a0b26dSToby Isaac PetscScalar inVal = 0;
170295a0b26dSToby Isaac for (k = 0; k < aDof; k++) {
1703085f0adfSToby Isaac PetscInt col = perm ? perm[k] : k;
170495a0b26dSToby Isaac
1705085f0adfSToby Isaac inVal += pointMat[r * numCols + offset + col] * vals[aMatOffset + aNumFillCols * k + j] * (flip ? flip[col] : 1.);
170695a0b26dSToby Isaac }
170795a0b26dSToby Isaac pointWork[r * aNumFillCols + j] = inVal;
170895a0b26dSToby Isaac }
170995a0b26dSToby Isaac }
171095a0b26dSToby Isaac /* assume that the columns are sorted, spend less time searching */
171195a0b26dSToby Isaac for (j = 0, k = 0; j < aNumFillCols; j++) {
171295a0b26dSToby Isaac PetscInt col = ja[aMatOffset + j];
171395a0b26dSToby Isaac for (; k < numFillCols; k++) {
1714ad540459SPierre Jolivet if (ja[matOffset + k] == col) break;
171595a0b26dSToby Isaac }
171663a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, col);
1717ad540459SPierre Jolivet for (r = 0; r < cDof; r++) vals[matOffset + numFillCols * r + k] = pointWork[r * aNumFillCols + j];
171895a0b26dSToby Isaac }
17199371c9d4SSatish Balay } else {
172095a0b26dSToby Isaac /* find where to put this portion of pointMat into the matrix */
172195a0b26dSToby Isaac for (k = 0; k < numFillCols; k++) {
1722ad540459SPierre Jolivet if (ja[matOffset + k] == aOff) break;
172395a0b26dSToby Isaac }
172463a3b9bcSJacob Faibussowitsch PetscCheck(k != numFillCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "No nonzero space for (%" PetscInt_FMT ", %" PetscInt_FMT ")", cOff, aOff);
172595a0b26dSToby Isaac for (r = 0; r < cDof; r++) {
1726085f0adfSToby Isaac for (j = 0; j < aDof; j++) {
1727085f0adfSToby Isaac PetscInt col = perm ? perm[j] : j;
1728085f0adfSToby Isaac
1729085f0adfSToby Isaac vals[matOffset + numFillCols * r + k + col] += pointMat[r * numCols + offset + j] * (flip ? flip[col] : 1.);
173095a0b26dSToby Isaac }
173195a0b26dSToby Isaac }
173295a0b26dSToby Isaac }
173395a0b26dSToby Isaac offset += aDof;
173495a0b26dSToby Isaac }
1735085f0adfSToby Isaac if (numFields) {
17369566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, closureSize, closure, &perms, &flips));
1737085f0adfSToby Isaac } else {
17389566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, closureSize, closure, &perms, &flips));
1739085f0adfSToby Isaac }
174095a0b26dSToby Isaac }
17419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, parent, PETSC_TRUE, &closureSize, &closure));
174295a0b26dSToby Isaac }
174348a46eb9SPierre Jolivet for (row = 0; row < nRows; row++) PetscCall(MatSetValues(cMat, 1, &row, ia[row + 1] - ia[row], &ja[ia[row]], &vals[ia[row]], INSERT_VALUES));
17449566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(cMat, 0, PETSC_FALSE, PETSC_FALSE, &nRows, &ia, &ja, &done));
174528b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)cMat), PETSC_ERR_PLIB, "Could not restore RowIJ of constraint matrix");
17469566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(cMat, MAT_FINAL_ASSEMBLY));
17479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(cMat, MAT_FINAL_ASSEMBLY));
17489566063dSJacob Faibussowitsch PetscCall(PetscFree(vals));
174995a0b26dSToby Isaac }
175095a0b26dSToby Isaac
175195a0b26dSToby Isaac /* clean up */
17529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anIS, &anchors));
17539566063dSJacob Faibussowitsch PetscCall(PetscFree2(perm, iperm));
17549566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork));
17559566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN));
17563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
175795a0b26dSToby Isaac }
175895a0b26dSToby Isaac
17596f5f1567SToby Isaac /* refine a single cell on rank 0: this is not intended to provide good local refinement, only to create an example of
17606f5f1567SToby Isaac * a non-conforming mesh. Local refinement comes later */
DMPlexTreeRefineCell(DM dm,PetscInt cell,DM * ncdm)1761d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTreeRefineCell(DM dm, PetscInt cell, DM *ncdm)
1762d71ae5a4SJacob Faibussowitsch {
17636f5f1567SToby Isaac DM K;
1764420f55faSMatthew G. Knepley PetscMPIInt rank;
17656f5f1567SToby Isaac PetscInt dim, *pNewStart, *pNewEnd, *pNewCount, *pOldStart, *pOldEnd, offset, d, pStart, pEnd;
17666f5f1567SToby Isaac PetscInt numNewCones, *newConeSizes, *newCones, *newOrientations;
17676f5f1567SToby Isaac PetscInt *Kembedding;
17686f5f1567SToby Isaac PetscInt *cellClosure = NULL, nc;
17696f5f1567SToby Isaac PetscScalar *newVertexCoords;
17706f5f1567SToby Isaac PetscInt numPointsWithParents, *parents, *childIDs, *perm, *iperm, *preOrient, pOffset;
17716f5f1567SToby Isaac PetscSection parentSection;
17726f5f1567SToby Isaac
17736f5f1567SToby Isaac PetscFunctionBegin;
17749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
17759566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
17769566063dSJacob Faibussowitsch PetscCall(DMPlexCreate(PetscObjectComm((PetscObject)dm), ncdm));
17779566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*ncdm, dim));
17786f5f1567SToby Isaac
17799566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
17809566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &parentSection));
17819566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &K));
17826858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm));
1783dd400576SPatrick Sanan if (rank == 0) {
17846f5f1567SToby Isaac /* compute the new charts */
17859566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(dim + 1, &pNewCount, dim + 1, &pNewStart, dim + 1, &pNewEnd, dim + 1, &pOldStart, dim + 1, &pOldEnd));
17866f5f1567SToby Isaac offset = 0;
17876f5f1567SToby Isaac for (d = 0; d <= dim; d++) {
17886f5f1567SToby Isaac PetscInt pOldCount, kStart, kEnd, k;
17896f5f1567SToby Isaac
17906f5f1567SToby Isaac pNewStart[d] = offset;
17919566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, d, &pOldStart[d], &pOldEnd[d]));
17929566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd));
17936f5f1567SToby Isaac pOldCount = pOldEnd[d] - pOldStart[d];
17946f5f1567SToby Isaac /* adding the new points */
17956f5f1567SToby Isaac pNewCount[d] = pOldCount + kEnd - kStart;
17966f5f1567SToby Isaac if (!d) {
17976f5f1567SToby Isaac /* removing the cell */
17986f5f1567SToby Isaac pNewCount[d]--;
17996f5f1567SToby Isaac }
18006f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) {
18016f5f1567SToby Isaac PetscInt parent;
18029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &parent, NULL));
18036f5f1567SToby Isaac if (parent == k) {
18046f5f1567SToby Isaac /* avoid double counting points that won't actually be new */
18056f5f1567SToby Isaac pNewCount[d]--;
18066f5f1567SToby Isaac }
18076f5f1567SToby Isaac }
18086f5f1567SToby Isaac pNewEnd[d] = pNewStart[d] + pNewCount[d];
18096f5f1567SToby Isaac offset = pNewEnd[d];
18106f5f1567SToby Isaac }
18111dca8a05SBarry Smith PetscCheck(cell >= pOldStart[0] && cell < pOldEnd[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "%" PetscInt_FMT " not in cell range [%" PetscInt_FMT ", %" PetscInt_FMT ")", cell, pOldStart[0], pOldEnd[0]);
18126f5f1567SToby Isaac /* get the current closure of the cell that we are removing */
18139566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure));
18146f5f1567SToby Isaac
18159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pNewEnd[dim], &newConeSizes));
18166f5f1567SToby Isaac {
1817b5a892a1SMatthew G. Knepley DMPolytopeType pct, qct;
18186f5f1567SToby Isaac PetscInt kStart, kEnd, k, closureSizeK, *closureK = NULL, j;
18196f5f1567SToby Isaac
18209566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(K, &kStart, &kEnd));
18219566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(kEnd - kStart, &Kembedding, kEnd - kStart, &perm, kEnd - kStart, &iperm, kEnd - kStart, &preOrient));
18226f5f1567SToby Isaac
18236f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) {
18246f5f1567SToby Isaac perm[k - kStart] = k;
18256f5f1567SToby Isaac iperm[k - kStart] = k - kStart;
18266f5f1567SToby Isaac preOrient[k - kStart] = 0;
18276f5f1567SToby Isaac }
18286f5f1567SToby Isaac
18299566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK));
18306f5f1567SToby Isaac for (j = 1; j < closureSizeK; j++) {
18316f5f1567SToby Isaac PetscInt parentOrientA = closureK[2 * j + 1];
18326f5f1567SToby Isaac PetscInt parentOrientB = cellClosure[2 * j + 1];
18336f5f1567SToby Isaac PetscInt p, q;
18346f5f1567SToby Isaac
18356f5f1567SToby Isaac p = closureK[2 * j];
18366f5f1567SToby Isaac q = cellClosure[2 * j];
18379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(K, p, &pct));
18389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, q, &qct));
18396f5f1567SToby Isaac for (d = 0; d <= dim; d++) {
1840ad540459SPierre Jolivet if (q >= pOldStart[d] && q < pOldEnd[d]) Kembedding[p] = (q - pOldStart[d]) + pNewStart[d];
18416f5f1567SToby Isaac }
1842b5a892a1SMatthew G. Knepley parentOrientA = DMPolytopeConvertNewOrientation_Internal(pct, parentOrientA);
1843b5a892a1SMatthew G. Knepley parentOrientB = DMPolytopeConvertNewOrientation_Internal(qct, parentOrientB);
18446f5f1567SToby Isaac if (parentOrientA != parentOrientB) {
18456f5f1567SToby Isaac PetscInt numChildren, i;
18466f5f1567SToby Isaac const PetscInt *children;
18476f5f1567SToby Isaac
18489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(K, p, &numChildren, &children));
18496f5f1567SToby Isaac for (i = 0; i < numChildren; i++) {
18506f5f1567SToby Isaac PetscInt kPerm, oPerm;
18516f5f1567SToby Isaac
18526f5f1567SToby Isaac k = children[i];
18539566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildSymmetry(K, p, parentOrientA, 0, k, parentOrientB, &oPerm, &kPerm));
18546f5f1567SToby Isaac /* perm = what refTree position I'm in */
18556f5f1567SToby Isaac perm[kPerm - kStart] = k;
18566f5f1567SToby Isaac /* iperm = who is at this position */
18576f5f1567SToby Isaac iperm[k - kStart] = kPerm - kStart;
18586f5f1567SToby Isaac preOrient[kPerm - kStart] = oPerm;
18596f5f1567SToby Isaac }
18606f5f1567SToby Isaac }
18616f5f1567SToby Isaac }
18629566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(K, 0, PETSC_TRUE, &closureSizeK, &closureK));
18636f5f1567SToby Isaac }
18649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, 0, pNewEnd[dim]));
18656f5f1567SToby Isaac offset = 0;
18666f5f1567SToby Isaac numNewCones = 0;
18676f5f1567SToby Isaac for (d = 0; d <= dim; d++) {
18686f5f1567SToby Isaac PetscInt kStart, kEnd, k;
18696f5f1567SToby Isaac PetscInt p;
18706f5f1567SToby Isaac PetscInt size;
18716f5f1567SToby Isaac
18726f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) {
18736f5f1567SToby Isaac /* skip cell 0 */
18746f5f1567SToby Isaac if (p == cell) continue;
18756f5f1567SToby Isaac /* old cones to new cones */
18769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size));
18776f5f1567SToby Isaac newConeSizes[offset++] = size;
18786f5f1567SToby Isaac numNewCones += size;
18796f5f1567SToby Isaac }
18806f5f1567SToby Isaac
18819566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd));
18826f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) {
18836f5f1567SToby Isaac PetscInt kParent;
18846f5f1567SToby Isaac
18859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL));
18866f5f1567SToby Isaac if (kParent != k) {
18876f5f1567SToby Isaac Kembedding[k] = offset;
18889566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size));
18896f5f1567SToby Isaac newConeSizes[offset++] = size;
18906f5f1567SToby Isaac numNewCones += size;
189148a46eb9SPierre Jolivet if (kParent != 0) PetscCall(PetscSectionSetDof(parentSection, Kembedding[k], 1));
18926f5f1567SToby Isaac }
18936f5f1567SToby Isaac }
18946f5f1567SToby Isaac }
18956f5f1567SToby Isaac
18969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection));
18979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(parentSection, &numPointsWithParents));
18989566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numNewCones, &newCones, numNewCones, &newOrientations));
18999566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numPointsWithParents, &parents, numPointsWithParents, &childIDs));
19006f5f1567SToby Isaac
19016f5f1567SToby Isaac /* fill new cones */
19026f5f1567SToby Isaac offset = 0;
19036f5f1567SToby Isaac for (d = 0; d <= dim; d++) {
19046f5f1567SToby Isaac PetscInt kStart, kEnd, k, l;
19056f5f1567SToby Isaac PetscInt p;
19066f5f1567SToby Isaac PetscInt size;
19076f5f1567SToby Isaac const PetscInt *cone, *orientation;
19086f5f1567SToby Isaac
19096f5f1567SToby Isaac for (p = pOldStart[d]; p < pOldEnd[d]; p++) {
19106f5f1567SToby Isaac /* skip cell 0 */
19116f5f1567SToby Isaac if (p == cell) continue;
19126f5f1567SToby Isaac /* old cones to new cones */
19139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size));
19149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone));
19159566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &orientation));
19166f5f1567SToby Isaac for (l = 0; l < size; l++) {
19176f5f1567SToby Isaac newCones[offset] = (cone[l] - pOldStart[d + 1]) + pNewStart[d + 1];
19186f5f1567SToby Isaac newOrientations[offset++] = orientation[l];
19196f5f1567SToby Isaac }
19206f5f1567SToby Isaac }
19216f5f1567SToby Isaac
19229566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, d, &kStart, &kEnd));
19236f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) {
19246f5f1567SToby Isaac PetscInt kPerm = perm[k], kParent;
19256f5f1567SToby Isaac PetscInt preO = preOrient[k];
19266f5f1567SToby Isaac
19279566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, k, &kParent, NULL));
19286f5f1567SToby Isaac if (kParent != k) {
19296f5f1567SToby Isaac /* embed new cones */
19309566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, k, &size));
19319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(K, kPerm, &cone));
19329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(K, kPerm, &orientation));
19336f5f1567SToby Isaac for (l = 0; l < size; l++) {
19346f5f1567SToby Isaac PetscInt q, m = (preO >= 0) ? ((preO + l) % size) : ((size - (preO + 1) - l) % size);
19356f5f1567SToby Isaac PetscInt newO, lSize, oTrue;
1936b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_NUM_POLYTOPES;
19376f5f1567SToby Isaac
19386f5f1567SToby Isaac q = iperm[cone[m]];
19396f5f1567SToby Isaac newCones[offset] = Kembedding[q];
19409566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(K, q, &lSize));
1941b5a892a1SMatthew G. Knepley if (lSize == 2) ct = DM_POLYTOPE_SEGMENT;
1942b5a892a1SMatthew G. Knepley else if (lSize == 4) ct = DM_POLYTOPE_QUADRILATERAL;
1943b5a892a1SMatthew G. Knepley oTrue = DMPolytopeConvertNewOrientation_Internal(ct, orientation[m]);
19446f5f1567SToby Isaac oTrue = ((!lSize) || (preOrient[k] >= 0)) ? oTrue : -(oTrue + 2);
19456f5f1567SToby Isaac newO = DihedralCompose(lSize, oTrue, preOrient[q]);
1946b5a892a1SMatthew G. Knepley newOrientations[offset++] = DMPolytopeConvertOldOrientation_Internal(ct, newO);
19476f5f1567SToby Isaac }
19486f5f1567SToby Isaac if (kParent != 0) {
19496f5f1567SToby Isaac PetscInt newPoint = Kembedding[kParent];
19509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(parentSection, Kembedding[k], &pOffset));
19516f5f1567SToby Isaac parents[pOffset] = newPoint;
19526f5f1567SToby Isaac childIDs[pOffset] = k;
19536f5f1567SToby Isaac }
19546f5f1567SToby Isaac }
19556f5f1567SToby Isaac }
19566f5f1567SToby Isaac }
19576f5f1567SToby Isaac
19589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dim * (pNewEnd[dim] - pNewStart[dim]), &newVertexCoords));
19596f5f1567SToby Isaac
19606f5f1567SToby Isaac /* fill coordinates */
19616f5f1567SToby Isaac offset = 0;
19626f5f1567SToby Isaac {
1963d90620a3SMatthew G. Knepley PetscInt kStart, kEnd, l;
19646f5f1567SToby Isaac PetscSection vSection;
19656f5f1567SToby Isaac PetscInt v;
19666f5f1567SToby Isaac Vec coords;
19676f5f1567SToby Isaac PetscScalar *coordvals;
19686f5f1567SToby Isaac PetscInt dof, off;
1969c111c6b7SMatthew G. Knepley PetscReal v0[3], J[9], detJ;
19706f5f1567SToby Isaac
197176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) {
1972d90620a3SMatthew G. Knepley PetscInt k;
19739566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(K, 0, &kStart, &kEnd));
19746f5f1567SToby Isaac for (k = kStart; k < kEnd; k++) {
19759566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(K, k, NULL, v0, J, NULL, &detJ));
197663a3b9bcSJacob Faibussowitsch PetscCheck(detJ > 0., PETSC_COMM_SELF, PETSC_ERR_PLIB, "reference tree cell %" PetscInt_FMT " has bad determinant", k);
19776f5f1567SToby Isaac }
1978d90620a3SMatthew G. Knepley }
19799566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, NULL, &detJ));
19809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &vSection));
19819566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coords));
19829566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals));
19836f5f1567SToby Isaac for (v = pOldStart[dim]; v < pOldEnd[dim]; v++) {
19849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(vSection, v, &dof));
19859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, v, &off));
1986ad540459SPierre Jolivet for (l = 0; l < dof; l++) newVertexCoords[offset++] = coordvals[off + l];
19876f5f1567SToby Isaac }
19889566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals));
19896f5f1567SToby Isaac
19909566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(K, &vSection));
19919566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(K, &coords));
19929566063dSJacob Faibussowitsch PetscCall(VecGetArray(coords, &coordvals));
19939566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(K, 0, &kStart, &kEnd));
19946f5f1567SToby Isaac for (v = kStart; v < kEnd; v++) {
19959bc368c7SMatthew G. Knepley PetscReal coord[3], newCoord[3];
19966f5f1567SToby Isaac PetscInt vPerm = perm[v];
19976f5f1567SToby Isaac PetscInt kParent;
1998c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.};
19996f5f1567SToby Isaac
20009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(K, v, &kParent, NULL));
20016f5f1567SToby Isaac if (kParent != v) {
20026f5f1567SToby Isaac /* this is a new vertex */
20039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(vSection, vPerm, &off));
20049bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) coord[l] = PetscRealPart(coordvals[off + l]);
2005367003a6SStefano Zampini CoordinatesRefToReal(dim, dim, xi0, v0, J, coord, newCoord);
20069bc368c7SMatthew G. Knepley for (l = 0; l < dim; ++l) newVertexCoords[offset + l] = newCoord[l];
20076f5f1567SToby Isaac offset += dim;
20086f5f1567SToby Isaac }
20096f5f1567SToby Isaac }
20109566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coords, &coordvals));
20116f5f1567SToby Isaac }
20126f5f1567SToby Isaac
20136f5f1567SToby Isaac /* need to reverse the order of pNewCount: vertices first, cells last */
20146f5f1567SToby Isaac for (d = 0; d < (dim + 1) / 2; d++) {
20156f5f1567SToby Isaac PetscInt tmp;
20166f5f1567SToby Isaac
20176f5f1567SToby Isaac tmp = pNewCount[d];
20186f5f1567SToby Isaac pNewCount[d] = pNewCount[dim - d];
20196f5f1567SToby Isaac pNewCount[dim - d] = tmp;
20206f5f1567SToby Isaac }
20216f5f1567SToby Isaac
20229566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, pNewCount, newConeSizes, newCones, newOrientations, newVertexCoords));
20239566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K));
20249566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, parents, childIDs));
20256f5f1567SToby Isaac
20266f5f1567SToby Isaac /* clean up */
20279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &nc, &cellClosure));
20289566063dSJacob Faibussowitsch PetscCall(PetscFree5(pNewCount, pNewStart, pNewEnd, pOldStart, pOldEnd));
20299566063dSJacob Faibussowitsch PetscCall(PetscFree(newConeSizes));
20309566063dSJacob Faibussowitsch PetscCall(PetscFree2(newCones, newOrientations));
20319566063dSJacob Faibussowitsch PetscCall(PetscFree(newVertexCoords));
20329566063dSJacob Faibussowitsch PetscCall(PetscFree2(parents, childIDs));
20339566063dSJacob Faibussowitsch PetscCall(PetscFree4(Kembedding, perm, iperm, preOrient));
20349371c9d4SSatish Balay } else {
20356f5f1567SToby Isaac PetscInt p, counts[4];
20366f5f1567SToby Isaac PetscInt *coneSizes, *cones, *orientations;
20376f5f1567SToby Isaac Vec coordVec;
20386f5f1567SToby Isaac PetscScalar *coords;
20396f5f1567SToby Isaac
20406f5f1567SToby Isaac for (d = 0; d <= dim; d++) {
20416f5f1567SToby Isaac PetscInt dStart, dEnd;
20426f5f1567SToby Isaac
20439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &dStart, &dEnd));
20446f5f1567SToby Isaac counts[d] = dEnd - dStart;
20456f5f1567SToby Isaac }
20469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &coneSizes));
204748a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(DMPlexGetConeSize(dm, p, &coneSizes[p - pStart]));
20489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones));
20499566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientations(dm, &orientations));
20509566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordVec));
20519566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordVec, &coords));
20526f5f1567SToby Isaac
20539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(parentSection, pStart, pEnd));
20549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(parentSection));
20559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*ncdm, dim, counts, coneSizes, cones, orientations, NULL));
20569566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(*ncdm, K));
20579566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(*ncdm, parentSection, NULL, NULL));
20589566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordVec, &coords));
20596f5f1567SToby Isaac }
20609566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&parentSection));
20613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
20626f5f1567SToby Isaac }
20636ecaa68aSToby Isaac
DMPlexComputeInterpolatorTree(DM coarse,DM fine,PetscSF coarseToFine,PetscInt * childIds,Mat mat)2064d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInterpolatorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat)
2065d71ae5a4SJacob Faibussowitsch {
20666ecaa68aSToby Isaac PetscSF coarseToFineEmbedded;
20676ecaa68aSToby Isaac PetscSection globalCoarse, globalFine;
20686ecaa68aSToby Isaac PetscSection localCoarse, localFine;
20696ecaa68aSToby Isaac PetscSection aSec, cSec;
20706ecaa68aSToby Isaac PetscSection rootIndicesSec, rootMatricesSec;
207146bdb399SToby Isaac PetscSection leafIndicesSec, leafMatricesSec;
207246bdb399SToby Isaac PetscInt *rootIndices, *leafIndices;
207346bdb399SToby Isaac PetscScalar *rootMatrices, *leafMatrices;
20746ecaa68aSToby Isaac IS aIS;
20756ecaa68aSToby Isaac const PetscInt *anchors;
20766ecaa68aSToby Isaac Mat cMat;
20774acb8e1eSToby Isaac PetscInt numFields, maxFields;
20786ecaa68aSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p;
20796ecaa68aSToby Isaac PetscInt aStart, aEnd, cStart, cEnd;
20801c58ffc4SToby Isaac PetscInt *maxChildIds;
2081e44e4e7fSToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO;
20824acb8e1eSToby Isaac const PetscInt ***perms;
20834acb8e1eSToby Isaac const PetscScalar ***flips;
20846ecaa68aSToby Isaac
20856ecaa68aSToby Isaac PetscFunctionBegin;
20869566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC));
20879566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF));
20889566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine));
20896ecaa68aSToby Isaac { /* winnow fine points that don't have global dofs out of the sf */
209089698031SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, nleaves, l;
209189698031SToby Isaac const PetscInt *leaves;
20926ecaa68aSToby Isaac
20939566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL));
209489698031SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) {
209589698031SToby Isaac p = leaves ? leaves[l] : l;
20969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof));
20979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof));
2098ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++;
20996ecaa68aSToby Isaac }
21009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs));
21017cc7abc7SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) {
210289698031SToby Isaac p = leaves ? leaves[l] : l;
21039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof));
21049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof));
2105ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = l;
21066ecaa68aSToby Isaac }
21079566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded));
21089566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs));
21096ecaa68aSToby Isaac }
21106ecaa68aSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */
21119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds));
2112ad540459SPierre Jolivet for (p = pStartC; p < pEndC; p++) maxChildIds[p - pStartC] = -2;
211357168dbeSPierre Jolivet PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX));
211457168dbeSPierre Jolivet PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, childIds, maxChildIds, MPI_MAX));
211546bdb399SToby Isaac
21169566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse));
21179566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse));
211846bdb399SToby Isaac
21199566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS));
21209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors));
21219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
212246bdb399SToby Isaac
21239566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL));
21249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd));
212546bdb399SToby Isaac
212646bdb399SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */
21279566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec));
21289566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootMatricesSec));
21299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootIndicesSec, pStartC, pEndC));
21309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootMatricesSec, pStartC, pEndC));
21319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields));
2132713c1c5dSToby Isaac maxFields = PetscMax(1, numFields);
21339566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields + 1, &offsets, maxFields + 1, &offsetsCopy, maxFields + 1, &newOffsets, maxFields + 1, &newOffsetsCopy, maxFields + 1, &rowOffsets, maxFields + 1, &numD, maxFields + 1, &numO));
21349566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxFields + 1, (PetscInt ****)&perms, maxFields + 1, (PetscScalar ****)&flips));
21359566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)perms, (maxFields + 1) * sizeof(const PetscInt **)));
21369566063dSJacob Faibussowitsch PetscCall(PetscMemzero((void *)flips, (maxFields + 1) * sizeof(const PetscScalar **)));
213746bdb399SToby Isaac
213846bdb399SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */
21398d2f55e7SToby Isaac PetscInt dof, matSize = 0;
21406ecaa68aSToby Isaac PetscInt aDof = 0;
21416ecaa68aSToby Isaac PetscInt cDof = 0;
21426ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC];
21436ecaa68aSToby Isaac PetscInt numRowIndices = 0;
21446ecaa68aSToby Isaac PetscInt numColIndices = 0;
2145f13f9184SToby Isaac PetscInt f;
21466ecaa68aSToby Isaac
21479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof));
2148ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1);
214948a46eb9SPierre Jolivet if (p >= aStart && p < aEnd) PetscCall(PetscSectionGetDof(aSec, p, &aDof));
215048a46eb9SPierre Jolivet if (p >= cStart && p < cEnd) PetscCall(PetscSectionGetDof(cSec, p, &cDof));
2151f13f9184SToby Isaac for (f = 0; f <= numFields; f++) offsets[f] = 0;
2152f13f9184SToby Isaac for (f = 0; f <= numFields; f++) newOffsets[f] = 0;
21536ecaa68aSToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */
2154f13f9184SToby Isaac PetscInt *closure = NULL, closureSize, cl;
21556ecaa68aSToby Isaac
21569566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure));
215746bdb399SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */
21586ecaa68aSToby Isaac PetscInt c = closure[2 * cl], clDof;
21596ecaa68aSToby Isaac
21609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof));
21616ecaa68aSToby Isaac numRowIndices += clDof;
21626ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
21639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &clDof));
21646ecaa68aSToby Isaac offsets[f + 1] += clDof;
21656ecaa68aSToby Isaac }
21666ecaa68aSToby Isaac }
21676ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
21686ecaa68aSToby Isaac offsets[f + 1] += offsets[f];
21696ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1];
21706ecaa68aSToby Isaac }
217146bdb399SToby Isaac /* get the number of indices needed and their field offsets */
21729566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, NULL, NULL, NULL, &numColIndices, NULL, NULL, newOffsets, PETSC_FALSE));
21739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure));
21746ecaa68aSToby Isaac if (!numColIndices) { /* there are no hanging constraint modifications, so the matrix is just the identity: do not send it */
21756ecaa68aSToby Isaac numColIndices = numRowIndices;
21766ecaa68aSToby Isaac matSize = 0;
21779371c9d4SSatish Balay } else if (numFields) { /* we send one submat for each field: sum their sizes */
21786ecaa68aSToby Isaac matSize = 0;
21796ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
21806ecaa68aSToby Isaac PetscInt numRow, numCol;
21816ecaa68aSToby Isaac
21826ecaa68aSToby Isaac numRow = offsets[f + 1] - offsets[f];
2183f13f9184SToby Isaac numCol = newOffsets[f + 1] - newOffsets[f];
21846ecaa68aSToby Isaac matSize += numRow * numCol;
21856ecaa68aSToby Isaac }
21869371c9d4SSatish Balay } else {
21876ecaa68aSToby Isaac matSize = numRowIndices * numColIndices;
21886ecaa68aSToby Isaac }
2189f13f9184SToby Isaac } else if (maxChildId == -1) {
21908d2f55e7SToby Isaac if (cDof > 0) { /* this point's dofs are interpolated via cMat: get the submatrix of cMat */
2191f13f9184SToby Isaac PetscInt aOff, a;
21926ecaa68aSToby Isaac
21939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff));
21946ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
21956ecaa68aSToby Isaac PetscInt fDof;
21966ecaa68aSToby Isaac
21979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof));
219821968bf8SToby Isaac offsets[f + 1] = fDof;
21996ecaa68aSToby Isaac }
22006ecaa68aSToby Isaac for (a = 0; a < aDof; a++) {
22016ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], aLocalDof;
22026ecaa68aSToby Isaac
22039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, anchor, &aLocalDof));
22046ecaa68aSToby Isaac numColIndices += aLocalDof;
22056ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
22066ecaa68aSToby Isaac PetscInt fDof;
22076ecaa68aSToby Isaac
22089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof));
220921968bf8SToby Isaac newOffsets[f + 1] += fDof;
22106ecaa68aSToby Isaac }
22116ecaa68aSToby Isaac }
22126ecaa68aSToby Isaac if (numFields) {
22136ecaa68aSToby Isaac matSize = 0;
2214ad540459SPierre Jolivet for (f = 0; f < numFields; f++) matSize += offsets[f + 1] * newOffsets[f + 1];
22159371c9d4SSatish Balay } else {
22166ecaa68aSToby Isaac matSize = numColIndices * dof;
22176ecaa68aSToby Isaac }
22189371c9d4SSatish Balay } else { /* no children, and no constraints on dofs: just get the global indices */
22196ecaa68aSToby Isaac numColIndices = dof;
22206ecaa68aSToby Isaac matSize = 0;
22216ecaa68aSToby Isaac }
22228d2f55e7SToby Isaac }
222346bdb399SToby Isaac /* we will pack the column indices with the field offsets */
22249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootIndicesSec, p, numColIndices ? numColIndices + 2 * numFields : 0));
22259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootMatricesSec, p, matSize));
22266ecaa68aSToby Isaac }
22279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootIndicesSec));
22289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootMatricesSec));
22296ecaa68aSToby Isaac {
22306ecaa68aSToby Isaac PetscInt numRootIndices, numRootMatrices;
22316ecaa68aSToby Isaac
22329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices));
22339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootMatricesSec, &numRootMatrices));
22349566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numRootIndices, &rootIndices, numRootMatrices, &rootMatrices));
22356ecaa68aSToby Isaac for (p = pStartC; p < pEndC; p++) {
22367853b79dSToby Isaac PetscInt numRowIndices = 0, numColIndices, matSize, dof;
2237f13f9184SToby Isaac PetscInt pIndOff, pMatOff, f;
22386ecaa68aSToby Isaac PetscInt *pInd;
22396ecaa68aSToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC];
22406ecaa68aSToby Isaac PetscScalar *pMat = NULL;
22416ecaa68aSToby Isaac
22429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, p, &numColIndices));
2243ad540459SPierre Jolivet if (!numColIndices) continue;
2244f13f9184SToby Isaac for (f = 0; f <= numFields; f++) {
2245f13f9184SToby Isaac offsets[f] = 0;
2246f13f9184SToby Isaac newOffsets[f] = 0;
2247f13f9184SToby Isaac offsetsCopy[f] = 0;
2248f13f9184SToby Isaac newOffsetsCopy[f] = 0;
2249f13f9184SToby Isaac }
22506ecaa68aSToby Isaac numColIndices -= 2 * numFields;
22519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, p, &pIndOff));
2252f4f49eeaSPierre Jolivet pInd = &rootIndices[pIndOff];
22539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootMatricesSec, p, &matSize));
22546ecaa68aSToby Isaac if (matSize) {
22559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootMatricesSec, p, &pMatOff));
22566ecaa68aSToby Isaac pMat = &rootMatrices[pMatOff];
22576ecaa68aSToby Isaac }
22589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof));
2259ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1);
22606ecaa68aSToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */
22616ecaa68aSToby Isaac PetscInt i, j;
22626ecaa68aSToby Isaac
22637853b79dSToby Isaac if (matSize == 0) { /* don't need to calculate the mat, just the indices */
22646ecaa68aSToby Isaac PetscInt numIndices, *indices;
22659566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL));
226608401ef6SPierre Jolivet PetscCheck(numIndices == numColIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "mismatching constraint indices calculations");
2267ad540459SPierre Jolivet for (i = 0; i < numColIndices; i++) pInd[i] = indices[i];
22686ecaa68aSToby Isaac for (i = 0; i < numFields; i++) {
226946bdb399SToby Isaac pInd[numColIndices + i] = offsets[i + 1];
227046bdb399SToby Isaac pInd[numColIndices + numFields + i] = offsets[i + 1];
22716ecaa68aSToby Isaac }
22729566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(coarse, localCoarse, globalCoarse, p, PETSC_TRUE, &numIndices, &indices, offsets, NULL));
22739371c9d4SSatish Balay } else {
22746ecaa68aSToby Isaac PetscInt closureSize, *closure = NULL, cl;
22756ecaa68aSToby Isaac PetscScalar *pMatIn, *pMatModified;
22766ecaa68aSToby Isaac PetscInt numPoints, *points;
22776ecaa68aSToby Isaac
22787853b79dSToby Isaac {
22797853b79dSToby Isaac PetscInt *closure = NULL, closureSize, cl;
22807853b79dSToby Isaac
22817853b79dSToby Isaac PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure));
22827853b79dSToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */
22837853b79dSToby Isaac PetscInt c = closure[2 * cl], clDof;
22847853b79dSToby Isaac
22857853b79dSToby Isaac PetscCall(PetscSectionGetDof(localCoarse, c, &clDof));
22867853b79dSToby Isaac numRowIndices += clDof;
22877853b79dSToby Isaac }
22887853b79dSToby Isaac PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure));
22897853b79dSToby Isaac }
22907853b79dSToby Isaac
22919566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices * numRowIndices, MPIU_SCALAR, &pMatIn));
22926ecaa68aSToby Isaac for (i = 0; i < numRowIndices; i++) { /* initialize to the identity */
2293ad540459SPierre Jolivet for (j = 0; j < numRowIndices; j++) pMatIn[i * numRowIndices + j] = (i == j) ? 1. : 0.;
22946ecaa68aSToby Isaac }
22959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure));
22964acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) {
22979566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f]));
22989566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f]));
22994acb8e1eSToby Isaac }
23006ecaa68aSToby Isaac if (numFields) {
23016ecaa68aSToby Isaac for (cl = 0; cl < closureSize; cl++) {
23026ecaa68aSToby Isaac PetscInt c = closure[2 * cl];
23036ecaa68aSToby Isaac
23046ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
23056ecaa68aSToby Isaac PetscInt fDof;
23066ecaa68aSToby Isaac
23079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, c, f, &fDof));
23086ecaa68aSToby Isaac offsets[f + 1] += fDof;
23096ecaa68aSToby Isaac }
23106ecaa68aSToby Isaac }
23116ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
23126ecaa68aSToby Isaac offsets[f + 1] += offsets[f];
23136ecaa68aSToby Isaac newOffsets[f + 1] = offsets[f + 1];
23146ecaa68aSToby Isaac }
23156ecaa68aSToby Isaac }
23164acb8e1eSToby Isaac /* TODO : flips here ? */
23176ecaa68aSToby Isaac /* apply hanging node constraints on the right, get the new points and the new offsets */
23189566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(coarse, localCoarse, closureSize, numRowIndices, closure, perms, pMatIn, &numPoints, NULL, &points, &pMatModified, newOffsets, PETSC_FALSE));
23194acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) {
23209566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, closureSize, closure, &perms[f], &flips[f]));
23219566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, closureSize, closure, &perms[f], &flips[f]));
23224acb8e1eSToby Isaac }
23234acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) {
23249566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionGetFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f]));
23259566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(localCoarse, numPoints, points, &perms[f], &flips[f]));
23264acb8e1eSToby Isaac }
23276ecaa68aSToby Isaac if (!numFields) {
2328ad540459SPierre Jolivet for (i = 0; i < numRowIndices * numColIndices; i++) pMat[i] = pMatModified[i];
23299371c9d4SSatish Balay } else {
2330f13f9184SToby Isaac PetscInt i, j, count;
23316ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) {
23326ecaa68aSToby Isaac for (i = offsets[f]; i < offsets[f + 1]; i++) {
2333ad540459SPierre Jolivet for (j = newOffsets[f]; j < newOffsets[f + 1]; j++, count++) pMat[count] = pMatModified[i * numColIndices + j];
23346ecaa68aSToby Isaac }
23356ecaa68aSToby Isaac }
23366ecaa68aSToby Isaac }
23379566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatModified));
23389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure));
23399566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices * numColIndices, MPIU_SCALAR, &pMatIn));
23406ecaa68aSToby Isaac if (numFields) {
234146bdb399SToby Isaac for (f = 0; f < numFields; f++) {
234246bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1];
234346bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1];
23446ecaa68aSToby Isaac }
23454acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) {
23464acb8e1eSToby Isaac PetscInt globalOff, c = points[2 * cl];
23479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff));
23489566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perms, cl, NULL, pInd));
23496ecaa68aSToby Isaac }
23506ecaa68aSToby Isaac } else {
23514acb8e1eSToby Isaac for (cl = 0; cl < numPoints; cl++) {
23524acb8e1eSToby Isaac PetscInt c = points[2 * cl], globalOff;
23534acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][cl] : NULL;
23544acb8e1eSToby Isaac
23559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, c, &globalOff));
23569566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, c, globalOff < 0 ? -(globalOff + 1) : globalOff, newOffsets, PETSC_FALSE, perm, NULL, pInd));
23576ecaa68aSToby Isaac }
23586ecaa68aSToby Isaac }
23594acb8e1eSToby Isaac for (f = 0; f < maxFields; f++) {
23609566063dSJacob Faibussowitsch if (numFields) PetscCall(PetscSectionRestoreFieldPointSyms(localCoarse, f, numPoints, points, &perms[f], &flips[f]));
23619566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(localCoarse, numPoints, points, &perms[f], &flips[f]));
23624acb8e1eSToby Isaac }
23639566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numPoints, MPIU_SCALAR, &points));
23646ecaa68aSToby Isaac }
23659371c9d4SSatish Balay } else if (matSize) {
23666ecaa68aSToby Isaac PetscInt cOff;
23677853b79dSToby Isaac PetscInt *rowIndices, *colIndices, a, aDof = 0, aOff;
23686ecaa68aSToby Isaac
23697853b79dSToby Isaac numRowIndices = dof;
23709566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices));
23719566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(coarse, numColIndices, MPIU_INT, &colIndices));
23729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &cOff));
23739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &aDof));
23749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &aOff));
23756ecaa68aSToby Isaac if (numFields) {
23766ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
23776ecaa68aSToby Isaac PetscInt fDof;
2378f13f9184SToby Isaac
23799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &fDof));
23806ecaa68aSToby Isaac offsets[f + 1] = fDof;
23816ecaa68aSToby Isaac for (a = 0; a < aDof; a++) {
23826ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff];
23839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, anchor, f, &fDof));
23846ecaa68aSToby Isaac newOffsets[f + 1] += fDof;
23856ecaa68aSToby Isaac }
23866ecaa68aSToby Isaac }
23876ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
23886ecaa68aSToby Isaac offsets[f + 1] += offsets[f];
23896ecaa68aSToby Isaac offsetsCopy[f + 1] = offsets[f + 1];
23906ecaa68aSToby Isaac newOffsets[f + 1] += newOffsets[f];
23916ecaa68aSToby Isaac newOffsetsCopy[f + 1] = newOffsets[f + 1];
23926ecaa68aSToby Isaac }
23939566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, -1, NULL, rowIndices));
23946ecaa68aSToby Isaac for (a = 0; a < aDof; a++) {
23956ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff;
23969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff));
23979566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, -1, NULL, colIndices));
23986ecaa68aSToby Isaac }
23999371c9d4SSatish Balay } else {
24009566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, p, cOff, offsetsCopy, PETSC_TRUE, NULL, NULL, rowIndices));
24016ecaa68aSToby Isaac for (a = 0; a < aDof; a++) {
24026ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff], lOff;
24039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, anchor, &lOff));
24049566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_TRUE, anchor, lOff, newOffsetsCopy, PETSC_TRUE, NULL, NULL, colIndices));
24056ecaa68aSToby Isaac }
24066ecaa68aSToby Isaac }
24076ecaa68aSToby Isaac if (numFields) {
2408f13f9184SToby Isaac PetscInt count, a;
2409f13f9184SToby Isaac
24106ecaa68aSToby Isaac for (f = 0, count = 0; f < numFields; f++) {
24116ecaa68aSToby Isaac PetscInt iSize = offsets[f + 1] - offsets[f];
24126ecaa68aSToby Isaac PetscInt jSize = newOffsets[f + 1] - newOffsets[f];
24139566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, iSize, &rowIndices[offsets[f]], jSize, &colIndices[newOffsets[f]], &pMat[count]));
24146ecaa68aSToby Isaac count += iSize * jSize;
241546bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1];
241646bdb399SToby Isaac pInd[numColIndices + numFields + f] = newOffsets[f + 1];
24176ecaa68aSToby Isaac }
24186ecaa68aSToby Isaac for (a = 0; a < aDof; a++) {
24196ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff];
24206ecaa68aSToby Isaac PetscInt gOff;
24219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff));
24229566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, -1, NULL, pInd));
24236ecaa68aSToby Isaac }
24249371c9d4SSatish Balay } else {
24256ecaa68aSToby Isaac PetscInt a;
24269566063dSJacob Faibussowitsch PetscCall(MatGetValues(cMat, numRowIndices, rowIndices, numColIndices, colIndices, pMat));
24276ecaa68aSToby Isaac for (a = 0; a < aDof; a++) {
24286ecaa68aSToby Isaac PetscInt anchor = anchors[a + aOff];
24296ecaa68aSToby Isaac PetscInt gOff;
24309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, anchor, &gOff));
24319566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, anchor, gOff < 0 ? -(gOff + 1) : gOff, newOffsets, PETSC_FALSE, NULL, NULL, pInd));
24326ecaa68aSToby Isaac }
24336ecaa68aSToby Isaac }
24349566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numColIndices, MPIU_INT, &colIndices));
24359566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(coarse, numRowIndices, MPIU_INT, &rowIndices));
24369371c9d4SSatish Balay } else {
24376ecaa68aSToby Isaac PetscInt gOff;
24386ecaa68aSToby Isaac
24399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff));
24406ecaa68aSToby Isaac if (numFields) {
24416ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
24426ecaa68aSToby Isaac PetscInt fDof;
24439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof));
24446ecaa68aSToby Isaac offsets[f + 1] = fDof + offsets[f];
24456ecaa68aSToby Isaac }
24466ecaa68aSToby Isaac for (f = 0; f < numFields; f++) {
244746bdb399SToby Isaac pInd[numColIndices + f] = offsets[f + 1];
244846bdb399SToby Isaac pInd[numColIndices + numFields + f] = offsets[f + 1];
24496ecaa68aSToby Isaac }
24509566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd));
2451367003a6SStefano Zampini } else {
24529566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd));
24536ecaa68aSToby Isaac }
24546ecaa68aSToby Isaac }
24556ecaa68aSToby Isaac }
24569566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds));
24576ecaa68aSToby Isaac }
245846bdb399SToby Isaac {
245946bdb399SToby Isaac PetscSF indicesSF, matricesSF;
246046bdb399SToby Isaac PetscInt *remoteOffsetsIndices, *remoteOffsetsMatrices, numLeafIndices, numLeafMatrices;
246146bdb399SToby Isaac
24629566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec));
24639566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafMatricesSec));
24649566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootIndicesSec, &remoteOffsetsIndices, leafIndicesSec));
24659566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootMatricesSec, &remoteOffsetsMatrices, leafMatricesSec));
24669566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootIndicesSec, remoteOffsetsIndices, leafIndicesSec, &indicesSF));
24679566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootMatricesSec, remoteOffsetsMatrices, leafMatricesSec, &matricesSF));
24689566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded));
24699566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsIndices));
24709566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsMatrices));
24719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numLeafIndices));
24729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafMatricesSec, &numLeafMatrices));
24739566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numLeafIndices, &leafIndices, numLeafMatrices, &leafMatrices));
24749566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE));
24759566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE));
24769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, rootIndices, leafIndices, MPI_REPLACE));
24779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matricesSF, MPIU_SCALAR, rootMatrices, leafMatrices, MPI_REPLACE));
24789566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&matricesSF));
24799566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF));
24809566063dSJacob Faibussowitsch PetscCall(PetscFree2(rootIndices, rootMatrices));
24819566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec));
24829566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootMatricesSec));
248346bdb399SToby Isaac }
248446bdb399SToby Isaac /* count to preallocate */
24859566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine));
248646bdb399SToby Isaac {
248746bdb399SToby Isaac PetscInt nGlobal;
248846bdb399SToby Isaac PetscInt *dnnz, *onnz;
2489b9a5774bSToby Isaac PetscLayout rowMap, colMap;
2490b9a5774bSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd;
24911c58ffc4SToby Isaac PetscInt maxDof;
24921c58ffc4SToby Isaac PetscInt *rowIndices;
24931c58ffc4SToby Isaac DM refTree;
24941c58ffc4SToby Isaac PetscInt **refPointFieldN;
24951c58ffc4SToby Isaac PetscScalar ***refPointFieldMats;
24961c58ffc4SToby Isaac PetscSection refConSec, refAnSec;
24970eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, maxConDof, maxColumns, leafStart, leafEnd;
24981c58ffc4SToby Isaac PetscScalar *pointWork;
249946bdb399SToby Isaac
25009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(globalFine, &nGlobal));
25019566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nGlobal, &dnnz, nGlobal, &onnz));
25029566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap));
25039566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap));
25049566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap));
25059566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd));
25069566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd));
25079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof));
25089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafIndicesSec, &leafStart, &leafEnd));
25099566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices));
25100eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) {
251146bdb399SToby Isaac PetscInt gDof, gcDof, gOff;
251246bdb399SToby Isaac PetscInt numColIndices, pIndOff, *pInd;
251346bdb399SToby Isaac PetscInt matSize;
251421968bf8SToby Isaac PetscInt i;
251546bdb399SToby Isaac
25169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof));
25179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof));
2518ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue;
25199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff));
252008401ef6SPierre Jolivet PetscCheck(gOff >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I though having global dofs meant a non-negative offset");
25211dca8a05SBarry Smith PetscCheck(gOff >= rowStart && (gOff + gDof - gcDof) <= rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "I thought the row map would constrain the global dofs");
25229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices));
25239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff));
252446bdb399SToby Isaac numColIndices -= 2 * numFields;
252508401ef6SPierre Jolivet PetscCheck(numColIndices > 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "global fine dof with no dofs to interpolate from");
252646bdb399SToby Isaac pInd = &leafIndices[pIndOff];
252721968bf8SToby Isaac offsets[0] = 0;
252821968bf8SToby Isaac offsetsCopy[0] = 0;
252921968bf8SToby Isaac newOffsets[0] = 0;
253021968bf8SToby Isaac newOffsetsCopy[0] = 0;
253146bdb399SToby Isaac if (numFields) {
253221968bf8SToby Isaac PetscInt f;
253346bdb399SToby Isaac for (f = 0; f < numFields; f++) {
253446bdb399SToby Isaac PetscInt rowDof;
253546bdb399SToby Isaac
25369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof));
253721968bf8SToby Isaac offsets[f + 1] = offsets[f] + rowDof;
253821968bf8SToby Isaac offsetsCopy[f + 1] = offsets[f + 1];
253921968bf8SToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f];
254021968bf8SToby Isaac numD[f] = 0;
254121968bf8SToby Isaac numO[f] = 0;
254246bdb399SToby Isaac }
25439566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices));
254446bdb399SToby Isaac for (f = 0; f < numFields; f++) {
254521968bf8SToby Isaac PetscInt colOffset = newOffsets[f];
254621968bf8SToby Isaac PetscInt numFieldCols = newOffsets[f + 1] - newOffsets[f];
254746bdb399SToby Isaac
254846bdb399SToby Isaac for (i = 0; i < numFieldCols; i++) {
254946bdb399SToby Isaac PetscInt gInd = pInd[i + colOffset];
255046bdb399SToby Isaac
255146bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) {
255221968bf8SToby Isaac numD[f]++;
25539371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */
255421968bf8SToby Isaac numO[f]++;
255546bdb399SToby Isaac }
255646bdb399SToby Isaac }
255746bdb399SToby Isaac }
25589371c9d4SSatish Balay } else {
25599566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices));
256021968bf8SToby Isaac numD[0] = 0;
256121968bf8SToby Isaac numO[0] = 0;
256246bdb399SToby Isaac for (i = 0; i < numColIndices; i++) {
256346bdb399SToby Isaac PetscInt gInd = pInd[i];
256446bdb399SToby Isaac
256546bdb399SToby Isaac if (gInd >= colStart && gInd < colEnd) {
256621968bf8SToby Isaac numD[0]++;
25679371c9d4SSatish Balay } else if (gInd >= 0) { /* negative means non-entry */
256821968bf8SToby Isaac numO[0]++;
256946bdb399SToby Isaac }
257046bdb399SToby Isaac }
257146bdb399SToby Isaac }
25729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize));
257346bdb399SToby Isaac if (!matSize) { /* incoming matrix is identity */
257446bdb399SToby Isaac PetscInt childId;
257546bdb399SToby Isaac
257646bdb399SToby Isaac childId = childIds[p - pStartF];
257721968bf8SToby Isaac if (childId < 0) { /* no child interpolation: one nnz per */
257846bdb399SToby Isaac if (numFields) {
2579b9a5774bSToby Isaac PetscInt f;
2580b9a5774bSToby Isaac for (f = 0; f < numFields; f++) {
258121968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row;
258246bdb399SToby Isaac for (row = 0; row < numRows; row++) {
258321968bf8SToby Isaac PetscInt gIndCoarse = pInd[newOffsets[f] + row];
258421968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row];
258546bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */
25861dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs");
2587b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1;
25889371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */
25891dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs");
2590b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1;
25919371c9d4SSatish Balay } else { /* constrained */
259208401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs");
259346bdb399SToby Isaac }
259446bdb399SToby Isaac }
259546bdb399SToby Isaac }
25969371c9d4SSatish Balay } else {
2597b9a5774bSToby Isaac PetscInt i;
2598b9a5774bSToby Isaac for (i = 0; i < gDof; i++) {
259946bdb399SToby Isaac PetscInt gIndCoarse = pInd[i];
260046bdb399SToby Isaac PetscInt gIndFine = rowIndices[i];
260146bdb399SToby Isaac if (gIndCoarse >= colStart && gIndCoarse < colEnd) { /* local */
26021dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs");
2603b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = 1;
26049371c9d4SSatish Balay } else if (gIndCoarse >= 0) { /* remote */
26051dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs");
2606b9a5774bSToby Isaac onnz[gIndFine - rowStart] = 1;
26079371c9d4SSatish Balay } else { /* constrained */
260808401ef6SPierre Jolivet PetscCheck(gIndFine < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs");
260946bdb399SToby Isaac }
261046bdb399SToby Isaac }
261146bdb399SToby Isaac }
26129371c9d4SSatish Balay } else { /* interpolate from all */
261346bdb399SToby Isaac if (numFields) {
2614b9a5774bSToby Isaac PetscInt f;
2615b9a5774bSToby Isaac for (f = 0; f < numFields; f++) {
261621968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row;
261746bdb399SToby Isaac for (row = 0; row < numRows; row++) {
261821968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row];
261946bdb399SToby Isaac if (gIndFine >= 0) {
26201dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs");
2621b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f];
2622b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f];
262346bdb399SToby Isaac }
262446bdb399SToby Isaac }
262546bdb399SToby Isaac }
26269371c9d4SSatish Balay } else {
2627b9a5774bSToby Isaac PetscInt i;
2628b9a5774bSToby Isaac for (i = 0; i < gDof; i++) {
262946bdb399SToby Isaac PetscInt gIndFine = rowIndices[i];
263046bdb399SToby Isaac if (gIndFine >= 0) {
26311dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs");
2632b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0];
2633b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0];
263446bdb399SToby Isaac }
263546bdb399SToby Isaac }
263646bdb399SToby Isaac }
263746bdb399SToby Isaac }
26389371c9d4SSatish Balay } else { /* interpolate from all */
263946bdb399SToby Isaac if (numFields) {
2640b9a5774bSToby Isaac PetscInt f;
2641b9a5774bSToby Isaac for (f = 0; f < numFields; f++) {
264221968bf8SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row;
264346bdb399SToby Isaac for (row = 0; row < numRows; row++) {
264421968bf8SToby Isaac PetscInt gIndFine = rowIndices[offsets[f] + row];
264546bdb399SToby Isaac if (gIndFine >= 0) {
26461dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs");
2647b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[f];
2648b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[f];
264946bdb399SToby Isaac }
265046bdb399SToby Isaac }
265146bdb399SToby Isaac }
26529371c9d4SSatish Balay } else { /* every dof get a full row */
2653b9a5774bSToby Isaac PetscInt i;
2654b9a5774bSToby Isaac for (i = 0; i < gDof; i++) {
265546bdb399SToby Isaac PetscInt gIndFine = rowIndices[i];
265646bdb399SToby Isaac if (gIndFine >= 0) {
26571dca8a05SBarry Smith PetscCheck(gIndFine >= rowStart && gIndFine < rowEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatched number of constrained dofs");
2658b9a5774bSToby Isaac dnnz[gIndFine - rowStart] = numD[0];
2659b9a5774bSToby Isaac onnz[gIndFine - rowStart] = numO[0];
266046bdb399SToby Isaac }
266146bdb399SToby Isaac }
266246bdb399SToby Isaac }
266346bdb399SToby Isaac }
266446bdb399SToby Isaac }
26659566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, dnnz, onnz, NULL, NULL));
26669566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnnz, onnz));
266721968bf8SToby Isaac
26689566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree));
2669d3a532e9SStefano Zampini PetscCall(DMCopyDisc(fine, refTree));
2670d3a532e9SStefano Zampini PetscCall(DMSetLocalSection(refTree, NULL));
2671d3a532e9SStefano Zampini PetscCall(DMSetDefaultConstraints(refTree, NULL, NULL, NULL));
26729566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN));
26739566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL));
26749566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL));
26759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd));
26769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxConDof));
26779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(leafIndicesSec, &maxColumns));
26789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxConDof * maxColumns, &pointWork));
26790eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) {
2680e44e4e7fSToby Isaac PetscInt gDof, gcDof, gOff;
2681e44e4e7fSToby Isaac PetscInt numColIndices, pIndOff, *pInd;
2682e44e4e7fSToby Isaac PetscInt matSize;
2683e44e4e7fSToby Isaac PetscInt childId;
2684e44e4e7fSToby Isaac
26859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof));
26869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof));
2687ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue;
2688e44e4e7fSToby Isaac childId = childIds[p - pStartF];
26899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff));
26909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &numColIndices));
26919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &pIndOff));
2692e44e4e7fSToby Isaac numColIndices -= 2 * numFields;
2693e44e4e7fSToby Isaac pInd = &leafIndices[pIndOff];
2694e44e4e7fSToby Isaac offsets[0] = 0;
2695e44e4e7fSToby Isaac offsetsCopy[0] = 0;
2696e44e4e7fSToby Isaac newOffsets[0] = 0;
2697e44e4e7fSToby Isaac newOffsetsCopy[0] = 0;
2698e44e4e7fSToby Isaac rowOffsets[0] = 0;
2699e44e4e7fSToby Isaac if (numFields) {
2700e44e4e7fSToby Isaac PetscInt f;
2701e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) {
2702e44e4e7fSToby Isaac PetscInt rowDof;
2703e44e4e7fSToby Isaac
27049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof));
2705e44e4e7fSToby Isaac offsets[f + 1] = offsets[f] + rowDof;
2706e44e4e7fSToby Isaac offsetsCopy[f + 1] = offsets[f + 1];
2707e44e4e7fSToby Isaac rowOffsets[f + 1] = pInd[numColIndices + f];
2708e44e4e7fSToby Isaac newOffsets[f + 1] = pInd[numColIndices + numFields + f];
2709e44e4e7fSToby Isaac }
27109566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices));
27119371c9d4SSatish Balay } else {
27129566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices));
27131c58ffc4SToby Isaac }
27149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafMatricesSec, p, &matSize));
2715e44e4e7fSToby Isaac if (!matSize) { /* incoming matrix is identity */
2716e44e4e7fSToby Isaac if (childId < 0) { /* no child interpolation: scatter */
2717e44e4e7fSToby Isaac if (numFields) {
2718e44e4e7fSToby Isaac PetscInt f;
2719e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) {
2720e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f], row;
272148a46eb9SPierre Jolivet for (row = 0; row < numRows; row++) PetscCall(MatSetValue(mat, rowIndices[offsets[f] + row], pInd[newOffsets[f] + row], 1., INSERT_VALUES));
272221968bf8SToby Isaac }
27239371c9d4SSatish Balay } else {
2724e44e4e7fSToby Isaac PetscInt numRows = gDof, row;
272548a46eb9SPierre Jolivet for (row = 0; row < numRows; row++) PetscCall(MatSetValue(mat, rowIndices[row], pInd[row], 1., INSERT_VALUES));
2726e44e4e7fSToby Isaac }
27279371c9d4SSatish Balay } else { /* interpolate from all */
2728e44e4e7fSToby Isaac if (numFields) {
2729e44e4e7fSToby Isaac PetscInt f;
2730e44e4e7fSToby Isaac for (f = 0; f < numFields; f++) {
2731e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f];
2732e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f];
27339566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], refPointFieldMats[childId - pRefStart][f], INSERT_VALUES));
2734e44e4e7fSToby Isaac }
27359371c9d4SSatish Balay } else {
27369566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, refPointFieldMats[childId - pRefStart][0], INSERT_VALUES));
2737e44e4e7fSToby Isaac }
2738e44e4e7fSToby Isaac }
27399371c9d4SSatish Balay } else { /* interpolate from all */
2740e44e4e7fSToby Isaac PetscInt pMatOff;
2741e44e4e7fSToby Isaac PetscScalar *pMat;
2742e44e4e7fSToby Isaac
27439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafMatricesSec, p, &pMatOff));
2744e44e4e7fSToby Isaac pMat = &leafMatrices[pMatOff];
2745e44e4e7fSToby Isaac if (childId < 0) { /* copy the incoming matrix */
2746e44e4e7fSToby Isaac if (numFields) {
2747e44e4e7fSToby Isaac PetscInt f, count;
2748e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) {
2749e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f];
2750e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f];
2751e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f];
2752e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count];
2753e44e4e7fSToby Isaac
27549566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], inMat, INSERT_VALUES));
2755e44e4e7fSToby Isaac count += numCols * numInRows;
2756e44e4e7fSToby Isaac }
27579371c9d4SSatish Balay } else {
27589566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, gDof, rowIndices, numColIndices, pInd, pMat, INSERT_VALUES));
2759e44e4e7fSToby Isaac }
27609371c9d4SSatish Balay } else { /* multiply the incoming matrix by the child interpolation */
2761e44e4e7fSToby Isaac if (numFields) {
2762e44e4e7fSToby Isaac PetscInt f, count;
2763e44e4e7fSToby Isaac for (f = 0, count = 0; f < numFields; f++) {
2764e44e4e7fSToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f];
2765e44e4e7fSToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f];
2766e44e4e7fSToby Isaac PetscInt numInRows = rowOffsets[f + 1] - rowOffsets[f];
2767e44e4e7fSToby Isaac PetscScalar *inMat = &pMat[count];
2768e44e4e7fSToby Isaac PetscInt i, j, k;
276908401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][f] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch");
2770e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) {
2771e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) {
2772e44e4e7fSToby Isaac PetscScalar val = 0.;
2773ad540459SPierre Jolivet for (k = 0; k < numInRows; k++) val += refPointFieldMats[childId - pRefStart][f][i * numInRows + k] * inMat[k * numCols + j];
2774e44e4e7fSToby Isaac pointWork[i * numCols + j] = val;
2775e44e4e7fSToby Isaac }
2776e44e4e7fSToby Isaac }
27779566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, &rowIndices[offsets[f]], numCols, &pInd[newOffsets[f]], pointWork, INSERT_VALUES));
2778e44e4e7fSToby Isaac count += numCols * numInRows;
2779e44e4e7fSToby Isaac }
27809371c9d4SSatish Balay } else { /* every dof gets a full row */
2781e44e4e7fSToby Isaac PetscInt numRows = gDof;
2782e44e4e7fSToby Isaac PetscInt numCols = numColIndices;
2783e44e4e7fSToby Isaac PetscInt numInRows = matSize / numColIndices;
2784e44e4e7fSToby Isaac PetscInt i, j, k;
278508401ef6SPierre Jolivet PetscCheck(refPointFieldN[childId - pRefStart][0] == numInRows, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point constraint matrix multiply dimension mismatch");
2786e44e4e7fSToby Isaac for (i = 0; i < numRows; i++) {
2787e44e4e7fSToby Isaac for (j = 0; j < numCols; j++) {
2788e44e4e7fSToby Isaac PetscScalar val = 0.;
2789ad540459SPierre Jolivet for (k = 0; k < numInRows; k++) val += refPointFieldMats[childId - pRefStart][0][i * numInRows + k] * pMat[k * numCols + j];
2790e44e4e7fSToby Isaac pointWork[i * numCols + j] = val;
2791e44e4e7fSToby Isaac }
2792e44e4e7fSToby Isaac }
27939566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numRows, rowIndices, numCols, pInd, pointWork, INSERT_VALUES));
2794e44e4e7fSToby Isaac }
2795e44e4e7fSToby Isaac }
2796e44e4e7fSToby Isaac }
2797e44e4e7fSToby Isaac }
27989566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN));
27999566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices));
28009566063dSJacob Faibussowitsch PetscCall(PetscFree(pointWork));
2801e44e4e7fSToby Isaac }
28029566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
28039566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
28049566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec));
28059566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafMatricesSec));
28069566063dSJacob Faibussowitsch PetscCall(PetscFree2(leafIndices, leafMatrices));
28079566063dSJacob Faibussowitsch PetscCall(PetscFree2(*(PetscInt ****)&perms, *(PetscScalar ****)&flips));
28089566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO));
28099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors));
28103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
28116ecaa68aSToby Isaac }
2812154bca37SToby Isaac
28138d2f55e7SToby Isaac /*
28148d2f55e7SToby Isaac * Assuming a nodal basis (w.r.t. the dual basis) basis:
28158d2f55e7SToby Isaac *
28168d2f55e7SToby Isaac * for each coarse dof \phi^c_i:
28178d2f55e7SToby Isaac * for each quadrature point (w_l,x_l) in the dual basis definition of \phi^c_i:
28188d2f55e7SToby Isaac * for each fine dof \phi^f_j;
28198d2f55e7SToby Isaac * a_{i,j} = 0;
28208d2f55e7SToby Isaac * for each fine dof \phi^f_k:
28218d2f55e7SToby Isaac * a_{i,j} += interp_{i,k} * \phi^f_k(x_l) * \phi^f_j(x_l) * w_l
28228d2f55e7SToby Isaac * [^^^ this is = \phi^c_i ^^^]
28238d2f55e7SToby Isaac */
DMPlexComputeInjectorReferenceTree(DM refTree,Mat * inj)2824d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInjectorReferenceTree(DM refTree, Mat *inj)
2825d71ae5a4SJacob Faibussowitsch {
28268d2f55e7SToby Isaac PetscDS ds;
28278d2f55e7SToby Isaac PetscSection section, cSection;
28288d2f55e7SToby Isaac DMLabel canonical, depth;
28298d2f55e7SToby Isaac Mat cMat, mat;
28308d2f55e7SToby Isaac PetscInt *nnz;
28318d2f55e7SToby Isaac PetscInt f, dim, numFields, numSecFields, p, pStart, pEnd, cStart, cEnd;
28328d2f55e7SToby Isaac PetscInt m, n;
28338d2f55e7SToby Isaac PetscScalar *pointScalar;
28348d2f55e7SToby Isaac PetscReal *v0, *v0parent, *vtmp, *J, *Jparent, *invJ, *pointRef, detJ, detJparent;
28358d2f55e7SToby Isaac
28368d2f55e7SToby Isaac PetscFunctionBegin;
28379566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, §ion));
28389566063dSJacob Faibussowitsch PetscCall(DMGetDimension(refTree, &dim));
28399566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(dim, &v0, dim, &v0parent, dim, &vtmp, dim * dim, &J, dim * dim, &Jparent, dim * dim, &invJ));
28409566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim, &pointScalar, dim, &pointRef));
28419566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds));
28429566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields));
28439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numSecFields));
28449566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "canonical", &canonical));
28459566063dSJacob Faibussowitsch PetscCall(DMGetLabel(refTree, "depth", &depth));
28469566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSection, &cMat, NULL));
28479566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(refTree, &pStart, &pEnd));
28489566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(refTree, 0, &cStart, &cEnd));
28499566063dSJacob Faibussowitsch PetscCall(MatGetSize(cMat, &n, &m)); /* the injector has transpose sizes from the constraint matrix */
28508d2f55e7SToby Isaac /* Step 1: compute non-zero pattern. A proper subset of constraint matrix non-zero */
28519566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(m, &nnz));
28528d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) { /* a point will have non-zeros if it is canonical, it has dofs, and its children have dofs */
28538d2f55e7SToby Isaac const PetscInt *children;
28548d2f55e7SToby Isaac PetscInt numChildren;
28558d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof;
28568d2f55e7SToby Isaac
28578d2f55e7SToby Isaac if (canonical) {
28588d2f55e7SToby Isaac PetscInt pCanonical;
28599566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical));
28608d2f55e7SToby Isaac if (p != pCanonical) continue;
28618d2f55e7SToby Isaac }
28629566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children));
28638d2f55e7SToby Isaac if (!numChildren) continue;
28648d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) {
28658d2f55e7SToby Isaac PetscInt child = children[i];
28668d2f55e7SToby Isaac PetscInt dof;
28678d2f55e7SToby Isaac
28689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof));
28698d2f55e7SToby Isaac numChildDof += dof;
28708d2f55e7SToby Isaac }
28719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof));
28728d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue;
28738d2f55e7SToby Isaac for (f = 0; f < numFields; f++) {
28748d2f55e7SToby Isaac PetscInt selfOff;
28758d2f55e7SToby Isaac
28768d2f55e7SToby Isaac if (numSecFields) { /* count the dofs for just this field */
28778d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) {
28788d2f55e7SToby Isaac PetscInt child = children[i];
28798d2f55e7SToby Isaac PetscInt dof;
28808d2f55e7SToby Isaac
28819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof));
28828d2f55e7SToby Isaac numChildDof += dof;
28838d2f55e7SToby Isaac }
28849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof));
28859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff));
28869371c9d4SSatish Balay } else {
28879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff));
28888d2f55e7SToby Isaac }
2889ad540459SPierre Jolivet for (i = 0; i < numSelfDof; i++) nnz[selfOff + i] = numChildDof;
28908d2f55e7SToby Isaac }
28918d2f55e7SToby Isaac }
28929566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(PETSC_COMM_SELF, m, n, m, n, -1, nnz, -1, NULL, &mat));
28939566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz));
28948d2f55e7SToby Isaac /* Setp 2: compute entries */
28958d2f55e7SToby Isaac for (p = pStart; p < pEnd; p++) {
28968d2f55e7SToby Isaac const PetscInt *children;
28978d2f55e7SToby Isaac PetscInt numChildren;
28988d2f55e7SToby Isaac PetscInt i, numChildDof, numSelfDof;
28998d2f55e7SToby Isaac
29008d2f55e7SToby Isaac /* same conditions about when entries occur */
29018d2f55e7SToby Isaac if (canonical) {
29028d2f55e7SToby Isaac PetscInt pCanonical;
29039566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(canonical, p, &pCanonical));
29048d2f55e7SToby Isaac if (p != pCanonical) continue;
29058d2f55e7SToby Isaac }
29069566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(refTree, p, &numChildren, &children));
29078d2f55e7SToby Isaac if (!numChildren) continue;
29088d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) {
29098d2f55e7SToby Isaac PetscInt child = children[i];
29108d2f55e7SToby Isaac PetscInt dof;
29118d2f55e7SToby Isaac
29129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, child, &dof));
29138d2f55e7SToby Isaac numChildDof += dof;
29148d2f55e7SToby Isaac }
29159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &numSelfDof));
29168d2f55e7SToby Isaac if (!numChildDof || !numSelfDof) continue;
29178d2f55e7SToby Isaac
29188d2f55e7SToby Isaac for (f = 0; f < numFields; f++) {
291959fc6756SToby Isaac PetscInt pI = -1, cI = -1;
292052a3aeb4SToby Isaac PetscInt selfOff, Nc, parentCell;
29218d2f55e7SToby Isaac PetscInt cellShapeOff;
29228d2f55e7SToby Isaac PetscObject disc;
29238d2f55e7SToby Isaac PetscDualSpace dsp;
29248d2f55e7SToby Isaac PetscClassId classId;
29258d2f55e7SToby Isaac PetscScalar *pointMat;
29263b1c2a6aSToby Isaac PetscInt *matRows, *matCols;
29271690c2aeSBarry Smith PetscInt pO = PETSC_INT_MIN;
29288d2f55e7SToby Isaac const PetscInt *depthNumDof;
29298d2f55e7SToby Isaac
29308d2f55e7SToby Isaac if (numSecFields) {
29318d2f55e7SToby Isaac for (i = 0, numChildDof = 0; i < numChildren; i++) {
29328d2f55e7SToby Isaac PetscInt child = children[i];
29338d2f55e7SToby Isaac PetscInt dof;
29348d2f55e7SToby Isaac
29359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, child, f, &dof));
29368d2f55e7SToby Isaac numChildDof += dof;
29378d2f55e7SToby Isaac }
29389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &numSelfDof));
29399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, p, f, &selfOff));
29409371c9d4SSatish Balay } else {
29419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &selfOff));
29428d2f55e7SToby Isaac }
29438d2f55e7SToby Isaac
29443b1c2a6aSToby Isaac /* find a cell whose closure contains p */
29458d2f55e7SToby Isaac if (p >= cStart && p < cEnd) {
29468d2f55e7SToby Isaac parentCell = p;
29479371c9d4SSatish Balay } else {
29488d2f55e7SToby Isaac PetscInt *star = NULL;
29498d2f55e7SToby Isaac PetscInt numStar;
29508d2f55e7SToby Isaac
29518d2f55e7SToby Isaac parentCell = -1;
29529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star));
29538d2f55e7SToby Isaac for (i = numStar - 1; i >= 0; i--) {
29548d2f55e7SToby Isaac PetscInt c = star[2 * i];
29558d2f55e7SToby Isaac
29568d2f55e7SToby Isaac if (c >= cStart && c < cEnd) {
29578d2f55e7SToby Isaac parentCell = c;
29588d2f55e7SToby Isaac break;
29598d2f55e7SToby Isaac }
29608d2f55e7SToby Isaac }
29619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, p, PETSC_FALSE, &numStar, &star));
29628d2f55e7SToby Isaac }
2963a5b23f4aSJose E. Roman /* determine the offset of p's shape functions within parentCell's shape functions */
29649566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc));
29659566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &classId));
2966c5356c36SToby Isaac if (classId == PETSCFE_CLASSID) {
29679566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
29689371c9d4SSatish Balay } else if (classId == PETSCFV_CLASSID) {
29699566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace((PetscFV)disc, &dsp));
29709371c9d4SSatish Balay } else {
29719b90b7cdSMatthew G. Knepley SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported discretization object");
2972c5356c36SToby Isaac }
29739566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumDof(dsp, &depthNumDof));
29749566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetNumComponents(dsp, &Nc));
29758d2f55e7SToby Isaac {
29768d2f55e7SToby Isaac PetscInt *closure = NULL;
29778d2f55e7SToby Isaac PetscInt numClosure;
29788d2f55e7SToby Isaac
29799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure));
298059fc6756SToby Isaac for (i = 0, pI = -1, cellShapeOff = 0; i < numClosure; i++) {
29818d2f55e7SToby Isaac PetscInt point = closure[2 * i], pointDepth;
29828d2f55e7SToby Isaac
29838d2f55e7SToby Isaac pO = closure[2 * i + 1];
298459fc6756SToby Isaac if (point == p) {
298559fc6756SToby Isaac pI = i;
298659fc6756SToby Isaac break;
298759fc6756SToby Isaac }
29889566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth));
29898d2f55e7SToby Isaac cellShapeOff += depthNumDof[pointDepth];
29908d2f55e7SToby Isaac }
29919566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, parentCell, PETSC_TRUE, &numClosure, &closure));
29928d2f55e7SToby Isaac }
29938d2f55e7SToby Isaac
29949566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat));
29959566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows));
299652a3aeb4SToby Isaac matCols = matRows + numSelfDof;
2997ad540459SPierre Jolivet for (i = 0; i < numSelfDof; i++) matRows[i] = selfOff + i;
299852a3aeb4SToby Isaac for (i = 0; i < numSelfDof * numChildDof; i++) pointMat[i] = 0.;
29993b1c2a6aSToby Isaac {
30003b1c2a6aSToby Isaac PetscInt colOff = 0;
30013b1c2a6aSToby Isaac
30023b1c2a6aSToby Isaac for (i = 0; i < numChildren; i++) {
30033b1c2a6aSToby Isaac PetscInt child = children[i];
30043b1c2a6aSToby Isaac PetscInt dof, off, j;
30053b1c2a6aSToby Isaac
30063b1c2a6aSToby Isaac if (numSecFields) {
30079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSection, child, f, &dof));
30089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSection, child, f, &off));
30099371c9d4SSatish Balay } else {
30109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSection, child, &dof));
30119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSection, child, &off));
30123b1c2a6aSToby Isaac }
30133b1c2a6aSToby Isaac
3014ad540459SPierre Jolivet for (j = 0; j < dof; j++) matCols[colOff++] = off + j;
30153b1c2a6aSToby Isaac }
30163b1c2a6aSToby Isaac }
30178d2f55e7SToby Isaac if (classId == PETSCFE_CLASSID) {
30188d2f55e7SToby Isaac PetscFE fe = (PetscFE)disc;
30198d2f55e7SToby Isaac PetscInt fSize;
302059fc6756SToby Isaac const PetscInt ***perms;
302159fc6756SToby Isaac const PetscScalar ***flips;
302259fc6756SToby Isaac const PetscInt *pperms;
302359fc6756SToby Isaac
30249566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &dsp));
30259566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(dsp, &fSize));
30269566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetSymmetries(dsp, &perms, &flips));
302759fc6756SToby Isaac pperms = perms ? perms[pI] ? perms[pI][pO] : NULL : NULL;
302852a3aeb4SToby Isaac for (i = 0; i < numSelfDof; i++) { /* for every shape function */
30298d2f55e7SToby Isaac PetscQuadrature q;
303052a3aeb4SToby Isaac PetscInt dim, thisNc, numPoints, j, k;
30318d2f55e7SToby Isaac const PetscReal *points;
30328d2f55e7SToby Isaac const PetscReal *weights;
30338d2f55e7SToby Isaac PetscInt *closure = NULL;
30348d2f55e7SToby Isaac PetscInt numClosure;
303559fc6756SToby Isaac PetscInt iCell = pperms ? pperms[i] : i;
303659fc6756SToby Isaac PetscInt parentCellShapeDof = cellShapeOff + iCell;
3037ef0bb6c7SMatthew G. Knepley PetscTabulation Tparent;
30388d2f55e7SToby Isaac
30399566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(dsp, parentCellShapeDof, &q));
30409566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, &dim, &thisNc, &numPoints, &points, &weights));
304163a3b9bcSJacob Faibussowitsch PetscCheck(thisNc == Nc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Functional dim %" PetscInt_FMT " does not much basis dim %" PetscInt_FMT, thisNc, Nc);
30429566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, numPoints, points, 0, &Tparent)); /* I'm expecting a nodal basis: weights[:]' * Bparent[:,cellShapeDof] = 1. */
30433b1c2a6aSToby Isaac for (j = 0; j < numPoints; j++) {
30448d2f55e7SToby Isaac PetscInt childCell = -1;
304552a3aeb4SToby Isaac PetscReal *parentValAtPoint;
3046c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.};
30478d2f55e7SToby Isaac const PetscReal *pointReal = &points[dim * j];
30488d2f55e7SToby Isaac const PetscScalar *point;
3049ef0bb6c7SMatthew G. Knepley PetscTabulation Tchild;
30508d2f55e7SToby Isaac PetscInt childCellShapeOff, pointMatOff;
30518d2f55e7SToby Isaac #if defined(PETSC_USE_COMPLEX)
30528d2f55e7SToby Isaac PetscInt d;
30538d2f55e7SToby Isaac
3054ad540459SPierre Jolivet for (d = 0; d < dim; d++) pointScalar[d] = points[dim * j + d];
30558d2f55e7SToby Isaac point = pointScalar;
30568d2f55e7SToby Isaac #else
30578d2f55e7SToby Isaac point = pointReal;
30588d2f55e7SToby Isaac #endif
30598d2f55e7SToby Isaac
3060ef0bb6c7SMatthew G. Knepley parentValAtPoint = &Tparent->T[0][(fSize * j + parentCellShapeDof) * Nc];
30613b1c2a6aSToby Isaac
30623b1c2a6aSToby Isaac for (k = 0; k < numChildren; k++) { /* locate the point in a child's star cell*/
30638d2f55e7SToby Isaac PetscInt child = children[k];
30648d2f55e7SToby Isaac PetscInt *star = NULL;
30658d2f55e7SToby Isaac PetscInt numStar, s;
30668d2f55e7SToby Isaac
30679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star));
30688d2f55e7SToby Isaac for (s = numStar - 1; s >= 0; s--) {
30698d2f55e7SToby Isaac PetscInt c = star[2 * s];
30708d2f55e7SToby Isaac
30718d2f55e7SToby Isaac if (c < cStart || c >= cEnd) continue;
30729566063dSJacob Faibussowitsch PetscCall(DMPlexLocatePoint_Internal(refTree, dim, point, c, &childCell));
30738d2f55e7SToby Isaac if (childCell >= 0) break;
30748d2f55e7SToby Isaac }
30759566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, child, PETSC_FALSE, &numStar, &star));
30768d2f55e7SToby Isaac if (childCell >= 0) break;
30778d2f55e7SToby Isaac }
307808401ef6SPierre Jolivet PetscCheck(childCell >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not locate quadrature point");
30799566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, childCell, NULL, v0, J, invJ, &detJ));
30809566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(refTree, parentCell, NULL, v0parent, Jparent, NULL, &detJparent));
3081c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0parent, Jparent, pointReal, vtmp);
3082c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0, invJ, vtmp, pointRef);
30838d2f55e7SToby Isaac
30849566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, 1, pointRef, 0, &Tchild));
30859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure));
30863b1c2a6aSToby Isaac for (k = 0, pointMatOff = 0; k < numChildren; k++) { /* point is located in cell => child dofs support at point are in closure of cell */
30871690c2aeSBarry Smith PetscInt child = children[k], childDepth, childDof, childO = PETSC_INT_MIN;
30888d2f55e7SToby Isaac PetscInt l;
308959fc6756SToby Isaac const PetscInt *cperms;
30908d2f55e7SToby Isaac
30919566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, child, &childDepth));
30928d2f55e7SToby Isaac childDof = depthNumDof[childDepth];
309359fc6756SToby Isaac for (l = 0, cI = -1, childCellShapeOff = 0; l < numClosure; l++) {
30948d2f55e7SToby Isaac PetscInt point = closure[2 * l];
30958d2f55e7SToby Isaac PetscInt pointDepth;
30968d2f55e7SToby Isaac
30978d2f55e7SToby Isaac childO = closure[2 * l + 1];
309859fc6756SToby Isaac if (point == child) {
309959fc6756SToby Isaac cI = l;
310059fc6756SToby Isaac break;
310159fc6756SToby Isaac }
31029566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, point, &pointDepth));
31038d2f55e7SToby Isaac childCellShapeOff += depthNumDof[pointDepth];
31048d2f55e7SToby Isaac }
31058d2f55e7SToby Isaac if (l == numClosure) {
31068d2f55e7SToby Isaac pointMatOff += childDof;
31078d2f55e7SToby Isaac continue; /* child is not in the closure of the cell: has nothing to contribute to this point */
31088d2f55e7SToby Isaac }
310959fc6756SToby Isaac cperms = perms ? perms[cI] ? perms[cI][childO] : NULL : NULL;
31108d2f55e7SToby Isaac for (l = 0; l < childDof; l++) {
311159fc6756SToby Isaac PetscInt lCell = cperms ? cperms[l] : l;
311259fc6756SToby Isaac PetscInt childCellDof = childCellShapeOff + lCell;
311352a3aeb4SToby Isaac PetscReal *childValAtPoint;
311452a3aeb4SToby Isaac PetscReal val = 0.;
31158d2f55e7SToby Isaac
3116ef0bb6c7SMatthew G. Knepley childValAtPoint = &Tchild->T[0][childCellDof * Nc];
3117ad540459SPierre Jolivet for (m = 0; m < Nc; m++) val += weights[j * Nc + m] * parentValAtPoint[m] * childValAtPoint[m];
311852a3aeb4SToby Isaac
311952a3aeb4SToby Isaac pointMat[i * numChildDof + pointMatOff + l] += val;
31208d2f55e7SToby Isaac }
31218d2f55e7SToby Isaac pointMatOff += childDof;
31228d2f55e7SToby Isaac }
31239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(refTree, childCell, PETSC_TRUE, &numClosure, &closure));
31249566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tchild));
31258d2f55e7SToby Isaac }
31269566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tparent));
31278d2f55e7SToby Isaac }
31289371c9d4SSatish Balay } else { /* just the volume-weighted averages of the children */
31293b1c2a6aSToby Isaac PetscReal parentVol;
3130bfaa5bdcSToby Isaac PetscInt childCell;
31313b1c2a6aSToby Isaac
31329566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, p, &parentVol, NULL, NULL));
3133bfaa5bdcSToby Isaac for (i = 0, childCell = 0; i < numChildren; i++) {
313452a3aeb4SToby Isaac PetscInt child = children[i], j;
31353b1c2a6aSToby Isaac PetscReal childVol;
31363b1c2a6aSToby Isaac
31373b1c2a6aSToby Isaac if (child < cStart || child >= cEnd) continue;
31389566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(refTree, child, &childVol, NULL, NULL));
3139ad540459SPierre Jolivet for (j = 0; j < Nc; j++) pointMat[j * numChildDof + Nc * childCell + j] = childVol / parentVol;
3140bfaa5bdcSToby Isaac childCell++;
31413b1c2a6aSToby Isaac }
31428d2f55e7SToby Isaac }
31433b1c2a6aSToby Isaac /* Insert pointMat into mat */
31449566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, numSelfDof, matRows, numChildDof, matCols, pointMat, INSERT_VALUES));
31459566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof + numChildDof, MPIU_INT, &matRows));
31469566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(refTree, numSelfDof * numChildDof, MPIU_SCALAR, &pointMat));
31478d2f55e7SToby Isaac }
31488d2f55e7SToby Isaac }
31499566063dSJacob Faibussowitsch PetscCall(PetscFree6(v0, v0parent, vtmp, J, Jparent, invJ));
31509566063dSJacob Faibussowitsch PetscCall(PetscFree2(pointScalar, pointRef));
31519566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
31529566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
31538d2f55e7SToby Isaac *inj = mat;
31543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
31558d2f55e7SToby Isaac }
31568d2f55e7SToby Isaac
DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree,Mat inj,PetscScalar **** childrenMats)3157d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats)
3158d71ae5a4SJacob Faibussowitsch {
3159f30e825dSToby Isaac PetscDS ds;
3160f30e825dSToby Isaac PetscInt numFields, f, pRefStart, pRefEnd, p, *rows, *cols, maxDof;
3161f30e825dSToby Isaac PetscScalar ***refPointFieldMats;
3162f30e825dSToby Isaac PetscSection refConSec, refSection;
3163f30e825dSToby Isaac
3164f30e825dSToby Isaac PetscFunctionBegin;
31659566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds));
31669566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields));
31679566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL));
31689566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection));
31699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd));
31709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pRefEnd - pRefStart, &refPointFieldMats));
31719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(refConSec, &maxDof));
31729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &rows));
31739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof * maxDof, &cols));
3174f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) {
3175f30e825dSToby Isaac PetscInt parent, pDof, parentDof;
3176f30e825dSToby Isaac
31779566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL));
31789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof));
31799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof));
3180f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue;
3181f30e825dSToby Isaac
31829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFields, &refPointFieldMats[p - pRefStart]));
3183f30e825dSToby Isaac for (f = 0; f < numFields; f++) {
318452a3aeb4SToby Isaac PetscInt cDof, cOff, numCols, r;
3185f30e825dSToby Isaac
3186f30e825dSToby Isaac if (numFields > 1) {
31879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof));
31889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refConSec, p, f, &cOff));
31899371c9d4SSatish Balay } else {
31909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof));
31919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refConSec, p, &cOff));
3192f30e825dSToby Isaac }
3193f30e825dSToby Isaac
3194ad540459SPierre Jolivet for (r = 0; r < cDof; r++) rows[r] = cOff + r;
3195f30e825dSToby Isaac numCols = 0;
3196f30e825dSToby Isaac {
3197f30e825dSToby Isaac PetscInt aDof, aOff, j;
3198f30e825dSToby Isaac
3199f30e825dSToby Isaac if (numFields > 1) {
32009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refSection, parent, f, &aDof));
32019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(refSection, parent, f, &aOff));
32029371c9d4SSatish Balay } else {
32039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &aDof));
32049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(refSection, parent, &aOff));
3205f30e825dSToby Isaac }
3206f30e825dSToby Isaac
3207ad540459SPierre Jolivet for (j = 0; j < aDof; j++) cols[numCols++] = aOff + j;
3208f30e825dSToby Isaac }
32099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cDof * numCols, &refPointFieldMats[p - pRefStart][f]));
3210f30e825dSToby Isaac /* transpose of constraint matrix */
32119566063dSJacob Faibussowitsch PetscCall(MatGetValues(inj, numCols, cols, cDof, rows, refPointFieldMats[p - pRefStart][f]));
3212f30e825dSToby Isaac }
3213f30e825dSToby Isaac }
3214f30e825dSToby Isaac *childrenMats = refPointFieldMats;
32159566063dSJacob Faibussowitsch PetscCall(PetscFree(rows));
32169566063dSJacob Faibussowitsch PetscCall(PetscFree(cols));
32173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3218f30e825dSToby Isaac }
3219f30e825dSToby Isaac
DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree,Mat inj,PetscScalar **** childrenMats)3220d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeRestoreChildrenMatrices_Injection(DM refTree, Mat inj, PetscScalar ****childrenMats)
3221d71ae5a4SJacob Faibussowitsch {
3222f30e825dSToby Isaac PetscDS ds;
3223f30e825dSToby Isaac PetscScalar ***refPointFieldMats;
3224f30e825dSToby Isaac PetscInt numFields, pRefStart, pRefEnd, p, f;
3225c6154584SToby Isaac PetscSection refConSec, refSection;
3226f30e825dSToby Isaac
3227f30e825dSToby Isaac PetscFunctionBegin;
3228f30e825dSToby Isaac refPointFieldMats = *childrenMats;
3229f30e825dSToby Isaac *childrenMats = NULL;
32309566063dSJacob Faibussowitsch PetscCall(DMGetDS(refTree, &ds));
32319566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(refTree, &refSection));
32329566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &numFields));
32339566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL));
32349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd));
3235f30e825dSToby Isaac for (p = pRefStart; p < pRefEnd; p++) {
3236f30e825dSToby Isaac PetscInt parent, pDof, parentDof;
3237f30e825dSToby Isaac
32389566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, p, &parent, NULL));
32399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &pDof));
32409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refSection, parent, &parentDof));
3241f30e825dSToby Isaac if (!pDof || !parentDof || parent == p) continue;
3242f30e825dSToby Isaac
3243f30e825dSToby Isaac for (f = 0; f < numFields; f++) {
3244f30e825dSToby Isaac PetscInt cDof;
3245f30e825dSToby Isaac
3246f30e825dSToby Isaac if (numFields > 1) {
32479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(refConSec, p, f, &cDof));
32489371c9d4SSatish Balay } else {
32499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(refConSec, p, &cDof));
3250f30e825dSToby Isaac }
3251f30e825dSToby Isaac
32529566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart][f]));
3253f30e825dSToby Isaac }
32549566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats[p - pRefStart]));
3255f30e825dSToby Isaac }
32569566063dSJacob Faibussowitsch PetscCall(PetscFree(refPointFieldMats));
32573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3258f30e825dSToby Isaac }
3259f30e825dSToby Isaac
DMPlexReferenceTreeGetInjector(DM refTree,Mat * injRef)3260d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexReferenceTreeGetInjector(DM refTree, Mat *injRef)
3261d71ae5a4SJacob Faibussowitsch {
3262ebf164c7SToby Isaac Mat cMatRef;
32636148253fSToby Isaac PetscObject injRefObj;
32648d2f55e7SToby Isaac
3265154bca37SToby Isaac PetscFunctionBegin;
32669566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, NULL, &cMatRef, NULL));
32679566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", &injRefObj));
3268ebf164c7SToby Isaac *injRef = (Mat)injRefObj;
3269ebf164c7SToby Isaac if (!*injRef) {
32709566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorReferenceTree(refTree, injRef));
32719566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)cMatRef, "DMPlexComputeInjectorTree_refTree", (PetscObject)*injRef));
3272ec92bd66SToby Isaac /* there is now a reference in cMatRef, which should be the only one for symmetry with the above case */
32739566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)*injRef));
3274ebf164c7SToby Isaac }
32753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
32766148253fSToby Isaac }
3277f30e825dSToby Isaac
DMPlexTransferInjectorTree(DM coarse,DM fine,PetscSF coarseToFine,const PetscInt * childIds,Vec fineVec,PetscInt numFields,PetscInt * offsets,PetscSection * rootMultiSec,PetscSection * multiLeafSec,PetscInt ** gatheredIndices,PetscScalar ** gatheredValues)3278d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, const PetscInt *childIds, Vec fineVec, PetscInt numFields, PetscInt *offsets, PetscSection *rootMultiSec, PetscSection *multiLeafSec, PetscInt **gatheredIndices, PetscScalar **gatheredValues)
3279d71ae5a4SJacob Faibussowitsch {
3280c921d74cSToby Isaac PetscInt pStartF, pEndF, pStartC, pEndC, p, maxDof, numMulti;
3281ebf164c7SToby Isaac PetscSection globalCoarse, globalFine;
3282ebf164c7SToby Isaac PetscSection localCoarse, localFine, leafIndicesSec;
3283c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec;
3284c921d74cSToby Isaac PetscInt *leafInds, *rootInds = NULL;
3285c921d74cSToby Isaac const PetscInt *rootDegrees;
3286c921d74cSToby Isaac PetscScalar *leafVals = NULL, *rootVals = NULL;
3287ebf164c7SToby Isaac PetscSF coarseToFineEmbedded;
3288ebf164c7SToby Isaac
3289ebf164c7SToby Isaac PetscFunctionBegin;
32909566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC));
32919566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF));
32929566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine));
32939566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine));
32949566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafIndicesSec));
32959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(leafIndicesSec, pStartF, pEndF));
32969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof));
32978d2f55e7SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */
32987e96bdafSToby Isaac PetscInt l, nleaves, dof, cdof, numPointsWithDofs, offset, *pointsWithDofs, numIndices;
32997e96bdafSToby Isaac const PetscInt *leaves;
33008d2f55e7SToby Isaac
33019566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL));
33027e96bdafSToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) {
33037e96bdafSToby Isaac p = leaves ? leaves[l] : l;
33049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof));
33059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof));
33068d2f55e7SToby Isaac if ((dof - cdof) > 0) {
33078d2f55e7SToby Isaac numPointsWithDofs++;
3308f30e825dSToby Isaac
33099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &dof));
33109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(leafIndicesSec, p, dof + 1));
33118d2f55e7SToby Isaac }
33128d2f55e7SToby Isaac }
33139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs));
33149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(leafIndicesSec));
33159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafIndicesSec, &numIndices));
331632603206SJames Wright PetscCall(PetscMalloc1((gatheredIndices ? numIndices : (maxDof + 1)), &leafInds));
33179566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(PetscMalloc1(numIndices, &leafVals));
33187e96bdafSToby Isaac for (l = 0, offset = 0; l < nleaves; l++) {
33197e96bdafSToby Isaac p = leaves ? leaves[l] : l;
33209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof));
33219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof));
33228d2f55e7SToby Isaac if ((dof - cdof) > 0) {
3323f30e825dSToby Isaac PetscInt off, gOff;
3324f30e825dSToby Isaac PetscInt *pInd;
3325c921d74cSToby Isaac PetscScalar *pVal = NULL;
3326f30e825dSToby Isaac
33277e96bdafSToby Isaac pointsWithDofs[offset++] = l;
3328f30e825dSToby Isaac
33299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off));
3330f30e825dSToby Isaac
3331c921d74cSToby Isaac pInd = gatheredIndices ? (&leafInds[off + 1]) : leafInds;
3332c921d74cSToby Isaac if (gatheredValues) {
3333c921d74cSToby Isaac PetscInt i;
3334c921d74cSToby Isaac
3335c921d74cSToby Isaac pVal = &leafVals[off + 1];
3336c921d74cSToby Isaac for (i = 0; i < dof; i++) pVal[i] = 0.;
3337c921d74cSToby Isaac }
33389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff));
3339f30e825dSToby Isaac
3340f30e825dSToby Isaac offsets[0] = 0;
3341f30e825dSToby Isaac if (numFields) {
3342f30e825dSToby Isaac PetscInt f;
3343f30e825dSToby Isaac
3344f30e825dSToby Isaac for (f = 0; f < numFields; f++) {
3345f30e825dSToby Isaac PetscInt fDof;
33469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &fDof));
3347f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f];
3348f30e825dSToby Isaac }
33499566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, -1, NULL, pInd));
3350367003a6SStefano Zampini } else {
33519566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsets, PETSC_FALSE, NULL, NULL, pInd));
3352f30e825dSToby Isaac }
33539566063dSJacob Faibussowitsch if (gatheredValues) PetscCall(VecGetValues(fineVec, dof, pInd, pVal));
33548d2f55e7SToby Isaac }
33558d2f55e7SToby Isaac }
33569566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded));
33579566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs));
33588d2f55e7SToby Isaac }
3359f30e825dSToby Isaac
33609566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC));
33619566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse));
33629566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse));
3363f30e825dSToby Isaac
33646148253fSToby Isaac { /* there may be the case where an sf root has a parent: broadcast parents back to children */
33656148253fSToby Isaac MPI_Datatype threeInt;
33666148253fSToby Isaac PetscMPIInt rank;
33676148253fSToby Isaac PetscInt (*parentNodeAndIdCoarse)[3];
33686148253fSToby Isaac PetscInt (*parentNodeAndIdFine)[3];
33696148253fSToby Isaac PetscInt p, nleaves, nleavesToParents;
33706148253fSToby Isaac PetscSF pointSF, sfToParents;
33716148253fSToby Isaac const PetscInt *ilocal;
33726148253fSToby Isaac const PetscSFNode *iremote;
33736148253fSToby Isaac PetscSFNode *iremoteToParents;
33746148253fSToby Isaac PetscInt *ilocalToParents;
33756148253fSToby Isaac
33769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)coarse), &rank));
33779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(3, MPIU_INT, &threeInt));
33789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&threeInt));
33799566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEndC - pStartC, &parentNodeAndIdCoarse, pEndF - pStartF, &parentNodeAndIdFine));
33809566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(coarse, &pointSF));
33819566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(pointSF, NULL, &nleaves, &ilocal, &iremote));
33826148253fSToby Isaac for (p = pStartC; p < pEndC; p++) {
33836148253fSToby Isaac PetscInt parent, childId;
33849566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(coarse, p, &parent, &childId));
33856148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = rank;
33866148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = parent - pStartC;
33876148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][2] = (p == parent) ? -1 : childId;
33886148253fSToby Isaac if (nleaves > 0) {
33896148253fSToby Isaac PetscInt leaf = -1;
33906148253fSToby Isaac
33916148253fSToby Isaac if (ilocal) {
33929566063dSJacob Faibussowitsch PetscCall(PetscFindInt(parent, nleaves, ilocal, &leaf));
33939371c9d4SSatish Balay } else {
33946148253fSToby Isaac leaf = p - pStartC;
33956148253fSToby Isaac }
33966148253fSToby Isaac if (leaf >= 0) {
33976148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][0] = iremote[leaf].rank;
33986148253fSToby Isaac parentNodeAndIdCoarse[p - pStartC][1] = iremote[leaf].index;
33996148253fSToby Isaac }
34006148253fSToby Isaac }
34016148253fSToby Isaac }
34026148253fSToby Isaac for (p = pStartF; p < pEndF; p++) {
34036148253fSToby Isaac parentNodeAndIdFine[p - pStartF][0] = -1;
34046148253fSToby Isaac parentNodeAndIdFine[p - pStartF][1] = -1;
34056148253fSToby Isaac parentNodeAndIdFine[p - pStartF][2] = -1;
34066148253fSToby Isaac }
34079566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE));
34089566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(coarseToFineEmbedded, threeInt, parentNodeAndIdCoarse, parentNodeAndIdFine, MPI_REPLACE));
34096148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) {
3410f30e825dSToby Isaac PetscInt dof;
3411f30e825dSToby Isaac
34129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafIndicesSec, p, &dof));
3413f30e825dSToby Isaac if (dof) {
3414f30e825dSToby Isaac PetscInt off;
3415f30e825dSToby Isaac
34169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafIndicesSec, p, &off));
3417c921d74cSToby Isaac if (gatheredIndices) {
3418c921d74cSToby Isaac leafInds[off] = PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]);
3419c921d74cSToby Isaac } else if (gatheredValues) {
3420c921d74cSToby Isaac leafVals[off] = (PetscScalar)PetscMax(childIds[p - pStartF], parentNodeAndIdFine[p - pStartF][2]);
3421c921d74cSToby Isaac }
3422f30e825dSToby Isaac }
3423ad540459SPierre Jolivet if (parentNodeAndIdFine[p - pStartF][0] >= 0) nleavesToParents++;
34246148253fSToby Isaac }
34259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &ilocalToParents));
34269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nleavesToParents, &iremoteToParents));
34276148253fSToby Isaac for (p = pStartF, nleavesToParents = 0; p < pEndF; p++) {
34286148253fSToby Isaac if (parentNodeAndIdFine[p - pStartF][0] >= 0) {
34296148253fSToby Isaac ilocalToParents[nleavesToParents] = p - pStartF;
34306497c311SBarry Smith // FIXME PetscCall(PetscMPIIntCast(parentNodeAndIdFine[p - pStartF][0],&iremoteToParents[nleavesToParents].rank));
3431835f2295SStefano Zampini iremoteToParents[nleavesToParents].rank = parentNodeAndIdFine[p - pStartF][0];
34326148253fSToby Isaac iremoteToParents[nleavesToParents].index = parentNodeAndIdFine[p - pStartF][1];
34336148253fSToby Isaac nleavesToParents++;
34346148253fSToby Isaac }
34356148253fSToby Isaac }
34369566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)coarse), &sfToParents));
34379566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfToParents, pEndC - pStartC, nleavesToParents, ilocalToParents, PETSC_OWN_POINTER, iremoteToParents, PETSC_OWN_POINTER));
34389566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded));
34396148253fSToby Isaac
34406148253fSToby Isaac coarseToFineEmbedded = sfToParents;
34416148253fSToby Isaac
34429566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentNodeAndIdCoarse, parentNodeAndIdFine));
34439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&threeInt));
34446148253fSToby Isaac }
3445f30e825dSToby Isaac
34466148253fSToby Isaac { /* winnow out coarse points that don't have dofs */
34476148253fSToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs;
34486148253fSToby Isaac PetscSF sfDofsOnly;
34496148253fSToby Isaac
34506148253fSToby Isaac for (p = pStartC, numPointsWithDofs = 0; p < pEndC; p++) {
34519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof));
34529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof));
3453ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++;
34546148253fSToby Isaac }
34559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs));
34566148253fSToby Isaac for (p = pStartC, offset = 0; p < pEndC; p++) {
34579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof));
34589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof));
3459ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = p - pStartC;
34606148253fSToby Isaac }
34619566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedRootSF(coarseToFineEmbedded, numPointsWithDofs, pointsWithDofs, &sfDofsOnly));
34629566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded));
34639566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs));
34646148253fSToby Isaac coarseToFineEmbedded = sfDofsOnly;
34656148253fSToby Isaac }
3466f30e825dSToby Isaac
34676148253fSToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require injection) */
34689566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeBegin(coarseToFineEmbedded, &rootDegrees));
34699566063dSJacob Faibussowitsch PetscCall(PetscSFComputeDegreeEnd(coarseToFineEmbedded, &rootDegrees));
34709566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &multiRootSec));
34719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(multiRootSec, pStartC, pEndC));
347248a46eb9SPierre Jolivet for (p = pStartC; p < pEndC; p++) PetscCall(PetscSectionSetDof(multiRootSec, p, rootDegrees[p - pStartC]));
34739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(multiRootSec));
34749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(multiRootSec, &numMulti));
34759566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootIndicesSec));
3476f30e825dSToby Isaac { /* distribute the leaf section */
3477f30e825dSToby Isaac PetscSF multi, multiInv, indicesSF;
3478f30e825dSToby Isaac PetscInt *remoteOffsets, numRootIndices;
34798d2f55e7SToby Isaac
34809566063dSJacob Faibussowitsch PetscCall(PetscSFGetMultiSF(coarseToFineEmbedded, &multi));
34819566063dSJacob Faibussowitsch PetscCall(PetscSFCreateInverseSF(multi, &multiInv));
34829566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(multiInv, leafIndicesSec, &remoteOffsets, rootIndicesSec));
34839566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(multiInv, leafIndicesSec, remoteOffsets, rootIndicesSec, &indicesSF));
34849566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets));
34859566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&multiInv));
34869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootIndicesSec, &numRootIndices));
3487c921d74cSToby Isaac if (gatheredIndices) {
34889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootInds));
34899566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE));
34909566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_INT, leafInds, rootInds, MPI_REPLACE));
3491c921d74cSToby Isaac }
3492c921d74cSToby Isaac if (gatheredValues) {
34939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootIndices, &rootVals));
34949566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE));
34959566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(indicesSF, MPIU_SCALAR, leafVals, rootVals, MPI_REPLACE));
3496c921d74cSToby Isaac }
34979566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&indicesSF));
34988d2f55e7SToby Isaac }
34999566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafIndicesSec));
35009566063dSJacob Faibussowitsch PetscCall(PetscFree(leafInds));
35019566063dSJacob Faibussowitsch PetscCall(PetscFree(leafVals));
35029566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded));
3503c921d74cSToby Isaac *rootMultiSec = multiRootSec;
3504c921d74cSToby Isaac *multiLeafSec = rootIndicesSec;
3505c921d74cSToby Isaac if (gatheredIndices) *gatheredIndices = rootInds;
3506c921d74cSToby Isaac if (gatheredValues) *gatheredValues = rootVals;
35073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3508ebf164c7SToby Isaac }
3509ebf164c7SToby Isaac
DMPlexComputeInjectorTree(DM coarse,DM fine,PetscSF coarseToFine,PetscInt * childIds,Mat mat)3510d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeInjectorTree(DM coarse, DM fine, PetscSF coarseToFine, PetscInt *childIds, Mat mat)
3511d71ae5a4SJacob Faibussowitsch {
3512ebf164c7SToby Isaac DM refTree;
3513c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec;
3514ebf164c7SToby Isaac PetscSection globalCoarse, globalFine;
3515ebf164c7SToby Isaac PetscSection localCoarse, localFine;
3516ebf164c7SToby Isaac PetscSection cSecRef;
3517277f51e8SBarry Smith PetscInt *rootIndices = NULL, *parentIndices, pRefStart, pRefEnd;
3518ebf164c7SToby Isaac Mat injRef;
3519c921d74cSToby Isaac PetscInt numFields, maxDof;
3520ebf164c7SToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p;
3521ebf164c7SToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets;
3522ebf164c7SToby Isaac PetscLayout rowMap, colMap;
3523ebf164c7SToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd, *nnzD, *nnzO;
3524ebf164c7SToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */
3525ebf164c7SToby Isaac
3526ebf164c7SToby Isaac PetscFunctionBegin;
3527ebf164c7SToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */
35289566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree));
3529d3a532e9SStefano Zampini PetscCall(DMCopyDisc(coarse, refTree));
3530d3a532e9SStefano Zampini PetscCall(DMSetLocalSection(refTree, NULL));
3531d3a532e9SStefano Zampini PetscCall(DMSetDefaultConstraints(refTree, NULL, NULL, NULL));
35329566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL));
35339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd));
35349566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef));
3535ebf164c7SToby Isaac
35369566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF));
35379566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine));
35389566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine));
35399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields));
35409566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC));
35419566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse));
35429566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse));
35439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof));
3544ebf164c7SToby Isaac {
3545ebf164c7SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1;
35469566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets));
3547ebf164c7SToby Isaac }
3548ebf164c7SToby Isaac
35499566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, childIds, NULL, numFields, offsets, &multiRootSec, &rootIndicesSec, &rootIndices, NULL));
35508d2f55e7SToby Isaac
35519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &parentIndices));
3552f30e825dSToby Isaac
3553f30e825dSToby Isaac /* count indices */
35549566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(mat, &rowMap, &colMap));
35559566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap));
35569566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap));
35579566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd));
35589566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd));
35599566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(rowEnd - rowStart, &nnzD, rowEnd - rowStart, &nnzO));
3560f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) {
3561f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff;
35628d2f55e7SToby Isaac
35639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof));
35649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof));
3565f30e825dSToby Isaac if ((dof - cdof) <= 0) continue;
35669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff));
35678d2f55e7SToby Isaac
35688d2f55e7SToby Isaac rowOffsets[0] = 0;
3569f30e825dSToby Isaac offsetsCopy[0] = 0;
35708d2f55e7SToby Isaac if (numFields) {
35718d2f55e7SToby Isaac PetscInt f;
35728d2f55e7SToby Isaac
3573f30e825dSToby Isaac for (f = 0; f < numFields; f++) {
3574f30e825dSToby Isaac PetscInt fDof;
35759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof));
3576f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f];
35778d2f55e7SToby Isaac }
35789566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices));
3579367003a6SStefano Zampini } else {
35809566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices));
3581f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0];
35828d2f55e7SToby Isaac }
3583f30e825dSToby Isaac
35849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves));
35859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart));
3586f30e825dSToby Isaac leafEnd = leafStart + numLeaves;
3587f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) {
3588f30e825dSToby Isaac PetscInt numIndices, childId, offset;
3589f30e825dSToby Isaac const PetscInt *childIndices;
3590f30e825dSToby Isaac
35919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices));
35929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset));
3593f30e825dSToby Isaac childId = rootIndices[offset++];
3594f30e825dSToby Isaac childIndices = &rootIndices[offset];
3595f30e825dSToby Isaac numIndices--;
3596f30e825dSToby Isaac
3597f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */
3598f30e825dSToby Isaac PetscInt i;
3599f30e825dSToby Isaac
3600f30e825dSToby Isaac for (i = 0; i < numIndices; i++) {
3601f30e825dSToby Isaac PetscInt colIndex = childIndices[i];
3602f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i];
3603f30e825dSToby Isaac if (rowIndex < 0) continue;
360408401ef6SPierre Jolivet PetscCheck(colIndex >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unconstrained fine and constrained coarse");
3605a47f92cbSToby Isaac if (colIndex >= colStart && colIndex < colEnd) {
3606f30e825dSToby Isaac nnzD[rowIndex - rowStart] = 1;
36079371c9d4SSatish Balay } else {
3608f30e825dSToby Isaac nnzO[rowIndex - rowStart] = 1;
3609f30e825dSToby Isaac }
3610f30e825dSToby Isaac }
36119371c9d4SSatish Balay } else {
3612f30e825dSToby Isaac PetscInt parentId, f, lim;
3613f30e825dSToby Isaac
36149566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL));
3615f30e825dSToby Isaac
3616f30e825dSToby Isaac lim = PetscMax(1, numFields);
3617f30e825dSToby Isaac offsets[0] = 0;
36188d2f55e7SToby Isaac if (numFields) {
36198d2f55e7SToby Isaac PetscInt f;
3620f30e825dSToby Isaac
36218d2f55e7SToby Isaac for (f = 0; f < numFields; f++) {
3622f30e825dSToby Isaac PetscInt fDof;
36239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof));
3624f30e825dSToby Isaac
3625f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f];
36268d2f55e7SToby Isaac }
36279371c9d4SSatish Balay } else {
3628f30e825dSToby Isaac PetscInt cDof;
3629f30e825dSToby Isaac
36309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof));
3631f30e825dSToby Isaac offsets[1] = cDof;
3632f30e825dSToby Isaac }
3633f30e825dSToby Isaac for (f = 0; f < lim; f++) {
3634f30e825dSToby Isaac PetscInt parentStart = rowOffsets[f], parentEnd = rowOffsets[f + 1];
3635f30e825dSToby Isaac PetscInt childStart = offsets[f], childEnd = offsets[f + 1];
3636f30e825dSToby Isaac PetscInt i, numD = 0, numO = 0;
3637f30e825dSToby Isaac
3638f30e825dSToby Isaac for (i = childStart; i < childEnd; i++) {
3639f30e825dSToby Isaac PetscInt colIndex = childIndices[i];
3640f30e825dSToby Isaac
3641f30e825dSToby Isaac if (colIndex < 0) continue;
3642f30e825dSToby Isaac if (colIndex >= colStart && colIndex < colEnd) {
3643f30e825dSToby Isaac numD++;
36449371c9d4SSatish Balay } else {
3645f30e825dSToby Isaac numO++;
3646f30e825dSToby Isaac }
3647f30e825dSToby Isaac }
3648f30e825dSToby Isaac for (i = parentStart; i < parentEnd; i++) {
3649f30e825dSToby Isaac PetscInt rowIndex = parentIndices[i];
3650f30e825dSToby Isaac
3651f30e825dSToby Isaac if (rowIndex < 0) continue;
3652f30e825dSToby Isaac nnzD[rowIndex - rowStart] += numD;
3653f30e825dSToby Isaac nnzO[rowIndex - rowStart] += numO;
36548d2f55e7SToby Isaac }
36558d2f55e7SToby Isaac }
36568d2f55e7SToby Isaac }
3657f30e825dSToby Isaac }
3658f30e825dSToby Isaac }
3659f30e825dSToby Isaac /* preallocate */
36609566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mat, 1, nnzD, nnzO, NULL, NULL));
36619566063dSJacob Faibussowitsch PetscCall(PetscFree2(nnzD, nnzO));
3662f30e825dSToby Isaac /* insert values */
36639566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats));
3664f30e825dSToby Isaac for (p = pStartC; p < pEndC; p++) {
3665f30e825dSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff;
3666f30e825dSToby Isaac
36679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof));
36689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof));
3669f30e825dSToby Isaac if ((dof - cdof) <= 0) continue;
36709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff));
3671f30e825dSToby Isaac
3672f30e825dSToby Isaac rowOffsets[0] = 0;
3673f30e825dSToby Isaac offsetsCopy[0] = 0;
36748d2f55e7SToby Isaac if (numFields) {
36758d2f55e7SToby Isaac PetscInt f;
3676f30e825dSToby Isaac
36778d2f55e7SToby Isaac for (f = 0; f < numFields; f++) {
3678f30e825dSToby Isaac PetscInt fDof;
36799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof));
3680f30e825dSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f];
3681f30e825dSToby Isaac }
36829566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices));
3683367003a6SStefano Zampini } else {
36849566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices));
3685f30e825dSToby Isaac rowOffsets[1] = offsetsCopy[0];
3686f30e825dSToby Isaac }
3687f30e825dSToby Isaac
36889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves));
36899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart));
3690f30e825dSToby Isaac leafEnd = leafStart + numLeaves;
3691f30e825dSToby Isaac for (l = leafStart; l < leafEnd; l++) {
3692f30e825dSToby Isaac PetscInt numIndices, childId, offset;
3693f30e825dSToby Isaac const PetscInt *childIndices;
3694f30e825dSToby Isaac
36959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices));
36969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset));
3697f30e825dSToby Isaac childId = rootIndices[offset++];
3698f30e825dSToby Isaac childIndices = &rootIndices[offset];
3699f30e825dSToby Isaac numIndices--;
3700f30e825dSToby Isaac
3701f30e825dSToby Isaac if (childId == -1) { /* equivalent points: scatter */
3702f30e825dSToby Isaac PetscInt i;
3703f30e825dSToby Isaac
370448a46eb9SPierre Jolivet for (i = 0; i < numIndices; i++) PetscCall(MatSetValue(mat, parentIndices[i], childIndices[i], 1., INSERT_VALUES));
37059371c9d4SSatish Balay } else {
3706f30e825dSToby Isaac PetscInt parentId, f, lim;
37078d2f55e7SToby Isaac
37089566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL));
3709f30e825dSToby Isaac
3710f30e825dSToby Isaac lim = PetscMax(1, numFields);
3711f30e825dSToby Isaac offsets[0] = 0;
37128d2f55e7SToby Isaac if (numFields) {
3713f30e825dSToby Isaac PetscInt f;
37148d2f55e7SToby Isaac
3715f30e825dSToby Isaac for (f = 0; f < numFields; f++) {
3716f30e825dSToby Isaac PetscInt fDof;
37179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof));
3718f30e825dSToby Isaac
3719f30e825dSToby Isaac offsets[f + 1] = fDof + offsets[f];
37208d2f55e7SToby Isaac }
37219371c9d4SSatish Balay } else {
3722f30e825dSToby Isaac PetscInt cDof;
3723f30e825dSToby Isaac
37249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof));
3725f30e825dSToby Isaac offsets[1] = cDof;
37268d2f55e7SToby Isaac }
3727f30e825dSToby Isaac for (f = 0; f < lim; f++) {
3728f30e825dSToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0];
3729f30e825dSToby Isaac PetscInt *rowIndices = &parentIndices[rowOffsets[f]];
3730f30e825dSToby Isaac const PetscInt *colIndices = &childIndices[offsets[f]];
3731f30e825dSToby Isaac
37329566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, rowOffsets[f + 1] - rowOffsets[f], rowIndices, offsets[f + 1] - offsets[f], colIndices, childMat, INSERT_VALUES));
37338d2f55e7SToby Isaac }
37348d2f55e7SToby Isaac }
37358d2f55e7SToby Isaac }
37368d2f55e7SToby Isaac }
37379566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec));
37389566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec));
37399566063dSJacob Faibussowitsch PetscCall(PetscFree(parentIndices));
37409566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats));
37419566063dSJacob Faibussowitsch PetscCall(PetscFree(rootIndices));
37429566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets));
3743f30e825dSToby Isaac
37449566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
37459566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
37463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3747154bca37SToby Isaac }
374838fc2455SToby Isaac
DMPlexTransferVecTree_Interpolate(DM coarse,Vec vecCoarseLocal,DM fine,Vec vecFine,PetscSF coarseToFine,PetscInt * cids,Vec grad,Vec cellGeom)3749d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferVecTree_Interpolate(DM coarse, Vec vecCoarseLocal, DM fine, Vec vecFine, PetscSF coarseToFine, PetscInt *cids, Vec grad, Vec cellGeom)
3750d71ae5a4SJacob Faibussowitsch {
375162095d54SToby Isaac PetscSF coarseToFineEmbedded;
375262095d54SToby Isaac PetscSection globalCoarse, globalFine;
375362095d54SToby Isaac PetscSection localCoarse, localFine;
375462095d54SToby Isaac PetscSection aSec, cSec;
375562095d54SToby Isaac PetscSection rootValuesSec;
375662095d54SToby Isaac PetscSection leafValuesSec;
375762095d54SToby Isaac PetscScalar *rootValues, *leafValues;
375862095d54SToby Isaac IS aIS;
375962095d54SToby Isaac const PetscInt *anchors;
376062095d54SToby Isaac Mat cMat;
376162095d54SToby Isaac PetscInt numFields;
3762412e9a14SMatthew G. Knepley PetscInt pStartC, pEndC, pStartF, pEndF, p, cellStart, cellEnd;
376362095d54SToby Isaac PetscInt aStart, aEnd, cStart, cEnd;
376462095d54SToby Isaac PetscInt *maxChildIds;
376562095d54SToby Isaac PetscInt *offsets, *newOffsets, *offsetsCopy, *newOffsetsCopy, *rowOffsets, *numD, *numO;
37660eb7e1eaSToby Isaac PetscFV fv = NULL;
37670eb7e1eaSToby Isaac PetscInt dim, numFVcomps = -1, fvField = -1;
37680eb7e1eaSToby Isaac DM cellDM = NULL, gradDM = NULL;
37690eb7e1eaSToby Isaac const PetscScalar *cellGeomArray = NULL;
37700eb7e1eaSToby Isaac const PetscScalar *gradArray = NULL;
377162095d54SToby Isaac
3772ebf164c7SToby Isaac PetscFunctionBegin;
37739566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE));
37749566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC));
37759566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(coarse, 0, &cellStart, &cellEnd));
37769566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF));
37779566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine));
37789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(coarse, &dim));
377962095d54SToby Isaac { /* winnow fine points that don't have global dofs out of the sf */
3780e4a60869SToby Isaac PetscInt nleaves, l;
3781e4a60869SToby Isaac const PetscInt *leaves;
378262095d54SToby Isaac PetscInt dof, cdof, numPointsWithDofs, offset, *pointsWithDofs;
378362095d54SToby Isaac
37849566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseToFine, NULL, &nleaves, &leaves, NULL));
3785e4a60869SToby Isaac
3786e4a60869SToby Isaac for (l = 0, numPointsWithDofs = 0; l < nleaves; l++) {
3787e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l;
3788e4a60869SToby Isaac
37899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof));
37909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof));
3791ad540459SPierre Jolivet if ((dof - cdof) > 0) numPointsWithDofs++;
379262095d54SToby Isaac }
37939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPointsWithDofs, &pointsWithDofs));
37944833aeb0SToby Isaac for (l = 0, offset = 0; l < nleaves; l++) {
3795e4a60869SToby Isaac PetscInt p = leaves ? leaves[l] : l;
3796e4a60869SToby Isaac
37979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &dof));
37989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &cdof));
3799ad540459SPierre Jolivet if ((dof - cdof) > 0) pointsWithDofs[offset++] = l;
380062095d54SToby Isaac }
38019566063dSJacob Faibussowitsch PetscCall(PetscSFCreateEmbeddedLeafSF(coarseToFine, numPointsWithDofs, pointsWithDofs, &coarseToFineEmbedded));
38029566063dSJacob Faibussowitsch PetscCall(PetscFree(pointsWithDofs));
380362095d54SToby Isaac }
380462095d54SToby Isaac /* communicate back to the coarse mesh which coarse points have children (that may require interpolation) */
38059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEndC - pStartC, &maxChildIds));
3806ad540459SPierre Jolivet for (p = pStartC; p < pEndC; p++) maxChildIds[p - pStartC] = -2;
38079566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX));
38089566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(coarseToFineEmbedded, MPIU_INT, cids, maxChildIds, MPIU_MAX));
380962095d54SToby Isaac
38109566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse));
38119566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse));
381262095d54SToby Isaac
38139566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(coarse, &aSec, &aIS));
38149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors));
38159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
381662095d54SToby Isaac
38179566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(coarse, &cSec, &cMat, NULL));
38189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd));
381962095d54SToby Isaac
382062095d54SToby Isaac /* create sections that will send to children the indices and matrices they will need to construct the interpolator */
38219566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)coarse), &rootValuesSec));
38229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(rootValuesSec, pStartC, pEndC));
38239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localCoarse, &numFields));
382462095d54SToby Isaac {
382562095d54SToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1;
38269566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &newOffsets, maxFields, &newOffsetsCopy, maxFields, &rowOffsets, maxFields, &numD, maxFields, &numO));
382762095d54SToby Isaac }
38280eb7e1eaSToby Isaac if (grad) {
38290eb7e1eaSToby Isaac PetscInt i;
38300eb7e1eaSToby Isaac
38319566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellGeom, &cellDM));
38329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeom, &cellGeomArray));
38339566063dSJacob Faibussowitsch PetscCall(VecGetDM(grad, &gradDM));
38349566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(grad, &gradArray));
38350eb7e1eaSToby Isaac for (i = 0; i < PetscMax(1, numFields); i++) {
38360eb7e1eaSToby Isaac PetscObject obj;
38370eb7e1eaSToby Isaac PetscClassId id;
38380eb7e1eaSToby Isaac
38399566063dSJacob Faibussowitsch PetscCall(DMGetField(coarse, i, NULL, &obj));
38409566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
38410eb7e1eaSToby Isaac if (id == PETSCFV_CLASSID) {
38420eb7e1eaSToby Isaac fv = (PetscFV)obj;
38439566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &numFVcomps));
38440eb7e1eaSToby Isaac fvField = i;
38450eb7e1eaSToby Isaac break;
38460eb7e1eaSToby Isaac }
38470eb7e1eaSToby Isaac }
38480eb7e1eaSToby Isaac }
384962095d54SToby Isaac
385062095d54SToby Isaac for (p = pStartC; p < pEndC; p++) { /* count the sizes of the indices and matrices */
385162095d54SToby Isaac PetscInt dof;
385262095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC];
385362095d54SToby Isaac PetscInt numValues = 0;
385462095d54SToby Isaac
38559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof));
3856ad540459SPierre Jolivet if (dof < 0) dof = -(dof + 1);
385762095d54SToby Isaac offsets[0] = 0;
385862095d54SToby Isaac newOffsets[0] = 0;
385962095d54SToby Isaac if (maxChildId >= 0) { /* this point has children (with dofs) that will need to be interpolated from the closure of p */
386062095d54SToby Isaac PetscInt *closure = NULL, closureSize, cl;
386162095d54SToby Isaac
38629566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure));
386362095d54SToby Isaac for (cl = 0; cl < closureSize; cl++) { /* get the closure */
386462095d54SToby Isaac PetscInt c = closure[2 * cl], clDof;
386562095d54SToby Isaac
38669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, c, &clDof));
386762095d54SToby Isaac numValues += clDof;
386862095d54SToby Isaac }
38699566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(coarse, p, PETSC_TRUE, &closureSize, &closure));
38709371c9d4SSatish Balay } else if (maxChildId == -1) {
38719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &numValues));
387262095d54SToby Isaac }
387362095d54SToby Isaac /* we will pack the column indices with the field offsets */
387478b7adb5SToby Isaac if (maxChildId >= 0 && grad && p >= cellStart && p < cellEnd) {
38750eb7e1eaSToby Isaac /* also send the centroid, and the gradient */
38760eb7e1eaSToby Isaac numValues += dim * (1 + numFVcomps);
38770eb7e1eaSToby Isaac }
38789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(rootValuesSec, p, numValues));
387962095d54SToby Isaac }
38809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(rootValuesSec));
388162095d54SToby Isaac {
388262095d54SToby Isaac PetscInt numRootValues;
388362095d54SToby Isaac const PetscScalar *coarseArray;
388462095d54SToby Isaac
38859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(rootValuesSec, &numRootValues));
38869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRootValues, &rootValues));
38879566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecCoarseLocal, &coarseArray));
388862095d54SToby Isaac for (p = pStartC; p < pEndC; p++) {
388962095d54SToby Isaac PetscInt numValues;
389062095d54SToby Isaac PetscInt pValOff;
389162095d54SToby Isaac PetscScalar *pVal;
389262095d54SToby Isaac PetscInt maxChildId = maxChildIds[p - pStartC];
389362095d54SToby Isaac
38949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootValuesSec, p, &numValues));
3895ad540459SPierre Jolivet if (!numValues) continue;
38969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootValuesSec, p, &pValOff));
3897f4f49eeaSPierre Jolivet pVal = &rootValues[pValOff];
389862095d54SToby Isaac if (maxChildId >= 0) { /* build an identity matrix, apply matrix constraints on the right */
38990eb7e1eaSToby Isaac PetscInt closureSize = numValues;
39009566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(coarse, NULL, vecCoarseLocal, p, &closureSize, &pVal));
39010eb7e1eaSToby Isaac if (grad && p >= cellStart && p < cellEnd) {
3902193eb951SToby Isaac PetscFVCellGeom *cg;
39036dd00756SToby Isaac PetscScalar *gradVals = NULL;
39040eb7e1eaSToby Isaac PetscInt i;
39050eb7e1eaSToby Isaac
39060eb7e1eaSToby Isaac pVal += (numValues - dim * (1 + numFVcomps));
39070eb7e1eaSToby Isaac
39089566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(cellDM, p, cellGeomArray, (void *)&cg));
39090eb7e1eaSToby Isaac for (i = 0; i < dim; i++) pVal[i] = cg->centroid[i];
39100eb7e1eaSToby Isaac pVal += dim;
39119566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRead(gradDM, p, gradArray, (void *)&gradVals));
39120eb7e1eaSToby Isaac for (i = 0; i < dim * numFVcomps; i++) pVal[i] = gradVals[i];
39130eb7e1eaSToby Isaac }
39149371c9d4SSatish Balay } else if (maxChildId == -1) {
391578b7adb5SToby Isaac PetscInt lDof, lOff, i;
391678b7adb5SToby Isaac
39179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &lDof));
39189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(localCoarse, p, &lOff));
391978b7adb5SToby Isaac for (i = 0; i < lDof; i++) pVal[i] = coarseArray[lOff + i];
392078b7adb5SToby Isaac }
392178b7adb5SToby Isaac }
39229566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecCoarseLocal, &coarseArray));
39239566063dSJacob Faibussowitsch PetscCall(PetscFree(maxChildIds));
392462095d54SToby Isaac }
392562095d54SToby Isaac {
392662095d54SToby Isaac PetscSF valuesSF;
392762095d54SToby Isaac PetscInt *remoteOffsetsValues, numLeafValues;
392862095d54SToby Isaac
39299566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)fine), &leafValuesSec));
39309566063dSJacob Faibussowitsch PetscCall(PetscSFDistributeSection(coarseToFineEmbedded, rootValuesSec, &remoteOffsetsValues, leafValuesSec));
39319566063dSJacob Faibussowitsch PetscCall(PetscSFCreateSectionSF(coarseToFineEmbedded, rootValuesSec, remoteOffsetsValues, leafValuesSec, &valuesSF));
39329566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseToFineEmbedded));
39339566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsetsValues));
39349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(leafValuesSec, &numLeafValues));
39359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeafValues, &leafValues));
39369566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE));
39379566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(valuesSF, MPIU_SCALAR, rootValues, leafValues, MPI_REPLACE));
39389566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&valuesSF));
39399566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues));
39409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootValuesSec));
394162095d54SToby Isaac }
39429566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine));
394362095d54SToby Isaac {
394462095d54SToby Isaac PetscInt maxDof;
394562095d54SToby Isaac PetscInt *rowIndices;
394662095d54SToby Isaac DM refTree;
394762095d54SToby Isaac PetscInt **refPointFieldN;
394862095d54SToby Isaac PetscScalar ***refPointFieldMats;
394962095d54SToby Isaac PetscSection refConSec, refAnSec;
39500eb7e1eaSToby Isaac PetscInt pRefStart, pRefEnd, leafStart, leafEnd;
395162095d54SToby Isaac PetscScalar *pointWork;
395262095d54SToby Isaac
39539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localFine, &maxDof));
39549566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_INT, &rowIndices));
39559566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork));
39569566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(fine, &refTree));
39579566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(fine, refTree));
39589566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN));
39599566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &refConSec, NULL, NULL));
39609566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(refTree, &refAnSec, NULL));
39619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(refConSec, &pRefStart, &pRefEnd));
39629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(leafValuesSec, &leafStart, &leafEnd));
39639566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(fine, 0, &cellStart, &cellEnd));
39640eb7e1eaSToby Isaac for (p = leafStart; p < leafEnd; p++) {
396562095d54SToby Isaac PetscInt gDof, gcDof, gOff, lDof;
396662095d54SToby Isaac PetscInt numValues, pValOff;
396762095d54SToby Isaac PetscInt childId;
396862095d54SToby Isaac const PetscScalar *pVal;
39690eb7e1eaSToby Isaac const PetscScalar *fvGradData = NULL;
397062095d54SToby Isaac
39719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalFine, p, &gDof));
39729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localFine, p, &lDof));
39739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalFine, p, &gcDof));
3974ad540459SPierre Jolivet if ((gDof - gcDof) <= 0) continue;
39759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFine, p, &gOff));
39769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(leafValuesSec, p, &numValues));
397762095d54SToby Isaac if (!numValues) continue;
39789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(leafValuesSec, p, &pValOff));
397962095d54SToby Isaac pVal = &leafValues[pValOff];
398062095d54SToby Isaac offsets[0] = 0;
398162095d54SToby Isaac offsetsCopy[0] = 0;
398262095d54SToby Isaac newOffsets[0] = 0;
398362095d54SToby Isaac newOffsetsCopy[0] = 0;
39844833aeb0SToby Isaac childId = cids[p - pStartF];
398562095d54SToby Isaac if (numFields) {
398662095d54SToby Isaac PetscInt f;
398762095d54SToby Isaac for (f = 0; f < numFields; f++) {
398862095d54SToby Isaac PetscInt rowDof;
398962095d54SToby Isaac
39909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localFine, p, f, &rowDof));
399162095d54SToby Isaac offsets[f + 1] = offsets[f] + rowDof;
399262095d54SToby Isaac offsetsCopy[f + 1] = offsets[f + 1];
399362095d54SToby Isaac /* TODO: closure indices */
39949f4e70e1SToby Isaac newOffsets[f + 1] = newOffsets[f] + ((childId == -1) ? rowDof : refPointFieldN[childId - pRefStart][f]);
399562095d54SToby Isaac }
39969566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, rowIndices));
39979371c9d4SSatish Balay } else {
39984833aeb0SToby Isaac offsets[0] = 0;
39994833aeb0SToby Isaac offsets[1] = lDof;
40004833aeb0SToby Isaac newOffsets[0] = 0;
40014833aeb0SToby Isaac newOffsets[1] = (childId == -1) ? lDof : refPointFieldN[childId - pRefStart][0];
40029566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localFine, PETSC_FALSE, p, gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, rowIndices));
400362095d54SToby Isaac }
400462095d54SToby Isaac if (childId == -1) { /* no child interpolation: one nnz per */
40059566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numValues, rowIndices, pVal, INSERT_VALUES));
400662095d54SToby Isaac } else {
400762095d54SToby Isaac PetscInt f;
400862095d54SToby Isaac
400978b7adb5SToby Isaac if (grad && p >= cellStart && p < cellEnd) {
401078b7adb5SToby Isaac numValues -= (dim * (1 + numFVcomps));
401178b7adb5SToby Isaac fvGradData = &pVal[numValues];
401278b7adb5SToby Isaac }
401362095d54SToby Isaac for (f = 0; f < PetscMax(1, numFields); f++) {
401462095d54SToby Isaac const PetscScalar *childMat = refPointFieldMats[childId - pRefStart][f];
401562095d54SToby Isaac PetscInt numRows = offsets[f + 1] - offsets[f];
401662095d54SToby Isaac PetscInt numCols = newOffsets[f + 1] - newOffsets[f];
401762095d54SToby Isaac const PetscScalar *cVal = &pVal[newOffsets[f]];
401862095d54SToby Isaac PetscScalar *rVal = &pointWork[offsets[f]];
401962095d54SToby Isaac PetscInt i, j;
402062095d54SToby Isaac
4021708c7f19SToby Isaac #if 0
402263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(coarse,"childId %" PetscInt_FMT ", numRows %" PetscInt_FMT ", numCols %" PetscInt_FMT ", refPointFieldN %" PetscInt_FMT " maxDof %" PetscInt_FMT "\n",childId,numRows,numCols,refPointFieldN[childId - pRefStart][f], maxDof));
4023708c7f19SToby Isaac #endif
402462095d54SToby Isaac for (i = 0; i < numRows; i++) {
402562095d54SToby Isaac PetscScalar val = 0.;
4026ad540459SPierre Jolivet for (j = 0; j < numCols; j++) val += childMat[i * numCols + j] * cVal[j];
402762095d54SToby Isaac rVal[i] = val;
402862095d54SToby Isaac }
40290eb7e1eaSToby Isaac if (f == fvField && p >= cellStart && p < cellEnd) {
40300eb7e1eaSToby Isaac PetscReal centroid[3];
40310eb7e1eaSToby Isaac PetscScalar diff[3];
40320eb7e1eaSToby Isaac const PetscScalar *parentCentroid = &fvGradData[0];
40330eb7e1eaSToby Isaac const PetscScalar *gradient = &fvGradData[dim];
40340eb7e1eaSToby Isaac
40359566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(fine, p, NULL, centroid, NULL));
4036ad540459SPierre Jolivet for (i = 0; i < dim; i++) diff[i] = centroid[i] - parentCentroid[i];
40370eb7e1eaSToby Isaac for (i = 0; i < numFVcomps; i++) {
40380eb7e1eaSToby Isaac PetscScalar val = 0.;
40390eb7e1eaSToby Isaac
4040ad540459SPierre Jolivet for (j = 0; j < dim; j++) val += gradient[dim * i + j] * diff[j];
40410eb7e1eaSToby Isaac rVal[i] += val;
40420eb7e1eaSToby Isaac }
40430eb7e1eaSToby Isaac }
40449566063dSJacob Faibussowitsch PetscCall(VecSetValues(vecFine, numRows, &rowIndices[offsets[f]], rVal, INSERT_VALUES));
404562095d54SToby Isaac }
404662095d54SToby Isaac }
404762095d54SToby Isaac }
40489566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices(refTree, &refPointFieldMats, &refPointFieldN));
40499566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_SCALAR, &pointWork));
40509566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(fine, maxDof, MPIU_INT, &rowIndices));
405162095d54SToby Isaac }
40529566063dSJacob Faibussowitsch PetscCall(PetscFree(leafValues));
40539566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&leafValuesSec));
40549566063dSJacob Faibussowitsch PetscCall(PetscFree7(offsets, offsetsCopy, newOffsets, newOffsetsCopy, rowOffsets, numD, numO));
40559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors));
40563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4057ebf164c7SToby Isaac }
4058ebf164c7SToby Isaac
DMPlexTransferVecTree_Inject(DM fine,Vec vecFine,DM coarse,Vec vecCoarse,PetscSF coarseToFine,PetscInt * cids)4059d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransferVecTree_Inject(DM fine, Vec vecFine, DM coarse, Vec vecCoarse, PetscSF coarseToFine, PetscInt *cids)
4060d71ae5a4SJacob Faibussowitsch {
4061c921d74cSToby Isaac DM refTree;
4062c921d74cSToby Isaac PetscSection multiRootSec, rootIndicesSec;
4063c921d74cSToby Isaac PetscSection globalCoarse, globalFine;
4064c921d74cSToby Isaac PetscSection localCoarse, localFine;
4065c921d74cSToby Isaac PetscSection cSecRef;
4066c921d74cSToby Isaac PetscInt *parentIndices, pRefStart, pRefEnd;
4067d3bc4906SToby Isaac PetscScalar *rootValues, *parentValues;
4068c921d74cSToby Isaac Mat injRef;
4069c921d74cSToby Isaac PetscInt numFields, maxDof;
4070c921d74cSToby Isaac PetscInt pStartC, pEndC, pStartF, pEndF, p;
4071c921d74cSToby Isaac PetscInt *offsets, *offsetsCopy, *rowOffsets;
4072c921d74cSToby Isaac PetscLayout rowMap, colMap;
4073c921d74cSToby Isaac PetscInt rowStart, rowEnd, colStart, colEnd;
4074c921d74cSToby Isaac PetscScalar ***childrenMats = NULL; /* gcc -O gives 'may be used uninitialized' warning'. Initializing to suppress this warning */
4075c921d74cSToby Isaac
4076ebf164c7SToby Isaac PetscFunctionBegin;
4077c921d74cSToby Isaac /* get the templates for the fine-to-coarse injection from the reference tree */
40789566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecFine, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE));
40799566063dSJacob Faibussowitsch PetscCall(VecSetOption(vecCoarse, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE));
40809566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(coarse, &refTree));
40819566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(coarse, refTree));
40829566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(refTree, &cSecRef, NULL, NULL));
40839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSecRef, &pRefStart, &pRefEnd));
40849566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetInjector(refTree, &injRef));
4085c921d74cSToby Isaac
40869566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(fine, &pStartF, &pEndF));
40879566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(fine, &localFine));
40889566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(fine, &globalFine));
40899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(localFine, &numFields));
40909566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(coarse, &pStartC, &pEndC));
40919566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(coarse, &localCoarse));
40929566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(coarse, &globalCoarse));
40939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(localCoarse, &maxDof));
4094c921d74cSToby Isaac {
4095c921d74cSToby Isaac PetscInt maxFields = PetscMax(1, numFields) + 1;
40969566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(maxFields, &offsets, maxFields, &offsetsCopy, maxFields, &rowOffsets));
4097c921d74cSToby Isaac }
4098c921d74cSToby Isaac
40999566063dSJacob Faibussowitsch PetscCall(DMPlexTransferInjectorTree(coarse, fine, coarseToFine, cids, vecFine, numFields, offsets, &multiRootSec, &rootIndicesSec, NULL, &rootValues));
4100c921d74cSToby Isaac
41019566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxDof, &parentIndices, maxDof, &parentValues));
4102c921d74cSToby Isaac
4103c921d74cSToby Isaac /* count indices */
41049566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecFine, &colMap));
41059566063dSJacob Faibussowitsch PetscCall(VecGetLayout(vecCoarse, &rowMap));
41069566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rowMap));
41079566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colMap));
41089566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rowMap, &rowStart, &rowEnd));
41099566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colMap, &colStart, &colEnd));
4110c921d74cSToby Isaac /* insert values */
41119566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeGetChildrenMatrices_Injection(refTree, injRef, &childrenMats));
4112c921d74cSToby Isaac for (p = pStartC; p < pEndC; p++) {
4113c921d74cSToby Isaac PetscInt numLeaves, leafStart, leafEnd, l, dof, cdof, gOff;
411478b7adb5SToby Isaac PetscBool contribute = PETSC_FALSE;
4115c921d74cSToby Isaac
41169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(globalCoarse, p, &dof));
41179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(globalCoarse, p, &cdof));
4118c921d74cSToby Isaac if ((dof - cdof) <= 0) continue;
41199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(localCoarse, p, &dof));
41209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCoarse, p, &gOff));
4121c921d74cSToby Isaac
4122c921d74cSToby Isaac rowOffsets[0] = 0;
4123c921d74cSToby Isaac offsetsCopy[0] = 0;
4124c921d74cSToby Isaac if (numFields) {
4125c921d74cSToby Isaac PetscInt f;
4126c921d74cSToby Isaac
4127c921d74cSToby Isaac for (f = 0; f < numFields; f++) {
4128c921d74cSToby Isaac PetscInt fDof;
41299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(localCoarse, p, f, &fDof));
4130c921d74cSToby Isaac rowOffsets[f + 1] = offsetsCopy[f + 1] = fDof + rowOffsets[f];
4131c921d74cSToby Isaac }
41329566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, -1, NULL, parentIndices));
4133367003a6SStefano Zampini } else {
41349566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(localCoarse, PETSC_FALSE, p, gOff < 0 ? -(gOff + 1) : gOff, offsetsCopy, PETSC_FALSE, NULL, NULL, parentIndices));
4135c921d74cSToby Isaac rowOffsets[1] = offsetsCopy[0];
4136c921d74cSToby Isaac }
4137c921d74cSToby Isaac
41389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(multiRootSec, p, &numLeaves));
41399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(multiRootSec, p, &leafStart));
4140c921d74cSToby Isaac leafEnd = leafStart + numLeaves;
41412f65e181SToby Isaac for (l = 0; l < dof; l++) parentValues[l] = 0.;
4142c921d74cSToby Isaac for (l = leafStart; l < leafEnd; l++) {
4143c921d74cSToby Isaac PetscInt numIndices, childId, offset;
4144c921d74cSToby Isaac const PetscScalar *childValues;
4145c921d74cSToby Isaac
41469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(rootIndicesSec, l, &numIndices));
41479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(rootIndicesSec, l, &offset));
4148c921d74cSToby Isaac childId = (PetscInt)PetscRealPart(rootValues[offset++]);
4149c921d74cSToby Isaac childValues = &rootValues[offset];
4150c921d74cSToby Isaac numIndices--;
4151c921d74cSToby Isaac
4152c921d74cSToby Isaac if (childId == -2) { /* skip */
4153c921d74cSToby Isaac continue;
4154c921d74cSToby Isaac } else if (childId == -1) { /* equivalent points: scatter */
41552f65e181SToby Isaac PetscInt m;
41562f65e181SToby Isaac
415778b7adb5SToby Isaac contribute = PETSC_TRUE;
41582f65e181SToby Isaac for (m = 0; m < numIndices; m++) parentValues[m] = childValues[m];
4159beedf8abSToby Isaac } else { /* contributions from children: sum with injectors from reference tree */
4160d3bc4906SToby Isaac PetscInt parentId, f, lim;
4161d3bc4906SToby Isaac
416278b7adb5SToby Isaac contribute = PETSC_TRUE;
41639566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(refTree, childId, &parentId, NULL));
4164d3bc4906SToby Isaac
4165d3bc4906SToby Isaac lim = PetscMax(1, numFields);
4166d3bc4906SToby Isaac offsets[0] = 0;
4167d3bc4906SToby Isaac if (numFields) {
4168d3bc4906SToby Isaac PetscInt f;
4169d3bc4906SToby Isaac
4170d3bc4906SToby Isaac for (f = 0; f < numFields; f++) {
4171d3bc4906SToby Isaac PetscInt fDof;
41729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSecRef, childId, f, &fDof));
4173d3bc4906SToby Isaac
4174d3bc4906SToby Isaac offsets[f + 1] = fDof + offsets[f];
4175d3bc4906SToby Isaac }
41769371c9d4SSatish Balay } else {
4177d3bc4906SToby Isaac PetscInt cDof;
4178d3bc4906SToby Isaac
41799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSecRef, childId, &cDof));
4180d3bc4906SToby Isaac offsets[1] = cDof;
4181d3bc4906SToby Isaac }
4182d3bc4906SToby Isaac for (f = 0; f < lim; f++) {
4183d3bc4906SToby Isaac PetscScalar *childMat = &childrenMats[childId - pRefStart][f][0];
4184d3bc4906SToby Isaac PetscInt n = offsets[f + 1] - offsets[f];
4185e328ff09SToby Isaac PetscInt m = rowOffsets[f + 1] - rowOffsets[f];
4186d3bc4906SToby Isaac PetscInt i, j;
4187d3bc4906SToby Isaac const PetscScalar *colValues = &childValues[offsets[f]];
4188d3bc4906SToby Isaac
4189e328ff09SToby Isaac for (i = 0; i < m; i++) {
4190d3bc4906SToby Isaac PetscScalar val = 0.;
4191ad540459SPierre Jolivet for (j = 0; j < n; j++) val += childMat[n * i + j] * colValues[j];
4192e328ff09SToby Isaac parentValues[rowOffsets[f] + i] += val;
4193d3bc4906SToby Isaac }
4194d3bc4906SToby Isaac }
4195c921d74cSToby Isaac }
4196c921d74cSToby Isaac }
41979566063dSJacob Faibussowitsch if (contribute) PetscCall(VecSetValues(vecCoarse, dof, parentIndices, parentValues, INSERT_VALUES));
4198c921d74cSToby Isaac }
41999566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&multiRootSec));
42009566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&rootIndicesSec));
42019566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentIndices, parentValues));
42029566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceTreeRestoreChildrenMatrices_Injection(refTree, injRef, &childrenMats));
42039566063dSJacob Faibussowitsch PetscCall(PetscFree(rootValues));
42049566063dSJacob Faibussowitsch PetscCall(PetscFree3(offsets, offsetsCopy, rowOffsets));
42053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4206ebf164c7SToby Isaac }
4207ebf164c7SToby Isaac
4208ff1f73f7SToby Isaac /*@
4209ff1f73f7SToby Isaac DMPlexTransferVecTree - transfer a vector between two meshes that differ from each other by refinement/coarsening
4210ff1f73f7SToby Isaac that can be represented by a common reference tree used by both. This routine can be used for a combination of
4211ff1f73f7SToby Isaac coarsening and refinement at the same time.
4212ff1f73f7SToby Isaac
421320f4b53cSBarry Smith Collective
4214ff1f73f7SToby Isaac
4215ff1f73f7SToby Isaac Input Parameters:
4216a1cb98faSBarry Smith + dmIn - The `DMPLEX` mesh for the input vector
421720f4b53cSBarry Smith . dmOut - The second `DMPLEX` mesh
4218ff1f73f7SToby Isaac . vecIn - The input vector
421920f4b53cSBarry Smith . sfRefine - A star forest indicating points in the mesh `dmIn` (roots in the star forest) that are parents to points in
422020f4b53cSBarry Smith the mesh `dmOut` (leaves in the star forest), i.e. where `dmOut` is more refined than `dmIn`
422120f4b53cSBarry Smith . sfCoarsen - A star forest indicating points in the mesh `dmOut` (roots in the star forest) that are parents to points in
422220f4b53cSBarry Smith the mesh `dmIn` (leaves in the star forest), i.e. where `dmOut` is more coarsened than `dmIn`
422320f4b53cSBarry Smith . cidsRefine - The childIds of the points in `dmOut`. These childIds relate back to the reference tree: childid[j] = k implies
422420f4b53cSBarry Smith that mesh point j of `dmOut` was refined from a point in `dmIn` just as the mesh point k in the reference
422520f4b53cSBarry Smith tree was refined from its parent. childid[j] = -1 indicates that the point j in `dmOut` is exactly
422620f4b53cSBarry Smith equivalent to its root in `dmIn`, so no interpolation is necessary. childid[j] = -2 indicates that this
422720f4b53cSBarry Smith point j in `dmOut` is not a leaf of `sfRefine`.
422820f4b53cSBarry Smith . cidsCoarsen - The childIds of the points in `dmIn`. These childIds relate back to the reference tree: childid[j] = k implies
422920f4b53cSBarry Smith that mesh point j of dmIn coarsens to a point in `dmOut` just as the mesh point k in the reference
423020f4b53cSBarry Smith tree coarsens to its parent. childid[j] = -2 indicates that point j in `dmOut` is not a leaf in `sfCoarsen`.
423120f4b53cSBarry Smith . useBCs - `PETSC_TRUE` indicates that boundary values should be inserted into `vecIn` before transfer.
4232ff1f73f7SToby Isaac - time - Used if boundary values are time dependent.
4233ff1f73f7SToby Isaac
42342fe279fdSBarry Smith Output Parameter:
42358966356dSPierre Jolivet . vecOut - Using interpolation and injection operators calculated on the reference tree, the transferred
423620f4b53cSBarry Smith projection of `vecIn` from `dmIn` to `dmOut`. Note that any field discretized with a `PetscFV` finite volume
4237ff1f73f7SToby Isaac method that uses gradient reconstruction will use reconstructed gradients when interpolating from
4238ff1f73f7SToby Isaac coarse points to fine points.
4239ff1f73f7SToby Isaac
4240ff1f73f7SToby Isaac Level: developer
4241ff1f73f7SToby Isaac
42421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSF`, `Vec`, `PetscFV`, `DMPlexSetReferenceTree()`, `DMPlexGetReferenceTree()`, `PetscFVGetComputeGradients()`
4243ff1f73f7SToby Isaac @*/
DMPlexTransferVecTree(DM dmIn,Vec vecIn,DM dmOut,Vec vecOut,PetscSF sfRefine,PetscSF sfCoarsen,PetscInt * cidsRefine,PetscInt * cidsCoarsen,PetscBool useBCs,PetscReal time)4244d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTransferVecTree(DM dmIn, Vec vecIn, DM dmOut, Vec vecOut, PetscSF sfRefine, PetscSF sfCoarsen, PetscInt *cidsRefine, PetscInt *cidsCoarsen, PetscBool useBCs, PetscReal time)
4245d71ae5a4SJacob Faibussowitsch {
424638fc2455SToby Isaac PetscFunctionBegin;
42479566063dSJacob Faibussowitsch PetscCall(VecSet(vecOut, 0.0));
4248ff1f73f7SToby Isaac if (sfRefine) {
4249fbfa57b9SToby Isaac Vec vecInLocal;
42500eb7e1eaSToby Isaac DM dmGrad = NULL;
42510eb7e1eaSToby Isaac Vec faceGeom = NULL, cellGeom = NULL, grad = NULL;
4252fbfa57b9SToby Isaac
42539566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmIn, &vecInLocal));
42549566063dSJacob Faibussowitsch PetscCall(VecSet(vecInLocal, 0.0));
42550eb7e1eaSToby Isaac {
42560eb7e1eaSToby Isaac PetscInt numFields, i;
42570eb7e1eaSToby Isaac
42589566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dmIn, &numFields));
42590eb7e1eaSToby Isaac for (i = 0; i < numFields; i++) {
42600eb7e1eaSToby Isaac PetscObject obj;
42610eb7e1eaSToby Isaac PetscClassId classid;
42620eb7e1eaSToby Isaac
42639566063dSJacob Faibussowitsch PetscCall(DMGetField(dmIn, i, NULL, &obj));
42649566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &classid));
42650eb7e1eaSToby Isaac if (classid == PETSCFV_CLASSID) {
42669566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dmIn, (PetscFV)obj, &cellGeom, &faceGeom, &dmGrad));
42670eb7e1eaSToby Isaac break;
42680eb7e1eaSToby Isaac }
42690eb7e1eaSToby Isaac }
42700eb7e1eaSToby Isaac }
42711baa6e33SBarry Smith if (useBCs) PetscCall(DMPlexInsertBoundaryValues(dmIn, PETSC_TRUE, vecInLocal, time, faceGeom, cellGeom, NULL));
42729566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmIn, vecIn, INSERT_VALUES, vecInLocal));
42739566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmIn, vecIn, INSERT_VALUES, vecInLocal));
42740eb7e1eaSToby Isaac if (dmGrad) {
42759566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmGrad, &grad));
42769566063dSJacob Faibussowitsch PetscCall(DMPlexReconstructGradientsFVM(dmIn, vecInLocal, grad));
42770eb7e1eaSToby Isaac }
42789566063dSJacob Faibussowitsch PetscCall(DMPlexTransferVecTree_Interpolate(dmIn, vecInLocal, dmOut, vecOut, sfRefine, cidsRefine, grad, cellGeom));
42799566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmIn, &vecInLocal));
428048a46eb9SPierre Jolivet if (dmGrad) PetscCall(DMRestoreGlobalVector(dmGrad, &grad));
4281ebf164c7SToby Isaac }
42821baa6e33SBarry Smith if (sfCoarsen) PetscCall(DMPlexTransferVecTree_Inject(dmIn, vecIn, dmOut, vecOut, sfCoarsen, cidsCoarsen));
42839566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(vecOut));
42849566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(vecOut));
42853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
428638fc2455SToby Isaac }
4287