1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/
2da97024aSMatthew G. Knepley #include <petscsf.h>
3cb1e1211SMatthew G Knepley
48e3a2eefSMatthew G. Knepley #include <petscblaslapack.h>
5e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h>
6af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h>
7af0996ceSBarry Smith #include <petsc/private/petscfvimpl.h>
8a0845e3aSMatthew G. Knepley
95f0b18bfSMatthew G. Knepley PetscBool Clementcite = PETSC_FALSE;
105f0b18bfSMatthew G. Knepley const char ClementCitation[] = "@article{clement1975approximation,\n"
115f0b18bfSMatthew G. Knepley " title = {Approximation by finite element functions using local regularization},\n"
125f0b18bfSMatthew G. Knepley " author = {Philippe Cl{\\'e}ment},\n"
135f0b18bfSMatthew G. Knepley " journal = {Revue fran{\\c{c}}aise d'automatique, informatique, recherche op{\\'e}rationnelle. Analyse num{\\'e}rique},\n"
145f0b18bfSMatthew G. Knepley " volume = {9},\n"
155f0b18bfSMatthew G. Knepley " number = {R2},\n"
165f0b18bfSMatthew G. Knepley " pages = {77--84},\n"
175f0b18bfSMatthew G. Knepley " year = {1975}\n}\n";
185f0b18bfSMatthew G. Knepley
DMPlexConvertPlex(DM dm,DM * plex,PetscBool copy)19d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConvertPlex(DM dm, DM *plex, PetscBool copy)
20d71ae5a4SJacob Faibussowitsch {
212f856554SMatthew G. Knepley PetscBool isPlex;
222f856554SMatthew G. Knepley
232f856554SMatthew G. Knepley PetscFunctionBegin;
249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isPlex));
252f856554SMatthew G. Knepley if (isPlex) {
262f856554SMatthew G. Knepley *plex = dm;
279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm));
282f856554SMatthew G. Knepley } else {
299566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "dm_plex", (PetscObject *)plex));
302f856554SMatthew G. Knepley if (!*plex) {
319566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, plex));
329566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "dm_plex", (PetscObject)*plex));
33cbf8eb3cSStefano Zampini } else {
34cbf8eb3cSStefano Zampini PetscCall(PetscObjectReference((PetscObject)*plex));
35cbf8eb3cSStefano Zampini }
362f856554SMatthew G. Knepley if (copy) {
372f856554SMatthew G. Knepley DMSubDomainHookLink link;
389a2a23afSMatthew G. Knepley
39bb4b53efSMatthew G. Knepley PetscCall(DMCopyDS(dm, PETSC_DETERMINE, PETSC_DETERMINE, *plex));
409566063dSJacob Faibussowitsch PetscCall(DMCopyAuxiliaryVec(dm, *plex));
419a2a23afSMatthew G. Knepley /* Run the subdomain hook (this will copy the DMSNES/DMTS) */
422f856554SMatthew G. Knepley for (link = dm->subdomainhook; link; link = link->next) {
439566063dSJacob Faibussowitsch if (link->ddhook) PetscCall((*link->ddhook)(dm, *plex, link->ctx));
442f856554SMatthew G. Knepley }
452f856554SMatthew G. Knepley }
462f856554SMatthew G. Knepley }
473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
482f856554SMatthew G. Knepley }
492f856554SMatthew G. Knepley
PetscContainerCtxDestroy_PetscFEGeom(PetscCtxRt ctx)50*2a8381b2SBarry Smith static PetscErrorCode PetscContainerCtxDestroy_PetscFEGeom(PetscCtxRt ctx)
51d71ae5a4SJacob Faibussowitsch {
52*2a8381b2SBarry Smith PetscFEGeom *geom = *(PetscFEGeom **)ctx;
539b6f715bSMatthew G. Knepley
549b6f715bSMatthew G. Knepley PetscFunctionBegin;
559566063dSJacob Faibussowitsch PetscCall(PetscFEGeomDestroy(&geom));
563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
579b6f715bSMatthew G. Knepley }
589b6f715bSMatthew G. Knepley
DMPlexGetFEGeom(DMField coordField,IS pointIS,PetscQuadrature quad,PetscFEGeomMode mode,PetscFEGeom ** geom)59ac9d17c7SMatthew G. Knepley static PetscErrorCode DMPlexGetFEGeom(DMField coordField, IS pointIS, PetscQuadrature quad, PetscFEGeomMode mode, PetscFEGeom **geom)
60d71ae5a4SJacob Faibussowitsch {
619b6f715bSMatthew G. Knepley char composeStr[33] = {0};
629b6f715bSMatthew G. Knepley PetscObjectId id;
639b6f715bSMatthew G. Knepley PetscContainer container;
649b6f715bSMatthew G. Knepley
659b6f715bSMatthew G. Knepley PetscFunctionBegin;
669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetId((PetscObject)quad, &id));
6763a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(composeStr, 32, "DMPlexGetFEGeom_%" PetscInt64_FMT "\n", id));
689566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pointIS, composeStr, (PetscObject *)&container));
699b6f715bSMatthew G. Knepley if (container) {
70*2a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(container, geom));
719b6f715bSMatthew G. Knepley } else {
72ac9d17c7SMatthew G. Knepley PetscCall(DMFieldCreateFEGeom(coordField, pointIS, quad, mode, geom));
739566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
749566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(container, (void *)*geom));
7549abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(container, PetscContainerCtxDestroy_PetscFEGeom));
769566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pointIS, composeStr, (PetscObject)container));
779566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&container));
789b6f715bSMatthew G. Knepley }
793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
809b6f715bSMatthew G. Knepley }
819b6f715bSMatthew G. Knepley
DMPlexRestoreFEGeom(DMField coordField,IS pointIS,PetscQuadrature quad,PetscFEGeomMode mode,PetscFEGeom ** geom)82ac9d17c7SMatthew G. Knepley static PetscErrorCode DMPlexRestoreFEGeom(DMField coordField, IS pointIS, PetscQuadrature quad, PetscFEGeomMode mode, PetscFEGeom **geom)
83d71ae5a4SJacob Faibussowitsch {
849b6f715bSMatthew G. Knepley PetscFunctionBegin;
859b6f715bSMatthew G. Knepley *geom = NULL;
863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
879b6f715bSMatthew G. Knepley }
889b6f715bSMatthew G. Knepley
8946fa42a0SMatthew G. Knepley /*@
9046fa42a0SMatthew G. Knepley DMPlexGetScale - Get the scale for the specified fundamental unit
9146fa42a0SMatthew G. Knepley
9220f4b53cSBarry Smith Not Collective
9346fa42a0SMatthew G. Knepley
944165533cSJose E. Roman Input Parameters:
95a1cb98faSBarry Smith + dm - the `DM`
9646fa42a0SMatthew G. Knepley - unit - The SI unit
9746fa42a0SMatthew G. Knepley
984165533cSJose E. Roman Output Parameter:
9946fa42a0SMatthew G. Knepley . scale - The value used to scale all quantities with this unit
10046fa42a0SMatthew G. Knepley
10146fa42a0SMatthew G. Knepley Level: advanced
10246fa42a0SMatthew G. Knepley
1031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetScale()`, `PetscUnit`
10446fa42a0SMatthew G. Knepley @*/
DMPlexGetScale(DM dm,PetscUnit unit,PetscReal * scale)105d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale)
106d71ae5a4SJacob Faibussowitsch {
107cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
108cb1e1211SMatthew G Knepley
109cb1e1211SMatthew G Knepley PetscFunctionBegin;
110cb1e1211SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1114f572ea9SToby Isaac PetscAssertPointer(scale, 3);
112cb1e1211SMatthew G Knepley *scale = mesh->scale[unit];
1133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
114cb1e1211SMatthew G Knepley }
115cb1e1211SMatthew G Knepley
11646fa42a0SMatthew G. Knepley /*@
11746fa42a0SMatthew G. Knepley DMPlexSetScale - Set the scale for the specified fundamental unit
11846fa42a0SMatthew G. Knepley
11920f4b53cSBarry Smith Not Collective
12046fa42a0SMatthew G. Knepley
1214165533cSJose E. Roman Input Parameters:
122a1cb98faSBarry Smith + dm - the `DM`
12346fa42a0SMatthew G. Knepley . unit - The SI unit
12446fa42a0SMatthew G. Knepley - scale - The value used to scale all quantities with this unit
12546fa42a0SMatthew G. Knepley
12646fa42a0SMatthew G. Knepley Level: advanced
12746fa42a0SMatthew G. Knepley
1281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetScale()`, `PetscUnit`
12946fa42a0SMatthew G. Knepley @*/
DMPlexSetScale(DM dm,PetscUnit unit,PetscReal scale)130d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale)
131d71ae5a4SJacob Faibussowitsch {
132cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
133cb1e1211SMatthew G Knepley
134cb1e1211SMatthew G Knepley PetscFunctionBegin;
135cb1e1211SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
136cb1e1211SMatthew G Knepley mesh->scale[unit] = scale;
1373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
138cb1e1211SMatthew G Knepley }
139cb1e1211SMatthew G Knepley
DMPlexGetUseCeed_Plex(DM dm,PetscBool * useCeed)140d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetUseCeed_Plex(DM dm, PetscBool *useCeed)
141d2b2dc1eSMatthew G. Knepley {
142d2b2dc1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
143d2b2dc1eSMatthew G. Knepley
144d2b2dc1eSMatthew G. Knepley PetscFunctionBegin;
145d2b2dc1eSMatthew G. Knepley *useCeed = mesh->useCeed;
146d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
147d2b2dc1eSMatthew G. Knepley }
DMPlexSetUseCeed_Plex(DM dm,PetscBool useCeed)148d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexSetUseCeed_Plex(DM dm, PetscBool useCeed)
149d2b2dc1eSMatthew G. Knepley {
150d2b2dc1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
151d2b2dc1eSMatthew G. Knepley
152d2b2dc1eSMatthew G. Knepley PetscFunctionBegin;
153d2b2dc1eSMatthew G. Knepley mesh->useCeed = useCeed;
154d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
155d2b2dc1eSMatthew G. Knepley }
156d2b2dc1eSMatthew G. Knepley
157d2b2dc1eSMatthew G. Knepley /*@
158d2b2dc1eSMatthew G. Knepley DMPlexGetUseCeed - Get flag for using the LibCEED backend
159d2b2dc1eSMatthew G. Knepley
160d2b2dc1eSMatthew G. Knepley Not collective
161d2b2dc1eSMatthew G. Knepley
162d2b2dc1eSMatthew G. Knepley Input Parameter:
163d2b2dc1eSMatthew G. Knepley . dm - The `DM`
164d2b2dc1eSMatthew G. Knepley
165d2b2dc1eSMatthew G. Knepley Output Parameter:
166d2b2dc1eSMatthew G. Knepley . useCeed - The flag
167d2b2dc1eSMatthew G. Knepley
168d2b2dc1eSMatthew G. Knepley Level: intermediate
169d2b2dc1eSMatthew G. Knepley
170d2b2dc1eSMatthew G. Knepley .seealso: `DMPlexSetUseCeed()`
171d2b2dc1eSMatthew G. Knepley @*/
DMPlexGetUseCeed(DM dm,PetscBool * useCeed)172d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetUseCeed(DM dm, PetscBool *useCeed)
173d2b2dc1eSMatthew G. Knepley {
174d2b2dc1eSMatthew G. Knepley PetscFunctionBegin;
175d2b2dc1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
176d2b2dc1eSMatthew G. Knepley PetscAssertPointer(useCeed, 2);
177d2b2dc1eSMatthew G. Knepley *useCeed = PETSC_FALSE;
178d2b2dc1eSMatthew G. Knepley PetscTryMethod(dm, "DMPlexGetUseCeed_C", (DM, PetscBool *), (dm, useCeed));
179d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
180d2b2dc1eSMatthew G. Knepley }
181d2b2dc1eSMatthew G. Knepley
182d2b2dc1eSMatthew G. Knepley /*@
183d2b2dc1eSMatthew G. Knepley DMPlexSetUseCeed - Set flag for using the LibCEED backend
184d2b2dc1eSMatthew G. Knepley
185d2b2dc1eSMatthew G. Knepley Not collective
186d2b2dc1eSMatthew G. Knepley
187d2b2dc1eSMatthew G. Knepley Input Parameters:
188d2b2dc1eSMatthew G. Knepley + dm - The `DM`
189d2b2dc1eSMatthew G. Knepley - useCeed - The flag
190d2b2dc1eSMatthew G. Knepley
191d2b2dc1eSMatthew G. Knepley Level: intermediate
192d2b2dc1eSMatthew G. Knepley
193fe8e7dddSPierre Jolivet .seealso: `DMPlexGetUseCeed()`
194d2b2dc1eSMatthew G. Knepley @*/
DMPlexSetUseCeed(DM dm,PetscBool useCeed)195d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexSetUseCeed(DM dm, PetscBool useCeed)
196d2b2dc1eSMatthew G. Knepley {
197d2b2dc1eSMatthew G. Knepley PetscFunctionBegin;
198d2b2dc1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
199d2b2dc1eSMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, useCeed, 2);
200d2b2dc1eSMatthew G. Knepley PetscUseMethod(dm, "DMPlexSetUseCeed_C", (DM, PetscBool), (dm, useCeed));
201d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
202d2b2dc1eSMatthew G. Knepley }
203d2b2dc1eSMatthew G. Knepley
204e8e188d2SZach Atkins /*@
205e8e188d2SZach Atkins DMPlexGetUseMatClosurePermutation - Get flag for using a closure permutation for matrix insertion
206e8e188d2SZach Atkins
207e8e188d2SZach Atkins Not collective
208e8e188d2SZach Atkins
209e8e188d2SZach Atkins Input Parameter:
210e8e188d2SZach Atkins . dm - The `DM`
211e8e188d2SZach Atkins
212e8e188d2SZach Atkins Output Parameter:
213e8e188d2SZach Atkins . useClPerm - The flag
214e8e188d2SZach Atkins
215e8e188d2SZach Atkins Level: intermediate
216e8e188d2SZach Atkins
217e8e188d2SZach Atkins .seealso: `DMPlexSetUseMatClosurePermutation()`
218e8e188d2SZach Atkins @*/
DMPlexGetUseMatClosurePermutation(DM dm,PetscBool * useClPerm)219e8e188d2SZach Atkins PetscErrorCode DMPlexGetUseMatClosurePermutation(DM dm, PetscBool *useClPerm)
220e8e188d2SZach Atkins {
221e8e188d2SZach Atkins DM_Plex *mesh = (DM_Plex *)dm->data;
222e8e188d2SZach Atkins
223e8e188d2SZach Atkins PetscFunctionBegin;
224e8e188d2SZach Atkins PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
225e8e188d2SZach Atkins PetscAssertPointer(useClPerm, 2);
226e8e188d2SZach Atkins *useClPerm = mesh->useMatClPerm;
227e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS);
228e8e188d2SZach Atkins }
229e8e188d2SZach Atkins
230e8e188d2SZach Atkins /*@
231e8e188d2SZach Atkins DMPlexSetUseMatClosurePermutation - Set flag for using a closure permutation for matrix insertion
232e8e188d2SZach Atkins
233e8e188d2SZach Atkins Not collective
234e8e188d2SZach Atkins
235e8e188d2SZach Atkins Input Parameters:
236e8e188d2SZach Atkins + dm - The `DM`
237e8e188d2SZach Atkins - useClPerm - The flag
238e8e188d2SZach Atkins
239e8e188d2SZach Atkins Level: intermediate
240e8e188d2SZach Atkins
241e8e188d2SZach Atkins .seealso: `DMPlexGetUseMatClosurePermutation()`
242e8e188d2SZach Atkins @*/
DMPlexSetUseMatClosurePermutation(DM dm,PetscBool useClPerm)243e8e188d2SZach Atkins PetscErrorCode DMPlexSetUseMatClosurePermutation(DM dm, PetscBool useClPerm)
244e8e188d2SZach Atkins {
245e8e188d2SZach Atkins DM_Plex *mesh = (DM_Plex *)dm->data;
246e8e188d2SZach Atkins
247e8e188d2SZach Atkins PetscFunctionBegin;
248e8e188d2SZach Atkins PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
249e8e188d2SZach Atkins PetscValidLogicalCollectiveBool(dm, useClPerm, 2);
250e8e188d2SZach Atkins mesh->useMatClPerm = useClPerm;
251e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS);
252e8e188d2SZach Atkins }
253e8e188d2SZach Atkins
DMPlexProjectRigidBody_Private(PetscInt dim,PetscReal t,const PetscReal X[],PetscInt Nc,PetscScalar * mode,PetscCtx ctx)254*2a8381b2SBarry Smith static PetscErrorCode DMPlexProjectRigidBody_Private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nc, PetscScalar *mode, PetscCtx ctx)
255d71ae5a4SJacob Faibussowitsch {
2569371c9d4SSatish Balay const PetscInt eps[3][3][3] = {
2579371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}},
2589371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} },
2599371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} }
2609371c9d4SSatish Balay };
261026175e5SToby Isaac PetscInt *ctxInt = (PetscInt *)ctx;
262ad917190SMatthew G. Knepley PetscInt dim2 = ctxInt[0];
263026175e5SToby Isaac PetscInt d = ctxInt[1];
264026175e5SToby Isaac PetscInt i, j, k = dim > 2 ? d - dim : d;
265026175e5SToby Isaac
266ad917190SMatthew G. Knepley PetscFunctionBegin;
26763a3b9bcSJacob Faibussowitsch PetscCheck(dim == dim2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input dimension %" PetscInt_FMT " does not match context dimension %" PetscInt_FMT, dim, dim2);
268026175e5SToby Isaac for (i = 0; i < dim; i++) mode[i] = 0.;
269026175e5SToby Isaac if (d < dim) {
27012adca46SMatthew G. Knepley mode[d] = 1.; /* Translation along axis d */
271ad917190SMatthew G. Knepley } else {
272026175e5SToby Isaac for (i = 0; i < dim; i++) {
273ac530a7eSPierre Jolivet for (j = 0; j < dim; j++) mode[j] += eps[i][j][k] * X[i]; /* Rotation about axis d */
274026175e5SToby Isaac }
275026175e5SToby Isaac }
2763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
277026175e5SToby Isaac }
278026175e5SToby Isaac
279cc4e42d9SMartin Diehl /*@
28012adca46SMatthew G. Knepley DMPlexCreateRigidBody - For the default global section, create rigid body modes by function space interpolation
281cb1e1211SMatthew G Knepley
28220f4b53cSBarry Smith Collective
283cb1e1211SMatthew G Knepley
2844165533cSJose E. Roman Input Parameters:
285a1cb98faSBarry Smith + dm - the `DM`
28656cf3b9cSMatthew G. Knepley - field - The field number for the rigid body space, or 0 for the default
287cb1e1211SMatthew G Knepley
2884165533cSJose E. Roman Output Parameter:
289cb1e1211SMatthew G Knepley . sp - the null space
290cb1e1211SMatthew G Knepley
291cb1e1211SMatthew G Knepley Level: advanced
292cb1e1211SMatthew G Knepley
293a1cb98faSBarry Smith Note:
294a1cb98faSBarry Smith This is necessary to provide a suitable coarse space for algebraic multigrid
295a1cb98faSBarry Smith
2961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `MatNullSpaceCreate()`, `PCGAMG`
297cb1e1211SMatthew G Knepley @*/
DMPlexCreateRigidBody(DM dm,PetscInt field,MatNullSpace * sp)298d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscInt field, MatNullSpace *sp)
299d71ae5a4SJacob Faibussowitsch {
30056cf3b9cSMatthew G. Knepley PetscErrorCode (**func)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *);
301cb1e1211SMatthew G Knepley MPI_Comm comm;
302026175e5SToby Isaac Vec mode[6];
303026175e5SToby Isaac PetscSection section, globalSection;
30456cf3b9cSMatthew G. Knepley PetscInt dim, dimEmbed, Nf, n, m, mmin, d, i, j;
305db14aad5SMatthew G. Knepley void **ctxs;
306cb1e1211SMatthew G Knepley
307cb1e1211SMatthew G Knepley PetscFunctionBegin;
3089566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
3099566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
3109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
3119566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf));
31263a3b9bcSJacob Faibussowitsch PetscCheck(!Nf || !(field < 0 || field >= Nf), comm, PETSC_ERR_ARG_OUTOFRANGE, "Field %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", field, Nf);
31356cf3b9cSMatthew G. Knepley if (dim == 1 && Nf < 2) {
3149566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp));
3153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
316cb1e1211SMatthew G Knepley }
3179566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
3189566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, &globalSection));
3199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(globalSection, &n));
320db14aad5SMatthew G. Knepley PetscCall(PetscCalloc2(Nf, &func, Nf, &ctxs));
321b247467aSMatthew G. Knepley m = (dim * (dim + 1)) / 2;
3229566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, &mode[0]));
3239566063dSJacob Faibussowitsch PetscCall(VecSetType(mode[0], dm->vectype));
3249566063dSJacob Faibussowitsch PetscCall(VecSetSizes(mode[0], n, PETSC_DETERMINE));
3259566063dSJacob Faibussowitsch PetscCall(VecSetUp(mode[0]));
3269566063dSJacob Faibussowitsch PetscCall(VecGetSize(mode[0], &n));
327b247467aSMatthew G. Knepley mmin = PetscMin(m, n);
32856cf3b9cSMatthew G. Knepley func[field] = DMPlexProjectRigidBody_Private;
3299566063dSJacob Faibussowitsch for (i = 1; i < m; ++i) PetscCall(VecDuplicate(mode[0], &mode[i]));
330026175e5SToby Isaac for (d = 0; d < m; d++) {
331330485fdSToby Isaac PetscInt ctx[2];
332cb1e1211SMatthew G Knepley
333db14aad5SMatthew G. Knepley ctxs[field] = (void *)(&ctx[0]);
3349d8fbdeaSMatthew G. Knepley ctx[0] = dimEmbed;
335330485fdSToby Isaac ctx[1] = d;
336db14aad5SMatthew G. Knepley PetscCall(DMProjectFunction(dm, 0.0, func, ctxs, INSERT_VALUES, mode[d]));
337cb1e1211SMatthew G Knepley }
3383b2202bfSJacob Faibussowitsch /* Orthonormalize system */
339b50a2c0aSJacob Faibussowitsch for (i = 0; i < mmin; ++i) {
340b77f2eeeSJacob Faibussowitsch PetscScalar dots[6];
3419c9054dfSZach Atkins PetscReal norm;
342b50a2c0aSJacob Faibussowitsch
3439c9054dfSZach Atkins PetscCall(VecNormalize(mode[i], &norm));
3449c9054dfSZach Atkins if (PetscAbsReal(norm) <= PETSC_SQRT_MACHINE_EPSILON) {
3459c9054dfSZach Atkins PetscCall(VecDestroy(&mode[i]));
3469c9054dfSZach Atkins if (i < mmin - 1) {
3479c9054dfSZach Atkins for (j = i; j < mmin - 1; j++) mode[j] = mode[j + 1];
3489c9054dfSZach Atkins mode[mmin - 1] = NULL;
3499c9054dfSZach Atkins }
3509c9054dfSZach Atkins m--;
3519c9054dfSZach Atkins mmin--;
3529c9054dfSZach Atkins i--;
3539c9054dfSZach Atkins continue;
3549c9054dfSZach Atkins }
3559566063dSJacob Faibussowitsch PetscCall(VecMDot(mode[i], mmin - i - 1, mode + i + 1, dots + i + 1));
356b50a2c0aSJacob Faibussowitsch for (j = i + 1; j < mmin; ++j) {
357b77f2eeeSJacob Faibussowitsch dots[j] *= -1.0;
3589566063dSJacob Faibussowitsch PetscCall(VecAXPY(mode[j], dots[j], mode[i]));
359b50a2c0aSJacob Faibussowitsch }
360cb1e1211SMatthew G Knepley }
3619566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(comm, PETSC_FALSE, mmin, mode, sp));
3629566063dSJacob Faibussowitsch for (i = 0; i < m; ++i) PetscCall(VecDestroy(&mode[i]));
363db14aad5SMatthew G. Knepley PetscCall(PetscFree2(func, ctxs));
3643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
365cb1e1211SMatthew G Knepley }
366cb1e1211SMatthew G Knepley
367cc4e42d9SMartin Diehl /*@
36812adca46SMatthew G. Knepley DMPlexCreateRigidBodies - For the default global section, create rigid body modes by function space interpolation
36912adca46SMatthew G. Knepley
37020f4b53cSBarry Smith Collective
37112adca46SMatthew G. Knepley
3724165533cSJose E. Roman Input Parameters:
373a1cb98faSBarry Smith + dm - the `DM`
37412adca46SMatthew G. Knepley . nb - The number of bodies
375a1cb98faSBarry Smith . label - The `DMLabel` marking each domain
37612adca46SMatthew G. Knepley . nids - The number of ids per body
37712adca46SMatthew G. Knepley - ids - An array of the label ids in sequence for each domain
37812adca46SMatthew G. Knepley
3794165533cSJose E. Roman Output Parameter:
38012adca46SMatthew G. Knepley . sp - the null space
38112adca46SMatthew G. Knepley
38212adca46SMatthew G. Knepley Level: advanced
38312adca46SMatthew G. Knepley
384a1cb98faSBarry Smith Note:
385a1cb98faSBarry Smith This is necessary to provide a suitable coarse space for algebraic multigrid
386a1cb98faSBarry Smith
3871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `MatNullSpaceCreate()`
38812adca46SMatthew G. Knepley @*/
DMPlexCreateRigidBodies(DM dm,PetscInt nb,DMLabel label,const PetscInt nids[],const PetscInt ids[],MatNullSpace * sp)389d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRigidBodies(DM dm, PetscInt nb, DMLabel label, const PetscInt nids[], const PetscInt ids[], MatNullSpace *sp)
390d71ae5a4SJacob Faibussowitsch {
39112adca46SMatthew G. Knepley MPI_Comm comm;
39212adca46SMatthew G. Knepley PetscSection section, globalSection;
39312adca46SMatthew G. Knepley Vec *mode;
39412adca46SMatthew G. Knepley PetscScalar *dots;
39512adca46SMatthew G. Knepley PetscInt dim, dimEmbed, n, m, b, d, i, j, off;
39612adca46SMatthew G. Knepley
39712adca46SMatthew G. Knepley PetscFunctionBegin;
3989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
3999566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
4009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
4019566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
4029566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, &globalSection));
4039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(globalSection, &n));
40412adca46SMatthew G. Knepley m = nb * (dim * (dim + 1)) / 2;
4059566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(m, &mode, m, &dots));
4069566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, &mode[0]));
4079566063dSJacob Faibussowitsch PetscCall(VecSetSizes(mode[0], n, PETSC_DETERMINE));
4089566063dSJacob Faibussowitsch PetscCall(VecSetUp(mode[0]));
4099566063dSJacob Faibussowitsch for (i = 1; i < m; ++i) PetscCall(VecDuplicate(mode[0], &mode[i]));
41012adca46SMatthew G. Knepley for (b = 0, off = 0; b < nb; ++b) {
41112adca46SMatthew G. Knepley for (d = 0; d < m / nb; ++d) {
41212adca46SMatthew G. Knepley PetscInt ctx[2];
41312adca46SMatthew G. Knepley PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *) = DMPlexProjectRigidBody_Private;
41412adca46SMatthew G. Knepley void *voidctx = (void *)(&ctx[0]);
41512adca46SMatthew G. Knepley
41612adca46SMatthew G. Knepley ctx[0] = dimEmbed;
41712adca46SMatthew G. Knepley ctx[1] = d;
4189566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLabel(dm, 0.0, label, nids[b], &ids[off], 0, NULL, &func, &voidctx, INSERT_VALUES, mode[d]));
41912adca46SMatthew G. Knepley off += nids[b];
42012adca46SMatthew G. Knepley }
42112adca46SMatthew G. Knepley }
4223b2202bfSJacob Faibussowitsch /* Orthonormalize system */
423606c1a1cSJacob Faibussowitsch for (i = 0; i < m; ++i) {
424b77f2eeeSJacob Faibussowitsch PetscScalar dots[6];
4255a0e29b9SJacob Faibussowitsch
4269566063dSJacob Faibussowitsch PetscCall(VecNormalize(mode[i], NULL));
4279566063dSJacob Faibussowitsch PetscCall(VecMDot(mode[i], m - i - 1, mode + i + 1, dots + i + 1));
4285a0e29b9SJacob Faibussowitsch for (j = i + 1; j < m; ++j) {
429b77f2eeeSJacob Faibussowitsch dots[j] *= -1.0;
4309566063dSJacob Faibussowitsch PetscCall(VecAXPY(mode[j], dots[j], mode[i]));
4315a0e29b9SJacob Faibussowitsch }
43212adca46SMatthew G. Knepley }
4339566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp));
4349566063dSJacob Faibussowitsch for (i = 0; i < m; ++i) PetscCall(VecDestroy(&mode[i]));
4359566063dSJacob Faibussowitsch PetscCall(PetscFree2(mode, dots));
4363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43712adca46SMatthew G. Knepley }
43812adca46SMatthew G. Knepley
439b29cfa1cSToby Isaac /*@
440b29cfa1cSToby Isaac DMPlexSetMaxProjectionHeight - In DMPlexProjectXXXLocal() functions, the projected values of a basis function's dofs
441b29cfa1cSToby Isaac are computed by associating the basis function with one of the mesh points in its transitively-closed support, and
442a4e35b19SJacob Faibussowitsch evaluating the dual space basis of that point.
443b29cfa1cSToby Isaac
444b29cfa1cSToby Isaac Input Parameters:
445a1cb98faSBarry Smith + dm - the `DMPLEX` object
446b29cfa1cSToby Isaac - height - the maximum projection height >= 0
447b29cfa1cSToby Isaac
448b29cfa1cSToby Isaac Level: advanced
449b29cfa1cSToby Isaac
450a4e35b19SJacob Faibussowitsch Notes:
451a4e35b19SJacob Faibussowitsch A basis function is associated with the point in its transitively-closed support whose mesh
452a4e35b19SJacob Faibussowitsch height is highest (w.r.t. DAG height), but not greater than the maximum projection height,
453a4e35b19SJacob Faibussowitsch which is set with this function. By default, the maximum projection height is zero, which
454a4e35b19SJacob Faibussowitsch means that only mesh cells are used to project basis functions. A height of one, for
455a4e35b19SJacob Faibussowitsch example, evaluates a cell-interior basis functions using its cells dual space basis, but all
456a4e35b19SJacob Faibussowitsch other basis functions with the dual space basis of a face.
457a4e35b19SJacob Faibussowitsch
4581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMaxProjectionHeight()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabelLocal()`
459b29cfa1cSToby Isaac @*/
DMPlexSetMaxProjectionHeight(DM dm,PetscInt height)460d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetMaxProjectionHeight(DM dm, PetscInt height)
461d71ae5a4SJacob Faibussowitsch {
462b29cfa1cSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data;
463b29cfa1cSToby Isaac
464b29cfa1cSToby Isaac PetscFunctionBegin;
465b29cfa1cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
466b29cfa1cSToby Isaac plex->maxProjectionHeight = height;
4673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
468b29cfa1cSToby Isaac }
469b29cfa1cSToby Isaac
470b29cfa1cSToby Isaac /*@
471b29cfa1cSToby Isaac DMPlexGetMaxProjectionHeight - Get the maximum height (w.r.t. DAG) of mesh points used to evaluate dual bases in
472b29cfa1cSToby Isaac DMPlexProjectXXXLocal() functions.
473b29cfa1cSToby Isaac
4742fe279fdSBarry Smith Input Parameter:
475a1cb98faSBarry Smith . dm - the `DMPLEX` object
476b29cfa1cSToby Isaac
4772fe279fdSBarry Smith Output Parameter:
478b29cfa1cSToby Isaac . height - the maximum projection height
479b29cfa1cSToby Isaac
480b29cfa1cSToby Isaac Level: intermediate
481b29cfa1cSToby Isaac
4821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetMaxProjectionHeight()`, `DMProjectFunctionLocal()`, `DMProjectFunctionLabelLocal()`
483b29cfa1cSToby Isaac @*/
DMPlexGetMaxProjectionHeight(DM dm,PetscInt * height)484d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxProjectionHeight(DM dm, PetscInt *height)
485d71ae5a4SJacob Faibussowitsch {
486b29cfa1cSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data;
487b29cfa1cSToby Isaac
488b29cfa1cSToby Isaac PetscFunctionBegin;
489b29cfa1cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
490b29cfa1cSToby Isaac *height = plex->maxProjectionHeight;
4913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
492b29cfa1cSToby Isaac }
493b29cfa1cSToby Isaac
494ca3d3a14SMatthew G. Knepley typedef struct {
495ca3d3a14SMatthew G. Knepley PetscReal alpha; /* The first Euler angle, and in 2D the only one */
496ca3d3a14SMatthew G. Knepley PetscReal beta; /* The second Euler angle */
497ca3d3a14SMatthew G. Knepley PetscReal gamma; /* The third Euler angle */
498ca3d3a14SMatthew G. Knepley PetscInt dim; /* The dimension of R */
499ca3d3a14SMatthew G. Knepley PetscScalar *R; /* The rotation matrix, transforming a vector in the local basis to the global basis */
500ca3d3a14SMatthew G. Knepley PetscScalar *RT; /* The transposed rotation matrix, transforming a vector in the global basis to the local basis */
501ca3d3a14SMatthew G. Knepley } RotCtx;
502ca3d3a14SMatthew G. Knepley
503ca3d3a14SMatthew G. Knepley /*
504ca3d3a14SMatthew G. Knepley Note: Following https://en.wikipedia.org/wiki/Euler_angles, we will specify Euler angles by extrinsic rotations, meaning that
505ca3d3a14SMatthew G. Knepley we rotate with respect to a fixed initial coordinate system, the local basis (x-y-z). The global basis (X-Y-Z) is reached as follows:
506ca3d3a14SMatthew G. Knepley $ The XYZ system rotates about the z axis by alpha. The X axis is now at angle alpha with respect to the x axis.
507ca3d3a14SMatthew G. Knepley $ The XYZ system rotates again about the x axis by beta. The Z axis is now at angle beta with respect to the z axis.
508ca3d3a14SMatthew G. Knepley $ The XYZ system rotates a third time about the z axis by gamma.
509ca3d3a14SMatthew G. Knepley */
DMPlexBasisTransformSetUp_Rotation_Internal(DM dm,PetscCtx ctx)510*2a8381b2SBarry Smith static PetscErrorCode DMPlexBasisTransformSetUp_Rotation_Internal(DM dm, PetscCtx ctx)
511d71ae5a4SJacob Faibussowitsch {
512ca3d3a14SMatthew G. Knepley RotCtx *rc = (RotCtx *)ctx;
513ca3d3a14SMatthew G. Knepley PetscInt dim = rc->dim;
514ca3d3a14SMatthew G. Knepley PetscReal c1, s1, c2, s2, c3, s3;
515ca3d3a14SMatthew G. Knepley
516ca3d3a14SMatthew G. Knepley PetscFunctionBegin;
5179566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(dim), &rc->R, PetscSqr(dim), &rc->RT));
518ca3d3a14SMatthew G. Knepley switch (dim) {
519ca3d3a14SMatthew G. Knepley case 2:
5209371c9d4SSatish Balay c1 = PetscCosReal(rc->alpha);
5219371c9d4SSatish Balay s1 = PetscSinReal(rc->alpha);
5229371c9d4SSatish Balay rc->R[0] = c1;
5239371c9d4SSatish Balay rc->R[1] = s1;
5249371c9d4SSatish Balay rc->R[2] = -s1;
5259371c9d4SSatish Balay rc->R[3] = c1;
5269566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(rc->RT, rc->R, PetscSqr(dim)));
527b458e8f1SJose E. Roman DMPlex_Transpose2D_Internal(rc->RT);
528ca3d3a14SMatthew G. Knepley break;
529ca3d3a14SMatthew G. Knepley case 3:
5309371c9d4SSatish Balay c1 = PetscCosReal(rc->alpha);
5319371c9d4SSatish Balay s1 = PetscSinReal(rc->alpha);
5329371c9d4SSatish Balay c2 = PetscCosReal(rc->beta);
5339371c9d4SSatish Balay s2 = PetscSinReal(rc->beta);
5349371c9d4SSatish Balay c3 = PetscCosReal(rc->gamma);
5359371c9d4SSatish Balay s3 = PetscSinReal(rc->gamma);
5369371c9d4SSatish Balay rc->R[0] = c1 * c3 - c2 * s1 * s3;
5379371c9d4SSatish Balay rc->R[1] = c3 * s1 + c1 * c2 * s3;
5389371c9d4SSatish Balay rc->R[2] = s2 * s3;
5399371c9d4SSatish Balay rc->R[3] = -c1 * s3 - c2 * c3 * s1;
5409371c9d4SSatish Balay rc->R[4] = c1 * c2 * c3 - s1 * s3;
5419371c9d4SSatish Balay rc->R[5] = c3 * s2;
5429371c9d4SSatish Balay rc->R[6] = s1 * s2;
5439371c9d4SSatish Balay rc->R[7] = -c1 * s2;
5449371c9d4SSatish Balay rc->R[8] = c2;
5459566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(rc->RT, rc->R, PetscSqr(dim)));
546b458e8f1SJose E. Roman DMPlex_Transpose3D_Internal(rc->RT);
547ca3d3a14SMatthew G. Knepley break;
548d71ae5a4SJacob Faibussowitsch default:
549d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " not supported", dim);
550ca3d3a14SMatthew G. Knepley }
5513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
552ca3d3a14SMatthew G. Knepley }
553ca3d3a14SMatthew G. Knepley
DMPlexBasisTransformDestroy_Rotation_Internal(DM dm,PetscCtx ctx)554*2a8381b2SBarry Smith static PetscErrorCode DMPlexBasisTransformDestroy_Rotation_Internal(DM dm, PetscCtx ctx)
555d71ae5a4SJacob Faibussowitsch {
556ca3d3a14SMatthew G. Knepley RotCtx *rc = (RotCtx *)ctx;
557ca3d3a14SMatthew G. Knepley
558ca3d3a14SMatthew G. Knepley PetscFunctionBegin;
5599566063dSJacob Faibussowitsch PetscCall(PetscFree2(rc->R, rc->RT));
5609566063dSJacob Faibussowitsch PetscCall(PetscFree(rc));
5613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
562ca3d3a14SMatthew G. Knepley }
563ca3d3a14SMatthew G. Knepley
DMPlexBasisTransformGetMatrix_Rotation_Internal(DM dm,const PetscReal x[],PetscBool l2g,const PetscScalar ** A,PetscCtx ctx)564*2a8381b2SBarry Smith static PetscErrorCode DMPlexBasisTransformGetMatrix_Rotation_Internal(DM dm, const PetscReal x[], PetscBool l2g, const PetscScalar **A, PetscCtx ctx)
565d71ae5a4SJacob Faibussowitsch {
566ca3d3a14SMatthew G. Knepley RotCtx *rc = (RotCtx *)ctx;
567ca3d3a14SMatthew G. Knepley
568ca3d3a14SMatthew G. Knepley PetscFunctionBeginHot;
5694f572ea9SToby Isaac PetscAssertPointer(ctx, 5);
5709371c9d4SSatish Balay if (l2g) {
5719371c9d4SSatish Balay *A = rc->R;
5729371c9d4SSatish Balay } else {
5739371c9d4SSatish Balay *A = rc->RT;
5749371c9d4SSatish Balay }
5753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
576ca3d3a14SMatthew G. Knepley }
577ca3d3a14SMatthew G. Knepley
DMPlexBasisTransformApplyReal_Internal(DM dm,const PetscReal x[],PetscBool l2g,PetscInt dim,const PetscReal * y,PetscReal * z,PetscCtx ctx)578*2a8381b2SBarry Smith PetscErrorCode DMPlexBasisTransformApplyReal_Internal(DM dm, const PetscReal x[], PetscBool l2g, PetscInt dim, const PetscReal *y, PetscReal *z, PetscCtx ctx)
579d71ae5a4SJacob Faibussowitsch {
580ec277c0fSMatthew G. Knepley PetscFunctionBegin;
581ab6a9622SMatthew G. Knepley #if defined(PETSC_USE_COMPLEX)
582ab6a9622SMatthew G. Knepley switch (dim) {
5839371c9d4SSatish Balay case 2: {
58427104ee2SJacob Faibussowitsch PetscScalar yt[2] = {y[0], y[1]}, zt[2] = {0.0, 0.0};
585ab6a9622SMatthew G. Knepley
5869566063dSJacob Faibussowitsch PetscCall(DMPlexBasisTransformApply_Internal(dm, x, l2g, dim, yt, zt, ctx));
5879371c9d4SSatish Balay z[0] = PetscRealPart(zt[0]);
5889371c9d4SSatish Balay z[1] = PetscRealPart(zt[1]);
5899371c9d4SSatish Balay } break;
5909371c9d4SSatish Balay case 3: {
59127104ee2SJacob Faibussowitsch PetscScalar yt[3] = {y[0], y[1], y[2]}, zt[3] = {0.0, 0.0, 0.0};
592ab6a9622SMatthew G. Knepley
5939566063dSJacob Faibussowitsch PetscCall(DMPlexBasisTransformApply_Internal(dm, x, l2g, dim, yt, zt, ctx));
5949371c9d4SSatish Balay z[0] = PetscRealPart(zt[0]);
5959371c9d4SSatish Balay z[1] = PetscRealPart(zt[1]);
5969371c9d4SSatish Balay z[2] = PetscRealPart(zt[2]);
5979371c9d4SSatish Balay } break;
598ab6a9622SMatthew G. Knepley }
599ab6a9622SMatthew G. Knepley #else
6009566063dSJacob Faibussowitsch PetscCall(DMPlexBasisTransformApply_Internal(dm, x, l2g, dim, y, z, ctx));
601ab6a9622SMatthew G. Knepley #endif
6023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
603ab6a9622SMatthew G. Knepley }
604ab6a9622SMatthew G. Knepley
DMPlexBasisTransformApply_Internal(DM dm,const PetscReal x[],PetscBool l2g,PetscInt dim,const PetscScalar * y,PetscScalar * z,PetscCtx ctx)605*2a8381b2SBarry Smith PetscErrorCode DMPlexBasisTransformApply_Internal(DM dm, const PetscReal x[], PetscBool l2g, PetscInt dim, const PetscScalar *y, PetscScalar *z, PetscCtx ctx)
606d71ae5a4SJacob Faibussowitsch {
607ca3d3a14SMatthew G. Knepley const PetscScalar *A;
608ca3d3a14SMatthew G. Knepley
609ca3d3a14SMatthew G. Knepley PetscFunctionBeginHot;
6109566063dSJacob Faibussowitsch PetscCall((*dm->transformGetMatrix)(dm, x, l2g, &A, ctx));
611ca3d3a14SMatthew G. Knepley switch (dim) {
612d71ae5a4SJacob Faibussowitsch case 2:
613d71ae5a4SJacob Faibussowitsch DMPlex_Mult2D_Internal(A, 1, y, z);
614d71ae5a4SJacob Faibussowitsch break;
615d71ae5a4SJacob Faibussowitsch case 3:
616d71ae5a4SJacob Faibussowitsch DMPlex_Mult3D_Internal(A, 1, y, z);
617d71ae5a4SJacob Faibussowitsch break;
618ca3d3a14SMatthew G. Knepley }
6193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
620ca3d3a14SMatthew G. Knepley }
621ca3d3a14SMatthew G. Knepley
DMPlexBasisTransformField_Internal(DM dm,DM tdm,Vec tv,PetscInt p,PetscInt f,PetscBool l2g,PetscScalar * a)622d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexBasisTransformField_Internal(DM dm, DM tdm, Vec tv, PetscInt p, PetscInt f, PetscBool l2g, PetscScalar *a)
623d71ae5a4SJacob Faibussowitsch {
624ca3d3a14SMatthew G. Knepley PetscSection ts;
625ca3d3a14SMatthew G. Knepley const PetscScalar *ta, *tva;
626ca3d3a14SMatthew G. Knepley PetscInt dof;
627ca3d3a14SMatthew G. Knepley
628ca3d3a14SMatthew G. Knepley PetscFunctionBeginHot;
6299566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(tdm, &ts));
6309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(ts, p, f, &dof));
6319566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tv, &ta));
6329566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRead(tdm, p, f, ta, &tva));
633ca3d3a14SMatthew G. Knepley if (l2g) {
634ca3d3a14SMatthew G. Knepley switch (dof) {
635d71ae5a4SJacob Faibussowitsch case 4:
636d71ae5a4SJacob Faibussowitsch DMPlex_Mult2D_Internal(tva, 1, a, a);
637d71ae5a4SJacob Faibussowitsch break;
638d71ae5a4SJacob Faibussowitsch case 9:
639d71ae5a4SJacob Faibussowitsch DMPlex_Mult3D_Internal(tva, 1, a, a);
640d71ae5a4SJacob Faibussowitsch break;
641ca3d3a14SMatthew G. Knepley }
642ca3d3a14SMatthew G. Knepley } else {
643ca3d3a14SMatthew G. Knepley switch (dof) {
644d71ae5a4SJacob Faibussowitsch case 4:
645d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose2D_Internal(tva, 1, a, a);
646d71ae5a4SJacob Faibussowitsch break;
647d71ae5a4SJacob Faibussowitsch case 9:
648d71ae5a4SJacob Faibussowitsch DMPlex_MultTranspose3D_Internal(tva, 1, a, a);
649d71ae5a4SJacob Faibussowitsch break;
650ca3d3a14SMatthew G. Knepley }
651ca3d3a14SMatthew G. Knepley }
6529566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tv, &ta));
6533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
654ca3d3a14SMatthew G. Knepley }
655ca3d3a14SMatthew G. Knepley
DMPlexBasisTransformFieldTensor_Internal(DM dm,DM tdm,Vec tv,PetscInt pf,PetscInt f,PetscInt pg,PetscInt g,PetscBool l2g,PetscInt lda,PetscScalar * a)656d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexBasisTransformFieldTensor_Internal(DM dm, DM tdm, Vec tv, PetscInt pf, PetscInt f, PetscInt pg, PetscInt g, PetscBool l2g, PetscInt lda, PetscScalar *a)
657d71ae5a4SJacob Faibussowitsch {
658ca3d3a14SMatthew G. Knepley PetscSection s, ts;
659ca3d3a14SMatthew G. Knepley const PetscScalar *ta, *tvaf, *tvag;
660ca3d3a14SMatthew G. Knepley PetscInt fdof, gdof, fpdof, gpdof;
661ca3d3a14SMatthew G. Knepley
662ca3d3a14SMatthew G. Knepley PetscFunctionBeginHot;
6639566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s));
6649566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(tdm, &ts));
6659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(s, pf, f, &fpdof));
6669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(s, pg, g, &gpdof));
6679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(ts, pf, f, &fdof));
6689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(ts, pg, g, &gdof));
6699566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tv, &ta));
6709566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRead(tdm, pf, f, ta, &tvaf));
6719566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRead(tdm, pg, g, ta, &tvag));
672ca3d3a14SMatthew G. Knepley if (l2g) {
673ca3d3a14SMatthew G. Knepley switch (fdof) {
674d71ae5a4SJacob Faibussowitsch case 4:
675d71ae5a4SJacob Faibussowitsch DMPlex_MatMult2D_Internal(tvaf, gpdof, lda, a, a);
676d71ae5a4SJacob Faibussowitsch break;
677d71ae5a4SJacob Faibussowitsch case 9:
678d71ae5a4SJacob Faibussowitsch DMPlex_MatMult3D_Internal(tvaf, gpdof, lda, a, a);
679d71ae5a4SJacob Faibussowitsch break;
680ca3d3a14SMatthew G. Knepley }
681ca3d3a14SMatthew G. Knepley switch (gdof) {
682d71ae5a4SJacob Faibussowitsch case 4:
683d71ae5a4SJacob Faibussowitsch DMPlex_MatMultTransposeLeft2D_Internal(tvag, fpdof, lda, a, a);
684d71ae5a4SJacob Faibussowitsch break;
685d71ae5a4SJacob Faibussowitsch case 9:
686d71ae5a4SJacob Faibussowitsch DMPlex_MatMultTransposeLeft3D_Internal(tvag, fpdof, lda, a, a);
687d71ae5a4SJacob Faibussowitsch break;
688ca3d3a14SMatthew G. Knepley }
689ca3d3a14SMatthew G. Knepley } else {
690ca3d3a14SMatthew G. Knepley switch (fdof) {
691d71ae5a4SJacob Faibussowitsch case 4:
692d71ae5a4SJacob Faibussowitsch DMPlex_MatMultTranspose2D_Internal(tvaf, gpdof, lda, a, a);
693d71ae5a4SJacob Faibussowitsch break;
694d71ae5a4SJacob Faibussowitsch case 9:
695d71ae5a4SJacob Faibussowitsch DMPlex_MatMultTranspose3D_Internal(tvaf, gpdof, lda, a, a);
696d71ae5a4SJacob Faibussowitsch break;
697ca3d3a14SMatthew G. Knepley }
698ca3d3a14SMatthew G. Knepley switch (gdof) {
699d71ae5a4SJacob Faibussowitsch case 4:
700d71ae5a4SJacob Faibussowitsch DMPlex_MatMultLeft2D_Internal(tvag, fpdof, lda, a, a);
701d71ae5a4SJacob Faibussowitsch break;
702d71ae5a4SJacob Faibussowitsch case 9:
703d71ae5a4SJacob Faibussowitsch DMPlex_MatMultLeft3D_Internal(tvag, fpdof, lda, a, a);
704d71ae5a4SJacob Faibussowitsch break;
705ca3d3a14SMatthew G. Knepley }
706ca3d3a14SMatthew G. Knepley }
7079566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tv, &ta));
7083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
709ca3d3a14SMatthew G. Knepley }
710ca3d3a14SMatthew G. Knepley
DMPlexBasisTransformPoint_Internal(DM dm,DM tdm,Vec tv,PetscInt p,PetscBool fieldActive[],PetscBool l2g,PetscScalar * a)711d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBasisTransformPoint_Internal(DM dm, DM tdm, Vec tv, PetscInt p, PetscBool fieldActive[], PetscBool l2g, PetscScalar *a)
712d71ae5a4SJacob Faibussowitsch {
713ca3d3a14SMatthew G. Knepley PetscSection s;
714ca3d3a14SMatthew G. Knepley PetscSection clSection;
715ca3d3a14SMatthew G. Knepley IS clPoints;
716ca3d3a14SMatthew G. Knepley const PetscInt *clp;
717ca3d3a14SMatthew G. Knepley PetscInt *points = NULL;
718ca3d3a14SMatthew G. Knepley PetscInt Nf, f, Np, cp, dof, d = 0;
719ca3d3a14SMatthew G. Knepley
720ca3d3a14SMatthew G. Knepley PetscFunctionBegin;
7219566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s));
7229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf));
72307218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, s, p, 0, &Np, &points, &clSection, &clPoints, &clp));
724ca3d3a14SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
725ca3d3a14SMatthew G. Knepley for (cp = 0; cp < Np * 2; cp += 2) {
7269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(s, points[cp], f, &dof));
727ca3d3a14SMatthew G. Knepley if (!dof) continue;
7289566063dSJacob Faibussowitsch if (fieldActive[f]) PetscCall(DMPlexBasisTransformField_Internal(dm, tdm, tv, points[cp], f, l2g, &a[d]));
729ca3d3a14SMatthew G. Knepley d += dof;
730ca3d3a14SMatthew G. Knepley }
731ca3d3a14SMatthew G. Knepley }
7329566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, s, p, &Np, &points, &clSection, &clPoints, &clp));
7333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
734ca3d3a14SMatthew G. Knepley }
735ca3d3a14SMatthew G. Knepley
DMPlexBasisTransformPointTensor_Internal(DM dm,DM tdm,Vec tv,PetscInt p,PetscBool l2g,PetscInt lda,PetscScalar * a)736d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBasisTransformPointTensor_Internal(DM dm, DM tdm, Vec tv, PetscInt p, PetscBool l2g, PetscInt lda, PetscScalar *a)
737d71ae5a4SJacob Faibussowitsch {
738ca3d3a14SMatthew G. Knepley PetscSection s;
739ca3d3a14SMatthew G. Knepley PetscSection clSection;
740ca3d3a14SMatthew G. Knepley IS clPoints;
741ca3d3a14SMatthew G. Knepley const PetscInt *clp;
742ca3d3a14SMatthew G. Knepley PetscInt *points = NULL;
7438bdb3c71SMatthew G. Knepley PetscInt Nf, f, g, Np, cpf, cpg, fdof, gdof, r, c = 0;
744ca3d3a14SMatthew G. Knepley
745ca3d3a14SMatthew G. Knepley PetscFunctionBegin;
7469566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s));
7479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf));
74807218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, s, p, 0, &Np, &points, &clSection, &clPoints, &clp));
749ca3d3a14SMatthew G. Knepley for (f = 0, r = 0; f < Nf; ++f) {
750ca3d3a14SMatthew G. Knepley for (cpf = 0; cpf < Np * 2; cpf += 2) {
7519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(s, points[cpf], f, &fdof));
752ca3d3a14SMatthew G. Knepley for (g = 0, c = 0; g < Nf; ++g) {
753ca3d3a14SMatthew G. Knepley for (cpg = 0; cpg < Np * 2; cpg += 2) {
7549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(s, points[cpg], g, &gdof));
7559566063dSJacob Faibussowitsch PetscCall(DMPlexBasisTransformFieldTensor_Internal(dm, tdm, tv, points[cpf], f, points[cpg], g, l2g, lda, &a[r * lda + c]));
756ca3d3a14SMatthew G. Knepley c += gdof;
757ca3d3a14SMatthew G. Knepley }
758ca3d3a14SMatthew G. Knepley }
75963a3b9bcSJacob Faibussowitsch PetscCheck(c == lda, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of columns %" PetscInt_FMT " should be %" PetscInt_FMT, c, lda);
760ca3d3a14SMatthew G. Knepley r += fdof;
761ca3d3a14SMatthew G. Knepley }
762ca3d3a14SMatthew G. Knepley }
76363a3b9bcSJacob Faibussowitsch PetscCheck(r == lda, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of rows %" PetscInt_FMT " should be %" PetscInt_FMT, c, lda);
7649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, s, p, &Np, &points, &clSection, &clPoints, &clp));
7653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
766ca3d3a14SMatthew G. Knepley }
767ca3d3a14SMatthew G. Knepley
DMPlexBasisTransform_Internal(DM dm,Vec lv,PetscBool l2g)768d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexBasisTransform_Internal(DM dm, Vec lv, PetscBool l2g)
769d71ae5a4SJacob Faibussowitsch {
770ca3d3a14SMatthew G. Knepley DM tdm;
771ca3d3a14SMatthew G. Knepley Vec tv;
772ca3d3a14SMatthew G. Knepley PetscSection ts, s;
773ca3d3a14SMatthew G. Knepley const PetscScalar *ta;
774ca3d3a14SMatthew G. Knepley PetscScalar *a, *va;
775ca3d3a14SMatthew G. Knepley PetscInt pStart, pEnd, p, Nf, f;
776ca3d3a14SMatthew G. Knepley
777ca3d3a14SMatthew G. Knepley PetscFunctionBegin;
7789566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformDM_Internal(dm, &tdm));
7799566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
7809566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(tdm, &ts));
7819566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s));
7829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
7839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf));
7849566063dSJacob Faibussowitsch PetscCall(VecGetArray(lv, &a));
7859566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tv, &ta));
786ca3d3a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) {
787ca3d3a14SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
7889566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRef(dm, p, f, a, &va));
7899566063dSJacob Faibussowitsch PetscCall(DMPlexBasisTransformField_Internal(dm, tdm, tv, p, f, l2g, va));
790ca3d3a14SMatthew G. Knepley }
791ca3d3a14SMatthew G. Knepley }
7929566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(lv, &a));
7939566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tv, &ta));
7943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
795ca3d3a14SMatthew G. Knepley }
796ca3d3a14SMatthew G. Knepley
797ca3d3a14SMatthew G. Knepley /*@
798ca3d3a14SMatthew G. Knepley DMPlexGlobalToLocalBasis - Transform the values in the given local vector from the global basis to the local basis
799ca3d3a14SMatthew G. Knepley
800ca3d3a14SMatthew G. Knepley Input Parameters:
801a1cb98faSBarry Smith + dm - The `DM`
802ca3d3a14SMatthew G. Knepley - lv - A local vector with values in the global basis
803ca3d3a14SMatthew G. Knepley
8042fe279fdSBarry Smith Output Parameter:
805ca3d3a14SMatthew G. Knepley . lv - A local vector with values in the local basis
806ca3d3a14SMatthew G. Knepley
807ca3d3a14SMatthew G. Knepley Level: developer
808ca3d3a14SMatthew G. Knepley
809a1cb98faSBarry Smith Note:
810a1cb98faSBarry Smith This method is only intended to be called inside `DMGlobalToLocal()`. It is unlikely that a user will have a local vector full of coefficients for the global basis unless they are reimplementing GlobalToLocal.
811a1cb98faSBarry Smith
8121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexLocalToGlobalBasis()`, `DMGetLocalSection()`, `DMPlexCreateBasisRotation()`
813ca3d3a14SMatthew G. Knepley @*/
DMPlexGlobalToLocalBasis(DM dm,Vec lv)814d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalToLocalBasis(DM dm, Vec lv)
815d71ae5a4SJacob Faibussowitsch {
816ca3d3a14SMatthew G. Knepley PetscFunctionBegin;
817ca3d3a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
818ca3d3a14SMatthew G. Knepley PetscValidHeaderSpecific(lv, VEC_CLASSID, 2);
8199566063dSJacob Faibussowitsch PetscCall(DMPlexBasisTransform_Internal(dm, lv, PETSC_FALSE));
8203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
821ca3d3a14SMatthew G. Knepley }
822ca3d3a14SMatthew G. Knepley
823ca3d3a14SMatthew G. Knepley /*@
824ca3d3a14SMatthew G. Knepley DMPlexLocalToGlobalBasis - Transform the values in the given local vector from the local basis to the global basis
825ca3d3a14SMatthew G. Knepley
826ca3d3a14SMatthew G. Knepley Input Parameters:
827a1cb98faSBarry Smith + dm - The `DM`
828ca3d3a14SMatthew G. Knepley - lv - A local vector with values in the local basis
829ca3d3a14SMatthew G. Knepley
8302fe279fdSBarry Smith Output Parameter:
831ca3d3a14SMatthew G. Knepley . lv - A local vector with values in the global basis
832ca3d3a14SMatthew G. Knepley
833ca3d3a14SMatthew G. Knepley Level: developer
834ca3d3a14SMatthew G. Knepley
835a1cb98faSBarry Smith Note:
836a1cb98faSBarry Smith This method is only intended to be called inside `DMGlobalToLocal()`. It is unlikely that a user would want a local vector full of coefficients for the global basis unless they are reimplementing GlobalToLocal.
837a1cb98faSBarry Smith
8381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGlobalToLocalBasis()`, `DMGetLocalSection()`, `DMPlexCreateBasisRotation()`
839ca3d3a14SMatthew G. Knepley @*/
DMPlexLocalToGlobalBasis(DM dm,Vec lv)840d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalToGlobalBasis(DM dm, Vec lv)
841d71ae5a4SJacob Faibussowitsch {
842ca3d3a14SMatthew G. Knepley PetscFunctionBegin;
843ca3d3a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
844ca3d3a14SMatthew G. Knepley PetscValidHeaderSpecific(lv, VEC_CLASSID, 2);
8459566063dSJacob Faibussowitsch PetscCall(DMPlexBasisTransform_Internal(dm, lv, PETSC_TRUE));
8463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
847ca3d3a14SMatthew G. Knepley }
848ca3d3a14SMatthew G. Knepley
849ca3d3a14SMatthew G. Knepley /*@
850ca3d3a14SMatthew G. Knepley DMPlexCreateBasisRotation - Create an internal transformation from the global basis, used to specify boundary conditions
851ca3d3a14SMatthew G. Knepley and global solutions, to a local basis, appropriate for discretization integrals and assembly.
852ca3d3a14SMatthew G. Knepley
853ca3d3a14SMatthew G. Knepley Input Parameters:
854a1cb98faSBarry Smith + dm - The `DM`
855ca3d3a14SMatthew G. Knepley . alpha - The first Euler angle, and in 2D the only one
856ca3d3a14SMatthew G. Knepley . beta - The second Euler angle
857f0fc11ceSJed Brown - gamma - The third Euler angle
858ca3d3a14SMatthew G. Knepley
859ca3d3a14SMatthew G. Knepley Level: developer
860ca3d3a14SMatthew G. Knepley
861a1cb98faSBarry Smith Note:
862a1cb98faSBarry Smith Following https://en.wikipedia.org/wiki/Euler_angles, we will specify Euler angles by extrinsic rotations, meaning that
863a1cb98faSBarry Smith we rotate with respect to a fixed initial coordinate system, the local basis (x-y-z). The global basis (X-Y-Z) is reached as follows
864a1cb98faSBarry Smith .vb
865a1cb98faSBarry Smith The XYZ system rotates about the z axis by alpha. The X axis is now at angle alpha with respect to the x axis.
866a1cb98faSBarry Smith The XYZ system rotates again about the x axis by beta. The Z axis is now at angle beta with respect to the z axis.
867a1cb98faSBarry Smith The XYZ system rotates a third time about the z axis by gamma.
868a1cb98faSBarry Smith .ve
869a1cb98faSBarry Smith
8701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGlobalToLocalBasis()`, `DMPlexLocalToGlobalBasis()`
871ca3d3a14SMatthew G. Knepley @*/
DMPlexCreateBasisRotation(DM dm,PetscReal alpha,PetscReal beta,PetscReal gamma)872d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBasisRotation(DM dm, PetscReal alpha, PetscReal beta, PetscReal gamma)
873d71ae5a4SJacob Faibussowitsch {
874ca3d3a14SMatthew G. Knepley RotCtx *rc;
875ca3d3a14SMatthew G. Knepley PetscInt cdim;
876ca3d3a14SMatthew G. Knepley
877362febeeSStefano Zampini PetscFunctionBegin;
8789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim));
8799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &rc));
880ca3d3a14SMatthew G. Knepley dm->transformCtx = rc;
881ca3d3a14SMatthew G. Knepley dm->transformSetUp = DMPlexBasisTransformSetUp_Rotation_Internal;
882ca3d3a14SMatthew G. Knepley dm->transformDestroy = DMPlexBasisTransformDestroy_Rotation_Internal;
883ca3d3a14SMatthew G. Knepley dm->transformGetMatrix = DMPlexBasisTransformGetMatrix_Rotation_Internal;
884ca3d3a14SMatthew G. Knepley rc->dim = cdim;
885ca3d3a14SMatthew G. Knepley rc->alpha = alpha;
886ca3d3a14SMatthew G. Knepley rc->beta = beta;
887ca3d3a14SMatthew G. Knepley rc->gamma = gamma;
8889566063dSJacob Faibussowitsch PetscCall((*dm->transformSetUp)(dm, dm->transformCtx));
8899566063dSJacob Faibussowitsch PetscCall(DMConstructBasisTransform_Internal(dm));
8903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
891ca3d3a14SMatthew G. Knepley }
892ca3d3a14SMatthew G. Knepley
893b278463cSMatthew G. Knepley /*@C
894ece3a9fcSMatthew G. Knepley DMPlexInsertBoundaryValuesEssential - Insert boundary values into a local vector using a function of the coordinates
895b278463cSMatthew G. Knepley
896b278463cSMatthew G. Knepley Input Parameters:
897a1cb98faSBarry Smith + dm - The `DM`, with a `PetscDS` that matches the problem being constrained
898b278463cSMatthew G. Knepley . time - The time
899b278463cSMatthew G. Knepley . field - The field to constrain
9001c531cf8SMatthew G. Knepley . Nc - The number of constrained field components, or 0 for all components
90120f4b53cSBarry Smith . comps - An array of constrained component numbers, or `NULL` for all components
902a1cb98faSBarry Smith . label - The `DMLabel` defining constrained points
903a1cb98faSBarry Smith . numids - The number of `DMLabel` ids for constrained points
904b278463cSMatthew G. Knepley . ids - An array of ids for constrained points
905b278463cSMatthew G. Knepley . func - A pointwise function giving boundary values
906*2a8381b2SBarry Smith - ctx - An optional application context for `bcFunc`
907b278463cSMatthew G. Knepley
908b278463cSMatthew G. Knepley Output Parameter:
909b278463cSMatthew G. Knepley . locX - A local vector to receives the boundary values
910b278463cSMatthew G. Knepley
911b278463cSMatthew G. Knepley Level: developer
912b278463cSMatthew G. Knepley
9131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabel`, `DMPlexInsertBoundaryValuesEssentialField()`, `DMPlexInsertBoundaryValuesEssentialBdField()`, `DMAddBoundary()`
914b278463cSMatthew G. Knepley @*/
DMPlexInsertBoundaryValuesEssential(DM dm,PetscReal time,PetscInt field,PetscInt Nc,const PetscInt comps[],DMLabel label,PetscInt numids,const PetscInt ids[],PetscErrorCode (* func)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),PetscCtx ctx,Vec locX)915*2a8381b2SBarry Smith PetscErrorCode DMPlexInsertBoundaryValuesEssential(DM dm, PetscReal time, PetscInt field, PetscInt Nc, const PetscInt comps[], DMLabel label, PetscInt numids, const PetscInt ids[], PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), PetscCtx ctx, Vec locX)
916d71ae5a4SJacob Faibussowitsch {
917*2a8381b2SBarry Smith PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, PetscCtx ctx);
91855f2e967SMatthew G. Knepley void **ctxs;
919d7ddef95SMatthew G. Knepley PetscInt numFields;
920d7ddef95SMatthew G. Knepley
921d7ddef95SMatthew G. Knepley PetscFunctionBegin;
9229566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields));
9239566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(numFields, &funcs, numFields, &ctxs));
924d7ddef95SMatthew G. Knepley funcs[field] = func;
925d7ddef95SMatthew G. Knepley ctxs[field] = ctx;
9269566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLabelLocal(dm, time, label, numids, ids, Nc, comps, funcs, ctxs, INSERT_BC_VALUES, locX));
9279566063dSJacob Faibussowitsch PetscCall(PetscFree2(funcs, ctxs));
9283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
929d7ddef95SMatthew G. Knepley }
930d7ddef95SMatthew G. Knepley
931b278463cSMatthew G. Knepley /*@C
932ece3a9fcSMatthew G. Knepley DMPlexInsertBoundaryValuesEssentialField - Insert boundary values into a local vector using a function of the coordinates and field data
933b278463cSMatthew G. Knepley
934b278463cSMatthew G. Knepley Input Parameters:
935a1cb98faSBarry Smith + dm - The `DM`, with a `PetscDS` that matches the problem being constrained
936b278463cSMatthew G. Knepley . time - The time
937b278463cSMatthew G. Knepley . locU - A local vector with the input solution values
938b278463cSMatthew G. Knepley . field - The field to constrain
9391c531cf8SMatthew G. Knepley . Nc - The number of constrained field components, or 0 for all components
94020f4b53cSBarry Smith . comps - An array of constrained component numbers, or `NULL` for all components
941a1cb98faSBarry Smith . label - The `DMLabel` defining constrained points
942a1cb98faSBarry Smith . numids - The number of `DMLabel` ids for constrained points
943b278463cSMatthew G. Knepley . ids - An array of ids for constrained points
944b278463cSMatthew G. Knepley . func - A pointwise function giving boundary values
945*2a8381b2SBarry Smith - ctx - An optional application context for `bcFunc`
946b278463cSMatthew G. Knepley
947b278463cSMatthew G. Knepley Output Parameter:
948b278463cSMatthew G. Knepley . locX - A local vector to receives the boundary values
949b278463cSMatthew G. Knepley
950b278463cSMatthew G. Knepley Level: developer
951b278463cSMatthew G. Knepley
9521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexInsertBoundaryValuesEssential()`, `DMPlexInsertBoundaryValuesEssentialBdField()`, `DMAddBoundary()`
953b278463cSMatthew G. Knepley @*/
DMPlexInsertBoundaryValuesEssentialField(DM dm,PetscReal time,Vec locU,PetscInt field,PetscInt Nc,const PetscInt comps[],DMLabel label,PetscInt numids,const PetscInt ids[],void (* func)(PetscInt,PetscInt,PetscInt,const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],PetscReal,const PetscReal[],PetscInt,const PetscScalar[],PetscScalar[]),PetscCtx ctx,Vec locX)954*2a8381b2SBarry Smith PetscErrorCode DMPlexInsertBoundaryValuesEssentialField(DM dm, PetscReal time, Vec locU, PetscInt field, PetscInt Nc, const PetscInt comps[], DMLabel label, PetscInt numids, const PetscInt ids[], void (*func)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), PetscCtx ctx, Vec locX)
955d71ae5a4SJacob Faibussowitsch {
9569371c9d4SSatish Balay void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]);
957c60e475cSMatthew G. Knepley void **ctxs;
958c60e475cSMatthew G. Knepley PetscInt numFields;
959c60e475cSMatthew G. Knepley
960c60e475cSMatthew G. Knepley PetscFunctionBegin;
9619566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields));
9629566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(numFields, &funcs, numFields, &ctxs));
963c60e475cSMatthew G. Knepley funcs[field] = func;
964c60e475cSMatthew G. Knepley ctxs[field] = ctx;
9659566063dSJacob Faibussowitsch PetscCall(DMProjectFieldLabelLocal(dm, time, label, numids, ids, Nc, comps, locU, funcs, INSERT_BC_VALUES, locX));
9669566063dSJacob Faibussowitsch PetscCall(PetscFree2(funcs, ctxs));
9673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
968c60e475cSMatthew G. Knepley }
969c60e475cSMatthew G. Knepley
970b278463cSMatthew G. Knepley /*@C
971d5b43468SJose E. Roman DMPlexInsertBoundaryValuesEssentialBdField - Insert boundary values into a local vector using a function of the coordinates and boundary field data
972ece3a9fcSMatthew G. Knepley
97320f4b53cSBarry Smith Collective
974ece3a9fcSMatthew G. Knepley
975ece3a9fcSMatthew G. Knepley Input Parameters:
976a1cb98faSBarry Smith + dm - The `DM`, with a `PetscDS` that matches the problem being constrained
977ece3a9fcSMatthew G. Knepley . time - The time
978ece3a9fcSMatthew G. Knepley . locU - A local vector with the input solution values
979ece3a9fcSMatthew G. Knepley . field - The field to constrain
980ece3a9fcSMatthew G. Knepley . Nc - The number of constrained field components, or 0 for all components
98120f4b53cSBarry Smith . comps - An array of constrained component numbers, or `NULL` for all components
982a1cb98faSBarry Smith . label - The `DMLabel` defining constrained points
983a1cb98faSBarry Smith . numids - The number of `DMLabel` ids for constrained points
984ece3a9fcSMatthew G. Knepley . ids - An array of ids for constrained points
98520f4b53cSBarry Smith . func - A pointwise function giving boundary values, the calling sequence is given in `DMProjectBdFieldLabelLocal()`
986*2a8381b2SBarry Smith - ctx - An optional application context for `func`
987ece3a9fcSMatthew G. Knepley
988ece3a9fcSMatthew G. Knepley Output Parameter:
989ece3a9fcSMatthew G. Knepley . locX - A local vector to receive the boundary values
990ece3a9fcSMatthew G. Knepley
991ece3a9fcSMatthew G. Knepley Level: developer
992ece3a9fcSMatthew G. Knepley
9931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMProjectBdFieldLabelLocal()`, `DMPlexInsertBoundaryValuesEssential()`, `DMPlexInsertBoundaryValuesEssentialField()`, `DMAddBoundary()`
994ece3a9fcSMatthew G. Knepley @*/
DMPlexInsertBoundaryValuesEssentialBdField(DM dm,PetscReal time,Vec locU,PetscInt field,PetscInt Nc,const PetscInt comps[],DMLabel label,PetscInt numids,const PetscInt ids[],void (* func)(PetscInt,PetscInt,PetscInt,const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],PetscReal,const PetscReal[],const PetscReal[],PetscInt,const PetscScalar[],PetscScalar[]),PetscCtx ctx,Vec locX)995*2a8381b2SBarry Smith PetscErrorCode DMPlexInsertBoundaryValuesEssentialBdField(DM dm, PetscReal time, Vec locU, PetscInt field, PetscInt Nc, const PetscInt comps[], DMLabel label, PetscInt numids, const PetscInt ids[], void (*func)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), PetscCtx ctx, Vec locX)
996d71ae5a4SJacob Faibussowitsch {
9979371c9d4SSatish Balay void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]);
998ece3a9fcSMatthew G. Knepley void **ctxs;
999ece3a9fcSMatthew G. Knepley PetscInt numFields;
1000ece3a9fcSMatthew G. Knepley
1001ece3a9fcSMatthew G. Knepley PetscFunctionBegin;
10029566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields));
10039566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(numFields, &funcs, numFields, &ctxs));
1004ece3a9fcSMatthew G. Knepley funcs[field] = func;
1005ece3a9fcSMatthew G. Knepley ctxs[field] = ctx;
10069566063dSJacob Faibussowitsch PetscCall(DMProjectBdFieldLabelLocal(dm, time, label, numids, ids, Nc, comps, locU, funcs, INSERT_BC_VALUES, locX));
10079566063dSJacob Faibussowitsch PetscCall(PetscFree2(funcs, ctxs));
10083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1009ece3a9fcSMatthew G. Knepley }
1010ece3a9fcSMatthew G. Knepley
1011ece3a9fcSMatthew G. Knepley /*@C
1012b278463cSMatthew G. Knepley DMPlexInsertBoundaryValuesRiemann - Insert boundary values into a local vector
1013b278463cSMatthew G. Knepley
1014b278463cSMatthew G. Knepley Input Parameters:
1015a1cb98faSBarry Smith + dm - The `DM`, with a `PetscDS` that matches the problem being constrained
1016b278463cSMatthew G. Knepley . time - The time
1017b278463cSMatthew G. Knepley . faceGeometry - A vector with the FVM face geometry information
1018b278463cSMatthew G. Knepley . cellGeometry - A vector with the FVM cell geometry information
1019b278463cSMatthew G. Knepley . Grad - A vector with the FVM cell gradient information
1020b278463cSMatthew G. Knepley . field - The field to constrain
10211c531cf8SMatthew G. Knepley . Nc - The number of constrained field components, or 0 for all components
102220f4b53cSBarry Smith . comps - An array of constrained component numbers, or `NULL` for all components
1023a1cb98faSBarry Smith . label - The `DMLabel` defining constrained points
1024a1cb98faSBarry Smith . numids - The number of `DMLabel` ids for constrained points
1025b278463cSMatthew G. Knepley . ids - An array of ids for constrained points
1026b278463cSMatthew G. Knepley . func - A pointwise function giving boundary values
1027*2a8381b2SBarry Smith - ctx - An optional application context for bcFunc
1028b278463cSMatthew G. Knepley
1029b278463cSMatthew G. Knepley Output Parameter:
1030b278463cSMatthew G. Knepley . locX - A local vector to receives the boundary values
1031b278463cSMatthew G. Knepley
1032b278463cSMatthew G. Knepley Level: developer
1033b278463cSMatthew G. Knepley
1034a1cb98faSBarry Smith Note:
1035a1cb98faSBarry Smith This implementation currently ignores the numcomps/comps argument from `DMAddBoundary()`
1036a1cb98faSBarry Smith
10371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexInsertBoundaryValuesEssential()`, `DMPlexInsertBoundaryValuesEssentialField()`, `DMAddBoundary()`
1038b278463cSMatthew G. Knepley @*/
DMPlexInsertBoundaryValuesRiemann(DM dm,PetscReal time,Vec faceGeometry,Vec cellGeometry,Vec Grad,PetscInt field,PetscInt Nc,const PetscInt comps[],DMLabel label,PetscInt numids,const PetscInt ids[],PetscErrorCode (* func)(PetscReal,const PetscReal *,const PetscReal *,const PetscScalar *,PetscScalar *,void *),PetscCtx ctx,Vec locX)1039*2a8381b2SBarry Smith PetscErrorCode DMPlexInsertBoundaryValuesRiemann(DM dm, PetscReal time, Vec faceGeometry, Vec cellGeometry, Vec Grad, PetscInt field, PetscInt Nc, const PetscInt comps[], DMLabel label, PetscInt numids, const PetscInt ids[], PetscErrorCode (*func)(PetscReal, const PetscReal *, const PetscReal *, const PetscScalar *, PetscScalar *, void *), PetscCtx ctx, Vec locX)
1040d71ae5a4SJacob Faibussowitsch {
104161f58d28SMatthew G. Knepley PetscDS prob;
1042da97024aSMatthew G. Knepley PetscSF sf;
1043d7ddef95SMatthew G. Knepley DM dmFace, dmCell, dmGrad;
104420369375SToby Isaac const PetscScalar *facegeom, *cellgeom = NULL, *grad;
1045da97024aSMatthew G. Knepley const PetscInt *leaves;
1046d7ddef95SMatthew G. Knepley PetscScalar *x, *fx;
1047520b3818SMatthew G. Knepley PetscInt dim, nleaves, loc, fStart, fEnd, pdim, i;
10483ba16761SJacob Faibussowitsch PetscErrorCode ierru = PETSC_SUCCESS;
1049d7ddef95SMatthew G. Knepley
1050d7ddef95SMatthew G. Knepley PetscFunctionBegin;
10519566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf));
10529566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL));
1053da97024aSMatthew G. Knepley nleaves = PetscMax(0, nleaves);
10549566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
10559566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
10569566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
10579566063dSJacob Faibussowitsch PetscCall(VecGetDM(faceGeometry, &dmFace));
10589566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(faceGeometry, &facegeom));
105920369375SToby Isaac if (cellGeometry) {
10609566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellGeometry, &dmCell));
10619566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeometry, &cellgeom));
106220369375SToby Isaac }
1063d7ddef95SMatthew G. Knepley if (Grad) {
1064c0a6632aSMatthew G. Knepley PetscFV fv;
1065c0a6632aSMatthew G. Knepley
10669566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, (PetscObject *)&fv));
10679566063dSJacob Faibussowitsch PetscCall(VecGetDM(Grad, &dmGrad));
10689566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Grad, &grad));
10699566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &pdim));
10709566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pdim, MPIU_SCALAR, &fx));
1071d7ddef95SMatthew G. Knepley }
10729566063dSJacob Faibussowitsch PetscCall(VecGetArray(locX, &x));
1073d7ddef95SMatthew G. Knepley for (i = 0; i < numids; ++i) {
1074d7ddef95SMatthew G. Knepley IS faceIS;
1075d7ddef95SMatthew G. Knepley const PetscInt *faces;
1076d7ddef95SMatthew G. Knepley PetscInt numFaces, f;
1077d7ddef95SMatthew G. Knepley
10789566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, ids[i], &faceIS));
1079d7ddef95SMatthew G. Knepley if (!faceIS) continue; /* No points with that id on this process */
10809566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(faceIS, &numFaces));
10819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(faceIS, &faces));
1082d7ddef95SMatthew G. Knepley for (f = 0; f < numFaces; ++f) {
1083d7ddef95SMatthew G. Knepley const PetscInt face = faces[f], *cells;
1084640bce14SSatish Balay PetscFVFaceGeom *fg;
1085d7ddef95SMatthew G. Knepley
1086d7ddef95SMatthew G. Knepley if ((face < fStart) || (face >= fEnd)) continue; /* Refinement adds non-faces to labels */
10879566063dSJacob Faibussowitsch PetscCall(PetscFindInt(face, nleaves, (PetscInt *)leaves, &loc));
1088da97024aSMatthew G. Knepley if (loc >= 0) continue;
10899566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, face, facegeom, &fg));
10909566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, face, &cells));
1091d7ddef95SMatthew G. Knepley if (Grad) {
1092640bce14SSatish Balay PetscFVCellGeom *cg;
1093640bce14SSatish Balay PetscScalar *cx, *cgrad;
1094d7ddef95SMatthew G. Knepley PetscScalar *xG;
1095d7ddef95SMatthew G. Knepley PetscReal dx[3];
1096d7ddef95SMatthew G. Knepley PetscInt d;
1097d7ddef95SMatthew G. Knepley
10989566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cg));
10999566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, cells[0], x, &cx));
11009566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmGrad, cells[0], grad, &cgrad));
11019566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRef(dm, cells[1], field, x, &xG));
1102d7ddef95SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, cg->centroid, fg->centroid, dx);
1103d7ddef95SMatthew G. Knepley for (d = 0; d < pdim; ++d) fx[d] = cx[d] + DMPlex_DotD_Internal(dim, &cgrad[d * dim], dx);
11049566063dSJacob Faibussowitsch PetscCall((*func)(time, fg->centroid, fg->normal, fx, xG, ctx));
1105d7ddef95SMatthew G. Knepley } else {
1106640bce14SSatish Balay PetscScalar *xI;
1107d7ddef95SMatthew G. Knepley PetscScalar *xG;
1108d7ddef95SMatthew G. Knepley
11099566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, cells[0], x, &xI));
11109566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRef(dm, cells[1], field, x, &xG));
1111e735a8a9SMatthew G. Knepley ierru = (*func)(time, fg->centroid, fg->normal, xI, xG, ctx);
1112e735a8a9SMatthew G. Knepley if (ierru) {
11139566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(faceIS, &faces));
11149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&faceIS));
1115e735a8a9SMatthew G. Knepley goto cleanup;
1116e735a8a9SMatthew G. Knepley }
1117d7ddef95SMatthew G. Knepley }
1118d7ddef95SMatthew G. Knepley }
11199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(faceIS, &faces));
11209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&faceIS));
1121d7ddef95SMatthew G. Knepley }
1122e735a8a9SMatthew G. Knepley cleanup:
11239566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(locX, &x));
1124d7ddef95SMatthew G. Knepley if (Grad) {
11259566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pdim, MPIU_SCALAR, &fx));
11269566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Grad, &grad));
1127d7ddef95SMatthew G. Knepley }
11289566063dSJacob Faibussowitsch if (cellGeometry) PetscCall(VecRestoreArrayRead(cellGeometry, &cellgeom));
11299566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(faceGeometry, &facegeom));
11309566063dSJacob Faibussowitsch PetscCall(ierru);
11313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1132d7ddef95SMatthew G. Knepley }
1133d7ddef95SMatthew G. Knepley
zero(PetscInt dim,PetscReal time,const PetscReal x[],PetscInt Nc,PetscScalar * u,PetscCtx ctx)1134*2a8381b2SBarry Smith static PetscErrorCode zero(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, PetscCtx ctx)
1135d71ae5a4SJacob Faibussowitsch {
11360c364540SMatthew G. Knepley PetscInt c;
11370c364540SMatthew G. Knepley for (c = 0; c < Nc; ++c) u[c] = 0.0;
11383ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
11390c364540SMatthew G. Knepley }
11400c364540SMatthew G. Knepley
DMPlexInsertBoundaryValues_Plex(DM dm,PetscBool insertEssential,Vec locX,PetscReal time,Vec faceGeomFVM,Vec cellGeomFVM,Vec gradFVM)1141d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertBoundaryValues_Plex(DM dm, PetscBool insertEssential, Vec locX, PetscReal time, Vec faceGeomFVM, Vec cellGeomFVM, Vec gradFVM)
1142d71ae5a4SJacob Faibussowitsch {
11430c364540SMatthew G. Knepley PetscObject isZero;
1144e5e52638SMatthew G. Knepley PetscDS prob;
1145d7ddef95SMatthew G. Knepley PetscInt numBd, b;
114655f2e967SMatthew G. Knepley
114755f2e967SMatthew G. Knepley PetscFunctionBegin;
11489566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
11499566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumBoundary(prob, &numBd));
11509566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)locX, "__Vec_bc_zero__", &isZero));
1151450c7a9fSMatthew G. Knepley PetscCall(PetscDSUpdateBoundaryLabels(prob, dm));
115255f2e967SMatthew G. Knepley for (b = 0; b < numBd; ++b) {
115345480ffeSMatthew G. Knepley PetscWeakForm wf;
1154f971fd6bSMatthew G. Knepley DMBoundaryConditionType type;
115545480ffeSMatthew G. Knepley const char *name;
1156d7ddef95SMatthew G. Knepley DMLabel label;
11571c531cf8SMatthew G. Knepley PetscInt field, Nc;
11581c531cf8SMatthew G. Knepley const PetscInt *comps;
1159d7ddef95SMatthew G. Knepley PetscObject obj;
1160d7ddef95SMatthew G. Knepley PetscClassId id;
116157d50842SBarry Smith PetscVoidFn *bvfunc;
1162d7ddef95SMatthew G. Knepley PetscInt numids;
1163d7ddef95SMatthew G. Knepley const PetscInt *ids;
116455f2e967SMatthew G. Knepley void *ctx;
116555f2e967SMatthew G. Knepley
11669566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(prob, b, &wf, &type, &name, &label, &numids, &ids, &field, &Nc, &comps, &bvfunc, NULL, &ctx));
1167f971fd6bSMatthew G. Knepley if (insertEssential != (type & DM_BC_ESSENTIAL)) continue;
11689566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, field, NULL, &obj));
11699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
1170d7ddef95SMatthew G. Knepley if (id == PETSCFE_CLASSID) {
1171c60e475cSMatthew G. Knepley switch (type) {
1172c60e475cSMatthew G. Knepley /* for FEM, there is no insertion to be done for non-essential boundary conditions */
11739371c9d4SSatish Balay case DM_BC_ESSENTIAL: {
11748434afd1SBarry Smith PetscSimplePointFn *func = (PetscSimplePointFn *)bvfunc;
117545480ffeSMatthew G. Knepley
117645480ffeSMatthew G. Knepley if (isZero) func = zero;
11779566063dSJacob Faibussowitsch PetscCall(DMPlexLabelAddCells(dm, label));
11789566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValuesEssential(dm, time, field, Nc, comps, label, numids, ids, func, ctx, locX));
11799566063dSJacob Faibussowitsch PetscCall(DMPlexLabelClearCells(dm, label));
11809371c9d4SSatish Balay } break;
11819371c9d4SSatish Balay case DM_BC_ESSENTIAL_FIELD: {
11822192575eSBarry Smith PetscPointFn *func = (PetscPointFn *)bvfunc;
118345480ffeSMatthew G. Knepley
11849566063dSJacob Faibussowitsch PetscCall(DMPlexLabelAddCells(dm, label));
11859566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValuesEssentialField(dm, time, locX, field, Nc, comps, label, numids, ids, func, ctx, locX));
11869566063dSJacob Faibussowitsch PetscCall(DMPlexLabelClearCells(dm, label));
11879371c9d4SSatish Balay } break;
1188d71ae5a4SJacob Faibussowitsch default:
1189d71ae5a4SJacob Faibussowitsch break;
1190c60e475cSMatthew G. Knepley }
1191d7ddef95SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
119245480ffeSMatthew G. Knepley {
119345480ffeSMatthew G. Knepley PetscErrorCode (*func)(PetscReal, const PetscReal *, const PetscReal *, const PetscScalar *, PetscScalar *, void *) = (PetscErrorCode (*)(PetscReal, const PetscReal *, const PetscReal *, const PetscScalar *, PetscScalar *, void *))bvfunc;
119445480ffeSMatthew G. Knepley
119543ea7facSMatthew G. Knepley if (!faceGeomFVM) continue;
11969566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValuesRiemann(dm, time, faceGeomFVM, cellGeomFVM, gradFVM, field, Nc, comps, label, numids, ids, func, ctx, locX));
119745480ffeSMatthew G. Knepley }
119863a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
119955f2e967SMatthew G. Knepley }
12003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
120155f2e967SMatthew G. Knepley }
120255f2e967SMatthew G. Knepley
DMPlexInsertTimeDerivativeBoundaryValues_Plex(DM dm,PetscBool insertEssential,Vec locX,PetscReal time,Vec faceGeomFVM,Vec cellGeomFVM,Vec gradFVM)1203d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertTimeDerivativeBoundaryValues_Plex(DM dm, PetscBool insertEssential, Vec locX, PetscReal time, Vec faceGeomFVM, Vec cellGeomFVM, Vec gradFVM)
1204d71ae5a4SJacob Faibussowitsch {
120556cf3b9cSMatthew G. Knepley PetscObject isZero;
120656cf3b9cSMatthew G. Knepley PetscDS prob;
120756cf3b9cSMatthew G. Knepley PetscInt numBd, b;
120856cf3b9cSMatthew G. Knepley
120956cf3b9cSMatthew G. Knepley PetscFunctionBegin;
12103ba16761SJacob Faibussowitsch if (!locX) PetscFunctionReturn(PETSC_SUCCESS);
12119566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
12129566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumBoundary(prob, &numBd));
12139566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)locX, "__Vec_bc_zero__", &isZero));
121456cf3b9cSMatthew G. Knepley for (b = 0; b < numBd; ++b) {
121545480ffeSMatthew G. Knepley PetscWeakForm wf;
121656cf3b9cSMatthew G. Knepley DMBoundaryConditionType type;
121745480ffeSMatthew G. Knepley const char *name;
121856cf3b9cSMatthew G. Knepley DMLabel label;
121956cf3b9cSMatthew G. Knepley PetscInt field, Nc;
122056cf3b9cSMatthew G. Knepley const PetscInt *comps;
122156cf3b9cSMatthew G. Knepley PetscObject obj;
122256cf3b9cSMatthew G. Knepley PetscClassId id;
122356cf3b9cSMatthew G. Knepley PetscInt numids;
122456cf3b9cSMatthew G. Knepley const PetscInt *ids;
122557d50842SBarry Smith PetscVoidFn *bvfunc;
122656cf3b9cSMatthew G. Knepley void *ctx;
122756cf3b9cSMatthew G. Knepley
12289566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(prob, b, &wf, &type, &name, &label, &numids, &ids, &field, &Nc, &comps, NULL, &bvfunc, &ctx));
122956cf3b9cSMatthew G. Knepley if (insertEssential != (type & DM_BC_ESSENTIAL)) continue;
12309566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, field, NULL, &obj));
12319566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
123256cf3b9cSMatthew G. Knepley if (id == PETSCFE_CLASSID) {
123356cf3b9cSMatthew G. Knepley switch (type) {
123456cf3b9cSMatthew G. Knepley /* for FEM, there is no insertion to be done for non-essential boundary conditions */
12359371c9d4SSatish Balay case DM_BC_ESSENTIAL: {
12368434afd1SBarry Smith PetscSimplePointFn *func_t = (PetscSimplePointFn *)bvfunc;
123745480ffeSMatthew G. Knepley
123845480ffeSMatthew G. Knepley if (isZero) func_t = zero;
12399566063dSJacob Faibussowitsch PetscCall(DMPlexLabelAddCells(dm, label));
12409566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValuesEssential(dm, time, field, Nc, comps, label, numids, ids, func_t, ctx, locX));
12419566063dSJacob Faibussowitsch PetscCall(DMPlexLabelClearCells(dm, label));
12429371c9d4SSatish Balay } break;
12439371c9d4SSatish Balay case DM_BC_ESSENTIAL_FIELD: {
12442192575eSBarry Smith PetscPointFn *func_t = (PetscPointFn *)bvfunc;
124545480ffeSMatthew G. Knepley
12469566063dSJacob Faibussowitsch PetscCall(DMPlexLabelAddCells(dm, label));
12479566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValuesEssentialField(dm, time, locX, field, Nc, comps, label, numids, ids, func_t, ctx, locX));
12489566063dSJacob Faibussowitsch PetscCall(DMPlexLabelClearCells(dm, label));
12499371c9d4SSatish Balay } break;
1250d71ae5a4SJacob Faibussowitsch default:
1251d71ae5a4SJacob Faibussowitsch break;
125256cf3b9cSMatthew G. Knepley }
125363a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
125456cf3b9cSMatthew G. Knepley }
12553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
125656cf3b9cSMatthew G. Knepley }
125756cf3b9cSMatthew G. Knepley
DMPlexInsertBounds_Plex(DM dm,PetscBool lower,PetscReal time,Vec locB)125801468941SMatthew G. Knepley PetscErrorCode DMPlexInsertBounds_Plex(DM dm, PetscBool lower, PetscReal time, Vec locB)
125901468941SMatthew G. Knepley {
126001468941SMatthew G. Knepley PetscDS ds;
126101468941SMatthew G. Knepley PetscInt numBd;
126201468941SMatthew G. Knepley
126301468941SMatthew G. Knepley PetscFunctionBegin;
126401468941SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds));
126501468941SMatthew G. Knepley PetscCall(PetscDSGetNumBoundary(ds, &numBd));
126601468941SMatthew G. Knepley PetscCall(PetscDSUpdateBoundaryLabels(ds, dm));
126701468941SMatthew G. Knepley for (PetscInt b = 0; b < numBd; ++b) {
126801468941SMatthew G. Knepley PetscWeakForm wf;
126901468941SMatthew G. Knepley DMBoundaryConditionType type;
127001468941SMatthew G. Knepley const char *name;
127101468941SMatthew G. Knepley DMLabel label;
127201468941SMatthew G. Knepley PetscInt numids;
127301468941SMatthew G. Knepley const PetscInt *ids;
127401468941SMatthew G. Knepley PetscInt field, Nc;
127501468941SMatthew G. Knepley const PetscInt *comps;
127657d50842SBarry Smith PetscVoidFn *bvfunc;
127701468941SMatthew G. Knepley void *ctx;
127801468941SMatthew G. Knepley
127901468941SMatthew G. Knepley PetscCall(PetscDSGetBoundary(ds, b, &wf, &type, &name, &label, &numids, &ids, &field, &Nc, &comps, &bvfunc, NULL, &ctx));
128001468941SMatthew G. Knepley if (lower && type != DM_BC_LOWER_BOUND) continue;
128101468941SMatthew G. Knepley if (!lower && type != DM_BC_UPPER_BOUND) continue;
128201468941SMatthew G. Knepley PetscCall(DMPlexLabelAddCells(dm, label));
128301468941SMatthew G. Knepley {
1284*2a8381b2SBarry Smith PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, PetscCtx ctx);
128501468941SMatthew G. Knepley void **ctxs;
128601468941SMatthew G. Knepley PetscInt Nf;
128701468941SMatthew G. Knepley
128801468941SMatthew G. Knepley PetscCall(DMGetNumFields(dm, &Nf));
128901468941SMatthew G. Knepley PetscCall(PetscCalloc2(Nf, &funcs, Nf, &ctxs));
129001468941SMatthew G. Knepley funcs[field] = (PetscSimplePointFn *)bvfunc;
129101468941SMatthew G. Knepley ctxs[field] = ctx;
129201468941SMatthew G. Knepley PetscCall(DMProjectFunctionLabelLocal(dm, time, label, numids, ids, Nc, comps, funcs, ctxs, INSERT_ALL_VALUES, locB));
129301468941SMatthew G. Knepley PetscCall(PetscFree2(funcs, ctxs));
129401468941SMatthew G. Knepley }
129501468941SMatthew G. Knepley PetscCall(DMPlexLabelClearCells(dm, label));
129601468941SMatthew G. Knepley }
129701468941SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
129801468941SMatthew G. Knepley }
129901468941SMatthew G. Knepley
1300f1d73a7aSMatthew G. Knepley /*@
1301f1d73a7aSMatthew G. Knepley DMPlexInsertBoundaryValues - Puts coefficients which represent boundary values into the local solution vector
1302f1d73a7aSMatthew G. Knepley
1303ed808b8fSJed Brown Not Collective
1304ed808b8fSJed Brown
1305f1d73a7aSMatthew G. Knepley Input Parameters:
1306a1cb98faSBarry Smith + dm - The `DM`
1307f1d73a7aSMatthew G. Knepley . insertEssential - Should I insert essential (e.g. Dirichlet) or inessential (e.g. Neumann) boundary conditions
1308f1d73a7aSMatthew G. Knepley . time - The time
1309f1d73a7aSMatthew G. Knepley . faceGeomFVM - Face geometry data for FV discretizations
1310f1d73a7aSMatthew G. Knepley . cellGeomFVM - Cell geometry data for FV discretizations
1311f1d73a7aSMatthew G. Knepley - gradFVM - Gradient reconstruction data for FV discretizations
1312f1d73a7aSMatthew G. Knepley
13132fe279fdSBarry Smith Output Parameter:
1314f1d73a7aSMatthew G. Knepley . locX - Solution updated with boundary values
1315f1d73a7aSMatthew G. Knepley
1316ed808b8fSJed Brown Level: intermediate
1317f1d73a7aSMatthew G. Knepley
13181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMProjectFunctionLabelLocal()`, `DMAddBoundary()`
1319f1d73a7aSMatthew G. Knepley @*/
DMPlexInsertBoundaryValues(DM dm,PetscBool insertEssential,Vec locX,PetscReal time,Vec faceGeomFVM,Vec cellGeomFVM,Vec gradFVM)1320d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertBoundaryValues(DM dm, PetscBool insertEssential, Vec locX, PetscReal time, Vec faceGeomFVM, Vec cellGeomFVM, Vec gradFVM)
1321d71ae5a4SJacob Faibussowitsch {
1322f1d73a7aSMatthew G. Knepley PetscFunctionBegin;
1323f1d73a7aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1324064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(locX, VEC_CLASSID, 3);
1325ad540459SPierre Jolivet if (faceGeomFVM) PetscValidHeaderSpecific(faceGeomFVM, VEC_CLASSID, 5);
1326ad540459SPierre Jolivet if (cellGeomFVM) PetscValidHeaderSpecific(cellGeomFVM, VEC_CLASSID, 6);
1327ad540459SPierre Jolivet if (gradFVM) PetscValidHeaderSpecific(gradFVM, VEC_CLASSID, 7);
1328cac4c232SBarry Smith PetscTryMethod(dm, "DMPlexInsertBoundaryValues_C", (DM, PetscBool, Vec, PetscReal, Vec, Vec, Vec), (dm, insertEssential, locX, time, faceGeomFVM, cellGeomFVM, gradFVM));
13293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1330f1d73a7aSMatthew G. Knepley }
1331f1d73a7aSMatthew G. Knepley
133256cf3b9cSMatthew G. Knepley /*@
1333a5b23f4aSJose E. Roman DMPlexInsertTimeDerivativeBoundaryValues - Puts coefficients which represent boundary values of the time derivative into the local solution vector
133456cf3b9cSMatthew G. Knepley
133556cf3b9cSMatthew G. Knepley Input Parameters:
1336a1cb98faSBarry Smith + dm - The `DM`
133756cf3b9cSMatthew G. Knepley . insertEssential - Should I insert essential (e.g. Dirichlet) or inessential (e.g. Neumann) boundary conditions
133856cf3b9cSMatthew G. Knepley . time - The time
133956cf3b9cSMatthew G. Knepley . faceGeomFVM - Face geometry data for FV discretizations
134056cf3b9cSMatthew G. Knepley . cellGeomFVM - Cell geometry data for FV discretizations
134156cf3b9cSMatthew G. Knepley - gradFVM - Gradient reconstruction data for FV discretizations
134256cf3b9cSMatthew G. Knepley
13432fe279fdSBarry Smith Output Parameter:
134456cf3b9cSMatthew G. Knepley . locX_t - Solution updated with boundary values
134556cf3b9cSMatthew G. Knepley
134656cf3b9cSMatthew G. Knepley Level: developer
134756cf3b9cSMatthew G. Knepley
13481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMProjectFunctionLabelLocal()`
134956cf3b9cSMatthew G. Knepley @*/
DMPlexInsertTimeDerivativeBoundaryValues(DM dm,PetscBool insertEssential,Vec locX_t,PetscReal time,Vec faceGeomFVM,Vec cellGeomFVM,Vec gradFVM)1350d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertTimeDerivativeBoundaryValues(DM dm, PetscBool insertEssential, Vec locX_t, PetscReal time, Vec faceGeomFVM, Vec cellGeomFVM, Vec gradFVM)
1351d71ae5a4SJacob Faibussowitsch {
135256cf3b9cSMatthew G. Knepley PetscFunctionBegin;
135356cf3b9cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1354ad540459SPierre Jolivet if (locX_t) PetscValidHeaderSpecific(locX_t, VEC_CLASSID, 3);
1355ad540459SPierre Jolivet if (faceGeomFVM) PetscValidHeaderSpecific(faceGeomFVM, VEC_CLASSID, 5);
1356ad540459SPierre Jolivet if (cellGeomFVM) PetscValidHeaderSpecific(cellGeomFVM, VEC_CLASSID, 6);
1357ad540459SPierre Jolivet if (gradFVM) PetscValidHeaderSpecific(gradFVM, VEC_CLASSID, 7);
13586c51210dSStefano Zampini PetscTryMethod(dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", (DM, PetscBool, Vec, PetscReal, Vec, Vec, Vec), (dm, insertEssential, locX_t, time, faceGeomFVM, cellGeomFVM, gradFVM));
13593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
136056cf3b9cSMatthew G. Knepley }
136156cf3b9cSMatthew G. Knepley
136201468941SMatthew G. Knepley /*@
136301468941SMatthew G. Knepley DMPlexInsertBounds - Puts coefficients which represent solution bounds into the local bounds vector
136401468941SMatthew G. Knepley
136501468941SMatthew G. Knepley Not Collective
136601468941SMatthew G. Knepley
136701468941SMatthew G. Knepley Input Parameters:
136801468941SMatthew G. Knepley + dm - The `DM`
136901468941SMatthew G. Knepley . lower - If `PETSC_TRUE` use `DM_BC_LOWER_BOUND` conditions, otherwise use `DM_BC_UPPER_BOUND`
137001468941SMatthew G. Knepley - time - The time
137101468941SMatthew G. Knepley
137201468941SMatthew G. Knepley Output Parameter:
137301468941SMatthew G. Knepley . locB - Bounds vector updated with new bounds
137401468941SMatthew G. Knepley
137501468941SMatthew G. Knepley Level: intermediate
137601468941SMatthew G. Knepley
137701468941SMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMProjectFunctionLabelLocal()`, `PetscDSAddBoundary()`
137801468941SMatthew G. Knepley @*/
DMPlexInsertBounds(DM dm,PetscBool lower,PetscReal time,Vec locB)137901468941SMatthew G. Knepley PetscErrorCode DMPlexInsertBounds(DM dm, PetscBool lower, PetscReal time, Vec locB)
138001468941SMatthew G. Knepley {
138101468941SMatthew G. Knepley PetscFunctionBegin;
138201468941SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
138301468941SMatthew G. Knepley PetscValidHeaderSpecific(locB, VEC_CLASSID, 4);
138401468941SMatthew G. Knepley PetscTryMethod(dm, "DMPlexInsertBounds_C", (DM, PetscBool, PetscReal, Vec), (dm, lower, time, locB));
138501468941SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
138601468941SMatthew G. Knepley }
138701468941SMatthew G. Knepley
13885962854dSMatthew G. Knepley // Handle non-essential (e.g. outflow) boundary values
DMPlexInsertBoundaryValuesFVM(DM dm,PetscFV fv,Vec locX,PetscReal time,Vec * locGradient)13895962854dSMatthew G. Knepley PetscErrorCode DMPlexInsertBoundaryValuesFVM(DM dm, PetscFV fv, Vec locX, PetscReal time, Vec *locGradient)
13905962854dSMatthew G. Knepley {
13915962854dSMatthew G. Knepley DM dmGrad;
13925962854dSMatthew G. Knepley Vec cellGeometryFVM, faceGeometryFVM, locGrad = NULL;
13935962854dSMatthew G. Knepley
13945962854dSMatthew G. Knepley PetscFunctionBegin;
13955962854dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
13965962854dSMatthew G. Knepley PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
13975962854dSMatthew G. Knepley PetscValidHeaderSpecific(locX, VEC_CLASSID, 3);
13985962854dSMatthew G. Knepley if (locGradient) {
13995962854dSMatthew G. Knepley PetscAssertPointer(locGradient, 5);
14005962854dSMatthew G. Knepley *locGradient = NULL;
14015962854dSMatthew G. Knepley }
14025962854dSMatthew G. Knepley PetscCall(DMPlexGetGeometryFVM(dm, &faceGeometryFVM, &cellGeometryFVM, NULL));
14035962854dSMatthew G. Knepley /* Reconstruct and limit cell gradients */
14045962854dSMatthew G. Knepley PetscCall(DMPlexGetGradientDM(dm, fv, &dmGrad));
14055962854dSMatthew G. Knepley if (dmGrad) {
14065962854dSMatthew G. Knepley Vec grad;
14075962854dSMatthew G. Knepley PetscInt fStart, fEnd;
14085962854dSMatthew G. Knepley
14095962854dSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
14105962854dSMatthew G. Knepley PetscCall(DMGetGlobalVector(dmGrad, &grad));
14115962854dSMatthew G. Knepley PetscCall(DMPlexReconstructGradients_Internal(dm, fv, fStart, fEnd, faceGeometryFVM, cellGeometryFVM, locX, grad));
14125962854dSMatthew G. Knepley /* Communicate gradient values */
14135962854dSMatthew G. Knepley PetscCall(DMGetLocalVector(dmGrad, &locGrad));
14145962854dSMatthew G. Knepley PetscCall(DMGlobalToLocalBegin(dmGrad, grad, INSERT_VALUES, locGrad));
14155962854dSMatthew G. Knepley PetscCall(DMGlobalToLocalEnd(dmGrad, grad, INSERT_VALUES, locGrad));
14165962854dSMatthew G. Knepley PetscCall(DMRestoreGlobalVector(dmGrad, &grad));
14175962854dSMatthew G. Knepley }
14185962854dSMatthew G. Knepley PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_FALSE, locX, time, faceGeometryFVM, cellGeometryFVM, locGrad));
14195962854dSMatthew G. Knepley if (locGradient) *locGradient = locGrad;
14205962854dSMatthew G. Knepley else if (locGrad) PetscCall(DMRestoreLocalVector(dmGrad, &locGrad));
14215962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
14225962854dSMatthew G. Knepley }
14235962854dSMatthew G. Knepley
DMComputeL2Diff_Plex(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,Vec X,PetscReal * diff)1424d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2Diff_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
1425d71ae5a4SJacob Faibussowitsch {
1426574a98acSMatthew G. Knepley Vec localX;
1427574a98acSMatthew G. Knepley
1428574a98acSMatthew G. Knepley PetscFunctionBegin;
14299566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &localX));
14309566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, localX, time, NULL, NULL, NULL));
14319566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX));
14329566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX));
14339566063dSJacob Faibussowitsch PetscCall(DMPlexComputeL2DiffLocal(dm, time, funcs, ctxs, localX, diff));
14349566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &localX));
14353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1436574a98acSMatthew G. Knepley }
1437574a98acSMatthew G. Knepley
1438574a98acSMatthew G. Knepley /*@C
143960225df5SJacob Faibussowitsch DMPlexComputeL2DiffLocal - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
1440574a98acSMatthew G. Knepley
144120f4b53cSBarry Smith Collective
1442c0f8e1fdSMatthew G. Knepley
1443574a98acSMatthew G. Knepley Input Parameters:
1444a1cb98faSBarry Smith + dm - The `DM`
1445574a98acSMatthew G. Knepley . time - The time
1446574a98acSMatthew G. Knepley . funcs - The functions to evaluate for each field component
144720f4b53cSBarry Smith . ctxs - Optional array of contexts to pass to each function, or `NULL`.
1448574a98acSMatthew G. Knepley - localX - The coefficient vector u_h, a local vector
1449574a98acSMatthew G. Knepley
1450574a98acSMatthew G. Knepley Output Parameter:
1451574a98acSMatthew G. Knepley . diff - The diff ||u - u_h||_2
1452574a98acSMatthew G. Knepley
1453574a98acSMatthew G. Knepley Level: developer
1454574a98acSMatthew G. Knepley
14551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMProjectFunction()`, `DMComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
1456574a98acSMatthew G. Knepley @*/
DMPlexComputeL2DiffLocal(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,Vec localX,PetscReal * diff)1457d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeL2DiffLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec localX, PetscReal *diff)
1458d71ae5a4SJacob Faibussowitsch {
14590f09c10fSMatthew G. Knepley const PetscInt debug = ((DM_Plex *)dm->data)->printL2;
1460ca3d3a14SMatthew G. Knepley DM tdm;
1461ca3d3a14SMatthew G. Knepley Vec tv;
1462cb1e1211SMatthew G Knepley PetscSection section;
1463c5bbbd5bSMatthew G. Knepley PetscQuadrature quad;
14644bee2e38SMatthew G. Knepley PetscFEGeom fegeom;
146515496722SMatthew G. Knepley PetscScalar *funcVal, *interpolant;
14664bee2e38SMatthew G. Knepley PetscReal *coords, *gcoords;
1467cb1e1211SMatthew G Knepley PetscReal localDiff = 0.0;
14687318780aSToby Isaac const PetscReal *quadWeights;
1469412e9a14SMatthew G. Knepley PetscInt dim, coordDim, numFields, numComponents = 0, qNc, Nq, cellHeight, cStart, cEnd, c, field, fieldOffset;
1470ca3d3a14SMatthew G. Knepley PetscBool transform;
1471cb1e1211SMatthew G Knepley
1472cb1e1211SMatthew G Knepley PetscFunctionBegin;
14739566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
14749566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim));
14752a4e142eSMatthew G. Knepley fegeom.dimEmbed = coordDim;
14769566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
14779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields));
14789566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformDM_Internal(dm, &tdm));
14799566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
14809566063dSJacob Faibussowitsch PetscCall(DMHasBasisTransform(dm, &transform));
1481eae3dc7dSJacob Faibussowitsch PetscCheck(numFields, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of fields is zero!");
1482cb1e1211SMatthew G Knepley for (field = 0; field < numFields; ++field) {
148315496722SMatthew G. Knepley PetscObject obj;
148415496722SMatthew G. Knepley PetscClassId id;
1485c5bbbd5bSMatthew G. Knepley PetscInt Nc;
1486c5bbbd5bSMatthew G. Knepley
14879566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, field, NULL, &obj));
14889566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
148915496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) {
149015496722SMatthew G. Knepley PetscFE fe = (PetscFE)obj;
149115496722SMatthew G. Knepley
14929566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quad));
14939566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc));
149415496722SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
149515496722SMatthew G. Knepley PetscFV fv = (PetscFV)obj;
149615496722SMatthew G. Knepley
14979566063dSJacob Faibussowitsch PetscCall(PetscFVGetQuadrature(fv, &quad));
14989566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc));
149963a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
1500c5bbbd5bSMatthew G. Knepley numComponents += Nc;
1501cb1e1211SMatthew G Knepley }
15029566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, NULL, &quadWeights));
150363a3b9bcSJacob Faibussowitsch PetscCheck(!(qNc != 1) || !(qNc != numComponents), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Quadrature components %" PetscInt_FMT " != %" PetscInt_FMT " field components", qNc, numComponents);
1504c9cb6370SYANG Zongze PetscCall(PetscMalloc6(numComponents, &funcVal, numComponents, &interpolant, coordDim * (Nq + 1), &coords, Nq, &fegeom.detJ, coordDim * coordDim * Nq, &fegeom.J, coordDim * coordDim * Nq, &fegeom.invJ));
15059566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
15069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
1507cb1e1211SMatthew G Knepley for (c = cStart; c < cEnd; ++c) {
1508a1e44745SMatthew G. Knepley PetscScalar *x = NULL;
1509cb1e1211SMatthew G Knepley PetscReal elemDiff = 0.0;
15109c3cf19fSMatthew G. Knepley PetscInt qc = 0;
1511cb1e1211SMatthew G Knepley
15129566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, quad, coords, fegeom.J, fegeom.invJ, fegeom.detJ));
151348162695SZach Atkins PetscCall(DMPlexVecGetOrientedClosure(dm, NULL, PETSC_FALSE, localX, c, 0, NULL, &x));
1514cb1e1211SMatthew G Knepley
151515496722SMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) {
151615496722SMatthew G. Knepley PetscObject obj;
151715496722SMatthew G. Knepley PetscClassId id;
1518c110b1eeSGeoffrey Irving void *const ctx = ctxs ? ctxs[field] : NULL;
151915496722SMatthew G. Knepley PetscInt Nb, Nc, q, fc;
1520cb1e1211SMatthew G Knepley
15219566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, field, NULL, &obj));
15229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
15239371c9d4SSatish Balay if (id == PETSCFE_CLASSID) {
15249371c9d4SSatish Balay PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
15259371c9d4SSatish Balay PetscCall(PetscFEGetDimension((PetscFE)obj, &Nb));
15269371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) {
15279371c9d4SSatish Balay PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
15289371c9d4SSatish Balay Nb = 1;
15299371c9d4SSatish Balay } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
1530cb1e1211SMatthew G Knepley if (debug) {
1531cb1e1211SMatthew G Knepley char title[1024];
153263a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(title, 1023, "Solution for Field %" PetscInt_FMT, field));
15339566063dSJacob Faibussowitsch PetscCall(DMPrintCellVector(c, title, Nb, &x[fieldOffset]));
1534cb1e1211SMatthew G Knepley }
15357318780aSToby Isaac for (q = 0; q < Nq; ++q) {
15362a4e142eSMatthew G. Knepley PetscFEGeom qgeom;
1537d0609cedSBarry Smith PetscErrorCode ierr;
15382a4e142eSMatthew G. Knepley
15392a4e142eSMatthew G. Knepley qgeom.dimEmbed = fegeom.dimEmbed;
15402a4e142eSMatthew G. Knepley qgeom.J = &fegeom.J[q * coordDim * coordDim];
15412a4e142eSMatthew G. Knepley qgeom.invJ = &fegeom.invJ[q * coordDim * coordDim];
15422a4e142eSMatthew G. Knepley qgeom.detJ = &fegeom.detJ[q];
154363a3b9bcSJacob Faibussowitsch PetscCheck(fegeom.detJ[q] > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT ", point %" PetscInt_FMT, (double)fegeom.detJ[q], c, q);
1544d3a7d86cSMatthew G. Knepley if (transform) {
1545d3a7d86cSMatthew G. Knepley gcoords = &coords[coordDim * Nq];
15469566063dSJacob Faibussowitsch PetscCall(DMPlexBasisTransformApplyReal_Internal(dm, &coords[coordDim * q], PETSC_TRUE, coordDim, &coords[coordDim * q], gcoords, dm->transformCtx));
1547d3a7d86cSMatthew G. Knepley } else {
1548d3a7d86cSMatthew G. Knepley gcoords = &coords[coordDim * q];
1549d3a7d86cSMatthew G. Knepley }
15509566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(funcVal, Nc));
1551ca3d3a14SMatthew G. Knepley ierr = (*funcs[field])(coordDim, time, gcoords, Nc, funcVal, ctx);
1552e735a8a9SMatthew G. Knepley if (ierr) {
15539566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x));
15549566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &localX));
15559566063dSJacob Faibussowitsch PetscCall(PetscFree6(funcVal, interpolant, coords, fegeom.detJ, fegeom.J, fegeom.invJ));
1556e735a8a9SMatthew G. Knepley }
15579566063dSJacob Faibussowitsch if (transform) PetscCall(DMPlexBasisTransformApply_Internal(dm, &coords[coordDim * q], PETSC_FALSE, Nc, funcVal, funcVal, dm->transformCtx));
15589566063dSJacob Faibussowitsch if (id == PETSCFE_CLASSID) PetscCall(PetscFEInterpolate_Static((PetscFE)obj, &x[fieldOffset], &qgeom, q, interpolant));
15599566063dSJacob Faibussowitsch else if (id == PETSCFV_CLASSID) PetscCall(PetscFVInterpolate_Static((PetscFV)obj, &x[fieldOffset], q, interpolant));
15602df84da0SMatthew G. Knepley else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
156115496722SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) {
1562beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q * qNc + (qNc == 1 ? 0 : qc + fc)];
15639371c9d4SSatish Balay if (debug)
1564835f2295SStefano Zampini PetscCall(PetscPrintf(PETSC_COMM_SELF, " elem %" PetscInt_FMT " field %" PetscInt_FMT ",%" PetscInt_FMT " point %g %g %g diff %g (%g, %g)\n", c, field, fc, (double)(coordDim > 0 ? coords[coordDim * q] : 0), (double)(coordDim > 1 ? coords[coordDim * q + 1] : 0), (double)(coordDim > 2 ? coords[coordDim * q + 2] : 0),
15659371c9d4SSatish Balay (double)(PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc])) * wt * fegeom.detJ[q]), (double)PetscRealPart(interpolant[fc]), (double)PetscRealPart(funcVal[fc])));
15664bee2e38SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc])) * wt * fegeom.detJ[q];
1567cb1e1211SMatthew G Knepley }
1568cb1e1211SMatthew G Knepley }
15699c3cf19fSMatthew G. Knepley fieldOffset += Nb;
1570beaa55a6SMatthew G. Knepley qc += Nc;
1571cb1e1211SMatthew G Knepley }
15729566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x));
15739566063dSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(PETSC_COMM_SELF, " elem %" PetscInt_FMT " diff %g\n", c, (double)elemDiff));
1574cb1e1211SMatthew G Knepley localDiff += elemDiff;
1575cb1e1211SMatthew G Knepley }
15769566063dSJacob Faibussowitsch PetscCall(PetscFree6(funcVal, interpolant, coords, fegeom.detJ, fegeom.J, fegeom.invJ));
1577462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm)));
1578cb1e1211SMatthew G Knepley *diff = PetscSqrtReal(*diff);
15793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1580cb1e1211SMatthew G Knepley }
1581cb1e1211SMatthew G Knepley
DMComputeL2GradientDiff_Plex(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,Vec X,const PetscReal n[],PetscReal * diff)1582d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2GradientDiff_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff)
1583d71ae5a4SJacob Faibussowitsch {
15840f09c10fSMatthew G. Knepley const PetscInt debug = ((DM_Plex *)dm->data)->printL2;
1585ca3d3a14SMatthew G. Knepley DM tdm;
1586cb1e1211SMatthew G Knepley PetscSection section;
158740e14135SMatthew G. Knepley PetscQuadrature quad;
1588ca3d3a14SMatthew G. Knepley Vec localX, tv;
15899c3cf19fSMatthew G. Knepley PetscScalar *funcVal, *interpolant;
15902a4e142eSMatthew G. Knepley const PetscReal *quadWeights;
15914bee2e38SMatthew G. Knepley PetscFEGeom fegeom;
15924bee2e38SMatthew G. Knepley PetscReal *coords, *gcoords;
159340e14135SMatthew G. Knepley PetscReal localDiff = 0.0;
1594485ad865SMatthew G. Knepley PetscInt dim, coordDim, qNc = 0, Nq = 0, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset;
1595ca3d3a14SMatthew G. Knepley PetscBool transform;
1596cb1e1211SMatthew G Knepley
1597cb1e1211SMatthew G Knepley PetscFunctionBegin;
15989566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
15999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim));
16004bee2e38SMatthew G. Knepley fegeom.dimEmbed = coordDim;
16019566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
16029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields));
16039566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &localX));
16049566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX));
16059566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX));
16069566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformDM_Internal(dm, &tdm));
16079566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
16089566063dSJacob Faibussowitsch PetscCall(DMHasBasisTransform(dm, &transform));
1609652b88e8SMatthew G. Knepley for (field = 0; field < numFields; ++field) {
16100f2d7e86SMatthew G. Knepley PetscFE fe;
161140e14135SMatthew G. Knepley PetscInt Nc;
1612652b88e8SMatthew G. Knepley
16139566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, field, NULL, (PetscObject *)&fe));
16149566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quad));
16159566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc));
161640e14135SMatthew G. Knepley numComponents += Nc;
1617652b88e8SMatthew G. Knepley }
16189566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, NULL, &quadWeights));
161963a3b9bcSJacob Faibussowitsch PetscCheck(!(qNc != 1) || !(qNc != numComponents), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Quadrature components %" PetscInt_FMT " != %" PetscInt_FMT " field components", qNc, numComponents);
16209566063dSJacob Faibussowitsch /* PetscCall(DMProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX)); */
1621c9cb6370SYANG Zongze PetscCall(PetscMalloc6(numComponents, &funcVal, coordDim * (Nq + 1), &coords, coordDim * coordDim * Nq, &fegeom.J, coordDim * coordDim * Nq, &fegeom.invJ, numComponents * coordDim, &interpolant, Nq, &fegeom.detJ));
16229566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
162340e14135SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
162440e14135SMatthew G. Knepley PetscScalar *x = NULL;
162540e14135SMatthew G. Knepley PetscReal elemDiff = 0.0;
16269c3cf19fSMatthew G. Knepley PetscInt qc = 0;
1627652b88e8SMatthew G. Knepley
16289566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, quad, coords, fegeom.J, fegeom.invJ, fegeom.detJ));
162948162695SZach Atkins PetscCall(DMPlexVecGetOrientedClosure(dm, NULL, PETSC_FALSE, localX, c, 0, NULL, &x));
163040e14135SMatthew G. Knepley
16319c3cf19fSMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) {
16320f2d7e86SMatthew G. Knepley PetscFE fe;
163351259fa3SMatthew G. Knepley void *const ctx = ctxs ? ctxs[field] : NULL;
16349c3cf19fSMatthew G. Knepley PetscInt Nb, Nc, q, fc;
163540e14135SMatthew G. Knepley
16369566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, field, NULL, (PetscObject *)&fe));
16379566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
16389566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc));
163940e14135SMatthew G. Knepley if (debug) {
164040e14135SMatthew G. Knepley char title[1024];
16419566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(title, 1023, "Solution for Field %" PetscInt_FMT, field));
16429566063dSJacob Faibussowitsch PetscCall(DMPrintCellVector(c, title, Nb, &x[fieldOffset]));
1643652b88e8SMatthew G. Knepley }
16449c3cf19fSMatthew G. Knepley for (q = 0; q < Nq; ++q) {
16452a4e142eSMatthew G. Knepley PetscFEGeom qgeom;
1646d0609cedSBarry Smith PetscErrorCode ierr;
16472a4e142eSMatthew G. Knepley
16482a4e142eSMatthew G. Knepley qgeom.dimEmbed = fegeom.dimEmbed;
16492a4e142eSMatthew G. Knepley qgeom.J = &fegeom.J[q * coordDim * coordDim];
16502a4e142eSMatthew G. Knepley qgeom.invJ = &fegeom.invJ[q * coordDim * coordDim];
16512a4e142eSMatthew G. Knepley qgeom.detJ = &fegeom.detJ[q];
16522df84da0SMatthew G. Knepley PetscCheck(fegeom.detJ[q] > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT ", quadrature points %" PetscInt_FMT, (double)fegeom.detJ[q], c, q);
1653d3a7d86cSMatthew G. Knepley if (transform) {
1654d3a7d86cSMatthew G. Knepley gcoords = &coords[coordDim * Nq];
16559566063dSJacob Faibussowitsch PetscCall(DMPlexBasisTransformApplyReal_Internal(dm, &coords[coordDim * q], PETSC_TRUE, coordDim, &coords[coordDim * q], gcoords, dm->transformCtx));
1656d3a7d86cSMatthew G. Knepley } else {
1657d3a7d86cSMatthew G. Knepley gcoords = &coords[coordDim * q];
1658d3a7d86cSMatthew G. Knepley }
16599566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(funcVal, Nc));
16604bee2e38SMatthew G. Knepley ierr = (*funcs[field])(coordDim, time, gcoords, n, Nc, funcVal, ctx);
1661e735a8a9SMatthew G. Knepley if (ierr) {
16629566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x));
16639566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &localX));
16649566063dSJacob Faibussowitsch PetscCall(PetscFree6(funcVal, coords, fegeom.J, fegeom.invJ, interpolant, fegeom.detJ));
1665e735a8a9SMatthew G. Knepley }
16669566063dSJacob Faibussowitsch if (transform) PetscCall(DMPlexBasisTransformApply_Internal(dm, &coords[coordDim * q], PETSC_FALSE, Nc, funcVal, funcVal, dm->transformCtx));
16679566063dSJacob Faibussowitsch PetscCall(PetscFEInterpolateGradient_Static(fe, 1, &x[fieldOffset], &qgeom, q, interpolant));
16684bee2e38SMatthew G. Knepley /* Overwrite with the dot product if the normal is given */
16694bee2e38SMatthew G. Knepley if (n) {
16704bee2e38SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) {
16714bee2e38SMatthew G. Knepley PetscScalar sum = 0.0;
16724bee2e38SMatthew G. Knepley PetscInt d;
16734bee2e38SMatthew G. Knepley for (d = 0; d < dim; ++d) sum += interpolant[fc * dim + d] * n[d];
16744bee2e38SMatthew G. Knepley interpolant[fc] = sum;
16754bee2e38SMatthew G. Knepley }
16764bee2e38SMatthew G. Knepley }
16779c3cf19fSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) {
1678beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q * qNc + (qNc == 1 ? 0 : qc + fc)];
167963a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(PETSC_COMM_SELF, " elem %" PetscInt_FMT " fieldDer %" PetscInt_FMT ",%" PetscInt_FMT " diff %g\n", c, field, fc, (double)(PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc])) * wt * fegeom.detJ[q])));
16804bee2e38SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc])) * wt * fegeom.detJ[q];
168140e14135SMatthew G. Knepley }
168240e14135SMatthew G. Knepley }
16839c3cf19fSMatthew G. Knepley fieldOffset += Nb;
16849c3cf19fSMatthew G. Knepley qc += Nc;
168540e14135SMatthew G. Knepley }
16869566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x));
168763a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(PETSC_COMM_SELF, " elem %" PetscInt_FMT " diff %g\n", c, (double)elemDiff));
168840e14135SMatthew G. Knepley localDiff += elemDiff;
168940e14135SMatthew G. Knepley }
16909566063dSJacob Faibussowitsch PetscCall(PetscFree6(funcVal, coords, fegeom.J, fegeom.invJ, interpolant, fegeom.detJ));
16919566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &localX));
1692462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm)));
169340e14135SMatthew G. Knepley *diff = PetscSqrtReal(*diff);
16943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1695cb1e1211SMatthew G Knepley }
1696cb1e1211SMatthew G Knepley
DMComputeL2FieldDiff_Plex(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,Vec X,PetscReal * diff)1697d71ae5a4SJacob Faibussowitsch PetscErrorCode DMComputeL2FieldDiff_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff)
1698d71ae5a4SJacob Faibussowitsch {
16990f09c10fSMatthew G. Knepley const PetscInt debug = ((DM_Plex *)dm->data)->printL2;
1700ca3d3a14SMatthew G. Knepley DM tdm;
1701083401c6SMatthew G. Knepley DMLabel depthLabel;
170273d901b8SMatthew G. Knepley PetscSection section;
1703ca3d3a14SMatthew G. Knepley Vec localX, tv;
170473d901b8SMatthew G. Knepley PetscReal *localDiff;
1705083401c6SMatthew G. Knepley PetscInt dim, depth, dE, Nf, f, Nds, s;
1706ca3d3a14SMatthew G. Knepley PetscBool transform;
170773d901b8SMatthew G. Knepley
170873d901b8SMatthew G. Knepley PetscFunctionBegin;
17099566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
17109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE));
17119566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
17129566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &localX));
17139566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformDM_Internal(dm, &tdm));
17149566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
17159566063dSJacob Faibussowitsch PetscCall(DMHasBasisTransform(dm, &transform));
17169566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf));
17179566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
17189566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(depthLabel, &depth));
1719083401c6SMatthew G. Knepley
17209566063dSJacob Faibussowitsch PetscCall(VecSet(localX, 0.0));
17219566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX));
17229566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX));
17239566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLocal(dm, time, funcs, ctxs, INSERT_BC_VALUES, localX));
17249566063dSJacob Faibussowitsch PetscCall(DMGetNumDS(dm, &Nds));
17259566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nf, &localDiff));
1726083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) {
1727083401c6SMatthew G. Knepley PetscDS ds;
1728083401c6SMatthew G. Knepley DMLabel label;
1729083401c6SMatthew G. Knepley IS fieldIS, pointIS;
1730083401c6SMatthew G. Knepley const PetscInt *fields, *points = NULL;
1731083401c6SMatthew G. Knepley PetscQuadrature quad;
1732083401c6SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights;
1733083401c6SMatthew G. Knepley PetscFEGeom fegeom;
1734083401c6SMatthew G. Knepley PetscReal *coords, *gcoords;
1735083401c6SMatthew G. Knepley PetscScalar *funcVal, *interpolant;
17365fedec97SMatthew G. Knepley PetscBool isCohesive;
1737083401c6SMatthew G. Knepley PetscInt qNc, Nq, totNc, cStart = 0, cEnd, c, dsNf;
173873d901b8SMatthew G. Knepley
173907218a29SMatthew G. Knepley PetscCall(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds, NULL));
17409566063dSJacob Faibussowitsch PetscCall(ISGetIndices(fieldIS, &fields));
17419566063dSJacob Faibussowitsch PetscCall(PetscDSIsCohesive(ds, &isCohesive));
17429566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &dsNf));
17439566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &totNc));
17449566063dSJacob Faibussowitsch PetscCall(PetscDSGetQuadrature(ds, &quad));
17459566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights));
174663a3b9bcSJacob Faibussowitsch PetscCheck(!(qNc != 1) || !(qNc != totNc), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Quadrature components %" PetscInt_FMT " != %" PetscInt_FMT " field components", qNc, totNc);
17479566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(totNc, &funcVal, totNc, &interpolant, dE * (Nq + 1), &coords, Nq, &fegeom.detJ, dE * dE * Nq, &fegeom.J, dE * dE * Nq, &fegeom.invJ));
1748083401c6SMatthew G. Knepley if (!label) {
17499566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
1750083401c6SMatthew G. Knepley } else {
17519566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, 1, &pointIS));
17529566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &cEnd));
17539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points));
1754083401c6SMatthew G. Knepley }
175573d901b8SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
1756083401c6SMatthew G. Knepley const PetscInt cell = points ? points[c] : c;
175773d901b8SMatthew G. Knepley PetscScalar *x = NULL;
17585fedec97SMatthew G. Knepley const PetscInt *cone;
17595fedec97SMatthew G. Knepley PetscInt qc = 0, fOff = 0, dep;
176073d901b8SMatthew G. Knepley
17619566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, cell, &dep));
1762083401c6SMatthew G. Knepley if (dep != depth - 1) continue;
17635fedec97SMatthew G. Knepley if (isCohesive) {
17649566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cell, &cone));
17659566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cone[0], quad, coords, fegeom.J, fegeom.invJ, fegeom.detJ));
176696959cd1SMatthew G. Knepley } else {
17679566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, quad, coords, fegeom.J, fegeom.invJ, fegeom.detJ));
176896959cd1SMatthew G. Knepley }
176948162695SZach Atkins PetscCall(DMPlexVecGetOrientedClosure(dm, NULL, PETSC_FALSE, localX, cell, 0, NULL, &x));
17705fedec97SMatthew G. Knepley for (f = 0; f < dsNf; ++f) {
177115496722SMatthew G. Knepley PetscObject obj;
177215496722SMatthew G. Knepley PetscClassId id;
1773083401c6SMatthew G. Knepley void *const ctx = ctxs ? ctxs[fields[f]] : NULL;
177415496722SMatthew G. Knepley PetscInt Nb, Nc, q, fc;
177515496722SMatthew G. Knepley PetscReal elemDiff = 0.0;
17765fedec97SMatthew G. Knepley PetscBool cohesive;
177715496722SMatthew G. Knepley
17789566063dSJacob Faibussowitsch PetscCall(PetscDSGetCohesive(ds, f, &cohesive));
17799566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &obj));
17809566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
17819371c9d4SSatish Balay if (id == PETSCFE_CLASSID) {
17829371c9d4SSatish Balay PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
17839371c9d4SSatish Balay PetscCall(PetscFEGetDimension((PetscFE)obj, &Nb));
17849371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) {
17859371c9d4SSatish Balay PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
17869371c9d4SSatish Balay Nb = 1;
17879371c9d4SSatish Balay } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, fields[f]);
1788c82db6dbSMatthew G. Knepley if (isCohesive && !cohesive) {
1789c82db6dbSMatthew G. Knepley fOff += Nb * 2;
1790c82db6dbSMatthew G. Knepley qc += Nc;
1791c82db6dbSMatthew G. Knepley continue;
1792c82db6dbSMatthew G. Knepley }
179373d901b8SMatthew G. Knepley if (debug) {
179473d901b8SMatthew G. Knepley char title[1024];
179563a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(title, 1023, "Solution for Field %" PetscInt_FMT, fields[f]));
17969566063dSJacob Faibussowitsch PetscCall(DMPrintCellVector(cell, title, Nb, &x[fOff]));
179773d901b8SMatthew G. Knepley }
17987318780aSToby Isaac for (q = 0; q < Nq; ++q) {
17992a4e142eSMatthew G. Knepley PetscFEGeom qgeom;
1800d0609cedSBarry Smith PetscErrorCode ierr;
18012a4e142eSMatthew G. Knepley
18022a4e142eSMatthew G. Knepley qgeom.dimEmbed = fegeom.dimEmbed;
1803083401c6SMatthew G. Knepley qgeom.J = &fegeom.J[q * dE * dE];
1804083401c6SMatthew G. Knepley qgeom.invJ = &fegeom.invJ[q * dE * dE];
18052a4e142eSMatthew G. Knepley qgeom.detJ = &fegeom.detJ[q];
180663a3b9bcSJacob Faibussowitsch PetscCheck(fegeom.detJ[q] > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for cell %" PetscInt_FMT ", quadrature point %" PetscInt_FMT, (double)fegeom.detJ[q], cell, q);
1807d3a7d86cSMatthew G. Knepley if (transform) {
1808083401c6SMatthew G. Knepley gcoords = &coords[dE * Nq];
18099566063dSJacob Faibussowitsch PetscCall(DMPlexBasisTransformApplyReal_Internal(dm, &coords[dE * q], PETSC_TRUE, dE, &coords[dE * q], gcoords, dm->transformCtx));
1810d3a7d86cSMatthew G. Knepley } else {
1811083401c6SMatthew G. Knepley gcoords = &coords[dE * q];
1812d3a7d86cSMatthew G. Knepley }
18132df84da0SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) funcVal[fc] = 0.;
1814083401c6SMatthew G. Knepley ierr = (*funcs[fields[f]])(dE, time, gcoords, Nc, funcVal, ctx);
1815e735a8a9SMatthew G. Knepley if (ierr) {
18169566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, NULL, localX, cell, NULL, &x));
18179566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &localX));
18189566063dSJacob Faibussowitsch PetscCall(PetscFree6(funcVal, interpolant, coords, fegeom.detJ, fegeom.J, fegeom.invJ));
1819e735a8a9SMatthew G. Knepley }
18209566063dSJacob Faibussowitsch if (transform) PetscCall(DMPlexBasisTransformApply_Internal(dm, &coords[dE * q], PETSC_FALSE, Nc, funcVal, funcVal, dm->transformCtx));
182196959cd1SMatthew G. Knepley /* Call once for each face, except for lagrange field */
18229566063dSJacob Faibussowitsch if (id == PETSCFE_CLASSID) PetscCall(PetscFEInterpolate_Static((PetscFE)obj, &x[fOff], &qgeom, q, interpolant));
18239566063dSJacob Faibussowitsch else if (id == PETSCFV_CLASSID) PetscCall(PetscFVInterpolate_Static((PetscFV)obj, &x[fOff], q, interpolant));
182463a3b9bcSJacob Faibussowitsch else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, fields[f]);
182515496722SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) {
1826beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q * qNc + (qNc == 1 ? 0 : qc + fc)];
18279371c9d4SSatish Balay if (debug)
1828835f2295SStefano Zampini PetscCall(PetscPrintf(PETSC_COMM_SELF, " cell %" PetscInt_FMT " field %" PetscInt_FMT ",%" PetscInt_FMT " point %g %g %g diff %g\n", cell, fields[f], fc, (double)(dE > 0 ? coords[dE * q] : 0), (double)(dE > 1 ? coords[dE * q + 1] : 0), (double)(dE > 2 ? coords[dE * q + 2] : 0),
18299371c9d4SSatish Balay (double)(PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc])) * wt * fegeom.detJ[q])));
18304bee2e38SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc])) * wt * fegeom.detJ[q];
183173d901b8SMatthew G. Knepley }
183273d901b8SMatthew G. Knepley }
1833083401c6SMatthew G. Knepley fOff += Nb;
18349c3cf19fSMatthew G. Knepley qc += Nc;
1835083401c6SMatthew G. Knepley localDiff[fields[f]] += elemDiff;
183663a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(PETSC_COMM_SELF, " cell %" PetscInt_FMT " field %" PetscInt_FMT " cum diff %g\n", cell, fields[f], (double)localDiff[fields[f]]));
183773d901b8SMatthew G. Knepley }
18389566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, NULL, localX, cell, NULL, &x));
1839083401c6SMatthew G. Knepley }
1840083401c6SMatthew G. Knepley if (label) {
18419566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points));
18429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
1843083401c6SMatthew G. Knepley }
18449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(fieldIS, &fields));
18459566063dSJacob Faibussowitsch PetscCall(PetscFree6(funcVal, interpolant, coords, fegeom.detJ, fegeom.J, fegeom.invJ));
184673d901b8SMatthew G. Knepley }
18479566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &localX));
1848e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Allreduce(localDiff, diff, Nf, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm)));
18499566063dSJacob Faibussowitsch PetscCall(PetscFree(localDiff));
1850083401c6SMatthew G. Knepley for (f = 0; f < Nf; ++f) diff[f] = PetscSqrtReal(diff[f]);
18513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
185273d901b8SMatthew G. Knepley }
185373d901b8SMatthew G. Knepley
1854e729f68cSMatthew G. Knepley /*@C
1855e729f68cSMatthew G. Knepley DMPlexComputeL2DiffVec - This function computes the cellwise L_2 difference between a function u and an FEM interpolant solution u_h, and stores it in a Vec.
1856e729f68cSMatthew G. Knepley
185720f4b53cSBarry Smith Collective
1858c0f8e1fdSMatthew G. Knepley
1859e729f68cSMatthew G. Knepley Input Parameters:
1860a1cb98faSBarry Smith + dm - The `DM`
18610163fd50SMatthew G. Knepley . time - The time
186220f4b53cSBarry Smith . funcs - The functions to evaluate for each field component: `NULL` means that component does not contribute to error calculation
186320f4b53cSBarry Smith . ctxs - Optional array of contexts to pass to each function, or `NULL`.
1864e729f68cSMatthew G. Knepley - X - The coefficient vector u_h
1865e729f68cSMatthew G. Knepley
1866e729f68cSMatthew G. Knepley Output Parameter:
186720f4b53cSBarry Smith . D - A `Vec` which holds the difference ||u - u_h||_2 for each cell
1868e729f68cSMatthew G. Knepley
1869e729f68cSMatthew G. Knepley Level: developer
1870e729f68cSMatthew G. Knepley
18711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMProjectFunction()`, `DMComputeL2Diff()`, `DMPlexComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
1872e729f68cSMatthew G. Knepley @*/
DMPlexComputeL2DiffVec(DM dm,PetscReal time,PetscErrorCode (** funcs)(PetscInt,PetscReal,const PetscReal[],PetscInt,PetscScalar *,void *),void ** ctxs,Vec X,Vec D)1873d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeL2DiffVec(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, Vec D)
1874d71ae5a4SJacob Faibussowitsch {
1875e729f68cSMatthew G. Knepley PetscSection section;
1876e729f68cSMatthew G. Knepley PetscQuadrature quad;
1877e729f68cSMatthew G. Knepley Vec localX;
18784bee2e38SMatthew G. Knepley PetscFEGeom fegeom;
1879e729f68cSMatthew G. Knepley PetscScalar *funcVal, *interpolant;
18804bee2e38SMatthew G. Knepley PetscReal *coords;
1881e729f68cSMatthew G. Knepley const PetscReal *quadPoints, *quadWeights;
1882485ad865SMatthew G. Knepley PetscInt dim, coordDim, numFields, numComponents = 0, qNc, Nq, cStart, cEnd, c, field, fieldOffset;
1883e729f68cSMatthew G. Knepley
1884e729f68cSMatthew G. Knepley PetscFunctionBegin;
18859566063dSJacob Faibussowitsch PetscCall(VecSet(D, 0.0));
18869566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
18879566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim));
18889566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
18899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields));
18909566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &localX));
18919566063dSJacob Faibussowitsch PetscCall(DMProjectFunctionLocal(dm, time, funcs, ctxs, INSERT_BC_VALUES, localX));
18929566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX));
18939566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX));
1894e729f68cSMatthew G. Knepley for (field = 0; field < numFields; ++field) {
1895e729f68cSMatthew G. Knepley PetscObject obj;
1896e729f68cSMatthew G. Knepley PetscClassId id;
1897e729f68cSMatthew G. Knepley PetscInt Nc;
1898e729f68cSMatthew G. Knepley
18999566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, field, NULL, &obj));
19009566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
1901e729f68cSMatthew G. Knepley if (id == PETSCFE_CLASSID) {
1902e729f68cSMatthew G. Knepley PetscFE fe = (PetscFE)obj;
1903e729f68cSMatthew G. Knepley
19049566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quad));
19059566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc));
1906e729f68cSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
1907e729f68cSMatthew G. Knepley PetscFV fv = (PetscFV)obj;
1908e729f68cSMatthew G. Knepley
19099566063dSJacob Faibussowitsch PetscCall(PetscFVGetQuadrature(fv, &quad));
19109566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc));
191163a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
1912e729f68cSMatthew G. Knepley numComponents += Nc;
1913e729f68cSMatthew G. Knepley }
19149566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights));
191563a3b9bcSJacob Faibussowitsch PetscCheck(!(qNc != 1) || !(qNc != numComponents), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Quadrature components %" PetscInt_FMT " != %" PetscInt_FMT " field components", qNc, numComponents);
19169566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(numComponents, &funcVal, numComponents, &interpolant, coordDim * Nq, &coords, Nq, &fegeom.detJ, coordDim * coordDim * Nq, &fegeom.J, coordDim * coordDim * Nq, &fegeom.invJ));
19179566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
1918e729f68cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
1919e729f68cSMatthew G. Knepley PetscScalar *x = NULL;
19206f288a59SMatthew G. Knepley PetscScalar elemDiff = 0.0;
19219c3cf19fSMatthew G. Knepley PetscInt qc = 0;
1922e729f68cSMatthew G. Knepley
19239566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, quad, coords, fegeom.J, fegeom.invJ, fegeom.detJ));
192448162695SZach Atkins PetscCall(DMPlexVecGetOrientedClosure(dm, NULL, PETSC_FALSE, localX, c, 0, NULL, &x));
1925e729f68cSMatthew G. Knepley
1926e729f68cSMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) {
1927e729f68cSMatthew G. Knepley PetscObject obj;
1928e729f68cSMatthew G. Knepley PetscClassId id;
1929e729f68cSMatthew G. Knepley void *const ctx = ctxs ? ctxs[field] : NULL;
1930e729f68cSMatthew G. Knepley PetscInt Nb, Nc, q, fc;
1931e729f68cSMatthew G. Knepley
19329566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, field, NULL, &obj));
19339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
19349371c9d4SSatish Balay if (id == PETSCFE_CLASSID) {
19359371c9d4SSatish Balay PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
19369371c9d4SSatish Balay PetscCall(PetscFEGetDimension((PetscFE)obj, &Nb));
19379371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) {
19389371c9d4SSatish Balay PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
19399371c9d4SSatish Balay Nb = 1;
19409371c9d4SSatish Balay } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
194123f34ed2SToby Isaac if (funcs[field]) {
19427318780aSToby Isaac for (q = 0; q < Nq; ++q) {
19432a4e142eSMatthew G. Knepley PetscFEGeom qgeom;
19442a4e142eSMatthew G. Knepley
19452a4e142eSMatthew G. Knepley qgeom.dimEmbed = fegeom.dimEmbed;
19462a4e142eSMatthew G. Knepley qgeom.J = &fegeom.J[q * coordDim * coordDim];
19472a4e142eSMatthew G. Knepley qgeom.invJ = &fegeom.invJ[q * coordDim * coordDim];
19482a4e142eSMatthew G. Knepley qgeom.detJ = &fegeom.detJ[q];
194963a3b9bcSJacob Faibussowitsch PetscCheck(fegeom.detJ[q] > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT ", quadrature points %" PetscInt_FMT, (double)fegeom.detJ[q], c, q);
19509566063dSJacob Faibussowitsch PetscCall((*funcs[field])(coordDim, time, &coords[q * coordDim], Nc, funcVal, ctx));
1951c3e24edfSBarry Smith #if defined(needs_fix_with_return_code_argument)
1952e735a8a9SMatthew G. Knepley if (ierr) {
19539566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x));
19549566063dSJacob Faibussowitsch PetscCall(PetscFree6(funcVal, interpolant, coords, fegeom.detJ, fegeom.J, fegeom.invJ));
19559566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &localX));
1956e735a8a9SMatthew G. Knepley }
1957c3e24edfSBarry Smith #endif
19589566063dSJacob Faibussowitsch if (id == PETSCFE_CLASSID) PetscCall(PetscFEInterpolate_Static((PetscFE)obj, &x[fieldOffset], &qgeom, q, interpolant));
19599566063dSJacob Faibussowitsch else if (id == PETSCFV_CLASSID) PetscCall(PetscFVInterpolate_Static((PetscFV)obj, &x[fieldOffset], q, interpolant));
196063a3b9bcSJacob Faibussowitsch else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
1961e729f68cSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) {
1962beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q * qNc + (qNc == 1 ? 0 : qc + fc)];
19634bee2e38SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc])) * wt * fegeom.detJ[q];
1964e729f68cSMatthew G. Knepley }
1965e729f68cSMatthew G. Knepley }
196623f34ed2SToby Isaac }
1967beaa55a6SMatthew G. Knepley fieldOffset += Nb;
19689c3cf19fSMatthew G. Knepley qc += Nc;
1969e729f68cSMatthew G. Knepley }
19709566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x));
19719566063dSJacob Faibussowitsch PetscCall(VecSetValue(D, c - cStart, elemDiff, INSERT_VALUES));
1972e729f68cSMatthew G. Knepley }
19739566063dSJacob Faibussowitsch PetscCall(PetscFree6(funcVal, interpolant, coords, fegeom.detJ, fegeom.J, fegeom.invJ));
19749566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &localX));
19759566063dSJacob Faibussowitsch PetscCall(VecSqrtAbs(D));
19763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1977e729f68cSMatthew G. Knepley }
1978e729f68cSMatthew G. Knepley
19795f0b18bfSMatthew G. Knepley /*@
19802353bfffSMatthew G. Knepley DMPlexComputeL2FluxDiffVecLocal - This function computes the integral of the difference between the gradient of field `f`in `u` and field `mf` in `mu`
19812353bfffSMatthew G. Knepley
19822353bfffSMatthew G. Knepley Collective
19832353bfffSMatthew G. Knepley
19842353bfffSMatthew G. Knepley Input Parameters:
19852353bfffSMatthew G. Knepley + lu - The local `Vec` containing the primal solution
19862353bfffSMatthew G. Knepley . f - The field number for the potential
19872353bfffSMatthew G. Knepley . lmu - The local `Vec` containing the mixed solution
19882353bfffSMatthew G. Knepley - mf - The field number for the flux
19892353bfffSMatthew G. Knepley
19902353bfffSMatthew G. Knepley Output Parameter:
19912353bfffSMatthew G. Knepley . eFlux - A global `Vec` which holds $||\nabla u_f - \mu_{mf}||$
19922353bfffSMatthew G. Knepley
19932353bfffSMatthew G. Knepley Level: advanced
19942353bfffSMatthew G. Knepley
19952353bfffSMatthew G. Knepley Notes:
19962353bfffSMatthew G. Knepley We assume that the `DM` for each solution has the same topology, geometry, and quadrature.
19972353bfffSMatthew G. Knepley
19982353bfffSMatthew G. Knepley This is usually used to get an error estimate for the primal solution, using the flux from a mixed solution.
19992353bfffSMatthew G. Knepley
20002353bfffSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexComputeL2FluxDiffVec()`, `DMProjectFunction()`, `DMComputeL2Diff()`, `DMPlexComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
20012353bfffSMatthew G. Knepley @*/
DMPlexComputeL2FluxDiffVecLocal(Vec lu,PetscInt f,Vec lmu,PetscInt mf,Vec eFlux)20022353bfffSMatthew G. Knepley PetscErrorCode DMPlexComputeL2FluxDiffVecLocal(Vec lu, PetscInt f, Vec lmu, PetscInt mf, Vec eFlux)
20032353bfffSMatthew G. Knepley {
20042353bfffSMatthew G. Knepley DM dm, mdm, edm;
20052353bfffSMatthew G. Knepley PetscFE fe, mfe;
20062353bfffSMatthew G. Knepley PetscFEGeom fegeom;
20072353bfffSMatthew G. Knepley PetscQuadrature quad;
20082353bfffSMatthew G. Knepley const PetscReal *quadWeights;
20092353bfffSMatthew G. Knepley PetscReal *coords;
20102353bfffSMatthew G. Knepley PetscScalar *interpolant, *minterpolant, *earray;
20112353bfffSMatthew G. Knepley PetscInt cdim, mcdim, cStart, cEnd, Nc, mNc, qNc, Nq;
20122353bfffSMatthew G. Knepley MPI_Comm comm;
20132353bfffSMatthew G. Knepley
20142353bfffSMatthew G. Knepley PetscFunctionBegin;
20152353bfffSMatthew G. Knepley PetscCall(VecGetDM(lu, &dm));
20162353bfffSMatthew G. Knepley PetscCall(VecGetDM(lmu, &mdm));
20172353bfffSMatthew G. Knepley PetscCall(VecGetDM(eFlux, &edm));
20182353bfffSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
20192353bfffSMatthew G. Knepley PetscCall(VecSet(eFlux, 0.0));
20202353bfffSMatthew G. Knepley
20212353bfffSMatthew G. Knepley // Check if the both problems are on the same mesh
20222353bfffSMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim));
20232353bfffSMatthew G. Knepley PetscCall(DMGetCoordinateDim(mdm, &mcdim));
20242353bfffSMatthew G. Knepley PetscCheck(cdim == mcdim, comm, PETSC_ERR_ARG_SIZ, "primal coordinate Dim %" PetscInt_FMT " != %" PetscInt_FMT " mixed coordinate Dim", cdim, mcdim);
20252353bfffSMatthew G. Knepley fegeom.dimEmbed = cdim;
20262353bfffSMatthew G. Knepley
20272353bfffSMatthew G. Knepley PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe));
20282353bfffSMatthew G. Knepley PetscCall(DMGetField(mdm, mf, NULL, (PetscObject *)&mfe));
20292353bfffSMatthew G. Knepley PetscCall(PetscFEGetNumComponents(fe, &Nc));
20302353bfffSMatthew G. Knepley PetscCall(PetscFEGetNumComponents(mfe, &mNc));
20312353bfffSMatthew G. Knepley PetscCall(PetscFEGetQuadrature(fe, &quad));
20322353bfffSMatthew G. Knepley PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, NULL, &quadWeights));
20332353bfffSMatthew G. Knepley PetscCheck(qNc == 1 || qNc == mNc, comm, PETSC_ERR_ARG_SIZ, "Quadrature components %" PetscInt_FMT " != %" PetscInt_FMT " field components", qNc, mNc);
20342353bfffSMatthew G. Knepley
20352353bfffSMatthew G. Knepley PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
20362353bfffSMatthew G. Knepley PetscCall(VecGetArrayWrite(eFlux, &earray));
20372353bfffSMatthew G. Knepley PetscCall(PetscMalloc6(Nc * cdim, &interpolant, mNc * cdim, &minterpolant, cdim * (Nq + 1), &coords, cdim * cdim * Nq, &fegeom.J, cdim * cdim * Nq, &fegeom.invJ, Nq, &fegeom.detJ));
20382353bfffSMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
20392353bfffSMatthew G. Knepley PetscScalar *x = NULL;
20402353bfffSMatthew G. Knepley PetscScalar *mx = NULL;
20412353bfffSMatthew G. Knepley PetscScalar *eval = NULL;
20422353bfffSMatthew G. Knepley PetscReal fluxElemDiff = 0.0;
20432353bfffSMatthew G. Knepley
20442353bfffSMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFEM(dm, c, quad, coords, fegeom.J, fegeom.invJ, fegeom.detJ));
20452353bfffSMatthew G. Knepley PetscCall(DMPlexVecGetClosure(dm, NULL, lu, c, NULL, &x));
20462353bfffSMatthew G. Knepley PetscCall(DMPlexVecGetClosure(mdm, NULL, lmu, c, NULL, &mx));
20472353bfffSMatthew G. Knepley
20482353bfffSMatthew G. Knepley for (PetscInt q = 0; q < Nq; ++q) {
20492353bfffSMatthew G. Knepley PetscFEGeom qgeom;
20502353bfffSMatthew G. Knepley
20512353bfffSMatthew G. Knepley qgeom.dimEmbed = fegeom.dimEmbed;
20522353bfffSMatthew G. Knepley qgeom.J = &fegeom.J[q * cdim * cdim];
20532353bfffSMatthew G. Knepley qgeom.invJ = &fegeom.invJ[q * cdim * cdim];
20542353bfffSMatthew G. Knepley qgeom.detJ = &fegeom.detJ[q];
20552353bfffSMatthew G. Knepley
20562353bfffSMatthew G. Knepley PetscCheck(fegeom.detJ[q] > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT ", quadrature points %" PetscInt_FMT, (double)fegeom.detJ[q], c, q);
20572353bfffSMatthew G. Knepley
20582353bfffSMatthew G. Knepley PetscCall(PetscFEInterpolate_Static(mfe, &mx[0], &qgeom, q, minterpolant));
20592353bfffSMatthew G. Knepley PetscCall(PetscFEInterpolateGradient_Static(fe, 1, &x[0], &qgeom, q, interpolant));
20602353bfffSMatthew G. Knepley
20612353bfffSMatthew G. Knepley /* Now take the elementwise difference and store that in a vector. */
20622353bfffSMatthew G. Knepley for (PetscInt fc = 0; fc < mNc; ++fc) {
20632353bfffSMatthew G. Knepley const PetscReal wt = quadWeights[q * qNc + (qNc == 1 ? 0 : fc)];
20642353bfffSMatthew G. Knepley fluxElemDiff += PetscSqr(PetscRealPart(interpolant[fc] - minterpolant[fc])) * wt * fegeom.detJ[q];
20652353bfffSMatthew G. Knepley }
20662353bfffSMatthew G. Knepley }
20672353bfffSMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(dm, NULL, lu, c, NULL, &x));
20682353bfffSMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(mdm, NULL, lmu, c, NULL, &mx));
20692353bfffSMatthew G. Knepley PetscCall(DMPlexPointGlobalRef(edm, c, earray, (void *)&eval));
20702353bfffSMatthew G. Knepley if (eval) eval[0] = fluxElemDiff;
20712353bfffSMatthew G. Knepley }
20722353bfffSMatthew G. Knepley PetscCall(PetscFree6(interpolant, minterpolant, coords, fegeom.detJ, fegeom.J, fegeom.invJ));
20732353bfffSMatthew G. Knepley PetscCall(VecRestoreArrayWrite(eFlux, &earray));
20742353bfffSMatthew G. Knepley
20752353bfffSMatthew G. Knepley PetscCall(VecAssemblyBegin(eFlux));
20762353bfffSMatthew G. Knepley PetscCall(VecAssemblyEnd(eFlux));
20772353bfffSMatthew G. Knepley PetscCall(VecSqrtAbs(eFlux));
20782353bfffSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
20792353bfffSMatthew G. Knepley }
20802353bfffSMatthew G. Knepley
20812353bfffSMatthew G. Knepley /*@
20822353bfffSMatthew G. Knepley DMPlexComputeL2FluxDiffVec - This function computes the integral of the difference between the gradient of field `f`in `u` and field `mf` in `mu`
20832353bfffSMatthew G. Knepley
20842353bfffSMatthew G. Knepley Collective
20852353bfffSMatthew G. Knepley
20862353bfffSMatthew G. Knepley Input Parameters:
20872353bfffSMatthew G. Knepley + u - The global `Vec` containing the primal solution
20882353bfffSMatthew G. Knepley . f - The field number for the potential
20892353bfffSMatthew G. Knepley . mu - The global `Vec` containing the mixed solution
20902353bfffSMatthew G. Knepley - mf - The field number for the flux
20912353bfffSMatthew G. Knepley
20922353bfffSMatthew G. Knepley Output Parameter:
20932353bfffSMatthew G. Knepley . eFlux - A global `Vec` which holds $||\nabla u_f - \mu_{mf}||$
20942353bfffSMatthew G. Knepley
20952353bfffSMatthew G. Knepley Level: advanced
20962353bfffSMatthew G. Knepley
20972353bfffSMatthew G. Knepley Notes:
20982353bfffSMatthew G. Knepley We assume that the `DM` for each solution has the same topology, geometry, and quadrature.
20992353bfffSMatthew G. Knepley
21002353bfffSMatthew G. Knepley This is usually used to get an error estimate for the primal solution, using the flux from a mixed solution.
21012353bfffSMatthew G. Knepley
21022353bfffSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexComputeL2FluxDiffVecLocal()`, `DMProjectFunction()`, `DMComputeL2Diff()`, `DMPlexComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
21032353bfffSMatthew G. Knepley @*/
DMPlexComputeL2FluxDiffVec(Vec u,PetscInt f,Vec mu,PetscInt mf,Vec eFlux)21042353bfffSMatthew G. Knepley PetscErrorCode DMPlexComputeL2FluxDiffVec(Vec u, PetscInt f, Vec mu, PetscInt mf, Vec eFlux)
21052353bfffSMatthew G. Knepley {
21062353bfffSMatthew G. Knepley DM dm, mdm;
21072353bfffSMatthew G. Knepley Vec lu, lmu;
21082353bfffSMatthew G. Knepley
21092353bfffSMatthew G. Knepley PetscFunctionBegin;
21102353bfffSMatthew G. Knepley PetscCall(VecGetDM(u, &dm));
21112353bfffSMatthew G. Knepley PetscCall(DMGetLocalVector(dm, &lu));
21122353bfffSMatthew G. Knepley PetscCall(DMGlobalToLocal(dm, u, INSERT_VALUES, lu));
21132353bfffSMatthew G. Knepley PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, lu, 0.0, NULL, NULL, NULL));
21142353bfffSMatthew G. Knepley
21152353bfffSMatthew G. Knepley PetscCall(VecGetDM(mu, &mdm));
21162353bfffSMatthew G. Knepley PetscCall(DMGetLocalVector(mdm, &lmu));
21172353bfffSMatthew G. Knepley PetscCall(DMGlobalToLocal(mdm, mu, INSERT_VALUES, lmu));
21182353bfffSMatthew G. Knepley PetscCall(DMPlexInsertBoundaryValues(mdm, PETSC_TRUE, lmu, 0.0, NULL, NULL, NULL));
21192353bfffSMatthew G. Knepley
21202353bfffSMatthew G. Knepley PetscCall(DMPlexComputeL2FluxDiffVecLocal(lu, f, lmu, mf, eFlux));
21212353bfffSMatthew G. Knepley
21222353bfffSMatthew G. Knepley PetscCall(DMRestoreLocalVector(dm, &lu));
21232353bfffSMatthew G. Knepley PetscCall(DMRestoreLocalVector(mdm, &lmu));
21242353bfffSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
21252353bfffSMatthew G. Knepley }
21262353bfffSMatthew G. Knepley
21272353bfffSMatthew G. Knepley /*@
212820f4b53cSBarry Smith DMPlexComputeClementInterpolant - This function computes the L2 projection of the cellwise values of a function u onto P1
21295f0b18bfSMatthew G. Knepley
213020f4b53cSBarry Smith Collective
21315f0b18bfSMatthew G. Knepley
21325f0b18bfSMatthew G. Knepley Input Parameters:
2133a1cb98faSBarry Smith + dm - The `DM`
21345f0b18bfSMatthew G. Knepley - locX - The coefficient vector u_h
21355f0b18bfSMatthew G. Knepley
21365f0b18bfSMatthew G. Knepley Output Parameter:
2137a1cb98faSBarry Smith . locC - A `Vec` which holds the Clement interpolant of the function
21385f0b18bfSMatthew G. Knepley
21395f0b18bfSMatthew G. Knepley Level: developer
21405f0b18bfSMatthew G. Knepley
2141a1cb98faSBarry Smith Note:
2142a1cb98faSBarry Smith $ u_h(v_i) = \sum_{T_i \in support(v_i)} |T_i| u_h(T_i) / \sum_{T_i \in support(v_i)} |T_i| $ where $ |T_i| $ is the cell volume
2143a1cb98faSBarry Smith
21441cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMProjectFunction()`, `DMComputeL2Diff()`, `DMPlexComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
21455f0b18bfSMatthew G. Knepley @*/
DMPlexComputeClementInterpolant(DM dm,Vec locX,Vec locC)2146d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeClementInterpolant(DM dm, Vec locX, Vec locC)
2147d71ae5a4SJacob Faibussowitsch {
21485f0b18bfSMatthew G. Knepley PetscInt debug = ((DM_Plex *)dm->data)->printFEM;
21495f0b18bfSMatthew G. Knepley DM dmc;
21505f0b18bfSMatthew G. Knepley PetscQuadrature quad;
21515f0b18bfSMatthew G. Knepley PetscScalar *interpolant, *valsum;
21525f0b18bfSMatthew G. Knepley PetscFEGeom fegeom;
21535f0b18bfSMatthew G. Knepley PetscReal *coords;
21545f0b18bfSMatthew G. Knepley const PetscReal *quadPoints, *quadWeights;
21555f0b18bfSMatthew G. Knepley PetscInt dim, cdim, Nf, f, Nc = 0, Nq, qNc, cStart, cEnd, vStart, vEnd, v;
21565f0b18bfSMatthew G. Knepley
21575f0b18bfSMatthew G. Knepley PetscFunctionBegin;
21589566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(ClementCitation, &Clementcite));
21599566063dSJacob Faibussowitsch PetscCall(VecGetDM(locC, &dmc));
21609566063dSJacob Faibussowitsch PetscCall(VecSet(locC, 0.0));
21619566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
21629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim));
21635f0b18bfSMatthew G. Knepley fegeom.dimEmbed = cdim;
21649566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf));
21655f0b18bfSMatthew G. Knepley PetscCheck(Nf > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of fields is zero!");
21665f0b18bfSMatthew G. Knepley for (f = 0; f < Nf; ++f) {
21675f0b18bfSMatthew G. Knepley PetscObject obj;
21685f0b18bfSMatthew G. Knepley PetscClassId id;
21695f0b18bfSMatthew G. Knepley PetscInt fNc;
21705f0b18bfSMatthew G. Knepley
21719566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, &obj));
21729566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
21735f0b18bfSMatthew G. Knepley if (id == PETSCFE_CLASSID) {
21745f0b18bfSMatthew G. Knepley PetscFE fe = (PetscFE)obj;
21755f0b18bfSMatthew G. Knepley
21769566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quad));
21779566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &fNc));
21785f0b18bfSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
21795f0b18bfSMatthew G. Knepley PetscFV fv = (PetscFV)obj;
21805f0b18bfSMatthew G. Knepley
21819566063dSJacob Faibussowitsch PetscCall(PetscFVGetQuadrature(fv, &quad));
21829566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &fNc));
218363a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
21845f0b18bfSMatthew G. Knepley Nc += fNc;
21855f0b18bfSMatthew G. Knepley }
21869566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights));
218763a3b9bcSJacob Faibussowitsch PetscCheck(qNc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Quadrature components %" PetscInt_FMT " > 1", qNc);
21889566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(Nc * 2, &valsum, Nc, &interpolant, cdim * Nq, &coords, Nq, &fegeom.detJ, cdim * cdim * Nq, &fegeom.J, cdim * cdim * Nq, &fegeom.invJ));
21899566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
21909566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
21915f0b18bfSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) {
21925f0b18bfSMatthew G. Knepley PetscScalar volsum = 0.0;
21935f0b18bfSMatthew G. Knepley PetscInt *star = NULL;
21945f0b18bfSMatthew G. Knepley PetscInt starSize, st, fc;
21955f0b18bfSMatthew G. Knepley
21969566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(valsum, Nc));
21979566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star));
21985f0b18bfSMatthew G. Knepley for (st = 0; st < starSize * 2; st += 2) {
21995f0b18bfSMatthew G. Knepley const PetscInt cell = star[st];
22005f0b18bfSMatthew G. Knepley PetscScalar *val = &valsum[Nc];
22015f0b18bfSMatthew G. Knepley PetscScalar *x = NULL;
22025f0b18bfSMatthew G. Knepley PetscReal vol = 0.0;
22035f0b18bfSMatthew G. Knepley PetscInt foff = 0;
22045f0b18bfSMatthew G. Knepley
22055f0b18bfSMatthew G. Knepley if ((cell < cStart) || (cell >= cEnd)) continue;
22069566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, quad, coords, fegeom.J, fegeom.invJ, fegeom.detJ));
22079566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, NULL, locX, cell, NULL, &x));
22085f0b18bfSMatthew G. Knepley for (f = 0; f < Nf; ++f) {
22095f0b18bfSMatthew G. Knepley PetscObject obj;
22105f0b18bfSMatthew G. Knepley PetscClassId id;
22115f0b18bfSMatthew G. Knepley PetscInt Nb, fNc, q;
22125f0b18bfSMatthew G. Knepley
22139566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(val, Nc));
22149566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, &obj));
22159566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
22169371c9d4SSatish Balay if (id == PETSCFE_CLASSID) {
22179371c9d4SSatish Balay PetscCall(PetscFEGetNumComponents((PetscFE)obj, &fNc));
22189371c9d4SSatish Balay PetscCall(PetscFEGetDimension((PetscFE)obj, &Nb));
22199371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) {
22209371c9d4SSatish Balay PetscCall(PetscFVGetNumComponents((PetscFV)obj, &fNc));
22219371c9d4SSatish Balay Nb = 1;
22229371c9d4SSatish Balay } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
22235f0b18bfSMatthew G. Knepley for (q = 0; q < Nq; ++q) {
22245f0b18bfSMatthew G. Knepley const PetscReal wt = quadWeights[q] * fegeom.detJ[q];
22255f0b18bfSMatthew G. Knepley PetscFEGeom qgeom;
22265f0b18bfSMatthew G. Knepley
22275f0b18bfSMatthew G. Knepley qgeom.dimEmbed = fegeom.dimEmbed;
22285f0b18bfSMatthew G. Knepley qgeom.J = &fegeom.J[q * cdim * cdim];
22295f0b18bfSMatthew G. Knepley qgeom.invJ = &fegeom.invJ[q * cdim * cdim];
22305f0b18bfSMatthew G. Knepley qgeom.detJ = &fegeom.detJ[q];
223163a3b9bcSJacob Faibussowitsch PetscCheck(fegeom.detJ[q] > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT ", quadrature points %" PetscInt_FMT, (double)fegeom.detJ[q], cell, q);
2232966bd95aSPierre Jolivet PetscCheck(id == PETSCFE_CLASSID, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
2233966bd95aSPierre Jolivet PetscCall(PetscFEInterpolate_Static((PetscFE)obj, &x[foff], &qgeom, q, interpolant));
22345f0b18bfSMatthew G. Knepley for (fc = 0; fc < fNc; ++fc) val[foff + fc] += interpolant[fc] * wt;
22355f0b18bfSMatthew G. Knepley vol += wt;
22365f0b18bfSMatthew G. Knepley }
22375f0b18bfSMatthew G. Knepley foff += Nb;
22385f0b18bfSMatthew G. Knepley }
22399566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, NULL, locX, cell, NULL, &x));
22405f0b18bfSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) valsum[fc] += val[fc];
22415f0b18bfSMatthew G. Knepley volsum += vol;
22425f0b18bfSMatthew G. Knepley if (debug) {
22439566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "Vertex %" PetscInt_FMT " Cell %" PetscInt_FMT " value: [", v, cell));
22445f0b18bfSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) {
22459566063dSJacob Faibussowitsch if (fc) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", "));
22469566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", (double)PetscRealPart(val[fc])));
22475f0b18bfSMatthew G. Knepley }
22489566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "]\n"));
22495f0b18bfSMatthew G. Knepley }
22505f0b18bfSMatthew G. Knepley }
22515f0b18bfSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) valsum[fc] /= volsum;
22529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star));
22539566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(dmc, NULL, locC, v, valsum, INSERT_VALUES));
22545f0b18bfSMatthew G. Knepley }
22559566063dSJacob Faibussowitsch PetscCall(PetscFree6(valsum, interpolant, coords, fegeom.detJ, fegeom.J, fegeom.invJ));
22563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
22575f0b18bfSMatthew G. Knepley }
22585f0b18bfSMatthew G. Knepley
22595f0b18bfSMatthew G. Knepley /*@
226020f4b53cSBarry Smith DMPlexComputeGradientClementInterpolant - This function computes the L2 projection of the cellwise gradient of a function u onto P1
22611555c271SMatthew G. Knepley
226220f4b53cSBarry Smith Collective
2263c0f8e1fdSMatthew G. Knepley
22641555c271SMatthew G. Knepley Input Parameters:
2265a1cb98faSBarry Smith + dm - The `DM`
22665f0b18bfSMatthew G. Knepley - locX - The coefficient vector u_h
22671555c271SMatthew G. Knepley
22681555c271SMatthew G. Knepley Output Parameter:
2269a1cb98faSBarry Smith . locC - A `Vec` which holds the Clement interpolant of the gradient
22701555c271SMatthew G. Knepley
22711555c271SMatthew G. Knepley Level: developer
22721555c271SMatthew G. Knepley
2273a1cb98faSBarry Smith Note:
2274a1cb98faSBarry Smith $\nabla u_h(v_i) = \sum_{T_i \in support(v_i)} |T_i| \nabla u_h(T_i) / \sum_{T_i \in support(v_i)} |T_i| $ where $ |T_i| $ is the cell volume
2275a1cb98faSBarry Smith
22761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMProjectFunction()`, `DMComputeL2Diff()`, `DMPlexComputeL2FieldDiff()`, `DMComputeL2GradientDiff()`
22771555c271SMatthew G. Knepley @*/
DMPlexComputeGradientClementInterpolant(DM dm,Vec locX,Vec locC)2278d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeGradientClementInterpolant(DM dm, Vec locX, Vec locC)
2279d71ae5a4SJacob Faibussowitsch {
2280db1066baSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
2281db1066baSMatthew G. Knepley PetscInt debug = mesh->printFEM;
22821555c271SMatthew G. Knepley DM dmC;
22831555c271SMatthew G. Knepley PetscQuadrature quad;
22841555c271SMatthew G. Knepley PetscScalar *interpolant, *gradsum;
22854bee2e38SMatthew G. Knepley PetscFEGeom fegeom;
22864bee2e38SMatthew G. Knepley PetscReal *coords;
22871555c271SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights;
2288485ad865SMatthew G. Knepley PetscInt dim, coordDim, numFields, numComponents = 0, qNc, Nq, cStart, cEnd, vStart, vEnd, v, field, fieldOffset;
22891555c271SMatthew G. Knepley
22901555c271SMatthew G. Knepley PetscFunctionBegin;
22919566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(ClementCitation, &Clementcite));
22929566063dSJacob Faibussowitsch PetscCall(VecGetDM(locC, &dmC));
22939566063dSJacob Faibussowitsch PetscCall(VecSet(locC, 0.0));
22949566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
22959566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &coordDim));
22964bee2e38SMatthew G. Knepley fegeom.dimEmbed = coordDim;
22979566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields));
22985f80ce2aSJacob Faibussowitsch PetscCheck(numFields, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of fields is zero!");
22991555c271SMatthew G. Knepley for (field = 0; field < numFields; ++field) {
23001555c271SMatthew G. Knepley PetscObject obj;
23011555c271SMatthew G. Knepley PetscClassId id;
23021555c271SMatthew G. Knepley PetscInt Nc;
23031555c271SMatthew G. Knepley
23049566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, field, NULL, &obj));
23059566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
23061555c271SMatthew G. Knepley if (id == PETSCFE_CLASSID) {
23071555c271SMatthew G. Knepley PetscFE fe = (PetscFE)obj;
23081555c271SMatthew G. Knepley
23099566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quad));
23109566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc));
23111555c271SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
23121555c271SMatthew G. Knepley PetscFV fv = (PetscFV)obj;
23131555c271SMatthew G. Knepley
23149566063dSJacob Faibussowitsch PetscCall(PetscFVGetQuadrature(fv, &quad));
23159566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc));
231663a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
23171555c271SMatthew G. Knepley numComponents += Nc;
23181555c271SMatthew G. Knepley }
23199566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights));
232063a3b9bcSJacob Faibussowitsch PetscCheck(!(qNc != 1) || !(qNc != numComponents), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Quadrature components %" PetscInt_FMT " != %" PetscInt_FMT " field components", qNc, numComponents);
23219566063dSJacob Faibussowitsch PetscCall(PetscMalloc6(coordDim * numComponents * 2, &gradsum, coordDim * numComponents, &interpolant, coordDim * Nq, &coords, Nq, &fegeom.detJ, coordDim * coordDim * Nq, &fegeom.J, coordDim * coordDim * Nq, &fegeom.invJ));
23229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
23239566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
23241555c271SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) {
23251555c271SMatthew G. Knepley PetscScalar volsum = 0.0;
23261555c271SMatthew G. Knepley PetscInt *star = NULL;
23271555c271SMatthew G. Knepley PetscInt starSize, st, d, fc;
23281555c271SMatthew G. Knepley
23299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gradsum, coordDim * numComponents));
23309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star));
23311555c271SMatthew G. Knepley for (st = 0; st < starSize * 2; st += 2) {
23321555c271SMatthew G. Knepley const PetscInt cell = star[st];
23331555c271SMatthew G. Knepley PetscScalar *grad = &gradsum[coordDim * numComponents];
23341555c271SMatthew G. Knepley PetscScalar *x = NULL;
23351555c271SMatthew G. Knepley PetscReal vol = 0.0;
23361555c271SMatthew G. Knepley
23371555c271SMatthew G. Knepley if ((cell < cStart) || (cell >= cEnd)) continue;
23389566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, quad, coords, fegeom.J, fegeom.invJ, fegeom.detJ));
23399566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, NULL, locX, cell, NULL, &x));
23401555c271SMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) {
23411555c271SMatthew G. Knepley PetscObject obj;
23421555c271SMatthew G. Knepley PetscClassId id;
23431555c271SMatthew G. Knepley PetscInt Nb, Nc, q, qc = 0;
23441555c271SMatthew G. Knepley
23459566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(grad, coordDim * numComponents));
23469566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, field, NULL, &obj));
23479566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
23489371c9d4SSatish Balay if (id == PETSCFE_CLASSID) {
23499371c9d4SSatish Balay PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
23509371c9d4SSatish Balay PetscCall(PetscFEGetDimension((PetscFE)obj, &Nb));
23519371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) {
23529371c9d4SSatish Balay PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
23539371c9d4SSatish Balay Nb = 1;
23549371c9d4SSatish Balay } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
23551555c271SMatthew G. Knepley for (q = 0; q < Nq; ++q) {
23562a4e142eSMatthew G. Knepley PetscFEGeom qgeom;
23572a4e142eSMatthew G. Knepley
23582a4e142eSMatthew G. Knepley qgeom.dimEmbed = fegeom.dimEmbed;
23592a4e142eSMatthew G. Knepley qgeom.J = &fegeom.J[q * coordDim * coordDim];
23602a4e142eSMatthew G. Knepley qgeom.invJ = &fegeom.invJ[q * coordDim * coordDim];
23612a4e142eSMatthew G. Knepley qgeom.detJ = &fegeom.detJ[q];
236263a3b9bcSJacob Faibussowitsch PetscCheck(fegeom.detJ[q] > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT ", quadrature points %" PetscInt_FMT, (double)fegeom.detJ[q], cell, q);
2363966bd95aSPierre Jolivet PetscCheck(id == PETSCFE_CLASSID, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
2364966bd95aSPierre Jolivet PetscCall(PetscFEInterpolateGradient_Static((PetscFE)obj, 1, &x[fieldOffset], &qgeom, q, interpolant));
23651555c271SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) {
236653d2db2dSJoe Wallwork const PetscReal wt = quadWeights[q * qNc + qc];
23671555c271SMatthew G. Knepley
23684bee2e38SMatthew G. Knepley for (d = 0; d < coordDim; ++d) grad[fc * coordDim + d] += interpolant[fc * dim + d] * wt * fegeom.detJ[q];
23691555c271SMatthew G. Knepley }
23704bee2e38SMatthew G. Knepley vol += quadWeights[q * qNc] * fegeom.detJ[q];
23711555c271SMatthew G. Knepley }
23721555c271SMatthew G. Knepley fieldOffset += Nb;
23731555c271SMatthew G. Knepley qc += Nc;
23741555c271SMatthew G. Knepley }
23759566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, NULL, locX, cell, NULL, &x));
2376f8527842SMatthew G. Knepley for (fc = 0; fc < numComponents; ++fc) {
2377ad540459SPierre Jolivet for (d = 0; d < coordDim; ++d) gradsum[fc * coordDim + d] += grad[fc * coordDim + d];
2378f8527842SMatthew G. Knepley }
2379f8527842SMatthew G. Knepley volsum += vol;
2380db1066baSMatthew G. Knepley if (debug) {
23819566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "Vertex %" PetscInt_FMT " Cell %" PetscInt_FMT " gradient: [", v, cell));
23821555c271SMatthew G. Knepley for (fc = 0; fc < numComponents; ++fc) {
23831555c271SMatthew G. Knepley for (d = 0; d < coordDim; ++d) {
23849566063dSJacob Faibussowitsch if (fc || d > 0) PetscCall(PetscPrintf(PETSC_COMM_SELF, ", "));
23859566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g", (double)PetscRealPart(grad[fc * coordDim + d])));
23861555c271SMatthew G. Knepley }
23871555c271SMatthew G. Knepley }
23889566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "]\n"));
2389db1066baSMatthew G. Knepley }
23901555c271SMatthew G. Knepley }
23911555c271SMatthew G. Knepley for (fc = 0; fc < numComponents; ++fc) {
23921555c271SMatthew G. Knepley for (d = 0; d < coordDim; ++d) gradsum[fc * coordDim + d] /= volsum;
23931555c271SMatthew G. Knepley }
23949566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star));
23959566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(dmC, NULL, locC, v, gradsum, INSERT_VALUES));
23961555c271SMatthew G. Knepley }
23979566063dSJacob Faibussowitsch PetscCall(PetscFree6(gradsum, interpolant, coords, fegeom.detJ, fegeom.J, fegeom.invJ));
23983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
23991555c271SMatthew G. Knepley }
24001555c271SMatthew G. Knepley
DMPlexComputeIntegral_Internal(DM dm,Vec locX,PetscInt cStart,PetscInt cEnd,PetscScalar * cintegral,PetscCtx ctx)2401*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeIntegral_Internal(DM dm, Vec locX, PetscInt cStart, PetscInt cEnd, PetscScalar *cintegral, PetscCtx ctx)
2402d71ae5a4SJacob Faibussowitsch {
2403cbf8eb3cSStefano Zampini DM dmAux = NULL, plexA = NULL;
240461aaff12SToby Isaac PetscDS prob, probAux = NULL;
240573d901b8SMatthew G. Knepley PetscSection section, sectionAux;
24066493148fSStefano Zampini Vec locA;
2407c330f8ffSToby Isaac PetscInt dim, numCells = cEnd - cStart, c, f;
2408c330f8ffSToby Isaac PetscBool useFVM = PETSC_FALSE;
2409338f77d5SMatthew G. Knepley /* DS */
2410338f77d5SMatthew G. Knepley PetscInt Nf, totDim, *uOff, *uOff_x, numConstants;
2411338f77d5SMatthew G. Knepley PetscInt NfAux, totDimAux, *aOff;
24128e3a54c0SPierre Jolivet PetscScalar *u, *a = NULL;
2413338f77d5SMatthew G. Knepley const PetscScalar *constants;
2414338f77d5SMatthew G. Knepley /* Geometry */
2415c330f8ffSToby Isaac PetscFEGeom *cgeomFEM;
2416338f77d5SMatthew G. Knepley DM dmGrad;
2417c330f8ffSToby Isaac PetscQuadrature affineQuad = NULL;
2418338f77d5SMatthew G. Knepley Vec cellGeometryFVM = NULL, faceGeometryFVM = NULL, locGrad = NULL;
2419b5a3613cSMatthew G. Knepley PetscFVCellGeom *cgeomFVM;
2420338f77d5SMatthew G. Knepley const PetscScalar *lgrad;
2421b7260050SToby Isaac PetscInt maxDegree;
2422c330f8ffSToby Isaac DMField coordField;
2423c330f8ffSToby Isaac IS cellIS;
242473d901b8SMatthew G. Knepley
242573d901b8SMatthew G. Knepley PetscFunctionBegin;
24269566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
24279566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
24289566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
24299566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf));
2430338f77d5SMatthew G. Knepley /* Determine which discretizations we have */
2431b5a3613cSMatthew G. Knepley for (f = 0; f < Nf; ++f) {
2432b5a3613cSMatthew G. Knepley PetscObject obj;
2433b5a3613cSMatthew G. Knepley PetscClassId id;
2434b5a3613cSMatthew G. Knepley
24359566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, &obj));
24369566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
2437338f77d5SMatthew G. Knepley if (id == PETSCFV_CLASSID) useFVM = PETSC_TRUE;
2438338f77d5SMatthew G. Knepley }
2439338f77d5SMatthew G. Knepley /* Read DS information */
24409566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim));
24419566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(prob, &uOff));
24429566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(prob, &uOff_x));
24439566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, numCells, cStart, 1, &cellIS));
24449566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(prob, &numConstants, &constants));
2445338f77d5SMatthew G. Knepley /* Read Auxiliary DS information */
24469566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, NULL, 0, 0, &locA));
24479a2a23afSMatthew G. Knepley if (locA) {
24489566063dSJacob Faibussowitsch PetscCall(VecGetDM(locA, &dmAux));
2449cbf8eb3cSStefano Zampini PetscCall(DMConvert(dmAux, DMPLEX, &plexA));
24509566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmAux, &probAux));
24519566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(probAux, &NfAux));
24529566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmAux, §ionAux));
24539566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(probAux, &totDimAux));
24549566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(probAux, &aOff));
2455338f77d5SMatthew G. Knepley }
2456338f77d5SMatthew G. Knepley /* Allocate data arrays */
24579566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numCells * totDim, &u));
24589566063dSJacob Faibussowitsch if (dmAux) PetscCall(PetscMalloc1(numCells * totDimAux, &a));
2459338f77d5SMatthew G. Knepley /* Read out geometry */
24609566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
24619566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, cellIS, NULL, &maxDegree));
2462b7260050SToby Isaac if (maxDegree <= 1) {
24639566063dSJacob Faibussowitsch PetscCall(DMFieldCreateDefaultQuadrature(coordField, cellIS, &affineQuad));
2464ac9d17c7SMatthew G. Knepley if (affineQuad) PetscCall(DMFieldCreateFEGeom(coordField, cellIS, affineQuad, PETSC_FEGEOM_BASIC, &cgeomFEM));
2465b5a3613cSMatthew G. Knepley }
2466b5a3613cSMatthew G. Knepley if (useFVM) {
2467338f77d5SMatthew G. Knepley PetscFV fv = NULL;
2468b5a3613cSMatthew G. Knepley Vec grad;
2469b5a3613cSMatthew G. Knepley PetscInt fStart, fEnd;
2470b5a3613cSMatthew G. Knepley PetscBool compGrad;
2471b5a3613cSMatthew G. Knepley
2472338f77d5SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
2473338f77d5SMatthew G. Knepley PetscObject obj;
2474338f77d5SMatthew G. Knepley PetscClassId id;
2475338f77d5SMatthew G. Knepley
24769566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, &obj));
24779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
24789371c9d4SSatish Balay if (id == PETSCFV_CLASSID) {
24799371c9d4SSatish Balay fv = (PetscFV)obj;
24809371c9d4SSatish Balay break;
24819371c9d4SSatish Balay }
2482338f77d5SMatthew G. Knepley }
24839566063dSJacob Faibussowitsch PetscCall(PetscFVGetComputeGradients(fv, &compGrad));
24849566063dSJacob Faibussowitsch PetscCall(PetscFVSetComputeGradients(fv, PETSC_TRUE));
24859566063dSJacob Faibussowitsch PetscCall(DMPlexComputeGeometryFVM(dm, &cellGeometryFVM, &faceGeometryFVM));
24869566063dSJacob Faibussowitsch PetscCall(DMPlexComputeGradientFVM(dm, fv, faceGeometryFVM, cellGeometryFVM, &dmGrad));
24879566063dSJacob Faibussowitsch PetscCall(PetscFVSetComputeGradients(fv, compGrad));
24889566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeometryFVM, (const PetscScalar **)&cgeomFVM));
2489b5a3613cSMatthew G. Knepley /* Reconstruct and limit cell gradients */
24909566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
24919566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmGrad, &grad));
24929566063dSJacob Faibussowitsch PetscCall(DMPlexReconstructGradients_Internal(dm, fv, fStart, fEnd, faceGeometryFVM, cellGeometryFVM, locX, grad));
2493b5a3613cSMatthew G. Knepley /* Communicate gradient values */
24949566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmGrad, &locGrad));
24959566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmGrad, grad, INSERT_VALUES, locGrad));
24969566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmGrad, grad, INSERT_VALUES, locGrad));
24979566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmGrad, &grad));
2498b5a3613cSMatthew G. Knepley /* Handle non-essential (e.g. outflow) boundary values */
24999566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_FALSE, locX, 0.0, faceGeometryFVM, cellGeometryFVM, locGrad));
25009566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(locGrad, &lgrad));
2501b5a3613cSMatthew G. Knepley }
2502338f77d5SMatthew G. Knepley /* Read out data from inputs */
250373d901b8SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
250473d901b8SMatthew G. Knepley PetscScalar *x = NULL;
250573d901b8SMatthew G. Knepley PetscInt i;
250673d901b8SMatthew G. Knepley
25079566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, section, locX, c, NULL, &x));
25080f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c * totDim + i] = x[i];
25099566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, section, locX, c, NULL, &x));
251073d901b8SMatthew G. Knepley if (dmAux) {
2511cbf8eb3cSStefano Zampini PetscCall(DMPlexVecGetClosure(plexA, sectionAux, locA, c, NULL, &x));
25120f2d7e86SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c * totDimAux + i] = x[i];
2513cbf8eb3cSStefano Zampini PetscCall(DMPlexVecRestoreClosure(plexA, sectionAux, locA, c, NULL, &x));
251473d901b8SMatthew G. Knepley }
251573d901b8SMatthew G. Knepley }
2516338f77d5SMatthew G. Knepley /* Do integration for each field */
251773d901b8SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
2518c1f031eeSMatthew G. Knepley PetscObject obj;
2519c1f031eeSMatthew G. Knepley PetscClassId id;
2520c1f031eeSMatthew G. Knepley PetscInt numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset;
252173d901b8SMatthew G. Knepley
25229566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, &obj));
25239566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
2524c1f031eeSMatthew G. Knepley if (id == PETSCFE_CLASSID) {
2525c1f031eeSMatthew G. Knepley PetscFE fe = (PetscFE)obj;
2526c1f031eeSMatthew G. Knepley PetscQuadrature q;
2527c330f8ffSToby Isaac PetscFEGeom *chunkGeom = NULL;
2528c1f031eeSMatthew G. Knepley PetscInt Nq, Nb;
2529c1f031eeSMatthew G. Knepley
25309566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
25319566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &q));
25329566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL));
25339566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
2534c1f031eeSMatthew G. Knepley blockSize = Nb * Nq;
253573d901b8SMatthew G. Knepley batchSize = numBlocks * blockSize;
25369566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
253773d901b8SMatthew G. Knepley numChunks = numCells / (numBatches * batchSize);
253873d901b8SMatthew G. Knepley Ne = numChunks * numBatches * batchSize;
253973d901b8SMatthew G. Knepley Nr = numCells % (numBatches * batchSize);
254073d901b8SMatthew G. Knepley offset = numCells - Nr;
2541ac9d17c7SMatthew G. Knepley if (!affineQuad) PetscCall(DMFieldCreateFEGeom(coordField, cellIS, q, PETSC_FEGEOM_BASIC, &cgeomFEM));
25429566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(cgeomFEM, 0, offset, &chunkGeom));
25439566063dSJacob Faibussowitsch PetscCall(PetscFEIntegrate(prob, f, Ne, chunkGeom, u, probAux, a, cintegral));
25449566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(cgeomFEM, offset, numCells, &chunkGeom));
25458e3a54c0SPierre Jolivet PetscCall(PetscFEIntegrate(prob, f, Nr, chunkGeom, &u[offset * totDim], probAux, PetscSafePointerPlusOffset(a, offset * totDimAux), &cintegral[offset * Nf]));
25469566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(cgeomFEM, offset, numCells, &chunkGeom));
254748a46eb9SPierre Jolivet if (!affineQuad) PetscCall(PetscFEGeomDestroy(&cgeomFEM));
2548c1f031eeSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
2549c1f031eeSMatthew G. Knepley PetscInt foff;
25502192575eSBarry Smith PetscPointFn *obj_func;
2551c1f031eeSMatthew G. Knepley
25529566063dSJacob Faibussowitsch PetscCall(PetscDSGetObjective(prob, f, &obj_func));
25539566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffset(prob, f, &foff));
2554c1f031eeSMatthew G. Knepley if (obj_func) {
2555c1f031eeSMatthew G. Knepley for (c = 0; c < numCells; ++c) {
2556b5a3613cSMatthew G. Knepley PetscScalar *u_x;
2557d627b919SMatthew G. Knepley PetscScalar lint = 0.;
2558b5a3613cSMatthew G. Knepley
25599566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmGrad, c, lgrad, &u_x));
256055bffe1bSPierre Jolivet obj_func(dim, Nf, NfAux, uOff, uOff_x, &u[totDim * c + foff], NULL, u_x, aOff, NULL, PetscSafePointerPlusOffset(a, totDimAux * c), NULL, NULL, 0.0, cgeomFVM[c].centroid, numConstants, constants, &lint);
2561338f77d5SMatthew G. Knepley cintegral[c * Nf + f] += PetscRealPart(lint) * cgeomFVM[c].volume;
256273d901b8SMatthew G. Knepley }
2563c1f031eeSMatthew G. Knepley }
256463a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
2565c1f031eeSMatthew G. Knepley }
2566338f77d5SMatthew G. Knepley /* Cleanup data arrays */
2567b5a3613cSMatthew G. Knepley if (useFVM) {
25689566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(locGrad, &lgrad));
25699566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellGeometryFVM, (const PetscScalar **)&cgeomFVM));
25709566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmGrad, &locGrad));
25719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&faceGeometryFVM));
25729566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cellGeometryFVM));
25739566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmGrad));
2574b5a3613cSMatthew G. Knepley }
25759566063dSJacob Faibussowitsch if (dmAux) PetscCall(PetscFree(a));
2576cbf8eb3cSStefano Zampini PetscCall(DMDestroy(&plexA));
25779566063dSJacob Faibussowitsch PetscCall(PetscFree(u));
2578338f77d5SMatthew G. Knepley /* Cleanup */
257948a46eb9SPierre Jolivet if (affineQuad) PetscCall(PetscFEGeomDestroy(&cgeomFEM));
25809566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&affineQuad));
25819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS));
25823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2583338f77d5SMatthew G. Knepley }
2584338f77d5SMatthew G. Knepley
2585338f77d5SMatthew G. Knepley /*@
2586338f77d5SMatthew G. Knepley DMPlexComputeIntegralFEM - Form the integral over the domain from the global input X using pointwise functions specified by the user
2587338f77d5SMatthew G. Knepley
2588338f77d5SMatthew G. Knepley Input Parameters:
2589338f77d5SMatthew G. Knepley + dm - The mesh
2590338f77d5SMatthew G. Knepley . X - Global input vector
2591*2a8381b2SBarry Smith - ctx - The application context
2592338f77d5SMatthew G. Knepley
2593338f77d5SMatthew G. Knepley Output Parameter:
2594338f77d5SMatthew G. Knepley . integral - Integral for each field
2595338f77d5SMatthew G. Knepley
2596338f77d5SMatthew G. Knepley Level: developer
2597338f77d5SMatthew G. Knepley
25981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSNESComputeResidualFEM()`
2599338f77d5SMatthew G. Knepley @*/
DMPlexComputeIntegralFEM(DM dm,Vec X,PetscScalar * integral,PetscCtx ctx)2600*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeIntegralFEM(DM dm, Vec X, PetscScalar *integral, PetscCtx ctx)
2601d71ae5a4SJacob Faibussowitsch {
2602cbf8eb3cSStefano Zampini PetscInt printFEM;
2603b8feb594SMatthew G. Knepley PetscScalar *cintegral, *lintegral;
2604412e9a14SMatthew G. Knepley PetscInt Nf, f, cellHeight, cStart, cEnd, cell;
26056493148fSStefano Zampini Vec locX;
2606338f77d5SMatthew G. Knepley
2607338f77d5SMatthew G. Knepley PetscFunctionBegin;
2608338f77d5SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2609338f77d5SMatthew G. Knepley PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
26104f572ea9SToby Isaac PetscAssertPointer(integral, 3);
26119566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_IntegralFEM, dm, 0, 0, 0));
2612cbf8eb3cSStefano Zampini PetscCall(DMPlexConvertPlex(dm, &dm, PETSC_TRUE));
26139566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf));
26149566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
26159566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
2616338f77d5SMatthew G. Knepley /* TODO Introduce a loop over large chunks (right now this is a single chunk) */
26179566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(Nf, &lintegral, (cEnd - cStart) * Nf, &cintegral));
26186493148fSStefano Zampini /* Get local solution with boundary values */
26196493148fSStefano Zampini PetscCall(DMGetLocalVector(dm, &locX));
26206493148fSStefano Zampini PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locX, 0.0, NULL, NULL, NULL));
26216493148fSStefano Zampini PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, locX));
26226493148fSStefano Zampini PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, locX));
2623*2a8381b2SBarry Smith PetscCall(DMPlexComputeIntegral_Internal(dm, locX, cStart, cEnd, cintegral, ctx));
26246493148fSStefano Zampini PetscCall(DMRestoreLocalVector(dm, &locX));
2625cbf8eb3cSStefano Zampini printFEM = ((DM_Plex *)dm->data)->printFEM;
2626338f77d5SMatthew G. Knepley /* Sum up values */
2627338f77d5SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) {
2628338f77d5SMatthew G. Knepley const PetscInt c = cell - cStart;
2629338f77d5SMatthew G. Knepley
2630cbf8eb3cSStefano Zampini if (printFEM > 1) PetscCall(DMPrintCellVector(cell, "Cell Integral", Nf, &cintegral[c * Nf]));
2631b8feb594SMatthew G. Knepley for (f = 0; f < Nf; ++f) lintegral[f] += cintegral[c * Nf + f];
2632338f77d5SMatthew G. Knepley }
2633e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Allreduce(lintegral, integral, Nf, MPIU_SCALAR, MPIU_SUM, PetscObjectComm((PetscObject)dm)));
2634cbf8eb3cSStefano Zampini if (printFEM) {
26359566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "Integral:"));
26369566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), " %g", (double)PetscRealPart(integral[f])));
26379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "\n"));
263873d901b8SMatthew G. Knepley }
26399566063dSJacob Faibussowitsch PetscCall(PetscFree2(lintegral, cintegral));
26409566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_IntegralFEM, dm, 0, 0, 0));
2641cbf8eb3cSStefano Zampini PetscCall(DMDestroy(&dm));
26423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2643338f77d5SMatthew G. Knepley }
2644338f77d5SMatthew G. Knepley
2645338f77d5SMatthew G. Knepley /*@
2646338f77d5SMatthew G. Knepley DMPlexComputeCellwiseIntegralFEM - Form the vector of cellwise integrals F from the global input X using pointwise functions specified by the user
2647338f77d5SMatthew G. Knepley
2648338f77d5SMatthew G. Knepley Input Parameters:
2649338f77d5SMatthew G. Knepley + dm - The mesh
2650338f77d5SMatthew G. Knepley . X - Global input vector
2651*2a8381b2SBarry Smith - ctx - The application context
2652338f77d5SMatthew G. Knepley
2653338f77d5SMatthew G. Knepley Output Parameter:
265460225df5SJacob Faibussowitsch . F - Cellwise integrals for each field
2655338f77d5SMatthew G. Knepley
2656338f77d5SMatthew G. Knepley Level: developer
2657338f77d5SMatthew G. Knepley
26581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSNESComputeResidualFEM()`
2659338f77d5SMatthew G. Knepley @*/
DMPlexComputeCellwiseIntegralFEM(DM dm,Vec X,Vec F,PetscCtx ctx)2660*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeCellwiseIntegralFEM(DM dm, Vec X, Vec F, PetscCtx ctx)
2661d71ae5a4SJacob Faibussowitsch {
2662cbf8eb3cSStefano Zampini PetscInt printFEM;
2663338f77d5SMatthew G. Knepley DM dmF;
26649c8ab049SStefano Zampini PetscSection sectionF = NULL;
2665338f77d5SMatthew G. Knepley PetscScalar *cintegral, *af;
26669c8ab049SStefano Zampini PetscInt Nf, f, cellHeight, cStart, cEnd, cell, n;
26676493148fSStefano Zampini Vec locX;
2668338f77d5SMatthew G. Knepley
2669338f77d5SMatthew G. Knepley PetscFunctionBegin;
2670338f77d5SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2671338f77d5SMatthew G. Knepley PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2672338f77d5SMatthew G. Knepley PetscValidHeaderSpecific(F, VEC_CLASSID, 3);
26739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_IntegralFEM, dm, 0, 0, 0));
2674cbf8eb3cSStefano Zampini PetscCall(DMPlexConvertPlex(dm, &dm, PETSC_TRUE));
26759566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf));
26769566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
26779566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
2678338f77d5SMatthew G. Knepley /* TODO Introduce a loop over large chunks (right now this is a single chunk) */
26799566063dSJacob Faibussowitsch PetscCall(PetscCalloc1((cEnd - cStart) * Nf, &cintegral));
26806493148fSStefano Zampini /* Get local solution with boundary values */
26816493148fSStefano Zampini PetscCall(DMGetLocalVector(dm, &locX));
26826493148fSStefano Zampini PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locX, 0.0, NULL, NULL, NULL));
26836493148fSStefano Zampini PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, locX));
26846493148fSStefano Zampini PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, locX));
2685*2a8381b2SBarry Smith PetscCall(DMPlexComputeIntegral_Internal(dm, locX, cStart, cEnd, cintegral, ctx));
26866493148fSStefano Zampini PetscCall(DMRestoreLocalVector(dm, &locX));
2687338f77d5SMatthew G. Knepley /* Put values in F */
26889566063dSJacob Faibussowitsch PetscCall(VecGetArray(F, &af));
26899c8ab049SStefano Zampini PetscCall(VecGetDM(F, &dmF));
26909c8ab049SStefano Zampini if (dmF) PetscCall(DMGetLocalSection(dmF, §ionF));
26919c8ab049SStefano Zampini PetscCall(VecGetLocalSize(F, &n));
26929c8ab049SStefano Zampini PetscCheck(n >= (cEnd - cStart) * Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vector size %" PetscInt_FMT " < %" PetscInt_FMT, n, (cEnd - cStart) * Nf);
2693cbf8eb3cSStefano Zampini printFEM = ((DM_Plex *)dm->data)->printFEM;
2694338f77d5SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) {
2695338f77d5SMatthew G. Knepley const PetscInt c = cell - cStart;
26969c8ab049SStefano Zampini PetscInt dof = Nf, off = c * Nf;
2697338f77d5SMatthew G. Knepley
2698cbf8eb3cSStefano Zampini if (printFEM > 1) PetscCall(DMPrintCellVector(cell, "Cell Integral", Nf, &cintegral[c * Nf]));
26999c8ab049SStefano Zampini if (sectionF) {
27009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionF, cell, &dof));
27019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionF, cell, &off));
27029c8ab049SStefano Zampini }
270363a3b9bcSJacob Faibussowitsch PetscCheck(dof == Nf, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cell dofs %" PetscInt_FMT " != %" PetscInt_FMT, dof, Nf);
2704338f77d5SMatthew G. Knepley for (f = 0; f < Nf; ++f) af[off + f] = cintegral[c * Nf + f];
2705338f77d5SMatthew G. Knepley }
27069566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(F, &af));
27079566063dSJacob Faibussowitsch PetscCall(PetscFree(cintegral));
27089566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_IntegralFEM, dm, 0, 0, 0));
2709cbf8eb3cSStefano Zampini PetscCall(DMDestroy(&dm));
27103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
271173d901b8SMatthew G. Knepley }
271273d901b8SMatthew G. Knepley
DMPlexComputeBdIntegral_Internal(DM dm,Vec locX,IS pointIS,void (** funcs)(PetscInt,PetscInt,PetscInt,const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],PetscReal,const PetscReal[],const PetscReal[],PetscInt,const PetscScalar[],PetscScalar[]),PetscScalar * fintegral,PetscCtx ctx)2713*2a8381b2SBarry Smith static PetscErrorCode DMPlexComputeBdIntegral_Internal(DM dm, Vec locX, IS pointIS, void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), PetscScalar *fintegral, PetscCtx ctx)
2714d71ae5a4SJacob Faibussowitsch {
27159b6f715bSMatthew G. Knepley DM plex = NULL, plexA = NULL;
2716a6e0b375SMatthew G. Knepley DMEnclosureType encAux;
27179b6f715bSMatthew G. Knepley PetscDS prob, probAux = NULL;
27189b6f715bSMatthew G. Knepley PetscSection section, sectionAux = NULL;
27199b6f715bSMatthew G. Knepley Vec locA = NULL;
27209b6f715bSMatthew G. Knepley DMField coordField;
27219b6f715bSMatthew G. Knepley PetscInt Nf, totDim, *uOff, *uOff_x;
27229b6f715bSMatthew G. Knepley PetscInt NfAux = 0, totDimAux = 0, *aOff = NULL;
27239b6f715bSMatthew G. Knepley PetscScalar *u, *a = NULL;
272464c72086SMatthew G. Knepley const PetscScalar *constants;
27259b6f715bSMatthew G. Knepley PetscInt numConstants, f;
272664c72086SMatthew G. Knepley
272764c72086SMatthew G. Knepley PetscFunctionBegin;
27289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
27299566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex));
27309566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
27319566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
27329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf));
273364c72086SMatthew G. Knepley /* Determine which discretizations we have */
27349b6f715bSMatthew G. Knepley for (f = 0; f < Nf; ++f) {
273564c72086SMatthew G. Knepley PetscObject obj;
273664c72086SMatthew G. Knepley PetscClassId id;
273764c72086SMatthew G. Knepley
27389566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, &obj));
27399566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
274063a3b9bcSJacob Faibussowitsch PetscCheck(id != PETSCFV_CLASSID, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not supported for FVM (field %" PetscInt_FMT ")", f);
274164c72086SMatthew G. Knepley }
274264c72086SMatthew G. Knepley /* Read DS information */
27439566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim));
27449566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(prob, &uOff));
27459566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentDerivativeOffsets(prob, &uOff_x));
27469566063dSJacob Faibussowitsch PetscCall(PetscDSGetConstants(prob, &numConstants, &constants));
274764c72086SMatthew G. Knepley /* Read Auxiliary DS information */
27489566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, NULL, 0, 0, &locA));
27499b6f715bSMatthew G. Knepley if (locA) {
27509b6f715bSMatthew G. Knepley DM dmAux;
27519b6f715bSMatthew G. Knepley
27529566063dSJacob Faibussowitsch PetscCall(VecGetDM(locA, &dmAux));
27539566063dSJacob Faibussowitsch PetscCall(DMGetEnclosureRelation(dmAux, dm, &encAux));
27549566063dSJacob Faibussowitsch PetscCall(DMConvert(dmAux, DMPLEX, &plexA));
27559566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmAux, &probAux));
27569566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(probAux, &NfAux));
27579566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmAux, §ionAux));
27589566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(probAux, &totDimAux));
27599566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffsets(probAux, &aOff));
276064c72086SMatthew G. Knepley }
27619b6f715bSMatthew G. Knepley /* Integrate over points */
27629b6f715bSMatthew G. Knepley {
27639b6f715bSMatthew G. Knepley PetscFEGeom *fgeom, *chunkGeom = NULL;
2764b7260050SToby Isaac PetscInt maxDegree;
27659b6f715bSMatthew G. Knepley PetscQuadrature qGeom = NULL;
27669b6f715bSMatthew G. Knepley const PetscInt *points;
27679b6f715bSMatthew G. Knepley PetscInt numFaces, face, Nq, field;
27689b6f715bSMatthew G. Knepley PetscInt numChunks, chunkSize, chunk, Nr, offset;
276964c72086SMatthew G. Knepley
27709566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numFaces));
27719566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points));
277232603206SJames Wright PetscCall(PetscCalloc2(numFaces * totDim, &u, (locA ? (size_t)numFaces * totDimAux : 0), &a));
27739566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, pointIS, NULL, &maxDegree));
277479ab67a3SMatthew G. Knepley for (face = 0; face < numFaces; ++face) {
277579ab67a3SMatthew G. Knepley const PetscInt point = points[face], *support;
277679ab67a3SMatthew G. Knepley PetscScalar *x = NULL;
277779ab67a3SMatthew G. Knepley
277879ab67a3SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, point, &support));
277979ab67a3SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(plex, section, locX, support[0], NULL, &x));
278079ab67a3SMatthew G. Knepley for (PetscInt i = 0; i < totDim; ++i) u[face * totDim + i] = x[i];
278179ab67a3SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(plex, section, locX, support[0], NULL, &x));
278279ab67a3SMatthew G. Knepley if (locA) {
278379ab67a3SMatthew G. Knepley PetscInt subp;
278479ab67a3SMatthew G. Knepley PetscCall(DMGetEnclosurePoint(plexA, dm, encAux, support[0], &subp));
278579ab67a3SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(plexA, sectionAux, locA, subp, NULL, &x));
278679ab67a3SMatthew G. Knepley for (PetscInt i = 0; i < totDimAux; ++i) a[f * totDimAux + i] = x[i];
278779ab67a3SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(plexA, sectionAux, locA, subp, NULL, &x));
278879ab67a3SMatthew G. Knepley }
278979ab67a3SMatthew G. Knepley }
279064c72086SMatthew G. Knepley for (field = 0; field < Nf; ++field) {
279164c72086SMatthew G. Knepley PetscFE fe;
279264c72086SMatthew G. Knepley
27939566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, (PetscObject *)&fe));
27949566063dSJacob Faibussowitsch if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, pointIS, &qGeom));
27959b6f715bSMatthew G. Knepley if (!qGeom) {
27969566063dSJacob Faibussowitsch PetscCall(PetscFEGetFaceQuadrature(fe, &qGeom));
27979566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)qGeom));
27989b6f715bSMatthew G. Knepley }
27999566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL));
2800ac9d17c7SMatthew G. Knepley PetscCall(DMPlexGetFEGeom(coordField, pointIS, qGeom, PETSC_FEGEOM_BOUNDARY, &fgeom));
28019b6f715bSMatthew G. Knepley /* Get blocking */
28029b6f715bSMatthew G. Knepley {
28039b6f715bSMatthew G. Knepley PetscQuadrature q;
28049b6f715bSMatthew G. Knepley PetscInt numBatches, batchSize, numBlocks, blockSize;
28059b6f715bSMatthew G. Knepley PetscInt Nq, Nb;
28069b6f715bSMatthew G. Knepley
28079566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
28089566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &q));
28099566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL));
28109566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
281164c72086SMatthew G. Knepley blockSize = Nb * Nq;
281264c72086SMatthew G. Knepley batchSize = numBlocks * blockSize;
28139b6f715bSMatthew G. Knepley chunkSize = numBatches * batchSize;
28149566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
28159b6f715bSMatthew G. Knepley numChunks = numFaces / chunkSize;
28169b6f715bSMatthew G. Knepley Nr = numFaces % chunkSize;
281764c72086SMatthew G. Knepley offset = numFaces - Nr;
281864c72086SMatthew G. Knepley }
28199b6f715bSMatthew G. Knepley /* Do integration for each field */
28209b6f715bSMatthew G. Knepley for (chunk = 0; chunk < numChunks; ++chunk) {
28219566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(fgeom, chunk * chunkSize, (chunk + 1) * chunkSize, &chunkGeom));
282279ab67a3SMatthew G. Knepley PetscCall(PetscFEIntegrateBd(prob, field, funcs[field], chunkSize, chunkGeom, &u[chunk * chunkSize * totDim], probAux, PetscSafePointerPlusOffset(a, chunk * chunkSize * totDimAux), &fintegral[chunk * chunkSize * Nf]));
28239566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(fgeom, 0, offset, &chunkGeom));
282464c72086SMatthew G. Knepley }
28259566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(fgeom, offset, numFaces, &chunkGeom));
282679ab67a3SMatthew G. Knepley PetscCall(PetscFEIntegrateBd(prob, field, funcs[field], Nr, chunkGeom, &u[offset * totDim], probAux, PetscSafePointerPlusOffset(a, offset * totDimAux), &fintegral[offset * Nf]));
28279566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(fgeom, offset, numFaces, &chunkGeom));
282864c72086SMatthew G. Knepley /* Cleanup data arrays */
2829ac9d17c7SMatthew G. Knepley PetscCall(DMPlexRestoreFEGeom(coordField, pointIS, qGeom, PETSC_FEGEOM_BOUNDARY, &fgeom));
28309566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&qGeom));
283179ab67a3SMatthew G. Knepley }
28329566063dSJacob Faibussowitsch PetscCall(PetscFree2(u, a));
28339566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points));
283464c72086SMatthew G. Knepley }
28359566063dSJacob Faibussowitsch if (plex) PetscCall(DMDestroy(&plex));
28369566063dSJacob Faibussowitsch if (plexA) PetscCall(DMDestroy(&plexA));
28373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
28389b6f715bSMatthew G. Knepley }
28399b6f715bSMatthew G. Knepley
284060225df5SJacob Faibussowitsch /*@C
28419b6f715bSMatthew G. Knepley DMPlexComputeBdIntegral - Form the integral over the specified boundary from the global input X using pointwise functions specified by the user
28429b6f715bSMatthew G. Knepley
28439b6f715bSMatthew G. Knepley Input Parameters:
28449b6f715bSMatthew G. Knepley + dm - The mesh
28459b6f715bSMatthew G. Knepley . X - Global input vector
2846a1cb98faSBarry Smith . label - The boundary `DMLabel`
2847a1cb98faSBarry Smith . numVals - The number of label values to use, or `PETSC_DETERMINE` for all values
2848a1cb98faSBarry Smith . vals - The label values to use, or NULL for all values
284979ab67a3SMatthew G. Knepley . funcs - The functions to integrate along the boundary for each field
2850*2a8381b2SBarry Smith - ctx - The application context
28519b6f715bSMatthew G. Knepley
28529b6f715bSMatthew G. Knepley Output Parameter:
28539b6f715bSMatthew G. Knepley . integral - Integral for each field
28549b6f715bSMatthew G. Knepley
28559b6f715bSMatthew G. Knepley Level: developer
28569b6f715bSMatthew G. Knepley
28571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexComputeIntegralFEM()`, `DMPlexComputeBdResidualFEM()`
28589b6f715bSMatthew G. Knepley @*/
DMPlexComputeBdIntegral(DM dm,Vec X,DMLabel label,PetscInt numVals,const PetscInt vals[],void (** funcs)(PetscInt,PetscInt,PetscInt,const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],const PetscInt[],const PetscInt[],const PetscScalar[],const PetscScalar[],const PetscScalar[],PetscReal,const PetscReal[],const PetscReal[],PetscInt,const PetscScalar[],PetscScalar[]),PetscScalar * integral,PetscCtx ctx)2859*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeBdIntegral(DM dm, Vec X, DMLabel label, PetscInt numVals, const PetscInt vals[], void (**funcs)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), PetscScalar *integral, PetscCtx ctx)
2860d71ae5a4SJacob Faibussowitsch {
28619b6f715bSMatthew G. Knepley Vec locX;
28629b6f715bSMatthew G. Knepley PetscSection section;
28639b6f715bSMatthew G. Knepley DMLabel depthLabel;
28649b6f715bSMatthew G. Knepley IS facetIS;
28659b6f715bSMatthew G. Knepley PetscInt dim, Nf, f, v;
28669b6f715bSMatthew G. Knepley
28679b6f715bSMatthew G. Knepley PetscFunctionBegin;
28689b6f715bSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28699b6f715bSMatthew G. Knepley PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
2870292bffcbSToby Isaac PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3);
28714f572ea9SToby Isaac if (vals) PetscAssertPointer(vals, 5);
28724f572ea9SToby Isaac PetscAssertPointer(integral, 7);
28739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_IntegralFEM, dm, 0, 0, 0));
28749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
28759566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
28769566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(depthLabel, dim - 1, &facetIS));
28779566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
28789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf));
28799b6f715bSMatthew G. Knepley /* Get local solution with boundary values */
28809566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locX));
28819566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locX, 0.0, NULL, NULL, NULL));
28829566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, X, INSERT_VALUES, locX));
28839566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, X, INSERT_VALUES, locX));
28849b6f715bSMatthew G. Knepley /* Loop over label values */
28859566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(integral, Nf));
28869b6f715bSMatthew G. Knepley for (v = 0; v < numVals; ++v) {
28879b6f715bSMatthew G. Knepley IS pointIS;
28889b6f715bSMatthew G. Knepley PetscInt numFaces, face;
28899b6f715bSMatthew G. Knepley PetscScalar *fintegral;
28909b6f715bSMatthew G. Knepley
28919566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, vals[v], &pointIS));
28929b6f715bSMatthew G. Knepley if (!pointIS) continue; /* No points with that id on this process */
28939b6f715bSMatthew G. Knepley {
28949b6f715bSMatthew G. Knepley IS isectIS;
28959b6f715bSMatthew G. Knepley
28969b6f715bSMatthew G. Knepley /* TODO: Special cases of ISIntersect where it is quick to check a priori if one is a superset of the other */
28979566063dSJacob Faibussowitsch PetscCall(ISIntersect_Caching_Internal(facetIS, pointIS, &isectIS));
28989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
28999b6f715bSMatthew G. Knepley pointIS = isectIS;
29009b6f715bSMatthew G. Knepley }
29019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numFaces));
29029566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numFaces * Nf, &fintegral));
2903*2a8381b2SBarry Smith PetscCall(DMPlexComputeBdIntegral_Internal(dm, locX, pointIS, funcs, fintegral, ctx));
29049b6f715bSMatthew G. Knepley /* Sum point contributions into integral */
29059371c9d4SSatish Balay for (f = 0; f < Nf; ++f)
29069371c9d4SSatish Balay for (face = 0; face < numFaces; ++face) integral[f] += fintegral[face * Nf + f];
29079566063dSJacob Faibussowitsch PetscCall(PetscFree(fintegral));
29089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
29099b6f715bSMatthew G. Knepley }
29109566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locX));
29119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&facetIS));
29129566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_IntegralFEM, dm, 0, 0, 0));
29133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
291464c72086SMatthew G. Knepley }
291564c72086SMatthew G. Knepley
2916d69c5d34SMatthew G. Knepley /*@
29170318f8a0SStefano Zampini DMPlexComputeInterpolatorNested - Form the local portion of the interpolation matrix from the coarse `DM` to a uniformly refined `DM`.
2918d69c5d34SMatthew G. Knepley
2919d69c5d34SMatthew G. Knepley Input Parameters:
2920cf51de39SMatthew G. Knepley + dmc - The coarse mesh
2921cf51de39SMatthew G. Knepley . dmf - The fine mesh
2922cf51de39SMatthew G. Knepley . isRefined - Flag indicating regular refinement, rather than the same topology
2923*2a8381b2SBarry Smith - ctx - The application context
2924d69c5d34SMatthew G. Knepley
2925d69c5d34SMatthew G. Knepley Output Parameter:
2926934789fcSMatthew G. Knepley . In - The interpolation matrix
2927d69c5d34SMatthew G. Knepley
2928d69c5d34SMatthew G. Knepley Level: developer
2929d69c5d34SMatthew G. Knepley
2930ae3cf2c1SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexComputeInterpolatorGeneral()`
2931d69c5d34SMatthew G. Knepley @*/
DMPlexComputeInterpolatorNested(DM dmc,DM dmf,PetscBool isRefined,Mat In,PetscCtx ctx)2932*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeInterpolatorNested(DM dmc, DM dmf, PetscBool isRefined, Mat In, PetscCtx ctx)
2933d71ae5a4SJacob Faibussowitsch {
2934d69c5d34SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmc->data;
2935d69c5d34SMatthew G. Knepley const char *name = "Interpolator";
2936d69c5d34SMatthew G. Knepley PetscFE *feRef;
293797c42addSMatthew G. Knepley PetscFV *fvRef;
2938d69c5d34SMatthew G. Knepley PetscSection fsection, fglobalSection;
2939d69c5d34SMatthew G. Knepley PetscSection csection, cglobalSection;
2940d69c5d34SMatthew G. Knepley PetscScalar *elemMat;
2941485ad865SMatthew G. Knepley PetscInt dim, Nf, f, fieldI, fieldJ, offsetI, offsetJ, cStart, cEnd, c;
29422ea9c922SToby Isaac PetscInt cTotDim = 0, rTotDim = 0;
2943d69c5d34SMatthew G. Knepley
2944d69c5d34SMatthew G. Knepley PetscFunctionBegin;
29459566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_InterpolatorFEM, dmc, dmf, 0, 0));
29469566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmf, &dim));
29479566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmf, &fsection));
29489566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmf, &fglobalSection));
29499566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmc, &csection));
29509566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmc, &cglobalSection));
29519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &Nf));
29529566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dmc, 0, &cStart, &cEnd));
29539566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(Nf, &feRef, Nf, &fvRef));
2954d69c5d34SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
29552ea9c922SToby Isaac PetscObject obj, objc;
29562ea9c922SToby Isaac PetscClassId id, idc;
29572ea9c922SToby Isaac PetscInt rNb = 0, Nc = 0, cNb = 0;
2958d69c5d34SMatthew G. Knepley
29599566063dSJacob Faibussowitsch PetscCall(DMGetField(dmf, f, NULL, &obj));
29609566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
296197c42addSMatthew G. Knepley if (id == PETSCFE_CLASSID) {
296297c42addSMatthew G. Knepley PetscFE fe = (PetscFE)obj;
296397c42addSMatthew G. Knepley
2964cf51de39SMatthew G. Knepley if (isRefined) {
29659566063dSJacob Faibussowitsch PetscCall(PetscFERefine(fe, &feRef[f]));
2966cf51de39SMatthew G. Knepley } else {
29679566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)fe));
2968cf51de39SMatthew G. Knepley feRef[f] = fe;
2969cf51de39SMatthew G. Knepley }
29709566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(feRef[f], &rNb));
29719566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc));
297297c42addSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
297397c42addSMatthew G. Knepley PetscFV fv = (PetscFV)obj;
297497c42addSMatthew G. Knepley PetscDualSpace Q;
297597c42addSMatthew G. Knepley
2976cf51de39SMatthew G. Knepley if (isRefined) {
29779566063dSJacob Faibussowitsch PetscCall(PetscFVRefine(fv, &fvRef[f]));
2978cf51de39SMatthew G. Knepley } else {
29799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)fv));
2980cf51de39SMatthew G. Knepley fvRef[f] = fv;
2981cf51de39SMatthew G. Knepley }
29829566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fvRef[f], &Q));
29839566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(Q, &rNb));
29849566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fv, &Q));
29859566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc));
298697c42addSMatthew G. Knepley }
29879566063dSJacob Faibussowitsch PetscCall(DMGetField(dmc, f, NULL, &objc));
29889566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(objc, &idc));
29892ea9c922SToby Isaac if (idc == PETSCFE_CLASSID) {
29902ea9c922SToby Isaac PetscFE fe = (PetscFE)objc;
29912ea9c922SToby Isaac
29929566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &cNb));
29932ea9c922SToby Isaac } else if (id == PETSCFV_CLASSID) {
29942ea9c922SToby Isaac PetscFV fv = (PetscFV)obj;
29952ea9c922SToby Isaac PetscDualSpace Q;
29962ea9c922SToby Isaac
29979566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fv, &Q));
29989566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(Q, &cNb));
2999d69c5d34SMatthew G. Knepley }
30002ea9c922SToby Isaac rTotDim += rNb;
30012ea9c922SToby Isaac cTotDim += cNb;
30022ea9c922SToby Isaac }
30039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rTotDim * cTotDim, &elemMat));
30049566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemMat, rTotDim * cTotDim));
3005d69c5d34SMatthew G. Knepley for (fieldI = 0, offsetI = 0; fieldI < Nf; ++fieldI) {
3006d69c5d34SMatthew G. Knepley PetscDualSpace Qref;
3007d69c5d34SMatthew G. Knepley PetscQuadrature f;
3008d69c5d34SMatthew G. Knepley const PetscReal *qpoints, *qweights;
3009d69c5d34SMatthew G. Knepley PetscReal *points;
3010d69c5d34SMatthew G. Knepley PetscInt npoints = 0, Nc, Np, fpdim, i, k, p, d;
3011d69c5d34SMatthew G. Knepley
3012d69c5d34SMatthew G. Knepley /* Compose points from all dual basis functionals */
301397c42addSMatthew G. Knepley if (feRef[fieldI]) {
30149566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(feRef[fieldI], &Qref));
30159566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(feRef[fieldI], &Nc));
301697c42addSMatthew G. Knepley } else {
30179566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fvRef[fieldI], &Qref));
30189566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fvRef[fieldI], &Nc));
301997c42addSMatthew G. Knepley }
30209566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(Qref, &fpdim));
3021d69c5d34SMatthew G. Knepley for (i = 0; i < fpdim; ++i) {
30229566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(Qref, i, &f));
30239566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(f, NULL, NULL, &Np, NULL, NULL));
3024d69c5d34SMatthew G. Knepley npoints += Np;
3025d69c5d34SMatthew G. Knepley }
30269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npoints * dim, &points));
3027d69c5d34SMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) {
30289566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(Qref, i, &f));
30299566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(f, NULL, NULL, &Np, &qpoints, NULL));
30309371c9d4SSatish Balay for (p = 0; p < Np; ++p, ++k)
30319371c9d4SSatish Balay for (d = 0; d < dim; ++d) points[k * dim + d] = qpoints[p * dim + d];
3032d69c5d34SMatthew G. Knepley }
3033d69c5d34SMatthew G. Knepley
3034d69c5d34SMatthew G. Knepley for (fieldJ = 0, offsetJ = 0; fieldJ < Nf; ++fieldJ) {
303597c42addSMatthew G. Knepley PetscObject obj;
303697c42addSMatthew G. Knepley PetscClassId id;
30379c3cf19fSMatthew G. Knepley PetscInt NcJ = 0, cpdim = 0, j, qNc;
3038d69c5d34SMatthew G. Knepley
30399566063dSJacob Faibussowitsch PetscCall(DMGetField(dmc, fieldJ, NULL, &obj));
30409566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
304197c42addSMatthew G. Knepley if (id == PETSCFE_CLASSID) {
304297c42addSMatthew G. Knepley PetscFE fe = (PetscFE)obj;
3043ef0bb6c7SMatthew G. Knepley PetscTabulation T = NULL;
3044d69c5d34SMatthew G. Knepley
3045d69c5d34SMatthew G. Knepley /* Evaluate basis at points */
30469566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &NcJ));
30479566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &cpdim));
3048ffe73a53SMatthew G. Knepley /* For now, fields only interpolate themselves */
3049ffe73a53SMatthew G. Knepley if (fieldI == fieldJ) {
305063a3b9bcSJacob Faibussowitsch PetscCheck(Nc == NcJ, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in fine space field %" PetscInt_FMT " does not match coarse field %" PetscInt_FMT, Nc, NcJ);
30519566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation(fe, 1, npoints, points, 0, &T));
3052d69c5d34SMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) {
30539566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(Qref, i, &f));
30549566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(f, NULL, &qNc, &Np, NULL, &qweights));
305563a3b9bcSJacob Faibussowitsch PetscCheck(qNc == NcJ, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in quadrature %" PetscInt_FMT " does not match coarse field %" PetscInt_FMT, qNc, NcJ);
3056d69c5d34SMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) {
305736a6d9c0SMatthew G. Knepley for (j = 0; j < cpdim; ++j) {
3058d172c84bSMatthew G. Knepley /*
3059d172c84bSMatthew G. Knepley cTotDim: Total columns in element interpolation matrix, sum of number of dual basis functionals in each field
3060d172c84bSMatthew G. Knepley offsetI, offsetJ: Offsets into the larger element interpolation matrix for different fields
3061d172c84bSMatthew G. Knepley fpdim, i, cpdim, j: Dofs for fine and coarse grids, correspond to dual space basis functionals
3062d172c84bSMatthew G. Knepley qNC, Nc, Ncj, c: Number of components in this field
3063d172c84bSMatthew G. Knepley Np, p: Number of quad points in the fine grid functional i
3064d172c84bSMatthew G. Knepley k: i*Np + p, overall point number for the interpolation
3065d172c84bSMatthew G. Knepley */
3066ef0bb6c7SMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[(offsetI + i) * cTotDim + offsetJ + j] += T->T[0][k * cpdim * NcJ + j * Nc + c] * qweights[p * qNc + c];
306736a6d9c0SMatthew G. Knepley }
3068d69c5d34SMatthew G. Knepley }
3069d69c5d34SMatthew G. Knepley }
30709566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&T));
3071ffe73a53SMatthew G. Knepley }
307297c42addSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
307397c42addSMatthew G. Knepley PetscFV fv = (PetscFV)obj;
307497c42addSMatthew G. Knepley
307597c42addSMatthew G. Knepley /* Evaluate constant function at points */
30769566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &NcJ));
307797c42addSMatthew G. Knepley cpdim = 1;
307897c42addSMatthew G. Knepley /* For now, fields only interpolate themselves */
307997c42addSMatthew G. Knepley if (fieldI == fieldJ) {
308063a3b9bcSJacob Faibussowitsch PetscCheck(Nc == NcJ, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in fine space field %" PetscInt_FMT " does not match coarse field %" PetscInt_FMT, Nc, NcJ);
308197c42addSMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) {
30829566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(Qref, i, &f));
30839566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(f, NULL, &qNc, &Np, NULL, &qweights));
308463a3b9bcSJacob Faibussowitsch PetscCheck(qNc == NcJ, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in quadrature %" PetscInt_FMT " does not match coarse field %" PetscInt_FMT, qNc, NcJ);
308597c42addSMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) {
308697c42addSMatthew G. Knepley for (j = 0; j < cpdim; ++j) {
3087458eb97cSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[(offsetI + i) * cTotDim + offsetJ + j] += 1.0 * qweights[p * qNc + c];
308897c42addSMatthew G. Knepley }
308997c42addSMatthew G. Knepley }
309097c42addSMatthew G. Knepley }
309197c42addSMatthew G. Knepley }
309297c42addSMatthew G. Knepley }
3093d172c84bSMatthew G. Knepley offsetJ += cpdim;
3094d69c5d34SMatthew G. Knepley }
3095d172c84bSMatthew G. Knepley offsetI += fpdim;
30969566063dSJacob Faibussowitsch PetscCall(PetscFree(points));
3097d69c5d34SMatthew G. Knepley }
30989566063dSJacob Faibussowitsch if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(0, name, rTotDim, cTotDim, elemMat));
30997f5b169aSMatthew G. Knepley /* Preallocate matrix */
31007f5b169aSMatthew G. Knepley {
3101c094ef40SMatthew G. Knepley Mat preallocator;
3102c094ef40SMatthew G. Knepley PetscScalar *vals;
3103c094ef40SMatthew G. Knepley PetscInt *cellCIndices, *cellFIndices;
3104c094ef40SMatthew G. Knepley PetscInt locRows, locCols, cell;
31057f5b169aSMatthew G. Knepley
31069566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(In, &locRows, &locCols));
31079566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)In), &preallocator));
31089566063dSJacob Faibussowitsch PetscCall(MatSetType(preallocator, MATPREALLOCATOR));
31099566063dSJacob Faibussowitsch PetscCall(MatSetSizes(preallocator, locRows, locCols, PETSC_DETERMINE, PETSC_DETERMINE));
31109566063dSJacob Faibussowitsch PetscCall(MatSetUp(preallocator));
31119566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(rTotDim * cTotDim, &vals, cTotDim, &cellCIndices, rTotDim, &cellFIndices));
3112b4ec2976SMatthew G. Knepley if (locRows || locCols) {
31137f5b169aSMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) {
3114cf51de39SMatthew G. Knepley if (isRefined) {
31159566063dSJacob Faibussowitsch PetscCall(DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, cell, cellCIndices, cellFIndices));
31169566063dSJacob Faibussowitsch PetscCall(MatSetValues(preallocator, rTotDim, cellFIndices, cTotDim, cellCIndices, vals, INSERT_VALUES));
3117cf51de39SMatthew G. Knepley } else {
3118e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosureGeneral(dmf, fsection, fglobalSection, PETSC_FALSE, dmc, csection, cglobalSection, PETSC_FALSE, preallocator, cell, vals, INSERT_VALUES));
3119cf51de39SMatthew G. Knepley }
31207f5b169aSMatthew G. Knepley }
3121b4ec2976SMatthew G. Knepley }
31229566063dSJacob Faibussowitsch PetscCall(PetscFree3(vals, cellCIndices, cellFIndices));
31239566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY));
31249566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY));
31259566063dSJacob Faibussowitsch PetscCall(MatPreallocatorPreallocate(preallocator, PETSC_TRUE, In));
31269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&preallocator));
31277f5b169aSMatthew G. Knepley }
31287f5b169aSMatthew G. Knepley /* Fill matrix */
31299566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(In));
3130d69c5d34SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
3131cf51de39SMatthew G. Knepley if (isRefined) {
31329566063dSJacob Faibussowitsch PetscCall(DMPlexMatSetClosureRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, In, c, elemMat, INSERT_VALUES));
3133cf51de39SMatthew G. Knepley } else {
3134e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosureGeneral(dmf, fsection, fglobalSection, PETSC_FALSE, dmc, csection, cglobalSection, PETSC_FALSE, In, c, elemMat, INSERT_VALUES));
3135cf51de39SMatthew G. Knepley }
3136d69c5d34SMatthew G. Knepley }
31379566063dSJacob Faibussowitsch for (f = 0; f < Nf; ++f) PetscCall(PetscFEDestroy(&feRef[f]));
31389566063dSJacob Faibussowitsch PetscCall(PetscFree2(feRef, fvRef));
31399566063dSJacob Faibussowitsch PetscCall(PetscFree(elemMat));
31409566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY));
31419566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY));
31429318fe57SMatthew G. Knepley if (mesh->printFEM > 1) {
31439566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)In), "%s:\n", name));
31442ce66baaSPierre Jolivet PetscCall(MatFilter(In, 1.0e-10, PETSC_FALSE, PETSC_FALSE));
31459566063dSJacob Faibussowitsch PetscCall(MatView(In, NULL));
3146d69c5d34SMatthew G. Knepley }
31479566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_InterpolatorFEM, dmc, dmf, 0, 0));
31483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3149d69c5d34SMatthew G. Knepley }
31506c73c22cSMatthew G. Knepley
DMPlexComputeMassMatrixNested(DM dmc,DM dmf,Mat mass,PetscCtx ctx)3151*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeMassMatrixNested(DM dmc, DM dmf, Mat mass, PetscCtx ctx)
3152d71ae5a4SJacob Faibussowitsch {
3153bd041c0cSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dmc), PETSC_ERR_SUP, "Laziness");
3154bd041c0cSMatthew G. Knepley }
3155bd041c0cSMatthew G. Knepley
315668132eb9SMatthew G. Knepley /*@
31570318f8a0SStefano Zampini DMPlexComputeInterpolatorGeneral - Form the local portion of the interpolation matrix from the coarse `DM` to a non-nested fine `DM`.
315868132eb9SMatthew G. Knepley
315968132eb9SMatthew G. Knepley Input Parameters:
316068132eb9SMatthew G. Knepley + dmf - The fine mesh
316168132eb9SMatthew G. Knepley . dmc - The coarse mesh
3162*2a8381b2SBarry Smith - ctx - The application context
316368132eb9SMatthew G. Knepley
316468132eb9SMatthew G. Knepley Output Parameter:
316568132eb9SMatthew G. Knepley . In - The interpolation matrix
316668132eb9SMatthew G. Knepley
316768132eb9SMatthew G. Knepley Level: developer
316868132eb9SMatthew G. Knepley
3169ae3cf2c1SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexComputeInterpolatorNested()`
317068132eb9SMatthew G. Knepley @*/
DMPlexComputeInterpolatorGeneral(DM dmc,DM dmf,Mat In,PetscCtx ctx)3171*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeInterpolatorGeneral(DM dmc, DM dmf, Mat In, PetscCtx ctx)
3172d71ae5a4SJacob Faibussowitsch {
317364e98e1dSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data;
317464e98e1dSMatthew G. Knepley const char *name = "Interpolator";
31754ef9d792SMatthew G. Knepley PetscDS prob;
3176a0806964SMatthew G. Knepley Mat interp;
3177a0806964SMatthew G. Knepley PetscSection fsection, globalFSection;
3178a0806964SMatthew G. Knepley PetscSection csection, globalCSection;
3179a0806964SMatthew G. Knepley PetscInt locRows, locCols;
31804ef9d792SMatthew G. Knepley PetscReal *x, *v0, *J, *invJ, detJ;
31814ef9d792SMatthew G. Knepley PetscReal *v0c, *Jc, *invJc, detJc;
31824ef9d792SMatthew G. Knepley PetscScalar *elemMat;
3183a0806964SMatthew G. Knepley PetscInt dim, Nf, field, totDim, cStart, cEnd, cell, ccell, s;
31844ef9d792SMatthew G. Knepley
31854ef9d792SMatthew G. Knepley PetscFunctionBegin;
31869566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_InterpolatorFEM, dmc, dmf, 0, 0));
31879566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmc, &dim));
31889566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &prob));
31899566063dSJacob Faibussowitsch PetscCall(PetscDSGetWorkspace(prob, &x, NULL, NULL, NULL, NULL));
31909566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf));
31919566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim * dim, &J, dim * dim, &invJ));
31929566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0c, dim * dim, &Jc, dim * dim, &invJc));
31939566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmf, &fsection));
31949566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmf, &globalFSection));
31959566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmc, &csection));
31969566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmc, &globalCSection));
3197a0806964SMatthew G. Knepley PetscCall(DMPlexGetSimplexOrBoxCells(dmf, 0, &cStart, &cEnd));
31989566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim));
31999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(totDim, &elemMat));
32004ef9d792SMatthew G. Knepley
3201a0806964SMatthew G. Knepley PetscCall(MatGetLocalSize(In, &locRows, &locCols));
3202a0806964SMatthew G. Knepley PetscCall(MatCreate(PetscObjectComm((PetscObject)In), &interp));
3203a0806964SMatthew G. Knepley PetscCall(MatSetType(interp, MATPREALLOCATOR));
3204a0806964SMatthew G. Knepley PetscCall(MatSetSizes(interp, locRows, locCols, PETSC_DETERMINE, PETSC_DETERMINE));
3205a0806964SMatthew G. Knepley PetscCall(MatSetUp(interp));
3206a0806964SMatthew G. Knepley for (s = 0; s < 2; ++s) {
32074ef9d792SMatthew G. Knepley for (field = 0; field < Nf; ++field) {
32084ef9d792SMatthew G. Knepley PetscObject obj;
32094ef9d792SMatthew G. Knepley PetscClassId id;
3210c0d7054bSMatthew G. Knepley PetscDualSpace Q = NULL;
3211ef0bb6c7SMatthew G. Knepley PetscTabulation T = NULL;
32124ef9d792SMatthew G. Knepley PetscQuadrature f;
32134ef9d792SMatthew G. Knepley const PetscReal *qpoints, *qweights;
3214d0f6233fSMatthew G. Knepley PetscInt Nc, qNc, Np, fpdim, off, i, d;
32154ef9d792SMatthew G. Knepley
3216d0f6233fSMatthew G. Knepley PetscCall(PetscDSGetFieldOffset(prob, field, &off));
32179566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, &obj));
32189566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
32194ef9d792SMatthew G. Knepley if (id == PETSCFE_CLASSID) {
32204ef9d792SMatthew G. Knepley PetscFE fe = (PetscFE)obj;
32214ef9d792SMatthew G. Knepley
32229566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &Q));
32239566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc));
3224a0806964SMatthew G. Knepley if (s) PetscCall(PetscFECreateTabulation(fe, 1, 1, x, 0, &T));
32254ef9d792SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
32264ef9d792SMatthew G. Knepley PetscFV fv = (PetscFV)obj;
32274ef9d792SMatthew G. Knepley
32289566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fv, &Q));
32294ef9d792SMatthew G. Knepley Nc = 1;
323063a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dmc), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, field);
32319566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(Q, &fpdim));
32324ef9d792SMatthew G. Knepley /* For each fine grid cell */
32334ef9d792SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) {
32344ef9d792SMatthew G. Knepley PetscInt *findices, *cindices;
32354ef9d792SMatthew G. Knepley PetscInt numFIndices, numCIndices;
32364ef9d792SMatthew G. Knepley
32379566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
32389566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
3239d0f6233fSMatthew G. Knepley PetscCheck(numFIndices == totDim, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of fine indices %" PetscInt_FMT " != %" PetscInt_FMT " dual basis vecs", numFIndices, totDim);
32404ef9d792SMatthew G. Knepley for (i = 0; i < fpdim; ++i) {
32414ef9d792SMatthew G. Knepley Vec pointVec;
32424ef9d792SMatthew G. Knepley PetscScalar *pV;
324312111d7cSToby Isaac PetscSF coarseCellSF = NULL;
32443a93e3b7SToby Isaac const PetscSFNode *coarseCells;
3245d0f6233fSMatthew G. Knepley PetscInt numCoarseCells, cpdim, row = findices[i + off], q, c, j;
32464ef9d792SMatthew G. Knepley
32474ef9d792SMatthew G. Knepley /* Get points from the dual basis functional quadrature */
32489566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(Q, i, &f));
32499566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(f, NULL, &qNc, &Np, &qpoints, &qweights));
325063a3b9bcSJacob Faibussowitsch PetscCheck(qNc == Nc, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in quadrature %" PetscInt_FMT " does not match coarse field %" PetscInt_FMT, qNc, Nc);
32519566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, Np * dim, &pointVec));
32529566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(pointVec, dim));
32539566063dSJacob Faibussowitsch PetscCall(VecGetArray(pointVec, &pV));
32544ef9d792SMatthew G. Knepley for (q = 0; q < Np; ++q) {
3255c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.};
3256c330f8ffSToby Isaac
32574ef9d792SMatthew G. Knepley /* Transform point to real space */
3258c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0, J, &qpoints[q * dim], x);
32594ef9d792SMatthew G. Knepley for (d = 0; d < dim; ++d) pV[q * dim + d] = x[d];
32604ef9d792SMatthew G. Knepley }
32619566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pointVec, &pV));
32624ef9d792SMatthew G. Knepley /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */
32631555c271SMatthew G. Knepley /* OPT: Read this out from preallocation information */
32649566063dSJacob Faibussowitsch PetscCall(DMLocatePoints(dmc, pointVec, DM_POINTLOCATION_NEAREST, &coarseCellSF));
32654ef9d792SMatthew G. Knepley /* Update preallocation info */
32669566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseCellSF, NULL, &numCoarseCells, NULL, &coarseCells));
32675f80ce2aSJacob Faibussowitsch PetscCheck(numCoarseCells == Np, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not all closure points located");
32689566063dSJacob Faibussowitsch PetscCall(VecGetArray(pointVec, &pV));
32694ef9d792SMatthew G. Knepley for (ccell = 0; ccell < numCoarseCells; ++ccell) {
3270826eb36dSMatthew G. Knepley PetscReal pVReal[3];
3271c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.};
3272826eb36dSMatthew G. Knepley
32739566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, PETSC_FALSE, &numCIndices, &cindices, NULL, NULL));
3274a0806964SMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetDimension((PetscFE)obj, &cpdim));
3275a0806964SMatthew G. Knepley else cpdim = 1;
3276a0806964SMatthew G. Knepley
3277a0806964SMatthew G. Knepley if (s) {
32784ef9d792SMatthew G. Knepley /* Transform points from real space to coarse reference space */
32799566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmc, coarseCells[ccell].index, NULL, v0c, Jc, invJc, &detJc));
3280e2d86523SMatthew G. Knepley for (d = 0; d < dim; ++d) pVReal[d] = PetscRealPart(pV[ccell * dim + d]);
3281c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0c, invJc, pVReal, x);
32824ef9d792SMatthew G. Knepley
32834ef9d792SMatthew G. Knepley if (id == PETSCFE_CLASSID) {
32844ef9d792SMatthew G. Knepley /* Evaluate coarse basis on contained point */
3285a0806964SMatthew G. Knepley PetscCall(PetscFEComputeTabulation((PetscFE)obj, 1, x, 0, T));
32869566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemMat, cpdim));
32874ef9d792SMatthew G. Knepley /* Get elemMat entries by multiplying by weight */
32884ef9d792SMatthew G. Knepley for (j = 0; j < cpdim; ++j) {
3289ef0bb6c7SMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[j] += T->T[0][j * Nc + c] * qweights[ccell * qNc + c];
32904ef9d792SMatthew G. Knepley }
32914ef9d792SMatthew G. Knepley } else {
32924ef9d792SMatthew G. Knepley for (j = 0; j < cpdim; ++j) {
32939c3cf19fSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[j] += 1.0 * qweights[ccell * qNc + c];
32944ef9d792SMatthew G. Knepley }
32954ef9d792SMatthew G. Knepley }
32969566063dSJacob Faibussowitsch if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat));
3297a0806964SMatthew G. Knepley }
3298a0806964SMatthew G. Knepley /* Update interpolator */
3299d0f6233fSMatthew G. Knepley PetscCheck(numCIndices == totDim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of element matrix columns %" PetscInt_FMT " != %" PetscInt_FMT, numCIndices, totDim);
3300a0806964SMatthew G. Knepley PetscCall(MatSetValues(interp, 1, &row, cpdim, &cindices[off], elemMat, INSERT_VALUES));
33019566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, PETSC_FALSE, &numCIndices, &cindices, NULL, NULL));
33024ef9d792SMatthew G. Knepley }
33039566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pointVec, &pV));
33049566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseCellSF));
33059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pointVec));
33064ef9d792SMatthew G. Knepley }
33079566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
33084ef9d792SMatthew G. Knepley }
3309a0806964SMatthew G. Knepley if (s && id == PETSCFE_CLASSID) PetscCall(PetscTabulationDestroy(&T));
3310a0806964SMatthew G. Knepley }
3311a0806964SMatthew G. Knepley if (!s) {
3312a0806964SMatthew G. Knepley PetscCall(MatAssemblyBegin(interp, MAT_FINAL_ASSEMBLY));
3313a0806964SMatthew G. Knepley PetscCall(MatAssemblyEnd(interp, MAT_FINAL_ASSEMBLY));
3314a0806964SMatthew G. Knepley PetscCall(MatPreallocatorPreallocate(interp, PETSC_TRUE, In));
3315a0806964SMatthew G. Knepley PetscCall(MatDestroy(&interp));
3316a0806964SMatthew G. Knepley interp = In;
3317a0806964SMatthew G. Knepley }
33184ef9d792SMatthew G. Knepley }
33199566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, J, invJ));
33209566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0c, Jc, invJc));
33219566063dSJacob Faibussowitsch PetscCall(PetscFree(elemMat));
33229566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY));
33239566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY));
33249566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_InterpolatorFEM, dmc, dmf, 0, 0));
33253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
33264ef9d792SMatthew G. Knepley }
33274ef9d792SMatthew G. Knepley
332846fa42a0SMatthew G. Knepley /*@
33290318f8a0SStefano Zampini DMPlexComputeMassMatrixGeneral - Form the local portion of the mass matrix from the coarse `DM` to a non-nested fine `DM`.
3330bd041c0cSMatthew G. Knepley
3331bd041c0cSMatthew G. Knepley Input Parameters:
3332bd041c0cSMatthew G. Knepley + dmf - The fine mesh
3333bd041c0cSMatthew G. Knepley . dmc - The coarse mesh
3334*2a8381b2SBarry Smith - ctx - The application context
3335bd041c0cSMatthew G. Knepley
3336bd041c0cSMatthew G. Knepley Output Parameter:
3337bd041c0cSMatthew G. Knepley . mass - The mass matrix
3338bd041c0cSMatthew G. Knepley
3339bd041c0cSMatthew G. Knepley Level: developer
3340bd041c0cSMatthew G. Knepley
3341ae3cf2c1SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexComputeMassMatrixNested()`, `DMPlexComputeInterpolatorNested()`, `DMPlexComputeInterpolatorGeneral()`
3342bd041c0cSMatthew G. Knepley @*/
DMPlexComputeMassMatrixGeneral(DM dmc,DM dmf,Mat mass,PetscCtx ctx)3343*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeMassMatrixGeneral(DM dmc, DM dmf, Mat mass, PetscCtx ctx)
3344d71ae5a4SJacob Faibussowitsch {
3345bd041c0cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data;
3346bd041c0cSMatthew G. Knepley const char *name = "Mass Matrix";
3347bd041c0cSMatthew G. Knepley PetscDS prob;
3348bd041c0cSMatthew G. Knepley PetscSection fsection, csection, globalFSection, globalCSection;
3349e8f14785SLisandro Dalcin PetscHSetIJ ht;
3350bd041c0cSMatthew G. Knepley PetscLayout rLayout;
3351bd041c0cSMatthew G. Knepley PetscInt *dnz, *onz;
3352bd041c0cSMatthew G. Knepley PetscInt locRows, rStart, rEnd;
3353bd041c0cSMatthew G. Knepley PetscReal *x, *v0, *J, *invJ, detJ;
3354bd041c0cSMatthew G. Knepley PetscReal *v0c, *Jc, *invJc, detJc;
3355bd041c0cSMatthew G. Knepley PetscScalar *elemMat;
3356bd041c0cSMatthew G. Knepley PetscInt dim, Nf, field, totDim, cStart, cEnd, cell, ccell;
3357bd041c0cSMatthew G. Knepley
3358bd041c0cSMatthew G. Knepley PetscFunctionBegin;
33599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmc, &dim));
33609566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &prob));
33619566063dSJacob Faibussowitsch PetscCall(PetscDSGetWorkspace(prob, &x, NULL, NULL, NULL, NULL));
33629566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf));
33639566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim * dim, &J, dim * dim, &invJ));
33649566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0c, dim * dim, &Jc, dim * dim, &invJc));
33659566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmf, &fsection));
33669566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmf, &globalFSection));
33679566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmc, &csection));
33689566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmc, &globalCSection));
33699566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
33709566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim));
33719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(totDim, &elemMat));
3372bd041c0cSMatthew G. Knepley
33739566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mass, &locRows, NULL));
33749566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)mass), &rLayout));
33759566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
33769566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
33779566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rLayout));
33789566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, &rEnd));
33799566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&rLayout));
33809566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
33819566063dSJacob Faibussowitsch PetscCall(PetscHSetIJCreate(&ht));
3382bd041c0cSMatthew G. Knepley for (field = 0; field < Nf; ++field) {
3383bd041c0cSMatthew G. Knepley PetscObject obj;
3384bd041c0cSMatthew G. Knepley PetscClassId id;
3385bd041c0cSMatthew G. Knepley PetscQuadrature quad;
3386bd041c0cSMatthew G. Knepley const PetscReal *qpoints;
3387bd041c0cSMatthew G. Knepley PetscInt Nq, Nc, i, d;
3388bd041c0cSMatthew G. Knepley
33899566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, &obj));
33909566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
33919566063dSJacob Faibussowitsch if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetQuadrature((PetscFE)obj, &quad));
33929566063dSJacob Faibussowitsch else PetscCall(PetscFVGetQuadrature((PetscFV)obj, &quad));
33939566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &Nc, &Nq, &qpoints, NULL));
3394bd041c0cSMatthew G. Knepley /* For each fine grid cell */
3395bd041c0cSMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) {
3396bd041c0cSMatthew G. Knepley Vec pointVec;
3397bd041c0cSMatthew G. Knepley PetscScalar *pV;
3398bd041c0cSMatthew G. Knepley PetscSF coarseCellSF = NULL;
3399bd041c0cSMatthew G. Knepley const PetscSFNode *coarseCells;
3400bd041c0cSMatthew G. Knepley PetscInt numCoarseCells, q, c;
3401bd041c0cSMatthew G. Knepley PetscInt *findices, *cindices;
3402bd041c0cSMatthew G. Knepley PetscInt numFIndices, numCIndices;
3403bd041c0cSMatthew G. Knepley
34049566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
34059566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
3406bd041c0cSMatthew G. Knepley /* Get points from the quadrature */
34079566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, Nq * dim, &pointVec));
34089566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(pointVec, dim));
34099566063dSJacob Faibussowitsch PetscCall(VecGetArray(pointVec, &pV));
3410bd041c0cSMatthew G. Knepley for (q = 0; q < Nq; ++q) {
3411c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.};
3412c330f8ffSToby Isaac
3413bd041c0cSMatthew G. Knepley /* Transform point to real space */
3414c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0, J, &qpoints[q * dim], x);
3415bd041c0cSMatthew G. Knepley for (d = 0; d < dim; ++d) pV[q * dim + d] = x[d];
3416bd041c0cSMatthew G. Knepley }
34179566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pointVec, &pV));
3418bd041c0cSMatthew G. Knepley /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */
34199566063dSJacob Faibussowitsch PetscCall(DMLocatePoints(dmc, pointVec, DM_POINTLOCATION_NEAREST, &coarseCellSF));
34209566063dSJacob Faibussowitsch PetscCall(PetscSFViewFromOptions(coarseCellSF, NULL, "-interp_sf_view"));
3421bd041c0cSMatthew G. Knepley /* Update preallocation info */
34229566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseCellSF, NULL, &numCoarseCells, NULL, &coarseCells));
34235f80ce2aSJacob Faibussowitsch PetscCheck(numCoarseCells == Nq, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not all closure points located");
3424bd041c0cSMatthew G. Knepley {
3425e8f14785SLisandro Dalcin PetscHashIJKey key;
3426e8f14785SLisandro Dalcin PetscBool missing;
3427bd041c0cSMatthew G. Knepley
3428bd041c0cSMatthew G. Knepley for (i = 0; i < numFIndices; ++i) {
3429e8f14785SLisandro Dalcin key.i = findices[i];
3430e8f14785SLisandro Dalcin if (key.i >= 0) {
3431bd041c0cSMatthew G. Knepley /* Get indices for coarse elements */
3432bd041c0cSMatthew G. Knepley for (ccell = 0; ccell < numCoarseCells; ++ccell) {
34339566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, PETSC_FALSE, &numCIndices, &cindices, NULL, NULL));
3434bd041c0cSMatthew G. Knepley for (c = 0; c < numCIndices; ++c) {
3435e8f14785SLisandro Dalcin key.j = cindices[c];
3436e8f14785SLisandro Dalcin if (key.j < 0) continue;
34379566063dSJacob Faibussowitsch PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
3438bd041c0cSMatthew G. Knepley if (missing) {
3439e8f14785SLisandro Dalcin if ((key.j >= rStart) && (key.j < rEnd)) ++dnz[key.i - rStart];
3440e8f14785SLisandro Dalcin else ++onz[key.i - rStart];
3441bd041c0cSMatthew G. Knepley }
3442bd041c0cSMatthew G. Knepley }
34439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, PETSC_FALSE, &numCIndices, &cindices, NULL, NULL));
3444bd041c0cSMatthew G. Knepley }
3445bd041c0cSMatthew G. Knepley }
3446bd041c0cSMatthew G. Knepley }
3447bd041c0cSMatthew G. Knepley }
34489566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseCellSF));
34499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pointVec));
34509566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
3451bd041c0cSMatthew G. Knepley }
3452bd041c0cSMatthew G. Knepley }
34539566063dSJacob Faibussowitsch PetscCall(PetscHSetIJDestroy(&ht));
34549566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
34559566063dSJacob Faibussowitsch PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
34569566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnz, onz));
3457bd041c0cSMatthew G. Knepley for (field = 0; field < Nf; ++field) {
3458bd041c0cSMatthew G. Knepley PetscObject obj;
3459bd041c0cSMatthew G. Knepley PetscClassId id;
3460ef0bb6c7SMatthew G. Knepley PetscTabulation T, Tfine;
3461bd041c0cSMatthew G. Knepley PetscQuadrature quad;
3462bd041c0cSMatthew G. Knepley const PetscReal *qpoints, *qweights;
3463bd041c0cSMatthew G. Knepley PetscInt Nq, Nc, i, d;
3464bd041c0cSMatthew G. Knepley
34659566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, &obj));
34669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
3467ef0bb6c7SMatthew G. Knepley if (id == PETSCFE_CLASSID) {
34689566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature((PetscFE)obj, &quad));
34699566063dSJacob Faibussowitsch PetscCall(PetscFEGetCellTabulation((PetscFE)obj, 1, &Tfine));
34709566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, 1, x, 0, &T));
3471ef0bb6c7SMatthew G. Knepley } else {
34729566063dSJacob Faibussowitsch PetscCall(PetscFVGetQuadrature((PetscFV)obj, &quad));
3473ef0bb6c7SMatthew G. Knepley }
34749566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, &Nc, &Nq, &qpoints, &qweights));
3475bd041c0cSMatthew G. Knepley /* For each fine grid cell */
3476bd041c0cSMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) {
3477bd041c0cSMatthew G. Knepley Vec pointVec;
3478bd041c0cSMatthew G. Knepley PetscScalar *pV;
3479bd041c0cSMatthew G. Knepley PetscSF coarseCellSF = NULL;
3480bd041c0cSMatthew G. Knepley const PetscSFNode *coarseCells;
3481bd041c0cSMatthew G. Knepley PetscInt numCoarseCells, cpdim, q, c, j;
3482bd041c0cSMatthew G. Knepley PetscInt *findices, *cindices;
3483bd041c0cSMatthew G. Knepley PetscInt numFIndices, numCIndices;
3484bd041c0cSMatthew G. Knepley
34859566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
34869566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
3487bd041c0cSMatthew G. Knepley /* Get points from the quadrature */
34889566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, Nq * dim, &pointVec));
34899566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(pointVec, dim));
34909566063dSJacob Faibussowitsch PetscCall(VecGetArray(pointVec, &pV));
3491bd041c0cSMatthew G. Knepley for (q = 0; q < Nq; ++q) {
3492c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.};
3493c330f8ffSToby Isaac
3494bd041c0cSMatthew G. Knepley /* Transform point to real space */
3495c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0, J, &qpoints[q * dim], x);
3496bd041c0cSMatthew G. Knepley for (d = 0; d < dim; ++d) pV[q * dim + d] = x[d];
3497bd041c0cSMatthew G. Knepley }
34989566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pointVec, &pV));
3499bd041c0cSMatthew G. Knepley /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */
35009566063dSJacob Faibussowitsch PetscCall(DMLocatePoints(dmc, pointVec, DM_POINTLOCATION_NEAREST, &coarseCellSF));
3501bd041c0cSMatthew G. Knepley /* Update matrix */
35029566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(coarseCellSF, NULL, &numCoarseCells, NULL, &coarseCells));
35035f80ce2aSJacob Faibussowitsch PetscCheck(numCoarseCells == Nq, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not all closure points located");
35049566063dSJacob Faibussowitsch PetscCall(VecGetArray(pointVec, &pV));
3505bd041c0cSMatthew G. Knepley for (ccell = 0; ccell < numCoarseCells; ++ccell) {
3506bd041c0cSMatthew G. Knepley PetscReal pVReal[3];
3507c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.};
3508c330f8ffSToby Isaac
35099566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, PETSC_FALSE, &numCIndices, &cindices, NULL, NULL));
3510bd041c0cSMatthew G. Knepley /* Transform points from real space to coarse reference space */
35119566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmc, coarseCells[ccell].index, NULL, v0c, Jc, invJc, &detJc));
3512bd041c0cSMatthew G. Knepley for (d = 0; d < dim; ++d) pVReal[d] = PetscRealPart(pV[ccell * dim + d]);
3513c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0c, invJc, pVReal, x);
3514bd041c0cSMatthew G. Knepley
3515bd041c0cSMatthew G. Knepley if (id == PETSCFE_CLASSID) {
3516bd041c0cSMatthew G. Knepley PetscFE fe = (PetscFE)obj;
3517bd041c0cSMatthew G. Knepley
3518bd041c0cSMatthew G. Knepley /* Evaluate coarse basis on contained point */
35199566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &cpdim));
35209566063dSJacob Faibussowitsch PetscCall(PetscFEComputeTabulation(fe, 1, x, 0, T));
3521bd041c0cSMatthew G. Knepley /* Get elemMat entries by multiplying by weight */
3522bd041c0cSMatthew G. Knepley for (i = 0; i < numFIndices; ++i) {
35239566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemMat, cpdim));
3524bd041c0cSMatthew G. Knepley for (j = 0; j < cpdim; ++j) {
3525ef0bb6c7SMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[j] += T->T[0][j * Nc + c] * Tfine->T[0][(ccell * numFIndices + i) * Nc + c] * qweights[ccell * Nc + c] * detJ;
3526bd041c0cSMatthew G. Knepley }
3527bd041c0cSMatthew G. Knepley /* Update interpolator */
35289566063dSJacob Faibussowitsch if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat));
352963a3b9bcSJacob Faibussowitsch PetscCheck(numCIndices == cpdim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of element matrix columns %" PetscInt_FMT " != %" PetscInt_FMT, numCIndices, cpdim);
35309566063dSJacob Faibussowitsch PetscCall(MatSetValues(mass, 1, &findices[i], numCIndices, cindices, elemMat, ADD_VALUES));
3531bd041c0cSMatthew G. Knepley }
3532bd041c0cSMatthew G. Knepley } else {
3533bd041c0cSMatthew G. Knepley cpdim = 1;
3534bd041c0cSMatthew G. Knepley for (i = 0; i < numFIndices; ++i) {
35359566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemMat, cpdim));
3536bd041c0cSMatthew G. Knepley for (j = 0; j < cpdim; ++j) {
3537bd041c0cSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[j] += 1.0 * 1.0 * qweights[ccell * Nc + c] * detJ;
3538bd041c0cSMatthew G. Knepley }
3539bd041c0cSMatthew G. Knepley /* Update interpolator */
35409566063dSJacob Faibussowitsch if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat));
354163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "Nq: %" PetscInt_FMT " %" PetscInt_FMT " Nf: %" PetscInt_FMT " %" PetscInt_FMT " Nc: %" PetscInt_FMT " %" PetscInt_FMT "\n", ccell, Nq, i, numFIndices, j, numCIndices));
354263a3b9bcSJacob Faibussowitsch PetscCheck(numCIndices == cpdim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of element matrix columns %" PetscInt_FMT " != %" PetscInt_FMT, numCIndices, cpdim);
35439566063dSJacob Faibussowitsch PetscCall(MatSetValues(mass, 1, &findices[i], numCIndices, cindices, elemMat, ADD_VALUES));
3544bd041c0cSMatthew G. Knepley }
3545bd041c0cSMatthew G. Knepley }
35469566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, PETSC_FALSE, &numCIndices, &cindices, NULL, NULL));
3547bd041c0cSMatthew G. Knepley }
35489566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pointVec, &pV));
35499566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&coarseCellSF));
35509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pointVec));
35519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
3552bd041c0cSMatthew G. Knepley }
35539566063dSJacob Faibussowitsch if (id == PETSCFE_CLASSID) PetscCall(PetscTabulationDestroy(&T));
3554bd041c0cSMatthew G. Knepley }
35559566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, J, invJ));
35569566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0c, Jc, invJc));
35579566063dSJacob Faibussowitsch PetscCall(PetscFree(elemMat));
35589566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
35599566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
35603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3561bd041c0cSMatthew G. Knepley }
3562bd041c0cSMatthew G. Knepley
3563bd041c0cSMatthew G. Knepley /*@
356446fa42a0SMatthew G. Knepley DMPlexComputeInjectorFEM - Compute a mapping from coarse unknowns to fine unknowns
356546fa42a0SMatthew G. Knepley
356646fa42a0SMatthew G. Knepley Input Parameters:
356746fa42a0SMatthew G. Knepley + dmc - The coarse mesh
356860225df5SJacob Faibussowitsch . dmf - The fine mesh
3569*2a8381b2SBarry Smith - ctx - The application context
357046fa42a0SMatthew G. Knepley
357146fa42a0SMatthew G. Knepley Output Parameter:
357246fa42a0SMatthew G. Knepley . sc - The mapping
357346fa42a0SMatthew G. Knepley
357446fa42a0SMatthew G. Knepley Level: developer
357546fa42a0SMatthew G. Knepley
3576ae3cf2c1SStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexComputeInterpolatorNested()`
357746fa42a0SMatthew G. Knepley @*/
DMPlexComputeInjectorFEM(DM dmc,DM dmf,VecScatter * sc,PetscCtx ctx)3578*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeInjectorFEM(DM dmc, DM dmf, VecScatter *sc, PetscCtx ctx)
3579d71ae5a4SJacob Faibussowitsch {
3580e9d4ef1bSMatthew G. Knepley PetscDS prob;
35817c927364SMatthew G. Knepley PetscFE *feRef;
358297c42addSMatthew G. Knepley PetscFV *fvRef;
35837c927364SMatthew G. Knepley Vec fv, cv;
35847c927364SMatthew G. Knepley IS fis, cis;
35857c927364SMatthew G. Knepley PetscSection fsection, fglobalSection, csection, cglobalSection;
35867c927364SMatthew G. Knepley PetscInt *cmap, *cellCIndices, *cellFIndices, *cindices, *findices;
3587485ad865SMatthew G. Knepley PetscInt cTotDim, fTotDim = 0, Nf, f, field, cStart, cEnd, c, dim, d, startC, endC, offsetC, offsetF, m;
35886f3d3cbcSMatthew G. Knepley PetscBool *needAvg;
35897c927364SMatthew G. Knepley
35907c927364SMatthew G. Knepley PetscFunctionBegin;
35919566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_InjectorFEM, dmc, dmf, 0, 0));
35929566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmf, &dim));
35939566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmf, &fsection));
35949566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmf, &fglobalSection));
35959566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmc, &csection));
35969566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmc, &cglobalSection));
35979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &Nf));
35989566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dmc, 0, &cStart, &cEnd));
35999566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &prob));
36009566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(Nf, &feRef, Nf, &fvRef, Nf, &needAvg));
36017c927364SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
360297c42addSMatthew G. Knepley PetscObject obj;
360397c42addSMatthew G. Knepley PetscClassId id;
3604aa7890ccSMatthew G. Knepley PetscInt fNb = 0, Nc = 0;
36057c927364SMatthew G. Knepley
36069566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, &obj));
36079566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
360897c42addSMatthew G. Knepley if (id == PETSCFE_CLASSID) {
360997c42addSMatthew G. Knepley PetscFE fe = (PetscFE)obj;
36106f3d3cbcSMatthew G. Knepley PetscSpace sp;
36119b2fc754SMatthew G. Knepley PetscInt maxDegree;
361297c42addSMatthew G. Knepley
36139566063dSJacob Faibussowitsch PetscCall(PetscFERefine(fe, &feRef[f]));
36149566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(feRef[f], &fNb));
36159566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(fe, &Nc));
36169566063dSJacob Faibussowitsch PetscCall(PetscFEGetBasisSpace(fe, &sp));
36179566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(sp, NULL, &maxDegree));
36189b2fc754SMatthew G. Knepley if (!maxDegree) needAvg[f] = PETSC_TRUE;
361997c42addSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
362097c42addSMatthew G. Knepley PetscFV fv = (PetscFV)obj;
362197c42addSMatthew G. Knepley PetscDualSpace Q;
362297c42addSMatthew G. Knepley
36239566063dSJacob Faibussowitsch PetscCall(PetscFVRefine(fv, &fvRef[f]));
36249566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fvRef[f], &Q));
36259566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(Q, &fNb));
36269566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc));
36276f3d3cbcSMatthew G. Knepley needAvg[f] = PETSC_TRUE;
362897c42addSMatthew G. Knepley }
3629d172c84bSMatthew G. Knepley fTotDim += fNb;
36307c927364SMatthew G. Knepley }
36319566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &cTotDim));
36329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cTotDim, &cmap));
36337c927364SMatthew G. Knepley for (field = 0, offsetC = 0, offsetF = 0; field < Nf; ++field) {
36347c927364SMatthew G. Knepley PetscFE feC;
363597c42addSMatthew G. Knepley PetscFV fvC;
36367c927364SMatthew G. Knepley PetscDualSpace QF, QC;
3637d172c84bSMatthew G. Knepley PetscInt order = -1, NcF, NcC, fpdim, cpdim;
36387c927364SMatthew G. Knepley
363997c42addSMatthew G. Knepley if (feRef[field]) {
36409566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, (PetscObject *)&feC));
36419566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(feC, &NcC));
36429566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents(feRef[field], &NcF));
36439566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(feRef[field], &QF));
36449566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetOrder(QF, &order));
36459566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(QF, &fpdim));
36469566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(feC, &QC));
36479566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(QC, &cpdim));
364897c42addSMatthew G. Knepley } else {
36499566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, (PetscObject *)&fvC));
36509566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fvC, &NcC));
36519566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fvRef[field], &NcF));
36529566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fvRef[field], &QF));
36539566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(QF, &fpdim));
36549566063dSJacob Faibussowitsch PetscCall(PetscFVGetDualSpace(fvC, &QC));
36559566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(QC, &cpdim));
365697c42addSMatthew G. Knepley }
365763a3b9bcSJacob Faibussowitsch PetscCheck(NcF == NcC, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in fine space field %" PetscInt_FMT " does not match coarse field %" PetscInt_FMT, NcF, NcC);
36587c927364SMatthew G. Knepley for (c = 0; c < cpdim; ++c) {
36597c927364SMatthew G. Knepley PetscQuadrature cfunc;
3660d172c84bSMatthew G. Knepley const PetscReal *cqpoints, *cqweights;
3661d172c84bSMatthew G. Knepley PetscInt NqcC, NpC;
366297c42addSMatthew G. Knepley PetscBool found = PETSC_FALSE;
36637c927364SMatthew G. Knepley
36649566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(QC, c, &cfunc));
36659566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(cfunc, NULL, &NqcC, &NpC, &cqpoints, &cqweights));
366663a3b9bcSJacob Faibussowitsch PetscCheck(NqcC == NcC, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of quadrature components %" PetscInt_FMT " must match number of field components %" PetscInt_FMT, NqcC, NcC);
36671dca8a05SBarry Smith PetscCheck(NpC == 1 || !feRef[field], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not know how to do injection for moments");
36687c927364SMatthew G. Knepley for (f = 0; f < fpdim; ++f) {
36697c927364SMatthew G. Knepley PetscQuadrature ffunc;
3670d172c84bSMatthew G. Knepley const PetscReal *fqpoints, *fqweights;
36717c927364SMatthew G. Knepley PetscReal sum = 0.0;
3672d172c84bSMatthew G. Knepley PetscInt NqcF, NpF;
36737c927364SMatthew G. Knepley
36749566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetFunctional(QF, f, &ffunc));
36759566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(ffunc, NULL, &NqcF, &NpF, &fqpoints, &fqweights));
367663a3b9bcSJacob Faibussowitsch PetscCheck(NqcF == NcF, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of quadrature components %" PetscInt_FMT " must match number of field components %" PetscInt_FMT, NqcF, NcF);
36777c927364SMatthew G. Knepley if (NpC != NpF) continue;
36787c927364SMatthew G. Knepley for (d = 0; d < dim; ++d) sum += PetscAbsReal(cqpoints[d] - fqpoints[d]);
36797c927364SMatthew G. Knepley if (sum > 1.0e-9) continue;
3680d172c84bSMatthew G. Knepley for (d = 0; d < NcC; ++d) sum += PetscAbsReal(cqweights[d] * fqweights[d]);
3681d172c84bSMatthew G. Knepley if (sum < 1.0e-9) continue;
3682d172c84bSMatthew G. Knepley cmap[offsetC + c] = offsetF + f;
368397c42addSMatthew G. Knepley found = PETSC_TRUE;
36847c927364SMatthew G. Knepley break;
36857c927364SMatthew G. Knepley }
368697c42addSMatthew G. Knepley if (!found) {
368797c42addSMatthew G. Knepley /* TODO We really want the average here, but some asshole put VecScatter in the interface */
3688966bd95aSPierre Jolivet PetscCheck(fvRef[field] || (feRef[field] && order == 0), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate matching functional for injection");
3689d172c84bSMatthew G. Knepley cmap[offsetC + c] = offsetF + 0;
369097c42addSMatthew G. Knepley }
36917c927364SMatthew G. Knepley }
3692d172c84bSMatthew G. Knepley offsetC += cpdim;
3693d172c84bSMatthew G. Knepley offsetF += fpdim;
36947c927364SMatthew G. Knepley }
36959371c9d4SSatish Balay for (f = 0; f < Nf; ++f) {
36969371c9d4SSatish Balay PetscCall(PetscFEDestroy(&feRef[f]));
36979371c9d4SSatish Balay PetscCall(PetscFVDestroy(&fvRef[f]));
36989371c9d4SSatish Balay }
36999566063dSJacob Faibussowitsch PetscCall(PetscFree3(feRef, fvRef, needAvg));
37007c927364SMatthew G. Knepley
37019566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmf, &fv));
37029566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmc, &cv));
37039566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(cv, &startC, &endC));
37049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(cglobalSection, &m));
37059566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(cTotDim, &cellCIndices, fTotDim, &cellFIndices));
37069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &cindices));
37079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &findices));
37087c927364SMatthew G. Knepley for (d = 0; d < m; ++d) cindices[d] = findices[d] = -1;
37097c927364SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
37109566063dSJacob Faibussowitsch PetscCall(DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, c, cellCIndices, cellFIndices));
37117c927364SMatthew G. Knepley for (d = 0; d < cTotDim; ++d) {
37120bd915a7SMatthew G. Knepley if ((cellCIndices[d] < startC) || (cellCIndices[d] >= endC)) continue;
3713d2457c26SMatthew G. Knepley PetscCheck(!(findices[cellCIndices[d] - startC] >= 0) || !(findices[cellCIndices[d] - startC] != cellFIndices[cmap[d]]), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cell %" PetscInt_FMT " Coarse dof %" PetscInt_FMT " maps to both %" PetscInt_FMT " and %" PetscInt_FMT, c, cindices[cellCIndices[d] - startC], findices[cellCIndices[d] - startC], cellFIndices[cmap[d]]);
37147c927364SMatthew G. Knepley cindices[cellCIndices[d] - startC] = cellCIndices[d];
37157c927364SMatthew G. Knepley findices[cellCIndices[d] - startC] = cellFIndices[cmap[d]];
37167c927364SMatthew G. Knepley }
37177c927364SMatthew G. Knepley }
37189566063dSJacob Faibussowitsch PetscCall(PetscFree(cmap));
37199566063dSJacob Faibussowitsch PetscCall(PetscFree2(cellCIndices, cellFIndices));
37207c927364SMatthew G. Knepley
37219566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, cindices, PETSC_OWN_POINTER, &cis));
37229566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, findices, PETSC_OWN_POINTER, &fis));
37239566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cv, cis, fv, fis, sc));
37249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cis));
37259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis));
37269566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmf, &fv));
37279566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmc, &cv));
37289566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_InjectorFEM, dmc, dmf, 0, 0));
37293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3730cb1e1211SMatthew G Knepley }
3731a1cf66bbSMatthew G. Knepley
37322f856554SMatthew G. Knepley /*@C
37332f856554SMatthew G. Knepley DMPlexGetCellFields - Retrieve the field values values for a chunk of cells
37342f856554SMatthew G. Knepley
37352f856554SMatthew G. Knepley Input Parameters:
3736a1cb98faSBarry Smith + dm - The `DM`
37372f856554SMatthew G. Knepley . cellIS - The cells to include
37382f856554SMatthew G. Knepley . locX - A local vector with the solution fields
3739ce78bad3SBarry Smith . locX_t - A local vector with solution field time derivatives, or `NULL`
3740ce78bad3SBarry Smith - locA - A local vector with auxiliary fields, or `NULL`
37412f856554SMatthew G. Knepley
37422f856554SMatthew G. Knepley Output Parameters:
37432f856554SMatthew G. Knepley + u - The field coefficients
37442f856554SMatthew G. Knepley . u_t - The fields derivative coefficients
37452f856554SMatthew G. Knepley - a - The auxiliary field coefficients
37462f856554SMatthew G. Knepley
37472f856554SMatthew G. Knepley Level: developer
37482f856554SMatthew G. Knepley
37491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetFaceFields()`
37502f856554SMatthew G. Knepley @*/
DMPlexGetCellFields(DM dm,IS cellIS,Vec locX,PeOp Vec locX_t,PeOp Vec locA,PetscScalar * u[],PetscScalar * u_t[],PetscScalar * a[])3751ce78bad3SBarry Smith PetscErrorCode DMPlexGetCellFields(DM dm, IS cellIS, Vec locX, PeOp Vec locX_t, PeOp Vec locA, PetscScalar *u[], PetscScalar *u_t[], PetscScalar *a[])
3752d71ae5a4SJacob Faibussowitsch {
37532f856554SMatthew G. Knepley DM plex, plexA = NULL;
3754a6e0b375SMatthew G. Knepley DMEnclosureType encAux;
37552f856554SMatthew G. Knepley PetscSection section, sectionAux;
37562f856554SMatthew G. Knepley PetscDS prob;
37572f856554SMatthew G. Knepley const PetscInt *cells;
37582f856554SMatthew G. Knepley PetscInt cStart, cEnd, numCells, totDim, totDimAux, c;
37592f856554SMatthew G. Knepley
37602f856554SMatthew G. Knepley PetscFunctionBegin;
37612f856554SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3762064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(locX, VEC_CLASSID, 3);
3763ad540459SPierre Jolivet if (locX_t) PetscValidHeaderSpecific(locX_t, VEC_CLASSID, 4);
3764ad540459SPierre Jolivet if (locA) PetscValidHeaderSpecific(locA, VEC_CLASSID, 5);
37654f572ea9SToby Isaac PetscAssertPointer(u, 6);
37664f572ea9SToby Isaac PetscAssertPointer(u_t, 7);
37674f572ea9SToby Isaac PetscAssertPointer(a, 8);
37689566063dSJacob Faibussowitsch PetscCall(DMPlexConvertPlex(dm, &plex, PETSC_FALSE));
37699566063dSJacob Faibussowitsch PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
37709566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
377107218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dm, cells ? cells[cStart] : cStart, &prob, NULL));
37729566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim));
37732f856554SMatthew G. Knepley if (locA) {
37742f856554SMatthew G. Knepley DM dmAux;
37752f856554SMatthew G. Knepley PetscDS probAux;
37762f856554SMatthew G. Knepley
37779566063dSJacob Faibussowitsch PetscCall(VecGetDM(locA, &dmAux));
37789566063dSJacob Faibussowitsch PetscCall(DMGetEnclosureRelation(dmAux, dm, &encAux));
37799566063dSJacob Faibussowitsch PetscCall(DMPlexConvertPlex(dmAux, &plexA, PETSC_FALSE));
37809566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmAux, §ionAux));
37819566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmAux, &probAux));
37829566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(probAux, &totDimAux));
37832f856554SMatthew G. Knepley }
37842f856554SMatthew G. Knepley numCells = cEnd - cStart;
37859566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numCells * totDim, MPIU_SCALAR, u));
37869371c9d4SSatish Balay if (locX_t) PetscCall(DMGetWorkArray(dm, numCells * totDim, MPIU_SCALAR, u_t));
3787ad540459SPierre Jolivet else *u_t = NULL;
37889371c9d4SSatish Balay if (locA) PetscCall(DMGetWorkArray(dm, numCells * totDimAux, MPIU_SCALAR, a));
3789ad540459SPierre Jolivet else *a = NULL;
37902f856554SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
37912f856554SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
37922f856554SMatthew G. Knepley const PetscInt cind = c - cStart;
37932f856554SMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL, *ul = *u, *ul_t = *u_t, *al = *a;
37942f856554SMatthew G. Knepley PetscInt i;
37952f856554SMatthew G. Knepley
37969566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plex, section, locX, cell, NULL, &x));
37972f856554SMatthew G. Knepley for (i = 0; i < totDim; ++i) ul[cind * totDim + i] = x[i];
37989566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plex, section, locX, cell, NULL, &x));
37992f856554SMatthew G. Knepley if (locX_t) {
38009566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plex, section, locX_t, cell, NULL, &x_t));
38012f856554SMatthew G. Knepley for (i = 0; i < totDim; ++i) ul_t[cind * totDim + i] = x_t[i];
38029566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plex, section, locX_t, cell, NULL, &x_t));
38032f856554SMatthew G. Knepley }
38042f856554SMatthew G. Knepley if (locA) {
38052f856554SMatthew G. Knepley PetscInt subcell;
38069566063dSJacob Faibussowitsch PetscCall(DMGetEnclosurePoint(plexA, dm, encAux, cell, &subcell));
38079566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plexA, sectionAux, locA, subcell, NULL, &x));
38082f856554SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) al[cind * totDimAux + i] = x[i];
38099566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plexA, sectionAux, locA, subcell, NULL, &x));
38102f856554SMatthew G. Knepley }
38112f856554SMatthew G. Knepley }
38129566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex));
38139566063dSJacob Faibussowitsch if (locA) PetscCall(DMDestroy(&plexA));
38149566063dSJacob Faibussowitsch PetscCall(ISRestorePointRange(cellIS, &cStart, &cEnd, &cells));
38153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
38162f856554SMatthew G. Knepley }
38172f856554SMatthew G. Knepley
38182f856554SMatthew G. Knepley /*@C
38192f856554SMatthew G. Knepley DMPlexRestoreCellFields - Restore the field values values for a chunk of cells
38202f856554SMatthew G. Knepley
38212f856554SMatthew G. Knepley Input Parameters:
3822a1cb98faSBarry Smith + dm - The `DM`
38232f856554SMatthew G. Knepley . cellIS - The cells to include
38242f856554SMatthew G. Knepley . locX - A local vector with the solution fields
3825ce78bad3SBarry Smith . locX_t - A local vector with solution field time derivatives, or `NULL`
3826ce78bad3SBarry Smith - locA - A local vector with auxiliary fields, or `NULL`
38272f856554SMatthew G. Knepley
38282f856554SMatthew G. Knepley Output Parameters:
38292f856554SMatthew G. Knepley + u - The field coefficients
38302f856554SMatthew G. Knepley . u_t - The fields derivative coefficients
38312f856554SMatthew G. Knepley - a - The auxiliary field coefficients
38322f856554SMatthew G. Knepley
38332f856554SMatthew G. Knepley Level: developer
38342f856554SMatthew G. Knepley
38351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetFaceFields()`
38362f856554SMatthew G. Knepley @*/
DMPlexRestoreCellFields(DM dm,IS cellIS,Vec locX,PeOp Vec locX_t,PeOp Vec locA,PetscScalar * u[],PetscScalar * u_t[],PetscScalar * a[])3837ce78bad3SBarry Smith PetscErrorCode DMPlexRestoreCellFields(DM dm, IS cellIS, Vec locX, PeOp Vec locX_t, PeOp Vec locA, PetscScalar *u[], PetscScalar *u_t[], PetscScalar *a[])
3838d71ae5a4SJacob Faibussowitsch {
38392f856554SMatthew G. Knepley PetscFunctionBegin;
38409566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, u));
38419566063dSJacob Faibussowitsch if (locX_t) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, u_t));
38429566063dSJacob Faibussowitsch if (locA) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, a));
38433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
38442f856554SMatthew G. Knepley }
38452f856554SMatthew G. Knepley
DMPlexGetHybridCellFields(DM dm,IS cellIS,Vec locX,Vec locX_t,Vec locA,PetscScalar ** u,PetscScalar ** u_t,PetscScalar ** a)3846a4e35b19SJacob Faibussowitsch static PetscErrorCode DMPlexGetHybridCellFields(DM dm, IS cellIS, Vec locX, Vec locX_t, Vec locA, PetscScalar **u, PetscScalar **u_t, PetscScalar **a)
3847d71ae5a4SJacob Faibussowitsch {
384807218a29SMatthew G. Knepley DM plex, plexA = NULL;
384907218a29SMatthew G. Knepley DMEnclosureType encAux;
385007218a29SMatthew G. Knepley PetscSection section, sectionAux;
385107218a29SMatthew G. Knepley PetscDS ds, dsIn;
38526528b96dSMatthew G. Knepley const PetscInt *cells;
385307218a29SMatthew G. Knepley PetscInt cStart, cEnd, numCells, c, totDim, totDimAux, Nf, f;
38546528b96dSMatthew G. Knepley
38556528b96dSMatthew G. Knepley PetscFunctionBegin;
385607218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
385707218a29SMatthew G. Knepley PetscValidHeaderSpecific(cellIS, IS_CLASSID, 2);
385807218a29SMatthew G. Knepley PetscValidHeaderSpecific(locX, VEC_CLASSID, 3);
3859ac530a7eSPierre Jolivet if (locX_t) PetscValidHeaderSpecific(locX_t, VEC_CLASSID, 4);
3860ac530a7eSPierre Jolivet if (locA) PetscValidHeaderSpecific(locA, VEC_CLASSID, 5);
38614f572ea9SToby Isaac PetscAssertPointer(u, 6);
38624f572ea9SToby Isaac PetscAssertPointer(u_t, 7);
38634f572ea9SToby Isaac PetscAssertPointer(a, 8);
386407218a29SMatthew G. Knepley PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
386507218a29SMatthew G. Knepley numCells = cEnd - cStart;
386607218a29SMatthew G. Knepley PetscCall(DMPlexConvertPlex(dm, &plex, PETSC_FALSE));
386707218a29SMatthew G. Knepley PetscCall(DMGetLocalSection(dm, §ion));
386807218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dm, cells ? cells[cStart] : cStart, &ds, &dsIn));
386907218a29SMatthew G. Knepley PetscCall(PetscDSGetNumFields(dsIn, &Nf));
387007218a29SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsIn, &totDim));
387107218a29SMatthew G. Knepley if (locA) {
387207218a29SMatthew G. Knepley DM dmAux;
387307218a29SMatthew G. Knepley PetscDS probAux;
387407218a29SMatthew G. Knepley
387507218a29SMatthew G. Knepley PetscCall(VecGetDM(locA, &dmAux));
387607218a29SMatthew G. Knepley PetscCall(DMGetEnclosureRelation(dmAux, dm, &encAux));
387707218a29SMatthew G. Knepley PetscCall(DMPlexConvertPlex(dmAux, &plexA, PETSC_FALSE));
387807218a29SMatthew G. Knepley PetscCall(DMGetLocalSection(dmAux, §ionAux));
387907218a29SMatthew G. Knepley PetscCall(DMGetDS(dmAux, &probAux));
388007218a29SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(probAux, &totDimAux));
388107218a29SMatthew G. Knepley }
388207218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, numCells * totDim, MPIU_SCALAR, u));
388307218a29SMatthew G. Knepley if (locX_t) PetscCall(DMGetWorkArray(dm, numCells * totDim, MPIU_SCALAR, u_t));
388407218a29SMatthew G. Knepley else {
388507218a29SMatthew G. Knepley *u_t = NULL;
388607218a29SMatthew G. Knepley }
388707218a29SMatthew G. Knepley if (locA) PetscCall(DMGetWorkArray(dm, numCells * totDimAux, MPIU_SCALAR, a));
388807218a29SMatthew G. Knepley else {
388907218a29SMatthew G. Knepley *a = NULL;
389007218a29SMatthew G. Knepley }
389107218a29SMatthew G. Knepley // Loop over cohesive cells
389207218a29SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
389307218a29SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
389407218a29SMatthew G. Knepley const PetscInt cind = c - cStart;
389574a0c561SMatthew G. Knepley PetscScalar *xf = NULL, *xc = NULL, *x = NULL, *xf_t = NULL, *xc_t = NULL;
38968e3a54c0SPierre Jolivet PetscScalar *ul = &(*u)[cind * totDim], *ul_t = PetscSafePointerPlusOffset(*u_t, cind * totDim);
389707218a29SMatthew G. Knepley const PetscInt *cone, *ornt;
389807218a29SMatthew G. Knepley PetscInt Nx = 0, Nxf, s;
389907218a29SMatthew G. Knepley
390007218a29SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, cell, &cone));
390107218a29SMatthew G. Knepley PetscCall(DMPlexGetConeOrientation(dm, cell, &ornt));
390207218a29SMatthew G. Knepley // Put in cohesive unknowns
390307218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(plex, section, locX, cell, &Nxf, &xf));
390474a0c561SMatthew G. Knepley if (locX_t) PetscCall(DMPlexVecGetClosure(plex, section, locX_t, cell, NULL, &xf_t));
390507218a29SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
390607218a29SMatthew G. Knepley PetscInt fdofIn, foff, foffIn;
390707218a29SMatthew G. Knepley PetscBool cohesive;
390807218a29SMatthew G. Knepley
390907218a29SMatthew G. Knepley PetscCall(PetscDSGetCohesive(dsIn, f, &cohesive));
391007218a29SMatthew G. Knepley if (!cohesive) continue;
391107218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldSize(dsIn, f, &fdofIn));
391207218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldOffsetCohesive(ds, f, &foff));
391307218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldOffsetCohesive(dsIn, f, &foffIn));
391407218a29SMatthew G. Knepley for (PetscInt i = 0; i < fdofIn; ++i) ul[foffIn + i] = xf[foff + i];
391574a0c561SMatthew G. Knepley if (locX_t)
391674a0c561SMatthew G. Knepley for (PetscInt i = 0; i < fdofIn; ++i) ul_t[foffIn + i] = xf_t[foff + i];
391707218a29SMatthew G. Knepley Nx += fdofIn;
391807218a29SMatthew G. Knepley }
391907218a29SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(plex, section, locX, cell, &Nxf, &xf));
392074a0c561SMatthew G. Knepley if (locX_t) PetscCall(DMPlexVecRestoreClosure(plex, section, locX_t, cell, NULL, &xf_t));
392107218a29SMatthew G. Knepley // Loop over sides of surface
392207218a29SMatthew G. Knepley for (s = 0; s < 2; ++s) {
392307218a29SMatthew G. Knepley const PetscInt *support;
392407218a29SMatthew G. Knepley const PetscInt face = cone[s];
3925989fa639SBrad Aagaard PetscDS dsC;
392607218a29SMatthew G. Knepley PetscInt ssize, ncell, Nxc;
392707218a29SMatthew G. Knepley
392807218a29SMatthew G. Knepley // I don't think I need the face to have 0 orientation in the hybrid cell
392907218a29SMatthew G. Knepley //PetscCheck(!ornt[s], PETSC_COMM_SELF, PETSC_ERR_SUP, "Face %" PetscInt_FMT " in hybrid cell %" PetscInt_FMT " has orientation %" PetscInt_FMT " != 0", face, cell, ornt[s]);
393007218a29SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, face, &support));
393107218a29SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, face, &ssize));
393207218a29SMatthew G. Knepley if (support[0] == cell) ncell = support[1];
393307218a29SMatthew G. Knepley else if (support[1] == cell) ncell = support[0];
393407218a29SMatthew G. Knepley else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " does not have cell %" PetscInt_FMT " in its support", face, cell);
393507218a29SMatthew G. Knepley // Get closure of both face and cell, stick in cell for normal fields and face for cohesive fields
3936989fa639SBrad Aagaard PetscCall(DMGetCellDS(dm, ncell, &dsC, NULL));
393707218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(plex, section, locX, ncell, &Nxc, &xc));
393874a0c561SMatthew G. Knepley if (locX_t) PetscCall(DMPlexVecGetClosure(plex, section, locX_t, ncell, NULL, &xc_t));
393907218a29SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
3940989fa639SBrad Aagaard PetscInt fdofIn, foffIn, foff;
394107218a29SMatthew G. Knepley PetscBool cohesive;
394207218a29SMatthew G. Knepley
394307218a29SMatthew G. Knepley PetscCall(PetscDSGetCohesive(dsIn, f, &cohesive));
394407218a29SMatthew G. Knepley if (cohesive) continue;
394507218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldSize(dsIn, f, &fdofIn));
3946989fa639SBrad Aagaard PetscCall(PetscDSGetFieldOffset(dsC, f, &foff));
394707218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldOffsetCohesive(dsIn, f, &foffIn));
3948989fa639SBrad Aagaard for (PetscInt i = 0; i < fdofIn; ++i) ul[foffIn + s * fdofIn + i] = xc[foff + i];
394974a0c561SMatthew G. Knepley if (locX_t)
3950989fa639SBrad Aagaard for (PetscInt i = 0; i < fdofIn; ++i) ul_t[foffIn + s * fdofIn + i] = xc_t[foff + i];
395107218a29SMatthew G. Knepley Nx += fdofIn;
395207218a29SMatthew G. Knepley }
395307218a29SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(plex, section, locX, ncell, &Nxc, &xc));
395474a0c561SMatthew G. Knepley if (locX_t) PetscCall(DMPlexVecRestoreClosure(plex, section, locX_t, ncell, NULL, &xc_t));
395507218a29SMatthew G. Knepley }
395607218a29SMatthew G. Knepley PetscCheck(Nx == totDim, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Closure size %" PetscInt_FMT " for cell %" PetscInt_FMT " does not match DS size %" PetscInt_FMT, Nx, cell, totDim);
395707218a29SMatthew G. Knepley
395807218a29SMatthew G. Knepley if (locA) {
395907218a29SMatthew G. Knepley PetscScalar *al = &(*a)[cind * totDimAux];
396007218a29SMatthew G. Knepley PetscInt subcell;
396107218a29SMatthew G. Knepley
396207218a29SMatthew G. Knepley PetscCall(DMGetEnclosurePoint(plexA, dm, encAux, cell, &subcell));
396307218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(plexA, sectionAux, locA, subcell, &Nx, &x));
396407218a29SMatthew G. Knepley PetscCheck(Nx == totDimAux, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Closure size %" PetscInt_FMT " for subcell %" PetscInt_FMT "does not match DS size %" PetscInt_FMT, Nx, subcell, totDimAux);
396507218a29SMatthew G. Knepley for (PetscInt i = 0; i < totDimAux; ++i) al[i] = x[i];
396607218a29SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(plexA, sectionAux, locA, subcell, &Nx, &x));
396707218a29SMatthew G. Knepley }
396807218a29SMatthew G. Knepley }
396907218a29SMatthew G. Knepley PetscCall(DMDestroy(&plex));
397007218a29SMatthew G. Knepley PetscCall(DMDestroy(&plexA));
397107218a29SMatthew G. Knepley PetscCall(ISRestorePointRange(cellIS, &cStart, &cEnd, &cells));
397207218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
397307218a29SMatthew G. Knepley }
397407218a29SMatthew G. Knepley
397507218a29SMatthew G. Knepley /*
39763e2b0218SMatthew G. Knepley DMPlexGetHybridFields - Get the field values for the negative side (s = 0) and positive side (s = 1) of the interface
397707218a29SMatthew G. Knepley
397807218a29SMatthew G. Knepley Input Parameters:
397907218a29SMatthew G. Knepley + dm - The full domain DM
398007218a29SMatthew G. Knepley . dmX - An array of DM for the field, say an auxiliary DM, indexed by s
398107218a29SMatthew G. Knepley . dsX - An array of PetscDS for the field, indexed by s
398207218a29SMatthew G. Knepley . cellIS - The interface cells for which we want values
398307218a29SMatthew G. Knepley . locX - An array of local vectors with the field values, indexed by s
398407218a29SMatthew G. Knepley - useCell - Flag to have values come from neighboring cell rather than endcap face
398507218a29SMatthew G. Knepley
398607218a29SMatthew G. Knepley Output Parameter:
398707218a29SMatthew G. Knepley . x - An array of field values, indexed by s
398807218a29SMatthew G. Knepley
398907218a29SMatthew G. Knepley Note:
399076fbde31SPierre Jolivet The arrays in `x` will be allocated using `DMGetWorkArray()`, and must be returned using `DMPlexRestoreHybridFields()`.
399107218a29SMatthew G. Knepley
399207218a29SMatthew G. Knepley Level: advanced
399307218a29SMatthew G. Knepley
399476fbde31SPierre Jolivet .seealso: `DMPlexRestoreHybridFields()`, `DMGetWorkArray()`
399507218a29SMatthew G. Knepley */
DMPlexGetHybridFields(DM dm,DM dmX[],PetscDS dsX[],IS cellIS,Vec locX[],PetscBool useCell,PetscScalar * x[])399607218a29SMatthew G. Knepley static PetscErrorCode DMPlexGetHybridFields(DM dm, DM dmX[], PetscDS dsX[], IS cellIS, Vec locX[], PetscBool useCell, PetscScalar *x[])
399707218a29SMatthew G. Knepley {
399807218a29SMatthew G. Knepley DM plexX[2];
399907218a29SMatthew G. Knepley DMEnclosureType encX[2];
400007218a29SMatthew G. Knepley PetscSection sectionX[2];
400107218a29SMatthew G. Knepley const PetscInt *cells;
400207218a29SMatthew G. Knepley PetscInt cStart, cEnd, numCells, c, s, totDimX[2];
400307218a29SMatthew G. Knepley
400407218a29SMatthew G. Knepley PetscFunctionBegin;
40054f572ea9SToby Isaac PetscAssertPointer(locX, 5);
400607218a29SMatthew G. Knepley if (!locX[0] || !locX[1]) PetscFunctionReturn(PETSC_SUCCESS);
40074f572ea9SToby Isaac PetscAssertPointer(dmX, 2);
40084f572ea9SToby Isaac PetscAssertPointer(dsX, 3);
400907218a29SMatthew G. Knepley PetscValidHeaderSpecific(cellIS, IS_CLASSID, 4);
40104f572ea9SToby Isaac PetscAssertPointer(x, 7);
40119566063dSJacob Faibussowitsch PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
40126528b96dSMatthew G. Knepley numCells = cEnd - cStart;
4013148442b3SMatthew G. Knepley for (s = 0; s < 2; ++s) {
401407218a29SMatthew G. Knepley PetscValidHeaderSpecific(dmX[s], DM_CLASSID, 2);
401507218a29SMatthew G. Knepley PetscValidHeaderSpecific(dsX[s], PETSCDS_CLASSID, 3);
401607218a29SMatthew G. Knepley PetscValidHeaderSpecific(locX[s], VEC_CLASSID, 5);
401707218a29SMatthew G. Knepley PetscCall(DMPlexConvertPlex(dmX[s], &plexX[s], PETSC_FALSE));
401807218a29SMatthew G. Knepley PetscCall(DMGetEnclosureRelation(dmX[s], dm, &encX[s]));
401907218a29SMatthew G. Knepley PetscCall(DMGetLocalSection(dmX[s], §ionX[s]));
402007218a29SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsX[s], &totDimX[s]));
402107218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dmX[s], numCells * totDimX[s], MPIU_SCALAR, &x[s]));
402204c51a94SMatthew G. Knepley }
4023148442b3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
40246528b96dSMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
40256528b96dSMatthew G. Knepley const PetscInt cind = c - cStart;
40266528b96dSMatthew G. Knepley const PetscInt *cone, *ornt;
40276528b96dSMatthew G. Knepley
40289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cell, &cone));
40299566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, cell, &ornt));
403007218a29SMatthew G. Knepley //PetscCheck(!ornt[0], PETSC_COMM_SELF, PETSC_ERR_SUP, "Face %" PetscInt_FMT " in hybrid cell %" PetscInt_FMT " has orientation %" PetscInt_FMT " != 0", cone[0], cell, ornt[0]);
4031148442b3SMatthew G. Knepley for (s = 0; s < 2; ++s) {
403207218a29SMatthew G. Knepley const PetscInt tdX = totDimX[s];
403307218a29SMatthew G. Knepley PetscScalar *closure = NULL, *xl = &x[s][cind * tdX];
403407218a29SMatthew G. Knepley PetscInt face = cone[s], point = face, subpoint, Nx, i;
403507218a29SMatthew G. Knepley
403607218a29SMatthew G. Knepley if (useCell) {
40375fedec97SMatthew G. Knepley const PetscInt *support;
403807218a29SMatthew G. Knepley PetscInt ssize;
40396528b96dSMatthew G. Knepley
404007218a29SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, face, &support));
404107218a29SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, face, &ssize));
404207218a29SMatthew G. Knepley PetscCheck(ssize == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " from cell %" PetscInt_FMT " has support size %" PetscInt_FMT " != 2", face, cell, ssize);
404307218a29SMatthew G. Knepley if (support[0] == cell) point = support[1];
404407218a29SMatthew G. Knepley else if (support[1] == cell) point = support[0];
404507218a29SMatthew G. Knepley else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " does not have cell %" PetscInt_FMT " in its support", face, cell);
404607218a29SMatthew G. Knepley }
404707218a29SMatthew G. Knepley PetscCall(DMGetEnclosurePoint(plexX[s], dm, encX[s], point, &subpoint));
404848162695SZach Atkins PetscCall(DMPlexVecGetOrientedClosure(plexX[s], sectionX[s], PETSC_FALSE, locX[s], subpoint, ornt[s], &Nx, &closure));
404907218a29SMatthew G. Knepley PetscCheck(Nx == tdX, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Closure size %" PetscInt_FMT " for subpoint %" PetscInt_FMT " does not match DS size %" PetscInt_FMT, Nx, subpoint, tdX);
405007218a29SMatthew G. Knepley for (i = 0; i < Nx; ++i) xl[i] = closure[i];
405107218a29SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(plexX[s], sectionX[s], locX[s], subpoint, &Nx, &closure));
40526528b96dSMatthew G. Knepley }
40536528b96dSMatthew G. Knepley }
405407218a29SMatthew G. Knepley for (s = 0; s < 2; ++s) PetscCall(DMDestroy(&plexX[s]));
40559566063dSJacob Faibussowitsch PetscCall(ISRestorePointRange(cellIS, &cStart, &cEnd, &cells));
40563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
40576528b96dSMatthew G. Knepley }
40586528b96dSMatthew G. Knepley
DMPlexRestoreHybridFields(DM dm,DM dmX[],PetscDS dsX[],IS cellIS,Vec locX[],PetscBool useCell,PetscScalar * x[])405907218a29SMatthew G. Knepley static PetscErrorCode DMPlexRestoreHybridFields(DM dm, DM dmX[], PetscDS dsX[], IS cellIS, Vec locX[], PetscBool useCell, PetscScalar *x[])
4060d71ae5a4SJacob Faibussowitsch {
40616528b96dSMatthew G. Knepley PetscFunctionBegin;
406207218a29SMatthew G. Knepley if (!locX[0] || !locX[1]) PetscFunctionReturn(PETSC_SUCCESS);
406307218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dmX[0], 0, MPIU_SCALAR, &x[0]));
406407218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dmX[1], 0, MPIU_SCALAR, &x[1]));
40653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
40666528b96dSMatthew G. Knepley }
40676528b96dSMatthew G. Knepley
40682f856554SMatthew G. Knepley /*@C
40692f856554SMatthew G. Knepley DMPlexGetFaceFields - Retrieve the field values values for a chunk of faces
40702f856554SMatthew G. Knepley
40712f856554SMatthew G. Knepley Input Parameters:
4072a1cb98faSBarry Smith + dm - The `DM`
40732f856554SMatthew G. Knepley . fStart - The first face to include
40742f856554SMatthew G. Knepley . fEnd - The first face to exclude
40752f856554SMatthew G. Knepley . locX - A local vector with the solution fields
4076ce78bad3SBarry Smith . locX_t - A local vector with solution field time derivatives, or `NULL`
40772f856554SMatthew G. Knepley . faceGeometry - A local vector with face geometry
40782f856554SMatthew G. Knepley . cellGeometry - A local vector with cell geometry
4079ce78bad3SBarry Smith - locGrad - A local vector with field gradients, or `NULL`
40802f856554SMatthew G. Knepley
40812f856554SMatthew G. Knepley Output Parameters:
40822f856554SMatthew G. Knepley + Nface - The number of faces with field values
40832f856554SMatthew G. Knepley . uL - The field values at the left side of the face
40842f856554SMatthew G. Knepley - uR - The field values at the right side of the face
40852f856554SMatthew G. Knepley
40862f856554SMatthew G. Knepley Level: developer
40872f856554SMatthew G. Knepley
40881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellFields()`
40892f856554SMatthew G. Knepley @*/
DMPlexGetFaceFields(DM dm,PetscInt fStart,PetscInt fEnd,Vec locX,PeOp Vec locX_t,Vec faceGeometry,Vec cellGeometry,PeOp Vec locGrad,PetscInt * Nface,PetscScalar * uL[],PetscScalar * uR[])4090ce78bad3SBarry Smith PetscErrorCode DMPlexGetFaceFields(DM dm, PetscInt fStart, PetscInt fEnd, Vec locX, PeOp Vec locX_t, Vec faceGeometry, Vec cellGeometry, PeOp Vec locGrad, PetscInt *Nface, PetscScalar *uL[], PetscScalar *uR[])
4091d71ae5a4SJacob Faibussowitsch {
40922f856554SMatthew G. Knepley DM dmFace, dmCell, dmGrad = NULL;
40932f856554SMatthew G. Knepley PetscSection section;
40942f856554SMatthew G. Knepley PetscDS prob;
40952f856554SMatthew G. Knepley DMLabel ghostLabel;
40962f856554SMatthew G. Knepley const PetscScalar *facegeom, *cellgeom, *x, *lgrad;
40972f856554SMatthew G. Knepley PetscBool *isFE;
40982f856554SMatthew G. Knepley PetscInt dim, Nf, f, Nc, numFaces = fEnd - fStart, iface, face;
40992f856554SMatthew G. Knepley
41002f856554SMatthew G. Knepley PetscFunctionBegin;
41012f856554SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41022f856554SMatthew G. Knepley PetscValidHeaderSpecific(locX, VEC_CLASSID, 4);
4103ad540459SPierre Jolivet if (locX_t) PetscValidHeaderSpecific(locX_t, VEC_CLASSID, 5);
41042f856554SMatthew G. Knepley PetscValidHeaderSpecific(faceGeometry, VEC_CLASSID, 6);
41052f856554SMatthew G. Knepley PetscValidHeaderSpecific(cellGeometry, VEC_CLASSID, 7);
4106ad540459SPierre Jolivet if (locGrad) PetscValidHeaderSpecific(locGrad, VEC_CLASSID, 8);
41074f572ea9SToby Isaac PetscAssertPointer(uL, 10);
41084f572ea9SToby Isaac PetscAssertPointer(uR, 11);
41099566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
41109566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
41119566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
41129566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf));
41139566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(prob, &Nc));
41149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nf, &isFE));
41152f856554SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
41162f856554SMatthew G. Knepley PetscObject obj;
41172f856554SMatthew G. Knepley PetscClassId id;
41182f856554SMatthew G. Knepley
41199566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, &obj));
41209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
41219371c9d4SSatish Balay if (id == PETSCFE_CLASSID) {
41229371c9d4SSatish Balay isFE[f] = PETSC_TRUE;
41239371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) {
41249371c9d4SSatish Balay isFE[f] = PETSC_FALSE;
41259371c9d4SSatish Balay } else {
41269371c9d4SSatish Balay isFE[f] = PETSC_FALSE;
41279371c9d4SSatish Balay }
41282f856554SMatthew G. Knepley }
41299566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "ghost", &ghostLabel));
41309566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(locX, &x));
41319566063dSJacob Faibussowitsch PetscCall(VecGetDM(faceGeometry, &dmFace));
41329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(faceGeometry, &facegeom));
41339566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellGeometry, &dmCell));
41349566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeometry, &cellgeom));
41352f856554SMatthew G. Knepley if (locGrad) {
41369566063dSJacob Faibussowitsch PetscCall(VecGetDM(locGrad, &dmGrad));
41379566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(locGrad, &lgrad));
41382f856554SMatthew G. Knepley }
41399566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numFaces * Nc, MPIU_SCALAR, uL));
41409566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numFaces * Nc, MPIU_SCALAR, uR));
41412f856554SMatthew G. Knepley /* Right now just eat the extra work for FE (could make a cell loop) */
41422f856554SMatthew G. Knepley for (face = fStart, iface = 0; face < fEnd; ++face) {
41432f856554SMatthew G. Knepley const PetscInt *cells;
41442f856554SMatthew G. Knepley PetscFVFaceGeom *fg;
41452f856554SMatthew G. Knepley PetscFVCellGeom *cgL, *cgR;
41462f856554SMatthew G. Knepley PetscScalar *xL, *xR, *gL, *gR;
41472f856554SMatthew G. Knepley PetscScalar *uLl = *uL, *uRl = *uR;
41482f856554SMatthew G. Knepley PetscInt ghost, nsupp, nchild;
41492f856554SMatthew G. Knepley
41509566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(ghostLabel, face, &ghost));
41519566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, face, &nsupp));
41529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, face, &nchild, NULL));
41532f856554SMatthew G. Knepley if (ghost >= 0 || nsupp > 2 || nchild > 0) continue;
41549566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, face, facegeom, &fg));
41559566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, face, &cells));
41569566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cgL));
41579566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cells[1], cellgeom, &cgR));
41582f856554SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
41592f856554SMatthew G. Knepley PetscInt off;
41602f856554SMatthew G. Knepley
41619566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponentOffset(prob, f, &off));
41622f856554SMatthew G. Knepley if (isFE[f]) {
41632f856554SMatthew G. Knepley const PetscInt *cone;
41642f856554SMatthew G. Knepley PetscInt comp, coneSizeL, coneSizeR, faceLocL, faceLocR, ldof, rdof, d;
41652f856554SMatthew G. Knepley
41662f856554SMatthew G. Knepley xL = xR = NULL;
41679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &comp));
4168835f2295SStefano Zampini PetscCall(DMPlexVecGetClosure(dm, section, locX, cells[0], &ldof, &xL));
4169835f2295SStefano Zampini PetscCall(DMPlexVecGetClosure(dm, section, locX, cells[1], &rdof, &xR));
41709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cells[0], &cone));
41719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cells[0], &coneSizeL));
41729371c9d4SSatish Balay for (faceLocL = 0; faceLocL < coneSizeL; ++faceLocL)
41739371c9d4SSatish Balay if (cone[faceLocL] == face) break;
41749566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cells[1], &cone));
41759566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cells[1], &coneSizeR));
41769371c9d4SSatish Balay for (faceLocR = 0; faceLocR < coneSizeR; ++faceLocR)
41779371c9d4SSatish Balay if (cone[faceLocR] == face) break;
41781dca8a05SBarry Smith PetscCheck(faceLocL != coneSizeL || faceLocR != coneSizeR, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %" PetscInt_FMT " in cone of cell %" PetscInt_FMT " or cell %" PetscInt_FMT, face, cells[0], cells[1]);
41792f856554SMatthew G. Knepley /* Check that FEM field has values in the right cell (sometimes its an FV ghost cell) */
41802f856554SMatthew G. Knepley /* TODO: this is a hack that might not be right for nonconforming */
41812f856554SMatthew G. Knepley if (faceLocL < coneSizeL) {
41829566063dSJacob Faibussowitsch PetscCall(PetscFEEvaluateFaceFields_Internal(prob, f, faceLocL, xL, &uLl[iface * Nc + off]));
41839566063dSJacob Faibussowitsch if (rdof == ldof && faceLocR < coneSizeR) PetscCall(PetscFEEvaluateFaceFields_Internal(prob, f, faceLocR, xR, &uRl[iface * Nc + off]));
41842f856554SMatthew G. Knepley else {
41859371c9d4SSatish Balay for (d = 0; d < comp; ++d) uRl[iface * Nc + off + d] = uLl[iface * Nc + off + d];
41869371c9d4SSatish Balay }
41879371c9d4SSatish Balay } else {
41889566063dSJacob Faibussowitsch PetscCall(PetscFEEvaluateFaceFields_Internal(prob, f, faceLocR, xR, &uRl[iface * Nc + off]));
41899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &comp));
41902f856554SMatthew G. Knepley for (d = 0; d < comp; ++d) uLl[iface * Nc + off + d] = uRl[iface * Nc + off + d];
41912f856554SMatthew G. Knepley }
4192835f2295SStefano Zampini PetscCall(DMPlexVecRestoreClosure(dm, section, locX, cells[0], &ldof, &xL));
4193835f2295SStefano Zampini PetscCall(DMPlexVecRestoreClosure(dm, section, locX, cells[1], &rdof, &xR));
41942f856554SMatthew G. Knepley } else {
41952f856554SMatthew G. Knepley PetscFV fv;
41962f856554SMatthew G. Knepley PetscInt numComp, c;
41972f856554SMatthew G. Knepley
41989566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, (PetscObject *)&fv));
41999566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &numComp));
42009566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRead(dm, cells[0], f, x, &xL));
42019566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRead(dm, cells[1], f, x, &xR));
42022f856554SMatthew G. Knepley if (dmGrad) {
42032f856554SMatthew G. Knepley PetscReal dxL[3], dxR[3];
42042f856554SMatthew G. Knepley
42059566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmGrad, cells[0], lgrad, &gL));
42069566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmGrad, cells[1], lgrad, &gR));
42072f856554SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, cgL->centroid, fg->centroid, dxL);
42082f856554SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, cgR->centroid, fg->centroid, dxR);
42092f856554SMatthew G. Knepley for (c = 0; c < numComp; ++c) {
42102f856554SMatthew G. Knepley uLl[iface * Nc + off + c] = xL[c] + DMPlex_DotD_Internal(dim, &gL[c * dim], dxL);
42112f856554SMatthew G. Knepley uRl[iface * Nc + off + c] = xR[c] + DMPlex_DotD_Internal(dim, &gR[c * dim], dxR);
42122f856554SMatthew G. Knepley }
42132f856554SMatthew G. Knepley } else {
42142f856554SMatthew G. Knepley for (c = 0; c < numComp; ++c) {
42152f856554SMatthew G. Knepley uLl[iface * Nc + off + c] = xL[c];
42162f856554SMatthew G. Knepley uRl[iface * Nc + off + c] = xR[c];
42172f856554SMatthew G. Knepley }
42182f856554SMatthew G. Knepley }
42192f856554SMatthew G. Knepley }
42202f856554SMatthew G. Knepley }
42212f856554SMatthew G. Knepley ++iface;
42222f856554SMatthew G. Knepley }
42232f856554SMatthew G. Knepley *Nface = iface;
42249566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(locX, &x));
42259566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(faceGeometry, &facegeom));
42269566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellGeometry, &cellgeom));
422748a46eb9SPierre Jolivet if (locGrad) PetscCall(VecRestoreArrayRead(locGrad, &lgrad));
42289566063dSJacob Faibussowitsch PetscCall(PetscFree(isFE));
42293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
42302f856554SMatthew G. Knepley }
42312f856554SMatthew G. Knepley
42322f856554SMatthew G. Knepley /*@C
42332f856554SMatthew G. Knepley DMPlexRestoreFaceFields - Restore the field values values for a chunk of faces
42342f856554SMatthew G. Knepley
42352f856554SMatthew G. Knepley Input Parameters:
4236a1cb98faSBarry Smith + dm - The `DM`
42372f856554SMatthew G. Knepley . fStart - The first face to include
42382f856554SMatthew G. Knepley . fEnd - The first face to exclude
42392f856554SMatthew G. Knepley . locX - A local vector with the solution fields
4240ce78bad3SBarry Smith . locX_t - A local vector with solution field time derivatives, or `NULL`
42412f856554SMatthew G. Knepley . faceGeometry - A local vector with face geometry
42422f856554SMatthew G. Knepley . cellGeometry - A local vector with cell geometry
4243ce78bad3SBarry Smith - locGrad - A local vector with field gradients, or `NULL`
42442f856554SMatthew G. Knepley
42452f856554SMatthew G. Knepley Output Parameters:
42462f856554SMatthew G. Knepley + Nface - The number of faces with field values
42472f856554SMatthew G. Knepley . uL - The field values at the left side of the face
42482f856554SMatthew G. Knepley - uR - The field values at the right side of the face
42492f856554SMatthew G. Knepley
42502f856554SMatthew G. Knepley Level: developer
42512f856554SMatthew G. Knepley
42521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetFaceFields()`
42532f856554SMatthew G. Knepley @*/
DMPlexRestoreFaceFields(DM dm,PetscInt fStart,PetscInt fEnd,Vec locX,PeOp Vec locX_t,Vec faceGeometry,Vec cellGeometry,PeOp Vec locGrad,PetscInt * Nface,PetscScalar * uL[],PetscScalar * uR[])4254ce78bad3SBarry Smith PetscErrorCode DMPlexRestoreFaceFields(DM dm, PetscInt fStart, PetscInt fEnd, Vec locX, PeOp Vec locX_t, Vec faceGeometry, Vec cellGeometry, PeOp Vec locGrad, PetscInt *Nface, PetscScalar *uL[], PetscScalar *uR[])
4255d71ae5a4SJacob Faibussowitsch {
42562f856554SMatthew G. Knepley PetscFunctionBegin;
42579566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, uL));
42589566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, uR));
42593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
42602f856554SMatthew G. Knepley }
42612f856554SMatthew G. Knepley
42622f856554SMatthew G. Knepley /*@C
42632f856554SMatthew G. Knepley DMPlexGetFaceGeometry - Retrieve the geometric values for a chunk of faces
42642f856554SMatthew G. Knepley
42652f856554SMatthew G. Knepley Input Parameters:
4266a1cb98faSBarry Smith + dm - The `DM`
42672f856554SMatthew G. Knepley . fStart - The first face to include
42682f856554SMatthew G. Knepley . fEnd - The first face to exclude
42692f856554SMatthew G. Knepley . faceGeometry - A local vector with face geometry
42702f856554SMatthew G. Knepley - cellGeometry - A local vector with cell geometry
42712f856554SMatthew G. Knepley
42722f856554SMatthew G. Knepley Output Parameters:
42732f856554SMatthew G. Knepley + Nface - The number of faces with field values
4274ce78bad3SBarry Smith . fgeom - The face centroid and normals
4275ce78bad3SBarry Smith - vol - The cell volumes
42762f856554SMatthew G. Knepley
42772f856554SMatthew G. Knepley Level: developer
42782f856554SMatthew G. Knepley
42791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellFields()`
42802f856554SMatthew G. Knepley @*/
DMPlexGetFaceGeometry(DM dm,PetscInt fStart,PetscInt fEnd,Vec faceGeometry,Vec cellGeometry,PetscInt * Nface,PetscFVFaceGeom * fgeom[],PetscReal * vol[])4281ce78bad3SBarry Smith PetscErrorCode DMPlexGetFaceGeometry(DM dm, PetscInt fStart, PetscInt fEnd, Vec faceGeometry, Vec cellGeometry, PetscInt *Nface, PetscFVFaceGeom *fgeom[], PetscReal *vol[])
4282d71ae5a4SJacob Faibussowitsch {
42832f856554SMatthew G. Knepley DM dmFace, dmCell;
42842f856554SMatthew G. Knepley DMLabel ghostLabel;
42852f856554SMatthew G. Knepley const PetscScalar *facegeom, *cellgeom;
42862f856554SMatthew G. Knepley PetscInt dim, numFaces = fEnd - fStart, iface, face;
42872f856554SMatthew G. Knepley
42882f856554SMatthew G. Knepley PetscFunctionBegin;
42892f856554SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
42902f856554SMatthew G. Knepley PetscValidHeaderSpecific(faceGeometry, VEC_CLASSID, 4);
42912f856554SMatthew G. Knepley PetscValidHeaderSpecific(cellGeometry, VEC_CLASSID, 5);
42924f572ea9SToby Isaac PetscAssertPointer(fgeom, 7);
42934f572ea9SToby Isaac PetscAssertPointer(vol, 8);
42949566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
42959566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "ghost", &ghostLabel));
42969566063dSJacob Faibussowitsch PetscCall(VecGetDM(faceGeometry, &dmFace));
42979566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(faceGeometry, &facegeom));
42989566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellGeometry, &dmCell));
42999566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellGeometry, &cellgeom));
43009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numFaces, fgeom));
43019566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numFaces * 2, MPIU_SCALAR, vol));
43022f856554SMatthew G. Knepley for (face = fStart, iface = 0; face < fEnd; ++face) {
43032f856554SMatthew G. Knepley const PetscInt *cells;
43042f856554SMatthew G. Knepley PetscFVFaceGeom *fg;
43052f856554SMatthew G. Knepley PetscFVCellGeom *cgL, *cgR;
43062f856554SMatthew G. Knepley PetscFVFaceGeom *fgeoml = *fgeom;
43072f856554SMatthew G. Knepley PetscReal *voll = *vol;
43082f856554SMatthew G. Knepley PetscInt ghost, d, nchild, nsupp;
43092f856554SMatthew G. Knepley
43109566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(ghostLabel, face, &ghost));
43119566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, face, &nsupp));
43129566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, face, &nchild, NULL));
43132f856554SMatthew G. Knepley if (ghost >= 0 || nsupp > 2 || nchild > 0) continue;
43149566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, face, facegeom, &fg));
43159566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, face, &cells));
43169566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cgL));
43179566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cells[1], cellgeom, &cgR));
43182f856554SMatthew G. Knepley for (d = 0; d < dim; ++d) {
43192f856554SMatthew G. Knepley fgeoml[iface].centroid[d] = fg->centroid[d];
43202f856554SMatthew G. Knepley fgeoml[iface].normal[d] = fg->normal[d];
43212f856554SMatthew G. Knepley }
43222f856554SMatthew G. Knepley voll[iface * 2 + 0] = cgL->volume;
43232f856554SMatthew G. Knepley voll[iface * 2 + 1] = cgR->volume;
43242f856554SMatthew G. Knepley ++iface;
43252f856554SMatthew G. Knepley }
43262f856554SMatthew G. Knepley *Nface = iface;
43279566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(faceGeometry, &facegeom));
43289566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellGeometry, &cellgeom));
43293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43302f856554SMatthew G. Knepley }
43312f856554SMatthew G. Knepley
43322f856554SMatthew G. Knepley /*@C
43332f856554SMatthew G. Knepley DMPlexRestoreFaceGeometry - Restore the field values values for a chunk of faces
43342f856554SMatthew G. Knepley
43352f856554SMatthew G. Knepley Input Parameters:
4336a1cb98faSBarry Smith + dm - The `DM`
43372f856554SMatthew G. Knepley . fStart - The first face to include
43382f856554SMatthew G. Knepley . fEnd - The first face to exclude
43392f856554SMatthew G. Knepley . faceGeometry - A local vector with face geometry
43402f856554SMatthew G. Knepley - cellGeometry - A local vector with cell geometry
43412f856554SMatthew G. Knepley
43422f856554SMatthew G. Knepley Output Parameters:
43432f856554SMatthew G. Knepley + Nface - The number of faces with field values
4344ce78bad3SBarry Smith . fgeom - The face centroid and normals
4345ce78bad3SBarry Smith - vol - The cell volumes
43462f856554SMatthew G. Knepley
43472f856554SMatthew G. Knepley Level: developer
43482f856554SMatthew G. Knepley
43491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetFaceFields()`
43502f856554SMatthew G. Knepley @*/
DMPlexRestoreFaceGeometry(DM dm,PetscInt fStart,PetscInt fEnd,Vec faceGeometry,Vec cellGeometry,PetscInt * Nface,PetscFVFaceGeom * fgeom[],PetscReal * vol[])4351ce78bad3SBarry Smith PetscErrorCode DMPlexRestoreFaceGeometry(DM dm, PetscInt fStart, PetscInt fEnd, Vec faceGeometry, Vec cellGeometry, PetscInt *Nface, PetscFVFaceGeom *fgeom[], PetscReal *vol[])
4352d71ae5a4SJacob Faibussowitsch {
43532f856554SMatthew G. Knepley PetscFunctionBegin;
43549566063dSJacob Faibussowitsch PetscCall(PetscFree(*fgeom));
43559566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_REAL, vol));
43563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
43572f856554SMatthew G. Knepley }
43582f856554SMatthew G. Knepley
DMSNESGetFEGeom(DMField coordField,IS pointIS,PetscQuadrature quad,PetscFEGeomMode mode,PetscFEGeom ** geom)4359ac9d17c7SMatthew G. Knepley PetscErrorCode DMSNESGetFEGeom(DMField coordField, IS pointIS, PetscQuadrature quad, PetscFEGeomMode mode, PetscFEGeom **geom)
4360d71ae5a4SJacob Faibussowitsch {
4361a1cf66bbSMatthew G. Knepley char composeStr[33] = {0};
4362a1cf66bbSMatthew G. Knepley PetscObjectId id;
4363a1cf66bbSMatthew G. Knepley PetscContainer container;
4364a1cf66bbSMatthew G. Knepley
4365a1cf66bbSMatthew G. Knepley PetscFunctionBegin;
43669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetId((PetscObject)quad, &id));
436763a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(composeStr, 32, "DMSNESGetFEGeom_%" PetscInt64_FMT "\n", id));
43689566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pointIS, composeStr, (PetscObject *)&container));
4369a1cf66bbSMatthew G. Knepley if (container) {
4370*2a8381b2SBarry Smith PetscCall(PetscContainerGetPointer(container, geom));
4371a1cf66bbSMatthew G. Knepley } else {
4372ac9d17c7SMatthew G. Knepley PetscCall(DMFieldCreateFEGeom(coordField, pointIS, quad, mode, geom));
43739566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
43749566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(container, (void *)*geom));
437549abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(container, PetscContainerCtxDestroy_PetscFEGeom));
43769566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pointIS, composeStr, (PetscObject)container));
43779566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&container));
4378a1cf66bbSMatthew G. Knepley }
43793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4380a1cf66bbSMatthew G. Knepley }
4381a1cf66bbSMatthew G. Knepley
DMSNESRestoreFEGeom(DMField coordField,IS pointIS,PetscQuadrature quad,PetscBool faceData,PetscFEGeom ** geom)4382d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSNESRestoreFEGeom(DMField coordField, IS pointIS, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom)
4383d71ae5a4SJacob Faibussowitsch {
4384a1cf66bbSMatthew G. Knepley PetscFunctionBegin;
4385a1cf66bbSMatthew G. Knepley *geom = NULL;
43863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4387a1cf66bbSMatthew G. Knepley }
4388a1cf66bbSMatthew G. Knepley
DMPlexComputeResidual_Patch_Internal(DM dm,PetscSection section,IS cellIS,PetscReal t,Vec locX,Vec locX_t,Vec locF,PetscCtx ctx)4389*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeResidual_Patch_Internal(DM dm, PetscSection section, IS cellIS, PetscReal t, Vec locX, Vec locX_t, Vec locF, PetscCtx ctx)
4390d71ae5a4SJacob Faibussowitsch {
439192d50984SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
439292d50984SMatthew G. Knepley const char *name = "Residual";
439392d50984SMatthew G. Knepley DM dmAux = NULL;
439492d50984SMatthew G. Knepley DMLabel ghostLabel = NULL;
439592d50984SMatthew G. Knepley PetscDS prob = NULL;
439692d50984SMatthew G. Knepley PetscDS probAux = NULL;
439792d50984SMatthew G. Knepley PetscBool useFEM = PETSC_FALSE;
439892d50984SMatthew G. Knepley PetscBool isImplicit = (locX_t || t == PETSC_MIN_REAL) ? PETSC_TRUE : PETSC_FALSE;
439992d50984SMatthew G. Knepley DMField coordField = NULL;
4400c0006e53SPatrick Farrell Vec locA;
4401c0006e53SPatrick Farrell PetscScalar *u = NULL, *u_t, *a, *uL = NULL, *uR = NULL;
440292d50984SMatthew G. Knepley IS chunkIS;
440392d50984SMatthew G. Knepley const PetscInt *cells;
440492d50984SMatthew G. Knepley PetscInt cStart, cEnd, numCells;
4405364207b6SKarl Rupp PetscInt Nf, f, totDim, totDimAux, numChunks, cellChunkSize, chunk, fStart, fEnd;
44061690c2aeSBarry Smith PetscInt maxDegree = PETSC_INT_MAX;
440706ad1575SMatthew G. Knepley PetscFormKey key;
440892d50984SMatthew G. Knepley PetscQuadrature affineQuad = NULL, *quads = NULL;
440992d50984SMatthew G. Knepley PetscFEGeom *affineGeom = NULL, **geoms = NULL;
441092d50984SMatthew G. Knepley
441192d50984SMatthew G. Knepley PetscFunctionBegin;
44129566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_ResidualFEM, dm, 0, 0, 0));
441392d50984SMatthew G. Knepley /* FEM+FVM */
441492d50984SMatthew G. Knepley /* 1: Get sizes from dm and dmAux */
44159566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "ghost", &ghostLabel));
44169566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
44179566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf));
44189566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim));
44199566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, NULL, 0, 0, &locA));
442092d50984SMatthew G. Knepley if (locA) {
44219566063dSJacob Faibussowitsch PetscCall(VecGetDM(locA, &dmAux));
44229566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmAux, &probAux));
44239566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(probAux, &totDimAux));
442492d50984SMatthew G. Knepley }
442592d50984SMatthew G. Knepley /* 2: Get geometric data */
442692d50984SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
442792d50984SMatthew G. Knepley PetscObject obj;
442892d50984SMatthew G. Knepley PetscClassId id;
442992d50984SMatthew G. Knepley PetscBool fimp;
443092d50984SMatthew G. Knepley
44319566063dSJacob Faibussowitsch PetscCall(PetscDSGetImplicit(prob, f, &fimp));
443292d50984SMatthew G. Knepley if (isImplicit != fimp) continue;
44339566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, &obj));
44349566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
4435ad540459SPierre Jolivet if (id == PETSCFE_CLASSID) useFEM = PETSC_TRUE;
44365f80ce2aSJacob Faibussowitsch PetscCheck(id != PETSCFV_CLASSID, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Use of FVM with PCPATCH not yet implemented");
443792d50984SMatthew G. Knepley }
443892d50984SMatthew G. Knepley if (useFEM) {
44399566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
44409566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, cellIS, NULL, &maxDegree));
444192d50984SMatthew G. Knepley if (maxDegree <= 1) {
44429566063dSJacob Faibussowitsch PetscCall(DMFieldCreateDefaultQuadrature(coordField, cellIS, &affineQuad));
4443ac9d17c7SMatthew G. Knepley if (affineQuad) PetscCall(DMSNESGetFEGeom(coordField, cellIS, affineQuad, PETSC_FEGEOM_BASIC, &affineGeom));
444492d50984SMatthew G. Knepley } else {
44459566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(Nf, &quads, Nf, &geoms));
444692d50984SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
444792d50984SMatthew G. Knepley PetscObject obj;
444892d50984SMatthew G. Knepley PetscClassId id;
444992d50984SMatthew G. Knepley PetscBool fimp;
445092d50984SMatthew G. Knepley
44519566063dSJacob Faibussowitsch PetscCall(PetscDSGetImplicit(prob, f, &fimp));
445292d50984SMatthew G. Knepley if (isImplicit != fimp) continue;
44539566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, &obj));
44549566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
445592d50984SMatthew G. Knepley if (id == PETSCFE_CLASSID) {
445692d50984SMatthew G. Knepley PetscFE fe = (PetscFE)obj;
445792d50984SMatthew G. Knepley
44589566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quads[f]));
44599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)quads[f]));
4460ac9d17c7SMatthew G. Knepley PetscCall(DMSNESGetFEGeom(coordField, cellIS, quads[f], PETSC_FEGEOM_BASIC, &geoms[f]));
446192d50984SMatthew G. Knepley }
446292d50984SMatthew G. Knepley }
446392d50984SMatthew G. Knepley }
446492d50984SMatthew G. Knepley }
446592d50984SMatthew G. Knepley /* Loop over chunks */
44669566063dSJacob Faibussowitsch PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
44679566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
44689566063dSJacob Faibussowitsch if (useFEM) PetscCall(ISCreate(PETSC_COMM_SELF, &chunkIS));
446992d50984SMatthew G. Knepley numCells = cEnd - cStart;
447092d50984SMatthew G. Knepley numChunks = 1;
447192d50984SMatthew G. Knepley cellChunkSize = numCells / numChunks;
447292d50984SMatthew G. Knepley numChunks = PetscMin(1, numCells);
44736528b96dSMatthew G. Knepley key.label = NULL;
44746528b96dSMatthew G. Knepley key.value = 0;
447506ad1575SMatthew G. Knepley key.part = 0;
447692d50984SMatthew G. Knepley for (chunk = 0; chunk < numChunks; ++chunk) {
4477c0006e53SPatrick Farrell PetscScalar *elemVec, *fluxL = NULL, *fluxR = NULL;
4478c0006e53SPatrick Farrell PetscReal *vol = NULL;
4479c0006e53SPatrick Farrell PetscFVFaceGeom *fgeom = NULL;
448092d50984SMatthew G. Knepley PetscInt cS = cStart + chunk * cellChunkSize, cE = PetscMin(cS + cellChunkSize, cEnd), numCells = cE - cS, c;
4481c0006e53SPatrick Farrell PetscInt numFaces = 0;
448292d50984SMatthew G. Knepley
448392d50984SMatthew G. Knepley /* Extract field coefficients */
448492d50984SMatthew G. Knepley if (useFEM) {
44859566063dSJacob Faibussowitsch PetscCall(ISGetPointSubrange(chunkIS, cS, cE, cells));
44869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellFields(dm, chunkIS, locX, locX_t, locA, &u, &u_t, &a));
44879566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numCells * totDim, MPIU_SCALAR, &elemVec));
44889566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemVec, numCells * totDim));
448992d50984SMatthew G. Knepley }
449092d50984SMatthew G. Knepley /* TODO We will interlace both our field coefficients (u, u_t, uL, uR, etc.) and our output (elemVec, fL, fR). I think this works */
449192d50984SMatthew G. Knepley /* Loop over fields */
449292d50984SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
449392d50984SMatthew G. Knepley PetscObject obj;
449492d50984SMatthew G. Knepley PetscClassId id;
449592d50984SMatthew G. Knepley PetscBool fimp;
449692d50984SMatthew G. Knepley PetscInt numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset;
449792d50984SMatthew G. Knepley
44986528b96dSMatthew G. Knepley key.field = f;
44999566063dSJacob Faibussowitsch PetscCall(PetscDSGetImplicit(prob, f, &fimp));
450092d50984SMatthew G. Knepley if (isImplicit != fimp) continue;
45019566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, &obj));
45029566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
450392d50984SMatthew G. Knepley if (id == PETSCFE_CLASSID) {
450492d50984SMatthew G. Knepley PetscFE fe = (PetscFE)obj;
450592d50984SMatthew G. Knepley PetscFEGeom *geom = affineGeom ? affineGeom : geoms[f];
450692d50984SMatthew G. Knepley PetscFEGeom *chunkGeom = NULL;
450792d50984SMatthew G. Knepley PetscQuadrature quad = affineQuad ? affineQuad : quads[f];
450892d50984SMatthew G. Knepley PetscInt Nq, Nb;
450992d50984SMatthew G. Knepley
45109566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
45119566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL));
45129566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
451392d50984SMatthew G. Knepley blockSize = Nb;
451492d50984SMatthew G. Knepley batchSize = numBlocks * blockSize;
45159566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
451692d50984SMatthew G. Knepley numChunks = numCells / (numBatches * batchSize);
451792d50984SMatthew G. Knepley Ne = numChunks * numBatches * batchSize;
451892d50984SMatthew G. Knepley Nr = numCells % (numBatches * batchSize);
451992d50984SMatthew G. Knepley offset = numCells - Nr;
452092d50984SMatthew G. Knepley /* Integrate FE residual to get elemVec (need fields at quadrature points) */
452192d50984SMatthew G. Knepley /* For FV, I think we use a P0 basis and the cell coefficients (for subdivided cells, we can tweak the basis tabulation to be the indicator function) */
45229566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(geom, 0, offset, &chunkGeom));
45239566063dSJacob Faibussowitsch PetscCall(PetscFEIntegrateResidual(prob, key, Ne, chunkGeom, u, u_t, probAux, a, t, elemVec));
45249566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(geom, offset, numCells, &chunkGeom));
45258e3a54c0SPierre Jolivet PetscCall(PetscFEIntegrateResidual(prob, key, Nr, chunkGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), probAux, &a[offset * totDimAux], t, &elemVec[offset * totDim]));
45269566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(geom, offset, numCells, &chunkGeom));
452792d50984SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
452892d50984SMatthew G. Knepley PetscFV fv = (PetscFV)obj;
452992d50984SMatthew G. Knepley
453092d50984SMatthew G. Knepley Ne = numFaces;
453192d50984SMatthew G. Knepley /* Riemann solve over faces (need fields at face centroids) */
453292d50984SMatthew G. Knepley /* We need to evaluate FE fields at those coordinates */
45339566063dSJacob Faibussowitsch PetscCall(PetscFVIntegrateRHSFunction(fv, prob, f, Ne, fgeom, vol, uL, uR, fluxL, fluxR));
453463a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
453592d50984SMatthew G. Knepley }
453692d50984SMatthew G. Knepley /* Loop over domain */
453792d50984SMatthew G. Knepley if (useFEM) {
453892d50984SMatthew G. Knepley /* Add elemVec to locX */
453992d50984SMatthew G. Knepley for (c = cS; c < cE; ++c) {
454092d50984SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
454192d50984SMatthew G. Knepley const PetscInt cind = c - cStart;
454292d50984SMatthew G. Knepley
45439566063dSJacob Faibussowitsch if (mesh->printFEM > 1) PetscCall(DMPrintCellVector(cell, name, totDim, &elemVec[cind * totDim]));
454492d50984SMatthew G. Knepley if (ghostLabel) {
454592d50984SMatthew G. Knepley PetscInt ghostVal;
454692d50984SMatthew G. Knepley
45479566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(ghostLabel, cell, &ghostVal));
454892d50984SMatthew G. Knepley if (ghostVal > 0) continue;
454992d50984SMatthew G. Knepley }
45509566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(dm, section, locF, cell, &elemVec[cind * totDim], ADD_ALL_VALUES));
455192d50984SMatthew G. Knepley }
455292d50984SMatthew G. Knepley }
455392d50984SMatthew G. Knepley /* Handle time derivative */
455492d50984SMatthew G. Knepley if (locX_t) {
455592d50984SMatthew G. Knepley PetscScalar *x_t, *fa;
455692d50984SMatthew G. Knepley
45579566063dSJacob Faibussowitsch PetscCall(VecGetArray(locF, &fa));
45589566063dSJacob Faibussowitsch PetscCall(VecGetArray(locX_t, &x_t));
455992d50984SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
456092d50984SMatthew G. Knepley PetscFV fv;
456192d50984SMatthew G. Knepley PetscObject obj;
456292d50984SMatthew G. Knepley PetscClassId id;
456392d50984SMatthew G. Knepley PetscInt pdim, d;
456492d50984SMatthew G. Knepley
45659566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, f, &obj));
45669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
456792d50984SMatthew G. Knepley if (id != PETSCFV_CLASSID) continue;
456892d50984SMatthew G. Knepley fv = (PetscFV)obj;
45699566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &pdim));
457092d50984SMatthew G. Knepley for (c = cS; c < cE; ++c) {
457192d50984SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
457292d50984SMatthew G. Knepley PetscScalar *u_t, *r;
457392d50984SMatthew G. Knepley
457492d50984SMatthew G. Knepley if (ghostLabel) {
457592d50984SMatthew G. Knepley PetscInt ghostVal;
457692d50984SMatthew G. Knepley
45779566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(ghostLabel, cell, &ghostVal));
457892d50984SMatthew G. Knepley if (ghostVal > 0) continue;
457992d50984SMatthew G. Knepley }
45809566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRead(dm, cell, f, x_t, &u_t));
45819566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRef(dm, cell, f, fa, &r));
458292d50984SMatthew G. Knepley for (d = 0; d < pdim; ++d) r[d] += u_t[d];
458392d50984SMatthew G. Knepley }
458492d50984SMatthew G. Knepley }
45859566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(locX_t, &x_t));
45869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(locF, &fa));
458792d50984SMatthew G. Knepley }
458892d50984SMatthew G. Knepley if (useFEM) {
45899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCellFields(dm, chunkIS, locX, locX_t, locA, &u, &u_t, &a));
45909566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numCells * totDim, MPIU_SCALAR, &elemVec));
459192d50984SMatthew G. Knepley }
459292d50984SMatthew G. Knepley }
45939566063dSJacob Faibussowitsch if (useFEM) PetscCall(ISDestroy(&chunkIS));
45949566063dSJacob Faibussowitsch PetscCall(ISRestorePointRange(cellIS, &cStart, &cEnd, &cells));
4595754e4fbaSMatthew G. Knepley /* TODO Could include boundary residual here (see DMPlexComputeResidualByKey) */
459692d50984SMatthew G. Knepley if (useFEM) {
459792d50984SMatthew G. Knepley if (maxDegree <= 1) {
45989566063dSJacob Faibussowitsch PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, affineQuad, PETSC_FALSE, &affineGeom));
45999566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&affineQuad));
460092d50984SMatthew G. Knepley } else {
460192d50984SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
46029566063dSJacob Faibussowitsch PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, quads[f], PETSC_FALSE, &geoms[f]));
46039566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&quads[f]));
460492d50984SMatthew G. Knepley }
46059566063dSJacob Faibussowitsch PetscCall(PetscFree2(quads, geoms));
460692d50984SMatthew G. Knepley }
460792d50984SMatthew G. Knepley }
46089566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_ResidualFEM, dm, 0, 0, 0));
46093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
461092d50984SMatthew G. Knepley }
461192d50984SMatthew G. Knepley
4612a1cf66bbSMatthew G. Knepley /*
4613a1cf66bbSMatthew G. Knepley We always assemble JacP, and if the matrix is different from Jac and two different sets of point functions are provided, we also assemble Jac
4614a1cf66bbSMatthew G. Knepley
4615a1cf66bbSMatthew G. Knepley X - The local solution vector
4616a5b23f4aSJose E. Roman X_t - The local solution time derivative vector, or NULL
4617a1cf66bbSMatthew G. Knepley */
DMPlexComputeJacobian_Patch_Internal(DM dm,PetscSection section,PetscSection globalSection,IS cellIS,PetscReal t,PetscReal X_tShift,Vec X,Vec X_t,Mat Jac,Mat JacP,PetscCtx ctx)4618*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeJacobian_Patch_Internal(DM dm, PetscSection section, PetscSection globalSection, IS cellIS, PetscReal t, PetscReal X_tShift, Vec X, Vec X_t, Mat Jac, Mat JacP, PetscCtx ctx)
4619d71ae5a4SJacob Faibussowitsch {
4620a1cf66bbSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
4621a1cf66bbSMatthew G. Knepley const char *name = "Jacobian", *nameP = "JacobianPre";
4622a1cf66bbSMatthew G. Knepley DM dmAux = NULL;
4623a1cf66bbSMatthew G. Knepley PetscDS prob, probAux = NULL;
4624a1cf66bbSMatthew G. Knepley PetscSection sectionAux = NULL;
4625a1cf66bbSMatthew G. Knepley Vec A;
4626a1cf66bbSMatthew G. Knepley DMField coordField;
4627a1cf66bbSMatthew G. Knepley PetscFEGeom *cgeomFEM;
4628a1cf66bbSMatthew G. Knepley PetscQuadrature qGeom = NULL;
4629a1cf66bbSMatthew G. Knepley Mat J = Jac, JP = JacP;
4630a1cf66bbSMatthew G. Knepley PetscScalar *work, *u = NULL, *u_t = NULL, *a = NULL, *elemMat = NULL, *elemMatP = NULL, *elemMatD = NULL;
4631e432b41dSStefano Zampini PetscBool hasJac, hasPrec, hasDyn, assembleJac, *isFE, hasFV = PETSC_FALSE;
4632a1cf66bbSMatthew G. Knepley const PetscInt *cells;
463306ad1575SMatthew G. Knepley PetscFormKey key;
46349b2fc754SMatthew G. Knepley PetscInt Nf, fieldI, fieldJ, maxDegree, numCells, cStart, cEnd, numChunks, chunkSize, chunk, totDim, totDimAux = 0, sz, wsz, off = 0, offCell = 0;
4635a1cf66bbSMatthew G. Knepley
4636a1cf66bbSMatthew G. Knepley PetscFunctionBegin;
46379566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(cellIS, &numCells));
46389566063dSJacob Faibussowitsch PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
46399566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_JacobianFEM, dm, 0, 0, 0));
46409566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
46419566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, NULL, 0, 0, &A));
46429a2a23afSMatthew G. Knepley if (A) {
46439566063dSJacob Faibussowitsch PetscCall(VecGetDM(A, &dmAux));
46449566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmAux, §ionAux));
46459566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmAux, &probAux));
4646a1cf66bbSMatthew G. Knepley }
4647a1cf66bbSMatthew G. Knepley /* Get flags */
46489566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf));
46495440e5dcSBarry Smith PetscCall(DMGetWorkArray(dm, Nf, MPI_C_BOOL, &isFE));
4650a1cf66bbSMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) {
4651a1cf66bbSMatthew G. Knepley PetscObject disc;
4652a1cf66bbSMatthew G. Knepley PetscClassId id;
46539566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, fieldI, &disc));
46549566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(disc, &id));
46559371c9d4SSatish Balay if (id == PETSCFE_CLASSID) {
46569371c9d4SSatish Balay isFE[fieldI] = PETSC_TRUE;
46579371c9d4SSatish Balay } else if (id == PETSCFV_CLASSID) {
46589371c9d4SSatish Balay hasFV = PETSC_TRUE;
46599371c9d4SSatish Balay isFE[fieldI] = PETSC_FALSE;
46609371c9d4SSatish Balay }
4661a1cf66bbSMatthew G. Knepley }
46629566063dSJacob Faibussowitsch PetscCall(PetscDSHasJacobian(prob, &hasJac));
46639566063dSJacob Faibussowitsch PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
46649566063dSJacob Faibussowitsch PetscCall(PetscDSHasDynamicJacobian(prob, &hasDyn));
4665a1cf66bbSMatthew G. Knepley assembleJac = hasJac && hasPrec && (Jac != JacP) ? PETSC_TRUE : PETSC_FALSE;
4666a1cf66bbSMatthew G. Knepley hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE;
46679566063dSJacob Faibussowitsch if (hasFV) PetscCall(MatSetOption(JP, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE)); /* No allocated space for FV stuff, so ignore the zero entries */
46689566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim));
46699566063dSJacob Faibussowitsch if (probAux) PetscCall(PetscDSGetTotalDimension(probAux, &totDimAux));
4670a1cf66bbSMatthew G. Knepley /* Compute batch sizes */
4671a1cf66bbSMatthew G. Knepley if (isFE[0]) {
4672a1cf66bbSMatthew G. Knepley PetscFE fe;
4673a1cf66bbSMatthew G. Knepley PetscQuadrature q;
4674a1cf66bbSMatthew G. Knepley PetscInt numQuadPoints, numBatches, batchSize, numBlocks, blockSize, Nb;
4675a1cf66bbSMatthew G. Knepley
46769566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, 0, (PetscObject *)&fe));
46779566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &q));
46789566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(q, NULL, NULL, &numQuadPoints, NULL, NULL));
46799566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
46809566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
4681a1cf66bbSMatthew G. Knepley blockSize = Nb * numQuadPoints;
4682a1cf66bbSMatthew G. Knepley batchSize = numBlocks * blockSize;
4683a1cf66bbSMatthew G. Knepley chunkSize = numBatches * batchSize;
4684a1cf66bbSMatthew G. Knepley numChunks = numCells / chunkSize + numCells % chunkSize;
46859566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
4686a1cf66bbSMatthew G. Knepley } else {
4687a1cf66bbSMatthew G. Knepley chunkSize = numCells;
4688a1cf66bbSMatthew G. Knepley numChunks = 1;
4689a1cf66bbSMatthew G. Knepley }
4690a1cf66bbSMatthew G. Knepley /* Get work space */
46912358c221SStefano Zampini wsz = (((X ? 1 : 0) + (X_t ? 1 : 0)) * totDim + (dmAux ? 1 : 0) * totDimAux + ((hasJac ? 1 : 0) + (hasPrec ? 1 : 0) + (hasDyn ? 1 : 0)) * totDim * totDim) * chunkSize;
46929566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, wsz, MPIU_SCALAR, &work));
46939566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(work, wsz));
4694a1cf66bbSMatthew G. Knepley off = 0;
4695a1cf66bbSMatthew G. Knepley u = X ? (sz = chunkSize * totDim, off += sz, work + off - sz) : NULL;
4696a1cf66bbSMatthew G. Knepley u_t = X_t ? (sz = chunkSize * totDim, off += sz, work + off - sz) : NULL;
4697a1cf66bbSMatthew G. Knepley a = dmAux ? (sz = chunkSize * totDimAux, off += sz, work + off - sz) : NULL;
4698a1cf66bbSMatthew G. Knepley elemMat = hasJac ? (sz = chunkSize * totDim * totDim, off += sz, work + off - sz) : NULL;
4699a1cf66bbSMatthew G. Knepley elemMatP = hasPrec ? (sz = chunkSize * totDim * totDim, off += sz, work + off - sz) : NULL;
4700a1cf66bbSMatthew G. Knepley elemMatD = hasDyn ? (sz = chunkSize * totDim * totDim, off += sz, work + off - sz) : NULL;
470163a3b9bcSJacob Faibussowitsch PetscCheck(off == wsz, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error is workspace size %" PetscInt_FMT " should be %" PetscInt_FMT, off, wsz);
4702a1cf66bbSMatthew G. Knepley /* Setup geometry */
47039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
47049566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, cellIS, NULL, &maxDegree));
47059566063dSJacob Faibussowitsch if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, cellIS, &qGeom));
4706a1cf66bbSMatthew G. Knepley if (!qGeom) {
4707a1cf66bbSMatthew G. Knepley PetscFE fe;
4708a1cf66bbSMatthew G. Knepley
47099566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, 0, (PetscObject *)&fe));
47109566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &qGeom));
47119566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)qGeom));
4712a1cf66bbSMatthew G. Knepley }
4713ac9d17c7SMatthew G. Knepley PetscCall(DMSNESGetFEGeom(coordField, cellIS, qGeom, PETSC_FEGEOM_BASIC, &cgeomFEM));
4714a1cf66bbSMatthew G. Knepley /* Compute volume integrals */
47159566063dSJacob Faibussowitsch if (assembleJac) PetscCall(MatZeroEntries(J));
47169566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(JP));
47176528b96dSMatthew G. Knepley key.label = NULL;
47186528b96dSMatthew G. Knepley key.value = 0;
471906ad1575SMatthew G. Knepley key.part = 0;
4720a1cf66bbSMatthew G. Knepley for (chunk = 0; chunk < numChunks; ++chunk, offCell += chunkSize) {
4721a1cf66bbSMatthew G. Knepley const PetscInt Ncell = PetscMin(chunkSize, numCells - offCell);
4722a1cf66bbSMatthew G. Knepley PetscInt c;
4723a1cf66bbSMatthew G. Knepley
4724a1cf66bbSMatthew G. Knepley /* Extract values */
4725a1cf66bbSMatthew G. Knepley for (c = 0; c < Ncell; ++c) {
4726a1cf66bbSMatthew G. Knepley const PetscInt cell = cells ? cells[c + offCell] : c + offCell;
4727a1cf66bbSMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL;
4728a1cf66bbSMatthew G. Knepley PetscInt i;
4729a1cf66bbSMatthew G. Knepley
4730a1cf66bbSMatthew G. Knepley if (X) {
47319566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, section, X, cell, NULL, &x));
4732a1cf66bbSMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c * totDim + i] = x[i];
47339566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, section, X, cell, NULL, &x));
4734a1cf66bbSMatthew G. Knepley }
4735a1cf66bbSMatthew G. Knepley if (X_t) {
47369566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, section, X_t, cell, NULL, &x_t));
4737a1cf66bbSMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[c * totDim + i] = x_t[i];
47389566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, section, X_t, cell, NULL, &x_t));
4739a1cf66bbSMatthew G. Knepley }
4740a1cf66bbSMatthew G. Knepley if (dmAux) {
47419566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dmAux, sectionAux, A, cell, NULL, &x));
4742a1cf66bbSMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c * totDimAux + i] = x[i];
47439566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dmAux, sectionAux, A, cell, NULL, &x));
4744a1cf66bbSMatthew G. Knepley }
4745a1cf66bbSMatthew G. Knepley }
4746a1cf66bbSMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) {
4747a1cf66bbSMatthew G. Knepley PetscFE fe;
47489566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, fieldI, (PetscObject *)&fe));
4749a1cf66bbSMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
47506528b96dSMatthew G. Knepley key.field = fieldI * Nf + fieldJ;
47514561e6c9SMatthew G. Knepley if (hasJac) PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN, key, Ncell, cgeomFEM, u, u_t, probAux, a, t, X_tShift, elemMat));
47524561e6c9SMatthew G. Knepley if (hasPrec) PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN_PRE, key, Ncell, cgeomFEM, u, u_t, probAux, a, t, X_tShift, elemMatP));
47534561e6c9SMatthew G. Knepley if (hasDyn) PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN_DYN, key, Ncell, cgeomFEM, u, u_t, probAux, a, t, X_tShift, elemMatD));
4754a1cf66bbSMatthew G. Knepley }
4755a1cf66bbSMatthew G. Knepley /* For finite volume, add the identity */
4756a1cf66bbSMatthew G. Knepley if (!isFE[fieldI]) {
4757a1cf66bbSMatthew G. Knepley PetscFV fv;
4758a1cf66bbSMatthew G. Knepley PetscInt eOffset = 0, Nc, fc, foff;
4759a1cf66bbSMatthew G. Knepley
47609566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffset(prob, fieldI, &foff));
47619566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, fieldI, (PetscObject *)&fv));
47629566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &Nc));
4763a1cf66bbSMatthew G. Knepley for (c = 0; c < chunkSize; ++c, eOffset += totDim * totDim) {
4764a1cf66bbSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) {
4765a1cf66bbSMatthew G. Knepley const PetscInt i = foff + fc;
4766ad540459SPierre Jolivet if (hasJac) elemMat[eOffset + i * totDim + i] = 1.0;
4767ad540459SPierre Jolivet if (hasPrec) elemMatP[eOffset + i * totDim + i] = 1.0;
4768a1cf66bbSMatthew G. Knepley }
4769a1cf66bbSMatthew G. Knepley }
4770a1cf66bbSMatthew G. Knepley }
4771a1cf66bbSMatthew G. Knepley }
4772a1cf66bbSMatthew G. Knepley /* Add contribution from X_t */
47739371c9d4SSatish Balay if (hasDyn) {
47749371c9d4SSatish Balay for (c = 0; c < chunkSize * totDim * totDim; ++c) elemMat[c] += X_tShift * elemMatD[c];
47759371c9d4SSatish Balay }
4776a1cf66bbSMatthew G. Knepley /* Insert values into matrix */
4777a1cf66bbSMatthew G. Knepley for (c = 0; c < Ncell; ++c) {
4778a1cf66bbSMatthew G. Knepley const PetscInt cell = cells ? cells[c + offCell] : c + offCell;
4779a1cf66bbSMatthew G. Knepley if (mesh->printFEM > 1) {
47809566063dSJacob Faibussowitsch if (hasJac) PetscCall(DMPrintCellMatrix(cell, name, totDim, totDim, &elemMat[(c - cStart) * totDim * totDim]));
47819566063dSJacob Faibussowitsch if (hasPrec) PetscCall(DMPrintCellMatrix(cell, nameP, totDim, totDim, &elemMatP[(c - cStart) * totDim * totDim]));
4782a1cf66bbSMatthew G. Knepley }
4783e8e188d2SZach Atkins if (assembleJac) PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, mesh->useMatClPerm, Jac, cell, &elemMat[(c - cStart) * totDim * totDim], ADD_VALUES));
4784e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, mesh->useMatClPerm, JP, cell, &elemMat[(c - cStart) * totDim * totDim], ADD_VALUES));
4785a1cf66bbSMatthew G. Knepley }
4786a1cf66bbSMatthew G. Knepley }
4787a1cf66bbSMatthew G. Knepley /* Cleanup */
47889566063dSJacob Faibussowitsch PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, qGeom, PETSC_FALSE, &cgeomFEM));
47899566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&qGeom));
47909566063dSJacob Faibussowitsch if (hasFV) PetscCall(MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_FALSE));
47915440e5dcSBarry Smith PetscCall(DMRestoreWorkArray(dm, Nf, MPI_C_BOOL, &isFE));
47929566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, ((1 + (X_t ? 1 : 0) + (dmAux ? 1 : 0)) * totDim + ((hasJac ? 1 : 0) + (hasPrec ? 1 : 0) + (hasDyn ? 1 : 0)) * totDim * totDim) * chunkSize, MPIU_SCALAR, &work));
4793a1cf66bbSMatthew G. Knepley /* Compute boundary integrals */
47949566063dSJacob Faibussowitsch /* PetscCall(DMPlexComputeBdJacobian_Internal(dm, X, X_t, t, X_tShift, Jac, JacP, ctx)); */
4795a1cf66bbSMatthew G. Knepley /* Assemble matrix */
47969371c9d4SSatish Balay if (assembleJac) {
47979371c9d4SSatish Balay PetscCall(MatAssemblyBegin(Jac, MAT_FINAL_ASSEMBLY));
47989371c9d4SSatish Balay PetscCall(MatAssemblyEnd(Jac, MAT_FINAL_ASSEMBLY));
47999371c9d4SSatish Balay }
48009371c9d4SSatish Balay PetscCall(MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY));
48019371c9d4SSatish Balay PetscCall(MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY));
48029566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_JacobianFEM, dm, 0, 0, 0));
48033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4804a1cf66bbSMatthew G. Knepley }
48053e9753d6SMatthew G. Knepley
48064ee01570SBarry Smith /* FEM Assembly Function */
48073e9753d6SMatthew G. Knepley
DMConvertPlex_Internal(DM dm,DM * plex,PetscBool copy)4808d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMConvertPlex_Internal(DM dm, DM *plex, PetscBool copy)
4809d71ae5a4SJacob Faibussowitsch {
48103e9753d6SMatthew G. Knepley PetscBool isPlex;
48113e9753d6SMatthew G. Knepley
48123e9753d6SMatthew G. Knepley PetscFunctionBegin;
48139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isPlex));
48143e9753d6SMatthew G. Knepley if (isPlex) {
48153e9753d6SMatthew G. Knepley *plex = dm;
48169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm));
48173e9753d6SMatthew G. Knepley } else {
48189566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)dm, "dm_plex", (PetscObject *)plex));
48193e9753d6SMatthew G. Knepley if (!*plex) {
48209566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, plex));
48219566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dm, "dm_plex", (PetscObject)*plex));
48223e9753d6SMatthew G. Knepley } else {
48239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)*plex));
48243e9753d6SMatthew G. Knepley }
4825cbf8eb3cSStefano Zampini if (copy) PetscCall(DMCopyAuxiliaryVec(dm, *plex));
48263e9753d6SMatthew G. Knepley }
48273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48283e9753d6SMatthew G. Knepley }
48293e9753d6SMatthew G. Knepley
48303e9753d6SMatthew G. Knepley /*@
48313e9753d6SMatthew G. Knepley DMPlexGetGeometryFVM - Return precomputed geometric data
48323e9753d6SMatthew G. Knepley
483320f4b53cSBarry Smith Collective
48343e9753d6SMatthew G. Knepley
48353e9753d6SMatthew G. Knepley Input Parameter:
4836a1cb98faSBarry Smith . dm - The `DM`
48373e9753d6SMatthew G. Knepley
48383e9753d6SMatthew G. Knepley Output Parameters:
48393e9753d6SMatthew G. Knepley + facegeom - The values precomputed from face geometry
48403e9753d6SMatthew G. Knepley . cellgeom - The values precomputed from cell geometry
4841ce78bad3SBarry Smith - minRadius - The minimum radius over the mesh of an inscribed sphere in a cell, or `NULL` if not needed
48423e9753d6SMatthew G. Knepley
48433e9753d6SMatthew G. Knepley Level: developer
48443e9753d6SMatthew G. Knepley
48451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMTSSetRHSFunctionLocal()`
48463e9753d6SMatthew G. Knepley @*/
DMPlexGetGeometryFVM(DM dm,Vec * facegeom,Vec * cellgeom,PeOp PetscReal * minRadius)4847ce78bad3SBarry Smith PetscErrorCode DMPlexGetGeometryFVM(DM dm, Vec *facegeom, Vec *cellgeom, PeOp PetscReal *minRadius)
4848d71ae5a4SJacob Faibussowitsch {
48493e9753d6SMatthew G. Knepley DM plex;
48503e9753d6SMatthew G. Knepley
48513e9753d6SMatthew G. Knepley PetscFunctionBegin;
48523e9753d6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48539566063dSJacob Faibussowitsch PetscCall(DMConvertPlex_Internal(dm, &plex, PETSC_TRUE));
48549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(plex, NULL, cellgeom, facegeom, NULL));
48559566063dSJacob Faibussowitsch if (minRadius) PetscCall(DMPlexGetMinRadius(plex, minRadius));
48569566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex));
48573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48583e9753d6SMatthew G. Knepley }
48593e9753d6SMatthew G. Knepley
48603e9753d6SMatthew G. Knepley /*@
48613e9753d6SMatthew G. Knepley DMPlexGetGradientDM - Return gradient data layout
48623e9753d6SMatthew G. Knepley
486320f4b53cSBarry Smith Collective
48643e9753d6SMatthew G. Knepley
48653e9753d6SMatthew G. Knepley Input Parameters:
4866a1cb98faSBarry Smith + dm - The `DM`
486720f4b53cSBarry Smith - fv - The `PetscFV`
48683e9753d6SMatthew G. Knepley
48693e9753d6SMatthew G. Knepley Output Parameter:
48703e9753d6SMatthew G. Knepley . dmGrad - The layout for gradient values
48713e9753d6SMatthew G. Knepley
48723e9753d6SMatthew G. Knepley Level: developer
48733e9753d6SMatthew G. Knepley
48741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetGeometryFVM()`
48753e9753d6SMatthew G. Knepley @*/
DMPlexGetGradientDM(DM dm,PetscFV fv,DM * dmGrad)4876d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetGradientDM(DM dm, PetscFV fv, DM *dmGrad)
4877d71ae5a4SJacob Faibussowitsch {
48783e9753d6SMatthew G. Knepley DM plex;
48793e9753d6SMatthew G. Knepley PetscBool computeGradients;
48803e9753d6SMatthew G. Knepley
48813e9753d6SMatthew G. Knepley PetscFunctionBegin;
48823e9753d6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48833e9753d6SMatthew G. Knepley PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
48844f572ea9SToby Isaac PetscAssertPointer(dmGrad, 3);
48859566063dSJacob Faibussowitsch PetscCall(PetscFVGetComputeGradients(fv, &computeGradients));
48869371c9d4SSatish Balay if (!computeGradients) {
48879371c9d4SSatish Balay *dmGrad = NULL;
48883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48899371c9d4SSatish Balay }
48909566063dSJacob Faibussowitsch PetscCall(DMConvertPlex_Internal(dm, &plex, PETSC_TRUE));
48919566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(plex, fv, NULL, NULL, dmGrad));
48929566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex));
48933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
48943e9753d6SMatthew G. Knepley }
48953e9753d6SMatthew G. Knepley
4896997bf629SMatthew G. Knepley /*@
4897997bf629SMatthew G. Knepley DMPlexComputeBdResidualSingleByKey - Compute the local boundary residual for terms matching the input key
4898997bf629SMatthew G. Knepley
4899997bf629SMatthew G. Knepley Not collective
4900997bf629SMatthew G. Knepley
4901997bf629SMatthew G. Knepley Input Parameters:
4902997bf629SMatthew G. Knepley + dm - The output `DM`
4903997bf629SMatthew G. Knepley . wf - The `PetscWeakForm` holding forms on this boundary
4904997bf629SMatthew G. Knepley . key - The `PetscFormKey` indicating what should be integrated
4905997bf629SMatthew G. Knepley . facetIS - The `IS` giving a set of faces to integrate over
4906997bf629SMatthew G. Knepley . locX - The local solution
4907997bf629SMatthew G. Knepley . locX_t - The time derivative of the local solution, or `NULL` for time-independent problems
4908997bf629SMatthew G. Knepley . t - The time
4909997bf629SMatthew G. Knepley - coordField - The `DMField` object with coordinates for these faces
4910997bf629SMatthew G. Knepley
4911997bf629SMatthew G. Knepley Output Parameter:
4912997bf629SMatthew G. Knepley . locF - The local residual
4913997bf629SMatthew G. Knepley
4914997bf629SMatthew G. Knepley Level: developer
4915997bf629SMatthew G. Knepley
4916997bf629SMatthew G. Knepley .seealso: `DMPlexComputeBdResidualSingle()`, `DMPlexComputeJacobianByKey()`, `DMPlexComputeResidualHybridByKey()`, `DMPlexComputeJacobianHybridByKey()`, `PetscFormKey`
4917997bf629SMatthew G. Knepley @*/
DMPlexComputeBdResidualSingleByKey(DM dm,PetscWeakForm wf,PetscFormKey key,IS facetIS,Vec locX,Vec locX_t,PetscReal t,DMField coordField,Vec locF)4918997bf629SMatthew G. Knepley PetscErrorCode DMPlexComputeBdResidualSingleByKey(DM dm, PetscWeakForm wf, PetscFormKey key, IS facetIS, Vec locX, Vec locX_t, PetscReal t, DMField coordField, Vec locF)
4919d71ae5a4SJacob Faibussowitsch {
49203e9753d6SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
49213e9753d6SMatthew G. Knepley DM plex = NULL, plexA = NULL;
4922673019faSMatthew G. Knepley const char *name = "BdResidual";
49233e9753d6SMatthew G. Knepley DMEnclosureType encAux;
49243e9753d6SMatthew G. Knepley PetscDS prob, probAux = NULL;
49253e9753d6SMatthew G. Knepley PetscSection section, sectionAux = NULL;
49263e9753d6SMatthew G. Knepley Vec locA = NULL;
49273e9753d6SMatthew G. Knepley PetscScalar *u = NULL, *u_t = NULL, *a = NULL, *elemVec = NULL;
49283e9753d6SMatthew G. Knepley PetscInt totDim, totDimAux = 0;
49293e9753d6SMatthew G. Knepley
49303e9753d6SMatthew G. Knepley PetscFunctionBegin;
49319566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex));
49329566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
49339566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
49349566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim));
49359566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, key.label, key.value, key.part, &locA));
49363e9753d6SMatthew G. Knepley if (locA) {
49373e9753d6SMatthew G. Knepley DM dmAux;
49383e9753d6SMatthew G. Knepley
49399566063dSJacob Faibussowitsch PetscCall(VecGetDM(locA, &dmAux));
49409566063dSJacob Faibussowitsch PetscCall(DMGetEnclosureRelation(dmAux, dm, &encAux));
49419566063dSJacob Faibussowitsch PetscCall(DMConvert(dmAux, DMPLEX, &plexA));
49429566063dSJacob Faibussowitsch PetscCall(DMGetDS(plexA, &probAux));
49439566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(probAux, &totDimAux));
49449566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(plexA, §ionAux));
49453e9753d6SMatthew G. Knepley }
49460c290148SMatthew G. Knepley {
49473e9753d6SMatthew G. Knepley PetscFEGeom *fgeom;
49483e9753d6SMatthew G. Knepley PetscInt maxDegree;
49493e9753d6SMatthew G. Knepley PetscQuadrature qGeom = NULL;
49503e9753d6SMatthew G. Knepley IS pointIS;
49513e9753d6SMatthew G. Knepley const PetscInt *points;
49523e9753d6SMatthew G. Knepley PetscInt numFaces, face, Nq;
49533e9753d6SMatthew G. Knepley
49549566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(key.label, key.value, &pointIS));
49550c290148SMatthew G. Knepley if (!pointIS) goto end; /* No points with that id on this process */
49563e9753d6SMatthew G. Knepley {
49573e9753d6SMatthew G. Knepley IS isectIS;
49583e9753d6SMatthew G. Knepley
49593e9753d6SMatthew G. Knepley /* TODO: Special cases of ISIntersect where it is quick to check a priori if one is a superset of the other */
49609566063dSJacob Faibussowitsch PetscCall(ISIntersect_Caching_Internal(facetIS, pointIS, &isectIS));
49619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
49623e9753d6SMatthew G. Knepley pointIS = isectIS;
49633e9753d6SMatthew G. Knepley }
49649566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numFaces));
49659566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points));
496632603206SJames Wright PetscCall(PetscMalloc4(numFaces * totDim, &u, (locX_t ? (size_t)numFaces * totDim : 0), &u_t, numFaces * totDim, &elemVec, (locA ? (size_t)numFaces * totDimAux : 0), &a));
49679566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, pointIS, NULL, &maxDegree));
496848a46eb9SPierre Jolivet if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, pointIS, &qGeom));
49693e9753d6SMatthew G. Knepley if (!qGeom) {
49703e9753d6SMatthew G. Knepley PetscFE fe;
49713e9753d6SMatthew G. Knepley
49729566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, key.field, (PetscObject *)&fe));
49739566063dSJacob Faibussowitsch PetscCall(PetscFEGetFaceQuadrature(fe, &qGeom));
49749566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)qGeom));
49753e9753d6SMatthew G. Knepley }
49769566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL));
4977ac9d17c7SMatthew G. Knepley PetscCall(DMSNESGetFEGeom(coordField, pointIS, qGeom, PETSC_FEGEOM_BOUNDARY, &fgeom));
49783e9753d6SMatthew G. Knepley for (face = 0; face < numFaces; ++face) {
4979f15274beSMatthew Knepley const PetscInt point = points[face], *support;
49803e9753d6SMatthew G. Knepley PetscScalar *x = NULL;
4981f15274beSMatthew Knepley PetscInt i;
49823e9753d6SMatthew G. Knepley
49839566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support));
49849566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plex, section, locX, support[0], NULL, &x));
49853e9753d6SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[face * totDim + i] = x[i];
49869566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plex, section, locX, support[0], NULL, &x));
49873e9753d6SMatthew G. Knepley if (locX_t) {
49889566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plex, section, locX_t, support[0], NULL, &x));
49893e9753d6SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[face * totDim + i] = x[i];
49909566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plex, section, locX_t, support[0], NULL, &x));
49913e9753d6SMatthew G. Knepley }
49923e9753d6SMatthew G. Knepley if (locA) {
49933e9753d6SMatthew G. Knepley PetscInt subp;
49943e9753d6SMatthew G. Knepley
49959566063dSJacob Faibussowitsch PetscCall(DMGetEnclosurePoint(plexA, dm, encAux, support[0], &subp));
49969566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plexA, sectionAux, locA, subp, NULL, &x));
49973e9753d6SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[face * totDimAux + i] = x[i];
49989566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plexA, sectionAux, locA, subp, NULL, &x));
49993e9753d6SMatthew G. Knepley }
50003e9753d6SMatthew G. Knepley }
50019566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemVec, numFaces * totDim));
50023e9753d6SMatthew G. Knepley {
50033e9753d6SMatthew G. Knepley PetscFE fe;
50043e9753d6SMatthew G. Knepley PetscInt Nb;
50053e9753d6SMatthew G. Knepley PetscFEGeom *chunkGeom = NULL;
50063e9753d6SMatthew G. Knepley /* Conforming batches */
50073e9753d6SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
50083e9753d6SMatthew G. Knepley /* Remainder */
50093e9753d6SMatthew G. Knepley PetscInt Nr, offset;
50103e9753d6SMatthew G. Knepley
50119566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, key.field, (PetscObject *)&fe));
50129566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
50139566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
50143e9753d6SMatthew G. Knepley /* TODO: documentation is unclear about what is going on with these numbers: how should Nb / Nq factor in ? */
50153e9753d6SMatthew G. Knepley blockSize = Nb;
50163e9753d6SMatthew G. Knepley batchSize = numBlocks * blockSize;
50179566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
50183e9753d6SMatthew G. Knepley numChunks = numFaces / (numBatches * batchSize);
50193e9753d6SMatthew G. Knepley Ne = numChunks * numBatches * batchSize;
50203e9753d6SMatthew G. Knepley Nr = numFaces % (numBatches * batchSize);
50213e9753d6SMatthew G. Knepley offset = numFaces - Nr;
50229566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(fgeom, 0, offset, &chunkGeom));
50239566063dSJacob Faibussowitsch PetscCall(PetscFEIntegrateBdResidual(prob, wf, key, Ne, chunkGeom, u, u_t, probAux, a, t, elemVec));
50249566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(fgeom, 0, offset, &chunkGeom));
50259566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(fgeom, offset, numFaces, &chunkGeom));
50268e3a54c0SPierre Jolivet PetscCall(PetscFEIntegrateBdResidual(prob, wf, key, Nr, chunkGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), probAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, &elemVec[offset * totDim]));
50279566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(fgeom, offset, numFaces, &chunkGeom));
50283e9753d6SMatthew G. Knepley }
50293e9753d6SMatthew G. Knepley for (face = 0; face < numFaces; ++face) {
50303e9753d6SMatthew G. Knepley const PetscInt point = points[face], *support;
50313e9753d6SMatthew G. Knepley
5032673019faSMatthew G. Knepley if (mesh->printFEM > 1) PetscCall(DMPrintCellVector(point, name, totDim, &elemVec[face * totDim]));
50339566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(plex, point, &support));
50349566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(plex, NULL, locF, support[0], &elemVec[face * totDim], ADD_ALL_VALUES));
50353e9753d6SMatthew G. Knepley }
50369566063dSJacob Faibussowitsch PetscCall(DMSNESRestoreFEGeom(coordField, pointIS, qGeom, PETSC_TRUE, &fgeom));
50379566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&qGeom));
50389566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points));
50399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
50409566063dSJacob Faibussowitsch PetscCall(PetscFree4(u, u_t, elemVec, a));
50413e9753d6SMatthew G. Knepley }
50420c290148SMatthew G. Knepley end:
5043673019faSMatthew G. Knepley if (mesh->printFEM) {
5044673019faSMatthew G. Knepley PetscSection s;
5045673019faSMatthew G. Knepley Vec locFbc;
5046673019faSMatthew G. Knepley PetscInt pStart, pEnd, maxDof;
5047673019faSMatthew G. Knepley PetscScalar *zeroes;
5048673019faSMatthew G. Knepley
5049673019faSMatthew G. Knepley PetscCall(DMGetLocalSection(dm, &s));
5050673019faSMatthew G. Knepley PetscCall(VecDuplicate(locF, &locFbc));
5051673019faSMatthew G. Knepley PetscCall(VecCopy(locF, locFbc));
5052673019faSMatthew G. Knepley PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
5053673019faSMatthew G. Knepley PetscCall(PetscSectionGetMaxDof(s, &maxDof));
5054673019faSMatthew G. Knepley PetscCall(PetscCalloc1(maxDof, &zeroes));
5055673019faSMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; p++) PetscCall(VecSetValuesSection(locFbc, s, p, zeroes, INSERT_BC_VALUES));
5056673019faSMatthew G. Knepley PetscCall(PetscFree(zeroes));
5057673019faSMatthew G. Knepley PetscCall(DMPrintLocalVec(dm, name, mesh->printTol, locFbc));
5058673019faSMatthew G. Knepley PetscCall(VecDestroy(&locFbc));
5059673019faSMatthew G. Knepley }
50609566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex));
50619566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plexA));
50623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
50633e9753d6SMatthew G. Knepley }
50643e9753d6SMatthew G. Knepley
5065997bf629SMatthew G. Knepley /*@
5066997bf629SMatthew G. Knepley DMPlexComputeBdResidualSingle - Compute the local boundary residual
5067997bf629SMatthew G. Knepley
5068997bf629SMatthew G. Knepley Not collective
5069997bf629SMatthew G. Knepley
5070997bf629SMatthew G. Knepley Input Parameters:
5071997bf629SMatthew G. Knepley + dm - The output `DM`
5072997bf629SMatthew G. Knepley . wf - The `PetscWeakForm` holding forms on this boundary
5073997bf629SMatthew G. Knepley . key - The `PetscFormKey` indicating what should be integrated
5074997bf629SMatthew G. Knepley . locX - The local solution
5075997bf629SMatthew G. Knepley . locX_t - The time derivative of the local solution, or `NULL` for time-independent problems
5076997bf629SMatthew G. Knepley - t - The time
5077997bf629SMatthew G. Knepley
5078997bf629SMatthew G. Knepley Output Parameter:
5079997bf629SMatthew G. Knepley . locF - The local residual
5080997bf629SMatthew G. Knepley
5081997bf629SMatthew G. Knepley Level: developer
5082997bf629SMatthew G. Knepley
5083997bf629SMatthew G. Knepley .seealso: `DMPlexComputeBdResidualSingleByKey()`, `DMPlexComputeJacobianByKey()`, `DMPlexComputeResidualHybridByKey()`, `DMPlexComputeJacobianHybridByKey()`, `PetscFormKey`
5084997bf629SMatthew G. Knepley @*/
DMPlexComputeBdResidualSingle(DM dm,PetscWeakForm wf,PetscFormKey key,Vec locX,Vec locX_t,PetscReal t,Vec locF)5085997bf629SMatthew G. Knepley PetscErrorCode DMPlexComputeBdResidualSingle(DM dm, PetscWeakForm wf, PetscFormKey key, Vec locX, Vec locX_t, PetscReal t, Vec locF)
5086d71ae5a4SJacob Faibussowitsch {
50873e9753d6SMatthew G. Knepley DMField coordField;
50883e9753d6SMatthew G. Knepley DMLabel depthLabel;
50893e9753d6SMatthew G. Knepley IS facetIS;
50903e9753d6SMatthew G. Knepley PetscInt dim;
50913e9753d6SMatthew G. Knepley
50923e9753d6SMatthew G. Knepley PetscFunctionBegin;
50939566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
50949566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
50959566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(depthLabel, dim - 1, &facetIS));
50969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
5097997bf629SMatthew G. Knepley PetscCall(DMPlexComputeBdResidualSingleByKey(dm, wf, key, facetIS, locX, locX_t, t, coordField, locF));
50989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&facetIS));
50993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
51003e9753d6SMatthew G. Knepley }
51013e9753d6SMatthew G. Knepley
DMPlexComputeBdResidual_Internal(DM dm,Vec locX,Vec locX_t,PetscReal t,Vec locF,PetscCtx ctx)5102*2a8381b2SBarry Smith static PetscErrorCode DMPlexComputeBdResidual_Internal(DM dm, Vec locX, Vec locX_t, PetscReal t, Vec locF, PetscCtx ctx)
5103d71ae5a4SJacob Faibussowitsch {
51043e9753d6SMatthew G. Knepley PetscDS prob;
51053e9753d6SMatthew G. Knepley PetscInt numBd, bd;
51063e9753d6SMatthew G. Knepley DMField coordField = NULL;
51073e9753d6SMatthew G. Knepley IS facetIS = NULL;
51083e9753d6SMatthew G. Knepley DMLabel depthLabel;
51093e9753d6SMatthew G. Knepley PetscInt dim;
51103e9753d6SMatthew G. Knepley
51113e9753d6SMatthew G. Knepley PetscFunctionBegin;
51129566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
51139566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
51149566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
51159566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(depthLabel, dim - 1, &facetIS));
51169566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumBoundary(prob, &numBd));
51173e9753d6SMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) {
511845480ffeSMatthew G. Knepley PetscWeakForm wf;
51193e9753d6SMatthew G. Knepley DMBoundaryConditionType type;
51203e9753d6SMatthew G. Knepley DMLabel label;
51213e9753d6SMatthew G. Knepley const PetscInt *values;
51220c290148SMatthew G. Knepley PetscInt field, numValues, v;
51233e9753d6SMatthew G. Knepley PetscObject obj;
51243e9753d6SMatthew G. Knepley PetscClassId id;
51250c290148SMatthew G. Knepley PetscFormKey key;
51263e9753d6SMatthew G. Knepley
51279566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(prob, bd, &wf, &type, NULL, &label, &numValues, &values, &field, NULL, NULL, NULL, NULL, NULL));
51283d3e5d66SMatthew G. Knepley if (type & DM_BC_ESSENTIAL) continue;
51299566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, &obj));
51309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
51313d3e5d66SMatthew G. Knepley if (id != PETSCFE_CLASSID) continue;
51323e9753d6SMatthew G. Knepley if (!facetIS) {
51333e9753d6SMatthew G. Knepley DMLabel depthLabel;
51343e9753d6SMatthew G. Knepley PetscInt dim;
51353e9753d6SMatthew G. Knepley
51369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
51379566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
51389566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(depthLabel, dim - 1, &facetIS));
51393e9753d6SMatthew G. Knepley }
51409566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
51410c290148SMatthew G. Knepley for (v = 0; v < numValues; ++v) {
51420c290148SMatthew G. Knepley key.label = label;
51430c290148SMatthew G. Knepley key.value = values[v];
51440c290148SMatthew G. Knepley key.field = field;
51450c290148SMatthew G. Knepley key.part = 0;
5146997bf629SMatthew G. Knepley PetscCall(DMPlexComputeBdResidualSingleByKey(dm, wf, key, facetIS, locX, locX_t, t, coordField, locF));
51470c290148SMatthew G. Knepley }
51483e9753d6SMatthew G. Knepley }
51499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&facetIS));
51503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
51513e9753d6SMatthew G. Knepley }
51523e9753d6SMatthew G. Knepley
5153754e4fbaSMatthew G. Knepley /*@
5154754e4fbaSMatthew G. Knepley DMPlexComputeResidualByKey - Compute the local residual for terms matching the input key
5155754e4fbaSMatthew G. Knepley
5156754e4fbaSMatthew G. Knepley Collective
5157754e4fbaSMatthew G. Knepley
5158754e4fbaSMatthew G. Knepley Input Parameters:
5159754e4fbaSMatthew G. Knepley + dm - The output `DM`
5160754e4fbaSMatthew G. Knepley . key - The `PetscFormKey` indicating what should be integrated
5161754e4fbaSMatthew G. Knepley . cellIS - The `IS` giving a set of cells to integrate over
5162754e4fbaSMatthew G. Knepley . time - The time, or `PETSC_MIN_REAL` to include implicit terms in a time-independent problems
5163754e4fbaSMatthew G. Knepley . locX - The local solution
5164754e4fbaSMatthew G. Knepley . locX_t - The time derivative of the local solution, or `NULL` for time-independent problems
5165754e4fbaSMatthew G. Knepley . t - The time
5166*2a8381b2SBarry Smith - ctx - An optional application context, passed to the pointwise functions
5167754e4fbaSMatthew G. Knepley
5168754e4fbaSMatthew G. Knepley Output Parameter:
5169754e4fbaSMatthew G. Knepley . locF - The local residual
5170754e4fbaSMatthew G. Knepley
5171754e4fbaSMatthew G. Knepley Level: developer
5172754e4fbaSMatthew G. Knepley
5173754e4fbaSMatthew G. Knepley .seealso: `DMPlexComputeJacobianByKey()`, `DMPlexComputeResidualHybridByKey()`, `DMPlexComputeJacobianHybridByKey()`, `PetscFormKey`
5174754e4fbaSMatthew G. Knepley @*/
DMPlexComputeResidualByKey(DM dm,PetscFormKey key,IS cellIS,PetscReal time,Vec locX,Vec locX_t,PetscReal t,Vec locF,PetscCtx ctx)5175*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeResidualByKey(DM dm, PetscFormKey key, IS cellIS, PetscReal time, Vec locX, Vec locX_t, PetscReal t, Vec locF, PetscCtx ctx)
5176d71ae5a4SJacob Faibussowitsch {
51773e9753d6SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
51783e9753d6SMatthew G. Knepley const char *name = "Residual";
51793e9753d6SMatthew G. Knepley DM dmAux = NULL;
51803e9753d6SMatthew G. Knepley DM dmGrad = NULL;
51813e9753d6SMatthew G. Knepley DMLabel ghostLabel = NULL;
51826528b96dSMatthew G. Knepley PetscDS ds = NULL;
51836528b96dSMatthew G. Knepley PetscDS dsAux = NULL;
51843e9753d6SMatthew G. Knepley PetscSection section = NULL;
51853e9753d6SMatthew G. Knepley PetscBool useFEM = PETSC_FALSE;
51863e9753d6SMatthew G. Knepley PetscBool useFVM = PETSC_FALSE;
51873e9753d6SMatthew G. Knepley PetscBool isImplicit = (locX_t || time == PETSC_MIN_REAL) ? PETSC_TRUE : PETSC_FALSE;
51883e9753d6SMatthew G. Knepley PetscFV fvm = NULL;
51893e9753d6SMatthew G. Knepley DMField coordField = NULL;
51905962854dSMatthew G. Knepley Vec locA, cellGeometryFVM = NULL, faceGeometryFVM = NULL, locGrad = NULL;
51913e9753d6SMatthew G. Knepley PetscScalar *u = NULL, *u_t, *a, *uL, *uR;
51923e9753d6SMatthew G. Knepley IS chunkIS;
51933e9753d6SMatthew G. Knepley const PetscInt *cells;
51943e9753d6SMatthew G. Knepley PetscInt cStart, cEnd, numCells;
51953e9753d6SMatthew G. Knepley PetscInt Nf, f, totDim, totDimAux, numChunks, cellChunkSize, faceChunkSize, chunk, fStart, fEnd;
51961690c2aeSBarry Smith PetscInt maxDegree = PETSC_INT_MAX;
51973e9753d6SMatthew G. Knepley PetscQuadrature affineQuad = NULL, *quads = NULL;
51983e9753d6SMatthew G. Knepley PetscFEGeom *affineGeom = NULL, **geoms = NULL;
51993e9753d6SMatthew G. Knepley
52003e9753d6SMatthew G. Knepley PetscFunctionBegin;
52019566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_ResidualFEM, dm, 0, 0, 0));
52023cc88e6aSStefano Zampini if (!cellIS) goto end;
52033cc88e6aSStefano Zampini PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
52043cc88e6aSStefano Zampini if (cStart >= cEnd) goto end;
52053e9753d6SMatthew G. Knepley /* TODO The places where we have to use isFE are probably the member functions for the PetscDisc class */
52063e9753d6SMatthew G. Knepley /* TODO The FVM geometry is over-manipulated. Make the precalc functions return exactly what we need */
52073e9753d6SMatthew G. Knepley /* FEM+FVM */
52089566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
52093e9753d6SMatthew G. Knepley /* 1: Get sizes from dm and dmAux */
52109566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
52119566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "ghost", &ghostLabel));
521207218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dm, cells ? cells[cStart] : cStart, &ds, NULL));
52139566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf));
52149566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim));
52159566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, key.label, key.value, key.part, &locA));
52163e9753d6SMatthew G. Knepley if (locA) {
52173e9753d6SMatthew G. Knepley PetscInt subcell;
52189566063dSJacob Faibussowitsch PetscCall(VecGetDM(locA, &dmAux));
52191059d808SMatthew G. Knepley PetscCall(DMGetEnclosurePoint(dmAux, dm, DM_ENC_UNKNOWN, cells ? cells[cStart] : cStart, &subcell));
522007218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dmAux, subcell, &dsAux, NULL));
52219566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux));
52223e9753d6SMatthew G. Knepley }
52233e9753d6SMatthew G. Knepley /* 2: Get geometric data */
52243e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
52253e9753d6SMatthew G. Knepley PetscObject obj;
52263e9753d6SMatthew G. Knepley PetscClassId id;
52273e9753d6SMatthew G. Knepley PetscBool fimp;
52283e9753d6SMatthew G. Knepley
52299566063dSJacob Faibussowitsch PetscCall(PetscDSGetImplicit(ds, f, &fimp));
52303e9753d6SMatthew G. Knepley if (isImplicit != fimp) continue;
52319566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &obj));
52329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
5233ad540459SPierre Jolivet if (id == PETSCFE_CLASSID) useFEM = PETSC_TRUE;
52349371c9d4SSatish Balay if (id == PETSCFV_CLASSID) {
52359371c9d4SSatish Balay useFVM = PETSC_TRUE;
52369371c9d4SSatish Balay fvm = (PetscFV)obj;
52379371c9d4SSatish Balay }
52383e9753d6SMatthew G. Knepley }
52393e9753d6SMatthew G. Knepley if (useFEM) {
52409566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
52419566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, cellIS, NULL, &maxDegree));
52423e9753d6SMatthew G. Knepley if (maxDegree <= 1) {
52439566063dSJacob Faibussowitsch PetscCall(DMFieldCreateDefaultQuadrature(coordField, cellIS, &affineQuad));
5244ac9d17c7SMatthew G. Knepley if (affineQuad) PetscCall(DMSNESGetFEGeom(coordField, cellIS, affineQuad, PETSC_FEGEOM_BASIC, &affineGeom));
52453e9753d6SMatthew G. Knepley } else {
52469566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(Nf, &quads, Nf, &geoms));
52473e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
52483e9753d6SMatthew G. Knepley PetscObject obj;
52493e9753d6SMatthew G. Knepley PetscClassId id;
52503e9753d6SMatthew G. Knepley PetscBool fimp;
52513e9753d6SMatthew G. Knepley
52529566063dSJacob Faibussowitsch PetscCall(PetscDSGetImplicit(ds, f, &fimp));
52533e9753d6SMatthew G. Knepley if (isImplicit != fimp) continue;
52549566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &obj));
52559566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
52563e9753d6SMatthew G. Knepley if (id == PETSCFE_CLASSID) {
52573e9753d6SMatthew G. Knepley PetscFE fe = (PetscFE)obj;
52583e9753d6SMatthew G. Knepley
52599566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quads[f]));
52609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)quads[f]));
5261ac9d17c7SMatthew G. Knepley PetscCall(DMSNESGetFEGeom(coordField, cellIS, quads[f], PETSC_FEGEOM_BASIC, &geoms[f]));
52623e9753d6SMatthew G. Knepley }
52633e9753d6SMatthew G. Knepley }
52643e9753d6SMatthew G. Knepley }
52653e9753d6SMatthew G. Knepley }
52665962854dSMatthew G. Knepley // Handle non-essential (e.g. outflow) boundary values
52673e9753d6SMatthew G. Knepley if (useFVM) {
52685962854dSMatthew G. Knepley PetscCall(DMPlexInsertBoundaryValuesFVM(dm, fvm, locX, time, &locGrad));
52699566063dSJacob Faibussowitsch PetscCall(DMPlexGetGeometryFVM(dm, &faceGeometryFVM, &cellGeometryFVM, NULL));
52709566063dSJacob Faibussowitsch PetscCall(DMPlexGetGradientDM(dm, fvm, &dmGrad));
52713e9753d6SMatthew G. Knepley }
52723e9753d6SMatthew G. Knepley /* Loop over chunks */
52739566063dSJacob Faibussowitsch if (useFEM) PetscCall(ISCreate(PETSC_COMM_SELF, &chunkIS));
52743e9753d6SMatthew G. Knepley numCells = cEnd - cStart;
52753e9753d6SMatthew G. Knepley numChunks = 1;
52763e9753d6SMatthew G. Knepley cellChunkSize = numCells / numChunks;
52773e9753d6SMatthew G. Knepley faceChunkSize = (fEnd - fStart) / numChunks;
52783e9753d6SMatthew G. Knepley numChunks = PetscMin(1, numCells);
52793e9753d6SMatthew G. Knepley for (chunk = 0; chunk < numChunks; ++chunk) {
52803e9753d6SMatthew G. Knepley PetscScalar *elemVec, *fluxL, *fluxR;
52813e9753d6SMatthew G. Knepley PetscReal *vol;
52823e9753d6SMatthew G. Knepley PetscFVFaceGeom *fgeom;
52833e9753d6SMatthew G. Knepley PetscInt cS = cStart + chunk * cellChunkSize, cE = PetscMin(cS + cellChunkSize, cEnd), numCells = cE - cS, c;
52843e9753d6SMatthew G. Knepley PetscInt fS = fStart + chunk * faceChunkSize, fE = PetscMin(fS + faceChunkSize, fEnd), numFaces = 0, face;
52853e9753d6SMatthew G. Knepley
52863e9753d6SMatthew G. Knepley /* Extract field coefficients */
52873e9753d6SMatthew G. Knepley if (useFEM) {
52889566063dSJacob Faibussowitsch PetscCall(ISGetPointSubrange(chunkIS, cS, cE, cells));
52899566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellFields(dm, chunkIS, locX, locX_t, locA, &u, &u_t, &a));
52909566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numCells * totDim, MPIU_SCALAR, &elemVec));
52919566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemVec, numCells * totDim));
52923e9753d6SMatthew G. Knepley }
52933e9753d6SMatthew G. Knepley if (useFVM) {
52949566063dSJacob Faibussowitsch PetscCall(DMPlexGetFaceFields(dm, fS, fE, locX, locX_t, faceGeometryFVM, cellGeometryFVM, locGrad, &numFaces, &uL, &uR));
52959566063dSJacob Faibussowitsch PetscCall(DMPlexGetFaceGeometry(dm, fS, fE, faceGeometryFVM, cellGeometryFVM, &numFaces, &fgeom, &vol));
52969566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numFaces * totDim, MPIU_SCALAR, &fluxL));
52979566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numFaces * totDim, MPIU_SCALAR, &fluxR));
52989566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(fluxL, numFaces * totDim));
52999566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(fluxR, numFaces * totDim));
53003e9753d6SMatthew G. Knepley }
53013e9753d6SMatthew G. Knepley /* TODO We will interlace both our field coefficients (u, u_t, uL, uR, etc.) and our output (elemVec, fL, fR). I think this works */
53023e9753d6SMatthew G. Knepley /* Loop over fields */
53033e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
53043e9753d6SMatthew G. Knepley PetscObject obj;
53053e9753d6SMatthew G. Knepley PetscClassId id;
53063e9753d6SMatthew G. Knepley PetscBool fimp;
53073e9753d6SMatthew G. Knepley PetscInt numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset;
53083e9753d6SMatthew G. Knepley
53096528b96dSMatthew G. Knepley key.field = f;
53109566063dSJacob Faibussowitsch PetscCall(PetscDSGetImplicit(ds, f, &fimp));
53113e9753d6SMatthew G. Knepley if (isImplicit != fimp) continue;
53129566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &obj));
53139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
53143e9753d6SMatthew G. Knepley if (id == PETSCFE_CLASSID) {
53153e9753d6SMatthew G. Knepley PetscFE fe = (PetscFE)obj;
53163e9753d6SMatthew G. Knepley PetscFEGeom *geom = affineGeom ? affineGeom : geoms[f];
53173e9753d6SMatthew G. Knepley PetscFEGeom *chunkGeom = NULL;
53183e9753d6SMatthew G. Knepley PetscQuadrature quad = affineQuad ? affineQuad : quads[f];
53193e9753d6SMatthew G. Knepley PetscInt Nq, Nb;
53203e9753d6SMatthew G. Knepley
53219566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
53229566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL));
53239566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
53243e9753d6SMatthew G. Knepley blockSize = Nb;
53253e9753d6SMatthew G. Knepley batchSize = numBlocks * blockSize;
53269566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
53273e9753d6SMatthew G. Knepley numChunks = numCells / (numBatches * batchSize);
53283e9753d6SMatthew G. Knepley Ne = numChunks * numBatches * batchSize;
53293e9753d6SMatthew G. Knepley Nr = numCells % (numBatches * batchSize);
53303e9753d6SMatthew G. Knepley offset = numCells - Nr;
53313e9753d6SMatthew G. Knepley /* Integrate FE residual to get elemVec (need fields at quadrature points) */
53323e9753d6SMatthew G. Knepley /* For FV, I think we use a P0 basis and the cell coefficients (for subdivided cells, we can tweak the basis tabulation to be the indicator function) */
53339566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(geom, 0, offset, &chunkGeom));
53349566063dSJacob Faibussowitsch PetscCall(PetscFEIntegrateResidual(ds, key, Ne, chunkGeom, u, u_t, dsAux, a, t, elemVec));
53359566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(geom, offset, numCells, &chunkGeom));
53368e3a54c0SPierre Jolivet PetscCall(PetscFEIntegrateResidual(ds, key, Nr, chunkGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), dsAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, &elemVec[offset * totDim]));
53379566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(geom, offset, numCells, &chunkGeom));
53383e9753d6SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) {
53393e9753d6SMatthew G. Knepley PetscFV fv = (PetscFV)obj;
53403e9753d6SMatthew G. Knepley
53413e9753d6SMatthew G. Knepley Ne = numFaces;
53423e9753d6SMatthew G. Knepley /* Riemann solve over faces (need fields at face centroids) */
53433e9753d6SMatthew G. Knepley /* We need to evaluate FE fields at those coordinates */
53449566063dSJacob Faibussowitsch PetscCall(PetscFVIntegrateRHSFunction(fv, ds, f, Ne, fgeom, vol, uL, uR, fluxL, fluxR));
534563a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
53463e9753d6SMatthew G. Knepley }
53473e9753d6SMatthew G. Knepley /* Loop over domain */
53483e9753d6SMatthew G. Knepley if (useFEM) {
53493e9753d6SMatthew G. Knepley /* Add elemVec to locX */
53503e9753d6SMatthew G. Knepley for (c = cS; c < cE; ++c) {
53513e9753d6SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
53523e9753d6SMatthew G. Knepley const PetscInt cind = c - cStart;
53533e9753d6SMatthew G. Knepley
53549566063dSJacob Faibussowitsch if (mesh->printFEM > 1) PetscCall(DMPrintCellVector(cell, name, totDim, &elemVec[cind * totDim]));
53553e9753d6SMatthew G. Knepley if (ghostLabel) {
53563e9753d6SMatthew G. Knepley PetscInt ghostVal;
53573e9753d6SMatthew G. Knepley
53589566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(ghostLabel, cell, &ghostVal));
53593e9753d6SMatthew G. Knepley if (ghostVal > 0) continue;
53603e9753d6SMatthew G. Knepley }
53619566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(dm, section, locF, cell, &elemVec[cind * totDim], ADD_ALL_VALUES));
53623e9753d6SMatthew G. Knepley }
53633e9753d6SMatthew G. Knepley }
53643e9753d6SMatthew G. Knepley if (useFVM) {
53653e9753d6SMatthew G. Knepley PetscScalar *fa;
53663e9753d6SMatthew G. Knepley PetscInt iface;
53673e9753d6SMatthew G. Knepley
53689566063dSJacob Faibussowitsch PetscCall(VecGetArray(locF, &fa));
53693e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
53703e9753d6SMatthew G. Knepley PetscFV fv;
53713e9753d6SMatthew G. Knepley PetscObject obj;
53723e9753d6SMatthew G. Knepley PetscClassId id;
53735962854dSMatthew G. Knepley PetscInt cdim, foff, pdim;
53743e9753d6SMatthew G. Knepley
53755962854dSMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim));
53769566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &obj));
53779566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffset(ds, f, &foff));
53789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
53793e9753d6SMatthew G. Knepley if (id != PETSCFV_CLASSID) continue;
53803e9753d6SMatthew G. Knepley fv = (PetscFV)obj;
53819566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &pdim));
53823e9753d6SMatthew G. Knepley /* Accumulate fluxes to cells */
53833e9753d6SMatthew G. Knepley for (face = fS, iface = 0; face < fE; ++face) {
53843e9753d6SMatthew G. Knepley const PetscInt *scells;
53853e9753d6SMatthew G. Knepley PetscScalar *fL = NULL, *fR = NULL;
53863e9753d6SMatthew G. Knepley PetscInt ghost, d, nsupp, nchild;
53873e9753d6SMatthew G. Knepley
53889566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(ghostLabel, face, &ghost));
53899566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, face, &nsupp));
53909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, face, &nchild, NULL));
53913e9753d6SMatthew G. Knepley if (ghost >= 0 || nsupp > 2 || nchild > 0) continue;
53929566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, face, &scells));
53939566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(ghostLabel, scells[0], &ghost));
53949566063dSJacob Faibussowitsch if (ghost <= 0) PetscCall(DMPlexPointLocalFieldRef(dm, scells[0], f, fa, &fL));
53959566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(ghostLabel, scells[1], &ghost));
53969566063dSJacob Faibussowitsch if (ghost <= 0) PetscCall(DMPlexPointLocalFieldRef(dm, scells[1], f, fa, &fR));
53975962854dSMatthew G. Knepley if (mesh->printFVM > 1) {
53985962854dSMatthew G. Knepley PetscCall(DMPrintCellVectorReal(face, "Residual: normal", cdim, fgeom[iface].normal));
53995962854dSMatthew G. Knepley PetscCall(DMPrintCellVector(face, "Residual: left state", pdim, &uL[iface * totDim + foff]));
54005962854dSMatthew G. Knepley PetscCall(DMPrintCellVector(face, "Residual: right state", pdim, &uR[iface * totDim + foff]));
54015962854dSMatthew G. Knepley PetscCall(DMPrintCellVector(face, "Residual: left flux", pdim, &fluxL[iface * totDim + foff]));
54025962854dSMatthew G. Knepley PetscCall(DMPrintCellVector(face, "Residual: right flux", pdim, &fluxR[iface * totDim + foff]));
54035962854dSMatthew G. Knepley }
54043e9753d6SMatthew G. Knepley for (d = 0; d < pdim; ++d) {
54053e9753d6SMatthew G. Knepley if (fL) fL[d] -= fluxL[iface * totDim + foff + d];
54063e9753d6SMatthew G. Knepley if (fR) fR[d] += fluxR[iface * totDim + foff + d];
54073e9753d6SMatthew G. Knepley }
54083e9753d6SMatthew G. Knepley ++iface;
54093e9753d6SMatthew G. Knepley }
54103e9753d6SMatthew G. Knepley }
54119566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(locF, &fa));
54123e9753d6SMatthew G. Knepley }
54133e9753d6SMatthew G. Knepley /* Handle time derivative */
54143e9753d6SMatthew G. Knepley if (locX_t) {
54153e9753d6SMatthew G. Knepley PetscScalar *x_t, *fa;
54163e9753d6SMatthew G. Knepley
54179566063dSJacob Faibussowitsch PetscCall(VecGetArray(locF, &fa));
54189566063dSJacob Faibussowitsch PetscCall(VecGetArray(locX_t, &x_t));
54193e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
54203e9753d6SMatthew G. Knepley PetscFV fv;
54213e9753d6SMatthew G. Knepley PetscObject obj;
54223e9753d6SMatthew G. Knepley PetscClassId id;
54233e9753d6SMatthew G. Knepley PetscInt pdim, d;
54243e9753d6SMatthew G. Knepley
54259566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &obj));
54269566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
54273e9753d6SMatthew G. Knepley if (id != PETSCFV_CLASSID) continue;
54283e9753d6SMatthew G. Knepley fv = (PetscFV)obj;
54299566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &pdim));
54303e9753d6SMatthew G. Knepley for (c = cS; c < cE; ++c) {
54313e9753d6SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
54323e9753d6SMatthew G. Knepley PetscScalar *u_t, *r;
54333e9753d6SMatthew G. Knepley
54343e9753d6SMatthew G. Knepley if (ghostLabel) {
54353e9753d6SMatthew G. Knepley PetscInt ghostVal;
54363e9753d6SMatthew G. Knepley
54379566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(ghostLabel, cell, &ghostVal));
54383e9753d6SMatthew G. Knepley if (ghostVal > 0) continue;
54393e9753d6SMatthew G. Knepley }
54409566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRead(dm, cell, f, x_t, &u_t));
54419566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalFieldRef(dm, cell, f, fa, &r));
54423e9753d6SMatthew G. Knepley for (d = 0; d < pdim; ++d) r[d] += u_t[d];
54433e9753d6SMatthew G. Knepley }
54443e9753d6SMatthew G. Knepley }
54459566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(locX_t, &x_t));
54469566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(locF, &fa));
54473e9753d6SMatthew G. Knepley }
54483e9753d6SMatthew G. Knepley if (useFEM) {
54499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCellFields(dm, chunkIS, locX, locX_t, locA, &u, &u_t, &a));
54509566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numCells * totDim, MPIU_SCALAR, &elemVec));
54513e9753d6SMatthew G. Knepley }
54523e9753d6SMatthew G. Knepley if (useFVM) {
54539566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreFaceFields(dm, fS, fE, locX, locX_t, faceGeometryFVM, cellGeometryFVM, locGrad, &numFaces, &uL, &uR));
54549566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreFaceGeometry(dm, fS, fE, faceGeometryFVM, cellGeometryFVM, &numFaces, &fgeom, &vol));
54559566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numFaces * totDim, MPIU_SCALAR, &fluxL));
54569566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numFaces * totDim, MPIU_SCALAR, &fluxR));
54579566063dSJacob Faibussowitsch if (dmGrad) PetscCall(DMRestoreLocalVector(dmGrad, &locGrad));
54583e9753d6SMatthew G. Knepley }
54593e9753d6SMatthew G. Knepley }
54609566063dSJacob Faibussowitsch if (useFEM) PetscCall(ISDestroy(&chunkIS));
54619566063dSJacob Faibussowitsch PetscCall(ISRestorePointRange(cellIS, &cStart, &cEnd, &cells));
54623e9753d6SMatthew G. Knepley
54633e9753d6SMatthew G. Knepley if (useFEM) {
5464*2a8381b2SBarry Smith PetscCall(DMPlexComputeBdResidual_Internal(dm, locX, locX_t, t, locF, ctx));
54653e9753d6SMatthew G. Knepley
54663e9753d6SMatthew G. Knepley if (maxDegree <= 1) {
54679566063dSJacob Faibussowitsch PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, affineQuad, PETSC_FALSE, &affineGeom));
54689566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&affineQuad));
54693e9753d6SMatthew G. Knepley } else {
54703e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
54719566063dSJacob Faibussowitsch PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, quads[f], PETSC_FALSE, &geoms[f]));
54729566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&quads[f]));
54733e9753d6SMatthew G. Knepley }
54749566063dSJacob Faibussowitsch PetscCall(PetscFree2(quads, geoms));
54753e9753d6SMatthew G. Knepley }
54763e9753d6SMatthew G. Knepley }
54773e9753d6SMatthew G. Knepley
54783e9753d6SMatthew G. Knepley /* FEM */
54793e9753d6SMatthew G. Knepley /* 1: Get sizes from dm and dmAux */
54803e9753d6SMatthew G. Knepley /* 2: Get geometric data */
54813e9753d6SMatthew G. Knepley /* 3: Handle boundary values */
54823e9753d6SMatthew G. Knepley /* 4: Loop over domain */
54833e9753d6SMatthew G. Knepley /* Extract coefficients */
54843e9753d6SMatthew G. Knepley /* Loop over fields */
54853e9753d6SMatthew G. Knepley /* Set tiling for FE*/
54863e9753d6SMatthew G. Knepley /* Integrate FE residual to get elemVec */
54873e9753d6SMatthew G. Knepley /* Loop over subdomain */
54883e9753d6SMatthew G. Knepley /* Loop over quad points */
54893e9753d6SMatthew G. Knepley /* Transform coords to real space */
54903e9753d6SMatthew G. Knepley /* Evaluate field and aux fields at point */
54913e9753d6SMatthew G. Knepley /* Evaluate residual at point */
54923e9753d6SMatthew G. Knepley /* Transform residual to real space */
54933e9753d6SMatthew G. Knepley /* Add residual to elemVec */
54943e9753d6SMatthew G. Knepley /* Loop over domain */
54953e9753d6SMatthew G. Knepley /* Add elemVec to locX */
54963e9753d6SMatthew G. Knepley
54973e9753d6SMatthew G. Knepley /* FVM */
54983e9753d6SMatthew G. Knepley /* Get geometric data */
54993e9753d6SMatthew G. Knepley /* If using gradients */
55003e9753d6SMatthew G. Knepley /* Compute gradient data */
55013e9753d6SMatthew G. Knepley /* Loop over domain faces */
55023e9753d6SMatthew G. Knepley /* Count computational faces */
55033e9753d6SMatthew G. Knepley /* Reconstruct cell gradient */
55043e9753d6SMatthew G. Knepley /* Loop over domain cells */
55053e9753d6SMatthew G. Knepley /* Limit cell gradients */
55063e9753d6SMatthew G. Knepley /* Handle boundary values */
55073e9753d6SMatthew G. Knepley /* Loop over domain faces */
55083e9753d6SMatthew G. Knepley /* Read out field, centroid, normal, volume for each side of face */
55093e9753d6SMatthew G. Knepley /* Riemann solve over faces */
55103e9753d6SMatthew G. Knepley /* Loop over domain faces */
55113e9753d6SMatthew G. Knepley /* Accumulate fluxes to cells */
55123e9753d6SMatthew G. Knepley /* TODO Change printFEM to printDisc here */
55133e9753d6SMatthew G. Knepley if (mesh->printFEM) {
55143e9753d6SMatthew G. Knepley Vec locFbc;
55153e9753d6SMatthew G. Knepley PetscInt pStart, pEnd, p, maxDof;
55163e9753d6SMatthew G. Knepley PetscScalar *zeroes;
55173e9753d6SMatthew G. Knepley
55189566063dSJacob Faibussowitsch PetscCall(VecDuplicate(locF, &locFbc));
55199566063dSJacob Faibussowitsch PetscCall(VecCopy(locF, locFbc));
55209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
55219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof));
55229566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(maxDof, &zeroes));
552348a46eb9SPierre Jolivet for (p = pStart; p < pEnd; p++) PetscCall(VecSetValuesSection(locFbc, section, p, zeroes, INSERT_BC_VALUES));
55249566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroes));
55259566063dSJacob Faibussowitsch PetscCall(DMPrintLocalVec(dm, name, mesh->printTol, locFbc));
55269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locFbc));
55273e9753d6SMatthew G. Knepley }
55283cc88e6aSStefano Zampini end:
55299566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_ResidualFEM, dm, 0, 0, 0));
55303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
55313e9753d6SMatthew G. Knepley }
55323e9753d6SMatthew G. Knepley
5533754e4fbaSMatthew G. Knepley /*@
5534754e4fbaSMatthew G. Knepley DMPlexComputeResidualHybridByKey - Compute the local residual over hybrid cells for terms matching the input key
55356528b96dSMatthew G. Knepley
5536754e4fbaSMatthew G. Knepley Collective
55376528b96dSMatthew G. Knepley
5538754e4fbaSMatthew G. Knepley Input Parameters:
5539754e4fbaSMatthew G. Knepley + dm - The output `DM`
5540754e4fbaSMatthew G. Knepley . key - The `PetscFormKey` array (left cell, right cell, cohesive cell) indicating what should be integrated
5541754e4fbaSMatthew G. Knepley . cellIS - The `IS` give a set of cells to integrate over
5542754e4fbaSMatthew G. Knepley . time - The time, or `PETSC_MIN_REAL` to include implicit terms in a time-independent problems
5543754e4fbaSMatthew G. Knepley . locX - The local solution
5544754e4fbaSMatthew G. Knepley . locX_t - The time derivative of the local solution, or `NULL` for time-independent problems
5545754e4fbaSMatthew G. Knepley . t - The time
5546*2a8381b2SBarry Smith - ctx - An optional application context, passed to the pointwise functions
55476528b96dSMatthew G. Knepley
5548754e4fbaSMatthew G. Knepley Output Parameter:
5549754e4fbaSMatthew G. Knepley . locF - The local residual
5550754e4fbaSMatthew G. Knepley
5551754e4fbaSMatthew G. Knepley Level: developer
5552754e4fbaSMatthew G. Knepley
5553754e4fbaSMatthew G. Knepley .seealso: `DMPlexComputeResidualByKey()`, `DMPlexComputeJacobianByKey()`, `DMPlexComputeJacobianHybridByKey()`, `PetscFormKey`
5554754e4fbaSMatthew G. Knepley @*/
DMPlexComputeResidualHybridByKey(DM dm,PetscFormKey key[],IS cellIS,PetscReal time,Vec locX,Vec locX_t,PetscReal t,Vec locF,PetscCtx ctx)5555*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeResidualHybridByKey(DM dm, PetscFormKey key[], IS cellIS, PetscReal time, Vec locX, Vec locX_t, PetscReal t, Vec locF, PetscCtx ctx)
5556d71ae5a4SJacob Faibussowitsch {
55573e9753d6SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
55583e9753d6SMatthew G. Knepley const char *name = "Hybrid Residual";
555904c51a94SMatthew G. Knepley DM dmAux[3] = {NULL, NULL, NULL};
55603e9753d6SMatthew G. Knepley DMLabel ghostLabel = NULL;
55616528b96dSMatthew G. Knepley PetscDS ds = NULL;
556207218a29SMatthew G. Knepley PetscDS dsIn = NULL;
55636528b96dSMatthew G. Knepley PetscDS dsAux[3] = {NULL, NULL, NULL};
556404c51a94SMatthew G. Knepley Vec locA[3] = {NULL, NULL, NULL};
556507218a29SMatthew G. Knepley DM dmScale[3] = {NULL, NULL, NULL};
556607218a29SMatthew G. Knepley PetscDS dsScale[3] = {NULL, NULL, NULL};
556707218a29SMatthew G. Knepley Vec locS[3] = {NULL, NULL, NULL};
55683e9753d6SMatthew G. Knepley PetscSection section = NULL;
55693e9753d6SMatthew G. Knepley DMField coordField = NULL;
557007218a29SMatthew G. Knepley PetscScalar *a[3] = {NULL, NULL, NULL};
557107218a29SMatthew G. Knepley PetscScalar *s[3] = {NULL, NULL, NULL};
5572b2ab40e6SMatthew G. Knepley PetscScalar *u = NULL, *u_t;
557307218a29SMatthew G. Knepley PetscScalar *elemVecNeg, *elemVecPos, *elemVecCoh;
5574989fa639SBrad Aagaard IS chunkISF, chunkISN;
55753e9753d6SMatthew G. Knepley const PetscInt *cells;
5576989fa639SBrad Aagaard PetscInt *faces, *neighbors;
55773e9753d6SMatthew G. Knepley PetscInt cStart, cEnd, numCells;
55783e2b0218SMatthew G. Knepley PetscInt Nf, f, totDim, totDimIn, totDimAux[3], totDimScale[3], numChunks, cellChunkSize, chunk;
55791690c2aeSBarry Smith PetscInt maxDegree = PETSC_INT_MAX;
5580989fa639SBrad Aagaard PetscQuadrature affineQuadF = NULL, *quadsF = NULL;
5581989fa639SBrad Aagaard PetscFEGeom *affineGeomF = NULL, **geomsF = NULL;
5582989fa639SBrad Aagaard PetscQuadrature affineQuadN = NULL, *quadsN = NULL;
5583989fa639SBrad Aagaard PetscFEGeom *affineGeomN = NULL, **geomsN = NULL;
55843e9753d6SMatthew G. Knepley
55853e9753d6SMatthew G. Knepley PetscFunctionBegin;
55863cc88e6aSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_ResidualFEM, dm, 0, 0, 0));
55873cc88e6aSStefano Zampini if (!cellIS) goto end;
5588437e83fbSMatthew G. Knepley PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
5589437e83fbSMatthew G. Knepley PetscCall(ISGetLocalSize(cellIS, &numCells));
55903cc88e6aSStefano Zampini if (cStart >= cEnd) goto end;
55915fedec97SMatthew G. Knepley if ((key[0].label == key[1].label) && (key[0].value == key[1].value) && (key[0].part == key[1].part)) {
55925fedec97SMatthew G. Knepley const char *name;
55939566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)key[0].label, &name));
559463a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Form keys for each side of a cohesive surface must be different (%s, %" PetscInt_FMT ", %" PetscInt_FMT ")", name, key[0].value, key[0].part);
55955fedec97SMatthew G. Knepley }
55963e9753d6SMatthew G. Knepley /* TODO The places where we have to use isFE are probably the member functions for the PetscDisc class */
55973e9753d6SMatthew G. Knepley /* FEM */
55983e9753d6SMatthew G. Knepley /* 1: Get sizes from dm and dmAux */
5599b98a7184SJames Wright PetscCall(DMGetLocalSection(dm, §ion));
56009566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "ghost", &ghostLabel));
560107218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dm, cells ? cells[cStart] : cStart, &ds, &dsIn));
56029566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf));
56039566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim));
560407218a29SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsIn, &totDimIn));
56059566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, key[2].label, key[2].value, key[2].part, &locA[2]));
560604c51a94SMatthew G. Knepley if (locA[2]) {
56071059d808SMatthew G. Knepley const PetscInt cellStart = cells ? cells[cStart] : cStart;
56081059d808SMatthew G. Knepley
56099566063dSJacob Faibussowitsch PetscCall(VecGetDM(locA[2], &dmAux[2]));
561007218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dmAux[2], cellStart, &dsAux[2], NULL));
56119566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux[2], &totDimAux[2]));
56126528b96dSMatthew G. Knepley {
56136528b96dSMatthew G. Knepley const PetscInt *cone;
56146528b96dSMatthew G. Knepley PetscInt c;
56156528b96dSMatthew G. Knepley
56161059d808SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, cellStart, &cone));
56176528b96dSMatthew G. Knepley for (c = 0; c < 2; ++c) {
56186528b96dSMatthew G. Knepley const PetscInt *support;
56196528b96dSMatthew G. Knepley PetscInt ssize, s;
56206528b96dSMatthew G. Knepley
56219566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support));
56229566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &ssize));
56231059d808SMatthew G. Knepley PetscCheck(ssize == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " from cell %" PetscInt_FMT " has support size %" PetscInt_FMT " != 2", cone[c], cellStart, ssize);
56241059d808SMatthew G. Knepley if (support[0] == cellStart) s = 1;
56251059d808SMatthew G. Knepley else if (support[1] == cellStart) s = 0;
56261059d808SMatthew G. Knepley else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " does not have cell %" PetscInt_FMT " in its support", cone[c], cellStart);
56279566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, key[c].label, key[c].value, key[c].part, &locA[c]));
5628c75bfeddSPierre Jolivet PetscCheck(locA[c], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must have auxiliary vector for (%p, %" PetscInt_FMT ", %" PetscInt_FMT ")", (void *)key[c].label, key[c].value, key[c].part);
56299566063dSJacob Faibussowitsch if (locA[c]) PetscCall(VecGetDM(locA[c], &dmAux[c]));
5630ad540459SPierre Jolivet else dmAux[c] = dmAux[2];
563107218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dmAux[c], support[s], &dsAux[c], NULL));
56329566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux[c], &totDimAux[c]));
56336528b96dSMatthew G. Knepley }
56346528b96dSMatthew G. Knepley }
56353e9753d6SMatthew G. Knepley }
563607218a29SMatthew G. Knepley /* Handle mass matrix scaling
563707218a29SMatthew G. Knepley The field in key[2] is the field to be scaled, and the scaling field is the first in the dsScale */
563807218a29SMatthew G. Knepley PetscCall(DMGetAuxiliaryVec(dm, key[2].label, -key[2].value, key[2].part, &locS[2]));
563907218a29SMatthew G. Knepley if (locS[2]) {
56403e2b0218SMatthew G. Knepley const PetscInt cellStart = cells ? cells[cStart] : cStart;
564107218a29SMatthew G. Knepley PetscInt Nb, Nbs;
564207218a29SMatthew G. Knepley
564307218a29SMatthew G. Knepley PetscCall(VecGetDM(locS[2], &dmScale[2]));
56443e2b0218SMatthew G. Knepley PetscCall(DMGetCellDS(dmScale[2], cellStart, &dsScale[2], NULL));
56453e2b0218SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsScale[2], &totDimScale[2]));
564607218a29SMatthew G. Knepley // BRAD: This is not set correctly
564707218a29SMatthew G. Knepley key[2].field = 2;
564807218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldSize(ds, key[2].field, &Nb));
564907218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldSize(dsScale[2], 0, &Nbs));
565007218a29SMatthew G. Knepley PetscCheck(Nb == Nbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Field %" PetscInt_FMT " of size %" PetscInt_FMT " cannot be scaled by field of size %" PetscInt_FMT, key[2].field, Nb, Nbs);
56513e2b0218SMatthew G. Knepley {
56523e2b0218SMatthew G. Knepley const PetscInt *cone;
56533e2b0218SMatthew G. Knepley PetscInt c;
56543e2b0218SMatthew G. Knepley
56553e2b0218SMatthew G. Knepley locS[1] = locS[0] = locS[2];
56563e2b0218SMatthew G. Knepley dmScale[1] = dmScale[0] = dmScale[2];
56573e2b0218SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, cellStart, &cone));
56583e2b0218SMatthew G. Knepley for (c = 0; c < 2; ++c) {
56593e2b0218SMatthew G. Knepley const PetscInt *support;
56603e2b0218SMatthew G. Knepley PetscInt ssize, s;
56613e2b0218SMatthew G. Knepley
56623e2b0218SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, cone[c], &support));
56633e2b0218SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, cone[c], &ssize));
56643e2b0218SMatthew G. Knepley PetscCheck(ssize == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " from cell %" PetscInt_FMT " has support size %" PetscInt_FMT " != 2", cone[c], cellStart, ssize);
56653e2b0218SMatthew G. Knepley if (support[0] == cellStart) s = 1;
56663e2b0218SMatthew G. Knepley else if (support[1] == cellStart) s = 0;
56673e2b0218SMatthew G. Knepley else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " does not have cell %" PetscInt_FMT " in its support", cone[c], cellStart);
56683e2b0218SMatthew G. Knepley PetscCall(DMGetCellDS(dmScale[c], support[s], &dsScale[c], NULL));
56693e2b0218SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsScale[c], &totDimScale[c]));
56703e2b0218SMatthew G. Knepley }
56713e2b0218SMatthew G. Knepley }
567207218a29SMatthew G. Knepley }
56733e9753d6SMatthew G. Knepley /* 2: Setup geometric data */
56749566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
56759566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, cellIS, NULL, &maxDegree));
56763e9753d6SMatthew G. Knepley if (maxDegree > 1) {
5677989fa639SBrad Aagaard PetscCall(PetscCalloc4(Nf, &quadsF, Nf, &geomsF, Nf, &quadsN, Nf, &geomsN));
56783e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
56793e9753d6SMatthew G. Knepley PetscFE fe;
5680989fa639SBrad Aagaard PetscBool isCohesiveField;
56813e9753d6SMatthew G. Knepley
56829566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, (PetscObject *)&fe));
56833e9753d6SMatthew G. Knepley if (fe) {
5684989fa639SBrad Aagaard PetscCall(PetscFEGetQuadrature(fe, &quadsF[f]));
5685989fa639SBrad Aagaard PetscCall(PetscObjectReference((PetscObject)quadsF[f]));
5686989fa639SBrad Aagaard }
5687989fa639SBrad Aagaard PetscCall(PetscDSGetDiscretization(dsIn, f, (PetscObject *)&fe));
5688989fa639SBrad Aagaard PetscCall(PetscDSGetCohesive(dsIn, f, &isCohesiveField));
5689989fa639SBrad Aagaard if (fe) {
5690989fa639SBrad Aagaard if (isCohesiveField) {
5691989fa639SBrad Aagaard for (PetscInt g = 0; g < Nf; ++g) {
5692989fa639SBrad Aagaard PetscCall(PetscDSGetDiscretization(dsIn, g, (PetscObject *)&fe));
5693989fa639SBrad Aagaard PetscCall(PetscDSGetCohesive(dsIn, g, &isCohesiveField));
5694989fa639SBrad Aagaard if (!isCohesiveField) break;
5695989fa639SBrad Aagaard }
5696989fa639SBrad Aagaard }
5697989fa639SBrad Aagaard PetscCall(PetscFEGetQuadrature(fe, &quadsN[f]));
5698989fa639SBrad Aagaard PetscCall(PetscObjectReference((PetscObject)quadsN[f]));
56993e9753d6SMatthew G. Knepley }
57003e9753d6SMatthew G. Knepley }
57013e9753d6SMatthew G. Knepley }
57023e9753d6SMatthew G. Knepley /* Loop over chunks */
57033e9753d6SMatthew G. Knepley cellChunkSize = numCells;
57043e9753d6SMatthew G. Knepley numChunks = !numCells ? 0 : PetscCeilReal(((PetscReal)numCells) / cellChunkSize);
5705989fa639SBrad Aagaard PetscCall(PetscCalloc2(2 * cellChunkSize, &faces, 2 * cellChunkSize, &neighbors));
5706989fa639SBrad Aagaard PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2 * cellChunkSize, faces, PETSC_USE_POINTER, &chunkISF));
5707989fa639SBrad Aagaard PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2 * cellChunkSize, neighbors, PETSC_USE_POINTER, &chunkISN));
57083e9753d6SMatthew G. Knepley /* Extract field coefficients */
57093e9753d6SMatthew G. Knepley /* NOTE This needs the end cap faces to have identical orientations */
571007218a29SMatthew G. Knepley PetscCall(DMPlexGetHybridCellFields(dm, cellIS, locX, locX_t, locA[2], &u, &u_t, &a[2]));
571107218a29SMatthew G. Knepley PetscCall(DMPlexGetHybridFields(dm, dmAux, dsAux, cellIS, locA, PETSC_TRUE, a));
57123e2b0218SMatthew G. Knepley PetscCall(DMPlexGetHybridFields(dm, dmScale, dsScale, cellIS, locS, PETSC_TRUE, s));
571307218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, cellChunkSize * totDim, MPIU_SCALAR, &elemVecNeg));
571407218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, cellChunkSize * totDim, MPIU_SCALAR, &elemVecPos));
571507218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, cellChunkSize * totDim, MPIU_SCALAR, &elemVecCoh));
57163e9753d6SMatthew G. Knepley for (chunk = 0; chunk < numChunks; ++chunk) {
57173e9753d6SMatthew G. Knepley PetscInt cS = cStart + chunk * cellChunkSize, cE = PetscMin(cS + cellChunkSize, cEnd), numCells = cE - cS, c;
57183e9753d6SMatthew G. Knepley
571907218a29SMatthew G. Knepley PetscCall(PetscArrayzero(elemVecNeg, cellChunkSize * totDim));
572007218a29SMatthew G. Knepley PetscCall(PetscArrayzero(elemVecPos, cellChunkSize * totDim));
572107218a29SMatthew G. Knepley PetscCall(PetscArrayzero(elemVecCoh, cellChunkSize * totDim));
5722989fa639SBrad Aagaard /* Get faces and neighbors */
57233e9753d6SMatthew G. Knepley for (c = cS; c < cE; ++c) {
57243e9753d6SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
5725989fa639SBrad Aagaard const PetscInt *cone, *support;
57269566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cell, &cone));
572707218a29SMatthew G. Knepley faces[(c - cS) * 2 + 0] = cone[0];
572807218a29SMatthew G. Knepley faces[(c - cS) * 2 + 1] = cone[1];
5729989fa639SBrad Aagaard PetscCall(DMPlexGetSupport(dm, cone[0], &support));
5730989fa639SBrad Aagaard neighbors[(c - cS) * 2 + 0] = support[0] == cell ? support[1] : support[0];
5731989fa639SBrad Aagaard PetscCall(DMPlexGetSupport(dm, cone[1], &support));
5732989fa639SBrad Aagaard neighbors[(c - cS) * 2 + 1] = support[0] == cell ? support[1] : support[0];
57333e9753d6SMatthew G. Knepley }
5734989fa639SBrad Aagaard PetscCall(ISGeneralSetIndices(chunkISF, 2 * cellChunkSize, faces, PETSC_USE_POINTER));
5735989fa639SBrad Aagaard PetscCall(ISGeneralSetIndices(chunkISN, 2 * cellChunkSize, neighbors, PETSC_USE_POINTER));
57363e9753d6SMatthew G. Knepley /* Get geometric data */
57373e9753d6SMatthew G. Knepley if (maxDegree <= 1) {
5738989fa639SBrad Aagaard if (!affineQuadF) PetscCall(DMFieldCreateDefaultQuadrature(coordField, chunkISF, &affineQuadF));
5739989fa639SBrad Aagaard if (affineQuadF) PetscCall(DMSNESGetFEGeom(coordField, chunkISF, affineQuadF, PETSC_FEGEOM_COHESIVE, &affineGeomF));
5740989fa639SBrad Aagaard if (!affineQuadN) {
5741989fa639SBrad Aagaard PetscInt dim;
5742989fa639SBrad Aagaard PetscCall(PetscQuadratureGetData(affineQuadF, &dim, NULL, NULL, NULL, NULL));
5743989fa639SBrad Aagaard PetscCall(DMFieldCreateDefaultFaceQuadrature(coordField, chunkISN, &affineQuadN));
5744989fa639SBrad Aagaard PetscCall(PetscQuadratureSetData(affineQuadN, dim + 1, PETSC_DECIDE, PETSC_DECIDE, NULL, NULL));
5745989fa639SBrad Aagaard }
5746989fa639SBrad Aagaard if (affineQuadN) PetscCall(DMSNESGetFEGeom(coordField, chunkISN, affineQuadN, PETSC_FEGEOM_BASIC, &affineGeomN));
57473e9753d6SMatthew G. Knepley } else {
57483e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
5749989fa639SBrad Aagaard if (quadsF[f]) PetscCall(DMSNESGetFEGeom(coordField, chunkISF, quadsF[f], PETSC_FEGEOM_COHESIVE, &geomsF[f]));
5750989fa639SBrad Aagaard if (quadsN[f]) PetscCall(DMSNESGetFEGeom(coordField, chunkISN, quadsN[f], PETSC_FEGEOM_BASIC, &geomsN[f]));
57513e9753d6SMatthew G. Knepley }
57523e9753d6SMatthew G. Knepley }
57533e9753d6SMatthew G. Knepley /* Loop over fields */
57543e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
57553e9753d6SMatthew G. Knepley PetscFE fe;
5756989fa639SBrad Aagaard PetscFEGeom *geomF = affineGeomF ? affineGeomF : geomsF[f];
5757989fa639SBrad Aagaard PetscFEGeom *chunkGeomF = NULL, *remGeomF = NULL;
5758989fa639SBrad Aagaard PetscFEGeom *geomN = affineGeomN ? affineGeomN : geomsN[f];
5759989fa639SBrad Aagaard PetscFEGeom *chunkGeomN = NULL, *remGeomN = NULL;
5760989fa639SBrad Aagaard PetscQuadrature quadF = affineQuadF ? affineQuadF : quadsF[f];
57613e9753d6SMatthew G. Knepley PetscInt numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset, Nq, Nb;
57625fedec97SMatthew G. Knepley PetscBool isCohesiveField;
57633e9753d6SMatthew G. Knepley
57649566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, (PetscObject *)&fe));
57653e9753d6SMatthew G. Knepley if (!fe) continue;
57669566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
5767989fa639SBrad Aagaard PetscCall(PetscQuadratureGetData(quadF, NULL, NULL, &Nq, NULL, NULL));
57689566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
57693e9753d6SMatthew G. Knepley blockSize = Nb;
57703e9753d6SMatthew G. Knepley batchSize = numBlocks * blockSize;
57719566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
57723e9753d6SMatthew G. Knepley numChunks = numCells / (numBatches * batchSize);
57733e9753d6SMatthew G. Knepley Ne = numChunks * numBatches * batchSize;
57743e9753d6SMatthew G. Knepley Nr = numCells % (numBatches * batchSize);
57753e9753d6SMatthew G. Knepley offset = numCells - Nr;
5776989fa639SBrad Aagaard PetscCall(PetscFEGeomGetChunk(geomF, 0, offset * 2, &chunkGeomF));
5777989fa639SBrad Aagaard PetscCall(PetscFEGeomGetChunk(geomF, offset * 2, numCells * 2, &remGeomF));
5778989fa639SBrad Aagaard PetscCall(PetscFEGeomGetChunk(geomN, 0, offset * 2, &chunkGeomN));
5779989fa639SBrad Aagaard PetscCall(PetscFEGeomGetChunk(geomN, offset * 2, numCells * 2, &remGeomN));
57809566063dSJacob Faibussowitsch PetscCall(PetscDSGetCohesive(ds, f, &isCohesiveField));
5781989fa639SBrad Aagaard // TODO Do I need to set isCohesive on the chunks?
57826528b96dSMatthew G. Knepley key[0].field = f;
57836528b96dSMatthew G. Knepley key[1].field = f;
57845fedec97SMatthew G. Knepley key[2].field = f;
5785989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridResidual(ds, dsIn, key[0], 0, Ne, chunkGeomF, chunkGeomN, u, u_t, dsAux[0], a[0], t, elemVecNeg));
5786989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridResidual(ds, dsIn, key[0], 0, Nr, remGeomF, remGeomN, &u[offset * totDimIn], PetscSafePointerPlusOffset(u_t, offset * totDimIn), dsAux[0], PetscSafePointerPlusOffset(a[0], offset * totDimAux[0]), t, &elemVecNeg[offset * totDim]));
5787989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridResidual(ds, dsIn, key[1], 1, Ne, chunkGeomF, chunkGeomN, u, u_t, dsAux[1], a[1], t, elemVecPos));
5788989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridResidual(ds, dsIn, key[1], 1, Nr, remGeomF, remGeomN, &u[offset * totDimIn], PetscSafePointerPlusOffset(u_t, offset * totDimIn), dsAux[1], PetscSafePointerPlusOffset(a[1], offset * totDimAux[1]), t, &elemVecPos[offset * totDim]));
5789989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridResidual(ds, dsIn, key[2], 2, Ne, chunkGeomF, chunkGeomN, u, u_t, dsAux[2], a[2], t, elemVecCoh));
5790989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridResidual(ds, dsIn, key[2], 2, Nr, remGeomF, remGeomN, &u[offset * totDimIn], PetscSafePointerPlusOffset(u_t, offset * totDimIn), dsAux[2], PetscSafePointerPlusOffset(a[2], offset * totDimAux[2]), t, &elemVecCoh[offset * totDim]));
5791989fa639SBrad Aagaard PetscCall(PetscFEGeomRestoreChunk(geomF, offset, numCells, &remGeomF));
5792989fa639SBrad Aagaard PetscCall(PetscFEGeomRestoreChunk(geomF, 0, offset, &chunkGeomF));
5793989fa639SBrad Aagaard PetscCall(PetscFEGeomRestoreChunk(geomN, offset, numCells, &remGeomN));
5794989fa639SBrad Aagaard PetscCall(PetscFEGeomRestoreChunk(geomN, 0, offset, &chunkGeomN));
57953e9753d6SMatthew G. Knepley }
57963e9753d6SMatthew G. Knepley /* Add elemVec to locX */
57973e9753d6SMatthew G. Knepley for (c = cS; c < cE; ++c) {
57983e9753d6SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
57993e9753d6SMatthew G. Knepley const PetscInt cind = c - cStart;
580007218a29SMatthew G. Knepley PetscInt i;
58013e9753d6SMatthew G. Knepley
580207218a29SMatthew G. Knepley /* Scale element values */
580307218a29SMatthew G. Knepley if (locS[0]) {
58043e2b0218SMatthew G. Knepley PetscInt Nb, off = cind * totDim, soff = cind * totDimScale[0];
580507218a29SMatthew G. Knepley PetscBool cohesive;
580607218a29SMatthew G. Knepley
580707218a29SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
580807218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldSize(ds, f, &Nb));
580907218a29SMatthew G. Knepley PetscCall(PetscDSGetCohesive(ds, f, &cohesive));
581007218a29SMatthew G. Knepley if (f == key[2].field) {
581107218a29SMatthew G. Knepley PetscCheck(cohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Scaling should not happen for face fields");
581207218a29SMatthew G. Knepley // No cohesive scaling field is currently input
581307218a29SMatthew G. Knepley for (i = 0; i < Nb; ++i) elemVecCoh[off + i] += s[0][soff + i] * elemVecNeg[off + i] + s[1][soff + i] * elemVecPos[off + i];
581407218a29SMatthew G. Knepley off += Nb;
581507218a29SMatthew G. Knepley } else {
581607218a29SMatthew G. Knepley const PetscInt N = cohesive ? Nb : Nb * 2;
581707218a29SMatthew G. Knepley
581807218a29SMatthew G. Knepley for (i = 0; i < N; ++i) elemVecCoh[off + i] += elemVecNeg[off + i] + elemVecPos[off + i];
581907218a29SMatthew G. Knepley off += N;
582007218a29SMatthew G. Knepley }
582107218a29SMatthew G. Knepley }
582207218a29SMatthew G. Knepley } else {
582307218a29SMatthew G. Knepley for (i = cind * totDim; i < (cind + 1) * totDim; ++i) elemVecCoh[i] += elemVecNeg[i] + elemVecPos[i];
582407218a29SMatthew G. Knepley }
582507218a29SMatthew G. Knepley if (mesh->printFEM > 1) PetscCall(DMPrintCellVector(cell, name, totDim, &elemVecCoh[cind * totDim]));
58263e9753d6SMatthew G. Knepley if (ghostLabel) {
58273e9753d6SMatthew G. Knepley PetscInt ghostVal;
58283e9753d6SMatthew G. Knepley
58299566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(ghostLabel, cell, &ghostVal));
58303e9753d6SMatthew G. Knepley if (ghostVal > 0) continue;
58313e9753d6SMatthew G. Knepley }
583207218a29SMatthew G. Knepley PetscCall(DMPlexVecSetClosure(dm, section, locF, cell, &elemVecCoh[cind * totDim], ADD_ALL_VALUES));
58333e9753d6SMatthew G. Knepley }
58343e9753d6SMatthew G. Knepley }
58359566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCellFields(dm, cellIS, locX, locX_t, locA[2], &u, &u_t, &a[2]));
583607218a29SMatthew G. Knepley PetscCall(DMPlexRestoreHybridFields(dm, dmAux, dsAux, cellIS, locA, PETSC_TRUE, a));
58373e2b0218SMatthew G. Knepley PetscCall(DMPlexRestoreHybridFields(dm, dmScale, dsScale, cellIS, locS, PETSC_TRUE, s));
583807218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, numCells * totDim, MPIU_SCALAR, &elemVecNeg));
583907218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, numCells * totDim, MPIU_SCALAR, &elemVecPos));
584007218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, numCells * totDim, MPIU_SCALAR, &elemVecCoh));
5841989fa639SBrad Aagaard PetscCall(PetscFree2(faces, neighbors));
5842989fa639SBrad Aagaard PetscCall(ISDestroy(&chunkISF));
5843989fa639SBrad Aagaard PetscCall(ISDestroy(&chunkISN));
58449566063dSJacob Faibussowitsch PetscCall(ISRestorePointRange(cellIS, &cStart, &cEnd, &cells));
58453e9753d6SMatthew G. Knepley if (maxDegree <= 1) {
5846989fa639SBrad Aagaard PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, affineQuadF, PETSC_FALSE, &affineGeomF));
5847989fa639SBrad Aagaard PetscCall(PetscQuadratureDestroy(&affineQuadF));
5848989fa639SBrad Aagaard PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, affineQuadN, PETSC_FALSE, &affineGeomN));
5849989fa639SBrad Aagaard PetscCall(PetscQuadratureDestroy(&affineQuadN));
58503e9753d6SMatthew G. Knepley } else {
58513e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
5852989fa639SBrad Aagaard if (geomsF) PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, quadsF[f], PETSC_FALSE, &geomsF[f]));
5853989fa639SBrad Aagaard if (quadsF) PetscCall(PetscQuadratureDestroy(&quadsF[f]));
5854989fa639SBrad Aagaard if (geomsN) PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, quadsN[f], PETSC_FALSE, &geomsN[f]));
5855989fa639SBrad Aagaard if (quadsN) PetscCall(PetscQuadratureDestroy(&quadsN[f]));
58563e9753d6SMatthew G. Knepley }
5857989fa639SBrad Aagaard PetscCall(PetscFree4(quadsF, geomsF, quadsN, geomsN));
58583e9753d6SMatthew G. Knepley }
585985cc2951SMatthew G. Knepley if (mesh->printFEM) {
586085cc2951SMatthew G. Knepley Vec locFbc;
586185cc2951SMatthew G. Knepley PetscInt pStart, pEnd, p, maxDof;
586285cc2951SMatthew G. Knepley PetscScalar *zeroes;
586385cc2951SMatthew G. Knepley
586485cc2951SMatthew G. Knepley PetscCall(VecDuplicate(locF, &locFbc));
586585cc2951SMatthew G. Knepley PetscCall(VecCopy(locF, locFbc));
586685cc2951SMatthew G. Knepley PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
586785cc2951SMatthew G. Knepley PetscCall(PetscSectionGetMaxDof(section, &maxDof));
586885cc2951SMatthew G. Knepley PetscCall(PetscCalloc1(maxDof, &zeroes));
586985cc2951SMatthew G. Knepley for (p = pStart; p < pEnd; p++) PetscCall(VecSetValuesSection(locFbc, section, p, zeroes, INSERT_BC_VALUES));
587085cc2951SMatthew G. Knepley PetscCall(PetscFree(zeroes));
587185cc2951SMatthew G. Knepley PetscCall(DMPrintLocalVec(dm, name, mesh->printTol, locFbc));
587285cc2951SMatthew G. Knepley PetscCall(VecDestroy(&locFbc));
587385cc2951SMatthew G. Knepley }
58743cc88e6aSStefano Zampini end:
58759566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_ResidualFEM, dm, 0, 0, 0));
58763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
58773e9753d6SMatthew G. Knepley }
58783e9753d6SMatthew G. Knepley
5879997bf629SMatthew G. Knepley /*@
5880997bf629SMatthew G. Knepley DMPlexComputeBdJacobianSingleByLabel - Compute the local boundary Jacobian for terms matching the input label
5881997bf629SMatthew G. Knepley
5882997bf629SMatthew G. Knepley Not collective
5883997bf629SMatthew G. Knepley
5884997bf629SMatthew G. Knepley Input Parameters:
5885997bf629SMatthew G. Knepley + dm - The output `DM`
5886997bf629SMatthew G. Knepley . wf - The `PetscWeakForm` holding forms on this boundary
5887997bf629SMatthew G. Knepley . label - The `DMLabel` indicating what faces should be integrated over
5888997bf629SMatthew G. Knepley . numValues - The number of label values
5889997bf629SMatthew G. Knepley . values - The array of label values
5890997bf629SMatthew G. Knepley . fieldI - The test field for these integrals
5891997bf629SMatthew G. Knepley . facetIS - The `IS` giving the set of possible faces to integrate over (intersected with the label)
5892997bf629SMatthew G. Knepley . locX - The local solution
5893997bf629SMatthew G. Knepley . locX_t - The time derivative of the local solution, or `NULL` for time-independent problems
5894997bf629SMatthew G. Knepley . t - The time
5895997bf629SMatthew G. Knepley . coordField - The `DMField` object with coordinates for these faces
5896997bf629SMatthew G. Knepley - X_tShift - The multiplier for dF/dxdot
5897997bf629SMatthew G. Knepley
5898997bf629SMatthew G. Knepley Output Parameters:
5899997bf629SMatthew G. Knepley + Jac - The local Jacobian
5900997bf629SMatthew G. Knepley - JacP - The local Jacobian preconditioner
5901997bf629SMatthew G. Knepley
5902997bf629SMatthew G. Knepley Level: developer
5903997bf629SMatthew G. Knepley
5904997bf629SMatthew G. Knepley .seealso: `DMPlexComputeBdJacobianSingle()`, `DMPlexComputeJacobianByKey()`, `DMPlexComputeResidualHybridByKey()`, `DMPlexComputeJacobianHybridByKey()`, `PetscFormKey`
5905997bf629SMatthew G. Knepley @*/
DMPlexComputeBdJacobianSingleByLabel(DM dm,PetscWeakForm wf,DMLabel label,PetscInt numValues,const PetscInt values[],PetscInt fieldI,IS facetIS,Vec locX,Vec locX_t,PetscReal t,DMField coordField,PetscReal X_tShift,Mat Jac,Mat JacP)5906997bf629SMatthew G. Knepley PetscErrorCode DMPlexComputeBdJacobianSingleByLabel(DM dm, PetscWeakForm wf, DMLabel label, PetscInt numValues, const PetscInt values[], PetscInt fieldI, IS facetIS, Vec locX, Vec locX_t, PetscReal t, DMField coordField, PetscReal X_tShift, Mat Jac, Mat JacP)
5907d71ae5a4SJacob Faibussowitsch {
59083e9753d6SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
59093e9753d6SMatthew G. Knepley DM plex = NULL, plexA = NULL, tdm;
59103e9753d6SMatthew G. Knepley DMEnclosureType encAux;
5911be62b2b4SMatthew G. Knepley PetscDS ds, dsAux = NULL;
59123e9753d6SMatthew G. Knepley PetscSection section, sectionAux = NULL;
5913e432b41dSStefano Zampini PetscSection globalSection;
59143e9753d6SMatthew G. Knepley Vec locA = NULL, tv;
5915be62b2b4SMatthew G. Knepley PetscScalar *u = NULL, *u_t = NULL, *a = NULL, *elemMat = NULL, *elemMatP = NULL;
59163e9753d6SMatthew G. Knepley PetscInt v;
59173e9753d6SMatthew G. Knepley PetscInt Nf, totDim, totDimAux = 0;
5918be62b2b4SMatthew G. Knepley PetscBool hasJac = PETSC_FALSE, hasPrec = PETSC_FALSE, transform;
59193e9753d6SMatthew G. Knepley
59203e9753d6SMatthew G. Knepley PetscFunctionBegin;
59219566063dSJacob Faibussowitsch PetscCall(DMHasBasisTransform(dm, &transform));
59229566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformDM_Internal(dm, &tdm));
59239566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
59249566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
5925be62b2b4SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds));
5926be62b2b4SMatthew G. Knepley PetscCall(PetscDSGetNumFields(ds, &Nf));
5927be62b2b4SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(ds, &totDim));
592821a4fad8SMatthew G. Knepley PetscCall(PetscWeakFormHasBdJacobian(wf, &hasJac));
592921a4fad8SMatthew G. Knepley PetscCall(PetscWeakFormHasBdJacobianPreconditioner(wf, &hasPrec));
593021a4fad8SMatthew G. Knepley if (!hasJac && !hasPrec) PetscFunctionReturn(PETSC_SUCCESS);
593121a4fad8SMatthew G. Knepley PetscCall(DMConvert(dm, DMPLEX, &plex));
59329566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, label, values[0], 0, &locA));
59333e9753d6SMatthew G. Knepley if (locA) {
59343e9753d6SMatthew G. Knepley DM dmAux;
59353e9753d6SMatthew G. Knepley
59369566063dSJacob Faibussowitsch PetscCall(VecGetDM(locA, &dmAux));
59379566063dSJacob Faibussowitsch PetscCall(DMGetEnclosureRelation(dmAux, dm, &encAux));
59389566063dSJacob Faibussowitsch PetscCall(DMConvert(dmAux, DMPLEX, &plexA));
5939be62b2b4SMatthew G. Knepley PetscCall(DMGetDS(plexA, &dsAux));
5940be62b2b4SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux));
59419566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(plexA, §ionAux));
59423e9753d6SMatthew G. Knepley }
59433e9753d6SMatthew G. Knepley
59449566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, &globalSection));
59453e9753d6SMatthew G. Knepley for (v = 0; v < numValues; ++v) {
59463e9753d6SMatthew G. Knepley PetscFEGeom *fgeom;
59473e9753d6SMatthew G. Knepley PetscInt maxDegree;
59483e9753d6SMatthew G. Knepley PetscQuadrature qGeom = NULL;
59493e9753d6SMatthew G. Knepley IS pointIS;
59503e9753d6SMatthew G. Knepley const PetscInt *points;
595106ad1575SMatthew G. Knepley PetscFormKey key;
59523e9753d6SMatthew G. Knepley PetscInt numFaces, face, Nq;
59533e9753d6SMatthew G. Knepley
595445480ffeSMatthew G. Knepley key.label = label;
595545480ffeSMatthew G. Knepley key.value = values[v];
595606ad1575SMatthew G. Knepley key.part = 0;
59579566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS));
59583e9753d6SMatthew G. Knepley if (!pointIS) continue; /* No points with that id on this process */
59593e9753d6SMatthew G. Knepley {
59603e9753d6SMatthew G. Knepley IS isectIS;
59613e9753d6SMatthew G. Knepley
59623e9753d6SMatthew G. Knepley /* TODO: Special cases of ISIntersect where it is quick to check a prior if one is a superset of the other */
59639566063dSJacob Faibussowitsch PetscCall(ISIntersect_Caching_Internal(facetIS, pointIS, &isectIS));
59649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
59653e9753d6SMatthew G. Knepley pointIS = isectIS;
59663e9753d6SMatthew G. Knepley }
59679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numFaces));
59689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points));
596932603206SJames Wright PetscCall(PetscMalloc5(numFaces * totDim, &u, (locX_t ? (size_t)numFaces * totDim : 0), &u_t, (hasJac ? (size_t)numFaces * totDim * totDim : 0), &elemMat, (hasPrec ? (size_t)numFaces * totDim * totDim : 0), &elemMatP, (locA ? (size_t)numFaces * totDimAux : 0), &a));
59709566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, pointIS, NULL, &maxDegree));
597148a46eb9SPierre Jolivet if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, pointIS, &qGeom));
59723e9753d6SMatthew G. Knepley if (!qGeom) {
59733e9753d6SMatthew G. Knepley PetscFE fe;
59743e9753d6SMatthew G. Knepley
5975be62b2b4SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(ds, fieldI, (PetscObject *)&fe));
59769566063dSJacob Faibussowitsch PetscCall(PetscFEGetFaceQuadrature(fe, &qGeom));
59779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)qGeom));
59783e9753d6SMatthew G. Knepley }
59799566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL));
5980ac9d17c7SMatthew G. Knepley PetscCall(DMSNESGetFEGeom(coordField, pointIS, qGeom, PETSC_FEGEOM_BOUNDARY, &fgeom));
59813e9753d6SMatthew G. Knepley for (face = 0; face < numFaces; ++face) {
5982f15274beSMatthew Knepley const PetscInt point = points[face], *support;
59833e9753d6SMatthew G. Knepley PetscScalar *x = NULL;
5984f15274beSMatthew Knepley PetscInt i;
59853e9753d6SMatthew G. Knepley
59869566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support));
59879566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plex, section, locX, support[0], NULL, &x));
59883e9753d6SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[face * totDim + i] = x[i];
59899566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plex, section, locX, support[0], NULL, &x));
59903e9753d6SMatthew G. Knepley if (locX_t) {
59919566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plex, section, locX_t, support[0], NULL, &x));
59923e9753d6SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[face * totDim + i] = x[i];
59939566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plex, section, locX_t, support[0], NULL, &x));
59943e9753d6SMatthew G. Knepley }
59953e9753d6SMatthew G. Knepley if (locA) {
59963e9753d6SMatthew G. Knepley PetscInt subp;
59979566063dSJacob Faibussowitsch PetscCall(DMGetEnclosurePoint(plexA, dm, encAux, support[0], &subp));
59989566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plexA, sectionAux, locA, subp, NULL, &x));
59993e9753d6SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[face * totDimAux + i] = x[i];
60009566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plexA, sectionAux, locA, subp, NULL, &x));
60013e9753d6SMatthew G. Knepley }
60023e9753d6SMatthew G. Knepley }
600321a4fad8SMatthew G. Knepley if (elemMat) PetscCall(PetscArrayzero(elemMat, numFaces * totDim * totDim));
600421a4fad8SMatthew G. Knepley if (elemMatP) PetscCall(PetscArrayzero(elemMatP, numFaces * totDim * totDim));
60053e9753d6SMatthew G. Knepley {
60063e9753d6SMatthew G. Knepley PetscFE fe;
60073e9753d6SMatthew G. Knepley PetscInt Nb;
60083e9753d6SMatthew G. Knepley /* Conforming batches */
60093e9753d6SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
60103e9753d6SMatthew G. Knepley /* Remainder */
60113e9753d6SMatthew G. Knepley PetscFEGeom *chunkGeom = NULL;
60123e9753d6SMatthew G. Knepley PetscInt fieldJ, Nr, offset;
60133e9753d6SMatthew G. Knepley
6014be62b2b4SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(ds, fieldI, (PetscObject *)&fe));
60159566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
60169566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
60173e9753d6SMatthew G. Knepley blockSize = Nb;
60183e9753d6SMatthew G. Knepley batchSize = numBlocks * blockSize;
60199566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
60203e9753d6SMatthew G. Knepley numChunks = numFaces / (numBatches * batchSize);
60213e9753d6SMatthew G. Knepley Ne = numChunks * numBatches * batchSize;
60223e9753d6SMatthew G. Knepley Nr = numFaces % (numBatches * batchSize);
60233e9753d6SMatthew G. Knepley offset = numFaces - Nr;
60249566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(fgeom, 0, offset, &chunkGeom));
60253e9753d6SMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
602645480ffeSMatthew G. Knepley key.field = fieldI * Nf + fieldJ;
6027be62b2b4SMatthew G. Knepley if (hasJac) PetscCall(PetscFEIntegrateBdJacobian(ds, wf, PETSCFE_JACOBIAN, key, Ne, chunkGeom, u, u_t, dsAux, a, t, X_tShift, elemMat));
6028be62b2b4SMatthew G. Knepley if (hasPrec) PetscCall(PetscFEIntegrateBdJacobian(ds, wf, PETSCFE_JACOBIAN_PRE, key, Ne, chunkGeom, u, u_t, dsAux, a, t, X_tShift, elemMatP));
60293e9753d6SMatthew G. Knepley }
60309566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(fgeom, offset, numFaces, &chunkGeom));
60313e9753d6SMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
603245480ffeSMatthew G. Knepley key.field = fieldI * Nf + fieldJ;
6033be62b2b4SMatthew G. Knepley if (hasJac)
60348e3a54c0SPierre Jolivet PetscCall(PetscFEIntegrateBdJacobian(ds, wf, PETSCFE_JACOBIAN, key, Nr, chunkGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), dsAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, X_tShift, &elemMat[offset * totDim * totDim]));
6035be62b2b4SMatthew G. Knepley if (hasPrec)
60368e3a54c0SPierre Jolivet PetscCall(PetscFEIntegrateBdJacobian(ds, wf, PETSCFE_JACOBIAN_PRE, key, Nr, chunkGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), dsAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, X_tShift, &elemMatP[offset * totDim * totDim]));
60373e9753d6SMatthew G. Knepley }
60389566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(fgeom, offset, numFaces, &chunkGeom));
60393e9753d6SMatthew G. Knepley }
60403e9753d6SMatthew G. Knepley for (face = 0; face < numFaces; ++face) {
60413e9753d6SMatthew G. Knepley const PetscInt point = points[face], *support;
60423e9753d6SMatthew G. Knepley
60433e9753d6SMatthew G. Knepley /* Transform to global basis before insertion in Jacobian */
60449566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(plex, point, &support));
604521a4fad8SMatthew G. Knepley if (hasJac && transform) PetscCall(DMPlexBasisTransformPointTensor_Internal(dm, tdm, tv, support[0], PETSC_TRUE, totDim, &elemMat[face * totDim * totDim]));
604621a4fad8SMatthew G. Knepley if (hasPrec && transform) PetscCall(DMPlexBasisTransformPointTensor_Internal(dm, tdm, tv, support[0], PETSC_TRUE, totDim, &elemMatP[face * totDim * totDim]));
6047be62b2b4SMatthew G. Knepley if (hasPrec) {
6048be62b2b4SMatthew G. Knepley if (hasJac) {
60499566063dSJacob Faibussowitsch if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(point, "BdJacobian", totDim, totDim, &elemMat[face * totDim * totDim]));
605021a4fad8SMatthew G. Knepley PetscCall(DMPlexMatSetClosure_Internal(plex, section, globalSection, mesh->useMatClPerm, Jac, support[0], &elemMat[face * totDim * totDim], ADD_VALUES));
60513e9753d6SMatthew G. Knepley }
6052be62b2b4SMatthew G. Knepley if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(point, "BdJacobian", totDim, totDim, &elemMatP[face * totDim * totDim]));
6053be62b2b4SMatthew G. Knepley PetscCall(DMPlexMatSetClosure_Internal(plex, section, globalSection, mesh->useMatClPerm, JacP, support[0], &elemMatP[face * totDim * totDim], ADD_VALUES));
6054be62b2b4SMatthew G. Knepley } else {
6055be62b2b4SMatthew G. Knepley if (hasJac) {
6056be62b2b4SMatthew G. Knepley if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(point, "BdJacobian", totDim, totDim, &elemMat[face * totDim * totDim]));
605721a4fad8SMatthew G. Knepley PetscCall(DMPlexMatSetClosure_Internal(plex, section, globalSection, mesh->useMatClPerm, Jac, support[0], &elemMat[face * totDim * totDim], ADD_VALUES));
6058be62b2b4SMatthew G. Knepley }
6059be62b2b4SMatthew G. Knepley }
6060be62b2b4SMatthew G. Knepley }
60619566063dSJacob Faibussowitsch PetscCall(DMSNESRestoreFEGeom(coordField, pointIS, qGeom, PETSC_TRUE, &fgeom));
60629566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&qGeom));
60639566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points));
60649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS));
6065be62b2b4SMatthew G. Knepley PetscCall(PetscFree5(u, u_t, elemMat, elemMatP, a));
60663e9753d6SMatthew G. Knepley }
60679566063dSJacob Faibussowitsch if (plex) PetscCall(DMDestroy(&plex));
60689566063dSJacob Faibussowitsch if (plexA) PetscCall(DMDestroy(&plexA));
60693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
60703e9753d6SMatthew G. Knepley }
60713e9753d6SMatthew G. Knepley
6072997bf629SMatthew G. Knepley /*@
6073997bf629SMatthew G. Knepley DMPlexComputeBdJacobianSingle - Compute the local boundary Jacobian
6074997bf629SMatthew G. Knepley
6075997bf629SMatthew G. Knepley Not collective
6076997bf629SMatthew G. Knepley
6077997bf629SMatthew G. Knepley Input Parameters:
6078997bf629SMatthew G. Knepley + dm - The output `DM`
6079997bf629SMatthew G. Knepley . wf - The `PetscWeakForm` holding forms on this boundary
6080997bf629SMatthew G. Knepley . label - The `DMLabel` indicating what faces should be integrated over
6081997bf629SMatthew G. Knepley . numValues - The number of label values
6082997bf629SMatthew G. Knepley . values - The array of label values
6083997bf629SMatthew G. Knepley . fieldI - The test field for these integrals
6084997bf629SMatthew G. Knepley . locX - The local solution
6085997bf629SMatthew G. Knepley . locX_t - The time derivative of the local solution, or `NULL` for time-independent problems
6086997bf629SMatthew G. Knepley . t - The time
6087997bf629SMatthew G. Knepley - X_tShift - The multiplier for dF/dxdot
6088997bf629SMatthew G. Knepley
6089997bf629SMatthew G. Knepley Output Parameters:
6090997bf629SMatthew G. Knepley + Jac - The local Jacobian
6091997bf629SMatthew G. Knepley - JacP - The local Jacobian preconditioner
6092997bf629SMatthew G. Knepley
6093997bf629SMatthew G. Knepley Level: developer
6094997bf629SMatthew G. Knepley
6095997bf629SMatthew G. Knepley .seealso: `DMPlexComputeBdJacobianSingleByLabel()`, `DMPlexComputeJacobianByKey()`, `DMPlexComputeResidualHybridByKey()`, `DMPlexComputeJacobianHybridByKey()`, `PetscFormKey`
6096997bf629SMatthew G. Knepley @*/
DMPlexComputeBdJacobianSingle(DM dm,PetscWeakForm wf,DMLabel label,PetscInt numValues,const PetscInt values[],PetscInt fieldI,Vec locX,Vec locX_t,PetscReal t,PetscReal X_tShift,Mat Jac,Mat JacP)6097997bf629SMatthew G. Knepley PetscErrorCode DMPlexComputeBdJacobianSingle(DM dm, PetscWeakForm wf, DMLabel label, PetscInt numValues, const PetscInt values[], PetscInt fieldI, Vec locX, Vec locX_t, PetscReal t, PetscReal X_tShift, Mat Jac, Mat JacP)
6098d71ae5a4SJacob Faibussowitsch {
60993e9753d6SMatthew G. Knepley DMField coordField;
61003e9753d6SMatthew G. Knepley DMLabel depthLabel;
61013e9753d6SMatthew G. Knepley IS facetIS;
61023e9753d6SMatthew G. Knepley PetscInt dim;
61033e9753d6SMatthew G. Knepley
61043e9753d6SMatthew G. Knepley PetscFunctionBegin;
61059566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
61069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
61079566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(depthLabel, dim - 1, &facetIS));
61089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
6109997bf629SMatthew G. Knepley PetscCall(DMPlexComputeBdJacobianSingleByLabel(dm, wf, label, numValues, values, fieldI, facetIS, locX, locX_t, t, coordField, X_tShift, Jac, JacP));
61109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&facetIS));
61113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
61123e9753d6SMatthew G. Knepley }
61133e9753d6SMatthew G. Knepley
DMPlexComputeBdJacobian_Internal(DM dm,Vec locX,Vec locX_t,PetscReal t,PetscReal X_tShift,Mat Jac,Mat JacP,PetscCtx ctx)6114*2a8381b2SBarry Smith static PetscErrorCode DMPlexComputeBdJacobian_Internal(DM dm, Vec locX, Vec locX_t, PetscReal t, PetscReal X_tShift, Mat Jac, Mat JacP, PetscCtx ctx)
6115d71ae5a4SJacob Faibussowitsch {
61163e9753d6SMatthew G. Knepley PetscDS prob;
61173e9753d6SMatthew G. Knepley PetscInt dim, numBd, bd;
61183e9753d6SMatthew G. Knepley DMLabel depthLabel;
61193e9753d6SMatthew G. Knepley DMField coordField = NULL;
61203e9753d6SMatthew G. Knepley IS facetIS;
61213e9753d6SMatthew G. Knepley
61223e9753d6SMatthew G. Knepley PetscFunctionBegin;
61239566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob));
61249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
61259566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim));
61269566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(depthLabel, dim - 1, &facetIS));
61279566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumBoundary(prob, &numBd));
61289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
61293e9753d6SMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) {
613045480ffeSMatthew G. Knepley PetscWeakForm wf;
61313e9753d6SMatthew G. Knepley DMBoundaryConditionType type;
61323e9753d6SMatthew G. Knepley DMLabel label;
61333e9753d6SMatthew G. Knepley const PetscInt *values;
61343e9753d6SMatthew G. Knepley PetscInt fieldI, numValues;
61353e9753d6SMatthew G. Knepley PetscObject obj;
61363e9753d6SMatthew G. Knepley PetscClassId id;
61373e9753d6SMatthew G. Knepley
61389566063dSJacob Faibussowitsch PetscCall(PetscDSGetBoundary(prob, bd, &wf, &type, NULL, &label, &numValues, &values, &fieldI, NULL, NULL, NULL, NULL, NULL));
61393d3e5d66SMatthew G. Knepley if (type & DM_BC_ESSENTIAL) continue;
61409566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, fieldI, &obj));
61419566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id));
61423d3e5d66SMatthew G. Knepley if (id != PETSCFE_CLASSID) continue;
6143997bf629SMatthew G. Knepley PetscCall(DMPlexComputeBdJacobianSingleByLabel(dm, wf, label, numValues, values, fieldI, facetIS, locX, locX_t, t, coordField, X_tShift, Jac, JacP));
61443e9753d6SMatthew G. Knepley }
61459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&facetIS));
61463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
61473e9753d6SMatthew G. Knepley }
61483e9753d6SMatthew G. Knepley
6149754e4fbaSMatthew G. Knepley /*@
6150754e4fbaSMatthew G. Knepley DMPlexComputeJacobianByKey - Compute the local Jacobian for terms matching the input key
6151754e4fbaSMatthew G. Knepley
6152754e4fbaSMatthew G. Knepley Collective
6153754e4fbaSMatthew G. Knepley
6154754e4fbaSMatthew G. Knepley Input Parameters:
6155754e4fbaSMatthew G. Knepley + dm - The output `DM`
6156754e4fbaSMatthew G. Knepley . key - The `PetscFormKey` indicating what should be integrated
6157754e4fbaSMatthew G. Knepley . cellIS - The `IS` give a set of cells to integrate over
6158754e4fbaSMatthew G. Knepley . t - The time
6159754e4fbaSMatthew G. Knepley . X_tShift - The multiplier for the Jacobian with respect to $X_t$
6160754e4fbaSMatthew G. Knepley . locX - The local solution
6161754e4fbaSMatthew G. Knepley . locX_t - The time derivative of the local solution, or `NULL` for time-independent problems
6162*2a8381b2SBarry Smith - ctx - An optional application context, passed to the pointwise functions
6163754e4fbaSMatthew G. Knepley
6164754e4fbaSMatthew G. Knepley Output Parameters:
6165754e4fbaSMatthew G. Knepley + Jac - The local Jacobian
6166754e4fbaSMatthew G. Knepley - JacP - The local Jacobian preconditioner
6167754e4fbaSMatthew G. Knepley
6168754e4fbaSMatthew G. Knepley Level: developer
6169754e4fbaSMatthew G. Knepley
6170754e4fbaSMatthew G. Knepley .seealso: `DMPlexComputeResidualByKey()`, `DMPlexComputeResidualHybridByKey()`, `DMPlexComputeJacobianHybridByKey()`, `PetscFormKey`
6171754e4fbaSMatthew G. Knepley @*/
DMPlexComputeJacobianByKey(DM dm,PetscFormKey key,IS cellIS,PetscReal t,PetscReal X_tShift,Vec locX,Vec locX_t,Mat Jac,Mat JacP,PetscCtx ctx)6172*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeJacobianByKey(DM dm, PetscFormKey key, IS cellIS, PetscReal t, PetscReal X_tShift, Vec locX, Vec locX_t, Mat Jac, Mat JacP, PetscCtx ctx)
6173d71ae5a4SJacob Faibussowitsch {
61743e9753d6SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
61753e9753d6SMatthew G. Knepley const char *name = "Jacobian";
61769a2a23afSMatthew G. Knepley DM dmAux = NULL, plex, tdm;
61773e9753d6SMatthew G. Knepley DMEnclosureType encAux;
61783e9753d6SMatthew G. Knepley Vec A, tv;
61793e9753d6SMatthew G. Knepley DMField coordField;
61803e9753d6SMatthew G. Knepley PetscDS prob, probAux = NULL;
6181e432b41dSStefano Zampini PetscSection section, globalSection, sectionAux;
61823e9753d6SMatthew G. Knepley PetscScalar *elemMat, *elemMatP, *elemMatD, *u, *u_t, *a = NULL;
61833e9753d6SMatthew G. Knepley const PetscInt *cells;
61843e9753d6SMatthew G. Knepley PetscInt Nf, fieldI, fieldJ;
618528351e22SJed Brown PetscInt totDim, totDimAux = 0, cStart, cEnd, numCells, c;
6186e04ae0b4SMatthew G. Knepley PetscBool hasJac = PETSC_FALSE, hasPrec = PETSC_FALSE, hasDyn, hasFV = PETSC_FALSE, transform;
61873e9753d6SMatthew G. Knepley
61883e9753d6SMatthew G. Knepley PetscFunctionBegin;
6189af18b51aSmarkadams4 PetscCall(PetscLogEventBegin(DMPLEX_JacobianFEM, dm, 0, 0, 0));
6190ae3cf2c1SStefano Zampini PetscCall(DMGetLocalSection(dm, §ion));
6191ae3cf2c1SStefano Zampini PetscCall(DMGetGlobalSection(dm, &globalSection));
6192ae3cf2c1SStefano Zampini PetscCall(DMGetAuxiliaryVec(dm, key.label, key.value, key.part, &A));
6193ae3cf2c1SStefano Zampini if (A) {
6194ae3cf2c1SStefano Zampini PetscCall(VecGetDM(A, &dmAux));
6195ae3cf2c1SStefano Zampini PetscCall(DMGetEnclosureRelation(dmAux, dm, &encAux));
6196ae3cf2c1SStefano Zampini PetscCall(DMConvert(dmAux, DMPLEX, &plex));
6197ae3cf2c1SStefano Zampini PetscCall(DMGetLocalSection(plex, §ionAux));
6198ae3cf2c1SStefano Zampini PetscCall(DMGetDS(dmAux, &probAux));
6199ae3cf2c1SStefano Zampini PetscCall(PetscDSGetTotalDimension(probAux, &totDimAux));
6200ae3cf2c1SStefano Zampini }
6201ae3cf2c1SStefano Zampini PetscCall(DMGetCoordinateField(dm, &coordField));
6202e04ae0b4SMatthew G. Knepley if (!cellIS) goto end;
62039566063dSJacob Faibussowitsch PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
6204437e83fbSMatthew G. Knepley PetscCall(ISGetLocalSize(cellIS, &numCells));
6205437e83fbSMatthew G. Knepley if (cStart >= cEnd) goto end;
62069566063dSJacob Faibussowitsch PetscCall(DMHasBasisTransform(dm, &transform));
62079566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformDM_Internal(dm, &tdm));
62089566063dSJacob Faibussowitsch PetscCall(DMGetBasisTransformVec_Internal(dm, &tv));
620907218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dm, cells ? cells[cStart] : cStart, &prob, NULL));
62109566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf));
62119566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim));
62129566063dSJacob Faibussowitsch PetscCall(PetscDSHasJacobian(prob, &hasJac));
62139566063dSJacob Faibussowitsch PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
62143e9753d6SMatthew G. Knepley /* user passed in the same matrix, avoid double contributions and
62153e9753d6SMatthew G. Knepley only assemble the Jacobian */
62163e9753d6SMatthew G. Knepley if (hasJac && Jac == JacP) hasPrec = PETSC_FALSE;
62179566063dSJacob Faibussowitsch PetscCall(PetscDSHasDynamicJacobian(prob, &hasDyn));
62183e9753d6SMatthew G. Knepley hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE;
6219754e4fbaSMatthew G. Knepley PetscCall(PetscMalloc5(numCells * totDim, &u, (locX_t ? (size_t)numCells * totDim : 0), &u_t, (hasJac ? (size_t)numCells * totDim * totDim : 0), &elemMat, (hasPrec ? (size_t)numCells * totDim * totDim : 0), &elemMatP, (hasDyn ? (size_t)numCells * totDim * totDim : 0), &elemMatD));
62209566063dSJacob Faibussowitsch if (dmAux) PetscCall(PetscMalloc1(numCells * totDimAux, &a));
62213e9753d6SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
62223e9753d6SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
62233e9753d6SMatthew G. Knepley const PetscInt cind = c - cStart;
62243e9753d6SMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL;
62253e9753d6SMatthew G. Knepley PetscInt i;
62263e9753d6SMatthew G. Knepley
6227754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecGetClosure(dm, section, locX, cell, NULL, &x));
62283e9753d6SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[cind * totDim + i] = x[i];
6229754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(dm, section, locX, cell, NULL, &x));
6230754e4fbaSMatthew G. Knepley if (locX_t) {
6231754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecGetClosure(dm, section, locX_t, cell, NULL, &x_t));
62323e9753d6SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[cind * totDim + i] = x_t[i];
6233754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(dm, section, locX_t, cell, NULL, &x_t));
62343e9753d6SMatthew G. Knepley }
62353e9753d6SMatthew G. Knepley if (dmAux) {
62363e9753d6SMatthew G. Knepley PetscInt subcell;
62379566063dSJacob Faibussowitsch PetscCall(DMGetEnclosurePoint(dmAux, dm, encAux, cell, &subcell));
62389566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plex, sectionAux, A, subcell, NULL, &x));
62393e9753d6SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[cind * totDimAux + i] = x[i];
62409566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plex, sectionAux, A, subcell, NULL, &x));
62413e9753d6SMatthew G. Knepley }
62423e9753d6SMatthew G. Knepley }
62439566063dSJacob Faibussowitsch if (hasJac) PetscCall(PetscArrayzero(elemMat, numCells * totDim * totDim));
62449566063dSJacob Faibussowitsch if (hasPrec) PetscCall(PetscArrayzero(elemMatP, numCells * totDim * totDim));
62459566063dSJacob Faibussowitsch if (hasDyn) PetscCall(PetscArrayzero(elemMatD, numCells * totDim * totDim));
62463e9753d6SMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) {
62473e9753d6SMatthew G. Knepley PetscClassId id;
62483e9753d6SMatthew G. Knepley PetscFE fe;
62493e9753d6SMatthew G. Knepley PetscQuadrature qGeom = NULL;
62503e9753d6SMatthew G. Knepley PetscInt Nb;
62513e9753d6SMatthew G. Knepley /* Conforming batches */
62523e9753d6SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
62533e9753d6SMatthew G. Knepley /* Remainder */
62543e9753d6SMatthew G. Knepley PetscInt Nr, offset, Nq;
62553e9753d6SMatthew G. Knepley PetscInt maxDegree;
62563e9753d6SMatthew G. Knepley PetscFEGeom *cgeomFEM, *chunkGeom = NULL, *remGeom = NULL;
62573e9753d6SMatthew G. Knepley
62589566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, fieldI, (PetscObject *)&fe));
62599566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
62609371c9d4SSatish Balay if (id == PETSCFV_CLASSID) {
62619371c9d4SSatish Balay hasFV = PETSC_TRUE;
62629371c9d4SSatish Balay continue;
62639371c9d4SSatish Balay }
62649566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
62659566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
62669566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, cellIS, NULL, &maxDegree));
626748a46eb9SPierre Jolivet if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, cellIS, &qGeom));
62683e9753d6SMatthew G. Knepley if (!qGeom) {
62699566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &qGeom));
62709566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)qGeom));
62713e9753d6SMatthew G. Knepley }
62729566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL));
6273ac9d17c7SMatthew G. Knepley PetscCall(DMSNESGetFEGeom(coordField, cellIS, qGeom, PETSC_FEGEOM_BASIC, &cgeomFEM));
62743e9753d6SMatthew G. Knepley blockSize = Nb;
62753e9753d6SMatthew G. Knepley batchSize = numBlocks * blockSize;
62769566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
62773e9753d6SMatthew G. Knepley numChunks = numCells / (numBatches * batchSize);
62783e9753d6SMatthew G. Knepley Ne = numChunks * numBatches * batchSize;
62793e9753d6SMatthew G. Knepley Nr = numCells % (numBatches * batchSize);
62803e9753d6SMatthew G. Knepley offset = numCells - Nr;
62819566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(cgeomFEM, 0, offset, &chunkGeom));
62829566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(cgeomFEM, offset, numCells, &remGeom));
62833e9753d6SMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
62846528b96dSMatthew G. Knepley key.field = fieldI * Nf + fieldJ;
62853e9753d6SMatthew G. Knepley if (hasJac) {
62864561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN, key, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat));
62874561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN, key, Nr, remGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), probAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, X_tShift, &elemMat[offset * totDim * totDim]));
62883e9753d6SMatthew G. Knepley }
62893e9753d6SMatthew G. Knepley if (hasPrec) {
62904561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN_PRE, key, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatP));
62914561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN_PRE, key, Nr, remGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), probAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, X_tShift, &elemMatP[offset * totDim * totDim]));
62923e9753d6SMatthew G. Knepley }
62933e9753d6SMatthew G. Knepley if (hasDyn) {
62944561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN_DYN, key, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatD));
62954561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN_DYN, key, Nr, remGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), probAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, X_tShift, &elemMatD[offset * totDim * totDim]));
62963e9753d6SMatthew G. Knepley }
62973e9753d6SMatthew G. Knepley }
62989566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(cgeomFEM, offset, numCells, &remGeom));
62999566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(cgeomFEM, 0, offset, &chunkGeom));
63009566063dSJacob Faibussowitsch PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, qGeom, PETSC_FALSE, &cgeomFEM));
63019566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&qGeom));
63023e9753d6SMatthew G. Knepley }
63033e9753d6SMatthew G. Knepley /* Add contribution from X_t */
63049371c9d4SSatish Balay if (hasDyn) {
63059371c9d4SSatish Balay for (c = 0; c < numCells * totDim * totDim; ++c) elemMat[c] += X_tShift * elemMatD[c];
63069371c9d4SSatish Balay }
63073e9753d6SMatthew G. Knepley if (hasFV) {
63083e9753d6SMatthew G. Knepley PetscClassId id;
63093e9753d6SMatthew G. Knepley PetscFV fv;
63103e9753d6SMatthew G. Knepley PetscInt offsetI, NcI, NbI = 1, fc, f;
63113e9753d6SMatthew G. Knepley
63123e9753d6SMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) {
63139566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, fieldI, (PetscObject *)&fv));
63149566063dSJacob Faibussowitsch PetscCall(PetscDSGetFieldOffset(prob, fieldI, &offsetI));
63159566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId((PetscObject)fv, &id));
63163e9753d6SMatthew G. Knepley if (id != PETSCFV_CLASSID) continue;
63172f86f8c5SMatthew G. Knepley /* Put in the weighted identity */
63189566063dSJacob Faibussowitsch PetscCall(PetscFVGetNumComponents(fv, &NcI));
63193e9753d6SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
63203e9753d6SMatthew G. Knepley const PetscInt cind = c - cStart;
63213e9753d6SMatthew G. Knepley const PetscInt eOffset = cind * totDim * totDim;
63222f86f8c5SMatthew G. Knepley PetscReal vol;
63232f86f8c5SMatthew G. Knepley
63242f86f8c5SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
63253e9753d6SMatthew G. Knepley for (fc = 0; fc < NcI; ++fc) {
63263e9753d6SMatthew G. Knepley for (f = 0; f < NbI; ++f) {
63273e9753d6SMatthew G. Knepley const PetscInt i = offsetI + f * NcI + fc;
63283e9753d6SMatthew G. Knepley if (hasPrec) {
63292f86f8c5SMatthew G. Knepley if (hasJac) elemMat[eOffset + i * totDim + i] = vol;
63302f86f8c5SMatthew G. Knepley elemMatP[eOffset + i * totDim + i] = vol;
63319371c9d4SSatish Balay } else {
63322f86f8c5SMatthew G. Knepley elemMat[eOffset + i * totDim + i] = vol;
63339371c9d4SSatish Balay }
63343e9753d6SMatthew G. Knepley }
63353e9753d6SMatthew G. Knepley }
63363e9753d6SMatthew G. Knepley }
63373e9753d6SMatthew G. Knepley }
63383e9753d6SMatthew G. Knepley /* No allocated space for FV stuff, so ignore the zero entries */
63399566063dSJacob Faibussowitsch PetscCall(MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE));
63403e9753d6SMatthew G. Knepley }
63413e9753d6SMatthew G. Knepley /* Insert values into matrix */
63423e9753d6SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
63433e9753d6SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
63443e9753d6SMatthew G. Knepley const PetscInt cind = c - cStart;
63453e9753d6SMatthew G. Knepley
63463e9753d6SMatthew G. Knepley /* Transform to global basis before insertion in Jacobian */
63479566063dSJacob Faibussowitsch if (transform) PetscCall(DMPlexBasisTransformPointTensor_Internal(dm, tdm, tv, cell, PETSC_TRUE, totDim, &elemMat[cind * totDim * totDim]));
63483e9753d6SMatthew G. Knepley if (hasPrec) {
63493e9753d6SMatthew G. Knepley if (hasJac) {
63509566063dSJacob Faibussowitsch if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, totDim, totDim, &elemMat[cind * totDim * totDim]));
6351e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, mesh->useMatClPerm, Jac, cell, &elemMat[cind * totDim * totDim], ADD_VALUES));
63523e9753d6SMatthew G. Knepley }
63539566063dSJacob Faibussowitsch if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, totDim, totDim, &elemMatP[cind * totDim * totDim]));
6354be62b2b4SMatthew G. Knepley PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, mesh->useMatClPerm, JacP, cell, &elemMatP[cind * totDim * totDim], ADD_VALUES));
63553e9753d6SMatthew G. Knepley } else {
63563e9753d6SMatthew G. Knepley if (hasJac) {
63579566063dSJacob Faibussowitsch if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, totDim, totDim, &elemMat[cind * totDim * totDim]));
6358e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, mesh->useMatClPerm, JacP, cell, &elemMat[cind * totDim * totDim], ADD_VALUES));
63593e9753d6SMatthew G. Knepley }
63603e9753d6SMatthew G. Knepley }
63613e9753d6SMatthew G. Knepley }
63629566063dSJacob Faibussowitsch PetscCall(ISRestorePointRange(cellIS, &cStart, &cEnd, &cells));
63639566063dSJacob Faibussowitsch if (hasFV) PetscCall(MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_FALSE));
63649566063dSJacob Faibussowitsch PetscCall(PetscFree5(u, u_t, elemMat, elemMatP, elemMatD));
6365d9302694SMatthew G. Knepley if (dmAux) PetscCall(PetscFree(a));
63663e9753d6SMatthew G. Knepley /* Compute boundary integrals */
6367*2a8381b2SBarry Smith PetscCall(DMPlexComputeBdJacobian_Internal(dm, locX, locX_t, t, X_tShift, Jac, JacP, ctx));
63683e9753d6SMatthew G. Knepley /* Assemble matrix */
63699371c9d4SSatish Balay end: {
6370e04ae0b4SMatthew G. Knepley PetscBool assOp = hasJac && hasPrec ? PETSC_TRUE : PETSC_FALSE, gassOp;
6371e04ae0b4SMatthew G. Knepley
6372d9302694SMatthew G. Knepley if (dmAux) PetscCall(DMDestroy(&plex));
63735440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&assOp, &gassOp, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
63743e9753d6SMatthew G. Knepley if (hasJac && hasPrec) {
63759566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Jac, MAT_FINAL_ASSEMBLY));
63769566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Jac, MAT_FINAL_ASSEMBLY));
63773e9753d6SMatthew G. Knepley }
6378e04ae0b4SMatthew G. Knepley }
63799566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY));
63809566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY));
63819566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_JacobianFEM, dm, 0, 0, 0));
63823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
63833e9753d6SMatthew G. Knepley }
63843e9753d6SMatthew G. Knepley
DMPlexComputeJacobianByKeyGeneral(DM dmr,DM dmc,PetscFormKey key,IS cellIS,PetscReal t,PetscReal X_tShift,Vec locX,Vec locX_t,Mat Jac,Mat JacP,PetscCtx ctx)6385*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeJacobianByKeyGeneral(DM dmr, DM dmc, PetscFormKey key, IS cellIS, PetscReal t, PetscReal X_tShift, Vec locX, Vec locX_t, Mat Jac, Mat JacP, PetscCtx ctx)
63864561e6c9SMatthew G. Knepley {
63874561e6c9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmr->data;
63884561e6c9SMatthew G. Knepley const char *name = "Jacobian";
63894561e6c9SMatthew G. Knepley DM dmAux = NULL, plex, tdm;
63904561e6c9SMatthew G. Knepley PetscInt printFEM = mesh->printFEM;
63914561e6c9SMatthew G. Knepley PetscBool clPerm = mesh->useMatClPerm;
63924561e6c9SMatthew G. Knepley DMEnclosureType encAux;
63934561e6c9SMatthew G. Knepley Vec A, tv;
63944561e6c9SMatthew G. Knepley DMField coordField;
63954561e6c9SMatthew G. Knepley PetscDS rds, cds, dsAux = NULL;
63964561e6c9SMatthew G. Knepley PetscSection rsection, rglobalSection, csection, cglobalSection, sectionAux;
63974561e6c9SMatthew G. Knepley PetscScalar *elemMat, *elemMatP, *elemMatD, *u, *u_t, *a = NULL;
63984561e6c9SMatthew G. Knepley const PetscInt *cells;
63994561e6c9SMatthew G. Knepley PetscInt Nf, cNf;
64004561e6c9SMatthew G. Knepley PetscInt totDim, ctotDim, totDimAux = 0, cStart, cEnd, numCells;
64014561e6c9SMatthew G. Knepley PetscBool hasJac = PETSC_FALSE, hasPrec = PETSC_FALSE, hasDyn, hasFV = PETSC_FALSE, transform;
64024561e6c9SMatthew G. Knepley MPI_Comm comm;
64034561e6c9SMatthew G. Knepley
64044561e6c9SMatthew G. Knepley PetscFunctionBegin;
64054561e6c9SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dmr, &comm));
64064561e6c9SMatthew G. Knepley PetscCall(PetscLogEventBegin(DMPLEX_JacobianFEM, dmr, 0, 0, 0));
64074561e6c9SMatthew G. Knepley PetscCall(DMGetLocalSection(dmr, &rsection));
64084561e6c9SMatthew G. Knepley PetscCall(DMGetGlobalSection(dmr, &rglobalSection));
64094561e6c9SMatthew G. Knepley PetscCall(DMGetLocalSection(dmc, &csection));
64104561e6c9SMatthew G. Knepley PetscCall(DMGetGlobalSection(dmc, &cglobalSection));
64114561e6c9SMatthew G. Knepley PetscCall(DMGetAuxiliaryVec(dmr, key.label, key.value, key.part, &A));
64124561e6c9SMatthew G. Knepley if (A) {
64134561e6c9SMatthew G. Knepley PetscCall(VecGetDM(A, &dmAux));
64144561e6c9SMatthew G. Knepley PetscCall(DMGetEnclosureRelation(dmAux, dmr, &encAux));
64154561e6c9SMatthew G. Knepley PetscCall(DMConvert(dmAux, DMPLEX, &plex));
64164561e6c9SMatthew G. Knepley PetscCall(DMGetLocalSection(plex, §ionAux));
64174561e6c9SMatthew G. Knepley PetscCall(DMGetDS(dmAux, &dsAux));
64184561e6c9SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsAux, &totDimAux));
64194561e6c9SMatthew G. Knepley }
64204561e6c9SMatthew G. Knepley PetscCall(DMGetCoordinateField(dmr, &coordField));
64214561e6c9SMatthew G. Knepley if (!cellIS) goto end;
64224561e6c9SMatthew G. Knepley PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
64234561e6c9SMatthew G. Knepley PetscCall(ISGetLocalSize(cellIS, &numCells));
64244561e6c9SMatthew G. Knepley if (cStart >= cEnd) goto end;
64254561e6c9SMatthew G. Knepley PetscCall(DMHasBasisTransform(dmr, &transform));
64264561e6c9SMatthew G. Knepley PetscCall(DMGetBasisTransformDM_Internal(dmr, &tdm));
64274561e6c9SMatthew G. Knepley PetscCall(DMGetBasisTransformVec_Internal(dmr, &tv));
64284561e6c9SMatthew G. Knepley PetscCall(DMGetCellDS(dmr, cells ? cells[cStart] : cStart, &rds, NULL));
64294561e6c9SMatthew G. Knepley PetscCall(DMGetCellDS(dmc, cells ? cells[cStart] : cStart, &cds, NULL));
64304561e6c9SMatthew G. Knepley PetscCall(PetscDSGetNumFields(rds, &Nf));
64314561e6c9SMatthew G. Knepley PetscCall(PetscDSGetNumFields(cds, &cNf));
64324561e6c9SMatthew G. Knepley PetscCheck(Nf == cNf, comm, PETSC_ERR_ARG_WRONG, "Number of row fields %" PetscInt_FMT " != %" PetscInt_FMT " number of columns field", Nf, cNf);
64334561e6c9SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(rds, &totDim));
64344561e6c9SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(cds, &ctotDim));
64354561e6c9SMatthew G. Knepley PetscCall(PetscDSHasJacobian(rds, &hasJac));
64364561e6c9SMatthew G. Knepley PetscCall(PetscDSHasJacobianPreconditioner(rds, &hasPrec));
64374561e6c9SMatthew G. Knepley /* user passed in the same matrix, avoid double contributions and
64384561e6c9SMatthew G. Knepley only assemble the Jacobian */
64394561e6c9SMatthew G. Knepley if (hasJac && Jac == JacP) hasPrec = PETSC_FALSE;
64404561e6c9SMatthew G. Knepley PetscCall(PetscDSHasDynamicJacobian(rds, &hasDyn));
64414561e6c9SMatthew G. Knepley hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE;
64424561e6c9SMatthew G. Knepley PetscCall(PetscMalloc5(numCells * totDim, &u, (locX_t ? (size_t)numCells * totDim : 0), &u_t, (hasJac ? (size_t)numCells * totDim * ctotDim : 0), &elemMat, (hasPrec ? (size_t)numCells * totDim * ctotDim : 0), &elemMatP, (hasDyn ? (size_t)numCells * totDim * ctotDim : 0), &elemMatD));
64434561e6c9SMatthew G. Knepley if (dmAux) PetscCall(PetscMalloc1(numCells * totDimAux, &a));
64444561e6c9SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
64454561e6c9SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
64464561e6c9SMatthew G. Knepley const PetscInt cind = c - cStart;
64474561e6c9SMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL;
64484561e6c9SMatthew G. Knepley PetscInt i;
64494561e6c9SMatthew G. Knepley
64504561e6c9SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(dmr, rsection, locX, cell, NULL, &x));
64514561e6c9SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[cind * totDim + i] = x[i];
64524561e6c9SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(dmr, rsection, locX, cell, NULL, &x));
64534561e6c9SMatthew G. Knepley if (locX_t) {
64544561e6c9SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(dmr, rsection, locX_t, cell, NULL, &x_t));
64554561e6c9SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[cind * totDim + i] = x_t[i];
64564561e6c9SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(dmr, rsection, locX_t, cell, NULL, &x_t));
64574561e6c9SMatthew G. Knepley }
64584561e6c9SMatthew G. Knepley if (dmAux) {
64594561e6c9SMatthew G. Knepley PetscInt subcell;
64604561e6c9SMatthew G. Knepley PetscCall(DMGetEnclosurePoint(dmAux, dmr, encAux, cell, &subcell));
64614561e6c9SMatthew G. Knepley PetscCall(DMPlexVecGetClosure(plex, sectionAux, A, subcell, NULL, &x));
64624561e6c9SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[cind * totDimAux + i] = x[i];
64634561e6c9SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(plex, sectionAux, A, subcell, NULL, &x));
64644561e6c9SMatthew G. Knepley }
64654561e6c9SMatthew G. Knepley }
64664561e6c9SMatthew G. Knepley if (hasJac) PetscCall(PetscArrayzero(elemMat, numCells * totDim * ctotDim));
64674561e6c9SMatthew G. Knepley if (hasPrec) PetscCall(PetscArrayzero(elemMatP, numCells * totDim * ctotDim));
64684561e6c9SMatthew G. Knepley if (hasDyn) PetscCall(PetscArrayzero(elemMatD, numCells * totDim * ctotDim));
64694561e6c9SMatthew G. Knepley for (PetscInt fieldI = 0; fieldI < Nf; ++fieldI) {
64704561e6c9SMatthew G. Knepley PetscClassId id;
64714561e6c9SMatthew G. Knepley PetscFE fe;
64724561e6c9SMatthew G. Knepley PetscQuadrature qGeom = NULL;
64734561e6c9SMatthew G. Knepley PetscInt Nb;
64744561e6c9SMatthew G. Knepley /* Conforming batches */
64754561e6c9SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
64764561e6c9SMatthew G. Knepley /* Remainder */
64774561e6c9SMatthew G. Knepley PetscInt Nr, offset, Nq;
64784561e6c9SMatthew G. Knepley PetscInt maxDegree;
64794561e6c9SMatthew G. Knepley PetscFEGeom *cgeomFEM, *chunkGeom = NULL, *remGeom = NULL;
64804561e6c9SMatthew G. Knepley
64814561e6c9SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(rds, fieldI, (PetscObject *)&fe));
64824561e6c9SMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
64834561e6c9SMatthew G. Knepley if (id == PETSCFV_CLASSID) {
64844561e6c9SMatthew G. Knepley hasFV = PETSC_TRUE;
64854561e6c9SMatthew G. Knepley continue;
64864561e6c9SMatthew G. Knepley }
64874561e6c9SMatthew G. Knepley PetscCall(PetscFEGetDimension(fe, &Nb));
64884561e6c9SMatthew G. Knepley PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
64894561e6c9SMatthew G. Knepley PetscCall(DMFieldGetDegree(coordField, cellIS, NULL, &maxDegree));
64904561e6c9SMatthew G. Knepley if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, cellIS, &qGeom));
64914561e6c9SMatthew G. Knepley if (!qGeom) {
64924561e6c9SMatthew G. Knepley PetscCall(PetscFEGetQuadrature(fe, &qGeom));
64934561e6c9SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)qGeom));
64944561e6c9SMatthew G. Knepley }
64954561e6c9SMatthew G. Knepley PetscCall(PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL));
64964561e6c9SMatthew G. Knepley PetscCall(DMSNESGetFEGeom(coordField, cellIS, qGeom, PETSC_FEGEOM_BASIC, &cgeomFEM));
64974561e6c9SMatthew G. Knepley blockSize = Nb;
64984561e6c9SMatthew G. Knepley batchSize = numBlocks * blockSize;
64994561e6c9SMatthew G. Knepley PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
65004561e6c9SMatthew G. Knepley numChunks = numCells / (numBatches * batchSize);
65014561e6c9SMatthew G. Knepley Ne = numChunks * numBatches * batchSize;
65024561e6c9SMatthew G. Knepley Nr = numCells % (numBatches * batchSize);
65034561e6c9SMatthew G. Knepley offset = numCells - Nr;
65044561e6c9SMatthew G. Knepley PetscCall(PetscFEGeomGetChunk(cgeomFEM, 0, offset, &chunkGeom));
65054561e6c9SMatthew G. Knepley PetscCall(PetscFEGeomGetChunk(cgeomFEM, offset, numCells, &remGeom));
65064561e6c9SMatthew G. Knepley for (PetscInt fieldJ = 0; fieldJ < Nf; ++fieldJ) {
65074561e6c9SMatthew G. Knepley key.field = fieldI * Nf + fieldJ;
65084561e6c9SMatthew G. Knepley if (hasJac) {
65094561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(rds, cds, PETSCFE_JACOBIAN, key, Ne, chunkGeom, u, u_t, dsAux, a, t, X_tShift, elemMat));
65104561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(rds, cds, PETSCFE_JACOBIAN, key, Nr, remGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), dsAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, X_tShift, &elemMat[offset * totDim * ctotDim]));
65114561e6c9SMatthew G. Knepley }
65124561e6c9SMatthew G. Knepley if (hasPrec) {
65134561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(rds, cds, PETSCFE_JACOBIAN_PRE, key, Ne, chunkGeom, u, u_t, dsAux, a, t, X_tShift, elemMatP));
65144561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(rds, cds, PETSCFE_JACOBIAN_PRE, key, Nr, remGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), dsAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, X_tShift, &elemMatP[offset * totDim * ctotDim]));
65154561e6c9SMatthew G. Knepley }
65164561e6c9SMatthew G. Knepley if (hasDyn) {
65174561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(rds, cds, PETSCFE_JACOBIAN_DYN, key, Ne, chunkGeom, u, u_t, dsAux, a, t, X_tShift, elemMatD));
65184561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(rds, cds, PETSCFE_JACOBIAN_DYN, key, Nr, remGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), dsAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, X_tShift, &elemMatD[offset * totDim * ctotDim]));
65194561e6c9SMatthew G. Knepley }
65204561e6c9SMatthew G. Knepley }
65214561e6c9SMatthew G. Knepley PetscCall(PetscFEGeomRestoreChunk(cgeomFEM, offset, numCells, &remGeom));
65224561e6c9SMatthew G. Knepley PetscCall(PetscFEGeomRestoreChunk(cgeomFEM, 0, offset, &chunkGeom));
65234561e6c9SMatthew G. Knepley PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, qGeom, PETSC_FALSE, &cgeomFEM));
65244561e6c9SMatthew G. Knepley PetscCall(PetscQuadratureDestroy(&qGeom));
65254561e6c9SMatthew G. Knepley }
65264561e6c9SMatthew G. Knepley /* Add contribution from X_t */
65274561e6c9SMatthew G. Knepley if (hasDyn) {
65284561e6c9SMatthew G. Knepley for (PetscInt c = 0; c < numCells * totDim * ctotDim; ++c) elemMat[c] += X_tShift * elemMatD[c];
65294561e6c9SMatthew G. Knepley }
65304561e6c9SMatthew G. Knepley if (hasFV) {
65314561e6c9SMatthew G. Knepley PetscClassId id;
65324561e6c9SMatthew G. Knepley PetscFV fv;
65334561e6c9SMatthew G. Knepley PetscInt offsetI, NcI, NbI = 1;
65344561e6c9SMatthew G. Knepley
65354561e6c9SMatthew G. Knepley for (PetscInt fieldI = 0; fieldI < Nf; ++fieldI) {
65364561e6c9SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(rds, fieldI, (PetscObject *)&fv));
65374561e6c9SMatthew G. Knepley PetscCall(PetscDSGetFieldOffset(rds, fieldI, &offsetI));
65384561e6c9SMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fv, &id));
65394561e6c9SMatthew G. Knepley if (id != PETSCFV_CLASSID) continue;
65404561e6c9SMatthew G. Knepley /* Put in the weighted identity */
65414561e6c9SMatthew G. Knepley PetscCall(PetscFVGetNumComponents(fv, &NcI));
65424561e6c9SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
65434561e6c9SMatthew G. Knepley const PetscInt cind = c - cStart;
65444561e6c9SMatthew G. Knepley const PetscInt eOffset = cind * totDim * ctotDim;
65454561e6c9SMatthew G. Knepley PetscReal vol;
65464561e6c9SMatthew G. Knepley
65474561e6c9SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(dmr, c, &vol, NULL, NULL));
65484561e6c9SMatthew G. Knepley for (PetscInt fc = 0; fc < NcI; ++fc) {
65494561e6c9SMatthew G. Knepley for (PetscInt f = 0; f < NbI; ++f) {
65504561e6c9SMatthew G. Knepley const PetscInt i = offsetI + f * NcI + fc;
65514561e6c9SMatthew G. Knepley if (hasPrec) {
65524561e6c9SMatthew G. Knepley if (hasJac) elemMat[eOffset + i * ctotDim + i] = vol;
65534561e6c9SMatthew G. Knepley elemMatP[eOffset + i * ctotDim + i] = vol;
65544561e6c9SMatthew G. Knepley } else {
65554561e6c9SMatthew G. Knepley elemMat[eOffset + i * ctotDim + i] = vol;
65564561e6c9SMatthew G. Knepley }
65574561e6c9SMatthew G. Knepley }
65584561e6c9SMatthew G. Knepley }
65594561e6c9SMatthew G. Knepley }
65604561e6c9SMatthew G. Knepley }
65614561e6c9SMatthew G. Knepley /* No allocated space for FV stuff, so ignore the zero entries */
65624561e6c9SMatthew G. Knepley PetscCall(MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE));
65634561e6c9SMatthew G. Knepley }
65644561e6c9SMatthew G. Knepley /* Insert values into matrix */
65654561e6c9SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) {
65664561e6c9SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
65674561e6c9SMatthew G. Knepley const PetscInt cind = c - cStart;
65684561e6c9SMatthew G. Knepley
65694561e6c9SMatthew G. Knepley /* Transform to global basis before insertion in Jacobian */
65704561e6c9SMatthew G. Knepley if (transform) PetscCall(DMPlexBasisTransformPointTensor_Internal(dmr, tdm, tv, cell, PETSC_TRUE, totDim, &elemMat[cind * totDim * ctotDim]));
65714561e6c9SMatthew G. Knepley if (hasPrec) {
65724561e6c9SMatthew G. Knepley if (hasJac) {
65734561e6c9SMatthew G. Knepley if (printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, totDim, ctotDim, &elemMat[cind * totDim * ctotDim]));
65744561e6c9SMatthew G. Knepley PetscCall(DMPlexMatSetClosureGeneral(dmr, rsection, rglobalSection, clPerm, dmc, csection, cglobalSection, clPerm, Jac, cell, &elemMat[cind * totDim * ctotDim], ADD_VALUES));
65754561e6c9SMatthew G. Knepley }
65764561e6c9SMatthew G. Knepley if (printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, totDim, ctotDim, &elemMatP[cind * totDim * ctotDim]));
65774561e6c9SMatthew G. Knepley PetscCall(DMPlexMatSetClosureGeneral(dmr, rsection, rglobalSection, clPerm, dmc, csection, cglobalSection, clPerm, JacP, cell, &elemMatP[cind * totDim * ctotDim], ADD_VALUES));
65784561e6c9SMatthew G. Knepley } else {
65794561e6c9SMatthew G. Knepley if (hasJac) {
65804561e6c9SMatthew G. Knepley if (printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, totDim, ctotDim, &elemMat[cind * totDim * ctotDim]));
65814561e6c9SMatthew G. Knepley PetscCall(DMPlexMatSetClosureGeneral(dmr, rsection, rglobalSection, clPerm, dmc, csection, cglobalSection, clPerm, JacP, cell, &elemMat[cind * totDim * ctotDim], ADD_VALUES));
65824561e6c9SMatthew G. Knepley }
65834561e6c9SMatthew G. Knepley }
65844561e6c9SMatthew G. Knepley }
65854561e6c9SMatthew G. Knepley PetscCall(ISRestorePointRange(cellIS, &cStart, &cEnd, &cells));
65864561e6c9SMatthew G. Knepley if (hasFV) PetscCall(MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_FALSE));
65874561e6c9SMatthew G. Knepley PetscCall(PetscFree5(u, u_t, elemMat, elemMatP, elemMatD));
65884561e6c9SMatthew G. Knepley if (dmAux) PetscCall(PetscFree(a));
65894561e6c9SMatthew G. Knepley /* Compute boundary integrals */
6590*2a8381b2SBarry Smith PetscCall(DMPlexComputeBdJacobian_Internal(dmr, locX, locX_t, t, X_tShift, Jac, JacP, ctx));
65914561e6c9SMatthew G. Knepley /* Assemble matrix */
65924561e6c9SMatthew G. Knepley end: {
65934561e6c9SMatthew G. Knepley PetscBool assOp = hasJac && hasPrec ? PETSC_TRUE : PETSC_FALSE, gassOp;
65944561e6c9SMatthew G. Knepley
65954561e6c9SMatthew G. Knepley if (dmAux) PetscCall(DMDestroy(&plex));
65965440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&assOp, &gassOp, 1, MPI_C_BOOL, MPI_LOR, comm));
65974561e6c9SMatthew G. Knepley if (hasJac && hasPrec) {
65984561e6c9SMatthew G. Knepley PetscCall(MatAssemblyBegin(Jac, MAT_FINAL_ASSEMBLY));
65994561e6c9SMatthew G. Knepley PetscCall(MatAssemblyEnd(Jac, MAT_FINAL_ASSEMBLY));
66004561e6c9SMatthew G. Knepley }
66014561e6c9SMatthew G. Knepley }
66024561e6c9SMatthew G. Knepley PetscCall(MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY));
66034561e6c9SMatthew G. Knepley PetscCall(MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY));
66044561e6c9SMatthew G. Knepley PetscCall(PetscLogEventEnd(DMPLEX_JacobianFEM, dmr, 0, 0, 0));
66054561e6c9SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
66064561e6c9SMatthew G. Knepley }
66074561e6c9SMatthew G. Knepley
6608754e4fbaSMatthew G. Knepley /*@
6609754e4fbaSMatthew G. Knepley DMPlexComputeJacobianHybridByKey - Compute the local Jacobian over hybrid cells for terms matching the input key
6610754e4fbaSMatthew G. Knepley
6611754e4fbaSMatthew G. Knepley Collective
6612754e4fbaSMatthew G. Knepley
6613754e4fbaSMatthew G. Knepley Input Parameters:
6614754e4fbaSMatthew G. Knepley + dm - The output `DM`
6615754e4fbaSMatthew G. Knepley . key - The `PetscFormKey` array (left cell, right cell, cohesive cell) indicating what should be integrated
6616754e4fbaSMatthew G. Knepley . cellIS - The `IS` give a set of cells to integrate over
6617754e4fbaSMatthew G. Knepley . t - The time
6618754e4fbaSMatthew G. Knepley . X_tShift - The multiplier for the Jacobian with respect to $X_t$
6619754e4fbaSMatthew G. Knepley . locX - The local solution
6620754e4fbaSMatthew G. Knepley . locX_t - The time derivative of the local solution, or `NULL` for time-independent problems
6621*2a8381b2SBarry Smith - ctx - An optional application context, passed to the pointwise functions
6622754e4fbaSMatthew G. Knepley
6623754e4fbaSMatthew G. Knepley Output Parameters:
6624754e4fbaSMatthew G. Knepley + Jac - The local Jacobian
6625754e4fbaSMatthew G. Knepley - JacP - The local Jacobian preconditioner
6626754e4fbaSMatthew G. Knepley
6627754e4fbaSMatthew G. Knepley Level: developer
6628754e4fbaSMatthew G. Knepley
6629754e4fbaSMatthew G. Knepley .seealso: `DMPlexComputeResidualByKey()`, `DMPlexComputeJacobianByKey()`, `DMPlexComputeResidualHybridByKey()`, `PetscFormKey`
6630754e4fbaSMatthew G. Knepley @*/
DMPlexComputeJacobianHybridByKey(DM dm,PetscFormKey key[],IS cellIS,PetscReal t,PetscReal X_tShift,Vec locX,Vec locX_t,Mat Jac,Mat JacP,PetscCtx ctx)6631*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeJacobianHybridByKey(DM dm, PetscFormKey key[], IS cellIS, PetscReal t, PetscReal X_tShift, Vec locX, Vec locX_t, Mat Jac, Mat JacP, PetscCtx ctx)
6632d71ae5a4SJacob Faibussowitsch {
66333e9753d6SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
66343e9753d6SMatthew G. Knepley const char *name = "Hybrid Jacobian";
6635148442b3SMatthew G. Knepley DM dmAux[3] = {NULL, NULL, NULL};
6636148442b3SMatthew G. Knepley DMLabel ghostLabel = NULL;
66373e9753d6SMatthew G. Knepley DM plex = NULL;
66383e9753d6SMatthew G. Knepley DM plexA = NULL;
6639148442b3SMatthew G. Knepley PetscDS ds = NULL;
664007218a29SMatthew G. Knepley PetscDS dsIn = NULL;
6641148442b3SMatthew G. Knepley PetscDS dsAux[3] = {NULL, NULL, NULL};
6642148442b3SMatthew G. Knepley Vec locA[3] = {NULL, NULL, NULL};
664307218a29SMatthew G. Knepley DM dmScale[3] = {NULL, NULL, NULL};
664407218a29SMatthew G. Knepley PetscDS dsScale[3] = {NULL, NULL, NULL};
664507218a29SMatthew G. Knepley Vec locS[3] = {NULL, NULL, NULL};
66463e9753d6SMatthew G. Knepley PetscSection section = NULL;
6647148442b3SMatthew G. Knepley PetscSection sectionAux[3] = {NULL, NULL, NULL};
66483e9753d6SMatthew G. Knepley DMField coordField = NULL;
664907218a29SMatthew G. Knepley PetscScalar *a[3] = {NULL, NULL, NULL};
665007218a29SMatthew G. Knepley PetscScalar *s[3] = {NULL, NULL, NULL};
665107218a29SMatthew G. Knepley PetscScalar *u = NULL, *u_t;
665207218a29SMatthew G. Knepley PetscScalar *elemMatNeg, *elemMatPos, *elemMatCoh;
665307218a29SMatthew G. Knepley PetscScalar *elemMatNegP, *elemMatPosP, *elemMatCohP;
6654e432b41dSStefano Zampini PetscSection globalSection;
6655989fa639SBrad Aagaard IS chunkISF, chunkISN;
66563e9753d6SMatthew G. Knepley const PetscInt *cells;
6657989fa639SBrad Aagaard PetscInt *faces, *neighbors;
66583e9753d6SMatthew G. Knepley PetscInt cStart, cEnd, numCells;
66593e2b0218SMatthew G. Knepley PetscInt Nf, fieldI, fieldJ, totDim, totDimIn, totDimAux[3], totDimScale[3], numChunks, cellChunkSize, chunk;
66601690c2aeSBarry Smith PetscInt maxDegree = PETSC_INT_MAX;
6661989fa639SBrad Aagaard PetscQuadrature affineQuadF = NULL, *quadsF = NULL;
6662989fa639SBrad Aagaard PetscFEGeom *affineGeomF = NULL, **geomsF = NULL;
6663989fa639SBrad Aagaard PetscQuadrature affineQuadN = NULL;
6664989fa639SBrad Aagaard PetscFEGeom *affineGeomN = NULL;
6665e432b41dSStefano Zampini PetscBool hasBdJac, hasBdPrec;
66663e9753d6SMatthew G. Knepley
66673e9753d6SMatthew G. Knepley PetscFunctionBegin;
66683cc88e6aSStefano Zampini PetscCall(PetscLogEventBegin(DMPLEX_JacobianFEM, dm, 0, 0, 0));
66693cc88e6aSStefano Zampini if (!cellIS) goto end;
6670437e83fbSMatthew G. Knepley PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
6671437e83fbSMatthew G. Knepley PetscCall(ISGetLocalSize(cellIS, &numCells));
66723cc88e6aSStefano Zampini if (cStart >= cEnd) goto end;
66735fedec97SMatthew G. Knepley if ((key[0].label == key[1].label) && (key[0].value == key[1].value) && (key[0].part == key[1].part)) {
66745fedec97SMatthew G. Knepley const char *name;
66759566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)key[0].label, &name));
667663a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Form keys for each side of a cohesive surface must be different (%s, %" PetscInt_FMT ", %" PetscInt_FMT ")", name, key[0].value, key[0].part);
66775fedec97SMatthew G. Knepley }
66789566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex));
6679b98a7184SJames Wright PetscCall(DMGetLocalSection(dm, §ion));
66809566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, &globalSection));
66819566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "ghost", &ghostLabel));
668207218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dm, cells ? cells[cStart] : cStart, &ds, &dsIn));
66839566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf));
66849566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(ds, &totDim));
668507218a29SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsIn, &totDimIn));
66869566063dSJacob Faibussowitsch PetscCall(PetscDSHasBdJacobian(ds, &hasBdJac));
66879566063dSJacob Faibussowitsch PetscCall(PetscDSHasBdJacobianPreconditioner(ds, &hasBdPrec));
66889566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, key[2].label, key[2].value, key[2].part, &locA[2]));
6689148442b3SMatthew G. Knepley if (locA[2]) {
66901059d808SMatthew G. Knepley const PetscInt cellStart = cells ? cells[cStart] : cStart;
66911059d808SMatthew G. Knepley
66929566063dSJacob Faibussowitsch PetscCall(VecGetDM(locA[2], &dmAux[2]));
66939566063dSJacob Faibussowitsch PetscCall(DMConvert(dmAux[2], DMPLEX, &plexA));
6694b98a7184SJames Wright PetscCall(DMGetLocalSection(dmAux[2], §ionAux[2]));
669507218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dmAux[2], cellStart, &dsAux[2], NULL));
66969566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux[2], &totDimAux[2]));
6697148442b3SMatthew G. Knepley {
6698148442b3SMatthew G. Knepley const PetscInt *cone;
6699148442b3SMatthew G. Knepley PetscInt c;
6700148442b3SMatthew G. Knepley
67011059d808SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, cellStart, &cone));
6702148442b3SMatthew G. Knepley for (c = 0; c < 2; ++c) {
6703148442b3SMatthew G. Knepley const PetscInt *support;
6704148442b3SMatthew G. Knepley PetscInt ssize, s;
6705148442b3SMatthew G. Knepley
67069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support));
67079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &ssize));
67081059d808SMatthew G. Knepley PetscCheck(ssize == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " from cell %" PetscInt_FMT " has support size %" PetscInt_FMT " != 2", cone[c], cellStart, ssize);
67091059d808SMatthew G. Knepley if (support[0] == cellStart) s = 1;
67101059d808SMatthew G. Knepley else if (support[1] == cellStart) s = 0;
67111059d808SMatthew G. Knepley else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " does not have cell %" PetscInt_FMT " in its support", cone[c], cellStart);
67129566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, key[c].label, key[c].value, key[c].part, &locA[c]));
67139566063dSJacob Faibussowitsch if (locA[c]) PetscCall(VecGetDM(locA[c], &dmAux[c]));
6714ad540459SPierre Jolivet else dmAux[c] = dmAux[2];
671507218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dmAux[c], support[s], &dsAux[c], NULL));
67169566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(dsAux[c], &totDimAux[c]));
6717148442b3SMatthew G. Knepley }
6718148442b3SMatthew G. Knepley }
67193e9753d6SMatthew G. Knepley }
672007218a29SMatthew G. Knepley /* Handle mass matrix scaling
672107218a29SMatthew G. Knepley The field in key[2] is the field to be scaled, and the scaling field is the first in the dsScale */
672207218a29SMatthew G. Knepley PetscCall(DMGetAuxiliaryVec(dm, key[2].label, -key[2].value, key[2].part, &locS[2]));
672307218a29SMatthew G. Knepley if (locS[2]) {
67243e2b0218SMatthew G. Knepley const PetscInt cellStart = cells ? cells[cStart] : cStart;
672507218a29SMatthew G. Knepley PetscInt Nb, Nbs;
672607218a29SMatthew G. Knepley
672707218a29SMatthew G. Knepley PetscCall(VecGetDM(locS[2], &dmScale[2]));
672807218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dmScale[2], cells ? cells[cStart] : cStart, &dsScale[2], NULL));
67293e2b0218SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsScale[2], &totDimScale[2]));
673007218a29SMatthew G. Knepley // BRAD: This is not set correctly
673107218a29SMatthew G. Knepley key[2].field = 2;
673207218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldSize(ds, key[2].field, &Nb));
673307218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldSize(dsScale[2], 0, &Nbs));
673407218a29SMatthew G. Knepley PetscCheck(Nb == Nbs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Field %" PetscInt_FMT " of size %" PetscInt_FMT " cannot be scaled by field of size %" PetscInt_FMT, key[2].field, Nb, Nbs);
67353e2b0218SMatthew G. Knepley {
67363e2b0218SMatthew G. Knepley const PetscInt *cone;
67373e2b0218SMatthew G. Knepley PetscInt c;
67383e2b0218SMatthew G. Knepley
67393e2b0218SMatthew G. Knepley locS[1] = locS[0] = locS[2];
67403e2b0218SMatthew G. Knepley dmScale[1] = dmScale[0] = dmScale[2];
67413e2b0218SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, cellStart, &cone));
67423e2b0218SMatthew G. Knepley for (c = 0; c < 2; ++c) {
67433e2b0218SMatthew G. Knepley const PetscInt *support;
67443e2b0218SMatthew G. Knepley PetscInt ssize, s;
67453e2b0218SMatthew G. Knepley
67463e2b0218SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, cone[c], &support));
67473e2b0218SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, cone[c], &ssize));
67483e2b0218SMatthew G. Knepley PetscCheck(ssize == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " from cell %" PetscInt_FMT " has support size %" PetscInt_FMT " != 2", cone[c], cellStart, ssize);
67493e2b0218SMatthew G. Knepley if (support[0] == cellStart) s = 1;
67503e2b0218SMatthew G. Knepley else if (support[1] == cellStart) s = 0;
67513e2b0218SMatthew G. Knepley else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " does not have cell %" PetscInt_FMT " in its support", cone[c], cellStart);
67523e2b0218SMatthew G. Knepley PetscCall(DMGetCellDS(dmScale[c], support[s], &dsScale[c], NULL));
67533e2b0218SMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(dsScale[c], &totDimScale[c]));
67543e2b0218SMatthew G. Knepley }
67553e2b0218SMatthew G. Knepley }
675607218a29SMatthew G. Knepley }
675707218a29SMatthew G. Knepley /* 2: Setup geometric data */
67589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
67599566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, cellIS, NULL, &maxDegree));
67603e9753d6SMatthew G. Knepley if (maxDegree > 1) {
67613e9753d6SMatthew G. Knepley PetscInt f;
6762989fa639SBrad Aagaard PetscCall(PetscCalloc2(Nf, &quadsF, Nf, &geomsF));
67633e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
67643e9753d6SMatthew G. Knepley PetscFE fe;
67653e9753d6SMatthew G. Knepley
67669566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, (PetscObject *)&fe));
67673e9753d6SMatthew G. Knepley if (fe) {
6768989fa639SBrad Aagaard PetscCall(PetscFEGetQuadrature(fe, &quadsF[f]));
6769989fa639SBrad Aagaard PetscCall(PetscObjectReference((PetscObject)quadsF[f]));
67703e9753d6SMatthew G. Knepley }
67713e9753d6SMatthew G. Knepley }
67723e9753d6SMatthew G. Knepley }
677307218a29SMatthew G. Knepley /* Loop over chunks */
67743e9753d6SMatthew G. Knepley cellChunkSize = numCells;
67753e9753d6SMatthew G. Knepley numChunks = !numCells ? 0 : PetscCeilReal(((PetscReal)numCells) / cellChunkSize);
6776989fa639SBrad Aagaard PetscCall(PetscCalloc2(2 * cellChunkSize, &faces, 2 * cellChunkSize, &neighbors));
6777989fa639SBrad Aagaard PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2 * cellChunkSize, faces, PETSC_USE_POINTER, &chunkISF));
6778989fa639SBrad Aagaard PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2 * cellChunkSize, neighbors, PETSC_USE_POINTER, &chunkISN));
677907218a29SMatthew G. Knepley /* Extract field coefficients */
678007218a29SMatthew G. Knepley /* NOTE This needs the end cap faces to have identical orientations */
678107218a29SMatthew G. Knepley PetscCall(DMPlexGetHybridCellFields(dm, cellIS, locX, locX_t, locA[2], &u, &u_t, &a[2]));
678207218a29SMatthew G. Knepley PetscCall(DMPlexGetHybridFields(dm, dmAux, dsAux, cellIS, locA, PETSC_TRUE, a));
67838bf0a22dSMatthew G. Knepley PetscCall(DMPlexGetHybridFields(dm, dmScale, dsScale, cellIS, locS, PETSC_TRUE, s));
678407218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, hasBdJac ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatNeg));
678507218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, hasBdJac ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatPos));
678607218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, hasBdJac ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatCoh));
678707218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, hasBdPrec ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatNegP));
678807218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, hasBdPrec ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatPosP));
678907218a29SMatthew G. Knepley PetscCall(DMGetWorkArray(dm, hasBdPrec ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatCohP));
67903e9753d6SMatthew G. Knepley for (chunk = 0; chunk < numChunks; ++chunk) {
67913e9753d6SMatthew G. Knepley PetscInt cS = cStart + chunk * cellChunkSize, cE = PetscMin(cS + cellChunkSize, cEnd), numCells = cE - cS, c;
67923e9753d6SMatthew G. Knepley
679307218a29SMatthew G. Knepley if (hasBdJac) {
679407218a29SMatthew G. Knepley PetscCall(PetscArrayzero(elemMatNeg, cellChunkSize * totDim * totDim));
679507218a29SMatthew G. Knepley PetscCall(PetscArrayzero(elemMatPos, cellChunkSize * totDim * totDim));
679607218a29SMatthew G. Knepley PetscCall(PetscArrayzero(elemMatCoh, cellChunkSize * totDim * totDim));
679707218a29SMatthew G. Knepley }
679807218a29SMatthew G. Knepley if (hasBdPrec) {
679907218a29SMatthew G. Knepley PetscCall(PetscArrayzero(elemMatNegP, cellChunkSize * totDim * totDim));
680007218a29SMatthew G. Knepley PetscCall(PetscArrayzero(elemMatPosP, cellChunkSize * totDim * totDim));
680107218a29SMatthew G. Knepley PetscCall(PetscArrayzero(elemMatCohP, cellChunkSize * totDim * totDim));
680207218a29SMatthew G. Knepley }
68033e9753d6SMatthew G. Knepley /* Get faces */
68043e9753d6SMatthew G. Knepley for (c = cS; c < cE; ++c) {
68053e9753d6SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
6806989fa639SBrad Aagaard const PetscInt *cone, *support;
68079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(plex, cell, &cone));
680807218a29SMatthew G. Knepley faces[(c - cS) * 2 + 0] = cone[0];
680907218a29SMatthew G. Knepley faces[(c - cS) * 2 + 1] = cone[1];
6810989fa639SBrad Aagaard PetscCall(DMPlexGetSupport(dm, cone[0], &support));
6811989fa639SBrad Aagaard neighbors[(c - cS) * 2 + 0] = support[0] == cell ? support[1] : support[0];
6812989fa639SBrad Aagaard PetscCall(DMPlexGetSupport(dm, cone[1], &support));
6813989fa639SBrad Aagaard neighbors[(c - cS) * 2 + 1] = support[0] == cell ? support[1] : support[0];
68143e9753d6SMatthew G. Knepley }
6815989fa639SBrad Aagaard PetscCall(ISGeneralSetIndices(chunkISF, 2 * cellChunkSize, faces, PETSC_USE_POINTER));
6816989fa639SBrad Aagaard PetscCall(ISGeneralSetIndices(chunkISN, 2 * cellChunkSize, neighbors, PETSC_USE_POINTER));
68173e9753d6SMatthew G. Knepley if (maxDegree <= 1) {
6818989fa639SBrad Aagaard if (!affineQuadF) PetscCall(DMFieldCreateDefaultQuadrature(coordField, chunkISF, &affineQuadF));
6819989fa639SBrad Aagaard if (affineQuadF) PetscCall(DMSNESGetFEGeom(coordField, chunkISF, affineQuadF, PETSC_FEGEOM_COHESIVE, &affineGeomF));
6820989fa639SBrad Aagaard if (!affineQuadN) {
6821989fa639SBrad Aagaard PetscInt dim;
6822989fa639SBrad Aagaard PetscCall(PetscQuadratureGetData(affineQuadF, &dim, NULL, NULL, NULL, NULL));
6823989fa639SBrad Aagaard PetscCall(DMFieldCreateDefaultFaceQuadrature(coordField, chunkISN, &affineQuadN));
6824989fa639SBrad Aagaard PetscCall(PetscQuadratureSetData(affineQuadN, dim + 1, PETSC_DECIDE, PETSC_DECIDE, NULL, NULL));
6825989fa639SBrad Aagaard }
6826989fa639SBrad Aagaard if (affineQuadN) PetscCall(DMSNESGetFEGeom(coordField, chunkISN, affineQuadN, PETSC_FEGEOM_BASIC, &affineGeomN));
68273e9753d6SMatthew G. Knepley } else {
68283e9753d6SMatthew G. Knepley PetscInt f;
68293e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
6830989fa639SBrad Aagaard if (quadsF[f]) PetscCall(DMSNESGetFEGeom(coordField, chunkISF, quadsF[f], PETSC_FEGEOM_COHESIVE, &geomsF[f]));
68313e9753d6SMatthew G. Knepley }
68323e9753d6SMatthew G. Knepley }
68333e9753d6SMatthew G. Knepley
68343e9753d6SMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) {
68353e9753d6SMatthew G. Knepley PetscFE feI;
6836989fa639SBrad Aagaard PetscFEGeom *geomF = affineGeomF ? affineGeomF : geomsF[fieldI];
6837989fa639SBrad Aagaard PetscFEGeom *chunkGeomF = NULL, *remGeomF = NULL;
6838989fa639SBrad Aagaard PetscFEGeom *geomN = affineGeomN ? affineGeomN : geomsF[fieldI];
6839989fa639SBrad Aagaard PetscFEGeom *chunkGeomN = NULL, *remGeomN = NULL;
6840989fa639SBrad Aagaard PetscQuadrature quadF = affineQuadF ? affineQuadF : quadsF[fieldI];
68413e9753d6SMatthew G. Knepley PetscInt numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset, Nq, Nb;
68425fedec97SMatthew G. Knepley PetscBool isCohesiveField;
68433e9753d6SMatthew G. Knepley
68449566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, fieldI, (PetscObject *)&feI));
68453e9753d6SMatthew G. Knepley if (!feI) continue;
68469566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(feI, NULL, &numBlocks, NULL, &numBatches));
6847989fa639SBrad Aagaard PetscCall(PetscQuadratureGetData(quadF, NULL, NULL, &Nq, NULL, NULL));
68489566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(feI, &Nb));
68493e9753d6SMatthew G. Knepley blockSize = Nb;
68503e9753d6SMatthew G. Knepley batchSize = numBlocks * blockSize;
68519566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(feI, blockSize, numBlocks, batchSize, numBatches));
68523e9753d6SMatthew G. Knepley numChunks = numCells / (numBatches * batchSize);
68533e9753d6SMatthew G. Knepley Ne = numChunks * numBatches * batchSize;
68543e9753d6SMatthew G. Knepley Nr = numCells % (numBatches * batchSize);
68553e9753d6SMatthew G. Knepley offset = numCells - Nr;
6856989fa639SBrad Aagaard PetscCall(PetscFEGeomGetChunk(geomF, 0, offset * 2, &chunkGeomF));
6857989fa639SBrad Aagaard PetscCall(PetscFEGeomGetChunk(geomF, offset * 2, numCells * 2, &remGeomF));
6858989fa639SBrad Aagaard PetscCall(PetscFEGeomGetChunk(geomN, 0, offset * 2, &chunkGeomN));
6859989fa639SBrad Aagaard PetscCall(PetscFEGeomGetChunk(geomN, offset * 2, numCells * 2, &remGeomN));
68609566063dSJacob Faibussowitsch PetscCall(PetscDSGetCohesive(ds, fieldI, &isCohesiveField));
68613e9753d6SMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
68623e9753d6SMatthew G. Knepley PetscFE feJ;
68633e9753d6SMatthew G. Knepley
68649566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, fieldJ, (PetscObject *)&feJ));
68653e9753d6SMatthew G. Knepley if (!feJ) continue;
6866148442b3SMatthew G. Knepley key[0].field = fieldI * Nf + fieldJ;
6867148442b3SMatthew G. Knepley key[1].field = fieldI * Nf + fieldJ;
68685fedec97SMatthew G. Knepley key[2].field = fieldI * Nf + fieldJ;
6869148442b3SMatthew G. Knepley if (hasBdJac) {
6870989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN, key[0], 0, Ne, chunkGeomF, chunkGeomN, u, u_t, dsAux[0], a[0], t, X_tShift, elemMatNeg));
6871989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN, key[0], 0, Nr, remGeomF, remGeomN, &u[offset * totDimIn], PetscSafePointerPlusOffset(u_t, offset * totDimIn), dsAux[0], PetscSafePointerPlusOffset(a[0], offset * totDimAux[0]), t, X_tShift, &elemMatNeg[offset * totDim * totDim]));
6872989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN, key[1], 1, Ne, chunkGeomF, chunkGeomN, u, u_t, dsAux[1], a[1], t, X_tShift, elemMatPos));
6873989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN, key[1], 1, Nr, remGeomF, remGeomN, &u[offset * totDimIn], PetscSafePointerPlusOffset(u_t, offset * totDimIn), dsAux[1], PetscSafePointerPlusOffset(a[1], offset * totDimAux[1]), t, X_tShift, &elemMatPos[offset * totDim * totDim]));
6874148442b3SMatthew G. Knepley }
6875148442b3SMatthew G. Knepley if (hasBdPrec) {
6876989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN_PRE, key[0], 0, Ne, chunkGeomF, chunkGeomN, u, u_t, dsAux[0], a[0], t, X_tShift, elemMatNegP));
6877989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN_PRE, key[0], 0, Nr, remGeomF, remGeomN, &u[offset * totDimIn], PetscSafePointerPlusOffset(u_t, offset * totDimIn), dsAux[0], &a[0][offset * totDimAux[0]], t, X_tShift, &elemMatNegP[offset * totDim * totDim]));
6878989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN_PRE, key[1], 1, Ne, chunkGeomF, chunkGeomN, u, u_t, dsAux[1], a[1], t, X_tShift, elemMatPosP));
6879989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN_PRE, key[1], 1, Nr, remGeomF, remGeomN, &u[offset * totDimIn], PetscSafePointerPlusOffset(u_t, offset * totDimIn), dsAux[1], &a[1][offset * totDimAux[1]], t, X_tShift, &elemMatPosP[offset * totDim * totDim]));
6880148442b3SMatthew G. Knepley }
68815fedec97SMatthew G. Knepley if (hasBdJac) {
6882989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN, key[2], 2, Ne, chunkGeomF, chunkGeomN, u, u_t, dsAux[2], a[2], t, X_tShift, elemMatCoh));
6883989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN, key[2], 2, Nr, remGeomF, remGeomN, &u[offset * totDimIn], PetscSafePointerPlusOffset(u_t, offset * totDimIn), dsAux[2], PetscSafePointerPlusOffset(a[2], offset * totDimAux[2]), t, X_tShift, &elemMatCoh[offset * totDim * totDim]));
6884148442b3SMatthew G. Knepley }
68855fedec97SMatthew G. Knepley if (hasBdPrec) {
6886989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN_PRE, key[2], 2, Ne, chunkGeomF, chunkGeomN, u, u_t, dsAux[2], a[2], t, X_tShift, elemMatCohP));
6887989fa639SBrad Aagaard PetscCall(PetscFEIntegrateHybridJacobian(ds, dsIn, PETSCFE_JACOBIAN_PRE, key[2], 2, Nr, remGeomF, remGeomN, &u[offset * totDimIn], PetscSafePointerPlusOffset(u_t, offset * totDimIn), dsAux[2], &a[2][offset * totDimAux[2]], t, X_tShift, &elemMatCohP[offset * totDim * totDim]));
68883e9753d6SMatthew G. Knepley }
68893e9753d6SMatthew G. Knepley }
6890989fa639SBrad Aagaard PetscCall(PetscFEGeomRestoreChunk(geomF, offset, numCells, &remGeomF));
6891989fa639SBrad Aagaard PetscCall(PetscFEGeomRestoreChunk(geomF, 0, offset, &chunkGeomF));
6892989fa639SBrad Aagaard PetscCall(PetscFEGeomRestoreChunk(geomN, offset, numCells, &remGeomN));
6893989fa639SBrad Aagaard PetscCall(PetscFEGeomRestoreChunk(geomN, 0, offset, &chunkGeomN));
68943e9753d6SMatthew G. Knepley }
68953e9753d6SMatthew G. Knepley /* Insert values into matrix */
68963e9753d6SMatthew G. Knepley for (c = cS; c < cE; ++c) {
68973e9753d6SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
689807218a29SMatthew G. Knepley const PetscInt cind = c - cS, coff = cind * totDim * totDim;
689907218a29SMatthew G. Knepley PetscInt i, j;
69003e9753d6SMatthew G. Knepley
690107218a29SMatthew G. Knepley /* Scale element values */
690207218a29SMatthew G. Knepley if (locS[0]) {
69033e2b0218SMatthew G. Knepley PetscInt Nb, soff = cind * totDimScale[0], off = 0;
690407218a29SMatthew G. Knepley PetscBool cohesive;
690507218a29SMatthew G. Knepley
690607218a29SMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) {
690707218a29SMatthew G. Knepley PetscCall(PetscDSGetFieldSize(ds, fieldI, &Nb));
690807218a29SMatthew G. Knepley PetscCall(PetscDSGetCohesive(ds, fieldI, &cohesive));
690907218a29SMatthew G. Knepley
691007218a29SMatthew G. Knepley if (fieldI == key[2].field) {
691107218a29SMatthew G. Knepley PetscCheck(cohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Scaling should not happen for face fields");
69128bf0a22dSMatthew G. Knepley for (i = 0; i < Nb; ++i) {
691307218a29SMatthew G. Knepley for (j = 0; j < totDim; ++j) elemMatCoh[coff + (off + i) * totDim + j] += s[0][soff + i] * elemMatNeg[coff + (off + i) * totDim + j] + s[1][soff + i] * elemMatPos[coff + (off + i) * totDim + j];
69148bf0a22dSMatthew G. Knepley if (hasBdPrec)
69158bf0a22dSMatthew G. Knepley for (j = 0; j < totDim; ++j) elemMatCohP[coff + (off + i) * totDim + j] += s[0][soff + i] * elemMatNegP[coff + (off + i) * totDim + j] + s[1][soff + i] * elemMatPosP[coff + (off + i) * totDim + j];
69168bf0a22dSMatthew G. Knepley }
691707218a29SMatthew G. Knepley off += Nb;
691807218a29SMatthew G. Knepley } else {
691907218a29SMatthew G. Knepley const PetscInt N = cohesive ? Nb : Nb * 2;
692007218a29SMatthew G. Knepley
69218bf0a22dSMatthew G. Knepley for (i = 0; i < N; ++i) {
692207218a29SMatthew G. Knepley for (j = 0; j < totDim; ++j) elemMatCoh[coff + (off + i) * totDim + j] += elemMatNeg[coff + (off + i) * totDim + j] + elemMatPos[coff + (off + i) * totDim + j];
69238bf0a22dSMatthew G. Knepley if (hasBdPrec)
69248bf0a22dSMatthew G. Knepley for (j = 0; j < totDim; ++j) elemMatCohP[coff + (off + i) * totDim + j] += elemMatNegP[coff + (off + i) * totDim + j] + elemMatPosP[coff + (off + i) * totDim + j];
69258bf0a22dSMatthew G. Knepley }
692607218a29SMatthew G. Knepley off += N;
692707218a29SMatthew G. Knepley }
692807218a29SMatthew G. Knepley }
692907218a29SMatthew G. Knepley } else {
693007218a29SMatthew G. Knepley for (i = 0; i < totDim * totDim; ++i) elemMatCoh[coff + i] += elemMatNeg[coff + i] + elemMatPos[coff + i];
69318bf0a22dSMatthew G. Knepley if (hasBdPrec)
69328bf0a22dSMatthew G. Knepley for (i = 0; i < totDim * totDim; ++i) elemMatCohP[coff + i] += elemMatNegP[coff + i] + elemMatPosP[coff + i];
693307218a29SMatthew G. Knepley }
69343e9753d6SMatthew G. Knepley if (hasBdPrec) {
69353e9753d6SMatthew G. Knepley if (hasBdJac) {
693607218a29SMatthew G. Knepley if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, totDim, totDim, &elemMatCoh[cind * totDim * totDim]));
6937e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(plex, section, globalSection, mesh->useMatClPerm, Jac, cell, &elemMatCoh[cind * totDim * totDim], ADD_VALUES));
69383e9753d6SMatthew G. Knepley }
693907218a29SMatthew G. Knepley if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, totDim, totDim, &elemMatCohP[cind * totDim * totDim]));
694007218a29SMatthew G. Knepley PetscCall(DMPlexMatSetClosure(plex, section, globalSection, JacP, cell, &elemMatCohP[cind * totDim * totDim], ADD_VALUES));
69413e9753d6SMatthew G. Knepley } else if (hasBdJac) {
694207218a29SMatthew G. Knepley if (mesh->printFEM > 1) PetscCall(DMPrintCellMatrix(cell, name, totDim, totDim, &elemMatCoh[cind * totDim * totDim]));
6943e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(plex, section, globalSection, mesh->useMatClPerm, JacP, cell, &elemMatCoh[cind * totDim * totDim], ADD_VALUES));
69443e9753d6SMatthew G. Knepley }
69453e9753d6SMatthew G. Knepley }
69463e9753d6SMatthew G. Knepley }
69479566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCellFields(dm, cellIS, locX, locX_t, locA[2], &u, &u_t, &a[2]));
694807218a29SMatthew G. Knepley PetscCall(DMPlexRestoreHybridFields(dm, dmAux, dsAux, cellIS, locA, PETSC_TRUE, a));
694907218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, hasBdJac ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatNeg));
695007218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, hasBdJac ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatPos));
695107218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, hasBdJac ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatCoh));
695207218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, hasBdPrec ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatNegP));
695307218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, hasBdPrec ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatPosP));
695407218a29SMatthew G. Knepley PetscCall(DMRestoreWorkArray(dm, hasBdPrec ? cellChunkSize * totDim * totDim : 0, MPIU_SCALAR, &elemMatCohP));
6955989fa639SBrad Aagaard PetscCall(PetscFree2(faces, neighbors));
6956989fa639SBrad Aagaard PetscCall(ISDestroy(&chunkISF));
6957989fa639SBrad Aagaard PetscCall(ISDestroy(&chunkISN));
69589566063dSJacob Faibussowitsch PetscCall(ISRestorePointRange(cellIS, &cStart, &cEnd, &cells));
69593e9753d6SMatthew G. Knepley if (maxDegree <= 1) {
6960989fa639SBrad Aagaard PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, affineQuadF, PETSC_FALSE, &affineGeomF));
6961989fa639SBrad Aagaard PetscCall(PetscQuadratureDestroy(&affineQuadF));
6962989fa639SBrad Aagaard PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, affineQuadN, PETSC_FALSE, &affineGeomN));
6963989fa639SBrad Aagaard PetscCall(PetscQuadratureDestroy(&affineQuadN));
69643e9753d6SMatthew G. Knepley } else {
69653e9753d6SMatthew G. Knepley PetscInt f;
69663e9753d6SMatthew G. Knepley for (f = 0; f < Nf; ++f) {
6967989fa639SBrad Aagaard if (geomsF) PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, quadsF[f], PETSC_FALSE, &geomsF[f]));
6968989fa639SBrad Aagaard if (quadsF) PetscCall(PetscQuadratureDestroy(&quadsF[f]));
69693e9753d6SMatthew G. Knepley }
6970989fa639SBrad Aagaard PetscCall(PetscFree2(quadsF, geomsF));
69713e9753d6SMatthew G. Knepley }
69729566063dSJacob Faibussowitsch if (dmAux[2]) PetscCall(DMDestroy(&plexA));
69739566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex));
69743cc88e6aSStefano Zampini end:
69759566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_JacobianFEM, dm, 0, 0, 0));
69763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
69773e9753d6SMatthew G. Knepley }
69788e3a2eefSMatthew G. Knepley
6979754e4fbaSMatthew G. Knepley /*@
6980754e4fbaSMatthew G. Knepley DMPlexComputeJacobianActionByKey - Compute the local Jacobian for terms matching the input key
6981754e4fbaSMatthew G. Knepley
6982754e4fbaSMatthew G. Knepley Collective
69838e3a2eefSMatthew G. Knepley
69848e3a2eefSMatthew G. Knepley Input Parameters:
6985754e4fbaSMatthew G. Knepley + dm - The output `DM`
6986754e4fbaSMatthew G. Knepley . key - The `PetscFormKey` indicating what should be integrated
6987754e4fbaSMatthew G. Knepley . cellIS - The `IS` give a set of cells to integrate over
69888e3a2eefSMatthew G. Knepley . t - The time
6989754e4fbaSMatthew G. Knepley . X_tShift - The multiplier for the Jacobian with respect to $X_t$
6990754e4fbaSMatthew G. Knepley . locX - The local solution
6991754e4fbaSMatthew G. Knepley . locX_t - The time derivative of the local solution, or `NULL` for time-independent problems
6992754e4fbaSMatthew G. Knepley . locY - The local vector acted on by J
6993*2a8381b2SBarry Smith - ctx - An optional application context, passed to the pointwise functions
69948e3a2eefSMatthew G. Knepley
69958e3a2eefSMatthew G. Knepley Output Parameter:
6996754e4fbaSMatthew G. Knepley . locF - The local residual F = J(X) Y
69978e3a2eefSMatthew G. Knepley
6998754e4fbaSMatthew G. Knepley Level: developer
6999754e4fbaSMatthew G. Knepley
7000754e4fbaSMatthew G. Knepley .seealso: `DMPlexComputeResidualByKey()`, `DMPlexComputeJacobianByKey()`, `DMPlexComputeResidualHybridByKey()`, `DMPlexComputeJacobianHybridByKey()`, `PetscFormKey`
7001754e4fbaSMatthew G. Knepley @*/
DMPlexComputeJacobianActionByKey(DM dm,PetscFormKey key,IS cellIS,PetscReal t,PetscReal X_tShift,Vec locX,Vec locX_t,Vec locY,Vec locF,PetscCtx ctx)7002*2a8381b2SBarry Smith PetscErrorCode DMPlexComputeJacobianActionByKey(DM dm, PetscFormKey key, IS cellIS, PetscReal t, PetscReal X_tShift, Vec locX, Vec locX_t, Vec locY, Vec locF, PetscCtx ctx)
7003d71ae5a4SJacob Faibussowitsch {
70048e3a2eefSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data;
70058e3a2eefSMatthew G. Knepley const char *name = "Jacobian";
70068e3a2eefSMatthew G. Knepley DM dmAux = NULL, plex, plexAux = NULL;
70078e3a2eefSMatthew G. Knepley DMEnclosureType encAux;
70088e3a2eefSMatthew G. Knepley Vec A;
70098e3a2eefSMatthew G. Knepley DMField coordField;
70108e3a2eefSMatthew G. Knepley PetscDS prob, probAux = NULL;
70118e3a2eefSMatthew G. Knepley PetscQuadrature quad;
70128e3a2eefSMatthew G. Knepley PetscSection section, globalSection, sectionAux;
70138e3a2eefSMatthew G. Knepley PetscScalar *elemMat, *elemMatD, *u, *u_t, *a = NULL, *y, *z;
70148e3a2eefSMatthew G. Knepley const PetscInt *cells;
70158e3a2eefSMatthew G. Knepley PetscInt Nf, fieldI, fieldJ;
70168e3a2eefSMatthew G. Knepley PetscInt totDim, totDimAux = 0, cStart, cEnd, numCells, c;
70178e3a2eefSMatthew G. Knepley PetscBool hasDyn;
70188e3a2eefSMatthew G. Knepley
70198e3a2eefSMatthew G. Knepley PetscFunctionBegin;
70209566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_JacobianFEM, dm, 0, 0, 0));
70219566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex));
70229566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(cellIS, &numCells));
70239566063dSJacob Faibussowitsch PetscCall(ISGetPointRange(cellIS, &cStart, &cEnd, &cells));
70249566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion));
70259566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, &globalSection));
702607218a29SMatthew G. Knepley PetscCall(DMGetCellDS(dm, cells ? cells[cStart] : cStart, &prob, NULL));
70279566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf));
70289566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim));
70299566063dSJacob Faibussowitsch PetscCall(PetscDSHasDynamicJacobian(prob, &hasDyn));
70308e3a2eefSMatthew G. Knepley hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE;
70319566063dSJacob Faibussowitsch PetscCall(DMGetAuxiliaryVec(dm, key.label, key.value, key.part, &A));
70328e3a2eefSMatthew G. Knepley if (A) {
70339566063dSJacob Faibussowitsch PetscCall(VecGetDM(A, &dmAux));
70349566063dSJacob Faibussowitsch PetscCall(DMGetEnclosureRelation(dmAux, dm, &encAux));
70359566063dSJacob Faibussowitsch PetscCall(DMConvert(dmAux, DMPLEX, &plexAux));
70369566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(plexAux, §ionAux));
70379566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmAux, &probAux));
70389566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(probAux, &totDimAux));
70398e3a2eefSMatthew G. Knepley }
7040754e4fbaSMatthew G. Knepley PetscCall(VecSet(locF, 0.0));
7041754e4fbaSMatthew G. Knepley PetscCall(PetscMalloc6(numCells * totDim, &u, (locX_t ? (size_t)numCells * totDim : 0), &u_t, numCells * totDim * totDim, &elemMat, (hasDyn ? (size_t)numCells * totDim * totDim : 0), &elemMatD, numCells * totDim, &y, totDim, &z));
70429566063dSJacob Faibussowitsch if (dmAux) PetscCall(PetscMalloc1(numCells * totDimAux, &a));
70439566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateField(dm, &coordField));
70448e3a2eefSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
70458e3a2eefSMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
70468e3a2eefSMatthew G. Knepley const PetscInt cind = c - cStart;
70478e3a2eefSMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL;
70488e3a2eefSMatthew G. Knepley PetscInt i;
70498e3a2eefSMatthew G. Knepley
7050754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecGetClosure(plex, section, locX, cell, NULL, &x));
70518e3a2eefSMatthew G. Knepley for (i = 0; i < totDim; ++i) u[cind * totDim + i] = x[i];
7052754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(plex, section, locX, cell, NULL, &x));
7053754e4fbaSMatthew G. Knepley if (locX_t) {
7054754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecGetClosure(plex, section, locX_t, cell, NULL, &x_t));
70558e3a2eefSMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[cind * totDim + i] = x_t[i];
7056754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(plex, section, locX_t, cell, NULL, &x_t));
70578e3a2eefSMatthew G. Knepley }
70588e3a2eefSMatthew G. Knepley if (dmAux) {
70598e3a2eefSMatthew G. Knepley PetscInt subcell;
70609566063dSJacob Faibussowitsch PetscCall(DMGetEnclosurePoint(dmAux, dm, encAux, cell, &subcell));
70619566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(plexAux, sectionAux, A, subcell, NULL, &x));
70628e3a2eefSMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[cind * totDimAux + i] = x[i];
70639566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(plexAux, sectionAux, A, subcell, NULL, &x));
70648e3a2eefSMatthew G. Knepley }
7065754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecGetClosure(plex, section, locY, cell, NULL, &x));
70668e3a2eefSMatthew G. Knepley for (i = 0; i < totDim; ++i) y[cind * totDim + i] = x[i];
7067754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(plex, section, locY, cell, NULL, &x));
70688e3a2eefSMatthew G. Knepley }
70699566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemMat, numCells * totDim * totDim));
70709566063dSJacob Faibussowitsch if (hasDyn) PetscCall(PetscArrayzero(elemMatD, numCells * totDim * totDim));
70718e3a2eefSMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) {
70728e3a2eefSMatthew G. Knepley PetscFE fe;
70738e3a2eefSMatthew G. Knepley PetscInt Nb;
70748e3a2eefSMatthew G. Knepley /* Conforming batches */
70758e3a2eefSMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize;
70768e3a2eefSMatthew G. Knepley /* Remainder */
70778e3a2eefSMatthew G. Knepley PetscInt Nr, offset, Nq;
70788e3a2eefSMatthew G. Knepley PetscQuadrature qGeom = NULL;
70798e3a2eefSMatthew G. Knepley PetscInt maxDegree;
70808e3a2eefSMatthew G. Knepley PetscFEGeom *cgeomFEM, *chunkGeom = NULL, *remGeom = NULL;
70818e3a2eefSMatthew G. Knepley
70829566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, fieldI, (PetscObject *)&fe));
70839566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &quad));
70849566063dSJacob Faibussowitsch PetscCall(PetscFEGetDimension(fe, &Nb));
70859566063dSJacob Faibussowitsch PetscCall(PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches));
70869566063dSJacob Faibussowitsch PetscCall(DMFieldGetDegree(coordField, cellIS, NULL, &maxDegree));
70879566063dSJacob Faibussowitsch if (maxDegree <= 1) PetscCall(DMFieldCreateDefaultQuadrature(coordField, cellIS, &qGeom));
70888e3a2eefSMatthew G. Knepley if (!qGeom) {
70899566063dSJacob Faibussowitsch PetscCall(PetscFEGetQuadrature(fe, &qGeom));
70909566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)qGeom));
70918e3a2eefSMatthew G. Knepley }
70929566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL));
7093ac9d17c7SMatthew G. Knepley PetscCall(DMSNESGetFEGeom(coordField, cellIS, qGeom, PETSC_FEGEOM_BASIC, &cgeomFEM));
70948e3a2eefSMatthew G. Knepley blockSize = Nb;
70958e3a2eefSMatthew G. Knepley batchSize = numBlocks * blockSize;
70969566063dSJacob Faibussowitsch PetscCall(PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches));
70978e3a2eefSMatthew G. Knepley numChunks = numCells / (numBatches * batchSize);
70988e3a2eefSMatthew G. Knepley Ne = numChunks * numBatches * batchSize;
70998e3a2eefSMatthew G. Knepley Nr = numCells % (numBatches * batchSize);
71008e3a2eefSMatthew G. Knepley offset = numCells - Nr;
71019566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(cgeomFEM, 0, offset, &chunkGeom));
71029566063dSJacob Faibussowitsch PetscCall(PetscFEGeomGetChunk(cgeomFEM, offset, numCells, &remGeom));
71038e3a2eefSMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) {
71048e3a2eefSMatthew G. Knepley key.field = fieldI * Nf + fieldJ;
71054561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN, key, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat));
71064561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN, key, Nr, remGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), probAux, PetscSafePointerPlusOffset(a, offset * totDimAux), t, X_tShift, &elemMat[offset * totDim * totDim]));
71078e3a2eefSMatthew G. Knepley if (hasDyn) {
71084561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN_DYN, key, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatD));
71094561e6c9SMatthew G. Knepley PetscCall(PetscFEIntegrateJacobian(prob, prob, PETSCFE_JACOBIAN_DYN, key, Nr, remGeom, &u[offset * totDim], PetscSafePointerPlusOffset(u_t, offset * totDim), probAux, &a[offset * totDimAux], t, X_tShift, &elemMatD[offset * totDim * totDim]));
71108e3a2eefSMatthew G. Knepley }
71118e3a2eefSMatthew G. Knepley }
71129566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(cgeomFEM, offset, numCells, &remGeom));
71139566063dSJacob Faibussowitsch PetscCall(PetscFEGeomRestoreChunk(cgeomFEM, 0, offset, &chunkGeom));
71149566063dSJacob Faibussowitsch PetscCall(DMSNESRestoreFEGeom(coordField, cellIS, qGeom, PETSC_FALSE, &cgeomFEM));
71159566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&qGeom));
71168e3a2eefSMatthew G. Knepley }
71178e3a2eefSMatthew G. Knepley if (hasDyn) {
71188e3a2eefSMatthew G. Knepley for (c = 0; c < numCells * totDim * totDim; ++c) elemMat[c] += X_tShift * elemMatD[c];
71198e3a2eefSMatthew G. Knepley }
71208e3a2eefSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {
71218e3a2eefSMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c;
71228e3a2eefSMatthew G. Knepley const PetscInt cind = c - cStart;
71236497c311SBarry Smith const PetscBLASInt one = 1;
71246497c311SBarry Smith PetscBLASInt M;
71258e3a2eefSMatthew G. Knepley const PetscScalar a = 1.0, b = 0.0;
71268e3a2eefSMatthew G. Knepley
71276497c311SBarry Smith PetscCall(PetscBLASIntCast(totDim, &M));
7128792fecdfSBarry Smith PetscCallBLAS("BLASgemv", BLASgemv_("N", &M, &M, &a, &elemMat[cind * totDim * totDim], &M, &y[cind * totDim], &one, &b, z, &one));
71298e3a2eefSMatthew G. Knepley if (mesh->printFEM > 1) {
71309566063dSJacob Faibussowitsch PetscCall(DMPrintCellMatrix(c, name, totDim, totDim, &elemMat[cind * totDim * totDim]));
71319566063dSJacob Faibussowitsch PetscCall(DMPrintCellVector(c, "Y", totDim, &y[cind * totDim]));
71329566063dSJacob Faibussowitsch PetscCall(DMPrintCellVector(c, "Z", totDim, z));
71338e3a2eefSMatthew G. Knepley }
7134754e4fbaSMatthew G. Knepley PetscCall(DMPlexVecSetClosure(dm, section, locF, cell, z, ADD_VALUES));
71358e3a2eefSMatthew G. Knepley }
71369566063dSJacob Faibussowitsch PetscCall(PetscFree6(u, u_t, elemMat, elemMatD, y, z));
71378e3a2eefSMatthew G. Knepley if (mesh->printFEM) {
7138754e4fbaSMatthew G. Knepley PetscCall(PetscPrintf(PetscObjectComm((PetscObject)locF), "Z:\n"));
7139754e4fbaSMatthew G. Knepley PetscCall(VecView(locF, NULL));
71408e3a2eefSMatthew G. Knepley }
71411059d808SMatthew G. Knepley PetscCall(ISRestorePointRange(cellIS, &cStart, &cEnd, &cells));
71429566063dSJacob Faibussowitsch PetscCall(PetscFree(a));
71439566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plexAux));
71449566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex));
71459566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_JacobianFEM, dm, 0, 0, 0));
71463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
71478e3a2eefSMatthew G. Knepley }
7148d52c2f21SMatthew G. Knepley
f0_1(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[])7149d52c2f21SMatthew G. Knepley static void f0_1(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
7150d52c2f21SMatthew G. Knepley {
7151d52c2f21SMatthew G. Knepley f0[0] = u[0];
7152d52c2f21SMatthew G. Knepley }
7153d52c2f21SMatthew G. Knepley
f0_x(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[])7154d52c2f21SMatthew G. Knepley static void f0_x(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
7155d52c2f21SMatthew G. Knepley {
7156d52c2f21SMatthew G. Knepley f0[0] = x[(int)PetscRealPart(constants[0])] * u[0];
7157d52c2f21SMatthew G. Knepley }
7158d52c2f21SMatthew G. Knepley
f0_x2(PetscInt dim,PetscInt Nf,PetscInt NfAux,const PetscInt uOff[],const PetscInt uOff_x[],const PetscScalar u[],const PetscScalar u_t[],const PetscScalar u_x[],const PetscInt aOff[],const PetscInt aOff_x[],const PetscScalar a[],const PetscScalar a_t[],const PetscScalar a_x[],PetscReal t,const PetscReal x[],PetscInt numConstants,const PetscScalar constants[],PetscScalar f0[])7159d52c2f21SMatthew G. Knepley static void f0_x2(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
7160d52c2f21SMatthew G. Knepley {
7161d52c2f21SMatthew G. Knepley PetscInt d;
7162d52c2f21SMatthew G. Knepley
7163d52c2f21SMatthew G. Knepley f0[0] = 0.0;
7164d52c2f21SMatthew G. Knepley for (d = 0; d < dim; ++d) f0[0] += PetscSqr(x[d]) * u[0];
7165d52c2f21SMatthew G. Knepley }
7166d52c2f21SMatthew G. Knepley
7167d52c2f21SMatthew G. Knepley /*@
7168d52c2f21SMatthew G. Knepley DMPlexComputeMoments - Compute the first three moments for a field
7169d52c2f21SMatthew G. Knepley
7170d52c2f21SMatthew G. Knepley Noncollective
7171d52c2f21SMatthew G. Knepley
7172d52c2f21SMatthew G. Knepley Input Parameters:
7173d52c2f21SMatthew G. Knepley + dm - the `DMPLEX`
7174d52c2f21SMatthew G. Knepley - u - the field
7175d52c2f21SMatthew G. Knepley
7176d52c2f21SMatthew G. Knepley Output Parameter:
7177d52c2f21SMatthew G. Knepley . moments - the field moments
7178d52c2f21SMatthew G. Knepley
7179d52c2f21SMatthew G. Knepley Level: intermediate
7180d52c2f21SMatthew G. Knepley
7181d52c2f21SMatthew G. Knepley Note:
718217314648SMatthew G. Knepley The `moments` array should be of length cdim + 2, where cdim is the number of components for the coordinate field.
7183d52c2f21SMatthew G. Knepley
7184d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMPLEX`, `DMSwarmComputeMoments()`
7185d52c2f21SMatthew G. Knepley @*/
DMPlexComputeMoments(DM dm,Vec u,PetscReal moments[])7186d52c2f21SMatthew G. Knepley PetscErrorCode DMPlexComputeMoments(DM dm, Vec u, PetscReal moments[])
7187d52c2f21SMatthew G. Knepley {
7188d52c2f21SMatthew G. Knepley PetscDS ds;
7189d52c2f21SMatthew G. Knepley PetscScalar mom, constants[1];
7190d52c2f21SMatthew G. Knepley const PetscScalar *oldConstants;
719117314648SMatthew G. Knepley PetscInt cdim, Nf, field = 0, Ncon;
7192d52c2f21SMatthew G. Knepley MPI_Comm comm;
7193*2a8381b2SBarry Smith void *ctx;
7194d52c2f21SMatthew G. Knepley
7195d52c2f21SMatthew G. Knepley PetscFunctionBeginUser;
7196d52c2f21SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
719717314648SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim));
7198*2a8381b2SBarry Smith PetscCall(DMGetApplicationContext(dm, &ctx));
7199d52c2f21SMatthew G. Knepley PetscCall(DMGetDS(dm, &ds));
7200d52c2f21SMatthew G. Knepley PetscCall(PetscDSGetNumFields(ds, &Nf));
7201d52c2f21SMatthew G. Knepley PetscCall(PetscDSGetConstants(ds, &Ncon, &oldConstants));
7202d52c2f21SMatthew G. Knepley PetscCheck(Nf == 1, comm, PETSC_ERR_ARG_WRONG, "We currently only support 1 field, not %" PetscInt_FMT, Nf);
7203d52c2f21SMatthew G. Knepley PetscCall(PetscDSSetObjective(ds, field, &f0_1));
7204*2a8381b2SBarry Smith PetscCall(DMPlexComputeIntegralFEM(dm, u, &mom, ctx));
7205d52c2f21SMatthew G. Knepley moments[0] = PetscRealPart(mom);
720617314648SMatthew G. Knepley for (PetscInt c = 0; c < cdim; ++c) {
7207d52c2f21SMatthew G. Knepley constants[0] = c;
720817314648SMatthew G. Knepley PetscCall(PetscDSSetConstants(ds, 1, constants));
7209d52c2f21SMatthew G. Knepley PetscCall(PetscDSSetObjective(ds, field, &f0_x));
7210*2a8381b2SBarry Smith PetscCall(DMPlexComputeIntegralFEM(dm, u, &mom, ctx));
7211d52c2f21SMatthew G. Knepley moments[c + 1] = PetscRealPart(mom);
7212d52c2f21SMatthew G. Knepley }
7213d52c2f21SMatthew G. Knepley PetscCall(PetscDSSetObjective(ds, field, &f0_x2));
7214*2a8381b2SBarry Smith PetscCall(DMPlexComputeIntegralFEM(dm, u, &mom, ctx));
721517314648SMatthew G. Knepley moments[cdim + 1] = PetscRealPart(mom);
7216d52c2f21SMatthew G. Knepley PetscCall(PetscDSSetConstants(ds, Ncon, (PetscScalar *)oldConstants));
7217d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS);
7218d52c2f21SMatthew G. Knepley }
7219