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 201*048b7b1eSToby Isaac .seealso: DMPlexGetMaxProjectionHeight(), 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 227*048b7b1eSToby Isaac .seealso: DMPlexSetMaxProjectionHeight(), 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 { 2437d1dd11eSToby 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; 2487d1dd11eSToby 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); 2567d1dd11eSToby Isaac ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 2577d1dd11eSToby Isaac if (maxHeight < 0 || maxHeight > dim) {SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"maximum projection height %d not in [0, %d)\n", maxHeight,dim);} 2587d1dd11eSToby Isaac if (maxHeight > 0) { 2597d1dd11eSToby Isaac ierr = PetscMalloc1(numFields,&cellsp);CHKERRQ(ierr); 2607d1dd11eSToby Isaac } 261*048b7b1eSToby Isaac else { 262*048b7b1eSToby Isaac cellsp = sp; 263*048b7b1eSToby Isaac } 2647d1dd11eSToby Isaac for (h = 0; h <= maxHeight; h++) { 2657d1dd11eSToby Isaac ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2667d1dd11eSToby Isaac if (pEnd <= pStart) continue; 2677d1dd11eSToby Isaac totDim = 0; 268a18a7fb9SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 2697d1dd11eSToby Isaac if (!h) { 2707d1dd11eSToby Isaac ierr = PetscFEGetDualSpace(fe[f], &cellsp[f]);CHKERRQ(ierr); 2717d1dd11eSToby Isaac sp[f] = cellsp[f]; 2727d1dd11eSToby Isaac } 2737d1dd11eSToby Isaac else { 2747d1dd11eSToby Isaac ierr = PetscDualSpaceGetHeightSubspace(cellsp[f], h, &sp[f]);CHKERRQ(ierr); 2757d1dd11eSToby Isaac if (!sp[f]) continue; 2767d1dd11eSToby Isaac } 277a18a7fb9SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe[f], &numComp);CHKERRQ(ierr); 278a18a7fb9SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 279a18a7fb9SMatthew G. Knepley totDim += spDim*numComp; 280a18a7fb9SMatthew G. Knepley } 2817d1dd11eSToby Isaac ierr = DMPlexVecGetClosure(dm, section, localX, pStart, &numValues, NULL);CHKERRQ(ierr); 2827d1dd11eSToby Isaac if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section point closure size %d != dual space dimension %d", numValues, totDim); 283a18a7fb9SMatthew G. Knepley ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 284ad96f515SMatthew G. Knepley ierr = DMGetWorkArray(dm, numFields, PETSC_BOOL, &fieldActive);CHKERRQ(ierr); 285ad96f515SMatthew G. Knepley for (f = 0; f < numFields; ++f) fieldActive[f] = funcs[f] ? PETSC_TRUE : PETSC_FALSE; 286a18a7fb9SMatthew G. Knepley for (i = 0; i < numIds; ++i) { 287a18a7fb9SMatthew G. Knepley IS pointIS; 288a18a7fb9SMatthew G. Knepley const PetscInt *points; 289a18a7fb9SMatthew G. Knepley PetscInt n, p; 290a18a7fb9SMatthew G. Knepley 291a18a7fb9SMatthew G. Knepley ierr = DMLabelGetStratumIS(label, ids[i], &pointIS);CHKERRQ(ierr); 292a18a7fb9SMatthew G. Knepley ierr = ISGetLocalSize(pointIS, &n);CHKERRQ(ierr); 293a18a7fb9SMatthew G. Knepley ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 294a18a7fb9SMatthew G. Knepley for (p = 0; p < n; ++p) { 295a18a7fb9SMatthew G. Knepley const PetscInt point = points[p]; 296a18a7fb9SMatthew G. Knepley PetscCellGeometry geom; 297a18a7fb9SMatthew G. Knepley 2987d1dd11eSToby Isaac if ((point < pStart) || (point >= pEnd)) continue; 2998e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, point, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 300a18a7fb9SMatthew G. Knepley geom.v0 = v0; 301a18a7fb9SMatthew G. Knepley geom.J = J; 302a18a7fb9SMatthew G. Knepley geom.detJ = &detJ; 303a18a7fb9SMatthew G. Knepley for (f = 0, v = 0; f < numFields; ++f) { 304a18a7fb9SMatthew G. Knepley void * const ctx = ctxs ? ctxs[f] : NULL; 3057d1dd11eSToby Isaac if (!sp[f]) continue; 306a18a7fb9SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe[f], &numComp);CHKERRQ(ierr); 307a18a7fb9SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 308a18a7fb9SMatthew G. Knepley for (d = 0; d < spDim; ++d) { 309a18a7fb9SMatthew G. Knepley if (funcs[f]) { 310a18a7fb9SMatthew G. Knepley ierr = PetscDualSpaceApply(sp[f], d, geom, numComp, funcs[f], ctx, &values[v]);CHKERRQ(ierr); 311a18a7fb9SMatthew G. Knepley } else { 312a18a7fb9SMatthew G. Knepley for (comp = 0; comp < numComp; ++comp) values[v+comp] = 0.0; 313a18a7fb9SMatthew G. Knepley } 314a18a7fb9SMatthew G. Knepley v += numComp; 315a18a7fb9SMatthew G. Knepley } 316a18a7fb9SMatthew G. Knepley } 317ad96f515SMatthew G. Knepley ierr = DMPlexVecSetFieldClosure_Internal(dm, section, localX, fieldActive, point, values, mode);CHKERRQ(ierr); 318a18a7fb9SMatthew G. Knepley } 319a18a7fb9SMatthew G. Knepley ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 320a18a7fb9SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 321a18a7fb9SMatthew G. Knepley } 3227d1dd11eSToby Isaac if (h) { 3237d1dd11eSToby Isaac for (f = 0; f < numFields; ++f) {ierr = PetscDualSpaceDestroy(&sp[f]);CHKERRQ(ierr);} 3247d1dd11eSToby Isaac } 3257d1dd11eSToby Isaac } 326a18a7fb9SMatthew G. Knepley ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 327ad96f515SMatthew G. Knepley ierr = DMRestoreWorkArray(dm, numFields, PETSC_BOOL, &fieldActive);CHKERRQ(ierr); 328a18a7fb9SMatthew G. Knepley ierr = PetscFree3(sp,v0,J);CHKERRQ(ierr); 3297d1dd11eSToby Isaac if (maxHeight > 0) { 3307d1dd11eSToby Isaac ierr = PetscFree(cellsp);CHKERRQ(ierr); 3317d1dd11eSToby Isaac } 332a18a7fb9SMatthew G. Knepley PetscFunctionReturn(0); 333a18a7fb9SMatthew G. Knepley } 334a18a7fb9SMatthew G. Knepley 335a18a7fb9SMatthew G. Knepley #undef __FUNCT__ 336cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexProjectFunctionLocal" 3370f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexProjectFunctionLocal(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 338cb1e1211SMatthew G Knepley { 3397d1dd11eSToby Isaac PetscDualSpace *sp, *cellsp; 34072f94c41SMatthew G. Knepley PetscSection section; 34172f94c41SMatthew G. Knepley PetscScalar *values; 34272f94c41SMatthew G. Knepley PetscReal *v0, *J, detJ; 3437d1dd11eSToby Isaac PetscInt numFields, numComp, dim, spDim, totDim, numValues, pStart, pEnd, p, f, d, v, comp, h, maxHeight; 344cb1e1211SMatthew G Knepley PetscErrorCode ierr; 345cb1e1211SMatthew G Knepley 346cb1e1211SMatthew G Knepley PetscFunctionBegin; 347cb1e1211SMatthew G Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 34872f94c41SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 349785e854fSJed Brown ierr = PetscMalloc1(numFields, &sp);CHKERRQ(ierr); 3507d1dd11eSToby Isaac ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3517d1dd11eSToby Isaac ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 3527d1dd11eSToby Isaac if (maxHeight < 0 || maxHeight > dim) {SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"maximum projection height %d not in [0, %d)\n", maxHeight,dim);} 3537d1dd11eSToby Isaac if (maxHeight > 0) { 3547d1dd11eSToby Isaac ierr = PetscMalloc1(numFields,&cellsp);CHKERRQ(ierr); 3557d1dd11eSToby Isaac } 356*048b7b1eSToby Isaac else { 357*048b7b1eSToby Isaac cellsp = sp; 358*048b7b1eSToby Isaac } 3597d1dd11eSToby Isaac ierr = PetscMalloc2(dim,&v0,dim*dim,&J);CHKERRQ(ierr); 3607d1dd11eSToby Isaac for (h = 0; h <= maxHeight; h++) { 3617d1dd11eSToby Isaac ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 362*048b7b1eSToby Isaac if (pEnd <= pStart) continue; 3637d1dd11eSToby Isaac totDim = 0; 36472f94c41SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 3650f2d7e86SMatthew G. Knepley PetscFE fe; 3660f2d7e86SMatthew G. Knepley 3670f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 3687d1dd11eSToby Isaac if (!h) { 3697d1dd11eSToby Isaac ierr = PetscFEGetDualSpace(fe, &cellsp[f]);CHKERRQ(ierr); 3707d1dd11eSToby Isaac sp[f] = cellsp[f]; 3717d1dd11eSToby Isaac } 3727d1dd11eSToby Isaac else { 3737d1dd11eSToby Isaac ierr = PetscDualSpaceGetHeightSubspace(cellsp[f], h, &sp[f]);CHKERRQ(ierr); 3747d1dd11eSToby Isaac if (!sp[f]) { 3757d1dd11eSToby Isaac continue; 3767d1dd11eSToby Isaac } 3777d1dd11eSToby Isaac } 3780f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &numComp);CHKERRQ(ierr); 37972f94c41SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 38072f94c41SMatthew G. Knepley totDim += spDim*numComp; 381cb1e1211SMatthew G Knepley } 3827d1dd11eSToby Isaac ierr = DMPlexVecGetClosure(dm, section, localX, pStart, &numValues, NULL);CHKERRQ(ierr); 3837d1dd11eSToby Isaac if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section point closure size %d != dual space dimension %d", numValues, totDim); 38472f94c41SMatthew G. Knepley ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 3857d1dd11eSToby Isaac for (p = pStart; p < pEnd; ++p) { 38672f94c41SMatthew G. Knepley PetscCellGeometry geom; 387cb1e1211SMatthew G Knepley 3887d1dd11eSToby Isaac ierr = DMPlexComputeCellGeometryFEM(dm, p, NULL, v0, J, NULL, &detJ);CHKERRQ(ierr); 38972f94c41SMatthew G. Knepley geom.v0 = v0; 39072f94c41SMatthew G. Knepley geom.J = J; 39172f94c41SMatthew G. Knepley geom.detJ = &detJ; 39272f94c41SMatthew G. Knepley for (f = 0, v = 0; f < numFields; ++f) { 3930f2d7e86SMatthew G. Knepley PetscFE fe; 394c110b1eeSGeoffrey Irving void * const ctx = ctxs ? ctxs[f] : NULL; 3950f2d7e86SMatthew G. Knepley 3967d1dd11eSToby Isaac if (!sp[f]) continue; 3970f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 3980f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &numComp);CHKERRQ(ierr); 39972f94c41SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 40072f94c41SMatthew G. Knepley for (d = 0; d < spDim; ++d) { 401120386c5SMatthew G. Knepley if (funcs[f]) { 402c110b1eeSGeoffrey Irving ierr = PetscDualSpaceApply(sp[f], d, geom, numComp, funcs[f], ctx, &values[v]);CHKERRQ(ierr); 403120386c5SMatthew G. Knepley } else { 404120386c5SMatthew G. Knepley for (comp = 0; comp < numComp; ++comp) values[v+comp] = 0.0; 405120386c5SMatthew G. Knepley } 40672f94c41SMatthew G. Knepley v += numComp; 407cb1e1211SMatthew G Knepley } 408cb1e1211SMatthew G Knepley } 4097d1dd11eSToby Isaac ierr = DMPlexVecSetClosure(dm, section, localX, p, values, mode);CHKERRQ(ierr); 410cb1e1211SMatthew G Knepley } 41172f94c41SMatthew G. Knepley ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 4127d1dd11eSToby Isaac if (h) { 4137d1dd11eSToby Isaac for (f = 0; f < numFields; f++) {ierr = PetscDualSpaceDestroy(&sp[f]);CHKERRQ(ierr);} 4147d1dd11eSToby Isaac } 4157d1dd11eSToby Isaac } 4161f2da991SMatthew G. Knepley ierr = PetscFree2(v0,J);CHKERRQ(ierr); 41772f94c41SMatthew G. Knepley ierr = PetscFree(sp);CHKERRQ(ierr); 4187d1dd11eSToby Isaac if (maxHeight > 0) { 4197d1dd11eSToby Isaac ierr = PetscFree(cellsp);CHKERRQ(ierr); 4207d1dd11eSToby Isaac } 421cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 422cb1e1211SMatthew G Knepley } 423cb1e1211SMatthew G Knepley 424cb1e1211SMatthew G Knepley #undef __FUNCT__ 425cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexProjectFunction" 426cb1e1211SMatthew G Knepley /*@C 427cb1e1211SMatthew G Knepley DMPlexProjectFunction - This projects the given function into the function space provided. 428cb1e1211SMatthew G Knepley 429cb1e1211SMatthew G Knepley Input Parameters: 430cb1e1211SMatthew G Knepley + dm - The DM 43172f94c41SMatthew G. Knepley . funcs - The coordinate functions to evaluate, one per field 432c110b1eeSGeoffrey Irving . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 433cb1e1211SMatthew G Knepley - mode - The insertion mode for values 434cb1e1211SMatthew G Knepley 435cb1e1211SMatthew G Knepley Output Parameter: 436cb1e1211SMatthew G Knepley . X - vector 437cb1e1211SMatthew G Knepley 438cb1e1211SMatthew G Knepley Level: developer 439cb1e1211SMatthew G Knepley 440878cb397SSatish Balay .seealso: DMPlexComputeL2Diff() 441878cb397SSatish Balay @*/ 4420f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexProjectFunction(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 443cb1e1211SMatthew G Knepley { 444cb1e1211SMatthew G Knepley Vec localX; 445cb1e1211SMatthew G Knepley PetscErrorCode ierr; 446cb1e1211SMatthew G Knepley 447cb1e1211SMatthew G Knepley PetscFunctionBegin; 4489a800dd8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 449cb1e1211SMatthew G Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 4500f2d7e86SMatthew G. Knepley ierr = DMPlexProjectFunctionLocal(dm, funcs, ctxs, mode, localX);CHKERRQ(ierr); 451cb1e1211SMatthew G Knepley ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 452cb1e1211SMatthew G Knepley ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 453cb1e1211SMatthew G Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 454cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 455cb1e1211SMatthew G Knepley } 456cb1e1211SMatthew G Knepley 45755f2e967SMatthew G. Knepley #undef __FUNCT__ 4580f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexProjectFieldLocal" 4593bc3b0a0SMatthew 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) 4600f2d7e86SMatthew G. Knepley { 4610f2d7e86SMatthew G. Knepley DM dmAux; 4622764a2aaSMatthew G. Knepley PetscDS prob, probAux; 4630f2d7e86SMatthew G. Knepley Vec A; 464326413afSMatthew G. Knepley PetscSection section, sectionAux; 465326413afSMatthew G. Knepley PetscScalar *values, *u, *u_x, *a, *a_x; 4660f2d7e86SMatthew G. Knepley PetscReal *x, *v0, *J, *invJ, detJ, **basisField, **basisFieldDer, **basisFieldAux, **basisFieldDerAux; 467*048b7b1eSToby Isaac PetscInt Nf, dim, spDim, totDim, numValues, cStart, cEnd, c, f, d, v, comp, maxHeight; 4680f2d7e86SMatthew G. Knepley PetscErrorCode ierr; 4690f2d7e86SMatthew G. Knepley 4700f2d7e86SMatthew G. Knepley PetscFunctionBegin; 471*048b7b1eSToby Isaac ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 472*048b7b1eSToby Isaac if (maxHeight > 0) {SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Field projection for height > 0 not supported yet");} 4732764a2aaSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 474c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4750f2d7e86SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4760f2d7e86SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4770f2d7e86SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4782764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 4792764a2aaSMatthew G. Knepley ierr = PetscDSGetTabulation(prob, &basisField, &basisFieldDer);CHKERRQ(ierr); 4802764a2aaSMatthew G. Knepley ierr = PetscDSGetEvaluationArrays(prob, &u, NULL, &u_x);CHKERRQ(ierr); 4812764a2aaSMatthew G. Knepley ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr); 4820f2d7e86SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 4830f2d7e86SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 4840f2d7e86SMatthew G. Knepley if (dmAux) { 4852764a2aaSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 486326413afSMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 4872764a2aaSMatthew G. Knepley ierr = PetscDSGetTabulation(prob, &basisFieldAux, &basisFieldDerAux);CHKERRQ(ierr); 4882764a2aaSMatthew G. Knepley ierr = PetscDSGetEvaluationArrays(probAux, &a, NULL, &a_x);CHKERRQ(ierr); 4890f2d7e86SMatthew G. Knepley } 4900f2d7e86SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesFEM(dm, localU);CHKERRQ(ierr); 4910f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, localX, cStart, &numValues, NULL);CHKERRQ(ierr); 4920f2d7e86SMatthew 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); 4930f2d7e86SMatthew G. Knepley ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 4940f2d7e86SMatthew G. Knepley ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 4950f2d7e86SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 496326413afSMatthew G. Knepley PetscScalar *coefficients = NULL, *coefficientsAux = NULL; 497326413afSMatthew G. Knepley 4988e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 499326413afSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, localU, c, NULL, &coefficients);CHKERRQ(ierr); 500326413afSMatthew G. Knepley if (dmAux) {ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &coefficientsAux);CHKERRQ(ierr);} 5010f2d7e86SMatthew G. Knepley for (f = 0, v = 0; f < Nf; ++f) { 5023113607cSMatthew G. Knepley PetscFE fe; 5033113607cSMatthew G. Knepley PetscDualSpace sp; 5043113607cSMatthew G. Knepley PetscInt Ncf; 5053113607cSMatthew G. Knepley 5062764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 5073113607cSMatthew G. Knepley ierr = PetscFEGetDualSpace(fe, &sp);CHKERRQ(ierr); 5083113607cSMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Ncf);CHKERRQ(ierr); 5093113607cSMatthew G. Knepley ierr = PetscDualSpaceGetDimension(sp, &spDim);CHKERRQ(ierr); 5100f2d7e86SMatthew G. Knepley for (d = 0; d < spDim; ++d) { 5110f2d7e86SMatthew G. Knepley PetscQuadrature quad; 5120f2d7e86SMatthew G. Knepley const PetscReal *points, *weights; 5130f2d7e86SMatthew G. Knepley PetscInt numPoints, q; 5140f2d7e86SMatthew G. Knepley 5150f2d7e86SMatthew G. Knepley if (funcs[f]) { 5163113607cSMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(sp, d, &quad);CHKERRQ(ierr); 5170f2d7e86SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numPoints, &points, &weights);CHKERRQ(ierr); 5183113607cSMatthew G. Knepley ierr = PetscFEGetTabulation(fe, numPoints, points, &basisField[f], &basisFieldDer[f], NULL);CHKERRQ(ierr); 5190f2d7e86SMatthew G. Knepley for (q = 0; q < numPoints; ++q) { 5200f2d7e86SMatthew G. Knepley CoordinatesRefToReal(dim, dim, v0, J, &points[q*dim], x); 521326413afSMatthew G. Knepley ierr = EvaluateFieldJets(prob, PETSC_FALSE, q, invJ, coefficients, NULL, u, u_x, NULL);CHKERRQ(ierr); 522326413afSMatthew G. Knepley ierr = EvaluateFieldJets(probAux, PETSC_FALSE, q, invJ, coefficientsAux, NULL, a, a_x, NULL);CHKERRQ(ierr); 5233bc3b0a0SMatthew G. Knepley (*funcs[f])(u, NULL, u_x, a, NULL, a_x, x, &values[v]); 5240f2d7e86SMatthew G. Knepley } 5253113607cSMatthew G. Knepley ierr = PetscFERestoreTabulation(fe, numPoints, points, &basisField[f], &basisFieldDer[f], NULL);CHKERRQ(ierr); 5260f2d7e86SMatthew G. Knepley } else { 5270f2d7e86SMatthew G. Knepley for (comp = 0; comp < Ncf; ++comp) values[v+comp] = 0.0; 5280f2d7e86SMatthew G. Knepley } 5290f2d7e86SMatthew G. Knepley v += Ncf; 5300f2d7e86SMatthew G. Knepley } 5310f2d7e86SMatthew G. Knepley } 532326413afSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, localU, c, NULL, &coefficients);CHKERRQ(ierr); 533326413afSMatthew G. Knepley if (dmAux) {ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &coefficientsAux);CHKERRQ(ierr);} 5340f2d7e86SMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, section, localX, c, values, mode);CHKERRQ(ierr); 5350f2d7e86SMatthew G. Knepley } 5360f2d7e86SMatthew G. Knepley ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 5370f2d7e86SMatthew G. Knepley ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr); 5380f2d7e86SMatthew G. Knepley PetscFunctionReturn(0); 5390f2d7e86SMatthew G. Knepley } 5400f2d7e86SMatthew G. Knepley 5410f2d7e86SMatthew G. Knepley #undef __FUNCT__ 5420f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexProjectField" 5430f2d7e86SMatthew G. Knepley /*@C 5440f2d7e86SMatthew G. Knepley DMPlexProjectField - This projects the given function of the fields into the function space provided. 5450f2d7e86SMatthew G. Knepley 5460f2d7e86SMatthew G. Knepley Input Parameters: 5470f2d7e86SMatthew G. Knepley + dm - The DM 5480f2d7e86SMatthew G. Knepley . U - The input field vector 5490f2d7e86SMatthew G. Knepley . funcs - The functions to evaluate, one per field 5500f2d7e86SMatthew G. Knepley - mode - The insertion mode for values 5510f2d7e86SMatthew G. Knepley 5520f2d7e86SMatthew G. Knepley Output Parameter: 5530f2d7e86SMatthew G. Knepley . X - The output vector 5540f2d7e86SMatthew G. Knepley 5550f2d7e86SMatthew G. Knepley Level: developer 5560f2d7e86SMatthew G. Knepley 5570f2d7e86SMatthew G. Knepley .seealso: DMPlexProjectFunction(), DMPlexComputeL2Diff() 5580f2d7e86SMatthew G. Knepley @*/ 5593bc3b0a0SMatthew 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) 5600f2d7e86SMatthew G. Knepley { 5610f2d7e86SMatthew G. Knepley Vec localX, localU; 5620f2d7e86SMatthew G. Knepley PetscErrorCode ierr; 5630f2d7e86SMatthew G. Knepley 5640f2d7e86SMatthew G. Knepley PetscFunctionBegin; 5650f2d7e86SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5660f2d7e86SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 5670f2d7e86SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localU);CHKERRQ(ierr); 5680f2d7e86SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, U, INSERT_VALUES, localU);CHKERRQ(ierr); 5690f2d7e86SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, U, INSERT_VALUES, localU);CHKERRQ(ierr); 5703113607cSMatthew G. Knepley ierr = DMPlexProjectFieldLocal(dm, localU, funcs, mode, localX);CHKERRQ(ierr); 5710f2d7e86SMatthew G. Knepley ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 5720f2d7e86SMatthew G. Knepley ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 5730f2d7e86SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 5740f2d7e86SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localU);CHKERRQ(ierr); 5750f2d7e86SMatthew G. Knepley PetscFunctionReturn(0); 5760f2d7e86SMatthew G. Knepley } 5770f2d7e86SMatthew G. Knepley 5780f2d7e86SMatthew G. Knepley #undef __FUNCT__ 5793351dd3dSMatthew G. Knepley #define __FUNCT__ "DMPlexInsertBoundaryValuesFEM" 5803351dd3dSMatthew G. Knepley PetscErrorCode DMPlexInsertBoundaryValuesFEM(DM dm, Vec localX) 58155f2e967SMatthew G. Knepley { 58255f2e967SMatthew G. Knepley void (**funcs)(const PetscReal x[], PetscScalar *u, void *ctx); 58355f2e967SMatthew G. Knepley void **ctxs; 58455f2e967SMatthew G. Knepley PetscFE *fe; 58555f2e967SMatthew G. Knepley PetscInt numFields, f, numBd, b; 58655f2e967SMatthew G. Knepley PetscErrorCode ierr; 58755f2e967SMatthew G. Knepley 58855f2e967SMatthew G. Knepley PetscFunctionBegin; 58955f2e967SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 59055f2e967SMatthew G. Knepley PetscValidHeaderSpecific(localX, VEC_CLASSID, 2); 59155f2e967SMatthew G. Knepley ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 59255f2e967SMatthew G. Knepley ierr = PetscMalloc3(numFields,&fe,numFields,&funcs,numFields,&ctxs);CHKERRQ(ierr); 59355f2e967SMatthew G. Knepley for (f = 0; f < numFields; ++f) {ierr = DMGetField(dm, f, (PetscObject *) &fe[f]);CHKERRQ(ierr);} 59455f2e967SMatthew G. Knepley /* OPT: Could attempt to do multiple BCs at once */ 59555f2e967SMatthew G. Knepley ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 59655f2e967SMatthew G. Knepley for (b = 0; b < numBd; ++b) { 597a18a7fb9SMatthew G. Knepley DMLabel label; 59855f2e967SMatthew G. Knepley const PetscInt *ids; 59963d5297fSMatthew G. Knepley const char *labelname; 60055f2e967SMatthew G. Knepley PetscInt numids, field; 60155f2e967SMatthew G. Knepley PetscBool isEssential; 60255f2e967SMatthew G. Knepley void (*func)(); 60355f2e967SMatthew G. Knepley void *ctx; 60455f2e967SMatthew G. Knepley 60563d5297fSMatthew G. Knepley ierr = DMPlexGetBoundary(dm, b, &isEssential, NULL, &labelname, &field, &func, &numids, &ids, &ctx);CHKERRQ(ierr); 60663d5297fSMatthew G. Knepley ierr = DMPlexGetLabel(dm, labelname, &label);CHKERRQ(ierr); 60755f2e967SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 60855f2e967SMatthew G. Knepley funcs[f] = field == f ? (void (*)(const PetscReal[], PetscScalar *, void *)) func : NULL; 60955f2e967SMatthew G. Knepley ctxs[f] = field == f ? ctx : NULL; 61055f2e967SMatthew G. Knepley } 611a18a7fb9SMatthew G. Knepley ierr = DMPlexProjectFunctionLabelLocal(dm, label, numids, ids, fe, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 61255f2e967SMatthew G. Knepley } 61355f2e967SMatthew G. Knepley ierr = PetscFree3(fe,funcs,ctxs);CHKERRQ(ierr); 61455f2e967SMatthew G. Knepley PetscFunctionReturn(0); 61555f2e967SMatthew G. Knepley } 61655f2e967SMatthew G. Knepley 617cb1e1211SMatthew G Knepley #undef __FUNCT__ 618cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexComputeL2Diff" 619cb1e1211SMatthew G Knepley /*@C 620cb1e1211SMatthew G Knepley DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 621cb1e1211SMatthew G Knepley 622cb1e1211SMatthew G Knepley Input Parameters: 623cb1e1211SMatthew G Knepley + dm - The DM 624cb1e1211SMatthew G Knepley . funcs - The functions to evaluate for each field component 62551259fa3SMatthew G. Knepley . ctxs - Optional array of contexts to pass to each function, or NULL. 626cb1e1211SMatthew G Knepley - X - The coefficient vector u_h 627cb1e1211SMatthew G Knepley 628cb1e1211SMatthew G Knepley Output Parameter: 629cb1e1211SMatthew G Knepley . diff - The diff ||u - u_h||_2 630cb1e1211SMatthew G Knepley 631cb1e1211SMatthew G Knepley Level: developer 632cb1e1211SMatthew G Knepley 63323d86601SMatthew G. Knepley .seealso: DMPlexProjectFunction(), DMPlexComputeL2GradientDiff() 634878cb397SSatish Balay @*/ 6350f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeL2Diff(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 636cb1e1211SMatthew G Knepley { 637cb1e1211SMatthew G Knepley const PetscInt debug = 0; 638cb1e1211SMatthew G Knepley PetscSection section; 639c5bbbd5bSMatthew G. Knepley PetscQuadrature quad; 640cb1e1211SMatthew G Knepley Vec localX; 64172f94c41SMatthew G. Knepley PetscScalar *funcVal; 642cb1e1211SMatthew G Knepley PetscReal *coords, *v0, *J, *invJ, detJ; 643cb1e1211SMatthew G Knepley PetscReal localDiff = 0.0; 644cb1e1211SMatthew G Knepley PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 645cb1e1211SMatthew G Knepley PetscErrorCode ierr; 646cb1e1211SMatthew G Knepley 647cb1e1211SMatthew G Knepley PetscFunctionBegin; 648c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 649cb1e1211SMatthew G Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 650cb1e1211SMatthew G Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 651cb1e1211SMatthew G Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 652cb1e1211SMatthew G Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 653cb1e1211SMatthew G Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 654cb1e1211SMatthew G Knepley for (field = 0; field < numFields; ++field) { 6550f2d7e86SMatthew G. Knepley PetscFE fe; 656c5bbbd5bSMatthew G. Knepley PetscInt Nc; 657c5bbbd5bSMatthew G. Knepley 6580f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 6590f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 6600f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 661c5bbbd5bSMatthew G. Knepley numComponents += Nc; 662cb1e1211SMatthew G Knepley } 6630f2d7e86SMatthew G. Knepley ierr = DMPlexProjectFunctionLocal(dm, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 664dcca6d9dSJed Brown ierr = PetscMalloc5(numComponents,&funcVal,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 665cb1e1211SMatthew G Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 666cb1e1211SMatthew G Knepley for (c = cStart; c < cEnd; ++c) { 667a1e44745SMatthew G. Knepley PetscScalar *x = NULL; 668cb1e1211SMatthew G Knepley PetscReal elemDiff = 0.0; 669cb1e1211SMatthew G Knepley 6708e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 671cb1e1211SMatthew G Knepley if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 672cb1e1211SMatthew G Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 673cb1e1211SMatthew G Knepley 674cb1e1211SMatthew G Knepley for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 6750f2d7e86SMatthew G. Knepley PetscFE fe; 676c110b1eeSGeoffrey Irving void * const ctx = ctxs ? ctxs[field] : NULL; 67721454ff5SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 678c5bbbd5bSMatthew G. Knepley PetscReal *basis; 67921454ff5SMatthew G. Knepley PetscInt numQuadPoints, numBasisFuncs, numBasisComps, q, d, e, fc, f; 680cb1e1211SMatthew G Knepley 6810f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 68221454ff5SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 6830f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &numBasisFuncs);CHKERRQ(ierr); 6840f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &numBasisComps);CHKERRQ(ierr); 6850f2d7e86SMatthew G. Knepley ierr = PetscFEGetDefaultTabulation(fe, &basis, NULL, NULL);CHKERRQ(ierr); 686cb1e1211SMatthew G Knepley if (debug) { 687cb1e1211SMatthew G Knepley char title[1024]; 688cb1e1211SMatthew G Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 689cb1e1211SMatthew G Knepley ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 690cb1e1211SMatthew G Knepley } 691cb1e1211SMatthew G Knepley for (q = 0; q < numQuadPoints; ++q) { 692cb1e1211SMatthew G Knepley for (d = 0; d < dim; d++) { 693cb1e1211SMatthew G Knepley coords[d] = v0[d]; 694cb1e1211SMatthew G Knepley for (e = 0; e < dim; e++) { 695cb1e1211SMatthew G Knepley coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 696cb1e1211SMatthew G Knepley } 697cb1e1211SMatthew G Knepley } 698c110b1eeSGeoffrey Irving (*funcs[field])(coords, funcVal, ctx); 699cb1e1211SMatthew G Knepley for (fc = 0; fc < numBasisComps; ++fc) { 700a1d24da5SMatthew G. Knepley PetscScalar interpolant = 0.0; 701a1d24da5SMatthew G. Knepley 702cb1e1211SMatthew G Knepley for (f = 0; f < numBasisFuncs; ++f) { 703cb1e1211SMatthew G Knepley const PetscInt fidx = f*numBasisComps+fc; 704a1d24da5SMatthew G. Knepley interpolant += x[fieldOffset+fidx]*basis[q*numBasisFuncs*numBasisComps+fidx]; 705cb1e1211SMatthew G Knepley } 70672f94c41SMatthew 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);} 70772f94c41SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ; 708cb1e1211SMatthew G Knepley } 709cb1e1211SMatthew G Knepley } 710cb1e1211SMatthew G Knepley comp += numBasisComps; 711cb1e1211SMatthew G Knepley fieldOffset += numBasisFuncs*numBasisComps; 712cb1e1211SMatthew G Knepley } 713cb1e1211SMatthew G Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 714cb1e1211SMatthew G Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 715cb1e1211SMatthew G Knepley localDiff += elemDiff; 716cb1e1211SMatthew G Knepley } 71772f94c41SMatthew G. Knepley ierr = PetscFree5(funcVal,coords,v0,J,invJ);CHKERRQ(ierr); 718cb1e1211SMatthew G Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 71986a74ee0SMatthew G. Knepley ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 720cb1e1211SMatthew G Knepley *diff = PetscSqrtReal(*diff); 721cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 722cb1e1211SMatthew G Knepley } 723cb1e1211SMatthew G Knepley 724cb1e1211SMatthew G Knepley #undef __FUNCT__ 72540e14135SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeL2GradientDiff" 72640e14135SMatthew G. Knepley /*@C 72740e14135SMatthew 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. 72840e14135SMatthew G. Knepley 72940e14135SMatthew G. Knepley Input Parameters: 73040e14135SMatthew G. Knepley + dm - The DM 73140e14135SMatthew G. Knepley . funcs - The gradient functions to evaluate for each field component 73251259fa3SMatthew G. Knepley . ctxs - Optional array of contexts to pass to each function, or NULL. 73340e14135SMatthew G. Knepley . X - The coefficient vector u_h 73440e14135SMatthew G. Knepley - n - The vector to project along 73540e14135SMatthew G. Knepley 73640e14135SMatthew G. Knepley Output Parameter: 73740e14135SMatthew G. Knepley . diff - The diff ||(grad u - grad u_h) . n||_2 73840e14135SMatthew G. Knepley 73940e14135SMatthew G. Knepley Level: developer 74040e14135SMatthew G. Knepley 74140e14135SMatthew G. Knepley .seealso: DMPlexProjectFunction(), DMPlexComputeL2Diff() 74240e14135SMatthew G. Knepley @*/ 7430f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeL2GradientDiff(DM dm, void (**funcs)(const PetscReal [], const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff) 744cb1e1211SMatthew G Knepley { 74540e14135SMatthew G. Knepley const PetscInt debug = 0; 746cb1e1211SMatthew G Knepley PetscSection section; 74740e14135SMatthew G. Knepley PetscQuadrature quad; 74840e14135SMatthew G. Knepley Vec localX; 74940e14135SMatthew G. Knepley PetscScalar *funcVal, *interpolantVec; 75040e14135SMatthew G. Knepley PetscReal *coords, *realSpaceDer, *v0, *J, *invJ, detJ; 75140e14135SMatthew G. Knepley PetscReal localDiff = 0.0; 75240e14135SMatthew G. Knepley PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 753cb1e1211SMatthew G Knepley PetscErrorCode ierr; 754cb1e1211SMatthew G Knepley 755cb1e1211SMatthew G Knepley PetscFunctionBegin; 756c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 75740e14135SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 75840e14135SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 75940e14135SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 76040e14135SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 76140e14135SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 762652b88e8SMatthew G. Knepley for (field = 0; field < numFields; ++field) { 7630f2d7e86SMatthew G. Knepley PetscFE fe; 76440e14135SMatthew G. Knepley PetscInt Nc; 765652b88e8SMatthew G. Knepley 7660f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 7670f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 7680f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 76940e14135SMatthew G. Knepley numComponents += Nc; 770652b88e8SMatthew G. Knepley } 77140e14135SMatthew G. Knepley /* ierr = DMPlexProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); */ 77240e14135SMatthew G. Knepley ierr = PetscMalloc7(numComponents,&funcVal,dim,&coords,dim,&realSpaceDer,dim,&v0,dim*dim,&J,dim*dim,&invJ,dim,&interpolantVec);CHKERRQ(ierr); 77340e14135SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 77440e14135SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 77540e14135SMatthew G. Knepley PetscScalar *x = NULL; 77640e14135SMatthew G. Knepley PetscReal elemDiff = 0.0; 777652b88e8SMatthew G. Knepley 7788e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 77940e14135SMatthew G. Knepley if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 78040e14135SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 78140e14135SMatthew G. Knepley 78240e14135SMatthew G. Knepley for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 7830f2d7e86SMatthew G. Knepley PetscFE fe; 78451259fa3SMatthew G. Knepley void * const ctx = ctxs ? ctxs[field] : NULL; 78521454ff5SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 78640e14135SMatthew G. Knepley PetscReal *basisDer; 78721454ff5SMatthew G. Knepley PetscInt numQuadPoints, Nb, Ncomp, q, d, e, fc, f, g; 78840e14135SMatthew G. Knepley 7890f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 79021454ff5SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 7910f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 7920f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Ncomp);CHKERRQ(ierr); 7930f2d7e86SMatthew G. Knepley ierr = PetscFEGetDefaultTabulation(fe, NULL, &basisDer, NULL);CHKERRQ(ierr); 79440e14135SMatthew G. Knepley if (debug) { 79540e14135SMatthew G. Knepley char title[1024]; 79640e14135SMatthew G. Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 79740e14135SMatthew G. Knepley ierr = DMPrintCellVector(c, title, Nb*Ncomp, &x[fieldOffset]);CHKERRQ(ierr); 798652b88e8SMatthew G. Knepley } 79940e14135SMatthew G. Knepley for (q = 0; q < numQuadPoints; ++q) { 80040e14135SMatthew G. Knepley for (d = 0; d < dim; d++) { 80140e14135SMatthew G. Knepley coords[d] = v0[d]; 80240e14135SMatthew G. Knepley for (e = 0; e < dim; e++) { 80340e14135SMatthew G. Knepley coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 804652b88e8SMatthew G. Knepley } 80540e14135SMatthew G. Knepley } 80651259fa3SMatthew G. Knepley (*funcs[field])(coords, n, funcVal, ctx); 80740e14135SMatthew G. Knepley for (fc = 0; fc < Ncomp; ++fc) { 80840e14135SMatthew G. Knepley PetscScalar interpolant = 0.0; 80940e14135SMatthew G. Knepley 81040e14135SMatthew G. Knepley for (d = 0; d < dim; ++d) interpolantVec[d] = 0.0; 81140e14135SMatthew G. Knepley for (f = 0; f < Nb; ++f) { 81240e14135SMatthew G. Knepley const PetscInt fidx = f*Ncomp+fc; 81340e14135SMatthew G. Knepley 81440e14135SMatthew G. Knepley for (d = 0; d < dim; ++d) { 81540e14135SMatthew G. Knepley realSpaceDer[d] = 0.0; 81640e14135SMatthew G. Knepley for (g = 0; g < dim; ++g) { 81740e14135SMatthew G. Knepley realSpaceDer[d] += invJ[g*dim+d]*basisDer[(q*Nb*Ncomp+fidx)*dim+g]; 81840e14135SMatthew G. Knepley } 81940e14135SMatthew G. Knepley interpolantVec[d] += x[fieldOffset+fidx]*realSpaceDer[d]; 82040e14135SMatthew G. Knepley } 82140e14135SMatthew G. Knepley } 82240e14135SMatthew G. Knepley for (d = 0; d < dim; ++d) interpolant += interpolantVec[d]*n[d]; 82340e14135SMatthew 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);} 82440e14135SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ; 82540e14135SMatthew G. Knepley } 82640e14135SMatthew G. Knepley } 82740e14135SMatthew G. Knepley comp += Ncomp; 82840e14135SMatthew G. Knepley fieldOffset += Nb*Ncomp; 82940e14135SMatthew G. Knepley } 83040e14135SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 83140e14135SMatthew G. Knepley if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 83240e14135SMatthew G. Knepley localDiff += elemDiff; 83340e14135SMatthew G. Knepley } 83440e14135SMatthew G. Knepley ierr = PetscFree7(funcVal,coords,realSpaceDer,v0,J,invJ,interpolantVec);CHKERRQ(ierr); 83540e14135SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 83640e14135SMatthew G. Knepley ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 83740e14135SMatthew G. Knepley *diff = PetscSqrtReal(*diff); 838cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 839cb1e1211SMatthew G Knepley } 840cb1e1211SMatthew G Knepley 841a0845e3aSMatthew G. Knepley #undef __FUNCT__ 84273d901b8SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeL2FieldDiff" 8430f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeL2FieldDiff(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 84473d901b8SMatthew G. Knepley { 84573d901b8SMatthew G. Knepley const PetscInt debug = 0; 84673d901b8SMatthew G. Knepley PetscSection section; 84773d901b8SMatthew G. Knepley PetscQuadrature quad; 84873d901b8SMatthew G. Knepley Vec localX; 84973d901b8SMatthew G. Knepley PetscScalar *funcVal; 85073d901b8SMatthew G. Knepley PetscReal *coords, *v0, *J, *invJ, detJ; 85173d901b8SMatthew G. Knepley PetscReal *localDiff; 85273d901b8SMatthew G. Knepley PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 85373d901b8SMatthew G. Knepley PetscErrorCode ierr; 85473d901b8SMatthew G. Knepley 85573d901b8SMatthew G. Knepley PetscFunctionBegin; 856c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 85773d901b8SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 85873d901b8SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 85973d901b8SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 86073d901b8SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 86173d901b8SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 86273d901b8SMatthew G. Knepley for (field = 0; field < numFields; ++field) { 8630f2d7e86SMatthew G. Knepley PetscFE fe; 86473d901b8SMatthew G. Knepley PetscInt Nc; 86573d901b8SMatthew G. Knepley 8660f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 8670f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 8680f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 86973d901b8SMatthew G. Knepley numComponents += Nc; 87073d901b8SMatthew G. Knepley } 8710f2d7e86SMatthew G. Knepley ierr = DMPlexProjectFunctionLocal(dm, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 87273d901b8SMatthew G. Knepley ierr = PetscCalloc6(numFields,&localDiff,numComponents,&funcVal,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 87373d901b8SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 87473d901b8SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 87573d901b8SMatthew G. Knepley PetscScalar *x = NULL; 87673d901b8SMatthew G. Knepley 8778e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 87873d901b8SMatthew G. Knepley if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 87973d901b8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 88073d901b8SMatthew G. Knepley 88173d901b8SMatthew G. Knepley for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 8820f2d7e86SMatthew G. Knepley PetscFE fe; 88373d901b8SMatthew G. Knepley void * const ctx = ctxs ? ctxs[field] : NULL; 88473d901b8SMatthew G. Knepley const PetscReal *quadPoints, *quadWeights; 88573d901b8SMatthew G. Knepley PetscReal *basis, elemDiff = 0.0; 88673d901b8SMatthew G. Knepley PetscInt numQuadPoints, numBasisFuncs, numBasisComps, q, d, e, fc, f; 88773d901b8SMatthew G. Knepley 8880f2d7e86SMatthew G. Knepley ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 88973d901b8SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 8900f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &numBasisFuncs);CHKERRQ(ierr); 8910f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &numBasisComps);CHKERRQ(ierr); 8920f2d7e86SMatthew G. Knepley ierr = PetscFEGetDefaultTabulation(fe, &basis, NULL, NULL);CHKERRQ(ierr); 89373d901b8SMatthew G. Knepley if (debug) { 89473d901b8SMatthew G. Knepley char title[1024]; 89573d901b8SMatthew G. Knepley ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 89673d901b8SMatthew G. Knepley ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 89773d901b8SMatthew G. Knepley } 89873d901b8SMatthew G. Knepley for (q = 0; q < numQuadPoints; ++q) { 89973d901b8SMatthew G. Knepley for (d = 0; d < dim; d++) { 90073d901b8SMatthew G. Knepley coords[d] = v0[d]; 90173d901b8SMatthew G. Knepley for (e = 0; e < dim; e++) { 90273d901b8SMatthew G. Knepley coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 90373d901b8SMatthew G. Knepley } 90473d901b8SMatthew G. Knepley } 90573d901b8SMatthew G. Knepley (*funcs[field])(coords, funcVal, ctx); 90673d901b8SMatthew G. Knepley for (fc = 0; fc < numBasisComps; ++fc) { 90773d901b8SMatthew G. Knepley PetscScalar interpolant = 0.0; 90873d901b8SMatthew G. Knepley 90973d901b8SMatthew G. Knepley for (f = 0; f < numBasisFuncs; ++f) { 91073d901b8SMatthew G. Knepley const PetscInt fidx = f*numBasisComps+fc; 91173d901b8SMatthew G. Knepley interpolant += x[fieldOffset+fidx]*basis[q*numBasisFuncs*numBasisComps+fidx]; 91273d901b8SMatthew G. Knepley } 91373d901b8SMatthew 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);} 91473d901b8SMatthew G. Knepley elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ; 91573d901b8SMatthew G. Knepley } 91673d901b8SMatthew G. Knepley } 91773d901b8SMatthew G. Knepley comp += numBasisComps; 91873d901b8SMatthew G. Knepley fieldOffset += numBasisFuncs*numBasisComps; 91973d901b8SMatthew G. Knepley localDiff[field] += elemDiff; 92073d901b8SMatthew G. Knepley } 92173d901b8SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 92273d901b8SMatthew G. Knepley } 92373d901b8SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 92473d901b8SMatthew G. Knepley ierr = MPI_Allreduce(localDiff, diff, numFields, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 92573d901b8SMatthew G. Knepley for (field = 0; field < numFields; ++field) diff[field] = PetscSqrtReal(diff[field]); 92673d901b8SMatthew G. Knepley ierr = PetscFree6(localDiff,funcVal,coords,v0,J,invJ);CHKERRQ(ierr); 92773d901b8SMatthew G. Knepley PetscFunctionReturn(0); 92873d901b8SMatthew G. Knepley } 92973d901b8SMatthew G. Knepley 93073d901b8SMatthew G. Knepley #undef __FUNCT__ 93173d901b8SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeIntegralFEM" 93273d901b8SMatthew G. Knepley /*@ 93373d901b8SMatthew G. Knepley DMPlexComputeIntegralFEM - Form the local integral F from the local input X using pointwise functions specified by the user 93473d901b8SMatthew G. Knepley 93573d901b8SMatthew G. Knepley Input Parameters: 93673d901b8SMatthew G. Knepley + dm - The mesh 93773d901b8SMatthew G. Knepley . X - Local input vector 93873d901b8SMatthew G. Knepley - user - The user context 93973d901b8SMatthew G. Knepley 94073d901b8SMatthew G. Knepley Output Parameter: 94173d901b8SMatthew G. Knepley . integral - Local integral for each field 94273d901b8SMatthew G. Knepley 94373d901b8SMatthew G. Knepley Level: developer 94473d901b8SMatthew G. Knepley 94573d901b8SMatthew G. Knepley .seealso: DMPlexComputeResidualFEM() 94673d901b8SMatthew G. Knepley @*/ 9470f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeIntegralFEM(DM dm, Vec X, PetscReal *integral, void *user) 94873d901b8SMatthew G. Knepley { 94973d901b8SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 95073d901b8SMatthew G. Knepley DM dmAux; 95173d901b8SMatthew G. Knepley Vec localX, A; 9522764a2aaSMatthew G. Knepley PetscDS prob, probAux = NULL; 95373d901b8SMatthew G. Knepley PetscQuadrature q; 95473d901b8SMatthew G. Knepley PetscCellGeometry geom; 95573d901b8SMatthew G. Knepley PetscSection section, sectionAux; 95673d901b8SMatthew G. Knepley PetscReal *v0, *J, *invJ, *detJ; 95773d901b8SMatthew G. Knepley PetscScalar *u, *a = NULL; 9580f2d7e86SMatthew G. Knepley PetscInt dim, Nf, f, numCells, cStart, cEnd, c; 9590f2d7e86SMatthew G. Knepley PetscInt totDim, totDimAux; 96073d901b8SMatthew G. Knepley PetscErrorCode ierr; 96173d901b8SMatthew G. Knepley 96273d901b8SMatthew G. Knepley PetscFunctionBegin; 96373d901b8SMatthew G. Knepley /*ierr = PetscLogEventBegin(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr);*/ 96473d901b8SMatthew G. Knepley ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 96573d901b8SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 96673d901b8SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 967c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 96873d901b8SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9692764a2aaSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 9702764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 97173d901b8SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 97273d901b8SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 97373d901b8SMatthew G. Knepley numCells = cEnd - cStart; 9740f2d7e86SMatthew G. Knepley for (f = 0; f < Nf; ++f) {integral[f] = 0.0;} 97573d901b8SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 97673d901b8SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 97773d901b8SMatthew G. Knepley if (dmAux) { 97873d901b8SMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 9792764a2aaSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 9802764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 98173d901b8SMatthew G. Knepley } 98273d901b8SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesFEM(dm, localX);CHKERRQ(ierr); 9830f2d7e86SMatthew G. Knepley ierr = PetscMalloc5(numCells*totDim,&u,numCells*dim,&v0,numCells*dim*dim,&J,numCells*dim*dim,&invJ,numCells,&detJ);CHKERRQ(ierr); 9840f2d7e86SMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 98573d901b8SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 98673d901b8SMatthew G. Knepley PetscScalar *x = NULL; 98773d901b8SMatthew G. Knepley PetscInt i; 98873d901b8SMatthew G. Knepley 9898e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 99073d901b8SMatthew G. Knepley if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 99173d901b8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, localX, c, NULL, &x);CHKERRQ(ierr); 9920f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 99373d901b8SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, localX, c, NULL, &x);CHKERRQ(ierr); 99473d901b8SMatthew G. Knepley if (dmAux) { 99573d901b8SMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 9960f2d7e86SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 99773d901b8SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 99873d901b8SMatthew G. Knepley } 99973d901b8SMatthew G. Knepley } 100073d901b8SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10010f2d7e86SMatthew G. Knepley PetscFE fe; 100273d901b8SMatthew G. Knepley PetscInt numQuadPoints, Nb; 100373d901b8SMatthew G. Knepley /* Conforming batches */ 100473d901b8SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 100573d901b8SMatthew G. Knepley /* Remainder */ 100673d901b8SMatthew G. Knepley PetscInt Nr, offset; 100773d901b8SMatthew G. Knepley 10082764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 10090f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 10100f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 10110f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 101273d901b8SMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 101373d901b8SMatthew G. Knepley blockSize = Nb*numQuadPoints; 101473d901b8SMatthew G. Knepley batchSize = numBlocks * blockSize; 10150f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 101673d901b8SMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 101773d901b8SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 101873d901b8SMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 101973d901b8SMatthew G. Knepley offset = numCells - Nr; 102073d901b8SMatthew G. Knepley geom.v0 = v0; 102173d901b8SMatthew G. Knepley geom.J = J; 102273d901b8SMatthew G. Knepley geom.invJ = invJ; 102373d901b8SMatthew G. Knepley geom.detJ = detJ; 10240f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrate(fe, prob, f, Ne, geom, u, probAux, a, integral);CHKERRQ(ierr); 102573d901b8SMatthew G. Knepley geom.v0 = &v0[offset*dim]; 102673d901b8SMatthew G. Knepley geom.J = &J[offset*dim*dim]; 102773d901b8SMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 102873d901b8SMatthew G. Knepley geom.detJ = &detJ[offset]; 10290f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrate(fe, prob, f, Nr, geom, &u[offset*totDim], probAux, &a[offset*totDimAux], integral);CHKERRQ(ierr); 103073d901b8SMatthew G. Knepley } 103173d901b8SMatthew G. Knepley ierr = PetscFree5(u,v0,J,invJ,detJ);CHKERRQ(ierr); 103273d901b8SMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 103373d901b8SMatthew G. Knepley if (mesh->printFEM) { 103473d901b8SMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "Local integral:");CHKERRQ(ierr); 103573d901b8SMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), " %g", integral[f]);CHKERRQ(ierr);} 103673d901b8SMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "\n");CHKERRQ(ierr); 103773d901b8SMatthew G. Knepley } 103873d901b8SMatthew G. Knepley ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 103973d901b8SMatthew G. Knepley /* TODO: Allreduce for integral */ 104073d901b8SMatthew G. Knepley /*ierr = PetscLogEventEnd(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr);*/ 104173d901b8SMatthew G. Knepley PetscFunctionReturn(0); 104273d901b8SMatthew G. Knepley } 104373d901b8SMatthew G. Knepley 104473d901b8SMatthew G. Knepley #undef __FUNCT__ 10450f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeResidualFEM_Internal" 10460f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeResidualFEM_Internal(DM dm, Vec X, Vec X_t, Vec F, void *user) 10470f2d7e86SMatthew G. Knepley { 10480f2d7e86SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 10490f2d7e86SMatthew G. Knepley const char *name = "Residual"; 10500f2d7e86SMatthew G. Knepley DM dmAux; 10510f2d7e86SMatthew G. Knepley DMLabel depth; 10520f2d7e86SMatthew G. Knepley Vec A; 10532764a2aaSMatthew G. Knepley PetscDS prob, probAux = NULL; 10540f2d7e86SMatthew G. Knepley PetscQuadrature q; 10550f2d7e86SMatthew G. Knepley PetscCellGeometry geom; 10560f2d7e86SMatthew G. Knepley PetscSection section, sectionAux; 10570f2d7e86SMatthew G. Knepley PetscReal *v0, *J, *invJ, *detJ; 10580f2d7e86SMatthew G. Knepley PetscScalar *elemVec, *u, *u_t, *a = NULL; 10590f2d7e86SMatthew G. Knepley PetscInt dim, Nf, f, numCells, cStart, cEnd, c, numBd, bd; 10600f2d7e86SMatthew G. Knepley PetscInt totDim, totDimBd, totDimAux; 10610f2d7e86SMatthew G. Knepley PetscErrorCode ierr; 10620f2d7e86SMatthew G. Knepley 10630f2d7e86SMatthew G. Knepley PetscFunctionBegin; 10640f2d7e86SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_ResidualFEM,dm,0,0,0);CHKERRQ(ierr); 1065c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 10660f2d7e86SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 10672764a2aaSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 10682764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 10692764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalBdDimension(prob, &totDimBd);CHKERRQ(ierr); 10700f2d7e86SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 10710f2d7e86SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 10720f2d7e86SMatthew G. Knepley numCells = cEnd - cStart; 10730f2d7e86SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 10740f2d7e86SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 10750f2d7e86SMatthew G. Knepley if (dmAux) { 10760f2d7e86SMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 10772764a2aaSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 10782764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 10790f2d7e86SMatthew G. Knepley } 10800f2d7e86SMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesFEM(dm, X);CHKERRQ(ierr); 10810f2d7e86SMatthew G. Knepley ierr = VecSet(F, 0.0);CHKERRQ(ierr); 10820f2d7e86SMatthew 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); 10830f2d7e86SMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 10840f2d7e86SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 10850f2d7e86SMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 10860f2d7e86SMatthew G. Knepley PetscInt i; 10870f2d7e86SMatthew G. Knepley 10888e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 10890f2d7e86SMatthew G. Knepley if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 10900f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 10910f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 10920f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 10930f2d7e86SMatthew G. Knepley if (X_t) { 10940f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 10950f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i]; 10960f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 10970f2d7e86SMatthew G. Knepley } 10980f2d7e86SMatthew G. Knepley if (dmAux) { 10990f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 11000f2d7e86SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 11010f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 11020f2d7e86SMatthew G. Knepley } 11030f2d7e86SMatthew G. Knepley } 11040f2d7e86SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 11050f2d7e86SMatthew G. Knepley PetscFE fe; 11060f2d7e86SMatthew G. Knepley PetscInt numQuadPoints, Nb; 11070f2d7e86SMatthew G. Knepley /* Conforming batches */ 11080f2d7e86SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 11090f2d7e86SMatthew G. Knepley /* Remainder */ 11100f2d7e86SMatthew G. Knepley PetscInt Nr, offset; 11110f2d7e86SMatthew G. Knepley 11122764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 11130f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 11140f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 11150f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 11160f2d7e86SMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 11170f2d7e86SMatthew G. Knepley blockSize = Nb*numQuadPoints; 11180f2d7e86SMatthew G. Knepley batchSize = numBlocks * blockSize; 11190f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 11200f2d7e86SMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 11210f2d7e86SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 11220f2d7e86SMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 11230f2d7e86SMatthew G. Knepley offset = numCells - Nr; 11240f2d7e86SMatthew G. Knepley geom.v0 = v0; 11250f2d7e86SMatthew G. Knepley geom.J = J; 11260f2d7e86SMatthew G. Knepley geom.invJ = invJ; 11270f2d7e86SMatthew G. Knepley geom.detJ = detJ; 11280f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateResidual(fe, prob, f, Ne, geom, u, u_t, probAux, a, elemVec);CHKERRQ(ierr); 11290f2d7e86SMatthew G. Knepley geom.v0 = &v0[offset*dim]; 11300f2d7e86SMatthew G. Knepley geom.J = &J[offset*dim*dim]; 11310f2d7e86SMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 11320f2d7e86SMatthew G. Knepley geom.detJ = &detJ[offset]; 11330f2d7e86SMatthew 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); 11340f2d7e86SMatthew G. Knepley } 11350f2d7e86SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 11360f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, name, totDim, &elemVec[c*totDim]);CHKERRQ(ierr);} 11370f2d7e86SMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, section, F, c, &elemVec[c*totDim], ADD_VALUES);CHKERRQ(ierr); 11380f2d7e86SMatthew G. Knepley } 11390f2d7e86SMatthew G. Knepley ierr = PetscFree7(u,u_t,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 11400f2d7e86SMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 11410f2d7e86SMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr); 11420f2d7e86SMatthew G. Knepley ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 11430f2d7e86SMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) { 11440f2d7e86SMatthew G. Knepley const char *bdLabel; 11450f2d7e86SMatthew G. Knepley DMLabel label; 11460f2d7e86SMatthew G. Knepley IS pointIS; 11470f2d7e86SMatthew G. Knepley const PetscInt *points; 11480f2d7e86SMatthew G. Knepley const PetscInt *values; 11490f2d7e86SMatthew G. Knepley PetscReal *n; 11500f2d7e86SMatthew G. Knepley PetscInt field, numValues, numPoints, p, dep, numFaces; 11510f2d7e86SMatthew G. Knepley PetscBool isEssential; 11520f2d7e86SMatthew G. Knepley 11530f2d7e86SMatthew G. Knepley ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, &bdLabel, &field, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 11540f2d7e86SMatthew G. Knepley if (isEssential) continue; 11550f2d7e86SMatthew G. Knepley if (numValues != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Bug me and I will fix this"); 11560f2d7e86SMatthew G. Knepley ierr = DMPlexGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 11570f2d7e86SMatthew G. Knepley ierr = DMLabelGetStratumSize(label, 1, &numPoints);CHKERRQ(ierr); 11580f2d7e86SMatthew G. Knepley ierr = DMLabelGetStratumIS(label, 1, &pointIS);CHKERRQ(ierr); 11590f2d7e86SMatthew G. Knepley ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 11600f2d7e86SMatthew G. Knepley for (p = 0, numFaces = 0; p < numPoints; ++p) { 11610f2d7e86SMatthew G. Knepley ierr = DMLabelGetValue(depth, points[p], &dep);CHKERRQ(ierr); 11620f2d7e86SMatthew G. Knepley if (dep == dim-1) ++numFaces; 11630f2d7e86SMatthew G. Knepley } 11640f2d7e86SMatthew 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); 11650f2d7e86SMatthew G. Knepley if (X_t) {ierr = PetscMalloc1(numFaces*totDimBd,&u_t);CHKERRQ(ierr);} 11660f2d7e86SMatthew G. Knepley for (p = 0, f = 0; p < numPoints; ++p) { 11670f2d7e86SMatthew G. Knepley const PetscInt point = points[p]; 11680f2d7e86SMatthew G. Knepley PetscScalar *x = NULL; 11690f2d7e86SMatthew G. Knepley PetscInt i; 11700f2d7e86SMatthew G. Knepley 11710f2d7e86SMatthew G. Knepley ierr = DMLabelGetValue(depth, points[p], &dep);CHKERRQ(ierr); 11720f2d7e86SMatthew G. Knepley if (dep != dim-1) continue; 11738e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, point, NULL, &v0[f*dim], &J[f*dim*dim], &invJ[f*dim*dim], &detJ[f]);CHKERRQ(ierr); 11740f2d7e86SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFVM(dm, point, NULL, NULL, &n[f*dim]); 11750f2d7e86SMatthew G. Knepley if (detJ[f] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for face %d", detJ[f], point); 11760f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, point, NULL, &x);CHKERRQ(ierr); 11770f2d7e86SMatthew G. Knepley for (i = 0; i < totDimBd; ++i) u[f*totDimBd+i] = x[i]; 11780f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, point, NULL, &x);CHKERRQ(ierr); 11790f2d7e86SMatthew G. Knepley if (X_t) { 11800f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, point, NULL, &x);CHKERRQ(ierr); 11810f2d7e86SMatthew G. Knepley for (i = 0; i < totDimBd; ++i) u_t[f*totDimBd+i] = x[i]; 11820f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, point, NULL, &x);CHKERRQ(ierr); 11830f2d7e86SMatthew G. Knepley } 11840f2d7e86SMatthew G. Knepley ++f; 11850f2d7e86SMatthew G. Knepley } 11860f2d7e86SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 11870f2d7e86SMatthew G. Knepley PetscFE fe; 11880f2d7e86SMatthew G. Knepley PetscInt numQuadPoints, Nb; 11890f2d7e86SMatthew G. Knepley /* Conforming batches */ 11900f2d7e86SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 11910f2d7e86SMatthew G. Knepley /* Remainder */ 11920f2d7e86SMatthew G. Knepley PetscInt Nr, offset; 11930f2d7e86SMatthew G. Knepley 11942764a2aaSMatthew G. Knepley ierr = PetscDSGetBdDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 11950f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 11960f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 11970f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 11980f2d7e86SMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 11990f2d7e86SMatthew G. Knepley blockSize = Nb*numQuadPoints; 12000f2d7e86SMatthew G. Knepley batchSize = numBlocks * blockSize; 12010f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 12020f2d7e86SMatthew G. Knepley numChunks = numFaces / (numBatches*batchSize); 12030f2d7e86SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 12040f2d7e86SMatthew G. Knepley Nr = numFaces % (numBatches*batchSize); 12050f2d7e86SMatthew G. Knepley offset = numFaces - Nr; 12060f2d7e86SMatthew G. Knepley geom.v0 = v0; 12070f2d7e86SMatthew G. Knepley geom.n = n; 12080f2d7e86SMatthew G. Knepley geom.J = J; 12090f2d7e86SMatthew G. Knepley geom.invJ = invJ; 12100f2d7e86SMatthew G. Knepley geom.detJ = detJ; 12110f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateBdResidual(fe, prob, f, Ne, geom, u, u_t, NULL, NULL, elemVec);CHKERRQ(ierr); 12120f2d7e86SMatthew G. Knepley geom.v0 = &v0[offset*dim]; 12130f2d7e86SMatthew G. Knepley geom.n = &n[offset*dim]; 12140f2d7e86SMatthew G. Knepley geom.J = &J[offset*dim*dim]; 12150f2d7e86SMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 12160f2d7e86SMatthew G. Knepley geom.detJ = &detJ[offset]; 12170f2d7e86SMatthew 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); 12180f2d7e86SMatthew G. Knepley } 12190f2d7e86SMatthew G. Knepley for (p = 0, f = 0; p < numPoints; ++p) { 12200f2d7e86SMatthew G. Knepley const PetscInt point = points[p]; 12210f2d7e86SMatthew G. Knepley 12220f2d7e86SMatthew G. Knepley ierr = DMLabelGetValue(depth, point, &dep);CHKERRQ(ierr); 12230f2d7e86SMatthew G. Knepley if (dep != dim-1) continue; 12240f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellVector(point, "BdResidual", totDimBd, &elemVec[f*totDimBd]);CHKERRQ(ierr);} 12250f2d7e86SMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, NULL, F, point, &elemVec[f*totDimBd], ADD_VALUES);CHKERRQ(ierr); 12260f2d7e86SMatthew G. Knepley ++f; 12270f2d7e86SMatthew G. Knepley } 12280f2d7e86SMatthew G. Knepley ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 12290f2d7e86SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 12300f2d7e86SMatthew G. Knepley ierr = PetscFree7(u,v0,n,J,invJ,detJ,elemVec);CHKERRQ(ierr); 12310f2d7e86SMatthew G. Knepley if (X_t) {ierr = PetscFree(u_t);CHKERRQ(ierr);} 12320f2d7e86SMatthew G. Knepley } 12330f2d7e86SMatthew G. Knepley if (mesh->printFEM) {ierr = DMPrintLocalVec(dm, name, mesh->printTol, F);CHKERRQ(ierr);} 12340f2d7e86SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_ResidualFEM,dm,0,0,0);CHKERRQ(ierr); 12350f2d7e86SMatthew G. Knepley PetscFunctionReturn(0); 12360f2d7e86SMatthew G. Knepley } 12370f2d7e86SMatthew G. Knepley 12380f2d7e86SMatthew G. Knepley #undef __FUNCT__ 123908f11eefSMatthew G. Knepley #define __FUNCT__ "DMPlexComputeResidualFEM_Check" 124008f11eefSMatthew G. Knepley static PetscErrorCode DMPlexComputeResidualFEM_Check(DM dm, Vec X, Vec X_t, Vec F, void *user) 124108f11eefSMatthew G. Knepley { 124208f11eefSMatthew G. Knepley DM dmCh, dmAux; 124308f11eefSMatthew G. Knepley Vec A; 12446f4eac71SMatthew G. Knepley PetscDS prob, probCh, probAux = NULL; 124508f11eefSMatthew G. Knepley PetscQuadrature q; 124608f11eefSMatthew G. Knepley PetscCellGeometry geom; 124708f11eefSMatthew G. Knepley PetscSection section, sectionAux; 124808f11eefSMatthew G. Knepley PetscReal *v0, *J, *invJ, *detJ; 124908f11eefSMatthew G. Knepley PetscScalar *elemVec, *elemVecCh, *u, *u_t, *a = NULL; 125008f11eefSMatthew G. Knepley PetscInt dim, Nf, f, numCells, cStart, cEnd, c; 125108f11eefSMatthew G. Knepley PetscInt totDim, totDimAux, diffCell = 0; 125208f11eefSMatthew G. Knepley PetscErrorCode ierr; 125308f11eefSMatthew G. Knepley 125408f11eefSMatthew G. Knepley PetscFunctionBegin; 1255c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 125608f11eefSMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 12576f4eac71SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 12586f4eac71SMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 125908f11eefSMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 126008f11eefSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 126108f11eefSMatthew G. Knepley numCells = cEnd - cStart; 126208f11eefSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmCh", (PetscObject *) &dmCh);CHKERRQ(ierr); 12636f4eac71SMatthew G. Knepley ierr = DMGetDS(dmCh, &probCh);CHKERRQ(ierr); 126408f11eefSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 126508f11eefSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 126608f11eefSMatthew G. Knepley if (dmAux) { 126708f11eefSMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 12686f4eac71SMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 12696f4eac71SMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 127008f11eefSMatthew G. Knepley } 127108f11eefSMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesFEM(dm, X);CHKERRQ(ierr); 127208f11eefSMatthew G. Knepley ierr = VecSet(F, 0.0);CHKERRQ(ierr); 127308f11eefSMatthew 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); 127408f11eefSMatthew G. Knepley ierr = PetscMalloc1(numCells*totDim,&elemVecCh);CHKERRQ(ierr); 127508f11eefSMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 127608f11eefSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 127708f11eefSMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 127808f11eefSMatthew G. Knepley PetscInt i; 127908f11eefSMatthew G. Knepley 12808e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 128108f11eefSMatthew G. Knepley if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 128208f11eefSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 128308f11eefSMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 128408f11eefSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 128508f11eefSMatthew G. Knepley if (X_t) { 128608f11eefSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 128708f11eefSMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i]; 128808f11eefSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 128908f11eefSMatthew G. Knepley } 129008f11eefSMatthew G. Knepley if (dmAux) { 129108f11eefSMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 129208f11eefSMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 129308f11eefSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 129408f11eefSMatthew G. Knepley } 129508f11eefSMatthew G. Knepley } 129608f11eefSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 129708f11eefSMatthew G. Knepley PetscFE fe, feCh; 129808f11eefSMatthew G. Knepley PetscInt numQuadPoints, Nb; 129908f11eefSMatthew G. Knepley /* Conforming batches */ 130008f11eefSMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 130108f11eefSMatthew G. Knepley /* Remainder */ 130208f11eefSMatthew G. Knepley PetscInt Nr, offset; 130308f11eefSMatthew G. Knepley 13046f4eac71SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 13056f4eac71SMatthew G. Knepley ierr = PetscDSGetDiscretization(probCh, f, (PetscObject *) &feCh);CHKERRQ(ierr); 130608f11eefSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 130708f11eefSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 130808f11eefSMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 130908f11eefSMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 131008f11eefSMatthew G. Knepley blockSize = Nb*numQuadPoints; 131108f11eefSMatthew G. Knepley batchSize = numBlocks * blockSize; 131208f11eefSMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 131308f11eefSMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 131408f11eefSMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 131508f11eefSMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 131608f11eefSMatthew G. Knepley offset = numCells - Nr; 131708f11eefSMatthew G. Knepley geom.v0 = v0; 131808f11eefSMatthew G. Knepley geom.J = J; 131908f11eefSMatthew G. Knepley geom.invJ = invJ; 132008f11eefSMatthew G. Knepley geom.detJ = detJ; 132108f11eefSMatthew G. Knepley ierr = PetscFEIntegrateResidual(fe, prob, f, Ne, geom, u, u_t, probAux, a, elemVec);CHKERRQ(ierr); 132208f11eefSMatthew G. Knepley ierr = PetscFEIntegrateResidual(feCh, prob, f, Ne, geom, u, u_t, probAux, a, elemVecCh);CHKERRQ(ierr); 132308f11eefSMatthew G. Knepley geom.v0 = &v0[offset*dim]; 132408f11eefSMatthew G. Knepley geom.J = &J[offset*dim*dim]; 132508f11eefSMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 132608f11eefSMatthew G. Knepley geom.detJ = &detJ[offset]; 132708f11eefSMatthew 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); 132808f11eefSMatthew 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); 132908f11eefSMatthew G. Knepley } 133008f11eefSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 133108f11eefSMatthew G. Knepley PetscBool diff = PETSC_FALSE; 133208f11eefSMatthew G. Knepley PetscInt d; 133308f11eefSMatthew G. Knepley 133408f11eefSMatthew 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;} 133508f11eefSMatthew G. Knepley if (diff) { 133608f11eefSMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "Different cell %d\n", c);CHKERRQ(ierr); 133708f11eefSMatthew G. Knepley ierr = DMPrintCellVector(c, "Residual", totDim, &elemVec[c*totDim]);CHKERRQ(ierr); 133808f11eefSMatthew G. Knepley ierr = DMPrintCellVector(c, "Check Residual", totDim, &elemVecCh[c*totDim]);CHKERRQ(ierr); 133908f11eefSMatthew G. Knepley ++diffCell; 134008f11eefSMatthew G. Knepley } 134108f11eefSMatthew G. Knepley if (diffCell > 9) break; 134208f11eefSMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, section, F, c, &elemVec[c*totDim], ADD_VALUES);CHKERRQ(ierr); 134308f11eefSMatthew G. Knepley } 134408f11eefSMatthew G. Knepley ierr = PetscFree7(u,u_t,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 134508f11eefSMatthew G. Knepley ierr = PetscFree(elemVecCh);CHKERRQ(ierr); 134608f11eefSMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 134708f11eefSMatthew G. Knepley PetscFunctionReturn(0); 134808f11eefSMatthew G. Knepley } 134908f11eefSMatthew G. Knepley 135008f11eefSMatthew G. Knepley #undef __FUNCT__ 13510f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexSNESComputeResidualFEM" 1352a0845e3aSMatthew G. Knepley /*@ 13530f2d7e86SMatthew G. Knepley DMPlexSNESComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 1354a0845e3aSMatthew G. Knepley 1355a0845e3aSMatthew G. Knepley Input Parameters: 1356a0845e3aSMatthew G. Knepley + dm - The mesh 13570f2d7e86SMatthew G. Knepley . X - Local solution 1358a0845e3aSMatthew G. Knepley - user - The user context 1359a0845e3aSMatthew G. Knepley 1360a0845e3aSMatthew G. Knepley Output Parameter: 1361a0845e3aSMatthew G. Knepley . F - Local output vector 1362a0845e3aSMatthew G. Knepley 1363a0845e3aSMatthew G. Knepley Level: developer 1364a0845e3aSMatthew G. Knepley 1365a0845e3aSMatthew G. Knepley .seealso: DMPlexComputeJacobianActionFEM() 1366a0845e3aSMatthew G. Knepley @*/ 13670f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 1368a0845e3aSMatthew G. Knepley { 136908f11eefSMatthew G. Knepley PetscObject check; 1370a0845e3aSMatthew G. Knepley PetscErrorCode ierr; 1371a0845e3aSMatthew G. Knepley 1372a0845e3aSMatthew G. Knepley PetscFunctionBegin; 137308f11eefSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmCh", &check);CHKERRQ(ierr); 137408f11eefSMatthew G. Knepley if (check) {ierr = DMPlexComputeResidualFEM_Check(dm, X, NULL, F, user);CHKERRQ(ierr);} 137508f11eefSMatthew G. Knepley else {ierr = DMPlexComputeResidualFEM_Internal(dm, X, NULL, F, user);CHKERRQ(ierr);} 13760f2d7e86SMatthew G. Knepley PetscFunctionReturn(0); 13770f2d7e86SMatthew G. Knepley } 13780f2d7e86SMatthew G. Knepley 13790f2d7e86SMatthew G. Knepley #undef __FUNCT__ 1380adbe6fbbSMatthew G. Knepley #define __FUNCT__ "DMPlexTSComputeIFunctionFEM" 1381adbe6fbbSMatthew G. Knepley /*@ 1382adbe6fbbSMatthew G. Knepley DMPlexTSComputeIFunctionFEM - Form the local residual F from the local input X using pointwise functions specified by the user 1383adbe6fbbSMatthew G. Knepley 1384adbe6fbbSMatthew G. Knepley Input Parameters: 1385adbe6fbbSMatthew G. Knepley + dm - The mesh 1386adbe6fbbSMatthew G. Knepley . t - The time 1387adbe6fbbSMatthew G. Knepley . X - Local solution 1388adbe6fbbSMatthew G. Knepley . X_t - Local solution time derivative, or NULL 1389adbe6fbbSMatthew G. Knepley - user - The user context 1390adbe6fbbSMatthew G. Knepley 1391adbe6fbbSMatthew G. Knepley Output Parameter: 1392adbe6fbbSMatthew G. Knepley . F - Local output vector 1393adbe6fbbSMatthew G. Knepley 1394adbe6fbbSMatthew G. Knepley Level: developer 1395adbe6fbbSMatthew G. Knepley 1396adbe6fbbSMatthew G. Knepley .seealso: DMPlexComputeJacobianActionFEM() 1397adbe6fbbSMatthew G. Knepley @*/ 1398adbe6fbbSMatthew G. Knepley PetscErrorCode DMPlexTSComputeIFunctionFEM(DM dm, PetscReal time, Vec X, Vec X_t, Vec F, void *user) 1399adbe6fbbSMatthew G. Knepley { 1400adbe6fbbSMatthew G. Knepley PetscErrorCode ierr; 1401adbe6fbbSMatthew G. Knepley 1402adbe6fbbSMatthew G. Knepley PetscFunctionBegin; 1403adbe6fbbSMatthew G. Knepley ierr = DMPlexComputeResidualFEM_Internal(dm, X, X_t, F, user);CHKERRQ(ierr); 1404adbe6fbbSMatthew G. Knepley PetscFunctionReturn(0); 1405adbe6fbbSMatthew G. Knepley } 1406adbe6fbbSMatthew G. Knepley 1407adbe6fbbSMatthew G. Knepley #undef __FUNCT__ 14080f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeJacobianFEM_Internal" 14090f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexComputeJacobianFEM_Internal(DM dm, Vec X, Vec X_t, Mat Jac, Mat JacP,void *user) 14100f2d7e86SMatthew G. Knepley { 14110f2d7e86SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 14120f2d7e86SMatthew G. Knepley const char *name = "Jacobian"; 14130f2d7e86SMatthew G. Knepley DM dmAux; 14140f2d7e86SMatthew G. Knepley DMLabel depth; 14150f2d7e86SMatthew G. Knepley Vec A; 14162764a2aaSMatthew G. Knepley PetscDS prob, probAux = NULL; 14170f2d7e86SMatthew G. Knepley PetscQuadrature quad; 14180f2d7e86SMatthew G. Knepley PetscCellGeometry geom; 14190f2d7e86SMatthew G. Knepley PetscSection section, globalSection, sectionAux; 14200f2d7e86SMatthew G. Knepley PetscReal *v0, *J, *invJ, *detJ; 14210f2d7e86SMatthew G. Knepley PetscScalar *elemMat, *u, *u_t, *a = NULL; 14220f2d7e86SMatthew G. Knepley PetscInt dim, Nf, f, fieldI, fieldJ, numCells, cStart, cEnd, c; 14230f2d7e86SMatthew G. Knepley PetscInt totDim, totDimBd, totDimAux, numBd, bd; 14240f2d7e86SMatthew G. Knepley PetscBool isShell; 14250f2d7e86SMatthew G. Knepley PetscErrorCode ierr; 14260f2d7e86SMatthew G. Knepley 14270f2d7e86SMatthew G. Knepley PetscFunctionBegin; 14280f2d7e86SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 1429c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1430a0845e3aSMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 14310f2d7e86SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 14322764a2aaSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 14332764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 14342764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalBdDimension(prob, &totDimBd);CHKERRQ(ierr); 14359a559087SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 1436a0845e3aSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1437a0845e3aSMatthew G. Knepley numCells = cEnd - cStart; 14389a559087SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 14399a559087SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 14409a559087SMatthew G. Knepley if (dmAux) { 14419a559087SMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 14422764a2aaSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 14432764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 14449a559087SMatthew G. Knepley } 14453351dd3dSMatthew G. Knepley ierr = DMPlexInsertBoundaryValuesFEM(dm, X);CHKERRQ(ierr); 14460f2d7e86SMatthew G. Knepley ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 14470f2d7e86SMatthew 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); 14480f2d7e86SMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 1449a0845e3aSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 14500f2d7e86SMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 1451a0845e3aSMatthew G. Knepley PetscInt i; 1452a0845e3aSMatthew G. Knepley 14538e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 1454a0845e3aSMatthew G. Knepley if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 1455a0845e3aSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 14560f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 1457a0845e3aSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 14580f2d7e86SMatthew G. Knepley if (X_t) { 14590f2d7e86SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 14600f2d7e86SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i]; 14610f2d7e86SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 14620f2d7e86SMatthew G. Knepley } 14639a559087SMatthew G. Knepley if (dmAux) { 14649a559087SMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 14650f2d7e86SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 14669a559087SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 1467a0845e3aSMatthew G. Knepley } 14689a559087SMatthew G. Knepley } 14690f2d7e86SMatthew G. Knepley ierr = PetscMemzero(elemMat, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr); 14700f2d7e86SMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 14710f2d7e86SMatthew G. Knepley PetscFE fe; 147221454ff5SMatthew G. Knepley PetscInt numQuadPoints, Nb; 1473a0845e3aSMatthew G. Knepley /* Conforming batches */ 1474f30c5766SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 1475a0845e3aSMatthew G. Knepley /* Remainder */ 1476a0845e3aSMatthew G. Knepley PetscInt Nr, offset; 1477a0845e3aSMatthew G. Knepley 14782764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 14790f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 14800f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 14810f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 14820f2d7e86SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 148321454ff5SMatthew G. Knepley blockSize = Nb*numQuadPoints; 1484a0845e3aSMatthew G. Knepley batchSize = numBlocks * blockSize; 14850f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 1486a0845e3aSMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 1487a0845e3aSMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 1488a0845e3aSMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 1489a0845e3aSMatthew G. Knepley offset = numCells - Nr; 14900f2d7e86SMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 1491a0845e3aSMatthew G. Knepley geom.v0 = v0; 1492a0845e3aSMatthew G. Knepley geom.J = J; 1493a0845e3aSMatthew G. Knepley geom.invJ = invJ; 1494a0845e3aSMatthew G. Knepley geom.detJ = detJ; 14950f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateJacobian(fe, prob, fieldI, fieldJ, Ne, geom, u, u_t, probAux, a, elemMat);CHKERRQ(ierr); 1496a0845e3aSMatthew G. Knepley geom.v0 = &v0[offset*dim]; 1497a0845e3aSMatthew G. Knepley geom.J = &J[offset*dim*dim]; 1498a0845e3aSMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 1499a0845e3aSMatthew G. Knepley geom.detJ = &detJ[offset]; 15000f2d7e86SMatthew 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); 15010f2d7e86SMatthew G. Knepley } 1502a0845e3aSMatthew G. Knepley } 1503a0845e3aSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 15040f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, name, totDim, totDim, &elemMat[c*totDim*totDim]);CHKERRQ(ierr);} 15050f2d7e86SMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, globalSection, JacP, c, &elemMat[c*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 1506a0845e3aSMatthew G. Knepley } 15070f2d7e86SMatthew G. Knepley ierr = PetscFree7(u,u_t,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 15089a559087SMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 15090f2d7e86SMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr); 15100f2d7e86SMatthew G. Knepley ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 15111c093863SMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr); 15121c093863SMatthew G. Knepley ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 15131c093863SMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) { 15141c093863SMatthew G. Knepley const char *bdLabel; 15151c093863SMatthew G. Knepley DMLabel label; 15161c093863SMatthew G. Knepley IS pointIS; 15171c093863SMatthew G. Knepley const PetscInt *points; 15181c093863SMatthew G. Knepley const PetscInt *values; 15191c093863SMatthew G. Knepley PetscReal *n; 15201c093863SMatthew G. Knepley PetscInt field, numValues, numPoints, p, dep, numFaces; 15211c093863SMatthew G. Knepley PetscBool isEssential; 15221c093863SMatthew G. Knepley 152363d5297fSMatthew G. Knepley ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, &bdLabel, &field, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 15240f2d7e86SMatthew G. Knepley if (isEssential) continue; 15251c093863SMatthew G. Knepley if (numValues != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Bug me and I will fix this"); 15261c093863SMatthew G. Knepley ierr = DMPlexGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 15271c093863SMatthew G. Knepley ierr = DMLabelGetStratumSize(label, 1, &numPoints);CHKERRQ(ierr); 15281c093863SMatthew G. Knepley ierr = DMLabelGetStratumIS(label, 1, &pointIS);CHKERRQ(ierr); 15291c093863SMatthew G. Knepley ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 1530075da914SMatthew G. Knepley for (p = 0, numFaces = 0; p < numPoints; ++p) { 1531075da914SMatthew G. Knepley ierr = DMLabelGetValue(depth, points[p], &dep);CHKERRQ(ierr); 1532075da914SMatthew G. Knepley if (dep == dim-1) ++numFaces; 1533075da914SMatthew G. Knepley } 15340f2d7e86SMatthew 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); 15350f2d7e86SMatthew G. Knepley if (X_t) {ierr = PetscMalloc1(numFaces*totDimBd,&u_t);CHKERRQ(ierr);} 1536075da914SMatthew G. Knepley for (p = 0, f = 0; p < numPoints; ++p) { 1537f1ea0e2fSMatthew G. Knepley const PetscInt point = points[p]; 1538f1ea0e2fSMatthew G. Knepley PetscScalar *x = NULL; 1539f1ea0e2fSMatthew G. Knepley PetscInt i; 1540f1ea0e2fSMatthew G. Knepley 1541075da914SMatthew G. Knepley ierr = DMLabelGetValue(depth, points[p], &dep);CHKERRQ(ierr); 1542075da914SMatthew G. Knepley if (dep != dim-1) continue; 15438e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, point, NULL, &v0[f*dim], &J[f*dim*dim], &invJ[f*dim*dim], &detJ[f]);CHKERRQ(ierr); 1544a8007bbfSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFVM(dm, point, NULL, NULL, &n[f*dim]); 1545075da914SMatthew G. Knepley if (detJ[f] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for face %d", detJ[f], point); 1546f1ea0e2fSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, point, NULL, &x);CHKERRQ(ierr); 15470f2d7e86SMatthew G. Knepley for (i = 0; i < totDimBd; ++i) u[f*totDimBd+i] = x[i]; 1548f1ea0e2fSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, point, NULL, &x);CHKERRQ(ierr); 15490f2d7e86SMatthew G. Knepley if (X_t) { 1550af1eca97SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, point, NULL, &x);CHKERRQ(ierr); 15510f2d7e86SMatthew G. Knepley for (i = 0; i < totDimBd; ++i) u_t[f*totDimBd+i] = x[i]; 1552af1eca97SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, point, NULL, &x);CHKERRQ(ierr); 15530f2d7e86SMatthew G. Knepley } 1554af1eca97SMatthew G. Knepley ++f; 1555af1eca97SMatthew G. Knepley } 15560f2d7e86SMatthew G. Knepley ierr = PetscMemzero(elemMat, numFaces*totDimBd*totDimBd * sizeof(PetscScalar));CHKERRQ(ierr); 15570f2d7e86SMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 15580f2d7e86SMatthew G. Knepley PetscFE fe; 1559af1eca97SMatthew G. Knepley PetscInt numQuadPoints, Nb; 1560af1eca97SMatthew G. Knepley /* Conforming batches */ 1561af1eca97SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 1562af1eca97SMatthew G. Knepley /* Remainder */ 1563af1eca97SMatthew G. Knepley PetscInt Nr, offset; 1564af1eca97SMatthew G. Knepley 15652764a2aaSMatthew G. Knepley ierr = PetscDSGetBdDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 15660f2d7e86SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 15670f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 15680f2d7e86SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 156921454ff5SMatthew G. Knepley ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 157021454ff5SMatthew G. Knepley blockSize = Nb*numQuadPoints; 15710483ade4SMatthew G. Knepley batchSize = numBlocks * blockSize; 15720f2d7e86SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 15730f2d7e86SMatthew G. Knepley numChunks = numFaces / (numBatches*batchSize); 15740483ade4SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 15750f2d7e86SMatthew G. Knepley Nr = numFaces % (numBatches*batchSize); 15760f2d7e86SMatthew G. Knepley offset = numFaces - Nr; 15770f2d7e86SMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 15780483ade4SMatthew G. Knepley geom.v0 = v0; 15790f2d7e86SMatthew G. Knepley geom.n = n; 15800483ade4SMatthew G. Knepley geom.J = J; 15810483ade4SMatthew G. Knepley geom.invJ = invJ; 15820483ade4SMatthew G. Knepley geom.detJ = detJ; 15830f2d7e86SMatthew G. Knepley ierr = PetscFEIntegrateBdJacobian(fe, prob, fieldI, fieldJ, Ne, geom, u, u_t, NULL, NULL, elemMat);CHKERRQ(ierr); 15840483ade4SMatthew G. Knepley geom.v0 = &v0[offset*dim]; 15850f2d7e86SMatthew G. Knepley geom.n = &n[offset*dim]; 15860483ade4SMatthew G. Knepley geom.J = &J[offset*dim*dim]; 15870483ade4SMatthew G. Knepley geom.invJ = &invJ[offset*dim*dim]; 15880483ade4SMatthew G. Knepley geom.detJ = &detJ[offset]; 15890f2d7e86SMatthew 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); 1590cb1e1211SMatthew G Knepley } 1591cb1e1211SMatthew G Knepley } 15920f2d7e86SMatthew G. Knepley for (p = 0, f = 0; p < numPoints; ++p) { 15930f2d7e86SMatthew G. Knepley const PetscInt point = points[p]; 1594cb1e1211SMatthew G Knepley 15950f2d7e86SMatthew G. Knepley ierr = DMLabelGetValue(depth, point, &dep);CHKERRQ(ierr); 15960f2d7e86SMatthew G. Knepley if (dep != dim-1) continue; 15970f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(point, "BdJacobian", totDimBd, totDimBd, &elemMat[f*totDimBd*totDimBd]);CHKERRQ(ierr);} 15980f2d7e86SMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, globalSection, JacP, point, &elemMat[f*totDimBd*totDimBd], ADD_VALUES);CHKERRQ(ierr); 15990f2d7e86SMatthew G. Knepley ++f; 1600cb1e1211SMatthew G Knepley } 16010f2d7e86SMatthew G. Knepley ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 16020f2d7e86SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 16030f2d7e86SMatthew G. Knepley ierr = PetscFree7(u,v0,n,J,invJ,detJ,elemMat);CHKERRQ(ierr); 16040f2d7e86SMatthew G. Knepley if (X_t) {ierr = PetscFree(u_t);CHKERRQ(ierr);} 1605cb1e1211SMatthew G Knepley } 16060f2d7e86SMatthew G. Knepley ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 16070f2d7e86SMatthew G. Knepley ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 16080f2d7e86SMatthew G. Knepley if (mesh->printFEM) { 16090f2d7e86SMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_WORLD, "%s:\n", name);CHKERRQ(ierr); 16100f2d7e86SMatthew G. Knepley ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 16110f2d7e86SMatthew G. Knepley ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 16120f2d7e86SMatthew G. Knepley } 16130f2d7e86SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 16140f2d7e86SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) Jac, MATSHELL, &isShell);CHKERRQ(ierr); 16150f2d7e86SMatthew G. Knepley if (isShell) { 16160f2d7e86SMatthew G. Knepley JacActionCtx *jctx; 16170f2d7e86SMatthew G. Knepley 16180f2d7e86SMatthew G. Knepley ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 16190f2d7e86SMatthew G. Knepley ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 16200f2d7e86SMatthew G. Knepley } 1621cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 1622cb1e1211SMatthew G Knepley } 1623cb1e1211SMatthew G Knepley 1624cb1e1211SMatthew G Knepley #undef __FUNCT__ 16250f2d7e86SMatthew G. Knepley #define __FUNCT__ "DMPlexSNESComputeJacobianFEM" 1626cb1e1211SMatthew G Knepley /*@ 16270f2d7e86SMatthew G. Knepley DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 1628cb1e1211SMatthew G Knepley 1629cb1e1211SMatthew G Knepley Input Parameters: 1630cb1e1211SMatthew G Knepley + dm - The mesh 1631cb1e1211SMatthew G Knepley . X - Local input vector 1632cb1e1211SMatthew G Knepley - user - The user context 1633cb1e1211SMatthew G Knepley 1634cb1e1211SMatthew G Knepley Output Parameter: 1635cb1e1211SMatthew G Knepley . Jac - Jacobian matrix 1636cb1e1211SMatthew G Knepley 1637cb1e1211SMatthew G Knepley Note: 16388026896cSMatthew G. Knepley The first member of the user context must be an FEMContext. 1639cb1e1211SMatthew G Knepley 1640cb1e1211SMatthew G Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 1641cb1e1211SMatthew G Knepley like a GPU, or vectorize on a multicore machine. 1642cb1e1211SMatthew G Knepley 16430059ad2aSSatish Balay Level: developer 16440059ad2aSSatish Balay 1645cb1e1211SMatthew G Knepley .seealso: FormFunctionLocal() 1646878cb397SSatish Balay @*/ 16470f2d7e86SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user) 1648cb1e1211SMatthew G Knepley { 1649cb1e1211SMatthew G Knepley PetscErrorCode ierr; 1650cb1e1211SMatthew G Knepley 1651cb1e1211SMatthew G Knepley PetscFunctionBegin; 16520f2d7e86SMatthew G. Knepley ierr = DMPlexComputeJacobianFEM_Internal(dm, X, NULL, Jac, JacP, user);CHKERRQ(ierr); 1653cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 1654cb1e1211SMatthew G Knepley } 1655bceba477SMatthew G. Knepley 1656d69c5d34SMatthew G. Knepley #undef __FUNCT__ 1657d69c5d34SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeInterpolatorFEM" 1658d69c5d34SMatthew G. Knepley /*@ 1659d69c5d34SMatthew G. Knepley DMPlexComputeInterpolatorFEM - Form the local portion of the interpolation matrix I from the coarse DM to the uniformly refined DM. 1660d69c5d34SMatthew G. Knepley 1661d69c5d34SMatthew G. Knepley Input Parameters: 1662d69c5d34SMatthew G. Knepley + dmf - The fine mesh 1663d69c5d34SMatthew G. Knepley . dmc - The coarse mesh 1664d69c5d34SMatthew G. Knepley - user - The user context 1665d69c5d34SMatthew G. Knepley 1666d69c5d34SMatthew G. Knepley Output Parameter: 1667934789fcSMatthew G. Knepley . In - The interpolation matrix 1668d69c5d34SMatthew G. Knepley 1669d69c5d34SMatthew G. Knepley Note: 1670d69c5d34SMatthew G. Knepley The first member of the user context must be an FEMContext. 1671d69c5d34SMatthew G. Knepley 1672d69c5d34SMatthew G. Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 1673d69c5d34SMatthew G. Knepley like a GPU, or vectorize on a multicore machine. 1674d69c5d34SMatthew G. Knepley 1675d69c5d34SMatthew G. Knepley Level: developer 1676d69c5d34SMatthew G. Knepley 1677d69c5d34SMatthew G. Knepley .seealso: DMPlexComputeJacobianFEM() 1678d69c5d34SMatthew G. Knepley @*/ 1679934789fcSMatthew G. Knepley PetscErrorCode DMPlexComputeInterpolatorFEM(DM dmc, DM dmf, Mat In, void *user) 1680d69c5d34SMatthew G. Knepley { 1681d69c5d34SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dmc->data; 1682d69c5d34SMatthew G. Knepley const char *name = "Interpolator"; 16832764a2aaSMatthew G. Knepley PetscDS prob; 1684d69c5d34SMatthew G. Knepley PetscFE *feRef; 1685d69c5d34SMatthew G. Knepley PetscSection fsection, fglobalSection; 1686d69c5d34SMatthew G. Knepley PetscSection csection, cglobalSection; 1687d69c5d34SMatthew G. Knepley PetscScalar *elemMat; 1688942a7a06SMatthew G. Knepley PetscInt dim, Nf, f, fieldI, fieldJ, offsetI, offsetJ, cStart, cEnd, c; 16890f2d7e86SMatthew G. Knepley PetscInt cTotDim, rTotDim = 0; 1690d69c5d34SMatthew G. Knepley PetscErrorCode ierr; 1691d69c5d34SMatthew G. Knepley 1692d69c5d34SMatthew G. Knepley PetscFunctionBegin; 1693d69c5d34SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1694c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 1695d69c5d34SMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 1696d69c5d34SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 1697d69c5d34SMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 1698d69c5d34SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 1699d69c5d34SMatthew G. Knepley ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 1700d69c5d34SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 17012764a2aaSMatthew G. Knepley ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr); 1702d69c5d34SMatthew G. Knepley ierr = PetscMalloc1(Nf,&feRef);CHKERRQ(ierr); 1703d69c5d34SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 17040f2d7e86SMatthew G. Knepley PetscFE fe; 17050f2d7e86SMatthew G. Knepley PetscInt rNb, Nc; 1706d69c5d34SMatthew G. Knepley 17072764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 17080f2d7e86SMatthew G. Knepley ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 1709d69c5d34SMatthew G. Knepley ierr = PetscFEGetDimension(feRef[f], &rNb);CHKERRQ(ierr); 17100f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 17110f2d7e86SMatthew G. Knepley rTotDim += rNb*Nc; 1712d69c5d34SMatthew G. Knepley } 17132764a2aaSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 17140f2d7e86SMatthew G. Knepley ierr = PetscMalloc1(rTotDim*cTotDim,&elemMat);CHKERRQ(ierr); 17150f2d7e86SMatthew G. Knepley ierr = PetscMemzero(elemMat, rTotDim*cTotDim * sizeof(PetscScalar));CHKERRQ(ierr); 1716d69c5d34SMatthew G. Knepley for (fieldI = 0, offsetI = 0; fieldI < Nf; ++fieldI) { 1717d69c5d34SMatthew G. Knepley PetscDualSpace Qref; 1718d69c5d34SMatthew G. Knepley PetscQuadrature f; 1719d69c5d34SMatthew G. Knepley const PetscReal *qpoints, *qweights; 1720d69c5d34SMatthew G. Knepley PetscReal *points; 1721d69c5d34SMatthew G. Knepley PetscInt npoints = 0, Nc, Np, fpdim, i, k, p, d; 1722d69c5d34SMatthew G. Knepley 1723d69c5d34SMatthew G. Knepley /* Compose points from all dual basis functionals */ 1724d69c5d34SMatthew G. Knepley ierr = PetscFEGetDualSpace(feRef[fieldI], &Qref);CHKERRQ(ierr); 17250f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(feRef[fieldI], &Nc);CHKERRQ(ierr); 1726d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(Qref, &fpdim);CHKERRQ(ierr); 1727d69c5d34SMatthew G. Knepley for (i = 0; i < fpdim; ++i) { 1728d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1729d69c5d34SMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &Np, NULL, NULL);CHKERRQ(ierr); 1730d69c5d34SMatthew G. Knepley npoints += Np; 1731d69c5d34SMatthew G. Knepley } 1732d69c5d34SMatthew G. Knepley ierr = PetscMalloc1(npoints*dim,&points);CHKERRQ(ierr); 1733d69c5d34SMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) { 1734d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1735d69c5d34SMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &Np, &qpoints, NULL);CHKERRQ(ierr); 1736d69c5d34SMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) for (d = 0; d < dim; ++d) points[k*dim+d] = qpoints[p*dim+d]; 1737d69c5d34SMatthew G. Knepley } 1738d69c5d34SMatthew G. Knepley 1739d69c5d34SMatthew G. Knepley for (fieldJ = 0, offsetJ = 0; fieldJ < Nf; ++fieldJ) { 17400f2d7e86SMatthew G. Knepley PetscFE fe; 1741d69c5d34SMatthew G. Knepley PetscReal *B; 174236a6d9c0SMatthew G. Knepley PetscInt NcJ, cpdim, j; 1743d69c5d34SMatthew G. Knepley 1744d69c5d34SMatthew G. Knepley /* Evaluate basis at points */ 17452764a2aaSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldJ, (PetscObject *) &fe);CHKERRQ(ierr); 17460f2d7e86SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &NcJ);CHKERRQ(ierr); 17470f2d7e86SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &cpdim);CHKERRQ(ierr); 1748ffe73a53SMatthew G. Knepley /* For now, fields only interpolate themselves */ 1749ffe73a53SMatthew G. Knepley if (fieldI == fieldJ) { 17507c927364SMatthew 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); 17510f2d7e86SMatthew G. Knepley ierr = PetscFEGetTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr); 1752d69c5d34SMatthew G. Knepley for (i = 0, k = 0; i < fpdim; ++i) { 1753d69c5d34SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1754d69c5d34SMatthew G. Knepley ierr = PetscQuadratureGetData(f, NULL, &Np, NULL, &qweights);CHKERRQ(ierr); 1755d69c5d34SMatthew G. Knepley for (p = 0; p < Np; ++p, ++k) { 175636a6d9c0SMatthew G. Knepley for (j = 0; j < cpdim; ++j) { 17570f2d7e86SMatthew 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]; 175836a6d9c0SMatthew G. Knepley } 1759d69c5d34SMatthew G. Knepley } 1760d69c5d34SMatthew G. Knepley } 17610f2d7e86SMatthew G. Knepley ierr = PetscFERestoreTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr);CHKERRQ(ierr); 1762ffe73a53SMatthew G. Knepley } 176336a6d9c0SMatthew G. Knepley offsetJ += cpdim*NcJ; 1764d69c5d34SMatthew G. Knepley } 1765d69c5d34SMatthew G. Knepley offsetI += fpdim*Nc; 1766549a8adaSMatthew G. Knepley ierr = PetscFree(points);CHKERRQ(ierr); 1767d69c5d34SMatthew G. Knepley } 17680f2d7e86SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(0, name, rTotDim, cTotDim, elemMat);CHKERRQ(ierr);} 17697f5b169aSMatthew G. Knepley /* Preallocate matrix */ 17707f5b169aSMatthew G. Knepley { 17717f5b169aSMatthew G. Knepley PetscHashJK ht; 17727f5b169aSMatthew G. Knepley PetscLayout rLayout; 17737f5b169aSMatthew G. Knepley PetscInt *dnz, *onz, *cellCIndices, *cellFIndices; 17747f5b169aSMatthew G. Knepley PetscInt locRows, rStart, rEnd, cell, r; 17757f5b169aSMatthew G. Knepley 17767f5b169aSMatthew G. Knepley ierr = MatGetLocalSize(In, &locRows, NULL);CHKERRQ(ierr); 17777f5b169aSMatthew G. Knepley ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) In), &rLayout);CHKERRQ(ierr); 17787f5b169aSMatthew G. Knepley ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 17797f5b169aSMatthew G. Knepley ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 17807f5b169aSMatthew G. Knepley ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 17817f5b169aSMatthew G. Knepley ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 17827f5b169aSMatthew G. Knepley ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 17837f5b169aSMatthew G. Knepley ierr = PetscCalloc4(locRows,&dnz,locRows,&onz,cTotDim,&cellCIndices,rTotDim,&cellFIndices);CHKERRQ(ierr); 17847f5b169aSMatthew G. Knepley ierr = PetscHashJKCreate(&ht);CHKERRQ(ierr); 17857f5b169aSMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 17867f5b169aSMatthew G. Knepley ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, cell, cellCIndices, cellFIndices);CHKERRQ(ierr); 17877f5b169aSMatthew G. Knepley for (r = 0; r < rTotDim; ++r) { 17887f5b169aSMatthew G. Knepley PetscHashJKKey key; 17897f5b169aSMatthew G. Knepley PetscHashJKIter missing, iter; 17907f5b169aSMatthew G. Knepley 17917f5b169aSMatthew G. Knepley key.j = cellFIndices[r]; 17927f5b169aSMatthew G. Knepley if (key.j < 0) continue; 17937f5b169aSMatthew G. Knepley for (c = 0; c < cTotDim; ++c) { 17947f5b169aSMatthew G. Knepley key.k = cellCIndices[c]; 17957f5b169aSMatthew G. Knepley if (key.k < 0) continue; 17967f5b169aSMatthew G. Knepley ierr = PetscHashJKPut(ht, key, &missing, &iter);CHKERRQ(ierr); 17977f5b169aSMatthew G. Knepley if (missing) { 17987f5b169aSMatthew G. Knepley ierr = PetscHashJKSet(ht, iter, 1);CHKERRQ(ierr); 17997f5b169aSMatthew G. Knepley if ((key.k >= rStart) && (key.k < rEnd)) ++dnz[key.j-rStart]; 18007f5b169aSMatthew G. Knepley else ++onz[key.j-rStart]; 18017f5b169aSMatthew G. Knepley } 18027f5b169aSMatthew G. Knepley } 18037f5b169aSMatthew G. Knepley } 18047f5b169aSMatthew G. Knepley } 18057f5b169aSMatthew G. Knepley ierr = PetscHashJKDestroy(&ht);CHKERRQ(ierr); 18067f5b169aSMatthew G. Knepley ierr = MatXAIJSetPreallocation(In, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr); 18077f5b169aSMatthew G. Knepley ierr = MatSetOption(In, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 18087f5b169aSMatthew G. Knepley ierr = PetscFree4(dnz,onz,cellCIndices,cellFIndices);CHKERRQ(ierr); 18097f5b169aSMatthew G. Knepley } 18107f5b169aSMatthew G. Knepley /* Fill matrix */ 18117f5b169aSMatthew G. Knepley ierr = MatZeroEntries(In);CHKERRQ(ierr); 1812d69c5d34SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1813934789fcSMatthew G. Knepley ierr = DMPlexMatSetClosureRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, In, c, elemMat, INSERT_VALUES);CHKERRQ(ierr); 1814d69c5d34SMatthew G. Knepley } 1815549a8adaSMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);} 1816d69c5d34SMatthew G. Knepley ierr = PetscFree(feRef);CHKERRQ(ierr); 1817549a8adaSMatthew G. Knepley ierr = PetscFree(elemMat);CHKERRQ(ierr); 1818934789fcSMatthew G. Knepley ierr = MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1819934789fcSMatthew G. Knepley ierr = MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1820d69c5d34SMatthew G. Knepley if (mesh->printFEM) { 1821d69c5d34SMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_WORLD, "%s:\n", name);CHKERRQ(ierr); 1822934789fcSMatthew G. Knepley ierr = MatChop(In, 1.0e-10);CHKERRQ(ierr); 1823934789fcSMatthew G. Knepley ierr = MatView(In, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1824d69c5d34SMatthew G. Knepley } 1825d69c5d34SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1826d69c5d34SMatthew G. Knepley PetscFunctionReturn(0); 1827d69c5d34SMatthew G. Knepley } 18286c73c22cSMatthew G. Knepley 18296c73c22cSMatthew G. Knepley #undef __FUNCT__ 18307c927364SMatthew G. Knepley #define __FUNCT__ "DMPlexComputeInjectorFEM" 18317c927364SMatthew G. Knepley PetscErrorCode DMPlexComputeInjectorFEM(DM dmc, DM dmf, VecScatter *sc, void *user) 18327c927364SMatthew G. Knepley { 1833e9d4ef1bSMatthew G. Knepley PetscDS prob; 18347c927364SMatthew G. Knepley PetscFE *feRef; 18357c927364SMatthew G. Knepley Vec fv, cv; 18367c927364SMatthew G. Knepley IS fis, cis; 18377c927364SMatthew G. Knepley PetscSection fsection, fglobalSection, csection, cglobalSection; 18387c927364SMatthew G. Knepley PetscInt *cmap, *cellCIndices, *cellFIndices, *cindices, *findices; 18397c927364SMatthew G. Knepley PetscInt cTotDim, fTotDim = 0, Nf, f, field, cStart, cEnd, c, dim, d, startC, offsetC, offsetF, m; 18407c927364SMatthew G. Knepley PetscErrorCode ierr; 18417c927364SMatthew G. Knepley 18427c927364SMatthew G. Knepley PetscFunctionBegin; 184375a69067SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1844c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 18457c927364SMatthew G. Knepley ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 18467c927364SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 18477c927364SMatthew G. Knepley ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 18487c927364SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 18497c927364SMatthew G. Knepley ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 18507c927364SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 1851e9d4ef1bSMatthew G. Knepley ierr = DMGetDS(dmc, &prob);CHKERRQ(ierr); 18527c927364SMatthew G. Knepley ierr = PetscMalloc1(Nf,&feRef);CHKERRQ(ierr); 18537c927364SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 18547c927364SMatthew G. Knepley PetscFE fe; 18557c927364SMatthew G. Knepley PetscInt fNb, Nc; 18567c927364SMatthew G. Knepley 1857e9d4ef1bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 18587c927364SMatthew G. Knepley ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 18597c927364SMatthew G. Knepley ierr = PetscFEGetDimension(feRef[f], &fNb);CHKERRQ(ierr); 18607c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 18617c927364SMatthew G. Knepley fTotDim += fNb*Nc; 18627c927364SMatthew G. Knepley } 1863e9d4ef1bSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 18647c927364SMatthew G. Knepley ierr = PetscMalloc1(cTotDim,&cmap);CHKERRQ(ierr); 18657c927364SMatthew G. Knepley for (field = 0, offsetC = 0, offsetF = 0; field < Nf; ++field) { 18667c927364SMatthew G. Knepley PetscFE feC; 18677c927364SMatthew G. Knepley PetscDualSpace QF, QC; 18687c927364SMatthew G. Knepley PetscInt NcF, NcC, fpdim, cpdim; 18697c927364SMatthew G. Knepley 1870e9d4ef1bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &feC);CHKERRQ(ierr); 18717c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(feC, &NcC);CHKERRQ(ierr); 18727c927364SMatthew G. Knepley ierr = PetscFEGetNumComponents(feRef[field], &NcF);CHKERRQ(ierr); 18737c927364SMatthew 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); 18747c927364SMatthew G. Knepley ierr = PetscFEGetDualSpace(feRef[field], &QF);CHKERRQ(ierr); 18757c927364SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QF, &fpdim);CHKERRQ(ierr); 18767c927364SMatthew G. Knepley ierr = PetscFEGetDualSpace(feC, &QC);CHKERRQ(ierr); 18777c927364SMatthew G. Knepley ierr = PetscDualSpaceGetDimension(QC, &cpdim);CHKERRQ(ierr); 18787c927364SMatthew G. Knepley for (c = 0; c < cpdim; ++c) { 18797c927364SMatthew G. Knepley PetscQuadrature cfunc; 18807c927364SMatthew G. Knepley const PetscReal *cqpoints; 18817c927364SMatthew G. Knepley PetscInt NpC; 18827c927364SMatthew G. Knepley 18837c927364SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(QC, c, &cfunc);CHKERRQ(ierr); 18847c927364SMatthew G. Knepley ierr = PetscQuadratureGetData(cfunc, NULL, &NpC, &cqpoints, NULL);CHKERRQ(ierr); 18857c927364SMatthew G. Knepley if (NpC != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not know how to do injection for moments"); 18867c927364SMatthew G. Knepley for (f = 0; f < fpdim; ++f) { 18877c927364SMatthew G. Knepley PetscQuadrature ffunc; 18887c927364SMatthew G. Knepley const PetscReal *fqpoints; 18897c927364SMatthew G. Knepley PetscReal sum = 0.0; 18907c927364SMatthew G. Knepley PetscInt NpF, comp; 18917c927364SMatthew G. Knepley 18927c927364SMatthew G. Knepley ierr = PetscDualSpaceGetFunctional(QF, f, &ffunc);CHKERRQ(ierr); 18937c927364SMatthew G. Knepley ierr = PetscQuadratureGetData(ffunc, NULL, &NpF, &fqpoints, NULL);CHKERRQ(ierr); 18947c927364SMatthew G. Knepley if (NpC != NpF) continue; 18957c927364SMatthew G. Knepley for (d = 0; d < dim; ++d) sum += PetscAbsReal(cqpoints[d] - fqpoints[d]); 18967c927364SMatthew G. Knepley if (sum > 1.0e-9) continue; 18977c927364SMatthew G. Knepley for (comp = 0; comp < NcC; ++comp) { 18987c927364SMatthew G. Knepley cmap[(offsetC+c)*NcC+comp] = (offsetF+f)*NcF+comp; 18997c927364SMatthew G. Knepley } 19007c927364SMatthew G. Knepley break; 19017c927364SMatthew G. Knepley } 19027c927364SMatthew G. Knepley } 19037c927364SMatthew G. Knepley offsetC += cpdim*NcC; 19047c927364SMatthew G. Knepley offsetF += fpdim*NcF; 19057c927364SMatthew G. Knepley } 19067c927364SMatthew G. Knepley for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);} 19077c927364SMatthew G. Knepley ierr = PetscFree(feRef);CHKERRQ(ierr); 19087c927364SMatthew G. Knepley 19097c927364SMatthew G. Knepley ierr = DMGetGlobalVector(dmf, &fv);CHKERRQ(ierr); 19107c927364SMatthew G. Knepley ierr = DMGetGlobalVector(dmc, &cv);CHKERRQ(ierr); 19117c927364SMatthew G. Knepley ierr = VecGetOwnershipRange(cv, &startC, NULL);CHKERRQ(ierr); 19127c927364SMatthew G. Knepley ierr = PetscSectionGetConstrainedStorageSize(cglobalSection, &m);CHKERRQ(ierr); 19137c927364SMatthew G. Knepley ierr = PetscMalloc2(cTotDim,&cellCIndices,fTotDim,&cellFIndices);CHKERRQ(ierr); 1914aa7da3c4SMatthew G. Knepley ierr = PetscMalloc1(m,&cindices);CHKERRQ(ierr); 1915aa7da3c4SMatthew G. Knepley ierr = PetscMalloc1(m,&findices);CHKERRQ(ierr); 19167c927364SMatthew G. Knepley for (d = 0; d < m; ++d) cindices[d] = findices[d] = -1; 19177c927364SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 19187c927364SMatthew G. Knepley ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, c, cellCIndices, cellFIndices);CHKERRQ(ierr); 19197c927364SMatthew G. Knepley for (d = 0; d < cTotDim; ++d) { 19207c927364SMatthew G. Knepley if (cellCIndices[d] < 0) continue; 19217c927364SMatthew 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]]); 19227c927364SMatthew G. Knepley cindices[cellCIndices[d]-startC] = cellCIndices[d]; 19237c927364SMatthew G. Knepley findices[cellCIndices[d]-startC] = cellFIndices[cmap[d]]; 19247c927364SMatthew G. Knepley } 19257c927364SMatthew G. Knepley } 19267c927364SMatthew G. Knepley ierr = PetscFree(cmap);CHKERRQ(ierr); 19277c927364SMatthew G. Knepley ierr = PetscFree2(cellCIndices,cellFIndices);CHKERRQ(ierr); 19287c927364SMatthew G. Knepley 19297c927364SMatthew G. Knepley ierr = ISCreateGeneral(PETSC_COMM_SELF, m, cindices, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 19307c927364SMatthew G. Knepley ierr = ISCreateGeneral(PETSC_COMM_SELF, m, findices, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 19317c927364SMatthew G. Knepley ierr = VecScatterCreate(cv, cis, fv, fis, sc);CHKERRQ(ierr); 19327c927364SMatthew G. Knepley ierr = ISDestroy(&cis);CHKERRQ(ierr); 19337c927364SMatthew G. Knepley ierr = ISDestroy(&fis);CHKERRQ(ierr); 19347c927364SMatthew G. Knepley ierr = DMRestoreGlobalVector(dmf, &fv);CHKERRQ(ierr); 19357c927364SMatthew G. Knepley ierr = DMRestoreGlobalVector(dmc, &cv);CHKERRQ(ierr); 193675a69067SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1937cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 1938cb1e1211SMatthew G Knepley } 1939cb1e1211SMatthew G Knepley 1940cb1e1211SMatthew G Knepley #undef __FUNCT__ 19418e136ac0SMatthew G. Knepley #define __FUNCT__ "BoundaryDuplicate" 19428e136ac0SMatthew G. Knepley static PetscErrorCode BoundaryDuplicate(DMBoundary bd, DMBoundary *boundary) 19438e136ac0SMatthew G. Knepley { 19448e136ac0SMatthew G. Knepley DMBoundary b = bd, b2, bold = NULL; 19458e136ac0SMatthew G. Knepley PetscErrorCode ierr; 19468e136ac0SMatthew G. Knepley 19478e136ac0SMatthew G. Knepley PetscFunctionBegin; 19488e136ac0SMatthew G. Knepley *boundary = NULL; 19498e136ac0SMatthew G. Knepley for (; b; b = b->next, bold = b2) { 19508e136ac0SMatthew G. Knepley ierr = PetscNew(&b2);CHKERRQ(ierr); 19518e136ac0SMatthew G. Knepley ierr = PetscStrallocpy(b->name, (char **) &b2->name);CHKERRQ(ierr); 19528e136ac0SMatthew G. Knepley ierr = PetscStrallocpy(b->labelname, (char **) &b2->labelname);CHKERRQ(ierr); 19538e136ac0SMatthew G. Knepley ierr = PetscMalloc1(b->numids, &b2->ids);CHKERRQ(ierr); 19548e136ac0SMatthew G. Knepley ierr = PetscMemcpy(b2->ids, b->ids, b->numids*sizeof(PetscInt));CHKERRQ(ierr); 19558e136ac0SMatthew G. Knepley b2->label = NULL; 19568e136ac0SMatthew G. Knepley b2->essential = b->essential; 19578e136ac0SMatthew G. Knepley b2->field = b->field; 19588e136ac0SMatthew G. Knepley b2->func = b->func; 19598e136ac0SMatthew G. Knepley b2->numids = b->numids; 19608e136ac0SMatthew G. Knepley b2->ctx = b->ctx; 19618e136ac0SMatthew G. Knepley b2->next = NULL; 19628e136ac0SMatthew G. Knepley if (!*boundary) *boundary = b2; 19638e136ac0SMatthew G. Knepley if (bold) bold->next = b2; 19648e136ac0SMatthew G. Knepley } 19658e136ac0SMatthew G. Knepley PetscFunctionReturn(0); 19668e136ac0SMatthew G. Knepley } 19678e136ac0SMatthew G. Knepley 19688e136ac0SMatthew G. Knepley #undef __FUNCT__ 19698e136ac0SMatthew G. Knepley #define __FUNCT__ "DMPlexCopyBoundary" 19708e136ac0SMatthew G. Knepley PetscErrorCode DMPlexCopyBoundary(DM dm, DM dmNew) 19718e136ac0SMatthew G. Knepley { 19728e136ac0SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 19738e136ac0SMatthew G. Knepley DM_Plex *meshNew = (DM_Plex *) dmNew->data; 19748e136ac0SMatthew G. Knepley DMBoundary b; 19758e136ac0SMatthew G. Knepley PetscErrorCode ierr; 19768e136ac0SMatthew G. Knepley 19778e136ac0SMatthew G. Knepley PetscFunctionBegin; 19788e136ac0SMatthew G. Knepley ierr = BoundaryDuplicate(mesh->boundary, &meshNew->boundary);CHKERRQ(ierr); 19798e136ac0SMatthew G. Knepley for (b = meshNew->boundary; b; b = b->next) { 19808e136ac0SMatthew G. Knepley if (b->labelname) { 19818e136ac0SMatthew G. Knepley ierr = DMPlexGetLabel(dmNew, b->labelname, &b->label);CHKERRQ(ierr); 19828e136ac0SMatthew G. Knepley if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 19838e136ac0SMatthew G. Knepley } 19848e136ac0SMatthew G. Knepley } 19858e136ac0SMatthew G. Knepley PetscFunctionReturn(0); 19868e136ac0SMatthew G. Knepley } 19878e136ac0SMatthew G. Knepley 19888e136ac0SMatthew G. Knepley #undef __FUNCT__ 1989cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexAddBoundary" 1990cb1e1211SMatthew G Knepley /* The ids can be overridden by the command line option -bc_<boundary name> */ 199163d5297fSMatthew 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) 1992cb1e1211SMatthew G Knepley { 1993cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1994cb1e1211SMatthew G Knepley DMBoundary b; 1995cb1e1211SMatthew G Knepley PetscErrorCode ierr; 1996cb1e1211SMatthew G Knepley 1997cb1e1211SMatthew G Knepley PetscFunctionBegin; 199863d5297fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1999cb1e1211SMatthew G Knepley ierr = PetscNew(&b);CHKERRQ(ierr); 2000cb1e1211SMatthew G Knepley ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 200163d5297fSMatthew G. Knepley ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr); 2002cb1e1211SMatthew G Knepley ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr); 2003cb1e1211SMatthew G Knepley ierr = PetscMemcpy(b->ids, ids, numids*sizeof(PetscInt));CHKERRQ(ierr); 200463d5297fSMatthew G. Knepley if (b->labelname) { 200563d5297fSMatthew G. Knepley ierr = DMPlexGetLabel(dm, b->labelname, &b->label);CHKERRQ(ierr); 200663d5297fSMatthew G. Knepley if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 200763d5297fSMatthew G. Knepley } 2008cb1e1211SMatthew G Knepley b->essential = isEssential; 2009cb1e1211SMatthew G Knepley b->field = field; 2010cb1e1211SMatthew G Knepley b->func = bcFunc; 2011cb1e1211SMatthew G Knepley b->numids = numids; 2012cb1e1211SMatthew G Knepley b->ctx = ctx; 2013cb1e1211SMatthew G Knepley b->next = mesh->boundary; 2014cb1e1211SMatthew G Knepley mesh->boundary = b; 2015cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 2016cb1e1211SMatthew G Knepley } 2017cb1e1211SMatthew G Knepley 2018cb1e1211SMatthew G Knepley #undef __FUNCT__ 2019cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexGetNumBoundary" 2020cb1e1211SMatthew G Knepley PetscErrorCode DMPlexGetNumBoundary(DM dm, PetscInt *numBd) 2021cb1e1211SMatthew G Knepley { 2022cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 2023cb1e1211SMatthew G Knepley DMBoundary b = mesh->boundary; 2024cb1e1211SMatthew G Knepley 2025cb1e1211SMatthew G Knepley PetscFunctionBegin; 202663d5297fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 202763d5297fSMatthew G. Knepley PetscValidPointer(numBd, 2); 2028cb1e1211SMatthew G Knepley *numBd = 0; 2029cb1e1211SMatthew G Knepley while (b) {++(*numBd); b = b->next;} 2030cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 2031cb1e1211SMatthew G Knepley } 2032cb1e1211SMatthew G Knepley 2033cb1e1211SMatthew G Knepley #undef __FUNCT__ 2034cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexGetBoundary" 203563d5297fSMatthew 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) 2036cb1e1211SMatthew G Knepley { 2037cb1e1211SMatthew G Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 2038cb1e1211SMatthew G Knepley DMBoundary b = mesh->boundary; 2039cb1e1211SMatthew G Knepley PetscInt n = 0; 2040cb1e1211SMatthew G Knepley 2041cb1e1211SMatthew G Knepley PetscFunctionBegin; 204263d5297fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2043cb1e1211SMatthew G Knepley while (b) { 2044cb1e1211SMatthew G Knepley if (n == bd) break; 2045cb1e1211SMatthew G Knepley b = b->next; 2046cb1e1211SMatthew G Knepley ++n; 2047cb1e1211SMatthew G Knepley } 2048cb1e1211SMatthew G Knepley if (n != bd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n); 2049cb1e1211SMatthew G Knepley if (isEssential) { 2050cb1e1211SMatthew G Knepley PetscValidPointer(isEssential, 3); 2051cb1e1211SMatthew G Knepley *isEssential = b->essential; 2052cb1e1211SMatthew G Knepley } 2053cb1e1211SMatthew G Knepley if (name) { 2054cb1e1211SMatthew G Knepley PetscValidPointer(name, 4); 2055cb1e1211SMatthew G Knepley *name = b->name; 2056cb1e1211SMatthew G Knepley } 205763d5297fSMatthew G. Knepley if (labelname) { 205863d5297fSMatthew G. Knepley PetscValidPointer(labelname, 5); 205963d5297fSMatthew G. Knepley *labelname = b->labelname; 206063d5297fSMatthew G. Knepley } 2061cb1e1211SMatthew G Knepley if (field) { 206263d5297fSMatthew G. Knepley PetscValidPointer(field, 6); 2063cb1e1211SMatthew G Knepley *field = b->field; 2064cb1e1211SMatthew G Knepley } 2065cb1e1211SMatthew G Knepley if (func) { 206663d5297fSMatthew G. Knepley PetscValidPointer(func, 7); 2067cb1e1211SMatthew G Knepley *func = b->func; 2068cb1e1211SMatthew G Knepley } 2069cb1e1211SMatthew G Knepley if (numids) { 207063d5297fSMatthew G. Knepley PetscValidPointer(numids, 8); 2071cb1e1211SMatthew G Knepley *numids = b->numids; 2072cb1e1211SMatthew G Knepley } 2073cb1e1211SMatthew G Knepley if (ids) { 207463d5297fSMatthew G. Knepley PetscValidPointer(ids, 9); 2075cb1e1211SMatthew G Knepley *ids = b->ids; 2076cb1e1211SMatthew G Knepley } 2077cb1e1211SMatthew G Knepley if (ctx) { 207863d5297fSMatthew G. Knepley PetscValidPointer(ctx, 10); 2079cb1e1211SMatthew G Knepley *ctx = b->ctx; 2080cb1e1211SMatthew G Knepley } 2081cb1e1211SMatthew G Knepley PetscFunctionReturn(0); 2082cb1e1211SMatthew G Knepley } 20830225b034SMatthew G. Knepley 20840225b034SMatthew G. Knepley #undef __FUNCT__ 20850225b034SMatthew G. Knepley #define __FUNCT__ "DMPlexIsBoundaryPoint" 20860225b034SMatthew G. Knepley PetscErrorCode DMPlexIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 20870225b034SMatthew G. Knepley { 20880225b034SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 20890225b034SMatthew G. Knepley DMBoundary b = mesh->boundary; 20900225b034SMatthew G. Knepley PetscErrorCode ierr; 20910225b034SMatthew G. Knepley 20920225b034SMatthew G. Knepley PetscFunctionBegin; 20930225b034SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20940225b034SMatthew G. Knepley PetscValidPointer(isBd, 3); 20950225b034SMatthew G. Knepley *isBd = PETSC_FALSE; 20960225b034SMatthew G. Knepley while (b && !(*isBd)) { 20970225b034SMatthew G. Knepley if (b->label) { 20980225b034SMatthew G. Knepley PetscInt i; 20990225b034SMatthew G. Knepley 21000225b034SMatthew G. Knepley for (i = 0; i < b->numids && !(*isBd); ++i) { 21010225b034SMatthew G. Knepley ierr = DMLabelStratumHasPoint(b->label, b->ids[i], point, isBd);CHKERRQ(ierr); 21020225b034SMatthew G. Knepley } 21030225b034SMatthew G. Knepley } 21040225b034SMatthew G. Knepley b = b->next; 21050225b034SMatthew G. Knepley } 21060225b034SMatthew G. Knepley PetscFunctionReturn(0); 21070225b034SMatthew G. Knepley } 2108