1cb1e1211SMatthew G Knepley #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2cb1e1211SMatthew G Knepley 30f2d7e86SMatthew G. Knepley #include <petsc-private/petscfeimpl.h> 4f62f30faSMatthew G. Knepley #include <petscfv.h> 5a0845e3aSMatthew G. Knepley 6cb1e1211SMatthew G Knepley #undef __FUNCT__ 7cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexGetScale" 8cb1e1211SMatthew G Knepley PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9cb1e1211SMatthew G Knepley { 10cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 11cb1e1211SMatthew G Knepley 12cb1e1211SMatthew G Knepley PetscFunctionBegin; 13cb1e1211SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 14cb1e1211SMatthew G Knepley PetscValidPointer(scale, 3); 15cb1e1211SMatthew G Knepley *scale = mesh->scale[unit]; 16cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 17cb1e1211SMatthew G Knepley } 18cb1e1211SMatthew G Knepley 19cb1e1211SMatthew G Knepley #undef __FUNCT__ 20cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexSetScale" 21cb1e1211SMatthew G Knepley PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 22cb1e1211SMatthew G Knepley { 23cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 24cb1e1211SMatthew G Knepley 25cb1e1211SMatthew G Knepley PetscFunctionBegin; 26cb1e1211SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27cb1e1211SMatthew G Knepley mesh->scale[unit] = scale; 28cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 29cb1e1211SMatthew G Knepley } 30cb1e1211SMatthew G Knepley 31cb1e1211SMatthew G Knepley PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 32cb1e1211SMatthew G Knepley { 33cb1e1211SMatthew G Knepley switch (i) { 34cb1e1211SMatthew G Knepley case 0: 35cb1e1211SMatthew G Knepley switch (j) { 36cb1e1211SMatthew G Knepley case 0: return 0; 37cb1e1211SMatthew G Knepley case 1: 38cb1e1211SMatthew G Knepley switch (k) { 39cb1e1211SMatthew G Knepley case 0: return 0; 40cb1e1211SMatthew G Knepley case 1: return 0; 41cb1e1211SMatthew G Knepley case 2: return 1; 42cb1e1211SMatthew G Knepley } 43cb1e1211SMatthew G Knepley case 2: 44cb1e1211SMatthew G Knepley switch (k) { 45cb1e1211SMatthew G Knepley case 0: return 0; 46cb1e1211SMatthew G Knepley case 1: return -1; 47cb1e1211SMatthew G Knepley case 2: return 0; 48cb1e1211SMatthew G Knepley } 49cb1e1211SMatthew G Knepley } 50cb1e1211SMatthew G Knepley case 1: 51cb1e1211SMatthew G Knepley switch (j) { 52cb1e1211SMatthew G Knepley case 0: 53cb1e1211SMatthew G Knepley switch (k) { 54cb1e1211SMatthew G Knepley case 0: return 0; 55cb1e1211SMatthew G Knepley case 1: return 0; 56cb1e1211SMatthew G Knepley case 2: return -1; 57cb1e1211SMatthew G Knepley } 58cb1e1211SMatthew G Knepley case 1: return 0; 59cb1e1211SMatthew G Knepley case 2: 60cb1e1211SMatthew G Knepley switch (k) { 61cb1e1211SMatthew G Knepley case 0: return 1; 62cb1e1211SMatthew G Knepley case 1: return 0; 63cb1e1211SMatthew G Knepley case 2: return 0; 64cb1e1211SMatthew G Knepley } 65cb1e1211SMatthew G Knepley } 66cb1e1211SMatthew G Knepley case 2: 67cb1e1211SMatthew G Knepley switch (j) { 68cb1e1211SMatthew G Knepley case 0: 69cb1e1211SMatthew G Knepley switch (k) { 70cb1e1211SMatthew G Knepley case 0: return 0; 71cb1e1211SMatthew G Knepley case 1: return 1; 72cb1e1211SMatthew G Knepley case 2: return 0; 73cb1e1211SMatthew G Knepley } 74cb1e1211SMatthew G Knepley case 1: 75cb1e1211SMatthew G Knepley switch (k) { 76cb1e1211SMatthew G Knepley case 0: return -1; 77cb1e1211SMatthew G Knepley case 1: return 0; 78cb1e1211SMatthew G Knepley case 2: return 0; 79cb1e1211SMatthew G Knepley } 80cb1e1211SMatthew G Knepley case 2: return 0; 81cb1e1211SMatthew G Knepley } 82cb1e1211SMatthew G Knepley } 83cb1e1211SMatthew G Knepley return 0; 84cb1e1211SMatthew G Knepley } 85cb1e1211SMatthew G Knepley 86cb1e1211SMatthew G Knepley #undef __FUNCT__ 87cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexCreateRigidBody" 88cb1e1211SMatthew G Knepley /*@C 89cb1e1211SMatthew G Knepley DMPlexCreateRigidBody - create rigid body modes from coordinates 90cb1e1211SMatthew G Knepley 91cb1e1211SMatthew G Knepley Collective on DM 92cb1e1211SMatthew G Knepley 93cb1e1211SMatthew G Knepley Input Arguments: 94cb1e1211SMatthew G Knepley + dm - the DM 95cb1e1211SMatthew G Knepley . section - the local section associated with the rigid field, or NULL for the default section 96cb1e1211SMatthew G Knepley - globalSection - the global section associated with the rigid field, or NULL for the default section 97cb1e1211SMatthew G Knepley 98cb1e1211SMatthew G Knepley Output Argument: 99cb1e1211SMatthew G Knepley . sp - the null space 100cb1e1211SMatthew G Knepley 101cb1e1211SMatthew G Knepley Note: This is necessary to take account of Dirichlet conditions on the displacements 102cb1e1211SMatthew G Knepley 103cb1e1211SMatthew G Knepley Level: advanced 104cb1e1211SMatthew G Knepley 105cb1e1211SMatthew G Knepley .seealso: MatNullSpaceCreate() 106cb1e1211SMatthew G Knepley @*/ 107cb1e1211SMatthew G Knepley PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 108cb1e1211SMatthew G Knepley { 109cb1e1211SMatthew G Knepley MPI_Comm comm; 110cb1e1211SMatthew G Knepley Vec coordinates, localMode, mode[6]; 111cb1e1211SMatthew G Knepley PetscSection coordSection; 112cb1e1211SMatthew G Knepley PetscScalar *coords; 113cb1e1211SMatthew G Knepley PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 114cb1e1211SMatthew G Knepley PetscErrorCode ierr; 115cb1e1211SMatthew G Knepley 116cb1e1211SMatthew G Knepley PetscFunctionBegin; 117cb1e1211SMatthew G Knepley ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 118c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 119cb1e1211SMatthew G Knepley if (dim == 1) { 120cb1e1211SMatthew G Knepley ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 121cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 122cb1e1211SMatthew G Knepley } 123cb1e1211SMatthew G Knepley if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 124cb1e1211SMatthew G Knepley if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 125cb1e1211SMatthew G Knepley ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 126cb1e1211SMatthew G Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 12769d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 128cb1e1211SMatthew G Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 129cb1e1211SMatthew G Knepley m = (dim*(dim+1))/2; 130cb1e1211SMatthew G Knepley ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 131cb1e1211SMatthew G Knepley ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 132cb1e1211SMatthew G Knepley ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 133cb1e1211SMatthew G Knepley for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 134cb1e1211SMatthew G Knepley /* Assume P1 */ 135cb1e1211SMatthew G Knepley ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 136cb1e1211SMatthew G Knepley for (d = 0; d < dim; ++d) { 137cb1e1211SMatthew G Knepley PetscScalar values[3] = {0.0, 0.0, 0.0}; 138cb1e1211SMatthew G Knepley 139cb1e1211SMatthew G Knepley values[d] = 1.0; 140cb1e1211SMatthew G Knepley ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 141cb1e1211SMatthew G Knepley for (v = vStart; v < vEnd; ++v) { 142cb1e1211SMatthew G Knepley ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 143cb1e1211SMatthew G Knepley } 144cb1e1211SMatthew G Knepley ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 145cb1e1211SMatthew G Knepley ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 146cb1e1211SMatthew G Knepley } 147cb1e1211SMatthew G Knepley ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 148cb1e1211SMatthew G Knepley for (d = dim; d < dim*(dim+1)/2; ++d) { 149cb1e1211SMatthew G Knepley PetscInt i, j, k = dim > 2 ? d - dim : d; 150cb1e1211SMatthew G Knepley 151cb1e1211SMatthew G Knepley ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 152cb1e1211SMatthew G Knepley for (v = vStart; v < vEnd; ++v) { 153cb1e1211SMatthew G Knepley PetscScalar values[3] = {0.0, 0.0, 0.0}; 154cb1e1211SMatthew G Knepley PetscInt off; 155cb1e1211SMatthew G Knepley 156cb1e1211SMatthew G Knepley ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 157cb1e1211SMatthew G Knepley for (i = 0; i < dim; ++i) { 158cb1e1211SMatthew G Knepley for (j = 0; j < dim; ++j) { 159cb1e1211SMatthew G Knepley values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 160cb1e1211SMatthew G Knepley } 161cb1e1211SMatthew G Knepley } 162cb1e1211SMatthew G Knepley ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 163cb1e1211SMatthew G Knepley } 164cb1e1211SMatthew G Knepley ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 165cb1e1211SMatthew G Knepley ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 166cb1e1211SMatthew G Knepley } 167cb1e1211SMatthew G Knepley ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 168cb1e1211SMatthew G Knepley ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 169cb1e1211SMatthew G Knepley for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 170cb1e1211SMatthew G Knepley /* Orthonormalize system */ 171cb1e1211SMatthew G Knepley for (i = dim; i < m; ++i) { 172cb1e1211SMatthew G Knepley PetscScalar dots[6]; 173cb1e1211SMatthew G Knepley 174cb1e1211SMatthew G Knepley ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 175cb1e1211SMatthew G Knepley for (j = 0; j < i; ++j) dots[j] *= -1.0; 176cb1e1211SMatthew G Knepley ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 177cb1e1211SMatthew G Knepley ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 178cb1e1211SMatthew G Knepley } 179cb1e1211SMatthew G Knepley ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 180cb1e1211SMatthew G Knepley for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 181cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 182cb1e1211SMatthew G Knepley } 183cb1e1211SMatthew G Knepley 184cb1e1211SMatthew G Knepley #undef __FUNCT__ 185b29cfa1cSToby Isaac #define __FUNCT__ "DMPlexSetMaxProjectionHeight" 186b29cfa1cSToby Isaac /*@ 187b29cfa1cSToby Isaac DMPlexSetMaxProjectionHeight - In DMPlexProjectXXXLocal() functions, the projected values of a basis function's dofs 188b29cfa1cSToby Isaac are computed by associating the basis function with one of the mesh points in its transitively-closed support, and 189b29cfa1cSToby Isaac evaluating the dual space basis of that point. A basis function is associated with the point in its 190b29cfa1cSToby Isaac transitively-closed support whose mesh height is highest (w.r.t. DAG height), but not greater than the maximum 191b29cfa1cSToby Isaac projection height, which is set with this function. By default, the maximum projection height is zero, which means 192b29cfa1cSToby Isaac that only mesh cells are used to project basis functions. A height of one, for example, evaluates a cell-interior 193b29cfa1cSToby Isaac basis functions using its cells dual space basis, but all other basis functions with the dual space basis of a face. 194b29cfa1cSToby Isaac 195b29cfa1cSToby Isaac Input Parameters: 196b29cfa1cSToby Isaac + dm - the DMPlex object 197b29cfa1cSToby Isaac - height - the maximum projection height >= 0 198b29cfa1cSToby Isaac 199b29cfa1cSToby Isaac Level: advanced 200b29cfa1cSToby Isaac 201b29cfa1cSToby Isaac .seealso: DMPlexGetMaxProjectionHeight(), DMPlexProjectFieldLocal(), DMPlexProjectFunctionLocal(), DMPlexProjectFunctionLabelLocal() 202b29cfa1cSToby Isaac @*/ 203b29cfa1cSToby Isaac PetscErrorCode DMPlexSetMaxProjectionHeight(DM dm, PetscInt height) 204b29cfa1cSToby Isaac { 205b29cfa1cSToby Isaac DM_Plex *plex = (DM_Plex *) dm->data; 206b29cfa1cSToby Isaac 207b29cfa1cSToby Isaac PetscFunctionBegin; 208b29cfa1cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 209b29cfa1cSToby Isaac plex->maxProjectionHeight = height; 210b29cfa1cSToby Isaac PetscFunctionReturn(0); 211b29cfa1cSToby Isaac } 212b29cfa1cSToby Isaac 213b29cfa1cSToby Isaac #undef __FUNCT__ 214b29cfa1cSToby Isaac #define __FUNCT__ "DMPlexGetMaxProjectionHeight" 215b29cfa1cSToby Isaac /*@ 216b29cfa1cSToby Isaac DMPlexGetMaxProjectionHeight - Get the maximum height (w.r.t. DAG) of mesh points used to evaluate dual bases in 217b29cfa1cSToby Isaac DMPlexProjectXXXLocal() functions. 218b29cfa1cSToby Isaac 219b29cfa1cSToby Isaac Input Parameters: 220b29cfa1cSToby Isaac . dm - the DMPlex object 221b29cfa1cSToby Isaac 222b29cfa1cSToby Isaac Output Parameters: 223b29cfa1cSToby Isaac . height - the maximum projection height 224b29cfa1cSToby Isaac 225b29cfa1cSToby Isaac Level: intermediate 226b29cfa1cSToby Isaac 227b29cfa1cSToby Isaac .seealso: DMPlexSetMaxProjectionHeight(), DMPlexProjectFieldLocal(), DMPlexProjectFunctionLocal(), DMPlexProjectFunctionLabelLocal() 228b29cfa1cSToby Isaac @*/ 229b29cfa1cSToby Isaac PetscErrorCode DMPlexGetMaxProjectionHeight(DM dm, PetscInt *height) 230b29cfa1cSToby Isaac { 231b29cfa1cSToby Isaac DM_Plex *plex = (DM_Plex *) dm->data; 232b29cfa1cSToby Isaac 233b29cfa1cSToby Isaac PetscFunctionBegin; 234b29cfa1cSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 235b29cfa1cSToby Isaac *height = plex->maxProjectionHeight; 236b29cfa1cSToby Isaac PetscFunctionReturn(0); 237b29cfa1cSToby Isaac } 238b29cfa1cSToby Isaac 239b29cfa1cSToby Isaac #undef __FUNCT__ 240a18a7fb9SMatthew G. Knepley #define __FUNCT__ "DMPlexProjectFunctionLabelLocal" 241a18a7fb9SMatthew G. Knepley PetscErrorCode DMPlexProjectFunctionLabelLocal(DM dm, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscFE fe[], void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 242a18a7fb9SMatthew G. Knepley { 243*7d1dd11eSToby Isaac PetscDualSpace *sp, *cellsp; 244a18a7fb9SMatthew G. Knepley PetscSection section; 245a18a7fb9SMatthew G. Knepley PetscScalar *values; 246a18a7fb9SMatthew G. Knepley PetscReal *v0, *J, detJ; 247ad96f515SMatthew G. Knepley PetscBool *fieldActive; 248*7d1dd11eSToby Isaac PetscInt numFields, numComp, dim, spDim, totDim, numValues, pStart, pEnd, f, d, v, i, comp, maxHeight, h; 249a18a7fb9SMatthew G. Knepley PetscErrorCode ierr; 250a18a7fb9SMatthew G. Knepley 251a18a7fb9SMatthew G. Knepley PetscFunctionBegin; 252c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 253a18a7fb9SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 254a18a7fb9SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 255a18a7fb9SMatthew G. Knepley ierr = PetscMalloc3(numFields,&sp,dim,&v0,dim*dim,&J);CHKERRQ(ierr); 256*7d1dd11eSToby Isaac ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 257*7d1dd11eSToby Isaac if (maxHeight < 0 || maxHeight > dim) {SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"maximum projection height %d not in [0, %d)\n", maxHeight,dim);} 258*7d1dd11eSToby Isaac if (maxHeight > 0) { 259*7d1dd11eSToby Isaac ierr = PetscMalloc1(numFields,&cellsp);CHKERRQ(ierr); 260*7d1dd11eSToby Isaac } 261*7d1dd11eSToby Isaac for (h = 0; h <= maxHeight; h++) { 262*7d1dd11eSToby Isaac ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 263*7d1dd11eSToby Isaac if (pEnd <= pStart) continue; 264*7d1dd11eSToby Isaac totDim = 0; 265a18a7fb9SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 266*7d1dd11eSToby Isaac if (!h) { 267*7d1dd11eSToby Isaac ierr = PetscFEGetDualSpace(fe[f], &cellsp[f]);CHKERRQ(ierr); 268*7d1dd11eSToby Isaac sp[f] = cellsp[f]; 269*7d1dd11eSToby Isaac } 270*7d1dd11eSToby Isaac else { 271*7d1dd11eSToby Isaac ierr = PetscDualSpaceGetHeightSubspace(cellsp[f], h, &sp[f]);CHKERRQ(ierr); 272*7d1dd11eSToby Isaac if (!sp[f]) continue; 273*7d1dd11eSToby Isaac } 274a18a7fb9SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe[f], &numComp);CHKERRQ(ierr); 275a18a7fb9SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 276a18a7fb9SMatthew G. Knepley totDim += spDim*numComp; 277a18a7fb9SMatthew G. Knepley } 278*7d1dd11eSToby Isaac ierr = DMPlexVecGetClosure(dm, section, localX, pStart, &numValues, NULL);CHKERRQ(ierr); 279*7d1dd11eSToby Isaac if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section point closure size %d != dual space dimension %d", numValues, totDim); 280a18a7fb9SMatthew G. Knepley ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 281ad96f515SMatthew G. Knepley ierr = DMGetWorkArray(dm, numFields, PETSC_BOOL, &fieldActive);CHKERRQ(ierr); 282ad96f515SMatthew G. Knepley for (f = 0; f < numFields; ++f) fieldActive[f] = funcs[f] ? PETSC_TRUE : PETSC_FALSE; 283a18a7fb9SMatthew G. Knepley for (i = 0; i < numIds; ++i) { 284a18a7fb9SMatthew G. Knepley IS pointIS; 285a18a7fb9SMatthew G. Knepley const PetscInt *points; 286a18a7fb9SMatthew G. Knepley PetscInt n, p; 287a18a7fb9SMatthew G. Knepley 288a18a7fb9SMatthew G. Knepley ierr = DMLabelGetStratumIS(label, ids[i], &pointIS);CHKERRQ(ierr); 289a18a7fb9SMatthew G. Knepley ierr = ISGetLocalSize(pointIS, &n);CHKERRQ(ierr); 290a18a7fb9SMatthew G. Knepley ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 291a18a7fb9SMatthew G. Knepley for (p = 0; p < n; ++p) { 292a18a7fb9SMatthew G. Knepley const PetscInt point = points[p]; 293a18a7fb9SMatthew G. Knepley PetscCellGeometry geom; 294a18a7fb9SMatthew G. Knepley 295*7d1dd11eSToby Isaac if ((point < pStart) || (point >= pEnd)) continue; 2968e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, point, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 297a18a7fb9SMatthew G. Knepley geom.v0 = v0; 298a18a7fb9SMatthew G. Knepley geom.J = J; 299a18a7fb9SMatthew G. Knepley geom.detJ = &detJ; 300a18a7fb9SMatthew G. Knepley for (f = 0, v = 0; f < numFields; ++f) { 301a18a7fb9SMatthew G. Knepley void * const ctx = ctxs ? ctxs[f] : NULL; 302*7d1dd11eSToby Isaac if (!sp[f]) continue; 303a18a7fb9SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe[f], &numComp);CHKERRQ(ierr); 304a18a7fb9SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 305a18a7fb9SMatthew G. Knepley for (d = 0; d < spDim; ++d) { 306a18a7fb9SMatthew G. Knepley if (funcs[f]) { 307a18a7fb9SMatthew G. Knepley ierr = PetscDualSpaceApply(sp[f], d, geom, numComp, funcs[f], ctx, &values[v]);CHKERRQ(ierr); 308a18a7fb9SMatthew G. Knepley } else { 309a18a7fb9SMatthew G. Knepley for (comp = 0; comp < numComp; ++comp) values[v+comp] = 0.0; 310a18a7fb9SMatthew G. Knepley } 311a18a7fb9SMatthew G. Knepley v += numComp; 312a18a7fb9SMatthew G. Knepley } 313a18a7fb9SMatthew G. Knepley } 314ad96f515SMatthew G. Knepley ierr = DMPlexVecSetFieldClosure_Internal(dm, section, localX, fieldActive, point, values, mode);CHKERRQ(ierr); 315a18a7fb9SMatthew G. Knepley } 316a18a7fb9SMatthew G. Knepley ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 317a18a7fb9SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 318a18a7fb9SMatthew G. Knepley } 319*7d1dd11eSToby Isaac if (h) { 320*7d1dd11eSToby Isaac for (f = 0; f < numFields; ++f) {ierr = PetscDualSpaceDestroy(&sp[f]);CHKERRQ(ierr);} 321*7d1dd11eSToby Isaac } 322*7d1dd11eSToby Isaac } 323a18a7fb9SMatthew G. Knepley ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 324ad96f515SMatthew G. Knepley ierr = DMRestoreWorkArray(dm, numFields, PETSC_BOOL, &fieldActive);CHKERRQ(ierr); 325a18a7fb9SMatthew G. Knepley ierr = PetscFree3(sp,v0,J);CHKERRQ(ierr); 326*7d1dd11eSToby Isaac if (maxHeight > 0) { 327*7d1dd11eSToby Isaac ierr = PetscFree(cellsp);CHKERRQ(ierr); 328*7d1dd11eSToby Isaac } 329a18a7fb9SMatthew G. Knepley PetscFunctionReturn(0); 330a18a7fb9SMatthew G. Knepley } 331a18a7fb9SMatthew G. Knepley 332a18a7fb9SMatthew G. Knepley #undef __FUNCT__ 333cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexProjectFunctionLocal" 3340f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexProjectFunctionLocal(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 335cb1e1211SMatthew G Knepley { 336*7d1dd11eSToby Isaac PetscDualSpace *sp, *cellsp; 33772f94c41SMatthew G. Knepley PetscSection section; 33872f94c41SMatthew G. Knepley PetscScalar *values; 33972f94c41SMatthew G. Knepley PetscReal *v0, *J, detJ; 340*7d1dd11eSToby Isaac PetscInt numFields, numComp, dim, spDim, totDim, numValues, pStart, pEnd, p, f, d, v, comp, h, maxHeight; 341cb1e1211SMatthew G Knepley PetscErrorCode ierr; 342cb1e1211SMatthew G Knepley 343cb1e1211SMatthew G Knepley PetscFunctionBegin; 344cb1e1211SMatthew G Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 34572f94c41SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 346785e854fSJed Brown ierr = PetscMalloc1(numFields, &sp);CHKERRQ(ierr); 347*7d1dd11eSToby Isaac ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 348*7d1dd11eSToby Isaac ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 349*7d1dd11eSToby Isaac if (maxHeight < 0 || maxHeight > dim) {SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"maximum projection height %d not in [0, %d)\n", maxHeight,dim);} 350*7d1dd11eSToby Isaac if (maxHeight > 0) { 351*7d1dd11eSToby Isaac ierr = PetscMalloc1(numFields,&cellsp);CHKERRQ(ierr); 352*7d1dd11eSToby Isaac } 353*7d1dd11eSToby Isaac ierr = PetscMalloc2(dim,&v0,dim*dim,&J);CHKERRQ(ierr); 354*7d1dd11eSToby Isaac for (h = 0; h <= maxHeight; h++) { 355*7d1dd11eSToby Isaac ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 356*7d1dd11eSToby Isaac if (pStart <= pEnd) continue; 357*7d1dd11eSToby Isaac totDim = 0; 35872f94c41SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 3590f2d7e86SMatthew G. Knepley PetscFE fe; 3600f2d7e86SMatthew G. Knepley 3610f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 362*7d1dd11eSToby Isaac if (!h) { 363*7d1dd11eSToby Isaac ierr = PetscFEGetDualSpace(fe, &cellsp[f]);CHKERRQ(ierr); 364*7d1dd11eSToby Isaac sp[f] = cellsp[f]; 365*7d1dd11eSToby Isaac } 366*7d1dd11eSToby Isaac else { 367*7d1dd11eSToby Isaac ierr = PetscDualSpaceGetHeightSubspace(cellsp[f], h, &sp[f]);CHKERRQ(ierr); 368*7d1dd11eSToby Isaac if (!sp[f]) { 369*7d1dd11eSToby Isaac continue; 370*7d1dd11eSToby Isaac } 371*7d1dd11eSToby Isaac } 3720f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &numComp);CHKERRQ(ierr); 37372f94c41SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 37472f94c41SMatthew G. Knepley totDim += spDim*numComp; 375cb1e1211SMatthew G Knepley } 376*7d1dd11eSToby Isaac ierr = DMPlexVecGetClosure(dm, section, localX, pStart, &numValues, NULL);CHKERRQ(ierr); 377*7d1dd11eSToby Isaac if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section point closure size %d != dual space dimension %d", numValues, totDim); 37872f94c41SMatthew G. Knepley ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 379*7d1dd11eSToby Isaac for (p = pStart; p < pEnd; ++p) { 38072f94c41SMatthew G. Knepley PetscCellGeometry geom; 381cb1e1211SMatthew G Knepley 382*7d1dd11eSToby Isaac ierr = DMPlexComputeCellGeometryFEM(dm, p, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 38372f94c41SMatthew G. Knepley geom.v0 = v0; 38472f94c41SMatthew G. Knepley geom.J = J; 38572f94c41SMatthew G. Knepley geom.detJ = &detJ; 38672f94c41SMatthew G. Knepley for (f = 0, v = 0; f < numFields; ++f) { 3870f2d7e86SMatthew G. Knepley PetscFE fe; 388c110b1eeSGeoffrey Irving void * const ctx = ctxs ? ctxs[f] : NULL; 3890f2d7e86SMatthew G. Knepley 390*7d1dd11eSToby Isaac if (!sp[f]) continue; 3910f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 3920f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &numComp);CHKERRQ(ierr); 39372f94c41SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 39472f94c41SMatthew G. Knepley for (d = 0; d < spDim; ++d) { 395120386c5SMatthew G. Knepley if (funcs[f]) { 396c110b1eeSGeoffrey Irving ierr = PetscDualSpaceApply(sp[f], d, geom, numComp, funcs[f], ctx, &values[v]);CHKERRQ(ierr); 397120386c5SMatthew G. Knepley } else { 398120386c5SMatthew G. Knepley for (comp = 0; comp < numComp; ++comp) values[v+comp] = 0.0; 399120386c5SMatthew G. Knepley } 40072f94c41SMatthew G. Knepley v += numComp; 401cb1e1211SMatthew G Knepley } 402cb1e1211SMatthew G Knepley } 403*7d1dd11eSToby Isaac ierr = DMPlexVecSetClosure(dm, section, localX, p, values, mode);CHKERRQ(ierr); 404cb1e1211SMatthew G Knepley } 40572f94c41SMatthew G. Knepley ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 406*7d1dd11eSToby Isaac if (h) { 407*7d1dd11eSToby Isaac for (f = 0; f < numFields; f++) {ierr = PetscDualSpaceDestroy(&sp[f]);CHKERRQ(ierr);} 408*7d1dd11eSToby Isaac } 409*7d1dd11eSToby Isaac } 4101f2da991SMatthew G. Knepley ierr = PetscFree2(v0,J);CHKERRQ(ierr); 41172f94c41SMatthew G. Knepley ierr = PetscFree(sp);CHKERRQ(ierr); 412*7d1dd11eSToby Isaac if (maxHeight > 0) { 413*7d1dd11eSToby Isaac ierr = PetscFree(cellsp);CHKERRQ(ierr); 414*7d1dd11eSToby Isaac } 415cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 416cb1e1211SMatthew G Knepley } 417cb1e1211SMatthew G Knepley 418cb1e1211SMatthew G Knepley #undef __FUNCT__ 419cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexProjectFunction" 420cb1e1211SMatthew G Knepley /*@C 421cb1e1211SMatthew G Knepley DMPlexProjectFunction - This projects the given function into the function space provided. 422cb1e1211SMatthew G Knepley 423cb1e1211SMatthew G Knepley Input Parameters: 424cb1e1211SMatthew G Knepley + dm - The DM 42572f94c41SMatthew G. Knepley . funcs - The coordinate functions to evaluate, one per field 426c110b1eeSGeoffrey Irving . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 427cb1e1211SMatthew G Knepley - mode - The insertion mode for values 428cb1e1211SMatthew G Knepley 429cb1e1211SMatthew G Knepley Output Parameter: 430cb1e1211SMatthew G Knepley . X - vector 431cb1e1211SMatthew G Knepley 432cb1e1211SMatthew G Knepley Level: developer 433cb1e1211SMatthew G Knepley 434878cb397SSatish Balay .seealso: DMPlexComputeL2Diff() 435878cb397SSatish Balay @*/ 4360f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexProjectFunction(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 437cb1e1211SMatthew G Knepley { 438cb1e1211SMatthew G Knepley Vec localX; 439cb1e1211SMatthew G Knepley PetscErrorCode ierr; 440cb1e1211SMatthew G Knepley 441cb1e1211SMatthew G Knepley PetscFunctionBegin; 4429a800dd8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 443cb1e1211SMatthew G Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 4440f2d7e86SMatthew G. Knepley ierr = DMPlexProjectFunctionLocal(dm, funcs, ctxs, mode, localX);CHKERRQ(ierr); 445cb1e1211SMatthew G Knepley ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 446cb1e1211SMatthew G Knepley ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 447cb1e1211SMatthew G Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 448cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 449cb1e1211SMatthew G Knepley } 450cb1e1211SMatthew G Knepley 45155f2e967SMatthew G. Knepley #undef __FUNCT__ 4520f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexProjectFieldLocal" 4533bc3b0a0SMatthew G. Knepley PetscErrorCode DMPlexProjectFieldLocal(DM dm, Vec localU, void (**funcs)(const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscReal [], PetscScalar []), InsertMode mode, Vec localX) 4540f2d7e86SMatthew G. Knepley { 4550f2d7e86SMatthew G. Knepley DM dmAux; 4562764a2aaSMatthew G. Knepley PetscDS prob, probAux; 4570f2d7e86SMatthew G. Knepley Vec A; 458326413afSMatthew G. Knepley PetscSection section, sectionAux; 459326413afSMatthew G. Knepley PetscScalar *values, *u, *u_x, *a, *a_x; 4600f2d7e86SMatthew G. Knepley PetscReal *x, *v0, *J, *invJ, detJ, **basisField, **basisFieldDer, **basisFieldAux, **basisFieldDerAux; 461326413afSMatthew G. Knepley PetscInt Nf, dim, spDim, totDim, numValues, cStart, cEnd, c, f, d, v, comp; 4620f2d7e86SMatthew G. Knepley PetscErrorCode ierr; 4630f2d7e86SMatthew G. Knepley 4640f2d7e86SMatthew G. Knepley PetscFunctionBegin; 4652764a2aaSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 466c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4670f2d7e86SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4680f2d7e86SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4690f2d7e86SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4702764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 4712764a2aaSMatthew G. Knepley ierr = PetscDSGetTabulation(prob, &basisField, &basisFieldDer);CHKERRQ(ierr); 4722764a2aaSMatthew G. Knepley ierr = PetscDSGetEvaluationArrays(prob, &u, NULL, &u_x);CHKERRQ(ierr); 4732764a2aaSMatthew G. Knepley ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr); 4740f2d7e86SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 4750f2d7e86SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 4760f2d7e86SMatthew G. Knepley if (dmAux) { 4772764a2aaSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 478326413afSMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 4792764a2aaSMatthew G. Knepley ierr = PetscDSGetTabulation(prob, &basisFieldAux, &basisFieldDerAux);CHKERRQ(ierr); 4802764a2aaSMatthew G. Knepley ierr = PetscDSGetEvaluationArrays(probAux, &a, NULL, &a_x);CHKERRQ(ierr); 4810f2d7e86SMatthew G. Knepley } 4820f2d7e86SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesFEM(dm, localU);CHKERRQ(ierr); 4830f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, localX, cStart, &numValues, NULL);CHKERRQ(ierr); 4840f2d7e86SMatthew G. Knepley if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section cell closure size %d != dual space dimension %d", numValues, totDim); 4850f2d7e86SMatthew G. Knepley ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 4860f2d7e86SMatthew G. Knepley ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 4870f2d7e86SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 488326413afSMatthew G. Knepley PetscScalar *coefficients = NULL, *coefficientsAux = NULL; 489326413afSMatthew G. Knepley 4908e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 491326413afSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, localU, c, NULL, &coefficients);CHKERRQ(ierr); 492326413afSMatthew G. Knepley if (dmAux) {ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &coefficientsAux);CHKERRQ(ierr);} 4930f2d7e86SMatthew G. Knepley for (f = 0, v = 0; f < Nf; ++f) { 4943113607cSMatthew G. Knepley PetscFE fe; 4953113607cSMatthew G. Knepley PetscDualSpace sp; 4963113607cSMatthew G. Knepley PetscInt Ncf; 4973113607cSMatthew G. Knepley 4982764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 4993113607cSMatthew G. Knepley ierr = PetscFEGetDualSpace(fe, &sp);CHKERRQ(ierr); 5003113607cSMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Ncf);CHKERRQ(ierr); 5013113607cSMatthew G. Knepley ierr = PetscDualSpaceGetDimension(sp, &spDim);CHKERRQ(ierr); 5020f2d7e86SMatthew G. Knepley for (d = 0; d < spDim; ++d) { 5030f2d7e86SMatthew G. Knepley PetscQuadrature quad; 5040f2d7e86SMatthew G. Knepley const PetscReal *points, *weights; 5050f2d7e86SMatthew G. Knepley PetscInt numPoints, q; 5060f2d7e86SMatthew G. Knepley 5070f2d7e86SMatthew G. Knepley if (funcs[f]) { 5083113607cSMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(sp, d, &quad);CHKERRQ(ierr); 5090f2d7e86SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numPoints, &points, &weights);CHKERRQ(ierr); 5103113607cSMatthew G. Knepley ierr = PetscFEGetTabulation(fe, numPoints, points, &basisField[f], &basisFieldDer[f], NULL);CHKERRQ(ierr); 5110f2d7e86SMatthew G. Knepley for (q = 0; q < numPoints; ++q) { 5120f2d7e86SMatthew G. Knepley CoordinatesRefToReal(dim, dim, v0, J, &points[q*dim], x); 513326413afSMatthew G. Knepley ierr = EvaluateFieldJets(prob, PETSC_FALSE, q, invJ, coefficients, NULL, u, u_x, NULL);CHKERRQ(ierr); 514326413afSMatthew G. Knepley ierr = EvaluateFieldJets(probAux, PETSC_FALSE, q, invJ, coefficientsAux, NULL, a, a_x, NULL);CHKERRQ(ierr); 5153bc3b0a0SMatthew G. Knepley (*funcs[f])(u, NULL, u_x, a, NULL, a_x, x, &values[v]); 5160f2d7e86SMatthew G. Knepley } 5173113607cSMatthew G. Knepley ierr = PetscFERestoreTabulation(fe, numPoints, points, &basisField[f], &basisFieldDer[f], NULL);CHKERRQ(ierr); 5180f2d7e86SMatthew G. Knepley } else { 5190f2d7e86SMatthew G. Knepley for (comp = 0; comp < Ncf; ++comp) values[v+comp] = 0.0; 5200f2d7e86SMatthew G. Knepley } 5210f2d7e86SMatthew G. Knepley v += Ncf; 5220f2d7e86SMatthew G. Knepley } 5230f2d7e86SMatthew G. Knepley } 524326413afSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, localU, c, NULL, &coefficients);CHKERRQ(ierr); 525326413afSMatthew G. Knepley if (dmAux) {ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &coefficientsAux);CHKERRQ(ierr);} 5260f2d7e86SMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, section, localX, c, values, mode);CHKERRQ(ierr); 5270f2d7e86SMatthew G. Knepley } 5280f2d7e86SMatthew G. Knepley ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 5290f2d7e86SMatthew G. Knepley ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr); 5300f2d7e86SMatthew G. Knepley PetscFunctionReturn(0); 5310f2d7e86SMatthew G. Knepley } 5320f2d7e86SMatthew G. Knepley 5330f2d7e86SMatthew G. Knepley #undef __FUNCT__ 5340f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexProjectField" 5350f2d7e86SMatthew G. Knepley /*@C 5360f2d7e86SMatthew G. Knepley DMPlexProjectField - This projects the given function of the fields into the function space provided. 5370f2d7e86SMatthew G. Knepley 5380f2d7e86SMatthew G. Knepley Input Parameters: 5390f2d7e86SMatthew G. Knepley + dm - The DM 5400f2d7e86SMatthew G. Knepley . U - The input field vector 5410f2d7e86SMatthew G. Knepley . funcs - The functions to evaluate, one per field 5420f2d7e86SMatthew G. Knepley - mode - The insertion mode for values 5430f2d7e86SMatthew G. Knepley 5440f2d7e86SMatthew G. Knepley Output Parameter: 5450f2d7e86SMatthew G. Knepley . X - The output vector 5460f2d7e86SMatthew G. Knepley 5470f2d7e86SMatthew G. Knepley Level: developer 5480f2d7e86SMatthew G. Knepley 5490f2d7e86SMatthew G. Knepley .seealso: DMPlexProjectFunction(), DMPlexComputeL2Diff() 5500f2d7e86SMatthew G. Knepley @*/ 5513bc3b0a0SMatthew G. Knepley PetscErrorCode DMPlexProjectField(DM dm, Vec U, void (**funcs)(const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscReal [], PetscScalar []), InsertMode mode, Vec X) 5520f2d7e86SMatthew G. Knepley { 5530f2d7e86SMatthew G. Knepley Vec localX, localU; 5540f2d7e86SMatthew G. Knepley PetscErrorCode ierr; 5550f2d7e86SMatthew G. Knepley 5560f2d7e86SMatthew G. Knepley PetscFunctionBegin; 5570f2d7e86SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5580f2d7e86SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 5590f2d7e86SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localU);CHKERRQ(ierr); 5600f2d7e86SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, U, INSERT_VALUES, localU);CHKERRQ(ierr); 5610f2d7e86SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, U, INSERT_VALUES, localU);CHKERRQ(ierr); 5623113607cSMatthew G. Knepley ierr = DMPlexProjectFieldLocal(dm, localU, funcs, mode, localX);CHKERRQ(ierr); 5630f2d7e86SMatthew G. Knepley ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 5640f2d7e86SMatthew G. Knepley ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 5650f2d7e86SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 5660f2d7e86SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localU);CHKERRQ(ierr); 5670f2d7e86SMatthew G. Knepley PetscFunctionReturn(0); 5680f2d7e86SMatthew G. Knepley } 5690f2d7e86SMatthew G. Knepley 5700f2d7e86SMatthew G. Knepley #undef __FUNCT__ 5713351dd3dSMatthew G. Knepley #define __FUNCT__ "DMPlexInsertBoundaryValuesFEM" 5723351dd3dSMatthew G. Knepley PetscErrorCode DMPlexInsertBoundaryValuesFEM(DM dm, Vec localX) 57355f2e967SMatthew G. Knepley { 57455f2e967SMatthew G. Knepley void (**funcs)(const PetscReal x[], PetscScalar *u, void *ctx); 57555f2e967SMatthew G. Knepley void **ctxs; 57655f2e967SMatthew G. Knepley PetscFE *fe; 57755f2e967SMatthew G. Knepley PetscInt numFields, f, numBd, b; 57855f2e967SMatthew G. Knepley PetscErrorCode ierr; 57955f2e967SMatthew G. Knepley 58055f2e967SMatthew G. Knepley PetscFunctionBegin; 58155f2e967SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58255f2e967SMatthew G. Knepley PetscValidHeaderSpecific(localX, VEC_CLASSID, 2); 58355f2e967SMatthew G. Knepley ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 58455f2e967SMatthew G. Knepley ierr = PetscMalloc3(numFields,&fe,numFields,&funcs,numFields,&ctxs);CHKERRQ(ierr); 58555f2e967SMatthew G. Knepley for (f = 0; f < numFields; ++f) {ierr = DMGetField(dm, f, (PetscObject *) &fe[f]);CHKERRQ(ierr);} 58655f2e967SMatthew G. Knepley /* OPT: Could attempt to do multiple BCs at once */ 58755f2e967SMatthew G. Knepley ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 58855f2e967SMatthew G. Knepley for (b = 0; b < numBd; ++b) { 589a18a7fb9SMatthew G. Knepley DMLabel label; 59055f2e967SMatthew G. Knepley const PetscInt *ids; 59163d5297fSMatthew G. Knepley const char *labelname; 59255f2e967SMatthew G. Knepley PetscInt numids, field; 59355f2e967SMatthew G. Knepley PetscBool isEssential; 59455f2e967SMatthew G. Knepley void (*func)(); 59555f2e967SMatthew G. Knepley void *ctx; 59655f2e967SMatthew G. Knepley 59763d5297fSMatthew G. Knepley ierr = DMPlexGetBoundary(dm, b, &isEssential, NULL, &labelname, &field, &func, &numids, &ids, &ctx);CHKERRQ(ierr); 59863d5297fSMatthew G. Knepley ierr = DMPlexGetLabel(dm, labelname, &label);CHKERRQ(ierr); 59955f2e967SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 60055f2e967SMatthew G. Knepley funcs[f] = field == f ? (void (*)(const PetscReal[], PetscScalar *, void *)) func : NULL; 60155f2e967SMatthew G. Knepley ctxs[f] = field == f ? ctx : NULL; 60255f2e967SMatthew G. Knepley } 603a18a7fb9SMatthew G. Knepley ierr = DMPlexProjectFunctionLabelLocal(dm, label, numids, ids, fe, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 60455f2e967SMatthew G. Knepley } 60555f2e967SMatthew G. Knepley ierr = PetscFree3(fe,funcs,ctxs);CHKERRQ(ierr); 60655f2e967SMatthew G. Knepley PetscFunctionReturn(0); 60755f2e967SMatthew G. Knepley } 60855f2e967SMatthew G. Knepley 609cb1e1211SMatthew G Knepley #undef __FUNCT__ 610cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexComputeL2Diff" 611cb1e1211SMatthew G Knepley /*@C 612cb1e1211SMatthew G Knepley DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 613cb1e1211SMatthew G Knepley 614cb1e1211SMatthew G Knepley Input Parameters: 615cb1e1211SMatthew G Knepley + dm - The DM 616cb1e1211SMatthew G Knepley . funcs - The functions to evaluate for each field component 61751259fa3SMatthew G. Knepley . ctxs - Optional array of contexts to pass to each function, or NULL. 618cb1e1211SMatthew G Knepley - X - The coefficient vector u_h 619cb1e1211SMatthew G Knepley 620cb1e1211SMatthew G Knepley Output Parameter: 621cb1e1211SMatthew G Knepley . diff - The diff ||u - u_h||_2 622cb1e1211SMatthew G Knepley 623cb1e1211SMatthew G Knepley Level: developer 624cb1e1211SMatthew G Knepley 62523d86601SMatthew G. Knepley .seealso: DMPlexProjectFunction(), DMPlexComputeL2GradientDiff() 626878cb397SSatish Balay @*/ 6270f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeL2Diff(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 628cb1e1211SMatthew G Knepley { 629cb1e1211SMatthew G Knepley const PetscInt debug = 0; 630cb1e1211SMatthew G Knepley PetscSection section; 631c5bbbd5bSMatthew G. Knepley PetscQuadrature quad; 632cb1e1211SMatthew G Knepley Vec localX; 63372f94c41SMatthew G. Knepley PetscScalar *funcVal; 634cb1e1211SMatthew G Knepley PetscReal *coords, *v0, *J, *invJ, detJ; 635cb1e1211SMatthew G Knepley PetscReal localDiff = 0.0; 636cb1e1211SMatthew G Knepley PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 637cb1e1211SMatthew G Knepley PetscErrorCode ierr; 638cb1e1211SMatthew G Knepley 639cb1e1211SMatthew G Knepley PetscFunctionBegin; 640c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 641cb1e1211SMatthew G Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 642cb1e1211SMatthew G Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 643cb1e1211SMatthew G Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 644cb1e1211SMatthew G Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 645cb1e1211SMatthew G Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 646cb1e1211SMatthew G Knepley for (field = 0; field < numFields; ++field) { 6470f2d7e86SMatthew G. Knepley PetscFE fe; 648c5bbbd5bSMatthew G. Knepley PetscInt Nc; 649c5bbbd5bSMatthew G. Knepley 6500f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 6510f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 6520f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 653c5bbbd5bSMatthew G. Knepley numComponents += Nc; 654cb1e1211SMatthew G Knepley } 6550f2d7e86SMatthew G. Knepley ierr = DMPlexProjectFunctionLocal(dm, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 656dcca6d9dSJed Brown ierr = PetscMalloc5(numComponents,&funcVal,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 657cb1e1211SMatthew G Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 658cb1e1211SMatthew G Knepley for (c = cStart; c < cEnd; ++c) { 659a1e44745SMatthew G. Knepley PetscScalar *x = NULL; 660cb1e1211SMatthew G Knepley PetscReal elemDiff = 0.0; 661cb1e1211SMatthew G Knepley 6628e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 663cb1e1211SMatthew G Knepley if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 664cb1e1211SMatthew G Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 665cb1e1211SMatthew G Knepley 666cb1e1211SMatthew G Knepley for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 6670f2d7e86SMatthew G. Knepley PetscFE fe; 668c110b1eeSGeoffrey Irving void * const ctx = ctxs ? ctxs[field] : NULL; 66921454ff5SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 670c5bbbd5bSMatthew G. Knepley PetscReal *basis; 67121454ff5SMatthew G. Knepley PetscInt numQuadPoints, numBasisFuncs, numBasisComps, q, d, e, fc, f; 672cb1e1211SMatthew G Knepley 6730f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 67421454ff5SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 6750f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &numBasisFuncs);CHKERRQ(ierr); 6760f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &numBasisComps);CHKERRQ(ierr); 6770f2d7e86SMatthew G. Knepley ierr = PetscFEGetDefaultTabulation(fe, &basis, NULL, NULL);CHKERRQ(ierr); 678cb1e1211SMatthew G Knepley if (debug) { 679cb1e1211SMatthew G Knepley char title[1024]; 680cb1e1211SMatthew G Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 681cb1e1211SMatthew G Knepley ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 682cb1e1211SMatthew G Knepley } 683cb1e1211SMatthew G Knepley for (q = 0; q < numQuadPoints; ++q) { 684cb1e1211SMatthew G Knepley for (d = 0; d < dim; d++) { 685cb1e1211SMatthew G Knepley coords[d] = v0[d]; 686cb1e1211SMatthew G Knepley for (e = 0; e < dim; e++) { 687cb1e1211SMatthew G Knepley coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 688cb1e1211SMatthew G Knepley } 689cb1e1211SMatthew G Knepley } 690c110b1eeSGeoffrey Irving (*funcs[field])(coords, funcVal, ctx); 691cb1e1211SMatthew G Knepley for (fc = 0; fc < numBasisComps; ++fc) { 692a1d24da5SMatthew G. Knepley PetscScalar interpolant = 0.0; 693a1d24da5SMatthew G. Knepley 694cb1e1211SMatthew G Knepley for (f = 0; f < numBasisFuncs; ++f) { 695cb1e1211SMatthew G Knepley const PetscInt fidx = f*numBasisComps+fc; 696a1d24da5SMatthew G. Knepley interpolant += x[fieldOffset+fidx]*basis[q*numBasisFuncs*numBasisComps+fidx]; 697cb1e1211SMatthew G Knepley } 69872f94c41SMatthew G. Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ);CHKERRQ(ierr);} 69972f94c41SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ; 700cb1e1211SMatthew G Knepley } 701cb1e1211SMatthew G Knepley } 702cb1e1211SMatthew G Knepley comp += numBasisComps; 703cb1e1211SMatthew G Knepley fieldOffset += numBasisFuncs*numBasisComps; 704cb1e1211SMatthew G Knepley } 705cb1e1211SMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 706cb1e1211SMatthew G Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 707cb1e1211SMatthew G Knepley localDiff += elemDiff; 708cb1e1211SMatthew G Knepley } 70972f94c41SMatthew G. Knepley ierr = PetscFree5(funcVal,coords,v0,J,invJ);CHKERRQ(ierr); 710cb1e1211SMatthew G Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 71186a74ee0SMatthew G. Knepley ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 712cb1e1211SMatthew G Knepley *diff = PetscSqrtReal(*diff); 713cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 714cb1e1211SMatthew G Knepley } 715cb1e1211SMatthew G Knepley 716cb1e1211SMatthew G Knepley #undef __FUNCT__ 71740e14135SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeL2GradientDiff" 71840e14135SMatthew G. Knepley /*@C 71940e14135SMatthew G. Knepley DMPlexComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 72040e14135SMatthew G. Knepley 72140e14135SMatthew G. Knepley Input Parameters: 72240e14135SMatthew G. Knepley + dm - The DM 72340e14135SMatthew G. Knepley . funcs - The gradient functions to evaluate for each field component 72451259fa3SMatthew G. Knepley . ctxs - Optional array of contexts to pass to each function, or NULL. 72540e14135SMatthew G. Knepley . X - The coefficient vector u_h 72640e14135SMatthew G. Knepley - n - The vector to project along 72740e14135SMatthew G. Knepley 72840e14135SMatthew G. Knepley Output Parameter: 72940e14135SMatthew G. Knepley . diff - The diff ||(grad u - grad u_h) . n||_2 73040e14135SMatthew G. Knepley 73140e14135SMatthew G. Knepley Level: developer 73240e14135SMatthew G. Knepley 73340e14135SMatthew G. Knepley .seealso: DMPlexProjectFunction(), DMPlexComputeL2Diff() 73440e14135SMatthew G. Knepley @*/ 7350f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeL2GradientDiff(DM dm, void (**funcs)(const PetscReal [], const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff) 736cb1e1211SMatthew G Knepley { 73740e14135SMatthew G. Knepley const PetscInt debug = 0; 738cb1e1211SMatthew G Knepley PetscSection section; 73940e14135SMatthew G. Knepley PetscQuadrature quad; 74040e14135SMatthew G. Knepley Vec localX; 74140e14135SMatthew G. Knepley PetscScalar *funcVal, *interpolantVec; 74240e14135SMatthew G. Knepley PetscReal *coords, *realSpaceDer, *v0, *J, *invJ, detJ; 74340e14135SMatthew G. Knepley PetscReal localDiff = 0.0; 74440e14135SMatthew G. Knepley PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 745cb1e1211SMatthew G Knepley PetscErrorCode ierr; 746cb1e1211SMatthew G Knepley 747cb1e1211SMatthew G Knepley PetscFunctionBegin; 748c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 74940e14135SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 75040e14135SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 75140e14135SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 75240e14135SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 75340e14135SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 754652b88e8SMatthew G. Knepley for (field = 0; field < numFields; ++field) { 7550f2d7e86SMatthew G. Knepley PetscFE fe; 75640e14135SMatthew G. Knepley PetscInt Nc; 757652b88e8SMatthew G. Knepley 7580f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 7590f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 7600f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 76140e14135SMatthew G. Knepley numComponents += Nc; 762652b88e8SMatthew G. Knepley } 76340e14135SMatthew G. Knepley /* ierr = DMPlexProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); */ 76440e14135SMatthew G. Knepley ierr = PetscMalloc7(numComponents,&funcVal,dim,&coords,dim,&realSpaceDer,dim,&v0,dim*dim,&J,dim*dim,&invJ,dim,&interpolantVec);CHKERRQ(ierr); 76540e14135SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 76640e14135SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 76740e14135SMatthew G. Knepley PetscScalar *x = NULL; 76840e14135SMatthew G. Knepley PetscReal elemDiff = 0.0; 769652b88e8SMatthew G. Knepley 7708e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 77140e14135SMatthew G. Knepley if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 77240e14135SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 77340e14135SMatthew G. Knepley 77440e14135SMatthew G. Knepley for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 7750f2d7e86SMatthew G. Knepley PetscFE fe; 77651259fa3SMatthew G. Knepley void * const ctx = ctxs ? ctxs[field] : NULL; 77721454ff5SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 77840e14135SMatthew G. Knepley PetscReal *basisDer; 77921454ff5SMatthew G. Knepley PetscInt numQuadPoints, Nb, Ncomp, q, d, e, fc, f, g; 78040e14135SMatthew G. Knepley 7810f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 78221454ff5SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 7830f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 7840f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Ncomp);CHKERRQ(ierr); 7850f2d7e86SMatthew G. Knepley ierr = PetscFEGetDefaultTabulation(fe, NULL, &basisDer, NULL);CHKERRQ(ierr); 78640e14135SMatthew G. Knepley if (debug) { 78740e14135SMatthew G. Knepley char title[1024]; 78840e14135SMatthew G. Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 78940e14135SMatthew G. Knepley ierr = DMPrintCellVector(c, title, Nb*Ncomp, &x[fieldOffset]);CHKERRQ(ierr); 790652b88e8SMatthew G. Knepley } 79140e14135SMatthew G. Knepley for (q = 0; q < numQuadPoints; ++q) { 79240e14135SMatthew G. Knepley for (d = 0; d < dim; d++) { 79340e14135SMatthew G. Knepley coords[d] = v0[d]; 79440e14135SMatthew G. Knepley for (e = 0; e < dim; e++) { 79540e14135SMatthew G. Knepley coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 796652b88e8SMatthew G. Knepley } 79740e14135SMatthew G. Knepley } 79851259fa3SMatthew G. Knepley (*funcs[field])(coords, n, funcVal, ctx); 79940e14135SMatthew G. Knepley for (fc = 0; fc < Ncomp; ++fc) { 80040e14135SMatthew G. Knepley PetscScalar interpolant = 0.0; 80140e14135SMatthew G. Knepley 80240e14135SMatthew G. Knepley for (d = 0; d < dim; ++d) interpolantVec[d] = 0.0; 80340e14135SMatthew G. Knepley for (f = 0; f < Nb; ++f) { 80440e14135SMatthew G. Knepley const PetscInt fidx = f*Ncomp+fc; 80540e14135SMatthew G. Knepley 80640e14135SMatthew G. Knepley for (d = 0; d < dim; ++d) { 80740e14135SMatthew G. Knepley realSpaceDer[d] = 0.0; 80840e14135SMatthew G. Knepley for (g = 0; g < dim; ++g) { 80940e14135SMatthew G. Knepley realSpaceDer[d] += invJ[g*dim+d]*basisDer[(q*Nb*Ncomp+fidx)*dim+g]; 81040e14135SMatthew G. Knepley } 81140e14135SMatthew G. Knepley interpolantVec[d] += x[fieldOffset+fidx]*realSpaceDer[d]; 81240e14135SMatthew G. Knepley } 81340e14135SMatthew G. Knepley } 81440e14135SMatthew G. Knepley for (d = 0; d < dim; ++d) interpolant += interpolantVec[d]*n[d]; 81540e14135SMatthew G. Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d fieldDer %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ);CHKERRQ(ierr);} 81640e14135SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ; 81740e14135SMatthew G. Knepley } 81840e14135SMatthew G. Knepley } 81940e14135SMatthew G. Knepley comp += Ncomp; 82040e14135SMatthew G. Knepley fieldOffset += Nb*Ncomp; 82140e14135SMatthew G. Knepley } 82240e14135SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 82340e14135SMatthew G. Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 82440e14135SMatthew G. Knepley localDiff += elemDiff; 82540e14135SMatthew G. Knepley } 82640e14135SMatthew G. Knepley ierr = PetscFree7(funcVal,coords,realSpaceDer,v0,J,invJ,interpolantVec);CHKERRQ(ierr); 82740e14135SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 82840e14135SMatthew G. Knepley ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 82940e14135SMatthew G. Knepley *diff = PetscSqrtReal(*diff); 830cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 831cb1e1211SMatthew G Knepley } 832cb1e1211SMatthew G Knepley 833a0845e3aSMatthew G. Knepley #undef __FUNCT__ 83473d901b8SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeL2FieldDiff" 8350f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeL2FieldDiff(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 83673d901b8SMatthew G. Knepley { 83773d901b8SMatthew G. Knepley const PetscInt debug = 0; 83873d901b8SMatthew G. Knepley PetscSection section; 83973d901b8SMatthew G. Knepley PetscQuadrature quad; 84073d901b8SMatthew G. Knepley Vec localX; 84173d901b8SMatthew G. Knepley PetscScalar *funcVal; 84273d901b8SMatthew G. Knepley PetscReal *coords, *v0, *J, *invJ, detJ; 84373d901b8SMatthew G. Knepley PetscReal *localDiff; 84473d901b8SMatthew G. Knepley PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 84573d901b8SMatthew G. Knepley PetscErrorCode ierr; 84673d901b8SMatthew G. Knepley 84773d901b8SMatthew G. Knepley PetscFunctionBegin; 848c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 84973d901b8SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 85073d901b8SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 85173d901b8SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 85273d901b8SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 85373d901b8SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 85473d901b8SMatthew G. Knepley for (field = 0; field < numFields; ++field) { 8550f2d7e86SMatthew G. Knepley PetscFE fe; 85673d901b8SMatthew G. Knepley PetscInt Nc; 85773d901b8SMatthew G. Knepley 8580f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 8590f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 8600f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 86173d901b8SMatthew G. Knepley numComponents += Nc; 86273d901b8SMatthew G. Knepley } 8630f2d7e86SMatthew G. Knepley ierr = DMPlexProjectFunctionLocal(dm, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 86473d901b8SMatthew G. Knepley ierr = PetscCalloc6(numFields,&localDiff,numComponents,&funcVal,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 86573d901b8SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 86673d901b8SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 86773d901b8SMatthew G. Knepley PetscScalar *x = NULL; 86873d901b8SMatthew G. Knepley 8698e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 87073d901b8SMatthew G. Knepley if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 87173d901b8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 87273d901b8SMatthew G. Knepley 87373d901b8SMatthew G. Knepley for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 8740f2d7e86SMatthew G. Knepley PetscFE fe; 87573d901b8SMatthew G. Knepley void * const ctx = ctxs ? ctxs[field] : NULL; 87673d901b8SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 87773d901b8SMatthew G. Knepley PetscReal *basis, elemDiff = 0.0; 87873d901b8SMatthew G. Knepley PetscInt numQuadPoints, numBasisFuncs, numBasisComps, q, d, e, fc, f; 87973d901b8SMatthew G. Knepley 8800f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 88173d901b8SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 8820f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &numBasisFuncs);CHKERRQ(ierr); 8830f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &numBasisComps);CHKERRQ(ierr); 8840f2d7e86SMatthew G. Knepley ierr = PetscFEGetDefaultTabulation(fe, &basis, NULL, NULL);CHKERRQ(ierr); 88573d901b8SMatthew G. Knepley if (debug) { 88673d901b8SMatthew G. Knepley char title[1024]; 88773d901b8SMatthew G. Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 88873d901b8SMatthew G. Knepley ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 88973d901b8SMatthew G. Knepley } 89073d901b8SMatthew G. Knepley for (q = 0; q < numQuadPoints; ++q) { 89173d901b8SMatthew G. Knepley for (d = 0; d < dim; d++) { 89273d901b8SMatthew G. Knepley coords[d] = v0[d]; 89373d901b8SMatthew G. Knepley for (e = 0; e < dim; e++) { 89473d901b8SMatthew G. Knepley coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 89573d901b8SMatthew G. Knepley } 89673d901b8SMatthew G. Knepley } 89773d901b8SMatthew G. Knepley (*funcs[field])(coords, funcVal, ctx); 89873d901b8SMatthew G. Knepley for (fc = 0; fc < numBasisComps; ++fc) { 89973d901b8SMatthew G. Knepley PetscScalar interpolant = 0.0; 90073d901b8SMatthew G. Knepley 90173d901b8SMatthew G. Knepley for (f = 0; f < numBasisFuncs; ++f) { 90273d901b8SMatthew G. Knepley const PetscInt fidx = f*numBasisComps+fc; 90373d901b8SMatthew G. Knepley interpolant += x[fieldOffset+fidx]*basis[q*numBasisFuncs*numBasisComps+fidx]; 90473d901b8SMatthew G. Knepley } 90573d901b8SMatthew G. Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ);CHKERRQ(ierr);} 90673d901b8SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ; 90773d901b8SMatthew G. Knepley } 90873d901b8SMatthew G. Knepley } 90973d901b8SMatthew G. Knepley comp += numBasisComps; 91073d901b8SMatthew G. Knepley fieldOffset += numBasisFuncs*numBasisComps; 91173d901b8SMatthew G. Knepley localDiff[field] += elemDiff; 91273d901b8SMatthew G. Knepley } 91373d901b8SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 91473d901b8SMatthew G. Knepley } 91573d901b8SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 91673d901b8SMatthew G. Knepley ierr = MPI_Allreduce(localDiff, diff, numFields, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 91773d901b8SMatthew G. Knepley for (field = 0; field < numFields; ++field) diff[field] = PetscSqrtReal(diff[field]); 91873d901b8SMatthew G. Knepley ierr = PetscFree6(localDiff,funcVal,coords,v0,J,invJ);CHKERRQ(ierr); 91973d901b8SMatthew G. Knepley PetscFunctionReturn(0); 92073d901b8SMatthew G. Knepley } 92173d901b8SMatthew G. Knepley 92273d901b8SMatthew G. Knepley #undef __FUNCT__ 92373d901b8SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeIntegralFEM" 92473d901b8SMatthew G. Knepley /*@ 92573d901b8SMatthew G. Knepley DMPlexComputeIntegralFEM - Form the local integral F from the local input X using pointwise functions specified by the user 92673d901b8SMatthew G. Knepley 92773d901b8SMatthew G. Knepley Input Parameters: 92873d901b8SMatthew G. Knepley + dm - The mesh 92973d901b8SMatthew G. Knepley . X - Local input vector 93073d901b8SMatthew G. Knepley - user - The user context 93173d901b8SMatthew G. Knepley 93273d901b8SMatthew G. Knepley Output Parameter: 93373d901b8SMatthew G. Knepley . integral - Local integral for each field 93473d901b8SMatthew G. Knepley 93573d901b8SMatthew G. Knepley Level: developer 93673d901b8SMatthew G. Knepley 93773d901b8SMatthew G. Knepley .seealso: DMPlexComputeResidualFEM() 93873d901b8SMatthew G. Knepley @*/ 9390f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeIntegralFEM(DM dm, Vec X, PetscReal *integral, void *user) 94073d901b8SMatthew G. Knepley { 94173d901b8SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 94273d901b8SMatthew G. Knepley DM dmAux; 94373d901b8SMatthew G. Knepley Vec localX, A; 9442764a2aaSMatthew G. Knepley PetscDS prob, probAux = NULL; 94573d901b8SMatthew G. Knepley PetscQuadrature q; 94673d901b8SMatthew G. Knepley PetscCellGeometry geom; 94773d901b8SMatthew G. Knepley PetscSection section, sectionAux; 94873d901b8SMatthew G. Knepley PetscReal *v0, *J, *invJ, *detJ; 94973d901b8SMatthew G. Knepley PetscScalar *u, *a = NULL; 9500f2d7e86SMatthew G. Knepley PetscInt dim, Nf, f, numCells, cStart, cEnd, c; 9510f2d7e86SMatthew G. Knepley PetscInt totDim, totDimAux; 95273d901b8SMatthew G. Knepley PetscErrorCode ierr; 95373d901b8SMatthew G. Knepley 95473d901b8SMatthew G. Knepley PetscFunctionBegin; 95573d901b8SMatthew G. Knepley /*ierr = PetscLogEventBegin(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr);*/ 95673d901b8SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 95773d901b8SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 95873d901b8SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 959c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 96073d901b8SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9612764a2aaSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 9622764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 96373d901b8SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 96473d901b8SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 96573d901b8SMatthew G. Knepley numCells = cEnd - cStart; 9660f2d7e86SMatthew G. Knepley for (f = 0; f < Nf; ++f) {integral[f] = 0.0;} 96773d901b8SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 96873d901b8SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 96973d901b8SMatthew G. Knepley if (dmAux) { 97073d901b8SMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 9712764a2aaSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 9722764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 97373d901b8SMatthew G. Knepley } 97473d901b8SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesFEM(dm, localX);CHKERRQ(ierr); 9750f2d7e86SMatthew G. Knepley ierr = PetscMalloc5(numCells*totDim,&u,numCells*dim,&v0,numCells*dim*dim,&J,numCells*dim*dim,&invJ,numCells,&detJ);CHKERRQ(ierr); 9760f2d7e86SMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 97773d901b8SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 97873d901b8SMatthew G. Knepley PetscScalar *x = NULL; 97973d901b8SMatthew G. Knepley PetscInt i; 98073d901b8SMatthew G. Knepley 9818e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 98273d901b8SMatthew G. Knepley if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 98373d901b8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, localX, c, NULL, &x);CHKERRQ(ierr); 9840f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 98573d901b8SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, localX, c, NULL, &x);CHKERRQ(ierr); 98673d901b8SMatthew G. Knepley if (dmAux) { 98773d901b8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 9880f2d7e86SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 98973d901b8SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 99073d901b8SMatthew G. Knepley } 99173d901b8SMatthew G. Knepley } 99273d901b8SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 9930f2d7e86SMatthew G. Knepley PetscFE fe; 99473d901b8SMatthew G. Knepley PetscInt numQuadPoints, Nb; 99573d901b8SMatthew G. Knepley /* Conforming batches */ 99673d901b8SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 99773d901b8SMatthew G. Knepley /* Remainder */ 99873d901b8SMatthew G. Knepley PetscInt Nr, offset; 99973d901b8SMatthew G. Knepley 10002764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 10010f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 10020f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 10030f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 100473d901b8SMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 100573d901b8SMatthew G. Knepley blockSize = Nb*numQuadPoints; 100673d901b8SMatthew G. Knepley batchSize = numBlocks * blockSize; 10070f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 100873d901b8SMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 100973d901b8SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 101073d901b8SMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 101173d901b8SMatthew G. Knepley offset = numCells - Nr; 101273d901b8SMatthew G. Knepley geom.v0 = v0; 101373d901b8SMatthew G. Knepley geom.J = J; 101473d901b8SMatthew G. Knepley geom.invJ = invJ; 101573d901b8SMatthew G. Knepley geom.detJ = detJ; 10160f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrate(fe, prob, f, Ne, geom, u, probAux, a, integral);CHKERRQ(ierr); 101773d901b8SMatthew G. Knepley geom.v0 = &v0[offset*dim]; 101873d901b8SMatthew G. Knepley geom.J = &J[offset*dim*dim]; 101973d901b8SMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 102073d901b8SMatthew G. Knepley geom.detJ = &detJ[offset]; 10210f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrate(fe, prob, f, Nr, geom, &u[offset*totDim], probAux, &a[offset*totDimAux], integral);CHKERRQ(ierr); 102273d901b8SMatthew G. Knepley } 102373d901b8SMatthew G. Knepley ierr = PetscFree5(u,v0,J,invJ,detJ);CHKERRQ(ierr); 102473d901b8SMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 102573d901b8SMatthew G. Knepley if (mesh->printFEM) { 102673d901b8SMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "Local integral:");CHKERRQ(ierr); 102773d901b8SMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), " %g", integral[f]);CHKERRQ(ierr);} 102873d901b8SMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "\n");CHKERRQ(ierr); 102973d901b8SMatthew G. Knepley } 103073d901b8SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 103173d901b8SMatthew G. Knepley /* TODO: Allreduce for integral */ 103273d901b8SMatthew G. Knepley /*ierr = PetscLogEventEnd(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr);*/ 103373d901b8SMatthew G. Knepley PetscFunctionReturn(0); 103473d901b8SMatthew G. Knepley } 103573d901b8SMatthew G. Knepley 103673d901b8SMatthew G. Knepley #undef __FUNCT__ 10370f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeResidualFEM_Internal" 10380f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeResidualFEM_Internal(DM dm, Vec X, Vec X_t, Vec F, void *user) 10390f2d7e86SMatthew G. Knepley { 10400f2d7e86SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 10410f2d7e86SMatthew G. Knepley const char *name = "Residual"; 10420f2d7e86SMatthew G. Knepley DM dmAux; 10430f2d7e86SMatthew G. Knepley DMLabel depth; 10440f2d7e86SMatthew G. Knepley Vec A; 10452764a2aaSMatthew G. Knepley PetscDS prob, probAux = NULL; 10460f2d7e86SMatthew G. Knepley PetscQuadrature q; 10470f2d7e86SMatthew G. Knepley PetscCellGeometry geom; 10480f2d7e86SMatthew G. Knepley PetscSection section, sectionAux; 10490f2d7e86SMatthew G. Knepley PetscReal *v0, *J, *invJ, *detJ; 10500f2d7e86SMatthew G. Knepley PetscScalar *elemVec, *u, *u_t, *a = NULL; 10510f2d7e86SMatthew G. Knepley PetscInt dim, Nf, f, numCells, cStart, cEnd, c, numBd, bd; 10520f2d7e86SMatthew G. Knepley PetscInt totDim, totDimBd, totDimAux; 10530f2d7e86SMatthew G. Knepley PetscErrorCode ierr; 10540f2d7e86SMatthew G. Knepley 10550f2d7e86SMatthew G. Knepley PetscFunctionBegin; 10560f2d7e86SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_ResidualFEM,dm,0,0,0);CHKERRQ(ierr); 1057c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 10580f2d7e86SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10592764a2aaSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 10602764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 10612764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalBdDimension(prob, &totDimBd);CHKERRQ(ierr); 10620f2d7e86SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 10630f2d7e86SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10640f2d7e86SMatthew G. Knepley numCells = cEnd - cStart; 10650f2d7e86SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 10660f2d7e86SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 10670f2d7e86SMatthew G. Knepley if (dmAux) { 10680f2d7e86SMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 10692764a2aaSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 10702764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 10710f2d7e86SMatthew G. Knepley } 10720f2d7e86SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesFEM(dm, X);CHKERRQ(ierr); 10730f2d7e86SMatthew G. Knepley ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10740f2d7e86SMatthew G. Knepley ierr = PetscMalloc7(numCells*totDim,&u,X_t ? numCells*totDim : 0,&u_t,numCells*dim,&v0,numCells*dim*dim,&J,numCells*dim*dim,&invJ,numCells,&detJ,numCells*totDim,&elemVec);CHKERRQ(ierr); 10750f2d7e86SMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 10760f2d7e86SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 10770f2d7e86SMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 10780f2d7e86SMatthew G. Knepley PetscInt i; 10790f2d7e86SMatthew G. Knepley 10808e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10810f2d7e86SMatthew G. Knepley if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10820f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 10830f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 10840f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 10850f2d7e86SMatthew G. Knepley if (X_t) { 10860f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 10870f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i]; 10880f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 10890f2d7e86SMatthew G. Knepley } 10900f2d7e86SMatthew G. Knepley if (dmAux) { 10910f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 10920f2d7e86SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 10930f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 10940f2d7e86SMatthew G. Knepley } 10950f2d7e86SMatthew G. Knepley } 10960f2d7e86SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10970f2d7e86SMatthew G. Knepley PetscFE fe; 10980f2d7e86SMatthew G. Knepley PetscInt numQuadPoints, Nb; 10990f2d7e86SMatthew G. Knepley /* Conforming batches */ 11000f2d7e86SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 11010f2d7e86SMatthew G. Knepley /* Remainder */ 11020f2d7e86SMatthew G. Knepley PetscInt Nr, offset; 11030f2d7e86SMatthew G. Knepley 11042764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 11050f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 11060f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 11070f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 11080f2d7e86SMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 11090f2d7e86SMatthew G. Knepley blockSize = Nb*numQuadPoints; 11100f2d7e86SMatthew G. Knepley batchSize = numBlocks * blockSize; 11110f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 11120f2d7e86SMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 11130f2d7e86SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 11140f2d7e86SMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 11150f2d7e86SMatthew G. Knepley offset = numCells - Nr; 11160f2d7e86SMatthew G. Knepley geom.v0 = v0; 11170f2d7e86SMatthew G. Knepley geom.J = J; 11180f2d7e86SMatthew G. Knepley geom.invJ = invJ; 11190f2d7e86SMatthew G. Knepley geom.detJ = detJ; 11200f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateResidual(fe, prob, f, Ne, geom, u, u_t, probAux, a, elemVec);CHKERRQ(ierr); 11210f2d7e86SMatthew G. Knepley geom.v0 = &v0[offset*dim]; 11220f2d7e86SMatthew G. Knepley geom.J = &J[offset*dim*dim]; 11230f2d7e86SMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 11240f2d7e86SMatthew G. Knepley geom.detJ = &detJ[offset]; 11250f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateResidual(fe, prob, f, Nr, geom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], &elemVec[offset*totDim]);CHKERRQ(ierr); 11260f2d7e86SMatthew G. Knepley } 11270f2d7e86SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 11280f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, name, totDim, &elemVec[c*totDim]);CHKERRQ(ierr);} 11290f2d7e86SMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, section, F, c, &elemVec[c*totDim], ADD_VALUES);CHKERRQ(ierr); 11300f2d7e86SMatthew G. Knepley } 11310f2d7e86SMatthew G. Knepley ierr = PetscFree7(u,u_t,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 11320f2d7e86SMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 11330f2d7e86SMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr); 11340f2d7e86SMatthew G. Knepley ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 11350f2d7e86SMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) { 11360f2d7e86SMatthew G. Knepley const char *bdLabel; 11370f2d7e86SMatthew G. Knepley DMLabel label; 11380f2d7e86SMatthew G. Knepley IS pointIS; 11390f2d7e86SMatthew G. Knepley const PetscInt *points; 11400f2d7e86SMatthew G. Knepley const PetscInt *values; 11410f2d7e86SMatthew G. Knepley PetscReal *n; 11420f2d7e86SMatthew G. Knepley PetscInt field, numValues, numPoints, p, dep, numFaces; 11430f2d7e86SMatthew G. Knepley PetscBool isEssential; 11440f2d7e86SMatthew G. Knepley 11450f2d7e86SMatthew G. Knepley ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, &bdLabel, &field, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 11460f2d7e86SMatthew G. Knepley if (isEssential) continue; 11470f2d7e86SMatthew G. Knepley if (numValues != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Bug me and I will fix this"); 11480f2d7e86SMatthew G. Knepley ierr = DMPlexGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 11490f2d7e86SMatthew G. Knepley ierr = DMLabelGetStratumSize(label, 1, &numPoints);CHKERRQ(ierr); 11500f2d7e86SMatthew G. Knepley ierr = DMLabelGetStratumIS(label, 1, &pointIS);CHKERRQ(ierr); 11510f2d7e86SMatthew G. Knepley ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 11520f2d7e86SMatthew G. Knepley for (p = 0, numFaces = 0; p < numPoints; ++p) { 11530f2d7e86SMatthew G. Knepley ierr = DMLabelGetValue(depth, points[p], &dep);CHKERRQ(ierr); 11540f2d7e86SMatthew G. Knepley if (dep == dim-1) ++numFaces; 11550f2d7e86SMatthew G. Knepley } 11560f2d7e86SMatthew G. Knepley ierr = PetscMalloc7(numFaces*totDimBd,&u,numFaces*dim,&v0,numFaces*dim,&n,numFaces*dim*dim,&J,numFaces*dim*dim,&invJ,numFaces,&detJ,numFaces*totDimBd,&elemVec);CHKERRQ(ierr); 11570f2d7e86SMatthew G. Knepley if (X_t) {ierr = PetscMalloc1(numFaces*totDimBd,&u_t);CHKERRQ(ierr);} 11580f2d7e86SMatthew G. Knepley for (p = 0, f = 0; p < numPoints; ++p) { 11590f2d7e86SMatthew G. Knepley const PetscInt point = points[p]; 11600f2d7e86SMatthew G. Knepley PetscScalar *x = NULL; 11610f2d7e86SMatthew G. Knepley PetscInt i; 11620f2d7e86SMatthew G. Knepley 11630f2d7e86SMatthew G. Knepley ierr = DMLabelGetValue(depth, points[p], &dep);CHKERRQ(ierr); 11640f2d7e86SMatthew G. Knepley if (dep != dim-1) continue; 11658e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, point, NULL, &v0[f*dim], &J[f*dim*dim], &invJ[f*dim*dim], &detJ[f]);CHKERRQ(ierr); 11660f2d7e86SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFVM(dm, point, NULL, NULL, &n[f*dim]); 11670f2d7e86SMatthew G. Knepley if (detJ[f] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for face %d", detJ[f], point); 11680f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, point, NULL, &x);CHKERRQ(ierr); 11690f2d7e86SMatthew G. Knepley for (i = 0; i < totDimBd; ++i) u[f*totDimBd+i] = x[i]; 11700f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, point, NULL, &x);CHKERRQ(ierr); 11710f2d7e86SMatthew G. Knepley if (X_t) { 11720f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, point, NULL, &x);CHKERRQ(ierr); 11730f2d7e86SMatthew G. Knepley for (i = 0; i < totDimBd; ++i) u_t[f*totDimBd+i] = x[i]; 11740f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, point, NULL, &x);CHKERRQ(ierr); 11750f2d7e86SMatthew G. Knepley } 11760f2d7e86SMatthew G. Knepley ++f; 11770f2d7e86SMatthew G. Knepley } 11780f2d7e86SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 11790f2d7e86SMatthew G. Knepley PetscFE fe; 11800f2d7e86SMatthew G. Knepley PetscInt numQuadPoints, Nb; 11810f2d7e86SMatthew G. Knepley /* Conforming batches */ 11820f2d7e86SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 11830f2d7e86SMatthew G. Knepley /* Remainder */ 11840f2d7e86SMatthew G. Knepley PetscInt Nr, offset; 11850f2d7e86SMatthew G. Knepley 11862764a2aaSMatthew G. Knepley ierr = PetscDSGetBdDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 11870f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 11880f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 11890f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 11900f2d7e86SMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 11910f2d7e86SMatthew G. Knepley blockSize = Nb*numQuadPoints; 11920f2d7e86SMatthew G. Knepley batchSize = numBlocks * blockSize; 11930f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 11940f2d7e86SMatthew G. Knepley numChunks = numFaces / (numBatches*batchSize); 11950f2d7e86SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 11960f2d7e86SMatthew G. Knepley Nr = numFaces % (numBatches*batchSize); 11970f2d7e86SMatthew G. Knepley offset = numFaces - Nr; 11980f2d7e86SMatthew G. Knepley geom.v0 = v0; 11990f2d7e86SMatthew G. Knepley geom.n = n; 12000f2d7e86SMatthew G. Knepley geom.J = J; 12010f2d7e86SMatthew G. Knepley geom.invJ = invJ; 12020f2d7e86SMatthew G. Knepley geom.detJ = detJ; 12030f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateBdResidual(fe, prob, f, Ne, geom, u, u_t, NULL, NULL, elemVec);CHKERRQ(ierr); 12040f2d7e86SMatthew G. Knepley geom.v0 = &v0[offset*dim]; 12050f2d7e86SMatthew G. Knepley geom.n = &n[offset*dim]; 12060f2d7e86SMatthew G. Knepley geom.J = &J[offset*dim*dim]; 12070f2d7e86SMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 12080f2d7e86SMatthew G. Knepley geom.detJ = &detJ[offset]; 12090f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateBdResidual(fe, prob, f, Nr, geom, &u[offset*totDimBd], u_t ? &u_t[offset*totDimBd] : NULL, NULL, NULL, &elemVec[offset*totDimBd]);CHKERRQ(ierr); 12100f2d7e86SMatthew G. Knepley } 12110f2d7e86SMatthew G. Knepley for (p = 0, f = 0; p < numPoints; ++p) { 12120f2d7e86SMatthew G. Knepley const PetscInt point = points[p]; 12130f2d7e86SMatthew G. Knepley 12140f2d7e86SMatthew G. Knepley ierr = DMLabelGetValue(depth, point, &dep);CHKERRQ(ierr); 12150f2d7e86SMatthew G. Knepley if (dep != dim-1) continue; 12160f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellVector(point, "BdResidual", totDimBd, &elemVec[f*totDimBd]);CHKERRQ(ierr);} 12170f2d7e86SMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, NULL, F, point, &elemVec[f*totDimBd], ADD_VALUES);CHKERRQ(ierr); 12180f2d7e86SMatthew G. Knepley ++f; 12190f2d7e86SMatthew G. Knepley } 12200f2d7e86SMatthew G. Knepley ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 12210f2d7e86SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 12220f2d7e86SMatthew G. Knepley ierr = PetscFree7(u,v0,n,J,invJ,detJ,elemVec);CHKERRQ(ierr); 12230f2d7e86SMatthew G. Knepley if (X_t) {ierr = PetscFree(u_t);CHKERRQ(ierr);} 12240f2d7e86SMatthew G. Knepley } 12250f2d7e86SMatthew G. Knepley if (mesh->printFEM) {ierr = DMPrintLocalVec(dm, name, mesh->printTol, F);CHKERRQ(ierr);} 12260f2d7e86SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_ResidualFEM,dm,0,0,0);CHKERRQ(ierr); 12270f2d7e86SMatthew G. Knepley PetscFunctionReturn(0); 12280f2d7e86SMatthew G. Knepley } 12290f2d7e86SMatthew G. Knepley 12300f2d7e86SMatthew G. Knepley #undef __FUNCT__ 123108f11eefSMatthew G. Knepley #define __FUNCT__ "DMPlexComputeResidualFEM_Check" 123208f11eefSMatthew G. Knepley static PetscErrorCode DMPlexComputeResidualFEM_Check(DM dm, Vec X, Vec X_t, Vec F, void *user) 123308f11eefSMatthew G. Knepley { 123408f11eefSMatthew G. Knepley DM dmCh, dmAux; 123508f11eefSMatthew G. Knepley Vec A; 12366f4eac71SMatthew G. Knepley PetscDS prob, probCh, probAux = NULL; 123708f11eefSMatthew G. Knepley PetscQuadrature q; 123808f11eefSMatthew G. Knepley PetscCellGeometry geom; 123908f11eefSMatthew G. Knepley PetscSection section, sectionAux; 124008f11eefSMatthew G. Knepley PetscReal *v0, *J, *invJ, *detJ; 124108f11eefSMatthew G. Knepley PetscScalar *elemVec, *elemVecCh, *u, *u_t, *a = NULL; 124208f11eefSMatthew G. Knepley PetscInt dim, Nf, f, numCells, cStart, cEnd, c; 124308f11eefSMatthew G. Knepley PetscInt totDim, totDimAux, diffCell = 0; 124408f11eefSMatthew G. Knepley PetscErrorCode ierr; 124508f11eefSMatthew G. Knepley 124608f11eefSMatthew G. Knepley PetscFunctionBegin; 1247c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 124808f11eefSMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 12496f4eac71SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 12506f4eac71SMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 125108f11eefSMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 125208f11eefSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 125308f11eefSMatthew G. Knepley numCells = cEnd - cStart; 125408f11eefSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmCh", (PetscObject *) &dmCh);CHKERRQ(ierr); 12556f4eac71SMatthew G. Knepley ierr = DMGetDS(dmCh, &probCh);CHKERRQ(ierr); 125608f11eefSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 125708f11eefSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 125808f11eefSMatthew G. Knepley if (dmAux) { 125908f11eefSMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 12606f4eac71SMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 12616f4eac71SMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 126208f11eefSMatthew G. Knepley } 126308f11eefSMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesFEM(dm, X);CHKERRQ(ierr); 126408f11eefSMatthew G. Knepley ierr = VecSet(F, 0.0);CHKERRQ(ierr); 126508f11eefSMatthew G. Knepley ierr = PetscMalloc7(numCells*totDim,&u,X_t ? numCells*totDim : 0,&u_t,numCells*dim,&v0,numCells*dim*dim,&J,numCells*dim*dim,&invJ,numCells,&detJ,numCells*totDim,&elemVec);CHKERRQ(ierr); 126608f11eefSMatthew G. Knepley ierr = PetscMalloc1(numCells*totDim,&elemVecCh);CHKERRQ(ierr); 126708f11eefSMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 126808f11eefSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 126908f11eefSMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 127008f11eefSMatthew G. Knepley PetscInt i; 127108f11eefSMatthew G. Knepley 12728e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 127308f11eefSMatthew G. Knepley if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 127408f11eefSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 127508f11eefSMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 127608f11eefSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 127708f11eefSMatthew G. Knepley if (X_t) { 127808f11eefSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 127908f11eefSMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i]; 128008f11eefSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 128108f11eefSMatthew G. Knepley } 128208f11eefSMatthew G. Knepley if (dmAux) { 128308f11eefSMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 128408f11eefSMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 128508f11eefSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 128608f11eefSMatthew G. Knepley } 128708f11eefSMatthew G. Knepley } 128808f11eefSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 128908f11eefSMatthew G. Knepley PetscFE fe, feCh; 129008f11eefSMatthew G. Knepley PetscInt numQuadPoints, Nb; 129108f11eefSMatthew G. Knepley /* Conforming batches */ 129208f11eefSMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 129308f11eefSMatthew G. Knepley /* Remainder */ 129408f11eefSMatthew G. Knepley PetscInt Nr, offset; 129508f11eefSMatthew G. Knepley 12966f4eac71SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 12976f4eac71SMatthew G. Knepley ierr = PetscDSGetDiscretization(probCh, f, (PetscObject *) &feCh);CHKERRQ(ierr); 129808f11eefSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 129908f11eefSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 130008f11eefSMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 130108f11eefSMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 130208f11eefSMatthew G. Knepley blockSize = Nb*numQuadPoints; 130308f11eefSMatthew G. Knepley batchSize = numBlocks * blockSize; 130408f11eefSMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 130508f11eefSMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 130608f11eefSMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 130708f11eefSMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 130808f11eefSMatthew G. Knepley offset = numCells - Nr; 130908f11eefSMatthew G. Knepley geom.v0 = v0; 131008f11eefSMatthew G. Knepley geom.J = J; 131108f11eefSMatthew G. Knepley geom.invJ = invJ; 131208f11eefSMatthew G. Knepley geom.detJ = detJ; 131308f11eefSMatthew G. Knepley ierr = PetscFEIntegrateResidual(fe, prob, f, Ne, geom, u, u_t, probAux, a, elemVec);CHKERRQ(ierr); 131408f11eefSMatthew G. Knepley ierr = PetscFEIntegrateResidual(feCh, prob, f, Ne, geom, u, u_t, probAux, a, elemVecCh);CHKERRQ(ierr); 131508f11eefSMatthew G. Knepley geom.v0 = &v0[offset*dim]; 131608f11eefSMatthew G. Knepley geom.J = &J[offset*dim*dim]; 131708f11eefSMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 131808f11eefSMatthew G. Knepley geom.detJ = &detJ[offset]; 131908f11eefSMatthew G. Knepley ierr = PetscFEIntegrateResidual(fe, prob, f, Nr, geom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], &elemVec[offset*totDim]);CHKERRQ(ierr); 132008f11eefSMatthew G. Knepley ierr = PetscFEIntegrateResidual(feCh, prob, f, Nr, geom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], &elemVecCh[offset*totDim]);CHKERRQ(ierr); 132108f11eefSMatthew G. Knepley } 132208f11eefSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 132308f11eefSMatthew G. Knepley PetscBool diff = PETSC_FALSE; 132408f11eefSMatthew G. Knepley PetscInt d; 132508f11eefSMatthew G. Knepley 132608f11eefSMatthew G. Knepley for (d = 0; d < totDim; ++d) if (PetscAbsScalar(elemVec[c*totDim+d] - elemVecCh[c*totDim+d]) > 1.0e-7) {diff = PETSC_TRUE;break;} 132708f11eefSMatthew G. Knepley if (diff) { 132808f11eefSMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "Different cell %d\n", c);CHKERRQ(ierr); 132908f11eefSMatthew G. Knepley ierr = DMPrintCellVector(c, "Residual", totDim, &elemVec[c*totDim]);CHKERRQ(ierr); 133008f11eefSMatthew G. Knepley ierr = DMPrintCellVector(c, "Check Residual", totDim, &elemVecCh[c*totDim]);CHKERRQ(ierr); 133108f11eefSMatthew G. Knepley ++diffCell; 133208f11eefSMatthew G. Knepley } 133308f11eefSMatthew G. Knepley if (diffCell > 9) break; 133408f11eefSMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, section, F, c, &elemVec[c*totDim], ADD_VALUES);CHKERRQ(ierr); 133508f11eefSMatthew G. Knepley } 133608f11eefSMatthew G. Knepley ierr = PetscFree7(u,u_t,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 133708f11eefSMatthew G. Knepley ierr = PetscFree(elemVecCh);CHKERRQ(ierr); 133808f11eefSMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 133908f11eefSMatthew G. Knepley PetscFunctionReturn(0); 134008f11eefSMatthew G. Knepley } 134108f11eefSMatthew G. Knepley 134208f11eefSMatthew G. Knepley #undef __FUNCT__ 13430f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexSNESComputeResidualFEM" 1344a0845e3aSMatthew G. Knepley /*@ 13450f2d7e86SMatthew G. Knepley DMPlexSNESComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 1346a0845e3aSMatthew G. Knepley 1347a0845e3aSMatthew G. Knepley Input Parameters: 1348a0845e3aSMatthew G. Knepley + dm - The mesh 13490f2d7e86SMatthew G. Knepley . X - Local solution 1350a0845e3aSMatthew G. Knepley - user - The user context 1351a0845e3aSMatthew G. Knepley 1352a0845e3aSMatthew G. Knepley Output Parameter: 1353a0845e3aSMatthew G. Knepley . F - Local output vector 1354a0845e3aSMatthew G. Knepley 1355a0845e3aSMatthew G. Knepley Level: developer 1356a0845e3aSMatthew G. Knepley 1357a0845e3aSMatthew G. Knepley .seealso: DMPlexComputeJacobianActionFEM() 1358a0845e3aSMatthew G. Knepley @*/ 13590f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 1360a0845e3aSMatthew G. Knepley { 136108f11eefSMatthew G. Knepley PetscObject check; 1362a0845e3aSMatthew G. Knepley PetscErrorCode ierr; 1363a0845e3aSMatthew G. Knepley 1364a0845e3aSMatthew G. Knepley PetscFunctionBegin; 136508f11eefSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmCh", &check);CHKERRQ(ierr); 136608f11eefSMatthew G. Knepley if (check) {ierr = DMPlexComputeResidualFEM_Check(dm, X, NULL, F, user);CHKERRQ(ierr);} 136708f11eefSMatthew G. Knepley else {ierr = DMPlexComputeResidualFEM_Internal(dm, X, NULL, F, user);CHKERRQ(ierr);} 13680f2d7e86SMatthew G. Knepley PetscFunctionReturn(0); 13690f2d7e86SMatthew G. Knepley } 13700f2d7e86SMatthew G. Knepley 13710f2d7e86SMatthew G. Knepley #undef __FUNCT__ 1372adbe6fbbSMatthew G. Knepley #define __FUNCT__ "DMPlexTSComputeIFunctionFEM" 1373adbe6fbbSMatthew G. Knepley /*@ 1374adbe6fbbSMatthew G. Knepley DMPlexTSComputeIFunctionFEM - Form the local residual F from the local input X using pointwise functions specified by the user 1375adbe6fbbSMatthew G. Knepley 1376adbe6fbbSMatthew G. Knepley Input Parameters: 1377adbe6fbbSMatthew G. Knepley + dm - The mesh 1378adbe6fbbSMatthew G. Knepley . t - The time 1379adbe6fbbSMatthew G. Knepley . X - Local solution 1380adbe6fbbSMatthew G. Knepley . X_t - Local solution time derivative, or NULL 1381adbe6fbbSMatthew G. Knepley - user - The user context 1382adbe6fbbSMatthew G. Knepley 1383adbe6fbbSMatthew G. Knepley Output Parameter: 1384adbe6fbbSMatthew G. Knepley . F - Local output vector 1385adbe6fbbSMatthew G. Knepley 1386adbe6fbbSMatthew G. Knepley Level: developer 1387adbe6fbbSMatthew G. Knepley 1388adbe6fbbSMatthew G. Knepley .seealso: DMPlexComputeJacobianActionFEM() 1389adbe6fbbSMatthew G. Knepley @*/ 1390adbe6fbbSMatthew G. Knepley PetscErrorCode DMPlexTSComputeIFunctionFEM(DM dm, PetscReal time, Vec X, Vec X_t, Vec F, void *user) 1391adbe6fbbSMatthew G. Knepley { 1392adbe6fbbSMatthew G. Knepley PetscErrorCode ierr; 1393adbe6fbbSMatthew G. Knepley 1394adbe6fbbSMatthew G. Knepley PetscFunctionBegin; 1395adbe6fbbSMatthew G. Knepley ierr = DMPlexComputeResidualFEM_Internal(dm, X, X_t, F, user);CHKERRQ(ierr); 1396adbe6fbbSMatthew G. Knepley PetscFunctionReturn(0); 1397adbe6fbbSMatthew G. Knepley } 1398adbe6fbbSMatthew G. Knepley 1399adbe6fbbSMatthew G. Knepley #undef __FUNCT__ 14000f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeJacobianFEM_Internal" 14010f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeJacobianFEM_Internal(DM dm, Vec X, Vec X_t, Mat Jac, Mat JacP,void *user) 14020f2d7e86SMatthew G. Knepley { 14030f2d7e86SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 14040f2d7e86SMatthew G. Knepley const char *name = "Jacobian"; 14050f2d7e86SMatthew G. Knepley DM dmAux; 14060f2d7e86SMatthew G. Knepley DMLabel depth; 14070f2d7e86SMatthew G. Knepley Vec A; 14082764a2aaSMatthew G. Knepley PetscDS prob, probAux = NULL; 14090f2d7e86SMatthew G. Knepley PetscQuadrature quad; 14100f2d7e86SMatthew G. Knepley PetscCellGeometry geom; 14110f2d7e86SMatthew G. Knepley PetscSection section, globalSection, sectionAux; 14120f2d7e86SMatthew G. Knepley PetscReal *v0, *J, *invJ, *detJ; 14130f2d7e86SMatthew G. Knepley PetscScalar *elemMat, *u, *u_t, *a = NULL; 14140f2d7e86SMatthew G. Knepley PetscInt dim, Nf, f, fieldI, fieldJ, numCells, cStart, cEnd, c; 14150f2d7e86SMatthew G. Knepley PetscInt totDim, totDimBd, totDimAux, numBd, bd; 14160f2d7e86SMatthew G. Knepley PetscBool isShell; 14170f2d7e86SMatthew G. Knepley PetscErrorCode ierr; 14180f2d7e86SMatthew G. Knepley 14190f2d7e86SMatthew G. Knepley PetscFunctionBegin; 14200f2d7e86SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 1421c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1422a0845e3aSMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 14230f2d7e86SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 14242764a2aaSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 14252764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 14262764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalBdDimension(prob, &totDimBd);CHKERRQ(ierr); 14279a559087SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 1428a0845e3aSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1429a0845e3aSMatthew G. Knepley numCells = cEnd - cStart; 14309a559087SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 14319a559087SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 14329a559087SMatthew G. Knepley if (dmAux) { 14339a559087SMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 14342764a2aaSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 14352764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 14369a559087SMatthew G. Knepley } 14373351dd3dSMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesFEM(dm, X);CHKERRQ(ierr); 14380f2d7e86SMatthew G. Knepley ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 14390f2d7e86SMatthew G. Knepley ierr = PetscMalloc7(numCells*totDim,&u,X_t ? numCells*totDim : 0,&u_t,numCells*dim,&v0,numCells*dim*dim,&J,numCells*dim*dim,&invJ,numCells,&detJ,numCells*totDim*totDim,&elemMat);CHKERRQ(ierr); 14400f2d7e86SMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 1441a0845e3aSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 14420f2d7e86SMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 1443a0845e3aSMatthew G. Knepley PetscInt i; 1444a0845e3aSMatthew G. Knepley 14458e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 1446a0845e3aSMatthew G. Knepley if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 1447a0845e3aSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 14480f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 1449a0845e3aSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 14500f2d7e86SMatthew G. Knepley if (X_t) { 14510f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 14520f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i]; 14530f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 14540f2d7e86SMatthew G. Knepley } 14559a559087SMatthew G. Knepley if (dmAux) { 14569a559087SMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 14570f2d7e86SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 14589a559087SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 1459a0845e3aSMatthew G. Knepley } 14609a559087SMatthew G. Knepley } 14610f2d7e86SMatthew G. Knepley ierr = PetscMemzero(elemMat, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr); 14620f2d7e86SMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 14630f2d7e86SMatthew G. Knepley PetscFE fe; 146421454ff5SMatthew G. Knepley PetscInt numQuadPoints, Nb; 1465a0845e3aSMatthew G. Knepley /* Conforming batches */ 1466f30c5766SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 1467a0845e3aSMatthew G. Knepley /* Remainder */ 1468a0845e3aSMatthew G. Knepley PetscInt Nr, offset; 1469a0845e3aSMatthew G. Knepley 14702764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 14710f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 14720f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 14730f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 14740f2d7e86SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 147521454ff5SMatthew G. Knepley blockSize = Nb*numQuadPoints; 1476a0845e3aSMatthew G. Knepley batchSize = numBlocks * blockSize; 14770f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 1478a0845e3aSMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 1479a0845e3aSMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 1480a0845e3aSMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 1481a0845e3aSMatthew G. Knepley offset = numCells - Nr; 14820f2d7e86SMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 1483a0845e3aSMatthew G. Knepley geom.v0 = v0; 1484a0845e3aSMatthew G. Knepley geom.J = J; 1485a0845e3aSMatthew G. Knepley geom.invJ = invJ; 1486a0845e3aSMatthew G. Knepley geom.detJ = detJ; 14870f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateJacobian(fe, prob, fieldI, fieldJ, Ne, geom, u, u_t, probAux, a, elemMat);CHKERRQ(ierr); 1488a0845e3aSMatthew G. Knepley geom.v0 = &v0[offset*dim]; 1489a0845e3aSMatthew G. Knepley geom.J = &J[offset*dim*dim]; 1490a0845e3aSMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 1491a0845e3aSMatthew G. Knepley geom.detJ = &detJ[offset]; 14920f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateJacobian(fe, prob, fieldI, fieldJ, Nr, geom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], &elemMat[offset*totDim*totDim]);CHKERRQ(ierr); 14930f2d7e86SMatthew G. Knepley } 1494a0845e3aSMatthew G. Knepley } 1495a0845e3aSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 14960f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, name, totDim, totDim, &elemMat[c*totDim*totDim]);CHKERRQ(ierr);} 14970f2d7e86SMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, globalSection, JacP, c, &elemMat[c*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 1498a0845e3aSMatthew G. Knepley } 14990f2d7e86SMatthew G. Knepley ierr = PetscFree7(u,u_t,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 15009a559087SMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 15010f2d7e86SMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr); 15020f2d7e86SMatthew G. Knepley ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 15031c093863SMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr); 15041c093863SMatthew G. Knepley ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 15051c093863SMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) { 15061c093863SMatthew G. Knepley const char *bdLabel; 15071c093863SMatthew G. Knepley DMLabel label; 15081c093863SMatthew G. Knepley IS pointIS; 15091c093863SMatthew G. Knepley const PetscInt *points; 15101c093863SMatthew G. Knepley const PetscInt *values; 15111c093863SMatthew G. Knepley PetscReal *n; 15121c093863SMatthew G. Knepley PetscInt field, numValues, numPoints, p, dep, numFaces; 15131c093863SMatthew G. Knepley PetscBool isEssential; 15141c093863SMatthew G. Knepley 151563d5297fSMatthew G. Knepley ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, &bdLabel, &field, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 15160f2d7e86SMatthew G. Knepley if (isEssential) continue; 15171c093863SMatthew G. Knepley if (numValues != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Bug me and I will fix this"); 15181c093863SMatthew G. Knepley ierr = DMPlexGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 15191c093863SMatthew G. Knepley ierr = DMLabelGetStratumSize(label, 1, &numPoints);CHKERRQ(ierr); 15201c093863SMatthew G. Knepley ierr = DMLabelGetStratumIS(label, 1, &pointIS);CHKERRQ(ierr); 15211c093863SMatthew G. Knepley ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 1522075da914SMatthew G. Knepley for (p = 0, numFaces = 0; p < numPoints; ++p) { 1523075da914SMatthew G. Knepley ierr = DMLabelGetValue(depth, points[p], &dep);CHKERRQ(ierr); 1524075da914SMatthew G. Knepley if (dep == dim-1) ++numFaces; 1525075da914SMatthew G. Knepley } 15260f2d7e86SMatthew G. Knepley ierr = PetscMalloc7(numFaces*totDimBd,&u,numFaces*dim,&v0,numFaces*dim,&n,numFaces*dim*dim,&J,numFaces*dim*dim,&invJ,numFaces,&detJ,numFaces*totDimBd*totDimBd,&elemMat);CHKERRQ(ierr); 15270f2d7e86SMatthew G. Knepley if (X_t) {ierr = PetscMalloc1(numFaces*totDimBd,&u_t);CHKERRQ(ierr);} 1528075da914SMatthew G. Knepley for (p = 0, f = 0; p < numPoints; ++p) { 1529f1ea0e2fSMatthew G. Knepley const PetscInt point = points[p]; 1530f1ea0e2fSMatthew G. Knepley PetscScalar *x = NULL; 1531f1ea0e2fSMatthew G. Knepley PetscInt i; 1532f1ea0e2fSMatthew G. Knepley 1533075da914SMatthew G. Knepley ierr = DMLabelGetValue(depth, points[p], &dep);CHKERRQ(ierr); 1534075da914SMatthew G. Knepley if (dep != dim-1) continue; 15358e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, point, NULL, &v0[f*dim], &J[f*dim*dim], &invJ[f*dim*dim], &detJ[f]);CHKERRQ(ierr); 1536a8007bbfSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFVM(dm, point, NULL, NULL, &n[f*dim]); 1537075da914SMatthew G. Knepley if (detJ[f] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for face %d", detJ[f], point); 1538f1ea0e2fSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, point, NULL, &x);CHKERRQ(ierr); 15390f2d7e86SMatthew G. Knepley for (i = 0; i < totDimBd; ++i) u[f*totDimBd+i] = x[i]; 1540f1ea0e2fSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, point, NULL, &x);CHKERRQ(ierr); 15410f2d7e86SMatthew G. Knepley if (X_t) { 1542af1eca97SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, point, NULL, &x);CHKERRQ(ierr); 15430f2d7e86SMatthew G. Knepley for (i = 0; i < totDimBd; ++i) u_t[f*totDimBd+i] = x[i]; 1544af1eca97SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, point, NULL, &x);CHKERRQ(ierr); 15450f2d7e86SMatthew G. Knepley } 1546af1eca97SMatthew G. Knepley ++f; 1547af1eca97SMatthew G. Knepley } 15480f2d7e86SMatthew G. Knepley ierr = PetscMemzero(elemMat, numFaces*totDimBd*totDimBd * sizeof(PetscScalar));CHKERRQ(ierr); 15490f2d7e86SMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 15500f2d7e86SMatthew G. Knepley PetscFE fe; 1551af1eca97SMatthew G. Knepley PetscInt numQuadPoints, Nb; 1552af1eca97SMatthew G. Knepley /* Conforming batches */ 1553af1eca97SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 1554af1eca97SMatthew G. Knepley /* Remainder */ 1555af1eca97SMatthew G. Knepley PetscInt Nr, offset; 1556af1eca97SMatthew G. Knepley 15572764a2aaSMatthew G. Knepley ierr = PetscDSGetBdDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 15580f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 15590f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 15600f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 156121454ff5SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 156221454ff5SMatthew G. Knepley blockSize = Nb*numQuadPoints; 15630483ade4SMatthew G. Knepley batchSize = numBlocks * blockSize; 15640f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 15650f2d7e86SMatthew G. Knepley numChunks = numFaces / (numBatches*batchSize); 15660483ade4SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 15670f2d7e86SMatthew G. Knepley Nr = numFaces % (numBatches*batchSize); 15680f2d7e86SMatthew G. Knepley offset = numFaces - Nr; 15690f2d7e86SMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 15700483ade4SMatthew G. Knepley geom.v0 = v0; 15710f2d7e86SMatthew G. Knepley geom.n = n; 15720483ade4SMatthew G. Knepley geom.J = J; 15730483ade4SMatthew G. Knepley geom.invJ = invJ; 15740483ade4SMatthew G. Knepley geom.detJ = detJ; 15750f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateBdJacobian(fe, prob, fieldI, fieldJ, Ne, geom, u, u_t, NULL, NULL, elemMat);CHKERRQ(ierr); 15760483ade4SMatthew G. Knepley geom.v0 = &v0[offset*dim]; 15770f2d7e86SMatthew G. Knepley geom.n = &n[offset*dim]; 15780483ade4SMatthew G. Knepley geom.J = &J[offset*dim*dim]; 15790483ade4SMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 15800483ade4SMatthew G. Knepley geom.detJ = &detJ[offset]; 15810f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateBdJacobian(fe, prob, fieldI, fieldJ, Nr, geom, &u[offset*totDimBd], u_t ? &u_t[offset*totDimBd] : NULL, NULL, NULL, &elemMat[offset*totDimBd*totDimBd]);CHKERRQ(ierr); 1582cb1e1211SMatthew G Knepley } 1583cb1e1211SMatthew G Knepley } 15840f2d7e86SMatthew G. Knepley for (p = 0, f = 0; p < numPoints; ++p) { 15850f2d7e86SMatthew G. Knepley const PetscInt point = points[p]; 1586cb1e1211SMatthew G Knepley 15870f2d7e86SMatthew G. Knepley ierr = DMLabelGetValue(depth, point, &dep);CHKERRQ(ierr); 15880f2d7e86SMatthew G. Knepley if (dep != dim-1) continue; 15890f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(point, "BdJacobian", totDimBd, totDimBd, &elemMat[f*totDimBd*totDimBd]);CHKERRQ(ierr);} 15900f2d7e86SMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, globalSection, JacP, point, &elemMat[f*totDimBd*totDimBd], ADD_VALUES);CHKERRQ(ierr); 15910f2d7e86SMatthew G. Knepley ++f; 1592cb1e1211SMatthew G Knepley } 15930f2d7e86SMatthew G. Knepley ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 15940f2d7e86SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 15950f2d7e86SMatthew G. Knepley ierr = PetscFree7(u,v0,n,J,invJ,detJ,elemMat);CHKERRQ(ierr); 15960f2d7e86SMatthew G. Knepley if (X_t) {ierr = PetscFree(u_t);CHKERRQ(ierr);} 1597cb1e1211SMatthew G Knepley } 15980f2d7e86SMatthew G. Knepley ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 15990f2d7e86SMatthew G. Knepley ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 16000f2d7e86SMatthew G. Knepley if (mesh->printFEM) { 16010f2d7e86SMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_WORLD, "%s:\n", name);CHKERRQ(ierr); 16020f2d7e86SMatthew G. Knepley ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 16030f2d7e86SMatthew G. Knepley ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 16040f2d7e86SMatthew G. Knepley } 16050f2d7e86SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 16060f2d7e86SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) Jac, MATSHELL, &isShell);CHKERRQ(ierr); 16070f2d7e86SMatthew G. Knepley if (isShell) { 16080f2d7e86SMatthew G. Knepley JacActionCtx *jctx; 16090f2d7e86SMatthew G. Knepley 16100f2d7e86SMatthew G. Knepley ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 16110f2d7e86SMatthew G. Knepley ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 16120f2d7e86SMatthew G. Knepley } 1613cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 1614cb1e1211SMatthew G Knepley } 1615cb1e1211SMatthew G Knepley 1616cb1e1211SMatthew G Knepley #undef __FUNCT__ 16170f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexSNESComputeJacobianFEM" 1618cb1e1211SMatthew G Knepley /*@ 16190f2d7e86SMatthew G. Knepley DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 1620cb1e1211SMatthew G Knepley 1621cb1e1211SMatthew G Knepley Input Parameters: 1622cb1e1211SMatthew G Knepley + dm - The mesh 1623cb1e1211SMatthew G Knepley . X - Local input vector 1624cb1e1211SMatthew G Knepley - user - The user context 1625cb1e1211SMatthew G Knepley 1626cb1e1211SMatthew G Knepley Output Parameter: 1627cb1e1211SMatthew G Knepley . Jac - Jacobian matrix 1628cb1e1211SMatthew G Knepley 1629cb1e1211SMatthew G Knepley Note: 16308026896cSMatthew G. Knepley The first member of the user context must be an FEMContext. 1631cb1e1211SMatthew G Knepley 1632cb1e1211SMatthew G Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 1633cb1e1211SMatthew G Knepley like a GPU, or vectorize on a multicore machine. 1634cb1e1211SMatthew G Knepley 16350059ad2aSSatish Balay Level: developer 16360059ad2aSSatish Balay 1637cb1e1211SMatthew G Knepley .seealso: FormFunctionLocal() 1638878cb397SSatish Balay @*/ 16390f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user) 1640cb1e1211SMatthew G Knepley { 1641cb1e1211SMatthew G Knepley PetscErrorCode ierr; 1642cb1e1211SMatthew G Knepley 1643cb1e1211SMatthew G Knepley PetscFunctionBegin; 16440f2d7e86SMatthew G. Knepley ierr = DMPlexComputeJacobianFEM_Internal(dm, X, NULL, Jac, JacP, user);CHKERRQ(ierr); 1645cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 1646cb1e1211SMatthew G Knepley } 1647bceba477SMatthew G. Knepley 1648d69c5d34SMatthew G. Knepley #undef __FUNCT__ 1649d69c5d34SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeInterpolatorFEM" 1650d69c5d34SMatthew G. Knepley /*@ 1651d69c5d34SMatthew G. Knepley DMPlexComputeInterpolatorFEM - Form the local portion of the interpolation matrix I from the coarse DM to the uniformly refined DM. 1652d69c5d34SMatthew G. Knepley 1653d69c5d34SMatthew G. Knepley Input Parameters: 1654d69c5d34SMatthew G. Knepley + dmf - The fine mesh 1655d69c5d34SMatthew G. Knepley . dmc - The coarse mesh 1656d69c5d34SMatthew G. Knepley - user - The user context 1657d69c5d34SMatthew G. Knepley 1658d69c5d34SMatthew G. Knepley Output Parameter: 1659934789fcSMatthew G. Knepley . In - The interpolation matrix 1660d69c5d34SMatthew G. Knepley 1661d69c5d34SMatthew G. Knepley Note: 1662d69c5d34SMatthew G. Knepley The first member of the user context must be an FEMContext. 1663d69c5d34SMatthew G. Knepley 1664d69c5d34SMatthew G. Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 1665d69c5d34SMatthew G. Knepley like a GPU, or vectorize on a multicore machine. 1666d69c5d34SMatthew G. Knepley 1667d69c5d34SMatthew G. Knepley Level: developer 1668d69c5d34SMatthew G. Knepley 1669d69c5d34SMatthew G. Knepley .seealso: DMPlexComputeJacobianFEM() 1670d69c5d34SMatthew G. Knepley @*/ 1671934789fcSMatthew G. Knepley PetscErrorCode DMPlexComputeInterpolatorFEM(DM dmc, DM dmf, Mat In, void *user) 1672d69c5d34SMatthew G. Knepley { 1673d69c5d34SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dmc->data; 1674d69c5d34SMatthew G. Knepley const char *name = "Interpolator"; 16752764a2aaSMatthew G. Knepley PetscDS prob; 1676d69c5d34SMatthew G. Knepley PetscFE *feRef; 1677d69c5d34SMatthew G. Knepley PetscSection fsection, fglobalSection; 1678d69c5d34SMatthew G. Knepley PetscSection csection, cglobalSection; 1679d69c5d34SMatthew G. Knepley PetscScalar *elemMat; 1680942a7a06SMatthew G. Knepley PetscInt dim, Nf, f, fieldI, fieldJ, offsetI, offsetJ, cStart, cEnd, c; 16810f2d7e86SMatthew G. Knepley PetscInt cTotDim, rTotDim = 0; 1682d69c5d34SMatthew G. Knepley PetscErrorCode ierr; 1683d69c5d34SMatthew G. Knepley 1684d69c5d34SMatthew G. Knepley PetscFunctionBegin; 1685d69c5d34SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1686c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 1687d69c5d34SMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 1688d69c5d34SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 1689d69c5d34SMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 1690d69c5d34SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 1691d69c5d34SMatthew G. Knepley ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 1692d69c5d34SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 16932764a2aaSMatthew G. Knepley ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr); 1694d69c5d34SMatthew G. Knepley ierr = PetscMalloc1(Nf,&feRef);CHKERRQ(ierr); 1695d69c5d34SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 16960f2d7e86SMatthew G. Knepley PetscFE fe; 16970f2d7e86SMatthew G. Knepley PetscInt rNb, Nc; 1698d69c5d34SMatthew G. Knepley 16992764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 17000f2d7e86SMatthew G. Knepley ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 1701d69c5d34SMatthew G. Knepley ierr = PetscFEGetDimension(feRef[f], &rNb);CHKERRQ(ierr); 17020f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 17030f2d7e86SMatthew G. Knepley rTotDim += rNb*Nc; 1704d69c5d34SMatthew G. Knepley } 17052764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 17060f2d7e86SMatthew G. Knepley ierr = PetscMalloc1(rTotDim*cTotDim,&elemMat);CHKERRQ(ierr); 17070f2d7e86SMatthew G. Knepley ierr = PetscMemzero(elemMat, rTotDim*cTotDim * sizeof(PetscScalar));CHKERRQ(ierr); 1708d69c5d34SMatthew G. Knepley for (fieldI = 0, offsetI = 0; fieldI < Nf; ++fieldI) { 1709d69c5d34SMatthew G. Knepley PetscDualSpace Qref; 1710d69c5d34SMatthew G. Knepley PetscQuadrature f; 1711d69c5d34SMatthew G. Knepley const PetscReal *qpoints, *qweights; 1712d69c5d34SMatthew G. Knepley PetscReal *points; 1713d69c5d34SMatthew G. Knepley PetscInt npoints = 0, Nc, Np, fpdim, i, k, p, d; 1714d69c5d34SMatthew G. Knepley 1715d69c5d34SMatthew G. Knepley /* Compose points from all dual basis functionals */ 1716d69c5d34SMatthew G. Knepley ierr = PetscFEGetDualSpace(feRef[fieldI], &Qref);CHKERRQ(ierr); 17170f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(feRef[fieldI], &Nc);CHKERRQ(ierr); 1718d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Qref, &fpdim);CHKERRQ(ierr); 1719d69c5d34SMatthew G. Knepley for (i = 0; i < fpdim; ++i) { 1720d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1721d69c5d34SMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &Np, NULL, NULL);CHKERRQ(ierr); 1722d69c5d34SMatthew G. Knepley npoints += Np; 1723d69c5d34SMatthew G. Knepley } 1724d69c5d34SMatthew G. Knepley ierr = PetscMalloc1(npoints*dim,&points);CHKERRQ(ierr); 1725d69c5d34SMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) { 1726d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1727d69c5d34SMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &Np, &qpoints, NULL);CHKERRQ(ierr); 1728d69c5d34SMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) for (d = 0; d < dim; ++d) points[k*dim+d] = qpoints[p*dim+d]; 1729d69c5d34SMatthew G. Knepley } 1730d69c5d34SMatthew G. Knepley 1731d69c5d34SMatthew G. Knepley for (fieldJ = 0, offsetJ = 0; fieldJ < Nf; ++fieldJ) { 17320f2d7e86SMatthew G. Knepley PetscFE fe; 1733d69c5d34SMatthew G. Knepley PetscReal *B; 173436a6d9c0SMatthew G. Knepley PetscInt NcJ, cpdim, j; 1735d69c5d34SMatthew G. Knepley 1736d69c5d34SMatthew G. Knepley /* Evaluate basis at points */ 17372764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldJ, (PetscObject *) &fe);CHKERRQ(ierr); 17380f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &NcJ);CHKERRQ(ierr); 17390f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &cpdim);CHKERRQ(ierr); 1740ffe73a53SMatthew G. Knepley /* For now, fields only interpolate themselves */ 1741ffe73a53SMatthew G. Knepley if (fieldI == fieldJ) { 17427c927364SMatthew 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); 17430f2d7e86SMatthew G. Knepley ierr = PetscFEGetTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr); 1744d69c5d34SMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) { 1745d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1746d69c5d34SMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &Np, NULL, &qweights);CHKERRQ(ierr); 1747d69c5d34SMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) { 174836a6d9c0SMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 17490f2d7e86SMatthew G. Knepley for (c = 0; c < Nc; ++c) elemMat[(offsetI + i*Nc + c)*cTotDim + offsetJ + j*NcJ + c] += B[k*cpdim*NcJ+j*Nc+c]*qweights[p]; 175036a6d9c0SMatthew G. Knepley } 1751d69c5d34SMatthew G. Knepley } 1752d69c5d34SMatthew G. Knepley } 17530f2d7e86SMatthew G. Knepley ierr = PetscFERestoreTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr);CHKERRQ(ierr); 1754ffe73a53SMatthew G. Knepley } 175536a6d9c0SMatthew G. Knepley offsetJ += cpdim*NcJ; 1756d69c5d34SMatthew G. Knepley } 1757d69c5d34SMatthew G. Knepley offsetI += fpdim*Nc; 1758549a8adaSMatthew G. Knepley ierr = PetscFree(points);CHKERRQ(ierr); 1759d69c5d34SMatthew G. Knepley } 17600f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(0, name, rTotDim, cTotDim, elemMat);CHKERRQ(ierr);} 17617f5b169aSMatthew G. Knepley /* Preallocate matrix */ 17627f5b169aSMatthew G. Knepley { 17637f5b169aSMatthew G. Knepley PetscHashJK ht; 17647f5b169aSMatthew G. Knepley PetscLayout rLayout; 17657f5b169aSMatthew G. Knepley PetscInt *dnz, *onz, *cellCIndices, *cellFIndices; 17667f5b169aSMatthew G. Knepley PetscInt locRows, rStart, rEnd, cell, r; 17677f5b169aSMatthew G. Knepley 17687f5b169aSMatthew G. Knepley ierr = MatGetLocalSize(In, &locRows, NULL);CHKERRQ(ierr); 17697f5b169aSMatthew G. Knepley ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) In), &rLayout);CHKERRQ(ierr); 17707f5b169aSMatthew G. Knepley ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 17717f5b169aSMatthew G. Knepley ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 17727f5b169aSMatthew G. Knepley ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 17737f5b169aSMatthew G. Knepley ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 17747f5b169aSMatthew G. Knepley ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 17757f5b169aSMatthew G. Knepley ierr = PetscCalloc4(locRows,&dnz,locRows,&onz,cTotDim,&cellCIndices,rTotDim,&cellFIndices);CHKERRQ(ierr); 17767f5b169aSMatthew G. Knepley ierr = PetscHashJKCreate(&ht);CHKERRQ(ierr); 17777f5b169aSMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 17787f5b169aSMatthew G. Knepley ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, cell, cellCIndices, cellFIndices);CHKERRQ(ierr); 17797f5b169aSMatthew G. Knepley for (r = 0; r < rTotDim; ++r) { 17807f5b169aSMatthew G. Knepley PetscHashJKKey key; 17817f5b169aSMatthew G. Knepley PetscHashJKIter missing, iter; 17827f5b169aSMatthew G. Knepley 17837f5b169aSMatthew G. Knepley key.j = cellFIndices[r]; 17847f5b169aSMatthew G. Knepley if (key.j < 0) continue; 17857f5b169aSMatthew G. Knepley for (c = 0; c < cTotDim; ++c) { 17867f5b169aSMatthew G. Knepley key.k = cellCIndices[c]; 17877f5b169aSMatthew G. Knepley if (key.k < 0) continue; 17887f5b169aSMatthew G. Knepley ierr = PetscHashJKPut(ht, key, &missing, &iter);CHKERRQ(ierr); 17897f5b169aSMatthew G. Knepley if (missing) { 17907f5b169aSMatthew G. Knepley ierr = PetscHashJKSet(ht, iter, 1);CHKERRQ(ierr); 17917f5b169aSMatthew G. Knepley if ((key.k >= rStart) && (key.k < rEnd)) ++dnz[key.j-rStart]; 17927f5b169aSMatthew G. Knepley else ++onz[key.j-rStart]; 17937f5b169aSMatthew G. Knepley } 17947f5b169aSMatthew G. Knepley } 17957f5b169aSMatthew G. Knepley } 17967f5b169aSMatthew G. Knepley } 17977f5b169aSMatthew G. Knepley ierr = PetscHashJKDestroy(&ht);CHKERRQ(ierr); 17987f5b169aSMatthew G. Knepley ierr = MatXAIJSetPreallocation(In, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr); 17997f5b169aSMatthew G. Knepley ierr = MatSetOption(In, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 18007f5b169aSMatthew G. Knepley ierr = PetscFree4(dnz,onz,cellCIndices,cellFIndices);CHKERRQ(ierr); 18017f5b169aSMatthew G. Knepley } 18027f5b169aSMatthew G. Knepley /* Fill matrix */ 18037f5b169aSMatthew G. Knepley ierr = MatZeroEntries(In);CHKERRQ(ierr); 1804d69c5d34SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1805934789fcSMatthew G. Knepley ierr = DMPlexMatSetClosureRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, In, c, elemMat, INSERT_VALUES);CHKERRQ(ierr); 1806d69c5d34SMatthew G. Knepley } 1807549a8adaSMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);} 1808d69c5d34SMatthew G. Knepley ierr = PetscFree(feRef);CHKERRQ(ierr); 1809549a8adaSMatthew G. Knepley ierr = PetscFree(elemMat);CHKERRQ(ierr); 1810934789fcSMatthew G. Knepley ierr = MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1811934789fcSMatthew G. Knepley ierr = MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1812d69c5d34SMatthew G. Knepley if (mesh->printFEM) { 1813d69c5d34SMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_WORLD, "%s:\n", name);CHKERRQ(ierr); 1814934789fcSMatthew G. Knepley ierr = MatChop(In, 1.0e-10);CHKERRQ(ierr); 1815934789fcSMatthew G. Knepley ierr = MatView(In, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1816d69c5d34SMatthew G. Knepley } 1817d69c5d34SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1818d69c5d34SMatthew G. Knepley PetscFunctionReturn(0); 1819d69c5d34SMatthew G. Knepley } 18206c73c22cSMatthew G. Knepley 18216c73c22cSMatthew G. Knepley #undef __FUNCT__ 18227c927364SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeInjectorFEM" 18237c927364SMatthew G. Knepley PetscErrorCode DMPlexComputeInjectorFEM(DM dmc, DM dmf, VecScatter *sc, void *user) 18247c927364SMatthew G. Knepley { 1825e9d4ef1bSMatthew G. Knepley PetscDS prob; 18267c927364SMatthew G. Knepley PetscFE *feRef; 18277c927364SMatthew G. Knepley Vec fv, cv; 18287c927364SMatthew G. Knepley IS fis, cis; 18297c927364SMatthew G. Knepley PetscSection fsection, fglobalSection, csection, cglobalSection; 18307c927364SMatthew G. Knepley PetscInt *cmap, *cellCIndices, *cellFIndices, *cindices, *findices; 18317c927364SMatthew G. Knepley PetscInt cTotDim, fTotDim = 0, Nf, f, field, cStart, cEnd, c, dim, d, startC, offsetC, offsetF, m; 18327c927364SMatthew G. Knepley PetscErrorCode ierr; 18337c927364SMatthew G. Knepley 18347c927364SMatthew G. Knepley PetscFunctionBegin; 183575a69067SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1836c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 18377c927364SMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 18387c927364SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 18397c927364SMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 18407c927364SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 18417c927364SMatthew G. Knepley ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 18427c927364SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 1843e9d4ef1bSMatthew G. Knepley ierr = DMGetDS(dmc, &prob);CHKERRQ(ierr); 18447c927364SMatthew G. Knepley ierr = PetscMalloc1(Nf,&feRef);CHKERRQ(ierr); 18457c927364SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 18467c927364SMatthew G. Knepley PetscFE fe; 18477c927364SMatthew G. Knepley PetscInt fNb, Nc; 18487c927364SMatthew G. Knepley 1849e9d4ef1bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 18507c927364SMatthew G. Knepley ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 18517c927364SMatthew G. Knepley ierr = PetscFEGetDimension(feRef[f], &fNb);CHKERRQ(ierr); 18527c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 18537c927364SMatthew G. Knepley fTotDim += fNb*Nc; 18547c927364SMatthew G. Knepley } 1855e9d4ef1bSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 18567c927364SMatthew G. Knepley ierr = PetscMalloc1(cTotDim,&cmap);CHKERRQ(ierr); 18577c927364SMatthew G. Knepley for (field = 0, offsetC = 0, offsetF = 0; field < Nf; ++field) { 18587c927364SMatthew G. Knepley PetscFE feC; 18597c927364SMatthew G. Knepley PetscDualSpace QF, QC; 18607c927364SMatthew G. Knepley PetscInt NcF, NcC, fpdim, cpdim; 18617c927364SMatthew G. Knepley 1862e9d4ef1bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &feC);CHKERRQ(ierr); 18637c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(feC, &NcC);CHKERRQ(ierr); 18647c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(feRef[field], &NcF);CHKERRQ(ierr); 18657c927364SMatthew 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); 18667c927364SMatthew G. Knepley ierr = PetscFEGetDualSpace(feRef[field], &QF);CHKERRQ(ierr); 18677c927364SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QF, &fpdim);CHKERRQ(ierr); 18687c927364SMatthew G. Knepley ierr = PetscFEGetDualSpace(feC, &QC);CHKERRQ(ierr); 18697c927364SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QC, &cpdim);CHKERRQ(ierr); 18707c927364SMatthew G. Knepley for (c = 0; c < cpdim; ++c) { 18717c927364SMatthew G. Knepley PetscQuadrature cfunc; 18727c927364SMatthew G. Knepley const PetscReal *cqpoints; 18737c927364SMatthew G. Knepley PetscInt NpC; 18747c927364SMatthew G. Knepley 18757c927364SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(QC, c, &cfunc);CHKERRQ(ierr); 18767c927364SMatthew G. Knepley ierr = PetscQuadratureGetData(cfunc, NULL, &NpC, &cqpoints, NULL);CHKERRQ(ierr); 18777c927364SMatthew G. Knepley if (NpC != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not know how to do injection for moments"); 18787c927364SMatthew G. Knepley for (f = 0; f < fpdim; ++f) { 18797c927364SMatthew G. Knepley PetscQuadrature ffunc; 18807c927364SMatthew G. Knepley const PetscReal *fqpoints; 18817c927364SMatthew G. Knepley PetscReal sum = 0.0; 18827c927364SMatthew G. Knepley PetscInt NpF, comp; 18837c927364SMatthew G. Knepley 18847c927364SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(QF, f, &ffunc);CHKERRQ(ierr); 18857c927364SMatthew G. Knepley ierr = PetscQuadratureGetData(ffunc, NULL, &NpF, &fqpoints, NULL);CHKERRQ(ierr); 18867c927364SMatthew G. Knepley if (NpC != NpF) continue; 18877c927364SMatthew G. Knepley for (d = 0; d < dim; ++d) sum += PetscAbsReal(cqpoints[d] - fqpoints[d]); 18887c927364SMatthew G. Knepley if (sum > 1.0e-9) continue; 18897c927364SMatthew G. Knepley for (comp = 0; comp < NcC; ++comp) { 18907c927364SMatthew G. Knepley cmap[(offsetC+c)*NcC+comp] = (offsetF+f)*NcF+comp; 18917c927364SMatthew G. Knepley } 18927c927364SMatthew G. Knepley break; 18937c927364SMatthew G. Knepley } 18947c927364SMatthew G. Knepley } 18957c927364SMatthew G. Knepley offsetC += cpdim*NcC; 18967c927364SMatthew G. Knepley offsetF += fpdim*NcF; 18977c927364SMatthew G. Knepley } 18987c927364SMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);} 18997c927364SMatthew G. Knepley ierr = PetscFree(feRef);CHKERRQ(ierr); 19007c927364SMatthew G. Knepley 19017c927364SMatthew G. Knepley ierr = DMGetGlobalVector(dmf, &fv);CHKERRQ(ierr); 19027c927364SMatthew G. Knepley ierr = DMGetGlobalVector(dmc, &cv);CHKERRQ(ierr); 19037c927364SMatthew G. Knepley ierr = VecGetOwnershipRange(cv, &startC, NULL);CHKERRQ(ierr); 19047c927364SMatthew G. Knepley ierr = PetscSectionGetConstrainedStorageSize(cglobalSection, &m);CHKERRQ(ierr); 19057c927364SMatthew G. Knepley ierr = PetscMalloc2(cTotDim,&cellCIndices,fTotDim,&cellFIndices);CHKERRQ(ierr); 1906aa7da3c4SMatthew G. Knepley ierr = PetscMalloc1(m,&cindices);CHKERRQ(ierr); 1907aa7da3c4SMatthew G. Knepley ierr = PetscMalloc1(m,&findices);CHKERRQ(ierr); 19087c927364SMatthew G. Knepley for (d = 0; d < m; ++d) cindices[d] = findices[d] = -1; 19097c927364SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 19107c927364SMatthew G. Knepley ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, c, cellCIndices, cellFIndices);CHKERRQ(ierr); 19117c927364SMatthew G. Knepley for (d = 0; d < cTotDim; ++d) { 19127c927364SMatthew G. Knepley if (cellCIndices[d] < 0) continue; 19137c927364SMatthew 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]]); 19147c927364SMatthew G. Knepley cindices[cellCIndices[d]-startC] = cellCIndices[d]; 19157c927364SMatthew G. Knepley findices[cellCIndices[d]-startC] = cellFIndices[cmap[d]]; 19167c927364SMatthew G. Knepley } 19177c927364SMatthew G. Knepley } 19187c927364SMatthew G. Knepley ierr = PetscFree(cmap);CHKERRQ(ierr); 19197c927364SMatthew G. Knepley ierr = PetscFree2(cellCIndices,cellFIndices);CHKERRQ(ierr); 19207c927364SMatthew G. Knepley 19217c927364SMatthew G. Knepley ierr = ISCreateGeneral(PETSC_COMM_SELF, m, cindices, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 19227c927364SMatthew G. Knepley ierr = ISCreateGeneral(PETSC_COMM_SELF, m, findices, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 19237c927364SMatthew G. Knepley ierr = VecScatterCreate(cv, cis, fv, fis, sc);CHKERRQ(ierr); 19247c927364SMatthew G. Knepley ierr = ISDestroy(&cis);CHKERRQ(ierr); 19257c927364SMatthew G. Knepley ierr = ISDestroy(&fis);CHKERRQ(ierr); 19267c927364SMatthew G. Knepley ierr = DMRestoreGlobalVector(dmf, &fv);CHKERRQ(ierr); 19277c927364SMatthew G. Knepley ierr = DMRestoreGlobalVector(dmc, &cv);CHKERRQ(ierr); 192875a69067SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1929cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 1930cb1e1211SMatthew G Knepley } 1931cb1e1211SMatthew G Knepley 1932cb1e1211SMatthew G Knepley #undef __FUNCT__ 19338e136ac0SMatthew G. Knepley #define __FUNCT__ "BoundaryDuplicate" 19348e136ac0SMatthew G. Knepley static PetscErrorCode BoundaryDuplicate(DMBoundary bd, DMBoundary *boundary) 19358e136ac0SMatthew G. Knepley { 19368e136ac0SMatthew G. Knepley DMBoundary b = bd, b2, bold = NULL; 19378e136ac0SMatthew G. Knepley PetscErrorCode ierr; 19388e136ac0SMatthew G. Knepley 19398e136ac0SMatthew G. Knepley PetscFunctionBegin; 19408e136ac0SMatthew G. Knepley *boundary = NULL; 19418e136ac0SMatthew G. Knepley for (; b; b = b->next, bold = b2) { 19428e136ac0SMatthew G. Knepley ierr = PetscNew(&b2);CHKERRQ(ierr); 19438e136ac0SMatthew G. Knepley ierr = PetscStrallocpy(b->name, (char **) &b2->name);CHKERRQ(ierr); 19448e136ac0SMatthew G. Knepley ierr = PetscStrallocpy(b->labelname, (char **) &b2->labelname);CHKERRQ(ierr); 19458e136ac0SMatthew G. Knepley ierr = PetscMalloc1(b->numids, &b2->ids);CHKERRQ(ierr); 19468e136ac0SMatthew G. Knepley ierr = PetscMemcpy(b2->ids, b->ids, b->numids*sizeof(PetscInt));CHKERRQ(ierr); 19478e136ac0SMatthew G. Knepley b2->label = NULL; 19488e136ac0SMatthew G. Knepley b2->essential = b->essential; 19498e136ac0SMatthew G. Knepley b2->field = b->field; 19508e136ac0SMatthew G. Knepley b2->func = b->func; 19518e136ac0SMatthew G. Knepley b2->numids = b->numids; 19528e136ac0SMatthew G. Knepley b2->ctx = b->ctx; 19538e136ac0SMatthew G. Knepley b2->next = NULL; 19548e136ac0SMatthew G. Knepley if (!*boundary) *boundary = b2; 19558e136ac0SMatthew G. Knepley if (bold) bold->next = b2; 19568e136ac0SMatthew G. Knepley } 19578e136ac0SMatthew G. Knepley PetscFunctionReturn(0); 19588e136ac0SMatthew G. Knepley } 19598e136ac0SMatthew G. Knepley 19608e136ac0SMatthew G. Knepley #undef __FUNCT__ 19618e136ac0SMatthew G. Knepley #define __FUNCT__ "DMPlexCopyBoundary" 19628e136ac0SMatthew G. Knepley PetscErrorCode DMPlexCopyBoundary(DM dm, DM dmNew) 19638e136ac0SMatthew G. Knepley { 19648e136ac0SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 19658e136ac0SMatthew G. Knepley DM_Plex *meshNew = (DM_Plex *) dmNew->data; 19668e136ac0SMatthew G. Knepley DMBoundary b; 19678e136ac0SMatthew G. Knepley PetscErrorCode ierr; 19688e136ac0SMatthew G. Knepley 19698e136ac0SMatthew G. Knepley PetscFunctionBegin; 19708e136ac0SMatthew G. Knepley ierr = BoundaryDuplicate(mesh->boundary, &meshNew->boundary);CHKERRQ(ierr); 19718e136ac0SMatthew G. Knepley for (b = meshNew->boundary; b; b = b->next) { 19728e136ac0SMatthew G. Knepley if (b->labelname) { 19738e136ac0SMatthew G. Knepley ierr = DMPlexGetLabel(dmNew, b->labelname, &b->label);CHKERRQ(ierr); 19748e136ac0SMatthew G. Knepley if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 19758e136ac0SMatthew G. Knepley } 19768e136ac0SMatthew G. Knepley } 19778e136ac0SMatthew G. Knepley PetscFunctionReturn(0); 19788e136ac0SMatthew G. Knepley } 19798e136ac0SMatthew G. Knepley 19808e136ac0SMatthew G. Knepley #undef __FUNCT__ 1981cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexAddBoundary" 1982cb1e1211SMatthew G Knepley /* The ids can be overridden by the command line option -bc_<boundary name> */ 198363d5297fSMatthew G. Knepley PetscErrorCode DMPlexAddBoundary(DM dm, PetscBool isEssential, const char name[], const char labelname[], PetscInt field, void (*bcFunc)(), PetscInt numids, const PetscInt *ids, void *ctx) 1984cb1e1211SMatthew G Knepley { 1985cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1986cb1e1211SMatthew G Knepley DMBoundary b; 1987cb1e1211SMatthew G Knepley PetscErrorCode ierr; 1988cb1e1211SMatthew G Knepley 1989cb1e1211SMatthew G Knepley PetscFunctionBegin; 199063d5297fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1991cb1e1211SMatthew G Knepley ierr = PetscNew(&b);CHKERRQ(ierr); 1992cb1e1211SMatthew G Knepley ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 199363d5297fSMatthew G. Knepley ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr); 1994cb1e1211SMatthew G Knepley ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr); 1995cb1e1211SMatthew G Knepley ierr = PetscMemcpy(b->ids, ids, numids*sizeof(PetscInt));CHKERRQ(ierr); 199663d5297fSMatthew G. Knepley if (b->labelname) { 199763d5297fSMatthew G. Knepley ierr = DMPlexGetLabel(dm, b->labelname, &b->label);CHKERRQ(ierr); 199863d5297fSMatthew G. Knepley if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 199963d5297fSMatthew G. Knepley } 2000cb1e1211SMatthew G Knepley b->essential = isEssential; 2001cb1e1211SMatthew G Knepley b->field = field; 2002cb1e1211SMatthew G Knepley b->func = bcFunc; 2003cb1e1211SMatthew G Knepley b->numids = numids; 2004cb1e1211SMatthew G Knepley b->ctx = ctx; 2005cb1e1211SMatthew G Knepley b->next = mesh->boundary; 2006cb1e1211SMatthew G Knepley mesh->boundary = b; 2007cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 2008cb1e1211SMatthew G Knepley } 2009cb1e1211SMatthew G Knepley 2010cb1e1211SMatthew G Knepley #undef __FUNCT__ 2011cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexGetNumBoundary" 2012cb1e1211SMatthew G Knepley PetscErrorCode DMPlexGetNumBoundary(DM dm, PetscInt *numBd) 2013cb1e1211SMatthew G Knepley { 2014cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 2015cb1e1211SMatthew G Knepley DMBoundary b = mesh->boundary; 2016cb1e1211SMatthew G Knepley 2017cb1e1211SMatthew G Knepley PetscFunctionBegin; 201863d5297fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 201963d5297fSMatthew G. Knepley PetscValidPointer(numBd, 2); 2020cb1e1211SMatthew G Knepley *numBd = 0; 2021cb1e1211SMatthew G Knepley while (b) {++(*numBd); b = b->next;} 2022cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 2023cb1e1211SMatthew G Knepley } 2024cb1e1211SMatthew G Knepley 2025cb1e1211SMatthew G Knepley #undef __FUNCT__ 2026cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexGetBoundary" 202763d5297fSMatthew G. Knepley PetscErrorCode DMPlexGetBoundary(DM dm, PetscInt bd, PetscBool *isEssential, const char **name, const char **labelname, PetscInt *field, void (**func)(), PetscInt *numids, const PetscInt **ids, void **ctx) 2028cb1e1211SMatthew G Knepley { 2029cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 2030cb1e1211SMatthew G Knepley DMBoundary b = mesh->boundary; 2031cb1e1211SMatthew G Knepley PetscInt n = 0; 2032cb1e1211SMatthew G Knepley 2033cb1e1211SMatthew G Knepley PetscFunctionBegin; 203463d5297fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2035cb1e1211SMatthew G Knepley while (b) { 2036cb1e1211SMatthew G Knepley if (n == bd) break; 2037cb1e1211SMatthew G Knepley b = b->next; 2038cb1e1211SMatthew G Knepley ++n; 2039cb1e1211SMatthew G Knepley } 2040cb1e1211SMatthew G Knepley if (n != bd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n); 2041cb1e1211SMatthew G Knepley if (isEssential) { 2042cb1e1211SMatthew G Knepley PetscValidPointer(isEssential, 3); 2043cb1e1211SMatthew G Knepley *isEssential = b->essential; 2044cb1e1211SMatthew G Knepley } 2045cb1e1211SMatthew G Knepley if (name) { 2046cb1e1211SMatthew G Knepley PetscValidPointer(name, 4); 2047cb1e1211SMatthew G Knepley *name = b->name; 2048cb1e1211SMatthew G Knepley } 204963d5297fSMatthew G. Knepley if (labelname) { 205063d5297fSMatthew G. Knepley PetscValidPointer(labelname, 5); 205163d5297fSMatthew G. Knepley *labelname = b->labelname; 205263d5297fSMatthew G. Knepley } 2053cb1e1211SMatthew G Knepley if (field) { 205463d5297fSMatthew G. Knepley PetscValidPointer(field, 6); 2055cb1e1211SMatthew G Knepley *field = b->field; 2056cb1e1211SMatthew G Knepley } 2057cb1e1211SMatthew G Knepley if (func) { 205863d5297fSMatthew G. Knepley PetscValidPointer(func, 7); 2059cb1e1211SMatthew G Knepley *func = b->func; 2060cb1e1211SMatthew G Knepley } 2061cb1e1211SMatthew G Knepley if (numids) { 206263d5297fSMatthew G. Knepley PetscValidPointer(numids, 8); 2063cb1e1211SMatthew G Knepley *numids = b->numids; 2064cb1e1211SMatthew G Knepley } 2065cb1e1211SMatthew G Knepley if (ids) { 206663d5297fSMatthew G. Knepley PetscValidPointer(ids, 9); 2067cb1e1211SMatthew G Knepley *ids = b->ids; 2068cb1e1211SMatthew G Knepley } 2069cb1e1211SMatthew G Knepley if (ctx) { 207063d5297fSMatthew G. Knepley PetscValidPointer(ctx, 10); 2071cb1e1211SMatthew G Knepley *ctx = b->ctx; 2072cb1e1211SMatthew G Knepley } 2073cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 2074cb1e1211SMatthew G Knepley } 20750225b034SMatthew G. Knepley 20760225b034SMatthew G. Knepley #undef __FUNCT__ 20770225b034SMatthew G. Knepley #define __FUNCT__ "DMPlexIsBoundaryPoint" 20780225b034SMatthew G. Knepley PetscErrorCode DMPlexIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 20790225b034SMatthew G. Knepley { 20800225b034SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 20810225b034SMatthew G. Knepley DMBoundary b = mesh->boundary; 20820225b034SMatthew G. Knepley PetscErrorCode ierr; 20830225b034SMatthew G. Knepley 20840225b034SMatthew G. Knepley PetscFunctionBegin; 20850225b034SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20860225b034SMatthew G. Knepley PetscValidPointer(isBd, 3); 20870225b034SMatthew G. Knepley *isBd = PETSC_FALSE; 20880225b034SMatthew G. Knepley while (b && !(*isBd)) { 20890225b034SMatthew G. Knepley if (b->label) { 20900225b034SMatthew G. Knepley PetscInt i; 20910225b034SMatthew G. Knepley 20920225b034SMatthew G. Knepley for (i = 0; i < b->numids && !(*isBd); ++i) { 20930225b034SMatthew G. Knepley ierr = DMLabelStratumHasPoint(b->label, b->ids[i], point, isBd);CHKERRQ(ierr); 20940225b034SMatthew G. Knepley } 20950225b034SMatthew G. Knepley } 20960225b034SMatthew G. Knepley b = b->next; 20970225b034SMatthew G. Knepley } 20980225b034SMatthew G. Knepley PetscFunctionReturn(0); 20990225b034SMatthew G. Knepley } 2100