1*3d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2*3d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3*3d8e8822SJeremy L Thompson // 4*3d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 5*3d8e8822SJeremy L Thompson // 6*3d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 7*3d8e8822SJeremy L Thompson 85754ecacSJeremy L Thompson /// @file 95754ecacSJeremy L Thompson /// Command line option processing for solid mechanics example using PETSc 105754ecacSJeremy L Thompson 115754ecacSJeremy L Thompson #include "../include/cl-options.h" 125754ecacSJeremy L Thompson 135754ecacSJeremy L Thompson // ----------------------------------------------------------------------------- 145754ecacSJeremy L Thompson // Process command line options 155754ecacSJeremy L Thompson // ----------------------------------------------------------------------------- 165754ecacSJeremy L Thompson // Process general command line options 175754ecacSJeremy L Thompson PetscErrorCode ProcessCommandLineOptions(MPI_Comm comm, AppCtx app_ctx) { 185754ecacSJeremy L Thompson PetscErrorCode ierr; 195754ecacSJeremy L Thompson PetscBool ceed_flag = PETSC_FALSE; 205754ecacSJeremy L Thompson 215754ecacSJeremy L Thompson PetscFunctionBeginUser; 225754ecacSJeremy L Thompson 235754ecacSJeremy L Thompson ierr = PetscOptionsBegin(comm, NULL, 245754ecacSJeremy L Thompson "Elasticity / Hyperelasticity in PETSc with libCEED", 255754ecacSJeremy L Thompson NULL); CHKERRQ(ierr); 265754ecacSJeremy L Thompson 275754ecacSJeremy L Thompson ierr = PetscOptionsString("-ceed", "CEED resource specifier", 285754ecacSJeremy L Thompson NULL, app_ctx->ceed_resource, app_ctx->ceed_resource, 295754ecacSJeremy L Thompson sizeof(app_ctx->ceed_resource), &ceed_flag); 305754ecacSJeremy L Thompson CHKERRQ(ierr); 315754ecacSJeremy L Thompson 325754ecacSJeremy L Thompson ierr = PetscStrncpy(app_ctx->output_dir, ".", 2); 335754ecacSJeremy L Thompson CHKERRQ(ierr); // Default - current directory 345754ecacSJeremy L Thompson ierr = PetscOptionsString("-output_dir", "Output directory", 355754ecacSJeremy L Thompson NULL, app_ctx->output_dir, app_ctx->output_dir, 365754ecacSJeremy L Thompson sizeof(app_ctx->output_dir), NULL); CHKERRQ(ierr); 375754ecacSJeremy L Thompson 385754ecacSJeremy L Thompson app_ctx->degree = 3; 395754ecacSJeremy L Thompson ierr = PetscOptionsInt("-degree", "Polynomial degree of tensor product basis", 405754ecacSJeremy L Thompson NULL, app_ctx->degree, &app_ctx->degree, NULL); 415754ecacSJeremy L Thompson CHKERRQ(ierr); 425754ecacSJeremy L Thompson 435754ecacSJeremy L Thompson app_ctx->q_extra = 0; 445754ecacSJeremy L Thompson ierr = PetscOptionsInt("-qextra", "Number of extra quadrature points", 455754ecacSJeremy L Thompson NULL, app_ctx->q_extra, &app_ctx->q_extra, NULL); 465754ecacSJeremy L Thompson CHKERRQ(ierr); 475754ecacSJeremy L Thompson 485754ecacSJeremy L Thompson ierr = PetscOptionsString("-mesh", "Read mesh from file", NULL, 495754ecacSJeremy L Thompson app_ctx->mesh_file, app_ctx->mesh_file, 505754ecacSJeremy L Thompson sizeof(app_ctx->mesh_file), NULL); CHKERRQ(ierr); 515754ecacSJeremy L Thompson 525754ecacSJeremy L Thompson app_ctx->problem_choice = ELAS_LINEAR; // Default - Linear Elasticity 535754ecacSJeremy L Thompson ierr = PetscOptionsEnum("-problem", 545754ecacSJeremy L Thompson "Solves Elasticity & Hyperelasticity Problems", 555754ecacSJeremy L Thompson NULL, problemTypes, (PetscEnum)app_ctx->problem_choice, 565754ecacSJeremy L Thompson (PetscEnum *)&app_ctx->problem_choice, NULL); 575754ecacSJeremy L Thompson CHKERRQ(ierr); 585754ecacSJeremy L Thompson app_ctx->name = problemTypes[app_ctx->problem_choice]; 595754ecacSJeremy L Thompson app_ctx->name_for_disp = problemTypesForDisp[app_ctx->problem_choice]; 605754ecacSJeremy L Thompson 615754ecacSJeremy L Thompson app_ctx->num_increments = app_ctx->problem_choice == ELAS_LINEAR ? 1 : 10; 625754ecacSJeremy L Thompson ierr = PetscOptionsInt("-num_steps", "Number of pseudo-time steps", 635754ecacSJeremy L Thompson NULL, app_ctx->num_increments, &app_ctx->num_increments, 645754ecacSJeremy L Thompson NULL); CHKERRQ(ierr); 655754ecacSJeremy L Thompson 665754ecacSJeremy L Thompson app_ctx->forcing_choice = FORCE_NONE; // Default - no forcing term 675754ecacSJeremy L Thompson ierr = PetscOptionsEnum("-forcing", "Set forcing function option", NULL, 685754ecacSJeremy L Thompson forcing_types, (PetscEnum)app_ctx->forcing_choice, 695754ecacSJeremy L Thompson (PetscEnum *)&app_ctx->forcing_choice, NULL); 705754ecacSJeremy L Thompson CHKERRQ(ierr); 715754ecacSJeremy L Thompson 725754ecacSJeremy L Thompson PetscInt max_n = 3; 735754ecacSJeremy L Thompson app_ctx->forcing_vector[0] = 0; 745754ecacSJeremy L Thompson app_ctx->forcing_vector[1] = -1; 755754ecacSJeremy L Thompson app_ctx->forcing_vector[2] = 0; 765754ecacSJeremy L Thompson ierr = PetscOptionsScalarArray("-forcing_vec", 775754ecacSJeremy L Thompson "Direction to apply constant force", NULL, 785754ecacSJeremy L Thompson app_ctx->forcing_vector, &max_n, NULL); 795754ecacSJeremy L Thompson CHKERRQ(ierr); 805754ecacSJeremy L Thompson 815754ecacSJeremy L Thompson if ((app_ctx->problem_choice == ELAS_FSInitial_NH1 || 825754ecacSJeremy L Thompson app_ctx->problem_choice == ELAS_FSInitial_NH2 || 835754ecacSJeremy L Thompson app_ctx->problem_choice == ELAS_FSCurrent_NH1 || 845754ecacSJeremy L Thompson app_ctx->problem_choice == ELAS_FSCurrent_NH2 || 855754ecacSJeremy L Thompson app_ctx->problem_choice == ELAS_FSInitial_MR1) && 865754ecacSJeremy L Thompson app_ctx->forcing_choice == FORCE_CONST) 875754ecacSJeremy L Thompson SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, 885754ecacSJeremy L Thompson "Cannot use constant forcing and finite strain formulation. " 895754ecacSJeremy L Thompson "Constant forcing in reference frame currently unavaliable."); 905754ecacSJeremy L Thompson 915754ecacSJeremy L Thompson // Dirichlet boundary conditions 925754ecacSJeremy L Thompson app_ctx->bc_clamp_count = 16; 935754ecacSJeremy L Thompson ierr = PetscOptionsIntArray("-bc_clamp", 945754ecacSJeremy L Thompson "Face IDs to apply incremental Dirichlet BC", 955754ecacSJeremy L Thompson NULL, app_ctx->bc_clamp_faces, &app_ctx->bc_clamp_count, 965754ecacSJeremy L Thompson NULL); CHKERRQ(ierr); 975754ecacSJeremy L Thompson // Set vector for each clamped BC 985754ecacSJeremy L Thompson for (PetscInt i = 0; i < app_ctx->bc_clamp_count; i++) { 995754ecacSJeremy L Thompson // Translation vector 1005754ecacSJeremy L Thompson char option_name[25]; 1015754ecacSJeremy L Thompson const size_t nclamp_params = sizeof(app_ctx->bc_clamp_max[0])/sizeof( 1025754ecacSJeremy L Thompson app_ctx->bc_clamp_max[0][0]); 1035754ecacSJeremy L Thompson for (PetscInt j = 0; j < nclamp_params; j++) 1045754ecacSJeremy L Thompson app_ctx->bc_clamp_max[i][j] = 0.; 1055754ecacSJeremy L Thompson 1065754ecacSJeremy L Thompson snprintf(option_name, sizeof option_name, "-bc_clamp_%d_translate", 1075754ecacSJeremy L Thompson app_ctx->bc_clamp_faces[i]); 1085754ecacSJeremy L Thompson max_n = 3; 1095754ecacSJeremy L Thompson ierr = PetscOptionsScalarArray(option_name, 1105754ecacSJeremy L Thompson "Vector to translate clamped end by", NULL, 1115754ecacSJeremy L Thompson app_ctx->bc_clamp_max[i], &max_n, NULL); 1125754ecacSJeremy L Thompson CHKERRQ(ierr); 1135754ecacSJeremy L Thompson 1145754ecacSJeremy L Thompson // Rotation vector 1155754ecacSJeremy L Thompson max_n = 5; 1165754ecacSJeremy L Thompson snprintf(option_name, sizeof option_name, "-bc_clamp_%d_rotate", 1175754ecacSJeremy L Thompson app_ctx->bc_clamp_faces[i]); 1185754ecacSJeremy L Thompson ierr = PetscOptionsScalarArray(option_name, 1195754ecacSJeremy L Thompson "Vector with axis of rotation and rotation, in radians", 1205754ecacSJeremy L Thompson NULL, &app_ctx->bc_clamp_max[i][3], &max_n, NULL); 1215754ecacSJeremy L Thompson CHKERRQ(ierr); 1225754ecacSJeremy L Thompson 1235754ecacSJeremy L Thompson // Normalize 1245754ecacSJeremy L Thompson PetscScalar norm = sqrt(app_ctx->bc_clamp_max[i][3]*app_ctx->bc_clamp_max[i][3] 1255754ecacSJeremy L Thompson + app_ctx->bc_clamp_max[i][4]*app_ctx->bc_clamp_max[i][4] 1265754ecacSJeremy L Thompson + app_ctx->bc_clamp_max[i][5]*app_ctx->bc_clamp_max[i][5]); 1275754ecacSJeremy L Thompson if (fabs(norm) < 1e-16) 1285754ecacSJeremy L Thompson norm = 1; 1295754ecacSJeremy L Thompson for (PetscInt j = 0; j < 3; j++) 1305754ecacSJeremy L Thompson app_ctx->bc_clamp_max[i][3 + j] /= norm; 1315754ecacSJeremy L Thompson } 1325754ecacSJeremy L Thompson 1335754ecacSJeremy L Thompson // Neumann boundary conditions 1345754ecacSJeremy L Thompson app_ctx->bc_traction_count = 16; 1355754ecacSJeremy L Thompson ierr = PetscOptionsIntArray("-bc_traction", 1365754ecacSJeremy L Thompson "Face IDs to apply traction (Neumann) BC", 1375754ecacSJeremy L Thompson NULL, app_ctx->bc_traction_faces, 1385754ecacSJeremy L Thompson &app_ctx->bc_traction_count, NULL); CHKERRQ(ierr); 1395754ecacSJeremy L Thompson // Set vector for each traction BC 1405754ecacSJeremy L Thompson for (PetscInt i = 0; i < app_ctx->bc_traction_count; i++) { 1415754ecacSJeremy L Thompson // Translation vector 1425754ecacSJeremy L Thompson char option_name[25]; 1435754ecacSJeremy L Thompson for (PetscInt j = 0; j < 3; j++) 1445754ecacSJeremy L Thompson app_ctx->bc_traction_vector[i][j] = 0.; 1455754ecacSJeremy L Thompson 1465754ecacSJeremy L Thompson snprintf(option_name, sizeof option_name, "-bc_traction_%d", 1475754ecacSJeremy L Thompson app_ctx->bc_traction_faces[i]); 1485754ecacSJeremy L Thompson max_n = 3; 1495754ecacSJeremy L Thompson PetscBool set = false; 1505754ecacSJeremy L Thompson ierr = PetscOptionsScalarArray(option_name, 1515754ecacSJeremy L Thompson "Traction vector for constrained face", NULL, 1525754ecacSJeremy L Thompson app_ctx->bc_traction_vector[i], &max_n, &set); 1535754ecacSJeremy L Thompson CHKERRQ(ierr); 1545754ecacSJeremy L Thompson 1555754ecacSJeremy L Thompson if (!set) 1565754ecacSJeremy L Thompson SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, 1575754ecacSJeremy L Thompson "Traction vector must be set for all traction boundary conditions."); 1585754ecacSJeremy L Thompson } 1595754ecacSJeremy L Thompson 1605754ecacSJeremy L Thompson app_ctx->multigrid_choice = MULTIGRID_LOGARITHMIC; 1615754ecacSJeremy L Thompson ierr = PetscOptionsEnum("-multigrid", "Set multigrid type option", NULL, 1625754ecacSJeremy L Thompson multigrid_types, (PetscEnum)app_ctx->multigrid_choice, 1635754ecacSJeremy L Thompson (PetscEnum *)&app_ctx->multigrid_choice, NULL); 1645754ecacSJeremy L Thompson CHKERRQ(ierr); 1655754ecacSJeremy L Thompson 1665754ecacSJeremy L Thompson app_ctx->test_mode = PETSC_FALSE; 1675754ecacSJeremy L Thompson ierr = PetscOptionsBool("-test", 1685754ecacSJeremy L Thompson "Testing mode (do not print unless error is large)", 1695754ecacSJeremy L Thompson NULL, app_ctx->test_mode, &(app_ctx->test_mode), NULL); 1705754ecacSJeremy L Thompson CHKERRQ(ierr); 1715754ecacSJeremy L Thompson 1725754ecacSJeremy L Thompson app_ctx->expect_final_strain = -1.; 1735754ecacSJeremy L Thompson ierr = PetscOptionsReal("-expect_final_strain_energy", 1745754ecacSJeremy L Thompson "Expect final strain energy close to this value.", 1755754ecacSJeremy L Thompson NULL, app_ctx->expect_final_strain, &app_ctx->expect_final_strain, NULL); 1765754ecacSJeremy L Thompson CHKERRQ(ierr); 1775754ecacSJeremy L Thompson 1785754ecacSJeremy L Thompson app_ctx->test_tol = 1e-8; 1795754ecacSJeremy L Thompson ierr = PetscOptionsReal("-expect_final_state_rtol", 1805754ecacSJeremy L Thompson "Relative tolerance for final strain energy test", 1815754ecacSJeremy L Thompson NULL, app_ctx->test_tol, &app_ctx->test_tol, NULL); 1825754ecacSJeremy L Thompson CHKERRQ(ierr); 1835754ecacSJeremy L Thompson 1845754ecacSJeremy L Thompson app_ctx->view_soln = PETSC_FALSE; 1855754ecacSJeremy L Thompson ierr = PetscOptionsBool("-view_soln", "Write out solution vector for viewing", 1865754ecacSJeremy L Thompson NULL, app_ctx->view_soln, &(app_ctx->view_soln), NULL); 1875754ecacSJeremy L Thompson CHKERRQ(ierr); 1885754ecacSJeremy L Thompson 1895754ecacSJeremy L Thompson app_ctx->view_final_soln = PETSC_FALSE; 1905754ecacSJeremy L Thompson ierr = PetscOptionsBool("-view_final_soln", 1915754ecacSJeremy L Thompson "Write out final solution vector for viewing", 1925754ecacSJeremy L Thompson NULL, app_ctx->view_final_soln, &(app_ctx->view_final_soln), 1935754ecacSJeremy L Thompson NULL); CHKERRQ(ierr); 1945754ecacSJeremy L Thompson CHKERRQ(ierr); 1955754ecacSJeremy L Thompson 1965754ecacSJeremy L Thompson PetscBool set; 1975754ecacSJeremy L Thompson char energy_viewer_filename[PETSC_MAX_PATH_LEN] = ""; 1985754ecacSJeremy L Thompson ierr = PetscOptionsString("-strain_energy_monitor", 1995754ecacSJeremy L Thompson "Print out current strain energy at every load increment", 2005754ecacSJeremy L Thompson NULL, energy_viewer_filename, 2015754ecacSJeremy L Thompson energy_viewer_filename, sizeof(energy_viewer_filename), 2025754ecacSJeremy L Thompson &set); CHKERRQ(ierr); 2035754ecacSJeremy L Thompson if (set) { 2045754ecacSJeremy L Thompson ierr = PetscViewerASCIIOpen(comm, energy_viewer_filename, 2055754ecacSJeremy L Thompson &app_ctx->energy_viewer); CHKERRQ(ierr); 2065754ecacSJeremy L Thompson ierr = PetscViewerASCIIPrintf(app_ctx->energy_viewer, "increment,energy\n"); 2075754ecacSJeremy L Thompson CHKERRQ(ierr); 2085754ecacSJeremy L Thompson // Initial configuration is base energy state; this may not be true if we extend in the future to 2095754ecacSJeremy L Thompson // initially loaded configurations (because a truly at-rest initial state may not be realizable). 2105754ecacSJeremy L Thompson ierr = PetscViewerASCIIPrintf(app_ctx->energy_viewer, "%f,%e\n", 0., 0.); 2115754ecacSJeremy L Thompson CHKERRQ(ierr); 2125754ecacSJeremy L Thompson } 2135754ecacSJeremy L Thompson ierr = PetscOptionsEnd(); CHKERRQ(ierr); // End of setting AppCtx 2145754ecacSJeremy L Thompson 2155754ecacSJeremy L Thompson // Check for all required values set 2165754ecacSJeremy L Thompson if (app_ctx->test_mode) { 2175754ecacSJeremy L Thompson if (app_ctx->forcing_choice == FORCE_NONE && !app_ctx->bc_clamp_count) 2185754ecacSJeremy L Thompson app_ctx->forcing_choice = FORCE_MMS; 2195754ecacSJeremy L Thompson } 2205754ecacSJeremy L Thompson if (!app_ctx->bc_clamp_count && app_ctx->forcing_choice != FORCE_MMS) { 2215754ecacSJeremy L Thompson SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "-boundary options needed"); 2225754ecacSJeremy L Thompson } 2235754ecacSJeremy L Thompson 2245754ecacSJeremy L Thompson // Provide default ceed resource if not specified 2255754ecacSJeremy L Thompson if (!ceed_flag) { 2265754ecacSJeremy L Thompson const char *ceed_resource = "/cpu/self"; 2275754ecacSJeremy L Thompson strncpy(app_ctx->ceed_resource, ceed_resource, 10); 2285754ecacSJeremy L Thompson } 2295754ecacSJeremy L Thompson 2305754ecacSJeremy L Thompson // Determine number of levels 2315754ecacSJeremy L Thompson switch (app_ctx->multigrid_choice) { 2325754ecacSJeremy L Thompson case MULTIGRID_LOGARITHMIC: 2335754ecacSJeremy L Thompson app_ctx->num_levels = ceil(log(app_ctx->degree)/log(2)) + 1; 2345754ecacSJeremy L Thompson break; 2355754ecacSJeremy L Thompson case MULTIGRID_UNIFORM: 2365754ecacSJeremy L Thompson app_ctx->num_levels = app_ctx->degree; 2375754ecacSJeremy L Thompson break; 2385754ecacSJeremy L Thompson case MULTIGRID_NONE: 2395754ecacSJeremy L Thompson app_ctx->num_levels = 1; 2405754ecacSJeremy L Thompson break; 2415754ecacSJeremy L Thompson } 2425754ecacSJeremy L Thompson 2435754ecacSJeremy L Thompson // Populate array of degrees for each level for multigrid 2445754ecacSJeremy L Thompson ierr = PetscMalloc1(app_ctx->num_levels, &(app_ctx->level_degrees)); 2455754ecacSJeremy L Thompson CHKERRQ(ierr); 2465754ecacSJeremy L Thompson 2475754ecacSJeremy L Thompson switch (app_ctx->multigrid_choice) { 2485754ecacSJeremy L Thompson case MULTIGRID_LOGARITHMIC: 2495754ecacSJeremy L Thompson for (int i = 0; i < app_ctx->num_levels-1; i++) 2505754ecacSJeremy L Thompson app_ctx->level_degrees[i] = pow(2,i); 2515754ecacSJeremy L Thompson app_ctx->level_degrees[app_ctx->num_levels-1] = app_ctx->degree; 2525754ecacSJeremy L Thompson break; 2535754ecacSJeremy L Thompson case MULTIGRID_UNIFORM: 2545754ecacSJeremy L Thompson for (int i = 0; i < app_ctx->num_levels; i++) 2555754ecacSJeremy L Thompson app_ctx->level_degrees[i] = i + 1; 2565754ecacSJeremy L Thompson break; 2575754ecacSJeremy L Thompson case MULTIGRID_NONE: 2585754ecacSJeremy L Thompson app_ctx->level_degrees[0] = app_ctx->degree; 2595754ecacSJeremy L Thompson break; 2605754ecacSJeremy L Thompson } 2615754ecacSJeremy L Thompson 2625754ecacSJeremy L Thompson PetscFunctionReturn(0); 2635754ecacSJeremy L Thompson }; 264