1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2da97024aSMatthew G. Knepley #include <petscsf.h> 3cb1e1211SMatthew G Knepley 4e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h> 5af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h> 6af0996ceSBarry Smith #include <petsc/private/petscfvimpl.h> 7a0845e3aSMatthew G. Knepley 846fa42a0SMatthew G. Knepley /*@ 946fa42a0SMatthew G. Knepley DMPlexGetScale - Get the scale for the specified fundamental unit 1046fa42a0SMatthew G. Knepley 1146fa42a0SMatthew G. Knepley Not collective 1246fa42a0SMatthew G. Knepley 1346fa42a0SMatthew G. Knepley Input Arguments: 1446fa42a0SMatthew G. Knepley + dm - the DM 1546fa42a0SMatthew G. Knepley - unit - The SI unit 1646fa42a0SMatthew G. Knepley 1746fa42a0SMatthew G. Knepley Output Argument: 1846fa42a0SMatthew G. Knepley . scale - The value used to scale all quantities with this unit 1946fa42a0SMatthew G. Knepley 2046fa42a0SMatthew G. Knepley Level: advanced 2146fa42a0SMatthew G. Knepley 2246fa42a0SMatthew G. Knepley .seealso: DMPlexSetScale(), PetscUnit 2346fa42a0SMatthew G. Knepley @*/ 24cb1e1211SMatthew G Knepley PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 25cb1e1211SMatthew G Knepley { 26cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 27cb1e1211SMatthew G Knepley 28cb1e1211SMatthew G Knepley PetscFunctionBegin; 29cb1e1211SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30cb1e1211SMatthew G Knepley PetscValidPointer(scale, 3); 31cb1e1211SMatthew G Knepley *scale = mesh->scale[unit]; 32cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 33cb1e1211SMatthew G Knepley } 34cb1e1211SMatthew G Knepley 3546fa42a0SMatthew G. Knepley /*@ 3646fa42a0SMatthew G. Knepley DMPlexSetScale - Set the scale for the specified fundamental unit 3746fa42a0SMatthew G. Knepley 3846fa42a0SMatthew G. Knepley Not collective 3946fa42a0SMatthew G. Knepley 4046fa42a0SMatthew G. Knepley Input Arguments: 4146fa42a0SMatthew G. Knepley + dm - the DM 4246fa42a0SMatthew G. Knepley . unit - The SI unit 4346fa42a0SMatthew G. Knepley - scale - The value used to scale all quantities with this unit 4446fa42a0SMatthew G. Knepley 4546fa42a0SMatthew G. Knepley Level: advanced 4646fa42a0SMatthew G. Knepley 4746fa42a0SMatthew G. Knepley .seealso: DMPlexGetScale(), PetscUnit 4846fa42a0SMatthew G. Knepley @*/ 49cb1e1211SMatthew G Knepley PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 50cb1e1211SMatthew G Knepley { 51cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 52cb1e1211SMatthew G Knepley 53cb1e1211SMatthew G Knepley PetscFunctionBegin; 54cb1e1211SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55cb1e1211SMatthew G Knepley mesh->scale[unit] = scale; 56cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 57cb1e1211SMatthew G Knepley } 58cb1e1211SMatthew G Knepley 59d1828a1cSMatthew G. Knepley static PetscErrorCode DMPlexProjectRigidBody_Private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *mode, void *ctx) 60026175e5SToby Isaac { 6112adca46SMatthew 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}}}; 62026175e5SToby Isaac PetscInt *ctxInt = (PetscInt *) ctx; 63ad917190SMatthew G. Knepley PetscInt dim2 = ctxInt[0]; 64026175e5SToby Isaac PetscInt d = ctxInt[1]; 65026175e5SToby Isaac PetscInt i, j, k = dim > 2 ? d - dim : d; 66026175e5SToby Isaac 67ad917190SMatthew G. Knepley PetscFunctionBegin; 68ad917190SMatthew G. Knepley if (dim != dim2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input dimension %d does not match context dimension %d", dim, dim2); 69026175e5SToby Isaac for (i = 0; i < dim; i++) mode[i] = 0.; 70026175e5SToby Isaac if (d < dim) { 7112adca46SMatthew G. Knepley mode[d] = 1.; /* Translation along axis d */ 72ad917190SMatthew G. Knepley } else { 73026175e5SToby Isaac for (i = 0; i < dim; i++) { 74026175e5SToby Isaac for (j = 0; j < dim; j++) { 7512adca46SMatthew G. Knepley mode[j] += eps[i][j][k]*X[i]; /* Rotation about axis d */ 76026175e5SToby Isaac } 77026175e5SToby Isaac } 78026175e5SToby Isaac } 79ad917190SMatthew G. Knepley PetscFunctionReturn(0); 80026175e5SToby Isaac } 81026175e5SToby Isaac 82cb1e1211SMatthew G Knepley /*@C 8312adca46SMatthew G. Knepley DMPlexCreateRigidBody - For the default global section, create rigid body modes by function space interpolation 84cb1e1211SMatthew G Knepley 85cb1e1211SMatthew G Knepley Collective on DM 86cb1e1211SMatthew G Knepley 87cb1e1211SMatthew G Knepley Input Arguments: 88026175e5SToby Isaac . dm - the DM 89cb1e1211SMatthew G Knepley 90cb1e1211SMatthew G Knepley Output Argument: 91cb1e1211SMatthew G Knepley . sp - the null space 92cb1e1211SMatthew G Knepley 9312adca46SMatthew G. Knepley Note: This is necessary to provide a suitable coarse space for algebraic multigrid 94cb1e1211SMatthew G Knepley 95cb1e1211SMatthew G Knepley Level: advanced 96cb1e1211SMatthew G Knepley 9712adca46SMatthew G. Knepley .seealso: MatNullSpaceCreate(), PCGAMG 98cb1e1211SMatthew G Knepley @*/ 99026175e5SToby Isaac PetscErrorCode DMPlexCreateRigidBody(DM dm, MatNullSpace *sp) 100cb1e1211SMatthew G Knepley { 101cb1e1211SMatthew G Knepley MPI_Comm comm; 102026175e5SToby Isaac Vec mode[6]; 103026175e5SToby Isaac PetscSection section, globalSection; 1049d8fbdeaSMatthew G. Knepley PetscInt dim, dimEmbed, n, m, d, i, j; 105cb1e1211SMatthew G Knepley PetscErrorCode ierr; 106cb1e1211SMatthew G Knepley 107cb1e1211SMatthew G Knepley PetscFunctionBegin; 108cb1e1211SMatthew G Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 109c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1109d8fbdeaSMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 111cb1e1211SMatthew G Knepley if (dim == 1) { 112cb1e1211SMatthew G Knepley ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 113cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 114cb1e1211SMatthew G Knepley } 115026175e5SToby Isaac ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 116026175e5SToby Isaac ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 117cb1e1211SMatthew G Knepley ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 118cb1e1211SMatthew G Knepley m = (dim*(dim+1))/2; 119cb1e1211SMatthew G Knepley ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 120cb1e1211SMatthew G Knepley ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 121cb1e1211SMatthew G Knepley ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 122cb1e1211SMatthew G Knepley for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 123026175e5SToby Isaac for (d = 0; d < m; d++) { 124330485fdSToby Isaac PetscInt ctx[2]; 125d1828a1cSMatthew G. Knepley PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *) = DMPlexProjectRigidBody_Private; 126026175e5SToby Isaac void *voidctx = (void *) (&ctx[0]); 127cb1e1211SMatthew G Knepley 1289d8fbdeaSMatthew G. Knepley ctx[0] = dimEmbed; 129330485fdSToby Isaac ctx[1] = d; 1300709b2feSToby Isaac ierr = DMProjectFunction(dm, 0.0, &func, &voidctx, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 131cb1e1211SMatthew G Knepley } 132cb1e1211SMatthew G Knepley for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 133cb1e1211SMatthew G Knepley /* Orthonormalize system */ 134cb1e1211SMatthew G Knepley for (i = dim; i < m; ++i) { 135cb1e1211SMatthew G Knepley PetscScalar dots[6]; 136cb1e1211SMatthew G Knepley 137cb1e1211SMatthew G Knepley ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 138cb1e1211SMatthew G Knepley for (j = 0; j < i; ++j) dots[j] *= -1.0; 139cb1e1211SMatthew G Knepley ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 140cb1e1211SMatthew G Knepley ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 141cb1e1211SMatthew G Knepley } 142cb1e1211SMatthew G Knepley ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 143cb1e1211SMatthew G Knepley for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 144cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 145cb1e1211SMatthew G Knepley } 146cb1e1211SMatthew G Knepley 14712adca46SMatthew G. Knepley /*@C 14812adca46SMatthew G. Knepley DMPlexCreateRigidBodies - For the default global section, create rigid body modes by function space interpolation 14912adca46SMatthew G. Knepley 15012adca46SMatthew G. Knepley Collective on DM 15112adca46SMatthew G. Knepley 15212adca46SMatthew G. Knepley Input Arguments: 15312adca46SMatthew G. Knepley + dm - the DM 15412adca46SMatthew G. Knepley . nb - The number of bodies 15512adca46SMatthew G. Knepley . label - The DMLabel marking each domain 15612adca46SMatthew G. Knepley . nids - The number of ids per body 15712adca46SMatthew G. Knepley - ids - An array of the label ids in sequence for each domain 15812adca46SMatthew G. Knepley 15912adca46SMatthew G. Knepley Output Argument: 16012adca46SMatthew G. Knepley . sp - the null space 16112adca46SMatthew G. Knepley 16212adca46SMatthew G. Knepley Note: This is necessary to provide a suitable coarse space for algebraic multigrid 16312adca46SMatthew G. Knepley 16412adca46SMatthew G. Knepley Level: advanced 16512adca46SMatthew G. Knepley 16612adca46SMatthew G. Knepley .seealso: MatNullSpaceCreate() 16712adca46SMatthew G. Knepley @*/ 16812adca46SMatthew G. Knepley PetscErrorCode DMPlexCreateRigidBodies(DM dm, PetscInt nb, DMLabel label, const PetscInt nids[], const PetscInt ids[], MatNullSpace *sp) 16912adca46SMatthew G. Knepley { 17012adca46SMatthew G. Knepley MPI_Comm comm; 17112adca46SMatthew G. Knepley PetscSection section, globalSection; 17212adca46SMatthew G. Knepley Vec *mode; 17312adca46SMatthew G. Knepley PetscScalar *dots; 17412adca46SMatthew G. Knepley PetscInt dim, dimEmbed, n, m, b, d, i, j, off; 17512adca46SMatthew G. Knepley PetscErrorCode ierr; 17612adca46SMatthew G. Knepley 17712adca46SMatthew G. Knepley PetscFunctionBegin; 17812adca46SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 17912adca46SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 18012adca46SMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 18112adca46SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 18212adca46SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 18312adca46SMatthew G. Knepley ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 18412adca46SMatthew G. Knepley m = nb * (dim*(dim+1))/2; 18512adca46SMatthew G. Knepley ierr = PetscMalloc2(m, &mode, m, &dots);CHKERRQ(ierr); 18612adca46SMatthew G. Knepley ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 18712adca46SMatthew G. Knepley ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 18812adca46SMatthew G. Knepley ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 18912adca46SMatthew G. Knepley for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 19012adca46SMatthew G. Knepley for (b = 0, off = 0; b < nb; ++b) { 19112adca46SMatthew G. Knepley for (d = 0; d < m/nb; ++d) { 19212adca46SMatthew G. Knepley PetscInt ctx[2]; 19312adca46SMatthew G. Knepley PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *) = DMPlexProjectRigidBody_Private; 19412adca46SMatthew G. Knepley void *voidctx = (void *) (&ctx[0]); 19512adca46SMatthew G. Knepley 19612adca46SMatthew G. Knepley ctx[0] = dimEmbed; 19712adca46SMatthew G. Knepley ctx[1] = d; 19812adca46SMatthew G. Knepley ierr = DMProjectFunctionLabel(dm, 0.0, label, nids[b], &ids[off], 0, NULL, &func, &voidctx, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 19912adca46SMatthew G. Knepley off += nids[b]; 20012adca46SMatthew G. Knepley } 20112adca46SMatthew G. Knepley } 20212adca46SMatthew G. Knepley for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 20312adca46SMatthew G. Knepley /* Orthonormalize system */ 20412adca46SMatthew G. Knepley for (i = 0; i < m; ++i) { 20512adca46SMatthew G. Knepley ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 20612adca46SMatthew G. Knepley for (j = 0; j < i; ++j) dots[j] *= -1.0; 20712adca46SMatthew G. Knepley ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 20812adca46SMatthew G. Knepley ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 20912adca46SMatthew G. Knepley } 21012adca46SMatthew G. Knepley ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 21112adca46SMatthew G. Knepley for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 21212adca46SMatthew G. Knepley ierr = PetscFree2(mode, dots);CHKERRQ(ierr); 21312adca46SMatthew G. Knepley PetscFunctionReturn(0); 21412adca46SMatthew G. Knepley } 21512adca46SMatthew G. Knepley 216b29cfa1cSToby Isaac /*@ 217b29cfa1cSToby Isaac DMPlexSetMaxProjectionHeight - In DMPlexProjectXXXLocal() functions, the projected values of a basis function's dofs 218b29cfa1cSToby Isaac are computed by associating the basis function with one of the mesh points in its transitively-closed support, and 219b29cfa1cSToby Isaac evaluating the dual space basis of that point. A basis function is associated with the point in its 220b29cfa1cSToby Isaac transitively-closed support whose mesh height is highest (w.r.t. DAG height), but not greater than the maximum 221b29cfa1cSToby Isaac projection height, which is set with this function. By default, the maximum projection height is zero, which means 222b29cfa1cSToby Isaac that only mesh cells are used to project basis functions. A height of one, for example, evaluates a cell-interior 223b29cfa1cSToby Isaac basis functions using its cells dual space basis, but all other basis functions with the dual space basis of a face. 224b29cfa1cSToby Isaac 225b29cfa1cSToby Isaac Input Parameters: 226b29cfa1cSToby Isaac + dm - the DMPlex object 227b29cfa1cSToby Isaac - height - the maximum projection height >= 0 228b29cfa1cSToby Isaac 229b29cfa1cSToby Isaac Level: advanced 230b29cfa1cSToby Isaac 2314d6f44ffSToby Isaac .seealso: DMPlexGetMaxProjectionHeight(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal() 232b29cfa1cSToby Isaac @*/ 233b29cfa1cSToby Isaac PetscErrorCode DMPlexSetMaxProjectionHeight(DM dm, PetscInt height) 234b29cfa1cSToby Isaac { 235b29cfa1cSToby Isaac DM_Plex *plex = (DM_Plex *) dm->data; 236b29cfa1cSToby Isaac 237b29cfa1cSToby Isaac PetscFunctionBegin; 238b29cfa1cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 239b29cfa1cSToby Isaac plex->maxProjectionHeight = height; 240b29cfa1cSToby Isaac PetscFunctionReturn(0); 241b29cfa1cSToby Isaac } 242b29cfa1cSToby Isaac 243b29cfa1cSToby Isaac /*@ 244b29cfa1cSToby Isaac DMPlexGetMaxProjectionHeight - Get the maximum height (w.r.t. DAG) of mesh points used to evaluate dual bases in 245b29cfa1cSToby Isaac DMPlexProjectXXXLocal() functions. 246b29cfa1cSToby Isaac 247b29cfa1cSToby Isaac Input Parameters: 248b29cfa1cSToby Isaac . dm - the DMPlex object 249b29cfa1cSToby Isaac 250b29cfa1cSToby Isaac Output Parameters: 251b29cfa1cSToby Isaac . height - the maximum projection height 252b29cfa1cSToby Isaac 253b29cfa1cSToby Isaac Level: intermediate 254b29cfa1cSToby Isaac 2554d6f44ffSToby Isaac .seealso: DMPlexSetMaxProjectionHeight(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal() 256b29cfa1cSToby Isaac @*/ 257b29cfa1cSToby Isaac PetscErrorCode DMPlexGetMaxProjectionHeight(DM dm, PetscInt *height) 258b29cfa1cSToby Isaac { 259b29cfa1cSToby Isaac DM_Plex *plex = (DM_Plex *) dm->data; 260b29cfa1cSToby Isaac 261b29cfa1cSToby Isaac PetscFunctionBegin; 262b29cfa1cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 263b29cfa1cSToby Isaac *height = plex->maxProjectionHeight; 264b29cfa1cSToby Isaac PetscFunctionReturn(0); 265b29cfa1cSToby Isaac } 266b29cfa1cSToby Isaac 267b278463cSMatthew G. Knepley /*@C 268b278463cSMatthew G. Knepley DMPlexInsertBoundaryValuesEssential - Insert boundary values into a local vector 269b278463cSMatthew G. Knepley 270b278463cSMatthew G. Knepley Input Parameters: 271b278463cSMatthew G. Knepley + dm - The DM, with a PetscDS that matches the problem being constrained 272b278463cSMatthew G. Knepley . time - The time 273b278463cSMatthew G. Knepley . field - The field to constrain 2741c531cf8SMatthew G. Knepley . Nc - The number of constrained field components, or 0 for all components 2751c531cf8SMatthew G. Knepley . comps - An array of constrained component numbers, or NULL for all components 276b278463cSMatthew G. Knepley . label - The DMLabel defining constrained points 277b278463cSMatthew G. Knepley . numids - The number of DMLabel ids for constrained points 278b278463cSMatthew G. Knepley . ids - An array of ids for constrained points 279b278463cSMatthew G. Knepley . func - A pointwise function giving boundary values 280b278463cSMatthew G. Knepley - ctx - An optional user context for bcFunc 281b278463cSMatthew G. Knepley 282b278463cSMatthew G. Knepley Output Parameter: 283b278463cSMatthew G. Knepley . locX - A local vector to receives the boundary values 284b278463cSMatthew G. Knepley 285b278463cSMatthew G. Knepley Level: developer 286b278463cSMatthew G. Knepley 287b278463cSMatthew G. Knepley .seealso: DMPlexInsertBoundaryValuesEssentialField(), DMAddBoundary() 288b278463cSMatthew G. Knepley @*/ 2891c531cf8SMatthew 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) 29055f2e967SMatthew G. Knepley { 2910163fd50SMatthew G. Knepley PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 29255f2e967SMatthew G. Knepley void **ctxs; 293d7ddef95SMatthew G. Knepley PetscInt numFields; 294d7ddef95SMatthew G. Knepley PetscErrorCode ierr; 295d7ddef95SMatthew G. Knepley 296d7ddef95SMatthew G. Knepley PetscFunctionBegin; 297d7ddef95SMatthew G. Knepley ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 298d7ddef95SMatthew G. Knepley ierr = PetscCalloc2(numFields,&funcs,numFields,&ctxs);CHKERRQ(ierr); 299d7ddef95SMatthew G. Knepley funcs[field] = func; 300d7ddef95SMatthew G. Knepley ctxs[field] = ctx; 3011c531cf8SMatthew G. Knepley ierr = DMProjectFunctionLabelLocal(dm, time, label, numids, ids, Nc, comps, funcs, ctxs, INSERT_BC_VALUES, locX);CHKERRQ(ierr); 302d7ddef95SMatthew G. Knepley ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr); 303d7ddef95SMatthew G. Knepley PetscFunctionReturn(0); 304d7ddef95SMatthew G. Knepley } 305d7ddef95SMatthew G. Knepley 306b278463cSMatthew G. Knepley /*@C 307b278463cSMatthew G. Knepley DMPlexInsertBoundaryValuesEssentialField - Insert boundary values into a local vector 308b278463cSMatthew G. Knepley 309b278463cSMatthew G. Knepley Input Parameters: 310b278463cSMatthew G. Knepley + dm - The DM, with a PetscDS that matches the problem being constrained 311b278463cSMatthew G. Knepley . time - The time 312b278463cSMatthew G. Knepley . locU - A local vector with the input solution values 313b278463cSMatthew G. Knepley . field - The field to constrain 3141c531cf8SMatthew G. Knepley . Nc - The number of constrained field components, or 0 for all components 3151c531cf8SMatthew G. Knepley . comps - An array of constrained component numbers, or NULL for all components 316b278463cSMatthew G. Knepley . label - The DMLabel defining constrained points 317b278463cSMatthew G. Knepley . numids - The number of DMLabel ids for constrained points 318b278463cSMatthew G. Knepley . ids - An array of ids for constrained points 319b278463cSMatthew G. Knepley . func - A pointwise function giving boundary values 320b278463cSMatthew G. Knepley - ctx - An optional user context for bcFunc 321b278463cSMatthew G. Knepley 322b278463cSMatthew G. Knepley Output Parameter: 323b278463cSMatthew G. Knepley . locX - A local vector to receives the boundary values 324b278463cSMatthew G. Knepley 325b278463cSMatthew G. Knepley Level: developer 326b278463cSMatthew G. Knepley 327b278463cSMatthew G. Knepley .seealso: DMPlexInsertBoundaryValuesEssential(), DMAddBoundary() 328b278463cSMatthew G. Knepley @*/ 3291c531cf8SMatthew G. Knepley PetscErrorCode DMPlexInsertBoundaryValuesEssentialField(DM dm, PetscReal time, Vec locU, PetscInt field, PetscInt Nc, const PetscInt comps[], DMLabel label, PetscInt numids, const PetscInt ids[], 330c60e475cSMatthew G. Knepley void (*func)(PetscInt, PetscInt, PetscInt, 331c60e475cSMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 332c60e475cSMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 33397b6e6e8SMatthew G. Knepley PetscReal, const PetscReal[], PetscInt, const PetscScalar[], 334b278463cSMatthew G. Knepley PetscScalar[]), 335b278463cSMatthew G. Knepley void *ctx, Vec locX) 336c60e475cSMatthew G. Knepley { 337c60e475cSMatthew G. Knepley void (**funcs)(PetscInt, PetscInt, PetscInt, 338c60e475cSMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 339c60e475cSMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 34097b6e6e8SMatthew G. Knepley PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]); 341c60e475cSMatthew G. Knepley void **ctxs; 342c60e475cSMatthew G. Knepley PetscInt numFields; 343c60e475cSMatthew G. Knepley PetscErrorCode ierr; 344c60e475cSMatthew G. Knepley 345c60e475cSMatthew G. Knepley PetscFunctionBegin; 346c60e475cSMatthew G. Knepley ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 347c60e475cSMatthew G. Knepley ierr = PetscCalloc2(numFields,&funcs,numFields,&ctxs);CHKERRQ(ierr); 348c60e475cSMatthew G. Knepley funcs[field] = func; 349c60e475cSMatthew G. Knepley ctxs[field] = ctx; 3501c531cf8SMatthew G. Knepley ierr = DMProjectFieldLabelLocal(dm, time, label, numids, ids, Nc, comps, locU, funcs, INSERT_BC_VALUES, locX);CHKERRQ(ierr); 351c60e475cSMatthew G. Knepley ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr); 352c60e475cSMatthew G. Knepley PetscFunctionReturn(0); 353c60e475cSMatthew G. Knepley } 354c60e475cSMatthew G. Knepley 355b278463cSMatthew G. Knepley /*@C 356b278463cSMatthew G. Knepley DMPlexInsertBoundaryValuesRiemann - Insert boundary values into a local vector 357b278463cSMatthew G. Knepley 358b278463cSMatthew G. Knepley Input Parameters: 359b278463cSMatthew G. Knepley + dm - The DM, with a PetscDS that matches the problem being constrained 360b278463cSMatthew G. Knepley . time - The time 361b278463cSMatthew G. Knepley . faceGeometry - A vector with the FVM face geometry information 362b278463cSMatthew G. Knepley . cellGeometry - A vector with the FVM cell geometry information 363b278463cSMatthew G. Knepley . Grad - A vector with the FVM cell gradient information 364b278463cSMatthew G. Knepley . field - The field to constrain 3651c531cf8SMatthew G. Knepley . Nc - The number of constrained field components, or 0 for all components 3661c531cf8SMatthew G. Knepley . comps - An array of constrained component numbers, or NULL for all components 367b278463cSMatthew G. Knepley . label - The DMLabel defining constrained points 368b278463cSMatthew G. Knepley . numids - The number of DMLabel ids for constrained points 369b278463cSMatthew G. Knepley . ids - An array of ids for constrained points 370b278463cSMatthew G. Knepley . func - A pointwise function giving boundary values 371b278463cSMatthew G. Knepley - ctx - An optional user context for bcFunc 372b278463cSMatthew G. Knepley 373b278463cSMatthew G. Knepley Output Parameter: 374b278463cSMatthew G. Knepley . locX - A local vector to receives the boundary values 375b278463cSMatthew G. Knepley 376b278463cSMatthew G. Knepley Note: This implementation currently ignores the numcomps/comps argument from DMAddBoundary() 377b278463cSMatthew G. Knepley 378b278463cSMatthew G. Knepley Level: developer 379b278463cSMatthew G. Knepley 380b278463cSMatthew G. Knepley .seealso: DMPlexInsertBoundaryValuesEssential(), DMPlexInsertBoundaryValuesEssentialField(), DMAddBoundary() 381b278463cSMatthew G. Knepley @*/ 3821c531cf8SMatthew 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[], 383b278463cSMatthew G. Knepley PetscErrorCode (*func)(PetscReal,const PetscReal*,const PetscReal*,const PetscScalar*,PetscScalar*,void*), void *ctx, Vec locX) 384d7ddef95SMatthew G. Knepley { 38561f58d28SMatthew G. Knepley PetscDS prob; 386da97024aSMatthew G. Knepley PetscSF sf; 387d7ddef95SMatthew G. Knepley DM dmFace, dmCell, dmGrad; 38820369375SToby Isaac const PetscScalar *facegeom, *cellgeom = NULL, *grad; 389da97024aSMatthew G. Knepley const PetscInt *leaves; 390d7ddef95SMatthew G. Knepley PetscScalar *x, *fx; 391520b3818SMatthew G. Knepley PetscInt dim, nleaves, loc, fStart, fEnd, pdim, i; 392e735a8a9SMatthew G. Knepley PetscErrorCode ierr, ierru = 0; 393d7ddef95SMatthew G. Knepley 394d7ddef95SMatthew G. Knepley PetscFunctionBegin; 395da97024aSMatthew G. Knepley ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 396da97024aSMatthew G. Knepley ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL);CHKERRQ(ierr); 397da97024aSMatthew G. Knepley nleaves = PetscMax(0, nleaves); 398d7ddef95SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 399d7ddef95SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 40061f58d28SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 401d7ddef95SMatthew G. Knepley ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr); 402d7ddef95SMatthew G. Knepley ierr = VecGetArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 40320369375SToby Isaac if (cellGeometry) { 404d7ddef95SMatthew G. Knepley ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr); 405d7ddef95SMatthew G. Knepley ierr = VecGetArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); 40620369375SToby Isaac } 407d7ddef95SMatthew G. Knepley if (Grad) { 408c0a6632aSMatthew G. Knepley PetscFV fv; 409c0a6632aSMatthew G. Knepley 410c0a6632aSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fv);CHKERRQ(ierr); 411d7ddef95SMatthew G. Knepley ierr = VecGetDM(Grad, &dmGrad);CHKERRQ(ierr); 412d7ddef95SMatthew G. Knepley ierr = VecGetArrayRead(Grad, &grad);CHKERRQ(ierr); 413d7ddef95SMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &pdim);CHKERRQ(ierr); 41469291d52SBarry Smith ierr = DMGetWorkArray(dm, pdim, MPIU_SCALAR, &fx);CHKERRQ(ierr); 415d7ddef95SMatthew G. Knepley } 416d7ddef95SMatthew G. Knepley ierr = VecGetArray(locX, &x);CHKERRQ(ierr); 417d7ddef95SMatthew G. Knepley for (i = 0; i < numids; ++i) { 418d7ddef95SMatthew G. Knepley IS faceIS; 419d7ddef95SMatthew G. Knepley const PetscInt *faces; 420d7ddef95SMatthew G. Knepley PetscInt numFaces, f; 421d7ddef95SMatthew G. Knepley 422d7ddef95SMatthew G. Knepley ierr = DMLabelGetStratumIS(label, ids[i], &faceIS);CHKERRQ(ierr); 423d7ddef95SMatthew G. Knepley if (!faceIS) continue; /* No points with that id on this process */ 424d7ddef95SMatthew G. Knepley ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 425d7ddef95SMatthew G. Knepley ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 426d7ddef95SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 427d7ddef95SMatthew G. Knepley const PetscInt face = faces[f], *cells; 428640bce14SSatish Balay PetscFVFaceGeom *fg; 429d7ddef95SMatthew G. Knepley 430d7ddef95SMatthew G. Knepley if ((face < fStart) || (face >= fEnd)) continue; /* Refinement adds non-faces to labels */ 431da97024aSMatthew G. Knepley ierr = PetscFindInt(face, nleaves, (PetscInt *) leaves, &loc);CHKERRQ(ierr); 432da97024aSMatthew G. Knepley if (loc >= 0) continue; 433d7ddef95SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr); 434d7ddef95SMatthew G. Knepley ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr); 435d7ddef95SMatthew G. Knepley if (Grad) { 436640bce14SSatish Balay PetscFVCellGeom *cg; 437640bce14SSatish Balay PetscScalar *cx, *cgrad; 438d7ddef95SMatthew G. Knepley PetscScalar *xG; 439d7ddef95SMatthew G. Knepley PetscReal dx[3]; 440d7ddef95SMatthew G. Knepley PetscInt d; 441d7ddef95SMatthew G. Knepley 442d7ddef95SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cg);CHKERRQ(ierr); 443d7ddef95SMatthew G. Knepley ierr = DMPlexPointLocalRead(dm, cells[0], x, &cx);CHKERRQ(ierr); 444d7ddef95SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmGrad, cells[0], grad, &cgrad);CHKERRQ(ierr); 445520b3818SMatthew G. Knepley ierr = DMPlexPointLocalFieldRef(dm, cells[1], field, x, &xG);CHKERRQ(ierr); 446d7ddef95SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, cg->centroid, fg->centroid, dx); 447d7ddef95SMatthew G. Knepley for (d = 0; d < pdim; ++d) fx[d] = cx[d] + DMPlex_DotD_Internal(dim, &cgrad[d*dim], dx); 448e735a8a9SMatthew G. Knepley ierru = (*func)(time, fg->centroid, fg->normal, fx, xG, ctx); 449e735a8a9SMatthew G. Knepley if (ierru) { 450e735a8a9SMatthew G. Knepley ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 451e735a8a9SMatthew G. Knepley ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 452e735a8a9SMatthew G. Knepley goto cleanup; 453e735a8a9SMatthew G. Knepley } 454d7ddef95SMatthew G. Knepley } else { 455640bce14SSatish Balay PetscScalar *xI; 456d7ddef95SMatthew G. Knepley PetscScalar *xG; 457d7ddef95SMatthew G. Knepley 458d7ddef95SMatthew G. Knepley ierr = DMPlexPointLocalRead(dm, cells[0], x, &xI);CHKERRQ(ierr); 459520b3818SMatthew G. Knepley ierr = DMPlexPointLocalFieldRef(dm, cells[1], field, x, &xG);CHKERRQ(ierr); 460e735a8a9SMatthew G. Knepley ierru = (*func)(time, fg->centroid, fg->normal, xI, xG, ctx); 461e735a8a9SMatthew G. Knepley if (ierru) { 462e735a8a9SMatthew G. Knepley ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 463e735a8a9SMatthew G. Knepley ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 464e735a8a9SMatthew G. Knepley goto cleanup; 465e735a8a9SMatthew G. Knepley } 466d7ddef95SMatthew G. Knepley } 467d7ddef95SMatthew G. Knepley } 468d7ddef95SMatthew G. Knepley ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 469d7ddef95SMatthew G. Knepley ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 470d7ddef95SMatthew G. Knepley } 471e735a8a9SMatthew G. Knepley cleanup: 472d7ddef95SMatthew G. Knepley ierr = VecRestoreArray(locX, &x);CHKERRQ(ierr); 473d7ddef95SMatthew G. Knepley if (Grad) { 47469291d52SBarry Smith ierr = DMRestoreWorkArray(dm, pdim, MPIU_SCALAR, &fx);CHKERRQ(ierr); 475d7ddef95SMatthew G. Knepley ierr = VecRestoreArrayRead(Grad, &grad);CHKERRQ(ierr); 476d7ddef95SMatthew G. Knepley } 477e735a8a9SMatthew G. Knepley if (cellGeometry) {ierr = VecRestoreArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr);} 478d7ddef95SMatthew G. Knepley ierr = VecRestoreArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 479e735a8a9SMatthew G. Knepley CHKERRQ(ierru); 480d7ddef95SMatthew G. Knepley PetscFunctionReturn(0); 481d7ddef95SMatthew G. Knepley } 482d7ddef95SMatthew G. Knepley 483f1d73a7aSMatthew G. Knepley PetscErrorCode DMPlexInsertBoundaryValues_Plex(DM dm, PetscBool insertEssential, Vec locX, PetscReal time, Vec faceGeomFVM, Vec cellGeomFVM, Vec gradFVM) 484d7ddef95SMatthew G. Knepley { 485d7ddef95SMatthew G. Knepley PetscInt numBd, b; 48655f2e967SMatthew G. Knepley PetscErrorCode ierr; 48755f2e967SMatthew G. Knepley 48855f2e967SMatthew G. Knepley PetscFunctionBegin; 489dff059c6SToby Isaac ierr = PetscDSGetNumBoundary(dm->prob, &numBd);CHKERRQ(ierr); 49055f2e967SMatthew G. Knepley for (b = 0; b < numBd; ++b) { 491f971fd6bSMatthew G. Knepley DMBoundaryConditionType type; 492d7ddef95SMatthew G. Knepley const char *labelname; 493d7ddef95SMatthew G. Knepley DMLabel label; 4941c531cf8SMatthew G. Knepley PetscInt field, Nc; 4951c531cf8SMatthew G. Knepley const PetscInt *comps; 496d7ddef95SMatthew G. Knepley PetscObject obj; 497d7ddef95SMatthew G. Knepley PetscClassId id; 498a30ec4eaSSatish Balay void (*func)(void); 499d7ddef95SMatthew G. Knepley PetscInt numids; 500d7ddef95SMatthew G. Knepley const PetscInt *ids; 50155f2e967SMatthew G. Knepley void *ctx; 50255f2e967SMatthew G. Knepley 5031c531cf8SMatthew G. Knepley ierr = DMGetBoundary(dm, b, &type, NULL, &labelname, &field, &Nc, &comps, &func, &numids, &ids, &ctx);CHKERRQ(ierr); 504f971fd6bSMatthew G. Knepley if (insertEssential != (type & DM_BC_ESSENTIAL)) continue; 505c58f1c22SToby Isaac ierr = DMGetLabel(dm, labelname, &label);CHKERRQ(ierr); 506d7ddef95SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 507d7ddef95SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 508d7ddef95SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 509c60e475cSMatthew G. Knepley switch (type) { 510c60e475cSMatthew G. Knepley /* for FEM, there is no insertion to be done for non-essential boundary conditions */ 511c60e475cSMatthew G. Knepley case DM_BC_ESSENTIAL: 512092e5057SToby Isaac ierr = DMPlexLabelAddCells(dm,label);CHKERRQ(ierr); 5131c531cf8SMatthew 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); 514092e5057SToby Isaac ierr = DMPlexLabelClearCells(dm,label);CHKERRQ(ierr); 515c60e475cSMatthew G. Knepley break; 516c60e475cSMatthew G. Knepley case DM_BC_ESSENTIAL_FIELD: 517c60e475cSMatthew G. Knepley ierr = DMPlexLabelAddCells(dm,label);CHKERRQ(ierr); 5181c531cf8SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesEssentialField(dm, time, locX, field, Nc, comps, label, numids, ids, 519b278463cSMatthew G. Knepley (void (*)(PetscInt, PetscInt, PetscInt, const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 520c60e475cSMatthew G. Knepley const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 52197b6e6e8SMatthew G. Knepley PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[])) func, ctx, locX);CHKERRQ(ierr); 522c60e475cSMatthew G. Knepley ierr = DMPlexLabelClearCells(dm,label);CHKERRQ(ierr); 523c60e475cSMatthew G. Knepley break; 524c60e475cSMatthew G. Knepley default: break; 525c60e475cSMatthew G. Knepley } 526d7ddef95SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 52743ea7facSMatthew G. Knepley if (!faceGeomFVM) continue; 5281c531cf8SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesRiemann(dm, time, faceGeomFVM, cellGeomFVM, gradFVM, field, Nc, comps, label, numids, ids, 529b278463cSMatthew G. Knepley (PetscErrorCode (*)(PetscReal,const PetscReal*,const PetscReal*,const PetscScalar*,PetscScalar*,void*)) func, ctx, locX);CHKERRQ(ierr); 530d7ddef95SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 53155f2e967SMatthew G. Knepley } 53255f2e967SMatthew G. Knepley PetscFunctionReturn(0); 53355f2e967SMatthew G. Knepley } 53455f2e967SMatthew G. Knepley 535f1d73a7aSMatthew G. Knepley /*@ 536f1d73a7aSMatthew G. Knepley DMPlexInsertBoundaryValues - Puts coefficients which represent boundary values into the local solution vector 537f1d73a7aSMatthew G. Knepley 538f1d73a7aSMatthew G. Knepley Input Parameters: 539f1d73a7aSMatthew G. Knepley + dm - The DM 540f1d73a7aSMatthew G. Knepley . insertEssential - Should I insert essential (e.g. Dirichlet) or inessential (e.g. Neumann) boundary conditions 541f1d73a7aSMatthew G. Knepley . time - The time 542f1d73a7aSMatthew G. Knepley . faceGeomFVM - Face geometry data for FV discretizations 543f1d73a7aSMatthew G. Knepley . cellGeomFVM - Cell geometry data for FV discretizations 544f1d73a7aSMatthew G. Knepley - gradFVM - Gradient reconstruction data for FV discretizations 545f1d73a7aSMatthew G. Knepley 546f1d73a7aSMatthew G. Knepley Output Parameters: 547f1d73a7aSMatthew G. Knepley . locX - Solution updated with boundary values 548f1d73a7aSMatthew G. Knepley 549f1d73a7aSMatthew G. Knepley Level: developer 550f1d73a7aSMatthew G. Knepley 551f1d73a7aSMatthew G. Knepley .seealso: DMProjectFunctionLabelLocal() 552f1d73a7aSMatthew G. Knepley @*/ 553f1d73a7aSMatthew G. Knepley PetscErrorCode DMPlexInsertBoundaryValues(DM dm, PetscBool insertEssential, Vec locX, PetscReal time, Vec faceGeomFVM, Vec cellGeomFVM, Vec gradFVM) 554f1d73a7aSMatthew G. Knepley { 555f1d73a7aSMatthew G. Knepley PetscErrorCode ierr; 556f1d73a7aSMatthew G. Knepley 557f1d73a7aSMatthew G. Knepley PetscFunctionBegin; 558f1d73a7aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 559f1d73a7aSMatthew G. Knepley PetscValidHeaderSpecific(locX, VEC_CLASSID, 2); 560f1d73a7aSMatthew G. Knepley if (faceGeomFVM) {PetscValidHeaderSpecific(faceGeomFVM, VEC_CLASSID, 4);} 561f1d73a7aSMatthew G. Knepley if (cellGeomFVM) {PetscValidHeaderSpecific(cellGeomFVM, VEC_CLASSID, 5);} 562f1d73a7aSMatthew G. Knepley if (gradFVM) {PetscValidHeaderSpecific(gradFVM, VEC_CLASSID, 6);} 563f1d73a7aSMatthew G. Knepley ierr = PetscTryMethod(dm,"DMPlexInsertBoundaryValues_C",(DM,PetscBool,Vec,PetscReal,Vec,Vec,Vec),(dm,insertEssential,locX,time,faceGeomFVM,cellGeomFVM,gradFVM));CHKERRQ(ierr); 564f1d73a7aSMatthew G. Knepley PetscFunctionReturn(0); 565f1d73a7aSMatthew G. Knepley } 566f1d73a7aSMatthew G. Knepley 5670709b2feSToby Isaac PetscErrorCode DMComputeL2Diff_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 568cb1e1211SMatthew G Knepley { 569574a98acSMatthew G. Knepley Vec localX; 570574a98acSMatthew G. Knepley PetscErrorCode ierr; 571574a98acSMatthew G. Knepley 572574a98acSMatthew G. Knepley PetscFunctionBegin; 573574a98acSMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 5745d42b983SMatthew G. Knepley ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, localX, time, NULL, NULL, NULL);CHKERRQ(ierr); 575574a98acSMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 576574a98acSMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 577574a98acSMatthew G. Knepley ierr = DMPlexComputeL2DiffLocal(dm, time, funcs, ctxs, localX, diff);CHKERRQ(ierr); 578574a98acSMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 579574a98acSMatthew G. Knepley PetscFunctionReturn(0); 580574a98acSMatthew G. Knepley } 581574a98acSMatthew G. Knepley 582574a98acSMatthew G. Knepley /*@C 583574a98acSMatthew G. Knepley DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 584574a98acSMatthew G. Knepley 585574a98acSMatthew G. Knepley Input Parameters: 586574a98acSMatthew G. Knepley + dm - The DM 587574a98acSMatthew G. Knepley . time - The time 588574a98acSMatthew G. Knepley . funcs - The functions to evaluate for each field component 589574a98acSMatthew G. Knepley . ctxs - Optional array of contexts to pass to each function, or NULL. 590574a98acSMatthew G. Knepley - localX - The coefficient vector u_h, a local vector 591574a98acSMatthew G. Knepley 592574a98acSMatthew G. Knepley Output Parameter: 593574a98acSMatthew G. Knepley . diff - The diff ||u - u_h||_2 594574a98acSMatthew G. Knepley 595574a98acSMatthew G. Knepley Level: developer 596574a98acSMatthew G. Knepley 597574a98acSMatthew G. Knepley .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 598574a98acSMatthew G. Knepley @*/ 599574a98acSMatthew G. Knepley PetscErrorCode DMPlexComputeL2DiffLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec localX, PetscReal *diff) 600574a98acSMatthew G. Knepley { 6010f09c10fSMatthew G. Knepley const PetscInt debug = ((DM_Plex*)dm->data)->printL2; 602cb1e1211SMatthew G Knepley PetscSection section; 603c5bbbd5bSMatthew G. Knepley PetscQuadrature quad; 60415496722SMatthew G. Knepley PetscScalar *funcVal, *interpolant; 6057318780aSToby Isaac PetscReal *coords, *detJ, *J; 606cb1e1211SMatthew G Knepley PetscReal localDiff = 0.0; 6077318780aSToby Isaac const PetscReal *quadWeights; 608aed3cbd0SMatthew G. Knepley PetscInt dim, coordDim, numFields, numComponents = 0, qNc, Nq, cellHeight, cStart, cEnd, cEndInterior, c, field, fieldOffset; 609cb1e1211SMatthew G Knepley PetscErrorCode ierr; 610cb1e1211SMatthew G Knepley 611cb1e1211SMatthew G Knepley PetscFunctionBegin; 612c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6137318780aSToby Isaac ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 614cb1e1211SMatthew G Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 615cb1e1211SMatthew G Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 616cb1e1211SMatthew G Knepley for (field = 0; field < numFields; ++field) { 61715496722SMatthew G. Knepley PetscObject obj; 61815496722SMatthew G. Knepley PetscClassId id; 619c5bbbd5bSMatthew G. Knepley PetscInt Nc; 620c5bbbd5bSMatthew G. Knepley 62115496722SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 62215496722SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 62315496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 62415496722SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 62515496722SMatthew G. Knepley 6260f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 6270f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 62815496722SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 62915496722SMatthew G. Knepley PetscFV fv = (PetscFV) obj; 63015496722SMatthew G. Knepley 63115496722SMatthew G. Knepley ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 63215496722SMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 63315496722SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 634c5bbbd5bSMatthew G. Knepley numComponents += Nc; 635cb1e1211SMatthew G Knepley } 6369c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, NULL, &quadWeights);CHKERRQ(ierr); 637beaa55a6SMatthew G. Knepley if ((qNc != 1) && (qNc != numComponents)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_SIZ, "Quadrature components %D != %D field components", qNc, numComponents); 6387318780aSToby Isaac ierr = PetscMalloc5(numComponents,&funcVal,numComponents,&interpolant,coordDim*Nq,&coords,Nq,&detJ,coordDim*coordDim*Nq,&J);CHKERRQ(ierr); 639aed3cbd0SMatthew G. Knepley ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 640aed3cbd0SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 6419ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 6429ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 643cb1e1211SMatthew G Knepley for (c = cStart; c < cEnd; ++c) { 644a1e44745SMatthew G. Knepley PetscScalar *x = NULL; 645cb1e1211SMatthew G Knepley PetscReal elemDiff = 0.0; 6469c3cf19fSMatthew G. Knepley PetscInt qc = 0; 647cb1e1211SMatthew G Knepley 6487318780aSToby Isaac ierr = DMPlexComputeCellGeometryFEM(dm, c, quad, coords, J, NULL, detJ);CHKERRQ(ierr); 649cb1e1211SMatthew G Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 650cb1e1211SMatthew G Knepley 65115496722SMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) { 65215496722SMatthew G. Knepley PetscObject obj; 65315496722SMatthew G. Knepley PetscClassId id; 654c110b1eeSGeoffrey Irving void * const ctx = ctxs ? ctxs[field] : NULL; 65515496722SMatthew G. Knepley PetscInt Nb, Nc, q, fc; 656cb1e1211SMatthew G Knepley 65715496722SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 65815496722SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 65915496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 66015496722SMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 66115496722SMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 662cb1e1211SMatthew G Knepley if (debug) { 663cb1e1211SMatthew G Knepley char title[1024]; 664cb1e1211SMatthew G Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 6654c848028SMatthew G. Knepley ierr = DMPrintCellVector(c, title, Nb, &x[fieldOffset]);CHKERRQ(ierr); 666cb1e1211SMatthew G Knepley } 6677318780aSToby Isaac for (q = 0; q < Nq; ++q) { 6687318780aSToby 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); 6697318780aSToby Isaac ierr = (*funcs[field])(coordDim, time, &coords[coordDim * q], Nc, funcVal, ctx); 670e735a8a9SMatthew G. Knepley if (ierr) { 671e735a8a9SMatthew G. Knepley PetscErrorCode ierr2; 672e735a8a9SMatthew G. Knepley ierr2 = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr2); 673e735a8a9SMatthew G. Knepley ierr2 = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr2); 6747318780aSToby Isaac ierr2 = PetscFree5(funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr2); 675e735a8a9SMatthew G. Knepley CHKERRQ(ierr); 676e735a8a9SMatthew G. Knepley } 67715496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 67815496722SMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 67915496722SMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 68015496722SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 681beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q*qNc+(qNc == 1 ? 0 : qc+fc)]; 682beaa55a6SMatthew 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);} 683beaa55a6SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]; 684cb1e1211SMatthew G Knepley } 685cb1e1211SMatthew G Knepley } 6869c3cf19fSMatthew G. Knepley fieldOffset += Nb; 687beaa55a6SMatthew G. Knepley qc += Nc; 688cb1e1211SMatthew G Knepley } 689cb1e1211SMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 690cb1e1211SMatthew G Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 691cb1e1211SMatthew G Knepley localDiff += elemDiff; 692cb1e1211SMatthew G Knepley } 6937318780aSToby Isaac ierr = PetscFree5(funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr); 694b2566f29SBarry Smith ierr = MPIU_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 695cb1e1211SMatthew G Knepley *diff = PetscSqrtReal(*diff); 696cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 697cb1e1211SMatthew G Knepley } 698cb1e1211SMatthew G Knepley 699b698f381SToby 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) 700cb1e1211SMatthew G Knepley { 7010f09c10fSMatthew G. Knepley const PetscInt debug = ((DM_Plex*)dm->data)->printL2; 702cb1e1211SMatthew G Knepley PetscSection section; 70340e14135SMatthew G. Knepley PetscQuadrature quad; 70440e14135SMatthew G. Knepley Vec localX; 7059c3cf19fSMatthew G. Knepley PetscScalar *funcVal, *interpolant; 7069c3cf19fSMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 7077318780aSToby Isaac PetscReal *coords, *realSpaceDer, *J, *invJ, *detJ; 70840e14135SMatthew G. Knepley PetscReal localDiff = 0.0; 7099c3cf19fSMatthew G. Knepley PetscInt dim, coordDim, qNc = 0, Nq = 0, numFields, numComponents = 0, cStart, cEnd, cEndInterior, c, field, fieldOffset; 710cb1e1211SMatthew G Knepley PetscErrorCode ierr; 711cb1e1211SMatthew G Knepley 712cb1e1211SMatthew G Knepley PetscFunctionBegin; 713c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 7147318780aSToby Isaac ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 71540e14135SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 71640e14135SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 71740e14135SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 71840e14135SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 71940e14135SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 720652b88e8SMatthew G. Knepley for (field = 0; field < numFields; ++field) { 7210f2d7e86SMatthew G. Knepley PetscFE fe; 72240e14135SMatthew G. Knepley PetscInt Nc; 723652b88e8SMatthew G. Knepley 7240f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 7250f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 7260f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 72740e14135SMatthew G. Knepley numComponents += Nc; 728652b88e8SMatthew G. Knepley } 7299c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr); 730beaa55a6SMatthew G. Knepley if ((qNc != 1) && (qNc != numComponents)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_SIZ, "Quadrature components %D != %D field components", qNc, numComponents); 7314d6f44ffSToby Isaac /* ierr = DMProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); */ 7329c3cf19fSMatthew 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); 73340e14135SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7349ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 7359ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 73640e14135SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 73740e14135SMatthew G. Knepley PetscScalar *x = NULL; 73840e14135SMatthew G. Knepley PetscReal elemDiff = 0.0; 7399c3cf19fSMatthew G. Knepley PetscInt qc = 0; 740652b88e8SMatthew G. Knepley 7417318780aSToby Isaac ierr = DMPlexComputeCellGeometryFEM(dm, c, quad, coords, J, invJ, detJ);CHKERRQ(ierr); 74240e14135SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 74340e14135SMatthew G. Knepley 7449c3cf19fSMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) { 7450f2d7e86SMatthew G. Knepley PetscFE fe; 74651259fa3SMatthew G. Knepley void * const ctx = ctxs ? ctxs[field] : NULL; 74740e14135SMatthew G. Knepley PetscReal *basisDer; 7489c3cf19fSMatthew G. Knepley PetscInt Nb, Nc, q, fc; 74940e14135SMatthew G. Knepley 7500f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 7510f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 7529c3cf19fSMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 7530f2d7e86SMatthew G. Knepley ierr = PetscFEGetDefaultTabulation(fe, NULL, &basisDer, NULL);CHKERRQ(ierr); 75440e14135SMatthew G. Knepley if (debug) { 75540e14135SMatthew G. Knepley char title[1024]; 75640e14135SMatthew G. Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 7579c3cf19fSMatthew G. Knepley ierr = DMPrintCellVector(c, title, Nb, &x[fieldOffset]);CHKERRQ(ierr); 758652b88e8SMatthew G. Knepley } 7599c3cf19fSMatthew G. Knepley for (q = 0; q < Nq; ++q) { 7607318780aSToby 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); 7617318780aSToby Isaac ierr = (*funcs[field])(coordDim, time, &coords[q*coordDim], n, numFields, funcVal, ctx); 762e735a8a9SMatthew G. Knepley if (ierr) { 763e735a8a9SMatthew G. Knepley PetscErrorCode ierr2; 764e735a8a9SMatthew G. Knepley ierr2 = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr2); 765e735a8a9SMatthew G. Knepley ierr2 = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr2); 7669c3cf19fSMatthew G. Knepley ierr2 = PetscFree7(funcVal,coords,realSpaceDer,J,invJ,interpolant,detJ);CHKERRQ(ierr2); 767e735a8a9SMatthew G. Knepley CHKERRQ(ierr); 768e735a8a9SMatthew G. Knepley } 7699c3cf19fSMatthew G. Knepley ierr = PetscFEInterpolateGradient_Static(fe, &x[fieldOffset], coordDim, invJ, n, q, interpolant);CHKERRQ(ierr); 7709c3cf19fSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 771beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q*qNc+(qNc == 1 ? 0 : qc+fc)]; 772beaa55a6SMatthew 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);} 773beaa55a6SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]; 77440e14135SMatthew G. Knepley } 77540e14135SMatthew G. Knepley } 7769c3cf19fSMatthew G. Knepley fieldOffset += Nb; 7779c3cf19fSMatthew G. Knepley qc += Nc; 77840e14135SMatthew G. Knepley } 77940e14135SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 78040e14135SMatthew G. Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 78140e14135SMatthew G. Knepley localDiff += elemDiff; 78240e14135SMatthew G. Knepley } 7839c3cf19fSMatthew G. Knepley ierr = PetscFree7(funcVal,coords,realSpaceDer,J,invJ,interpolant,detJ);CHKERRQ(ierr); 78440e14135SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 785b2566f29SBarry Smith ierr = MPIU_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 78640e14135SMatthew G. Knepley *diff = PetscSqrtReal(*diff); 787cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 788cb1e1211SMatthew G Knepley } 789cb1e1211SMatthew G Knepley 790c6eecec3SToby Isaac PetscErrorCode DMComputeL2FieldDiff_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 79173d901b8SMatthew G. Knepley { 7920f09c10fSMatthew G. Knepley const PetscInt debug = ((DM_Plex*)dm->data)->printL2; 79373d901b8SMatthew G. Knepley PetscSection section; 79473d901b8SMatthew G. Knepley PetscQuadrature quad; 79573d901b8SMatthew G. Knepley Vec localX; 79615496722SMatthew G. Knepley PetscScalar *funcVal, *interpolant; 7977318780aSToby Isaac PetscReal *coords, *detJ, *J; 79873d901b8SMatthew G. Knepley PetscReal *localDiff; 79915496722SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 8009c3cf19fSMatthew G. Knepley PetscInt dim, coordDim, numFields, numComponents = 0, qNc, Nq, cStart, cEnd, cEndInterior, c, field, fieldOffset; 80173d901b8SMatthew G. Knepley PetscErrorCode ierr; 80273d901b8SMatthew G. Knepley 80373d901b8SMatthew G. Knepley PetscFunctionBegin; 804c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 8057318780aSToby Isaac ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 80673d901b8SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 80773d901b8SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 80873d901b8SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 809bdd6f66aSToby Isaac ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 81073d901b8SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 81173d901b8SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 81273d901b8SMatthew G. Knepley for (field = 0; field < numFields; ++field) { 81315496722SMatthew G. Knepley PetscObject obj; 81415496722SMatthew G. Knepley PetscClassId id; 81573d901b8SMatthew G. Knepley PetscInt Nc; 81673d901b8SMatthew G. Knepley 81715496722SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 81815496722SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 81915496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 82015496722SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 82115496722SMatthew G. Knepley 8220f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 8230f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 82415496722SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 82515496722SMatthew G. Knepley PetscFV fv = (PetscFV) obj; 82615496722SMatthew G. Knepley 82715496722SMatthew G. Knepley ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 82815496722SMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 82915496722SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 83073d901b8SMatthew G. Knepley numComponents += Nc; 83173d901b8SMatthew G. Knepley } 8329c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr); 833beaa55a6SMatthew G. Knepley if ((qNc != 1) && (qNc != numComponents)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_SIZ, "Quadrature components %D != %D field components", qNc, numComponents); 8347318780aSToby Isaac ierr = PetscCalloc6(numFields,&localDiff,numComponents,&funcVal,numComponents,&interpolant,coordDim*Nq,&coords,Nq,&detJ,coordDim*coordDim*Nq,&J);CHKERRQ(ierr); 83573d901b8SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8369ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 8379ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 83873d901b8SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 83973d901b8SMatthew G. Knepley PetscScalar *x = NULL; 8409c3cf19fSMatthew G. Knepley PetscInt qc = 0; 84173d901b8SMatthew G. Knepley 8427318780aSToby Isaac ierr = DMPlexComputeCellGeometryFEM(dm, c, quad, coords, J, NULL, detJ);CHKERRQ(ierr); 84373d901b8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 84473d901b8SMatthew G. Knepley 84515496722SMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) { 84615496722SMatthew G. Knepley PetscObject obj; 84715496722SMatthew G. Knepley PetscClassId id; 84873d901b8SMatthew G. Knepley void * const ctx = ctxs ? ctxs[field] : NULL; 84915496722SMatthew G. Knepley PetscInt Nb, Nc, q, fc; 85073d901b8SMatthew G. Knepley 85115496722SMatthew G. Knepley PetscReal elemDiff = 0.0; 85215496722SMatthew G. Knepley 85315496722SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 85415496722SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 85515496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 85615496722SMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 85715496722SMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 85873d901b8SMatthew G. Knepley if (debug) { 85973d901b8SMatthew G. Knepley char title[1024]; 86073d901b8SMatthew G. Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 86115496722SMatthew G. Knepley ierr = DMPrintCellVector(c, title, Nb*Nc, &x[fieldOffset]);CHKERRQ(ierr); 86273d901b8SMatthew G. Knepley } 8637318780aSToby Isaac for (q = 0; q < Nq; ++q) { 8647318780aSToby 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); 8657318780aSToby Isaac ierr = (*funcs[field])(coordDim, time, &coords[coordDim*q], numFields, funcVal, ctx); 866e735a8a9SMatthew G. Knepley if (ierr) { 867e735a8a9SMatthew G. Knepley PetscErrorCode ierr2; 868e735a8a9SMatthew G. Knepley ierr2 = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr2); 869e735a8a9SMatthew G. Knepley ierr2 = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr2); 8707318780aSToby Isaac ierr2 = PetscFree6(localDiff,funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr2); 871e735a8a9SMatthew G. Knepley CHKERRQ(ierr); 872e735a8a9SMatthew G. Knepley } 87315496722SMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 87415496722SMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 87515496722SMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 87615496722SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 877beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q*qNc+(qNc == 1 ? 0 : qc+fc)]; 878beaa55a6SMatthew 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);} 879beaa55a6SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]; 88073d901b8SMatthew G. Knepley } 88173d901b8SMatthew G. Knepley } 882beaa55a6SMatthew G. Knepley fieldOffset += Nb; 8839c3cf19fSMatthew G. Knepley qc += Nc; 88473d901b8SMatthew G. Knepley localDiff[field] += elemDiff; 88573d901b8SMatthew G. Knepley } 88673d901b8SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 88773d901b8SMatthew G. Knepley } 88873d901b8SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 889b2566f29SBarry Smith ierr = MPIU_Allreduce(localDiff, diff, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 89073d901b8SMatthew G. Knepley for (field = 0; field < numFields; ++field) diff[field] = PetscSqrtReal(diff[field]); 8917318780aSToby Isaac ierr = PetscFree6(localDiff,funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr); 89273d901b8SMatthew G. Knepley PetscFunctionReturn(0); 89373d901b8SMatthew G. Knepley } 89473d901b8SMatthew G. Knepley 895e729f68cSMatthew G. Knepley /*@C 896e729f68cSMatthew 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. 897e729f68cSMatthew G. Knepley 898e729f68cSMatthew G. Knepley Input Parameters: 899e729f68cSMatthew G. Knepley + dm - The DM 9000163fd50SMatthew G. Knepley . time - The time 901ca3eba1bSToby Isaac . funcs - The functions to evaluate for each field component: NULL means that component does not contribute to error calculation 902e729f68cSMatthew G. Knepley . ctxs - Optional array of contexts to pass to each function, or NULL. 903e729f68cSMatthew G. Knepley - X - The coefficient vector u_h 904e729f68cSMatthew G. Knepley 905e729f68cSMatthew G. Knepley Output Parameter: 906e729f68cSMatthew G. Knepley . D - A Vec which holds the difference ||u - u_h||_2 for each cell 907e729f68cSMatthew G. Knepley 908e729f68cSMatthew G. Knepley Level: developer 909e729f68cSMatthew G. Knepley 910b698f381SToby Isaac .seealso: DMProjectFunction(), DMComputeL2Diff(), DMPlexComputeL2FieldDiff(), DMComputeL2GradientDiff() 911e729f68cSMatthew G. Knepley @*/ 9120163fd50SMatthew G. Knepley PetscErrorCode DMPlexComputeL2DiffVec(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, Vec D) 913e729f68cSMatthew G. Knepley { 914e729f68cSMatthew G. Knepley PetscSection section; 915e729f68cSMatthew G. Knepley PetscQuadrature quad; 916e729f68cSMatthew G. Knepley Vec localX; 917e729f68cSMatthew G. Knepley PetscScalar *funcVal, *interpolant; 9187318780aSToby Isaac PetscReal *coords, *detJ, *J; 919e729f68cSMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 9209c3cf19fSMatthew G. Knepley PetscInt dim, coordDim, numFields, numComponents = 0, qNc, Nq, cStart, cEnd, cEndInterior, c, field, fieldOffset; 921e729f68cSMatthew G. Knepley PetscErrorCode ierr; 922e729f68cSMatthew G. Knepley 923e729f68cSMatthew G. Knepley PetscFunctionBegin; 924e729f68cSMatthew G. Knepley ierr = VecSet(D, 0.0);CHKERRQ(ierr); 925e729f68cSMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 9267318780aSToby Isaac ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 927e729f68cSMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 928e729f68cSMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 929e729f68cSMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 930bdd6f66aSToby Isaac ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 931e729f68cSMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 932e729f68cSMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 933e729f68cSMatthew G. Knepley for (field = 0; field < numFields; ++field) { 934e729f68cSMatthew G. Knepley PetscObject obj; 935e729f68cSMatthew G. Knepley PetscClassId id; 936e729f68cSMatthew G. Knepley PetscInt Nc; 937e729f68cSMatthew G. Knepley 938e729f68cSMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 939e729f68cSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 940e729f68cSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 941e729f68cSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 942e729f68cSMatthew G. Knepley 943e729f68cSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 944e729f68cSMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 945e729f68cSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 946e729f68cSMatthew G. Knepley PetscFV fv = (PetscFV) obj; 947e729f68cSMatthew G. Knepley 948e729f68cSMatthew G. Knepley ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 949e729f68cSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 950e729f68cSMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 951e729f68cSMatthew G. Knepley numComponents += Nc; 952e729f68cSMatthew G. Knepley } 9539c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr); 954beaa55a6SMatthew G. Knepley if ((qNc != 1) && (qNc != numComponents)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_SIZ, "Quadrature components %D != %D field components", qNc, numComponents); 9557318780aSToby Isaac ierr = PetscMalloc5(numComponents,&funcVal,numComponents,&interpolant,coordDim*Nq,&coords,Nq,&detJ,coordDim*coordDim*Nq,&J);CHKERRQ(ierr); 956e729f68cSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 957e729f68cSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 958e729f68cSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 959e729f68cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 960e729f68cSMatthew G. Knepley PetscScalar *x = NULL; 9616f288a59SMatthew G. Knepley PetscScalar elemDiff = 0.0; 9629c3cf19fSMatthew G. Knepley PetscInt qc = 0; 963e729f68cSMatthew G. Knepley 9647318780aSToby Isaac ierr = DMPlexComputeCellGeometryFEM(dm, c, quad, coords, J, NULL, detJ);CHKERRQ(ierr); 965e729f68cSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 966e729f68cSMatthew G. Knepley 967e729f68cSMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) { 968e729f68cSMatthew G. Knepley PetscObject obj; 969e729f68cSMatthew G. Knepley PetscClassId id; 970e729f68cSMatthew G. Knepley void * const ctx = ctxs ? ctxs[field] : NULL; 971e729f68cSMatthew G. Knepley PetscInt Nb, Nc, q, fc; 972e729f68cSMatthew G. Knepley 973e729f68cSMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 974e729f68cSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 975e729f68cSMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 976e729f68cSMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 977e729f68cSMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 97823f34ed2SToby Isaac if (funcs[field]) { 9797318780aSToby Isaac for (q = 0; q < Nq; ++q) { 9807f79407eSBarry Smith if (detJ[q] <= 0.0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D, quadrature points %D", (double)detJ[q], c, q); 981274e8aaeSMatthew G. Knepley ierr = (*funcs[field])(coordDim, time, &coords[q*coordDim], Nc, funcVal, ctx); 982e735a8a9SMatthew G. Knepley if (ierr) { 983e735a8a9SMatthew G. Knepley PetscErrorCode ierr2; 984e735a8a9SMatthew G. Knepley ierr2 = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr2); 9857f79407eSBarry Smith ierr2 = PetscFree5(funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr2); 986e735a8a9SMatthew G. Knepley ierr2 = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr2); 987e735a8a9SMatthew G. Knepley CHKERRQ(ierr); 988e735a8a9SMatthew G. Knepley } 989e729f68cSMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 990e729f68cSMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 991e729f68cSMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 992e729f68cSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 993beaa55a6SMatthew G. Knepley const PetscReal wt = quadWeights[q*qNc+(qNc == 1 ? 0 : qc+fc)]; 994beaa55a6SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*wt*detJ[q]; 995e729f68cSMatthew G. Knepley } 996e729f68cSMatthew G. Knepley } 99723f34ed2SToby Isaac } 998beaa55a6SMatthew G. Knepley fieldOffset += Nb; 9999c3cf19fSMatthew G. Knepley qc += Nc; 1000e729f68cSMatthew G. Knepley } 1001e729f68cSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 100223f34ed2SToby Isaac ierr = VecSetValue(D, c - cStart, elemDiff, INSERT_VALUES);CHKERRQ(ierr); 1003e729f68cSMatthew G. Knepley } 10047318780aSToby Isaac ierr = PetscFree5(funcVal,interpolant,coords,detJ,J);CHKERRQ(ierr); 1005e729f68cSMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 1006e729f68cSMatthew G. Knepley ierr = VecSqrtAbs(D);CHKERRQ(ierr); 1007e729f68cSMatthew G. Knepley PetscFunctionReturn(0); 1008e729f68cSMatthew G. Knepley } 1009e729f68cSMatthew G. Knepley 10101555c271SMatthew G. Knepley /*@C 10111555c271SMatthew G. Knepley DMPlexComputeGradientClementInterpolant - This function computes the L2 projection of the cellwise gradient of a function u onto P1, and stores it in a Vec. 10121555c271SMatthew G. Knepley 10131555c271SMatthew G. Knepley Input Parameters: 10141555c271SMatthew G. Knepley + dm - The DM 10151555c271SMatthew G. Knepley - LocX - The coefficient vector u_h 10161555c271SMatthew G. Knepley 10171555c271SMatthew G. Knepley Output Parameter: 10181555c271SMatthew G. Knepley . locC - A Vec which holds the Clement interpolant of the gradient 10191555c271SMatthew G. Knepley 102095452b02SPatrick Sanan Notes: 102195452b02SPatrick Sanan Add citation to (Clement, 1975) and definition of the interpolant 10221555c271SMatthew G. Knepley \nabla u_h(v_i) = \sum_{T_i \in support(v_i)} |T_i| \nabla u_h(T_i) / \sum_{T_i \in support(v_i)} |T_i| where |T_i| is the cell volume 10231555c271SMatthew G. Knepley 10241555c271SMatthew G. Knepley Level: developer 10251555c271SMatthew G. Knepley 10261555c271SMatthew G. Knepley .seealso: DMProjectFunction(), DMComputeL2Diff(), DMPlexComputeL2FieldDiff(), DMComputeL2GradientDiff() 10271555c271SMatthew G. Knepley @*/ 10281555c271SMatthew G. Knepley PetscErrorCode DMPlexComputeGradientClementInterpolant(DM dm, Vec locX, Vec locC) 10291555c271SMatthew G. Knepley { 1030db1066baSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1031db1066baSMatthew G. Knepley PetscInt debug = mesh->printFEM; 10321555c271SMatthew G. Knepley DM dmC; 10331555c271SMatthew G. Knepley PetscSection section; 10341555c271SMatthew G. Knepley PetscQuadrature quad; 10351555c271SMatthew G. Knepley PetscScalar *interpolant, *gradsum; 10361555c271SMatthew G. Knepley PetscReal *coords, *detJ, *J, *invJ; 10371555c271SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 10381555c271SMatthew G. Knepley PetscInt dim, coordDim, numFields, numComponents = 0, qNc, Nq, cStart, cEnd, cEndInterior, vStart, vEnd, v, field, fieldOffset; 10391555c271SMatthew G. Knepley PetscErrorCode ierr; 10401555c271SMatthew G. Knepley 10411555c271SMatthew G. Knepley PetscFunctionBegin; 10421555c271SMatthew G. Knepley ierr = VecGetDM(locC, &dmC);CHKERRQ(ierr); 10431555c271SMatthew G. Knepley ierr = VecSet(locC, 0.0);CHKERRQ(ierr); 10441555c271SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 10451555c271SMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &coordDim);CHKERRQ(ierr); 10461555c271SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10471555c271SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 10481555c271SMatthew G. Knepley for (field = 0; field < numFields; ++field) { 10491555c271SMatthew G. Knepley PetscObject obj; 10501555c271SMatthew G. Knepley PetscClassId id; 10511555c271SMatthew G. Knepley PetscInt Nc; 10521555c271SMatthew G. Knepley 10531555c271SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 10541555c271SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 10551555c271SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 10561555c271SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 10571555c271SMatthew G. Knepley 10581555c271SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 10591555c271SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 10601555c271SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 10611555c271SMatthew G. Knepley PetscFV fv = (PetscFV) obj; 10621555c271SMatthew G. Knepley 10631555c271SMatthew G. Knepley ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 10641555c271SMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 10651555c271SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 10661555c271SMatthew G. Knepley numComponents += Nc; 10671555c271SMatthew G. Knepley } 10681555c271SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &qNc, &Nq, &quadPoints, &quadWeights);CHKERRQ(ierr); 10691555c271SMatthew G. Knepley if ((qNc != 1) && (qNc != numComponents)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_SIZ, "Quadrature components %D != %D field components", qNc, numComponents); 10701555c271SMatthew G. Knepley ierr = PetscMalloc6(coordDim*numComponents*2,&gradsum,coordDim*numComponents,&interpolant,coordDim*Nq,&coords,Nq,&detJ,coordDim*coordDim*Nq,&J,coordDim*coordDim*Nq,&invJ);CHKERRQ(ierr); 10711555c271SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 10721555c271SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10731555c271SMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 10741555c271SMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 10751555c271SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 10761555c271SMatthew G. Knepley PetscScalar volsum = 0.0; 10771555c271SMatthew G. Knepley PetscInt *star = NULL; 10781555c271SMatthew G. Knepley PetscInt starSize, st, d, fc; 10791555c271SMatthew G. Knepley 10801555c271SMatthew G. Knepley ierr = PetscMemzero(gradsum, coordDim*numComponents * sizeof(PetscScalar));CHKERRQ(ierr); 10811555c271SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 10821555c271SMatthew G. Knepley for (st = 0; st < starSize*2; st += 2) { 10831555c271SMatthew G. Knepley const PetscInt cell = star[st]; 10841555c271SMatthew G. Knepley PetscScalar *grad = &gradsum[coordDim*numComponents]; 10851555c271SMatthew G. Knepley PetscScalar *x = NULL; 10861555c271SMatthew G. Knepley PetscReal vol = 0.0; 10871555c271SMatthew G. Knepley 10881555c271SMatthew G. Knepley if ((cell < cStart) || (cell >= cEnd)) continue; 10891555c271SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, cell, quad, coords, J, invJ, detJ);CHKERRQ(ierr); 10901555c271SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, locX, cell, NULL, &x);CHKERRQ(ierr); 10911555c271SMatthew G. Knepley for (field = 0, fieldOffset = 0; field < numFields; ++field) { 10921555c271SMatthew G. Knepley PetscObject obj; 10931555c271SMatthew G. Knepley PetscClassId id; 10941555c271SMatthew G. Knepley PetscInt Nb, Nc, q, qc = 0; 10951555c271SMatthew G. Knepley 10961555c271SMatthew G. Knepley ierr = PetscMemzero(grad, coordDim*numComponents * sizeof(PetscScalar));CHKERRQ(ierr); 10971555c271SMatthew G. Knepley ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 10981555c271SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 10991555c271SMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 11001555c271SMatthew G. Knepley else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 11011555c271SMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 11021555c271SMatthew G. Knepley for (q = 0; q < Nq; ++q) { 11031555c271SMatthew G. Knepley if (detJ[q] <= 0.0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D, quadrature points %D", (double)detJ[q], cell, q); 11041555c271SMatthew G. Knepley if (ierr) { 11051555c271SMatthew G. Knepley PetscErrorCode ierr2; 11061555c271SMatthew G. Knepley ierr2 = DMPlexVecRestoreClosure(dm, NULL, locX, cell, NULL, &x);CHKERRQ(ierr2); 11071555c271SMatthew G. Knepley ierr2 = DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr2); 11081555c271SMatthew G. Knepley ierr2 = PetscFree4(interpolant,coords,detJ,J);CHKERRQ(ierr2); 11091555c271SMatthew G. Knepley CHKERRQ(ierr); 11101555c271SMatthew G. Knepley } 11111555c271SMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolateGradient_Static((PetscFE) obj, &x[fieldOffset], coordDim, invJ, NULL, q, interpolant);CHKERRQ(ierr);} 11121555c271SMatthew G. Knepley else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 11131555c271SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 11141555c271SMatthew G. Knepley const PetscReal wt = quadWeights[q*qNc+qc+fc]; 11151555c271SMatthew G. Knepley 11161555c271SMatthew G. Knepley for (d = 0; d < coordDim; ++d) grad[fc*coordDim+d] += interpolant[fc*dim+d]*wt*detJ[q]; 11171555c271SMatthew G. Knepley } 11181555c271SMatthew G. Knepley vol += quadWeights[q*qNc]*detJ[q]; 11191555c271SMatthew G. Knepley } 11201555c271SMatthew G. Knepley fieldOffset += Nb; 11211555c271SMatthew G. Knepley qc += Nc; 11221555c271SMatthew G. Knepley } 11231555c271SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, locX, cell, NULL, &x);CHKERRQ(ierr); 1124f8527842SMatthew G. Knepley for (fc = 0; fc < numComponents; ++fc) { 1125f8527842SMatthew G. Knepley for (d = 0; d < coordDim; ++d) { 1126f8527842SMatthew G. Knepley gradsum[fc*coordDim+d] += grad[fc*coordDim+d]; 1127f8527842SMatthew G. Knepley } 1128f8527842SMatthew G. Knepley } 1129f8527842SMatthew G. Knepley volsum += vol; 1130db1066baSMatthew G. Knepley if (debug) { 11316d20ae03SJed Brown ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D gradient: [", cell);CHKERRQ(ierr); 11321555c271SMatthew G. Knepley for (fc = 0; fc < numComponents; ++fc) { 11331555c271SMatthew G. Knepley for (d = 0; d < coordDim; ++d) { 11341555c271SMatthew G. Knepley if (fc || d > 0) {ierr = PetscPrintf(PETSC_COMM_SELF, ", ");CHKERRQ(ierr);} 11356d20ae03SJed Brown ierr = PetscPrintf(PETSC_COMM_SELF, "%g", (double)PetscRealPart(grad[fc*coordDim+d]));CHKERRQ(ierr); 11361555c271SMatthew G. Knepley } 11371555c271SMatthew G. Knepley } 11381555c271SMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_SELF, "]\n");CHKERRQ(ierr); 1139db1066baSMatthew G. Knepley } 11401555c271SMatthew G. Knepley } 11411555c271SMatthew G. Knepley for (fc = 0; fc < numComponents; ++fc) { 11421555c271SMatthew G. Knepley for (d = 0; d < coordDim; ++d) gradsum[fc*coordDim+d] /= volsum; 11431555c271SMatthew G. Knepley } 11441555c271SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 11451555c271SMatthew G. Knepley ierr = DMPlexVecSetClosure(dmC, NULL, locC, v, gradsum, INSERT_VALUES);CHKERRQ(ierr); 11461555c271SMatthew G. Knepley } 11471555c271SMatthew G. Knepley ierr = PetscFree6(gradsum,interpolant,coords,detJ,J,invJ);CHKERRQ(ierr); 11481555c271SMatthew G. Knepley PetscFunctionReturn(0); 11491555c271SMatthew G. Knepley } 11501555c271SMatthew G. Knepley 1151338f77d5SMatthew G. Knepley static PetscErrorCode DMPlexComputeIntegral_Internal(DM dm, Vec X, PetscInt cStart, PetscInt cEnd, PetscScalar *cintegral, void *user) 115273d901b8SMatthew G. Knepley { 1153338f77d5SMatthew G. Knepley DM dmAux = NULL; 11549bb067fcSMatthew G. Knepley PetscDS prob, probAux = NULL; 115573d901b8SMatthew G. Knepley PetscSection section, sectionAux; 1156338f77d5SMatthew G. Knepley Vec locX, locA; 1157c330f8ffSToby Isaac PetscInt dim, numCells = cEnd - cStart, c, f; 1158c330f8ffSToby Isaac PetscBool useFVM = PETSC_FALSE; 1159338f77d5SMatthew G. Knepley /* DS */ 1160338f77d5SMatthew G. Knepley PetscInt Nf, totDim, *uOff, *uOff_x, numConstants; 1161338f77d5SMatthew G. Knepley PetscInt NfAux, totDimAux, *aOff; 1162338f77d5SMatthew G. Knepley PetscScalar *u, *a; 1163338f77d5SMatthew G. Knepley const PetscScalar *constants; 1164338f77d5SMatthew G. Knepley /* Geometry */ 1165c330f8ffSToby Isaac PetscFEGeom *cgeomFEM; 1166338f77d5SMatthew G. Knepley DM dmGrad; 1167c330f8ffSToby Isaac PetscQuadrature affineQuad = NULL; 1168338f77d5SMatthew G. Knepley Vec cellGeometryFVM = NULL, faceGeometryFVM = NULL, locGrad = NULL; 1169b5a3613cSMatthew G. Knepley PetscFVCellGeom *cgeomFVM; 1170338f77d5SMatthew G. Knepley const PetscScalar *lgrad; 1171c330f8ffSToby Isaac PetscBool isAffine; 1172c330f8ffSToby Isaac DMField coordField; 1173c330f8ffSToby Isaac IS cellIS; 117473d901b8SMatthew G. Knepley PetscErrorCode ierr; 117573d901b8SMatthew G. Knepley 117673d901b8SMatthew G. Knepley PetscFunctionBegin; 1177338f77d5SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 1178c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 117973d901b8SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 118073d901b8SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 1181338f77d5SMatthew G. Knepley /* Determine which discretizations we have */ 1182b5a3613cSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1183b5a3613cSMatthew G. Knepley PetscObject obj; 1184b5a3613cSMatthew G. Knepley PetscClassId id; 1185b5a3613cSMatthew G. Knepley 1186b5a3613cSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1187b5a3613cSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1188338f77d5SMatthew G. Knepley if (id == PETSCFV_CLASSID) useFVM = PETSC_TRUE; 1189338f77d5SMatthew G. Knepley } 1190338f77d5SMatthew G. Knepley /* Get local solution with boundary values */ 1191338f77d5SMatthew G. Knepley ierr = DMGetLocalVector(dm, &locX);CHKERRQ(ierr); 1192338f77d5SMatthew G. Knepley ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locX, 0.0, NULL, NULL, NULL);CHKERRQ(ierr); 1193338f77d5SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, locX);CHKERRQ(ierr); 1194338f77d5SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, locX);CHKERRQ(ierr); 1195338f77d5SMatthew G. Knepley /* Read DS information */ 1196338f77d5SMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 1197338f77d5SMatthew G. Knepley ierr = PetscDSGetComponentOffsets(prob, &uOff);CHKERRQ(ierr); 1198338f77d5SMatthew G. Knepley ierr = PetscDSGetComponentDerivativeOffsets(prob, &uOff_x);CHKERRQ(ierr); 1199c330f8ffSToby Isaac ierr = ISCreateStride(PETSC_COMM_SELF,numCells,cStart,1,&cellIS);CHKERRQ(ierr); 1200338f77d5SMatthew G. Knepley ierr = PetscDSGetConstants(prob, &numConstants, &constants);CHKERRQ(ierr); 1201338f77d5SMatthew G. Knepley /* Read Auxiliary DS information */ 1202338f77d5SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 1203338f77d5SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &locA);CHKERRQ(ierr); 1204338f77d5SMatthew G. Knepley if (dmAux) { 1205338f77d5SMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 1206338f77d5SMatthew G. Knepley ierr = PetscDSGetNumFields(probAux, &NfAux);CHKERRQ(ierr); 1207338f77d5SMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 1208338f77d5SMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 1209338f77d5SMatthew G. Knepley ierr = PetscDSGetComponentOffsets(probAux, &aOff);CHKERRQ(ierr); 1210338f77d5SMatthew G. Knepley } 1211338f77d5SMatthew G. Knepley /* Allocate data arrays */ 1212338f77d5SMatthew G. Knepley ierr = PetscCalloc1(numCells*totDim, &u);CHKERRQ(ierr); 1213338f77d5SMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 1214338f77d5SMatthew G. Knepley /* Read out geometry */ 1215c330f8ffSToby Isaac ierr = DMGetCoordinateField(dm,&coordField);CHKERRQ(ierr); 1216c330f8ffSToby Isaac ierr = DMFieldGetFEInvariance(coordField,cellIS,NULL,&isAffine,NULL);CHKERRQ(ierr); 1217c330f8ffSToby Isaac if (isAffine) { 1218c330f8ffSToby Isaac ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&affineQuad);CHKERRQ(ierr); 1219c330f8ffSToby Isaac if (affineQuad) { 1220c330f8ffSToby Isaac ierr = DMFieldCreateFEGeom(coordField,cellIS,affineQuad,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr); 1221338f77d5SMatthew G. Knepley } 1222b5a3613cSMatthew G. Knepley } 1223b5a3613cSMatthew G. Knepley if (useFVM) { 1224338f77d5SMatthew G. Knepley PetscFV fv = NULL; 1225b5a3613cSMatthew G. Knepley Vec grad; 1226b5a3613cSMatthew G. Knepley PetscInt fStart, fEnd; 1227b5a3613cSMatthew G. Knepley PetscBool compGrad; 1228b5a3613cSMatthew G. Knepley 1229338f77d5SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1230338f77d5SMatthew G. Knepley PetscObject obj; 1231338f77d5SMatthew G. Knepley PetscClassId id; 1232338f77d5SMatthew G. Knepley 1233338f77d5SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1234338f77d5SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1235338f77d5SMatthew G. Knepley if (id == PETSCFV_CLASSID) {fv = (PetscFV) obj; break;} 1236338f77d5SMatthew G. Knepley } 1237338f77d5SMatthew G. Knepley ierr = PetscFVGetComputeGradients(fv, &compGrad);CHKERRQ(ierr); 1238338f77d5SMatthew G. Knepley ierr = PetscFVSetComputeGradients(fv, PETSC_TRUE);CHKERRQ(ierr); 1239b5a3613cSMatthew G. Knepley ierr = DMPlexComputeGeometryFVM(dm, &cellGeometryFVM, &faceGeometryFVM);CHKERRQ(ierr); 1240338f77d5SMatthew G. Knepley ierr = DMPlexComputeGradientFVM(dm, fv, faceGeometryFVM, cellGeometryFVM, &dmGrad);CHKERRQ(ierr); 1241338f77d5SMatthew G. Knepley ierr = PetscFVSetComputeGradients(fv, compGrad);CHKERRQ(ierr); 1242b5a3613cSMatthew G. Knepley ierr = VecGetArrayRead(cellGeometryFVM, (const PetscScalar **) &cgeomFVM);CHKERRQ(ierr); 1243b5a3613cSMatthew G. Knepley /* Reconstruct and limit cell gradients */ 1244b5a3613cSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 1245b5a3613cSMatthew G. Knepley ierr = DMGetGlobalVector(dmGrad, &grad);CHKERRQ(ierr); 1246338f77d5SMatthew G. Knepley ierr = DMPlexReconstructGradients_Internal(dm, fv, fStart, fEnd, faceGeometryFVM, cellGeometryFVM, locX, grad);CHKERRQ(ierr); 1247b5a3613cSMatthew G. Knepley /* Communicate gradient values */ 1248b5a3613cSMatthew G. Knepley ierr = DMGetLocalVector(dmGrad, &locGrad);CHKERRQ(ierr); 1249b5a3613cSMatthew G. Knepley ierr = DMGlobalToLocalBegin(dmGrad, grad, INSERT_VALUES, locGrad);CHKERRQ(ierr); 1250b5a3613cSMatthew G. Knepley ierr = DMGlobalToLocalEnd(dmGrad, grad, INSERT_VALUES, locGrad);CHKERRQ(ierr); 1251b5a3613cSMatthew G. Knepley ierr = DMRestoreGlobalVector(dmGrad, &grad);CHKERRQ(ierr); 1252b5a3613cSMatthew G. Knepley /* Handle non-essential (e.g. outflow) boundary values */ 1253338f77d5SMatthew G. Knepley ierr = DMPlexInsertBoundaryValues(dm, PETSC_FALSE, locX, 0.0, faceGeometryFVM, cellGeometryFVM, locGrad);CHKERRQ(ierr); 1254b5a3613cSMatthew G. Knepley ierr = VecGetArrayRead(locGrad, &lgrad);CHKERRQ(ierr); 1255b5a3613cSMatthew G. Knepley } 1256338f77d5SMatthew G. Knepley /* Read out data from inputs */ 125773d901b8SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 125873d901b8SMatthew G. Knepley PetscScalar *x = NULL; 125973d901b8SMatthew G. Knepley PetscInt i; 126073d901b8SMatthew G. Knepley 1261338f77d5SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, locX, c, NULL, &x);CHKERRQ(ierr); 12620f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 1263338f77d5SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, locX, c, NULL, &x);CHKERRQ(ierr); 126473d901b8SMatthew G. Knepley if (dmAux) { 1265338f77d5SMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, locA, c, NULL, &x);CHKERRQ(ierr); 12660f2d7e86SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 1267338f77d5SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, locA, c, NULL, &x);CHKERRQ(ierr); 126873d901b8SMatthew G. Knepley } 126973d901b8SMatthew G. Knepley } 1270338f77d5SMatthew G. Knepley /* Do integration for each field */ 127173d901b8SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1272c1f031eeSMatthew G. Knepley PetscObject obj; 1273c1f031eeSMatthew G. Knepley PetscClassId id; 1274c1f031eeSMatthew G. Knepley PetscInt numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset; 127573d901b8SMatthew G. Knepley 1276c1f031eeSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1277c1f031eeSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1278c1f031eeSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 1279c1f031eeSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 1280c1f031eeSMatthew G. Knepley PetscQuadrature q; 1281c330f8ffSToby Isaac PetscFEGeom *chunkGeom = NULL; 1282c1f031eeSMatthew G. Knepley PetscInt Nq, Nb; 1283c1f031eeSMatthew G. Knepley 12840f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 1285c1f031eeSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 12869c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 1287c1f031eeSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 1288c1f031eeSMatthew G. Knepley blockSize = Nb*Nq; 128973d901b8SMatthew G. Knepley batchSize = numBlocks * blockSize; 12900f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 129173d901b8SMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 129273d901b8SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 129373d901b8SMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 129473d901b8SMatthew G. Knepley offset = numCells - Nr; 1295c330f8ffSToby Isaac if (!affineQuad) { 1296c330f8ffSToby Isaac ierr = DMFieldCreateFEGeom(coordField,cellIS,q,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr); 1297c330f8ffSToby Isaac } 1298c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr); 1299c330f8ffSToby Isaac ierr = PetscFEIntegrate(fe, prob, f, Ne, chunkGeom, u, probAux, a, cintegral);CHKERRQ(ierr); 1300c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(cgeomFEM,offset,numCells,&chunkGeom);CHKERRQ(ierr); 1301c330f8ffSToby Isaac ierr = PetscFEIntegrate(fe, prob, f, Nr, chunkGeom, &u[offset*totDim], probAux, &a[offset*totDimAux], &cintegral[offset*Nf]);CHKERRQ(ierr); 1302c330f8ffSToby Isaac ierr = PetscFEGeomRestoreChunk(cgeomFEM,offset,numCells,&chunkGeom);CHKERRQ(ierr); 1303c330f8ffSToby Isaac if (!affineQuad) { 1304c330f8ffSToby Isaac ierr = PetscFEGeomDestroy(&cgeomFEM);CHKERRQ(ierr); 1305c330f8ffSToby Isaac } 1306c1f031eeSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 1307c1f031eeSMatthew G. Knepley PetscInt foff; 1308420e96edSMatthew G. Knepley PetscPointFunc obj_func; 1309b69edc29SMatthew G. Knepley PetscScalar lint; 1310c1f031eeSMatthew G. Knepley 1311c1f031eeSMatthew G. Knepley ierr = PetscDSGetObjective(prob, f, &obj_func);CHKERRQ(ierr); 1312c1f031eeSMatthew G. Knepley ierr = PetscDSGetFieldOffset(prob, f, &foff);CHKERRQ(ierr); 1313c1f031eeSMatthew G. Knepley if (obj_func) { 1314c1f031eeSMatthew G. Knepley for (c = 0; c < numCells; ++c) { 1315b5a3613cSMatthew G. Knepley PetscScalar *u_x; 1316b5a3613cSMatthew G. Knepley 1317b5a3613cSMatthew G. Knepley ierr = DMPlexPointLocalRead(dmGrad, c, lgrad, &u_x);CHKERRQ(ierr); 1318338f77d5SMatthew G. Knepley obj_func(dim, Nf, NfAux, uOff, uOff_x, &u[totDim*c+foff], NULL, u_x, aOff, NULL, &a[totDimAux*c], NULL, NULL, 0.0, cgeomFVM[c].centroid, numConstants, constants, &lint); 1319338f77d5SMatthew G. Knepley cintegral[c*Nf+f] += PetscRealPart(lint)*cgeomFVM[c].volume; 132073d901b8SMatthew G. Knepley } 1321c1f031eeSMatthew G. Knepley } 1322c1f031eeSMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 1323c1f031eeSMatthew G. Knepley } 1324338f77d5SMatthew G. Knepley /* Cleanup data arrays */ 1325b5a3613cSMatthew G. Knepley if (useFVM) { 1326b5a3613cSMatthew G. Knepley ierr = VecRestoreArrayRead(locGrad, &lgrad);CHKERRQ(ierr); 1327b5a3613cSMatthew G. Knepley ierr = VecRestoreArrayRead(cellGeometryFVM, (const PetscScalar **) &cgeomFVM);CHKERRQ(ierr); 1328b5a3613cSMatthew G. Knepley ierr = DMRestoreLocalVector(dmGrad, &locGrad);CHKERRQ(ierr); 1329b5a3613cSMatthew G. Knepley ierr = VecDestroy(&faceGeometryFVM);CHKERRQ(ierr); 1330b5a3613cSMatthew G. Knepley ierr = VecDestroy(&cellGeometryFVM);CHKERRQ(ierr); 1331b5a3613cSMatthew G. Knepley ierr = DMDestroy(&dmGrad);CHKERRQ(ierr); 1332b5a3613cSMatthew G. Knepley } 133373d901b8SMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 1334338f77d5SMatthew G. Knepley ierr = PetscFree(u);CHKERRQ(ierr); 1335338f77d5SMatthew G. Knepley /* Cleanup */ 1336f99c8401SToby Isaac if (affineQuad) { 1337f99c8401SToby Isaac ierr = PetscFEGeomDestroy(&cgeomFEM);CHKERRQ(ierr); 1338f99c8401SToby Isaac } 1339f99c8401SToby Isaac ierr = PetscQuadratureDestroy(&affineQuad);CHKERRQ(ierr); 1340c330f8ffSToby Isaac ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 1341338f77d5SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &locX);CHKERRQ(ierr); 1342338f77d5SMatthew G. Knepley PetscFunctionReturn(0); 1343338f77d5SMatthew G. Knepley } 1344338f77d5SMatthew G. Knepley 1345338f77d5SMatthew G. Knepley /*@ 1346338f77d5SMatthew G. Knepley DMPlexComputeIntegralFEM - Form the integral over the domain from the global input X using pointwise functions specified by the user 1347338f77d5SMatthew G. Knepley 1348338f77d5SMatthew G. Knepley Input Parameters: 1349338f77d5SMatthew G. Knepley + dm - The mesh 1350338f77d5SMatthew G. Knepley . X - Global input vector 1351338f77d5SMatthew G. Knepley - user - The user context 1352338f77d5SMatthew G. Knepley 1353338f77d5SMatthew G. Knepley Output Parameter: 1354338f77d5SMatthew G. Knepley . integral - Integral for each field 1355338f77d5SMatthew G. Knepley 1356338f77d5SMatthew G. Knepley Level: developer 1357338f77d5SMatthew G. Knepley 1358338f77d5SMatthew G. Knepley .seealso: DMPlexComputeResidualFEM() 1359338f77d5SMatthew G. Knepley @*/ 1360b8feb594SMatthew G. Knepley PetscErrorCode DMPlexComputeIntegralFEM(DM dm, Vec X, PetscScalar *integral, void *user) 1361338f77d5SMatthew G. Knepley { 1362338f77d5SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1363b8feb594SMatthew G. Knepley PetscScalar *cintegral, *lintegral; 1364338f77d5SMatthew G. Knepley PetscInt Nf, f, cellHeight, cStart, cEnd, cEndInterior[4], cell; 1365338f77d5SMatthew G. Knepley PetscErrorCode ierr; 1366338f77d5SMatthew G. Knepley 1367338f77d5SMatthew G. Knepley PetscFunctionBegin; 1368338f77d5SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1369338f77d5SMatthew G. Knepley PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 1370338f77d5SMatthew G. Knepley PetscValidPointer(integral, 3); 1371338f77d5SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr); 1372338f77d5SMatthew G. Knepley ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 1373338f77d5SMatthew G. Knepley ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1374338f77d5SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 1375338f77d5SMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior[0], &cEndInterior[1], &cEndInterior[2], &cEndInterior[3]);CHKERRQ(ierr); 1376338f77d5SMatthew G. Knepley cEnd = cEndInterior[cellHeight] < 0 ? cEnd : cEndInterior[cellHeight]; 1377338f77d5SMatthew G. Knepley /* TODO Introduce a loop over large chunks (right now this is a single chunk) */ 1378338f77d5SMatthew G. Knepley ierr = PetscCalloc2(Nf, &lintegral, (cEnd-cStart)*Nf, &cintegral);CHKERRQ(ierr); 1379338f77d5SMatthew G. Knepley ierr = DMPlexComputeIntegral_Internal(dm, X, cStart, cEnd, cintegral, user);CHKERRQ(ierr); 1380338f77d5SMatthew G. Knepley /* Sum up values */ 1381338f77d5SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 1382338f77d5SMatthew G. Knepley const PetscInt c = cell - cStart; 1383338f77d5SMatthew G. Knepley 1384338f77d5SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellVector(cell, "Cell Integral", Nf, &cintegral[c*Nf]);CHKERRQ(ierr);} 1385b8feb594SMatthew G. Knepley for (f = 0; f < Nf; ++f) lintegral[f] += cintegral[c*Nf+f]; 1386338f77d5SMatthew G. Knepley } 1387b8feb594SMatthew G. Knepley ierr = MPIU_Allreduce(lintegral, integral, Nf, MPIU_SCALAR, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 138873d901b8SMatthew G. Knepley if (mesh->printFEM) { 1389338f77d5SMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "Integral:");CHKERRQ(ierr); 1390b8feb594SMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), " %g", (double) PetscRealPart(integral[f]));CHKERRQ(ierr);} 139173d901b8SMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "\n");CHKERRQ(ierr); 139273d901b8SMatthew G. Knepley } 1393338f77d5SMatthew G. Knepley ierr = PetscFree2(lintegral, cintegral);CHKERRQ(ierr); 1394338f77d5SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr); 1395338f77d5SMatthew G. Knepley PetscFunctionReturn(0); 1396338f77d5SMatthew G. Knepley } 1397338f77d5SMatthew G. Knepley 1398338f77d5SMatthew G. Knepley /*@ 1399338f77d5SMatthew G. Knepley DMPlexComputeCellwiseIntegralFEM - Form the vector of cellwise integrals F from the global input X using pointwise functions specified by the user 1400338f77d5SMatthew G. Knepley 1401338f77d5SMatthew G. Knepley Input Parameters: 1402338f77d5SMatthew G. Knepley + dm - The mesh 1403338f77d5SMatthew G. Knepley . X - Global input vector 1404338f77d5SMatthew G. Knepley - user - The user context 1405338f77d5SMatthew G. Knepley 1406338f77d5SMatthew G. Knepley Output Parameter: 1407338f77d5SMatthew G. Knepley . integral - Cellwise integrals for each field 1408338f77d5SMatthew G. Knepley 1409338f77d5SMatthew G. Knepley Level: developer 1410338f77d5SMatthew G. Knepley 1411338f77d5SMatthew G. Knepley .seealso: DMPlexComputeResidualFEM() 1412338f77d5SMatthew G. Knepley @*/ 1413338f77d5SMatthew G. Knepley PetscErrorCode DMPlexComputeCellwiseIntegralFEM(DM dm, Vec X, Vec F, void *user) 1414338f77d5SMatthew G. Knepley { 1415338f77d5SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1416338f77d5SMatthew G. Knepley DM dmF; 1417338f77d5SMatthew G. Knepley PetscSection sectionF; 1418338f77d5SMatthew G. Knepley PetscScalar *cintegral, *af; 1419338f77d5SMatthew G. Knepley PetscInt Nf, f, cellHeight, cStart, cEnd, cEndInterior[4], cell; 1420338f77d5SMatthew G. Knepley PetscErrorCode ierr; 1421338f77d5SMatthew G. Knepley 1422338f77d5SMatthew G. Knepley PetscFunctionBegin; 1423338f77d5SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1424338f77d5SMatthew G. Knepley PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 1425338f77d5SMatthew G. Knepley PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 1426338f77d5SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr); 1427338f77d5SMatthew G. Knepley ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 1428338f77d5SMatthew G. Knepley ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 1429338f77d5SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 1430338f77d5SMatthew G. Knepley ierr = DMPlexGetHybridBounds(dm, &cEndInterior[0], &cEndInterior[1], &cEndInterior[2], &cEndInterior[3]);CHKERRQ(ierr); 1431338f77d5SMatthew G. Knepley cEnd = cEndInterior[cellHeight] < 0 ? cEnd : cEndInterior[cellHeight]; 1432338f77d5SMatthew G. Knepley /* TODO Introduce a loop over large chunks (right now this is a single chunk) */ 1433338f77d5SMatthew G. Knepley ierr = PetscCalloc1((cEnd-cStart)*Nf, &cintegral);CHKERRQ(ierr); 1434338f77d5SMatthew G. Knepley ierr = DMPlexComputeIntegral_Internal(dm, X, cStart, cEnd, cintegral, user);CHKERRQ(ierr); 1435338f77d5SMatthew G. Knepley /* Put values in F*/ 1436338f77d5SMatthew G. Knepley ierr = VecGetDM(F, &dmF);CHKERRQ(ierr); 1437338f77d5SMatthew G. Knepley ierr = DMGetDefaultSection(dmF, §ionF);CHKERRQ(ierr); 1438338f77d5SMatthew G. Knepley ierr = VecGetArray(F, &af);CHKERRQ(ierr); 1439338f77d5SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 1440338f77d5SMatthew G. Knepley const PetscInt c = cell - cStart; 1441338f77d5SMatthew G. Knepley PetscInt dof, off; 1442338f77d5SMatthew G. Knepley 1443338f77d5SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellVector(cell, "Cell Integral", Nf, &cintegral[c*Nf]);CHKERRQ(ierr);} 1444338f77d5SMatthew G. Knepley ierr = PetscSectionGetDof(sectionF, cell, &dof);CHKERRQ(ierr); 1445338f77d5SMatthew G. Knepley ierr = PetscSectionGetOffset(sectionF, cell, &off);CHKERRQ(ierr); 1446338f77d5SMatthew G. Knepley if (dof != Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The number of cell dofs %D != %D", dof, Nf); 1447338f77d5SMatthew G. Knepley for (f = 0; f < Nf; ++f) af[off+f] = cintegral[c*Nf+f]; 1448338f77d5SMatthew G. Knepley } 1449338f77d5SMatthew G. Knepley ierr = VecRestoreArray(F, &af);CHKERRQ(ierr); 1450338f77d5SMatthew G. Knepley ierr = PetscFree(cintegral);CHKERRQ(ierr); 1451c1f031eeSMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr); 145273d901b8SMatthew G. Knepley PetscFunctionReturn(0); 145373d901b8SMatthew G. Knepley } 145473d901b8SMatthew G. Knepley 1455d69c5d34SMatthew G. Knepley /*@ 145668132eb9SMatthew G. Knepley DMPlexComputeInterpolatorNested - Form the local portion of the interpolation matrix I from the coarse DM to the uniformly refined DM. 1457d69c5d34SMatthew G. Knepley 1458d69c5d34SMatthew G. Knepley Input Parameters: 1459d69c5d34SMatthew G. Knepley + dmf - The fine mesh 1460d69c5d34SMatthew G. Knepley . dmc - The coarse mesh 1461d69c5d34SMatthew G. Knepley - user - The user context 1462d69c5d34SMatthew G. Knepley 1463d69c5d34SMatthew G. Knepley Output Parameter: 1464934789fcSMatthew G. Knepley . In - The interpolation matrix 1465d69c5d34SMatthew G. Knepley 1466d69c5d34SMatthew G. Knepley Level: developer 1467d69c5d34SMatthew G. Knepley 146868132eb9SMatthew G. Knepley .seealso: DMPlexComputeInterpolatorGeneral(), DMPlexComputeJacobianFEM() 1469d69c5d34SMatthew G. Knepley @*/ 147068132eb9SMatthew G. Knepley PetscErrorCode DMPlexComputeInterpolatorNested(DM dmc, DM dmf, Mat In, void *user) 1471d69c5d34SMatthew G. Knepley { 1472d69c5d34SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dmc->data; 1473d69c5d34SMatthew G. Knepley const char *name = "Interpolator"; 14742764a2aaSMatthew G. Knepley PetscDS prob; 1475d69c5d34SMatthew G. Knepley PetscFE *feRef; 147697c42addSMatthew G. Knepley PetscFV *fvRef; 1477d69c5d34SMatthew G. Knepley PetscSection fsection, fglobalSection; 1478d69c5d34SMatthew G. Knepley PetscSection csection, cglobalSection; 1479d69c5d34SMatthew G. Knepley PetscScalar *elemMat; 14809ac3fadcSMatthew G. Knepley PetscInt dim, Nf, f, fieldI, fieldJ, offsetI, offsetJ, cStart, cEnd, cEndInterior, c; 14810f2d7e86SMatthew G. Knepley PetscInt cTotDim, rTotDim = 0; 1482d69c5d34SMatthew G. Knepley PetscErrorCode ierr; 1483d69c5d34SMatthew G. Knepley 1484d69c5d34SMatthew G. Knepley PetscFunctionBegin; 1485d69c5d34SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1486c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 1487d69c5d34SMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 1488d69c5d34SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 1489d69c5d34SMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 1490d69c5d34SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 1491d69c5d34SMatthew G. Knepley ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 1492d69c5d34SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 14939ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dmc, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 14949ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 14952764a2aaSMatthew G. Knepley ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr); 149697c42addSMatthew G. Knepley ierr = PetscCalloc2(Nf,&feRef,Nf,&fvRef);CHKERRQ(ierr); 1497d69c5d34SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 149897c42addSMatthew G. Knepley PetscObject obj; 149997c42addSMatthew G. Knepley PetscClassId id; 1500aa7890ccSMatthew G. Knepley PetscInt rNb = 0, Nc = 0; 1501d69c5d34SMatthew G. Knepley 150297c42addSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 150397c42addSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 150497c42addSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 150597c42addSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 150697c42addSMatthew G. Knepley 15070f2d7e86SMatthew G. Knepley ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 1508d69c5d34SMatthew G. Knepley ierr = PetscFEGetDimension(feRef[f], &rNb);CHKERRQ(ierr); 15090f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 151097c42addSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 151197c42addSMatthew G. Knepley PetscFV fv = (PetscFV) obj; 151297c42addSMatthew G. Knepley PetscDualSpace Q; 151397c42addSMatthew G. Knepley 151497c42addSMatthew G. Knepley ierr = PetscFVRefine(fv, &fvRef[f]);CHKERRQ(ierr); 151597c42addSMatthew G. Knepley ierr = PetscFVGetDualSpace(fvRef[f], &Q);CHKERRQ(ierr); 151697c42addSMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Q, &rNb);CHKERRQ(ierr); 151797c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 151897c42addSMatthew G. Knepley } 15199c3cf19fSMatthew G. Knepley rTotDim += rNb; 1520d69c5d34SMatthew G. Knepley } 15212764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 15220f2d7e86SMatthew G. Knepley ierr = PetscMalloc1(rTotDim*cTotDim,&elemMat);CHKERRQ(ierr); 15230f2d7e86SMatthew G. Knepley ierr = PetscMemzero(elemMat, rTotDim*cTotDim * sizeof(PetscScalar));CHKERRQ(ierr); 1524d69c5d34SMatthew G. Knepley for (fieldI = 0, offsetI = 0; fieldI < Nf; ++fieldI) { 1525d69c5d34SMatthew G. Knepley PetscDualSpace Qref; 1526d69c5d34SMatthew G. Knepley PetscQuadrature f; 1527d69c5d34SMatthew G. Knepley const PetscReal *qpoints, *qweights; 1528d69c5d34SMatthew G. Knepley PetscReal *points; 1529d69c5d34SMatthew G. Knepley PetscInt npoints = 0, Nc, Np, fpdim, i, k, p, d; 1530d69c5d34SMatthew G. Knepley 1531d69c5d34SMatthew G. Knepley /* Compose points from all dual basis functionals */ 153297c42addSMatthew G. Knepley if (feRef[fieldI]) { 1533d69c5d34SMatthew G. Knepley ierr = PetscFEGetDualSpace(feRef[fieldI], &Qref);CHKERRQ(ierr); 15340f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(feRef[fieldI], &Nc);CHKERRQ(ierr); 153597c42addSMatthew G. Knepley } else { 153697c42addSMatthew G. Knepley ierr = PetscFVGetDualSpace(fvRef[fieldI], &Qref);CHKERRQ(ierr); 153797c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fvRef[fieldI], &Nc);CHKERRQ(ierr); 153897c42addSMatthew G. Knepley } 1539d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Qref, &fpdim);CHKERRQ(ierr); 1540d69c5d34SMatthew G. Knepley for (i = 0; i < fpdim; ++i) { 1541d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 15429c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, NULL, &Np, NULL, NULL);CHKERRQ(ierr); 1543d69c5d34SMatthew G. Knepley npoints += Np; 1544d69c5d34SMatthew G. Knepley } 1545d69c5d34SMatthew G. Knepley ierr = PetscMalloc1(npoints*dim,&points);CHKERRQ(ierr); 1546d69c5d34SMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) { 1547d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 15489c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, NULL, &Np, &qpoints, NULL);CHKERRQ(ierr); 1549d69c5d34SMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) for (d = 0; d < dim; ++d) points[k*dim+d] = qpoints[p*dim+d]; 1550d69c5d34SMatthew G. Knepley } 1551d69c5d34SMatthew G. Knepley 1552d69c5d34SMatthew G. Knepley for (fieldJ = 0, offsetJ = 0; fieldJ < Nf; ++fieldJ) { 155397c42addSMatthew G. Knepley PetscObject obj; 155497c42addSMatthew G. Knepley PetscClassId id; 1555d69c5d34SMatthew G. Knepley PetscReal *B; 15569c3cf19fSMatthew G. Knepley PetscInt NcJ = 0, cpdim = 0, j, qNc; 1557d69c5d34SMatthew G. Knepley 155897c42addSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldJ, &obj);CHKERRQ(ierr); 155997c42addSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 156097c42addSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 156197c42addSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 1562d69c5d34SMatthew G. Knepley 1563d69c5d34SMatthew G. Knepley /* Evaluate basis at points */ 15640f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &NcJ);CHKERRQ(ierr); 15650f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &cpdim);CHKERRQ(ierr); 1566ffe73a53SMatthew G. Knepley /* For now, fields only interpolate themselves */ 1567ffe73a53SMatthew G. Knepley if (fieldI == fieldJ) { 15689c3cf19fSMatthew 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); 15690f2d7e86SMatthew G. Knepley ierr = PetscFEGetTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr); 1570d69c5d34SMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) { 1571d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 15729c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &qNc, &Np, NULL, &qweights);CHKERRQ(ierr); 15739c3cf19fSMatthew 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); 1574d69c5d34SMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) { 157536a6d9c0SMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 1576d172c84bSMatthew G. Knepley /* 1577d172c84bSMatthew G. Knepley cTotDim: Total columns in element interpolation matrix, sum of number of dual basis functionals in each field 1578d172c84bSMatthew G. Knepley offsetI, offsetJ: Offsets into the larger element interpolation matrix for different fields 1579d172c84bSMatthew G. Knepley fpdim, i, cpdim, j: Dofs for fine and coarse grids, correspond to dual space basis functionals 1580d172c84bSMatthew G. Knepley qNC, Nc, Ncj, c: Number of components in this field 1581d172c84bSMatthew G. Knepley Np, p: Number of quad points in the fine grid functional i 1582d172c84bSMatthew G. Knepley k: i*Np + p, overall point number for the interpolation 1583d172c84bSMatthew G. Knepley */ 15849c3cf19fSMatthew 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]; 158536a6d9c0SMatthew G. Knepley } 1586d69c5d34SMatthew G. Knepley } 1587d69c5d34SMatthew G. Knepley } 15880f2d7e86SMatthew G. Knepley ierr = PetscFERestoreTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr);CHKERRQ(ierr); 1589ffe73a53SMatthew G. Knepley } 159097c42addSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 159197c42addSMatthew G. Knepley PetscFV fv = (PetscFV) obj; 159297c42addSMatthew G. Knepley 159397c42addSMatthew G. Knepley /* Evaluate constant function at points */ 159497c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &NcJ);CHKERRQ(ierr); 159597c42addSMatthew G. Knepley cpdim = 1; 159697c42addSMatthew G. Knepley /* For now, fields only interpolate themselves */ 159797c42addSMatthew G. Knepley if (fieldI == fieldJ) { 159897c42addSMatthew 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); 159997c42addSMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) { 160097c42addSMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 16019c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &qNc, &Np, NULL, &qweights);CHKERRQ(ierr); 16029c3cf19fSMatthew 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); 160397c42addSMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) { 160497c42addSMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 1605458eb97cSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[(offsetI + i)*cTotDim + offsetJ + j] += 1.0*qweights[p*qNc+c]; 160697c42addSMatthew G. Knepley } 160797c42addSMatthew G. Knepley } 160897c42addSMatthew G. Knepley } 160997c42addSMatthew G. Knepley } 161097c42addSMatthew G. Knepley } 1611458eb97cSMatthew G. Knepley offsetJ += cpdim; 1612d69c5d34SMatthew G. Knepley } 1613458eb97cSMatthew G. Knepley offsetI += fpdim; 1614549a8adaSMatthew G. Knepley ierr = PetscFree(points);CHKERRQ(ierr); 1615d69c5d34SMatthew G. Knepley } 16160f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(0, name, rTotDim, cTotDim, elemMat);CHKERRQ(ierr);} 16177f5b169aSMatthew G. Knepley /* Preallocate matrix */ 16187f5b169aSMatthew G. Knepley { 1619c094ef40SMatthew G. Knepley Mat preallocator; 1620c094ef40SMatthew G. Knepley PetscScalar *vals; 1621c094ef40SMatthew G. Knepley PetscInt *cellCIndices, *cellFIndices; 1622c094ef40SMatthew G. Knepley PetscInt locRows, locCols, cell; 16237f5b169aSMatthew G. Knepley 1624c094ef40SMatthew G. Knepley ierr = MatGetLocalSize(In, &locRows, &locCols);CHKERRQ(ierr); 1625c094ef40SMatthew G. Knepley ierr = MatCreate(PetscObjectComm((PetscObject) In), &preallocator);CHKERRQ(ierr); 1626c094ef40SMatthew G. Knepley ierr = MatSetType(preallocator, MATPREALLOCATOR);CHKERRQ(ierr); 1627c094ef40SMatthew G. Knepley ierr = MatSetSizes(preallocator, locRows, locCols, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1628c094ef40SMatthew G. Knepley ierr = MatSetUp(preallocator);CHKERRQ(ierr); 1629c094ef40SMatthew G. Knepley ierr = PetscCalloc3(rTotDim*cTotDim, &vals,cTotDim,&cellCIndices,rTotDim,&cellFIndices);CHKERRQ(ierr); 16307f5b169aSMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 16317f5b169aSMatthew G. Knepley ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, cell, cellCIndices, cellFIndices);CHKERRQ(ierr); 1632c094ef40SMatthew G. Knepley ierr = MatSetValues(preallocator, rTotDim, cellFIndices, cTotDim, cellCIndices, vals, INSERT_VALUES);CHKERRQ(ierr); 16337f5b169aSMatthew G. Knepley } 1634c094ef40SMatthew G. Knepley ierr = PetscFree3(vals,cellCIndices,cellFIndices);CHKERRQ(ierr); 1635c094ef40SMatthew G. Knepley ierr = MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1636c094ef40SMatthew G. Knepley ierr = MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1637c094ef40SMatthew G. Knepley ierr = MatPreallocatorPreallocate(preallocator, PETSC_TRUE, In);CHKERRQ(ierr); 1638c094ef40SMatthew G. Knepley ierr = MatDestroy(&preallocator);CHKERRQ(ierr); 16397f5b169aSMatthew G. Knepley } 16407f5b169aSMatthew G. Knepley /* Fill matrix */ 16417f5b169aSMatthew G. Knepley ierr = MatZeroEntries(In);CHKERRQ(ierr); 1642d69c5d34SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1643934789fcSMatthew G. Knepley ierr = DMPlexMatSetClosureRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, In, c, elemMat, INSERT_VALUES);CHKERRQ(ierr); 1644d69c5d34SMatthew G. Knepley } 1645549a8adaSMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);} 164697c42addSMatthew G. Knepley ierr = PetscFree2(feRef,fvRef);CHKERRQ(ierr); 1647549a8adaSMatthew G. Knepley ierr = PetscFree(elemMat);CHKERRQ(ierr); 1648934789fcSMatthew G. Knepley ierr = MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1649934789fcSMatthew G. Knepley ierr = MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1650d69c5d34SMatthew G. Knepley if (mesh->printFEM) { 1651d69c5d34SMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_WORLD, "%s:\n", name);CHKERRQ(ierr); 1652934789fcSMatthew G. Knepley ierr = MatChop(In, 1.0e-10);CHKERRQ(ierr); 1653934789fcSMatthew G. Knepley ierr = MatView(In, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1654d69c5d34SMatthew G. Knepley } 1655d69c5d34SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1656d69c5d34SMatthew G. Knepley PetscFunctionReturn(0); 1657d69c5d34SMatthew G. Knepley } 16586c73c22cSMatthew G. Knepley 1659bd041c0cSMatthew G. Knepley PetscErrorCode DMPlexComputeMassMatrixNested(DM dmc, DM dmf, Mat mass, void *user) 1660bd041c0cSMatthew G. Knepley { 1661bd041c0cSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dmc), PETSC_ERR_SUP, "Laziness"); 1662bd041c0cSMatthew G. Knepley } 1663bd041c0cSMatthew G. Knepley 166468132eb9SMatthew G. Knepley /*@ 166568132eb9SMatthew G. Knepley DMPlexComputeInterpolatorGeneral - Form the local portion of the interpolation matrix I from the coarse DM to a non-nested fine DM. 166668132eb9SMatthew G. Knepley 166768132eb9SMatthew G. Knepley Input Parameters: 166868132eb9SMatthew G. Knepley + dmf - The fine mesh 166968132eb9SMatthew G. Knepley . dmc - The coarse mesh 167068132eb9SMatthew G. Knepley - user - The user context 167168132eb9SMatthew G. Knepley 167268132eb9SMatthew G. Knepley Output Parameter: 167368132eb9SMatthew G. Knepley . In - The interpolation matrix 167468132eb9SMatthew G. Knepley 167568132eb9SMatthew G. Knepley Level: developer 167668132eb9SMatthew G. Knepley 167768132eb9SMatthew G. Knepley .seealso: DMPlexComputeInterpolatorNested(), DMPlexComputeJacobianFEM() 167868132eb9SMatthew G. Knepley @*/ 167968132eb9SMatthew G. Knepley PetscErrorCode DMPlexComputeInterpolatorGeneral(DM dmc, DM dmf, Mat In, void *user) 16804ef9d792SMatthew G. Knepley { 168164e98e1dSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dmf->data; 168264e98e1dSMatthew G. Knepley const char *name = "Interpolator"; 16834ef9d792SMatthew G. Knepley PetscDS prob; 16844ef9d792SMatthew G. Knepley PetscSection fsection, csection, globalFSection, globalCSection; 1685e8f14785SLisandro Dalcin PetscHSetIJ ht; 16864ef9d792SMatthew G. Knepley PetscLayout rLayout; 16874ef9d792SMatthew G. Knepley PetscInt *dnz, *onz; 16884ef9d792SMatthew G. Knepley PetscInt locRows, rStart, rEnd; 16894ef9d792SMatthew G. Knepley PetscReal *x, *v0, *J, *invJ, detJ; 16904ef9d792SMatthew G. Knepley PetscReal *v0c, *Jc, *invJc, detJc; 16914ef9d792SMatthew G. Knepley PetscScalar *elemMat; 16924ef9d792SMatthew G. Knepley PetscInt dim, Nf, field, totDim, cStart, cEnd, cell, ccell; 16934ef9d792SMatthew G. Knepley PetscErrorCode ierr; 16944ef9d792SMatthew G. Knepley 16954ef9d792SMatthew G. Knepley PetscFunctionBegin; 169677711781SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 16974ef9d792SMatthew G. Knepley ierr = DMGetCoordinateDim(dmc, &dim);CHKERRQ(ierr); 16984ef9d792SMatthew G. Knepley ierr = DMGetDS(dmc, &prob);CHKERRQ(ierr); 16994ef9d792SMatthew G. Knepley ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr); 17004ef9d792SMatthew G. Knepley ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 17014ef9d792SMatthew G. Knepley ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 17024ef9d792SMatthew G. Knepley ierr = PetscMalloc3(dim,&v0c,dim*dim,&Jc,dim*dim,&invJc);CHKERRQ(ierr); 17034ef9d792SMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 17044ef9d792SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr); 17054ef9d792SMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 17064ef9d792SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr); 17074ef9d792SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr); 17084ef9d792SMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 17099c3cf19fSMatthew G. Knepley ierr = PetscMalloc1(totDim, &elemMat);CHKERRQ(ierr); 17104ef9d792SMatthew G. Knepley 17114ef9d792SMatthew G. Knepley ierr = MatGetLocalSize(In, &locRows, NULL);CHKERRQ(ierr); 17124ef9d792SMatthew G. Knepley ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) In), &rLayout);CHKERRQ(ierr); 17134ef9d792SMatthew G. Knepley ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 17144ef9d792SMatthew G. Knepley ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 17154ef9d792SMatthew G. Knepley ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 17164ef9d792SMatthew G. Knepley ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 17174ef9d792SMatthew G. Knepley ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 17184ef9d792SMatthew G. Knepley ierr = PetscCalloc2(locRows,&dnz,locRows,&onz);CHKERRQ(ierr); 1719e8f14785SLisandro Dalcin ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr); 17204ef9d792SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 17214ef9d792SMatthew G. Knepley PetscObject obj; 17224ef9d792SMatthew G. Knepley PetscClassId id; 1723c0d7054bSMatthew G. Knepley PetscDualSpace Q = NULL; 17244ef9d792SMatthew G. Knepley PetscQuadrature f; 172517f047d8SMatthew G. Knepley const PetscReal *qpoints; 172617f047d8SMatthew G. Knepley PetscInt Nc, Np, fpdim, i, d; 17274ef9d792SMatthew G. Knepley 17284ef9d792SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr); 17294ef9d792SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 17304ef9d792SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 17314ef9d792SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 17324ef9d792SMatthew G. Knepley 17334ef9d792SMatthew G. Knepley ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 17344ef9d792SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 17354ef9d792SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 17364ef9d792SMatthew G. Knepley PetscFV fv = (PetscFV) obj; 17374ef9d792SMatthew G. Knepley 17384ef9d792SMatthew G. Knepley ierr = PetscFVGetDualSpace(fv, &Q);CHKERRQ(ierr); 17394ef9d792SMatthew G. Knepley Nc = 1; 17404ef9d792SMatthew G. Knepley } 17414ef9d792SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Q, &fpdim);CHKERRQ(ierr); 17424ef9d792SMatthew G. Knepley /* For each fine grid cell */ 17434ef9d792SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 17444ef9d792SMatthew G. Knepley PetscInt *findices, *cindices; 17454ef9d792SMatthew G. Knepley PetscInt numFIndices, numCIndices; 17464ef9d792SMatthew G. Knepley 17476ecaa68aSToby Isaac ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 17484ef9d792SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 17499c3cf19fSMatthew G. Knepley if (numFIndices != fpdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of fine indices %d != %d dual basis vecs", numFIndices, fpdim); 17504ef9d792SMatthew G. Knepley for (i = 0; i < fpdim; ++i) { 17514ef9d792SMatthew G. Knepley Vec pointVec; 17524ef9d792SMatthew G. Knepley PetscScalar *pV; 17533a93e3b7SToby Isaac PetscSF coarseCellSF = NULL; 17543a93e3b7SToby Isaac const PetscSFNode *coarseCells; 17559c3cf19fSMatthew G. Knepley PetscInt numCoarseCells, q, c; 17564ef9d792SMatthew G. Knepley 17574ef9d792SMatthew G. Knepley /* Get points from the dual basis functional quadrature */ 17584ef9d792SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Q, i, &f);CHKERRQ(ierr); 17599c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, NULL, &Np, &qpoints, NULL);CHKERRQ(ierr); 17604ef9d792SMatthew G. Knepley ierr = VecCreateSeq(PETSC_COMM_SELF, Np*dim, &pointVec);CHKERRQ(ierr); 17614ef9d792SMatthew G. Knepley ierr = VecSetBlockSize(pointVec, dim);CHKERRQ(ierr); 17624ef9d792SMatthew G. Knepley ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 17634ef9d792SMatthew G. Knepley for (q = 0; q < Np; ++q) { 1764c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 1765c330f8ffSToby Isaac 17664ef9d792SMatthew G. Knepley /* Transform point to real space */ 1767c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0, J, &qpoints[q*dim], x); 17684ef9d792SMatthew G. Knepley for (d = 0; d < dim; ++d) pV[q*dim+d] = x[d]; 17694ef9d792SMatthew G. Knepley } 17704ef9d792SMatthew G. Knepley ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 17714ef9d792SMatthew G. Knepley /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */ 17721555c271SMatthew G. Knepley /* OPT: Pack all quad points from fine cell */ 177362a38674SMatthew G. Knepley ierr = DMLocatePoints(dmc, pointVec, DM_POINTLOCATION_NEAREST, &coarseCellSF);CHKERRQ(ierr); 17743a93e3b7SToby Isaac ierr = PetscSFViewFromOptions(coarseCellSF, NULL, "-interp_sf_view");CHKERRQ(ierr); 17754ef9d792SMatthew G. Knepley /* Update preallocation info */ 17763a93e3b7SToby Isaac ierr = PetscSFGetGraph(coarseCellSF, NULL, &numCoarseCells, NULL, &coarseCells);CHKERRQ(ierr); 17773a93e3b7SToby Isaac if (numCoarseCells != Np) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located"); 17789c3cf19fSMatthew G. Knepley { 1779e8f14785SLisandro Dalcin PetscHashIJKey key; 1780e8f14785SLisandro Dalcin PetscBool missing; 17814ef9d792SMatthew G. Knepley 1782e8f14785SLisandro Dalcin key.i = findices[i]; 1783e8f14785SLisandro Dalcin if (key.i >= 0) { 17844ef9d792SMatthew G. Knepley /* Get indices for coarse elements */ 17854ef9d792SMatthew G. Knepley for (ccell = 0; ccell < numCoarseCells; ++ccell) { 17863a93e3b7SToby Isaac ierr = DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 17874ef9d792SMatthew G. Knepley for (c = 0; c < numCIndices; ++c) { 1788e8f14785SLisandro Dalcin key.j = cindices[c]; 1789e8f14785SLisandro Dalcin if (key.j < 0) continue; 1790e8f14785SLisandro Dalcin ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr); 17914ef9d792SMatthew G. Knepley if (missing) { 1792e8f14785SLisandro Dalcin if ((key.j >= rStart) && (key.j < rEnd)) ++dnz[key.i-rStart]; 1793e8f14785SLisandro Dalcin else ++onz[key.i-rStart]; 17944ef9d792SMatthew G. Knepley } 17954ef9d792SMatthew G. Knepley } 17963a93e3b7SToby Isaac ierr = DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 17974ef9d792SMatthew G. Knepley } 17984ef9d792SMatthew G. Knepley } 17998c543595SMatthew G. Knepley } 18003a93e3b7SToby Isaac ierr = PetscSFDestroy(&coarseCellSF);CHKERRQ(ierr); 18014ef9d792SMatthew G. Knepley ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 18024ef9d792SMatthew G. Knepley } 180346bdb399SToby Isaac ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 18044ef9d792SMatthew G. Knepley } 18054ef9d792SMatthew G. Knepley } 1806e8f14785SLisandro Dalcin ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr); 18074ef9d792SMatthew G. Knepley ierr = MatXAIJSetPreallocation(In, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr); 18084ef9d792SMatthew G. Knepley ierr = MatSetOption(In, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 18094ef9d792SMatthew G. Knepley ierr = PetscFree2(dnz,onz);CHKERRQ(ierr); 18104ef9d792SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 18114ef9d792SMatthew G. Knepley PetscObject obj; 18124ef9d792SMatthew G. Knepley PetscClassId id; 1813c0d7054bSMatthew G. Knepley PetscDualSpace Q = NULL; 18144ef9d792SMatthew G. Knepley PetscQuadrature f; 18154ef9d792SMatthew G. Knepley const PetscReal *qpoints, *qweights; 18169c3cf19fSMatthew G. Knepley PetscInt Nc, qNc, Np, fpdim, i, d; 18174ef9d792SMatthew G. Knepley 18184ef9d792SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr); 18194ef9d792SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 18204ef9d792SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 18214ef9d792SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 18224ef9d792SMatthew G. Knepley 18234ef9d792SMatthew G. Knepley ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 18244ef9d792SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 18254ef9d792SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 18264ef9d792SMatthew G. Knepley PetscFV fv = (PetscFV) obj; 18274ef9d792SMatthew G. Knepley 18284ef9d792SMatthew G. Knepley ierr = PetscFVGetDualSpace(fv, &Q);CHKERRQ(ierr); 18294ef9d792SMatthew G. Knepley Nc = 1; 183025ce1634SJed Brown } else SETERRQ1(PetscObjectComm((PetscObject)dmc),PETSC_ERR_ARG_WRONG,"Unknown discretization type for field %d",field); 18314ef9d792SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Q, &fpdim);CHKERRQ(ierr); 18324ef9d792SMatthew G. Knepley /* For each fine grid cell */ 18334ef9d792SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 18344ef9d792SMatthew G. Knepley PetscInt *findices, *cindices; 18354ef9d792SMatthew G. Knepley PetscInt numFIndices, numCIndices; 18364ef9d792SMatthew G. Knepley 18376ecaa68aSToby Isaac ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 18384ef9d792SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 18399c3cf19fSMatthew G. Knepley if (numFIndices != fpdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of fine indices %d != %d dual basis vecs", numFIndices, fpdim); 18404ef9d792SMatthew G. Knepley for (i = 0; i < fpdim; ++i) { 18414ef9d792SMatthew G. Knepley Vec pointVec; 18424ef9d792SMatthew G. Knepley PetscScalar *pV; 184312111d7cSToby Isaac PetscSF coarseCellSF = NULL; 18443a93e3b7SToby Isaac const PetscSFNode *coarseCells; 184517f047d8SMatthew G. Knepley PetscInt numCoarseCells, cpdim, q, c, j; 18464ef9d792SMatthew G. Knepley 18474ef9d792SMatthew G. Knepley /* Get points from the dual basis functional quadrature */ 18484ef9d792SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Q, i, &f);CHKERRQ(ierr); 18499c3cf19fSMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &qNc, &Np, &qpoints, &qweights);CHKERRQ(ierr); 18509c3cf19fSMatthew 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); 18514ef9d792SMatthew G. Knepley ierr = VecCreateSeq(PETSC_COMM_SELF, Np*dim, &pointVec);CHKERRQ(ierr); 18524ef9d792SMatthew G. Knepley ierr = VecSetBlockSize(pointVec, dim);CHKERRQ(ierr); 18534ef9d792SMatthew G. Knepley ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 18544ef9d792SMatthew G. Knepley for (q = 0; q < Np; ++q) { 1855c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 1856c330f8ffSToby Isaac 18574ef9d792SMatthew G. Knepley /* Transform point to real space */ 1858c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0, J, &qpoints[q*dim], x); 18594ef9d792SMatthew G. Knepley for (d = 0; d < dim; ++d) pV[q*dim+d] = x[d]; 18604ef9d792SMatthew G. Knepley } 18614ef9d792SMatthew G. Knepley ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 18624ef9d792SMatthew G. Knepley /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */ 18631555c271SMatthew G. Knepley /* OPT: Read this out from preallocation information */ 186462a38674SMatthew G. Knepley ierr = DMLocatePoints(dmc, pointVec, DM_POINTLOCATION_NEAREST, &coarseCellSF);CHKERRQ(ierr); 18654ef9d792SMatthew G. Knepley /* Update preallocation info */ 18663a93e3b7SToby Isaac ierr = PetscSFGetGraph(coarseCellSF, NULL, &numCoarseCells, NULL, &coarseCells);CHKERRQ(ierr); 18673a93e3b7SToby Isaac if (numCoarseCells != Np) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located"); 18684ef9d792SMatthew G. Knepley ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 18694ef9d792SMatthew G. Knepley for (ccell = 0; ccell < numCoarseCells; ++ccell) { 1870826eb36dSMatthew G. Knepley PetscReal pVReal[3]; 1871c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 1872826eb36dSMatthew G. Knepley 18733a93e3b7SToby Isaac ierr = DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 18744ef9d792SMatthew G. Knepley /* Transform points from real space to coarse reference space */ 18753a93e3b7SToby Isaac ierr = DMPlexComputeCellGeometryFEM(dmc, coarseCells[ccell].index, NULL, v0c, Jc, invJc, &detJc);CHKERRQ(ierr); 1876e2d86523SMatthew G. Knepley for (d = 0; d < dim; ++d) pVReal[d] = PetscRealPart(pV[ccell*dim+d]); 1877c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0c, invJc, pVReal, x); 18784ef9d792SMatthew G. Knepley 18794ef9d792SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 18804ef9d792SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 18814ef9d792SMatthew G. Knepley PetscReal *B; 18824ef9d792SMatthew G. Knepley 18834ef9d792SMatthew G. Knepley /* Evaluate coarse basis on contained point */ 18844ef9d792SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &cpdim);CHKERRQ(ierr); 18854ef9d792SMatthew G. Knepley ierr = PetscFEGetTabulation(fe, 1, x, &B, NULL, NULL);CHKERRQ(ierr); 18869c3cf19fSMatthew G. Knepley ierr = PetscMemzero(elemMat, cpdim * sizeof(PetscScalar));CHKERRQ(ierr); 18874ef9d792SMatthew G. Knepley /* Get elemMat entries by multiplying by weight */ 18884ef9d792SMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 18899c3cf19fSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[j] += B[j*Nc + c]*qweights[ccell*qNc + c]; 18904ef9d792SMatthew G. Knepley } 18914ef9d792SMatthew G. Knepley ierr = PetscFERestoreTabulation(fe, 1, x, &B, NULL, NULL);CHKERRQ(ierr);CHKERRQ(ierr); 18924ef9d792SMatthew G. Knepley } else { 18934ef9d792SMatthew G. Knepley cpdim = 1; 18944ef9d792SMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 18959c3cf19fSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[j] += 1.0*qweights[ccell*qNc + c]; 18964ef9d792SMatthew G. Knepley } 18974ef9d792SMatthew G. Knepley } 18984ef9d792SMatthew G. Knepley /* Update interpolator */ 18999c3cf19fSMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);} 19009c3cf19fSMatthew G. Knepley if (numCIndices != cpdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of element matrix columns %D != %D", numCIndices, cpdim); 19019c3cf19fSMatthew G. Knepley ierr = MatSetValues(In, 1, &findices[i], numCIndices, cindices, elemMat, INSERT_VALUES);CHKERRQ(ierr); 19023a93e3b7SToby Isaac ierr = DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 19034ef9d792SMatthew G. Knepley } 19044ef9d792SMatthew G. Knepley ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 19053a93e3b7SToby Isaac ierr = PetscSFDestroy(&coarseCellSF);CHKERRQ(ierr); 19064ef9d792SMatthew G. Knepley ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 19074ef9d792SMatthew G. Knepley } 190846bdb399SToby Isaac ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 19094ef9d792SMatthew G. Knepley } 19104ef9d792SMatthew G. Knepley } 19114ef9d792SMatthew G. Knepley ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr); 19124ef9d792SMatthew G. Knepley ierr = PetscFree3(v0c,Jc,invJc);CHKERRQ(ierr); 19134ef9d792SMatthew G. Knepley ierr = PetscFree(elemMat);CHKERRQ(ierr); 19144ef9d792SMatthew G. Knepley ierr = MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 19154ef9d792SMatthew G. Knepley ierr = MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 191677711781SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 19174ef9d792SMatthew G. Knepley PetscFunctionReturn(0); 19184ef9d792SMatthew G. Knepley } 19194ef9d792SMatthew G. Knepley 192046fa42a0SMatthew G. Knepley /*@ 1921bd041c0cSMatthew G. Knepley DMPlexComputeMassMatrixGeneral - Form the local portion of the mass matrix M from the coarse DM to a non-nested fine DM. 1922bd041c0cSMatthew G. Knepley 1923bd041c0cSMatthew G. Knepley Input Parameters: 1924bd041c0cSMatthew G. Knepley + dmf - The fine mesh 1925bd041c0cSMatthew G. Knepley . dmc - The coarse mesh 1926bd041c0cSMatthew G. Knepley - user - The user context 1927bd041c0cSMatthew G. Knepley 1928bd041c0cSMatthew G. Knepley Output Parameter: 1929bd041c0cSMatthew G. Knepley . mass - The mass matrix 1930bd041c0cSMatthew G. Knepley 1931bd041c0cSMatthew G. Knepley Level: developer 1932bd041c0cSMatthew G. Knepley 1933bd041c0cSMatthew G. Knepley .seealso: DMPlexComputeMassMatrixNested(), DMPlexComputeInterpolatorNested(), DMPlexComputeInterpolatorGeneral(), DMPlexComputeJacobianFEM() 1934bd041c0cSMatthew G. Knepley @*/ 1935bd041c0cSMatthew G. Knepley PetscErrorCode DMPlexComputeMassMatrixGeneral(DM dmc, DM dmf, Mat mass, void *user) 1936bd041c0cSMatthew G. Knepley { 1937bd041c0cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dmf->data; 1938bd041c0cSMatthew G. Knepley const char *name = "Mass Matrix"; 1939bd041c0cSMatthew G. Knepley PetscDS prob; 1940bd041c0cSMatthew G. Knepley PetscSection fsection, csection, globalFSection, globalCSection; 1941e8f14785SLisandro Dalcin PetscHSetIJ ht; 1942bd041c0cSMatthew G. Knepley PetscLayout rLayout; 1943bd041c0cSMatthew G. Knepley PetscInt *dnz, *onz; 1944bd041c0cSMatthew G. Knepley PetscInt locRows, rStart, rEnd; 1945bd041c0cSMatthew G. Knepley PetscReal *x, *v0, *J, *invJ, detJ; 1946bd041c0cSMatthew G. Knepley PetscReal *v0c, *Jc, *invJc, detJc; 1947bd041c0cSMatthew G. Knepley PetscScalar *elemMat; 1948bd041c0cSMatthew G. Knepley PetscInt dim, Nf, field, totDim, cStart, cEnd, cell, ccell; 1949bd041c0cSMatthew G. Knepley PetscErrorCode ierr; 1950bd041c0cSMatthew G. Knepley 1951bd041c0cSMatthew G. Knepley PetscFunctionBegin; 1952bd041c0cSMatthew G. Knepley ierr = DMGetCoordinateDim(dmc, &dim);CHKERRQ(ierr); 1953bd041c0cSMatthew G. Knepley ierr = DMGetDS(dmc, &prob);CHKERRQ(ierr); 1954bd041c0cSMatthew G. Knepley ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr); 1955bd041c0cSMatthew G. Knepley ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 1956bd041c0cSMatthew G. Knepley ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 1957bd041c0cSMatthew G. Knepley ierr = PetscMalloc3(dim,&v0c,dim*dim,&Jc,dim*dim,&invJc);CHKERRQ(ierr); 1958bd041c0cSMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 1959bd041c0cSMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr); 1960bd041c0cSMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 1961bd041c0cSMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr); 1962bd041c0cSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr); 1963bd041c0cSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 1964bd041c0cSMatthew G. Knepley ierr = PetscMalloc1(totDim, &elemMat);CHKERRQ(ierr); 1965bd041c0cSMatthew G. Knepley 1966bd041c0cSMatthew G. Knepley ierr = MatGetLocalSize(mass, &locRows, NULL);CHKERRQ(ierr); 1967bd041c0cSMatthew G. Knepley ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) mass), &rLayout);CHKERRQ(ierr); 1968bd041c0cSMatthew G. Knepley ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 1969bd041c0cSMatthew G. Knepley ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 1970bd041c0cSMatthew G. Knepley ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 1971bd041c0cSMatthew G. Knepley ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 1972bd041c0cSMatthew G. Knepley ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 1973bd041c0cSMatthew G. Knepley ierr = PetscCalloc2(locRows,&dnz,locRows,&onz);CHKERRQ(ierr); 1974e8f14785SLisandro Dalcin ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr); 1975bd041c0cSMatthew G. Knepley for (field = 0; field < Nf; ++field) { 1976bd041c0cSMatthew G. Knepley PetscObject obj; 1977bd041c0cSMatthew G. Knepley PetscClassId id; 1978bd041c0cSMatthew G. Knepley PetscQuadrature quad; 1979bd041c0cSMatthew G. Knepley const PetscReal *qpoints; 1980bd041c0cSMatthew G. Knepley PetscInt Nq, Nc, i, d; 1981bd041c0cSMatthew G. Knepley 1982bd041c0cSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr); 1983bd041c0cSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1984bd041c0cSMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);} 1985bd041c0cSMatthew G. Knepley else {ierr = PetscFVGetQuadrature((PetscFV) obj, &quad);CHKERRQ(ierr);} 1986bd041c0cSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, &qpoints, NULL);CHKERRQ(ierr); 1987bd041c0cSMatthew G. Knepley /* For each fine grid cell */ 1988bd041c0cSMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 1989bd041c0cSMatthew G. Knepley Vec pointVec; 1990bd041c0cSMatthew G. Knepley PetscScalar *pV; 1991bd041c0cSMatthew G. Knepley PetscSF coarseCellSF = NULL; 1992bd041c0cSMatthew G. Knepley const PetscSFNode *coarseCells; 1993bd041c0cSMatthew G. Knepley PetscInt numCoarseCells, q, c; 1994bd041c0cSMatthew G. Knepley PetscInt *findices, *cindices; 1995bd041c0cSMatthew G. Knepley PetscInt numFIndices, numCIndices; 1996bd041c0cSMatthew G. Knepley 1997bd041c0cSMatthew G. Knepley ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 1998bd041c0cSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 1999bd041c0cSMatthew G. Knepley /* Get points from the quadrature */ 2000bd041c0cSMatthew G. Knepley ierr = VecCreateSeq(PETSC_COMM_SELF, Nq*dim, &pointVec);CHKERRQ(ierr); 2001bd041c0cSMatthew G. Knepley ierr = VecSetBlockSize(pointVec, dim);CHKERRQ(ierr); 2002bd041c0cSMatthew G. Knepley ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 2003bd041c0cSMatthew G. Knepley for (q = 0; q < Nq; ++q) { 2004c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 2005c330f8ffSToby Isaac 2006bd041c0cSMatthew G. Knepley /* Transform point to real space */ 2007c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0, J, &qpoints[q*dim], x); 2008bd041c0cSMatthew G. Knepley for (d = 0; d < dim; ++d) pV[q*dim+d] = x[d]; 2009bd041c0cSMatthew G. Knepley } 2010bd041c0cSMatthew G. Knepley ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 2011bd041c0cSMatthew G. Knepley /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */ 2012bd041c0cSMatthew G. Knepley ierr = DMLocatePoints(dmc, pointVec, DM_POINTLOCATION_NEAREST, &coarseCellSF);CHKERRQ(ierr); 2013bd041c0cSMatthew G. Knepley ierr = PetscSFViewFromOptions(coarseCellSF, NULL, "-interp_sf_view");CHKERRQ(ierr); 2014bd041c0cSMatthew G. Knepley /* Update preallocation info */ 2015bd041c0cSMatthew G. Knepley ierr = PetscSFGetGraph(coarseCellSF, NULL, &numCoarseCells, NULL, &coarseCells);CHKERRQ(ierr); 2016bd041c0cSMatthew G. Knepley if (numCoarseCells != Nq) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located"); 2017bd041c0cSMatthew G. Knepley { 2018e8f14785SLisandro Dalcin PetscHashIJKey key; 2019e8f14785SLisandro Dalcin PetscBool missing; 2020bd041c0cSMatthew G. Knepley 2021bd041c0cSMatthew G. Knepley for (i = 0; i < numFIndices; ++i) { 2022e8f14785SLisandro Dalcin key.i = findices[i]; 2023e8f14785SLisandro Dalcin if (key.i >= 0) { 2024bd041c0cSMatthew G. Knepley /* Get indices for coarse elements */ 2025bd041c0cSMatthew G. Knepley for (ccell = 0; ccell < numCoarseCells; ++ccell) { 2026bd041c0cSMatthew G. Knepley ierr = DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 2027bd041c0cSMatthew G. Knepley for (c = 0; c < numCIndices; ++c) { 2028e8f14785SLisandro Dalcin key.j = cindices[c]; 2029e8f14785SLisandro Dalcin if (key.j < 0) continue; 2030e8f14785SLisandro Dalcin ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr); 2031bd041c0cSMatthew G. Knepley if (missing) { 2032e8f14785SLisandro Dalcin if ((key.j >= rStart) && (key.j < rEnd)) ++dnz[key.i-rStart]; 2033e8f14785SLisandro Dalcin else ++onz[key.i-rStart]; 2034bd041c0cSMatthew G. Knepley } 2035bd041c0cSMatthew G. Knepley } 2036bd041c0cSMatthew G. Knepley ierr = DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 2037bd041c0cSMatthew G. Knepley } 2038bd041c0cSMatthew G. Knepley } 2039bd041c0cSMatthew G. Knepley } 2040bd041c0cSMatthew G. Knepley } 2041bd041c0cSMatthew G. Knepley ierr = PetscSFDestroy(&coarseCellSF);CHKERRQ(ierr); 2042bd041c0cSMatthew G. Knepley ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 2043bd041c0cSMatthew G. Knepley ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 2044bd041c0cSMatthew G. Knepley } 2045bd041c0cSMatthew G. Knepley } 2046e8f14785SLisandro Dalcin ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr); 2047bd041c0cSMatthew G. Knepley ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr); 2048bd041c0cSMatthew G. Knepley ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 2049bd041c0cSMatthew G. Knepley ierr = PetscFree2(dnz,onz);CHKERRQ(ierr); 2050bd041c0cSMatthew G. Knepley for (field = 0; field < Nf; ++field) { 2051bd041c0cSMatthew G. Knepley PetscObject obj; 2052bd041c0cSMatthew G. Knepley PetscClassId id; 2053bd041c0cSMatthew G. Knepley PetscQuadrature quad; 2054bd041c0cSMatthew G. Knepley PetscReal *Bfine; 2055bd041c0cSMatthew G. Knepley const PetscReal *qpoints, *qweights; 2056bd041c0cSMatthew G. Knepley PetscInt Nq, Nc, i, d; 2057bd041c0cSMatthew G. Knepley 2058bd041c0cSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr); 2059bd041c0cSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 2060bd041c0cSMatthew G. Knepley if (id == PETSCFE_CLASSID) {ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);ierr = PetscFEGetDefaultTabulation((PetscFE) obj, &Bfine, NULL, NULL);CHKERRQ(ierr);} 2061bd041c0cSMatthew G. Knepley else {ierr = PetscFVGetQuadrature((PetscFV) obj, &quad);CHKERRQ(ierr);} 2062bd041c0cSMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, &qpoints, &qweights);CHKERRQ(ierr); 2063bd041c0cSMatthew G. Knepley /* For each fine grid cell */ 2064bd041c0cSMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 2065bd041c0cSMatthew G. Knepley Vec pointVec; 2066bd041c0cSMatthew G. Knepley PetscScalar *pV; 2067bd041c0cSMatthew G. Knepley PetscSF coarseCellSF = NULL; 2068bd041c0cSMatthew G. Knepley const PetscSFNode *coarseCells; 2069bd041c0cSMatthew G. Knepley PetscInt numCoarseCells, cpdim, q, c, j; 2070bd041c0cSMatthew G. Knepley PetscInt *findices, *cindices; 2071bd041c0cSMatthew G. Knepley PetscInt numFIndices, numCIndices; 2072bd041c0cSMatthew G. Knepley 2073bd041c0cSMatthew G. Knepley ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 2074bd041c0cSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 2075bd041c0cSMatthew G. Knepley /* Get points from the quadrature */ 2076bd041c0cSMatthew G. Knepley ierr = VecCreateSeq(PETSC_COMM_SELF, Nq*dim, &pointVec);CHKERRQ(ierr); 2077bd041c0cSMatthew G. Knepley ierr = VecSetBlockSize(pointVec, dim);CHKERRQ(ierr); 2078bd041c0cSMatthew G. Knepley ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 2079bd041c0cSMatthew G. Knepley for (q = 0; q < Nq; ++q) { 2080c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 2081c330f8ffSToby Isaac 2082bd041c0cSMatthew G. Knepley /* Transform point to real space */ 2083c330f8ffSToby Isaac CoordinatesRefToReal(dim, dim, xi0, v0, J, &qpoints[q*dim], x); 2084bd041c0cSMatthew G. Knepley for (d = 0; d < dim; ++d) pV[q*dim+d] = x[d]; 2085bd041c0cSMatthew G. Knepley } 2086bd041c0cSMatthew G. Knepley ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 2087bd041c0cSMatthew G. Knepley /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */ 2088bd041c0cSMatthew G. Knepley ierr = DMLocatePoints(dmc, pointVec, DM_POINTLOCATION_NEAREST, &coarseCellSF);CHKERRQ(ierr); 2089bd041c0cSMatthew G. Knepley /* Update matrix */ 2090bd041c0cSMatthew G. Knepley ierr = PetscSFGetGraph(coarseCellSF, NULL, &numCoarseCells, NULL, &coarseCells);CHKERRQ(ierr); 2091bd041c0cSMatthew G. Knepley if (numCoarseCells != Nq) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located"); 2092bd041c0cSMatthew G. Knepley ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 2093bd041c0cSMatthew G. Knepley for (ccell = 0; ccell < numCoarseCells; ++ccell) { 2094bd041c0cSMatthew G. Knepley PetscReal pVReal[3]; 2095c330f8ffSToby Isaac const PetscReal xi0[3] = {-1., -1., -1.}; 2096c330f8ffSToby Isaac 2097bd041c0cSMatthew G. Knepley 2098bd041c0cSMatthew G. Knepley ierr = DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 2099bd041c0cSMatthew G. Knepley /* Transform points from real space to coarse reference space */ 2100bd041c0cSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dmc, coarseCells[ccell].index, NULL, v0c, Jc, invJc, &detJc);CHKERRQ(ierr); 2101bd041c0cSMatthew G. Knepley for (d = 0; d < dim; ++d) pVReal[d] = PetscRealPart(pV[ccell*dim+d]); 2102c330f8ffSToby Isaac CoordinatesRealToRef(dim, dim, xi0, v0c, invJc, pVReal, x); 2103bd041c0cSMatthew G. Knepley 2104bd041c0cSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 2105bd041c0cSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 2106bd041c0cSMatthew G. Knepley PetscReal *B; 2107bd041c0cSMatthew G. Knepley 2108bd041c0cSMatthew G. Knepley /* Evaluate coarse basis on contained point */ 2109bd041c0cSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &cpdim);CHKERRQ(ierr); 2110bd041c0cSMatthew G. Knepley ierr = PetscFEGetTabulation(fe, 1, x, &B, NULL, NULL);CHKERRQ(ierr); 2111bd041c0cSMatthew G. Knepley /* Get elemMat entries by multiplying by weight */ 2112bd041c0cSMatthew G. Knepley for (i = 0; i < numFIndices; ++i) { 2113bd041c0cSMatthew G. Knepley ierr = PetscMemzero(elemMat, cpdim * sizeof(PetscScalar));CHKERRQ(ierr); 2114bd041c0cSMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 2115bd041c0cSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[j] += B[j*Nc + c]*Bfine[(ccell*numFIndices + i)*Nc + c]*qweights[ccell*Nc + c]*detJ; 2116bd041c0cSMatthew G. Knepley } 2117bd041c0cSMatthew G. Knepley /* Update interpolator */ 2118bd041c0cSMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);} 2119bd041c0cSMatthew G. Knepley if (numCIndices != cpdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of element matrix columns %D != %D", numCIndices, cpdim); 2120bd041c0cSMatthew G. Knepley ierr = MatSetValues(mass, 1, &findices[i], numCIndices, cindices, elemMat, ADD_VALUES);CHKERRQ(ierr); 2121bd041c0cSMatthew G. Knepley } 2122bd041c0cSMatthew G. Knepley ierr = PetscFERestoreTabulation(fe, 1, x, &B, NULL, NULL);CHKERRQ(ierr);CHKERRQ(ierr); 2123bd041c0cSMatthew G. Knepley } else { 2124bd041c0cSMatthew G. Knepley cpdim = 1; 2125bd041c0cSMatthew G. Knepley for (i = 0; i < numFIndices; ++i) { 2126bd041c0cSMatthew G. Knepley ierr = PetscMemzero(elemMat, cpdim * sizeof(PetscScalar));CHKERRQ(ierr); 2127bd041c0cSMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 2128bd041c0cSMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[j] += 1.0*1.0*qweights[ccell*Nc + c]*detJ; 2129bd041c0cSMatthew G. Knepley } 2130bd041c0cSMatthew G. Knepley /* Update interpolator */ 2131bd041c0cSMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);} 2132bd041c0cSMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_SELF, "Nq: %d %d Nf: %d %d Nc: %d %d\n", ccell, Nq, i, numFIndices, j, numCIndices);CHKERRQ(ierr); 2133bd041c0cSMatthew G. Knepley if (numCIndices != cpdim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of element matrix columns %D != %D", numCIndices, cpdim); 2134bd041c0cSMatthew G. Knepley ierr = MatSetValues(mass, 1, &findices[i], numCIndices, cindices, elemMat, ADD_VALUES);CHKERRQ(ierr); 2135bd041c0cSMatthew G. Knepley } 2136bd041c0cSMatthew G. Knepley } 2137bd041c0cSMatthew G. Knepley ierr = DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell].index, &numCIndices, &cindices, NULL);CHKERRQ(ierr); 2138bd041c0cSMatthew G. Knepley } 2139bd041c0cSMatthew G. Knepley ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 2140bd041c0cSMatthew G. Knepley ierr = PetscSFDestroy(&coarseCellSF);CHKERRQ(ierr); 2141bd041c0cSMatthew G. Knepley ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 2142bd041c0cSMatthew G. Knepley ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 2143bd041c0cSMatthew G. Knepley } 2144bd041c0cSMatthew G. Knepley } 2145bd041c0cSMatthew G. Knepley ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr); 2146bd041c0cSMatthew G. Knepley ierr = PetscFree3(v0c,Jc,invJc);CHKERRQ(ierr); 2147bd041c0cSMatthew G. Knepley ierr = PetscFree(elemMat);CHKERRQ(ierr); 2148bd041c0cSMatthew G. Knepley ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2149bd041c0cSMatthew G. Knepley ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2150bd041c0cSMatthew G. Knepley PetscFunctionReturn(0); 2151bd041c0cSMatthew G. Knepley } 2152bd041c0cSMatthew G. Knepley 2153bd041c0cSMatthew G. Knepley /*@ 215446fa42a0SMatthew G. Knepley DMPlexComputeInjectorFEM - Compute a mapping from coarse unknowns to fine unknowns 215546fa42a0SMatthew G. Knepley 215646fa42a0SMatthew G. Knepley Input Parameters: 215746fa42a0SMatthew G. Knepley + dmc - The coarse mesh 215846fa42a0SMatthew G. Knepley - dmf - The fine mesh 215946fa42a0SMatthew G. Knepley - user - The user context 216046fa42a0SMatthew G. Knepley 216146fa42a0SMatthew G. Knepley Output Parameter: 216246fa42a0SMatthew G. Knepley . sc - The mapping 216346fa42a0SMatthew G. Knepley 216446fa42a0SMatthew G. Knepley Level: developer 216546fa42a0SMatthew G. Knepley 216646fa42a0SMatthew G. Knepley .seealso: DMPlexComputeInterpolatorNested(), DMPlexComputeJacobianFEM() 216746fa42a0SMatthew G. Knepley @*/ 21687c927364SMatthew G. Knepley PetscErrorCode DMPlexComputeInjectorFEM(DM dmc, DM dmf, VecScatter *sc, void *user) 21697c927364SMatthew G. Knepley { 2170e9d4ef1bSMatthew G. Knepley PetscDS prob; 21717c927364SMatthew G. Knepley PetscFE *feRef; 217297c42addSMatthew G. Knepley PetscFV *fvRef; 21737c927364SMatthew G. Knepley Vec fv, cv; 21747c927364SMatthew G. Knepley IS fis, cis; 21757c927364SMatthew G. Knepley PetscSection fsection, fglobalSection, csection, cglobalSection; 21767c927364SMatthew G. Knepley PetscInt *cmap, *cellCIndices, *cellFIndices, *cindices, *findices; 21770bd915a7SMatthew G. Knepley PetscInt cTotDim, fTotDim = 0, Nf, f, field, cStart, cEnd, cEndInterior, c, dim, d, startC, endC, offsetC, offsetF, m; 21786f3d3cbcSMatthew G. Knepley PetscBool *needAvg; 21797c927364SMatthew G. Knepley PetscErrorCode ierr; 21807c927364SMatthew G. Knepley 21817c927364SMatthew G. Knepley PetscFunctionBegin; 218275a69067SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 2183c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 21847c927364SMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 21857c927364SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 21867c927364SMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 21877c927364SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 21887c927364SMatthew G. Knepley ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 21897c927364SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 21909ac3fadcSMatthew G. Knepley ierr = DMPlexGetHybridBounds(dmc, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 21919ac3fadcSMatthew G. Knepley cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 2192e9d4ef1bSMatthew G. Knepley ierr = DMGetDS(dmc, &prob);CHKERRQ(ierr); 21936f3d3cbcSMatthew G. Knepley ierr = PetscCalloc3(Nf,&feRef,Nf,&fvRef,Nf,&needAvg);CHKERRQ(ierr); 21947c927364SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 219597c42addSMatthew G. Knepley PetscObject obj; 219697c42addSMatthew G. Knepley PetscClassId id; 2197aa7890ccSMatthew G. Knepley PetscInt fNb = 0, Nc = 0; 21987c927364SMatthew G. Knepley 219997c42addSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 220097c42addSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 220197c42addSMatthew G. Knepley if (id == PETSCFE_CLASSID) { 220297c42addSMatthew G. Knepley PetscFE fe = (PetscFE) obj; 22036f3d3cbcSMatthew G. Knepley PetscSpace sp; 22046f3d3cbcSMatthew G. Knepley PetscInt order; 220597c42addSMatthew G. Knepley 22067c927364SMatthew G. Knepley ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 22077c927364SMatthew G. Knepley ierr = PetscFEGetDimension(feRef[f], &fNb);CHKERRQ(ierr); 22087c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 22096f3d3cbcSMatthew G. Knepley ierr = PetscFEGetBasisSpace(fe, &sp);CHKERRQ(ierr); 22106f3d3cbcSMatthew G. Knepley ierr = PetscSpaceGetOrder(sp, &order);CHKERRQ(ierr); 22116f3d3cbcSMatthew G. Knepley if (!order) needAvg[f] = PETSC_TRUE; 221297c42addSMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 221397c42addSMatthew G. Knepley PetscFV fv = (PetscFV) obj; 221497c42addSMatthew G. Knepley PetscDualSpace Q; 221597c42addSMatthew G. Knepley 221697c42addSMatthew G. Knepley ierr = PetscFVRefine(fv, &fvRef[f]);CHKERRQ(ierr); 221797c42addSMatthew G. Knepley ierr = PetscFVGetDualSpace(fvRef[f], &Q);CHKERRQ(ierr); 221897c42addSMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Q, &fNb);CHKERRQ(ierr); 221997c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 22206f3d3cbcSMatthew G. Knepley needAvg[f] = PETSC_TRUE; 222197c42addSMatthew G. Knepley } 2222d172c84bSMatthew G. Knepley fTotDim += fNb; 22237c927364SMatthew G. Knepley } 2224e9d4ef1bSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 22257c927364SMatthew G. Knepley ierr = PetscMalloc1(cTotDim,&cmap);CHKERRQ(ierr); 22267c927364SMatthew G. Knepley for (field = 0, offsetC = 0, offsetF = 0; field < Nf; ++field) { 22277c927364SMatthew G. Knepley PetscFE feC; 222897c42addSMatthew G. Knepley PetscFV fvC; 22297c927364SMatthew G. Knepley PetscDualSpace QF, QC; 2230d172c84bSMatthew G. Knepley PetscInt order = -1, NcF, NcC, fpdim, cpdim; 22317c927364SMatthew G. Knepley 223297c42addSMatthew G. Knepley if (feRef[field]) { 2233e9d4ef1bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &feC);CHKERRQ(ierr); 22347c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(feC, &NcC);CHKERRQ(ierr); 22357c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(feRef[field], &NcF);CHKERRQ(ierr); 22367c927364SMatthew G. Knepley ierr = PetscFEGetDualSpace(feRef[field], &QF);CHKERRQ(ierr); 2237d172c84bSMatthew G. Knepley ierr = PetscDualSpaceGetOrder(QF, &order);CHKERRQ(ierr); 22387c927364SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QF, &fpdim);CHKERRQ(ierr); 22397c927364SMatthew G. Knepley ierr = PetscFEGetDualSpace(feC, &QC);CHKERRQ(ierr); 22407c927364SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QC, &cpdim);CHKERRQ(ierr); 224197c42addSMatthew G. Knepley } else { 224297c42addSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fvC);CHKERRQ(ierr); 224397c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fvC, &NcC);CHKERRQ(ierr); 224497c42addSMatthew G. Knepley ierr = PetscFVGetNumComponents(fvRef[field], &NcF);CHKERRQ(ierr); 224597c42addSMatthew G. Knepley ierr = PetscFVGetDualSpace(fvRef[field], &QF);CHKERRQ(ierr); 224697c42addSMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QF, &fpdim);CHKERRQ(ierr); 224797c42addSMatthew G. Knepley ierr = PetscFVGetDualSpace(fvC, &QC);CHKERRQ(ierr); 224897c42addSMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QC, &cpdim);CHKERRQ(ierr); 224997c42addSMatthew G. Knepley } 225097c42addSMatthew 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); 22517c927364SMatthew G. Knepley for (c = 0; c < cpdim; ++c) { 22527c927364SMatthew G. Knepley PetscQuadrature cfunc; 22536f3d3cbcSMatthew G. Knepley const PetscReal *cqpoints, *cqweights; 2254d172c84bSMatthew G. Knepley PetscInt NqcC, NpC; 225597c42addSMatthew G. Knepley PetscBool found = PETSC_FALSE; 22567c927364SMatthew G. Knepley 22577c927364SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(QC, c, &cfunc);CHKERRQ(ierr); 2258d172c84bSMatthew G. Knepley ierr = PetscQuadratureGetData(cfunc, NULL, &NqcC, &NpC, &cqpoints, &cqweights);CHKERRQ(ierr); 2259d172c84bSMatthew G. Knepley if (NqcC != NcC) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of quadrature components %D must match number of field components", NqcC, NcC); 226097c42addSMatthew G. Knepley if (NpC != 1 && feRef[field]) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not know how to do injection for moments"); 22617c927364SMatthew G. Knepley for (f = 0; f < fpdim; ++f) { 22627c927364SMatthew G. Knepley PetscQuadrature ffunc; 22636f3d3cbcSMatthew G. Knepley const PetscReal *fqpoints, *fqweights; 22647c927364SMatthew G. Knepley PetscReal sum = 0.0; 2265d172c84bSMatthew G. Knepley PetscInt NqcF, NpF; 22667c927364SMatthew G. Knepley 22677c927364SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(QF, f, &ffunc);CHKERRQ(ierr); 2268d172c84bSMatthew G. Knepley ierr = PetscQuadratureGetData(ffunc, NULL, &NqcF, &NpF, &fqpoints, &fqweights);CHKERRQ(ierr); 2269d172c84bSMatthew G. Knepley if (NqcF != NcF) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of quadrature components %D must match number of field components", NqcF, NcF); 22707c927364SMatthew G. Knepley if (NpC != NpF) continue; 22717c927364SMatthew G. Knepley for (d = 0; d < dim; ++d) sum += PetscAbsReal(cqpoints[d] - fqpoints[d]); 22727c927364SMatthew G. Knepley if (sum > 1.0e-9) continue; 2273d172c84bSMatthew G. Knepley for (d = 0; d < NcC; ++d) sum += PetscAbsReal(cqweights[d]*fqweights[d]); 2274d172c84bSMatthew G. Knepley if (sum < 1.0e-9) continue; 22756f3d3cbcSMatthew G. Knepley cmap[offsetC+c] = offsetF+f; 227697c42addSMatthew G. Knepley found = PETSC_TRUE; 22777c927364SMatthew G. Knepley break; 22787c927364SMatthew G. Knepley } 227997c42addSMatthew G. Knepley if (!found) { 228097c42addSMatthew G. Knepley /* TODO We really want the average here, but some asshole put VecScatter in the interface */ 2281d172c84bSMatthew G. Knepley if (fvRef[field] || (feRef[field] && order == 0)) { 2282d172c84bSMatthew G. Knepley cmap[offsetC+c] = offsetF+0; 228397c42addSMatthew G. Knepley } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate matching functional for injection"); 228497c42addSMatthew G. Knepley } 22857c927364SMatthew G. Knepley } 22866f3d3cbcSMatthew G. Knepley offsetC += cpdim; 22876f3d3cbcSMatthew G. Knepley offsetF += fpdim; 22887c927364SMatthew G. Knepley } 228997c42addSMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);ierr = PetscFVDestroy(&fvRef[f]);CHKERRQ(ierr);} 22906f3d3cbcSMatthew G. Knepley ierr = PetscFree3(feRef,fvRef,needAvg);CHKERRQ(ierr); 22917c927364SMatthew G. Knepley 22927c927364SMatthew G. Knepley ierr = DMGetGlobalVector(dmf, &fv);CHKERRQ(ierr); 22937c927364SMatthew G. Knepley ierr = DMGetGlobalVector(dmc, &cv);CHKERRQ(ierr); 22940bd915a7SMatthew G. Knepley ierr = VecGetOwnershipRange(cv, &startC, &endC);CHKERRQ(ierr); 22957c927364SMatthew G. Knepley ierr = PetscSectionGetConstrainedStorageSize(cglobalSection, &m);CHKERRQ(ierr); 22967c927364SMatthew G. Knepley ierr = PetscMalloc2(cTotDim,&cellCIndices,fTotDim,&cellFIndices);CHKERRQ(ierr); 2297aa7da3c4SMatthew G. Knepley ierr = PetscMalloc1(m,&cindices);CHKERRQ(ierr); 2298aa7da3c4SMatthew G. Knepley ierr = PetscMalloc1(m,&findices);CHKERRQ(ierr); 22997c927364SMatthew G. Knepley for (d = 0; d < m; ++d) cindices[d] = findices[d] = -1; 23007c927364SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 23017c927364SMatthew G. Knepley ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, c, cellCIndices, cellFIndices);CHKERRQ(ierr); 23027c927364SMatthew G. Knepley for (d = 0; d < cTotDim; ++d) { 23030bd915a7SMatthew G. Knepley if ((cellCIndices[d] < startC) || (cellCIndices[d] >= endC)) continue; 23047c927364SMatthew 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]]); 23057c927364SMatthew G. Knepley cindices[cellCIndices[d]-startC] = cellCIndices[d]; 23067c927364SMatthew G. Knepley findices[cellCIndices[d]-startC] = cellFIndices[cmap[d]]; 23077c927364SMatthew G. Knepley } 23087c927364SMatthew G. Knepley } 23097c927364SMatthew G. Knepley ierr = PetscFree(cmap);CHKERRQ(ierr); 23107c927364SMatthew G. Knepley ierr = PetscFree2(cellCIndices,cellFIndices);CHKERRQ(ierr); 23117c927364SMatthew G. Knepley 23127c927364SMatthew G. Knepley ierr = ISCreateGeneral(PETSC_COMM_SELF, m, cindices, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 23137c927364SMatthew G. Knepley ierr = ISCreateGeneral(PETSC_COMM_SELF, m, findices, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 23147c927364SMatthew G. Knepley ierr = VecScatterCreate(cv, cis, fv, fis, sc);CHKERRQ(ierr); 23157c927364SMatthew G. Knepley ierr = ISDestroy(&cis);CHKERRQ(ierr); 23167c927364SMatthew G. Knepley ierr = ISDestroy(&fis);CHKERRQ(ierr); 23177c927364SMatthew G. Knepley ierr = DMRestoreGlobalVector(dmf, &fv);CHKERRQ(ierr); 23187c927364SMatthew G. Knepley ierr = DMRestoreGlobalVector(dmc, &cv);CHKERRQ(ierr); 231975a69067SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 2320cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 2321cb1e1211SMatthew G Knepley } 2322*a1cf66bbSMatthew G. Knepley 2323*a1cf66bbSMatthew G. Knepley static PetscErrorCode PetscContainerUserDestroy_PetscFEGeom (void *ctx) 2324*a1cf66bbSMatthew G. Knepley { 2325*a1cf66bbSMatthew G. Knepley PetscFEGeom *geom = (PetscFEGeom *) ctx; 2326*a1cf66bbSMatthew G. Knepley PetscErrorCode ierr; 2327*a1cf66bbSMatthew G. Knepley 2328*a1cf66bbSMatthew G. Knepley PetscFunctionBegin; 2329*a1cf66bbSMatthew G. Knepley ierr = PetscFEGeomDestroy(&geom);CHKERRQ(ierr); 2330*a1cf66bbSMatthew G. Knepley PetscFunctionReturn(0); 2331*a1cf66bbSMatthew G. Knepley } 2332*a1cf66bbSMatthew G. Knepley 2333*a1cf66bbSMatthew G. Knepley PetscErrorCode DMSNESGetFEGeom(DMField coordField, IS pointIS, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom) 2334*a1cf66bbSMatthew G. Knepley { 2335*a1cf66bbSMatthew G. Knepley char composeStr[33] = {0}; 2336*a1cf66bbSMatthew G. Knepley PetscObjectId id; 2337*a1cf66bbSMatthew G. Knepley PetscContainer container; 2338*a1cf66bbSMatthew G. Knepley PetscErrorCode ierr; 2339*a1cf66bbSMatthew G. Knepley 2340*a1cf66bbSMatthew G. Knepley PetscFunctionBegin; 2341*a1cf66bbSMatthew G. Knepley ierr = PetscObjectGetId((PetscObject)quad,&id);CHKERRQ(ierr); 2342*a1cf66bbSMatthew G. Knepley ierr = PetscSNPrintf(composeStr, 32, "DMSNESGetFEGeom_%x\n", id);CHKERRQ(ierr); 2343*a1cf66bbSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) pointIS, composeStr, (PetscObject *) &container);CHKERRQ(ierr); 2344*a1cf66bbSMatthew G. Knepley if (container) { 2345*a1cf66bbSMatthew G. Knepley ierr = PetscContainerGetPointer(container, (void **) geom);CHKERRQ(ierr); 2346*a1cf66bbSMatthew G. Knepley } else { 2347*a1cf66bbSMatthew G. Knepley ierr = DMFieldCreateFEGeom(coordField, pointIS, quad, faceData, geom);CHKERRQ(ierr); 2348*a1cf66bbSMatthew G. Knepley ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr); 2349*a1cf66bbSMatthew G. Knepley ierr = PetscContainerSetPointer(container, (void *) *geom);CHKERRQ(ierr); 2350*a1cf66bbSMatthew G. Knepley ierr = PetscContainerSetUserDestroy(container, PetscContainerUserDestroy_PetscFEGeom);CHKERRQ(ierr); 2351*a1cf66bbSMatthew G. Knepley ierr = PetscObjectCompose((PetscObject) pointIS, composeStr, (PetscObject) container);CHKERRQ(ierr); 2352*a1cf66bbSMatthew G. Knepley ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 2353*a1cf66bbSMatthew G. Knepley } 2354*a1cf66bbSMatthew G. Knepley PetscFunctionReturn(0); 2355*a1cf66bbSMatthew G. Knepley } 2356*a1cf66bbSMatthew G. Knepley 2357*a1cf66bbSMatthew G. Knepley PetscErrorCode DMSNESRestoreFEGeom(DMField coordField, IS pointIS, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom) 2358*a1cf66bbSMatthew G. Knepley { 2359*a1cf66bbSMatthew G. Knepley PetscFunctionBegin; 2360*a1cf66bbSMatthew G. Knepley *geom = NULL; 2361*a1cf66bbSMatthew G. Knepley PetscFunctionReturn(0); 2362*a1cf66bbSMatthew G. Knepley } 2363*a1cf66bbSMatthew G. Knepley 2364*a1cf66bbSMatthew G. Knepley /* 2365*a1cf66bbSMatthew G. Knepley We always assemble JacP, and if the matrix is different from Jac and two different sets of point functions are provided, we also assemble Jac 2366*a1cf66bbSMatthew G. Knepley 2367*a1cf66bbSMatthew G. Knepley X - The local solution vector 2368*a1cf66bbSMatthew G. Knepley X_t - The local solution time derviative vector, or NULL 2369*a1cf66bbSMatthew G. Knepley */ 2370*a1cf66bbSMatthew G. Knepley PetscErrorCode DMPlexComputeJacobian_Patch_Internal(DM dm, PetscSection section, PetscSection globalSection, IS cellIS, 2371*a1cf66bbSMatthew G. Knepley PetscReal t, PetscReal X_tShift, Vec X, Vec X_t, Mat Jac, Mat JacP, void *ctx) 2372*a1cf66bbSMatthew G. Knepley { 2373*a1cf66bbSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 2374*a1cf66bbSMatthew G. Knepley const char *name = "Jacobian", *nameP = "JacobianPre"; 2375*a1cf66bbSMatthew G. Knepley DM dmAux = NULL; 2376*a1cf66bbSMatthew G. Knepley PetscDS prob, probAux = NULL; 2377*a1cf66bbSMatthew G. Knepley PetscSection sectionAux = NULL; 2378*a1cf66bbSMatthew G. Knepley Vec A; 2379*a1cf66bbSMatthew G. Knepley DMField coordField; 2380*a1cf66bbSMatthew G. Knepley PetscFEGeom *cgeomFEM; 2381*a1cf66bbSMatthew G. Knepley PetscQuadrature qGeom = NULL; 2382*a1cf66bbSMatthew G. Knepley Mat J = Jac, JP = JacP; 2383*a1cf66bbSMatthew G. Knepley PetscScalar *work, *u = NULL, *u_t = NULL, *a = NULL, *elemMat = NULL, *elemMatP = NULL, *elemMatD = NULL; 2384*a1cf66bbSMatthew G. Knepley PetscBool hasJac, hasPrec, hasDyn, isAffine, assembleJac, isMatIS, isMatISP, *isFE, hasFV = PETSC_FALSE; 2385*a1cf66bbSMatthew G. Knepley const PetscInt *cells; 2386*a1cf66bbSMatthew G. Knepley PetscInt Nf, fieldI, fieldJ, numCells, cStart, cEnd, numChunks, chunkSize, chunk, totDim, totDimAux = 0, sz, wsz, off = 0, offCell = 0; 2387*a1cf66bbSMatthew G. Knepley PetscErrorCode ierr; 2388*a1cf66bbSMatthew G. Knepley 2389*a1cf66bbSMatthew G. Knepley PetscFunctionBegin; 2390*a1cf66bbSMatthew G. Knepley CHKMEMQ; 2391*a1cf66bbSMatthew G. Knepley ierr = ISGetLocalSize(cellIS, &numCells);CHKERRQ(ierr); 2392*a1cf66bbSMatthew G. Knepley ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr); 2393*a1cf66bbSMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 2394*a1cf66bbSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 2395*a1cf66bbSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 2396*a1cf66bbSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 2397*a1cf66bbSMatthew G. Knepley if (dmAux) { 2398*a1cf66bbSMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 2399*a1cf66bbSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 2400*a1cf66bbSMatthew G. Knepley } 2401*a1cf66bbSMatthew G. Knepley /* Get flags */ 2402*a1cf66bbSMatthew G. Knepley ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 2403*a1cf66bbSMatthew G. Knepley ierr = DMGetWorkArray(dm, Nf, MPIU_BOOL, &isFE);CHKERRQ(ierr); 2404*a1cf66bbSMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 2405*a1cf66bbSMatthew G. Knepley PetscObject disc; 2406*a1cf66bbSMatthew G. Knepley PetscClassId id; 2407*a1cf66bbSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, &disc);CHKERRQ(ierr); 2408*a1cf66bbSMatthew G. Knepley ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 2409*a1cf66bbSMatthew G. Knepley if (id == PETSCFE_CLASSID) {isFE[fieldI] = PETSC_TRUE;} 2410*a1cf66bbSMatthew G. Knepley else if (id == PETSCFV_CLASSID) {hasFV = PETSC_TRUE; isFE[fieldI] = PETSC_FALSE;} 2411*a1cf66bbSMatthew G. Knepley } 2412*a1cf66bbSMatthew G. Knepley ierr = PetscDSHasJacobian(prob, &hasJac);CHKERRQ(ierr); 2413*a1cf66bbSMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(prob, &hasPrec);CHKERRQ(ierr); 2414*a1cf66bbSMatthew G. Knepley ierr = PetscDSHasDynamicJacobian(prob, &hasDyn);CHKERRQ(ierr); 2415*a1cf66bbSMatthew G. Knepley assembleJac = hasJac && hasPrec && (Jac != JacP) ? PETSC_TRUE : PETSC_FALSE; 2416*a1cf66bbSMatthew G. Knepley hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE; 2417*a1cf66bbSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) Jac, MATIS, &isMatIS);CHKERRQ(ierr); 2418*a1cf66bbSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) JacP, MATIS, &isMatISP);CHKERRQ(ierr); 2419*a1cf66bbSMatthew G. Knepley /* Setup input data and temp arrays (should be DMGetWorkArray) */ 2420*a1cf66bbSMatthew G. Knepley if (isMatISP || isMatISP) {ierr = DMPlexGetSubdomainSection(dm, &globalSection);CHKERRQ(ierr);} 2421*a1cf66bbSMatthew G. Knepley if (isMatIS) {ierr = MatISGetLocalMat(Jac, &J);CHKERRQ(ierr);} 2422*a1cf66bbSMatthew G. Knepley if (isMatISP) {ierr = MatISGetLocalMat(JacP, &JP);CHKERRQ(ierr);} 2423*a1cf66bbSMatthew G. Knepley if (hasFV) {ierr = MatSetOption(JP, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE);CHKERRQ(ierr);} /* No allocated space for FV stuff, so ignore the zero entries */ 2424*a1cf66bbSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 2425*a1cf66bbSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 2426*a1cf66bbSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 2427*a1cf66bbSMatthew G. Knepley if (probAux) {ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);} 2428*a1cf66bbSMatthew G. Knepley CHKMEMQ; 2429*a1cf66bbSMatthew G. Knepley /* Compute batch sizes */ 2430*a1cf66bbSMatthew G. Knepley if (isFE[0]) { 2431*a1cf66bbSMatthew G. Knepley PetscFE fe; 2432*a1cf66bbSMatthew G. Knepley PetscQuadrature q; 2433*a1cf66bbSMatthew G. Knepley PetscInt numQuadPoints, numBatches, batchSize, numBlocks, blockSize, Nb; 2434*a1cf66bbSMatthew G. Knepley 2435*a1cf66bbSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, 0, (PetscObject *) &fe);CHKERRQ(ierr); 2436*a1cf66bbSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 2437*a1cf66bbSMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 2438*a1cf66bbSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 2439*a1cf66bbSMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 2440*a1cf66bbSMatthew G. Knepley blockSize = Nb*numQuadPoints; 2441*a1cf66bbSMatthew G. Knepley batchSize = numBlocks * blockSize; 2442*a1cf66bbSMatthew G. Knepley chunkSize = numBatches * batchSize; 2443*a1cf66bbSMatthew G. Knepley numChunks = numCells / chunkSize + numCells % chunkSize; 2444*a1cf66bbSMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 2445*a1cf66bbSMatthew G. Knepley } else { 2446*a1cf66bbSMatthew G. Knepley chunkSize = numCells; 2447*a1cf66bbSMatthew G. Knepley numChunks = 1; 2448*a1cf66bbSMatthew G. Knepley } 2449*a1cf66bbSMatthew G. Knepley /* Get work space */ 2450*a1cf66bbSMatthew G. Knepley wsz = (((X?1:0) + (X_t?1:0) + (dmAux?1:0))*totDim + ((hasJac?1:0) + (hasPrec?1:0) + (hasDyn?1:0))*totDim*totDim)*chunkSize; 2451*a1cf66bbSMatthew G. Knepley ierr = DMGetWorkArray(dm, wsz, MPIU_SCALAR, &work);CHKERRQ(ierr); 2452*a1cf66bbSMatthew G. Knepley ierr = PetscMemzero(work, wsz * sizeof(PetscScalar));CHKERRQ(ierr); 2453*a1cf66bbSMatthew G. Knepley off = 0; 2454*a1cf66bbSMatthew G. Knepley u = X ? (sz = chunkSize*totDim, off += sz, work+off-sz) : NULL; 2455*a1cf66bbSMatthew G. Knepley u_t = X_t ? (sz = chunkSize*totDim, off += sz, work+off-sz) : NULL; 2456*a1cf66bbSMatthew G. Knepley a = dmAux ? (sz = chunkSize*totDimAux, off += sz, work+off-sz) : NULL; 2457*a1cf66bbSMatthew G. Knepley elemMat = hasJac ? (sz = chunkSize*totDim*totDim, off += sz, work+off-sz) : NULL; 2458*a1cf66bbSMatthew G. Knepley elemMatP = hasPrec ? (sz = chunkSize*totDim*totDim, off += sz, work+off-sz) : NULL; 2459*a1cf66bbSMatthew G. Knepley elemMatD = hasDyn ? (sz = chunkSize*totDim*totDim, off += sz, work+off-sz) : NULL; 2460*a1cf66bbSMatthew G. Knepley if (off != wsz) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error is workspace size %D should be %D", off, wsz); 2461*a1cf66bbSMatthew G. Knepley /* Setup geometry */ 2462*a1cf66bbSMatthew G. Knepley ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 2463*a1cf66bbSMatthew G. Knepley ierr = DMFieldGetFEInvariance(coordField, cellIS, NULL, &isAffine, NULL);CHKERRQ(ierr); 2464*a1cf66bbSMatthew G. Knepley if (isAffine) {ierr = DMFieldCreateDefaultQuadrature(coordField, cellIS, &qGeom);CHKERRQ(ierr);} 2465*a1cf66bbSMatthew G. Knepley if (!qGeom) { 2466*a1cf66bbSMatthew G. Knepley PetscFE fe; 2467*a1cf66bbSMatthew G. Knepley 2468*a1cf66bbSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, 0, (PetscObject *) &fe);CHKERRQ(ierr); 2469*a1cf66bbSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &qGeom);CHKERRQ(ierr); 2470*a1cf66bbSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) qGeom);CHKERRQ(ierr); 2471*a1cf66bbSMatthew G. Knepley } 2472*a1cf66bbSMatthew G. Knepley ierr = DMSNESGetFEGeom(coordField, cellIS, qGeom, PETSC_FALSE, &cgeomFEM);CHKERRQ(ierr); 2473*a1cf66bbSMatthew G. Knepley /* Compute volume integrals */ 2474*a1cf66bbSMatthew G. Knepley if (assembleJac) {ierr = MatZeroEntries(J);CHKERRQ(ierr);} 2475*a1cf66bbSMatthew G. Knepley ierr = MatZeroEntries(JP);CHKERRQ(ierr); 2476*a1cf66bbSMatthew G. Knepley for (chunk = 0; chunk < numChunks; ++chunk, offCell += chunkSize) { 2477*a1cf66bbSMatthew G. Knepley const PetscInt Ncell = PetscMin(chunkSize, numCells - offCell); 2478*a1cf66bbSMatthew G. Knepley PetscInt c; 2479*a1cf66bbSMatthew G. Knepley 2480*a1cf66bbSMatthew G. Knepley /* Extract values */ 2481*a1cf66bbSMatthew G. Knepley for (c = 0; c < Ncell; ++c) { 2482*a1cf66bbSMatthew G. Knepley const PetscInt cell = cells ? cells[c+offCell] : c+offCell; 2483*a1cf66bbSMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 2484*a1cf66bbSMatthew G. Knepley PetscInt i; 2485*a1cf66bbSMatthew G. Knepley 2486*a1cf66bbSMatthew G. Knepley if (X) { 2487*a1cf66bbSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr); 2488*a1cf66bbSMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 2489*a1cf66bbSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr); 2490*a1cf66bbSMatthew G. Knepley } 2491*a1cf66bbSMatthew G. Knepley if (X_t) { 2492*a1cf66bbSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr); 2493*a1cf66bbSMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i]; 2494*a1cf66bbSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr); 2495*a1cf66bbSMatthew G. Knepley } 2496*a1cf66bbSMatthew G. Knepley if (dmAux) { 2497*a1cf66bbSMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr); 2498*a1cf66bbSMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 2499*a1cf66bbSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr); 2500*a1cf66bbSMatthew G. Knepley } 2501*a1cf66bbSMatthew G. Knepley } 2502*a1cf66bbSMatthew G. Knepley CHKMEMQ; 2503*a1cf66bbSMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 2504*a1cf66bbSMatthew G. Knepley PetscFE fe; 2505*a1cf66bbSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 2506*a1cf66bbSMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 2507*a1cf66bbSMatthew G. Knepley if (hasJac) {ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN, fieldI, fieldJ, Ncell, cgeomFEM, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr);} 2508*a1cf66bbSMatthew G. Knepley if (hasPrec) {ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_PRE, fieldI, fieldJ, Ncell, cgeomFEM, u, u_t, probAux, a, t, X_tShift, elemMatP);CHKERRQ(ierr);} 2509*a1cf66bbSMatthew G. Knepley if (hasDyn) {ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Ncell, cgeomFEM, u, u_t, probAux, a, t, X_tShift, elemMatD);CHKERRQ(ierr);} 2510*a1cf66bbSMatthew G. Knepley } 2511*a1cf66bbSMatthew G. Knepley /* For finite volume, add the identity */ 2512*a1cf66bbSMatthew G. Knepley if (!isFE[fieldI]) { 2513*a1cf66bbSMatthew G. Knepley PetscFV fv; 2514*a1cf66bbSMatthew G. Knepley PetscInt eOffset = 0, Nc, fc, foff; 2515*a1cf66bbSMatthew G. Knepley 2516*a1cf66bbSMatthew G. Knepley ierr = PetscDSGetFieldOffset(prob, fieldI, &foff);CHKERRQ(ierr); 2517*a1cf66bbSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fv);CHKERRQ(ierr); 2518*a1cf66bbSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 2519*a1cf66bbSMatthew G. Knepley for (c = 0; c < chunkSize; ++c, eOffset += totDim*totDim) { 2520*a1cf66bbSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 2521*a1cf66bbSMatthew G. Knepley const PetscInt i = foff + fc; 2522*a1cf66bbSMatthew G. Knepley if (hasJac) {elemMat [eOffset+i*totDim+i] = 1.0;} 2523*a1cf66bbSMatthew G. Knepley if (hasPrec) {elemMatP[eOffset+i*totDim+i] = 1.0;} 2524*a1cf66bbSMatthew G. Knepley } 2525*a1cf66bbSMatthew G. Knepley } 2526*a1cf66bbSMatthew G. Knepley } 2527*a1cf66bbSMatthew G. Knepley } 2528*a1cf66bbSMatthew G. Knepley CHKMEMQ; 2529*a1cf66bbSMatthew G. Knepley /* Add contribution from X_t */ 2530*a1cf66bbSMatthew G. Knepley if (hasDyn) {for (c = 0; c < chunkSize*totDim*totDim; ++c) elemMat[c] += X_tShift*elemMatD[c];} 2531*a1cf66bbSMatthew G. Knepley /* Insert values into matrix */ 2532*a1cf66bbSMatthew G. Knepley for (c = 0; c < Ncell; ++c) { 2533*a1cf66bbSMatthew G. Knepley const PetscInt cell = cells ? cells[c+offCell] : c+offCell; 2534*a1cf66bbSMatthew G. Knepley if (mesh->printFEM > 1) { 2535*a1cf66bbSMatthew G. Knepley if (hasJac) {ierr = DMPrintCellMatrix(cell, name, totDim, totDim, &elemMat[(c-cStart)*totDim*totDim]);CHKERRQ(ierr);} 2536*a1cf66bbSMatthew G. Knepley if (hasPrec) {ierr = DMPrintCellMatrix(cell, nameP, totDim, totDim, &elemMatP[(c-cStart)*totDim*totDim]);CHKERRQ(ierr);} 2537*a1cf66bbSMatthew G. Knepley } 2538*a1cf66bbSMatthew G. Knepley if (assembleJac) {ierr = DMPlexMatSetClosure(dm, section, globalSection, Jac, cell, &elemMat[(c-cStart)*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);} 2539*a1cf66bbSMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, globalSection, JP, cell, &elemMat[(c-cStart)*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 2540*a1cf66bbSMatthew G. Knepley } 2541*a1cf66bbSMatthew G. Knepley CHKMEMQ; 2542*a1cf66bbSMatthew G. Knepley } 2543*a1cf66bbSMatthew G. Knepley /* Cleanup */ 2544*a1cf66bbSMatthew G. Knepley ierr = DMSNESRestoreFEGeom(coordField, cellIS, qGeom, PETSC_FALSE, &cgeomFEM);CHKERRQ(ierr); 2545*a1cf66bbSMatthew G. Knepley ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr); 2546*a1cf66bbSMatthew G. Knepley if (hasFV) {ierr = MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_FALSE);CHKERRQ(ierr);} 2547*a1cf66bbSMatthew G. Knepley ierr = DMRestoreWorkArray(dm, Nf, MPIU_BOOL, &isFE);CHKERRQ(ierr); 2548*a1cf66bbSMatthew G. Knepley ierr = DMRestoreWorkArray(dm, ((1 + (X_t?1:0) + (dmAux?1:0))*totDim + ((hasJac?1:0) + (hasPrec?1:0) + (hasDyn?1:0))*totDim*totDim)*chunkSize, MPIU_SCALAR, &work);CHKERRQ(ierr); 2549*a1cf66bbSMatthew G. Knepley /* Compute boundary integrals */ 2550*a1cf66bbSMatthew G. Knepley /* ierr = DMPlexComputeBdJacobian_Internal(dm, X, X_t, t, X_tShift, Jac, JacP, ctx);CHKERRQ(ierr); */ 2551*a1cf66bbSMatthew G. Knepley /* Assemble matrix */ 2552*a1cf66bbSMatthew G. Knepley if (assembleJac) {ierr = MatAssemblyBegin(Jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);ierr = MatAssemblyEnd(Jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);} 2553*a1cf66bbSMatthew G. Knepley ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2554*a1cf66bbSMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 2555*a1cf66bbSMatthew G. Knepley CHKMEMQ; 2556*a1cf66bbSMatthew G. Knepley PetscFunctionReturn(0); 2557*a1cf66bbSMatthew G. Knepley } 2558