xref: /libCEED/examples/solids/src/cl-options.c (revision ee4ca9cbfe2be39196684117442f3ce8d00b6506)
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