13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 33d8e8822SJeremy L Thompson // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 53d8e8822SJeremy L Thompson // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 73d8e8822SJeremy 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 1349aac155SJeremy L Thompson #include <ceed.h> 1449aac155SJeremy L Thompson #include <petscsys.h> 1549aac155SJeremy L Thompson 165754ecacSJeremy L Thompson // ----------------------------------------------------------------------------- 175754ecacSJeremy L Thompson // Process command line options 185754ecacSJeremy L Thompson // ----------------------------------------------------------------------------- 195754ecacSJeremy L Thompson // Process general command line options 205754ecacSJeremy L Thompson PetscErrorCode ProcessCommandLineOptions(MPI_Comm comm, AppCtx app_ctx) { 215754ecacSJeremy L Thompson PetscBool ceed_flag = PETSC_FALSE; 225754ecacSJeremy L Thompson 235754ecacSJeremy L Thompson PetscFunctionBeginUser; 245754ecacSJeremy L Thompson 252b730f8bSJeremy L Thompson PetscOptionsBegin(comm, NULL, "Elasticity / Hyperelasticity in PETSc with libCEED", NULL); 265754ecacSJeremy L Thompson 272b730f8bSJeremy L Thompson PetscCall(PetscOptionsString("-ceed", "CEED resource specifier", NULL, app_ctx->ceed_resource, app_ctx->ceed_resource, 282b730f8bSJeremy L Thompson sizeof(app_ctx->ceed_resource), &ceed_flag)); 295754ecacSJeremy L Thompson 302b730f8bSJeremy L Thompson PetscCall(PetscStrncpy(app_ctx->output_dir, ".", 2)); // Default - current directory 312b730f8bSJeremy L Thompson PetscCall(PetscOptionsString("-output_dir", "Output directory", NULL, app_ctx->output_dir, app_ctx->output_dir, sizeof(app_ctx->output_dir), NULL)); 325754ecacSJeremy L Thompson 335754ecacSJeremy L Thompson app_ctx->degree = 3; 342b730f8bSJeremy L Thompson PetscCall(PetscOptionsInt("-degree", "Polynomial degree of tensor product basis", NULL, app_ctx->degree, &app_ctx->degree, NULL)); 355754ecacSJeremy L Thompson 365754ecacSJeremy L Thompson app_ctx->q_extra = 0; 372b730f8bSJeremy L Thompson PetscCall(PetscOptionsInt("-q_extra", "Number of extra quadrature points", NULL, app_ctx->q_extra, &app_ctx->q_extra, NULL)); 385754ecacSJeremy L Thompson 392b730f8bSJeremy L Thompson PetscCall(PetscOptionsString("-mesh", "Read mesh from file", NULL, app_ctx->mesh_file, app_ctx->mesh_file, sizeof(app_ctx->mesh_file), NULL)); 405754ecacSJeremy L Thompson 415754ecacSJeremy L Thompson app_ctx->problem_choice = ELAS_LINEAR; // Default - Linear Elasticity 422b730f8bSJeremy L Thompson PetscCall(PetscOptionsEnum("-problem", "Solves Elasticity & Hyperelasticity Problems", NULL, problemTypes, (PetscEnum)app_ctx->problem_choice, 432b730f8bSJeremy L Thompson (PetscEnum *)&app_ctx->problem_choice, NULL)); 445754ecacSJeremy L Thompson app_ctx->name = problemTypes[app_ctx->problem_choice]; 455754ecacSJeremy L Thompson app_ctx->name_for_disp = problemTypesForDisp[app_ctx->problem_choice]; 465754ecacSJeremy L Thompson 475754ecacSJeremy L Thompson app_ctx->num_increments = app_ctx->problem_choice == ELAS_LINEAR ? 1 : 10; 482b730f8bSJeremy L Thompson PetscCall(PetscOptionsInt("-num_steps", "Number of pseudo-time steps", NULL, app_ctx->num_increments, &app_ctx->num_increments, NULL)); 495754ecacSJeremy L Thompson 505754ecacSJeremy L Thompson app_ctx->forcing_choice = FORCE_NONE; // Default - no forcing term 512b730f8bSJeremy L Thompson PetscCall(PetscOptionsEnum("-forcing", "Set forcing function option", NULL, forcing_types, (PetscEnum)app_ctx->forcing_choice, 522b730f8bSJeremy L Thompson (PetscEnum *)&app_ctx->forcing_choice, NULL)); 535754ecacSJeremy L Thompson 545754ecacSJeremy L Thompson PetscInt max_n = 3; 555754ecacSJeremy L Thompson app_ctx->forcing_vector[0] = 0; 565754ecacSJeremy L Thompson app_ctx->forcing_vector[1] = -1; 575754ecacSJeremy L Thompson app_ctx->forcing_vector[2] = 0; 582b730f8bSJeremy L Thompson PetscCall(PetscOptionsScalarArray("-forcing_vec", "Direction to apply constant force", NULL, app_ctx->forcing_vector, &max_n, NULL)); 595754ecacSJeremy L Thompson 602b730f8bSJeremy L Thompson if ((app_ctx->problem_choice == ELAS_FSInitial_NH1 || app_ctx->problem_choice == ELAS_FSInitial_NH2 || 612b730f8bSJeremy L Thompson app_ctx->problem_choice == ELAS_FSCurrent_NH1 || app_ctx->problem_choice == ELAS_FSCurrent_NH2 || 625754ecacSJeremy L Thompson app_ctx->problem_choice == ELAS_FSInitial_MR1) && 6349aac155SJeremy L Thompson app_ctx->forcing_choice == FORCE_CONST) { 645754ecacSJeremy L Thompson SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, 655754ecacSJeremy L Thompson "Cannot use constant forcing and finite strain formulation. " 6649aac155SJeremy L Thompson "Constant forcing in reference frame currently unavailable."); 6749aac155SJeremy L Thompson } 685754ecacSJeremy L Thompson 695754ecacSJeremy L Thompson // Dirichlet boundary conditions 705754ecacSJeremy L Thompson app_ctx->bc_clamp_count = 16; 712b730f8bSJeremy L Thompson PetscCall( 722b730f8bSJeremy L Thompson PetscOptionsIntArray("-bc_clamp", "Face IDs to apply incremental Dirichlet BC", NULL, app_ctx->bc_clamp_faces, &app_ctx->bc_clamp_count, NULL)); 735754ecacSJeremy L Thompson // Set vector for each clamped BC 745754ecacSJeremy L Thompson for (PetscInt i = 0; i < app_ctx->bc_clamp_count; i++) { 755754ecacSJeremy L Thompson // Translation vector 765754ecacSJeremy L Thompson char option_name[25]; 772b730f8bSJeremy L Thompson const size_t nclamp_params = sizeof(app_ctx->bc_clamp_max[0]) / sizeof(app_ctx->bc_clamp_max[0][0]); 782b730f8bSJeremy L Thompson for (PetscInt j = 0; j < nclamp_params; j++) app_ctx->bc_clamp_max[i][j] = 0.; 795754ecacSJeremy L Thompson 802b730f8bSJeremy L Thompson snprintf(option_name, sizeof option_name, "-bc_clamp_%" PetscInt_FMT "_translate", app_ctx->bc_clamp_faces[i]); 815754ecacSJeremy L Thompson max_n = 3; 822b730f8bSJeremy L Thompson PetscCall(PetscOptionsScalarArray(option_name, "Vector to translate clamped end by", NULL, app_ctx->bc_clamp_max[i], &max_n, NULL)); 835754ecacSJeremy L Thompson 845754ecacSJeremy L Thompson // Rotation vector 855754ecacSJeremy L Thompson max_n = 5; 862b730f8bSJeremy L Thompson snprintf(option_name, sizeof option_name, "-bc_clamp_%" PetscInt_FMT "_rotate", app_ctx->bc_clamp_faces[i]); 872b730f8bSJeremy L Thompson PetscCall(PetscOptionsScalarArray(option_name, "Vector with axis of rotation and rotation, in radians", NULL, &app_ctx->bc_clamp_max[i][3], 882b730f8bSJeremy L Thompson &max_n, NULL)); 895754ecacSJeremy L Thompson 905754ecacSJeremy L Thompson // Normalize 912b730f8bSJeremy L Thompson PetscScalar norm = sqrt(app_ctx->bc_clamp_max[i][3] * app_ctx->bc_clamp_max[i][3] + app_ctx->bc_clamp_max[i][4] * app_ctx->bc_clamp_max[i][4] + 922b730f8bSJeremy L Thompson app_ctx->bc_clamp_max[i][5] * app_ctx->bc_clamp_max[i][5]); 932b730f8bSJeremy L Thompson if (fabs(norm) < 1e-16) norm = 1; 942b730f8bSJeremy L Thompson for (PetscInt j = 0; j < 3; j++) app_ctx->bc_clamp_max[i][3 + j] /= norm; 955754ecacSJeremy L Thompson } 965754ecacSJeremy L Thompson 975754ecacSJeremy L Thompson // Neumann boundary conditions 985754ecacSJeremy L Thompson app_ctx->bc_traction_count = 16; 992b730f8bSJeremy L Thompson PetscCall(PetscOptionsIntArray("-bc_traction", "Face IDs to apply traction (Neumann) BC", NULL, app_ctx->bc_traction_faces, 1002b730f8bSJeremy L Thompson &app_ctx->bc_traction_count, NULL)); 1015754ecacSJeremy L Thompson // Set vector for each traction BC 1025754ecacSJeremy L Thompson for (PetscInt i = 0; i < app_ctx->bc_traction_count; i++) { 1035754ecacSJeremy L Thompson // Translation vector 1045754ecacSJeremy L Thompson char option_name[25]; 1052b730f8bSJeremy L Thompson for (PetscInt j = 0; j < 3; j++) app_ctx->bc_traction_vector[i][j] = 0.; 1065754ecacSJeremy L Thompson 1072b730f8bSJeremy L Thompson snprintf(option_name, sizeof option_name, "-bc_traction_%" PetscInt_FMT, app_ctx->bc_traction_faces[i]); 1085754ecacSJeremy L Thompson max_n = 3; 1095754ecacSJeremy L Thompson PetscBool set = false; 1102b730f8bSJeremy L Thompson PetscCall(PetscOptionsScalarArray(option_name, "Traction vector for constrained face", NULL, app_ctx->bc_traction_vector[i], &max_n, &set)); 1115754ecacSJeremy L Thompson 1122b730f8bSJeremy L Thompson if (!set) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Traction vector must be set for all traction boundary conditions."); 1135754ecacSJeremy L Thompson } 1145754ecacSJeremy L Thompson 1155754ecacSJeremy L Thompson app_ctx->multigrid_choice = MULTIGRID_LOGARITHMIC; 1162b730f8bSJeremy L Thompson PetscCall(PetscOptionsEnum("-multigrid", "Set multigrid type option", NULL, multigrid_types, (PetscEnum)app_ctx->multigrid_choice, 1172b730f8bSJeremy L Thompson (PetscEnum *)&app_ctx->multigrid_choice, NULL)); 1185754ecacSJeremy L Thompson 1195754ecacSJeremy L Thompson app_ctx->test_mode = PETSC_FALSE; 1202b730f8bSJeremy L Thompson PetscCall(PetscOptionsBool("-test", "Testing mode (do not print unless error is large)", NULL, app_ctx->test_mode, &(app_ctx->test_mode), NULL)); 1215754ecacSJeremy L Thompson 1225754ecacSJeremy L Thompson app_ctx->expect_final_strain = -1.; 1232b730f8bSJeremy L Thompson PetscCall(PetscOptionsReal("-expect_final_strain_energy", "Expect final strain energy close to this value.", NULL, app_ctx->expect_final_strain, 1242b730f8bSJeremy L Thompson &app_ctx->expect_final_strain, NULL)); 1255754ecacSJeremy L Thompson 1265754ecacSJeremy L Thompson app_ctx->test_tol = 1e-8; 1272b730f8bSJeremy L Thompson PetscCall(PetscOptionsReal("-expect_final_state_rtol", "Relative tolerance for final strain energy test", NULL, app_ctx->test_tol, 1282b730f8bSJeremy L Thompson &app_ctx->test_tol, NULL)); 1295754ecacSJeremy L Thompson 1305754ecacSJeremy L Thompson app_ctx->view_soln = PETSC_FALSE; 1312b730f8bSJeremy L Thompson PetscCall(PetscOptionsBool("-view_soln", "Write out solution vector for viewing", NULL, app_ctx->view_soln, &(app_ctx->view_soln), NULL)); 1325754ecacSJeremy L Thompson 1335754ecacSJeremy L Thompson app_ctx->view_final_soln = PETSC_FALSE; 1342b730f8bSJeremy L Thompson PetscCall(PetscOptionsBool("-view_final_soln", "Write out final solution vector for viewing", NULL, app_ctx->view_final_soln, 1352b730f8bSJeremy L Thompson &(app_ctx->view_final_soln), NULL)); 1365754ecacSJeremy L Thompson 1375754ecacSJeremy L Thompson PetscBool set; 1385754ecacSJeremy L Thompson char energy_viewer_filename[PETSC_MAX_PATH_LEN] = ""; 1392b730f8bSJeremy L Thompson PetscCall(PetscOptionsString("-strain_energy_monitor", "Print out current strain energy at every load increment", NULL, energy_viewer_filename, 1402b730f8bSJeremy L Thompson energy_viewer_filename, sizeof(energy_viewer_filename), &set)); 1415754ecacSJeremy L Thompson if (set) { 1422b730f8bSJeremy L Thompson PetscCall(PetscViewerASCIIOpen(comm, energy_viewer_filename, &app_ctx->energy_viewer)); 1432b730f8bSJeremy L Thompson PetscCall(PetscViewerASCIIPrintf(app_ctx->energy_viewer, "increment,energy\n")); 144ea61e9acSJeremy L Thompson // Initial configuration is base energy state; this may not be true if we extend in the future to initially loaded configurations (because a truly 145ea61e9acSJeremy L Thompson // at-rest initial state may not be realizable). 1462b730f8bSJeremy L Thompson PetscCall(PetscViewerASCIIPrintf(app_ctx->energy_viewer, "%f,%e\n", 0., 0.)); 1475754ecacSJeremy L Thompson } 14867490bc6SJeremy L Thompson PetscOptionsEnd(); // End of setting AppCtx 1495754ecacSJeremy L Thompson 1505754ecacSJeremy L Thompson // Check for all required values set 1515754ecacSJeremy L Thompson if (app_ctx->test_mode) { 1522b730f8bSJeremy L Thompson if (app_ctx->forcing_choice == FORCE_NONE && !app_ctx->bc_clamp_count) app_ctx->forcing_choice = FORCE_MMS; 1535754ecacSJeremy L Thompson } 1545754ecacSJeremy L Thompson if (!app_ctx->bc_clamp_count && app_ctx->forcing_choice != FORCE_MMS) { 1555754ecacSJeremy L Thompson SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "-boundary options needed"); 1565754ecacSJeremy L Thompson } 1575754ecacSJeremy L Thompson 1585754ecacSJeremy L Thompson // Provide default ceed resource if not specified 1595754ecacSJeremy L Thompson if (!ceed_flag) { 1605754ecacSJeremy L Thompson const char *ceed_resource = "/cpu/self"; 1615754ecacSJeremy L Thompson strncpy(app_ctx->ceed_resource, ceed_resource, 10); 1625754ecacSJeremy L Thompson } 1635754ecacSJeremy L Thompson 1645754ecacSJeremy L Thompson // Determine number of levels 1655754ecacSJeremy L Thompson switch (app_ctx->multigrid_choice) { 1665754ecacSJeremy L Thompson case MULTIGRID_LOGARITHMIC: 1675754ecacSJeremy L Thompson app_ctx->num_levels = ceil(log(app_ctx->degree) / log(2)) + 1; 1685754ecacSJeremy L Thompson break; 1695754ecacSJeremy L Thompson case MULTIGRID_UNIFORM: 1705754ecacSJeremy L Thompson app_ctx->num_levels = app_ctx->degree; 1715754ecacSJeremy L Thompson break; 1725754ecacSJeremy L Thompson case MULTIGRID_NONE: 1735754ecacSJeremy L Thompson app_ctx->num_levels = 1; 1745754ecacSJeremy L Thompson break; 1755754ecacSJeremy L Thompson } 1765754ecacSJeremy L Thompson 1775754ecacSJeremy L Thompson // Populate array of degrees for each level for multigrid 1782b730f8bSJeremy L Thompson PetscCall(PetscMalloc1(app_ctx->num_levels, &(app_ctx->level_degrees))); 1795754ecacSJeremy L Thompson 1805754ecacSJeremy L Thompson switch (app_ctx->multigrid_choice) { 1815754ecacSJeremy L Thompson case MULTIGRID_LOGARITHMIC: 1822b730f8bSJeremy L Thompson for (int i = 0; i < app_ctx->num_levels - 1; i++) app_ctx->level_degrees[i] = pow(2, i); 1835754ecacSJeremy L Thompson app_ctx->level_degrees[app_ctx->num_levels - 1] = app_ctx->degree; 1845754ecacSJeremy L Thompson break; 1855754ecacSJeremy L Thompson case MULTIGRID_UNIFORM: 1862b730f8bSJeremy L Thompson for (int i = 0; i < app_ctx->num_levels; i++) app_ctx->level_degrees[i] = i + 1; 1875754ecacSJeremy L Thompson break; 1885754ecacSJeremy L Thompson case MULTIGRID_NONE: 1895754ecacSJeremy L Thompson app_ctx->level_degrees[0] = app_ctx->degree; 1905754ecacSJeremy L Thompson break; 1915754ecacSJeremy L Thompson } 1925754ecacSJeremy L Thompson 193*ee4ca9cbSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1945754ecacSJeremy L Thompson }; 195