PetscErrorCode SetupSection(DM dm, AppCtx *user) { DM cdm = dm; const PetscInt id = 1; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = PetscObjectSetName((PetscObject) user->fe[0], "potential");CHKERRQ(ierr); while (cdm) { ierr = DMSetNumFields(cdm, 1);CHKERRQ(ierr); ierr = DMSetField(cdm, 0, (PetscObject) user->fe[0]);CHKERRQ(ierr); ierr = DMPlexAddBoundary(cdm, user->bcType == DIRICHLET, user->bcType == NEUMANN ? "boundary" : "marker", 0, user->exactFuncs[0], 1, &id, user);CHKERRQ(ierr); ierr = DMPlexGetCoarseDM(cdm, &cdm);CHKERRQ(ierr); } PetscFunctionReturn(0); }
int main(int argc, char **argv) { DM dm, dmDist = NULL; Vec u; PetscSection section; PetscViewer viewer; PetscInt dim = 2, numFields, numBC, i; PetscInt numComp[3]; PetscInt numDof[12]; PetscInt bcField[1]; IS bcPointIS[1]; PetscBool interpolate = PETSC_TRUE; PetscErrorCode ierr; ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr; ierr = PetscOptionsGetInt(NULL,NULL, "-dim", &dim, NULL);CHKERRQ(ierr); /* Create a mesh */ ierr = DMPlexCreateBoxMesh(PETSC_COMM_WORLD, dim, PETSC_TRUE, NULL, NULL, NULL, NULL, interpolate, &dm);CHKERRQ(ierr); /* Distribute mesh over processes */ ierr = DMPlexDistribute(dm, 0, NULL, &dmDist);CHKERRQ(ierr); if (dmDist) {ierr = DMDestroy(&dm);CHKERRQ(ierr); dm = dmDist;} /* Create a scalar field u, a vector field v, and a surface vector field w */ numFields = 3; numComp[0] = 1; numComp[1] = dim; numComp[2] = dim-1; for (i = 0; i < numFields*(dim+1); ++i) numDof[i] = 0; /* Let u be defined on vertices */ numDof[0*(dim+1)+0] = 1; /* Let v be defined on cells */ numDof[1*(dim+1)+dim] = dim; /* Let v be defined on faces */ numDof[2*(dim+1)+dim-1] = dim-1; /* Setup boundary conditions */ numBC = 1; /* Prescribe a Dirichlet condition on u on the boundary Label "marker" is made by the mesh creation routine */ bcField[0] = 0; ierr = DMGetStratumIS(dm, "marker", 1, &bcPointIS[0]);CHKERRQ(ierr); /* Create a PetscSection with this data layout */ ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); ierr = DMPlexCreateSection(dm, NULL, numComp, numDof, numBC, bcField, NULL, bcPointIS, NULL, §ion);CHKERRQ(ierr); ierr = ISDestroy(&bcPointIS[0]);CHKERRQ(ierr); /* Name the Field variables */ ierr = PetscSectionSetFieldName(section, 0, "u");CHKERRQ(ierr); ierr = PetscSectionSetFieldName(section, 1, "v");CHKERRQ(ierr); ierr = PetscSectionSetFieldName(section, 2, "w");CHKERRQ(ierr); ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); /* Tell the DM to use this data layout */ ierr = DMSetSection(dm, section);CHKERRQ(ierr); /* Create a Vec with this layout and view it */ ierr = DMGetGlobalVector(dm, &u);CHKERRQ(ierr); ierr = PetscViewerCreate(PETSC_COMM_WORLD, &viewer);CHKERRQ(ierr); ierr = PetscViewerSetType(viewer, PETSCVIEWERVTK);CHKERRQ(ierr); ierr = PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_VTK);CHKERRQ(ierr); ierr = PetscViewerFileSetName(viewer, "sol.vtk");CHKERRQ(ierr); ierr = VecView(u, viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(dm, &u);CHKERRQ(ierr); /* Cleanup */ ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
/* This assumes that the DM has been cloned prior to the call */ PetscErrorCode DMCreateSubDM_Section_Private(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) { PetscSection section, sectionGlobal; PetscInt *subIndices; PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; PetscErrorCode ierr; PetscFunctionBegin; if (!numFields) PetscFunctionReturn(0); ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting fields"); if (!sectionGlobal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default global section for DM before splitting fields"); ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); if (is) { ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); for (p = pStart; p < pEnd; ++p) { PetscInt gdof; ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); if (gdof > 0) { for (f = 0; f < numFields; ++f) { PetscInt fdof, fcdof; ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); subSize += fdof-fcdof; } } } ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); for (p = pStart; p < pEnd; ++p) { PetscInt gdof, goff; ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); if (gdof > 0) { ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); for (f = 0; f < numFields; ++f) { PetscInt fdof, fcdof, fc, f2, poff = 0; /* Can get rid of this loop by storing field information in the global section */ for (f2 = 0; f2 < fields[f]; ++f2) { ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); poff += fdof-fcdof; } ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { subIndices[subOff] = goff+poff+fc; } } } } ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); } if (subdm) { PetscSection subsection; PetscBool haveNull = PETSC_FALSE; PetscInt f, nf = 0; ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); for (f = 0; f < numFields; ++f) { (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; if ((*subdm)->nullspaceConstructors[f]) { haveNull = PETSC_TRUE; nf = f; } } if (haveNull && is) { MatNullSpace nullSpace; ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); } if (dm->prob) { PetscInt Nf; ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); if (nF != Nf) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", Nf, nF); ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); for (f = 0; f < numFields; ++f) { PetscObject disc; ierr = DMGetField(dm, fields[f], &disc);CHKERRQ(ierr); ierr = DMSetField(*subdm, f, disc);CHKERRQ(ierr); } if (numFields == 1 && is) { PetscObject disc, space, pmat; ierr = DMGetField(*subdm, 0, &disc);CHKERRQ(ierr); ierr = PetscObjectQuery(disc, "nullspace", &space);CHKERRQ(ierr); if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", space);CHKERRQ(ierr);} ierr = PetscObjectQuery(disc, "nearnullspace", &space);CHKERRQ(ierr); if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", space);CHKERRQ(ierr);} ierr = PetscObjectQuery(disc, "pmat", &pmat);CHKERRQ(ierr); if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", pmat);CHKERRQ(ierr);} } } } #if 0 /* We need a way to filter the original SF for given fields: - Keeping the original section around it too much I think - We could keep the distributed section, and subset it */ if (dm->sfNatural) { PetscSF sfNatural; ierr = PetscSectionCreateSubsection(dm->originalSection, numFields, fields, &(*subdm)->originalSection);CHKERRQ(ierr); ierr = DMPlexCreateGlobalToNaturalPetscSF(*subdm, &sfNatural);CHKERRQ(ierr); ierr = DMPlexSetGlobalToNaturalPetscSF(*subdm, sfNatural);CHKERRQ(ierr); } #endif PetscFunctionReturn(0); }
/* This assumes that the DM has been cloned prior to the call */ PetscErrorCode DMCreateSubDM_Section_Private(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) { PetscSection section, sectionGlobal; PetscInt *subIndices; PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; PetscErrorCode ierr; PetscFunctionBegin; if (!numFields) PetscFunctionReturn(0); ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting fields"); if (!sectionGlobal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default global section for DM before splitting fields"); ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); if (is) { ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); for (p = pStart; p < pEnd; ++p) { PetscInt gdof; ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); if (gdof > 0) { for (f = 0; f < numFields; ++f) { PetscInt fdof, fcdof; ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); subSize += fdof-fcdof; } } } ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr); for (p = pStart; p < pEnd; ++p) { PetscInt gdof, goff; ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); if (gdof > 0) { ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); for (f = 0; f < numFields; ++f) { PetscInt fdof, fcdof, fc, f2, poff = 0; /* Can get rid of this loop by storing field information in the global section */ for (f2 = 0; f2 < fields[f]; ++f2) { ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); poff += fdof-fcdof; } ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { subIndices[subOff] = goff+poff+fc; } } } } ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); } if (subdm) { PetscSection subsection; PetscBool haveNull = PETSC_FALSE; PetscInt f, nf = 0; ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr); for (f = 0; f < numFields; ++f) { (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; if ((*subdm)->nullspaceConstructors[f]) { haveNull = PETSC_TRUE; nf = f; } } if (haveNull) { MatNullSpace nullSpace; ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); } if (dm->fields) { if (nF != dm->numFields) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); for (f = 0; f < numFields; ++f) { ierr = PetscObjectListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);CHKERRQ(ierr); } if (numFields == 1) { MatNullSpace space; Mat pmat; ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject*) &space);CHKERRQ(ierr); if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject*) &space);CHKERRQ(ierr); if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject*) &pmat);CHKERRQ(ierr); if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} } } } PetscFunctionReturn(0); }