1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2af0996ceSBarry Smith #include <petsc/private/isimpl.h> 3e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h> 48135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h> 50c312b8eSJed Brown #include <petscsf.h> 6e228b242SToby Isaac #include <petscds.h> 7e412dcbdSMatthew G. Knepley #include <petscdraw.h> 8f19dbd58SToby Isaac #include <petscdmfield.h> 9552f7358SJed Brown 10552f7358SJed Brown /* Logging support */ 1130b0ce1bSStefano Zampini PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF; 12552f7358SJed Brown 135a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 14552f7358SJed Brown 15e5337592SStefano Zampini /*@ 16412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 17e5337592SStefano Zampini 18412e9a14SMatthew G. Knepley Input Parameter: 19412e9a14SMatthew G. Knepley + dm - The DMPlex object 20412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 21e5337592SStefano Zampini 22e5337592SStefano Zampini Output Parameters: 23412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 24412e9a14SMatthew G. Knepley - cEnd - The upper bound on "normal"" cells 25e5337592SStefano Zampini 26412e9a14SMatthew G. Knepley Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 27e5337592SStefano Zampini 28412e9a14SMatthew G. Knepley Level: developer 29e5337592SStefano Zampini 30412e9a14SMatthew G. Knepley .seealso DMPlexConstructGhostCells(), DMPlexSetGhostCellStratum() 31e5337592SStefano Zampini @*/ 32412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 33e5337592SStefano Zampini { 34412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 35412e9a14SMatthew G. Knepley PetscInt cS, cE, c; 36e5337592SStefano Zampini PetscErrorCode ierr; 37e5337592SStefano Zampini 38e5337592SStefano Zampini PetscFunctionBegin; 39412e9a14SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr); 40412e9a14SMatthew G. Knepley for (c = cS; c < cE; ++c) { 41412e9a14SMatthew G. Knepley DMPolytopeType cct; 42412e9a14SMatthew G. Knepley 43412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr); 44412e9a14SMatthew G. Knepley if ((PetscInt) cct < 0) break; 45412e9a14SMatthew G. Knepley switch (cct) { 46ba2698f1SMatthew G. Knepley case DM_POLYTOPE_POINT: 47ba2698f1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 48ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 49ba2698f1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 50ba2698f1SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 51ba2698f1SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: 52412e9a14SMatthew G. Knepley ct = cct; 53e5337592SStefano Zampini break; 54412e9a14SMatthew G. Knepley default: break; 55e5337592SStefano Zampini } 56412e9a14SMatthew G. Knepley if (ct != DM_POLYTOPE_UNKNOWN) break; 57e5337592SStefano Zampini } 58412e9a14SMatthew G. Knepley if (ct != DM_POLYTOPE_UNKNOWN) { 59412e9a14SMatthew G. Knepley DMLabel ctLabel; 60412e9a14SMatthew G. Knepley 61412e9a14SMatthew G. Knepley ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 62412e9a14SMatthew G. Knepley ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr); 63e5337592SStefano Zampini } 64412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 65412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 66e5337592SStefano Zampini PetscFunctionReturn(0); 67e5337592SStefano Zampini } 68e5337592SStefano Zampini 697afe7537SMatthew G. Knepley PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 707e42fee7SMatthew G. Knepley { 71412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 72a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0,0}, globalvcdof[2]; 737e42fee7SMatthew G. Knepley PetscErrorCode ierr; 747e42fee7SMatthew G. Knepley 757e42fee7SMatthew G. Knepley PetscFunctionBegin; 76e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 77f094498dSMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 787e42fee7SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 79412e9a14SMatthew G. Knepley ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 807e42fee7SMatthew G. Knepley ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 817e42fee7SMatthew G. Knepley if (field >= 0) { 82a99a26bcSAdrian Croucher if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);} 83a99a26bcSAdrian Croucher if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);} 847e42fee7SMatthew G. Knepley } else { 85a99a26bcSAdrian Croucher if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);} 86a99a26bcSAdrian Croucher if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);} 877e42fee7SMatthew G. Knepley } 885483465cSMatthew G. Knepley ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 89a99a26bcSAdrian Croucher if (globalvcdof[0]) { 907e42fee7SMatthew G. Knepley *sStart = vStart; 917e42fee7SMatthew G. Knepley *sEnd = vEnd; 92f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 937e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 94a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 957e42fee7SMatthew G. Knepley *sStart = cStart; 967e42fee7SMatthew G. Knepley *sEnd = cEnd; 97f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 987e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 99e630c359SToby Isaac } else { 100e630c359SToby Isaac if (field >= 0) { 101e630c359SToby Isaac const char *fieldname; 102e630c359SToby Isaac 103e630c359SToby Isaac ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr); 104e630c359SToby Isaac ierr = PetscInfo2((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr); 105e630c359SToby Isaac } else { 106e630c359SToby Isaac ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output typp of section\"%s\"\n");CHKERRQ(ierr); 107e630c359SToby Isaac } 108e630c359SToby Isaac } 1097e42fee7SMatthew G. Knepley PetscFunctionReturn(0); 1107e42fee7SMatthew G. Knepley } 1117e42fee7SMatthew G. Knepley 1127cd05799SMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 113e412dcbdSMatthew G. Knepley { 114e412dcbdSMatthew G. Knepley DM dm; 115d1df6f1dSMatthew G. Knepley PetscSection s; 116e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 117e412dcbdSMatthew G. Knepley DM cdm; 118e412dcbdSMatthew G. Knepley PetscSection coordSection; 119e412dcbdSMatthew G. Knepley Vec coordinates; 120e412dcbdSMatthew G. Knepley const PetscScalar *coords, *array; 121e412dcbdSMatthew G. Knepley PetscReal bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 122339e3443SMatthew G. Knepley PetscReal vbound[2], time; 123339e3443SMatthew G. Knepley PetscBool isnull, flg; 124d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 125e412dcbdSMatthew G. Knepley const char *name; 126339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 127e412dcbdSMatthew G. Knepley PetscErrorCode ierr; 128e412dcbdSMatthew G. Knepley 129e412dcbdSMatthew G. Knepley PetscFunctionBegin; 130d1df6f1dSMatthew G. Knepley ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 131d1df6f1dSMatthew G. Knepley ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 132d1df6f1dSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 133d1df6f1dSMatthew G. Knepley 134e412dcbdSMatthew G. Knepley ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 135e412dcbdSMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1368135c375SStefano Zampini if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim); 13792fd8e1eSJed Brown ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 138d1df6f1dSMatthew G. Knepley ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr); 139e412dcbdSMatthew G. Knepley ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr); 140e412dcbdSMatthew G. Knepley ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 14192fd8e1eSJed Brown ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 142e412dcbdSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 143e412dcbdSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 144e412dcbdSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 145e412dcbdSMatthew G. Knepley 146e412dcbdSMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 147339e3443SMatthew G. Knepley ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr); 148e412dcbdSMatthew G. Knepley 149e412dcbdSMatthew G. Knepley ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 150e412dcbdSMatthew G. Knepley ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 151e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 1520c81f2a8SMatthew G. Knepley bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 1530c81f2a8SMatthew G. Knepley bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 154e412dcbdSMatthew G. Knepley } 155e412dcbdSMatthew G. Knepley ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 156e412dcbdSMatthew G. Knepley ierr = PetscDrawClear(draw);CHKERRQ(ierr); 157e412dcbdSMatthew G. Knepley 158d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 159d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 160d1df6f1dSMatthew G. Knepley DM fdm = dm; 161d1df6f1dSMatthew G. Knepley Vec fv = v; 162d1df6f1dSMatthew G. Knepley IS fis; 163d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 164d1df6f1dSMatthew G. Knepley const char *fname; 165d1df6f1dSMatthew G. Knepley 166d1df6f1dSMatthew G. Knepley ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr); 167d1df6f1dSMatthew G. Knepley ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr); 168d1df6f1dSMatthew G. Knepley 169a126751eSBarry Smith if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);} 170d1df6f1dSMatthew G. Knepley else {prefix[0] = '\0';} 171d1df6f1dSMatthew G. Knepley if (Nf > 1) { 172d1df6f1dSMatthew G. Knepley ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr); 173d1df6f1dSMatthew G. Knepley ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr); 174a126751eSBarry Smith ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr); 175a126751eSBarry Smith ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr); 176d1df6f1dSMatthew G. Knepley } 177d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 178d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 179d1df6f1dSMatthew G. Knepley 180d1df6f1dSMatthew G. Knepley ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr); 181d1df6f1dSMatthew G. Knepley if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);} 182d1df6f1dSMatthew G. Knepley else {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);} 183d1df6f1dSMatthew G. Knepley ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr); 184d1df6f1dSMatthew G. Knepley 185d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 186d1df6f1dSMatthew G. Knepley ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr); 187339e3443SMatthew G. Knepley if (!flg) { 188d1df6f1dSMatthew G. Knepley ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr); 189d1df6f1dSMatthew G. Knepley ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr); 190d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 191339e3443SMatthew G. Knepley } 192e412dcbdSMatthew G. Knepley ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr); 193339e3443SMatthew G. Knepley ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr); 194d1df6f1dSMatthew G. Knepley ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr); 195e412dcbdSMatthew G. Knepley 196d1df6f1dSMatthew G. Knepley ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr); 197e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 19899a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 199e56f9228SJed Brown PetscInt numCoords, color[4] = {-1,-1,-1,-1}; 200e412dcbdSMatthew G. Knepley 201d1df6f1dSMatthew G. Knepley ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr); 202339e3443SMatthew G. Knepley if (a) { 203d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 204339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 205339e3443SMatthew G. Knepley } else { 206339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 207339e3443SMatthew G. Knepley PetscInt numVals, va; 208339e3443SMatthew G. Knepley 209d1df6f1dSMatthew G. Knepley ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 210d1df6f1dSMatthew G. Knepley if (numVals % Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %D does not divide the number of values in the closure %D", Nc, numVals); 211d1df6f1dSMatthew G. Knepley switch (numVals/Nc) { 212d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 213d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 214d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]); 215339e3443SMatthew G. Knepley break; 216d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 217d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 218d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]); 219d1df6f1dSMatthew G. Knepley break; 220d1df6f1dSMatthew G. Knepley default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc); 221339e3443SMatthew G. Knepley } 222d1df6f1dSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr); 223339e3443SMatthew G. Knepley } 224e412dcbdSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 225e412dcbdSMatthew G. Knepley switch (numCoords) { 226e412dcbdSMatthew G. Knepley case 6: 227339e3443SMatthew G. Knepley ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 228e412dcbdSMatthew G. Knepley break; 229e412dcbdSMatthew G. Knepley case 8: 230339e3443SMatthew G. Knepley ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr); 231339e3443SMatthew G. Knepley ierr = PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]);CHKERRQ(ierr); 232e412dcbdSMatthew G. Knepley break; 233e412dcbdSMatthew G. Knepley default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords); 234e412dcbdSMatthew G. Knepley } 235e412dcbdSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 236e412dcbdSMatthew G. Knepley } 237d1df6f1dSMatthew G. Knepley ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr); 238e412dcbdSMatthew G. Knepley ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 239e412dcbdSMatthew G. Knepley ierr = PetscDrawPause(draw);CHKERRQ(ierr); 240e412dcbdSMatthew G. Knepley ierr = PetscDrawSave(draw);CHKERRQ(ierr); 241d1df6f1dSMatthew G. Knepley } 242d1df6f1dSMatthew G. Knepley if (Nf > 1) { 243d1df6f1dSMatthew G. Knepley ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr); 244d1df6f1dSMatthew G. Knepley ierr = ISDestroy(&fis);CHKERRQ(ierr); 245d1df6f1dSMatthew G. Knepley ierr = DMDestroy(&fdm);CHKERRQ(ierr); 246d1df6f1dSMatthew G. Knepley } 247d1df6f1dSMatthew G. Knepley } 248e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 249e412dcbdSMatthew G. Knepley } 250e412dcbdSMatthew G. Knepley 251684b87d9SLisandro Dalcin static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 252684b87d9SLisandro Dalcin { 253684b87d9SLisandro Dalcin DM dm; 254684b87d9SLisandro Dalcin Vec locv; 255684b87d9SLisandro Dalcin const char *name; 256684b87d9SLisandro Dalcin PetscSection section; 257684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 258e630c359SToby Isaac PetscInt numFields; 259684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 260684b87d9SLisandro Dalcin PetscErrorCode ierr; 261684b87d9SLisandro Dalcin 262684b87d9SLisandro Dalcin PetscFunctionBegin; 263684b87d9SLisandro Dalcin ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 264684b87d9SLisandro Dalcin ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */ 265684b87d9SLisandro Dalcin ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 266684b87d9SLisandro Dalcin ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 267684b87d9SLisandro Dalcin ierr = VecCopy(v, locv);CHKERRQ(ierr); 26892fd8e1eSJed Brown ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 269e630c359SToby Isaac ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 270e630c359SToby Isaac if (!numFields) { 271684b87d9SLisandro Dalcin ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 272e630c359SToby Isaac ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 273e630c359SToby Isaac } else { 274e630c359SToby Isaac PetscInt f; 275e630c359SToby Isaac 276e630c359SToby Isaac for (f = 0; f < numFields; f++) { 277e630c359SToby Isaac ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr); 278e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 279e630c359SToby Isaac ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr); 280e630c359SToby Isaac ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr); 281e630c359SToby Isaac } 282e630c359SToby Isaac ierr = VecDestroy(&locv);CHKERRQ(ierr); 283e630c359SToby Isaac } 284684b87d9SLisandro Dalcin PetscFunctionReturn(0); 285684b87d9SLisandro Dalcin } 286684b87d9SLisandro Dalcin 287552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 288552f7358SJed Brown { 289552f7358SJed Brown DM dm; 290684b87d9SLisandro Dalcin PetscBool isvtk, ishdf5, isdraw, isglvis; 291552f7358SJed Brown PetscErrorCode ierr; 292552f7358SJed Brown 293552f7358SJed Brown PetscFunctionBegin; 294552f7358SJed Brown ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 29582f516ccSBarry Smith if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 296552f7358SJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 297b136c2c9SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 298f13a32a3SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 2998135c375SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 300684b87d9SLisandro Dalcin if (isvtk || ishdf5 || isdraw || isglvis) { 301684b87d9SLisandro Dalcin PetscInt i,numFields; 302684b87d9SLisandro Dalcin PetscObject fe; 303ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 304684b87d9SLisandro Dalcin Vec locv = v; 305684b87d9SLisandro Dalcin const char *name; 306684b87d9SLisandro Dalcin PetscInt step; 307684b87d9SLisandro Dalcin PetscReal time; 308ef31f671SMatthew G. Knepley 309ef31f671SMatthew G. Knepley ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 310684b87d9SLisandro Dalcin for (i=0; i<numFields; i++) { 31144a7f3ddSMatthew G. Knepley ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr); 312684b87d9SLisandro Dalcin if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; } 313ef31f671SMatthew G. Knepley } 314684b87d9SLisandro Dalcin if (fem) { 315684b87d9SLisandro Dalcin ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 316684b87d9SLisandro Dalcin ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 317684b87d9SLisandro Dalcin ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 318684b87d9SLisandro Dalcin ierr = VecCopy(v, locv);CHKERRQ(ierr); 319684b87d9SLisandro Dalcin ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 320684b87d9SLisandro Dalcin ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr); 321ef31f671SMatthew G. Knepley } 322552f7358SJed Brown if (isvtk) { 323684b87d9SLisandro Dalcin ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr); 324b136c2c9SMatthew G. Knepley } else if (ishdf5) { 325b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 326684b87d9SLisandro Dalcin ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr); 327b136c2c9SMatthew G. Knepley #else 328b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 329b136c2c9SMatthew G. Knepley #endif 330f13a32a3SMatthew G. Knepley } else if (isdraw) { 331684b87d9SLisandro Dalcin ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr); 332684b87d9SLisandro Dalcin } else if (isglvis) { 333684b87d9SLisandro Dalcin ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr); 334684b87d9SLisandro Dalcin ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr); 335684b87d9SLisandro Dalcin ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr); 336684b87d9SLisandro Dalcin } 337684b87d9SLisandro Dalcin if (fem) {ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr);} 338552f7358SJed Brown } else { 339684b87d9SLisandro Dalcin PetscBool isseq; 340684b87d9SLisandro Dalcin 341684b87d9SLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 34255f2e967SMatthew G. Knepley if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 34355f2e967SMatthew G. Knepley else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 344552f7358SJed Brown } 345552f7358SJed Brown PetscFunctionReturn(0); 346552f7358SJed Brown } 347552f7358SJed Brown 348552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 349552f7358SJed Brown { 350552f7358SJed Brown DM dm; 351684b87d9SLisandro Dalcin PetscBool isvtk, ishdf5, isdraw, isglvis; 352552f7358SJed Brown PetscErrorCode ierr; 353552f7358SJed Brown 354552f7358SJed Brown PetscFunctionBegin; 355552f7358SJed Brown ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 35682f516ccSBarry Smith if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 357552f7358SJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 35833c3e6b4SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 359e412dcbdSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 3608135c375SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 361684b87d9SLisandro Dalcin if (isvtk || isdraw || isglvis) { 362552f7358SJed Brown Vec locv; 363552f7358SJed Brown const char *name; 364552f7358SJed Brown 365c8dd51e9SBarry Smith ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 366552f7358SJed Brown ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 367552f7358SJed Brown ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 368552f7358SJed Brown ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 369552f7358SJed Brown ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 370552f7358SJed Brown ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 371c8dd51e9SBarry Smith ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 372b136c2c9SMatthew G. Knepley } else if (ishdf5) { 373b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 37439d25373SMatthew G. Knepley ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 375b136c2c9SMatthew G. Knepley #else 376b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 377b136c2c9SMatthew G. Knepley #endif 378552f7358SJed Brown } else { 379684b87d9SLisandro Dalcin PetscBool isseq; 380684b87d9SLisandro Dalcin 381684b87d9SLisandro Dalcin ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 38255f2e967SMatthew G. Knepley if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 38355f2e967SMatthew G. Knepley else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 384552f7358SJed Brown } 385552f7358SJed Brown PetscFunctionReturn(0); 386552f7358SJed Brown } 387552f7358SJed Brown 388d930f514SMatthew G. Knepley PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 389d930f514SMatthew G. Knepley { 390d930f514SMatthew G. Knepley DM dm; 391d930f514SMatthew G. Knepley MPI_Comm comm; 392d930f514SMatthew G. Knepley PetscViewerFormat format; 393d930f514SMatthew G. Knepley Vec v; 394d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 395d930f514SMatthew G. Knepley PetscErrorCode ierr; 396d930f514SMatthew G. Knepley 397d930f514SMatthew G. Knepley PetscFunctionBegin; 398d930f514SMatthew G. Knepley ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 399d930f514SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 4002c4c0c81SMatthew G. Knepley if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 401d930f514SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 402d930f514SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 403d930f514SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 404d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 405a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 406a8ad634aSStefano Zampini /* this need a better fix */ 407a8ad634aSStefano Zampini if (dm->useNatural) { 408a8ad634aSStefano Zampini if (dm->sfNatural) { 409d930f514SMatthew G. Knepley const char *vecname; 410d930f514SMatthew G. Knepley PetscInt n, nroots; 411d930f514SMatthew G. Knepley 412ca43db0aSBarry Smith ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr); 413d930f514SMatthew G. Knepley ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 414d930f514SMatthew G. Knepley if (n == nroots) { 415d930f514SMatthew G. Knepley ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 416d930f514SMatthew G. Knepley ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 417d930f514SMatthew G. Knepley ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 418d930f514SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 419d930f514SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 420d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 421d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 422a8ad634aSStefano Zampini } else v = originalv; 423a8ad634aSStefano Zampini } else v = originalv; 424a8ad634aSStefano Zampini 425d930f514SMatthew G. Knepley if (ishdf5) { 426d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 42739d25373SMatthew G. Knepley ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 428d930f514SMatthew G. Knepley #else 429d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 430d930f514SMatthew G. Knepley #endif 431d930f514SMatthew G. Knepley } else if (isvtk) { 432d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 433d930f514SMatthew G. Knepley } else { 434d930f514SMatthew G. Knepley PetscBool isseq; 435d930f514SMatthew G. Knepley 436d930f514SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 437d930f514SMatthew G. Knepley if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 438d930f514SMatthew G. Knepley else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 439d930f514SMatthew G. Knepley } 440a8ad634aSStefano Zampini if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 441d930f514SMatthew G. Knepley PetscFunctionReturn(0); 442d930f514SMatthew G. Knepley } 443d930f514SMatthew G. Knepley 4442c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 4452c40f234SMatthew G. Knepley { 4462c40f234SMatthew G. Knepley DM dm; 4472c40f234SMatthew G. Knepley PetscBool ishdf5; 4482c40f234SMatthew G. Knepley PetscErrorCode ierr; 4492c40f234SMatthew G. Knepley 4502c40f234SMatthew G. Knepley PetscFunctionBegin; 4512c40f234SMatthew G. Knepley ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 4522c40f234SMatthew G. Knepley if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 4532c40f234SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4542c40f234SMatthew G. Knepley if (ishdf5) { 4552c40f234SMatthew G. Knepley DM dmBC; 4562c40f234SMatthew G. Knepley Vec gv; 4572c40f234SMatthew G. Knepley const char *name; 4582c40f234SMatthew G. Knepley 4592c40f234SMatthew G. Knepley ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 4602c40f234SMatthew G. Knepley ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 4612c40f234SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 4622c40f234SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 4632c40f234SMatthew G. Knepley ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 4642c40f234SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 4652c40f234SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 4662c40f234SMatthew G. Knepley ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 4672c40f234SMatthew G. Knepley } else { 4682c40f234SMatthew G. Knepley ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 4692c40f234SMatthew G. Knepley } 4702c40f234SMatthew G. Knepley PetscFunctionReturn(0); 4712c40f234SMatthew G. Knepley } 4722c40f234SMatthew G. Knepley 4732c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 4742c40f234SMatthew G. Knepley { 4752c40f234SMatthew G. Knepley DM dm; 4762c40f234SMatthew G. Knepley PetscBool ishdf5; 4772c40f234SMatthew G. Knepley PetscErrorCode ierr; 4782c40f234SMatthew G. Knepley 4792c40f234SMatthew G. Knepley PetscFunctionBegin; 4802c40f234SMatthew G. Knepley ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 4812c40f234SMatthew G. Knepley if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 4822c40f234SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4832c40f234SMatthew G. Knepley if (ishdf5) { 484878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 48539d25373SMatthew G. Knepley ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr); 486b136c2c9SMatthew G. Knepley #else 487b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 488878b459fSMatthew G. Knepley #endif 4892c40f234SMatthew G. Knepley } else { 4902c40f234SMatthew G. Knepley ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 491552f7358SJed Brown } 492552f7358SJed Brown PetscFunctionReturn(0); 493552f7358SJed Brown } 494552f7358SJed Brown 495d930f514SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 496d930f514SMatthew G. Knepley { 497d930f514SMatthew G. Knepley DM dm; 498d930f514SMatthew G. Knepley PetscViewerFormat format; 499d930f514SMatthew G. Knepley PetscBool ishdf5; 500d930f514SMatthew G. Knepley PetscErrorCode ierr; 501d930f514SMatthew G. Knepley 502d930f514SMatthew G. Knepley PetscFunctionBegin; 503d930f514SMatthew G. Knepley ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 504d930f514SMatthew G. Knepley if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 505d930f514SMatthew G. Knepley ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 506d930f514SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 507d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 508a8ad634aSStefano Zampini if (dm->useNatural) { 509d930f514SMatthew G. Knepley if (dm->sfNatural) { 510d930f514SMatthew G. Knepley if (ishdf5) { 511d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 512d930f514SMatthew G. Knepley Vec v; 513d930f514SMatthew G. Knepley const char *vecname; 514d930f514SMatthew G. Knepley 515d930f514SMatthew G. Knepley ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 516d930f514SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 517d930f514SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 51839d25373SMatthew G. Knepley ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr); 519d930f514SMatthew G. Knepley ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 520d930f514SMatthew G. Knepley ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 521d930f514SMatthew G. Knepley ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 522d930f514SMatthew G. Knepley #else 523d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 524d930f514SMatthew G. Knepley #endif 525d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 526d930f514SMatthew G. Knepley } 527a8ad634aSStefano Zampini } else { 528a8ad634aSStefano Zampini ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr); 529a8ad634aSStefano Zampini } 530d930f514SMatthew G. Knepley } 531d930f514SMatthew G. Knepley PetscFunctionReturn(0); 532d930f514SMatthew G. Knepley } 533d930f514SMatthew G. Knepley 5347cd05799SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 535731e8ddeSMatthew G. Knepley { 536731e8ddeSMatthew G. Knepley PetscSection coordSection; 537731e8ddeSMatthew G. Knepley Vec coordinates; 538ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 539731e8ddeSMatthew G. Knepley const char *name[4]; 540731e8ddeSMatthew G. Knepley const PetscScalar *a; 541731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 542731e8ddeSMatthew G. Knepley PetscErrorCode ierr; 543731e8ddeSMatthew G. Knepley 544731e8ddeSMatthew G. Knepley PetscFunctionBegin; 545731e8ddeSMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 546731e8ddeSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 547731e8ddeSMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 548731e8ddeSMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 549ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr); 550731e8ddeSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 551731e8ddeSMatthew G. Knepley ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 552731e8ddeSMatthew G. Knepley ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 553731e8ddeSMatthew G. Knepley name[0] = "vertex"; 554731e8ddeSMatthew G. Knepley name[1] = "edge"; 555731e8ddeSMatthew G. Knepley name[dim-1] = "face"; 556731e8ddeSMatthew G. Knepley name[dim] = "cell"; 557731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 558731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 559ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 560731e8ddeSMatthew G. Knepley 561ba2698f1SMatthew G. Knepley ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr); 562ba2698f1SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr); 563731e8ddeSMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 564731e8ddeSMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 565731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 566731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 567731e8ddeSMatthew G. Knepley 568731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 569731e8ddeSMatthew G. Knepley ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 570731e8ddeSMatthew G. Knepley if (!dof) continue; 571731e8ddeSMatthew G. Knepley ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 572731e8ddeSMatthew G. Knepley ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 573f347f43bSBarry Smith ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 574731e8ddeSMatthew G. Knepley for (p = 0; p < dof/dim; ++p) { 575731e8ddeSMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 576731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 577731e8ddeSMatthew G. Knepley if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 578087ef6b2SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 579731e8ddeSMatthew G. Knepley } 580731e8ddeSMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 581731e8ddeSMatthew G. Knepley } 582731e8ddeSMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 583731e8ddeSMatthew G. Knepley } 584731e8ddeSMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 585731e8ddeSMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 586731e8ddeSMatthew G. Knepley } 587731e8ddeSMatthew G. Knepley ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 588731e8ddeSMatthew G. Knepley PetscFunctionReturn(0); 589731e8ddeSMatthew G. Knepley } 590731e8ddeSMatthew G. Knepley 5917cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 592552f7358SJed Brown { 593552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 594552f7358SJed Brown DM cdm; 595412e9a14SMatthew G. Knepley DMLabel markers, celltypes; 596552f7358SJed Brown PetscSection coordSection; 597552f7358SJed Brown Vec coordinates; 598552f7358SJed Brown PetscViewerFormat format; 599552f7358SJed Brown PetscErrorCode ierr; 600552f7358SJed Brown 601552f7358SJed Brown PetscFunctionBegin; 602552f7358SJed Brown ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 60392fd8e1eSJed Brown ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 604552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 605552f7358SJed Brown ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 606552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 607552f7358SJed Brown const char *name; 608f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 609552f7358SJed Brown PetscInt pStart, pEnd, p; 610552f7358SJed Brown PetscMPIInt rank, size; 611552f7358SJed Brown 61282f516ccSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 61382f516ccSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 614552f7358SJed Brown ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 615552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 616552f7358SJed Brown ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 617f73eea6eSMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 618f73eea6eSMatthew G. Knepley ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 619f73eea6eSMatthew G. Knepley if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 620f73eea6eSMatthew G. Knepley else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 621f73eea6eSMatthew G. Knepley if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 622e9cb465cSMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr); 6234d4c343aSBarry Smith ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 624e9cb465cSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr); 625552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 626552f7358SJed Brown PetscInt dof, off, s; 627552f7358SJed Brown 628552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 629552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 630552f7358SJed Brown for (s = off; s < off+dof; ++s) { 631e4b003c7SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 632552f7358SJed Brown } 633552f7358SJed Brown } 634552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 635e9cb465cSMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr); 636e9cb465cSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr); 637552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 638552f7358SJed Brown PetscInt dof, off, c; 639552f7358SJed Brown 640552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 641552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 642552f7358SJed Brown for (c = off; c < off+dof; ++c) { 643e4b003c7SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 644552f7358SJed Brown } 645552f7358SJed Brown } 646552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 6474d4c343aSBarry Smith ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 6483d2e540fSStefano Zampini if (coordSection && coordinates) { 64980180ce3SStefano Zampini ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr); 6503d2e540fSStefano Zampini } 651c58f1c22SToby Isaac ierr = DMGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 6527422c0d1SMatthew G. Knepley if (markers) {ierr = DMLabelView(markers,viewer);CHKERRQ(ierr);} 653412e9a14SMatthew G. Knepley ierr = DMPlexGetCellTypeLabel(dm, &celltypes);CHKERRQ(ierr); 654412e9a14SMatthew G. Knepley if (celltypes) {ierr = DMLabelView(celltypes, viewer);CHKERRQ(ierr);} 655552f7358SJed Brown if (size > 1) { 656552f7358SJed Brown PetscSF sf; 657552f7358SJed Brown 658552f7358SJed Brown ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 659552f7358SJed Brown ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 660552f7358SJed Brown } 661552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 662552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 6630588280cSMatthew G. Knepley const char *name, *color; 6640588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 6650588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 666fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 667552f7358SJed Brown PetscReal scale = 2.0; 66878081901SStefano Zampini PetscReal tikzscale = 1.0; 6690588280cSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, useLabels, useColors; 6700588280cSMatthew G. Knepley double tcoords[3]; 671552f7358SJed Brown PetscScalar *coords; 6720588280cSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 673552f7358SJed Brown PetscMPIInt rank, size; 6740588280cSMatthew G. Knepley char **names, **colors, **lcolors; 675fe1cc32dSStefano Zampini PetscBool plotEdges, flg, lflg; 676fe1cc32dSStefano Zampini PetscBT wp = NULL; 677fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 678552f7358SJed Brown 6790588280cSMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 680552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 681c58f1c22SToby Isaac ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6820588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 6830588280cSMatthew G. Knepley numColors = 10; 6840588280cSMatthew G. Knepley numLColors = 10; 6850588280cSMatthew G. Knepley ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 686c5929fdfSBarry Smith ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 68778081901SStefano Zampini ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr); 688c5929fdfSBarry Smith ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 689c5929fdfSBarry Smith ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 6900588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 691c5929fdfSBarry Smith ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 6920588280cSMatthew G. Knepley if (!useColors) { 6930588280cSMatthew G. Knepley numColors = 3; 6940588280cSMatthew G. Knepley for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 6950588280cSMatthew G. Knepley } 696c5929fdfSBarry Smith ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 6970588280cSMatthew G. Knepley if (!useColors) { 6980588280cSMatthew G. Knepley numLColors = 4; 6990588280cSMatthew G. Knepley for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 7000588280cSMatthew G. Knepley } 701fe1cc32dSStefano Zampini ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, PETSC_MAX_PATH_LEN, &lflg);CHKERRQ(ierr); 702202fd40aSStefano Zampini plotEdges = (PetscBool)(depth > 1 && useNumbers && dim < 3); 703202fd40aSStefano Zampini ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr); 704202fd40aSStefano Zampini if (flg && plotEdges && depth < dim) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 705202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 706fe1cc32dSStefano Zampini 707fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 708fe1cc32dSStefano Zampini ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 709fe1cc32dSStefano Zampini if (lflg) { 710fe1cc32dSStefano Zampini DMLabel lbl; 711fe1cc32dSStefano Zampini 712fe1cc32dSStefano Zampini ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr); 713fe1cc32dSStefano Zampini if (lbl) { 714fe1cc32dSStefano Zampini PetscInt val, defval; 715fe1cc32dSStefano Zampini 716fe1cc32dSStefano Zampini ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr); 717fe1cc32dSStefano Zampini ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr); 718fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 719fe1cc32dSStefano Zampini PetscInt *closure = NULL; 720fe1cc32dSStefano Zampini PetscInt closureSize; 721fe1cc32dSStefano Zampini 722fe1cc32dSStefano Zampini ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr); 723fe1cc32dSStefano Zampini if (val == defval) continue; 724fe1cc32dSStefano Zampini 725fe1cc32dSStefano Zampini ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 726fe1cc32dSStefano Zampini for (p = 0; p < closureSize*2; p += 2) { 727fe1cc32dSStefano Zampini ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr); 728fe1cc32dSStefano Zampini } 729fe1cc32dSStefano Zampini ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 730fe1cc32dSStefano Zampini } 731fe1cc32dSStefano Zampini } 732fe1cc32dSStefano Zampini } 733fe1cc32dSStefano Zampini 73482f516ccSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 73582f516ccSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 736552f7358SJed Brown ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 737770b213bSMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer, "\ 7380588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 739552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 740552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 741552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 7420588280cSMatthew G. Knepley \\begin{document}\n");CHKERRQ(ierr); 7430588280cSMatthew G. Knepley if (size > 1) { 744f738dd31SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 745770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 746770b213bSMatthew G Knepley if (p > 0 && p == size-1) { 747770b213bSMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 748770b213bSMatthew G Knepley } else if (p > 0) { 749770b213bSMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 750770b213bSMatthew G Knepley } 751770b213bSMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 752770b213bSMatthew G Knepley } 7530588280cSMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 7540588280cSMatthew G. Knepley } 755087ef6b2SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr); 756fe1cc32dSStefano Zampini 757552f7358SJed Brown /* Plot vertices */ 758552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 759552f7358SJed Brown ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 7604d4c343aSBarry Smith ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 761552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 762552f7358SJed Brown PetscInt off, dof, d; 7630588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 764552f7358SJed Brown 765fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,v - pStart)) continue; 766552f7358SJed Brown ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 767552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 7680588280cSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 769f6dae198SJed Brown if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 7700588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 7710588280cSMatthew G. Knepley tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 772c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 7730588280cSMatthew G. Knepley } 7740588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 7750588280cSMatthew G. Knepley if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 776552f7358SJed Brown for (d = 0; d < dof; ++d) { 777552f7358SJed Brown if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 778087ef6b2SMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr); 779552f7358SJed Brown } 7800588280cSMatthew G. Knepley color = colors[rank%numColors]; 7810588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 7820588280cSMatthew G. Knepley PetscInt val; 783c58f1c22SToby Isaac ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 7840588280cSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 7850588280cSMatthew G. Knepley } 7860588280cSMatthew G. Knepley if (useNumbers) { 787e4b003c7SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 7880588280cSMatthew G. Knepley } else { 789e4b003c7SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 7900588280cSMatthew G. Knepley } 791552f7358SJed Brown } 792552f7358SJed Brown ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 793552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 794846a3e8bSMatthew G. Knepley /* Plot cells */ 795846a3e8bSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 79678081901SStefano Zampini ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 797846a3e8bSMatthew G. Knepley if (dim == 3 || !useNumbers) { 798846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 799846a3e8bSMatthew G. Knepley const PetscInt *cone; 800846a3e8bSMatthew G. Knepley 801fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,e - pStart)) continue; 802846a3e8bSMatthew G. Knepley color = colors[rank%numColors]; 803846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 804846a3e8bSMatthew G. Knepley PetscInt val; 805846a3e8bSMatthew G. Knepley ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 806846a3e8bSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; break;} 807846a3e8bSMatthew G. Knepley } 808846a3e8bSMatthew G. Knepley ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 809846a3e8bSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 810846a3e8bSMatthew G. Knepley } 811846a3e8bSMatthew G. Knepley } else { 812846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 813846a3e8bSMatthew G. Knepley PetscInt *closure = NULL; 814846a3e8bSMatthew G. Knepley PetscInt closureSize, firstPoint = -1; 815846a3e8bSMatthew G. Knepley 816fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,c - pStart)) continue; 817846a3e8bSMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 818846a3e8bSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 819846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize*2; p += 2) { 820846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 821846a3e8bSMatthew G. Knepley 822846a3e8bSMatthew G. Knepley if ((point < vStart) || (point >= vEnd)) continue; 823846a3e8bSMatthew G. Knepley if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 824846a3e8bSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", point, rank);CHKERRQ(ierr); 825846a3e8bSMatthew G. Knepley if (firstPoint < 0) firstPoint = point; 826846a3e8bSMatthew G. Knepley } 827846a3e8bSMatthew G. Knepley /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 828846a3e8bSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d);\n", firstPoint, rank);CHKERRQ(ierr); 829846a3e8bSMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 830846a3e8bSMatthew G. Knepley } 831846a3e8bSMatthew G. Knepley } 832846a3e8bSMatthew G. Knepley ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 833846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 834846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 835846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 836846a3e8bSMatthew G. Knepley PetscInt *closure = NULL; 837846a3e8bSMatthew G. Knepley PetscInt closureSize, dof, d, n = 0; 838846a3e8bSMatthew G. Knepley 839fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,c - pStart)) continue; 840846a3e8bSMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 841846a3e8bSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 842846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize*2; p += 2) { 843846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 844846a3e8bSMatthew G. Knepley PetscInt off; 845846a3e8bSMatthew G. Knepley 846846a3e8bSMatthew G. Knepley if ((point < vStart) || (point >= vEnd)) continue; 847846a3e8bSMatthew G. Knepley ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 848846a3e8bSMatthew G. Knepley ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 849846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) { 850846a3e8bSMatthew G. Knepley tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 851846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 852846a3e8bSMatthew G. Knepley } 853846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 854846a3e8bSMatthew G. Knepley if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 855846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];} 856846a3e8bSMatthew G. Knepley ++n; 857846a3e8bSMatthew G. Knepley } 858846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) {ccoords[d] /= n;} 859846a3e8bSMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 860846a3e8bSMatthew G. Knepley for (d = 0; d < dof; ++d) { 861846a3e8bSMatthew G. Knepley if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 862087ef6b2SMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr); 863846a3e8bSMatthew G. Knepley } 864846a3e8bSMatthew G. Knepley color = colors[rank%numColors]; 865846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 866846a3e8bSMatthew G. Knepley PetscInt val; 867846a3e8bSMatthew G. Knepley ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr); 868846a3e8bSMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 869846a3e8bSMatthew G. Knepley } 870846a3e8bSMatthew G. Knepley if (useNumbers) { 871846a3e8bSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr); 872846a3e8bSMatthew G. Knepley } else { 873846a3e8bSMatthew G. Knepley ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 874846a3e8bSMatthew G. Knepley } 875846a3e8bSMatthew G. Knepley } 876846a3e8bSMatthew G. Knepley ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 877552f7358SJed Brown /* Plot edges */ 878202fd40aSStefano Zampini if (plotEdges) { 879552f7358SJed Brown ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 880552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 881552f7358SJed Brown for (e = eStart; e < eEnd; ++e) { 882552f7358SJed Brown const PetscInt *cone; 883552f7358SJed Brown PetscInt coneSize, offA, offB, dof, d; 884552f7358SJed Brown 885fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp,e - pStart)) continue; 886552f7358SJed Brown ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 887f347f43bSBarry Smith if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 888552f7358SJed Brown ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 889552f7358SJed Brown ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 890552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 891552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 892552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 893552f7358SJed Brown for (d = 0; d < dof; ++d) { 894202fd40aSStefano Zampini tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 895c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 896552f7358SJed Brown } 8970588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 8980588280cSMatthew G. Knepley if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 8990588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 9000588280cSMatthew G. Knepley if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 901f347f43bSBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 9020588280cSMatthew G. Knepley } 9030588280cSMatthew G. Knepley color = colors[rank%numColors]; 9040588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 9050588280cSMatthew G. Knepley PetscInt val; 906c58f1c22SToby Isaac ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 9070750fff4SMatthew G. Knepley if (val >= 0) {color = lcolors[l%numLColors]; break;} 9080588280cSMatthew G. Knepley } 909e4b003c7SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 910552f7358SJed Brown } 911552f7358SJed Brown ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 912552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 913552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 9140588280cSMatthew G. Knepley } 915552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 9164d4c343aSBarry Smith ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 9170588280cSMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 918770b213bSMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 9190588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 9200588280cSMatthew G. Knepley for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 9210588280cSMatthew G. Knepley for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 9220588280cSMatthew G. Knepley ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 923fe1cc32dSStefano Zampini ierr = PetscBTDestroy(&wp);CHKERRQ(ierr); 9240f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 9250f7d6e4aSStefano Zampini Vec cown,acown; 9260f7d6e4aSStefano Zampini VecScatter sct; 9270f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 9280f7d6e4aSStefano Zampini IS gid,acis; 9290f7d6e4aSStefano Zampini MPI_Comm comm,ncomm = MPI_COMM_NULL; 9300f7d6e4aSStefano Zampini MPI_Group ggroup,ngroup; 9310f7d6e4aSStefano Zampini PetscScalar *array,nid; 9320f7d6e4aSStefano Zampini const PetscInt *idxs; 9330f7d6e4aSStefano Zampini PetscInt *idxs2,*start,*adjacency,*work; 9340f7d6e4aSStefano Zampini PetscInt64 lm[3],gm[3]; 9350f7d6e4aSStefano Zampini PetscInt i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight; 9360f7d6e4aSStefano Zampini PetscMPIInt d1,d2,rank; 9370f7d6e4aSStefano Zampini 9380f7d6e4aSStefano Zampini ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 9390f7d6e4aSStefano Zampini ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 940b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 9410f7d6e4aSStefano Zampini ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRQ(ierr); 9420f7d6e4aSStefano Zampini #endif 9430f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 9440f7d6e4aSStefano Zampini ierr = MPI_Comm_group(comm,&ggroup);CHKERRQ(ierr); 9450f7d6e4aSStefano Zampini ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRQ(ierr); 9460f7d6e4aSStefano Zampini d1 = 0; 9470f7d6e4aSStefano Zampini ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRQ(ierr); 9480f7d6e4aSStefano Zampini nid = d2; 9490f7d6e4aSStefano Zampini ierr = MPI_Group_free(&ggroup);CHKERRQ(ierr); 9500f7d6e4aSStefano Zampini ierr = MPI_Group_free(&ngroup);CHKERRQ(ierr); 9510f7d6e4aSStefano Zampini ierr = MPI_Comm_free(&ncomm);CHKERRQ(ierr); 9520f7d6e4aSStefano Zampini } else nid = 0.0; 9530f7d6e4aSStefano Zampini 9540f7d6e4aSStefano Zampini /* Get connectivity */ 9550f7d6e4aSStefano Zampini ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr); 9560f7d6e4aSStefano Zampini ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr); 9570f7d6e4aSStefano Zampini 9580f7d6e4aSStefano Zampini /* filter overlapped local cells */ 9590f7d6e4aSStefano Zampini ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr); 9600f7d6e4aSStefano Zampini ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr); 9610f7d6e4aSStefano Zampini ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr); 9620f7d6e4aSStefano Zampini ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr); 9630f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 9640f7d6e4aSStefano Zampini if (idxs[c-cStart] < 0) continue; 9650f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c-cStart]; 9660f7d6e4aSStefano Zampini } 9670f7d6e4aSStefano Zampini ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr); 9680f7d6e4aSStefano Zampini if (numVertices != cum) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum); 9690f7d6e4aSStefano Zampini ierr = ISDestroy(&gid);CHKERRQ(ierr); 9700f7d6e4aSStefano Zampini ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr); 9710f7d6e4aSStefano Zampini 9720f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 9730f7d6e4aSStefano Zampini ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr); 9740f7d6e4aSStefano Zampini ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr); 9750f7d6e4aSStefano Zampini ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr); 9760f7d6e4aSStefano Zampini ierr = VecGetArray(cown,&array);CHKERRQ(ierr); 9770f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 9780f7d6e4aSStefano Zampini ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr); 9790f7d6e4aSStefano Zampini ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr); 9800f7d6e4aSStefano Zampini ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 9810f7d6e4aSStefano Zampini ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 9820f7d6e4aSStefano Zampini ierr = ISDestroy(&acis);CHKERRQ(ierr); 9830f7d6e4aSStefano Zampini ierr = VecScatterDestroy(&sct);CHKERRQ(ierr); 9840f7d6e4aSStefano Zampini ierr = VecDestroy(&cown);CHKERRQ(ierr); 9850f7d6e4aSStefano Zampini 9860f7d6e4aSStefano Zampini /* compute edgeCut */ 9870f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]); 9880f7d6e4aSStefano Zampini ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr); 9890f7d6e4aSStefano Zampini ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr); 9900f7d6e4aSStefano Zampini ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr); 9910f7d6e4aSStefano Zampini ierr = ISDestroy(&gid);CHKERRQ(ierr); 9920f7d6e4aSStefano Zampini ierr = VecGetArray(acown,&array);CHKERRQ(ierr); 9930f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 9940f7d6e4aSStefano Zampini PetscInt totl; 9950f7d6e4aSStefano Zampini 9960f7d6e4aSStefano Zampini totl = start[c+1]-start[c]; 9970f7d6e4aSStefano Zampini ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr); 9980f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 9990f7d6e4aSStefano Zampini if (work[i] < 0) { 10000f7d6e4aSStefano Zampini ect += 1; 10010f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 10020f7d6e4aSStefano Zampini } 10030f7d6e4aSStefano Zampini } 10040f7d6e4aSStefano Zampini } 10050f7d6e4aSStefano Zampini ierr = PetscFree(work);CHKERRQ(ierr); 10060f7d6e4aSStefano Zampini ierr = VecRestoreArray(acown,&array);CHKERRQ(ierr); 10070f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 10080f7d6e4aSStefano Zampini lm[1] = -numVertices; 10090f7d6e4aSStefano Zampini ierr = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRQ(ierr); 10100f7d6e4aSStefano Zampini ierr = PetscViewerASCIIPrintf(viewer," Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr); 10110f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 10120f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 10130f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 10140f7d6e4aSStefano Zampini ierr = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRQ(ierr); 10150f7d6e4aSStefano Zampini ierr = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr); 1016b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 10170f7d6e4aSStefano Zampini ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),gm[0] ? ((double)(gm[1]))/((double)gm[0]) : 1.);CHKERRQ(ierr); 10180f7d6e4aSStefano Zampini #else 10190f7d6e4aSStefano Zampini ierr = PetscViewerASCIIPrintf(viewer," Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr); 10200f7d6e4aSStefano Zampini #endif 10210f7d6e4aSStefano Zampini ierr = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr); 10220f7d6e4aSStefano Zampini ierr = PetscFree(start);CHKERRQ(ierr); 10230f7d6e4aSStefano Zampini ierr = PetscFree(adjacency);CHKERRQ(ierr); 10240f7d6e4aSStefano Zampini ierr = VecDestroy(&acown);CHKERRQ(ierr); 1025552f7358SJed Brown } else { 1026412e9a14SMatthew G. Knepley const char *name; 1027d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1028412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1029d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1030a57dd577SMatthew G Knepley PetscInt numLabels, l; 1031412e9a14SMatthew G. Knepley DMPolytopeType ct0; 1032412e9a14SMatthew G. Knepley MPI_Comm comm; 1033412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1034552f7358SJed Brown 103582f516ccSBarry Smith ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 1036552f7358SJed Brown ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 1037412e9a14SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1038c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1039f73eea6eSMatthew G. Knepley ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 10405f64d76eSMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 1041f73eea6eSMatthew G. Knepley if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1042f73eea6eSMatthew G. Knepley else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);} 1043f73eea6eSMatthew G. Knepley if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, " Cells are at height %D\n", cellHeight);CHKERRQ(ierr);} 1044552f7358SJed Brown ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 1045b2566f29SBarry Smith ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 1046d80ece95SMatthew G. Knepley ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr); 1047d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 1048d80ece95SMatthew G. Knepley ierr = PetscCalloc3(size,&sizes,size,&hybsizes,size,&ghostsizes);CHKERRQ(ierr); 1049412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1050412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1051412e9a14SMatthew G. Knepley 1052552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 1053412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr); 1054412e9a14SMatthew G. Knepley ict = ct0; 1055412e9a14SMatthew G. Knepley ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 1056412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType) ict; 1057412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1058412e9a14SMatthew G. Knepley DMPolytopeType ct; 1059412e9a14SMatthew G. Knepley 1060412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 1061412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1062412e9a14SMatthew G. Knepley else ++Nc[1]; 1063412e9a14SMatthew G. Knepley } 1064412e9a14SMatthew G. Knepley ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 1065412e9a14SMatthew G. Knepley ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 1066412e9a14SMatthew G. Knepley if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);} 1067412e9a14SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", (depth == 1) && d ? dim : d);CHKERRQ(ierr); 1068834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1069cbb7f117SMark Adams if (!rank) { 1070412e9a14SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr); 1071412e9a14SMatthew G. Knepley if (hybsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);} 1072412e9a14SMatthew G. Knepley if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);} 1073834065abSMatthew G. Knepley } 1074cbb7f117SMark Adams } 1075552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 1076552f7358SJed Brown } 1077d80ece95SMatthew G. Knepley ierr = PetscFree3(sizes,hybsizes,ghostsizes);CHKERRQ(ierr); 1078c58f1c22SToby Isaac ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 1079a57dd577SMatthew G Knepley if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 1080a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1081a57dd577SMatthew G Knepley DMLabel label; 1082a57dd577SMatthew G Knepley const char *name; 1083a57dd577SMatthew G Knepley IS valueIS; 1084a57dd577SMatthew G Knepley const PetscInt *values; 1085a57dd577SMatthew G Knepley PetscInt numValues, v; 1086a57dd577SMatthew G Knepley 1087c58f1c22SToby Isaac ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 1088c58f1c22SToby Isaac ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1089a57dd577SMatthew G Knepley ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 1090d72f73ffSMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, " %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr); 1091a57dd577SMatthew G Knepley ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1092a57dd577SMatthew G Knepley ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1093120dea56SMatthew G. Knepley ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 1094a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1095a57dd577SMatthew G Knepley PetscInt size; 1096a57dd577SMatthew G Knepley 1097a57dd577SMatthew G Knepley ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 1098a57dd577SMatthew G Knepley if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1099d72f73ffSMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr); 1100a57dd577SMatthew G Knepley } 1101a57dd577SMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 1102120dea56SMatthew G. Knepley ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 1103a57dd577SMatthew G Knepley ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 11044d41221fSMatthew G Knepley ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1105a57dd577SMatthew G Knepley } 110634aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 110734aa8a36SMatthew G. Knepley if (dm->Nf) { 110834aa8a36SMatthew G. Knepley PetscInt f; 110934aa8a36SMatthew G. Knepley 111034aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 111134aa8a36SMatthew G. Knepley const char *name; 111234aa8a36SMatthew G. Knepley 111334aa8a36SMatthew G. Knepley ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr); 111434aa8a36SMatthew G. Knepley if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);} 111534aa8a36SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 111634aa8a36SMatthew G. Knepley if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);} 111734aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 111834aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);} 1119ed59e46eSMatthew G. Knepley else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);} 112034aa8a36SMatthew G. Knepley } else { 112134aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);} 112234aa8a36SMatthew G. Knepley else {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);} 112334aa8a36SMatthew G. Knepley } 112434aa8a36SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 112534aa8a36SMatthew G. Knepley } 112634aa8a36SMatthew G. Knepley } 1127a8fb8f29SToby Isaac ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr); 11288e7ff633SMatthew G. Knepley if (cdm) { 11298e7ff633SMatthew G. Knepley ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 11308e7ff633SMatthew G. Knepley ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr); 11318e7ff633SMatthew G. Knepley ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 11328e7ff633SMatthew G. Knepley } 1133552f7358SJed Brown } 1134552f7358SJed Brown PetscFunctionReturn(0); 1135552f7358SJed Brown } 1136552f7358SJed Brown 1137*e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1138*e5c487bfSMatthew G. Knepley { 1139*e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1140*e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1141*e5c487bfSMatthew G. Knepley PetscErrorCode ierr; 1142*e5c487bfSMatthew G. Knepley 1143*e5c487bfSMatthew G. Knepley PetscFunctionBegin; 1144*e5c487bfSMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 1145*e5c487bfSMatthew G. Knepley ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1146*e5c487bfSMatthew G. Knepley switch (ct) { 1147*e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 1148*e5c487bfSMatthew G. Knepley ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1149*e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1150*e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1151*e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1152*e5c487bfSMatthew G. Knepley ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1153*e5c487bfSMatthew G. Knepley ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1154*e5c487bfSMatthew G. Knepley ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1155*e5c487bfSMatthew G. Knepley break; 1156*e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 1157*e5c487bfSMatthew G. Knepley ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), 1158*e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1159*e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1160*e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1161*e5c487bfSMatthew G. Knepley ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), 1162*e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1163*e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2, 1164*e5c487bfSMatthew G. Knepley PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr); 1165*e5c487bfSMatthew G. Knepley ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1166*e5c487bfSMatthew G. Knepley ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1167*e5c487bfSMatthew G. Knepley ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1168*e5c487bfSMatthew G. Knepley ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr); 1169*e5c487bfSMatthew G. Knepley break; 1170*e5c487bfSMatthew G. Knepley default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1171*e5c487bfSMatthew G. Knepley } 1172*e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1173*e5c487bfSMatthew G. Knepley } 1174*e5c487bfSMatthew G. Knepley 1175*e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1176*e5c487bfSMatthew G. Knepley { 1177*e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1178*e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1179*e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1180*e5c487bfSMatthew G. Knepley PetscInt fillColor, v, e, d; 1181*e5c487bfSMatthew G. Knepley PetscErrorCode ierr; 1182*e5c487bfSMatthew G. Knepley 1183*e5c487bfSMatthew G. Knepley PetscFunctionBegin; 1184*e5c487bfSMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 1185*e5c487bfSMatthew G. Knepley ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr); 1186*e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2; 1187*e5c487bfSMatthew G. Knepley switch (ct) { 1188*e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 1189*e5c487bfSMatthew G. Knepley { 1190*e5c487bfSMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1191*e5c487bfSMatthew G. Knepley 1192*e5c487bfSMatthew G. Knepley for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;} 1193*e5c487bfSMatthew G. Knepley for (e = 0; e < 3; ++e) { 1194*e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e*2+0]; 1195*e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e*2+1]; 1196*e5c487bfSMatthew G. Knepley for (d = 1; d <= edgeDiv; ++d) { 1197*e5c487bfSMatthew G. Knepley refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv; 1198*e5c487bfSMatthew G. Knepley refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv; 1199*e5c487bfSMatthew G. Knepley } 1200*e5c487bfSMatthew G. Knepley ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr); 1201*e5c487bfSMatthew G. Knepley for (d = 0; d < edgeDiv; ++d) { 1202*e5c487bfSMatthew G. Knepley ierr = PetscDrawTriangle(draw, centroid[0], centroid[1], edgeCoords[d*2+0], edgeCoords[d*2+1], edgeCoords[(d+1)*2+0], edgeCoords[(d+1)*2+1], fillColor, fillColor, fillColor);CHKERRQ(ierr); 1203*e5c487bfSMatthew G. Knepley ierr = PetscDrawLine(draw, edgeCoords[d*2+0], edgeCoords[d*2+1], edgeCoords[(d+1)*2+0], edgeCoords[(d+1)*2+1], PETSC_DRAW_BLACK);CHKERRQ(ierr); 1204*e5c487bfSMatthew G. Knepley } 1205*e5c487bfSMatthew G. Knepley } 1206*e5c487bfSMatthew G. Knepley } 1207*e5c487bfSMatthew G. Knepley break; 1208*e5c487bfSMatthew G. Knepley default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1209*e5c487bfSMatthew G. Knepley } 1210*e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 1211*e5c487bfSMatthew G. Knepley } 1212*e5c487bfSMatthew G. Knepley 12137cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1214e412dcbdSMatthew G. Knepley { 1215e412dcbdSMatthew G. Knepley PetscDraw draw; 1216e412dcbdSMatthew G. Knepley DM cdm; 1217e412dcbdSMatthew G. Knepley PetscSection coordSection; 1218e412dcbdSMatthew G. Knepley Vec coordinates; 1219e412dcbdSMatthew G. Knepley const PetscScalar *coords; 122029494db1SLisandro Dalcin PetscReal xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1221*e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1222*e5c487bfSMatthew G. Knepley PetscBool isnull, drawAffine = PETSC_TRUE; 1223*e5c487bfSMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4; 1224e412dcbdSMatthew G. Knepley PetscErrorCode ierr; 1225e412dcbdSMatthew G. Knepley 1226e412dcbdSMatthew G. Knepley PetscFunctionBegin; 1227e412dcbdSMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 1228e412dcbdSMatthew G. Knepley if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim); 1229*e5c487bfSMatthew G. Knepley ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr); 1230*e5c487bfSMatthew G. Knepley if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);} 1231e412dcbdSMatthew G. Knepley ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123292fd8e1eSJed Brown ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1233e412dcbdSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 1234e412dcbdSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1235e412dcbdSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1236e412dcbdSMatthew G. Knepley 1237e412dcbdSMatthew G. Knepley ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr); 1238e412dcbdSMatthew G. Knepley ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr); 1239e412dcbdSMatthew G. Knepley if (isnull) PetscFunctionReturn(0); 1240e412dcbdSMatthew G. Knepley ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr); 1241e412dcbdSMatthew G. Knepley 1242e412dcbdSMatthew G. Knepley ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr); 1243e412dcbdSMatthew G. Knepley ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 1244e412dcbdSMatthew G. Knepley for (c = 0; c < N; c += dim) { 12450c81f2a8SMatthew G. Knepley bound[0] = PetscMin(bound[0], PetscRealPart(coords[c])); bound[2] = PetscMax(bound[2], PetscRealPart(coords[c])); 12460c81f2a8SMatthew G. Knepley bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1])); 1247e412dcbdSMatthew G. Knepley } 1248e412dcbdSMatthew G. Knepley ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 124929494db1SLisandro Dalcin ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 125029494db1SLisandro Dalcin ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 125129494db1SLisandro Dalcin ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr); 1252e412dcbdSMatthew G. Knepley ierr = PetscDrawClear(draw);CHKERRQ(ierr); 1253e412dcbdSMatthew G. Knepley 1254cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1255cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1256ba2698f1SMatthew G. Knepley PetscInt numCoords; 1257cf3064d3SMatthew G. Knepley 1258*e5c487bfSMatthew G. Knepley ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr); 1259*e5c487bfSMatthew G. Knepley if (drawAffine) { 1260*e5c487bfSMatthew G. Knepley ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr); 1261*e5c487bfSMatthew G. Knepley } else { 1262*e5c487bfSMatthew G. Knepley ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr); 1263cf3064d3SMatthew G. Knepley } 1264cf3064d3SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr); 1265cf3064d3SMatthew G. Knepley } 1266*e5c487bfSMatthew G. Knepley if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);} 1267e412dcbdSMatthew G. Knepley ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 1268e412dcbdSMatthew G. Knepley ierr = PetscDrawPause(draw);CHKERRQ(ierr); 1269e412dcbdSMatthew G. Knepley ierr = PetscDrawSave(draw);CHKERRQ(ierr); 1270e412dcbdSMatthew G. Knepley PetscFunctionReturn(0); 1271e412dcbdSMatthew G. Knepley } 1272e412dcbdSMatthew G. Knepley 12731e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 12741e50132fSMatthew G. Knepley #include <exodusII.h> 12751e50132fSMatthew G. Knepley #endif 12761e50132fSMatthew G. Knepley 1277552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1278552f7358SJed Brown { 12791e50132fSMatthew G. Knepley PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus; 1280002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1281552f7358SJed Brown PetscErrorCode ierr; 1282552f7358SJed Brown 1283552f7358SJed Brown PetscFunctionBegin; 1284552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1285552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1286552f7358SJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 1287fcf6c8fdSToby Isaac ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 1288c6ccd67eSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1289e412dcbdSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW, &isdraw);CHKERRQ(ierr); 12908135c375SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr); 12911e50132fSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr); 1292552f7358SJed Brown if (iascii) { 12938135c375SStefano Zampini PetscViewerFormat format; 12948135c375SStefano Zampini ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 12958135c375SStefano Zampini if (format == PETSC_VIEWER_ASCII_GLVIS) { 12968135c375SStefano Zampini ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 12978135c375SStefano Zampini } else { 1298552f7358SJed Brown ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 12998135c375SStefano Zampini } 1300c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1301c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 130239d25373SMatthew G. Knepley ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1303c6ccd67eSMatthew G. Knepley #else 1304c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1305552f7358SJed Brown #endif 1306e412dcbdSMatthew G. Knepley } else if (isvtk) { 1307fcf6c8fdSToby Isaac ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 1308e412dcbdSMatthew G. Knepley } else if (isdraw) { 1309e412dcbdSMatthew G. Knepley ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr); 13108135c375SStefano Zampini } else if (isglvis) { 13118135c375SStefano Zampini ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr); 13121e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 13131e50132fSMatthew G. Knepley } else if (isexodus) { 13141e50132fSMatthew G. Knepley int exoid; 13151e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 13161e50132fSMatthew G. Knepley 13171e50132fSMatthew G. Knepley ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr); 13181e50132fSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 13191e50132fSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);} 13201e50132fSMatthew G. Knepley ierr = PetscViewerExodusIIGetId(viewer, &exoid);CHKERRQ(ierr); 13211e50132fSMatthew G. Knepley ierr = DMPlexView_ExodusII_Internal(dm, exoid, 1);CHKERRQ(ierr); 13221e50132fSMatthew G. Knepley #endif 132362201deeSVaclav Hapla } else { 1324a94aea51SVaclav Hapla SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1325fcf6c8fdSToby Isaac } 1326cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 1327cb3ba0daSMatthew G. Knepley ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr); 1328cb3ba0daSMatthew G. Knepley if (flg) { 1329cb3ba0daSMatthew G. Knepley Vec ranks; 1330cb3ba0daSMatthew G. Knepley ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr); 1331cb3ba0daSMatthew G. Knepley ierr = VecView(ranks, viewer);CHKERRQ(ierr); 1332cb3ba0daSMatthew G. Knepley ierr = VecDestroy(&ranks);CHKERRQ(ierr); 1333cb3ba0daSMatthew G. Knepley } 1334002a2709SMatthew G. Knepley /* Optionally view a label */ 1335002a2709SMatthew G. Knepley ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, PETSC_MAX_PATH_LEN, &flg);CHKERRQ(ierr); 1336002a2709SMatthew G. Knepley if (flg) { 1337002a2709SMatthew G. Knepley DMLabel label; 1338002a2709SMatthew G. Knepley Vec val; 1339002a2709SMatthew G. Knepley 1340002a2709SMatthew G. Knepley ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 1341002a2709SMatthew G. Knepley if (!label) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 1342002a2709SMatthew G. Knepley ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr); 1343002a2709SMatthew G. Knepley ierr = VecView(val, viewer);CHKERRQ(ierr); 1344002a2709SMatthew G. Knepley ierr = VecDestroy(&val);CHKERRQ(ierr); 1345002a2709SMatthew G. Knepley } 1346552f7358SJed Brown PetscFunctionReturn(0); 1347552f7358SJed Brown } 1348552f7358SJed Brown 13492c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 13502c40f234SMatthew G. Knepley { 1351d4f5a9a0SVaclav Hapla PetscBool ishdf5; 13522c40f234SMatthew G. Knepley PetscErrorCode ierr; 13532c40f234SMatthew G. Knepley 13542c40f234SMatthew G. Knepley PetscFunctionBegin; 13552c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 13562c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 13572c40f234SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 1358d4f5a9a0SVaclav Hapla if (ishdf5) { 13592c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 13609c48423bSVaclav Hapla PetscViewerFormat format; 13619c48423bSVaclav Hapla ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 13629c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 13639c48423bSVaclav Hapla ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr); 1364509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 136539d25373SMatthew G. Knepley ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr); 1366509517efSVaclav Hapla } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 13672c40f234SMatthew G. Knepley #else 13682c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1369552f7358SJed Brown #endif 1370d4f5a9a0SVaclav Hapla } else { 1371d4f5a9a0SVaclav Hapla SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 1372552f7358SJed Brown } 1373552f7358SJed Brown PetscFunctionReturn(0); 1374552f7358SJed Brown } 1375552f7358SJed Brown 1376552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm) 1377552f7358SJed Brown { 1378552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 1379552f7358SJed Brown PetscErrorCode ierr; 1380552f7358SJed Brown 1381552f7358SJed Brown PetscFunctionBegin; 13828135c375SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr); 13838135c375SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr); 138428d58a37SPierre Jolivet ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr); 13850d644c17SKarl Rupp if (--mesh->refct > 0) PetscFunctionReturn(0); 1386552f7358SJed Brown ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 1387552f7358SJed Brown ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 1388552f7358SJed Brown ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 1389552f7358SJed Brown ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 1390be36d101SStefano Zampini ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr); 1391552f7358SJed Brown ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 1392552f7358SJed Brown ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 1393d9deefdfSMatthew G. Knepley ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 1394d9deefdfSMatthew G. Knepley ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 139577623264SMatthew G. Knepley ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 1396a89082eeSMatthew G Knepley ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 139797d8846cSMatthew Knepley ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr); 1398552f7358SJed Brown ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 1399552f7358SJed Brown ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 1400a68b90caSToby Isaac ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 1401a68b90caSToby Isaac ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 1402d961a43aSToby Isaac ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 1403d961a43aSToby Isaac ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 1404d961a43aSToby Isaac ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 1405d961a43aSToby Isaac ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 1406d961a43aSToby Isaac ierr = PetscFree(mesh->children);CHKERRQ(ierr); 1407d6a7ad0dSToby Isaac ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 1408fec49543SMatthew G. Knepley ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr); 14090a19bb7dSprj- ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr); 1410552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 1411552f7358SJed Brown ierr = PetscFree(mesh);CHKERRQ(ierr); 1412552f7358SJed Brown PetscFunctionReturn(0); 1413552f7358SJed Brown } 1414552f7358SJed Brown 1415b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 1416552f7358SJed Brown { 14178d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 1418acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 1419552f7358SJed Brown PetscInt localSize; 1420837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 1421552f7358SJed Brown PetscErrorCode ierr; 1422b412c318SBarry Smith MatType mtype; 14231428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 1424552f7358SJed Brown 1425552f7358SJed Brown PetscFunctionBegin; 1426607a6623SBarry Smith ierr = MatInitializePackage();CHKERRQ(ierr); 1427b412c318SBarry Smith mtype = dm->mattype; 1428e87a4003SBarry Smith ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1429552f7358SJed Brown /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 1430552f7358SJed Brown ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 143182f516ccSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 1432552f7358SJed Brown ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1433552f7358SJed Brown ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 1434552f7358SJed Brown ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 1435acd755d7SMatthew G. Knepley ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr); 1436acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 1437552f7358SJed Brown ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 1438552f7358SJed Brown ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 1439552f7358SJed Brown ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 1440552f7358SJed Brown ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 1441552f7358SJed Brown ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 1442552f7358SJed Brown ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 1443552f7358SJed Brown ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 1444837628f4SStefano Zampini ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr); 1445552f7358SJed Brown if (!isShell) { 1446be36d101SStefano Zampini PetscSection subSection; 1447837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 14480be3e97aSMatthew G. Knepley PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize; 1449fad22124SMatthew G Knepley PetscInt pStart, pEnd, p, dof, cdof; 1450552f7358SJed Brown 145100140cc3SStefano Zampini /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */ 1452be36d101SStefano Zampini if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */ 1453be36d101SStefano Zampini PetscSection section; 1454be36d101SStefano Zampini PetscInt size; 1455be36d101SStefano Zampini 145692fd8e1eSJed Brown ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 1457be36d101SStefano Zampini ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 1458be36d101SStefano Zampini ierr = PetscMalloc1(size,<ogidx);CHKERRQ(ierr); 1459be36d101SStefano Zampini ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 1460be36d101SStefano Zampini } else { 146100140cc3SStefano Zampini ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 1462be36d101SStefano Zampini } 1463552f7358SJed Brown ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1464be36d101SStefano Zampini for (p = pStart, lsize = 0; p < pEnd; ++p) { 1465a9d99c84SMatthew G. Knepley PetscInt bdof; 1466a9d99c84SMatthew G. Knepley 1467552f7358SJed Brown ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1468fad22124SMatthew G Knepley ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 14691d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof+1) : dof; 14701d17a0a3SMatthew G. Knepley bdof = cdof && (dof-cdof) ? 1 : dof; 14711d17a0a3SMatthew G. Knepley if (dof) { 14721d17a0a3SMatthew G. Knepley if (bs < 0) {bs = bdof;} 1473be36d101SStefano Zampini else if (bs != bdof) {bs = 1; if (!isMatIS) break;} 1474be36d101SStefano Zampini } 1475be36d101SStefano Zampini if (isMatIS) { 1476be36d101SStefano Zampini PetscInt loff,c,off; 1477be36d101SStefano Zampini ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr); 1478be36d101SStefano Zampini ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 1479be36d101SStefano Zampini for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c; 1480552f7358SJed Brown } 14812a28c762SMatthew G Knepley } 14822a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 14830be3e97aSMatthew G. Knepley bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 14840be3e97aSMatthew G. Knepley ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 14850be3e97aSMatthew G. Knepley if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 14860be3e97aSMatthew G. Knepley else {bs = bsMinMax[0];} 14876fd5c86aSStefano Zampini bs = PetscMax(1,bs); 14886fd5c86aSStefano Zampini if (isMatIS) { /* Must reduce indices by blocksize */ 14894fa26246SMatthew G. Knepley PetscInt l; 14906fd5c86aSStefano Zampini 14916fd5c86aSStefano Zampini lsize = lsize/bs; 14926fd5c86aSStefano Zampini if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs; 14934fa26246SMatthew G. Knepley ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, <og);CHKERRQ(ierr); 1494be36d101SStefano Zampini } 1495be36d101SStefano Zampini ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 1496be36d101SStefano Zampini if (isMatIS) { 1497be36d101SStefano Zampini ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 1498be36d101SStefano Zampini } 14991795a4d1SJed Brown ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 15008d1174e4SMatthew G. Knepley ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1501552f7358SJed Brown ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1502552f7358SJed Brown } 1503b1f74addSMatthew G. Knepley ierr = MatSetDM(*J, dm);CHKERRQ(ierr); 1504552f7358SJed Brown PetscFunctionReturn(0); 1505552f7358SJed Brown } 1506552f7358SJed Brown 15077cd05799SMatthew G. Knepley /*@ 1508a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 1509be36d101SStefano Zampini 1510be36d101SStefano Zampini Not collective 1511be36d101SStefano Zampini 1512be36d101SStefano Zampini Input Parameter: 1513be36d101SStefano Zampini . mesh - The DMPlex 1514be36d101SStefano Zampini 1515be36d101SStefano Zampini Output Parameters: 1516be36d101SStefano Zampini . subsection - The subdomain section 1517be36d101SStefano Zampini 1518be36d101SStefano Zampini Level: developer 1519be36d101SStefano Zampini 1520be36d101SStefano Zampini .seealso: 15217cd05799SMatthew G. Knepley @*/ 1522be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 1523be36d101SStefano Zampini { 1524be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex*) dm->data; 1525be36d101SStefano Zampini PetscErrorCode ierr; 1526be36d101SStefano Zampini 1527be36d101SStefano Zampini PetscFunctionBegin; 1528be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1529be36d101SStefano Zampini if (!mesh->subdomainSection) { 1530be36d101SStefano Zampini PetscSection section; 1531be36d101SStefano Zampini PetscSF sf; 1532be36d101SStefano Zampini 1533be36d101SStefano Zampini ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr); 153492fd8e1eSJed Brown ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 1535be36d101SStefano Zampini ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr); 1536be36d101SStefano Zampini ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 1537be36d101SStefano Zampini } 1538be36d101SStefano Zampini *subsection = mesh->subdomainSection; 1539be36d101SStefano Zampini PetscFunctionReturn(0); 1540be36d101SStefano Zampini } 1541be36d101SStefano Zampini 1542552f7358SJed Brown /*@ 1543552f7358SJed Brown DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1544552f7358SJed Brown 1545552f7358SJed Brown Not collective 1546552f7358SJed Brown 1547552f7358SJed Brown Input Parameter: 1548552f7358SJed Brown . mesh - The DMPlex 1549552f7358SJed Brown 1550552f7358SJed Brown Output Parameters: 1551552f7358SJed Brown + pStart - The first mesh point 1552552f7358SJed Brown - pEnd - The upper bound for mesh points 1553552f7358SJed Brown 1554552f7358SJed Brown Level: beginner 1555552f7358SJed Brown 1556552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart() 1557552f7358SJed Brown @*/ 1558552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1559552f7358SJed Brown { 1560552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 1561552f7358SJed Brown PetscErrorCode ierr; 1562552f7358SJed Brown 1563552f7358SJed Brown PetscFunctionBegin; 1564552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1565552f7358SJed Brown ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1566552f7358SJed Brown PetscFunctionReturn(0); 1567552f7358SJed Brown } 1568552f7358SJed Brown 1569552f7358SJed Brown /*@ 1570552f7358SJed Brown DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1571552f7358SJed Brown 1572552f7358SJed Brown Not collective 1573552f7358SJed Brown 1574552f7358SJed Brown Input Parameters: 1575552f7358SJed Brown + mesh - The DMPlex 1576552f7358SJed Brown . pStart - The first mesh point 1577552f7358SJed Brown - pEnd - The upper bound for mesh points 1578552f7358SJed Brown 1579552f7358SJed Brown Output Parameters: 1580552f7358SJed Brown 1581552f7358SJed Brown Level: beginner 1582552f7358SJed Brown 1583552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetChart() 1584552f7358SJed Brown @*/ 1585552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1586552f7358SJed Brown { 1587552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 1588552f7358SJed Brown PetscErrorCode ierr; 1589552f7358SJed Brown 1590552f7358SJed Brown PetscFunctionBegin; 1591552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1592552f7358SJed Brown ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1593552f7358SJed Brown ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1594552f7358SJed Brown PetscFunctionReturn(0); 1595552f7358SJed Brown } 1596552f7358SJed Brown 1597552f7358SJed Brown /*@ 1598eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 1599552f7358SJed Brown 1600552f7358SJed Brown Not collective 1601552f7358SJed Brown 1602552f7358SJed Brown Input Parameters: 1603552f7358SJed Brown + mesh - The DMPlex 1604eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 1605552f7358SJed Brown 1606552f7358SJed Brown Output Parameter: 1607552f7358SJed Brown . size - The cone size for point p 1608552f7358SJed Brown 1609552f7358SJed Brown Level: beginner 1610552f7358SJed Brown 1611552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1612552f7358SJed Brown @*/ 1613552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1614552f7358SJed Brown { 1615552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 1616552f7358SJed Brown PetscErrorCode ierr; 1617552f7358SJed Brown 1618552f7358SJed Brown PetscFunctionBegin; 1619552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1620552f7358SJed Brown PetscValidPointer(size, 3); 1621552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1622552f7358SJed Brown PetscFunctionReturn(0); 1623552f7358SJed Brown } 1624552f7358SJed Brown 1625552f7358SJed Brown /*@ 1626eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 1627552f7358SJed Brown 1628552f7358SJed Brown Not collective 1629552f7358SJed Brown 1630552f7358SJed Brown Input Parameters: 1631552f7358SJed Brown + mesh - The DMPlex 1632eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 1633552f7358SJed Brown - size - The cone size for point p 1634552f7358SJed Brown 1635552f7358SJed Brown Output Parameter: 1636552f7358SJed Brown 1637552f7358SJed Brown Note: 1638552f7358SJed Brown This should be called after DMPlexSetChart(). 1639552f7358SJed Brown 1640552f7358SJed Brown Level: beginner 1641552f7358SJed Brown 1642552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1643552f7358SJed Brown @*/ 1644552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1645552f7358SJed Brown { 1646552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 1647552f7358SJed Brown PetscErrorCode ierr; 1648552f7358SJed Brown 1649552f7358SJed Brown PetscFunctionBegin; 1650552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1651552f7358SJed Brown ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 16520d644c17SKarl Rupp 1653552f7358SJed Brown mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1654552f7358SJed Brown PetscFunctionReturn(0); 1655552f7358SJed Brown } 1656552f7358SJed Brown 1657f5a469b9SMatthew G. Knepley /*@ 1658eaf898f9SPatrick Sanan DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG 1659f5a469b9SMatthew G. Knepley 1660f5a469b9SMatthew G. Knepley Not collective 1661f5a469b9SMatthew G. Knepley 1662f5a469b9SMatthew G. Knepley Input Parameters: 1663f5a469b9SMatthew G. Knepley + mesh - The DMPlex 1664eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 1665f5a469b9SMatthew G. Knepley - size - The additional cone size for point p 1666f5a469b9SMatthew G. Knepley 1667f5a469b9SMatthew G. Knepley Output Parameter: 1668f5a469b9SMatthew G. Knepley 1669f5a469b9SMatthew G. Knepley Note: 1670f5a469b9SMatthew G. Knepley This should be called after DMPlexSetChart(). 1671f5a469b9SMatthew G. Knepley 1672f5a469b9SMatthew G. Knepley Level: beginner 1673f5a469b9SMatthew G. Knepley 1674f5a469b9SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 1675f5a469b9SMatthew G. Knepley @*/ 1676f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 1677f5a469b9SMatthew G. Knepley { 1678f5a469b9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 1679f5a469b9SMatthew G. Knepley PetscInt csize; 1680f5a469b9SMatthew G. Knepley PetscErrorCode ierr; 1681f5a469b9SMatthew G. Knepley 1682f5a469b9SMatthew G. Knepley PetscFunctionBegin; 1683f5a469b9SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1684f5a469b9SMatthew G. Knepley ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1685f5a469b9SMatthew G. Knepley ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 1686f5a469b9SMatthew G. Knepley 1687f5a469b9SMatthew G. Knepley mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 1688f5a469b9SMatthew G. Knepley PetscFunctionReturn(0); 1689f5a469b9SMatthew G. Knepley } 1690f5a469b9SMatthew G. Knepley 1691552f7358SJed Brown /*@C 1692eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 1693552f7358SJed Brown 1694552f7358SJed Brown Not collective 1695552f7358SJed Brown 1696552f7358SJed Brown Input Parameters: 1697833c876bSVaclav Hapla + dm - The DMPlex 1698eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 1699552f7358SJed Brown 1700552f7358SJed Brown Output Parameter: 1701552f7358SJed Brown . cone - An array of points which are on the in-edges for point p 1702552f7358SJed Brown 1703552f7358SJed Brown Level: beginner 1704552f7358SJed Brown 17053813dfbdSMatthew G Knepley Fortran Notes: 17063813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 17073813dfbdSMatthew G Knepley include petsc.h90 in your code. 1708922102d1SVaclav Hapla You must also call DMPlexRestoreCone() after you finish using the returned array. 1709922102d1SVaclav Hapla DMPlexRestoreCone() is not needed/available in C. 17103813dfbdSMatthew G Knepley 17110ce7577fSVaclav Hapla .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart() 1712552f7358SJed Brown @*/ 1713552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1714552f7358SJed Brown { 1715552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 1716552f7358SJed Brown PetscInt off; 1717552f7358SJed Brown PetscErrorCode ierr; 1718552f7358SJed Brown 1719552f7358SJed Brown PetscFunctionBegin; 1720552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1721552f7358SJed Brown PetscValidPointer(cone, 3); 1722552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1723552f7358SJed Brown *cone = &mesh->cones[off]; 1724552f7358SJed Brown PetscFunctionReturn(0); 1725552f7358SJed Brown } 1726552f7358SJed Brown 17270ce7577fSVaclav Hapla /*@C 17280ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 17290ce7577fSVaclav Hapla 17300ce7577fSVaclav Hapla Not collective 17310ce7577fSVaclav Hapla 17320ce7577fSVaclav Hapla Input Parameters: 17330ce7577fSVaclav Hapla + dm - The DMPlex 17340ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart() 17350ce7577fSVaclav Hapla 17360ce7577fSVaclav Hapla Output Parameter: 17370ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones 17380ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p 17390ce7577fSVaclav Hapla 17400ce7577fSVaclav Hapla Level: intermediate 17410ce7577fSVaclav Hapla 1742d4636a37SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart() 17430ce7577fSVaclav Hapla @*/ 17440ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 17450ce7577fSVaclav Hapla { 17460ce7577fSVaclav Hapla PetscSection cs, newcs; 17470ce7577fSVaclav Hapla PetscInt *cones; 17480ce7577fSVaclav Hapla PetscInt *newarr=NULL; 17490ce7577fSVaclav Hapla PetscInt n; 17500ce7577fSVaclav Hapla PetscErrorCode ierr; 17510ce7577fSVaclav Hapla 17520ce7577fSVaclav Hapla PetscFunctionBegin; 17530ce7577fSVaclav Hapla ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 17540ce7577fSVaclav Hapla ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr); 17550ce7577fSVaclav Hapla ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 17560ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 17570ce7577fSVaclav Hapla if (pCones) { 17580ce7577fSVaclav Hapla ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 17590ce7577fSVaclav Hapla ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr); 17600ce7577fSVaclav Hapla } 17610ce7577fSVaclav Hapla PetscFunctionReturn(0); 17620ce7577fSVaclav Hapla } 17630ce7577fSVaclav Hapla 1764af9eab45SVaclav Hapla /*@ 1765af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 1766d4636a37SVaclav Hapla 1767d4636a37SVaclav Hapla Not collective 1768d4636a37SVaclav Hapla 1769d4636a37SVaclav Hapla Input Parameters: 1770d4636a37SVaclav Hapla + dm - The DMPlex 1771af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 1772d4636a37SVaclav Hapla 1773d4636a37SVaclav Hapla Output Parameter: 1774af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 1775d4636a37SVaclav Hapla 1776d4636a37SVaclav Hapla Level: advanced 1777d4636a37SVaclav Hapla 1778af9eab45SVaclav Hapla Notes: 1779af9eab45SVaclav Hapla Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections. 1780af9eab45SVaclav Hapla There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate. 1781af9eab45SVaclav Hapla 1782af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth() 1783d4636a37SVaclav Hapla @*/ 1784af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 1785d4636a37SVaclav Hapla { 1786af9eab45SVaclav Hapla IS *expandedPointsAll; 1787af9eab45SVaclav Hapla PetscInt depth; 1788d4636a37SVaclav Hapla PetscErrorCode ierr; 1789d4636a37SVaclav Hapla 1790d4636a37SVaclav Hapla PetscFunctionBegin; 1791af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1792af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 1793af9eab45SVaclav Hapla PetscValidPointer(expandedPoints, 3); 1794af9eab45SVaclav Hapla ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 1795af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 1796af9eab45SVaclav Hapla ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]); 1797af9eab45SVaclav Hapla ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr); 1798af9eab45SVaclav Hapla PetscFunctionReturn(0); 1799af9eab45SVaclav Hapla } 1800af9eab45SVaclav Hapla 1801af9eab45SVaclav Hapla /*@ 1802af9eab45SVaclav Hapla DMPlexGetConeRecursive - Expand each given point into its cone points and do that recursively until we end up just with vertices (DAG points of depth 0, i.e. without cones). 1803af9eab45SVaclav Hapla 1804af9eab45SVaclav Hapla Not collective 1805af9eab45SVaclav Hapla 1806af9eab45SVaclav Hapla Input Parameters: 1807af9eab45SVaclav Hapla + dm - The DMPlex 1808af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 1809af9eab45SVaclav Hapla 1810af9eab45SVaclav Hapla Output Parameter: 1811af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 1812af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 1813af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 1814af9eab45SVaclav Hapla 1815af9eab45SVaclav Hapla Level: advanced 1816af9eab45SVaclav Hapla 1817af9eab45SVaclav Hapla Notes: 1818af9eab45SVaclav Hapla Like DMPlexGetConeTuple() but recursive. 1819af9eab45SVaclav Hapla 1820af9eab45SVaclav Hapla Array expandedPoints has size equal to depth. Each expandedPoints[d] contains DAG points with maximum depth d, recursively cone-wise expanded from the input points. 1821af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 1822af9eab45SVaclav Hapla 1823af9eab45SVaclav Hapla Array section has size equal to depth. Each PetscSection sections[d] realizes mapping from expandedPoints[d+1] (section points) to expandedPoints[d] (section dofs) as follows: 1824af9eab45SVaclav Hapla (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d]; 1825af9eab45SVaclav Hapla (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d]. 1826af9eab45SVaclav Hapla 1827af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 1828af9eab45SVaclav Hapla @*/ 1829af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 1830af9eab45SVaclav Hapla { 1831af9eab45SVaclav Hapla const PetscInt *arr0=NULL, *cone=NULL; 1832af9eab45SVaclav Hapla PetscInt *arr=NULL, *newarr=NULL; 1833af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 1834af9eab45SVaclav Hapla IS *expandedPoints_; 1835af9eab45SVaclav Hapla PetscSection *sections_; 1836af9eab45SVaclav Hapla PetscErrorCode ierr; 1837af9eab45SVaclav Hapla 1838af9eab45SVaclav Hapla PetscFunctionBegin; 1839af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1840af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 1841af9eab45SVaclav Hapla if (depth) PetscValidIntPointer(depth, 3); 1842af9eab45SVaclav Hapla if (expandedPoints) PetscValidPointer(expandedPoints, 4); 1843af9eab45SVaclav Hapla if (sections) PetscValidPointer(sections, 5); 1844af9eab45SVaclav Hapla ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr); 1845af9eab45SVaclav Hapla ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr); 1846af9eab45SVaclav Hapla ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 1847af9eab45SVaclav Hapla ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr); 1848af9eab45SVaclav Hapla ierr = PetscCalloc1(depth_, §ions_);CHKERRQ(ierr); 1849af9eab45SVaclav Hapla arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */ 1850af9eab45SVaclav Hapla for (d=depth_-1; d>=0; d--) { 1851af9eab45SVaclav Hapla ierr = PetscSectionCreate(PETSC_COMM_SELF, §ions_[d]);CHKERRQ(ierr); 1852af9eab45SVaclav Hapla ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr); 1853af9eab45SVaclav Hapla for (i=0; i<n; i++) { 1854af9eab45SVaclav Hapla ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr); 1855af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 1856af9eab45SVaclav Hapla ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr); 1857af9eab45SVaclav Hapla ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr); 1858af9eab45SVaclav Hapla } else { 1859af9eab45SVaclav Hapla ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr); 1860af9eab45SVaclav Hapla } 1861af9eab45SVaclav Hapla } 1862af9eab45SVaclav Hapla ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr); 1863af9eab45SVaclav Hapla ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr); 1864af9eab45SVaclav Hapla ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr); 1865af9eab45SVaclav Hapla for (i=0; i<n; i++) { 1866af9eab45SVaclav Hapla ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr); 1867af9eab45SVaclav Hapla ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr); 1868af9eab45SVaclav Hapla if (cn > 1) { 1869af9eab45SVaclav Hapla ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr); 1870af9eab45SVaclav Hapla ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr); 1871af9eab45SVaclav Hapla } else { 1872af9eab45SVaclav Hapla newarr[co] = arr[i]; 1873af9eab45SVaclav Hapla } 1874af9eab45SVaclav Hapla } 1875af9eab45SVaclav Hapla ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr); 1876af9eab45SVaclav Hapla arr = newarr; 1877af9eab45SVaclav Hapla n = newn; 1878af9eab45SVaclav Hapla } 1879ba2698f1SMatthew G. Knepley ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr); 1880af9eab45SVaclav Hapla *depth = depth_; 1881af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 1882af9eab45SVaclav Hapla else { 1883af9eab45SVaclav Hapla for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);} 1884af9eab45SVaclav Hapla ierr = PetscFree(expandedPoints_);CHKERRQ(ierr); 1885af9eab45SVaclav Hapla } 1886af9eab45SVaclav Hapla if (sections) *sections = sections_; 1887af9eab45SVaclav Hapla else { 1888af9eab45SVaclav Hapla for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(§ions_[d]);CHKERRQ(ierr);} 1889af9eab45SVaclav Hapla ierr = PetscFree(sections_);CHKERRQ(ierr); 1890af9eab45SVaclav Hapla } 1891af9eab45SVaclav Hapla PetscFunctionReturn(0); 1892af9eab45SVaclav Hapla } 1893af9eab45SVaclav Hapla 1894af9eab45SVaclav Hapla /*@ 1895af9eab45SVaclav Hapla DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive 1896af9eab45SVaclav Hapla 1897af9eab45SVaclav Hapla Not collective 1898af9eab45SVaclav Hapla 1899af9eab45SVaclav Hapla Input Parameters: 1900af9eab45SVaclav Hapla + dm - The DMPlex 1901af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart() 1902af9eab45SVaclav Hapla 1903af9eab45SVaclav Hapla Output Parameter: 1904af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth() 1905af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 1906af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 1907af9eab45SVaclav Hapla 1908af9eab45SVaclav Hapla Level: advanced 1909af9eab45SVaclav Hapla 1910af9eab45SVaclav Hapla Notes: 1911af9eab45SVaclav Hapla See DMPlexGetConeRecursive() for details. 1912af9eab45SVaclav Hapla 1913af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth() 1914af9eab45SVaclav Hapla @*/ 1915af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 1916af9eab45SVaclav Hapla { 1917af9eab45SVaclav Hapla PetscInt d, depth_; 1918af9eab45SVaclav Hapla PetscErrorCode ierr; 1919af9eab45SVaclav Hapla 1920af9eab45SVaclav Hapla PetscFunctionBegin; 1921af9eab45SVaclav Hapla ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr); 1922af9eab45SVaclav Hapla if (depth && *depth != depth_) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 1923af9eab45SVaclav Hapla if (depth) *depth = 0; 1924af9eab45SVaclav Hapla if (expandedPoints) { 1925af9eab45SVaclav Hapla for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);} 1926af9eab45SVaclav Hapla ierr = PetscFree(*expandedPoints);CHKERRQ(ierr); 1927af9eab45SVaclav Hapla } 1928af9eab45SVaclav Hapla if (sections) { 1929af9eab45SVaclav Hapla for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);} 1930af9eab45SVaclav Hapla ierr = PetscFree(*sections);CHKERRQ(ierr); 1931af9eab45SVaclav Hapla } 1932d4636a37SVaclav Hapla PetscFunctionReturn(0); 1933d4636a37SVaclav Hapla } 1934d4636a37SVaclav Hapla 1935552f7358SJed Brown /*@ 193692371b87SBarry Smith DMPlexSetCone - Set the points on the in-edges for this point in the DAG; that is these are the points that cover the specific point 1937552f7358SJed Brown 1938552f7358SJed Brown Not collective 1939552f7358SJed Brown 1940552f7358SJed Brown Input Parameters: 1941552f7358SJed Brown + mesh - The DMPlex 1942eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 1943552f7358SJed Brown - cone - An array of points which are on the in-edges for point p 1944552f7358SJed Brown 1945552f7358SJed Brown Output Parameter: 1946552f7358SJed Brown 1947552f7358SJed Brown Note: 1948552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1949552f7358SJed Brown 195092371b87SBarry Smith Developer Note: Why not call this DMPlexSetCover() 195192371b87SBarry Smith 1952552f7358SJed Brown Level: beginner 1953552f7358SJed Brown 195492371b87SBarry Smith .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize() 1955552f7358SJed Brown @*/ 1956552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1957552f7358SJed Brown { 1958552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 1959552f7358SJed Brown PetscInt pStart, pEnd; 1960552f7358SJed Brown PetscInt dof, off, c; 1961552f7358SJed Brown PetscErrorCode ierr; 1962552f7358SJed Brown 1963552f7358SJed Brown PetscFunctionBegin; 1964552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1965552f7358SJed Brown ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1966552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1967552f7358SJed Brown if (dof) PetscValidPointer(cone, 3); 1968552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 196982f516ccSBarry Smith if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1970552f7358SJed Brown for (c = 0; c < dof; ++c) { 197182f516ccSBarry Smith if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1972552f7358SJed Brown mesh->cones[off+c] = cone[c]; 1973552f7358SJed Brown } 1974552f7358SJed Brown PetscFunctionReturn(0); 1975552f7358SJed Brown } 1976552f7358SJed Brown 1977552f7358SJed Brown /*@C 1978eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 1979552f7358SJed Brown 1980552f7358SJed Brown Not collective 1981552f7358SJed Brown 1982552f7358SJed Brown Input Parameters: 1983552f7358SJed Brown + mesh - The DMPlex 1984eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 1985552f7358SJed Brown 1986552f7358SJed Brown Output Parameter: 1987552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1988552f7358SJed Brown integer giving the prescription for cone traversal. If it is negative, the cone is 1989552f7358SJed Brown traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1990552f7358SJed Brown the index of the cone point on which to start. 1991552f7358SJed Brown 1992552f7358SJed Brown Level: beginner 1993552f7358SJed Brown 19943813dfbdSMatthew G Knepley Fortran Notes: 19953813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 19963813dfbdSMatthew G Knepley include petsc.h90 in your code. 19973b12b3d8SVaclav Hapla You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 1998922102d1SVaclav Hapla DMPlexRestoreConeOrientation() is not needed/available in C. 19993813dfbdSMatthew G Knepley 2000552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 2001552f7358SJed Brown @*/ 2002552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 2003552f7358SJed Brown { 2004552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2005552f7358SJed Brown PetscInt off; 2006552f7358SJed Brown PetscErrorCode ierr; 2007552f7358SJed Brown 2008552f7358SJed Brown PetscFunctionBegin; 2009552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 201076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 2011552f7358SJed Brown PetscInt dof; 2012552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2013552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 2014552f7358SJed Brown } 2015552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 20160d644c17SKarl Rupp 2017552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 2018552f7358SJed Brown PetscFunctionReturn(0); 2019552f7358SJed Brown } 2020552f7358SJed Brown 2021552f7358SJed Brown /*@ 2022eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 2023552f7358SJed Brown 2024552f7358SJed Brown Not collective 2025552f7358SJed Brown 2026552f7358SJed Brown Input Parameters: 2027552f7358SJed Brown + mesh - The DMPlex 2028eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2029552f7358SJed Brown - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 2030552f7358SJed Brown integer giving the prescription for cone traversal. If it is negative, the cone is 2031552f7358SJed Brown traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 2032552f7358SJed Brown the index of the cone point on which to start. 2033552f7358SJed Brown 2034552f7358SJed Brown Output Parameter: 2035552f7358SJed Brown 2036552f7358SJed Brown Note: 2037552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 2038552f7358SJed Brown 2039552f7358SJed Brown Level: beginner 2040552f7358SJed Brown 2041552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 2042552f7358SJed Brown @*/ 2043552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 2044552f7358SJed Brown { 2045552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2046552f7358SJed Brown PetscInt pStart, pEnd; 2047552f7358SJed Brown PetscInt dof, off, c; 2048552f7358SJed Brown PetscErrorCode ierr; 2049552f7358SJed Brown 2050552f7358SJed Brown PetscFunctionBegin; 2051552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2052552f7358SJed Brown ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2053552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2054552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 2055552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 205682f516ccSBarry Smith if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 2057552f7358SJed Brown for (c = 0; c < dof; ++c) { 2058552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 2059552f7358SJed Brown 2060552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 206182f516ccSBarry Smith if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 2062552f7358SJed Brown mesh->coneOrientations[off+c] = o; 2063552f7358SJed Brown } 2064552f7358SJed Brown PetscFunctionReturn(0); 2065552f7358SJed Brown } 2066552f7358SJed Brown 20677cd05799SMatthew G. Knepley /*@ 2068eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 20697cd05799SMatthew G. Knepley 20707cd05799SMatthew G. Knepley Not collective 20717cd05799SMatthew G. Knepley 20727cd05799SMatthew G. Knepley Input Parameters: 20737cd05799SMatthew G. Knepley + mesh - The DMPlex 2074eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 20757cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 20767cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 20777cd05799SMatthew G. Knepley 20787cd05799SMatthew G. Knepley Level: beginner 20797cd05799SMatthew G. Knepley 20807cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 20817cd05799SMatthew G. Knepley @*/ 2082552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 2083552f7358SJed Brown { 2084552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2085552f7358SJed Brown PetscInt pStart, pEnd; 2086552f7358SJed Brown PetscInt dof, off; 2087552f7358SJed Brown PetscErrorCode ierr; 2088552f7358SJed Brown 2089552f7358SJed Brown PetscFunctionBegin; 2090552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2091552f7358SJed Brown ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 209282f516ccSBarry Smith if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 209382f516ccSBarry Smith if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 209477c88f5bSMatthew G Knepley ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 209577c88f5bSMatthew G Knepley ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 209677c88f5bSMatthew G Knepley if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 2097552f7358SJed Brown mesh->cones[off+conePos] = conePoint; 2098552f7358SJed Brown PetscFunctionReturn(0); 2099552f7358SJed Brown } 2100552f7358SJed Brown 21017cd05799SMatthew G. Knepley /*@ 2102eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 21037cd05799SMatthew G. Knepley 21047cd05799SMatthew G. Knepley Not collective 21057cd05799SMatthew G. Knepley 21067cd05799SMatthew G. Knepley Input Parameters: 21077cd05799SMatthew G. Knepley + mesh - The DMPlex 2108eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 21097cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 21107cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 21117cd05799SMatthew G. Knepley 21127cd05799SMatthew G. Knepley Level: beginner 21137cd05799SMatthew G. Knepley 21147cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 21157cd05799SMatthew G. Knepley @*/ 211677c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 211777c88f5bSMatthew G Knepley { 211877c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 211977c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 212077c88f5bSMatthew G Knepley PetscInt dof, off; 212177c88f5bSMatthew G Knepley PetscErrorCode ierr; 212277c88f5bSMatthew G Knepley 212377c88f5bSMatthew G Knepley PetscFunctionBegin; 212477c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 212577c88f5bSMatthew G Knepley ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 212677c88f5bSMatthew G Knepley if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 212777c88f5bSMatthew G Knepley ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 212877c88f5bSMatthew G Knepley ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 212977c88f5bSMatthew G Knepley if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 213077c88f5bSMatthew G Knepley mesh->coneOrientations[off+conePos] = coneOrientation; 213177c88f5bSMatthew G Knepley PetscFunctionReturn(0); 213277c88f5bSMatthew G Knepley } 213377c88f5bSMatthew G Knepley 2134552f7358SJed Brown /*@ 2135eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 2136552f7358SJed Brown 2137552f7358SJed Brown Not collective 2138552f7358SJed Brown 2139552f7358SJed Brown Input Parameters: 2140552f7358SJed Brown + mesh - The DMPlex 2141eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2142552f7358SJed Brown 2143552f7358SJed Brown Output Parameter: 2144552f7358SJed Brown . size - The support size for point p 2145552f7358SJed Brown 2146552f7358SJed Brown Level: beginner 2147552f7358SJed Brown 2148552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 2149552f7358SJed Brown @*/ 2150552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 2151552f7358SJed Brown { 2152552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2153552f7358SJed Brown PetscErrorCode ierr; 2154552f7358SJed Brown 2155552f7358SJed Brown PetscFunctionBegin; 2156552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2157552f7358SJed Brown PetscValidPointer(size, 3); 2158552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 2159552f7358SJed Brown PetscFunctionReturn(0); 2160552f7358SJed Brown } 2161552f7358SJed Brown 2162552f7358SJed Brown /*@ 2163eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 2164552f7358SJed Brown 2165552f7358SJed Brown Not collective 2166552f7358SJed Brown 2167552f7358SJed Brown Input Parameters: 2168552f7358SJed Brown + mesh - The DMPlex 2169eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2170552f7358SJed Brown - size - The support size for point p 2171552f7358SJed Brown 2172552f7358SJed Brown Output Parameter: 2173552f7358SJed Brown 2174552f7358SJed Brown Note: 2175552f7358SJed Brown This should be called after DMPlexSetChart(). 2176552f7358SJed Brown 2177552f7358SJed Brown Level: beginner 2178552f7358SJed Brown 2179552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 2180552f7358SJed Brown @*/ 2181552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 2182552f7358SJed Brown { 2183552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2184552f7358SJed Brown PetscErrorCode ierr; 2185552f7358SJed Brown 2186552f7358SJed Brown PetscFunctionBegin; 2187552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2188552f7358SJed Brown ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 21890d644c17SKarl Rupp 2190552f7358SJed Brown mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 2191552f7358SJed Brown PetscFunctionReturn(0); 2192552f7358SJed Brown } 2193552f7358SJed Brown 2194552f7358SJed Brown /*@C 2195eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 2196552f7358SJed Brown 2197552f7358SJed Brown Not collective 2198552f7358SJed Brown 2199552f7358SJed Brown Input Parameters: 2200552f7358SJed Brown + mesh - The DMPlex 2201eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart() 2202552f7358SJed Brown 2203552f7358SJed Brown Output Parameter: 2204552f7358SJed Brown . support - An array of points which are on the out-edges for point p 2205552f7358SJed Brown 2206552f7358SJed Brown Level: beginner 2207552f7358SJed Brown 22083813dfbdSMatthew G Knepley Fortran Notes: 22093813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 22103813dfbdSMatthew G Knepley include petsc.h90 in your code. 22113b12b3d8SVaclav Hapla You must also call DMPlexRestoreSupport() after you finish using the returned array. 2212922102d1SVaclav Hapla DMPlexRestoreSupport() is not needed/available in C. 22133813dfbdSMatthew G Knepley 2214552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2215552f7358SJed Brown @*/ 2216552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 2217552f7358SJed Brown { 2218552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2219552f7358SJed Brown PetscInt off; 2220552f7358SJed Brown PetscErrorCode ierr; 2221552f7358SJed Brown 2222552f7358SJed Brown PetscFunctionBegin; 2223552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2224552f7358SJed Brown PetscValidPointer(support, 3); 2225552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 2226552f7358SJed Brown *support = &mesh->supports[off]; 2227552f7358SJed Brown PetscFunctionReturn(0); 2228552f7358SJed Brown } 2229552f7358SJed Brown 2230552f7358SJed Brown /*@ 223192371b87SBarry Smith DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 2232552f7358SJed Brown 2233552f7358SJed Brown Not collective 2234552f7358SJed Brown 2235552f7358SJed Brown Input Parameters: 2236552f7358SJed Brown + mesh - The DMPlex 2237eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 223892371b87SBarry Smith - support - An array of points which are on the out-edges for point p 2239552f7358SJed Brown 2240552f7358SJed Brown Output Parameter: 2241552f7358SJed Brown 2242552f7358SJed Brown Note: 2243552f7358SJed Brown This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 2244552f7358SJed Brown 2245552f7358SJed Brown Level: beginner 2246552f7358SJed Brown 224792371b87SBarry Smith .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 2248552f7358SJed Brown @*/ 2249552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 2250552f7358SJed Brown { 2251552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2252552f7358SJed Brown PetscInt pStart, pEnd; 2253552f7358SJed Brown PetscInt dof, off, c; 2254552f7358SJed Brown PetscErrorCode ierr; 2255552f7358SJed Brown 2256552f7358SJed Brown PetscFunctionBegin; 2257552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2258552f7358SJed Brown ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 2259552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2260552f7358SJed Brown if (dof) PetscValidPointer(support, 3); 2261552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 226282f516ccSBarry Smith if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 2263552f7358SJed Brown for (c = 0; c < dof; ++c) { 226482f516ccSBarry Smith if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 2265552f7358SJed Brown mesh->supports[off+c] = support[c]; 2266552f7358SJed Brown } 2267552f7358SJed Brown PetscFunctionReturn(0); 2268552f7358SJed Brown } 2269552f7358SJed Brown 22707cd05799SMatthew G. Knepley /*@ 2271eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 22727cd05799SMatthew G. Knepley 22737cd05799SMatthew G. Knepley Not collective 22747cd05799SMatthew G. Knepley 22757cd05799SMatthew G. Knepley Input Parameters: 22767cd05799SMatthew G. Knepley + mesh - The DMPlex 2277eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 22787cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 22797cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 22807cd05799SMatthew G. Knepley 22817cd05799SMatthew G. Knepley Level: beginner 22827cd05799SMatthew G. Knepley 22837cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 22847cd05799SMatthew G. Knepley @*/ 2285552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 2286552f7358SJed Brown { 2287552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2288552f7358SJed Brown PetscInt pStart, pEnd; 2289552f7358SJed Brown PetscInt dof, off; 2290552f7358SJed Brown PetscErrorCode ierr; 2291552f7358SJed Brown 2292552f7358SJed Brown PetscFunctionBegin; 2293552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2294552f7358SJed Brown ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 2295552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 2296552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 229782f516ccSBarry Smith if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 229882f516ccSBarry Smith if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 229982f516ccSBarry Smith if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 2300552f7358SJed Brown mesh->supports[off+supportPos] = supportPoint; 2301552f7358SJed Brown PetscFunctionReturn(0); 2302552f7358SJed Brown } 2303552f7358SJed Brown 2304552f7358SJed Brown /*@C 2305eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 2306552f7358SJed Brown 2307552f7358SJed Brown Not collective 2308552f7358SJed Brown 2309552f7358SJed Brown Input Parameters: 2310552f7358SJed Brown + mesh - The DMPlex 2311eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2312552f7358SJed Brown . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 23130298fd71SBarry Smith - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 2314552f7358SJed Brown 2315552f7358SJed Brown Output Parameters: 2316552f7358SJed Brown + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 2317552f7358SJed Brown - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 2318552f7358SJed Brown 2319552f7358SJed Brown Note: 23200298fd71SBarry Smith If using internal storage (points is NULL on input), each call overwrites the last output. 2321552f7358SJed Brown 23223813dfbdSMatthew G Knepley Fortran Notes: 23233813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 23243813dfbdSMatthew G Knepley include petsc.h90 in your code. 23253813dfbdSMatthew G Knepley 23263813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 23273813dfbdSMatthew G Knepley 2328552f7358SJed Brown Level: beginner 2329552f7358SJed Brown 2330552f7358SJed Brown .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2331552f7358SJed Brown @*/ 2332552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 2333552f7358SJed Brown { 2334552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2335552f7358SJed Brown PetscInt *closure, *fifo; 23360298fd71SBarry Smith const PetscInt *tmp = NULL, *tmpO = NULL; 2337552f7358SJed Brown PetscInt tmpSize, t; 2338552f7358SJed Brown PetscInt depth = 0, maxSize; 2339552f7358SJed Brown PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 2340552f7358SJed Brown PetscErrorCode ierr; 2341552f7358SJed Brown 2342552f7358SJed Brown PetscFunctionBegin; 2343552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2344552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2345552f7358SJed Brown /* This is only 1-level */ 2346552f7358SJed Brown if (useCone) { 2347552f7358SJed Brown ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 2348552f7358SJed Brown ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 2349552f7358SJed Brown ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 2350552f7358SJed Brown } else { 2351552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 2352552f7358SJed Brown ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 2353552f7358SJed Brown } 2354bfbcdd7aSMatthew G. Knepley if (depth == 1) { 2355bfbcdd7aSMatthew G. Knepley if (*points) { 2356bfbcdd7aSMatthew G. Knepley closure = *points; 2357bfbcdd7aSMatthew G. Knepley } else { 2358bfbcdd7aSMatthew G. Knepley maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 235969291d52SBarry Smith ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 2360bfbcdd7aSMatthew G. Knepley } 2361bfbcdd7aSMatthew G. Knepley closure[0] = p; closure[1] = 0; 2362bfbcdd7aSMatthew G. Knepley for (t = 0; t < tmpSize; ++t, closureSize += 2) { 2363bfbcdd7aSMatthew G. Knepley closure[closureSize] = tmp[t]; 2364bfbcdd7aSMatthew G. Knepley closure[closureSize+1] = tmpO ? tmpO[t] : 0; 2365bfbcdd7aSMatthew G. Knepley } 2366bfbcdd7aSMatthew G. Knepley if (numPoints) *numPoints = closureSize/2; 2367bfbcdd7aSMatthew G. Knepley if (points) *points = closure; 2368bfbcdd7aSMatthew G. Knepley PetscFunctionReturn(0); 2369bfbcdd7aSMatthew G. Knepley } 237024c766afSToby Isaac { 237124c766afSToby Isaac PetscInt c, coneSeries, s,supportSeries; 237224c766afSToby Isaac 237324c766afSToby Isaac c = mesh->maxConeSize; 237424c766afSToby Isaac coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 237524c766afSToby Isaac s = mesh->maxSupportSize; 237624c766afSToby Isaac supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 237724c766afSToby Isaac maxSize = 2*PetscMax(coneSeries,supportSeries); 237824c766afSToby Isaac } 237969291d52SBarry Smith ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2380bfbcdd7aSMatthew G. Knepley if (*points) { 2381bfbcdd7aSMatthew G. Knepley closure = *points; 2382bfbcdd7aSMatthew G. Knepley } else { 238369291d52SBarry Smith ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 2384bfbcdd7aSMatthew G. Knepley } 2385bfbcdd7aSMatthew G. Knepley closure[0] = p; closure[1] = 0; 2386552f7358SJed Brown for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 2387552f7358SJed Brown const PetscInt cp = tmp[t]; 2388552f7358SJed Brown const PetscInt co = tmpO ? tmpO[t] : 0; 2389552f7358SJed Brown 2390552f7358SJed Brown closure[closureSize] = cp; 2391552f7358SJed Brown closure[closureSize+1] = co; 2392552f7358SJed Brown fifo[fifoSize] = cp; 2393552f7358SJed Brown fifo[fifoSize+1] = co; 2394552f7358SJed Brown } 2395bfbcdd7aSMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 2396552f7358SJed Brown while (fifoSize - fifoStart) { 2397552f7358SJed Brown const PetscInt q = fifo[fifoStart]; 2398552f7358SJed Brown const PetscInt o = fifo[fifoStart+1]; 2399552f7358SJed Brown const PetscInt rev = o >= 0 ? 0 : 1; 2400552f7358SJed Brown const PetscInt off = rev ? -(o+1) : o; 2401552f7358SJed Brown 2402552f7358SJed Brown if (useCone) { 2403552f7358SJed Brown ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 2404552f7358SJed Brown ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 2405552f7358SJed Brown ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 2406552f7358SJed Brown } else { 2407552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 2408552f7358SJed Brown ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 24090298fd71SBarry Smith tmpO = NULL; 2410552f7358SJed Brown } 2411552f7358SJed Brown for (t = 0; t < tmpSize; ++t) { 2412552f7358SJed Brown const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 2413552f7358SJed Brown const PetscInt cp = tmp[i]; 24142e1b13c2SMatthew G. Knepley /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 24152e1b13c2SMatthew G. Knepley /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 24162e1b13c2SMatthew G. Knepley const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 24172e1b13c2SMatthew G. Knepley PetscInt co = tmpO ? tmpO[i] : 0; 2418552f7358SJed Brown PetscInt c; 2419552f7358SJed Brown 24202e1b13c2SMatthew G. Knepley if (rev) { 24212e1b13c2SMatthew G. Knepley PetscInt childSize, coff; 24222e1b13c2SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 24232e1b13c2SMatthew G. Knepley coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 24242e1b13c2SMatthew G. Knepley co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 24252e1b13c2SMatthew G. Knepley } 2426552f7358SJed Brown /* Check for duplicate */ 2427552f7358SJed Brown for (c = 0; c < closureSize; c += 2) { 2428552f7358SJed Brown if (closure[c] == cp) break; 2429552f7358SJed Brown } 2430552f7358SJed Brown if (c == closureSize) { 2431552f7358SJed Brown closure[closureSize] = cp; 2432552f7358SJed Brown closure[closureSize+1] = co; 2433552f7358SJed Brown fifo[fifoSize] = cp; 2434552f7358SJed Brown fifo[fifoSize+1] = co; 2435552f7358SJed Brown closureSize += 2; 2436552f7358SJed Brown fifoSize += 2; 2437552f7358SJed Brown } 2438552f7358SJed Brown } 2439552f7358SJed Brown fifoStart += 2; 2440552f7358SJed Brown } 2441552f7358SJed Brown if (numPoints) *numPoints = closureSize/2; 2442552f7358SJed Brown if (points) *points = closure; 244369291d52SBarry Smith ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 2444552f7358SJed Brown PetscFunctionReturn(0); 2445552f7358SJed Brown } 2446552f7358SJed Brown 24479bf0dad6SMatthew G. Knepley /*@C 2448eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure_Internal - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG with a specified initial orientation 24499bf0dad6SMatthew G. Knepley 24509bf0dad6SMatthew G. Knepley Not collective 24519bf0dad6SMatthew G. Knepley 24529bf0dad6SMatthew G. Knepley Input Parameters: 24539bf0dad6SMatthew G. Knepley + mesh - The DMPlex 2454eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 24559bf0dad6SMatthew G. Knepley . orientation - The orientation of the point 24569bf0dad6SMatthew G. Knepley . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 24579bf0dad6SMatthew G. Knepley - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 24589bf0dad6SMatthew G. Knepley 24599bf0dad6SMatthew G. Knepley Output Parameters: 24609bf0dad6SMatthew G. Knepley + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 24619bf0dad6SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 24629bf0dad6SMatthew G. Knepley 24639bf0dad6SMatthew G. Knepley Note: 24649bf0dad6SMatthew G. Knepley If using internal storage (points is NULL on input), each call overwrites the last output. 24659bf0dad6SMatthew G. Knepley 24669bf0dad6SMatthew G. Knepley Fortran Notes: 24679bf0dad6SMatthew G. Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 24689bf0dad6SMatthew G. Knepley include petsc.h90 in your code. 24699bf0dad6SMatthew G. Knepley 24709bf0dad6SMatthew G. Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 24719bf0dad6SMatthew G. Knepley 24729bf0dad6SMatthew G. Knepley Level: beginner 24739bf0dad6SMatthew G. Knepley 24749bf0dad6SMatthew G. Knepley .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 24759bf0dad6SMatthew G. Knepley @*/ 24769bf0dad6SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 24779bf0dad6SMatthew G. Knepley { 24789bf0dad6SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 24799bf0dad6SMatthew G. Knepley PetscInt *closure, *fifo; 24809bf0dad6SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 24819bf0dad6SMatthew G. Knepley PetscInt tmpSize, t; 24829bf0dad6SMatthew G. Knepley PetscInt depth = 0, maxSize; 24839bf0dad6SMatthew G. Knepley PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 24849bf0dad6SMatthew G. Knepley PetscErrorCode ierr; 24859bf0dad6SMatthew G. Knepley 24869bf0dad6SMatthew G. Knepley PetscFunctionBegin; 24879bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24889bf0dad6SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 24899bf0dad6SMatthew G. Knepley /* This is only 1-level */ 24909bf0dad6SMatthew G. Knepley if (useCone) { 24919bf0dad6SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 24929bf0dad6SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 24939bf0dad6SMatthew G. Knepley ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 24949bf0dad6SMatthew G. Knepley } else { 24959bf0dad6SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 24969bf0dad6SMatthew G. Knepley ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 24979bf0dad6SMatthew G. Knepley } 24989bf0dad6SMatthew G. Knepley if (depth == 1) { 24999bf0dad6SMatthew G. Knepley if (*points) { 25009bf0dad6SMatthew G. Knepley closure = *points; 25019bf0dad6SMatthew G. Knepley } else { 25029bf0dad6SMatthew G. Knepley maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 250369291d52SBarry Smith ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 25049bf0dad6SMatthew G. Knepley } 25059bf0dad6SMatthew G. Knepley closure[0] = p; closure[1] = ornt; 25069bf0dad6SMatthew G. Knepley for (t = 0; t < tmpSize; ++t, closureSize += 2) { 25079bf0dad6SMatthew G. Knepley const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 25089bf0dad6SMatthew G. Knepley closure[closureSize] = tmp[i]; 25099bf0dad6SMatthew G. Knepley closure[closureSize+1] = tmpO ? tmpO[i] : 0; 25109bf0dad6SMatthew G. Knepley } 25119bf0dad6SMatthew G. Knepley if (numPoints) *numPoints = closureSize/2; 25129bf0dad6SMatthew G. Knepley if (points) *points = closure; 25139bf0dad6SMatthew G. Knepley PetscFunctionReturn(0); 25149bf0dad6SMatthew G. Knepley } 251524c766afSToby Isaac { 251624c766afSToby Isaac PetscInt c, coneSeries, s,supportSeries; 251724c766afSToby Isaac 251824c766afSToby Isaac c = mesh->maxConeSize; 251924c766afSToby Isaac coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 252024c766afSToby Isaac s = mesh->maxSupportSize; 252124c766afSToby Isaac supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 252224c766afSToby Isaac maxSize = 2*PetscMax(coneSeries,supportSeries); 252324c766afSToby Isaac } 252469291d52SBarry Smith ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 25259bf0dad6SMatthew G. Knepley if (*points) { 25269bf0dad6SMatthew G. Knepley closure = *points; 25279bf0dad6SMatthew G. Knepley } else { 252869291d52SBarry Smith ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr); 25299bf0dad6SMatthew G. Knepley } 25309bf0dad6SMatthew G. Knepley closure[0] = p; closure[1] = ornt; 25319bf0dad6SMatthew G. Knepley for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 25329bf0dad6SMatthew G. Knepley const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 25339bf0dad6SMatthew G. Knepley const PetscInt cp = tmp[i]; 25349bf0dad6SMatthew G. Knepley PetscInt co = tmpO ? tmpO[i] : 0; 25359bf0dad6SMatthew G. Knepley 25369bf0dad6SMatthew G. Knepley if (ornt < 0) { 25379bf0dad6SMatthew G. Knepley PetscInt childSize, coff; 25389bf0dad6SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 253986b63641SMatthew G. Knepley coff = co < 0 ? -(tmpO[i]+1) : tmpO[i]; 25409bf0dad6SMatthew G. Knepley co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 25419bf0dad6SMatthew G. Knepley } 25429bf0dad6SMatthew G. Knepley closure[closureSize] = cp; 25439bf0dad6SMatthew G. Knepley closure[closureSize+1] = co; 25449bf0dad6SMatthew G. Knepley fifo[fifoSize] = cp; 25459bf0dad6SMatthew G. Knepley fifo[fifoSize+1] = co; 25469bf0dad6SMatthew G. Knepley } 25479bf0dad6SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 25489bf0dad6SMatthew G. Knepley while (fifoSize - fifoStart) { 25499bf0dad6SMatthew G. Knepley const PetscInt q = fifo[fifoStart]; 25509bf0dad6SMatthew G. Knepley const PetscInt o = fifo[fifoStart+1]; 25519bf0dad6SMatthew G. Knepley const PetscInt rev = o >= 0 ? 0 : 1; 25529bf0dad6SMatthew G. Knepley const PetscInt off = rev ? -(o+1) : o; 25539bf0dad6SMatthew G. Knepley 25549bf0dad6SMatthew G. Knepley if (useCone) { 25559bf0dad6SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 25569bf0dad6SMatthew G. Knepley ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 25579bf0dad6SMatthew G. Knepley ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 25589bf0dad6SMatthew G. Knepley } else { 25599bf0dad6SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 25609bf0dad6SMatthew G. Knepley ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 25619bf0dad6SMatthew G. Knepley tmpO = NULL; 25629bf0dad6SMatthew G. Knepley } 25639bf0dad6SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 25649bf0dad6SMatthew G. Knepley const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 25659bf0dad6SMatthew G. Knepley const PetscInt cp = tmp[i]; 25669bf0dad6SMatthew G. Knepley /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 25679bf0dad6SMatthew G. Knepley /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 25689bf0dad6SMatthew G. Knepley const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 25699bf0dad6SMatthew G. Knepley PetscInt co = tmpO ? tmpO[i] : 0; 25709bf0dad6SMatthew G. Knepley PetscInt c; 25719bf0dad6SMatthew G. Knepley 25729bf0dad6SMatthew G. Knepley if (rev) { 25739bf0dad6SMatthew G. Knepley PetscInt childSize, coff; 25749bf0dad6SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 25759bf0dad6SMatthew G. Knepley coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 25769bf0dad6SMatthew G. Knepley co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 25779bf0dad6SMatthew G. Knepley } 25789bf0dad6SMatthew G. Knepley /* Check for duplicate */ 25799bf0dad6SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 25809bf0dad6SMatthew G. Knepley if (closure[c] == cp) break; 25819bf0dad6SMatthew G. Knepley } 25829bf0dad6SMatthew G. Knepley if (c == closureSize) { 25839bf0dad6SMatthew G. Knepley closure[closureSize] = cp; 25849bf0dad6SMatthew G. Knepley closure[closureSize+1] = co; 25859bf0dad6SMatthew G. Knepley fifo[fifoSize] = cp; 25869bf0dad6SMatthew G. Knepley fifo[fifoSize+1] = co; 25879bf0dad6SMatthew G. Knepley closureSize += 2; 25889bf0dad6SMatthew G. Knepley fifoSize += 2; 25899bf0dad6SMatthew G. Knepley } 25909bf0dad6SMatthew G. Knepley } 25919bf0dad6SMatthew G. Knepley fifoStart += 2; 25929bf0dad6SMatthew G. Knepley } 25939bf0dad6SMatthew G. Knepley if (numPoints) *numPoints = closureSize/2; 25949bf0dad6SMatthew G. Knepley if (points) *points = closure; 259569291d52SBarry Smith ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr); 25969bf0dad6SMatthew G. Knepley PetscFunctionReturn(0); 25979bf0dad6SMatthew G. Knepley } 25989bf0dad6SMatthew G. Knepley 2599552f7358SJed Brown /*@C 2600eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 2601552f7358SJed Brown 2602552f7358SJed Brown Not collective 2603552f7358SJed Brown 2604552f7358SJed Brown Input Parameters: 2605552f7358SJed Brown + mesh - The DMPlex 2606eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart() 2607552f7358SJed Brown . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 2608e5c84f05SJed Brown . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit 2609e5c84f05SJed Brown - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit 2610552f7358SJed Brown 2611552f7358SJed Brown Note: 26120298fd71SBarry Smith If not using internal storage (points is not NULL on input), this call is unnecessary 2613552f7358SJed Brown 26143813dfbdSMatthew G Knepley Fortran Notes: 26153813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 26163813dfbdSMatthew G Knepley include petsc.h90 in your code. 26173813dfbdSMatthew G Knepley 26183813dfbdSMatthew G Knepley The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 26193813dfbdSMatthew G Knepley 2620552f7358SJed Brown Level: beginner 2621552f7358SJed Brown 2622552f7358SJed Brown .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 2623552f7358SJed Brown @*/ 2624552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 2625552f7358SJed Brown { 2626552f7358SJed Brown PetscErrorCode ierr; 2627552f7358SJed Brown 2628552f7358SJed Brown PetscFunctionBegin; 2629552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2630e5c84f05SJed Brown if (numPoints) PetscValidIntPointer(numPoints,4); 2631e5c84f05SJed Brown if (points) PetscValidPointer(points,5); 263269291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr); 26334ff43b2cSJed Brown if (numPoints) *numPoints = 0; 2634552f7358SJed Brown PetscFunctionReturn(0); 2635552f7358SJed Brown } 2636552f7358SJed Brown 2637552f7358SJed Brown /*@ 2638eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 2639552f7358SJed Brown 2640552f7358SJed Brown Not collective 2641552f7358SJed Brown 2642552f7358SJed Brown Input Parameter: 2643552f7358SJed Brown . mesh - The DMPlex 2644552f7358SJed Brown 2645552f7358SJed Brown Output Parameters: 2646552f7358SJed Brown + maxConeSize - The maximum number of in-edges 2647552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 2648552f7358SJed Brown 2649552f7358SJed Brown Level: beginner 2650552f7358SJed Brown 2651552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 2652552f7358SJed Brown @*/ 2653552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 2654552f7358SJed Brown { 2655552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2656552f7358SJed Brown 2657552f7358SJed Brown PetscFunctionBegin; 2658552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2659552f7358SJed Brown if (maxConeSize) *maxConeSize = mesh->maxConeSize; 2660552f7358SJed Brown if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 2661552f7358SJed Brown PetscFunctionReturn(0); 2662552f7358SJed Brown } 2663552f7358SJed Brown 2664552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm) 2665552f7358SJed Brown { 2666552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2667552f7358SJed Brown PetscInt size; 2668552f7358SJed Brown PetscErrorCode ierr; 2669552f7358SJed Brown 2670552f7358SJed Brown PetscFunctionBegin; 2671552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2672552f7358SJed Brown ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 2673552f7358SJed Brown ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 26741795a4d1SJed Brown ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 26751795a4d1SJed Brown ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 2676552f7358SJed Brown if (mesh->maxSupportSize) { 2677552f7358SJed Brown ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 2678552f7358SJed Brown ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 26791795a4d1SJed Brown ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 2680552f7358SJed Brown } 2681552f7358SJed Brown PetscFunctionReturn(0); 2682552f7358SJed Brown } 2683552f7358SJed Brown 2684276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 2685552f7358SJed Brown { 2686552f7358SJed Brown PetscErrorCode ierr; 2687552f7358SJed Brown 2688552f7358SJed Brown PetscFunctionBegin; 26894d9407bcSMatthew G. Knepley if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 2690792b654fSMatthew G. Knepley ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 2691c2939958SSatish Balay if (subdm) {(*subdm)->useNatural = dm->useNatural;} 2692736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 2693f94b4a02SBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 2694f94b4a02SBlaise Bourdin PetscSection section, sectionSeq; 2695f94b4a02SBlaise Bourdin 26963dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 26973dcd263cSBlaise Bourdin ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr); 2698c3b366b1Sprj- ierr = DMGetLocalSection((*subdm), §ion);CHKERRQ(ierr); 2699f94b4a02SBlaise Bourdin ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 2700f94b4a02SBlaise Bourdin ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), §ionSeq);CHKERRQ(ierr); 2701f94b4a02SBlaise Bourdin ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 2702f94b4a02SBlaise Bourdin 2703f94b4a02SBlaise Bourdin ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 2704c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 2705f94b4a02SBlaise Bourdin ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 2706f94b4a02SBlaise Bourdin ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 2707f94b4a02SBlaise Bourdin } 2708552f7358SJed Brown PetscFunctionReturn(0); 2709552f7358SJed Brown } 2710552f7358SJed Brown 27112adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 27122adcc780SMatthew G. Knepley { 27132adcc780SMatthew G. Knepley PetscErrorCode ierr; 27143dcd263cSBlaise Bourdin PetscInt i = 0; 27152adcc780SMatthew G. Knepley 27162adcc780SMatthew G. Knepley PetscFunctionBegin; 2717435bcee1SStefano Zampini ierr = DMClone(dms[0], superdm);CHKERRQ(ierr); 2718792b654fSMatthew G. Knepley ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr); 2719c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 27203dcd263cSBlaise Bourdin for (i = 0; i < len; i++){ 27213dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 27223dcd263cSBlaise Bourdin PetscSF sfMigrationInv,sfNatural; 27233dcd263cSBlaise Bourdin PetscSection section, sectionSeq; 27243dcd263cSBlaise Bourdin 27253dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 27263dcd263cSBlaise Bourdin ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr); 2727c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 272892fd8e1eSJed Brown ierr = DMGetLocalSection((*superdm), §ion);CHKERRQ(ierr); 27293dcd263cSBlaise Bourdin ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr); 27303dcd263cSBlaise Bourdin ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), §ionSeq);CHKERRQ(ierr); 27313dcd263cSBlaise Bourdin ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr); 27323dcd263cSBlaise Bourdin 27333dcd263cSBlaise Bourdin ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr); 2734c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 27353dcd263cSBlaise Bourdin ierr = PetscSectionDestroy(§ionSeq);CHKERRQ(ierr); 27363dcd263cSBlaise Bourdin ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr); 27373dcd263cSBlaise Bourdin break; 27383dcd263cSBlaise Bourdin } 27393dcd263cSBlaise Bourdin } 27402adcc780SMatthew G. Knepley PetscFunctionReturn(0); 27412adcc780SMatthew G. Knepley } 27422adcc780SMatthew G. Knepley 2743552f7358SJed Brown /*@ 2744eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 2745552f7358SJed Brown 2746552f7358SJed Brown Not collective 2747552f7358SJed Brown 2748552f7358SJed Brown Input Parameter: 2749552f7358SJed Brown . mesh - The DMPlex 2750552f7358SJed Brown 2751552f7358SJed Brown Output Parameter: 2752552f7358SJed Brown 2753552f7358SJed Brown Note: 2754552f7358SJed Brown This should be called after all calls to DMPlexSetCone() 2755552f7358SJed Brown 2756552f7358SJed Brown Level: beginner 2757552f7358SJed Brown 2758552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 2759552f7358SJed Brown @*/ 2760552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm) 2761552f7358SJed Brown { 2762552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 2763552f7358SJed Brown PetscInt *offsets; 2764552f7358SJed Brown PetscInt supportSize; 2765552f7358SJed Brown PetscInt pStart, pEnd, p; 2766552f7358SJed Brown PetscErrorCode ierr; 2767552f7358SJed Brown 2768552f7358SJed Brown PetscFunctionBegin; 2769552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 277082f516ccSBarry Smith if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 277130b0ce1bSStefano Zampini ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 2772552f7358SJed Brown /* Calculate support sizes */ 2773552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2774552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 2775552f7358SJed Brown PetscInt dof, off, c; 2776552f7358SJed Brown 2777552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2778552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2779552f7358SJed Brown for (c = off; c < off+dof; ++c) { 2780552f7358SJed Brown ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 2781552f7358SJed Brown } 2782552f7358SJed Brown } 2783552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 2784552f7358SJed Brown PetscInt dof; 2785552f7358SJed Brown 2786552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 27870d644c17SKarl Rupp 2788552f7358SJed Brown mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 2789552f7358SJed Brown } 2790552f7358SJed Brown ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 2791552f7358SJed Brown /* Calculate supports */ 2792552f7358SJed Brown ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 27931795a4d1SJed Brown ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 27941795a4d1SJed Brown ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 2795552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 2796552f7358SJed Brown PetscInt dof, off, c; 2797552f7358SJed Brown 2798552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 2799552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 2800552f7358SJed Brown for (c = off; c < off+dof; ++c) { 2801552f7358SJed Brown const PetscInt q = mesh->cones[c]; 2802552f7358SJed Brown PetscInt offS; 2803552f7358SJed Brown 2804552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 28050d644c17SKarl Rupp 2806552f7358SJed Brown mesh->supports[offS+offsets[q]] = p; 2807552f7358SJed Brown ++offsets[q]; 2808552f7358SJed Brown } 2809552f7358SJed Brown } 2810552f7358SJed Brown ierr = PetscFree(offsets);CHKERRQ(ierr); 281130b0ce1bSStefano Zampini ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr); 2812552f7358SJed Brown PetscFunctionReturn(0); 2813552f7358SJed Brown } 2814552f7358SJed Brown 2815277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 2816277ea44aSLisandro Dalcin { 2817277ea44aSLisandro Dalcin IS stratumIS; 2818277ea44aSLisandro Dalcin PetscErrorCode ierr; 2819277ea44aSLisandro Dalcin 2820277ea44aSLisandro Dalcin PetscFunctionBegin; 2821277ea44aSLisandro Dalcin if (pStart >= pEnd) PetscFunctionReturn(0); 282276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 2823277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 2824277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 2825277ea44aSLisandro Dalcin ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr); 2826277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 2827277ea44aSLisandro Dalcin ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 2828277ea44aSLisandro Dalcin if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;} 2829277ea44aSLisandro Dalcin } 2830277ea44aSLisandro Dalcin if (overlap) SETERRQ6(PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %D range [%D,%D) overlaps with depth %D range [%D,%D)", depth, pStart, pEnd, level, qStart, qEnd); 2831277ea44aSLisandro Dalcin } 2832277ea44aSLisandro Dalcin ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr); 2833277ea44aSLisandro Dalcin ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr); 2834277ea44aSLisandro Dalcin ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 2835277ea44aSLisandro Dalcin PetscFunctionReturn(0); 2836277ea44aSLisandro Dalcin } 2837277ea44aSLisandro Dalcin 2838552f7358SJed Brown /*@ 2839a8d69d7bSBarry Smith DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 28406dd80730SBarry Smith can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2841552f7358SJed Brown same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2842552f7358SJed Brown the DAG. 2843552f7358SJed Brown 2844bf4602e4SToby Isaac Collective on dm 2845552f7358SJed Brown 2846552f7358SJed Brown Input Parameter: 2847552f7358SJed Brown . mesh - The DMPlex 2848552f7358SJed Brown 2849552f7358SJed Brown Output Parameter: 2850552f7358SJed Brown 2851552f7358SJed Brown Notes: 2852b1bb481bSMatthew Knepley Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 2853b1bb481bSMatthew Knepley meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 2854b1bb481bSMatthew Knepley until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 2855c58f1c22SToby Isaac manually via DMGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 2856150b719bSJed Brown via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 2857552f7358SJed Brown 2858b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 2859b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 2860b1bb481bSMatthew Knepley we had a mesh consisting of one triangle (c0) and three vertices (v0, v1, v2), and only one edge is on the boundary so we choose 2861b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 2862b1bb481bSMatthew Knepley $ cone(c0) = {e0, v2} 2863b1bb481bSMatthew Knepley $ cone(e0) = {v0, v1} 2864b1bb481bSMatthew Knepley If DMPlexStratify() is run on this mesh, it will give depths 2865b1bb481bSMatthew Knepley $ depth 0 = {v0, v1, v2} 2866b1bb481bSMatthew Knepley $ depth 1 = {e0, c0} 2867b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 2868b1bb481bSMatthew Knepley 2869150b719bSJed Brown DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 2870552f7358SJed Brown 2871552f7358SJed Brown Level: beginner 2872552f7358SJed Brown 2873ba2698f1SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes() 2874552f7358SJed Brown @*/ 2875552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm) 2876552f7358SJed Brown { 2877df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 2878aa50250dSMatthew G. Knepley DMLabel label; 2879552f7358SJed Brown PetscInt pStart, pEnd, p; 2880552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 2881552f7358SJed Brown PetscErrorCode ierr; 2882552f7358SJed Brown 2883552f7358SJed Brown PetscFunctionBegin; 2884552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2885552f7358SJed Brown ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2886277ea44aSLisandro Dalcin 2887277ea44aSLisandro Dalcin /* Create depth label */ 2888aa50250dSMatthew G. Knepley ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2889c58f1c22SToby Isaac ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr); 2890aa50250dSMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2891277ea44aSLisandro Dalcin 2892277ea44aSLisandro Dalcin { 2893552f7358SJed Brown /* Initialize roots and count leaves */ 2894277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 2895277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 2896552f7358SJed Brown PetscInt coneSize, supportSize; 2897552f7358SJed Brown 2898277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 2899552f7358SJed Brown ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2900552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2901552f7358SJed Brown if (!coneSize && supportSize) { 2902277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 2903277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 2904552f7358SJed Brown ++numRoots; 2905552f7358SJed Brown } else if (!supportSize && coneSize) { 2906552f7358SJed Brown ++numLeaves; 2907552f7358SJed Brown } else if (!supportSize && !coneSize) { 2908552f7358SJed Brown /* Isolated points */ 2909277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 2910277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 2911552f7358SJed Brown } 2912552f7358SJed Brown } 2913277ea44aSLisandro Dalcin ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr); 2914277ea44aSLisandro Dalcin } 2915277ea44aSLisandro Dalcin 2916552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 2917277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 2918277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 2919552f7358SJed Brown PetscInt coneSize, supportSize; 2920552f7358SJed Brown 2921277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 2922552f7358SJed Brown ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2923552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2924552f7358SJed Brown if (!supportSize && coneSize) { 2925277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 2926277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 2927552f7358SJed Brown } 2928552f7358SJed Brown } 2929277ea44aSLisandro Dalcin ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr); 2930552f7358SJed Brown } else { 2931277ea44aSLisandro Dalcin PetscInt level = 0; 2932277ea44aSLisandro Dalcin PetscInt qStart, qEnd, q; 2933552f7358SJed Brown 2934277ea44aSLisandro Dalcin ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 2935277ea44aSLisandro Dalcin while (qEnd > qStart) { 2936277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 2937277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 293874ef644bSMatthew G. Knepley 2939277ea44aSLisandro Dalcin for (q = qStart; q < qEnd; ++q) { 294074ef644bSMatthew G. Knepley const PetscInt *support; 294174ef644bSMatthew G. Knepley PetscInt supportSize, s; 294274ef644bSMatthew G. Knepley 2943277ea44aSLisandro Dalcin ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr); 2944277ea44aSLisandro Dalcin ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr); 294574ef644bSMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 2946277ea44aSLisandro Dalcin sMin = PetscMin(support[s], sMin); 2947277ea44aSLisandro Dalcin sMax = PetscMax(support[s], sMax); 2948552f7358SJed Brown } 2949552f7358SJed Brown } 2950277ea44aSLisandro Dalcin ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr); 2951277ea44aSLisandro Dalcin ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr); 2952277ea44aSLisandro Dalcin ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr); 295374ef644bSMatthew G. Knepley } 295474ef644bSMatthew G. Knepley } 2955bf4602e4SToby Isaac { /* just in case there is an empty process */ 2956bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 2957bf4602e4SToby Isaac 2958bf4602e4SToby Isaac ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 29596d1e82d3SBarry Smith ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 2960bf4602e4SToby Isaac for (v = numValues; v < maxValues; v++) { 2961367003a6SStefano Zampini ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr); 2962bf4602e4SToby Isaac } 2963bf4602e4SToby Isaac } 2964d67d17b1SMatthew G. Knepley ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr); 2965552f7358SJed Brown ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2966552f7358SJed Brown PetscFunctionReturn(0); 2967552f7358SJed Brown } 2968552f7358SJed Brown 2969412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 2970ba2698f1SMatthew G. Knepley { 2971412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 2972412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 2973ba2698f1SMatthew G. Knepley PetscErrorCode ierr; 2974ba2698f1SMatthew G. Knepley 2975412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 2976ba2698f1SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2977ba2698f1SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2978ba2698f1SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2979ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 2980ba2698f1SMatthew G. Knepley if (depth <= 1) { 2981ba2698f1SMatthew G. Knepley switch (pdepth) { 2982ba2698f1SMatthew G. Knepley case 0: ct = DM_POLYTOPE_POINT;break; 2983ba2698f1SMatthew G. Knepley case 1: 2984ba2698f1SMatthew G. Knepley switch (coneSize) { 2985ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 2986ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 2987ba2698f1SMatthew G. Knepley case 4: 2988ba2698f1SMatthew G. Knepley switch (dim) { 2989ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_QUADRILATERAL;break; 2990ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TETRAHEDRON;break; 2991ba2698f1SMatthew G. Knepley default: break; 2992ba2698f1SMatthew G. Knepley } 2993ba2698f1SMatthew G. Knepley break; 2994ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 2995ba2698f1SMatthew G. Knepley case 8: ct = DM_POLYTOPE_HEXAHEDRON;break; 2996ba2698f1SMatthew G. Knepley default: break; 2997ba2698f1SMatthew G. Knepley } 2998ba2698f1SMatthew G. Knepley } 2999ba2698f1SMatthew G. Knepley } else { 3000ba2698f1SMatthew G. Knepley if (pdepth == 0) { 3001ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 3002ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 3003ba2698f1SMatthew G. Knepley switch (dim) { 3004ba2698f1SMatthew G. Knepley case 1: 3005ba2698f1SMatthew G. Knepley switch (coneSize) { 3006ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 3007ba2698f1SMatthew G. Knepley default: break; 3008ba2698f1SMatthew G. Knepley } 3009ba2698f1SMatthew G. Knepley break; 3010ba2698f1SMatthew G. Knepley case 2: 3011ba2698f1SMatthew G. Knepley switch (coneSize) { 3012ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3013ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3014ba2698f1SMatthew G. Knepley default: break; 3015ba2698f1SMatthew G. Knepley } 3016ba2698f1SMatthew G. Knepley break; 3017ba2698f1SMatthew G. Knepley case 3: 3018ba2698f1SMatthew G. Knepley switch (coneSize) { 3019ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_TETRAHEDRON;break; 3020ba2698f1SMatthew G. Knepley case 5: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 3021ba2698f1SMatthew G. Knepley case 6: ct = DM_POLYTOPE_HEXAHEDRON;break; 3022ba2698f1SMatthew G. Knepley default: break; 3023ba2698f1SMatthew G. Knepley } 3024ba2698f1SMatthew G. Knepley break; 3025ba2698f1SMatthew G. Knepley default: break; 3026ba2698f1SMatthew G. Knepley } 3027ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 3028ba2698f1SMatthew G. Knepley switch (coneSize) { 3029ba2698f1SMatthew G. Knepley case 2: ct = DM_POLYTOPE_SEGMENT;break; 3030ba2698f1SMatthew G. Knepley case 3: ct = DM_POLYTOPE_TRIANGLE;break; 3031ba2698f1SMatthew G. Knepley case 4: ct = DM_POLYTOPE_QUADRILATERAL;break; 3032ba2698f1SMatthew G. Knepley default: break; 3033ba2698f1SMatthew G. Knepley } 3034ba2698f1SMatthew G. Knepley } 3035ba2698f1SMatthew G. Knepley } 3036412e9a14SMatthew G. Knepley *pt = ct; 3037412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 3038ba2698f1SMatthew G. Knepley } 3039412e9a14SMatthew G. Knepley 3040412e9a14SMatthew G. Knepley /*@ 3041412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 3042412e9a14SMatthew G. Knepley 3043412e9a14SMatthew G. Knepley Collective on dm 3044412e9a14SMatthew G. Knepley 3045412e9a14SMatthew G. Knepley Input Parameter: 3046412e9a14SMatthew G. Knepley . mesh - The DMPlex 3047412e9a14SMatthew G. Knepley 3048412e9a14SMatthew G. Knepley DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify() 3049412e9a14SMatthew G. Knepley 3050412e9a14SMatthew G. Knepley Level: developer 3051412e9a14SMatthew G. Knepley 3052412e9a14SMatthew G. Knepley Note: This function is normally called automatically by Plex when a cell type is requested. It creates an 3053412e9a14SMatthew G. Knepley internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable 3054412e9a14SMatthew G. Knepley automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype"). 3055412e9a14SMatthew G. Knepley 3056412e9a14SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel() 3057412e9a14SMatthew G. Knepley @*/ 3058412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm) 3059412e9a14SMatthew G. Knepley { 3060412e9a14SMatthew G. Knepley DM_Plex *mesh; 3061412e9a14SMatthew G. Knepley DMLabel ctLabel; 3062412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 3063412e9a14SMatthew G. Knepley PetscErrorCode ierr; 3064412e9a14SMatthew G. Knepley 3065412e9a14SMatthew G. Knepley PetscFunctionBegin; 3066412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3067412e9a14SMatthew G. Knepley mesh = (DM_Plex *) dm->data; 3068412e9a14SMatthew G. Knepley ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 3069412e9a14SMatthew G. Knepley ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 3070412e9a14SMatthew G. Knepley ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3071412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3072412e9a14SMatthew G. Knepley DMPolytopeType ct; 3073412e9a14SMatthew G. Knepley PetscInt pdepth; 3074412e9a14SMatthew G. Knepley 3075412e9a14SMatthew G. Knepley ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr); 3076412e9a14SMatthew G. Knepley ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr); 3077412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p); 3078412e9a14SMatthew G. Knepley ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr); 3079412e9a14SMatthew G. Knepley } 3080412e9a14SMatthew G. Knepley ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr); 3081412e9a14SMatthew G. Knepley ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr); 3082ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 3083ba2698f1SMatthew G. Knepley } 3084ba2698f1SMatthew G. Knepley 3085552f7358SJed Brown /*@C 3086552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 3087552f7358SJed Brown 3088552f7358SJed Brown Not Collective 3089552f7358SJed Brown 3090552f7358SJed Brown Input Parameters: 3091552f7358SJed Brown + dm - The DMPlex object 3092552f7358SJed Brown . numPoints - The number of input points for the join 3093552f7358SJed Brown - points - The input points 3094552f7358SJed Brown 3095552f7358SJed Brown Output Parameters: 3096552f7358SJed Brown + numCoveredPoints - The number of points in the join 3097552f7358SJed Brown - coveredPoints - The points in the join 3098552f7358SJed Brown 3099552f7358SJed Brown Level: intermediate 3100552f7358SJed Brown 3101552f7358SJed Brown Note: Currently, this is restricted to a single level join 3102552f7358SJed Brown 31033813dfbdSMatthew G Knepley Fortran Notes: 31043813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 31053813dfbdSMatthew G Knepley include petsc.h90 in your code. 31063813dfbdSMatthew G Knepley 31073813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 31083813dfbdSMatthew G Knepley 3109552f7358SJed Brown .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 3110552f7358SJed Brown @*/ 3111552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3112552f7358SJed Brown { 3113552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3114552f7358SJed Brown PetscInt *join[2]; 3115552f7358SJed Brown PetscInt joinSize, i = 0; 3116552f7358SJed Brown PetscInt dof, off, p, c, m; 3117552f7358SJed Brown PetscErrorCode ierr; 3118552f7358SJed Brown 3119552f7358SJed Brown PetscFunctionBegin; 3120552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 312148bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 312248bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 312348bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 312469291d52SBarry Smith ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 312569291d52SBarry Smith ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3126552f7358SJed Brown /* Copy in support of first point */ 3127552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 3128552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 3129552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 3130552f7358SJed Brown join[i][joinSize] = mesh->supports[off+joinSize]; 3131552f7358SJed Brown } 3132552f7358SJed Brown /* Check each successive support */ 3133552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 3134552f7358SJed Brown PetscInt newJoinSize = 0; 3135552f7358SJed Brown 3136552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 3137552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 3138552f7358SJed Brown for (c = 0; c < dof; ++c) { 3139552f7358SJed Brown const PetscInt point = mesh->supports[off+c]; 3140552f7358SJed Brown 3141552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 3142552f7358SJed Brown if (point == join[i][m]) { 3143552f7358SJed Brown join[1-i][newJoinSize++] = point; 3144552f7358SJed Brown break; 3145552f7358SJed Brown } 3146552f7358SJed Brown } 3147552f7358SJed Brown } 3148552f7358SJed Brown joinSize = newJoinSize; 3149552f7358SJed Brown i = 1-i; 3150552f7358SJed Brown } 3151552f7358SJed Brown *numCoveredPoints = joinSize; 3152552f7358SJed Brown *coveredPoints = join[i]; 315369291d52SBarry Smith ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 3154552f7358SJed Brown PetscFunctionReturn(0); 3155552f7358SJed Brown } 3156552f7358SJed Brown 3157552f7358SJed Brown /*@C 3158552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 3159552f7358SJed Brown 3160552f7358SJed Brown Not Collective 3161552f7358SJed Brown 3162552f7358SJed Brown Input Parameters: 3163552f7358SJed Brown + dm - The DMPlex object 3164552f7358SJed Brown . numPoints - The number of input points for the join 3165552f7358SJed Brown - points - The input points 3166552f7358SJed Brown 3167552f7358SJed Brown Output Parameters: 3168552f7358SJed Brown + numCoveredPoints - The number of points in the join 3169552f7358SJed Brown - coveredPoints - The points in the join 3170552f7358SJed Brown 31713813dfbdSMatthew G Knepley Fortran Notes: 31723813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 31733813dfbdSMatthew G Knepley include petsc.h90 in your code. 31743813dfbdSMatthew G Knepley 31753813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 31763813dfbdSMatthew G Knepley 3177552f7358SJed Brown Level: intermediate 3178552f7358SJed Brown 3179552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 3180552f7358SJed Brown @*/ 3181552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3182552f7358SJed Brown { 3183552f7358SJed Brown PetscErrorCode ierr; 3184552f7358SJed Brown 3185552f7358SJed Brown PetscFunctionBegin; 3186552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3187d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 3188d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 3189d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints, 5); 319069291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 3191d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 3192552f7358SJed Brown PetscFunctionReturn(0); 3193552f7358SJed Brown } 3194552f7358SJed Brown 3195552f7358SJed Brown /*@C 3196552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 3197552f7358SJed Brown 3198552f7358SJed Brown Not Collective 3199552f7358SJed Brown 3200552f7358SJed Brown Input Parameters: 3201552f7358SJed Brown + dm - The DMPlex object 3202552f7358SJed Brown . numPoints - The number of input points for the join 3203552f7358SJed Brown - points - The input points 3204552f7358SJed Brown 3205552f7358SJed Brown Output Parameters: 3206552f7358SJed Brown + numCoveredPoints - The number of points in the join 3207552f7358SJed Brown - coveredPoints - The points in the join 3208552f7358SJed Brown 32093813dfbdSMatthew G Knepley Fortran Notes: 32103813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 32113813dfbdSMatthew G Knepley include petsc.h90 in your code. 32123813dfbdSMatthew G Knepley 32133813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 32143813dfbdSMatthew G Knepley 3215552f7358SJed Brown Level: intermediate 3216552f7358SJed Brown 3217552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 3218552f7358SJed Brown @*/ 3219552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3220552f7358SJed Brown { 3221552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3222552f7358SJed Brown PetscInt *offsets, **closures; 3223552f7358SJed Brown PetscInt *join[2]; 3224552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 322524c766afSToby Isaac PetscInt p, d, c, m, ms; 3226552f7358SJed Brown PetscErrorCode ierr; 3227552f7358SJed Brown 3228552f7358SJed Brown PetscFunctionBegin; 3229552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 323048bb261cSVaclav Hapla PetscValidIntPointer(points, 3); 323148bb261cSVaclav Hapla PetscValidIntPointer(numCoveredPoints, 4); 323248bb261cSVaclav Hapla PetscValidPointer(coveredPoints, 5); 3233552f7358SJed Brown 3234552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 32351795a4d1SJed Brown ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 323669291d52SBarry Smith ierr = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 323724c766afSToby Isaac ms = mesh->maxSupportSize; 323824c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 323969291d52SBarry Smith ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr); 324069291d52SBarry Smith ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr); 3241552f7358SJed Brown 3242552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 3243552f7358SJed Brown PetscInt closureSize; 3244552f7358SJed Brown 3245552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 32460d644c17SKarl Rupp 3247552f7358SJed Brown offsets[p*(depth+2)+0] = 0; 3248552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 3249552f7358SJed Brown PetscInt pStart, pEnd, i; 3250552f7358SJed Brown 3251552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3252552f7358SJed Brown for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 3253552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 3254552f7358SJed Brown offsets[p*(depth+2)+d+1] = i; 3255552f7358SJed Brown break; 3256552f7358SJed Brown } 3257552f7358SJed Brown } 3258552f7358SJed Brown if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 3259552f7358SJed Brown } 326082f516ccSBarry Smith if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 3261552f7358SJed Brown } 3262552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 3263552f7358SJed Brown PetscInt dof; 3264552f7358SJed Brown 3265552f7358SJed Brown /* Copy in support of first point */ 3266552f7358SJed Brown dof = offsets[d+1] - offsets[d]; 3267552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 3268552f7358SJed Brown join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 3269552f7358SJed Brown } 3270552f7358SJed Brown /* Check each successive cone */ 3271552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 3272552f7358SJed Brown PetscInt newJoinSize = 0; 3273552f7358SJed Brown 3274552f7358SJed Brown dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 3275552f7358SJed Brown for (c = 0; c < dof; ++c) { 3276552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 3277552f7358SJed Brown 3278552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 3279552f7358SJed Brown if (point == join[i][m]) { 3280552f7358SJed Brown join[1-i][newJoinSize++] = point; 3281552f7358SJed Brown break; 3282552f7358SJed Brown } 3283552f7358SJed Brown } 3284552f7358SJed Brown } 3285552f7358SJed Brown joinSize = newJoinSize; 3286552f7358SJed Brown i = 1-i; 3287552f7358SJed Brown } 3288552f7358SJed Brown if (joinSize) break; 3289552f7358SJed Brown } 3290552f7358SJed Brown *numCoveredPoints = joinSize; 3291552f7358SJed Brown *coveredPoints = join[i]; 3292552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 32930298fd71SBarry Smith ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 3294552f7358SJed Brown } 3295552f7358SJed Brown ierr = PetscFree(closures);CHKERRQ(ierr); 329669291d52SBarry Smith ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr); 329769291d52SBarry Smith ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr); 3298552f7358SJed Brown PetscFunctionReturn(0); 3299552f7358SJed Brown } 3300552f7358SJed Brown 3301552f7358SJed Brown /*@C 3302552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 3303552f7358SJed Brown 3304552f7358SJed Brown Not Collective 3305552f7358SJed Brown 3306552f7358SJed Brown Input Parameters: 3307552f7358SJed Brown + dm - The DMPlex object 3308552f7358SJed Brown . numPoints - The number of input points for the meet 3309552f7358SJed Brown - points - The input points 3310552f7358SJed Brown 3311552f7358SJed Brown Output Parameters: 3312552f7358SJed Brown + numCoveredPoints - The number of points in the meet 3313552f7358SJed Brown - coveredPoints - The points in the meet 3314552f7358SJed Brown 3315552f7358SJed Brown Level: intermediate 3316552f7358SJed Brown 3317552f7358SJed Brown Note: Currently, this is restricted to a single level meet 3318552f7358SJed Brown 33193813dfbdSMatthew G Knepley Fortran Notes: 33203813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 33213813dfbdSMatthew G Knepley include petsc.h90 in your code. 33223813dfbdSMatthew G Knepley 33233813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 33243813dfbdSMatthew G Knepley 3325552f7358SJed Brown .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 3326552f7358SJed Brown @*/ 3327552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 3328552f7358SJed Brown { 3329552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3330552f7358SJed Brown PetscInt *meet[2]; 3331552f7358SJed Brown PetscInt meetSize, i = 0; 3332552f7358SJed Brown PetscInt dof, off, p, c, m; 3333552f7358SJed Brown PetscErrorCode ierr; 3334552f7358SJed Brown 3335552f7358SJed Brown PetscFunctionBegin; 3336552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3337552f7358SJed Brown PetscValidPointer(points, 2); 3338552f7358SJed Brown PetscValidPointer(numCoveringPoints, 3); 3339552f7358SJed Brown PetscValidPointer(coveringPoints, 4); 334069291d52SBarry Smith ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 334169291d52SBarry Smith ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 3342552f7358SJed Brown /* Copy in cone of first point */ 3343552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 3344552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 3345552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 3346552f7358SJed Brown meet[i][meetSize] = mesh->cones[off+meetSize]; 3347552f7358SJed Brown } 3348552f7358SJed Brown /* Check each successive cone */ 3349552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 3350552f7358SJed Brown PetscInt newMeetSize = 0; 3351552f7358SJed Brown 3352552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 3353552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 3354552f7358SJed Brown for (c = 0; c < dof; ++c) { 3355552f7358SJed Brown const PetscInt point = mesh->cones[off+c]; 3356552f7358SJed Brown 3357552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 3358552f7358SJed Brown if (point == meet[i][m]) { 3359552f7358SJed Brown meet[1-i][newMeetSize++] = point; 3360552f7358SJed Brown break; 3361552f7358SJed Brown } 3362552f7358SJed Brown } 3363552f7358SJed Brown } 3364552f7358SJed Brown meetSize = newMeetSize; 3365552f7358SJed Brown i = 1-i; 3366552f7358SJed Brown } 3367552f7358SJed Brown *numCoveringPoints = meetSize; 3368552f7358SJed Brown *coveringPoints = meet[i]; 336969291d52SBarry Smith ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 3370552f7358SJed Brown PetscFunctionReturn(0); 3371552f7358SJed Brown } 3372552f7358SJed Brown 3373552f7358SJed Brown /*@C 3374552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 3375552f7358SJed Brown 3376552f7358SJed Brown Not Collective 3377552f7358SJed Brown 3378552f7358SJed Brown Input Parameters: 3379552f7358SJed Brown + dm - The DMPlex object 3380552f7358SJed Brown . numPoints - The number of input points for the meet 3381552f7358SJed Brown - points - The input points 3382552f7358SJed Brown 3383552f7358SJed Brown Output Parameters: 3384552f7358SJed Brown + numCoveredPoints - The number of points in the meet 3385552f7358SJed Brown - coveredPoints - The points in the meet 3386552f7358SJed Brown 3387552f7358SJed Brown Level: intermediate 3388552f7358SJed Brown 33893813dfbdSMatthew G Knepley Fortran Notes: 33903813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 33913813dfbdSMatthew G Knepley include petsc.h90 in your code. 33923813dfbdSMatthew G Knepley 33933813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 33943813dfbdSMatthew G Knepley 3395552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 3396552f7358SJed Brown @*/ 3397552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3398552f7358SJed Brown { 3399552f7358SJed Brown PetscErrorCode ierr; 3400552f7358SJed Brown 3401552f7358SJed Brown PetscFunctionBegin; 3402552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3403d7902bd2SMatthew G. Knepley if (points) PetscValidIntPointer(points,3); 3404d7902bd2SMatthew G. Knepley if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 3405d7902bd2SMatthew G. Knepley PetscValidPointer(coveredPoints,5); 340669291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr); 3407d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 3408552f7358SJed Brown PetscFunctionReturn(0); 3409552f7358SJed Brown } 3410552f7358SJed Brown 3411552f7358SJed Brown /*@C 3412552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 3413552f7358SJed Brown 3414552f7358SJed Brown Not Collective 3415552f7358SJed Brown 3416552f7358SJed Brown Input Parameters: 3417552f7358SJed Brown + dm - The DMPlex object 3418552f7358SJed Brown . numPoints - The number of input points for the meet 3419552f7358SJed Brown - points - The input points 3420552f7358SJed Brown 3421552f7358SJed Brown Output Parameters: 3422552f7358SJed Brown + numCoveredPoints - The number of points in the meet 3423552f7358SJed Brown - coveredPoints - The points in the meet 3424552f7358SJed Brown 3425552f7358SJed Brown Level: intermediate 3426552f7358SJed Brown 34273813dfbdSMatthew G Knepley Fortran Notes: 34283813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 34293813dfbdSMatthew G Knepley include petsc.h90 in your code. 34303813dfbdSMatthew G Knepley 34313813dfbdSMatthew G Knepley The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 34323813dfbdSMatthew G Knepley 3433552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 3434552f7358SJed Brown @*/ 3435552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 3436552f7358SJed Brown { 3437552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 3438552f7358SJed Brown PetscInt *offsets, **closures; 3439552f7358SJed Brown PetscInt *meet[2]; 3440552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 344124c766afSToby Isaac PetscInt p, h, c, m, mc; 3442552f7358SJed Brown PetscErrorCode ierr; 3443552f7358SJed Brown 3444552f7358SJed Brown PetscFunctionBegin; 3445552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3446552f7358SJed Brown PetscValidPointer(points, 2); 3447552f7358SJed Brown PetscValidPointer(numCoveredPoints, 3); 3448552f7358SJed Brown PetscValidPointer(coveredPoints, 4); 3449552f7358SJed Brown 3450552f7358SJed Brown ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 3451785e854fSJed Brown ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 345269291d52SBarry Smith ierr = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 345324c766afSToby Isaac mc = mesh->maxConeSize; 345424c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 345569291d52SBarry Smith ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr); 345669291d52SBarry Smith ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr); 3457552f7358SJed Brown 3458552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 3459552f7358SJed Brown PetscInt closureSize; 3460552f7358SJed Brown 3461552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 34620d644c17SKarl Rupp 3463552f7358SJed Brown offsets[p*(height+2)+0] = 0; 3464552f7358SJed Brown for (h = 0; h < height+1; ++h) { 3465552f7358SJed Brown PetscInt pStart, pEnd, i; 3466552f7358SJed Brown 3467552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 3468552f7358SJed Brown for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 3469552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 3470552f7358SJed Brown offsets[p*(height+2)+h+1] = i; 3471552f7358SJed Brown break; 3472552f7358SJed Brown } 3473552f7358SJed Brown } 3474552f7358SJed Brown if (i == closureSize) offsets[p*(height+2)+h+1] = i; 3475552f7358SJed Brown } 347682f516ccSBarry Smith if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 3477552f7358SJed Brown } 3478552f7358SJed Brown for (h = 0; h < height+1; ++h) { 3479552f7358SJed Brown PetscInt dof; 3480552f7358SJed Brown 3481552f7358SJed Brown /* Copy in cone of first point */ 3482552f7358SJed Brown dof = offsets[h+1] - offsets[h]; 3483552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 3484552f7358SJed Brown meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 3485552f7358SJed Brown } 3486552f7358SJed Brown /* Check each successive cone */ 3487552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 3488552f7358SJed Brown PetscInt newMeetSize = 0; 3489552f7358SJed Brown 3490552f7358SJed Brown dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 3491552f7358SJed Brown for (c = 0; c < dof; ++c) { 3492552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 3493552f7358SJed Brown 3494552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 3495552f7358SJed Brown if (point == meet[i][m]) { 3496552f7358SJed Brown meet[1-i][newMeetSize++] = point; 3497552f7358SJed Brown break; 3498552f7358SJed Brown } 3499552f7358SJed Brown } 3500552f7358SJed Brown } 3501552f7358SJed Brown meetSize = newMeetSize; 3502552f7358SJed Brown i = 1-i; 3503552f7358SJed Brown } 3504552f7358SJed Brown if (meetSize) break; 3505552f7358SJed Brown } 3506552f7358SJed Brown *numCoveredPoints = meetSize; 3507552f7358SJed Brown *coveredPoints = meet[i]; 3508552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 35090298fd71SBarry Smith ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 3510552f7358SJed Brown } 3511552f7358SJed Brown ierr = PetscFree(closures);CHKERRQ(ierr); 351269291d52SBarry Smith ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr); 351369291d52SBarry Smith ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr); 3514552f7358SJed Brown PetscFunctionReturn(0); 3515552f7358SJed Brown } 3516552f7358SJed Brown 35174e3744c5SMatthew G. Knepley /*@C 35184e3744c5SMatthew G. Knepley DMPlexEqual - Determine if two DMs have the same topology 35194e3744c5SMatthew G. Knepley 35204e3744c5SMatthew G. Knepley Not Collective 35214e3744c5SMatthew G. Knepley 35224e3744c5SMatthew G. Knepley Input Parameters: 35234e3744c5SMatthew G. Knepley + dmA - A DMPlex object 35244e3744c5SMatthew G. Knepley - dmB - A DMPlex object 35254e3744c5SMatthew G. Knepley 35264e3744c5SMatthew G. Knepley Output Parameters: 35274e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical 35284e3744c5SMatthew G. Knepley 35294e3744c5SMatthew G. Knepley Level: intermediate 35304e3744c5SMatthew G. Knepley 35314e3744c5SMatthew G. Knepley Notes: 35324e3744c5SMatthew G. Knepley We are not solving graph isomorphism, so we do not permutation. 35334e3744c5SMatthew G. Knepley 35344e3744c5SMatthew G. Knepley .seealso: DMPlexGetCone() 35354e3744c5SMatthew G. Knepley @*/ 35364e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 35374e3744c5SMatthew G. Knepley { 35384e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 35394e3744c5SMatthew G. Knepley PetscErrorCode ierr; 35404e3744c5SMatthew G. Knepley 35414e3744c5SMatthew G. Knepley PetscFunctionBegin; 35424e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 35434e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 35444e3744c5SMatthew G. Knepley PetscValidPointer(equal, 3); 35454e3744c5SMatthew G. Knepley 35464e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 35474e3744c5SMatthew G. Knepley ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 35484e3744c5SMatthew G. Knepley ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 35494e3744c5SMatthew G. Knepley if (depth != depthB) PetscFunctionReturn(0); 35504e3744c5SMatthew G. Knepley ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 35514e3744c5SMatthew G. Knepley ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 35524e3744c5SMatthew G. Knepley if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 35534e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 35544e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 35554e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 35564e3744c5SMatthew G. Knepley 35574e3744c5SMatthew G. Knepley ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 35584e3744c5SMatthew G. Knepley ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 35594e3744c5SMatthew G. Knepley ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 35604e3744c5SMatthew G. Knepley ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 35614e3744c5SMatthew G. Knepley ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 35624e3744c5SMatthew G. Knepley ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 35634e3744c5SMatthew G. Knepley if (coneSize != coneSizeB) PetscFunctionReturn(0); 35644e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 35654e3744c5SMatthew G. Knepley if (cone[c] != coneB[c]) PetscFunctionReturn(0); 35664e3744c5SMatthew G. Knepley if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 35674e3744c5SMatthew G. Knepley } 35684e3744c5SMatthew G. Knepley ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 35694e3744c5SMatthew G. Knepley ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 35704e3744c5SMatthew G. Knepley ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 35714e3744c5SMatthew G. Knepley ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 35724e3744c5SMatthew G. Knepley if (supportSize != supportSizeB) PetscFunctionReturn(0); 35734e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 35744e3744c5SMatthew G. Knepley if (support[s] != supportB[s]) PetscFunctionReturn(0); 35754e3744c5SMatthew G. Knepley } 35764e3744c5SMatthew G. Knepley } 35774e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 35784e3744c5SMatthew G. Knepley PetscFunctionReturn(0); 35794e3744c5SMatthew G. Knepley } 35804e3744c5SMatthew G. Knepley 35817cd05799SMatthew G. Knepley /*@C 35827cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 35837cd05799SMatthew G. Knepley 35847cd05799SMatthew G. Knepley Not Collective 35857cd05799SMatthew G. Knepley 35867cd05799SMatthew G. Knepley Input Parameters: 35877cd05799SMatthew G. Knepley + dm - The DMPlex 35887cd05799SMatthew G. Knepley . cellDim - The cell dimension 35897cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 35907cd05799SMatthew G. Knepley 35917cd05799SMatthew G. Knepley Output Parameters: 35927cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 35937cd05799SMatthew G. Knepley 35947cd05799SMatthew G. Knepley Level: developer 35957cd05799SMatthew G. Knepley 35967cd05799SMatthew G. Knepley Notes: 35977cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 35987cd05799SMatthew G. Knepley 35997cd05799SMatthew G. Knepley .seealso: DMPlexGetCone() 36007cd05799SMatthew G. Knepley @*/ 360118ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 3602a6dfd86eSKarl Rupp { 360382f516ccSBarry Smith MPI_Comm comm; 3604552f7358SJed Brown PetscErrorCode ierr; 3605552f7358SJed Brown 3606552f7358SJed Brown PetscFunctionBegin; 360782f516ccSBarry Smith ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3608552f7358SJed Brown PetscValidPointer(numFaceVertices,3); 3609552f7358SJed Brown switch (cellDim) { 3610552f7358SJed Brown case 0: 3611552f7358SJed Brown *numFaceVertices = 0; 3612552f7358SJed Brown break; 3613552f7358SJed Brown case 1: 3614552f7358SJed Brown *numFaceVertices = 1; 3615552f7358SJed Brown break; 3616552f7358SJed Brown case 2: 3617552f7358SJed Brown switch (numCorners) { 361819436ca2SJed Brown case 3: /* triangle */ 361919436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 3620552f7358SJed Brown break; 362119436ca2SJed Brown case 4: /* quadrilateral */ 362219436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 3623552f7358SJed Brown break; 362419436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 362519436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 3626552f7358SJed Brown break; 362719436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 362819436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 3629552f7358SJed Brown break; 3630552f7358SJed Brown default: 3631f347f43bSBarry Smith SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 3632552f7358SJed Brown } 3633552f7358SJed Brown break; 3634552f7358SJed Brown case 3: 3635552f7358SJed Brown switch (numCorners) { 363619436ca2SJed Brown case 4: /* tetradehdron */ 363719436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 3638552f7358SJed Brown break; 363919436ca2SJed Brown case 6: /* tet cohesive cells */ 364019436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 3641552f7358SJed Brown break; 364219436ca2SJed Brown case 8: /* hexahedron */ 364319436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 3644552f7358SJed Brown break; 364519436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 364619436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 3647552f7358SJed Brown break; 364819436ca2SJed Brown case 10: /* quadratic tetrahedron */ 364919436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 3650552f7358SJed Brown break; 365119436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 365219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 3653552f7358SJed Brown break; 365419436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 365519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 3656552f7358SJed Brown break; 365719436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 365819436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 3659552f7358SJed Brown break; 3660552f7358SJed Brown default: 3661f347f43bSBarry Smith SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 3662552f7358SJed Brown } 3663552f7358SJed Brown break; 3664552f7358SJed Brown default: 3665f347f43bSBarry Smith SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 3666552f7358SJed Brown } 3667552f7358SJed Brown PetscFunctionReturn(0); 3668552f7358SJed Brown } 3669552f7358SJed Brown 3670552f7358SJed Brown /*@ 3671aa50250dSMatthew G. Knepley DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 3672552f7358SJed Brown 3673552f7358SJed Brown Not Collective 3674552f7358SJed Brown 3675aa50250dSMatthew G. Knepley Input Parameter: 3676552f7358SJed Brown . dm - The DMPlex object 3677552f7358SJed Brown 3678aa50250dSMatthew G. Knepley Output Parameter: 3679aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth 3680552f7358SJed Brown 3681552f7358SJed Brown Level: developer 3682552f7358SJed Brown 3683dc287ab2SVaclav Hapla .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), 3684aa50250dSMatthew G. Knepley @*/ 3685aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 3686aa50250dSMatthew G. Knepley { 3687aa50250dSMatthew G. Knepley PetscFunctionBegin; 3688aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3689aa50250dSMatthew G. Knepley PetscValidPointer(depthLabel, 2); 3690c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 3691aa50250dSMatthew G. Knepley PetscFunctionReturn(0); 3692aa50250dSMatthew G. Knepley } 3693aa50250dSMatthew G. Knepley 3694aa50250dSMatthew G. Knepley /*@ 3695aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 3696aa50250dSMatthew G. Knepley 3697aa50250dSMatthew G. Knepley Not Collective 3698aa50250dSMatthew G. Knepley 3699aa50250dSMatthew G. Knepley Input Parameter: 3700aa50250dSMatthew G. Knepley . dm - The DMPlex object 3701aa50250dSMatthew G. Knepley 3702aa50250dSMatthew G. Knepley Output Parameter: 3703aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 3704aa50250dSMatthew G. Knepley 3705aa50250dSMatthew G. Knepley Level: developer 3706552f7358SJed Brown 3707b1bb481bSMatthew Knepley Notes: 3708b1bb481bSMatthew Knepley This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel(). 3709dc287ab2SVaclav Hapla The point depth is described more in detail in DMPlexGetDepthStratum(). 3710dc287ab2SVaclav Hapla An empty mesh gives -1. 3711b1bb481bSMatthew Knepley 3712dc287ab2SVaclav Hapla .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize() 3713552f7358SJed Brown @*/ 3714552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 3715552f7358SJed Brown { 3716aa50250dSMatthew G. Knepley DMLabel label; 3717aa50250dSMatthew G. Knepley PetscInt d = 0; 3718552f7358SJed Brown PetscErrorCode ierr; 3719552f7358SJed Brown 3720552f7358SJed Brown PetscFunctionBegin; 3721552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3722552f7358SJed Brown PetscValidPointer(depth, 2); 3723aa50250dSMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 3724aa50250dSMatthew G. Knepley if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 3725552f7358SJed Brown *depth = d-1; 3726552f7358SJed Brown PetscFunctionReturn(0); 3727552f7358SJed Brown } 3728552f7358SJed Brown 3729552f7358SJed Brown /*@ 3730552f7358SJed Brown DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 3731552f7358SJed Brown 3732552f7358SJed Brown Not Collective 3733552f7358SJed Brown 3734552f7358SJed Brown Input Parameters: 3735552f7358SJed Brown + dm - The DMPlex object 3736552f7358SJed Brown - stratumValue - The requested depth 3737552f7358SJed Brown 3738552f7358SJed Brown Output Parameters: 3739552f7358SJed Brown + start - The first point at this depth 3740552f7358SJed Brown - end - One beyond the last point at this depth 3741552f7358SJed Brown 3742647867b2SJed Brown Notes: 3743647867b2SJed Brown Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 3744647867b2SJed Brown often "vertices". If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next 3745647867b2SJed Brown higher dimension, e.g., "edges". 3746647867b2SJed Brown 3747552f7358SJed Brown Level: developer 3748552f7358SJed Brown 3749dc287ab2SVaclav Hapla .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate() 3750552f7358SJed Brown @*/ 37510adebc6cSBarry Smith PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 37520adebc6cSBarry Smith { 3753aa50250dSMatthew G. Knepley DMLabel label; 375463d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 3755552f7358SJed Brown PetscErrorCode ierr; 3756552f7358SJed Brown 3757552f7358SJed Brown PetscFunctionBegin; 3758552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 375963d1a920SMatthew G. Knepley if (start) {PetscValidPointer(start, 3); *start = 0;} 376063d1a920SMatthew G. Knepley if (end) {PetscValidPointer(end, 4); *end = 0;} 3761552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 37620d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 376363d1a920SMatthew G. Knepley if (stratumValue < 0) { 376463d1a920SMatthew G. Knepley if (start) *start = pStart; 376563d1a920SMatthew G. Knepley if (end) *end = pEnd; 376663d1a920SMatthew G. Knepley PetscFunctionReturn(0); 3767552f7358SJed Brown } 3768aa50250dSMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 376963d1a920SMatthew G. Knepley if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 377063d1a920SMatthew G. Knepley ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 3771552f7358SJed Brown PetscFunctionReturn(0); 3772552f7358SJed Brown } 3773552f7358SJed Brown 3774552f7358SJed Brown /*@ 3775552f7358SJed Brown DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 3776552f7358SJed Brown 3777552f7358SJed Brown Not Collective 3778552f7358SJed Brown 3779552f7358SJed Brown Input Parameters: 3780552f7358SJed Brown + dm - The DMPlex object 3781552f7358SJed Brown - stratumValue - The requested height 3782552f7358SJed Brown 3783552f7358SJed Brown Output Parameters: 3784552f7358SJed Brown + start - The first point at this height 3785552f7358SJed Brown - end - One beyond the last point at this height 3786552f7358SJed Brown 3787647867b2SJed Brown Notes: 3788647867b2SJed Brown Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 3789647867b2SJed Brown points, often called "cells" or "elements". If the mesh is "interpolated" (see DMPlexInterpolate()), then height 3790647867b2SJed Brown stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 3791647867b2SJed Brown 3792552f7358SJed Brown Level: developer 3793552f7358SJed Brown 37943dc9a465SVaclav Hapla .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight() 3795552f7358SJed Brown @*/ 37960adebc6cSBarry Smith PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 37970adebc6cSBarry Smith { 3798aa50250dSMatthew G. Knepley DMLabel label; 379963d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 3800552f7358SJed Brown PetscErrorCode ierr; 3801552f7358SJed Brown 3802552f7358SJed Brown PetscFunctionBegin; 3803552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 380463d1a920SMatthew G. Knepley if (start) {PetscValidPointer(start, 3); *start = 0;} 380563d1a920SMatthew G. Knepley if (end) {PetscValidPointer(end, 4); *end = 0;} 3806552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 38070d644c17SKarl Rupp if (pStart == pEnd) PetscFunctionReturn(0); 380863d1a920SMatthew G. Knepley if (stratumValue < 0) { 380963d1a920SMatthew G. Knepley if (start) *start = pStart; 381063d1a920SMatthew G. Knepley if (end) *end = pEnd; 381163d1a920SMatthew G. Knepley PetscFunctionReturn(0); 3812552f7358SJed Brown } 3813aa50250dSMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 381413903a91SSatish Balay if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 381563d1a920SMatthew G. Knepley ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 381663d1a920SMatthew G. Knepley ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 3817552f7358SJed Brown PetscFunctionReturn(0); 3818552f7358SJed Brown } 3819552f7358SJed Brown 3820ba2698f1SMatthew G. Knepley /*@ 3821ba2698f1SMatthew G. Knepley DMPlexGetPointDepth - Get the depth of a given point 3822ba2698f1SMatthew G. Knepley 3823ba2698f1SMatthew G. Knepley Not Collective 3824ba2698f1SMatthew G. Knepley 3825ba2698f1SMatthew G. Knepley Input Parameter: 3826ba2698f1SMatthew G. Knepley + dm - The DMPlex object 3827ba2698f1SMatthew G. Knepley - point - The point 3828ba2698f1SMatthew G. Knepley 3829ba2698f1SMatthew G. Knepley Output Parameter: 3830ba2698f1SMatthew G. Knepley . depth - The depth of the point 3831ba2698f1SMatthew G. Knepley 3832ba2698f1SMatthew G. Knepley Level: intermediate 3833ba2698f1SMatthew G. Knepley 38343dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight() 3835ba2698f1SMatthew G. Knepley @*/ 3836ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 3837ba2698f1SMatthew G. Knepley { 3838ba2698f1SMatthew G. Knepley PetscErrorCode ierr; 3839ba2698f1SMatthew G. Knepley 3840ba2698f1SMatthew G. Knepley PetscFunctionBegin; 3841ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 384240a2aa30SMatthew G. Knepley PetscValidIntPointer(depth, 3); 3843ba2698f1SMatthew G. Knepley ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr); 3844ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 3845ba2698f1SMatthew G. Knepley } 3846ba2698f1SMatthew G. Knepley 3847ba2698f1SMatthew G. Knepley /*@ 38480c0a32dcSVaclav Hapla DMPlexGetPointHeight - Get the height of a given point 38490c0a32dcSVaclav Hapla 38500c0a32dcSVaclav Hapla Not Collective 38510c0a32dcSVaclav Hapla 38520c0a32dcSVaclav Hapla Input Parameter: 38530c0a32dcSVaclav Hapla + dm - The DMPlex object 38540c0a32dcSVaclav Hapla - point - The point 38550c0a32dcSVaclav Hapla 38560c0a32dcSVaclav Hapla Output Parameter: 38570c0a32dcSVaclav Hapla . height - The height of the point 38580c0a32dcSVaclav Hapla 38590c0a32dcSVaclav Hapla Level: intermediate 38600c0a32dcSVaclav Hapla 38613dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth() 38620c0a32dcSVaclav Hapla @*/ 38630c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 38640c0a32dcSVaclav Hapla { 38650c0a32dcSVaclav Hapla PetscInt n, pDepth; 38660c0a32dcSVaclav Hapla PetscErrorCode ierr; 38670c0a32dcSVaclav Hapla 38680c0a32dcSVaclav Hapla PetscFunctionBegin; 38690c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38700c0a32dcSVaclav Hapla PetscValidIntPointer(height, 3); 38710c0a32dcSVaclav Hapla ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr); 38720c0a32dcSVaclav Hapla ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr); 38730c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 38740c0a32dcSVaclav Hapla PetscFunctionReturn(0); 38750c0a32dcSVaclav Hapla } 38760c0a32dcSVaclav Hapla 38770c0a32dcSVaclav Hapla /*@ 3878ba2698f1SMatthew G. Knepley DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell 3879ba2698f1SMatthew G. Knepley 3880ba2698f1SMatthew G. Knepley Not Collective 3881ba2698f1SMatthew G. Knepley 3882ba2698f1SMatthew G. Knepley Input Parameter: 3883ba2698f1SMatthew G. Knepley . dm - The DMPlex object 3884ba2698f1SMatthew G. Knepley 3885ba2698f1SMatthew G. Knepley Output Parameter: 3886ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type 3887ba2698f1SMatthew G. Knepley 3888412e9a14SMatthew G. Knepley Note: This function will trigger automatica computation of cell types. This can be disabled by calling 3889412e9a14SMatthew G. Knepley DMCreateLabel(dm, "celltype") beforehand. 3890412e9a14SMatthew G. Knepley 3891ba2698f1SMatthew G. Knepley Level: developer 3892ba2698f1SMatthew G. Knepley 3893dc287ab2SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel() 3894ba2698f1SMatthew G. Knepley @*/ 3895ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 3896ba2698f1SMatthew G. Knepley { 3897ba2698f1SMatthew G. Knepley PetscErrorCode ierr; 3898ba2698f1SMatthew G. Knepley 3899ba2698f1SMatthew G. Knepley PetscFunctionBegin; 3900ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3901ba2698f1SMatthew G. Knepley PetscValidPointer(celltypeLabel, 2); 3902ba2698f1SMatthew G. Knepley if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);} 3903ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 3904ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 3905ba2698f1SMatthew G. Knepley } 3906ba2698f1SMatthew G. Knepley 3907ba2698f1SMatthew G. Knepley /*@ 3908ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 3909ba2698f1SMatthew G. Knepley 3910ba2698f1SMatthew G. Knepley Not Collective 3911ba2698f1SMatthew G. Knepley 3912ba2698f1SMatthew G. Knepley Input Parameter: 3913ba2698f1SMatthew G. Knepley + dm - The DMPlex object 3914ba2698f1SMatthew G. Knepley - cell - The cell 3915ba2698f1SMatthew G. Knepley 3916ba2698f1SMatthew G. Knepley Output Parameter: 3917ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 3918ba2698f1SMatthew G. Knepley 3919ba2698f1SMatthew G. Knepley Level: intermediate 3920ba2698f1SMatthew G. Knepley 3921ba2698f1SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth() 3922ba2698f1SMatthew G. Knepley @*/ 3923ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 3924ba2698f1SMatthew G. Knepley { 3925ba2698f1SMatthew G. Knepley DMLabel label; 3926ba2698f1SMatthew G. Knepley PetscInt ct; 3927ba2698f1SMatthew G. Knepley PetscErrorCode ierr; 3928ba2698f1SMatthew G. Knepley 3929ba2698f1SMatthew G. Knepley PetscFunctionBegin; 3930ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3931ba2698f1SMatthew G. Knepley PetscValidPointer(celltype, 3); 3932ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 3933ba2698f1SMatthew G. Knepley ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr); 3934ba2698f1SMatthew G. Knepley *celltype = (DMPolytopeType) ct; 3935ba2698f1SMatthew G. Knepley PetscFunctionReturn(0); 3936ba2698f1SMatthew G. Knepley } 3937ba2698f1SMatthew G. Knepley 3938412e9a14SMatthew G. Knepley /*@ 3939412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 3940412e9a14SMatthew G. Knepley 3941412e9a14SMatthew G. Knepley Not Collective 3942412e9a14SMatthew G. Knepley 3943412e9a14SMatthew G. Knepley Input Parameters: 3944412e9a14SMatthew G. Knepley + dm - The DMPlex object 3945412e9a14SMatthew G. Knepley . cell - The cell 3946412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 3947412e9a14SMatthew G. Knepley 3948412e9a14SMatthew G. Knepley Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function 3949412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 3950412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 3951412e9a14SMatthew G. Knepley DMCreaateLabel(dm, "celltype") before getting or setting any cell types. 3952412e9a14SMatthew G. Knepley 3953412e9a14SMatthew G. Knepley Level: advanced 3954412e9a14SMatthew G. Knepley 3955412e9a14SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel() 3956412e9a14SMatthew G. Knepley @*/ 3957412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 3958412e9a14SMatthew G. Knepley { 3959412e9a14SMatthew G. Knepley DMLabel label; 3960412e9a14SMatthew G. Knepley PetscErrorCode ierr; 3961412e9a14SMatthew G. Knepley 3962412e9a14SMatthew G. Knepley PetscFunctionBegin; 3963412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3964412e9a14SMatthew G. Knepley ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr); 3965412e9a14SMatthew G. Knepley ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr); 3966412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 3967412e9a14SMatthew G. Knepley } 3968412e9a14SMatthew G. Knepley 39690adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 39700adebc6cSBarry Smith { 3971efe440bfSMatthew G. Knepley PetscSection section, s; 3972efe440bfSMatthew G. Knepley Mat m; 39733e922f36SToby Isaac PetscInt maxHeight; 3974552f7358SJed Brown PetscErrorCode ierr; 3975552f7358SJed Brown 3976552f7358SJed Brown PetscFunctionBegin; 397738221697SMatthew G. Knepley ierr = DMClone(dm, cdm);CHKERRQ(ierr); 39783e922f36SToby Isaac ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr); 39793e922f36SToby Isaac ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr); 398082f516ccSBarry Smith ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 398192fd8e1eSJed Brown ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr); 39821d799100SJed Brown ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3983efe440bfSMatthew G. Knepley ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr); 3984efe440bfSMatthew G. Knepley ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr); 3985efe440bfSMatthew G. Knepley ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr); 3986efe440bfSMatthew G. Knepley ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 3987efe440bfSMatthew G. Knepley ierr = MatDestroy(&m);CHKERRQ(ierr); 39888f4c458bSMatthew G. Knepley 39898f4c458bSMatthew G. Knepley ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr); 39908f4c458bSMatthew G. Knepley ierr = DMCreateDS(*cdm);CHKERRQ(ierr); 3991552f7358SJed Brown PetscFunctionReturn(0); 3992552f7358SJed Brown } 3993552f7358SJed Brown 3994f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 3995f19dbd58SToby Isaac { 3996f19dbd58SToby Isaac Vec coordsLocal; 3997f19dbd58SToby Isaac DM coordsDM; 3998f19dbd58SToby Isaac PetscErrorCode ierr; 3999f19dbd58SToby Isaac 4000f19dbd58SToby Isaac PetscFunctionBegin; 4001f19dbd58SToby Isaac *field = NULL; 4002f19dbd58SToby Isaac ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr); 4003f19dbd58SToby Isaac ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr); 4004f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 4005f19dbd58SToby Isaac ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr); 4006f19dbd58SToby Isaac } 4007f19dbd58SToby Isaac PetscFunctionReturn(0); 4008f19dbd58SToby Isaac } 4009f19dbd58SToby Isaac 40107cd05799SMatthew G. Knepley /*@C 40117cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 40127cd05799SMatthew G. Knepley 40137cd05799SMatthew G. Knepley Not Collective 40147cd05799SMatthew G. Knepley 40157cd05799SMatthew G. Knepley Input Parameters: 40167cd05799SMatthew G. Knepley . dm - The DMPlex object 40177cd05799SMatthew G. Knepley 40187cd05799SMatthew G. Knepley Output Parameter: 40197cd05799SMatthew G. Knepley . section - The PetscSection object 40207cd05799SMatthew G. Knepley 40217cd05799SMatthew G. Knepley Level: developer 40227cd05799SMatthew G. Knepley 40237cd05799SMatthew G. Knepley .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations() 40247cd05799SMatthew G. Knepley @*/ 40250adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 40260adebc6cSBarry Smith { 4027552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4028552f7358SJed Brown 4029552f7358SJed Brown PetscFunctionBegin; 4030552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4031552f7358SJed Brown if (section) *section = mesh->coneSection; 4032552f7358SJed Brown PetscFunctionReturn(0); 4033552f7358SJed Brown } 4034552f7358SJed Brown 40357cd05799SMatthew G. Knepley /*@C 40367cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 40377cd05799SMatthew G. Knepley 40387cd05799SMatthew G. Knepley Not Collective 40397cd05799SMatthew G. Knepley 40407cd05799SMatthew G. Knepley Input Parameters: 40417cd05799SMatthew G. Knepley . dm - The DMPlex object 40427cd05799SMatthew G. Knepley 40437cd05799SMatthew G. Knepley Output Parameter: 40447cd05799SMatthew G. Knepley . section - The PetscSection object 40457cd05799SMatthew G. Knepley 40467cd05799SMatthew G. Knepley Level: developer 40477cd05799SMatthew G. Knepley 40487cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection() 40497cd05799SMatthew G. Knepley @*/ 40508cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 40518cb4d582SMatthew G. Knepley { 40528cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 40538cb4d582SMatthew G. Knepley 40548cb4d582SMatthew G. Knepley PetscFunctionBegin; 40558cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40568cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 40578cb4d582SMatthew G. Knepley PetscFunctionReturn(0); 40588cb4d582SMatthew G. Knepley } 40598cb4d582SMatthew G. Knepley 40607cd05799SMatthew G. Knepley /*@C 40617cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 40627cd05799SMatthew G. Knepley 40637cd05799SMatthew G. Knepley Not Collective 40647cd05799SMatthew G. Knepley 40657cd05799SMatthew G. Knepley Input Parameters: 40667cd05799SMatthew G. Knepley . dm - The DMPlex object 40677cd05799SMatthew G. Knepley 40687cd05799SMatthew G. Knepley Output Parameter: 40697cd05799SMatthew G. Knepley . cones - The cone for each point 40707cd05799SMatthew G. Knepley 40717cd05799SMatthew G. Knepley Level: developer 40727cd05799SMatthew G. Knepley 40737cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection() 40747cd05799SMatthew G. Knepley @*/ 4075a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 4076a6dfd86eSKarl Rupp { 4077552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4078552f7358SJed Brown 4079552f7358SJed Brown PetscFunctionBegin; 4080552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4081552f7358SJed Brown if (cones) *cones = mesh->cones; 4082552f7358SJed Brown PetscFunctionReturn(0); 4083552f7358SJed Brown } 4084552f7358SJed Brown 40857cd05799SMatthew G. Knepley /*@C 40867cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 40877cd05799SMatthew G. Knepley 40887cd05799SMatthew G. Knepley Not Collective 40897cd05799SMatthew G. Knepley 40907cd05799SMatthew G. Knepley Input Parameters: 40917cd05799SMatthew G. Knepley . dm - The DMPlex object 40927cd05799SMatthew G. Knepley 40937cd05799SMatthew G. Knepley Output Parameter: 40947cd05799SMatthew G. Knepley . coneOrientations - The cone orientation for each point 40957cd05799SMatthew G. Knepley 40967cd05799SMatthew G. Knepley Level: developer 40977cd05799SMatthew G. Knepley 40987cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection() 40997cd05799SMatthew G. Knepley @*/ 4100a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 4101a6dfd86eSKarl Rupp { 4102552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 4103552f7358SJed Brown 4104552f7358SJed Brown PetscFunctionBegin; 4105552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4106552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 4107552f7358SJed Brown PetscFunctionReturn(0); 4108552f7358SJed Brown } 4109552f7358SJed Brown 4110552f7358SJed Brown /******************************** FEM Support **********************************/ 4111552f7358SJed Brown 41129e8305c2SJed Brown /* 41139e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 41149e8305c2SJed Brown representing a line in the section. 41159e8305c2SJed Brown */ 41169e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k) 41179e8305c2SJed Brown { 41189e8305c2SJed Brown PetscErrorCode ierr; 41199e8305c2SJed Brown 41209e8305c2SJed Brown PetscFunctionBeginHot; 41219e8305c2SJed Brown ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr); 4122a433471fSStefano Zampini if (line < 0) { 4123a433471fSStefano Zampini *k = 0; 4124a433471fSStefano Zampini *Nc = 0; 4125a433471fSStefano Zampini } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */ 41269e8305c2SJed Brown *k = 1; 41279e8305c2SJed Brown } else { /* Assume the full interpolated mesh is in the chart; lines in particular */ 41289e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 41299e8305c2SJed Brown ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr); 41309e8305c2SJed Brown *k = *k / *Nc + 1; 41319e8305c2SJed Brown } 41329e8305c2SJed Brown PetscFunctionReturn(0); 41339e8305c2SJed Brown } 41349e8305c2SJed Brown 4135a4355906SMatthew Knepley /*@ 4136bc1eb3faSJed Brown 4137bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 4138bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 41391bb6d2a8SBarry Smith section provided (or the section of the DM). 4140a4355906SMatthew Knepley 4141a4355906SMatthew Knepley Input Parameters: 4142a4355906SMatthew Knepley + dm - The DM 4143a4355906SMatthew Knepley . point - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE 4144a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section 4145a4355906SMatthew Knepley 4146a4355906SMatthew Knepley Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 4147a4355906SMatthew Knepley degree of the basis. 4148a4355906SMatthew Knepley 4149bc1eb3faSJed Brown Example: 4150bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 4151bc1eb3faSJed Brown .vb 4152bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 4153bc1eb3faSJed Brown 4154bc1eb3faSJed Brown v4 -- e6 -- v3 4155bc1eb3faSJed Brown | | 4156bc1eb3faSJed Brown e7 c0 e8 4157bc1eb3faSJed Brown | | 4158bc1eb3faSJed Brown v1 -- e5 -- v2 4159bc1eb3faSJed Brown .ve 4160bc1eb3faSJed Brown 4161bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 4162bc1eb3faSJed Brown dofs in the order of points, e.g., 4163bc1eb3faSJed Brown .vb 4164bc1eb3faSJed Brown c0 -> [0,1,2,3] 4165bc1eb3faSJed Brown v1 -> [4] 4166bc1eb3faSJed Brown ... 4167bc1eb3faSJed Brown e5 -> [8, 9] 4168bc1eb3faSJed Brown .ve 4169bc1eb3faSJed Brown 4170bc1eb3faSJed Brown which corresponds to the dofs 4171bc1eb3faSJed Brown .vb 4172bc1eb3faSJed Brown 6 10 11 7 4173bc1eb3faSJed Brown 13 2 3 15 4174bc1eb3faSJed Brown 12 0 1 14 4175bc1eb3faSJed Brown 4 8 9 5 4176bc1eb3faSJed Brown .ve 4177bc1eb3faSJed Brown 4178bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 4179bc1eb3faSJed Brown .vb 4180bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 4181bc1eb3faSJed Brown .ve 4182bc1eb3faSJed Brown 4183bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 4184bc1eb3faSJed Brown .vb 4185bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 4186bc1eb3faSJed Brown .ve 4187bc1eb3faSJed Brown 4188a4355906SMatthew Knepley Level: developer 4189a4355906SMatthew Knepley 41909df75925SJed Brown .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection() 4191a4355906SMatthew Knepley @*/ 4192bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 41933194fc30SMatthew G. Knepley { 41947391a63aSMatthew G. Knepley DMLabel label; 41953194fc30SMatthew G. Knepley PetscInt *perm; 4196a433471fSStefano Zampini PetscInt dim, depth = -1, eStart = -1, k, Nf, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 41979e8305c2SJed Brown PetscBool vertexchart; 41983194fc30SMatthew G. Knepley PetscErrorCode ierr; 41993194fc30SMatthew G. Knepley 42003194fc30SMatthew G. Knepley PetscFunctionBegin; 42013194fc30SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4202a433471fSStefano Zampini if (dim < 1) PetscFunctionReturn(0); 4203a433471fSStefano Zampini if (point < 0) { 4204a433471fSStefano Zampini PetscInt sStart,sEnd; 4205a433471fSStefano Zampini 4206a433471fSStefano Zampini ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr); 4207a433471fSStefano Zampini point = sEnd-sStart ? sStart : point; 4208a433471fSStefano Zampini } 42097391a63aSMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 4210a433471fSStefano Zampini if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); } 4211a433471fSStefano Zampini if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 42127391a63aSMatthew G. Knepley if (depth == 1) {eStart = point;} 42137391a63aSMatthew G. Knepley else if (depth == dim) { 42147391a63aSMatthew G. Knepley const PetscInt *cone; 42157391a63aSMatthew G. Knepley 42167391a63aSMatthew G. Knepley ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 4217d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 4218d4e6627bSStefano Zampini else if (dim == 3) { 4219d4e6627bSStefano Zampini const PetscInt *cone2; 4220d4e6627bSStefano Zampini ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr); 4221d4e6627bSStefano Zampini eStart = cone2[0]; 4222d4e6627bSStefano Zampini } else SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim); 4223a433471fSStefano Zampini } else if (depth >= 0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim); 42249e8305c2SJed Brown { /* Determine whether the chart covers all points or just vertices. */ 42259e8305c2SJed Brown PetscInt pStart,pEnd,cStart,cEnd; 42269e8305c2SJed Brown ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr); 42279e8305c2SJed Brown ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr); 42289e8305c2SJed Brown if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Just vertices */ 42299e8305c2SJed Brown else vertexchart = PETSC_FALSE; /* Assume all interpolated points are in chart */ 42309e8305c2SJed Brown } 42313194fc30SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 42323194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 42339e8305c2SJed Brown ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 423489eabcffSMatthew G. Knepley size += PetscPowInt(k+1, dim)*Nc; 42353194fc30SMatthew G. Knepley } 42363194fc30SMatthew G. Knepley ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr); 42373194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 423889eabcffSMatthew G. Knepley switch (dim) { 4239babf31e0SJed Brown case 1: 42409e8305c2SJed Brown ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 4241babf31e0SJed Brown /* 4242babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 4243babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 4244babf31e0SJed Brown */ 4245babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset; 4246babf31e0SJed Brown for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset; 4247babf31e0SJed Brown for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset; 4248babf31e0SJed Brown foffset = offset; 4249babf31e0SJed Brown break; 425089eabcffSMatthew G. Knepley case 2: 42513194fc30SMatthew G. Knepley /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 42529e8305c2SJed Brown ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 42533194fc30SMatthew G. Knepley /* The SEM order is 42543194fc30SMatthew G. Knepley 42553194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 425689eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 42573194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 42583194fc30SMatthew G. Knepley */ 42593194fc30SMatthew G. Knepley { 42603194fc30SMatthew G. Knepley const PetscInt of = 0; 42613194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k-1); 42623194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k-1); 42633194fc30SMatthew G. Knepley const PetscInt oet = oer + (k-1); 42643194fc30SMatthew G. Knepley const PetscInt oel = oet + (k-1); 42653194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k-1); 42663194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 42673194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 42683194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 42693194fc30SMatthew G. Knepley PetscInt o; 42703194fc30SMatthew G. Knepley 42713194fc30SMatthew G. Knepley /* bottom */ 42723194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset; 42733194fc30SMatthew G. Knepley for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 42743194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset; 42753194fc30SMatthew G. Knepley /* middle */ 42763194fc30SMatthew G. Knepley for (i = 0; i < k-1; ++i) { 42773194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset; 42783194fc30SMatthew G. Knepley for (o = of+(k-1)*i; o < of+(k-1)*(i+1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 42793194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset; 42803194fc30SMatthew G. Knepley } 42813194fc30SMatthew G. Knepley /* top */ 42823194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset; 42833194fc30SMatthew G. Knepley for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 42843194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset; 42853194fc30SMatthew G. Knepley foffset = offset; 42863194fc30SMatthew G. Knepley } 428789eabcffSMatthew G. Knepley break; 428889eabcffSMatthew G. Knepley case 3: 428989eabcffSMatthew G. Knepley /* The original hex closure is 429089eabcffSMatthew G. Knepley 429189eabcffSMatthew G. Knepley {c, 429289eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 429389eabcffSMatthew G. Knepley e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 429489eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 429589eabcffSMatthew G. Knepley */ 42969e8305c2SJed Brown ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr); 429789eabcffSMatthew G. Knepley /* The SEM order is 429889eabcffSMatthew G. Knepley Bottom Slice 429989eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 430089eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 430189eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 430289eabcffSMatthew G. Knepley 430389eabcffSMatthew G. Knepley Middle Slice (j) 430489eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 430589eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 430689eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 430789eabcffSMatthew G. Knepley 430889eabcffSMatthew G. Knepley Top Slice 430989eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 431089eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 431189eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 431289eabcffSMatthew G. Knepley */ 431389eabcffSMatthew G. Knepley { 431489eabcffSMatthew G. Knepley const PetscInt oc = 0; 431589eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k-1)*(k-1); 431689eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k-1); 431789eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k-1); 431889eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k-1); 431989eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k-1); 432089eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k-1); 432189eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k-1); 432289eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k-1); 432389eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k-1); 432489eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k-1); 432589eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k-1); 432689eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k-1); 432789eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k-1); 432889eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k-1); 432989eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k-1); 433089eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k-1); 433189eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k-1); 433289eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k-1); 433389eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k-1); 433489eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 433589eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 433689eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 433789eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 433889eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 433989eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 434089eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 434189eabcffSMatthew G. Knepley PetscInt o, n; 434289eabcffSMatthew G. Knepley 434389eabcffSMatthew G. Knepley /* Bottom Slice */ 434489eabcffSMatthew G. Knepley /* bottom */ 434589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset; 434689eabcffSMatthew G. Knepley for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 434789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset; 434889eabcffSMatthew G. Knepley /* middle */ 434989eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 435089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset; 4351316b7f87SMax Rietmann for (n = 0; n < k-1; ++n) {o = ofb+n*(k-1)+i; for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;} 435289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset; 43533194fc30SMatthew G. Knepley } 435489eabcffSMatthew G. Knepley /* top */ 435589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset; 435689eabcffSMatthew G. Knepley for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 435789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset; 435889eabcffSMatthew G. Knepley 435989eabcffSMatthew G. Knepley /* Middle Slice */ 436089eabcffSMatthew G. Knepley for (j = 0; j < k-1; ++j) { 436189eabcffSMatthew G. Knepley /* bottom */ 436289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset; 436389eabcffSMatthew G. Knepley for (o = off+j*(k-1); o < off+(j+1)*(k-1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 436489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset; 436589eabcffSMatthew G. Knepley /* middle */ 436689eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 436789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset; 436889eabcffSMatthew G. Knepley for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc+(j*(k-1)+i)*(k-1)+n)*Nc + c + foffset; 436989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset; 437089eabcffSMatthew G. Knepley } 437189eabcffSMatthew G. Knepley /* top */ 437289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset; 437389eabcffSMatthew G. Knepley for (o = ofk+j*(k-1)+(k-2); o >= ofk+j*(k-1); --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 437489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset; 437589eabcffSMatthew G. Knepley } 437689eabcffSMatthew G. Knepley 437789eabcffSMatthew G. Knepley /* Top Slice */ 437889eabcffSMatthew G. Knepley /* bottom */ 437989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset; 438089eabcffSMatthew G. Knepley for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 438189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset; 438289eabcffSMatthew G. Knepley /* middle */ 438389eabcffSMatthew G. Knepley for (i = 0; i < k-1; ++i) { 438489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset; 438589eabcffSMatthew G. Knepley for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset; 438689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset; 438789eabcffSMatthew G. Knepley } 438889eabcffSMatthew G. Knepley /* top */ 438989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset; 439089eabcffSMatthew G. Knepley for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset; 439189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset; 439289eabcffSMatthew G. Knepley 439389eabcffSMatthew G. Knepley foffset = offset; 439489eabcffSMatthew G. Knepley } 439589eabcffSMatthew G. Knepley break; 439689eabcffSMatthew G. Knepley default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", dim); 439789eabcffSMatthew G. Knepley } 439889eabcffSMatthew G. Knepley } 439989eabcffSMatthew G. Knepley if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size); 44003194fc30SMatthew G. Knepley /* Check permutation */ 44013194fc30SMatthew G. Knepley { 44023194fc30SMatthew G. Knepley PetscInt *check; 44033194fc30SMatthew G. Knepley 44043194fc30SMatthew G. Knepley ierr = PetscMalloc1(size, &check);CHKERRQ(ierr); 44053194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) {check[i] = -1; if (perm[i] < 0 || perm[i] >= size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid permutation index p[%D] = %D", i, perm[i]);} 44063194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 44073194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);} 44083194fc30SMatthew G. Knepley ierr = PetscFree(check);CHKERRQ(ierr); 44093194fc30SMatthew G. Knepley } 44101fdd32a2SMatthew G. Knepley ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr); 44113194fc30SMatthew G. Knepley PetscFunctionReturn(0); 44123194fc30SMatthew G. Knepley } 44133194fc30SMatthew G. Knepley 4414e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 4415e071409bSToby Isaac { 4416e071409bSToby Isaac PetscDS prob; 4417e071409bSToby Isaac PetscInt depth, Nf, h; 4418e071409bSToby Isaac DMLabel label; 4419e071409bSToby Isaac PetscErrorCode ierr; 4420e071409bSToby Isaac 4421e071409bSToby Isaac PetscFunctionBeginHot; 4422e5e52638SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 4423e071409bSToby Isaac Nf = prob->Nf; 4424e071409bSToby Isaac label = dm->depthLabel; 4425e071409bSToby Isaac *dspace = NULL; 4426e071409bSToby Isaac if (field < Nf) { 4427e071409bSToby Isaac PetscObject disc = prob->disc[field]; 4428e071409bSToby Isaac 4429e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 4430e071409bSToby Isaac PetscDualSpace dsp; 4431e071409bSToby Isaac 4432e071409bSToby Isaac ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr); 4433e071409bSToby Isaac ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr); 4434e071409bSToby Isaac ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr); 4435e071409bSToby Isaac h = depth - 1 - h; 4436e071409bSToby Isaac if (h) { 4437e071409bSToby Isaac ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr); 4438e071409bSToby Isaac } else { 4439e071409bSToby Isaac *dspace = dsp; 4440e071409bSToby Isaac } 4441e071409bSToby Isaac } 4442e071409bSToby Isaac } 4443e071409bSToby Isaac PetscFunctionReturn(0); 4444e071409bSToby Isaac } 4445e071409bSToby Isaac 4446e071409bSToby Isaac 44471a271a75SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4448a6dfd86eSKarl Rupp { 4449552f7358SJed Brown PetscScalar *array, *vArray; 4450d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 44511a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 4452552f7358SJed Brown PetscErrorCode ierr; 4453552f7358SJed Brown 44541b406b76SMatthew G. Knepley PetscFunctionBeginHot; 44552a3aaacfSMatthew G. Knepley ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 44565a1bb5cfSMatthew G. Knepley ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 44575a1bb5cfSMatthew G. Knepley ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 44585a1bb5cfSMatthew G. Knepley ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 44593f7cbbe7SMatthew G. Knepley if (!values || !*values) { 44609df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 44619df71ca4SMatthew G. Knepley PetscInt dof; 4462d9917b9dSMatthew G. Knepley 44639df71ca4SMatthew G. Knepley ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 44649df71ca4SMatthew G. Knepley size += dof; 44659df71ca4SMatthew G. Knepley } 44669df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 44679df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 44682a3aaacfSMatthew G. Knepley PetscInt dof; 44695a1bb5cfSMatthew G. Knepley 44705a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 44712a3aaacfSMatthew G. Knepley ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 44725a1bb5cfSMatthew G. Knepley size += dof; 44735a1bb5cfSMatthew G. Knepley } 44743f7cbbe7SMatthew G. Knepley if (!values) { 44753f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 44763f7cbbe7SMatthew G. Knepley PetscFunctionReturn(0); 44773f7cbbe7SMatthew G. Knepley } 447869291d52SBarry Smith ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr); 4479982e9ed1SMatthew G. Knepley } else { 4480982e9ed1SMatthew G. Knepley array = *values; 4481982e9ed1SMatthew G. Knepley } 44829df71ca4SMatthew G. Knepley size = 0; 44835a1bb5cfSMatthew G. Knepley ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 44849df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 44859df71ca4SMatthew G. Knepley PetscInt dof, off, d; 44869df71ca4SMatthew G. Knepley PetscScalar *varr; 4487d9917b9dSMatthew G. Knepley 44889df71ca4SMatthew G. Knepley ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 44899df71ca4SMatthew G. Knepley ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 44909df71ca4SMatthew G. Knepley varr = &vArray[off]; 44911a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 44921a271a75SMatthew G. Knepley array[offset] = varr[d]; 44939df71ca4SMatthew G. Knepley } 44949df71ca4SMatthew G. Knepley size += dof; 44959df71ca4SMatthew G. Knepley } 44969df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 44979df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 44989df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 44995a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 45005a1bb5cfSMatthew G. Knepley PetscScalar *varr; 45015a1bb5cfSMatthew G. Knepley 450252ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 45035a1bb5cfSMatthew G. Knepley ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 45045a1bb5cfSMatthew G. Knepley ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 45055a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 45065a1bb5cfSMatthew G. Knepley if (o >= 0) { 45071a271a75SMatthew G. Knepley for (d = 0; d < dof; ++d, ++offset) { 45081a271a75SMatthew G. Knepley array[offset] = varr[d]; 45095a1bb5cfSMatthew G. Knepley } 45105a1bb5cfSMatthew G. Knepley } else { 45111a271a75SMatthew G. Knepley for (d = dof-1; d >= 0; --d, ++offset) { 45121a271a75SMatthew G. Knepley array[offset] = varr[d]; 45135a1bb5cfSMatthew G. Knepley } 45145a1bb5cfSMatthew G. Knepley } 45159df71ca4SMatthew G. Knepley size += dof; 45165a1bb5cfSMatthew G. Knepley } 45175a1bb5cfSMatthew G. Knepley ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 45189df71ca4SMatthew G. Knepley if (!*values) { 45195a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 45205a1bb5cfSMatthew G. Knepley *values = array; 45219df71ca4SMatthew G. Knepley } else { 45228ccfff9cSToby Isaac if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 45238c312ff3SMatthew G. Knepley *csize = size; 45249df71ca4SMatthew G. Knepley } 45255a1bb5cfSMatthew G. Knepley PetscFunctionReturn(0); 45265a1bb5cfSMatthew G. Knepley } 4527d9917b9dSMatthew G. Knepley 452897529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 45291dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 4530923c78e0SToby Isaac { 4531923c78e0SToby Isaac const PetscInt *cla; 4532923c78e0SToby Isaac PetscInt np, *pts = NULL; 4533923c78e0SToby Isaac PetscErrorCode ierr; 4534923c78e0SToby Isaac 4535923c78e0SToby Isaac PetscFunctionBeginHot; 4536923c78e0SToby Isaac ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr); 4537923c78e0SToby Isaac if (!*clPoints) { 4538923c78e0SToby Isaac PetscInt pStart, pEnd, p, q; 4539923c78e0SToby Isaac 4540923c78e0SToby Isaac ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4541923c78e0SToby Isaac ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr); 4542923c78e0SToby Isaac /* Compress out points not in the section */ 4543923c78e0SToby Isaac for (p = 0, q = 0; p < np; p++) { 4544923c78e0SToby Isaac PetscInt r = pts[2*p]; 4545923c78e0SToby Isaac if ((r >= pStart) && (r < pEnd)) { 4546923c78e0SToby Isaac pts[q*2] = r; 4547923c78e0SToby Isaac pts[q*2+1] = pts[2*p+1]; 4548923c78e0SToby Isaac ++q; 4549923c78e0SToby Isaac } 4550923c78e0SToby Isaac } 4551923c78e0SToby Isaac np = q; 4552923c78e0SToby Isaac cla = NULL; 4553923c78e0SToby Isaac } else { 4554923c78e0SToby Isaac PetscInt dof, off; 4555923c78e0SToby Isaac 4556923c78e0SToby Isaac ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr); 4557923c78e0SToby Isaac ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr); 4558923c78e0SToby Isaac ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr); 4559923c78e0SToby Isaac np = dof/2; 4560923c78e0SToby Isaac pts = (PetscInt *) &cla[off]; 4561923c78e0SToby Isaac } 4562923c78e0SToby Isaac *numPoints = np; 4563923c78e0SToby Isaac *points = pts; 4564923c78e0SToby Isaac *clp = cla; 4565923c78e0SToby Isaac 4566923c78e0SToby Isaac PetscFunctionReturn(0); 4567923c78e0SToby Isaac } 4568923c78e0SToby Isaac 45691dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 4570923c78e0SToby Isaac { 4571923c78e0SToby Isaac PetscErrorCode ierr; 4572923c78e0SToby Isaac 4573923c78e0SToby Isaac PetscFunctionBeginHot; 4574923c78e0SToby Isaac if (!*clPoints) { 4575923c78e0SToby Isaac ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr); 4576923c78e0SToby Isaac } else { 4577923c78e0SToby Isaac ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr); 4578923c78e0SToby Isaac } 4579923c78e0SToby Isaac *numPoints = 0; 4580923c78e0SToby Isaac *points = NULL; 4581923c78e0SToby Isaac *clSec = NULL; 4582923c78e0SToby Isaac *clPoints = NULL; 4583923c78e0SToby Isaac *clp = NULL; 4584923c78e0SToby Isaac PetscFunctionReturn(0); 4585923c78e0SToby Isaac } 4586923c78e0SToby Isaac 458797e99dd9SToby Isaac PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 45881a271a75SMatthew G. Knepley { 45891a271a75SMatthew G. Knepley PetscInt offset = 0, p; 459097e99dd9SToby Isaac const PetscInt **perms = NULL; 459197e99dd9SToby Isaac const PetscScalar **flips = NULL; 45921a271a75SMatthew G. Knepley PetscErrorCode ierr; 45931a271a75SMatthew G. Knepley 45941a271a75SMatthew G. Knepley PetscFunctionBeginHot; 4595fe02ba77SJed Brown *size = 0; 459697e99dd9SToby Isaac ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 459797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 459897e99dd9SToby Isaac const PetscInt point = points[2*p]; 459997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 460097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 46011a271a75SMatthew G. Knepley PetscInt dof, off, d; 46021a271a75SMatthew G. Knepley const PetscScalar *varr; 46031a271a75SMatthew G. Knepley 46041a271a75SMatthew G. Knepley ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 46051a271a75SMatthew G. Knepley ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 46061a271a75SMatthew G. Knepley varr = &vArray[off]; 460797e99dd9SToby Isaac if (clperm) { 460897e99dd9SToby Isaac if (perm) { 460997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 46101a271a75SMatthew G. Knepley } else { 461197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] = varr[d]; 461297e99dd9SToby Isaac } 461397e99dd9SToby Isaac if (flip) { 461497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d ]] *= flip[d]; 461597e99dd9SToby Isaac } 461697e99dd9SToby Isaac } else { 461797e99dd9SToby Isaac if (perm) { 461897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 461997e99dd9SToby Isaac } else { 462097e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] = varr[d]; 462197e99dd9SToby Isaac } 462297e99dd9SToby Isaac if (flip) { 462397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d ] *= flip[d]; 46241a271a75SMatthew G. Knepley } 46251a271a75SMatthew G. Knepley } 462697e99dd9SToby Isaac offset += dof; 462797e99dd9SToby Isaac } 462897e99dd9SToby Isaac ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 46291a271a75SMatthew G. Knepley *size = offset; 46301a271a75SMatthew G. Knepley PetscFunctionReturn(0); 46311a271a75SMatthew G. Knepley } 46321a271a75SMatthew G. Knepley 463397e99dd9SToby Isaac PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 46341a271a75SMatthew G. Knepley { 46351a271a75SMatthew G. Knepley PetscInt offset = 0, f; 46361a271a75SMatthew G. Knepley PetscErrorCode ierr; 46371a271a75SMatthew G. Knepley 46381a271a75SMatthew G. Knepley PetscFunctionBeginHot; 4639fe02ba77SJed Brown *size = 0; 46401a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 464197e99dd9SToby Isaac PetscInt p; 464297e99dd9SToby Isaac const PetscInt **perms = NULL; 464397e99dd9SToby Isaac const PetscScalar **flips = NULL; 46441a271a75SMatthew G. Knepley 464597e99dd9SToby Isaac ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 464697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 464797e99dd9SToby Isaac const PetscInt point = points[2*p]; 464897e99dd9SToby Isaac PetscInt fdof, foff, b; 46491a271a75SMatthew G. Knepley const PetscScalar *varr; 465097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 465197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 46521a271a75SMatthew G. Knepley 46531a271a75SMatthew G. Knepley ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 46541a271a75SMatthew G. Knepley ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 46551a271a75SMatthew G. Knepley varr = &vArray[foff]; 465697e99dd9SToby Isaac if (clperm) { 465797e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]] = varr[b];}} 465897e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] = varr[b];}} 465997e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset + b ]] *= flip[b];}} 46601a271a75SMatthew G. Knepley } else { 466197e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]] = varr[b];}} 466297e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {array[offset + b ] = varr[b];}} 466397e99dd9SToby Isaac if (flip) {for (b = 0; b < fdof; b++) {array[offset + b ] *= flip[b];}} 46641a271a75SMatthew G. Knepley } 466597e99dd9SToby Isaac offset += fdof; 46661a271a75SMatthew G. Knepley } 466797e99dd9SToby Isaac ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 46681a271a75SMatthew G. Knepley } 46691a271a75SMatthew G. Knepley *size = offset; 46701a271a75SMatthew G. Knepley PetscFunctionReturn(0); 46711a271a75SMatthew G. Knepley } 46721a271a75SMatthew G. Knepley 4673552f7358SJed Brown /*@C 4674552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 4675552f7358SJed Brown 4676552f7358SJed Brown Not collective 4677552f7358SJed Brown 4678552f7358SJed Brown Input Parameters: 4679552f7358SJed Brown + dm - The DM 4680552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section 4681552f7358SJed Brown . v - The local vector 468222c1ee49SMatthew G. Knepley . point - The point in the DM 468322c1ee49SMatthew G. Knepley . csize - The size of the input values array, or NULL 468422c1ee49SMatthew G. Knepley - values - An array to use for the values, or NULL to have it allocated automatically 4685552f7358SJed Brown 4686552f7358SJed Brown Output Parameters: 468722c1ee49SMatthew G. Knepley + csize - The number of values in the closure 468822c1ee49SMatthew G. Knepley - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed 468922c1ee49SMatthew G. Knepley 469022c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the 469122c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat 469222c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation. 469322c1ee49SMatthew G. Knepley $ 469422c1ee49SMatthew G. Knepley $ A typical use could be 469522c1ee49SMatthew G. Knepley $ 469622c1ee49SMatthew G. Knepley $ values = NULL; 469722c1ee49SMatthew G. Knepley $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 469822c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 469922c1ee49SMatthew G. Knepley $ <Compute on closure> 470022c1ee49SMatthew G. Knepley $ } 470122c1ee49SMatthew G. Knepley $ ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 470222c1ee49SMatthew G. Knepley $ 470322c1ee49SMatthew G. Knepley $ or 470422c1ee49SMatthew G. Knepley $ 470522c1ee49SMatthew G. Knepley $ PetscMalloc1(clMaxSize, &values); 470622c1ee49SMatthew G. Knepley $ for (p = pStart; p < pEnd; ++p) { 470722c1ee49SMatthew G. Knepley $ clSize = clMaxSize; 470822c1ee49SMatthew G. Knepley $ ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr); 470922c1ee49SMatthew G. Knepley $ for (cl = 0; cl < clSize; ++cl) { 471022c1ee49SMatthew G. Knepley $ <Compute on closure> 471122c1ee49SMatthew G. Knepley $ } 471222c1ee49SMatthew G. Knepley $ } 471322c1ee49SMatthew G. Knepley $ PetscFree(values); 4714552f7358SJed Brown 4715552f7358SJed Brown Fortran Notes: 4716552f7358SJed Brown Since it returns an array, this routine is only available in Fortran 90, and you must 4717552f7358SJed Brown include petsc.h90 in your code. 4718552f7358SJed Brown 4719552f7358SJed Brown The csize argument is not present in the Fortran 90 binding since it is internal to the array. 4720552f7358SJed Brown 4721552f7358SJed Brown Level: intermediate 4722552f7358SJed Brown 4723552f7358SJed Brown .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4724552f7358SJed Brown @*/ 4725552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4726552f7358SJed Brown { 4727552f7358SJed Brown PetscSection clSection; 4728d9917b9dSMatthew G. Knepley IS clPoints; 47298a84db2dSMatthew G. Knepley PetscScalar *array; 47308a84db2dSMatthew G. Knepley const PetscScalar *vArray; 4731552f7358SJed Brown PetscInt *points = NULL; 47328f3be42fSMatthew G. Knepley const PetscInt *clp, *perm; 47331a271a75SMatthew G. Knepley PetscInt depth, numFields, numPoints, size; 4734552f7358SJed Brown PetscErrorCode ierr; 4735552f7358SJed Brown 4736d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 4737552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 473892fd8e1eSJed Brown if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 47391a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 47401a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4741552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4742552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4743552f7358SJed Brown if (depth == 1 && numFields < 2) { 47441a271a75SMatthew G. Knepley ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 4745552f7358SJed Brown PetscFunctionReturn(0); 4746552f7358SJed Brown } 47471a271a75SMatthew G. Knepley /* Get points */ 4748923c78e0SToby Isaac ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 47491fdd32a2SMatthew G. Knepley ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 47501a271a75SMatthew G. Knepley /* Get array */ 4751bd6c0d32SMatthew G. Knepley if (!values || !*values) { 47521a271a75SMatthew G. Knepley PetscInt asize = 0, dof, p; 4753552f7358SJed Brown 47541a271a75SMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 4755552f7358SJed Brown ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 47561a271a75SMatthew G. Knepley asize += dof; 4757552f7358SJed Brown } 4758bd6c0d32SMatthew G. Knepley if (!values) { 4759923c78e0SToby Isaac ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 47601a271a75SMatthew G. Knepley if (csize) *csize = asize; 4761bd6c0d32SMatthew G. Knepley PetscFunctionReturn(0); 4762bd6c0d32SMatthew G. Knepley } 476369291d52SBarry Smith ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 4764d0f6b257SMatthew G. Knepley } else { 4765d0f6b257SMatthew G. Knepley array = *values; 4766d0f6b257SMatthew G. Knepley } 47678a84db2dSMatthew G. Knepley ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 47681a271a75SMatthew G. Knepley /* Get values */ 476997e99dd9SToby Isaac if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 477097e99dd9SToby Isaac else {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, array);CHKERRQ(ierr);} 47711a271a75SMatthew G. Knepley /* Cleanup points */ 4772923c78e0SToby Isaac ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 47731a271a75SMatthew G. Knepley /* Cleanup array */ 47748a84db2dSMatthew G. Knepley ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 4775d0f6b257SMatthew G. Knepley if (!*values) { 4776552f7358SJed Brown if (csize) *csize = size; 4777552f7358SJed Brown *values = array; 4778d0f6b257SMatthew G. Knepley } else { 4779f347f43bSBarry Smith if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4780d0f6b257SMatthew G. Knepley *csize = size; 4781d0f6b257SMatthew G. Knepley } 4782552f7358SJed Brown PetscFunctionReturn(0); 4783552f7358SJed Brown } 4784552f7358SJed Brown 4785*e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 4786*e5c487bfSMatthew G. Knepley { 4787*e5c487bfSMatthew G. Knepley DMLabel depthLabel; 4788*e5c487bfSMatthew G. Knepley PetscSection clSection; 4789*e5c487bfSMatthew G. Knepley IS clPoints; 4790*e5c487bfSMatthew G. Knepley PetscScalar *array; 4791*e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 4792*e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 4793*e5c487bfSMatthew G. Knepley const PetscInt *clp, *perm; 4794*e5c487bfSMatthew G. Knepley PetscInt mdepth, numFields, numPoints, Np = 0, p, size; 4795*e5c487bfSMatthew G. Knepley PetscErrorCode ierr; 4796*e5c487bfSMatthew G. Knepley 4797*e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 4798*e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4799*e5c487bfSMatthew G. Knepley if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 4800*e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4801*e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 4802*e5c487bfSMatthew G. Knepley ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr); 4803*e5c487bfSMatthew G. Knepley ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 4804*e5c487bfSMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4805*e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 4806*e5c487bfSMatthew G. Knepley ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 4807*e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 4808*e5c487bfSMatthew G. Knepley } 4809*e5c487bfSMatthew G. Knepley /* Get points */ 4810*e5c487bfSMatthew G. Knepley ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4811*e5c487bfSMatthew G. Knepley ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &perm);CHKERRQ(ierr); 4812*e5c487bfSMatthew G. Knepley /* Filter points */ 4813*e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 4814*e5c487bfSMatthew G. Knepley PetscInt dep; 4815*e5c487bfSMatthew G. Knepley 4816*e5c487bfSMatthew G. Knepley ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr); 4817*e5c487bfSMatthew G. Knepley if (dep != depth) continue; 4818*e5c487bfSMatthew G. Knepley points[Np*2+0] = points[p]; 4819*e5c487bfSMatthew G. Knepley points[Np*2+1] = points[p+1]; 4820*e5c487bfSMatthew G. Knepley ++Np; 4821*e5c487bfSMatthew G. Knepley } 4822*e5c487bfSMatthew G. Knepley /* Get array */ 4823*e5c487bfSMatthew G. Knepley if (!values || !*values) { 4824*e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 4825*e5c487bfSMatthew G. Knepley 4826*e5c487bfSMatthew G. Knepley for (p = 0; p < Np*2; p += 2) { 4827*e5c487bfSMatthew G. Knepley ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4828*e5c487bfSMatthew G. Knepley asize += dof; 4829*e5c487bfSMatthew G. Knepley } 4830*e5c487bfSMatthew G. Knepley if (!values) { 4831*e5c487bfSMatthew G. Knepley ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4832*e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 4833*e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 4834*e5c487bfSMatthew G. Knepley } 4835*e5c487bfSMatthew G. Knepley ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr); 4836*e5c487bfSMatthew G. Knepley } else { 4837*e5c487bfSMatthew G. Knepley array = *values; 4838*e5c487bfSMatthew G. Knepley } 4839*e5c487bfSMatthew G. Knepley ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr); 4840*e5c487bfSMatthew G. Knepley /* Get values */ 4841*e5c487bfSMatthew G. Knepley if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);} 4842*e5c487bfSMatthew G. Knepley else {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);} 4843*e5c487bfSMatthew G. Knepley /* Cleanup points */ 4844*e5c487bfSMatthew G. Knepley ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 4845*e5c487bfSMatthew G. Knepley /* Cleanup array */ 4846*e5c487bfSMatthew G. Knepley ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr); 4847*e5c487bfSMatthew G. Knepley if (!*values) { 4848*e5c487bfSMatthew G. Knepley if (csize) *csize = size; 4849*e5c487bfSMatthew G. Knepley *values = array; 4850*e5c487bfSMatthew G. Knepley } else { 4851*e5c487bfSMatthew G. Knepley if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 4852*e5c487bfSMatthew G. Knepley *csize = size; 4853*e5c487bfSMatthew G. Knepley } 4854*e5c487bfSMatthew G. Knepley PetscFunctionReturn(0); 4855*e5c487bfSMatthew G. Knepley } 4856*e5c487bfSMatthew G. Knepley 4857552f7358SJed Brown /*@C 4858552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 4859552f7358SJed Brown 4860552f7358SJed Brown Not collective 4861552f7358SJed Brown 4862552f7358SJed Brown Input Parameters: 4863552f7358SJed Brown + dm - The DM 48640298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section 4865552f7358SJed Brown . v - The local vector 4866eaf898f9SPatrick Sanan . point - The point in the DM 48670298fd71SBarry Smith . csize - The number of values in the closure, or NULL 4868552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 4869552f7358SJed Brown 487022c1ee49SMatthew G. Knepley Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure() 487122c1ee49SMatthew G. Knepley 48723813dfbdSMatthew G Knepley Fortran Notes: 48733813dfbdSMatthew G Knepley Since it returns an array, this routine is only available in Fortran 90, and you must 48743813dfbdSMatthew G Knepley include petsc.h90 in your code. 48753813dfbdSMatthew G Knepley 48763813dfbdSMatthew G Knepley The csize argument is not present in the Fortran 90 binding since it is internal to the array. 48773813dfbdSMatthew G Knepley 4878552f7358SJed Brown Level: intermediate 4879552f7358SJed Brown 4880552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 4881552f7358SJed Brown @*/ 48827c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 4883a6dfd86eSKarl Rupp { 4884552f7358SJed Brown PetscInt size = 0; 4885552f7358SJed Brown PetscErrorCode ierr; 4886552f7358SJed Brown 4887552f7358SJed Brown PetscFunctionBegin; 4888552f7358SJed Brown /* Should work without recalculating size */ 488969291d52SBarry Smith ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr); 4890c9fdaa05SMatthew G. Knepley *values = NULL; 4891552f7358SJed Brown PetscFunctionReturn(0); 4892552f7358SJed Brown } 4893552f7358SJed Brown 4894552f7358SJed Brown PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 4895552f7358SJed Brown PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 4896552f7358SJed Brown 489797e99dd9SToby Isaac PETSC_STATIC_INLINE PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 4898552f7358SJed Brown { 4899552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 4900552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4901552f7358SJed Brown PetscScalar *a; 4902552f7358SJed Brown PetscInt off, cind = 0, k; 4903552f7358SJed Brown PetscErrorCode ierr; 4904552f7358SJed Brown 4905552f7358SJed Brown PetscFunctionBegin; 4906552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4907552f7358SJed Brown ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4908552f7358SJed Brown a = &array[off]; 4909552f7358SJed Brown if (!cdof || setBC) { 491097e99dd9SToby Isaac if (clperm) { 491197e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}} 491297e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.));}} 4913552f7358SJed Brown } else { 491497e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}} 491597e99dd9SToby Isaac else {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.));}} 4916552f7358SJed Brown } 4917552f7358SJed Brown } else { 4918552f7358SJed Brown ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 491997e99dd9SToby Isaac if (clperm) { 492097e99dd9SToby Isaac if (perm) {for (k = 0; k < dof; ++k) { 4921552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 492297e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 4923552f7358SJed Brown } 4924552f7358SJed Brown } else { 4925552f7358SJed Brown for (k = 0; k < dof; ++k) { 4926552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 492797e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 492897e99dd9SToby Isaac } 492997e99dd9SToby Isaac } 493097e99dd9SToby Isaac } else { 493197e99dd9SToby Isaac if (perm) { 493297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 493397e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 493497e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 493597e99dd9SToby Isaac } 493697e99dd9SToby Isaac } else { 493797e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 493897e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 493997e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 494097e99dd9SToby Isaac } 4941552f7358SJed Brown } 4942552f7358SJed Brown } 4943552f7358SJed Brown } 4944552f7358SJed Brown PetscFunctionReturn(0); 4945552f7358SJed Brown } 4946552f7358SJed Brown 494797e99dd9SToby Isaac PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 4948a5e93ea8SMatthew G. Knepley { 4949a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 4950a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4951a5e93ea8SMatthew G. Knepley PetscScalar *a; 4952a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 4953a5e93ea8SMatthew G. Knepley PetscErrorCode ierr; 4954a5e93ea8SMatthew G. Knepley 4955a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 4956a5e93ea8SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4957a5e93ea8SMatthew G. Knepley ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 4958a5e93ea8SMatthew G. Knepley a = &array[off]; 4959a5e93ea8SMatthew G. Knepley if (cdof) { 4960a5e93ea8SMatthew G. Knepley ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 496197e99dd9SToby Isaac if (clperm) { 496297e99dd9SToby Isaac if (perm) { 4963a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 4964a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 496597e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.)); 496697e99dd9SToby Isaac cind++; 4967a5e93ea8SMatthew G. Knepley } 4968a5e93ea8SMatthew G. Knepley } 4969a5e93ea8SMatthew G. Knepley } else { 4970a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 4971a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 497297e99dd9SToby Isaac fuse(&a[k], values[clperm[offset+ k ]] * (flip ? flip[ k ] : 1.)); 497397e99dd9SToby Isaac cind++; 497497e99dd9SToby Isaac } 497597e99dd9SToby Isaac } 497697e99dd9SToby Isaac } 497797e99dd9SToby Isaac } else { 497897e99dd9SToby Isaac if (perm) { 497997e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 498097e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 498197e99dd9SToby Isaac fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.)); 498297e99dd9SToby Isaac cind++; 498397e99dd9SToby Isaac } 498497e99dd9SToby Isaac } 498597e99dd9SToby Isaac } else { 498697e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 498797e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 498897e99dd9SToby Isaac fuse(&a[k], values[offset+ k ] * (flip ? flip[ k ] : 1.)); 498997e99dd9SToby Isaac cind++; 499097e99dd9SToby Isaac } 4991a5e93ea8SMatthew G. Knepley } 4992a5e93ea8SMatthew G. Knepley } 4993a5e93ea8SMatthew G. Knepley } 4994a5e93ea8SMatthew G. Knepley } 4995a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 4996a5e93ea8SMatthew G. Knepley } 4997a5e93ea8SMatthew G. Knepley 499897e99dd9SToby Isaac PETSC_STATIC_INLINE PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, const PetscInt *perm, const PetscScalar *flip, PetscInt f, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 4999a6dfd86eSKarl Rupp { 5000552f7358SJed Brown PetscScalar *a; 50011a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 50021a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 500397e99dd9SToby Isaac PetscInt cind = 0, b; 5004552f7358SJed Brown PetscErrorCode ierr; 5005552f7358SJed Brown 5006552f7358SJed Brown PetscFunctionBegin; 5007552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5008552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 50091a271a75SMatthew G. Knepley ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 50101a271a75SMatthew G. Knepley a = &array[foff]; 5011552f7358SJed Brown if (!fcdof || setBC) { 501297e99dd9SToby Isaac if (clperm) { 501397e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}} 501497e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));}} 5015552f7358SJed Brown } else { 501697e99dd9SToby Isaac if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}} 501797e99dd9SToby Isaac else {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));}} 5018552f7358SJed Brown } 5019552f7358SJed Brown } else { 5020552f7358SJed Brown ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 502197e99dd9SToby Isaac if (clperm) { 502297e99dd9SToby Isaac if (perm) { 502397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 502497e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 502597e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5026552f7358SJed Brown } 5027552f7358SJed Brown } else { 502897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 502997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 503097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 503197e99dd9SToby Isaac } 503297e99dd9SToby Isaac } 503397e99dd9SToby Isaac } else { 503497e99dd9SToby Isaac if (perm) { 503597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 503697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 503797e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 503897e99dd9SToby Isaac } 503997e99dd9SToby Isaac } else { 504097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 504197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;} 504297e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5043552f7358SJed Brown } 5044552f7358SJed Brown } 5045552f7358SJed Brown } 5046552f7358SJed Brown } 50471a271a75SMatthew G. Knepley *offset += fdof; 5048552f7358SJed Brown PetscFunctionReturn(0); 5049552f7358SJed Brown } 5050552f7358SJed Brown 5051ba322698SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, const PetscInt perm[], const PetscScalar flip[], PetscInt f, PetscInt Ncc, const PetscInt comps[], void (*fuse)(PetscScalar*, PetscScalar), const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 5052a5e93ea8SMatthew G. Knepley { 5053a5e93ea8SMatthew G. Knepley PetscScalar *a; 50541a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 50551a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 50565da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 5057ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 5058a5e93ea8SMatthew G. Knepley PetscErrorCode ierr; 5059a5e93ea8SMatthew G. Knepley 5060a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 50615da9d227SMatthew G. Knepley ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr); 5062a5e93ea8SMatthew G. Knepley ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5063a5e93ea8SMatthew G. Knepley ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 50641a271a75SMatthew G. Knepley ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 50651a271a75SMatthew G. Knepley a = &array[foff]; 5066a5e93ea8SMatthew G. Knepley if (fcdof) { 5067ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 5068a5e93ea8SMatthew G. Knepley ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 506997e99dd9SToby Isaac if (clperm) { 507097e99dd9SToby Isaac if (perm) { 5071ba322698SMatthew G. Knepley if (comps) { 5072ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 5073ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 50745da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5075ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5076ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));} 5077ba322698SMatthew G. Knepley } 5078ba322698SMatthew G. Knepley } else { 507997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 508097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 508197e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.)); 5082a5e93ea8SMatthew G. Knepley ++cind; 5083a5e93ea8SMatthew G. Knepley } 5084a5e93ea8SMatthew G. Knepley } 5085ba322698SMatthew G. Knepley } 5086ba322698SMatthew G. Knepley } else { 5087ba322698SMatthew G. Knepley if (comps) { 5088ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 5089ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 50905da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5091ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5092ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.));} 5093ba322698SMatthew G. Knepley } 5094a5e93ea8SMatthew G. Knepley } else { 509597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 509697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 509797e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset+ b ]] * (flip ? flip[ b ] : 1.)); 509897e99dd9SToby Isaac ++cind; 509997e99dd9SToby Isaac } 510097e99dd9SToby Isaac } 510197e99dd9SToby Isaac } 5102ba322698SMatthew G. Knepley } 510397e99dd9SToby Isaac } else { 510497e99dd9SToby Isaac if (perm) { 5105ba322698SMatthew G. Knepley if (comps) { 5106ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 5107ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 51085da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5109ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5110ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));} 5111ba322698SMatthew G. Knepley } 5112ba322698SMatthew G. Knepley } else { 511397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 511497e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 511597e99dd9SToby Isaac fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.)); 511697e99dd9SToby Isaac ++cind; 511797e99dd9SToby Isaac } 511897e99dd9SToby Isaac } 5119ba322698SMatthew G. Knepley } 5120ba322698SMatthew G. Knepley } else { 5121ba322698SMatthew G. Knepley if (comps) { 5122ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 5123ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 51245da9d227SMatthew G. Knepley if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;} 5125ba322698SMatthew G. Knepley if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; fcSet = PETSC_TRUE;} 5126ba322698SMatthew G. Knepley if (ncSet && fcSet) {fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.));} 5127ba322698SMatthew G. Knepley } 512897e99dd9SToby Isaac } else { 512997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 513097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 513197e99dd9SToby Isaac fuse(&a[b], values[foffset+ b ] * (flip ? flip[ b ] : 1.)); 5132a5e93ea8SMatthew G. Knepley ++cind; 5133a5e93ea8SMatthew G. Knepley } 5134a5e93ea8SMatthew G. Knepley } 5135a5e93ea8SMatthew G. Knepley } 5136a5e93ea8SMatthew G. Knepley } 5137a5e93ea8SMatthew G. Knepley } 5138ba322698SMatthew G. Knepley } 51391a271a75SMatthew G. Knepley *offset += fdof; 5140a5e93ea8SMatthew G. Knepley PetscFunctionReturn(0); 5141a5e93ea8SMatthew G. Knepley } 5142a5e93ea8SMatthew G. Knepley 51438f3be42fSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 5144a6dfd86eSKarl Rupp { 5145552f7358SJed Brown PetscScalar *array; 51461b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 51471b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 5148552f7358SJed Brown PetscErrorCode ierr; 5149552f7358SJed Brown 51501b406b76SMatthew G. Knepley PetscFunctionBeginHot; 5151b6ebb6e6SMatthew G. Knepley ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5152b6ebb6e6SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 5153b6ebb6e6SMatthew G. Knepley ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 5154b6ebb6e6SMatthew G. Knepley ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 5155b6ebb6e6SMatthew G. Knepley ierr = VecGetArray(v, &array);CHKERRQ(ierr); 5156b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 5157b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p-1]; 5158b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p-1]; 5159b6ebb6e6SMatthew G. Knepley 5160b6ebb6e6SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 5161b6ebb6e6SMatthew G. Knepley ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 5162b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 5163b6ebb6e6SMatthew G. Knepley { 5164b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5165b6ebb6e6SMatthew G. Knepley PetscScalar *a; 5166b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 5167b6ebb6e6SMatthew G. Knepley 5168b6ebb6e6SMatthew G. Knepley ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 5169b6ebb6e6SMatthew G. Knepley ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 5170b6ebb6e6SMatthew G. Knepley a = &array[coff]; 5171b6ebb6e6SMatthew G. Knepley if (!cdof) { 5172b6ebb6e6SMatthew G. Knepley if (o >= 0) { 5173b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 5174b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 5175b6ebb6e6SMatthew G. Knepley } 5176b6ebb6e6SMatthew G. Knepley } else { 5177b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 5178b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 5179b6ebb6e6SMatthew G. Knepley } 5180b6ebb6e6SMatthew G. Knepley } 5181b6ebb6e6SMatthew G. Knepley } else { 5182b6ebb6e6SMatthew G. Knepley ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 5183b6ebb6e6SMatthew G. Knepley if (o >= 0) { 5184b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 5185b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5186b6ebb6e6SMatthew G. Knepley a[k] += values[off+k]; 5187b6ebb6e6SMatthew G. Knepley } 5188b6ebb6e6SMatthew G. Knepley } else { 5189b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 5190b6ebb6e6SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 5191b6ebb6e6SMatthew G. Knepley a[k] += values[off+dof-k-1]; 5192b6ebb6e6SMatthew G. Knepley } 5193b6ebb6e6SMatthew G. Knepley } 5194b6ebb6e6SMatthew G. Knepley } 5195b6ebb6e6SMatthew G. Knepley } 5196b6ebb6e6SMatthew G. Knepley } 5197b6ebb6e6SMatthew G. Knepley ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5198b6ebb6e6SMatthew G. Knepley PetscFunctionReturn(0); 5199b6ebb6e6SMatthew G. Knepley } 52001b406b76SMatthew G. Knepley 52011b406b76SMatthew G. Knepley /*@C 52021b406b76SMatthew G. Knepley DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 52031b406b76SMatthew G. Knepley 52041b406b76SMatthew G. Knepley Not collective 52051b406b76SMatthew G. Knepley 52061b406b76SMatthew G. Knepley Input Parameters: 52071b406b76SMatthew G. Knepley + dm - The DM 52081b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section 52091b406b76SMatthew G. Knepley . v - The local vector 5210eaf898f9SPatrick Sanan . point - The point in the DM 52111b406b76SMatthew G. Knepley . values - The array of values 521222c1ee49SMatthew G. Knepley - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES, 521322c1ee49SMatthew G. Knepley where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions. 52141b406b76SMatthew G. Knepley 52151b406b76SMatthew G. Knepley Fortran Notes: 52161b406b76SMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 52171b406b76SMatthew G. Knepley 52181b406b76SMatthew G. Knepley Level: intermediate 52191b406b76SMatthew G. Knepley 52201b406b76SMatthew G. Knepley .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 52211b406b76SMatthew G. Knepley @*/ 52221b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 52231b406b76SMatthew G. Knepley { 52241b406b76SMatthew G. Knepley PetscSection clSection; 52251b406b76SMatthew G. Knepley IS clPoints; 52261b406b76SMatthew G. Knepley PetscScalar *array; 52271b406b76SMatthew G. Knepley PetscInt *points = NULL; 522897e99dd9SToby Isaac const PetscInt *clp, *clperm; 52291a271a75SMatthew G. Knepley PetscInt depth, numFields, numPoints, p; 52301b406b76SMatthew G. Knepley PetscErrorCode ierr; 52311b406b76SMatthew G. Knepley 52321a271a75SMatthew G. Knepley PetscFunctionBeginHot; 52331b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 523492fd8e1eSJed Brown if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 52351a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 52361a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 52371b406b76SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 52381b406b76SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 52391b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 52408f3be42fSMatthew G. Knepley ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 52411b406b76SMatthew G. Knepley PetscFunctionReturn(0); 52421b406b76SMatthew G. Knepley } 52431a271a75SMatthew G. Knepley /* Get points */ 524497e99dd9SToby Isaac ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 5245923c78e0SToby Isaac ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 52461a271a75SMatthew G. Knepley /* Get array */ 5247552f7358SJed Brown ierr = VecGetArray(v, &array);CHKERRQ(ierr); 52481a271a75SMatthew G. Knepley /* Get values */ 5249ef90cfe2SMatthew G. Knepley if (numFields > 0) { 525097e99dd9SToby Isaac PetscInt offset = 0, f; 5251552f7358SJed Brown for (f = 0; f < numFields; ++f) { 525297e99dd9SToby Isaac const PetscInt **perms = NULL; 525397e99dd9SToby Isaac const PetscScalar **flips = NULL; 525497e99dd9SToby Isaac 525597e99dd9SToby Isaac ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5256552f7358SJed Brown switch (mode) { 5257552f7358SJed Brown case INSERT_VALUES: 525897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 525997e99dd9SToby Isaac const PetscInt point = points[2*p]; 526097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 526197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 526297e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array); 5263552f7358SJed Brown } break; 5264552f7358SJed Brown case INSERT_ALL_VALUES: 526597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 526697e99dd9SToby Isaac const PetscInt point = points[2*p]; 526797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 526897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 526997e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array); 5270552f7358SJed Brown } break; 5271a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 527297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 527397e99dd9SToby Isaac const PetscInt point = points[2*p]; 527497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 527597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 5276ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array); 5277a5e93ea8SMatthew G. Knepley } break; 5278552f7358SJed Brown case ADD_VALUES: 527997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 528097e99dd9SToby Isaac const PetscInt point = points[2*p]; 528197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 528297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 528397e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array); 5284552f7358SJed Brown } break; 5285552f7358SJed Brown case ADD_ALL_VALUES: 528697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 528797e99dd9SToby Isaac const PetscInt point = points[2*p]; 528897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 528997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 529097e99dd9SToby Isaac updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array); 5291552f7358SJed Brown } break; 5292304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 529397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 529497e99dd9SToby Isaac const PetscInt point = points[2*p]; 529597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 529697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 5297ba322698SMatthew G. Knepley updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array); 5298304ab55fSMatthew G. Knepley } break; 5299552f7358SJed Brown default: 5300f347f43bSBarry Smith SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 5301552f7358SJed Brown } 530297e99dd9SToby Isaac ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 53031a271a75SMatthew G. Knepley } 5304552f7358SJed Brown } else { 53051a271a75SMatthew G. Knepley PetscInt dof, off; 530697e99dd9SToby Isaac const PetscInt **perms = NULL; 530797e99dd9SToby Isaac const PetscScalar **flips = NULL; 53081a271a75SMatthew G. Knepley 530997e99dd9SToby Isaac ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5310552f7358SJed Brown switch (mode) { 5311552f7358SJed Brown case INSERT_VALUES: 531297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 531397e99dd9SToby Isaac const PetscInt point = points[2*p]; 531497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 531597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 531697e99dd9SToby Isaac ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 531797e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array); 5318552f7358SJed Brown } break; 5319552f7358SJed Brown case INSERT_ALL_VALUES: 532097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 532197e99dd9SToby Isaac const PetscInt point = points[2*p]; 532297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 532397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 532497e99dd9SToby Isaac ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 532597e99dd9SToby Isaac updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array); 5326552f7358SJed Brown } break; 5327a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 532897e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 532997e99dd9SToby Isaac const PetscInt point = points[2*p]; 533097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 533197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 533297e99dd9SToby Isaac ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 533397e99dd9SToby Isaac updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array); 5334a5e93ea8SMatthew G. Knepley } break; 5335552f7358SJed Brown case ADD_VALUES: 533697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 533797e99dd9SToby Isaac const PetscInt point = points[2*p]; 533897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 533997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 534097e99dd9SToby Isaac ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 534197e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array); 5342552f7358SJed Brown } break; 5343552f7358SJed Brown case ADD_ALL_VALUES: 534497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 534597e99dd9SToby Isaac const PetscInt point = points[2*p]; 534697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 534797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 534897e99dd9SToby Isaac ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 534997e99dd9SToby Isaac updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array); 5350552f7358SJed Brown } break; 5351304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 535297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 535397e99dd9SToby Isaac const PetscInt point = points[2*p]; 535497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 535597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 535697e99dd9SToby Isaac ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 535797e99dd9SToby Isaac updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array); 5358304ab55fSMatthew G. Knepley } break; 5359552f7358SJed Brown default: 5360f347f43bSBarry Smith SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 5361552f7358SJed Brown } 536297e99dd9SToby Isaac ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5363552f7358SJed Brown } 53641a271a75SMatthew G. Knepley /* Cleanup points */ 5365923c78e0SToby Isaac ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 53661a271a75SMatthew G. Knepley /* Cleanup array */ 5367552f7358SJed Brown ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5368552f7358SJed Brown PetscFunctionReturn(0); 5369552f7358SJed Brown } 5370552f7358SJed Brown 53715f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 53725f790a90SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset) 53735f790a90SMatthew G. Knepley { 53745f790a90SMatthew G. Knepley PetscFunctionBegin; 53755f790a90SMatthew G. Knepley if (label) { 53765f790a90SMatthew G. Knepley PetscInt val, fdof; 53775f790a90SMatthew G. Knepley PetscErrorCode ierr; 53785f790a90SMatthew G. Knepley 53795f790a90SMatthew G. Knepley /* There is a problem with this: 53805f790a90SMatthew G. Knepley Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that 53815f790a90SMatthew G. Knepley touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell. 53825f790a90SMatthew G. Knepley Thus I am only going to check val != -1, not val != labelId 53835f790a90SMatthew G. Knepley */ 53845f790a90SMatthew G. Knepley ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 53855f790a90SMatthew G. Knepley if (val < 0) { 53865f790a90SMatthew G. Knepley ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 53875f790a90SMatthew G. Knepley *offset += fdof; 53885f790a90SMatthew G. Knepley PetscFunctionReturn(1); 53895f790a90SMatthew G. Knepley } 53905f790a90SMatthew G. Knepley } 53915f790a90SMatthew G. Knepley PetscFunctionReturn(0); 53925f790a90SMatthew G. Knepley } 53935f790a90SMatthew G. Knepley 539497529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 53955f790a90SMatthew G. Knepley PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt labelId, const PetscScalar values[], InsertMode mode) 5396e07394fbSMatthew G. Knepley { 5397e07394fbSMatthew G. Knepley PetscSection clSection; 5398e07394fbSMatthew G. Knepley IS clPoints; 5399e07394fbSMatthew G. Knepley PetscScalar *array; 5400e07394fbSMatthew G. Knepley PetscInt *points = NULL; 540197529cf3SJed Brown const PetscInt *clp; 5402e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 540397e99dd9SToby Isaac PetscInt offset = 0, f; 5404e07394fbSMatthew G. Knepley PetscErrorCode ierr; 5405e07394fbSMatthew G. Knepley 5406e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 5407e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 540892fd8e1eSJed Brown if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 5409e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5410e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 5411e07394fbSMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5412e07394fbSMatthew G. Knepley /* Get points */ 5413923c78e0SToby Isaac ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5414e07394fbSMatthew G. Knepley /* Get array */ 5415e07394fbSMatthew G. Knepley ierr = VecGetArray(v, &array);CHKERRQ(ierr); 5416e07394fbSMatthew G. Knepley /* Get values */ 5417e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 541897e99dd9SToby Isaac const PetscInt **perms = NULL; 541997e99dd9SToby Isaac const PetscScalar **flips = NULL; 542097e99dd9SToby Isaac 5421e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 5422e07394fbSMatthew G. Knepley for (p = 0; p < numPoints*2; p += 2) { 5423e07394fbSMatthew G. Knepley PetscInt fdof; 5424e07394fbSMatthew G. Knepley ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 5425e07394fbSMatthew G. Knepley offset += fdof; 5426e07394fbSMatthew G. Knepley } 5427e07394fbSMatthew G. Knepley continue; 5428e07394fbSMatthew G. Knepley } 542997e99dd9SToby Isaac ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5430e07394fbSMatthew G. Knepley switch (mode) { 5431e07394fbSMatthew G. Knepley case INSERT_VALUES: 543297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 543397e99dd9SToby Isaac const PetscInt point = points[2*p]; 543497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 543597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 54365f790a90SMatthew G. Knepley ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 543797529cf3SJed Brown updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array); 5438e07394fbSMatthew G. Knepley } break; 5439e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 544097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 544197e99dd9SToby Isaac const PetscInt point = points[2*p]; 544297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 544397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 54445f790a90SMatthew G. Knepley ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 544597529cf3SJed Brown updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array); 5446e07394fbSMatthew G. Knepley } break; 5447e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 544897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 544997e99dd9SToby Isaac const PetscInt point = points[2*p]; 545097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 545197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 54525f790a90SMatthew G. Knepley ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 545397529cf3SJed Brown updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array); 5454e07394fbSMatthew G. Knepley } break; 5455e07394fbSMatthew G. Knepley case ADD_VALUES: 545697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 545797e99dd9SToby Isaac const PetscInt point = points[2*p]; 545897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 545997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 54605f790a90SMatthew G. Knepley ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 546197529cf3SJed Brown updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array); 5462e07394fbSMatthew G. Knepley } break; 5463e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 546497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 546597e99dd9SToby Isaac const PetscInt point = points[2*p]; 546697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 546797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 54685f790a90SMatthew G. Knepley ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue; 546997529cf3SJed Brown updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array); 5470e07394fbSMatthew G. Knepley } break; 5471e07394fbSMatthew G. Knepley default: 5472f347f43bSBarry Smith SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 5473e07394fbSMatthew G. Knepley } 547497e99dd9SToby Isaac ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr); 5475e07394fbSMatthew G. Knepley } 5476e07394fbSMatthew G. Knepley /* Cleanup points */ 5477923c78e0SToby Isaac ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 5478e07394fbSMatthew G. Knepley /* Cleanup array */ 5479e07394fbSMatthew G. Knepley ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 5480e07394fbSMatthew G. Knepley PetscFunctionReturn(0); 5481e07394fbSMatthew G. Knepley } 5482e07394fbSMatthew G. Knepley 54837cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 5484552f7358SJed Brown { 5485552f7358SJed Brown PetscMPIInt rank; 5486552f7358SJed Brown PetscInt i, j; 5487552f7358SJed Brown PetscErrorCode ierr; 5488552f7358SJed Brown 5489552f7358SJed Brown PetscFunctionBegin; 549082f516ccSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 5491eaf898f9SPatrick Sanan ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr); 5492e4b003c7SBarry Smith for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 5493e4b003c7SBarry Smith for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 5494b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 5495b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 5496e4b003c7SBarry Smith ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 5497b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 5498519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 54997eba1a17SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 5500552f7358SJed Brown #else 5501b0ecff45SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 5502552f7358SJed Brown #endif 5503552f7358SJed Brown } 550477a6746dSMatthew G Knepley ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 5505552f7358SJed Brown } 5506552f7358SJed Brown PetscFunctionReturn(0); 5507552f7358SJed Brown } 5508552f7358SJed Brown 550905586334SMatthew G. Knepley /* 551005586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 551105586334SMatthew G. Knepley 551205586334SMatthew G. Knepley Input Parameters: 551305586334SMatthew G. Knepley + section - The section for this data layout 551436fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 551505586334SMatthew G. Knepley . point - The point contributing dofs with these indices 551605586334SMatthew G. Knepley . off - The global offset of this point 551705586334SMatthew G. Knepley . loff - The local offset of each field 551805586334SMatthew G. Knepley . setBC - The flag determining whether to include indices of bounsary values 551905586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 552005586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 552105586334SMatthew G. Knepley 552205586334SMatthew G. Knepley Output Parameter: 552305586334SMatthew G. Knepley . indices - Indices for dofs on this point 552405586334SMatthew G. Knepley 552505586334SMatthew G. Knepley Level: developer 552605586334SMatthew G. Knepley 552705586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 552805586334SMatthew G. Knepley */ 552936fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 5530a6dfd86eSKarl Rupp { 5531e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 5532552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 5533552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 5534552f7358SJed Brown PetscInt cind = 0, k; 5535552f7358SJed Brown PetscErrorCode ierr; 5536552f7358SJed Brown 5537552f7358SJed Brown PetscFunctionBegin; 553836fa2b79SJed Brown if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 5539552f7358SJed Brown ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 5540552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 5541552f7358SJed Brown if (!cdof || setBC) { 554205586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 554305586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 554405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 554505586334SMatthew G. Knepley 554605586334SMatthew G. Knepley indices[ind] = off + k; 5547552f7358SJed Brown } 5548552f7358SJed Brown } else { 5549552f7358SJed Brown ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 55504acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 555105586334SMatthew G. Knepley const PetscInt preind = perm ? *loff+perm[k] : *loff+k; 555205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 555305586334SMatthew G. Knepley 55544acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 55554acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 555605586334SMatthew G. Knepley indices[ind] = -(off+k+1); 55574acb8e1eSToby Isaac ++cind; 55584acb8e1eSToby Isaac } else { 555936fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 5560552f7358SJed Brown } 5561552f7358SJed Brown } 5562552f7358SJed Brown } 5563e6ccafaeSMatthew G Knepley *loff += dof; 5564552f7358SJed Brown PetscFunctionReturn(0); 5565552f7358SJed Brown } 5566552f7358SJed Brown 55677e29afd2SMatthew G. Knepley /* 556836fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 55697e29afd2SMatthew G. Knepley 557036fa2b79SJed Brown Input Parameters: 557136fa2b79SJed Brown + section - a section (global or local) 557236fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global 557336fa2b79SJed Brown . point - point within section 557436fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 557536fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 557636fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 557736fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 557836fa2b79SJed Brown . permsoff - offset 557936fa2b79SJed Brown - indperm - index permutation 558036fa2b79SJed Brown 558136fa2b79SJed Brown Output Parameter: 558236fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 558336fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 558436fa2b79SJed Brown 558536fa2b79SJed Brown Notes: 558636fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 558736fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 558836fa2b79SJed Brown in the local vector. 558936fa2b79SJed Brown 559036fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 559136fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 559236fa2b79SJed Brown 559336fa2b79SJed Brown Developer Note: 559436fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 559536fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 559636fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 559736fa2b79SJed Brown 559836fa2b79SJed Brown Example: 559936fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 560036fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 560136fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 560236fa2b79SJed Brown The global vector does not store constrained dofs, so when this function returns global indices, say {110, -112, 111}, the value of -112 is an arbitrary flag that should not be interpreted beyond its sign. 560336fa2b79SJed Brown 560436fa2b79SJed Brown Level: developer 56057e29afd2SMatthew G. Knepley */ 560636fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 5607a6dfd86eSKarl Rupp { 5608552f7358SJed Brown PetscInt numFields, foff, f; 5609552f7358SJed Brown PetscErrorCode ierr; 5610552f7358SJed Brown 5611552f7358SJed Brown PetscFunctionBegin; 561236fa2b79SJed Brown if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC"); 5613552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5614552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 56154acb8e1eSToby Isaac PetscInt fdof, cfdof; 5616552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 56174acb8e1eSToby Isaac PetscInt cind = 0, b; 56184acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 5619552f7358SJed Brown 5620552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 5621552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 5622552f7358SJed Brown if (!cfdof || setBC) { 562305586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 562405586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 562505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 562605586334SMatthew G. Knepley 562705586334SMatthew G. Knepley indices[ind] = off+foff+b; 562805586334SMatthew G. Knepley } 5629552f7358SJed Brown } else { 5630552f7358SJed Brown ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 563105586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 563205586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 563305586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 563405586334SMatthew G. Knepley 56354acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 563605586334SMatthew G. Knepley indices[ind] = -(off+foff+b+1); 5637552f7358SJed Brown ++cind; 5638552f7358SJed Brown } else { 563936fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 5640552f7358SJed Brown } 5641552f7358SJed Brown } 5642552f7358SJed Brown } 564336fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 5644552f7358SJed Brown foffs[f] += fdof; 5645552f7358SJed Brown } 5646552f7358SJed Brown PetscFunctionReturn(0); 5647552f7358SJed Brown } 5648552f7358SJed Brown 56497e29afd2SMatthew G. Knepley /* 56507e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 56517e29afd2SMatthew G. Knepley 56527e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 5653645102dcSJed Brown 5654645102dcSJed Brown Notes: 5655645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 5656645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 56577e29afd2SMatthew G. Knepley */ 5658645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 56597e29afd2SMatthew G. Knepley { 56607e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 56617e29afd2SMatthew G. Knepley PetscErrorCode ierr; 56627e29afd2SMatthew G. Knepley 56637e29afd2SMatthew G. Knepley PetscFunctionBegin; 56647e29afd2SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 56657e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 56667e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 56677e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 56687e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 56697e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 56707e29afd2SMatthew G. Knepley 56717e29afd2SMatthew G. Knepley ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 56727e29afd2SMatthew G. Knepley ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 56737e29afd2SMatthew G. Knepley ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr); 5674645102dcSJed Brown if (!cfdof) { 567505586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 567605586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 567705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 567805586334SMatthew G. Knepley 567905586334SMatthew G. Knepley indices[ind] = foff+b; 568005586334SMatthew G. Knepley } 56817e29afd2SMatthew G. Knepley } else { 56827e29afd2SMatthew G. Knepley ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 568305586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 568405586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b; 568505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 568605586334SMatthew G. Knepley 56877e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 568805586334SMatthew G. Knepley indices[ind] = -(foff+b+1); 56897e29afd2SMatthew G. Knepley ++cind; 56907e29afd2SMatthew G. Knepley } else { 569105586334SMatthew G. Knepley indices[ind] = foff+b-cind; 56927e29afd2SMatthew G. Knepley } 56937e29afd2SMatthew G. Knepley } 56947e29afd2SMatthew G. Knepley } 56957e29afd2SMatthew G. Knepley foffs[f] += fdof; 56967e29afd2SMatthew G. Knepley } 56977e29afd2SMatthew G. Knepley PetscFunctionReturn(0); 56987e29afd2SMatthew G. Knepley } 56997e29afd2SMatthew G. Knepley 57004acb8e1eSToby Isaac PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft) 5701d3d1a6afSToby Isaac { 5702d3d1a6afSToby Isaac Mat cMat; 5703d3d1a6afSToby Isaac PetscSection aSec, cSec; 5704d3d1a6afSToby Isaac IS aIS; 5705d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 5706d3d1a6afSToby Isaac const PetscInt *anchors; 5707e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 5708d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 5709d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 5710d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 5711d3d1a6afSToby Isaac PetscInt newOffsets[32]; 5712d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 5713d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 5714d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 57156ecaa68aSToby Isaac PetscScalar *newValues=NULL,*tmpValues; 5716d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 5717d3d1a6afSToby Isaac PetscErrorCode ierr; 5718d3d1a6afSToby Isaac 5719d3d1a6afSToby Isaac PetscFunctionBegin; 5720d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5721d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 5722d3d1a6afSToby Isaac ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 5723d3d1a6afSToby Isaac 5724a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 5725d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 5726d3d1a6afSToby Isaac if (aSec) { 5727580bdb30SBarry Smith ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr); 5728d3d1a6afSToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 5729d3d1a6afSToby Isaac ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 5730d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 5731d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 5732d3d1a6afSToby Isaac * into the global matrix anyway) */ 5733d3d1a6afSToby Isaac for (p = 0; p < 2*numPoints; p+=2) { 5734d3d1a6afSToby Isaac PetscInt b = points[p]; 57354b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 5736d3d1a6afSToby Isaac 57374b2f2278SToby Isaac ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 57384b2f2278SToby Isaac if (!bSecDof) { 57394b2f2278SToby Isaac continue; 57404b2f2278SToby Isaac } 5741d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 5742d3d1a6afSToby Isaac ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 5743d3d1a6afSToby Isaac } 5744d3d1a6afSToby Isaac if (bDof) { 5745d3d1a6afSToby Isaac /* this point is constrained */ 5746d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 5747d3d1a6afSToby Isaac PetscInt bOff, q; 5748d3d1a6afSToby Isaac 5749d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 5750d3d1a6afSToby Isaac newNumPoints += bDof; 5751d3d1a6afSToby Isaac ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 5752d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 5753d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 5754d3d1a6afSToby Isaac PetscInt aDof; 5755d3d1a6afSToby Isaac 5756d3d1a6afSToby Isaac ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 5757d3d1a6afSToby Isaac newNumIndices += aDof; 5758d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 5759d3d1a6afSToby Isaac PetscInt fDof; 5760d3d1a6afSToby Isaac 5761d3d1a6afSToby Isaac ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 5762d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 5763d3d1a6afSToby Isaac } 5764d3d1a6afSToby Isaac } 5765d3d1a6afSToby Isaac } 5766d3d1a6afSToby Isaac else { 5767d3d1a6afSToby Isaac /* this point is not constrained */ 5768d3d1a6afSToby Isaac newNumPoints++; 57694b2f2278SToby Isaac newNumIndices += bSecDof; 5770d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 5771d3d1a6afSToby Isaac PetscInt fDof; 5772d3d1a6afSToby Isaac 5773d3d1a6afSToby Isaac ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5774d3d1a6afSToby Isaac newOffsets[f+1] += fDof; 5775d3d1a6afSToby Isaac } 5776d3d1a6afSToby Isaac } 5777d3d1a6afSToby Isaac } 5778d3d1a6afSToby Isaac } 5779d3d1a6afSToby Isaac if (!anyConstrained) { 578072b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 578172b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 578272b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 578372b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 578472b80496SMatthew G. Knepley if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 5785d3d1a6afSToby Isaac PetscFunctionReturn(0); 5786d3d1a6afSToby Isaac } 5787d3d1a6afSToby Isaac 57886ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 57896ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 57906ecaa68aSToby Isaac 5791f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 5792d3d1a6afSToby Isaac 57936ecaa68aSToby Isaac if (!outPoints && !outValues) { 57946ecaa68aSToby Isaac if (offsets) { 57956ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 57966ecaa68aSToby Isaac offsets[f] = newOffsets[f]; 57976ecaa68aSToby Isaac } 57986ecaa68aSToby Isaac } 57996ecaa68aSToby Isaac if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 58006ecaa68aSToby Isaac PetscFunctionReturn(0); 58016ecaa68aSToby Isaac } 58026ecaa68aSToby Isaac 5803f347f43bSBarry Smith if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 5804d3d1a6afSToby Isaac 5805f7c74593SToby Isaac ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 5806d3d1a6afSToby Isaac 5807d3d1a6afSToby Isaac /* workspaces */ 5808d3d1a6afSToby Isaac if (numFields) { 5809d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 581069291d52SBarry Smith ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 581169291d52SBarry Smith ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 5812d3d1a6afSToby Isaac } 5813d3d1a6afSToby Isaac } 5814d3d1a6afSToby Isaac else { 581569291d52SBarry Smith ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 581669291d52SBarry Smith ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 5817d3d1a6afSToby Isaac } 5818d3d1a6afSToby Isaac 5819d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 5820d3d1a6afSToby Isaac if (numFields) { 58214b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 58224b2f2278SToby Isaac 5823d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 5824d3d1a6afSToby Isaac PetscInt b = points[2*p]; 58254b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 5826d3d1a6afSToby Isaac 58274b2f2278SToby Isaac ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 58284b2f2278SToby Isaac if (!bSecDof) { 58294b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 58304b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 58314b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 58324b2f2278SToby Isaac } 58334b2f2278SToby Isaac continue; 58344b2f2278SToby Isaac } 5835d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 5836d3d1a6afSToby Isaac ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5837d3d1a6afSToby Isaac } 5838d3d1a6afSToby Isaac if (bDof) { 5839d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 5840d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 5841d3d1a6afSToby Isaac 5842d3d1a6afSToby Isaac ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5843d3d1a6afSToby Isaac ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5844d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 5845d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 5846d3d1a6afSToby Isaac PetscInt aFDof; 5847d3d1a6afSToby Isaac 5848d3d1a6afSToby Isaac ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 5849d3d1a6afSToby Isaac allFDof += aFDof; 5850d3d1a6afSToby Isaac } 5851d3d1a6afSToby Isaac newPointOffsets[f][p+1] = allFDof; 5852d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = fDof * allFDof; 5853d3d1a6afSToby Isaac } 5854d3d1a6afSToby Isaac } 5855d3d1a6afSToby Isaac else { 5856d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 5857d3d1a6afSToby Isaac PetscInt fDof; 5858d3d1a6afSToby Isaac 5859d3d1a6afSToby Isaac ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 5860d3d1a6afSToby Isaac newPointOffsets[f][p+1] = fDof; 5861d3d1a6afSToby Isaac pointMatOffsets[f][p+1] = 0; 5862d3d1a6afSToby Isaac } 5863d3d1a6afSToby Isaac } 5864d3d1a6afSToby Isaac } 58654b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 58664b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 58674b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 5868d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 5869d3d1a6afSToby Isaac newPointOffsets[f][p+1] += newPointOffsets[f][p]; 5870d3d1a6afSToby Isaac pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 5871d3d1a6afSToby Isaac } 587219f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 587319f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 587469291d52SBarry Smith ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 5875d3d1a6afSToby Isaac } 5876d3d1a6afSToby Isaac } 5877d3d1a6afSToby Isaac else { 5878d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 5879d3d1a6afSToby Isaac PetscInt b = points[2*p]; 58804b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 5881d3d1a6afSToby Isaac 58824b2f2278SToby Isaac ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr); 58834b2f2278SToby Isaac if (!bSecDof) { 58844b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 58854b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 58864b2f2278SToby Isaac continue; 58874b2f2278SToby Isaac } 5888d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 5889d3d1a6afSToby Isaac ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5890d3d1a6afSToby Isaac } 5891d3d1a6afSToby Isaac if (bDof) { 58924b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 5893d3d1a6afSToby Isaac 5894d3d1a6afSToby Isaac ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5895d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 5896d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 5897d3d1a6afSToby Isaac 5898d3d1a6afSToby Isaac ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 5899d3d1a6afSToby Isaac allDof += aDof; 5900d3d1a6afSToby Isaac } 5901d3d1a6afSToby Isaac newPointOffsets[0][p+1] = allDof; 59024b2f2278SToby Isaac pointMatOffsets[0][p+1] = bSecDof * allDof; 5903d3d1a6afSToby Isaac } 5904d3d1a6afSToby Isaac else { 59054b2f2278SToby Isaac newPointOffsets[0][p+1] = bSecDof; 5906d3d1a6afSToby Isaac pointMatOffsets[0][p+1] = 0; 5907d3d1a6afSToby Isaac } 5908d3d1a6afSToby Isaac } 5909d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 5910d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 5911d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 5912d3d1a6afSToby Isaac newPointOffsets[0][p+1] += newPointOffsets[0][p]; 5913d3d1a6afSToby Isaac pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 5914d3d1a6afSToby Isaac } 591569291d52SBarry Smith ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 5916d3d1a6afSToby Isaac } 5917d3d1a6afSToby Isaac 59186ecaa68aSToby Isaac /* output arrays */ 591969291d52SBarry Smith ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 59206ecaa68aSToby Isaac 5921d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 5922d3d1a6afSToby Isaac ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 5923d3d1a6afSToby Isaac ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 592469291d52SBarry Smith ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 592569291d52SBarry Smith ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 5926d3d1a6afSToby Isaac if (numFields) { 5927d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 5928d3d1a6afSToby Isaac PetscInt b = points[2*p]; 5929d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 59304b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 5931d3d1a6afSToby Isaac 59324b2f2278SToby Isaac ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 59334b2f2278SToby Isaac if (!bSecDof) { 59344b2f2278SToby Isaac continue; 59354b2f2278SToby Isaac } 5936d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 5937d3d1a6afSToby Isaac ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5938d3d1a6afSToby Isaac } 5939d3d1a6afSToby Isaac if (bDof) { 5940d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 5941d3d1a6afSToby Isaac 5942d3d1a6afSToby Isaac fStart[0] = 0; 5943d3d1a6afSToby Isaac fEnd[0] = 0; 5944d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 5945d3d1a6afSToby Isaac PetscInt fDof; 5946d3d1a6afSToby Isaac 5947d3d1a6afSToby Isaac ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 5948d3d1a6afSToby Isaac fStart[f+1] = fStart[f] + fDof; 5949d3d1a6afSToby Isaac fEnd[f+1] = fStart[f+1]; 5950d3d1a6afSToby Isaac } 5951d3d1a6afSToby Isaac ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 595236fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr); 5953d3d1a6afSToby Isaac 5954d3d1a6afSToby Isaac fAnchorStart[0] = 0; 5955d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 5956d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 5957d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 5958d3d1a6afSToby Isaac 5959d3d1a6afSToby Isaac fAnchorStart[f+1] = fAnchorStart[f] + fDof; 5960d3d1a6afSToby Isaac fAnchorEnd[f+1] = fAnchorStart[f + 1]; 5961d3d1a6afSToby Isaac } 5962d3d1a6afSToby Isaac ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 5963d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 5964d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 5965d3d1a6afSToby Isaac 5966d3d1a6afSToby Isaac /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 5967d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 5968d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 5969302440fdSBarry Smith ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 597036fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr); 5971d3d1a6afSToby Isaac } 5972d3d1a6afSToby Isaac newP += bDof; 5973d3d1a6afSToby Isaac 59746ecaa68aSToby Isaac if (outValues) { 5975d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 5976d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 5977d3d1a6afSToby Isaac ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 5978d3d1a6afSToby Isaac } 5979d3d1a6afSToby Isaac } 59806ecaa68aSToby Isaac } 5981d3d1a6afSToby Isaac else { 5982d3d1a6afSToby Isaac newPoints[2 * newP] = b; 5983d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 5984d3d1a6afSToby Isaac newP++; 5985d3d1a6afSToby Isaac } 5986d3d1a6afSToby Isaac } 5987d3d1a6afSToby Isaac } else { 5988d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 5989d3d1a6afSToby Isaac PetscInt b = points[2*p]; 5990d3d1a6afSToby Isaac PetscInt o = points[2*p+1]; 59914b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 5992d3d1a6afSToby Isaac 59934b2f2278SToby Isaac ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr); 59944b2f2278SToby Isaac if (!bSecDof) { 59954b2f2278SToby Isaac continue; 59964b2f2278SToby Isaac } 5997d3d1a6afSToby Isaac if (b >= aStart && b < aEnd) { 5998d3d1a6afSToby Isaac ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 5999d3d1a6afSToby Isaac } 6000d3d1a6afSToby Isaac if (bDof) { 6001d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 6002d3d1a6afSToby Isaac 6003d3d1a6afSToby Isaac ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 600436fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr); 6005d3d1a6afSToby Isaac 6006d3d1a6afSToby Isaac ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 6007d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 6008d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 6009d3d1a6afSToby Isaac 6010d3d1a6afSToby Isaac /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 6011d3d1a6afSToby Isaac 6012d3d1a6afSToby Isaac newPoints[2*(newP + q)] = a; 6013d3d1a6afSToby Isaac newPoints[2*(newP + q) + 1] = 0; 6014302440fdSBarry Smith ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 601536fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr); 6016d3d1a6afSToby Isaac } 6017d3d1a6afSToby Isaac newP += bDof; 6018d3d1a6afSToby Isaac 6019d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 60206ecaa68aSToby Isaac if (outValues) { 6021d3d1a6afSToby Isaac ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 6022d3d1a6afSToby Isaac } 60236ecaa68aSToby Isaac } 6024d3d1a6afSToby Isaac else { 6025d3d1a6afSToby Isaac newPoints[2 * newP] = b; 6026d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 6027d3d1a6afSToby Isaac newP++; 6028d3d1a6afSToby Isaac } 6029d3d1a6afSToby Isaac } 6030d3d1a6afSToby Isaac } 6031d3d1a6afSToby Isaac 60326ecaa68aSToby Isaac if (outValues) { 603369291d52SBarry Smith ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 6034580bdb30SBarry Smith ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr); 6035d3d1a6afSToby Isaac /* multiply constraints on the right */ 6036d3d1a6afSToby Isaac if (numFields) { 6037d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6038d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 6039d3d1a6afSToby Isaac 6040d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6041d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 6042d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 6043d3d1a6afSToby Isaac PetscInt c, r, k; 6044d3d1a6afSToby Isaac PetscInt dof; 6045d3d1a6afSToby Isaac 6046d3d1a6afSToby Isaac ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 60474b2f2278SToby Isaac if (!dof) { 60484b2f2278SToby Isaac continue; 60494b2f2278SToby Isaac } 6050d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6051d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p+1]-cStart; 6052d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 6053d3d1a6afSToby Isaac 6054d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 6055d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 6056d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 60574acb8e1eSToby Isaac tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 6058d3d1a6afSToby Isaac } 6059d3d1a6afSToby Isaac } 6060d3d1a6afSToby Isaac } 6061d3d1a6afSToby Isaac } 6062d3d1a6afSToby Isaac else { 6063d3d1a6afSToby Isaac /* copy this column as is */ 6064d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 6065d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 6066d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 6067d3d1a6afSToby Isaac } 6068d3d1a6afSToby Isaac } 6069d3d1a6afSToby Isaac } 6070d3d1a6afSToby Isaac oldOff += dof; 6071d3d1a6afSToby Isaac } 6072d3d1a6afSToby Isaac } 6073d3d1a6afSToby Isaac } 6074d3d1a6afSToby Isaac else { 6075d3d1a6afSToby Isaac PetscInt oldOff = 0; 6076d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6077d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 6078d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 6079d3d1a6afSToby Isaac PetscInt c, r, k; 6080d3d1a6afSToby Isaac PetscInt dof; 6081d3d1a6afSToby Isaac 6082d3d1a6afSToby Isaac ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 60834b2f2278SToby Isaac if (!dof) { 60844b2f2278SToby Isaac continue; 60854b2f2278SToby Isaac } 6086d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 6087d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p+1]-cStart; 6088d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 6089d3d1a6afSToby Isaac 6090d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 6091d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 6092d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 6093d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 6094d3d1a6afSToby Isaac } 6095d3d1a6afSToby Isaac } 6096d3d1a6afSToby Isaac } 6097d3d1a6afSToby Isaac } 6098d3d1a6afSToby Isaac else { 6099d3d1a6afSToby Isaac /* copy this column as is */ 6100d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 6101d3d1a6afSToby Isaac for (c = 0; c < dof; c++) { 6102d3d1a6afSToby Isaac tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 6103d3d1a6afSToby Isaac } 6104d3d1a6afSToby Isaac } 6105d3d1a6afSToby Isaac } 6106d3d1a6afSToby Isaac oldOff += dof; 6107d3d1a6afSToby Isaac } 6108d3d1a6afSToby Isaac } 6109d3d1a6afSToby Isaac 61106ecaa68aSToby Isaac if (multiplyLeft) { 611169291d52SBarry Smith ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 6112580bdb30SBarry Smith ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr); 6113d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 6114d3d1a6afSToby Isaac if (numFields) { 6115d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 6116d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 6117d3d1a6afSToby Isaac 6118d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6119d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 6120d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 6121d3d1a6afSToby Isaac PetscInt c, r, k; 6122d3d1a6afSToby Isaac PetscInt dof; 6123d3d1a6afSToby Isaac 6124d3d1a6afSToby Isaac ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 6125d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 6126d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p+1]-rStart; 6127d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 6128d3d1a6afSToby Isaac 6129d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 6130d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 6131d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 6132d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 6133d3d1a6afSToby Isaac } 6134d3d1a6afSToby Isaac } 6135d3d1a6afSToby Isaac } 6136d3d1a6afSToby Isaac } 6137d3d1a6afSToby Isaac else { 6138d3d1a6afSToby Isaac /* copy this row as is */ 6139d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 6140d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 6141d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 6142d3d1a6afSToby Isaac } 6143d3d1a6afSToby Isaac } 6144d3d1a6afSToby Isaac } 6145d3d1a6afSToby Isaac oldOff += dof; 6146d3d1a6afSToby Isaac } 6147d3d1a6afSToby Isaac } 6148d3d1a6afSToby Isaac } 6149d3d1a6afSToby Isaac else { 6150d3d1a6afSToby Isaac PetscInt oldOff = 0; 6151d3d1a6afSToby Isaac 6152d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 6153d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 6154d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 6155d3d1a6afSToby Isaac PetscInt c, r, k; 6156d3d1a6afSToby Isaac PetscInt dof; 6157d3d1a6afSToby Isaac 6158d3d1a6afSToby Isaac ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 6159d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 6160d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p+1]-rStart; 6161d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 6162d3d1a6afSToby Isaac 6163d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 6164d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 6165d3d1a6afSToby Isaac for (k = 0; k < dof; k++) { 6166d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 6167d3d1a6afSToby Isaac } 6168d3d1a6afSToby Isaac } 6169d3d1a6afSToby Isaac } 6170d3d1a6afSToby Isaac } 6171d3d1a6afSToby Isaac else { 6172d3d1a6afSToby Isaac /* copy this row as is */ 61739fc93327SToby Isaac for (r = 0; r < dof; r++) { 6174d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 6175d3d1a6afSToby Isaac newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 6176d3d1a6afSToby Isaac } 6177d3d1a6afSToby Isaac } 6178d3d1a6afSToby Isaac } 6179d3d1a6afSToby Isaac oldOff += dof; 6180d3d1a6afSToby Isaac } 6181d3d1a6afSToby Isaac } 6182d3d1a6afSToby Isaac 618369291d52SBarry Smith ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr); 61846ecaa68aSToby Isaac } 61856ecaa68aSToby Isaac else { 61866ecaa68aSToby Isaac newValues = tmpValues; 61876ecaa68aSToby Isaac } 61886ecaa68aSToby Isaac } 61896ecaa68aSToby Isaac 6190d3d1a6afSToby Isaac /* clean up */ 619169291d52SBarry Smith ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr); 619269291d52SBarry Smith ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr); 61936ecaa68aSToby Isaac 6194d3d1a6afSToby Isaac if (numFields) { 6195d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 619669291d52SBarry Smith ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr); 619769291d52SBarry Smith ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 619869291d52SBarry Smith ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr); 6199d3d1a6afSToby Isaac } 6200d3d1a6afSToby Isaac } 6201d3d1a6afSToby Isaac else { 620269291d52SBarry Smith ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr); 620369291d52SBarry Smith ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 620469291d52SBarry Smith ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr); 6205d3d1a6afSToby Isaac } 6206d3d1a6afSToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 6207d3d1a6afSToby Isaac 6208d3d1a6afSToby Isaac /* output */ 62096ecaa68aSToby Isaac if (outPoints) { 6210d3d1a6afSToby Isaac *outPoints = newPoints; 62116ecaa68aSToby Isaac } 62126ecaa68aSToby Isaac else { 621369291d52SBarry Smith ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 62146ecaa68aSToby Isaac } 621531620726SToby Isaac if (outValues) { 6216d3d1a6afSToby Isaac *outValues = newValues; 62176ecaa68aSToby Isaac } 62186ecaa68aSToby Isaac for (f = 0; f <= numFields; f++) { 6219d3d1a6afSToby Isaac offsets[f] = newOffsets[f]; 6220d3d1a6afSToby Isaac } 6221d3d1a6afSToby Isaac PetscFunctionReturn(0); 6222d3d1a6afSToby Isaac } 6223d3d1a6afSToby Isaac 62247cd05799SMatthew G. Knepley /*@C 62252cdc749cSStefano Zampini DMPlexGetClosureIndices - Get the global indices for all local points in the closure of the given point 62267cd05799SMatthew G. Knepley 62277cd05799SMatthew G. Knepley Not collective 62287cd05799SMatthew G. Knepley 62297cd05799SMatthew G. Knepley Input Parameters: 62307cd05799SMatthew G. Knepley + dm - The DM 623136fa2b79SJed Brown . section - The section describing the points (a local section) 623236fa2b79SJed Brown . idxSection - The section on which to obtain indices (may be local or global) 62337cd05799SMatthew G. Knepley - point - The mesh point 62347cd05799SMatthew G. Knepley 62357cd05799SMatthew G. Knepley Output parameters: 62367cd05799SMatthew G. Knepley + numIndices - The number of indices 62377cd05799SMatthew G. Knepley . indices - The indices 62387cd05799SMatthew G. Knepley - outOffsets - Field offset if not NULL 62397cd05799SMatthew G. Knepley 624036fa2b79SJed Brown Notes: 624136fa2b79SJed Brown Must call DMPlexRestoreClosureIndices() to free allocated memory 624236fa2b79SJed Brown 624336fa2b79SJed Brown If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices. The value 624436fa2b79SJed Brown of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 624536fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 624636fa2b79SJed Brown indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 624736fa2b79SJed Brown indices (with the above semantics) are implied. 62487cd05799SMatthew G. Knepley 62497cd05799SMatthew G. Knepley Level: advanced 62507cd05799SMatthew G. Knepley 625136fa2b79SJed Brown .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection() 62527cd05799SMatthew G. Knepley @*/ 625336fa2b79SJed Brown PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscInt *numIndices, PetscInt **indices, PetscInt *outOffsets) 62547773e69fSMatthew G. Knepley { 625536fa2b79SJed Brown PetscBool isLocal = (PetscBool)(section == idxSection); 62567773e69fSMatthew G. Knepley PetscSection clSection; 62577773e69fSMatthew G. Knepley IS clPoints; 625805586334SMatthew G. Knepley const PetscInt *clp, *clperm; 62594acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 62607773e69fSMatthew G. Knepley PetscInt *points = NULL, *pointsNew; 62617773e69fSMatthew G. Knepley PetscInt numPoints, numPointsNew; 62627773e69fSMatthew G. Knepley PetscInt offsets[32]; 626336fa2b79SJed Brown PetscInt Nf, Nind, NindNew, off, idxOff, f, p; 62647773e69fSMatthew G. Knepley PetscErrorCode ierr; 62657773e69fSMatthew G. Knepley 62667773e69fSMatthew G. Knepley PetscFunctionBegin; 62677773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 62687773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 626936fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 62707773e69fSMatthew G. Knepley if (numIndices) PetscValidPointer(numIndices, 4); 62717773e69fSMatthew G. Knepley PetscValidPointer(indices, 5); 62727773e69fSMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 62737773e69fSMatthew G. Knepley if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 6274580bdb30SBarry Smith ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 62757773e69fSMatthew G. Knepley /* Get points in closure */ 6276923c78e0SToby Isaac ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 627705586334SMatthew G. Knepley ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 62787773e69fSMatthew G. Knepley /* Get number of indices and indices per field */ 62797773e69fSMatthew G. Knepley for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 62807773e69fSMatthew G. Knepley PetscInt dof, fdof; 62817773e69fSMatthew G. Knepley 62827773e69fSMatthew G. Knepley ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 62837773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 62847773e69fSMatthew G. Knepley ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 62857773e69fSMatthew G. Knepley offsets[f+1] += fdof; 62867773e69fSMatthew G. Knepley } 62877773e69fSMatthew G. Knepley Nind += dof; 62887773e69fSMatthew G. Knepley } 62897773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 62908ccfff9cSToby Isaac if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Nind); 62914acb8e1eSToby Isaac if (!Nf) offsets[1] = Nind; 62924acb8e1eSToby Isaac /* Get dual space symmetries */ 62934acb8e1eSToby Isaac for (f = 0; f < PetscMax(1,Nf); f++) { 62944acb8e1eSToby Isaac if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 62954acb8e1eSToby Isaac else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 62964acb8e1eSToby Isaac } 62977773e69fSMatthew G. Knepley /* Correct for hanging node constraints */ 62987773e69fSMatthew G. Knepley { 62994acb8e1eSToby Isaac ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, perms, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets, PETSC_TRUE);CHKERRQ(ierr); 63007773e69fSMatthew G. Knepley if (numPointsNew) { 63014acb8e1eSToby Isaac for (f = 0; f < PetscMax(1,Nf); f++) { 63024acb8e1eSToby Isaac if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 63034acb8e1eSToby Isaac else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 63044acb8e1eSToby Isaac } 63054acb8e1eSToby Isaac for (f = 0; f < PetscMax(1,Nf); f++) { 63064acb8e1eSToby Isaac if (Nf) {ierr = PetscSectionGetFieldPointSyms(section,f,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 63074acb8e1eSToby Isaac else {ierr = PetscSectionGetPointSyms(section,numPointsNew,pointsNew,&perms[f],NULL);CHKERRQ(ierr);} 63084acb8e1eSToby Isaac } 6309923c78e0SToby Isaac ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 63107773e69fSMatthew G. Knepley numPoints = numPointsNew; 63117773e69fSMatthew G. Knepley Nind = NindNew; 63127773e69fSMatthew G. Knepley points = pointsNew; 63137773e69fSMatthew G. Knepley } 63147773e69fSMatthew G. Knepley } 63157773e69fSMatthew G. Knepley /* Calculate indices */ 631669291d52SBarry Smith ierr = DMGetWorkArray(dm, Nind, MPIU_INT, indices);CHKERRQ(ierr); 63177773e69fSMatthew G. Knepley if (Nf) { 63186ecaa68aSToby Isaac if (outOffsets) { 63196ecaa68aSToby Isaac PetscInt f; 63206ecaa68aSToby Isaac 632146bdb399SToby Isaac for (f = 0; f <= Nf; f++) { 63226ecaa68aSToby Isaac outOffsets[f] = offsets[f]; 63236ecaa68aSToby Isaac } 63246ecaa68aSToby Isaac } 63254acb8e1eSToby Isaac for (p = 0; p < numPoints; p++) { 632636fa2b79SJed Brown ierr = PetscSectionGetOffset(idxSection, points[2*p], &idxOff);CHKERRQ(ierr); 632736fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, points[2*p], idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, *indices);CHKERRQ(ierr); 63287773e69fSMatthew G. Knepley } 63297773e69fSMatthew G. Knepley } else { 63304acb8e1eSToby Isaac for (p = 0, off = 0; p < numPoints; p++) { 63314acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 63324acb8e1eSToby Isaac 633336fa2b79SJed Brown ierr = PetscSectionGetOffset(idxSection, points[2*p], &idxOff);CHKERRQ(ierr); 633436fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, points[2*p], idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, *indices);CHKERRQ(ierr); 63357773e69fSMatthew G. Knepley } 63367773e69fSMatthew G. Knepley } 63377773e69fSMatthew G. Knepley /* Cleanup points */ 63384acb8e1eSToby Isaac for (f = 0; f < PetscMax(1,Nf); f++) { 63394acb8e1eSToby Isaac if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 63404acb8e1eSToby Isaac else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],NULL);CHKERRQ(ierr);} 63414acb8e1eSToby Isaac } 63427773e69fSMatthew G. Knepley if (numPointsNew) { 634369291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 2*numPointsNew, MPIU_INT, &pointsNew);CHKERRQ(ierr); 63447773e69fSMatthew G. Knepley } else { 6345923c78e0SToby Isaac ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 63467773e69fSMatthew G. Knepley } 63477773e69fSMatthew G. Knepley if (numIndices) *numIndices = Nind; 63487773e69fSMatthew G. Knepley PetscFunctionReturn(0); 63497773e69fSMatthew G. Knepley } 63507773e69fSMatthew G. Knepley 63517cd05799SMatthew G. Knepley /*@C 63527cd05799SMatthew G. Knepley DMPlexRestoreClosureIndices - Restore the indices in a vector v for all points in the closure of the given point 63537cd05799SMatthew G. Knepley 63547cd05799SMatthew G. Knepley Not collective 63557cd05799SMatthew G. Knepley 63567cd05799SMatthew G. Knepley Input Parameters: 63577cd05799SMatthew G. Knepley + dm - The DM 63587cd05799SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section 63597cd05799SMatthew G. Knepley . globalSection - The section describing the parallel layout in v, or NULL to use the default section 63607cd05799SMatthew G. Knepley . point - The mesh point 63617cd05799SMatthew G. Knepley . numIndices - The number of indices 63627cd05799SMatthew G. Knepley . indices - The indices 63637cd05799SMatthew G. Knepley - outOffsets - Field offset if not NULL 63647cd05799SMatthew G. Knepley 63657cd05799SMatthew G. Knepley Level: advanced 63667cd05799SMatthew G. Knepley 63677cd05799SMatthew G. Knepley .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure() 63687cd05799SMatthew G. Knepley @*/ 636946bdb399SToby Isaac PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices,PetscInt *outOffsets) 63707773e69fSMatthew G. Knepley { 63717773e69fSMatthew G. Knepley PetscErrorCode ierr; 63727773e69fSMatthew G. Knepley 63737773e69fSMatthew G. Knepley PetscFunctionBegin; 63747773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 63757773e69fSMatthew G. Knepley PetscValidPointer(indices, 5); 637669291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr); 63777773e69fSMatthew G. Knepley PetscFunctionReturn(0); 63787773e69fSMatthew G. Knepley } 63797773e69fSMatthew G. Knepley 63807f5d1fdeSMatthew G. Knepley /*@C 63817f5d1fdeSMatthew G. Knepley DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 63827f5d1fdeSMatthew G. Knepley 63837f5d1fdeSMatthew G. Knepley Not collective 63847f5d1fdeSMatthew G. Knepley 63857f5d1fdeSMatthew G. Knepley Input Parameters: 63867f5d1fdeSMatthew G. Knepley + dm - The DM 6387ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section 6388ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section 63897f5d1fdeSMatthew G. Knepley . A - The matrix 6390eaf898f9SPatrick Sanan . point - The point in the DM 63917f5d1fdeSMatthew G. Knepley . values - The array of values 63927f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 63937f5d1fdeSMatthew G. Knepley 63947f5d1fdeSMatthew G. Knepley Fortran Notes: 63957f5d1fdeSMatthew G. Knepley This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 63967f5d1fdeSMatthew G. Knepley 63977f5d1fdeSMatthew G. Knepley Level: intermediate 63987f5d1fdeSMatthew G. Knepley 63997f5d1fdeSMatthew G. Knepley .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 64007f5d1fdeSMatthew G. Knepley @*/ 64017c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6402552f7358SJed Brown { 6403552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 64041b406b76SMatthew G. Knepley PetscSection clSection; 64051b406b76SMatthew G. Knepley IS clPoints; 6406d3d1a6afSToby Isaac PetscInt *points = NULL, *newPoints; 640705586334SMatthew G. Knepley const PetscInt *clp, *clperm; 6408552f7358SJed Brown PetscInt *indices; 6409552f7358SJed Brown PetscInt offsets[32]; 64104acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 64114acb8e1eSToby Isaac const PetscScalar **flips[32] = {NULL}; 6412923c78e0SToby Isaac PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, p, f; 64134acb8e1eSToby Isaac PetscScalar *valCopy = NULL; 6414d3d1a6afSToby Isaac PetscScalar *newValues; 6415552f7358SJed Brown PetscErrorCode ierr; 6416552f7358SJed Brown 6417552f7358SJed Brown PetscFunctionBegin; 6418552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 641992fd8e1eSJed Brown if (!section) {ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr);} 64203dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6421e87a4003SBarry Smith if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 64223dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 64233dc93601SMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 6424552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 642582f516ccSBarry Smith if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6426580bdb30SBarry Smith ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr); 642705586334SMatthew G. Knepley ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, NULL, &clperm);CHKERRQ(ierr); 6428923c78e0SToby Isaac ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6429552f7358SJed Brown for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 6430552f7358SJed Brown PetscInt fdof; 6431552f7358SJed Brown 6432552f7358SJed Brown ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 6433552f7358SJed Brown for (f = 0; f < numFields; ++f) { 6434552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 6435552f7358SJed Brown offsets[f+1] += fdof; 6436552f7358SJed Brown } 6437552f7358SJed Brown numIndices += dof; 6438552f7358SJed Brown } 64390d644c17SKarl Rupp for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 64400d644c17SKarl Rupp 64418ccfff9cSToby Isaac if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[numFields], numIndices); 64424acb8e1eSToby Isaac /* Get symmetries */ 64434acb8e1eSToby Isaac for (f = 0; f < PetscMax(1,numFields); f++) { 64444acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 64454acb8e1eSToby Isaac else {ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 64464acb8e1eSToby Isaac if (values && flips[f]) { /* may need to apply sign changes to the element matrix */ 64474acb8e1eSToby Isaac PetscInt foffset = offsets[f]; 64484acb8e1eSToby Isaac 64494acb8e1eSToby Isaac for (p = 0; p < numPoints; p++) { 64504acb8e1eSToby Isaac PetscInt point = points[2*p], fdof; 64514acb8e1eSToby Isaac const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 64524acb8e1eSToby Isaac 64534acb8e1eSToby Isaac if (!numFields) { 64544acb8e1eSToby Isaac ierr = PetscSectionGetDof(section,point,&fdof);CHKERRQ(ierr); 64554acb8e1eSToby Isaac } else { 64564acb8e1eSToby Isaac ierr = PetscSectionGetFieldDof(section,point,f,&fdof);CHKERRQ(ierr); 64574acb8e1eSToby Isaac } 64584acb8e1eSToby Isaac if (flip) { 64594acb8e1eSToby Isaac PetscInt i, j, k; 64604acb8e1eSToby Isaac 64614acb8e1eSToby Isaac if (!valCopy) { 646269291d52SBarry Smith ierr = DMGetWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 64634acb8e1eSToby Isaac for (j = 0; j < numIndices * numIndices; j++) valCopy[j] = values[j]; 64644acb8e1eSToby Isaac values = valCopy; 64654acb8e1eSToby Isaac } 64664acb8e1eSToby Isaac for (i = 0; i < fdof; i++) { 6467775f7be2SToby Isaac PetscScalar fval = flip[i]; 64684acb8e1eSToby Isaac 64694acb8e1eSToby Isaac for (k = 0; k < numIndices; k++) { 64704acb8e1eSToby Isaac valCopy[numIndices * (foffset + i) + k] *= fval; 64714acb8e1eSToby Isaac valCopy[numIndices * k + (foffset + i)] *= fval; 64724acb8e1eSToby Isaac } 64734acb8e1eSToby Isaac } 64744acb8e1eSToby Isaac } 64754acb8e1eSToby Isaac foffset += fdof; 64764acb8e1eSToby Isaac } 64774acb8e1eSToby Isaac } 64784acb8e1eSToby Isaac } 64794acb8e1eSToby Isaac ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,perms,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets,PETSC_TRUE);CHKERRQ(ierr); 6480d3d1a6afSToby Isaac if (newNumPoints) { 64814acb8e1eSToby Isaac if (valCopy) { 648269291d52SBarry Smith ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 64834acb8e1eSToby Isaac } 64844acb8e1eSToby Isaac for (f = 0; f < PetscMax(1,numFields); f++) { 64854acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 64864acb8e1eSToby Isaac else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 64874acb8e1eSToby Isaac } 64884acb8e1eSToby Isaac for (f = 0; f < PetscMax(1,numFields); f++) { 64894acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionGetFieldPointSyms(section,f,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 64904acb8e1eSToby Isaac else {ierr = PetscSectionGetPointSyms(section,newNumPoints,newPoints,&perms[f],&flips[f]);CHKERRQ(ierr);} 64914acb8e1eSToby Isaac } 6492923c78e0SToby Isaac ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6493d3d1a6afSToby Isaac numPoints = newNumPoints; 6494d3d1a6afSToby Isaac numIndices = newNumIndices; 6495d3d1a6afSToby Isaac points = newPoints; 6496d3d1a6afSToby Isaac values = newValues; 6497d3d1a6afSToby Isaac } 649869291d52SBarry Smith ierr = DMGetWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 6499552f7358SJed Brown if (numFields) { 65007e29afd2SMatthew G. Knepley PetscBool useFieldOffsets; 65017e29afd2SMatthew G. Knepley 65027e29afd2SMatthew G. Knepley ierr = PetscSectionGetUseFieldOffsets(globalSection, &useFieldOffsets);CHKERRQ(ierr); 65037e29afd2SMatthew G. Knepley if (useFieldOffsets) { 65047e29afd2SMatthew G. Knepley for (p = 0; p < numPoints; p++) { 6505645102dcSJed Brown ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, globalSection, points[2*p], offsets, perms, p, clperm, indices);CHKERRQ(ierr); 65067e29afd2SMatthew G. Knepley } 65077e29afd2SMatthew G. Knepley } else { 65084acb8e1eSToby Isaac for (p = 0; p < numPoints; p++) { 65094acb8e1eSToby Isaac ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 651036fa2b79SJed Brown /* Note that we pass a local section even though we're using global offsets. This is because global sections do 651136fa2b79SJed Brown * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 651236fa2b79SJed Brown * global section. */ 651336fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_FALSE, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, perms, p, clperm, indices);CHKERRQ(ierr); 6514552f7358SJed Brown } 65157e29afd2SMatthew G. Knepley } 6516552f7358SJed Brown } else { 65174acb8e1eSToby Isaac for (p = 0, off = 0; p < numPoints; p++) { 65184acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 65194acb8e1eSToby Isaac ierr = PetscSectionGetOffset(globalSection, points[2*p], &globalOff);CHKERRQ(ierr); 652036fa2b79SJed Brown /* Note that we pass a local section even though we're using global offsets. This is because global sections do 652136fa2b79SJed Brown * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 652236fa2b79SJed Brown * global section. */ 652336fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_FALSE, points[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, clperm, indices);CHKERRQ(ierr); 6524552f7358SJed Brown } 6525552f7358SJed Brown } 6526b0ecff45SMatthew G. Knepley if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 652736fa2b79SJed Brown ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);CHKERRQ(ierr); 6528ab1d0545SMatthew G. Knepley if (mesh->printFEM > 1) { 6529ab1d0545SMatthew G. Knepley PetscInt i; 6530ab1d0545SMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 65318ccfff9cSToby Isaac for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);} 6532ab1d0545SMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 6533ab1d0545SMatthew G. Knepley } 6534552f7358SJed Brown if (ierr) { 6535552f7358SJed Brown PetscMPIInt rank; 6536552f7358SJed Brown PetscErrorCode ierr2; 6537552f7358SJed Brown 653882f516ccSBarry Smith ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 6539e4b003c7SBarry Smith ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 6540b0ecff45SMatthew G. Knepley ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 654169291d52SBarry Smith ierr2 = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr2); 6542552f7358SJed Brown CHKERRQ(ierr); 6543552f7358SJed Brown } 65444acb8e1eSToby Isaac for (f = 0; f < PetscMax(1,numFields); f++) { 65454acb8e1eSToby Isaac if (numFields) {ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 65464acb8e1eSToby Isaac else {ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms[f],&flips[f]);CHKERRQ(ierr);} 65474acb8e1eSToby Isaac } 6548d3d1a6afSToby Isaac if (newNumPoints) { 654969291d52SBarry Smith ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr); 655069291d52SBarry Smith ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr); 6551d3d1a6afSToby Isaac } 6552d3d1a6afSToby Isaac else { 65534acb8e1eSToby Isaac if (valCopy) { 655469291d52SBarry Smith ierr = DMRestoreWorkArray(dm,numIndices*numIndices,MPIU_SCALAR,&valCopy);CHKERRQ(ierr); 65554acb8e1eSToby Isaac } 6556923c78e0SToby Isaac ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr); 6557d3d1a6afSToby Isaac } 655869291d52SBarry Smith ierr = DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices);CHKERRQ(ierr); 6559552f7358SJed Brown PetscFunctionReturn(0); 6560552f7358SJed Brown } 6561552f7358SJed Brown 6562de41b84cSMatthew G. Knepley PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 6563de41b84cSMatthew G. Knepley { 6564de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dmf->data; 6565de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 6566de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 6567de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 656817c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 6569de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 6570412e9a14SMatthew G. Knepley DMPolytopeType ct; 65714ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 6572de41b84cSMatthew G. Knepley PetscErrorCode ierr; 6573de41b84cSMatthew G. Knepley 6574de41b84cSMatthew G. Knepley PetscFunctionBegin; 6575de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 6576de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 657792fd8e1eSJed Brown if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 6578de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 657992fd8e1eSJed Brown if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 6580de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 6581e87a4003SBarry Smith if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 6582de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 6583e87a4003SBarry Smith if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 6584de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 6585de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 6586de41b84cSMatthew G. Knepley ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 6587de41b84cSMatthew G. Knepley if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6588580bdb30SBarry Smith ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 6589580bdb30SBarry Smith ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 6590de41b84cSMatthew G. Knepley /* Column indices */ 6591de41b84cSMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 65924ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 6593de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 6594de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 6595de41b84cSMatthew G. Knepley ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 6596de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 6597de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 6598de41b84cSMatthew G. Knepley cpoints[q*2] = cpoints[p]; 6599de41b84cSMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 6600de41b84cSMatthew G. Knepley ++q; 6601de41b84cSMatthew G. Knepley } 6602de41b84cSMatthew G. Knepley } 6603de41b84cSMatthew G. Knepley numCPoints = q; 6604de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 6605de41b84cSMatthew G. Knepley PetscInt fdof; 6606de41b84cSMatthew G. Knepley 6607de41b84cSMatthew G. Knepley ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 66084ca5e9f5SMatthew G. Knepley if (!dof) continue; 6609de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 6610de41b84cSMatthew G. Knepley ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 6611de41b84cSMatthew G. Knepley coffsets[f+1] += fdof; 6612de41b84cSMatthew G. Knepley } 6613de41b84cSMatthew G. Knepley numCIndices += dof; 6614de41b84cSMatthew G. Knepley } 6615de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 6616de41b84cSMatthew G. Knepley /* Row indices */ 6617412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 6618412e9a14SMatthew G. Knepley { 6619412e9a14SMatthew G. Knepley DMPlexCellRefiner cr; 6620412e9a14SMatthew G. Knepley ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr); 6621412e9a14SMatthew G. Knepley ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 6622412e9a14SMatthew G. Knepley ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 6623412e9a14SMatthew G. Knepley } 662469291d52SBarry Smith ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6625de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 6626de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 6627de41b84cSMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6628de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 6629de41b84cSMatthew G. Knepley ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 6630de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 6631de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 66324ca5e9f5SMatthew G. Knepley ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 66334ca5e9f5SMatthew G. Knepley if (!dof) continue; 66344ca5e9f5SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 66354ca5e9f5SMatthew G. Knepley if (s < q) continue; 6636de41b84cSMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 6637de41b84cSMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 6638de41b84cSMatthew G. Knepley ++q; 6639de41b84cSMatthew G. Knepley } 6640de41b84cSMatthew G. Knepley } 6641de41b84cSMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 6642de41b84cSMatthew G. Knepley } 6643de41b84cSMatthew G. Knepley numFPoints = q; 6644de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 6645de41b84cSMatthew G. Knepley PetscInt fdof; 6646de41b84cSMatthew G. Knepley 6647de41b84cSMatthew G. Knepley ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 66484ca5e9f5SMatthew G. Knepley if (!dof) continue; 6649de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 6650de41b84cSMatthew G. Knepley ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 6651de41b84cSMatthew G. Knepley foffsets[f+1] += fdof; 6652de41b84cSMatthew G. Knepley } 6653de41b84cSMatthew G. Knepley numFIndices += dof; 6654de41b84cSMatthew G. Knepley } 6655de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 6656de41b84cSMatthew G. Knepley 66578ccfff9cSToby Isaac if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 66588ccfff9cSToby Isaac if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 665969291d52SBarry Smith ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 666069291d52SBarry Smith ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 6661de41b84cSMatthew G. Knepley if (numFields) { 66624acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 66634acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 66644acb8e1eSToby Isaac 66654acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 66664acb8e1eSToby Isaac ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 66674acb8e1eSToby Isaac ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6668de41b84cSMatthew G. Knepley } 66694acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 66704acb8e1eSToby Isaac ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 667136fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 66724acb8e1eSToby Isaac } 66734acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 66744acb8e1eSToby Isaac ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 667536fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 66764acb8e1eSToby Isaac } 66774acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 66784acb8e1eSToby Isaac ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 66794acb8e1eSToby Isaac ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 6680de41b84cSMatthew G. Knepley } 6681de41b84cSMatthew G. Knepley } else { 66824acb8e1eSToby Isaac const PetscInt **permsF = NULL; 66834acb8e1eSToby Isaac const PetscInt **permsC = NULL; 66844acb8e1eSToby Isaac 66854acb8e1eSToby Isaac ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 66864acb8e1eSToby Isaac ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 66874acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 66884acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 66894acb8e1eSToby Isaac 66904acb8e1eSToby Isaac ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 669136fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 6692de41b84cSMatthew G. Knepley } 66934acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 66944acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 66954acb8e1eSToby Isaac 66964acb8e1eSToby Isaac ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 669736fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 6698de41b84cSMatthew G. Knepley } 66994acb8e1eSToby Isaac ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 67004acb8e1eSToby Isaac ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 6701de41b84cSMatthew G. Knepley } 6702de41b84cSMatthew G. Knepley if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 67034acb8e1eSToby Isaac /* TODO: flips */ 6704de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 6705de41b84cSMatthew G. Knepley if (ierr) { 6706de41b84cSMatthew G. Knepley PetscMPIInt rank; 6707de41b84cSMatthew G. Knepley PetscErrorCode ierr2; 6708de41b84cSMatthew G. Knepley 6709de41b84cSMatthew G. Knepley ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 6710e4b003c7SBarry Smith ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 6711de41b84cSMatthew G. Knepley ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 671269291d52SBarry Smith ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2); 671369291d52SBarry Smith ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2); 6714de41b84cSMatthew G. Knepley CHKERRQ(ierr); 6715de41b84cSMatthew G. Knepley } 671669291d52SBarry Smith ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 6717de41b84cSMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 671869291d52SBarry Smith ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr); 671969291d52SBarry Smith ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr); 6720de41b84cSMatthew G. Knepley PetscFunctionReturn(0); 6721de41b84cSMatthew G. Knepley } 6722de41b84cSMatthew G. Knepley 67237c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 67247c927364SMatthew G. Knepley { 67257c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 67267c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 67277c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 672817c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 6729412e9a14SMatthew G. Knepley DMPolytopeType ct; 67307c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 67317c927364SMatthew G. Knepley PetscErrorCode ierr; 67327c927364SMatthew G. Knepley 67337c927364SMatthew G. Knepley PetscFunctionBegin; 67347c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 67357c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 673692fd8e1eSJed Brown if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);} 67377c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 673892fd8e1eSJed Brown if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);} 67397c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 6740e87a4003SBarry Smith if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 67417c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 6742e87a4003SBarry Smith if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 67437c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 67447c927364SMatthew G. Knepley ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 67457c927364SMatthew G. Knepley if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 6746580bdb30SBarry Smith ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr); 6747580bdb30SBarry Smith ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr); 67487c927364SMatthew G. Knepley /* Column indices */ 67497c927364SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 67507c927364SMatthew G. Knepley maxFPoints = numCPoints; 67517c927364SMatthew G. Knepley /* Compress out points not in the section */ 67527c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 67537c927364SMatthew G. Knepley ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 67547c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints*2; p += 2) { 67557c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 67567c927364SMatthew G. Knepley cpoints[q*2] = cpoints[p]; 67577c927364SMatthew G. Knepley cpoints[q*2+1] = cpoints[p+1]; 67587c927364SMatthew G. Knepley ++q; 67597c927364SMatthew G. Knepley } 67607c927364SMatthew G. Knepley } 67617c927364SMatthew G. Knepley numCPoints = q; 67627c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 67637c927364SMatthew G. Knepley PetscInt fdof; 67647c927364SMatthew G. Knepley 67657c927364SMatthew G. Knepley ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 67667c927364SMatthew G. Knepley if (!dof) continue; 67677c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 67687c927364SMatthew G. Knepley ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 67697c927364SMatthew G. Knepley coffsets[f+1] += fdof; 67707c927364SMatthew G. Knepley } 67717c927364SMatthew G. Knepley numCIndices += dof; 67727c927364SMatthew G. Knepley } 67737c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 67747c927364SMatthew G. Knepley /* Row indices */ 6775412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr); 6776412e9a14SMatthew G. Knepley { 6777412e9a14SMatthew G. Knepley DMPlexCellRefiner cr; 6778412e9a14SMatthew G. Knepley ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr); 6779412e9a14SMatthew G. Knepley ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 6780412e9a14SMatthew G. Knepley ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 6781412e9a14SMatthew G. Knepley } 678269291d52SBarry Smith ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 67837c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 67847c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 67857c927364SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 67867c927364SMatthew G. Knepley /* Compress out points not in the section */ 67877c927364SMatthew G. Knepley ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 67887c927364SMatthew G. Knepley for (p = 0; p < numFPoints*2; p += 2) { 67897c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 67907c927364SMatthew G. Knepley ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 67917c927364SMatthew G. Knepley if (!dof) continue; 67927c927364SMatthew G. Knepley for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 67937c927364SMatthew G. Knepley if (s < q) continue; 67947c927364SMatthew G. Knepley ftotpoints[q*2] = fpoints[p]; 67957c927364SMatthew G. Knepley ftotpoints[q*2+1] = fpoints[p+1]; 67967c927364SMatthew G. Knepley ++q; 67977c927364SMatthew G. Knepley } 67987c927364SMatthew G. Knepley } 67997c927364SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 68007c927364SMatthew G. Knepley } 68017c927364SMatthew G. Knepley numFPoints = q; 68027c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 68037c927364SMatthew G. Knepley PetscInt fdof; 68047c927364SMatthew G. Knepley 68057c927364SMatthew G. Knepley ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 68067c927364SMatthew G. Knepley if (!dof) continue; 68077c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 68087c927364SMatthew G. Knepley ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 68097c927364SMatthew G. Knepley foffsets[f+1] += fdof; 68107c927364SMatthew G. Knepley } 68117c927364SMatthew G. Knepley numFIndices += dof; 68127c927364SMatthew G. Knepley } 68137c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 68147c927364SMatthew G. Knepley 68158ccfff9cSToby Isaac if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices); 68168ccfff9cSToby Isaac if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices); 68177c927364SMatthew G. Knepley if (numFields) { 68184acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 68194acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 68204acb8e1eSToby Isaac 68214acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 68224acb8e1eSToby Isaac ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 68234acb8e1eSToby Isaac ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 68247c927364SMatthew G. Knepley } 68254acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 68264acb8e1eSToby Isaac ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 682736fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr); 68284acb8e1eSToby Isaac } 68294acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 68304acb8e1eSToby Isaac ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 683136fa2b79SJed Brown ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr); 68324acb8e1eSToby Isaac } 68334acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 68344acb8e1eSToby Isaac ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr); 68354acb8e1eSToby Isaac ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr); 68367c927364SMatthew G. Knepley } 68377c927364SMatthew G. Knepley } else { 68384acb8e1eSToby Isaac const PetscInt **permsF = NULL; 68394acb8e1eSToby Isaac const PetscInt **permsC = NULL; 68404acb8e1eSToby Isaac 68414acb8e1eSToby Isaac ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 68424acb8e1eSToby Isaac ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 68434acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 68444acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 68454acb8e1eSToby Isaac 68464acb8e1eSToby Isaac ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr); 684736fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr); 68487c927364SMatthew G. Knepley } 68494acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 68504acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 68514acb8e1eSToby Isaac 68524acb8e1eSToby Isaac ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr); 685336fa2b79SJed Brown ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr); 68547c927364SMatthew G. Knepley } 68554acb8e1eSToby Isaac ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr); 68564acb8e1eSToby Isaac ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr); 68577c927364SMatthew G. Knepley } 685869291d52SBarry Smith ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr); 68597c927364SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 68607c927364SMatthew G. Knepley PetscFunctionReturn(0); 68617c927364SMatthew G. Knepley } 68627c927364SMatthew G. Knepley 68637cd05799SMatthew G. Knepley /*@C 68647cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 68657cd05799SMatthew G. Knepley 68667cd05799SMatthew G. Knepley Input Parameter: 68677cd05799SMatthew G. Knepley . dm - The DMPlex object 68687cd05799SMatthew G. Knepley 68697cd05799SMatthew G. Knepley Output Parameter: 68707cd05799SMatthew G. Knepley . cellHeight - The height of a cell 68717cd05799SMatthew G. Knepley 68727cd05799SMatthew G. Knepley Level: developer 68737cd05799SMatthew G. Knepley 68747cd05799SMatthew G. Knepley .seealso DMPlexSetVTKCellHeight() 68757cd05799SMatthew G. Knepley @*/ 6876552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 6877552f7358SJed Brown { 6878552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 6879552f7358SJed Brown 6880552f7358SJed Brown PetscFunctionBegin; 6881552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6882552f7358SJed Brown PetscValidPointer(cellHeight, 2); 6883552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 6884552f7358SJed Brown PetscFunctionReturn(0); 6885552f7358SJed Brown } 6886552f7358SJed Brown 68877cd05799SMatthew G. Knepley /*@C 68887cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 68897cd05799SMatthew G. Knepley 68907cd05799SMatthew G. Knepley Input Parameters: 68917cd05799SMatthew G. Knepley + dm - The DMPlex object 68927cd05799SMatthew G. Knepley - cellHeight - The height of a cell 68937cd05799SMatthew G. Knepley 68947cd05799SMatthew G. Knepley Level: developer 68957cd05799SMatthew G. Knepley 68967cd05799SMatthew G. Knepley .seealso DMPlexGetVTKCellHeight() 68977cd05799SMatthew G. Knepley @*/ 6898552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 6899552f7358SJed Brown { 6900552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 6901552f7358SJed Brown 6902552f7358SJed Brown PetscFunctionBegin; 6903552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6904552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 6905552f7358SJed Brown PetscFunctionReturn(0); 6906552f7358SJed Brown } 6907552f7358SJed Brown 6908e6139122SMatthew G. Knepley /*@ 6909e6139122SMatthew G. Knepley DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions 6910e6139122SMatthew G. Knepley 6911e6139122SMatthew G. Knepley Input Parameter: 6912e6139122SMatthew G. Knepley . dm - The DMPlex object 6913e6139122SMatthew G. Knepley 6914e6139122SMatthew G. Knepley Output Parameters: 69152a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL 69162a9f31c0SMatthew G. Knepley - gcEnd - The upper bound on ghost cells, or NULL 6917e6139122SMatthew G. Knepley 69182a9f31c0SMatthew G. Knepley Level: advanced 6919e6139122SMatthew G. Knepley 6920412e9a14SMatthew G. Knepley .seealso DMPlexConstructGhostCells(), DMPlexSetGhostCellStratum() 6921e6139122SMatthew G. Knepley @*/ 6922e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) 6923e6139122SMatthew G. Knepley { 6924412e9a14SMatthew G. Knepley DMLabel ctLabel; 6925e6139122SMatthew G. Knepley PetscErrorCode ierr; 6926e6139122SMatthew G. Knepley 6927e6139122SMatthew G. Knepley PetscFunctionBegin; 6928e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6929412e9a14SMatthew G. Knepley ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 6930412e9a14SMatthew G. Knepley ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr); 6931e6139122SMatthew G. Knepley PetscFunctionReturn(0); 6932e6139122SMatthew G. Knepley } 6933e6139122SMatthew G. Knepley 6934552f7358SJed Brown /* We can easily have a form that takes an IS instead */ 69359886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 6936552f7358SJed Brown { 6937552f7358SJed Brown PetscSection section, globalSection; 6938552f7358SJed Brown PetscInt *numbers, p; 6939552f7358SJed Brown PetscErrorCode ierr; 6940552f7358SJed Brown 6941552f7358SJed Brown PetscFunctionBegin; 694282f516ccSBarry Smith ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 6943552f7358SJed Brown ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 6944552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 6945552f7358SJed Brown ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 6946552f7358SJed Brown } 6947552f7358SJed Brown ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 694815b58121SMatthew G. Knepley ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 6949854ce69bSBarry Smith ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 6950552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 6951552f7358SJed Brown ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 6952ef48cebcSMatthew G. Knepley if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 6953ef48cebcSMatthew G. Knepley else numbers[p-pStart] += shift; 6954552f7358SJed Brown } 695582f516ccSBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 6956ef48cebcSMatthew G. Knepley if (globalSize) { 6957ef48cebcSMatthew G. Knepley PetscLayout layout; 6958ef48cebcSMatthew G. Knepley ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 6959ef48cebcSMatthew G. Knepley ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 6960ef48cebcSMatthew G. Knepley ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 6961ef48cebcSMatthew G. Knepley } 6962552f7358SJed Brown ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 6963552f7358SJed Brown ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 6964552f7358SJed Brown PetscFunctionReturn(0); 6965552f7358SJed Brown } 6966552f7358SJed Brown 696781ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 6968552f7358SJed Brown { 6969412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 6970552f7358SJed Brown PetscErrorCode ierr; 6971552f7358SJed Brown 6972552f7358SJed Brown PetscFunctionBegin; 6973552f7358SJed Brown ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 6974412e9a14SMatthew G. Knepley if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 6975412e9a14SMatthew G. Knepley else {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);} 69769886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr); 697781ed3555SMatthew G. Knepley PetscFunctionReturn(0); 6978552f7358SJed Brown } 697981ed3555SMatthew G. Knepley 69808dab3259SMatthew G. Knepley /*@ 69817cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 69827cd05799SMatthew G. Knepley 69837cd05799SMatthew G. Knepley Input Parameter: 69847cd05799SMatthew G. Knepley . dm - The DMPlex object 69857cd05799SMatthew G. Knepley 69867cd05799SMatthew G. Knepley Output Parameter: 69877cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 69887cd05799SMatthew G. Knepley 69897cd05799SMatthew G. Knepley Level: developer 69907cd05799SMatthew G. Knepley 69917cd05799SMatthew G. Knepley .seealso DMPlexGetVertexNumbering() 69927cd05799SMatthew G. Knepley @*/ 699381ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 699481ed3555SMatthew G. Knepley { 699581ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex*) dm->data; 699681ed3555SMatthew G. Knepley PetscErrorCode ierr; 699781ed3555SMatthew G. Knepley 699881ed3555SMatthew G. Knepley PetscFunctionBegin; 699981ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 700081ed3555SMatthew G. Knepley if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);} 7001552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 7002552f7358SJed Brown PetscFunctionReturn(0); 7003552f7358SJed Brown } 7004552f7358SJed Brown 700581ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 700681ed3555SMatthew G. Knepley { 7007412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 700881ed3555SMatthew G. Knepley PetscErrorCode ierr; 700981ed3555SMatthew G. Knepley 701081ed3555SMatthew G. Knepley PetscFunctionBegin; 701181ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 701281ed3555SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 70139886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr); 701481ed3555SMatthew G. Knepley PetscFunctionReturn(0); 701581ed3555SMatthew G. Knepley } 701681ed3555SMatthew G. Knepley 70178dab3259SMatthew G. Knepley /*@ 70186aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 70197cd05799SMatthew G. Knepley 70207cd05799SMatthew G. Knepley Input Parameter: 70217cd05799SMatthew G. Knepley . dm - The DMPlex object 70227cd05799SMatthew G. Knepley 70237cd05799SMatthew G. Knepley Output Parameter: 70247cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 70257cd05799SMatthew G. Knepley 70267cd05799SMatthew G. Knepley Level: developer 70277cd05799SMatthew G. Knepley 70287cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering() 70297cd05799SMatthew G. Knepley @*/ 7030552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 7031552f7358SJed Brown { 7032552f7358SJed Brown DM_Plex *mesh = (DM_Plex*) dm->data; 7033552f7358SJed Brown PetscErrorCode ierr; 7034552f7358SJed Brown 7035552f7358SJed Brown PetscFunctionBegin; 7036552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 703781ed3555SMatthew G. Knepley if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);} 7038552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 7039552f7358SJed Brown PetscFunctionReturn(0); 7040552f7358SJed Brown } 7041552f7358SJed Brown 70428dab3259SMatthew G. Knepley /*@ 70437cd05799SMatthew G. Knepley DMPlexCreatePointNumbering - Create a global numbering for all points on this process 70447cd05799SMatthew G. Knepley 70457cd05799SMatthew G. Knepley Input Parameter: 70467cd05799SMatthew G. Knepley . dm - The DMPlex object 70477cd05799SMatthew G. Knepley 70487cd05799SMatthew G. Knepley Output Parameter: 70497cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 70507cd05799SMatthew G. Knepley 70517cd05799SMatthew G. Knepley Level: developer 70527cd05799SMatthew G. Knepley 70537cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering() 70547cd05799SMatthew G. Knepley @*/ 7055ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 7056ef48cebcSMatthew G. Knepley { 7057ef48cebcSMatthew G. Knepley IS nums[4]; 7058862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 7059ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 7060ef48cebcSMatthew G. Knepley PetscErrorCode ierr; 7061ef48cebcSMatthew G. Knepley 7062ef48cebcSMatthew G. Knepley PetscFunctionBegin; 7063ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7064ef48cebcSMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 70658abc87a0SMichael Lange /* For unstratified meshes use dim instead of depth */ 70668abc87a0SMichael Lange if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 7067862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 7068862913ffSStefano Zampini PetscInt end; 7069862913ffSStefano Zampini 7070862913ffSStefano Zampini depths[d] = depth-d; 7071862913ffSStefano Zampini ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr); 7072862913ffSStefano Zampini if (!(starts[d]-end)) { starts[d] = depths[d] = -1; } 7073862913ffSStefano Zampini } 7074862913ffSStefano Zampini ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr); 7075862913ffSStefano Zampini ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 7076862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 7077862913ffSStefano Zampini if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]); 7078862913ffSStefano Zampini } 7079ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 7080ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 7081ef48cebcSMatthew G. Knepley 7082862913ffSStefano Zampini ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr); 70839886b8cfSStefano Zampini ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 7084ef48cebcSMatthew G. Knepley shift += gsize; 7085ef48cebcSMatthew G. Knepley } 7086302440fdSBarry Smith ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 7087ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 7088ef48cebcSMatthew G. Knepley PetscFunctionReturn(0); 7089ef48cebcSMatthew G. Knepley } 7090ef48cebcSMatthew G. Knepley 709108a22f4bSMatthew G. Knepley 709208a22f4bSMatthew G. Knepley /*@ 709308a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 709408a22f4bSMatthew G. Knepley 709508a22f4bSMatthew G. Knepley Input Parameter: 709608a22f4bSMatthew G. Knepley . dm - The DMPlex object 709708a22f4bSMatthew G. Knepley 709808a22f4bSMatthew G. Knepley Output Parameter: 709908a22f4bSMatthew G. Knepley . ranks - The rank field 710008a22f4bSMatthew G. Knepley 710108a22f4bSMatthew G. Knepley Options Database Keys: 710208a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer 710308a22f4bSMatthew G. Knepley 710408a22f4bSMatthew G. Knepley Level: intermediate 710508a22f4bSMatthew G. Knepley 710608a22f4bSMatthew G. Knepley .seealso: DMView() 710708a22f4bSMatthew G. Knepley @*/ 710808a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 710908a22f4bSMatthew G. Knepley { 711008a22f4bSMatthew G. Knepley DM rdm; 711108a22f4bSMatthew G. Knepley PetscFE fe; 711208a22f4bSMatthew G. Knepley PetscScalar *r; 711308a22f4bSMatthew G. Knepley PetscMPIInt rank; 711408a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 711508a22f4bSMatthew G. Knepley PetscErrorCode ierr; 711608a22f4bSMatthew G. Knepley 711708a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 7118f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7119f95ace6aSMatthew G. Knepley PetscValidPointer(ranks, 2); 712008a22f4bSMatthew G. Knepley ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 712108a22f4bSMatthew G. Knepley ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 712208a22f4bSMatthew G. Knepley ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 7123f95ace6aSMatthew G. Knepley ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___rank_", -1, &fe);CHKERRQ(ierr); 712408a22f4bSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr); 7125e5e52638SMatthew G. Knepley ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 712608a22f4bSMatthew G. Knepley ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 7127e5e52638SMatthew G. Knepley ierr = DMCreateDS(rdm);CHKERRQ(ierr); 712808a22f4bSMatthew G. Knepley ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 712908a22f4bSMatthew G. Knepley ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr); 713008a22f4bSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr); 713108a22f4bSMatthew G. Knepley ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr); 713208a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 713308a22f4bSMatthew G. Knepley PetscScalar *lr; 713408a22f4bSMatthew G. Knepley 713508a22f4bSMatthew G. Knepley ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr); 713671f09efeSPierre Jolivet if (lr) *lr = rank; 713708a22f4bSMatthew G. Knepley } 713808a22f4bSMatthew G. Knepley ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr); 713908a22f4bSMatthew G. Knepley ierr = DMDestroy(&rdm);CHKERRQ(ierr); 714008a22f4bSMatthew G. Knepley PetscFunctionReturn(0); 714108a22f4bSMatthew G. Knepley } 714208a22f4bSMatthew G. Knepley 7143ca8062c8SMatthew G. Knepley /*@ 714418e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 714518e14f0cSMatthew G. Knepley 714618e14f0cSMatthew G. Knepley Input Parameters: 714718e14f0cSMatthew G. Knepley + dm - The DMPlex 714818e14f0cSMatthew G. Knepley - label - The DMLabel 714918e14f0cSMatthew G. Knepley 715018e14f0cSMatthew G. Knepley Output Parameter: 715118e14f0cSMatthew G. Knepley . val - The label value field 715218e14f0cSMatthew G. Knepley 715318e14f0cSMatthew G. Knepley Options Database Keys: 715418e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer 715518e14f0cSMatthew G. Knepley 715618e14f0cSMatthew G. Knepley Level: intermediate 715718e14f0cSMatthew G. Knepley 715818e14f0cSMatthew G. Knepley .seealso: DMView() 715918e14f0cSMatthew G. Knepley @*/ 716018e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 716118e14f0cSMatthew G. Knepley { 716218e14f0cSMatthew G. Knepley DM rdm; 716318e14f0cSMatthew G. Knepley PetscFE fe; 716418e14f0cSMatthew G. Knepley PetscScalar *v; 716518e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 716618e14f0cSMatthew G. Knepley PetscErrorCode ierr; 716718e14f0cSMatthew G. Knepley 716818e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 716918e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 717018e14f0cSMatthew G. Knepley PetscValidPointer(label, 2); 717118e14f0cSMatthew G. Knepley PetscValidPointer(val, 3); 717218e14f0cSMatthew G. Knepley ierr = DMClone(dm, &rdm);CHKERRQ(ierr); 717318e14f0cSMatthew G. Knepley ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr); 717418e14f0cSMatthew G. Knepley ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr); 717518e14f0cSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr); 7176e5e52638SMatthew G. Knepley ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 717718e14f0cSMatthew G. Knepley ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 7178e5e52638SMatthew G. Knepley ierr = DMCreateDS(rdm);CHKERRQ(ierr); 717918e14f0cSMatthew G. Knepley ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 718018e14f0cSMatthew G. Knepley ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr); 7181effbd7cbSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr); 718218e14f0cSMatthew G. Knepley ierr = VecGetArray(*val, &v);CHKERRQ(ierr); 718318e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 718418e14f0cSMatthew G. Knepley PetscScalar *lv; 718518e14f0cSMatthew G. Knepley PetscInt cval; 718618e14f0cSMatthew G. Knepley 718718e14f0cSMatthew G. Knepley ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr); 718818e14f0cSMatthew G. Knepley ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr); 718918e14f0cSMatthew G. Knepley *lv = cval; 719018e14f0cSMatthew G. Knepley } 719118e14f0cSMatthew G. Knepley ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr); 719218e14f0cSMatthew G. Knepley ierr = DMDestroy(&rdm);CHKERRQ(ierr); 719318e14f0cSMatthew G. Knepley PetscFunctionReturn(0); 719418e14f0cSMatthew G. Knepley } 719518e14f0cSMatthew G. Knepley 719618e14f0cSMatthew G. Knepley /*@ 7197ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 7198ca8062c8SMatthew G. Knepley 719969916449SMatthew G. Knepley Input Parameter: 720069916449SMatthew G. Knepley . dm - The DMPlex object 7201ca8062c8SMatthew G. Knepley 720295eb5ee5SVaclav Hapla Notes: 720395eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 720495eb5ee5SVaclav Hapla 720595eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7206ca8062c8SMatthew G. Knepley 7207ca8062c8SMatthew G. Knepley Level: developer 7208ca8062c8SMatthew G. Knepley 720995eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions() 7210ca8062c8SMatthew G. Knepley @*/ 7211ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm) 7212ca8062c8SMatthew G. Knepley { 7213ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 7214ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 7215ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 721657beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 721757beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 7218ca8062c8SMatthew G. Knepley PetscErrorCode ierr; 7219ca8062c8SMatthew G. Knepley 7220ca8062c8SMatthew G. Knepley PetscFunctionBegin; 7221ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7222412e9a14SMatthew G. Knepley ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr); 7223ca8062c8SMatthew G. Knepley ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 7224ca8062c8SMatthew G. Knepley ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 7225ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 7226ca8062c8SMatthew G. Knepley ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 7227ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 7228ca8062c8SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 7229ca8062c8SMatthew G. Knepley ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 7230ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 723142e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 723242e66dfaSMatthew G. Knepley PetscInt d; 723342e66dfaSMatthew G. Knepley for (d = c-1; d >= 0; --d) { 723442e66dfaSMatthew G. Knepley if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 723542e66dfaSMatthew G. Knepley } 7236ca8062c8SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 7237ca8062c8SMatthew G. Knepley ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 7238ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 7239ca8062c8SMatthew G. Knepley if (support[s] == p) break; 7240ca8062c8SMatthew G. Knepley } 724142e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s+1] != p))) { 72428ccfff9cSToby Isaac ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr); 7243ca8062c8SMatthew G. Knepley for (s = 0; s < coneSize; ++s) { 72448ccfff9cSToby Isaac ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr); 7245ca8062c8SMatthew G. Knepley } 7246302440fdSBarry Smith ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 72478ccfff9cSToby Isaac ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr); 7248ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 72498ccfff9cSToby Isaac ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr); 7250ca8062c8SMatthew G. Knepley } 7251302440fdSBarry Smith ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 72528ccfff9cSToby Isaac if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]); 72538ccfff9cSToby Isaac else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]); 7254ca8062c8SMatthew G. Knepley } 725542e66dfaSMatthew G. Knepley } 725657beb4faSStefano Zampini ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr); 725757beb4faSStefano Zampini if (p != pp) { storagecheck = PETSC_FALSE; continue; } 7258ca8062c8SMatthew G. Knepley ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 7259ca8062c8SMatthew G. Knepley ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 7260ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 7261ca8062c8SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 7262ca8062c8SMatthew G. Knepley ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 7263ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 726457beb4faSStefano Zampini ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr); 726557beb4faSStefano Zampini if (cone[c] != pp) { c = 0; break; } 7266ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 7267ca8062c8SMatthew G. Knepley } 7268ca8062c8SMatthew G. Knepley if (c >= coneSize) { 72698ccfff9cSToby Isaac ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr); 7270ca8062c8SMatthew G. Knepley for (c = 0; c < supportSize; ++c) { 72718ccfff9cSToby Isaac ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr); 7272ca8062c8SMatthew G. Knepley } 7273302440fdSBarry Smith ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 72748ccfff9cSToby Isaac ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr); 7275ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 72768ccfff9cSToby Isaac ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr); 7277ca8062c8SMatthew G. Knepley } 7278302440fdSBarry Smith ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 72798ccfff9cSToby Isaac SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]); 7280ca8062c8SMatthew G. Knepley } 7281ca8062c8SMatthew G. Knepley } 7282ca8062c8SMatthew G. Knepley } 728357beb4faSStefano Zampini if (storagecheck) { 7284ca8062c8SMatthew G. Knepley ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 7285ca8062c8SMatthew G. Knepley ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 72868ccfff9cSToby Isaac if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize); 728757beb4faSStefano Zampini } 7288ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 7289ca8062c8SMatthew G. Knepley } 7290ca8062c8SMatthew G. Knepley 7291412e9a14SMatthew G. Knepley /* 7292412e9a14SMatthew G. Knepley For submeshes with cohesive cells (see DMPlexConstructCohesiveCells()), we allow a special case where some of the boundary of a face (edges and vertices) are not duplicated. We call these special boundary points "unsplit", since the same edge or vertex appears in both copies of the face. These unsplit points throw off our counting, so we have to explicitly account for them here. 7293412e9a14SMatthew G. Knepley */ 7294412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 7295412e9a14SMatthew G. Knepley { 7296412e9a14SMatthew G. Knepley DMPolytopeType cct; 7297412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 7298412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 7299412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 7300412e9a14SMatthew G. Knepley PetscErrorCode ierr; 7301412e9a14SMatthew G. Knepley 7302412e9a14SMatthew G. Knepley PetscFunctionBegin; 7303412e9a14SMatthew G. Knepley *unsplit = 0; 7304412e9a14SMatthew G. Knepley switch (ct) { 7305412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 7306412e9a14SMatthew G. Knepley ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 7307412e9a14SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7308412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 7309412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr); 7310412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 7311412e9a14SMatthew G. Knepley } 7312412e9a14SMatthew G. Knepley break; 7313412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 7314412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 7315412e9a14SMatthew G. Knepley ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 7316412e9a14SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7317412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 7318412e9a14SMatthew G. Knepley ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr); 7319412e9a14SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr); 7320412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 7321412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr); 7322412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 7323412e9a14SMatthew G. Knepley PetscInt p; 7324412e9a14SMatthew G. Knepley for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break; 7325412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 7326412e9a14SMatthew G. Knepley } 7327412e9a14SMatthew G. Knepley } 7328412e9a14SMatthew G. Knepley } 7329412e9a14SMatthew G. Knepley break; 7330412e9a14SMatthew G. Knepley default: break; 7331412e9a14SMatthew G. Knepley } 7332412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 7333412e9a14SMatthew G. Knepley ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr); 7334412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 7335412e9a14SMatthew G. Knepley } 7336412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 7337412e9a14SMatthew G. Knepley } 7338412e9a14SMatthew G. Knepley 7339ca8062c8SMatthew G. Knepley /*@ 7340ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 7341ca8062c8SMatthew G. Knepley 7342ca8062c8SMatthew G. Knepley Input Parameters: 7343ca8062c8SMatthew G. Knepley + dm - The DMPlex object 734458723a97SMatthew G. Knepley - cellHeight - Normally 0 7345ca8062c8SMatthew G. Knepley 734695eb5ee5SVaclav Hapla Notes: 734795eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 734825c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 7349ca8062c8SMatthew G. Knepley 735095eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 735195eb5ee5SVaclav Hapla 7352ca8062c8SMatthew G. Knepley Level: developer 7353ca8062c8SMatthew G. Knepley 735495eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions() 7355ca8062c8SMatthew G. Knepley @*/ 735625c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 7357ca8062c8SMatthew G. Knepley { 7358412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 7359412e9a14SMatthew G. Knepley DMPolytopeType ct; 7360412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 7361ca8062c8SMatthew G. Knepley PetscErrorCode ierr; 7362ca8062c8SMatthew G. Knepley 7363ca8062c8SMatthew G. Knepley PetscFunctionBegin; 7364ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7365412e9a14SMatthew G. Knepley ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr); 736625c50c26SVaclav Hapla ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 736758723a97SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7368412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 7369412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 7370412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 737158723a97SMatthew G. Knepley 7372412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 7373412e9a14SMatthew G. Knepley if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c); 7374412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 7375412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 7376412e9a14SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7377412e9a14SMatthew G. Knepley if (coneSize != DMPolytopeTypeGetConeSize(ct)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has cone size %D != %D", c, coneSize, DMPolytopeTypeGetConeSize(ct)); 7378412e9a14SMatthew G. Knepley } 737958723a97SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 738058723a97SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 738158723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 7382412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 738358723a97SMatthew G. Knepley } 738458723a97SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 7385412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 7386412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 7387412e9a14SMatthew G. Knepley PetscInt unsplit; 738842363296SMatthew G. Knepley 7389412e9a14SMatthew G. Knepley ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 7390412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 739142363296SMatthew G. Knepley } 7392412e9a14SMatthew G. Knepley if (Nv != DMPolytopeTypeGetNumVertices(ct)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D vertices != %D", c, Nv, DMPolytopeTypeGetNumVertices(ct)); 739342363296SMatthew G. Knepley } 7394ca8062c8SMatthew G. Knepley PetscFunctionReturn(0); 7395ca8062c8SMatthew G. Knepley } 73969bf0dad6SMatthew G. Knepley 73979bf0dad6SMatthew G. Knepley /*@ 73989bf0dad6SMatthew G. Knepley DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 73999bf0dad6SMatthew G. Knepley 7400899ea2b8SJacob Faibussowitsch Not Collective 7401899ea2b8SJacob Faibussowitsch 74029bf0dad6SMatthew G. Knepley Input Parameters: 74039bf0dad6SMatthew G. Knepley + dm - The DMPlex object 74049bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 74059bf0dad6SMatthew G. Knepley 740645da879fSVaclav Hapla Notes: 740745da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 740845da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 740945da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 741045da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 74119bf0dad6SMatthew G. Knepley 741295eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 741395eb5ee5SVaclav Hapla 74149bf0dad6SMatthew G. Knepley Level: developer 74159bf0dad6SMatthew G. Knepley 741695eb5ee5SVaclav Hapla .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions() 74179bf0dad6SMatthew G. Knepley @*/ 741825c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 74199bf0dad6SMatthew G. Knepley { 7420ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 74219bf0dad6SMatthew G. Knepley PetscErrorCode ierr; 7422899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 74239bf0dad6SMatthew G. Knepley 74249bf0dad6SMatthew G. Knepley PetscFunctionBegin; 74259bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7426899ea2b8SJacob Faibussowitsch ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr); 742745da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0); 742845da879fSVaclav Hapla if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) { 7429899ea2b8SJacob Faibussowitsch PetscMPIInt rank; 7430899ea2b8SJacob Faibussowitsch MPI_Comm comm; 7431899ea2b8SJacob Faibussowitsch 7432899ea2b8SJacob Faibussowitsch ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 7433899ea2b8SJacob Faibussowitsch ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 743445da879fSVaclav Hapla SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank); 7435899ea2b8SJacob Faibussowitsch } 7436899ea2b8SJacob Faibussowitsch 7437c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 7438ab91121cSMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 74399bf0dad6SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7440ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 74413554e41dSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 74423554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 7443412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 7444412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 7445ba2698f1SMatthew G. Knepley DMPolytopeType ct; 7446412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 7447412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 74489bf0dad6SMatthew G. Knepley 7449ba2698f1SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 7450412e9a14SMatthew G. Knepley ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 7451412e9a14SMatthew G. Knepley if (unsplit) continue; 74529bf0dad6SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 74539bf0dad6SMatthew G. Knepley ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 74549bf0dad6SMatthew G. Knepley ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 74559bf0dad6SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 74569bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 74579bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 74589bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 74599bf0dad6SMatthew G. Knepley } 7460412e9a14SMatthew G. Knepley ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 74618ccfff9cSToby Isaac if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has %D faces but should have %D", c, coneSize, numFaces); 74629bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 74639bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 74649bf0dad6SMatthew G. Knepley 74659bf0dad6SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 74669bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize*2; cl += 2) { 74679bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 74689bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 74699bf0dad6SMatthew G. Knepley } 7470412e9a14SMatthew G. Knepley if (fnumCorners != faceSizes[f]) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D (%D) of cell %D has %D vertices but should have %D", cone[f], f, c, fnumCorners, faceSizes[f]); 74719bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 7472412e9a14SMatthew G. Knepley if (fclosure[v] != faces[fOff+v]) SETERRQ6(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D (%d) of cell %D vertex %D, %D != %D", cone[f], f, c, v, fclosure[v], faces[fOff+v]); 74739bf0dad6SMatthew G. Knepley } 74749bf0dad6SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 7475412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 74769bf0dad6SMatthew G. Knepley } 7477412e9a14SMatthew G. Knepley ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr); 74789bf0dad6SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 74799bf0dad6SMatthew G. Knepley } 74803554e41dSMatthew G. Knepley } 7481552f7358SJed Brown PetscFunctionReturn(0); 7482552f7358SJed Brown } 74833913d7c8SMatthew G. Knepley 7484bb6a34a8SMatthew G. Knepley /*@ 7485bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 7486bb6a34a8SMatthew G. Knepley 7487bb6a34a8SMatthew G. Knepley Input Parameter: 7488bb6a34a8SMatthew G. Knepley . dm - The DMPlex object 7489bb6a34a8SMatthew G. Knepley 749095eb5ee5SVaclav Hapla Notes: 749195eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 749295eb5ee5SVaclav Hapla 749395eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7494bb6a34a8SMatthew G. Knepley 7495bb6a34a8SMatthew G. Knepley Level: developer 7496bb6a34a8SMatthew G. Knepley 749795eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions() 7498bb6a34a8SMatthew G. Knepley @*/ 7499bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm) 7500bb6a34a8SMatthew G. Knepley { 7501bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 7502bb6a34a8SMatthew G. Knepley PetscReal vol; 7503412e9a14SMatthew G. Knepley PetscBool periodic; 7504412e9a14SMatthew G. Knepley PetscInt dim, depth, d, cStart, cEnd, c; 7505bb6a34a8SMatthew G. Knepley PetscErrorCode ierr; 7506bb6a34a8SMatthew G. Knepley 7507bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 7508bb6a34a8SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 7509bb6a34a8SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 7510412e9a14SMatthew G. Knepley ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 7511bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 7512bb6a34a8SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7513412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 7514412e9a14SMatthew G. Knepley DMPolytopeType ct; 7515412e9a14SMatthew G. Knepley PetscInt unsplit; 7516412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 7517412e9a14SMatthew G. Knepley 7518412e9a14SMatthew G. Knepley ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 7519412e9a14SMatthew G. Knepley switch (ct) { 7520412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 7521412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 7522412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 7523412e9a14SMatthew G. Knepley ignoreZeroVol = PETSC_TRUE; break; 7524412e9a14SMatthew G. Knepley default: break; 7525412e9a14SMatthew G. Knepley } 7526412e9a14SMatthew G. Knepley switch (ct) { 7527412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 7528412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 7529412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 7530412e9a14SMatthew G. Knepley continue; 7531412e9a14SMatthew G. Knepley default: break; 7532412e9a14SMatthew G. Knepley } 7533412e9a14SMatthew G. Knepley ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr); 7534412e9a14SMatthew G. Knepley if (unsplit) continue; 7535bb6a34a8SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr); 7536412e9a14SMatthew G. Knepley if (detJ < -PETSC_SMALL || (detJ <= 0.0 && !ignoreZeroVol)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted, |J| = %g", c, (double) detJ); 7537bb6a34a8SMatthew G. Knepley ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr); 7538412e9a14SMatthew G. Knepley if (depth > 1 && !periodic) { 7539bb6a34a8SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); 7540412e9a14SMatthew G. Knepley if (vol < -PETSC_SMALL || (vol <= 0.0 && !ignoreZeroVol)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %d is inverted, vol = %g", c, (double) vol); 7541bb6a34a8SMatthew G. Knepley ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr); 7542bb6a34a8SMatthew G. Knepley } 7543bb6a34a8SMatthew G. Knepley } 7544bb6a34a8SMatthew G. Knepley PetscFunctionReturn(0); 7545bb6a34a8SMatthew G. Knepley } 7546bb6a34a8SMatthew G. Knepley 754703da9461SVaclav Hapla /*@ 7548e83a0d2dSVaclav Hapla DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex. 754903da9461SVaclav Hapla 755003da9461SVaclav Hapla Input Parameters: 755103da9461SVaclav Hapla . dm - The DMPlex object 755203da9461SVaclav Hapla 7553e83a0d2dSVaclav Hapla Notes: 7554e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 75558918e3e2SVaclav Hapla It currently checks only meshes with no partition overlapping. 755603da9461SVaclav Hapla 755795eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 755895eb5ee5SVaclav Hapla 755903da9461SVaclav Hapla Level: developer 756003da9461SVaclav Hapla 756195eb5ee5SVaclav Hapla .seealso: DMGetPointSF(), DMSetFromOptions() 756203da9461SVaclav Hapla @*/ 756303da9461SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm) 756403da9461SVaclav Hapla { 7565f0cfc026SVaclav Hapla PetscSF pointSF; 7566f5869d18SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd, l, nleaves, nroots, overlap; 7567f5869d18SMatthew G. Knepley const PetscInt *locals, *rootdegree; 7568f0cfc026SVaclav Hapla PetscBool distributed; 756903da9461SVaclav Hapla PetscErrorCode ierr; 757003da9461SVaclav Hapla 757103da9461SVaclav Hapla PetscFunctionBegin; 757203da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7573f0cfc026SVaclav Hapla ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr); 7574f0cfc026SVaclav Hapla ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 7575f0cfc026SVaclav Hapla if (!distributed) PetscFunctionReturn(0); 7576f0cfc026SVaclav Hapla ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr); 7577f0cfc026SVaclav Hapla if (overlap) { 75788918e3e2SVaclav Hapla ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping"); 75798918e3e2SVaclav Hapla PetscFunctionReturn(0); 75808918e3e2SVaclav Hapla } 7581f0cfc026SVaclav Hapla if (!pointSF) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached"); 7582f0cfc026SVaclav Hapla ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr); 7583f0cfc026SVaclav Hapla if (nroots < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set"); 7584f5869d18SMatthew G. Knepley ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr); 7585f5869d18SMatthew G. Knepley ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr); 758603da9461SVaclav Hapla 7587ece87651SVaclav Hapla /* 1) check there are no faces in 2D, cells in 3D, in interface */ 7588f5869d18SMatthew G. Knepley ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 7589f5869d18SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 7590f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 7591f5869d18SMatthew G. Knepley const PetscInt point = locals[l]; 7592f5869d18SMatthew G. Knepley 7593f5869d18SMatthew G. Knepley if (point >= cStart && point < cEnd) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point); 759403da9461SVaclav Hapla } 7595ece87651SVaclav Hapla 7596f5869d18SMatthew G. Knepley /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 7597f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 7598f5869d18SMatthew G. Knepley const PetscInt point = locals[l]; 7599f5869d18SMatthew G. Knepley const PetscInt *cone; 7600f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 7601f5869d18SMatthew G. Knepley 7602f5869d18SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 7603f5869d18SMatthew G. Knepley ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 7604f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 7605f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 7606f5869d18SMatthew G. Knepley ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr); 7607f5869d18SMatthew G. Knepley if (idx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]); 7608f5869d18SMatthew G. Knepley } 7609f5869d18SMatthew G. Knepley } 7610ece87651SVaclav Hapla } 761103da9461SVaclav Hapla PetscFunctionReturn(0); 761203da9461SVaclav Hapla } 761303da9461SVaclav Hapla 7614068a5610SStefano Zampini typedef struct cell_stats 7615068a5610SStefano Zampini { 7616068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 7617068a5610SStefano Zampini PetscInt count; 7618068a5610SStefano Zampini } cell_stats_t; 7619068a5610SStefano Zampini 762025befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype) 7621068a5610SStefano Zampini { 7622068a5610SStefano Zampini PetscInt i, N = *len; 7623068a5610SStefano Zampini 7624068a5610SStefano Zampini for (i = 0; i < N; i++) { 7625068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *) a; 7626068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *) b; 7627068a5610SStefano Zampini 7628068a5610SStefano Zampini B->min = PetscMin(A->min,B->min); 7629068a5610SStefano Zampini B->max = PetscMax(A->max,B->max); 7630068a5610SStefano Zampini B->sum += A->sum; 7631068a5610SStefano Zampini B->squaresum += A->squaresum; 7632068a5610SStefano Zampini B->count += A->count; 7633068a5610SStefano Zampini } 7634068a5610SStefano Zampini } 7635068a5610SStefano Zampini 7636068a5610SStefano Zampini /*@ 763743fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 7638068a5610SStefano Zampini 76398261a58bSMatthew G. Knepley Collective on dm 76408261a58bSMatthew G. Knepley 7641068a5610SStefano Zampini Input Parameters: 7642068a5610SStefano Zampini + dm - The DMPlex object 764343fa8764SMatthew G. Knepley . output - If true, statistics will be displayed on stdout 764443fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output 7645068a5610SStefano Zampini 764695eb5ee5SVaclav Hapla Notes: 764795eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 764895eb5ee5SVaclav Hapla 764995eb5ee5SVaclav Hapla For the complete list of DMPlexCheck* functions, see DMSetFromOptions(). 7650068a5610SStefano Zampini 7651068a5610SStefano Zampini Level: developer 7652068a5610SStefano Zampini 765395eb5ee5SVaclav Hapla .seealso: DMSetFromOptions() 7654068a5610SStefano Zampini @*/ 765543fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 7656068a5610SStefano Zampini { 7657068a5610SStefano Zampini DM dmCoarse; 765843fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 765943fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 766043fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 766143fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 7662412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 766343fa8764SMatthew G. Knepley PetscMPIInt rank,size; 7664068a5610SStefano Zampini PetscErrorCode ierr; 7665068a5610SStefano Zampini 7666068a5610SStefano Zampini PetscFunctionBegin; 7667068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7668068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 7669068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 7670068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 7671068a5610SStefano Zampini stats.count = 0; 7672068a5610SStefano Zampini 767343fa8764SMatthew G. Knepley ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 767443fa8764SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 767543fa8764SMatthew G. Knepley ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr); 767643fa8764SMatthew G. Knepley ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr); 7677412e9a14SMatthew G. Knepley ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 767843fa8764SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); 7679412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 7680068a5610SStefano Zampini PetscInt i; 7681068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 7682068a5610SStefano Zampini 7683068a5610SStefano Zampini ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr); 7684068a5610SStefano Zampini if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c); 768543fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 7686068a5610SStefano Zampini frobJ += J[i] * J[i]; 7687068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 7688068a5610SStefano Zampini } 7689068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 7690068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 7691068a5610SStefano Zampini 7692068a5610SStefano Zampini stats.min = PetscMin(stats.min,cond); 7693068a5610SStefano Zampini stats.max = PetscMax(stats.max,cond); 7694068a5610SStefano Zampini stats.sum += cond; 7695068a5610SStefano Zampini stats.squaresum += cond2; 7696068a5610SStefano Zampini stats.count++; 76978261a58bSMatthew G. Knepley if (output && cond > limit) { 769843fa8764SMatthew G. Knepley PetscSection coordSection; 769943fa8764SMatthew G. Knepley Vec coordsLocal; 770043fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 770143fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 770243fa8764SMatthew G. Knepley 770343fa8764SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 770443fa8764SMatthew G. Knepley ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 770543fa8764SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 7706087ef6b2SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr); 770743fa8764SMatthew G. Knepley for (i = 0; i < Nv/cdim; ++i) { 770843fa8764SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, " Vertex %D: (", i);CHKERRQ(ierr); 770943fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 771043fa8764SMatthew G. Knepley if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);} 771148afe810SSatish Balay ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr); 771243fa8764SMatthew G. Knepley } 771343fa8764SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr); 771443fa8764SMatthew G. Knepley } 771543fa8764SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 771643fa8764SMatthew G. Knepley for (cl = 0; cl < clSize*2; cl += 2) { 771743fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 771843fa8764SMatthew G. Knepley 771943fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 772043fa8764SMatthew G. Knepley PetscReal len; 772143fa8764SMatthew G. Knepley 772243fa8764SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr); 7723087ef6b2SMatthew G. Knepley ierr = PetscSynchronizedPrintf(comm, " Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr); 772443fa8764SMatthew G. Knepley } 772543fa8764SMatthew G. Knepley } 772643fa8764SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 772743fa8764SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr); 772843fa8764SMatthew G. Knepley } 7729068a5610SStefano Zampini } 77308261a58bSMatthew G. Knepley if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);} 7731068a5610SStefano Zampini 7732068a5610SStefano Zampini if (size > 1) { 7733068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4,1}; 7734068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)}; 7735068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL,MPIU_INT}, statType; 7736068a5610SStefano Zampini MPI_Op statReduce; 7737068a5610SStefano Zampini 7738068a5610SStefano Zampini ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRQ(ierr); 7739068a5610SStefano Zampini ierr = MPI_Type_commit(&statType);CHKERRQ(ierr); 7740068a5610SStefano Zampini ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRQ(ierr); 7741068a5610SStefano Zampini ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRQ(ierr); 7742068a5610SStefano Zampini ierr = MPI_Op_free(&statReduce);CHKERRQ(ierr); 7743068a5610SStefano Zampini ierr = MPI_Type_free(&statType);CHKERRQ(ierr); 7744068a5610SStefano Zampini } else { 7745580bdb30SBarry Smith ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr); 7746068a5610SStefano Zampini } 7747068a5610SStefano Zampini if (!rank) { 7748068a5610SStefano Zampini count = globalStats.count; 7749068a5610SStefano Zampini min = globalStats.min; 7750068a5610SStefano Zampini max = globalStats.max; 7751068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 7752068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0; 7753068a5610SStefano Zampini } 7754068a5610SStefano Zampini 7755068a5610SStefano Zampini if (output) { 7756068a5610SStefano Zampini ierr = PetscPrintf(comm,"Mesh with %D cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double) min, (double) max, (double) mean, (double) stdev);CHKERRQ(ierr); 7757068a5610SStefano Zampini } 7758068a5610SStefano Zampini ierr = PetscFree2(J,invJ);CHKERRQ(ierr); 7759068a5610SStefano Zampini 7760068a5610SStefano Zampini ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr); 7761068a5610SStefano Zampini if (dmCoarse) { 7762068a5610SStefano Zampini PetscBool isplex; 7763068a5610SStefano Zampini 7764068a5610SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr); 7765068a5610SStefano Zampini if (isplex) { 776643fa8764SMatthew G. Knepley ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr); 7767068a5610SStefano Zampini } 7768068a5610SStefano Zampini } 7769068a5610SStefano Zampini PetscFunctionReturn(0); 7770068a5610SStefano Zampini } 7771068a5610SStefano Zampini 7772bceba477SMatthew G. Knepley /* Pointwise interpolation 7773bceba477SMatthew G. Knepley Just code FEM for now 7774bceba477SMatthew G. Knepley u^f = I u^c 77754ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 77764ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 77774ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 7778bceba477SMatthew G. Knepley */ 7779bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 7780bceba477SMatthew G. Knepley { 7781bceba477SMatthew G. Knepley PetscSection gsc, gsf; 7782bceba477SMatthew G. Knepley PetscInt m, n; 7783a063dac3SMatthew G. Knepley void *ctx; 778468132eb9SMatthew G. Knepley DM cdm; 7785fd194bc8SStefano Zampini PetscBool regular, ismatis; 7786bceba477SMatthew G. Knepley PetscErrorCode ierr; 7787bceba477SMatthew G. Knepley 7788bceba477SMatthew G. Knepley PetscFunctionBegin; 7789e87a4003SBarry Smith ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 7790bceba477SMatthew G. Knepley ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 7791e87a4003SBarry Smith ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 7792bceba477SMatthew G. Knepley ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 779368132eb9SMatthew G. Knepley 7794fd194bc8SStefano Zampini ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr); 7795bceba477SMatthew G. Knepley ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 7796bceba477SMatthew G. Knepley ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 7797fd194bc8SStefano Zampini ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr); 7798a063dac3SMatthew G. Knepley ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 779968132eb9SMatthew G. Knepley 7800a8fb8f29SToby Isaac ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 780168132eb9SMatthew G. Knepley ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 780268132eb9SMatthew G. Knepley if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 780368132eb9SMatthew G. Knepley else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 780468132eb9SMatthew G. Knepley ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 78054db47ee9SStefano Zampini if (scaling) { 78065d1c2e58SMatthew G. Knepley /* Use naive scaling */ 78075d1c2e58SMatthew G. Knepley ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 78084db47ee9SStefano Zampini } 7809a063dac3SMatthew G. Knepley PetscFunctionReturn(0); 7810a063dac3SMatthew G. Knepley } 7811bceba477SMatthew G. Knepley 78126dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 7813a063dac3SMatthew G. Knepley { 781490748bafSMatthew G. Knepley PetscErrorCode ierr; 78156dbf9973SLawrence Mitchell VecScatter ctx; 781690748bafSMatthew G. Knepley 7817a063dac3SMatthew G. Knepley PetscFunctionBegin; 78186dbf9973SLawrence Mitchell ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 78196dbf9973SLawrence Mitchell ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 78206dbf9973SLawrence Mitchell ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 7821bceba477SMatthew G. Knepley PetscFunctionReturn(0); 7822bceba477SMatthew G. Knepley } 7823bceba477SMatthew G. Knepley 7824bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 7825bd041c0cSMatthew G. Knepley { 7826bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 7827bd041c0cSMatthew G. Knepley PetscInt m, n; 7828bd041c0cSMatthew G. Knepley void *ctx; 7829bd041c0cSMatthew G. Knepley DM cdm; 7830bd041c0cSMatthew G. Knepley PetscBool regular; 7831bd041c0cSMatthew G. Knepley PetscErrorCode ierr; 7832bd041c0cSMatthew G. Knepley 7833bd041c0cSMatthew G. Knepley PetscFunctionBegin; 7834e87a4003SBarry Smith ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 7835bd041c0cSMatthew G. Knepley ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 7836e87a4003SBarry Smith ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 7837bd041c0cSMatthew G. Knepley ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 7838bd041c0cSMatthew G. Knepley 7839bd041c0cSMatthew G. Knepley ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr); 7840bd041c0cSMatthew G. Knepley ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 7841bd041c0cSMatthew G. Knepley ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr); 7842bd041c0cSMatthew G. Knepley ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 7843bd041c0cSMatthew G. Knepley 7844bd041c0cSMatthew G. Knepley ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 7845bd041c0cSMatthew G. Knepley ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 7846bd041c0cSMatthew G. Knepley if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 7847bd041c0cSMatthew G. Knepley else {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);} 7848bd041c0cSMatthew G. Knepley ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr); 7849bd041c0cSMatthew G. Knepley PetscFunctionReturn(0); 7850bd041c0cSMatthew G. Knepley } 7851bd041c0cSMatthew G. Knepley 78520aef6b92SMatthew G. Knepley /*@ 78530aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 78540aef6b92SMatthew G. Knepley 78550aef6b92SMatthew G. Knepley Input Parameter: 78560aef6b92SMatthew G. Knepley . dm - The DMPlex object 78570aef6b92SMatthew G. Knepley 78580aef6b92SMatthew G. Knepley Output Parameter: 78590aef6b92SMatthew G. Knepley . regular - The flag 78600aef6b92SMatthew G. Knepley 78610aef6b92SMatthew G. Knepley Level: intermediate 78620aef6b92SMatthew G. Knepley 78630aef6b92SMatthew G. Knepley .seealso: DMPlexSetRegularRefinement() 78640aef6b92SMatthew G. Knepley @*/ 78650aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 78660aef6b92SMatthew G. Knepley { 78670aef6b92SMatthew G. Knepley PetscFunctionBegin; 78680aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 78690aef6b92SMatthew G. Knepley PetscValidPointer(regular, 2); 78700aef6b92SMatthew G. Knepley *regular = ((DM_Plex *) dm->data)->regularRefinement; 78710aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 78720aef6b92SMatthew G. Knepley } 78730aef6b92SMatthew G. Knepley 78740aef6b92SMatthew G. Knepley /*@ 78750aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 78760aef6b92SMatthew G. Knepley 78770aef6b92SMatthew G. Knepley Input Parameters: 78780aef6b92SMatthew G. Knepley + dm - The DMPlex object 78790aef6b92SMatthew G. Knepley - regular - The flag 78800aef6b92SMatthew G. Knepley 78810aef6b92SMatthew G. Knepley Level: intermediate 78820aef6b92SMatthew G. Knepley 78830aef6b92SMatthew G. Knepley .seealso: DMPlexGetRegularRefinement() 78840aef6b92SMatthew G. Knepley @*/ 78850aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 78860aef6b92SMatthew G. Knepley { 78870aef6b92SMatthew G. Knepley PetscFunctionBegin; 78880aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 78890aef6b92SMatthew G. Knepley ((DM_Plex *) dm->data)->regularRefinement = regular; 78900aef6b92SMatthew G. Knepley PetscFunctionReturn(0); 78910aef6b92SMatthew G. Knepley } 78920aef6b92SMatthew G. Knepley 7893412e9a14SMatthew G. Knepley /*@ 7894412e9a14SMatthew G. Knepley DMPlexGetCellRefinerType - Get the strategy for refining a cell 7895412e9a14SMatthew G. Knepley 7896412e9a14SMatthew G. Knepley Input Parameter: 7897412e9a14SMatthew G. Knepley . dm - The DMPlex object 7898412e9a14SMatthew G. Knepley 7899412e9a14SMatthew G. Knepley Output Parameter: 7900412e9a14SMatthew G. Knepley . cr - The strategy number 7901412e9a14SMatthew G. Knepley 7902412e9a14SMatthew G. Knepley Level: intermediate 7903412e9a14SMatthew G. Knepley 7904412e9a14SMatthew G. Knepley .seealso: DMPlexSetCellRefinerType(), DMPlexSetRegularRefinement() 7905412e9a14SMatthew G. Knepley @*/ 7906412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetCellRefinerType(DM dm, DMPlexCellRefinerType *cr) 7907412e9a14SMatthew G. Knepley { 7908412e9a14SMatthew G. Knepley PetscFunctionBegin; 7909412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7910412e9a14SMatthew G. Knepley PetscValidPointer(cr, 2); 7911412e9a14SMatthew G. Knepley *cr = ((DM_Plex *) dm->data)->cellRefiner; 7912412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 7913412e9a14SMatthew G. Knepley } 7914412e9a14SMatthew G. Knepley 7915412e9a14SMatthew G. Knepley /*@ 7916412e9a14SMatthew G. Knepley DMPlexSetCellRefinerType - Set the strategy for refining a cell 7917412e9a14SMatthew G. Knepley 7918412e9a14SMatthew G. Knepley Input Parameters: 7919412e9a14SMatthew G. Knepley + dm - The DMPlex object 7920412e9a14SMatthew G. Knepley - cr - The strategy number 7921412e9a14SMatthew G. Knepley 7922412e9a14SMatthew G. Knepley Level: intermediate 7923412e9a14SMatthew G. Knepley 7924412e9a14SMatthew G. Knepley .seealso: DMPlexGetCellRefinerType(), DMPlexGetRegularRefinement() 7925412e9a14SMatthew G. Knepley @*/ 7926412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellRefinerType(DM dm, DMPlexCellRefinerType cr) 7927412e9a14SMatthew G. Knepley { 7928412e9a14SMatthew G. Knepley PetscFunctionBegin; 7929412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7930412e9a14SMatthew G. Knepley ((DM_Plex *) dm->data)->cellRefiner = cr; 7931412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 7932412e9a14SMatthew G. Knepley } 7933412e9a14SMatthew G. Knepley 7934f7c74593SToby Isaac /* anchors */ 7935a68b90caSToby Isaac /*@ 7936f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 7937f7c74593SToby Isaac call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 7938a68b90caSToby Isaac 7939e228b242SToby Isaac not collective 7940a68b90caSToby Isaac 7941a68b90caSToby Isaac Input Parameters: 7942a68b90caSToby Isaac . dm - The DMPlex object 7943a68b90caSToby Isaac 7944a68b90caSToby Isaac Output Parameters: 7945a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 7946a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 7947a68b90caSToby Isaac 7948a68b90caSToby Isaac 7949a68b90caSToby Isaac Level: intermediate 7950a68b90caSToby Isaac 7951f7c74593SToby Isaac .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 7952a68b90caSToby Isaac @*/ 7953a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 7954a68b90caSToby Isaac { 7955a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 795641e6d900SToby Isaac PetscErrorCode ierr; 7957a68b90caSToby Isaac 7958a68b90caSToby Isaac PetscFunctionBegin; 7959a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 796041e6d900SToby Isaac if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 7961a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 7962a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 7963a68b90caSToby Isaac PetscFunctionReturn(0); 7964a68b90caSToby Isaac } 7965a68b90caSToby Isaac 7966a68b90caSToby Isaac /*@ 7967f7c74593SToby Isaac DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 7968f7c74593SToby Isaac when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 7969a68b90caSToby Isaac point's degrees of freedom to be a linear combination of other points' degrees of freedom. 7970a68b90caSToby Isaac 7971a17985deSToby Isaac After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 7972f7c74593SToby Isaac DMGetConstraints() and filling in the entries in the constraint matrix. 7973a68b90caSToby Isaac 7974e228b242SToby Isaac collective on dm 7975a68b90caSToby Isaac 7976a68b90caSToby Isaac Input Parameters: 7977a68b90caSToby Isaac + dm - The DMPlex object 7978e228b242SToby Isaac . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. Must have a local communicator (PETSC_COMM_SELF or derivative). 7979e228b242SToby Isaac - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 7980a68b90caSToby Isaac 7981a68b90caSToby Isaac The reference counts of anchorSection and anchorIS are incremented. 7982a68b90caSToby Isaac 7983a68b90caSToby Isaac Level: intermediate 7984a68b90caSToby Isaac 7985f7c74593SToby Isaac .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 7986a68b90caSToby Isaac @*/ 7987a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 7988a68b90caSToby Isaac { 7989a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 7990e228b242SToby Isaac PetscMPIInt result; 7991a68b90caSToby Isaac PetscErrorCode ierr; 7992a68b90caSToby Isaac 7993a68b90caSToby Isaac PetscFunctionBegin; 7994a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7995e228b242SToby Isaac if (anchorSection) { 7996e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 7997e228b242SToby Isaac ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 7998f6a3d38cSToby Isaac if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 7999e228b242SToby Isaac } 8000e228b242SToby Isaac if (anchorIS) { 8001e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 8002e228b242SToby Isaac ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 8003f6a3d38cSToby Isaac if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 8004e228b242SToby Isaac } 8005a68b90caSToby Isaac 8006a68b90caSToby Isaac ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 8007a68b90caSToby Isaac ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 8008a68b90caSToby Isaac plex->anchorSection = anchorSection; 8009a68b90caSToby Isaac 8010a68b90caSToby Isaac ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 8011a68b90caSToby Isaac ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 8012a68b90caSToby Isaac plex->anchorIS = anchorIS; 8013a68b90caSToby Isaac 8014cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 8015a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 8016a68b90caSToby Isaac const PetscInt *anchors; 8017a68b90caSToby Isaac 8018a68b90caSToby Isaac ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 8019a68b90caSToby Isaac ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 8020a68b90caSToby Isaac ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 8021a68b90caSToby Isaac for (a = 0; a < size; a++) { 8022a68b90caSToby Isaac PetscInt p; 8023a68b90caSToby Isaac 8024a68b90caSToby Isaac p = anchors[a]; 8025a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 8026a68b90caSToby Isaac PetscInt dof; 8027a68b90caSToby Isaac 8028a68b90caSToby Isaac ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 8029a68b90caSToby Isaac if (dof) { 8030a68b90caSToby Isaac PetscErrorCode ierr2; 8031a68b90caSToby Isaac 8032a68b90caSToby Isaac ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 80338ccfff9cSToby Isaac SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p); 8034a68b90caSToby Isaac } 8035a68b90caSToby Isaac } 8036a68b90caSToby Isaac } 8037a68b90caSToby Isaac ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 8038a68b90caSToby Isaac } 8039f7c74593SToby Isaac /* reset the generic constraints */ 8040f7c74593SToby Isaac ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 8041a68b90caSToby Isaac PetscFunctionReturn(0); 8042a68b90caSToby Isaac } 8043a68b90caSToby Isaac 8044f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 8045a68b90caSToby Isaac { 8046f7c74593SToby Isaac PetscSection anchorSection; 80476995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 8048a68b90caSToby Isaac PetscErrorCode ierr; 8049a68b90caSToby Isaac 8050a68b90caSToby Isaac PetscFunctionBegin; 8051a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8052a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 8053e228b242SToby Isaac ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 8054a68b90caSToby Isaac ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 80556995de1eSToby Isaac if (numFields) { 8056719ab38cSToby Isaac PetscInt f; 8057a68b90caSToby Isaac ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 8058719ab38cSToby Isaac 8059719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 8060719ab38cSToby Isaac PetscInt numComp; 8061719ab38cSToby Isaac 8062719ab38cSToby Isaac ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr); 8063719ab38cSToby Isaac ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr); 8064719ab38cSToby Isaac } 80656995de1eSToby Isaac } 8066a68b90caSToby Isaac ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 80676995de1eSToby Isaac ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 80686995de1eSToby Isaac pStart = PetscMax(pStart,sStart); 80696995de1eSToby Isaac pEnd = PetscMin(pEnd,sEnd); 80706995de1eSToby Isaac pEnd = PetscMax(pStart,pEnd); 8071a68b90caSToby Isaac ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 8072a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 8073a68b90caSToby Isaac ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 8074a68b90caSToby Isaac if (dof) { 8075a68b90caSToby Isaac ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 8076a68b90caSToby Isaac ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 8077a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 8078a68b90caSToby Isaac ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 8079a68b90caSToby Isaac ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 8080a68b90caSToby Isaac } 8081a68b90caSToby Isaac } 8082a68b90caSToby Isaac } 8083a68b90caSToby Isaac ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 8084a68b90caSToby Isaac PetscFunctionReturn(0); 8085a68b90caSToby Isaac } 8086a68b90caSToby Isaac 8087f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 8088a68b90caSToby Isaac { 8089f7c74593SToby Isaac PetscSection aSec; 80900ac89760SToby Isaac PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 80910ac89760SToby Isaac const PetscInt *anchors; 80920ac89760SToby Isaac PetscInt numFields, f; 809366ad2231SToby Isaac IS aIS; 80940ac89760SToby Isaac PetscErrorCode ierr; 80950ac89760SToby Isaac 80960ac89760SToby Isaac PetscFunctionBegin; 80970ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80980ac89760SToby Isaac ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 80990ac89760SToby Isaac ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 81000ac89760SToby Isaac ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 81010ac89760SToby Isaac ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 8102302440fdSBarry Smith ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 8103a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 810466ad2231SToby Isaac ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 81056995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 81066995de1eSToby Isaac ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 81070ac89760SToby Isaac ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 81080ac89760SToby Isaac i[0] = 0; 81090ac89760SToby Isaac ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 81100ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 8111f19733c5SToby Isaac PetscInt rDof, rOff, r; 8112f19733c5SToby Isaac 8113f19733c5SToby Isaac ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 8114f19733c5SToby Isaac if (!rDof) continue; 8115f19733c5SToby Isaac ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 81160ac89760SToby Isaac if (numFields) { 81170ac89760SToby Isaac for (f = 0; f < numFields; f++) { 81180ac89760SToby Isaac annz = 0; 8119f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 8120f19733c5SToby Isaac a = anchors[rOff + r]; 81210ac89760SToby Isaac ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 81220ac89760SToby Isaac annz += aDof; 81230ac89760SToby Isaac } 81240ac89760SToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 81250ac89760SToby Isaac ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 81260ac89760SToby Isaac for (q = 0; q < dof; q++) { 81270ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 81280ac89760SToby Isaac } 81290ac89760SToby Isaac } 81300ac89760SToby Isaac } 81310ac89760SToby Isaac else { 81320ac89760SToby Isaac annz = 0; 81330ac89760SToby Isaac for (q = 0; q < dof; q++) { 81340ac89760SToby Isaac a = anchors[off + q]; 81350ac89760SToby Isaac ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 81360ac89760SToby Isaac annz += aDof; 81370ac89760SToby Isaac } 81380ac89760SToby Isaac ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 81390ac89760SToby Isaac ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 81400ac89760SToby Isaac for (q = 0; q < dof; q++) { 81410ac89760SToby Isaac i[off + q + 1] = i[off + q] + annz; 81420ac89760SToby Isaac } 81430ac89760SToby Isaac } 81440ac89760SToby Isaac } 81450ac89760SToby Isaac nnz = i[m]; 81460ac89760SToby Isaac ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 81470ac89760SToby Isaac offset = 0; 81480ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 81490ac89760SToby Isaac if (numFields) { 81500ac89760SToby Isaac for (f = 0; f < numFields; f++) { 81510ac89760SToby Isaac ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 81520ac89760SToby Isaac for (q = 0; q < dof; q++) { 81530ac89760SToby Isaac PetscInt rDof, rOff, r; 81540ac89760SToby Isaac ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 81550ac89760SToby Isaac ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 81560ac89760SToby Isaac for (r = 0; r < rDof; r++) { 81570ac89760SToby Isaac PetscInt s; 81580ac89760SToby Isaac 81590ac89760SToby Isaac a = anchors[rOff + r]; 81600ac89760SToby Isaac ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 81610ac89760SToby Isaac ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 81620ac89760SToby Isaac for (s = 0; s < aDof; s++) { 81630ac89760SToby Isaac j[offset++] = aOff + s; 81640ac89760SToby Isaac } 81650ac89760SToby Isaac } 81660ac89760SToby Isaac } 81670ac89760SToby Isaac } 81680ac89760SToby Isaac } 81690ac89760SToby Isaac else { 81700ac89760SToby Isaac ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 81710ac89760SToby Isaac for (q = 0; q < dof; q++) { 81720ac89760SToby Isaac PetscInt rDof, rOff, r; 81730ac89760SToby Isaac ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 81740ac89760SToby Isaac ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 81750ac89760SToby Isaac for (r = 0; r < rDof; r++) { 81760ac89760SToby Isaac PetscInt s; 81770ac89760SToby Isaac 81780ac89760SToby Isaac a = anchors[rOff + r]; 81790ac89760SToby Isaac ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 81800ac89760SToby Isaac ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 81810ac89760SToby Isaac for (s = 0; s < aDof; s++) { 81820ac89760SToby Isaac j[offset++] = aOff + s; 81830ac89760SToby Isaac } 81840ac89760SToby Isaac } 81850ac89760SToby Isaac } 81860ac89760SToby Isaac } 81870ac89760SToby Isaac } 81880ac89760SToby Isaac ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 818925570a81SToby Isaac ierr = PetscFree(i);CHKERRQ(ierr); 819025570a81SToby Isaac ierr = PetscFree(j);CHKERRQ(ierr); 819166ad2231SToby Isaac ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 81920ac89760SToby Isaac PetscFunctionReturn(0); 81930ac89760SToby Isaac } 81940ac89760SToby Isaac 819566ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 819666ad2231SToby Isaac { 8197f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 8198f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 819966ad2231SToby Isaac Mat cMat; 820066ad2231SToby Isaac PetscErrorCode ierr; 820166ad2231SToby Isaac 820266ad2231SToby Isaac PetscFunctionBegin; 820366ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8204a17985deSToby Isaac ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 820566ad2231SToby Isaac if (anchorSection) { 820644a7f3ddSMatthew G. Knepley PetscInt Nf; 8207e228b242SToby Isaac 820892fd8e1eSJed Brown ierr = DMGetLocalSection(dm,§ion);CHKERRQ(ierr); 8209f7c74593SToby Isaac ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 8210f7c74593SToby Isaac ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 821144a7f3ddSMatthew G. Knepley ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr); 821244a7f3ddSMatthew G. Knepley if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 821366ad2231SToby Isaac ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 821466ad2231SToby Isaac ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 821566ad2231SToby Isaac ierr = MatDestroy(&cMat);CHKERRQ(ierr); 821666ad2231SToby Isaac } 821766ad2231SToby Isaac PetscFunctionReturn(0); 821866ad2231SToby Isaac } 8219a93c429eSMatthew G. Knepley 8220a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 8221a93c429eSMatthew G. Knepley { 8222a93c429eSMatthew G. Knepley IS subis; 8223a93c429eSMatthew G. Knepley PetscSection section, subsection; 8224a93c429eSMatthew G. Knepley PetscErrorCode ierr; 8225a93c429eSMatthew G. Knepley 8226a93c429eSMatthew G. Knepley PetscFunctionBegin; 822792fd8e1eSJed Brown ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 8228a93c429eSMatthew G. Knepley if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 8229a93c429eSMatthew G. Knepley if (!subdm) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 8230a93c429eSMatthew G. Knepley /* Create subdomain */ 8231a93c429eSMatthew G. Knepley ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr); 8232a93c429eSMatthew G. Knepley /* Create submodel */ 823397d8846cSMatthew Knepley ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr); 8234a93c429eSMatthew G. Knepley ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr); 823592fd8e1eSJed Brown ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr); 8236a93c429eSMatthew G. Knepley ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); 8237e5e52638SMatthew G. Knepley ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr); 8238a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 8239a93c429eSMatthew G. Knepley if (is) { 8240a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 8241a93c429eSMatthew G. Knepley IS spIS; 8242a93c429eSMatthew G. Knepley const PetscInt *spmap; 8243a93c429eSMatthew G. Knepley PetscInt *subIndices; 8244a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 8245a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 8246a93c429eSMatthew G. Knepley 824797d8846cSMatthew Knepley ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr); 8248a93c429eSMatthew G. Knepley ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr); 8249a93c429eSMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 82506f0eb057SJed Brown ierr = DMGetGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 82516f0eb057SJed Brown ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr); 8252a93c429eSMatthew G. Knepley ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr); 8253a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 8254a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 8255a93c429eSMatthew G. Knepley 8256a93c429eSMatthew G. Knepley ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 8257a93c429eSMatthew G. Knepley if (gdof > 0) { 8258a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 8259a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 8260a93c429eSMatthew G. Knepley 8261a93c429eSMatthew G. Knepley ierr = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr); 8262a93c429eSMatthew G. Knepley ierr = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr); 8263a93c429eSMatthew G. Knepley pSubSize += fdof-fcdof; 8264a93c429eSMatthew G. Knepley } 8265a93c429eSMatthew G. Knepley subSize += pSubSize; 8266a93c429eSMatthew G. Knepley if (pSubSize) { 8267a93c429eSMatthew G. Knepley if (bs < 0) { 8268a93c429eSMatthew G. Knepley bs = pSubSize; 8269a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 8270a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 8271a93c429eSMatthew G. Knepley bs = 1; 8272a93c429eSMatthew G. Knepley } 8273a93c429eSMatthew G. Knepley } 8274a93c429eSMatthew G. Knepley } 8275a93c429eSMatthew G. Knepley } 8276a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 8277a93c429eSMatthew G. Knepley bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs; 8278a93c429eSMatthew G. Knepley ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr); 8279a93c429eSMatthew G. Knepley if (bsMinMax[0] != bsMinMax[1]) {bs = 1;} 8280a93c429eSMatthew G. Knepley else {bs = bsMinMax[0];} 8281a93c429eSMatthew G. Knepley ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); 8282a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 8283a93c429eSMatthew G. Knepley PetscInt gdof, goff; 8284a93c429eSMatthew G. Knepley 8285a93c429eSMatthew G. Knepley ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr); 8286a93c429eSMatthew G. Knepley if (gdof > 0) { 8287a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 8288a93c429eSMatthew G. Knepley 8289a93c429eSMatthew G. Knepley ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr); 8290a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 8291a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 8292a93c429eSMatthew G. Knepley 8293a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 8294a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 8295a93c429eSMatthew G. Knepley ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 8296a93c429eSMatthew G. Knepley ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 8297a93c429eSMatthew G. Knepley poff += fdof-fcdof; 8298a93c429eSMatthew G. Knepley } 8299a93c429eSMatthew G. Knepley ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 8300a93c429eSMatthew G. Knepley ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 8301a93c429eSMatthew G. Knepley for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 8302a93c429eSMatthew G. Knepley subIndices[subOff] = goff+poff+fc; 8303a93c429eSMatthew G. Knepley } 8304a93c429eSMatthew G. Knepley } 8305a93c429eSMatthew G. Knepley } 8306a93c429eSMatthew G. Knepley } 8307a93c429eSMatthew G. Knepley ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr); 8308a93c429eSMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 8309a93c429eSMatthew G. Knepley if (bs > 1) { 8310a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 8311a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 8312a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 8313a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 8314a93c429eSMatthew G. Knepley if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;} 8315a93c429eSMatthew G. Knepley } 8316a93c429eSMatthew G. Knepley } 8317a93c429eSMatthew G. Knepley if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);} 8318a93c429eSMatthew G. Knepley } 8319a93c429eSMatthew G. Knepley /* Attach nullspace */ 8320a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 8321a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 8322a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 8323a93c429eSMatthew G. Knepley } 8324a93c429eSMatthew G. Knepley if (f < Nf) { 8325a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 8326a93c429eSMatthew G. Knepley 8327a93c429eSMatthew G. Knepley ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, &nullSpace);CHKERRQ(ierr); 8328a93c429eSMatthew G. Knepley ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 8329a93c429eSMatthew G. Knepley ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 8330a93c429eSMatthew G. Knepley } 8331a93c429eSMatthew G. Knepley } 8332a93c429eSMatthew G. Knepley PetscFunctionReturn(0); 8333a93c429eSMatthew G. Knepley } 8334c0f0dcc3SMatthew G. Knepley 8335c0f0dcc3SMatthew G. Knepley /*@ 8336c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 8337c0f0dcc3SMatthew G. Knepley 8338c0f0dcc3SMatthew G. Knepley Input Parameter: 8339c0f0dcc3SMatthew G. Knepley - dm - The DM 8340c0f0dcc3SMatthew G. Knepley 8341c0f0dcc3SMatthew G. Knepley Level: developer 8342c0f0dcc3SMatthew G. Knepley 8343c0f0dcc3SMatthew G. Knepley Options Database Keys: 8344c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor 8345c0f0dcc3SMatthew G. Knepley 8346c0f0dcc3SMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreate() 8347c0f0dcc3SMatthew G. Knepley @*/ 8348c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 8349c0f0dcc3SMatthew G. Knepley { 8350e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG) 8351c0f0dcc3SMatthew G. Knepley PetscStageLog stageLog; 8352c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 8353c0f0dcc3SMatthew G. Knepley PetscLogStage stage; 8354c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 8355c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 8356c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 8357c0f0dcc3SMatthew G. Knepley const char *name; 8358c0f0dcc3SMatthew G. Knepley PetscErrorCode ierr; 8359e5ed2c37SJose E. Roman #endif 8360c0f0dcc3SMatthew G. Knepley 8361c0f0dcc3SMatthew G. Knepley PetscFunctionBegin; 8362c0f0dcc3SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8363c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG) 8364c0f0dcc3SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 8365c0f0dcc3SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8366c0f0dcc3SMatthew G. Knepley ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 8367c0f0dcc3SMatthew G. Knepley ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr); 8368c0f0dcc3SMatthew G. Knepley ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr); 8369c0f0dcc3SMatthew G. Knepley ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr); 8370c0f0dcc3SMatthew G. Knepley ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr); 8371c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart)*Nf*eventInfo.count; 8372c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops/eventInfo.time; 8373c0f0dcc3SMatthew G. Knepley cellRate = N/eventInfo.time; 8374fae64647SBarry Smith ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "DM (%s) FE Residual Integration: %D integrals %D reps\n Cell rate: %.2g/s flop rate: %.2g MF/s\n", name ? name : "unknown", N, eventInfo.count, (double) cellRate, (double) (flopRate/1.e6));CHKERRQ(ierr); 8375c0f0dcc3SMatthew G. Knepley #else 8376c0f0dcc3SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log."); 8377c0f0dcc3SMatthew G. Knepley #endif 8378c0f0dcc3SMatthew G. Knepley PetscFunctionReturn(0); 8379c0f0dcc3SMatthew G. Knepley } 8380