1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2da97024aSMatthew G. Knepley #include <petscsf.h> 3cb1e1211SMatthew G Knepley 4af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h> 5af0996ceSBarry Smith #include <petsc/private/petscfvimpl.h> 6a0845e3aSMatthew G. Knepley 746fa42a0SMatthew G. Knepley /*@ 846fa42a0SMatthew G. Knepley DMPlexGetScale - Get the scale for the specified fundamental unit 946fa42a0SMatthew G. Knepley 1046fa42a0SMatthew G. Knepley Not collective 1146fa42a0SMatthew G. Knepley 1246fa42a0SMatthew G. Knepley Input Arguments: 1346fa42a0SMatthew G. Knepley + dm - the DM 1446fa42a0SMatthew G. Knepley - unit - The SI unit 1546fa42a0SMatthew G. Knepley 1646fa42a0SMatthew G. Knepley Output Argument: 1746fa42a0SMatthew G. Knepley . scale - The value used to scale all quantities with this unit 1846fa42a0SMatthew G. Knepley 1946fa42a0SMatthew G. Knepley Level: advanced 2046fa42a0SMatthew G. Knepley 2146fa42a0SMatthew G. Knepley .seealso: DMPlexSetScale(), PetscUnit 2246fa42a0SMatthew G. Knepley @*/ 23cb1e1211SMatthew G Knepley PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 24cb1e1211SMatthew G Knepley { 25cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 26cb1e1211SMatthew G Knepley 27cb1e1211SMatthew G Knepley PetscFunctionBegin; 28cb1e1211SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29cb1e1211SMatthew G Knepley PetscValidPointer(scale, 3); 30cb1e1211SMatthew G Knepley *scale = mesh->scale[unit]; 31cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 32cb1e1211SMatthew G Knepley } 33cb1e1211SMatthew G Knepley 3446fa42a0SMatthew G. Knepley /*@ 3546fa42a0SMatthew G. Knepley DMPlexSetScale - Set the scale for the specified fundamental unit 3646fa42a0SMatthew G. Knepley 3746fa42a0SMatthew G. Knepley Not collective 3846fa42a0SMatthew G. Knepley 3946fa42a0SMatthew G. Knepley Input Arguments: 4046fa42a0SMatthew G. Knepley + dm - the DM 4146fa42a0SMatthew G. Knepley . unit - The SI unit 4246fa42a0SMatthew G. Knepley - scale - The value used to scale all quantities with this unit 4346fa42a0SMatthew G. Knepley 4446fa42a0SMatthew G. Knepley Level: advanced 4546fa42a0SMatthew G. Knepley 4646fa42a0SMatthew G. Knepley .seealso: DMPlexGetScale(), PetscUnit 4746fa42a0SMatthew G. Knepley @*/ 48cb1e1211SMatthew G Knepley PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 49cb1e1211SMatthew G Knepley { 50cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 51cb1e1211SMatthew G Knepley 52cb1e1211SMatthew G Knepley PetscFunctionBegin; 53cb1e1211SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54cb1e1211SMatthew G Knepley mesh->scale[unit] = scale; 55cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 56cb1e1211SMatthew G Knepley } 57cb1e1211SMatthew G Knepley 58d1828a1cSMatthew G. Knepley static PetscErrorCode DMPlexProjectRigidBody_Private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *mode, void *ctx) 59026175e5SToby Isaac { 60*12adca46SMatthew G. Knepley const PetscInt eps[3][3][3] = {{{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, {{0, 0, -1}, {0, 0, 0}, {1, 0, 0}}, {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0}}}; 61026175e5SToby Isaac PetscInt *ctxInt = (PetscInt *) ctx; 62ad917190SMatthew G. Knepley PetscInt dim2 = ctxInt[0]; 63026175e5SToby Isaac PetscInt d = ctxInt[1]; 64026175e5SToby Isaac PetscInt i, j, k = dim > 2 ? d - dim : d; 65026175e5SToby Isaac 66ad917190SMatthew G. Knepley PetscFunctionBegin; 67ad917190SMatthew G. Knepley if (dim != dim2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input dimension %d does not match context dimension %d", dim, dim2); 68026175e5SToby Isaac for (i = 0; i < dim; i++) mode[i] = 0.; 69026175e5SToby Isaac if (d < dim) { 70*12adca46SMatthew G. Knepley mode[d] = 1.; /* Translation along axis d */ 71ad917190SMatthew G. Knepley } else { 72026175e5SToby Isaac for (i = 0; i < dim; i++) { 73026175e5SToby Isaac for (j = 0; j < dim; j++) { 74*12adca46SMatthew G. Knepley mode[j] += eps[i][j][k]*X[i]; /* Rotation about axis d */ 75026175e5SToby Isaac } 76026175e5SToby Isaac } 77026175e5SToby Isaac } 78ad917190SMatthew G. Knepley PetscFunctionReturn(0); 79026175e5SToby Isaac } 80026175e5SToby Isaac 81cb1e1211SMatthew G Knepley /*@C 82*12adca46SMatthew G. Knepley DMPlexCreateRigidBody - For the default global section, create rigid body modes by function space interpolation 83cb1e1211SMatthew G Knepley 84cb1e1211SMatthew G Knepley Collective on DM 85cb1e1211SMatthew G Knepley 86cb1e1211SMatthew G Knepley Input Arguments: 87026175e5SToby Isaac . dm - the DM 88cb1e1211SMatthew G Knepley 89cb1e1211SMatthew G Knepley Output Argument: 90cb1e1211SMatthew G Knepley . sp - the null space 91cb1e1211SMatthew G Knepley 92*12adca46SMatthew G. Knepley Note: This is necessary to provide a suitable coarse space for algebraic multigrid 93cb1e1211SMatthew G Knepley 94cb1e1211SMatthew G Knepley Level: advanced 95cb1e1211SMatthew G Knepley 96*12adca46SMatthew G. Knepley .seealso: MatNullSpaceCreate(), PCGAMG 97cb1e1211SMatthew G Knepley @*/ 98026175e5SToby Isaac PetscErrorCode DMPlexCreateRigidBody(DM dm, MatNullSpace *sp) 99cb1e1211SMatthew G Knepley { 100cb1e1211SMatthew G Knepley MPI_Comm comm; 101026175e5SToby Isaac Vec mode[6]; 102026175e5SToby Isaac PetscSection section, globalSection; 1039d8fbdeaSMatthew G. Knepley PetscInt dim, dimEmbed, n, m, d, i, j; 104cb1e1211SMatthew G Knepley PetscErrorCode ierr; 105cb1e1211SMatthew G Knepley 106cb1e1211SMatthew G Knepley PetscFunctionBegin; 107cb1e1211SMatthew G Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 108c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1099d8fbdeaSMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 110cb1e1211SMatthew G Knepley if (dim == 1) { 111cb1e1211SMatthew G Knepley ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 112cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 113cb1e1211SMatthew G Knepley } 114026175e5SToby Isaac ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 115026175e5SToby Isaac ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 116cb1e1211SMatthew G Knepley ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 117cb1e1211SMatthew G Knepley m = (dim*(dim+1))/2; 118cb1e1211SMatthew G Knepley ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 119cb1e1211SMatthew G Knepley ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 120cb1e1211SMatthew G Knepley ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 121cb1e1211SMatthew G Knepley for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 122026175e5SToby Isaac for (d = 0; d < m; d++) { 123330485fdSToby Isaac PetscInt ctx[2]; 124d1828a1cSMatthew G. Knepley PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *) = DMPlexProjectRigidBody_Private; 125026175e5SToby Isaac void *voidctx = (void *) (&ctx[0]); 126cb1e1211SMatthew G Knepley 1279d8fbdeaSMatthew G. Knepley ctx[0] = dimEmbed; 128330485fdSToby Isaac ctx[1] = d; 1290709b2feSToby Isaac ierr = DMProjectFunction(dm, 0.0, &func, &voidctx, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 130cb1e1211SMatthew G Knepley } 131cb1e1211SMatthew G Knepley for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 132cb1e1211SMatthew G Knepley /* Orthonormalize system */ 133cb1e1211SMatthew G Knepley for (i = dim; i < m; ++i) { 134cb1e1211SMatthew G Knepley PetscScalar dots[6]; 135cb1e1211SMatthew G Knepley 136cb1e1211SMatthew G Knepley ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 137cb1e1211SMatthew G Knepley for (j = 0; j < i; ++j) dots[j] *= -1.0; 138cb1e1211SMatthew G Knepley ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 139cb1e1211SMatthew G Knepley ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 140cb1e1211SMatthew G Knepley } 141cb1e1211SMatthew G Knepley ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 142cb1e1211SMatthew G Knepley for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 143cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 144cb1e1211SMatthew G Knepley } 145cb1e1211SMatthew G Knepley 146*12adca46SMatthew G. Knepley /*@C 147*12adca46SMatthew G. Knepley DMPlexCreateRigidBodies - For the default global section, create rigid body modes by function space interpolation 148*12adca46SMatthew G. Knepley 149*12adca46SMatthew G. Knepley Collective on DM 150*12adca46SMatthew G. Knepley 151*12adca46SMatthew G. Knepley Input Arguments: 152*12adca46SMatthew G. Knepley + dm - the DM 153*12adca46SMatthew G. Knepley . nb - The number of bodies 154*12adca46SMatthew G. Knepley . label - The DMLabel marking each domain 155*12adca46SMatthew G. Knepley . nids - The number of ids per body 156*12adca46SMatthew G. Knepley - ids - An array of the label ids in sequence for each domain 157*12adca46SMatthew G. Knepley 158*12adca46SMatthew G. Knepley Output Argument: 159*12adca46SMatthew G. Knepley . sp - the null space 160*12adca46SMatthew G. Knepley 161*12adca46SMatthew G. Knepley Note: This is necessary to provide a suitable coarse space for algebraic multigrid 162*12adca46SMatthew G. Knepley 163*12adca46SMatthew G. Knepley Level: advanced 164*12adca46SMatthew G. Knepley 165*12adca46SMatthew G. Knepley .seealso: MatNullSpaceCreate() 166*12adca46SMatthew G. Knepley @*/ 167*12adca46SMatthew G. Knepley PetscErrorCode DMPlexCreateRigidBodies(DM dm, PetscInt nb, DMLabel label, const PetscInt nids[], const PetscInt ids[], MatNullSpace *sp) 168*12adca46SMatthew G. Knepley { 169*12adca46SMatthew G. Knepley MPI_Comm comm; 170*12adca46SMatthew G. Knepley PetscSection section, globalSection; 171*12adca46SMatthew G. Knepley Vec *mode; 172*12adca46SMatthew G. Knepley PetscScalar *dots; 173*12adca46SMatthew G. Knepley PetscInt dim, dimEmbed, n, m, b, d, i, j, off; 174*12adca46SMatthew G. Knepley PetscErrorCode ierr; 175*12adca46SMatthew G. Knepley 176*12adca46SMatthew G. Knepley PetscFunctionBegin; 177*12adca46SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 178*12adca46SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 179*12adca46SMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 180*12adca46SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 181*12adca46SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 182*12adca46SMatthew G. Knepley ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 183*12adca46SMatthew G. Knepley m = nb * (dim*(dim+1))/2; 184*12adca46SMatthew G. Knepley ierr = PetscMalloc2(m, &mode, m, &dots);CHKERRQ(ierr); 185*12adca46SMatthew G. Knepley ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 186*12adca46SMatthew G. Knepley ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 187*12adca46SMatthew G. Knepley ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 188*12adca46SMatthew G. Knepley for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 189*12adca46SMatthew G. Knepley for (b = 0, off = 0; b < nb; ++b) { 190*12adca46SMatthew G. Knepley for (d = 0; d < m/nb; ++d) { 191*12adca46SMatthew G. Knepley PetscInt ctx[2]; 192*12adca46SMatthew G. Knepley PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *) = DMPlexProjectRigidBody_Private; 193*12adca46SMatthew G. Knepley void *voidctx = (void *) (&ctx[0]); 194*12adca46SMatthew G. Knepley 195*12adca46SMatthew G. Knepley ctx[0] = dimEmbed; 196*12adca46SMatthew G. Knepley ctx[1] = d; 197*12adca46SMatthew G. Knepley ierr = DMProjectFunctionLabel(dm, 0.0, label, nids[b], &ids[off], 0, NULL, &func, &voidctx, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 198*12adca46SMatthew G. Knepley off += nids[b]; 199*12adca46SMatthew G. Knepley } 200*12adca46SMatthew G. Knepley } 201*12adca46SMatthew G. Knepley for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 202*12adca46SMatthew G. Knepley /* Orthonormalize system */ 203*12adca46SMatthew G. Knepley for (i = 0; i < m; ++i) { 204*12adca46SMatthew G. Knepley ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 205*12adca46SMatthew G. Knepley for (j = 0; j < i; ++j) dots[j] *= -1.0; 206*12adca46SMatthew G. Knepley ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 207*12adca46SMatthew G. Knepley ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 208*12adca46SMatthew G. Knepley } 209*12adca46SMatthew G. Knepley ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 210*12adca46SMatthew G. Knepley for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 211*12adca46SMatthew G. Knepley ierr = PetscFree2(mode, dots);CHKERRQ(ierr); 212*12adca46SMatthew G. Knepley PetscFunctionReturn(0); 213*12adca46SMatthew G. Knepley } 214*12adca46SMatthew G. Knepley 215b29cfa1cSToby Isaac /*@ 216b29cfa1cSToby Isaac DMPlexSetMaxProjectionHeight - In DMPlexProjectXXXLocal() functions, the projected values of a basis function's dofs 217b29cfa1cSToby Isaac are computed by associating the basis function with one of the mesh points in its transitively-closed support, and 218b29cfa1cSToby Isaac evaluating the dual space basis of that point. A basis function is associated with the point in its 219b29cfa1cSToby Isaac transitively-closed support whose mesh height is highest (w.r.t. DAG height), but not greater than the maximum 220b29cfa1cSToby Isaac projection height, which is set with this function. By default, the maximum projection height is zero, which means 221b29cfa1cSToby Isaac that only mesh cells are used to project basis functions. A height of one, for example, evaluates a cell-interior 222b29cfa1cSToby Isaac basis functions using its cells dual space basis, but all other basis functions with the dual space basis of a face. 223b29cfa1cSToby Isaac 224b29cfa1cSToby Isaac Input Parameters: 225b29cfa1cSToby Isaac + dm - the DMPlex object 226b29cfa1cSToby Isaac - height - the maximum projection height >= 0 227b29cfa1cSToby Isaac 228b29cfa1cSToby Isaac Level: advanced 229b29cfa1cSToby Isaac 2304d6f44ffSToby Isaac .seealso: DMPlexGetMaxProjectionHeight(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal() 231b29cfa1cSToby Isaac @*/ 232b29cfa1cSToby Isaac PetscErrorCode DMPlexSetMaxProjectionHeight(DM dm, PetscInt height) 233b29cfa1cSToby Isaac { 234b29cfa1cSToby Isaac DM_Plex *plex = (DM_Plex *) dm->data; 235b29cfa1cSToby Isaac 236b29cfa1cSToby Isaac PetscFunctionBegin; 237b29cfa1cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 238b29cfa1cSToby Isaac plex->maxProjectionHeight = height; 239b29cfa1cSToby Isaac PetscFunctionReturn(0); 240b29cfa1cSToby Isaac } 241b29cfa1cSToby Isaac 242b29cfa1cSToby Isaac /*@ 243b29cfa1cSToby Isaac DMPlexGetMaxProjectionHeight - Get the maximum height (w.r.t. DAG) of mesh points used to evaluate dual bases in 244b29cfa1cSToby Isaac DMPlexProjectXXXLocal() functions. 245b29cfa1cSToby Isaac 246b29cfa1cSToby Isaac Input Parameters: 247b29cfa1cSToby Isaac . dm - the DMPlex object 248b29cfa1cSToby Isaac 249b29cfa1cSToby Isaac Output Parameters: 250b29cfa1cSToby Isaac . height - the maximum projection height 251b29cfa1cSToby Isaac 252b29cfa1cSToby Isaac Level: intermediate 253b29cfa1cSToby Isaac 2544d6f44ffSToby Isaac .seealso: DMPlexSetMaxProjectionHeight(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal() 255b29cfa1cSToby Isaac @*/ 256b29cfa1cSToby Isaac PetscErrorCode DMPlexGetMaxProjectionHeight(DM dm, PetscInt *height) 257b29cfa1cSToby Isaac { 258b29cfa1cSToby Isaac DM_Plex *plex = (DM_Plex *) dm->data; 259b29cfa1cSToby Isaac 260b29cfa1cSToby Isaac PetscFunctionBegin; 261b29cfa1cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 262b29cfa1cSToby Isaac *height = plex->maxProjectionHeight; 263b29cfa1cSToby Isaac PetscFunctionReturn(0); 264b29cfa1cSToby Isaac } 265b29cfa1cSToby Isaac 266b278463cSMatthew G. Knepley /*@C 267b278463cSMatthew G. Knepley DMPlexInsertBoundaryValuesEssential - Insert boundary values into a local vector 268b278463cSMatthew G. Knepley 269b278463cSMatthew G. Knepley Input Parameters: 270b278463cSMatthew G. Knepley + dm - The DM, with a PetscDS that matches the problem being constrained 271b278463cSMatthew G. Knepley . time - The time 272b278463cSMatthew G. Knepley . field - The field to constrain 2731c531cf8SMatthew G. Knepley . Nc - The number of constrained field components, or 0 for all components 2741c531cf8SMatthew G. Knepley . comps - An array of constrained component numbers, or NULL for all components 275b278463cSMatthew G. Knepley . label - The DMLabel defining constrained points 276b278463cSMatthew G. Knepley . numids - The number of DMLabel ids for constrained points 277b278463cSMatthew G. Knepley . ids - An array of ids for constrained points 278b278463cSMatthew G. Knepley . func - A pointwise function giving boundary values 279b278463cSMatthew G. Knepley - ctx - An optional user context for bcFunc 280b278463cSMatthew G. Knepley 281b278463cSMatthew G. Knepley Output Parameter: 282b278463cSMatthew G. Knepley . locX - A local vector to receives the boundary values 283b278463cSMatthew G. Knepley 284b278463cSMatthew G. Knepley Level: developer 285b278463cSMatthew G. Knepley 286b278463cSMatthew G. Knepley .seealso: DMPlexInsertBoundaryValuesEssentialField(), DMAddBoundary() 287b278463cSMatthew G. Knepley @*/ 2881c531cf8SMatthew G. Knepley 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 *), void *ctx, Vec locX) 28955f2e967SMatthew G. Knepley { 2900163fd50SMatthew G. Knepley PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 29155f2e967SMatthew G. Knepley void **ctxs; 292d7ddef95SMatthew G. Knepley PetscInt numFields; 293d7ddef95SMatthew G. Knepley PetscErrorCode ierr; 294d7ddef95SMatthew G. Knepley 295d7ddef95SMatthew G. Knepley PetscFunctionBegin; 296d7ddef95SMatthew G. Knepley ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 297d7ddef95SMatthew G. Knepley ierr = PetscCalloc2(numFields,&funcs,numFields,&ctxs);CHKERRQ(ierr); 298d7ddef95SMatthew G. Knepley funcs[field] = func; 299d7ddef95SMatthew G. Knepley ctxs[field] = ctx; 3001c531cf8SMatthew G. Knepley ierr = DMProjectFunctionLabelLocal(dm, time, label, numids, ids, Nc, comps, funcs, ctxs, INSERT_BC_VALUES, locX);CHKERRQ(ierr); 301d7ddef95SMatthew G. Knepley ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr); 302d7ddef95SMatthew G. Knepley PetscFunctionReturn(0); 303d7ddef95SMatthew G. Knepley } 304d7ddef95SMatthew G. Knepley 305b278463cSMatthew G. Knepley /*@C 306b278463cSMatthew G. Knepley DMPlexInsertBoundaryValuesEssentialField - Insert boundary values into a local vector 307b278463cSMatthew G. Knepley 308b278463cSMatthew G. Knepley Input Parameters: 309b278463cSMatthew G. Knepley + dm - The DM, with a PetscDS that matches the problem being constrained 310b278463cSMatthew G. Knepley . time - The time 311b278463cSMatthew G. Knepley . locU - A local vector with the input solution values 312b278463cSMatthew G. Knepley . field - The field to constrain 3131c531cf8SMatthew G. Knepley . Nc - The number of constrained field components, or 0 for all components 3141c531cf8SMatthew G. Knepley . comps - An array of constrained component numbers, or NULL for all components 315b278463cSMatthew G. Knepley . label - The DMLabel defining constrained points 316b278463cSMatthew G. Knepley . numids - The number of DMLabel ids for constrained points 317b278463cSMatthew G. Knepley . ids - An array of ids for constrained points 318b278463cSMatthew G. Knepley . func - A pointwise function giving boundary values 319b278463cSMatthew G. Knepley - ctx - An optional user context for bcFunc 320b278463cSMatthew G. Knepley 321b278463cSMatthew G. Knepley Output Parameter: 322b278463cSMatthew G. Knepley . locX - A local vector to receives the boundary values 323b278463cSMatthew G. Knepley 324b278463cSMatthew G. Knepley Level: developer 325b278463cSMatthew G. Knepley 326b278463cSMatthew G. Knepley .seealso: DMPlexInsertBoundaryValuesEssential(), DMAddBoundary() 327b278463cSMatthew G. Knepley @*/ 3281c531cf8SMatthew G. Knepley PetscErrorCode DMPlexInsertBoundaryValuesEssentialField(DM dm, PetscReal time, Vec locU, PetscInt field, PetscInt Nc, const PetscInt comps[], DMLabel label, PetscInt numids, const PetscInt ids[], 329c60e475cSMatthew G. Knepley void (*func)(PetscInt, PetscInt, PetscInt, 330c60e475cSMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 331c60e475cSMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 33297b6e6e8SMatthew G. Knepley PetscReal, const PetscReal[], PetscInt, const PetscScalar[], 333b278463cSMatthew G. Knepley PetscScalar[]), 334b278463cSMatthew G. Knepley void *ctx, Vec locX) 335c60e475cSMatthew G. Knepley { 336c60e475cSMatthew G. Knepley void (**funcs)(PetscInt, PetscInt, PetscInt, 337c60e475cSMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 338c60e475cSMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 33997b6e6e8SMatthew G. Knepley PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]); 340c60e475cSMatthew G. Knepley void **ctxs; 341c60e475cSMatthew G. Knepley PetscInt numFields; 342c60e475cSMatthew G. Knepley PetscErrorCode ierr; 343c60e475cSMatthew G. Knepley 344c60e475cSMatthew G. Knepley PetscFunctionBegin; 345c60e475cSMatthew G. Knepley ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 346c60e475cSMatthew G. Knepley ierr = PetscCalloc2(numFields,&funcs,numFields,&ctxs);CHKERRQ(ierr); 347c60e475cSMatthew G. Knepley funcs[field] = func; 348c60e475cSMatthew G. Knepley ctxs[field] = ctx; 3491c531cf8SMatthew G. Knepley ierr = DMProjectFieldLabelLocal(dm, time, label, numids, ids, Nc, comps, locU, funcs, INSERT_BC_VALUES, locX);CHKERRQ(ierr); 350c60e475cSMatthew G. Knepley ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr); 351c60e475cSMatthew G. Knepley PetscFunctionReturn(0); 352c60e475cSMatthew G. Knepley } 353c60e475cSMatthew G. Knepley 354b278463cSMatthew G. Knepley /*@C 355b278463cSMatthew G. Knepley DMPlexInsertBoundaryValuesRiemann - Insert boundary values into a local vector 356b278463cSMatthew G. Knepley 357b278463cSMatthew G. Knepley Input Parameters: 358b278463cSMatthew G. Knepley + dm - The DM, with a PetscDS that matches the problem being constrained 359b278463cSMatthew G. Knepley . time - The time 360b278463cSMatthew G. Knepley . faceGeometry - A vector with the FVM face geometry information 361b278463cSMatthew G. Knepley . cellGeometry - A vector with the FVM cell geometry information 362b278463cSMatthew G. Knepley . Grad - A vector with the FVM cell gradient information 363b278463cSMatthew G. Knepley . field - The field to constrain 3641c531cf8SMatthew G. Knepley . Nc - The number of constrained field components, or 0 for all components 3651c531cf8SMatthew G. Knepley . comps - An array of constrained component numbers, or NULL for all components 366b278463cSMatthew G. Knepley . label - The DMLabel defining constrained points 367b278463cSMatthew G. Knepley . numids - The number of DMLabel ids for constrained points 368b278463cSMatthew G. Knepley . ids - An array of ids for constrained points 369b278463cSMatthew G. Knepley . func - A pointwise function giving boundary values 370b278463cSMatthew G. Knepley - ctx - An optional user context for bcFunc 371b278463cSMatthew G. Knepley 372b278463cSMatthew G. Knepley Output Parameter: 373b278463cSMatthew G. Knepley . locX - A local vector to receives the boundary values 374b278463cSMatthew G. Knepley 375b278463cSMatthew G. Knepley Note: This implementation currently ignores the numcomps/comps argument from DMAddBoundary() 376b278463cSMatthew G. Knepley 377b278463cSMatthew G. Knepley Level: developer 378b278463cSMatthew G. Knepley 379b278463cSMatthew G. Knepley .seealso: DMPlexInsertBoundaryValuesEssential(), DMPlexInsertBoundaryValuesEssentialField(), DMAddBoundary() 380b278463cSMatthew G. Knepley @*/ 3811c531cf8SMatthew G. Knepley 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[], 382b278463cSMatthew G. Knepley PetscErrorCode (*func)(PetscReal,const PetscReal*,const PetscReal*,const PetscScalar*,PetscScalar*,void*), void *ctx, Vec locX) 383d7ddef95SMatthew G. Knepley { 38461f58d28SMatthew G. Knepley PetscDS prob; 385da97024aSMatthew G. Knepley PetscSF sf; 386d7ddef95SMatthew G. Knepley DM dmFace, dmCell, dmGrad; 38720369375SToby Isaac const PetscScalar *facegeom, *cellgeom = NULL, *grad; 388da97024aSMatthew G. Knepley const PetscInt *leaves; 389d7ddef95SMatthew G. Knepley PetscScalar *x, *fx; 390520b3818SMatthew G. Knepley PetscInt dim, nleaves, loc, fStart, fEnd, pdim, i; 391e735a8a9SMatthew G. Knepley PetscErrorCode ierr, ierru = 0; 392d7ddef95SMatthew G. Knepley 393d7ddef95SMatthew G. Knepley PetscFunctionBegin; 394da97024aSMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 395da97024aSMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL);CHKERRQ(ierr); 396da97024aSMatthew G. Knepley nleaves = PetscMax(0, nleaves); 397d7ddef95SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 398d7ddef95SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 39961f58d28SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 400d7ddef95SMatthew G. Knepley ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr); 401d7ddef95SMatthew G. Knepley ierr = VecGetArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 40220369375SToby Isaac if (cellGeometry) { 403d7ddef95SMatthew G. Knepley ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr); 404d7ddef95SMatthew G. Knepley ierr = VecGetArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); 40520369375SToby Isaac } 406d7ddef95SMatthew G. Knepley if (Grad) { 407c0a6632aSMatthew G. Knepley PetscFV fv; 408c0a6632aSMatthew G. Knepley 409c0a6632aSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fv);CHKERRQ(ierr); 410d7ddef95SMatthew G. Knepley ierr = VecGetDM(Grad, &dmGrad);CHKERRQ(ierr); 411d7ddef95SMatthew G. Knepley ierr = VecGetArrayRead(Grad, &grad);CHKERRQ(ierr); 412d7ddef95SMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &pdim);CHKERRQ(ierr); 413d7ddef95SMatthew G. Knepley ierr = DMGetWorkArray(dm, pdim, PETSC_SCALAR, &fx);CHKERRQ(ierr); 414d7ddef95SMatthew G. Knepley } 415d7ddef95SMatthew G. Knepley ierr = VecGetArray(locX, &x);CHKERRQ(ierr); 416d7ddef95SMatthew G. Knepley for (i = 0; i < numids; ++i) { 417d7ddef95SMatthew G. Knepley IS faceIS; 418d7ddef95SMatthew G. Knepley const PetscInt *faces; 419d7ddef95SMatthew G. Knepley PetscInt numFaces, f; 420d7ddef95SMatthew G. Knepley 421d7ddef95SMatthew G. Knepley ierr = DMLabelGetStratumIS(label, ids[i], &faceIS);CHKERRQ(ierr); 422d7ddef95SMatthew G. Knepley if (!faceIS) continue; /* No points with that id on this process */ 423d7ddef95SMatthew G. Knepley ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 424d7ddef95SMatthew G. Knepley ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 425d7ddef95SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 426d7ddef95SMatthew G. Knepley const PetscInt face = faces[f], *cells; 427640bce14SSatish Balay PetscFVFaceGeom *fg; 428d7ddef95SMatthew G. Knepley 429d7ddef95SMatthew G. Knepley if ((face < fStart) || (face >= fEnd)) continue; /* Refinement adds non-faces to labels */ 430da97024aSMatthew G. Knepley ierr = PetscFindInt(face, nleaves, (PetscInt *) leaves, &loc);CHKERRQ(ierr); 431da97024aSMatthew G. Knepley if (loc >= 0) continue; 432d7ddef95SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr); 433d7ddef95SMatthew G. Knepley ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr); 434d7ddef95SMatthew G. Knepley if (Grad) { 435640bce14SSatish Balay PetscFVCellGeom *cg; 436640bce14SSatish Balay PetscScalar *cx, *cgrad; 437d7ddef95SMatthew G. Knepley PetscScalar *xG; 438d7ddef95SMatthew G. Knepley PetscReal dx[3]; 439d7ddef95SMatthew G. Knepley PetscInt d; 440d7ddef95SMatthew G. Knepley 441d7ddef95SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cg);CHKERRQ(ierr); 442d7ddef95SMatthew G. Knepley ierr = DMPlexPointLocalRead(dm, cells[0], x, &cx);CHKERRQ(ierr); 443d7ddef95SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmGrad, cells[0], grad, &cgrad);CHKERRQ(ierr); 444520b3818SMatthew G. Knepley ierr = DMPlexPointLocalFieldRef(dm, cells[1], field, x, &xG);CHKERRQ(ierr); 445d7ddef95SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, cg->centroid, fg->centroid, dx); 446d7ddef95SMatthew G. Knepley for (d = 0; d < pdim; ++d) fx[d] = cx[d] + DMPlex_DotD_Internal(dim, &cgrad[d*dim], dx); 447e735a8a9SMatthew G. Knepley ierru = (*func)(time, fg->centroid, fg->normal, fx, xG, ctx); 448e735a8a9SMatthew G. Knepley if (ierru) { 449e735a8a9SMatthew G. Knepley ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 450e735a8a9SMatthew G. Knepley ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 451e735a8a9SMatthew G. Knepley goto cleanup; 452e735a8a9SMatthew G. Knepley } 453d7ddef95SMatthew G. Knepley } else { 454640bce14SSatish Balay PetscScalar *xI; 455d7ddef95SMatthew G. Knepley PetscScalar *xG; 456d7ddef95SMatthew G. Knepley 457d7ddef95SMatthew G. Knepley ierr = DMPlexPointLocalRead(dm, cells[0], x, &xI);CHKERRQ(ierr); 458520b3818SMatthew G. Knepley ierr = DMPlexPointLocalFieldRef(dm, cells[1], field, x, &xG);CHKERRQ(ierr); 459e735a8a9SMatthew G. Knepley ierru = (*func)(time, fg->centroid, fg->normal, xI, xG, ctx); 460e735a8a9SMatthew G. Knepley if (ierru) { 461e735a8a9SMatthew G. Knepley ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 462e735a8a9SMatthew G. Knepley ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 463e735a8a9SMatthew G. Knepley goto cleanup; 464e735a8a9SMatthew G. Knepley } 465d7ddef95SMatthew G. Knepley } 466d7ddef95SMatthew G. Knepley } 467d7ddef95SMatthew G. Knepley ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 468d7ddef95SMatthew G. Knepley ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 469d7ddef95SMatthew G. Knepley } 470e735a8a9SMatthew G. Knepley cleanup: 471d7ddef95SMatthew G. Knepley ierr = VecRestoreArray(locX, &x);CHKERRQ(ierr); 472d7ddef95SMatthew G. Knepley if (Grad) { 473d7ddef95SMatthew G. Knepley ierr = DMRestoreWorkArray(dm, pdim, PETSC_SCALAR, &fx);CHKERRQ(ierr); 474d7ddef95SMatthew G. Knepley ierr = VecRestoreArrayRead(Grad, &grad);CHKERRQ(ierr); 475d7ddef95SMatthew G. Knepley } 476e735a8a9SMatthew G. Knepley if (cellGeometry) {ierr = VecRestoreArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr);} 477d7ddef95SMatthew G. Knepley ierr = VecRestoreArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 478e735a8a9SMatthew G. Knepley CHKERRQ(ierru); 479d7ddef95SMatthew G. Knepley PetscFunctionReturn(0); 480d7ddef95SMatthew G. Knepley } 481d7ddef95SMatthew G. Knepley 482f1d73a7aSMatthew G. Knepley PetscErrorCode DMPlexInsertBoundaryValues_Plex(DM dm, PetscBool insertEssential, Vec locX, PetscReal time, Vec faceGeomFVM, Vec cellGeomFVM, Vec gradFVM) 483d7ddef95SMatthew G. Knepley { 484d7ddef95SMatthew G. Knepley PetscInt numBd, b; 48555f2e967SMatthew G. Knepley PetscErrorCode ierr; 48655f2e967SMatthew G. Knepley 48755f2e967SMatthew G. Knepley PetscFunctionBegin; 488dff059c6SToby Isaac ierr = PetscDSGetNumBoundary(dm->prob, &numBd);CHKERRQ(ierr); 48955f2e967SMatthew G. Knepley for (b = 0; b < numBd; ++b) { 490f971fd6bSMatthew G. Knepley DMBoundaryConditionType type; 491d7ddef95SMatthew G. Knepley const char *labelname; 492d7ddef95SMatthew G. Knepley DMLabel label; 4931c531cf8SMatthew G. Knepley PetscInt field, Nc; 4941c531cf8SMatthew G. Knepley const PetscInt *comps; 495d7ddef95SMatthew G. Knepley PetscObject obj; 496d7ddef95SMatthew G. Knepley PetscClassId id; 497a30ec4eaSSatish Balay void (*func)(void); 498d7ddef95SMatthew G. Knepley PetscInt numids; 499d7ddef95SMatthew G. Knepley const PetscInt *ids; 50055f2e967SMatthew G. Knepley void *ctx; 50155f2e967SMatthew G. Knepley 5021c531cf8SMatthew G. Knepley ierr = DMGetBoundary(dm, b, &type, NULL, &labelname, &field, &Nc, &comps, &func, &numids, &ids, &ctx);CHKERRQ(ierr); 503f971fd6bSMatthew G. Knepley if (insertEssential != (type & DM_BC_ESSENTIAL)) continue; 504c58f1c22SToby Isaac ierr = DMGetLabel(dm, labelname, &label);CHKERRQ(ierr); 505d7ddef95SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 506d7ddef95SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 507d7ddef95SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 508c60e475cSMatthew G. Knepley switch (type) { 509c60e475cSMatthew G. Knepley /* for FEM, there is no insertion to be done for non-essential boundary conditions */ 510c60e475cSMatthew G. Knepley case DM_BC_ESSENTIAL: 511092e5057SToby Isaac ierr = DMPlexLabelAddCells(dm,label);CHKERRQ(ierr); 5121c531cf8SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesEssential(dm, time, field, Nc, comps, label, numids, ids, (PetscErrorCode (*)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *)) func, ctx, locX);CHKERRQ(ierr); 513092e5057SToby Isaac ierr = DMPlexLabelClearCells(dm,label);CHKERRQ(ierr); 514c60e475cSMatthew G. Knepley break; 515c60e475cSMatthew G. Knepley case DM_BC_ESSENTIAL_FIELD: 516c60e475cSMatthew G. Knepley ierr = DMPlexLabelAddCells(dm,label);CHKERRQ(ierr); 5171c531cf8SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesEssentialField(dm, time, locX, field, Nc, comps, label, numids, ids, 518b278463cSMatthew G. Knepley (void (*)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 519c60e475cSMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 52097b6e6e8SMatthew G. Knepley PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[])) func, ctx, locX);CHKERRQ(ierr); 521c60e475cSMatthew G. Knepley ierr = DMPlexLabelClearCells(dm,label);CHKERRQ(ierr); 522c60e475cSMatthew G. Knepley break; 523c60e475cSMatthew G. Knepley default: break; 524c60e475cSMatthew G. Knepley } 525d7ddef95SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 52643ea7facSMatthew G. Knepley if (!faceGeomFVM) continue; 5271c531cf8SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesRiemann(dm, time, faceGeomFVM, cellGeomFVM, gradFVM, field, Nc, comps, label, numids, ids, 528b278463cSMatthew G. Knepley (PetscErrorCode (*)(PetscReal,const PetscReal*,const PetscReal*,const PetscScalar*,PetscScalar*,void*)) func, ctx, locX);CHKERRQ(ierr); 529d7ddef95SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 53055f2e967SMatthew G. Knepley } 53155f2e967SMatthew G. Knepley PetscFunctionReturn(0); 53255f2e967SMatthew G. Knepley } 53355f2e967SMatthew G. Knepley 534f1d73a7aSMatthew G. Knepley /*@ 535f1d73a7aSMatthew G. Knepley DMPlexInsertBoundaryValues - Puts coefficients which represent boundary values into the local solution vector 536f1d73a7aSMatthew G. Knepley 537f1d73a7aSMatthew G. Knepley Input Parameters: 538f1d73a7aSMatthew G. Knepley + dm - The DM 539f1d73a7aSMatthew G. Knepley . insertEssential - Should I insert essential (e.g. Dirichlet) or inessential (e.g. Neumann) boundary conditions 540f1d73a7aSMatthew G. Knepley . time - The time 541f1d73a7aSMatthew G. Knepley . faceGeomFVM - Face geometry data for FV discretizations 542f1d73a7aSMatthew G. Knepley . cellGeomFVM - Cell geometry data for FV discretizations 543f1d73a7aSMatthew G. Knepley - gradFVM - Gradient reconstruction data for FV discretizations 544f1d73a7aSMatthew G. Knepley 545f1d73a7aSMatthew G. Knepley Output Parameters: 546f1d73a7aSMatthew G. Knepley . locX - Solution updated with boundary values 547f1d73a7aSMatthew G. Knepley 548f1d73a7aSMatthew G. Knepley Level: developer 549f1d73a7aSMatthew G. Knepley 550f1d73a7aSMatthew G. Knepley .seealso: DMProjectFunctionLabelLocal() 551f1d73a7aSMatthew G. Knepley @*/ 552f1d73a7aSMatthew G. Knepley PetscErrorCode DMPlexInsertBoundaryValues(DM dm, PetscBool insertEssential, Vec locX, PetscReal time, Vec faceGeomFVM, Vec cellGeomFVM, Vec gradFVM) 553f1d73a7aSMatthew G. Knepley { 554f1d73a7aSMatthew G. Knepley PetscErrorCode ierr; 555f1d73a7aSMatthew G. Knepley 556f1d73a7aSMatthew G. Knepley PetscFunctionBegin; 557f1d73a7aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 558f1d73a7aSMatthew G. Knepley PetscValidHeaderSpecific(locX, VEC_CLASSID, 2); 559f1d73a7aSMatthew G. Knepley if (faceGeomFVM) {PetscValidHeaderSpecific(faceGeomFVM, VEC_CLASSID, 4);} 560f1d73a7aSMatthew G. Knepley if (cellGeomFVM) {PetscValidHeaderSpecific(cellGeomFVM, VEC_CLASSID, 5);} 561f1d73a7aSMatthew G. Knepley if (gradFVM) {PetscValidHeaderSpecific(gradFVM, VEC_CLASSID, 6);} 562f1d73a7aSMatthew G. Knepley ierr = PetscTryMethod(dm,"DMPlexInsertBoundaryValues_C",(DM,PetscBool,Vec,PetscReal,Vec,Vec,Vec),(dm,insertEssential,locX,time,faceGeomFVM,cellGeomFVM,gradFVM));CHKERRQ(ierr); 563f1d73a7aSMatthew G. Knepley PetscFunctionReturn(0); 564f1d73a7aSMatthew G. Knepley } 565f1d73a7aSMatthew G. Knepley 5660709b2feSToby Isaac PetscErrorCode DMComputeL2Diff_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 567cb1e1211SMatthew G Knepley { 568cb1e1211SMatthew G Knepley const PetscInt debug = 0; 569cb1e1211SMatthew G Knepley PetscSection section; 570c5bbbd5bSMatthew G. Knepley PetscQuadrature quad; 571cb1e1211SMatthew G Knepley Vec localX; 57215496722SMatthew G. Knepley PetscScalar *funcVal, *interpolant; 5737318780aSToby Isaac PetscReal *coords, *detJ, *J; 574cb1e1211SMatthew G Knepley PetscReal localDiff = 0.0; 5757318780aSToby Isaac const PetscReal *quadWeights; 5769c3cf19fSMatthew G. Knepley PetscInt dim, coordDim, numFields, numComponents = 0, qNc, Nq, cStart, cEnd, cEndInterior, c, field, fieldOffset; 577cb1e1211SMatthew G Knepley PetscErrorCode ierr; 578cb1e1211SMatthew G Knepley 579cb1e1211SMatthew G Knepley PetscFunctionBegin; 580c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5817318780aSToby Isaac ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 582cb1e1211SMatthew G Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 583cb1e1211SMatthew G Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 584cb1e1211SMatthew G Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 585bdd6f66aSToby Isaac ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 586cb1e1211SMatthew G Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 587cb1e1211SMatthew G Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 588cb1e1211SMatthew G Knepley for (field = 0; field < numFields; ++field) { 58915496722SMatthew G. Knepley PetscObject obj; 59015496722SMatthew G. Knepley PetscClassId id; 591c5bbbd5bSMatthew G. Knepley PetscInt Nc; 592c5bbbd5bSMatthew G. Knepley 59315496722SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 59415496722SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 59515496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 59615496722SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 59715496722SMatthew G. Knepley 5980f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 5990f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 60015496722SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 60115496722SMatthew G. Knepley PetscFV fv = (PetscFV) obj; 60215496722SMatthew G. Knepley 60315496722SMatthew G. Knepley ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 60415496722SMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 60515496722SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 606c5bbbd5bSMatthew G. Knepley numComponents += Nc; 607cb1e1211SMatthew G Knepley } 6089c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, NULL, &quadWeights);CHKERRQ(ierr); 609beaa55a6SMatthew G. Knepley if ((qNc != 1) && (qNc != numComponents)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_SIZ, "Quadrature components %D != %D field components", qNc, numComponents); 6107318780aSToby Isaac ierr = PetscMalloc5(numComponents,&funcVal,numComponents,&interpolant,coordDim*Nq,&coords,Nq,&detJ,coordDim*coordDim*Nq,&J);CHKERRQ(ierr); 611cb1e1211SMatthew G Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6129ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 6139ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 614cb1e1211SMatthew G Knepley for (c = cStart; c < cEnd; ++c) { 615a1e44745SMatthew G. Knepley PetscScalar *x = NULL; 616cb1e1211SMatthew G Knepley PetscReal elemDiff = 0.0; 6179c3cf19fSMatthew G. Knepley PetscInt qc = 0; 618cb1e1211SMatthew G Knepley 6197318780aSToby Isaac ierr = DMPlexComputeCellGeometryFEM(dm, c, quad, coords, J, NULL, detJ);CHKERRQ(ierr); 620cb1e1211SMatthew G Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 621cb1e1211SMatthew G Knepley 62215496722SMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) { 62315496722SMatthew G. Knepley PetscObject obj; 62415496722SMatthew G. Knepley PetscClassId id; 625c110b1eeSGeoffrey Irving void * const ctx = ctxs ? ctxs[field] : NULL; 62615496722SMatthew G. Knepley PetscInt Nb, Nc, q, fc; 627cb1e1211SMatthew G Knepley 62815496722SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 62915496722SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 63015496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 63115496722SMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 63215496722SMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 633cb1e1211SMatthew G Knepley if (debug) { 634cb1e1211SMatthew G Knepley char title[1024]; 635cb1e1211SMatthew G Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 63615496722SMatthew G. Knepley ierr = DMPrintCellVector(c, title, Nb*Nc, &x[fieldOffset]);CHKERRQ(ierr); 637cb1e1211SMatthew G Knepley } 6387318780aSToby Isaac for (q = 0; q < Nq; ++q) { 6397318780aSToby Isaac if (detJ[q] <= 0.0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D, point %D", detJ[q], c, q); 6407318780aSToby Isaac ierr = (*funcs[field])(coordDim, time, &coords[coordDim * q], Nc, funcVal, ctx); 641e735a8a9SMatthew G. Knepley if (ierr) { 642e735a8a9SMatthew G. Knepley PetscErrorCode ierr2; 643e735a8a9SMatthew G. Knepley ierr2 = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr2); 644e735a8a9SMatthew G. Knepley ierr2 = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr2); 6457318780aSToby Isaac ierr2 = PetscFree5(funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr2); 646e735a8a9SMatthew G. Knepley CHKERRQ(ierr); 647e735a8a9SMatthew G. Knepley } 64815496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 64915496722SMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 65015496722SMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 65115496722SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 652beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q*qNc+(qNc == 1 ? 0 : qc+fc)]; 653beaa55a6SMatthew G. Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]);CHKERRQ(ierr);} 654beaa55a6SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]; 655cb1e1211SMatthew G Knepley } 656cb1e1211SMatthew G Knepley } 6579c3cf19fSMatthew G. Knepley fieldOffset += Nb; 658beaa55a6SMatthew G. Knepley qc += Nc; 659cb1e1211SMatthew G Knepley } 660cb1e1211SMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 661cb1e1211SMatthew G Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 662cb1e1211SMatthew G Knepley localDiff += elemDiff; 663cb1e1211SMatthew G Knepley } 6647318780aSToby Isaac ierr = PetscFree5(funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr); 665cb1e1211SMatthew G Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 666b2566f29SBarry Smith ierr = MPIU_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 667cb1e1211SMatthew G Knepley *diff = PetscSqrtReal(*diff); 668cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 669cb1e1211SMatthew G Knepley } 670cb1e1211SMatthew G Knepley 671b698f381SToby Isaac 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) 672cb1e1211SMatthew G Knepley { 67340e14135SMatthew G. Knepley const PetscInt debug = 0; 674cb1e1211SMatthew G Knepley PetscSection section; 67540e14135SMatthew G. Knepley PetscQuadrature quad; 67640e14135SMatthew G. Knepley Vec localX; 6779c3cf19fSMatthew G. Knepley PetscScalar *funcVal, *interpolant; 6789c3cf19fSMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 6797318780aSToby Isaac PetscReal *coords, *realSpaceDer, *J, *invJ, *detJ; 68040e14135SMatthew G. Knepley PetscReal localDiff = 0.0; 6819c3cf19fSMatthew G. Knepley PetscInt dim, coordDim, qNc = 0, Nq = 0, numFields, numComponents = 0, cStart, cEnd, cEndInterior, c, field, fieldOffset; 682cb1e1211SMatthew G Knepley PetscErrorCode ierr; 683cb1e1211SMatthew G Knepley 684cb1e1211SMatthew G Knepley PetscFunctionBegin; 685c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6867318780aSToby Isaac ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 68740e14135SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 68840e14135SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 68940e14135SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 69040e14135SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 69140e14135SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 692652b88e8SMatthew G. Knepley for (field = 0; field < numFields; ++field) { 6930f2d7e86SMatthew G. Knepley PetscFE fe; 69440e14135SMatthew G. Knepley PetscInt Nc; 695652b88e8SMatthew G. Knepley 6960f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 6970f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 6980f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 69940e14135SMatthew G. Knepley numComponents += Nc; 700652b88e8SMatthew G. Knepley } 7019c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr); 702beaa55a6SMatthew G. Knepley if ((qNc != 1) && (qNc != numComponents)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_SIZ, "Quadrature components %D != %D field components", qNc, numComponents); 7034d6f44ffSToby Isaac /* ierr = DMProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); */ 7049c3cf19fSMatthew G. Knepley ierr = PetscMalloc7(numComponents,&funcVal,coordDim*Nq,&coords,coordDim*Nq,&realSpaceDer,coordDim*coordDim*Nq,&J,coordDim*coordDim*Nq,&invJ,numComponents,&interpolant,Nq,&detJ);CHKERRQ(ierr); 70540e14135SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7069ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 7079ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 70840e14135SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 70940e14135SMatthew G. Knepley PetscScalar *x = NULL; 71040e14135SMatthew G. Knepley PetscReal elemDiff = 0.0; 7119c3cf19fSMatthew G. Knepley PetscInt qc = 0; 712652b88e8SMatthew G. Knepley 7137318780aSToby Isaac ierr = DMPlexComputeCellGeometryFEM(dm, c, quad, coords, J, invJ, detJ);CHKERRQ(ierr); 71440e14135SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 71540e14135SMatthew G. Knepley 7169c3cf19fSMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) { 7170f2d7e86SMatthew G. Knepley PetscFE fe; 71851259fa3SMatthew G. Knepley void * const ctx = ctxs ? ctxs[field] : NULL; 71940e14135SMatthew G. Knepley PetscReal *basisDer; 7209c3cf19fSMatthew G. Knepley PetscInt Nb, Nc, q, fc; 72140e14135SMatthew G. Knepley 7220f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 7230f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 7249c3cf19fSMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 7250f2d7e86SMatthew G. Knepley ierr = PetscFEGetDefaultTabulation(fe, NULL, &basisDer, NULL);CHKERRQ(ierr); 72640e14135SMatthew G. Knepley if (debug) { 72740e14135SMatthew G. Knepley char title[1024]; 72840e14135SMatthew G. Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 7299c3cf19fSMatthew G. Knepley ierr = DMPrintCellVector(c, title, Nb, &x[fieldOffset]);CHKERRQ(ierr); 730652b88e8SMatthew G. Knepley } 7319c3cf19fSMatthew G. Knepley for (q = 0; q < Nq; ++q) { 7327318780aSToby Isaac if (detJ[q] <= 0.0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D, quadrature points %D", detJ[q], c, q); 7337318780aSToby Isaac ierr = (*funcs[field])(coordDim, time, &coords[q*coordDim], n, numFields, funcVal, ctx); 734e735a8a9SMatthew G. Knepley if (ierr) { 735e735a8a9SMatthew G. Knepley PetscErrorCode ierr2; 736e735a8a9SMatthew G. Knepley ierr2 = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr2); 737e735a8a9SMatthew G. Knepley ierr2 = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr2); 7389c3cf19fSMatthew G. Knepley ierr2 = PetscFree7(funcVal,coords,realSpaceDer,J,invJ,interpolant,detJ);CHKERRQ(ierr2); 739e735a8a9SMatthew G. Knepley CHKERRQ(ierr); 740e735a8a9SMatthew G. Knepley } 7419c3cf19fSMatthew G. Knepley ierr = PetscFEInterpolateGradient_Static(fe, &x[fieldOffset], coordDim, invJ, n, q, interpolant);CHKERRQ(ierr); 7429c3cf19fSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 743beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q*qNc+(qNc == 1 ? 0 : qc+fc)]; 744beaa55a6SMatthew G. Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d fieldDer %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]);CHKERRQ(ierr);} 745beaa55a6SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]; 74640e14135SMatthew G. Knepley } 74740e14135SMatthew G. Knepley } 7489c3cf19fSMatthew G. Knepley fieldOffset += Nb; 7499c3cf19fSMatthew G. Knepley qc += Nc; 75040e14135SMatthew G. Knepley } 75140e14135SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 75240e14135SMatthew G. Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 75340e14135SMatthew G. Knepley localDiff += elemDiff; 75440e14135SMatthew G. Knepley } 7559c3cf19fSMatthew G. Knepley ierr = PetscFree7(funcVal,coords,realSpaceDer,J,invJ,interpolant,detJ);CHKERRQ(ierr); 75640e14135SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 757b2566f29SBarry Smith ierr = MPIU_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 75840e14135SMatthew G. Knepley *diff = PetscSqrtReal(*diff); 759cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 760cb1e1211SMatthew G Knepley } 761cb1e1211SMatthew G Knepley 762c6eecec3SToby Isaac PetscErrorCode DMComputeL2FieldDiff_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 76373d901b8SMatthew G. Knepley { 76473d901b8SMatthew G. Knepley const PetscInt debug = 0; 76573d901b8SMatthew G. Knepley PetscSection section; 76673d901b8SMatthew G. Knepley PetscQuadrature quad; 76773d901b8SMatthew G. Knepley Vec localX; 76815496722SMatthew G. Knepley PetscScalar *funcVal, *interpolant; 7697318780aSToby Isaac PetscReal *coords, *detJ, *J; 77073d901b8SMatthew G. Knepley PetscReal *localDiff; 77115496722SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 7729c3cf19fSMatthew G. Knepley PetscInt dim, coordDim, numFields, numComponents = 0, qNc, Nq, cStart, cEnd, cEndInterior, c, field, fieldOffset; 77373d901b8SMatthew G. Knepley PetscErrorCode ierr; 77473d901b8SMatthew G. Knepley 77573d901b8SMatthew G. Knepley PetscFunctionBegin; 776c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 7777318780aSToby Isaac ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 77873d901b8SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 77973d901b8SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 78073d901b8SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 781bdd6f66aSToby Isaac ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 78273d901b8SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 78373d901b8SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 78473d901b8SMatthew G. Knepley for (field = 0; field < numFields; ++field) { 78515496722SMatthew G. Knepley PetscObject obj; 78615496722SMatthew G. Knepley PetscClassId id; 78773d901b8SMatthew G. Knepley PetscInt Nc; 78873d901b8SMatthew G. Knepley 78915496722SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 79015496722SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 79115496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 79215496722SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 79315496722SMatthew G. Knepley 7940f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 7950f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 79615496722SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 79715496722SMatthew G. Knepley PetscFV fv = (PetscFV) obj; 79815496722SMatthew G. Knepley 79915496722SMatthew G. Knepley ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 80015496722SMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 80115496722SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 80273d901b8SMatthew G. Knepley numComponents += Nc; 80373d901b8SMatthew G. Knepley } 8049c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr); 805beaa55a6SMatthew G. Knepley if ((qNc != 1) && (qNc != numComponents)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_SIZ, "Quadrature components %D != %D field components", qNc, numComponents); 8067318780aSToby Isaac ierr = PetscCalloc6(numFields,&localDiff,numComponents,&funcVal,numComponents,&interpolant,coordDim*Nq,&coords,Nq,&detJ,coordDim*coordDim*Nq,&J);CHKERRQ(ierr); 80773d901b8SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8089ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 8099ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 81073d901b8SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 81173d901b8SMatthew G. Knepley PetscScalar *x = NULL; 8129c3cf19fSMatthew G. Knepley PetscInt qc = 0; 81373d901b8SMatthew G. Knepley 8147318780aSToby Isaac ierr = DMPlexComputeCellGeometryFEM(dm, c, quad, coords, J, NULL, detJ);CHKERRQ(ierr); 81573d901b8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 81673d901b8SMatthew G. Knepley 81715496722SMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) { 81815496722SMatthew G. Knepley PetscObject obj; 81915496722SMatthew G. Knepley PetscClassId id; 82073d901b8SMatthew G. Knepley void * const ctx = ctxs ? ctxs[field] : NULL; 82115496722SMatthew G. Knepley PetscInt Nb, Nc, q, fc; 82273d901b8SMatthew G. Knepley 82315496722SMatthew G. Knepley PetscReal elemDiff = 0.0; 82415496722SMatthew G. Knepley 82515496722SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 82615496722SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 82715496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 82815496722SMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 82915496722SMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 83073d901b8SMatthew G. Knepley if (debug) { 83173d901b8SMatthew G. Knepley char title[1024]; 83273d901b8SMatthew G. Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 83315496722SMatthew G. Knepley ierr = DMPrintCellVector(c, title, Nb*Nc, &x[fieldOffset]);CHKERRQ(ierr); 83473d901b8SMatthew G. Knepley } 8357318780aSToby Isaac for (q = 0; q < Nq; ++q) { 8367318780aSToby Isaac if (detJ[q] <= 0.0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D, quadrature point %D", detJ, c, q); 8377318780aSToby Isaac ierr = (*funcs[field])(coordDim, time, &coords[coordDim*q], numFields, funcVal, ctx); 838e735a8a9SMatthew G. Knepley if (ierr) { 839e735a8a9SMatthew G. Knepley PetscErrorCode ierr2; 840e735a8a9SMatthew G. Knepley ierr2 = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr2); 841e735a8a9SMatthew G. Knepley ierr2 = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr2); 8427318780aSToby Isaac ierr2 = PetscFree6(localDiff,funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr2); 843e735a8a9SMatthew G. Knepley CHKERRQ(ierr); 844e735a8a9SMatthew G. Knepley } 84515496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 84615496722SMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 84715496722SMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 84815496722SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 849beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q*qNc+(qNc == 1 ? 0 : qc+fc)]; 850beaa55a6SMatthew G. Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d point %g %g %g diff %g\n", c, field, coordDim > 0 ? coords[0] : 0., coordDim > 1 ? coords[1] : 0., coordDim > 2 ? coords[2] : 0., PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]);CHKERRQ(ierr);} 851beaa55a6SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]; 85273d901b8SMatthew G. Knepley } 85373d901b8SMatthew G. Knepley } 854beaa55a6SMatthew G. Knepley fieldOffset += Nb; 8559c3cf19fSMatthew G. Knepley qc += Nc; 85673d901b8SMatthew G. Knepley localDiff[field] += elemDiff; 85773d901b8SMatthew G. Knepley } 85873d901b8SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 85973d901b8SMatthew G. Knepley } 86073d901b8SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 861b2566f29SBarry Smith ierr = MPIU_Allreduce(localDiff, diff, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 86273d901b8SMatthew G. Knepley for (field = 0; field < numFields; ++field) diff[field] = PetscSqrtReal(diff[field]); 8637318780aSToby Isaac ierr = PetscFree6(localDiff,funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr); 86473d901b8SMatthew G. Knepley PetscFunctionReturn(0); 86573d901b8SMatthew G. Knepley } 86673d901b8SMatthew G. Knepley 867e729f68cSMatthew G. Knepley /*@C 868e729f68cSMatthew 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. 869e729f68cSMatthew G. Knepley 870e729f68cSMatthew G. Knepley Input Parameters: 871e729f68cSMatthew G. Knepley + dm - The DM 8720163fd50SMatthew G. Knepley . time - The time 873ca3eba1bSToby Isaac . funcs - The functions to evaluate for each field component: NULL means that component does not contribute to error calculation 874e729f68cSMatthew G. Knepley . ctxs - Optional array of contexts to pass to each function, or NULL. 875e729f68cSMatthew G. Knepley - X - The coefficient vector u_h 876e729f68cSMatthew G. Knepley 877e729f68cSMatthew G. Knepley Output Parameter: 878e729f68cSMatthew G. Knepley . D - A Vec which holds the difference ||u - u_h||_2 for each cell 879e729f68cSMatthew G. Knepley 880e729f68cSMatthew G. Knepley Level: developer 881e729f68cSMatthew G. Knepley 882b698f381SToby Isaac .seealso: DMProjectFunction(), DMComputeL2Diff(), DMPlexComputeL2FieldDiff(), DMComputeL2GradientDiff() 883e729f68cSMatthew G. Knepley @*/ 8840163fd50SMatthew G. Knepley PetscErrorCode DMPlexComputeL2DiffVec(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, Vec D) 885e729f68cSMatthew G. Knepley { 886e729f68cSMatthew G. Knepley PetscSection section; 887e729f68cSMatthew G. Knepley PetscQuadrature quad; 888e729f68cSMatthew G. Knepley Vec localX; 889e729f68cSMatthew G. Knepley PetscScalar *funcVal, *interpolant; 8907318780aSToby Isaac PetscReal *coords, *detJ, *J; 891e729f68cSMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 8929c3cf19fSMatthew G. Knepley PetscInt dim, coordDim, numFields, numComponents = 0, qNc, Nq, cStart, cEnd, cEndInterior, c, field, fieldOffset; 893e729f68cSMatthew G. Knepley PetscErrorCode ierr; 894e729f68cSMatthew G. Knepley 895e729f68cSMatthew G. Knepley PetscFunctionBegin; 896e729f68cSMatthew G. Knepley ierr = VecSet(D, 0.0);CHKERRQ(ierr); 897e729f68cSMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8987318780aSToby Isaac ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 899e729f68cSMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 900e729f68cSMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 901e729f68cSMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 902bdd6f66aSToby Isaac ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 903e729f68cSMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 904e729f68cSMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 905e729f68cSMatthew G. Knepley for (field = 0; field < numFields; ++field) { 906e729f68cSMatthew G. Knepley PetscObject obj; 907e729f68cSMatthew G. Knepley PetscClassId id; 908e729f68cSMatthew G. Knepley PetscInt Nc; 909e729f68cSMatthew G. Knepley 910e729f68cSMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 911e729f68cSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 912e729f68cSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 913e729f68cSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 914e729f68cSMatthew G. Knepley 915e729f68cSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 916e729f68cSMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 917e729f68cSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 918e729f68cSMatthew G. Knepley PetscFV fv = (PetscFV) obj; 919e729f68cSMatthew G. Knepley 920e729f68cSMatthew G. Knepley ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 921e729f68cSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 922e729f68cSMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 923e729f68cSMatthew G. Knepley numComponents += Nc; 924e729f68cSMatthew G. Knepley } 9259c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr); 926beaa55a6SMatthew G. Knepley if ((qNc != 1) && (qNc != numComponents)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_SIZ, "Quadrature components %D != %D field components", qNc, numComponents); 9277318780aSToby Isaac ierr = PetscMalloc5(numComponents,&funcVal,numComponents,&interpolant,coordDim*Nq,&coords,Nq,&detJ,coordDim*coordDim*Nq,&J);CHKERRQ(ierr); 928e729f68cSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 929e729f68cSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 930e729f68cSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 931e729f68cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 932e729f68cSMatthew G. Knepley PetscScalar *x = NULL; 9336f288a59SMatthew G. Knepley PetscScalar elemDiff = 0.0; 9349c3cf19fSMatthew G. Knepley PetscInt qc = 0; 935e729f68cSMatthew G. Knepley 9367318780aSToby Isaac ierr = DMPlexComputeCellGeometryFEM(dm, c, quad, coords, J, NULL, detJ);CHKERRQ(ierr); 937e729f68cSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 938e729f68cSMatthew G. Knepley 939e729f68cSMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) { 940e729f68cSMatthew G. Knepley PetscObject obj; 941e729f68cSMatthew G. Knepley PetscClassId id; 942e729f68cSMatthew G. Knepley void * const ctx = ctxs ? ctxs[field] : NULL; 943e729f68cSMatthew G. Knepley PetscInt Nb, Nc, q, fc; 944e729f68cSMatthew G. Knepley 945e729f68cSMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 946e729f68cSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 947e729f68cSMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 948e729f68cSMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 949e729f68cSMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 95023f34ed2SToby Isaac if (funcs[field]) { 9517318780aSToby Isaac for (q = 0; q < Nq; ++q) { 9527318780aSToby Isaac if (detJ[q] <= 0.0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D, quadrature points %D", detJ[q], c, q); 9537318780aSToby Isaac ierr = (*funcs[field])(dim, time, &coords[q*coordDim], Nc, funcVal, ctx); 954e735a8a9SMatthew G. Knepley if (ierr) { 955e735a8a9SMatthew G. Knepley PetscErrorCode ierr2; 956e735a8a9SMatthew G. Knepley ierr2 = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr2); 9577318780aSToby Isaac ierr2 = PetscFree5(funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr); 958e735a8a9SMatthew G. Knepley ierr2 = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr2); 959e735a8a9SMatthew G. Knepley CHKERRQ(ierr); 960e735a8a9SMatthew G. Knepley } 961e729f68cSMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 962e729f68cSMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 963e729f68cSMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 964e729f68cSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 965beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q*qNc+(qNc == 1 ? 0 : qc+fc)]; 966beaa55a6SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]; 967e729f68cSMatthew G. Knepley } 968e729f68cSMatthew G. Knepley } 96923f34ed2SToby Isaac } 970beaa55a6SMatthew G. Knepley fieldOffset += Nb; 9719c3cf19fSMatthew G. Knepley qc += Nc; 972e729f68cSMatthew G. Knepley } 973e729f68cSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 97423f34ed2SToby Isaac ierr = VecSetValue(D, c - cStart, elemDiff, INSERT_VALUES);CHKERRQ(ierr); 975e729f68cSMatthew G. Knepley } 9767318780aSToby Isaac ierr = PetscFree5(funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr); 977e729f68cSMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 978e729f68cSMatthew G. Knepley ierr = VecSqrtAbs(D);CHKERRQ(ierr); 979e729f68cSMatthew G. Knepley PetscFunctionReturn(0); 980e729f68cSMatthew G. Knepley } 981e729f68cSMatthew G. Knepley 98273d901b8SMatthew G. Knepley /*@ 98373d901b8SMatthew G. Knepley DMPlexComputeIntegralFEM - Form the local integral F from the local input X using pointwise functions specified by the user 98473d901b8SMatthew G. Knepley 98573d901b8SMatthew G. Knepley Input Parameters: 98673d901b8SMatthew G. Knepley + dm - The mesh 98773d901b8SMatthew G. Knepley . X - Local input vector 98873d901b8SMatthew G. Knepley - user - The user context 98973d901b8SMatthew G. Knepley 99073d901b8SMatthew G. Knepley Output Parameter: 99173d901b8SMatthew G. Knepley . integral - Local integral for each field 99273d901b8SMatthew G. Knepley 99373d901b8SMatthew G. Knepley Level: developer 99473d901b8SMatthew G. Knepley 99573d901b8SMatthew G. Knepley .seealso: DMPlexComputeResidualFEM() 99673d901b8SMatthew G. Knepley @*/ 9970f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeIntegralFEM(DM dm, Vec X, PetscReal *integral, void *user) 99873d901b8SMatthew G. Knepley { 99973d901b8SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1000b5a3613cSMatthew G. Knepley DM dmAux, dmGrad; 1001425f1808SMatthew G. Knepley Vec localX, A, cellGeometryFVM = NULL, faceGeometryFVM = NULL, locGrad = NULL; 10022764a2aaSMatthew G. Knepley PetscDS prob, probAux = NULL; 100373d901b8SMatthew G. Knepley PetscSection section, sectionAux; 1004b5a3613cSMatthew G. Knepley PetscFV fvm = NULL; 1005b5a3613cSMatthew G. Knepley PetscFECellGeom *cgeomFEM; 1006b5a3613cSMatthew G. Knepley PetscFVFaceGeom *fgeomFVM; 1007b5a3613cSMatthew G. Knepley PetscFVCellGeom *cgeomFVM; 100873d901b8SMatthew G. Knepley PetscScalar *u, *a = NULL; 100997b6e6e8SMatthew G. Knepley const PetscScalar *constants, *lgrad; 1010b5a3613cSMatthew G. Knepley PetscReal *lintegral; 1011b5a3613cSMatthew G. Knepley PetscInt *uOff, *uOff_x, *aOff = NULL; 101297b6e6e8SMatthew G. Knepley PetscInt dim, numConstants, Nf, NfAux = 0, f, numCells, cStart, cEnd, cEndInterior, c; 10130f2d7e86SMatthew G. Knepley PetscInt totDim, totDimAux; 1014425f1808SMatthew G. Knepley PetscBool useFVM = PETSC_FALSE; 101573d901b8SMatthew G. Knepley PetscErrorCode ierr; 101673d901b8SMatthew G. Knepley 101773d901b8SMatthew G. Knepley PetscFunctionBegin; 1018c1f031eeSMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr); 101973d901b8SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 1020bdd6f66aSToby Isaac ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, localX, 0.0, NULL, NULL, NULL);CHKERRQ(ierr); 102173d901b8SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 102273d901b8SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 1023c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 102473d901b8SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10252764a2aaSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 10262764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 1027b5a3613cSMatthew G. Knepley ierr = PetscDSGetComponentOffsets(prob, &uOff);CHKERRQ(ierr); 1028b5a3613cSMatthew G. Knepley ierr = PetscDSGetComponentDerivativeOffsets(prob, &uOff_x);CHKERRQ(ierr); 102997b6e6e8SMatthew G. Knepley ierr = PetscDSGetConstants(prob, &numConstants, &constants);CHKERRQ(ierr); 103073d901b8SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 103173d901b8SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10329ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 10339ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 103473d901b8SMatthew G. Knepley numCells = cEnd - cStart; 103573d901b8SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 103673d901b8SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 103773d901b8SMatthew G. Knepley if (dmAux) { 10382764a2aaSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 1039b5a3613cSMatthew G. Knepley ierr = PetscDSGetNumFields(probAux, &NfAux);CHKERRQ(ierr); 1040b5a3613cSMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 10412764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 1042b5a3613cSMatthew G. Knepley ierr = PetscDSGetComponentOffsets(probAux, &aOff);CHKERRQ(ierr); 1043b5a3613cSMatthew G. Knepley ierr = PetscDSGetEvaluationArrays(probAux, &a, NULL, NULL);CHKERRQ(ierr); 104473d901b8SMatthew G. Knepley } 1045b5a3613cSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1046b5a3613cSMatthew G. Knepley PetscObject obj; 1047b5a3613cSMatthew G. Knepley PetscClassId id; 1048b5a3613cSMatthew G. Knepley 1049b5a3613cSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1050b5a3613cSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1051b5a3613cSMatthew G. Knepley if (id == PETSCFV_CLASSID) {useFVM = PETSC_TRUE; fvm = (PetscFV) obj;} 1052b5a3613cSMatthew G. Knepley } 1053b5a3613cSMatthew G. Knepley if (useFVM) { 1054b5a3613cSMatthew G. Knepley Vec grad; 1055b5a3613cSMatthew G. Knepley PetscInt fStart, fEnd; 1056b5a3613cSMatthew G. Knepley PetscBool compGrad; 1057b5a3613cSMatthew G. Knepley 1058b5a3613cSMatthew G. Knepley ierr = PetscFVGetComputeGradients(fvm, &compGrad);CHKERRQ(ierr); 1059b5a3613cSMatthew G. Knepley ierr = PetscFVSetComputeGradients(fvm, PETSC_TRUE);CHKERRQ(ierr); 1060b5a3613cSMatthew G. Knepley ierr = DMPlexComputeGeometryFVM(dm, &cellGeometryFVM, &faceGeometryFVM);CHKERRQ(ierr); 1061b5a3613cSMatthew G. Knepley ierr = DMPlexComputeGradientFVM(dm, fvm, faceGeometryFVM, cellGeometryFVM, &dmGrad);CHKERRQ(ierr); 1062b5a3613cSMatthew G. Knepley ierr = PetscFVSetComputeGradients(fvm, compGrad);CHKERRQ(ierr); 1063b5a3613cSMatthew G. Knepley ierr = VecGetArrayRead(faceGeometryFVM, (const PetscScalar **) &fgeomFVM);CHKERRQ(ierr); 1064b5a3613cSMatthew G. Knepley ierr = VecGetArrayRead(cellGeometryFVM, (const PetscScalar **) &cgeomFVM);CHKERRQ(ierr); 1065b5a3613cSMatthew G. Knepley /* Reconstruct and limit cell gradients */ 1066b5a3613cSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 1067b5a3613cSMatthew G. Knepley ierr = DMGetGlobalVector(dmGrad, &grad);CHKERRQ(ierr); 1068b5a3613cSMatthew G. Knepley ierr = DMPlexReconstructGradients_Internal(dm, fvm, fStart, fEnd, faceGeometryFVM, cellGeometryFVM, localX, grad);CHKERRQ(ierr); 1069b5a3613cSMatthew G. Knepley /* Communicate gradient values */ 1070b5a3613cSMatthew G. Knepley ierr = DMGetLocalVector(dmGrad, &locGrad);CHKERRQ(ierr); 1071b5a3613cSMatthew G. Knepley ierr = DMGlobalToLocalBegin(dmGrad, grad, INSERT_VALUES, locGrad);CHKERRQ(ierr); 1072b5a3613cSMatthew G. Knepley ierr = DMGlobalToLocalEnd(dmGrad, grad, INSERT_VALUES, locGrad);CHKERRQ(ierr); 1073b5a3613cSMatthew G. Knepley ierr = DMRestoreGlobalVector(dmGrad, &grad);CHKERRQ(ierr); 1074b5a3613cSMatthew G. Knepley /* Handle non-essential (e.g. outflow) boundary values */ 1075b5a3613cSMatthew G. Knepley ierr = DMPlexInsertBoundaryValues(dm, PETSC_FALSE, localX, 0.0, faceGeometryFVM, cellGeometryFVM, locGrad);CHKERRQ(ierr); 1076b5a3613cSMatthew G. Knepley ierr = VecGetArrayRead(locGrad, &lgrad);CHKERRQ(ierr); 1077b5a3613cSMatthew G. Knepley } 1078b5a3613cSMatthew G. Knepley ierr = PetscMalloc3(Nf,&lintegral,numCells*totDim,&u,numCells,&cgeomFEM);CHKERRQ(ierr); 10790f2d7e86SMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 1080c1f031eeSMatthew G. Knepley for (f = 0; f < Nf; ++f) {lintegral[f] = 0.0;} 108173d901b8SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 108273d901b8SMatthew G. Knepley PetscScalar *x = NULL; 108373d901b8SMatthew G. Knepley PetscInt i; 108473d901b8SMatthew G. Knepley 1085b5a3613cSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, cgeomFEM[c].v0, cgeomFEM[c].J, cgeomFEM[c].invJ, &cgeomFEM[c].detJ);CHKERRQ(ierr); 1086b5a3613cSMatthew G. Knepley if (cgeomFEM[c].detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", cgeomFEM[c].detJ, c); 108773d901b8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, localX, c, NULL, &x);CHKERRQ(ierr); 10880f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 108973d901b8SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, localX, c, NULL, &x);CHKERRQ(ierr); 109073d901b8SMatthew G. Knepley if (dmAux) { 109173d901b8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 10920f2d7e86SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 109373d901b8SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 109473d901b8SMatthew G. Knepley } 109573d901b8SMatthew G. Knepley } 109673d901b8SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1097c1f031eeSMatthew G. Knepley PetscObject obj; 1098c1f031eeSMatthew G. Knepley PetscClassId id; 1099c1f031eeSMatthew G. Knepley PetscInt numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset; 110073d901b8SMatthew G. Knepley 1101c1f031eeSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1102c1f031eeSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1103c1f031eeSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 1104c1f031eeSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 1105c1f031eeSMatthew G. Knepley PetscQuadrature q; 1106c1f031eeSMatthew G. Knepley PetscInt Nq, Nb; 1107c1f031eeSMatthew G. Knepley 11080f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 1109c1f031eeSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 11109c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 1111c1f031eeSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 1112c1f031eeSMatthew G. Knepley blockSize = Nb*Nq; 111373d901b8SMatthew G. Knepley batchSize = numBlocks * blockSize; 11140f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 111573d901b8SMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 111673d901b8SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 111773d901b8SMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 111873d901b8SMatthew G. Knepley offset = numCells - Nr; 1119b5a3613cSMatthew G. Knepley ierr = PetscFEIntegrate(fe, prob, f, Ne, cgeomFEM, u, probAux, a, lintegral);CHKERRQ(ierr); 1120b5a3613cSMatthew G. Knepley ierr = PetscFEIntegrate(fe, prob, f, Nr, &cgeomFEM[offset], &u[offset*totDim], probAux, &a[offset*totDimAux], lintegral);CHKERRQ(ierr); 1121c1f031eeSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 1122b69edc29SMatthew G. Knepley /* PetscFV fv = (PetscFV) obj; */ 1123c1f031eeSMatthew G. Knepley PetscInt foff; 1124420e96edSMatthew G. Knepley PetscPointFunc obj_func; 1125b69edc29SMatthew G. Knepley PetscScalar lint; 1126c1f031eeSMatthew G. Knepley 1127c1f031eeSMatthew G. Knepley ierr = PetscDSGetObjective(prob, f, &obj_func);CHKERRQ(ierr); 1128c1f031eeSMatthew G. Knepley ierr = PetscDSGetFieldOffset(prob, f, &foff);CHKERRQ(ierr); 1129c1f031eeSMatthew G. Knepley if (obj_func) { 1130c1f031eeSMatthew G. Knepley for (c = 0; c < numCells; ++c) { 1131b5a3613cSMatthew G. Knepley PetscScalar *u_x; 1132b5a3613cSMatthew G. Knepley 1133b5a3613cSMatthew G. Knepley ierr = DMPlexPointLocalRead(dmGrad, c, lgrad, &u_x);CHKERRQ(ierr); 113497b6e6e8SMatthew G. Knepley obj_func(dim, Nf, NfAux, uOff, uOff_x, &u[totDim*c+foff], NULL, u_x, aOff, NULL, a, NULL, NULL, 0.0, cgeomFVM[c].centroid, numConstants, constants, &lint); 1135b5a3613cSMatthew G. Knepley lintegral[f] += PetscRealPart(lint)*cgeomFVM[c].volume; 113673d901b8SMatthew G. Knepley } 1137c1f031eeSMatthew G. Knepley } 1138c1f031eeSMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 1139c1f031eeSMatthew G. Knepley } 1140b5a3613cSMatthew G. Knepley if (useFVM) { 1141b5a3613cSMatthew G. Knepley ierr = VecRestoreArrayRead(locGrad, &lgrad);CHKERRQ(ierr); 1142b5a3613cSMatthew G. Knepley ierr = VecRestoreArrayRead(faceGeometryFVM, (const PetscScalar **) &fgeomFVM);CHKERRQ(ierr); 1143b5a3613cSMatthew G. Knepley ierr = VecRestoreArrayRead(cellGeometryFVM, (const PetscScalar **) &cgeomFVM);CHKERRQ(ierr); 1144b5a3613cSMatthew G. Knepley ierr = DMRestoreLocalVector(dmGrad, &locGrad);CHKERRQ(ierr); 1145b5a3613cSMatthew G. Knepley ierr = VecDestroy(&faceGeometryFVM);CHKERRQ(ierr); 1146b5a3613cSMatthew G. Knepley ierr = VecDestroy(&cellGeometryFVM);CHKERRQ(ierr); 1147b5a3613cSMatthew G. Knepley ierr = DMDestroy(&dmGrad);CHKERRQ(ierr); 1148b5a3613cSMatthew G. Knepley } 114973d901b8SMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 115073d901b8SMatthew G. Knepley if (mesh->printFEM) { 115173d901b8SMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "Local integral:");CHKERRQ(ierr); 1152c1f031eeSMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), " %g", lintegral[f]);CHKERRQ(ierr);} 115373d901b8SMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "\n");CHKERRQ(ierr); 115473d901b8SMatthew G. Knepley } 115573d901b8SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 1156b2566f29SBarry Smith ierr = MPIU_Allreduce(lintegral, integral, Nf, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 1157b5a3613cSMatthew G. Knepley ierr = PetscFree3(lintegral,u,cgeomFEM);CHKERRQ(ierr); 1158c1f031eeSMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr); 115973d901b8SMatthew G. Knepley PetscFunctionReturn(0); 116073d901b8SMatthew G. Knepley } 116173d901b8SMatthew G. Knepley 1162d69c5d34SMatthew G. Knepley /*@ 116368132eb9SMatthew G. Knepley DMPlexComputeInterpolatorNested - Form the local portion of the interpolation matrix I from the coarse DM to the uniformly refined DM. 1164d69c5d34SMatthew G. Knepley 1165d69c5d34SMatthew G. Knepley Input Parameters: 1166d69c5d34SMatthew G. Knepley + dmf - The fine mesh 1167d69c5d34SMatthew G. Knepley . dmc - The coarse mesh 1168d69c5d34SMatthew G. Knepley - user - The user context 1169d69c5d34SMatthew G. Knepley 1170d69c5d34SMatthew G. Knepley Output Parameter: 1171934789fcSMatthew G. Knepley . In - The interpolation matrix 1172d69c5d34SMatthew G. Knepley 1173d69c5d34SMatthew G. Knepley Level: developer 1174d69c5d34SMatthew G. Knepley 117568132eb9SMatthew G. Knepley .seealso: DMPlexComputeInterpolatorGeneral(), DMPlexComputeJacobianFEM() 1176d69c5d34SMatthew G. Knepley @*/ 117768132eb9SMatthew G. Knepley PetscErrorCode DMPlexComputeInterpolatorNested(DM dmc, DM dmf, Mat In, void *user) 1178d69c5d34SMatthew G. Knepley { 1179d69c5d34SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dmc->data; 1180d69c5d34SMatthew G. Knepley const char *name = "Interpolator"; 11812764a2aaSMatthew G. Knepley PetscDS prob; 1182d69c5d34SMatthew G. Knepley PetscFE *feRef; 118397c42addSMatthew G. Knepley PetscFV *fvRef; 1184d69c5d34SMatthew G. Knepley PetscSection fsection, fglobalSection; 1185d69c5d34SMatthew G. Knepley PetscSection csection, cglobalSection; 1186d69c5d34SMatthew G. Knepley PetscScalar *elemMat; 11879ac3fadcSMatthew G. Knepley PetscInt dim, Nf, f, fieldI, fieldJ, offsetI, offsetJ, cStart, cEnd, cEndInterior, c; 11880f2d7e86SMatthew G. Knepley PetscInt cTotDim, rTotDim = 0; 1189d69c5d34SMatthew G. Knepley PetscErrorCode ierr; 1190d69c5d34SMatthew G. Knepley 1191d69c5d34SMatthew G. Knepley PetscFunctionBegin; 1192d69c5d34SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1193c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 1194d69c5d34SMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 1195d69c5d34SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 1196d69c5d34SMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 1197d69c5d34SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 1198d69c5d34SMatthew G. Knepley ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 1199d69c5d34SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 12009ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dmc, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 12019ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 12022764a2aaSMatthew G. Knepley ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr); 120397c42addSMatthew G. Knepley ierr = PetscCalloc2(Nf,&feRef,Nf,&fvRef);CHKERRQ(ierr); 1204d69c5d34SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 120597c42addSMatthew G. Knepley PetscObject obj; 120697c42addSMatthew G. Knepley PetscClassId id; 1207aa7890ccSMatthew G. Knepley PetscInt rNb = 0, Nc = 0; 1208d69c5d34SMatthew G. Knepley 120997c42addSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 121097c42addSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 121197c42addSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 121297c42addSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 121397c42addSMatthew G. Knepley 12140f2d7e86SMatthew G. Knepley ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 1215d69c5d34SMatthew G. Knepley ierr = PetscFEGetDimension(feRef[f], &rNb);CHKERRQ(ierr); 12160f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 121797c42addSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 121897c42addSMatthew G. Knepley PetscFV fv = (PetscFV) obj; 121997c42addSMatthew G. Knepley PetscDualSpace Q; 122097c42addSMatthew G. Knepley 122197c42addSMatthew G. Knepley ierr = PetscFVRefine(fv, &fvRef[f]);CHKERRQ(ierr); 122297c42addSMatthew G. Knepley ierr = PetscFVGetDualSpace(fvRef[f], &Q);CHKERRQ(ierr); 122397c42addSMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Q, &rNb);CHKERRQ(ierr); 122497c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 122597c42addSMatthew G. Knepley } 12269c3cf19fSMatthew G. Knepley rTotDim += rNb; 1227d69c5d34SMatthew G. Knepley } 12282764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 12290f2d7e86SMatthew G. Knepley ierr = PetscMalloc1(rTotDim*cTotDim,&elemMat);CHKERRQ(ierr); 12300f2d7e86SMatthew G. Knepley ierr = PetscMemzero(elemMat, rTotDim*cTotDim * sizeof(PetscScalar));CHKERRQ(ierr); 1231d69c5d34SMatthew G. Knepley for (fieldI = 0, offsetI = 0; fieldI < Nf; ++fieldI) { 1232d69c5d34SMatthew G. Knepley PetscDualSpace Qref; 1233d69c5d34SMatthew G. Knepley PetscQuadrature f; 1234d69c5d34SMatthew G. Knepley const PetscReal *qpoints, *qweights; 1235d69c5d34SMatthew G. Knepley PetscReal *points; 1236d69c5d34SMatthew G. Knepley PetscInt npoints = 0, Nc, Np, fpdim, i, k, p, d; 1237d69c5d34SMatthew G. Knepley 1238d69c5d34SMatthew G. Knepley /* Compose points from all dual basis functionals */ 123997c42addSMatthew G. Knepley if (feRef[fieldI]) { 1240d69c5d34SMatthew G. Knepley ierr = PetscFEGetDualSpace(feRef[fieldI], &Qref);CHKERRQ(ierr); 12410f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(feRef[fieldI], &Nc);CHKERRQ(ierr); 124297c42addSMatthew G. Knepley } else { 124397c42addSMatthew G. Knepley ierr = PetscFVGetDualSpace(fvRef[fieldI], &Qref);CHKERRQ(ierr); 124497c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fvRef[fieldI], &Nc);CHKERRQ(ierr); 124597c42addSMatthew G. Knepley } 1246d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Qref, &fpdim);CHKERRQ(ierr); 1247d69c5d34SMatthew G. Knepley for (i = 0; i < fpdim; ++i) { 1248d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 12499c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, NULL, &Np, NULL, NULL);CHKERRQ(ierr); 1250d69c5d34SMatthew G. Knepley npoints += Np; 1251d69c5d34SMatthew G. Knepley } 1252d69c5d34SMatthew G. Knepley ierr = PetscMalloc1(npoints*dim,&points);CHKERRQ(ierr); 1253d69c5d34SMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) { 1254d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 12559c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, NULL, &Np, &qpoints, NULL);CHKERRQ(ierr); 1256d69c5d34SMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) for (d = 0; d < dim; ++d) points[k*dim+d] = qpoints[p*dim+d]; 1257d69c5d34SMatthew G. Knepley } 1258d69c5d34SMatthew G. Knepley 1259d69c5d34SMatthew G. Knepley for (fieldJ = 0, offsetJ = 0; fieldJ < Nf; ++fieldJ) { 126097c42addSMatthew G. Knepley PetscObject obj; 126197c42addSMatthew G. Knepley PetscClassId id; 1262d69c5d34SMatthew G. Knepley PetscReal *B; 12639c3cf19fSMatthew G. Knepley PetscInt NcJ = 0, cpdim = 0, j, qNc; 1264d69c5d34SMatthew G. Knepley 126597c42addSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldJ, &obj);CHKERRQ(ierr); 126697c42addSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 126797c42addSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 126897c42addSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 1269d69c5d34SMatthew G. Knepley 1270d69c5d34SMatthew G. Knepley /* Evaluate basis at points */ 12710f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &NcJ);CHKERRQ(ierr); 12720f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &cpdim);CHKERRQ(ierr); 1273ffe73a53SMatthew G. Knepley /* For now, fields only interpolate themselves */ 1274ffe73a53SMatthew G. Knepley if (fieldI == fieldJ) { 12759c3cf19fSMatthew G. Knepley if (Nc != NcJ) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in fine space field %D does not match coarse field %D", Nc, NcJ); 12760f2d7e86SMatthew G. Knepley ierr = PetscFEGetTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr); 1277d69c5d34SMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) { 1278d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 12799c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &qNc, &Np, NULL, &qweights);CHKERRQ(ierr); 12809c3cf19fSMatthew G. Knepley if (qNc != NcJ) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in quadrature %D does not match coarse field %D", qNc, NcJ); 1281d69c5d34SMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) { 128236a6d9c0SMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 12839c3cf19fSMatthew G. Knepley /* NOTE: This is not quite right, unless fpdim == number of fine grid functional quad points */ 12849c3cf19fSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[(offsetI + i)*cTotDim + offsetJ + j] += B[k*cpdim*NcJ+j*Nc+c]*qweights[p*qNc+c]; 128536a6d9c0SMatthew G. Knepley } 1286d69c5d34SMatthew G. Knepley } 1287d69c5d34SMatthew G. Knepley } 12880f2d7e86SMatthew G. Knepley ierr = PetscFERestoreTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr);CHKERRQ(ierr); 1289ffe73a53SMatthew G. Knepley } 129097c42addSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 129197c42addSMatthew G. Knepley PetscFV fv = (PetscFV) obj; 129297c42addSMatthew G. Knepley 129397c42addSMatthew G. Knepley /* Evaluate constant function at points */ 129497c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &NcJ);CHKERRQ(ierr); 129597c42addSMatthew G. Knepley cpdim = 1; 129697c42addSMatthew G. Knepley /* For now, fields only interpolate themselves */ 129797c42addSMatthew G. Knepley if (fieldI == fieldJ) { 129897c42addSMatthew G. Knepley if (Nc != NcJ) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in fine space field %d does not match coarse field %d", Nc, NcJ); 129997c42addSMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) { 130097c42addSMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 13019c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &qNc, &Np, NULL, &qweights);CHKERRQ(ierr); 13029c3cf19fSMatthew G. Knepley if (qNc != NcJ) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in quadrature %D does not match coarse field %D", qNc, NcJ); 130397c42addSMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) { 130497c42addSMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 13059c3cf19fSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[(offsetI + i*Nc + c)*cTotDim + offsetJ + j*NcJ + c] += 1.0*qweights[p*qNc+c]; 130697c42addSMatthew G. Knepley } 130797c42addSMatthew G. Knepley } 130897c42addSMatthew G. Knepley } 130997c42addSMatthew G. Knepley } 131097c42addSMatthew G. Knepley } 131136a6d9c0SMatthew G. Knepley offsetJ += cpdim*NcJ; 1312d69c5d34SMatthew G. Knepley } 1313d69c5d34SMatthew G. Knepley offsetI += fpdim*Nc; 1314549a8adaSMatthew G. Knepley ierr = PetscFree(points);CHKERRQ(ierr); 1315d69c5d34SMatthew G. Knepley } 13160f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(0, name, rTotDim, cTotDim, elemMat);CHKERRQ(ierr);} 13177f5b169aSMatthew G. Knepley /* Preallocate matrix */ 13187f5b169aSMatthew G. Knepley { 1319c094ef40SMatthew G. Knepley Mat preallocator; 1320c094ef40SMatthew G. Knepley PetscScalar *vals; 1321c094ef40SMatthew G. Knepley PetscInt *cellCIndices, *cellFIndices; 1322c094ef40SMatthew G. Knepley PetscInt locRows, locCols, cell; 13237f5b169aSMatthew G. Knepley 1324c094ef40SMatthew G. Knepley ierr = MatGetLocalSize(In, &locRows, &locCols);CHKERRQ(ierr); 1325c094ef40SMatthew G. Knepley ierr = MatCreate(PetscObjectComm((PetscObject) In), &preallocator);CHKERRQ(ierr); 1326c094ef40SMatthew G. Knepley ierr = MatSetType(preallocator, MATPREALLOCATOR);CHKERRQ(ierr); 1327c094ef40SMatthew G. Knepley ierr = MatSetSizes(preallocator, locRows, locCols, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1328c094ef40SMatthew G. Knepley ierr = MatSetUp(preallocator);CHKERRQ(ierr); 1329c094ef40SMatthew G. Knepley ierr = PetscCalloc3(rTotDim*cTotDim, &vals,cTotDim,&cellCIndices,rTotDim,&cellFIndices);CHKERRQ(ierr); 13307f5b169aSMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 13317f5b169aSMatthew G. Knepley ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, cell, cellCIndices, cellFIndices);CHKERRQ(ierr); 1332c094ef40SMatthew G. Knepley ierr = MatSetValues(preallocator, rTotDim, cellFIndices, cTotDim, cellCIndices, vals, INSERT_VALUES);CHKERRQ(ierr); 13337f5b169aSMatthew G. Knepley } 1334c094ef40SMatthew G. Knepley ierr = PetscFree3(vals,cellCIndices,cellFIndices);CHKERRQ(ierr); 1335c094ef40SMatthew G. Knepley ierr = MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1336c094ef40SMatthew G. Knepley ierr = MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1337c094ef40SMatthew G. Knepley ierr = MatPreallocatorPreallocate(preallocator, PETSC_TRUE, In);CHKERRQ(ierr); 1338c094ef40SMatthew G. Knepley ierr = MatDestroy(&preallocator);CHKERRQ(ierr); 13397f5b169aSMatthew G. Knepley } 13407f5b169aSMatthew G. Knepley /* Fill matrix */ 13417f5b169aSMatthew G. Knepley ierr = MatZeroEntries(In);CHKERRQ(ierr); 1342d69c5d34SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1343934789fcSMatthew G. Knepley ierr = DMPlexMatSetClosureRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, In, c, elemMat, INSERT_VALUES);CHKERRQ(ierr); 1344d69c5d34SMatthew G. Knepley } 1345549a8adaSMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);} 134697c42addSMatthew G. Knepley ierr = PetscFree2(feRef,fvRef);CHKERRQ(ierr); 1347549a8adaSMatthew G. Knepley ierr = PetscFree(elemMat);CHKERRQ(ierr); 1348934789fcSMatthew G. Knepley ierr = MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1349934789fcSMatthew G. Knepley ierr = MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1350d69c5d34SMatthew G. Knepley if (mesh->printFEM) { 1351d69c5d34SMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_WORLD, "%s:\n", name);CHKERRQ(ierr); 1352934789fcSMatthew G. Knepley ierr = MatChop(In, 1.0e-10);CHKERRQ(ierr); 1353934789fcSMatthew G. Knepley ierr = MatView(In, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1354d69c5d34SMatthew G. Knepley } 1355d69c5d34SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1356d69c5d34SMatthew G. Knepley PetscFunctionReturn(0); 1357d69c5d34SMatthew G. Knepley } 13586c73c22cSMatthew G. Knepley 135968132eb9SMatthew G. Knepley /*@ 136068132eb9SMatthew G. Knepley DMPlexComputeInterpolatorGeneral - Form the local portion of the interpolation matrix I from the coarse DM to a non-nested fine DM. 136168132eb9SMatthew G. Knepley 136268132eb9SMatthew G. Knepley Input Parameters: 136368132eb9SMatthew G. Knepley + dmf - The fine mesh 136468132eb9SMatthew G. Knepley . dmc - The coarse mesh 136568132eb9SMatthew G. Knepley - user - The user context 136668132eb9SMatthew G. Knepley 136768132eb9SMatthew G. Knepley Output Parameter: 136868132eb9SMatthew G. Knepley . In - The interpolation matrix 136968132eb9SMatthew G. Knepley 137068132eb9SMatthew G. Knepley Level: developer 137168132eb9SMatthew G. Knepley 137268132eb9SMatthew G. Knepley .seealso: DMPlexComputeInterpolatorNested(), DMPlexComputeJacobianFEM() 137368132eb9SMatthew G. Knepley @*/ 137468132eb9SMatthew G. Knepley PetscErrorCode DMPlexComputeInterpolatorGeneral(DM dmc, DM dmf, Mat In, void *user) 13754ef9d792SMatthew G. Knepley { 137664e98e1dSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dmf->data; 137764e98e1dSMatthew G. Knepley const char *name = "Interpolator"; 13784ef9d792SMatthew G. Knepley PetscDS prob; 13794ef9d792SMatthew G. Knepley PetscSection fsection, csection, globalFSection, globalCSection; 13804ef9d792SMatthew G. Knepley PetscHashJK ht; 13814ef9d792SMatthew G. Knepley PetscLayout rLayout; 13824ef9d792SMatthew G. Knepley PetscInt *dnz, *onz; 13834ef9d792SMatthew G. Knepley PetscInt locRows, rStart, rEnd; 13844ef9d792SMatthew G. Knepley PetscReal *x, *v0, *J, *invJ, detJ; 13854ef9d792SMatthew G. Knepley PetscReal *v0c, *Jc, *invJc, detJc; 13864ef9d792SMatthew G. Knepley PetscScalar *elemMat; 13874ef9d792SMatthew G. Knepley PetscInt dim, Nf, field, totDim, cStart, cEnd, cell, ccell; 13884ef9d792SMatthew G. Knepley PetscErrorCode ierr; 13894ef9d792SMatthew G. Knepley 13904ef9d792SMatthew G. Knepley PetscFunctionBegin; 139177711781SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 13924ef9d792SMatthew G. Knepley ierr = DMGetCoordinateDim(dmc, &dim);CHKERRQ(ierr); 13934ef9d792SMatthew G. Knepley ierr = DMGetDS(dmc, &prob);CHKERRQ(ierr); 13944ef9d792SMatthew G. Knepley ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr); 13954ef9d792SMatthew G. Knepley ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 13964ef9d792SMatthew G. Knepley ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 13974ef9d792SMatthew G. Knepley ierr = PetscMalloc3(dim,&v0c,dim*dim,&Jc,dim*dim,&invJc);CHKERRQ(ierr); 13984ef9d792SMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 13994ef9d792SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr); 14004ef9d792SMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 14014ef9d792SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr); 14024ef9d792SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr); 14034ef9d792SMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 14049c3cf19fSMatthew G. Knepley ierr = PetscMalloc1(totDim, &elemMat);CHKERRQ(ierr); 14054ef9d792SMatthew G. Knepley 14064ef9d792SMatthew G. Knepley ierr = MatGetLocalSize(In, &locRows, NULL);CHKERRQ(ierr); 14074ef9d792SMatthew G. Knepley ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) In), &rLayout);CHKERRQ(ierr); 14084ef9d792SMatthew G. Knepley ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 14094ef9d792SMatthew G. Knepley ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 14104ef9d792SMatthew G. Knepley ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 14114ef9d792SMatthew G. Knepley ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 14124ef9d792SMatthew G. Knepley ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 14134ef9d792SMatthew G. Knepley ierr = PetscCalloc2(locRows,&dnz,locRows,&onz);CHKERRQ(ierr); 14144ef9d792SMatthew G. Knepley ierr = PetscHashJKCreate(&ht);CHKERRQ(ierr); 14154ef9d792SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 14164ef9d792SMatthew G. Knepley PetscObject obj; 14174ef9d792SMatthew G. Knepley PetscClassId id; 1418c0d7054bSMatthew G. Knepley PetscDualSpace Q = NULL; 14194ef9d792SMatthew G. Knepley PetscQuadrature f; 142017f047d8SMatthew G. Knepley const PetscReal *qpoints; 142117f047d8SMatthew G. Knepley PetscInt Nc, Np, fpdim, i, d; 14224ef9d792SMatthew G. Knepley 14234ef9d792SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr); 14244ef9d792SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 14254ef9d792SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 14264ef9d792SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 14274ef9d792SMatthew G. Knepley 14284ef9d792SMatthew G. Knepley ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 14294ef9d792SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 14304ef9d792SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 14314ef9d792SMatthew G. Knepley PetscFV fv = (PetscFV) obj; 14324ef9d792SMatthew G. Knepley 14334ef9d792SMatthew G. Knepley ierr = PetscFVGetDualSpace(fv, &Q);CHKERRQ(ierr); 14344ef9d792SMatthew G. Knepley Nc = 1; 14354ef9d792SMatthew G. Knepley } 14364ef9d792SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Q, &fpdim);CHKERRQ(ierr); 14374ef9d792SMatthew G. Knepley /* For each fine grid cell */ 14384ef9d792SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 14394ef9d792SMatthew G. Knepley PetscInt *findices, *cindices; 14404ef9d792SMatthew G. Knepley PetscInt numFIndices, numCIndices; 14414ef9d792SMatthew G. Knepley 14426ecaa68aSToby Isaac ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 14434ef9d792SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 14449c3cf19fSMatthew G. Knepley if (numFIndices != fpdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of fine indices %d != %d dual basis vecs", numFIndices, fpdim); 14454ef9d792SMatthew G. Knepley for (i = 0; i < fpdim; ++i) { 14464ef9d792SMatthew G. Knepley Vec pointVec; 14474ef9d792SMatthew G. Knepley PetscScalar *pV; 14483a93e3b7SToby Isaac PetscSF coarseCellSF = NULL; 14493a93e3b7SToby Isaac const PetscSFNode *coarseCells; 14509c3cf19fSMatthew G. Knepley PetscInt numCoarseCells, q, c; 14514ef9d792SMatthew G. Knepley 14524ef9d792SMatthew G. Knepley /* Get points from the dual basis functional quadrature */ 14534ef9d792SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Q, i, &f);CHKERRQ(ierr); 14549c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, NULL, &Np, &qpoints, NULL);CHKERRQ(ierr); 14554ef9d792SMatthew G. Knepley ierr = VecCreateSeq(PETSC_COMM_SELF, Np*dim, &pointVec);CHKERRQ(ierr); 14564ef9d792SMatthew G. Knepley ierr = VecSetBlockSize(pointVec, dim);CHKERRQ(ierr); 14574ef9d792SMatthew G. Knepley ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 14584ef9d792SMatthew G. Knepley for (q = 0; q < Np; ++q) { 14594ef9d792SMatthew G. Knepley /* Transform point to real space */ 14604ef9d792SMatthew G. Knepley CoordinatesRefToReal(dim, dim, v0, J, &qpoints[q*dim], x); 14614ef9d792SMatthew G. Knepley for (d = 0; d < dim; ++d) pV[q*dim+d] = x[d]; 14624ef9d792SMatthew G. Knepley } 14634ef9d792SMatthew G. Knepley ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 14644ef9d792SMatthew G. Knepley /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */ 146562a38674SMatthew G. Knepley ierr = DMLocatePoints(dmc, pointVec, DM_POINTLOCATION_NEAREST, &coarseCellSF);CHKERRQ(ierr); 14663a93e3b7SToby Isaac ierr = PetscSFViewFromOptions(coarseCellSF, NULL, "-interp_sf_view");CHKERRQ(ierr); 14674ef9d792SMatthew G. Knepley /* Update preallocation info */ 14683a93e3b7SToby Isaac ierr = PetscSFGetGraph(coarseCellSF, NULL, &numCoarseCells, NULL, &coarseCells);CHKERRQ(ierr); 14693a93e3b7SToby Isaac if (numCoarseCells != Np) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located"); 14709c3cf19fSMatthew G. Knepley { 14714ef9d792SMatthew G. Knepley PetscHashJKKey key; 14724ef9d792SMatthew G. Knepley PetscHashJKIter missing, iter; 14734ef9d792SMatthew G. Knepley 14749c3cf19fSMatthew G. Knepley key.j = findices[i]; 14758c543595SMatthew G. Knepley if (key.j >= 0) { 14764ef9d792SMatthew G. Knepley /* Get indices for coarse elements */ 14774ef9d792SMatthew G. Knepley for (ccell = 0; ccell < numCoarseCells; ++ccell) { 14783a93e3b7SToby Isaac ierr = DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 14794ef9d792SMatthew G. Knepley for (c = 0; c < numCIndices; ++c) { 14804ef9d792SMatthew G. Knepley key.k = cindices[c]; 14814ef9d792SMatthew G. Knepley if (key.k < 0) continue; 14824ef9d792SMatthew G. Knepley ierr = PetscHashJKPut(ht, key, &missing, &iter);CHKERRQ(ierr); 14834ef9d792SMatthew G. Knepley if (missing) { 14844ef9d792SMatthew G. Knepley ierr = PetscHashJKSet(ht, iter, 1);CHKERRQ(ierr); 14854ef9d792SMatthew G. Knepley if ((key.k >= rStart) && (key.k < rEnd)) ++dnz[key.j-rStart]; 14864ef9d792SMatthew G. Knepley else ++onz[key.j-rStart]; 14874ef9d792SMatthew G. Knepley } 14884ef9d792SMatthew G. Knepley } 14893a93e3b7SToby Isaac ierr = DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 14904ef9d792SMatthew G. Knepley } 14914ef9d792SMatthew G. Knepley } 14928c543595SMatthew G. Knepley } 14933a93e3b7SToby Isaac ierr = PetscSFDestroy(&coarseCellSF);CHKERRQ(ierr); 14944ef9d792SMatthew G. Knepley ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 14954ef9d792SMatthew G. Knepley } 149646bdb399SToby Isaac ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 14974ef9d792SMatthew G. Knepley } 14984ef9d792SMatthew G. Knepley } 14994ef9d792SMatthew G. Knepley ierr = PetscHashJKDestroy(&ht);CHKERRQ(ierr); 15004ef9d792SMatthew G. Knepley ierr = MatXAIJSetPreallocation(In, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr); 15014ef9d792SMatthew G. Knepley ierr = MatSetOption(In, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 15024ef9d792SMatthew G. Knepley ierr = PetscFree2(dnz,onz);CHKERRQ(ierr); 15034ef9d792SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 15044ef9d792SMatthew G. Knepley PetscObject obj; 15054ef9d792SMatthew G. Knepley PetscClassId id; 1506c0d7054bSMatthew G. Knepley PetscDualSpace Q = NULL; 15074ef9d792SMatthew G. Knepley PetscQuadrature f; 15084ef9d792SMatthew G. Knepley const PetscReal *qpoints, *qweights; 15099c3cf19fSMatthew G. Knepley PetscInt Nc, qNc, Np, fpdim, i, d; 15104ef9d792SMatthew G. Knepley 15114ef9d792SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr); 15124ef9d792SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 15134ef9d792SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 15144ef9d792SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 15154ef9d792SMatthew G. Knepley 15164ef9d792SMatthew G. Knepley ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 15174ef9d792SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 15184ef9d792SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 15194ef9d792SMatthew G. Knepley PetscFV fv = (PetscFV) obj; 15204ef9d792SMatthew G. Knepley 15214ef9d792SMatthew G. Knepley ierr = PetscFVGetDualSpace(fv, &Q);CHKERRQ(ierr); 15224ef9d792SMatthew G. Knepley Nc = 1; 15234ef9d792SMatthew G. Knepley } 15244ef9d792SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Q, &fpdim);CHKERRQ(ierr); 15254ef9d792SMatthew G. Knepley /* For each fine grid cell */ 15264ef9d792SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 15274ef9d792SMatthew G. Knepley PetscInt *findices, *cindices; 15284ef9d792SMatthew G. Knepley PetscInt numFIndices, numCIndices; 15294ef9d792SMatthew G. Knepley 15306ecaa68aSToby Isaac ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 15314ef9d792SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 15329c3cf19fSMatthew G. Knepley if (numFIndices != fpdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of fine indices %d != %d dual basis vecs", numFIndices, fpdim); 15334ef9d792SMatthew G. Knepley for (i = 0; i < fpdim; ++i) { 15344ef9d792SMatthew G. Knepley Vec pointVec; 15354ef9d792SMatthew G. Knepley PetscScalar *pV; 153612111d7cSToby Isaac PetscSF coarseCellSF = NULL; 15373a93e3b7SToby Isaac const PetscSFNode *coarseCells; 153817f047d8SMatthew G. Knepley PetscInt numCoarseCells, cpdim, q, c, j; 15394ef9d792SMatthew G. Knepley 15404ef9d792SMatthew G. Knepley /* Get points from the dual basis functional quadrature */ 15414ef9d792SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Q, i, &f);CHKERRQ(ierr); 15429c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &qNc, &Np, &qpoints, &qweights);CHKERRQ(ierr); 15439c3cf19fSMatthew G. Knepley if (qNc != Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in quadrature %D does not match coarse field %D", qNc, Nc); 15444ef9d792SMatthew G. Knepley ierr = VecCreateSeq(PETSC_COMM_SELF, Np*dim, &pointVec);CHKERRQ(ierr); 15454ef9d792SMatthew G. Knepley ierr = VecSetBlockSize(pointVec, dim);CHKERRQ(ierr); 15464ef9d792SMatthew G. Knepley ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 15474ef9d792SMatthew G. Knepley for (q = 0; q < Np; ++q) { 15484ef9d792SMatthew G. Knepley /* Transform point to real space */ 15494ef9d792SMatthew G. Knepley CoordinatesRefToReal(dim, dim, v0, J, &qpoints[q*dim], x); 15504ef9d792SMatthew G. Knepley for (d = 0; d < dim; ++d) pV[q*dim+d] = x[d]; 15514ef9d792SMatthew G. Knepley } 15524ef9d792SMatthew G. Knepley ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 15534ef9d792SMatthew G. Knepley /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */ 155462a38674SMatthew G. Knepley ierr = DMLocatePoints(dmc, pointVec, DM_POINTLOCATION_NEAREST, &coarseCellSF);CHKERRQ(ierr); 15554ef9d792SMatthew G. Knepley /* Update preallocation info */ 15563a93e3b7SToby Isaac ierr = PetscSFGetGraph(coarseCellSF, NULL, &numCoarseCells, NULL, &coarseCells);CHKERRQ(ierr); 15573a93e3b7SToby Isaac if (numCoarseCells != Np) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located"); 15584ef9d792SMatthew G. Knepley ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 15594ef9d792SMatthew G. Knepley for (ccell = 0; ccell < numCoarseCells; ++ccell) { 1560826eb36dSMatthew G. Knepley PetscReal pVReal[3]; 1561826eb36dSMatthew G. Knepley 15623a93e3b7SToby Isaac ierr = DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 15634ef9d792SMatthew G. Knepley /* Transform points from real space to coarse reference space */ 15643a93e3b7SToby Isaac ierr = DMPlexComputeCellGeometryFEM(dmc, coarseCells[ccell].index, NULL, v0c, Jc, invJc, &detJc);CHKERRQ(ierr); 1565e2d86523SMatthew G. Knepley for (d = 0; d < dim; ++d) pVReal[d] = PetscRealPart(pV[ccell*dim+d]); 1566826eb36dSMatthew G. Knepley CoordinatesRealToRef(dim, dim, v0c, invJc, pVReal, x); 15674ef9d792SMatthew G. Knepley 15684ef9d792SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 15694ef9d792SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 15704ef9d792SMatthew G. Knepley PetscReal *B; 15714ef9d792SMatthew G. Knepley 15724ef9d792SMatthew G. Knepley /* Evaluate coarse basis on contained point */ 15734ef9d792SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &cpdim);CHKERRQ(ierr); 15744ef9d792SMatthew G. Knepley ierr = PetscFEGetTabulation(fe, 1, x, &B, NULL, NULL);CHKERRQ(ierr); 15759c3cf19fSMatthew G. Knepley ierr = PetscMemzero(elemMat, cpdim * sizeof(PetscScalar));CHKERRQ(ierr); 15764ef9d792SMatthew G. Knepley /* Get elemMat entries by multiplying by weight */ 15774ef9d792SMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 15789c3cf19fSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[j] += B[j*Nc + c]*qweights[ccell*qNc + c]; 15794ef9d792SMatthew G. Knepley } 15804ef9d792SMatthew G. Knepley ierr = PetscFERestoreTabulation(fe, 1, x, &B, NULL, NULL);CHKERRQ(ierr);CHKERRQ(ierr); 15814ef9d792SMatthew G. Knepley } else { 15824ef9d792SMatthew G. Knepley cpdim = 1; 15834ef9d792SMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 15849c3cf19fSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[j] += 1.0*qweights[ccell*qNc + c]; 15854ef9d792SMatthew G. Knepley } 15864ef9d792SMatthew G. Knepley } 15874ef9d792SMatthew G. Knepley /* Update interpolator */ 15889c3cf19fSMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);} 15899c3cf19fSMatthew G. Knepley if (numCIndices != cpdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of element matrix columns %D != %D", numCIndices, cpdim); 15909c3cf19fSMatthew G. Knepley ierr = MatSetValues(In, 1, &findices[i], numCIndices, cindices, elemMat, INSERT_VALUES);CHKERRQ(ierr); 15913a93e3b7SToby Isaac ierr = DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 15924ef9d792SMatthew G. Knepley } 15934ef9d792SMatthew G. Knepley ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 15943a93e3b7SToby Isaac ierr = PetscSFDestroy(&coarseCellSF);CHKERRQ(ierr); 15954ef9d792SMatthew G. Knepley ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 15964ef9d792SMatthew G. Knepley } 159746bdb399SToby Isaac ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 15984ef9d792SMatthew G. Knepley } 15994ef9d792SMatthew G. Knepley } 16004ef9d792SMatthew G. Knepley ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr); 16014ef9d792SMatthew G. Knepley ierr = PetscFree3(v0c,Jc,invJc);CHKERRQ(ierr); 16024ef9d792SMatthew G. Knepley ierr = PetscFree(elemMat);CHKERRQ(ierr); 16034ef9d792SMatthew G. Knepley ierr = MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 16044ef9d792SMatthew G. Knepley ierr = MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 160577711781SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 16064ef9d792SMatthew G. Knepley PetscFunctionReturn(0); 16074ef9d792SMatthew G. Knepley } 16084ef9d792SMatthew G. Knepley 160946fa42a0SMatthew G. Knepley /*@ 161046fa42a0SMatthew G. Knepley DMPlexComputeInjectorFEM - Compute a mapping from coarse unknowns to fine unknowns 161146fa42a0SMatthew G. Knepley 161246fa42a0SMatthew G. Knepley Input Parameters: 161346fa42a0SMatthew G. Knepley + dmc - The coarse mesh 161446fa42a0SMatthew G. Knepley - dmf - The fine mesh 161546fa42a0SMatthew G. Knepley - user - The user context 161646fa42a0SMatthew G. Knepley 161746fa42a0SMatthew G. Knepley Output Parameter: 161846fa42a0SMatthew G. Knepley . sc - The mapping 161946fa42a0SMatthew G. Knepley 162046fa42a0SMatthew G. Knepley Level: developer 162146fa42a0SMatthew G. Knepley 162246fa42a0SMatthew G. Knepley .seealso: DMPlexComputeInterpolatorNested(), DMPlexComputeJacobianFEM() 162346fa42a0SMatthew G. Knepley @*/ 16247c927364SMatthew G. Knepley PetscErrorCode DMPlexComputeInjectorFEM(DM dmc, DM dmf, VecScatter *sc, void *user) 16257c927364SMatthew G. Knepley { 1626e9d4ef1bSMatthew G. Knepley PetscDS prob; 16277c927364SMatthew G. Knepley PetscFE *feRef; 162897c42addSMatthew G. Knepley PetscFV *fvRef; 16297c927364SMatthew G. Knepley Vec fv, cv; 16307c927364SMatthew G. Knepley IS fis, cis; 16317c927364SMatthew G. Knepley PetscSection fsection, fglobalSection, csection, cglobalSection; 16327c927364SMatthew G. Knepley PetscInt *cmap, *cellCIndices, *cellFIndices, *cindices, *findices; 16330bd915a7SMatthew G. Knepley PetscInt cTotDim, fTotDim = 0, Nf, f, field, cStart, cEnd, cEndInterior, c, dim, d, startC, endC, offsetC, offsetF, m; 16347c927364SMatthew G. Knepley PetscErrorCode ierr; 16357c927364SMatthew G. Knepley 16367c927364SMatthew G. Knepley PetscFunctionBegin; 163775a69067SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1638c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 16397c927364SMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 16407c927364SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 16417c927364SMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 16427c927364SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 16437c927364SMatthew G. Knepley ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 16447c927364SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 16459ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dmc, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 16469ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 1647e9d4ef1bSMatthew G. Knepley ierr = DMGetDS(dmc, &prob);CHKERRQ(ierr); 164897c42addSMatthew G. Knepley ierr = PetscCalloc2(Nf,&feRef,Nf,&fvRef);CHKERRQ(ierr); 16497c927364SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 165097c42addSMatthew G. Knepley PetscObject obj; 165197c42addSMatthew G. Knepley PetscClassId id; 1652aa7890ccSMatthew G. Knepley PetscInt fNb = 0, Nc = 0; 16537c927364SMatthew G. Knepley 165497c42addSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 165597c42addSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 165697c42addSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 165797c42addSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 165897c42addSMatthew G. Knepley 16597c927364SMatthew G. Knepley ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 16607c927364SMatthew G. Knepley ierr = PetscFEGetDimension(feRef[f], &fNb);CHKERRQ(ierr); 16617c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 166297c42addSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 166397c42addSMatthew G. Knepley PetscFV fv = (PetscFV) obj; 166497c42addSMatthew G. Knepley PetscDualSpace Q; 166597c42addSMatthew G. Knepley 166697c42addSMatthew G. Knepley ierr = PetscFVRefine(fv, &fvRef[f]);CHKERRQ(ierr); 166797c42addSMatthew G. Knepley ierr = PetscFVGetDualSpace(fvRef[f], &Q);CHKERRQ(ierr); 166897c42addSMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Q, &fNb);CHKERRQ(ierr); 166997c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 167097c42addSMatthew G. Knepley } 16717c927364SMatthew G. Knepley fTotDim += fNb*Nc; 16727c927364SMatthew G. Knepley } 1673e9d4ef1bSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 16747c927364SMatthew G. Knepley ierr = PetscMalloc1(cTotDim,&cmap);CHKERRQ(ierr); 16757c927364SMatthew G. Knepley for (field = 0, offsetC = 0, offsetF = 0; field < Nf; ++field) { 16767c927364SMatthew G. Knepley PetscFE feC; 167797c42addSMatthew G. Knepley PetscFV fvC; 16787c927364SMatthew G. Knepley PetscDualSpace QF, QC; 16797c927364SMatthew G. Knepley PetscInt NcF, NcC, fpdim, cpdim; 16807c927364SMatthew G. Knepley 168197c42addSMatthew G. Knepley if (feRef[field]) { 1682e9d4ef1bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &feC);CHKERRQ(ierr); 16837c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(feC, &NcC);CHKERRQ(ierr); 16847c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(feRef[field], &NcF);CHKERRQ(ierr); 16857c927364SMatthew G. Knepley ierr = PetscFEGetDualSpace(feRef[field], &QF);CHKERRQ(ierr); 16867c927364SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QF, &fpdim);CHKERRQ(ierr); 16877c927364SMatthew G. Knepley ierr = PetscFEGetDualSpace(feC, &QC);CHKERRQ(ierr); 16887c927364SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QC, &cpdim);CHKERRQ(ierr); 168997c42addSMatthew G. Knepley } else { 169097c42addSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fvC);CHKERRQ(ierr); 169197c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fvC, &NcC);CHKERRQ(ierr); 169297c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fvRef[field], &NcF);CHKERRQ(ierr); 169397c42addSMatthew G. Knepley ierr = PetscFVGetDualSpace(fvRef[field], &QF);CHKERRQ(ierr); 169497c42addSMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QF, &fpdim);CHKERRQ(ierr); 169597c42addSMatthew G. Knepley ierr = PetscFVGetDualSpace(fvC, &QC);CHKERRQ(ierr); 169697c42addSMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QC, &cpdim);CHKERRQ(ierr); 169797c42addSMatthew G. Knepley } 169897c42addSMatthew G. Knepley if (NcF != NcC) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in fine space field %d does not match coarse field %d", NcF, NcC); 16997c927364SMatthew G. Knepley for (c = 0; c < cpdim; ++c) { 17007c927364SMatthew G. Knepley PetscQuadrature cfunc; 17017c927364SMatthew G. Knepley const PetscReal *cqpoints; 17027c927364SMatthew G. Knepley PetscInt NpC; 170397c42addSMatthew G. Knepley PetscBool found = PETSC_FALSE; 17047c927364SMatthew G. Knepley 17057c927364SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(QC, c, &cfunc);CHKERRQ(ierr); 17069c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(cfunc, NULL, NULL, &NpC, &cqpoints, NULL);CHKERRQ(ierr); 170797c42addSMatthew G. Knepley if (NpC != 1 && feRef[field]) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not know how to do injection for moments"); 17087c927364SMatthew G. Knepley for (f = 0; f < fpdim; ++f) { 17097c927364SMatthew G. Knepley PetscQuadrature ffunc; 17107c927364SMatthew G. Knepley const PetscReal *fqpoints; 17117c927364SMatthew G. Knepley PetscReal sum = 0.0; 17127c927364SMatthew G. Knepley PetscInt NpF, comp; 17137c927364SMatthew G. Knepley 17147c927364SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(QF, f, &ffunc);CHKERRQ(ierr); 17159c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(ffunc, NULL, NULL, &NpF, &fqpoints, NULL);CHKERRQ(ierr); 17167c927364SMatthew G. Knepley if (NpC != NpF) continue; 17177c927364SMatthew G. Knepley for (d = 0; d < dim; ++d) sum += PetscAbsReal(cqpoints[d] - fqpoints[d]); 17187c927364SMatthew G. Knepley if (sum > 1.0e-9) continue; 17197c927364SMatthew G. Knepley for (comp = 0; comp < NcC; ++comp) { 17207c927364SMatthew G. Knepley cmap[(offsetC+c)*NcC+comp] = (offsetF+f)*NcF+comp; 17217c927364SMatthew G. Knepley } 172297c42addSMatthew G. Knepley found = PETSC_TRUE; 17237c927364SMatthew G. Knepley break; 17247c927364SMatthew G. Knepley } 172597c42addSMatthew G. Knepley if (!found) { 172697c42addSMatthew G. Knepley /* TODO We really want the average here, but some asshole put VecScatter in the interface */ 172797c42addSMatthew G. Knepley if (fvRef[field]) { 172897c42addSMatthew G. Knepley PetscInt comp; 172997c42addSMatthew G. Knepley for (comp = 0; comp < NcC; ++comp) { 173097c42addSMatthew G. Knepley cmap[(offsetC+c)*NcC+comp] = (offsetF+0)*NcF+comp; 173197c42addSMatthew G. Knepley } 173297c42addSMatthew G. Knepley } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate matching functional for injection"); 173397c42addSMatthew G. Knepley } 17347c927364SMatthew G. Knepley } 17357c927364SMatthew G. Knepley offsetC += cpdim*NcC; 17367c927364SMatthew G. Knepley offsetF += fpdim*NcF; 17377c927364SMatthew G. Knepley } 173897c42addSMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);ierr = PetscFVDestroy(&fvRef[f]);CHKERRQ(ierr);} 173997c42addSMatthew G. Knepley ierr = PetscFree2(feRef,fvRef);CHKERRQ(ierr); 17407c927364SMatthew G. Knepley 17417c927364SMatthew G. Knepley ierr = DMGetGlobalVector(dmf, &fv);CHKERRQ(ierr); 17427c927364SMatthew G. Knepley ierr = DMGetGlobalVector(dmc, &cv);CHKERRQ(ierr); 17430bd915a7SMatthew G. Knepley ierr = VecGetOwnershipRange(cv, &startC, &endC);CHKERRQ(ierr); 17447c927364SMatthew G. Knepley ierr = PetscSectionGetConstrainedStorageSize(cglobalSection, &m);CHKERRQ(ierr); 17457c927364SMatthew G. Knepley ierr = PetscMalloc2(cTotDim,&cellCIndices,fTotDim,&cellFIndices);CHKERRQ(ierr); 1746aa7da3c4SMatthew G. Knepley ierr = PetscMalloc1(m,&cindices);CHKERRQ(ierr); 1747aa7da3c4SMatthew G. Knepley ierr = PetscMalloc1(m,&findices);CHKERRQ(ierr); 17487c927364SMatthew G. Knepley for (d = 0; d < m; ++d) cindices[d] = findices[d] = -1; 17497c927364SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 17507c927364SMatthew G. Knepley ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, c, cellCIndices, cellFIndices);CHKERRQ(ierr); 17517c927364SMatthew G. Knepley for (d = 0; d < cTotDim; ++d) { 17520bd915a7SMatthew G. Knepley if ((cellCIndices[d] < startC) || (cellCIndices[d] >= endC)) continue; 17537c927364SMatthew G. Knepley if ((findices[cellCIndices[d]-startC] >= 0) && (findices[cellCIndices[d]-startC] != cellFIndices[cmap[d]])) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Coarse dof %d maps to both %d and %d", cindices[cellCIndices[d]-startC], findices[cellCIndices[d]-startC], cellFIndices[cmap[d]]); 17547c927364SMatthew G. Knepley cindices[cellCIndices[d]-startC] = cellCIndices[d]; 17557c927364SMatthew G. Knepley findices[cellCIndices[d]-startC] = cellFIndices[cmap[d]]; 17567c927364SMatthew G. Knepley } 17577c927364SMatthew G. Knepley } 17587c927364SMatthew G. Knepley ierr = PetscFree(cmap);CHKERRQ(ierr); 17597c927364SMatthew G. Knepley ierr = PetscFree2(cellCIndices,cellFIndices);CHKERRQ(ierr); 17607c927364SMatthew G. Knepley 17617c927364SMatthew G. Knepley ierr = ISCreateGeneral(PETSC_COMM_SELF, m, cindices, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 17627c927364SMatthew G. Knepley ierr = ISCreateGeneral(PETSC_COMM_SELF, m, findices, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 17637c927364SMatthew G. Knepley ierr = VecScatterCreate(cv, cis, fv, fis, sc);CHKERRQ(ierr); 17647c927364SMatthew G. Knepley ierr = ISDestroy(&cis);CHKERRQ(ierr); 17657c927364SMatthew G. Knepley ierr = ISDestroy(&fis);CHKERRQ(ierr); 17667c927364SMatthew G. Knepley ierr = DMRestoreGlobalVector(dmf, &fv);CHKERRQ(ierr); 17677c927364SMatthew G. Knepley ierr = DMRestoreGlobalVector(dmc, &cv);CHKERRQ(ierr); 176875a69067SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1769cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 1770cb1e1211SMatthew G Knepley } 1771