PetscErrorCode CreateTensorProductHybrid_2D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm = NULL, hdm = NULL; DMLabel faultLabel, hybridLabel; PetscInt p; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { PetscInt numPoints[2] = {6, 2}; PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4,}; PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[12] = {-1.0, -0.5, 0.0, -0.5, 0.0, 0.5, -1.0, 0.5, 1.0, -0.5, 1.0, 0.5}; PetscInt faultPoints[2] = {3, 4}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 2; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} ierr = DMPlexCheckSymmetry(*dm);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCheckSymmetry(idm);CHKERRQ(ierr); ierr = DMGetLabel(*dm, "fault", &faultLabel);CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, faultLabel, &hybridLabel, &hdm);CHKERRQ(ierr); ierr = DMLabelDestroy(&hybridLabel);CHKERRQ(ierr); } else { PetscInt numPoints[3] = {0, 0, 0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, NULL, NULL, &hdm);CHKERRQ(ierr); } ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; PetscFunctionReturn(0); }
static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *newdm) { PetscInt dim = user->dim; PetscBool cellSimplex = user->cellSimplex; PetscErrorCode ierr; PetscFunctionBegin; switch (dim) { case 2: if (cellSimplex) { ierr = CreateSimplex_2D(comm, newdm);CHKERRQ(ierr); } else { ierr = CreateQuad_2D(comm, newdm);CHKERRQ(ierr); } break; case 3: if (cellSimplex) { ierr = CreateSimplex_3D(comm, newdm);CHKERRQ(ierr); } else { ierr = CreateHex_3D(comm, newdm);CHKERRQ(ierr); } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); } if (user->refinementLimit > 0.0) { DM rdm; const char *name; ierr = DMPlexSetRefinementUniform(*newdm, PETSC_FALSE);CHKERRQ(ierr); ierr = DMPlexSetRefinementLimit(*newdm, user->refinementLimit);CHKERRQ(ierr); ierr = DMRefine(*newdm, PETSC_COMM_SELF, &rdm);CHKERRQ(ierr); ierr = PetscObjectGetName((PetscObject) *newdm, &name);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) rdm, name);CHKERRQ(ierr); ierr = DMDestroy(newdm);CHKERRQ(ierr); *newdm = rdm; } if (user->interpolate) { DM idm = NULL; const char *name; ierr = DMPlexInterpolate(*newdm, &idm);CHKERRQ(ierr); ierr = PetscObjectGetName((PetscObject) *newdm, &name);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) idm, name);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*newdm, idm);CHKERRQ(ierr); ierr = DMDestroy(newdm);CHKERRQ(ierr); *newdm = idm; } ierr = DMSetFromOptions(*newdm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode CreateTensorProduct_3D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm = NULL; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { switch (testNum) { case 0: { PetscInt numPoints[2] = {12, 2}; PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[36] = {-1.0, -0.5, -0.5, -1.0, 0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); } break; case 1: { PetscInt numPoints[2] = {8, 1}; PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[24] = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); } } else { PetscInt numPoints[4] = {0, 0, 0, 0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); } ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; PetscFunctionReturn(0); }
PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) { PetscInt dim = user->dim; PetscBool cellHybrid = user->cellHybrid; PetscBool cellSimplex = user->cellSimplex; PetscMPIInt rank, size; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); switch (dim) { case 1: if (cellHybrid) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make hybrid meshes for dimension %d", dim); ierr = CreateSimplex_1D(comm, dm);CHKERRQ(ierr); break; case 2: if (cellSimplex) { if (cellHybrid) { ierr = CreateSimplexHybrid_2D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateSimplex_2D(comm, dm);CHKERRQ(ierr); } } else { if (cellHybrid) { ierr = CreateTensorProductHybrid_2D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateTensorProduct_2D(comm, user->testNum, dm);CHKERRQ(ierr); } } break; case 3: if (cellSimplex) { if (cellHybrid) { ierr = CreateSimplexHybrid_3D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateSimplex_3D(comm, user->testNum, dm);CHKERRQ(ierr); } } else { if (cellHybrid) { ierr = CreateTensorProductHybrid_3D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateTensorProduct_3D(comm, user->testNum, dm);CHKERRQ(ierr); } } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); } if (user->testPartition && size > 1) { PetscPartitioner part; PetscInt *sizes = NULL; PetscInt *points = NULL; if (!rank) { if (dim == 2 && cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt triSizes_p2[2] = {1, 1}; PetscInt triPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, triSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, triPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for triangular mesh on 2 procs", user->testNum); } } else if (dim == 2 && cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt triSizes_p2[2] = {1, 2}; PetscInt triPoints_p2[3] = {0, 1, 2}; ierr = PetscMalloc2(2, &sizes, 3, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, triSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, triPoints_p2, 3 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for triangular hybrid mesh on 2 procs", user->testNum); } } else if (dim == 2 && !cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt quadSizes_p2[2] = {1, 1}; PetscInt quadPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, quadSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, quadPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for quadrilateral mesh on 2 procs", user->testNum); } } else if (dim == 2 && !cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt quadSizes_p2[2] = {1, 2}; PetscInt quadPoints_p2[3] = {0, 1, 2}; ierr = PetscMalloc2(2, &sizes, 3, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, quadSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, quadPoints_p2, 3 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for quadrilateral hybrid mesh on 2 procs", user->testNum); } } else if (dim == 3 && cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt tetSizes_p2[2] = {1, 1}; PetscInt tetPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} case 1: { PetscInt tetSizes_p2[2] = {1, 1}; PetscInt tetPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for tetrahedral mesh on 2 procs", user->testNum); } } else if (dim == 3 && cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt tetSizes_p2[2] = {1, 2}; PetscInt tetPoints_p2[3] = {0, 1, 2}; ierr = PetscMalloc2(2, &sizes, 3, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 3 * sizeof(PetscInt));CHKERRQ(ierr);break;} case 1: { PetscInt tetSizes_p2[2] = {3, 4}; PetscInt tetPoints_p2[7] = {0, 3, 5, 1, 2, 4, 6}; ierr = PetscMalloc2(2, &sizes, 7, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 7 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for tetrahedral hybrid mesh on 2 procs", user->testNum); } } else if (dim == 3 && !cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt hexSizes_p2[2] = {1, 1}; PetscInt hexPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, hexSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, hexPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for hexahedral mesh on 2 procs", user->testNum); } } else if (dim == 3 && !cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt hexSizes_p2[2] = {1, 1}; PetscInt hexPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, hexSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, hexPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} case 1: { PetscInt hexSizes_p2[2] = {5, 4}; PetscInt hexPoints_p2[9] = {3, 4, 5, 7, 8, 0, 1, 2, 6}; ierr = PetscMalloc2(2, &sizes, 9, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, hexSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, hexPoints_p2, 9 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for hexahedral hybrid mesh on 2 procs", user->testNum); } } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test partition"); } ierr = DMPlexGetPartitioner(*dm, &part);CHKERRQ(ierr); ierr = PetscPartitionerSetType(part, PETSCPARTITIONERSHELL);CHKERRQ(ierr); ierr = PetscPartitionerShellSetPartition(part, size, sizes, points);CHKERRQ(ierr); ierr = PetscFree2(sizes, points);CHKERRQ(ierr); } else { PetscPartitioner part; ierr = DMPlexGetPartitioner(*dm,&part);CHKERRQ(ierr); ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); } { DM pdm = NULL; ierr = DMPlexDistribute(*dm, 0, NULL, &pdm);CHKERRQ(ierr); if (pdm) { ierr = DMViewFromOptions(pdm, NULL, "-dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = pdm; } } ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); if (user->simplex2tensor) { DM rdm = NULL; ierr = DMPlexSetRefinementUniform(*dm, PETSC_TRUE);CHKERRQ(ierr); ierr = DMPlexRefineSimplexToTensor(*dm, &rdm);CHKERRQ(ierr); if (rdm) { ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = rdm; } user->cellSimplex = PETSC_FALSE; } if (user->uninterpolate || user->reinterpolate) { DM udm = NULL; ierr = DMPlexUninterpolate(*dm, &udm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, udm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = udm; } if (user->reinterpolate) { DM idm = NULL; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } ierr = PetscObjectSetName((PetscObject) *dm, "Hybrid Mesh");CHKERRQ(ierr); ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject) *dm, "hyb_");CHKERRQ(ierr); ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode TestTriangle(MPI_Comm comm, PetscBool interpolate, PetscBool transform) { DM dm; PetscRandom r, ang, ang2; PetscInt dim, t; PetscErrorCode ierr; PetscFunctionBegin; /* Create reference triangle */ dim = 2; ierr = DMCreate(comm, &dm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) dm, "triangle");CHKERRQ(ierr); ierr = DMSetType(dm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(dm, dim);CHKERRQ(ierr); { PetscInt numPoints[2] = {3, 1}; PetscInt coneSize[4] = {3, 0, 0, 0}; PetscInt cones[3] = {1, 2, 3}; PetscInt coneOrientations[3] = {0, 0, 0}; PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; ierr = DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); if (interpolate) { DM idm; ierr = DMPlexInterpolate(dm, &idm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) idm, "triangle");CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(dm, idm);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); dm = idm; } ierr = DMSetFromOptions(dm);CHKERRQ(ierr); } /* Check reference geometry: determinant is scaled by reference volume (2.0) */ { PetscReal v0Ex[2] = {-1.0, -1.0}; PetscReal JEx[4] = {1.0, 0.0, 0.0, 1.0}; PetscReal invJEx[4] = {1.0, 0.0, 0.0, 1.0}; PetscReal detJEx = 1.0; PetscReal centroidEx[2] = {-0.333333333333, -0.333333333333}; PetscReal normalEx[2] = {0.0, 0.0}; PetscReal volEx = 2.0; ierr = CheckFEMGeometry(dm, 0, dim, v0Ex, JEx, invJEx, detJEx);CHKERRQ(ierr); if (interpolate) {ierr = CheckFVMGeometry(dm, 0, dim, centroidEx, normalEx, volEx);CHKERRQ(ierr);} } /* Check random triangles: rotate, scale, then translate */ if (transform) { ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); ierr = PetscRandomSetInterval(r, 0.0, 10.0);CHKERRQ(ierr); ierr = PetscRandomCreate(PETSC_COMM_SELF, &ang);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(ang);CHKERRQ(ierr); ierr = PetscRandomSetInterval(ang, 0.0, 2*PETSC_PI);CHKERRQ(ierr); for (t = 0; t < 100; ++t) { PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}, trans[2]; PetscReal v0Ex[2] = {-1.0, -1.0}; PetscReal JEx[4] = {1.0, 0.0, 0.0, 1.0}, R[4], rot[2], rotM[4]; PetscReal invJEx[4] = {1.0, 0.0, 0.0, 1.0}; PetscReal detJEx = 1.0, scale, phi; PetscReal centroidEx[2] = {-0.333333333333, -0.333333333333}; PetscReal normalEx[2] = {0.0, 0.0}; PetscReal volEx = 2.0; PetscInt d, e, f, p; ierr = PetscRandomGetValueReal(r, &scale);CHKERRQ(ierr); ierr = PetscRandomGetValueReal(ang, &phi);CHKERRQ(ierr); R[0] = cos(phi); R[1] = -sin(phi); R[2] = sin(phi); R[3] = cos(phi); for (p = 0; p < 3; ++p) { for (d = 0; d < dim; ++d) { for (e = 0, rot[d] = 0.0; e < dim; ++e) { rot[d] += R[d*dim+e] * vertexCoords[p*dim+e]; } } for (d = 0; d < dim; ++d) vertexCoords[p*dim+d] = rot[d]; } for (d = 0; d < dim; ++d) { for (e = 0, rot[d] = 0.0; e < dim; ++e) { rot[d] += R[d*dim+e] * centroidEx[e]; } } for (d = 0; d < dim; ++d) centroidEx[d] = rot[d]; for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { for (f = 0, rotM[d*dim+e] = 0.0; f < dim; ++f) { rotM[d*dim+e] += R[d*dim+f] * JEx[f*dim+e]; } } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { JEx[d*dim+e] = rotM[d*dim+e]; } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { for (f = 0, rotM[d*dim+e] = 0.0; f < dim; ++f) { rotM[d*dim+e] += invJEx[d*dim+f] * R[e*dim+f]; } } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { invJEx[d*dim+e] = rotM[d*dim+e]; } } for (d = 0; d < dim; ++d) { ierr = PetscRandomGetValueReal(r, &trans[d]);CHKERRQ(ierr); for (p = 0; p < 3; ++p) { vertexCoords[p*dim+d] *= scale; vertexCoords[p*dim+d] += trans[d]; } v0Ex[d] = vertexCoords[d]; for (e = 0; e < dim; ++e) { JEx[d*dim+e] *= scale; invJEx[d*dim+e] /= scale; } detJEx *= scale; centroidEx[d] *= scale; centroidEx[d] += trans[d]; volEx *= scale; } ierr = ChangeCoordinates(dm, dim, vertexCoords);CHKERRQ(ierr); ierr = CheckFEMGeometry(dm, 0, dim, v0Ex, JEx, invJEx, detJEx);CHKERRQ(ierr); if (interpolate) {ierr = CheckFVMGeometry(dm, 0, dim, centroidEx, normalEx, volEx);CHKERRQ(ierr);} } ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); ierr = PetscRandomDestroy(&ang);CHKERRQ(ierr); } /* Move to 3D: Check reference geometry: determinant is scaled by reference volume (2.0) */ dim = 3; { PetscScalar vertexCoords[9] = {-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0}; PetscReal v0Ex[3] = {-1.0, -1.0, 0.0}; PetscReal JEx[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; PetscReal invJEx[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; PetscReal detJEx = 1.0; PetscReal centroidEx[3] = {-0.333333333333, -0.333333333333, 0.0}; PetscReal normalEx[3] = {0.0, 0.0, 1.0}; PetscReal volEx = 2.0; ierr = ChangeCoordinates(dm, dim, vertexCoords);CHKERRQ(ierr); ierr = CheckFEMGeometry(dm, 0, dim, v0Ex, JEx, invJEx, detJEx);CHKERRQ(ierr); if (interpolate) {ierr = CheckFVMGeometry(dm, 0, dim, centroidEx, normalEx, volEx);CHKERRQ(ierr);} } /* Rotated reference element */ { PetscScalar vertexCoords[9] = {0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0}; PetscReal v0Ex[3] = {0.0, -1.0, -1.0}; PetscReal JEx[9] = {0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0}; PetscReal invJEx[9] = {0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0}; PetscReal detJEx = 1.0; PetscReal centroidEx[3] = {0.0, -0.333333333333, -0.333333333333}; PetscReal normalEx[3] = {1.0, 0.0, 0.0}; PetscReal volEx = 2.0; ierr = ChangeCoordinates(dm, dim, vertexCoords);CHKERRQ(ierr); ierr = CheckFEMGeometry(dm, 0, dim, v0Ex, JEx, invJEx, detJEx);CHKERRQ(ierr); if (interpolate) {ierr = CheckFVMGeometry(dm, 0, dim, centroidEx, normalEx, volEx);CHKERRQ(ierr);} } /* Check random triangles: scale, translate, then rotate */ if (transform) { ierr = PetscRandomCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(r);CHKERRQ(ierr); ierr = PetscRandomSetInterval(r, 0.0, 10.0);CHKERRQ(ierr); ierr = PetscRandomCreate(PETSC_COMM_SELF, &ang);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(ang);CHKERRQ(ierr); ierr = PetscRandomSetInterval(ang, 0.0, 2*PETSC_PI);CHKERRQ(ierr); ierr = PetscRandomCreate(PETSC_COMM_SELF, &ang2);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(ang2);CHKERRQ(ierr); ierr = PetscRandomSetInterval(ang2, 0.0, PETSC_PI);CHKERRQ(ierr); for (t = 0; t < 100; ++t) { PetscScalar vertexCoords[9] = {-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0}, trans[3]; PetscReal v0Ex[3] = {-1.0, -1.0, 0.0}; PetscReal JEx[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}, R[9], rot[3], rotM[9]; PetscReal invJEx[9] = {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; PetscReal detJEx = 1.0, scale, phi, theta, psi = 0.0; PetscReal centroidEx[3] = {-0.333333333333, -0.333333333333, 0.0}; PetscReal normalEx[3] = {0.0, 0.0, 1.0}; PetscReal volEx = 2.0; PetscInt d, e, f, p; ierr = PetscRandomGetValueReal(r, &scale);CHKERRQ(ierr); ierr = PetscRandomGetValueReal(ang, &phi);CHKERRQ(ierr); ierr = PetscRandomGetValueReal(ang2, &theta);CHKERRQ(ierr); for (d = 0; d < dim; ++d) { ierr = PetscRandomGetValueReal(r, &trans[d]);CHKERRQ(ierr); for (p = 0; p < 3; ++p) { vertexCoords[p*dim+d] *= scale; vertexCoords[p*dim+d] += trans[d]; } centroidEx[d] *= scale; centroidEx[d] += trans[d]; for (e = 0; e < dim-1; ++e) { JEx[d*dim+e] *= scale; invJEx[d*dim+e] /= scale; } if (d < dim-1) { detJEx *= scale; volEx *= scale; } } R[0] = cos(theta)*cos(psi); R[1] = sin(phi)*sin(theta)*cos(psi) - cos(phi)*sin(psi); R[2] = sin(phi)*sin(psi) + cos(phi)*sin(theta)*cos(psi); R[3] = cos(theta)*sin(psi); R[4] = cos(phi)*cos(psi) + sin(phi)*sin(theta)*sin(psi); R[5] = cos(phi)*sin(theta)*sin(psi) - sin(phi)*cos(psi); R[6] = -sin(theta); R[7] = sin(phi)*cos(theta); R[8] = cos(phi)*cos(theta); for (p = 0; p < 3; ++p) { for (d = 0; d < dim; ++d) { for (e = 0, rot[d] = 0.0; e < dim; ++e) { rot[d] += R[d*dim+e] * vertexCoords[p*dim+e]; } } for (d = 0; d < dim; ++d) vertexCoords[p*dim+d] = rot[d]; } for (d = 0; d < dim; ++d) { for (e = 0, rot[d] = 0.0; e < dim; ++e) { rot[d] += R[d*dim+e] * centroidEx[e]; } } for (d = 0; d < dim; ++d) centroidEx[d] = rot[d]; for (d = 0; d < dim; ++d) { for (e = 0, rot[d] = 0.0; e < dim; ++e) { rot[d] += R[d*dim+e] * normalEx[e]; } } for (d = 0; d < dim; ++d) normalEx[d] = rot[d]; for (d = 0; d < dim; ++d) { v0Ex[d] = vertexCoords[d]; for (e = 0; e < dim; ++e) { for (f = 0, rotM[d*dim+e] = 0.0; f < dim; ++f) { rotM[d*dim+e] += R[d*dim+f] * JEx[f*dim+e]; } } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { JEx[d*dim+e] = rotM[d*dim+e]; } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { for (f = 0, rotM[d*dim+e] = 0.0; f < dim; ++f) { rotM[d*dim+e] += invJEx[d*dim+f] * R[e*dim+f]; } } } for (d = 0; d < dim; ++d) { for (e = 0; e < dim; ++e) { invJEx[d*dim+e] = rotM[d*dim+e]; } } ierr = ChangeCoordinates(dm, dim, vertexCoords);CHKERRQ(ierr); ierr = CheckFEMGeometry(dm, 0, dim, v0Ex, JEx, invJEx, detJEx);CHKERRQ(ierr); if (interpolate) {ierr = CheckFVMGeometry(dm, 0, dim, centroidEx, normalEx, volEx);CHKERRQ(ierr);} } ierr = PetscRandomDestroy(&r);CHKERRQ(ierr); ierr = PetscRandomDestroy(&ang);CHKERRQ(ierr); ierr = PetscRandomDestroy(&ang2);CHKERRQ(ierr); } /* Cleanup */ ierr = DMDestroy(&dm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PETSC_EXTERN void PETSC_STDCALL dmplexcopycoordinates_(DM dmA,DM dmB, int *__ierr ){ *__ierr = DMPlexCopyCoordinates( (DM)PetscToPointer((dmA) ), (DM)PetscToPointer((dmB) )); }
PetscErrorCode CreateMesh(MPI_Comm comm, PetscInt testNum, AppCtx *user, DM *dm) { PetscInt dim = user->dim; PetscBool cellSimplex = user->cellSimplex; PetscBool useGenerator = user->useGenerator; const char *filename = user->filename; size_t len; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = PetscStrlen(filename, &len);CHKERRQ(ierr); if (len) { ierr = DMPlexCreateFromFile(comm, filename, PETSC_FALSE, dm);CHKERRQ(ierr); ierr = DMGetDimension(*dm, &dim);CHKERRQ(ierr); } else if (useGenerator) { if (cellSimplex) { ierr = DMPlexCreateBoxMesh(comm, dim, dim == 2 ? 2 : 1, PETSC_FALSE, dm);CHKERRQ(ierr); } else { const PetscInt cells[3] = {2, 2, 2}; ierr = DMPlexCreateHexBoxMesh(comm, dim, cells, PETSC_FALSE, PETSC_FALSE, PETSC_FALSE, dm);CHKERRQ(ierr); } } else { ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); switch (dim) { case 2: if (cellSimplex) { ierr = CreateSimplex_2D(comm, *dm);CHKERRQ(ierr); } else { ierr = CreateQuad_2D(comm, testNum, *dm);CHKERRQ(ierr); } break; case 3: if (cellSimplex) { ierr = CreateSimplex_3D(comm, *dm);CHKERRQ(ierr); } else { ierr = CreateHex_3D(comm, *dm);CHKERRQ(ierr); } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); } } { DM interpolatedMesh = NULL; ierr = CheckMesh(*dm, user);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &interpolatedMesh);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, interpolatedMesh);CHKERRQ(ierr); ierr = CompareCones(*dm, interpolatedMesh);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = interpolatedMesh; } { DM distributedMesh = NULL; /* Distribute mesh over processes */ ierr = DMPlexDistribute(*dm, 0, NULL, &distributedMesh);CHKERRQ(ierr); if (distributedMesh) { ierr = DMViewFromOptions(distributedMesh, NULL, "-dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = distributedMesh; } } ierr = PetscObjectSetName((PetscObject) *dm, "Interpolated Mesh");CHKERRQ(ierr); ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); user->dm = *dm; PetscFunctionReturn(0); }
PetscErrorCode CreateMesh(MPI_Comm comm, PetscInt testNum, AppCtx *user, DM *dm) { PetscInt dim = user->dim; PetscBool cellSimplex = user->cellSimplex; PetscBool useGenerator = user->useGenerator; const char *filename = user->filename; const char *partitioner = "chaco"; size_t len; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = PetscStrlen(filename, &len);CHKERRQ(ierr); if (len) { #if defined(PETSC_HAVE_EXODUSII) int CPU_word_size = 0, IO_word_size = 0, exoid = -1; float version; if (!rank) { exoid = ex_open(filename, EX_READ, &CPU_word_size, &IO_word_size, &version); if (exoid <= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open(\"%s\",...) did not return a valid file ID", filename); } ierr = DMPlexCreateExodus(comm, exoid, PETSC_FALSE, dm);CHKERRQ(ierr); if (!rank) {ierr = ex_close(exoid);CHKERRQ(ierr);} ierr = DMPlexGetDimension(*dm, &dim);CHKERRQ(ierr); #else SETERRQ(comm, PETSC_ERR_SUP, "Loading meshes requires ExodusII support. Reconfigure using --download-exodusii"); #endif } else if (useGenerator) { if (cellSimplex) { ierr = DMPlexCreateBoxMesh(comm, dim, PETSC_FALSE, dm);CHKERRQ(ierr); } else { ierr = DMPlexCreateHexBoxMesh(comm, dim, PETSC_FALSE, dm);CHKERRQ(ierr); } } else { ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); switch (dim) { case 2: if (cellSimplex) { ierr = CreateSimplex_2D(comm, *dm);CHKERRQ(ierr); } else { ierr = CreateQuad_2D(comm, testNum, *dm);CHKERRQ(ierr); } break; case 3: if (cellSimplex) { ierr = CreateSimplex_3D(comm, *dm);CHKERRQ(ierr); } else { ierr = CreateHex_3D(comm, *dm);CHKERRQ(ierr); } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); } } { DM interpolatedMesh = NULL; ierr = CheckMesh(*dm);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &interpolatedMesh);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, interpolatedMesh);CHKERRQ(ierr); ierr = CompareCones(*dm, interpolatedMesh);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = interpolatedMesh; } { DM distributedMesh = NULL; /* Distribute mesh over processes */ ierr = DMPlexDistribute(*dm, partitioner, 0, &distributedMesh);CHKERRQ(ierr); if (distributedMesh) { ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = distributedMesh; } } ierr = PetscObjectSetName((PetscObject) *dm, "Interpolated Mesh");CHKERRQ(ierr); ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); user->dm = *dm; PetscFunctionReturn(0); }
int main(int argc, char **argv) { DM dm; /* Problem specification */ DM dmAux; /* Material specification */ SNES snes; /* nonlinear solver */ Vec u,r; /* solution, residual vectors */ Mat A,J; /* Jacobian matrix */ MatNullSpace nullSpace; /* May be necessary for Neumann conditions */ AppCtx user; /* user-defined work context */ JacActionCtx userJ; /* context for Jacobian MF action */ PetscInt its; /* iterations for convergence */ PetscReal error = 0.0; /* L_2 error in the solution */ PetscInt numComponents; PetscErrorCode ierr; ierr = PetscInitialize(&argc, &argv, NULL, help);CHKERRQ(ierr); ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr); ierr = SNESCreate(PETSC_COMM_WORLD, &snes);CHKERRQ(ierr); ierr = CreateMesh(PETSC_COMM_WORLD, &user, &dm);CHKERRQ(ierr); ierr = SNESSetDM(snes, dm);CHKERRQ(ierr); ierr = DMSetApplicationContext(dm, &user);CHKERRQ(ierr); user.fem.fe = user.fe; ierr = PetscFECreateDefault(dm, user.dim, 1, PETSC_TRUE, NULL, -1, &user.fe[0]);CHKERRQ(ierr); if (user.bcType != NEUMANN) { user.fem.feBd = NULL; user.feBd[0] = NULL; } else { user.fem.feBd = user.feBd; ierr = PetscFECreateDefault(dm, user.dim-1, 1, PETSC_TRUE, "bd_", -1, &user.feBd[0]);CHKERRQ(ierr); } ierr = PetscFEGetNumComponents(user.fe[0], &numComponents);CHKERRQ(ierr); ierr = PetscMalloc(NUM_FIELDS * sizeof(void (*)(const PetscReal[], PetscScalar *, void *)), &user.exactFuncs);CHKERRQ(ierr); ierr = SetupProblem(dm, &user);CHKERRQ(ierr); ierr = SetupSection(dm, &user);CHKERRQ(ierr); /* Setup Material */ ierr = DMClone(dm, &dmAux);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(dm, dmAux);CHKERRQ(ierr); if (user.variableCoefficient != COEFF_FIELD) { user.fem.feAux = NULL; user.feAux[0] = NULL; } else { PetscQuadrature q; user.fem.feAux = user.feAux; ierr = PetscFECreateDefault(dmAux, user.dim, 1, PETSC_TRUE, "mat_", -1, &user.feAux[0]);CHKERRQ(ierr); ierr = PetscFEGetQuadrature(user.fe[0], &q);CHKERRQ(ierr); ierr = PetscFESetQuadrature(user.feAux[0], q);CHKERRQ(ierr); } ierr = SetupMaterialSection(dmAux, &user);CHKERRQ(ierr); ierr = SetupMaterial(dm, dmAux, &user);CHKERRQ(ierr); ierr = DMDestroy(&dmAux);CHKERRQ(ierr); ierr = DMCreateGlobalVector(dm, &u);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) u, "potential");CHKERRQ(ierr); ierr = VecDuplicate(u, &r);CHKERRQ(ierr); ierr = DMSetMatType(dm,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr); if (user.jacobianMF) { PetscInt M, m, N, n; ierr = MatGetSize(J, &M, &N);CHKERRQ(ierr); ierr = MatGetLocalSize(J, &m, &n);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD, &A);CHKERRQ(ierr); ierr = MatSetSizes(A, m, n, M, N);CHKERRQ(ierr); ierr = MatSetType(A, MATSHELL);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); #if 0 ierr = MatShellSetOperation(A, MATOP_MULT, (void (*)(void))FormJacobianAction);CHKERRQ(ierr); #endif userJ.dm = dm; userJ.J = J; userJ.user = &user; ierr = DMCreateLocalVector(dm, &userJ.u);CHKERRQ(ierr); ierr = DMPlexProjectFunctionLocal(dm, user.fe, user.exactFuncs, NULL, INSERT_BC_VALUES, userJ.u);CHKERRQ(ierr); ierr = MatShellSetContext(A, &userJ);CHKERRQ(ierr); } else { A = J; } if (user.bcType == NEUMANN) { ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject) dm), PETSC_TRUE, 0, NULL, &nullSpace);CHKERRQ(ierr); ierr = MatSetNullSpace(J, nullSpace);CHKERRQ(ierr); if (A != J) { ierr = MatSetNullSpace(A, nullSpace);CHKERRQ(ierr); } } ierr = DMSNESSetFunctionLocal(dm, (PetscErrorCode (*)(DM,Vec,Vec,void*)) DMPlexComputeResidualFEM, &user);CHKERRQ(ierr); ierr = DMSNESSetJacobianLocal(dm, (PetscErrorCode (*)(DM,Vec,Mat,Mat,void*)) DMPlexComputeJacobianFEM, &user);CHKERRQ(ierr); ierr = SNESSetJacobian(snes, A, J, NULL, NULL);CHKERRQ(ierr); ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); ierr = DMPlexProjectFunction(dm, user.fe, user.exactFuncs, NULL, INSERT_ALL_VALUES, u);CHKERRQ(ierr); if (user.checkpoint) { #if defined(PETSC_HAVE_HDF5) ierr = PetscViewerHDF5PushGroup(user.checkpoint, "/fields");CHKERRQ(ierr); ierr = VecLoad(u, user.checkpoint);CHKERRQ(ierr); ierr = PetscViewerHDF5PopGroup(user.checkpoint);CHKERRQ(ierr); #endif } ierr = PetscViewerDestroy(&user.checkpoint);CHKERRQ(ierr); if (user.showInitial) { Vec lv; ierr = DMGetLocalVector(dm, &lv);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(dm, u, INSERT_VALUES, lv);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(dm, u, INSERT_VALUES, lv);CHKERRQ(ierr); ierr = DMPrintLocalVec(dm, "Local function", 1.0e-10, lv);CHKERRQ(ierr); ierr = DMRestoreLocalVector(dm, &lv);CHKERRQ(ierr); } if (user.runType == RUN_FULL) { void (*initialGuess[numComponents])(const PetscReal x[], PetscScalar *, void *ctx); PetscInt c; for (c = 0; c < numComponents; ++c) initialGuess[c] = zero; ierr = DMPlexProjectFunction(dm, user.fe, initialGuess, NULL, INSERT_VALUES, u);CHKERRQ(ierr); if (user.debug) { ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial guess\n");CHKERRQ(ierr); ierr = VecView(u, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } ierr = SNESSolve(snes, NULL, u);CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes, &its);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Number of SNES iterations = %D\n", its);CHKERRQ(ierr); ierr = DMPlexComputeL2Diff(dm, user.fe, user.exactFuncs, NULL, u, &error);CHKERRQ(ierr); if (error < 1.0e-11) {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: < 1.0e-11\n");CHKERRQ(ierr);} else {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: %g\n", error);CHKERRQ(ierr);} if (user.showSolution) { ierr = PetscPrintf(PETSC_COMM_WORLD, "Solution\n");CHKERRQ(ierr); ierr = VecChop(u, 3.0e-9);CHKERRQ(ierr); ierr = VecView(u, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } } else if (user.runType == RUN_PERF) { PetscReal res = 0.0; ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial Residual\n");CHKERRQ(ierr); ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Residual: %g\n", res);CHKERRQ(ierr); } else { PetscReal res = 0.0; /* Check discretization error */ ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial guess\n");CHKERRQ(ierr); ierr = VecView(u, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = DMPlexComputeL2Diff(dm, user.fe, user.exactFuncs, NULL, u, &error);CHKERRQ(ierr); if (error < 1.0e-11) {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: < 1.0e-11\n");CHKERRQ(ierr);} else {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: %g\n", error);CHKERRQ(ierr);} /* Check residual */ ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial Residual\n");CHKERRQ(ierr); ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); ierr = VecView(r, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Residual: %g\n", res);CHKERRQ(ierr); /* Check Jacobian */ { Vec b; ierr = SNESComputeJacobian(snes, u, A, A);CHKERRQ(ierr); ierr = VecDuplicate(u, &b);CHKERRQ(ierr); ierr = VecSet(r, 0.0);CHKERRQ(ierr); ierr = SNESComputeFunction(snes, r, b);CHKERRQ(ierr); ierr = MatMult(A, u, r);CHKERRQ(ierr); ierr = VecAXPY(r, 1.0, b);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Au - b = Au + F(0)\n");CHKERRQ(ierr); ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); ierr = VecView(r, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Linear L_2 Residual: %g\n", res);CHKERRQ(ierr); } } ierr = VecViewFromOptions(u, NULL, "-vec_view");CHKERRQ(ierr); if (user.bcType == NEUMANN) { ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); } if (user.jacobianMF) { ierr = VecDestroy(&userJ.u);CHKERRQ(ierr); } if (A != J) {ierr = MatDestroy(&A);CHKERRQ(ierr);} ierr = PetscFEDestroy(&user.fe[0]);CHKERRQ(ierr); ierr = PetscFEDestroy(&user.feBd[0]);CHKERRQ(ierr); ierr = PetscFEDestroy(&user.feAux[0]);CHKERRQ(ierr); ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); ierr = PetscFree(user.exactFuncs);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
PetscErrorCode CreateTensorProductHybrid_3D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm = NULL, hdm = NULL; DMLabel faultLabel; PetscInt p; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { switch (testNum) { case 0: { PetscInt numPoints[2] = {12, 2}; PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[36] = {-1.0, -0.5, -0.5, -1.0, 0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5}; PetscInt faultPoints[4] = {2, 3, 5, 6}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 4; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} } break; case 1: { PetscInt numPoints[2] = {30, 7}; PetscInt coneSize[37] = {8,8,8,8,8,8,8, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; PetscInt cones[56] = { 8, 21, 20, 7, 13, 12, 23, 24, 14, 15, 10, 9, 13, 8, 21, 24, 15, 16, 11, 10, 24, 21, 22, 25, 30, 29, 28, 21, 35, 24, 33, 34, 24, 21, 30, 35, 25, 36, 31, 22, 27, 20, 21, 28, 32, 33, 24, 23, 15, 24, 13, 14, 19, 18, 17, 26}; PetscInt coneOrientations[56] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; PetscScalar vertexCoords[90] = {-2.0, -2.0, -2.0, -2.0, -1.0, -2.0, -3.0, 0.0, -2.0, -2.0, 1.0, -2.0, -2.0, 2.0, -2.0, -2.0, -2.0, 0.0, -2.0, -1.0, 0.0, -3.0, 0.0, 0.0, -2.0, 1.0, 0.0, -2.0, 2.0, 0.0, -2.0, -1.0, 2.0, -3.0, 0.0, 2.0, -2.0, 1.0, 2.0, 0.0, -2.0, -2.0, 0.0, 0.0, -2.0, 0.0, 2.0, -2.0, 0.0, -2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 2.0, -2.0, -2.0, 2.0, -1.0, -2.0, 3.0, 0.0, -2.0, 2.0, 1.0, -2.0, 2.0, 2.0, -2.0, 2.0, -2.0, 0.0, 2.0, -1.0, 0.0, 3.0, 0.0, 0.0, 2.0, 1.0, 0.0, 2.0, 2.0, 0.0}; PetscInt faultPoints[6] = {20, 21, 22, 23, 24, 25}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 6; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); } ierr = DMPlexCheckSymmetry(*dm);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCheckSymmetry(idm);CHKERRQ(ierr); ierr = DMGetLabel(*dm, "fault", &faultLabel);CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, faultLabel, NULL, &hdm);CHKERRQ(ierr); ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; } else { PetscInt numPoints[4] = {0, 0, 0, 0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, NULL, NULL, &hdm);CHKERRQ(ierr); ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; } PetscFunctionReturn(0); }
/* Two tetrahedrons separated by a zero-volume cell with 6 vertices cell 6 ___33___10______ cell 0 / | \ |\ \ 1 21 | 23 | 29 27 /12 24 14\ 30 \ \ 3-20-|----5--32-|---9--26--7 \ 13| 11/ |18 / / 19 | 22 | 28 25 \ | / |/ / 4----31----8------ cell 2 */ PetscErrorCode CreateSimplexHybrid_3D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm = NULL, hdm = NULL; DMLabel faultLabel, hybridLabel; PetscInt p; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { switch (testNum) { case 0: { PetscInt numPoints[2] = {5, 2}; PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[15] = {-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0}; PetscInt faultPoints[3] = {3, 4, 5}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} } break; case 1: { /* Tets 0,3,5 and 1,2,4 */ PetscInt numPoints[2] = {9, 6}; PetscInt coneSize[15] = {4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscInt cones[24] = { 7, 9, 8, 6, 11, 9, 13, 14, 10, 13, 11, 9, 10, 9, 11, 7, 9, 13, 14, 12, 7, 11, 8, 9}; PetscInt coneOrientations[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[27] = {-2.0, -1.0, 0.0, -2.0, 0.0, 0.0, -2.0, 0.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, -1.0, 0.0, 2.0, 0.0, 0.0, 2.0, 0.0, 1.0}; PetscInt faultPoints[3] = {9, 10, 11}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "fault", faultPoints[p], 1);CHKERRQ(ierr);} } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); } ierr = DMPlexCheckSymmetry(*dm);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCheckSymmetry(idm);CHKERRQ(ierr); ierr = DMGetLabel(*dm, "fault", &faultLabel);CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, faultLabel, &hybridLabel, &hdm);CHKERRQ(ierr); ierr = DMLabelDestroy(&hybridLabel);CHKERRQ(ierr); ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; } else { PetscInt numPoints[4] = {0, 0, 0, 0}; ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMPlexCreateHybridMesh(idm, NULL, NULL, &hdm);CHKERRQ(ierr); ierr = DMDestroy(&idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = hdm; } PetscFunctionReturn(0); }
/* Two tetrahedrons cell 5 5______ cell 0 / | \ |\ \ 1 17 | 18 | 18 13 21 /8 19 10\ 19 \ \ 2-14-|----4 | 4--22--6 \ 9 | 7 / |10 / / 16 | 15 | 15 12 20 \ | / |/ / 3 3------ */ PetscErrorCode CreateSimplex_3D(MPI_Comm comm, PetscInt testNum, DM *dm) { DM idm = NULL; PetscInt depth = 3; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); if (!rank) { switch (testNum) { case 0: { PetscInt numPoints[4] = {5, 9, 7, 2}; PetscInt coneSize[23] = {4, 4, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2}; PetscInt cones[47] = { 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 14, 16, 19, 17, 15, 18, 19, 20, 21, 19, 15, 22, 20, 18, 21, 22, 2, 4, 4, 3, 3, 2, 2, 5, 5, 4, 3, 5, 3, 6, 6, 5, 4, 6}; PetscInt coneOrientations[47] = { 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, 0, -2, -2, -2, -2, 0, 0, -2, -2, 0, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[15] = {0.0, 0.0, -0.5, 0.0, -0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5}; ierr = DMPlexCreateFromDAG(*dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); } break; case 1: { PetscInt numPoints[2] = {5, 2}; PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[15] = {-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0}; depth = 1; ierr = DMPlexCreateFromDAG(*dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } break; case 2: { PetscInt numPoints[2] = {4, 1}; PetscInt coneSize[5] = {4, 0, 0, 0, 0}; PetscInt cones[4] = {2, 3, 4, 1}; PetscInt coneOrientations[4] = {0, 0, 0, 0}; PetscScalar vertexCoords[12] = {0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; depth = 1; ierr = DMPlexCreateFromDAG(*dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); } } else { PetscInt numPoints[4] = {0, 0, 0, 0}; ierr = DMPlexCreateFromDAG(*dm, depth, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); switch (testNum) { case 1: ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMViewFromOptions(idm, NULL, "-in_dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; break; } } PetscFunctionReturn(0); }
PetscErrorCode SetupDiscretization(DM dm, AppCtx *user) { DM cdm = dm; const PetscInt dim = user->dim; const PetscInt id = 1; PetscFE feAux = NULL; PetscFE feBd = NULL; PetscFE feCh = NULL; PetscFE fe; PetscDS prob; PetscErrorCode ierr; PetscFunctionBeginUser; /* Create finite element */ ierr = PetscFECreateDefault(dm, dim, 1, PETSC_TRUE, NULL, -1, &fe);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) fe, "potential");CHKERRQ(ierr); if (user->bcType == NEUMANN) { ierr = PetscFECreateDefault(dm, dim-1, 1, PETSC_TRUE, "bd_", -1, &feBd);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) feBd, "potential");CHKERRQ(ierr); } if (user->variableCoefficient == COEFF_FIELD) { PetscQuadrature q; ierr = PetscFECreateDefault(dm, dim, 1, PETSC_TRUE, "mat_", -1, &feAux);CHKERRQ(ierr); ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); ierr = PetscFESetQuadrature(feAux, q);CHKERRQ(ierr); } if (user->check) {ierr = PetscFECreateDefault(dm, dim, 1, PETSC_TRUE, "ch_", -1, &feCh);CHKERRQ(ierr);} /* Set discretization and boundary conditions for each mesh */ while (cdm) { ierr = DMGetDS(cdm, &prob);CHKERRQ(ierr); ierr = PetscDSSetDiscretization(prob, 0, (PetscObject) fe);CHKERRQ(ierr); ierr = PetscDSSetBdDiscretization(prob, 0, (PetscObject) feBd);CHKERRQ(ierr); if (feAux) { DM dmAux; PetscDS probAux; ierr = DMClone(cdm, &dmAux);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(cdm, dmAux);CHKERRQ(ierr); ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); ierr = PetscDSSetDiscretization(probAux, 0, (PetscObject) feAux);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dm, "dmAux", (PetscObject) dmAux);CHKERRQ(ierr); ierr = SetupMaterial(cdm, dmAux, user);CHKERRQ(ierr); ierr = DMDestroy(&dmAux);CHKERRQ(ierr); } if (feCh) { DM dmCh; PetscDS probCh; ierr = DMClone(cdm, &dmCh);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(cdm, dmCh);CHKERRQ(ierr); ierr = DMGetDS(dmCh, &probCh);CHKERRQ(ierr); ierr = PetscDSSetDiscretization(probCh, 0, (PetscObject) feCh);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject) dm, "dmCh", (PetscObject) dmCh);CHKERRQ(ierr); ierr = DMDestroy(&dmCh);CHKERRQ(ierr); } ierr = SetupProblem(cdm, user);CHKERRQ(ierr); ierr = DMPlexAddBoundary(cdm, user->bcType == DIRICHLET, "wall", user->bcType == NEUMANN ? "boundary" : "marker", 0, user->exactFuncs[0], 1, &id, user);CHKERRQ(ierr); ierr = DMPlexGetCoarseDM(cdm, &cdm);CHKERRQ(ierr); } ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); ierr = PetscFEDestroy(&feBd);CHKERRQ(ierr); ierr = PetscFEDestroy(&feAux);CHKERRQ(ierr); ierr = PetscFEDestroy(&feCh);CHKERRQ(ierr); PetscFunctionReturn(0); }