1*5754ecacSJeremy L Thompson /// @file 2*5754ecacSJeremy L Thompson /// DM setup for solid mechanics example using PETSc 3*5754ecacSJeremy L Thompson 4*5754ecacSJeremy L Thompson #include "../include/boundary.h" 5*5754ecacSJeremy L Thompson #include "../include/setup-dm.h" 6*5754ecacSJeremy L Thompson #include "../include/petsc-macros.h" 7*5754ecacSJeremy L Thompson 8*5754ecacSJeremy L Thompson // ----------------------------------------------------------------------------- 9*5754ecacSJeremy L Thompson // Setup DM 10*5754ecacSJeremy L Thompson // ----------------------------------------------------------------------------- 11*5754ecacSJeremy L Thompson PetscErrorCode CreateBCLabel(DM dm, const char name[]) { 12*5754ecacSJeremy L Thompson PetscErrorCode ierr; 13*5754ecacSJeremy L Thompson DMLabel label; 14*5754ecacSJeremy L Thompson 15*5754ecacSJeremy L Thompson PetscFunctionBeginUser; 16*5754ecacSJeremy L Thompson 17*5754ecacSJeremy L Thompson ierr = DMCreateLabel(dm, name); CHKERRQ(ierr); 18*5754ecacSJeremy L Thompson ierr = DMGetLabel(dm, name, &label); CHKERRQ(ierr); 19*5754ecacSJeremy L Thompson ierr = DMPlexMarkBoundaryFaces(dm, 1, label); CHKERRQ(ierr); 20*5754ecacSJeremy L Thompson ierr = DMPlexLabelComplete(dm, label); CHKERRQ(ierr); 21*5754ecacSJeremy L Thompson 22*5754ecacSJeremy L Thompson PetscFunctionReturn(0); 23*5754ecacSJeremy L Thompson }; 24*5754ecacSJeremy L Thompson 25*5754ecacSJeremy L Thompson // Read mesh and distribute DM in parallel 26*5754ecacSJeremy L Thompson PetscErrorCode CreateDistributedDM(MPI_Comm comm, AppCtx app_ctx, DM *dm) { 27*5754ecacSJeremy L Thompson PetscErrorCode ierr; 28*5754ecacSJeremy L Thompson const char *filename = app_ctx->mesh_file; 29*5754ecacSJeremy L Thompson PetscBool interpolate = PETSC_TRUE; 30*5754ecacSJeremy L Thompson DM distributed_mesh = NULL; 31*5754ecacSJeremy L Thompson PetscPartitioner part; 32*5754ecacSJeremy L Thompson 33*5754ecacSJeremy L Thompson PetscFunctionBeginUser; 34*5754ecacSJeremy L Thompson 35*5754ecacSJeremy L Thompson if (!*filename) { 36*5754ecacSJeremy L Thompson PetscInt dim = 3, faces[3] = {3, 3, 3}; 37*5754ecacSJeremy L Thompson ierr = PetscOptionsGetIntArray(NULL, NULL, "-dm_plex_box_faces", 38*5754ecacSJeremy L Thompson faces, &dim, NULL); CHKERRQ(ierr); 39*5754ecacSJeremy L Thompson ierr = DMPlexCreateBoxMesh(comm, dim, PETSC_FALSE, faces, NULL, 40*5754ecacSJeremy L Thompson NULL, NULL, interpolate, dm); CHKERRQ(ierr); 41*5754ecacSJeremy L Thompson } else { 42*5754ecacSJeremy L Thompson ierr = DMPlexCreateFromFile(comm, filename, interpolate, dm); CHKERRQ(ierr); 43*5754ecacSJeremy L Thompson } 44*5754ecacSJeremy L Thompson 45*5754ecacSJeremy L Thompson // Distribute DM in parallel 46*5754ecacSJeremy L Thompson ierr = DMPlexGetPartitioner(*dm, &part); CHKERRQ(ierr); 47*5754ecacSJeremy L Thompson ierr = PetscPartitionerSetFromOptions(part); CHKERRQ(ierr); 48*5754ecacSJeremy L Thompson ierr = DMPlexDistribute(*dm, 0, NULL, &distributed_mesh); CHKERRQ(ierr); 49*5754ecacSJeremy L Thompson if (distributed_mesh) { 50*5754ecacSJeremy L Thompson ierr = DMDestroy(dm); CHKERRQ(ierr); 51*5754ecacSJeremy L Thompson *dm = distributed_mesh; 52*5754ecacSJeremy L Thompson } 53*5754ecacSJeremy L Thompson ierr = DMViewFromOptions(*dm, NULL, "-dm_view"); CHKERRQ(ierr); 54*5754ecacSJeremy L Thompson 55*5754ecacSJeremy L Thompson PetscFunctionReturn(0); 56*5754ecacSJeremy L Thompson }; 57*5754ecacSJeremy L Thompson 58*5754ecacSJeremy L Thompson // Create FE by degree 59*5754ecacSJeremy L Thompson PetscErrorCode PetscFECreateByDegree(DM dm, PetscInt dim, PetscInt Nc, 60*5754ecacSJeremy L Thompson PetscBool isSimplex, const char prefix[], 61*5754ecacSJeremy L Thompson PetscInt order, PetscFE *fem) { 62*5754ecacSJeremy L Thompson PetscQuadrature q, fq; 63*5754ecacSJeremy L Thompson DM K; 64*5754ecacSJeremy L Thompson PetscSpace P; 65*5754ecacSJeremy L Thompson PetscDualSpace Q; 66*5754ecacSJeremy L Thompson PetscInt quadPointsPerEdge; 67*5754ecacSJeremy L Thompson PetscBool tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 68*5754ecacSJeremy L Thompson PetscErrorCode ierr; 69*5754ecacSJeremy L Thompson 70*5754ecacSJeremy L Thompson PetscFunctionBeginUser; 71*5754ecacSJeremy L Thompson /* Create space */ 72*5754ecacSJeremy L Thompson ierr = PetscSpaceCreate(PetscObjectComm((PetscObject) dm), &P); CHKERRQ(ierr); 73*5754ecacSJeremy L Thompson ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix); CHKERRQ(ierr); 74*5754ecacSJeremy L Thompson ierr = PetscSpacePolynomialSetTensor(P, tensor); CHKERRQ(ierr); 75*5754ecacSJeremy L Thompson ierr = PetscSpaceSetFromOptions(P); CHKERRQ(ierr); 76*5754ecacSJeremy L Thompson ierr = PetscSpaceSetNumComponents(P, Nc); CHKERRQ(ierr); 77*5754ecacSJeremy L Thompson ierr = PetscSpaceSetNumVariables(P, dim); CHKERRQ(ierr); 78*5754ecacSJeremy L Thompson ierr = PetscSpaceSetDegree(P, order, order); CHKERRQ(ierr); 79*5754ecacSJeremy L Thompson ierr = PetscSpaceSetUp(P); CHKERRQ(ierr); 80*5754ecacSJeremy L Thompson ierr = PetscSpacePolynomialGetTensor(P, &tensor); CHKERRQ(ierr); 81*5754ecacSJeremy L Thompson /* Create dual space */ 82*5754ecacSJeremy L Thompson ierr = PetscDualSpaceCreate(PetscObjectComm((PetscObject) dm), &Q); 83*5754ecacSJeremy L Thompson CHKERRQ(ierr); 84*5754ecacSJeremy L Thompson ierr = PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE); CHKERRQ(ierr); 85*5754ecacSJeremy L Thompson ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix); CHKERRQ(ierr); 86*5754ecacSJeremy L Thompson ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K); CHKERRQ(ierr); 87*5754ecacSJeremy L Thompson ierr = PetscDualSpaceSetDM(Q, K); CHKERRQ(ierr); 88*5754ecacSJeremy L Thompson ierr = DMDestroy(&K); CHKERRQ(ierr); 89*5754ecacSJeremy L Thompson ierr = PetscDualSpaceSetNumComponents(Q, Nc); CHKERRQ(ierr); 90*5754ecacSJeremy L Thompson ierr = PetscDualSpaceSetOrder(Q, order); CHKERRQ(ierr); 91*5754ecacSJeremy L Thompson ierr = PetscDualSpaceLagrangeSetTensor(Q, tensor); CHKERRQ(ierr); 92*5754ecacSJeremy L Thompson ierr = PetscDualSpaceSetFromOptions(Q); CHKERRQ(ierr); 93*5754ecacSJeremy L Thompson ierr = PetscDualSpaceSetUp(Q); CHKERRQ(ierr); 94*5754ecacSJeremy L Thompson /* Create element */ 95*5754ecacSJeremy L Thompson ierr = PetscFECreate(PetscObjectComm((PetscObject) dm), fem); CHKERRQ(ierr); 96*5754ecacSJeremy L Thompson ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix); CHKERRQ(ierr); 97*5754ecacSJeremy L Thompson ierr = PetscFESetFromOptions(*fem); CHKERRQ(ierr); 98*5754ecacSJeremy L Thompson ierr = PetscFESetBasisSpace(*fem, P); CHKERRQ(ierr); 99*5754ecacSJeremy L Thompson ierr = PetscFESetDualSpace(*fem, Q); CHKERRQ(ierr); 100*5754ecacSJeremy L Thompson ierr = PetscFESetNumComponents(*fem, Nc); CHKERRQ(ierr); 101*5754ecacSJeremy L Thompson ierr = PetscFESetUp(*fem); CHKERRQ(ierr); 102*5754ecacSJeremy L Thompson ierr = PetscSpaceDestroy(&P); CHKERRQ(ierr); 103*5754ecacSJeremy L Thompson ierr = PetscDualSpaceDestroy(&Q); CHKERRQ(ierr); 104*5754ecacSJeremy L Thompson /* Create quadrature */ 105*5754ecacSJeremy L Thompson quadPointsPerEdge = PetscMax(order + 1,1); 106*5754ecacSJeremy L Thompson if (isSimplex) { 107*5754ecacSJeremy L Thompson ierr = PetscDTStroudConicalQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, 108*5754ecacSJeremy L Thompson &q); CHKERRQ(ierr); 109*5754ecacSJeremy L Thompson ierr = PetscDTStroudConicalQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, 110*5754ecacSJeremy L Thompson &fq); CHKERRQ(ierr); 111*5754ecacSJeremy L Thompson } else { 112*5754ecacSJeremy L Thompson ierr = PetscDTGaussTensorQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, 113*5754ecacSJeremy L Thompson &q); CHKERRQ(ierr); 114*5754ecacSJeremy L Thompson ierr = PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, 115*5754ecacSJeremy L Thompson &fq); CHKERRQ(ierr); 116*5754ecacSJeremy L Thompson } 117*5754ecacSJeremy L Thompson ierr = PetscFESetQuadrature(*fem, q); CHKERRQ(ierr); 118*5754ecacSJeremy L Thompson ierr = PetscFESetFaceQuadrature(*fem, fq); CHKERRQ(ierr); 119*5754ecacSJeremy L Thompson ierr = PetscQuadratureDestroy(&q); CHKERRQ(ierr); 120*5754ecacSJeremy L Thompson ierr = PetscQuadratureDestroy(&fq); CHKERRQ(ierr); 121*5754ecacSJeremy L Thompson 122*5754ecacSJeremy L Thompson PetscFunctionReturn(0); 123*5754ecacSJeremy L Thompson } 124*5754ecacSJeremy L Thompson 125*5754ecacSJeremy L Thompson // Setup DM with FE space of appropriate degree 126*5754ecacSJeremy L Thompson PetscErrorCode SetupDMByDegree(DM dm, AppCtx app_ctx, PetscInt order, 127*5754ecacSJeremy L Thompson PetscBool boundary, PetscInt num_comp_u) { 128*5754ecacSJeremy L Thompson PetscErrorCode ierr; 129*5754ecacSJeremy L Thompson PetscInt dim; 130*5754ecacSJeremy L Thompson PetscFE fe; 131*5754ecacSJeremy L Thompson IS face_set_is; // Index Set for Face Sets 132*5754ecacSJeremy L Thompson const char *name = "Face Sets"; // PETSc internal requirement 133*5754ecacSJeremy L Thompson PetscInt num_face_sets; // Number of FaceSets in face_set_is 134*5754ecacSJeremy L Thompson const PetscInt *face_set_ids; // id of each FaceSet 135*5754ecacSJeremy L Thompson 136*5754ecacSJeremy L Thompson PetscFunctionBeginUser; 137*5754ecacSJeremy L Thompson 138*5754ecacSJeremy L Thompson // Setup DM 139*5754ecacSJeremy L Thompson ierr = DMGetDimension(dm, &dim); CHKERRQ(ierr); 140*5754ecacSJeremy L Thompson ierr = PetscFECreateByDegree(dm, dim, num_comp_u, PETSC_FALSE, NULL, order, 141*5754ecacSJeremy L Thompson &fe); 142*5754ecacSJeremy L Thompson CHKERRQ(ierr); 143*5754ecacSJeremy L Thompson ierr = DMSetFromOptions(dm); CHKERRQ(ierr); 144*5754ecacSJeremy L Thompson ierr = DMAddField(dm, NULL, (PetscObject)fe); CHKERRQ(ierr); 145*5754ecacSJeremy L Thompson ierr = DMCreateDS(dm); CHKERRQ(ierr); 146*5754ecacSJeremy L Thompson 147*5754ecacSJeremy L Thompson // Add Dirichlet (Essential) boundary 148*5754ecacSJeremy L Thompson if (boundary) { 149*5754ecacSJeremy L Thompson if (app_ctx->forcing_choice == FORCE_MMS) { 150*5754ecacSJeremy L Thompson if (app_ctx->test_mode) { 151*5754ecacSJeremy L Thompson // -- Test mode - box mesh 152*5754ecacSJeremy L Thompson PetscBool has_label; 153*5754ecacSJeremy L Thompson PetscInt marker_ids[1] = {1}; 154*5754ecacSJeremy L Thompson ierr = DMHasLabel(dm, "marker", &has_label); CHKERRQ(ierr); 155*5754ecacSJeremy L Thompson if (!has_label) { 156*5754ecacSJeremy L Thompson ierr = CreateBCLabel(dm, "marker"); CHKERRQ(ierr); 157*5754ecacSJeremy L Thompson } 158*5754ecacSJeremy L Thompson DMLabel label; 159*5754ecacSJeremy L Thompson ierr = DMGetLabel(dm, "marker", &label); CHKERRQ(ierr); 160*5754ecacSJeremy L Thompson ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "mms", label, "marker", 1, marker_ids, 161*5754ecacSJeremy L Thompson 0, 0, NULL, (void(*)(void))BCMMS, NULL, NULL, NULL); 162*5754ecacSJeremy L Thompson CHKERRQ(ierr); 163*5754ecacSJeremy L Thompson } else { 164*5754ecacSJeremy L Thompson // -- ExodusII mesh with MMS 165*5754ecacSJeremy L Thompson ierr = DMGetLabelIdIS(dm, name, &face_set_is); CHKERRQ(ierr); 166*5754ecacSJeremy L Thompson ierr = ISGetSize(face_set_is,&num_face_sets); CHKERRQ(ierr); 167*5754ecacSJeremy L Thompson ierr = ISGetIndices(face_set_is, &face_set_ids); CHKERRQ(ierr); 168*5754ecacSJeremy L Thompson DMLabel label; 169*5754ecacSJeremy L Thompson ierr = DMGetLabel(dm, "Face Sets", &label); CHKERRQ(ierr); 170*5754ecacSJeremy L Thompson ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "mms", label, "Face Sets", 171*5754ecacSJeremy L Thompson num_face_sets, face_set_ids, 0, 0, NULL, 172*5754ecacSJeremy L Thompson (void(*)(void))BCMMS, NULL, NULL, NULL); 173*5754ecacSJeremy L Thompson CHKERRQ(ierr); 174*5754ecacSJeremy L Thompson ierr = ISRestoreIndices(face_set_is, &face_set_ids); CHKERRQ(ierr); 175*5754ecacSJeremy L Thompson ierr = ISDestroy(&face_set_is); CHKERRQ(ierr); 176*5754ecacSJeremy L Thompson } 177*5754ecacSJeremy L Thompson } else { 178*5754ecacSJeremy L Thompson // -- ExodusII mesh with user specified BCs 179*5754ecacSJeremy L Thompson // -- Clamp BCs 180*5754ecacSJeremy L Thompson DMLabel label; 181*5754ecacSJeremy L Thompson ierr = DMGetLabel(dm, "Face Sets", &label); CHKERRQ(ierr); 182*5754ecacSJeremy L Thompson for (PetscInt i = 0; i < app_ctx->bc_clamp_count; i++) { 183*5754ecacSJeremy L Thompson char bcName[25]; 184*5754ecacSJeremy L Thompson snprintf(bcName, sizeof bcName, "clamp_%d", app_ctx->bc_clamp_faces[i]); 185*5754ecacSJeremy L Thompson ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, bcName, label, "Face Sets", 1, 186*5754ecacSJeremy L Thompson &app_ctx->bc_clamp_faces[i], 0, 0, 187*5754ecacSJeremy L Thompson NULL, (void(*)(void))BCClamp, NULL, 188*5754ecacSJeremy L Thompson (void *)&app_ctx->bc_clamp_max[i], NULL); 189*5754ecacSJeremy L Thompson CHKERRQ(ierr); 190*5754ecacSJeremy L Thompson } 191*5754ecacSJeremy L Thompson } 192*5754ecacSJeremy L Thompson } 193*5754ecacSJeremy L Thompson ierr = DMPlexSetClosurePermutationTensor(dm, PETSC_DETERMINE, NULL); 194*5754ecacSJeremy L Thompson CHKERRQ(ierr); 195*5754ecacSJeremy L Thompson 196*5754ecacSJeremy L Thompson // Cleanup 197*5754ecacSJeremy L Thompson ierr = PetscFEDestroy(&fe); CHKERRQ(ierr); 198*5754ecacSJeremy L Thompson 199*5754ecacSJeremy L Thompson PetscFunctionReturn(0); 200*5754ecacSJeremy L Thompson }; 201