-
Notifications
You must be signed in to change notification settings - Fork 34
Gretl solid mechanics #1501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Gretl solid mechanics #1501
Conversation
…ction abstraction.
| /// adjoint solves | ||
| class LinearDifferentiableSolver : public DifferentiableSolver { | ||
| public: | ||
| /// @brief Construct from a linear solver and linear precondition which may be used by the linear solver |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sentence needs more linear!
| nonlinear_solver_; ///< the nonlinear equation solver used for the forward pass | ||
| }; | ||
|
|
||
| /// @brief Abstract interface to DifferentiableBlockSolver inteface. Each dfferenriable block solve should provide |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// @brief Abstract interface to DifferentiableBlockSolver inteface. Each dfferenriable block solve should provide | |
| /// @brief Abstract interface to DifferentiableBlockSolver interface. Each differentiable block solve should provide |
| using DualPtr = std::shared_ptr<FieldD>; ///< using | ||
| using MatrixPtr = std::unique_ptr<mfem::HypreParMatrix>; ///< using | ||
|
|
||
| /// @brief required for certain solvers/preconditions, e.g. when multigrid algorithms want a near null-space |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// @brief required for certain solvers/preconditions, e.g. when multigrid algorithms want a near null-space | |
| /// @brief Required for certain solvers/preconditions, e.g. when multigrid algorithms want a near null-space |
| { | ||
| } | ||
|
|
||
| } // namespace smith No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } // namespace smith | |
| } // namespace smith | |
I know this is your favorite thing i nitpick....
| DirichletBoundaryConditions(const Mesh& mesh, mfem::ParFiniteElementSpace& space); | ||
|
|
||
| /// @brief Specify time and space varying Dirichlet boundary conditions over a domain. | ||
| /// @param domain domain All dofs in this domain have boundary conditions applied to it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// @param domain domain All dofs in this domain have boundary conditions applied to it. | |
| /// @param domain All dofs in this domain have boundary conditions applied to it. |
pretty sure thats not supposed to be there.
| } | ||
|
|
||
| /// @brief Specify time and space varying Dirichlet boundary conditions over a domain. | ||
| /// @param domain domain All dofs in this domain have boundary conditions applied to it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// @param domain domain All dofs in this domain have boundary conditions applied to it. | |
| /// @param domain All dofs in this domain have boundary conditions applied to it. |
| mfem::ParFiniteElementSpace& space_; ///< save the space for the field which will be constrained | ||
| }; | ||
|
|
||
| } // namespace smith No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } // namespace smith | |
| } // namespace smith | |
| /// @brief initialize on the gretl::DataStore a ResultantState with values from s | ||
| inline ResultantState create_field_resultant(gretl::DataStore& dataStore, const smith::FEDualPtr& s) | ||
| /// @brief initialize on the gretl::DataStore a ReactionState with values from s | ||
| inline ReactionState create_reaction_state(gretl::DataStore& dataStore, const smith::FEDualPtr& s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As much as i like pot-hole case, Smith does camel case.
| @@ -0,0 +1,574 @@ | |||
| #include "smith/physics/weak_form.hpp" | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| #include "smith/physics/weak_form.hpp" | |
| // Copyright (c) Lawrence Livermore National Security, LLC and | |
| // other Smith Project Developers. See the top-level LICENSE file for | |
| // details. | |
| // | |
| // SPDX-License-Identifier: (BSD-3-Clause) | |
| #include "smith/physics/weak_form.hpp" |
|
|
||
| auto eval_residuals = [=](const std::vector<FEFieldPtr>& unknowns) { | ||
| SLIC_ERROR_IF(unknowns.size() != num_rows, | ||
| "block solver unknown size must match the number or residuals in block_solve"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "block solver unknown size must match the number or residuals in block_solve"); | |
| "block solver unknowns size must match the number or residuals in block_solve"); |
.. i think...
| @@ -0,0 +1,66 @@ | |||
| // Copyright (c) 2019-2024, Lawrence Livermore National Security, LLC and | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Copyright (c) 2019-2024, Lawrence Livermore National Security, LLC and | |
| // Copyright (c) Lawrence Livermore National Security, LLC and |
| @@ -0,0 +1,89 @@ | |||
| // Copyright (c), Lawrence Livermore National Security, LLC and | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Copyright (c), Lawrence Livermore National Security, LLC and | |
| // Copyright (c) Lawrence Livermore National Security, LLC and |
|
|
||
| /// @brief gretl-function implementation which evaluates the residual force (which is minus the mechanical force) | ||
| /// given | ||
| /// shape displacement, states and params. The field_for_residual_space Field is only used to set the approriate size |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// shape displacement, states and params. The field_for_residual_space Field is only used to set the approriate size | |
| /// shape displacement, states and params. The field_for_residual_space Field is only used to set the appropriate size |
| FEDualPtr R = std::make_shared<FiniteElementDual>(field_for_residual_space_->space(), | ||
| "residual"); // set up output pointer | ||
| // evaluate the residual with zero acceleration contribution | ||
| // std::cout << "time info = " << time_info.time() << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete dead code... does this comment go with the dead code or line below?
| @@ -0,0 +1,62 @@ | |||
| #include "smith/physics/weak_form.hpp" | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| #include "smith/physics/weak_form.hpp" | |
| // Copyright (c) Lawrence Livermore National Security, LLC and | |
| // other Smith Project Developers. See the top-level LICENSE file for | |
| // details. | |
| // | |
| // SPDX-License-Identifier: (BSD-3-Clause) | |
| #include "smith/physics/weak_form.hpp" |
| @@ -0,0 +1,118 @@ | |||
| // Copyright (c) 2019-2024, Lawrence Livermore National Security, LLC and | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Copyright (c) 2019-2024, Lawrence Livermore National Security, LLC and | |
| // Copyright (c) Lawrence Livermore National Security, LLC and |
| * @file solid_mechanics_state_advancer.hpp | ||
| * .hpp | ||
| * | ||
| * @brief Specifies parametrized residuals and various linearized evaluations for arbitrary nonlinear systems of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * @brief Specifies parametrized residuals and various linearized evaluations for arbitrary nonlinear systems of | |
| * @brief Specifies parameterized residuals and various linearized evaluations for arbitrary nonlinear systems of |
| } | ||
|
|
||
| /// @brief Utility function to consistently construct all the weak forms and FieldStates for a solid mechanics | ||
| /// application You will get back: shape_disp, states, params, time, and solid_mechanics_weak_form |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// application You will get back: shape_disp, states, params, time, and solid_mechanics_weak_form | |
| /// application you will get back: shape_disp, states, params, time, and solid_mechanics_weak_form |
| @@ -0,0 +1,154 @@ | |||
| // Copyright (c) 2019-2024, Lawrence Livermore National Security, LLC and | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Copyright (c) 2019-2024, Lawrence Livermore National Security, LLC and | |
| // Copyright (c) Lawrence Livermore National Security, LLC and |
| [[maybe_unused]] const T4& accel_old) const | ||
| { | ||
| return (2.0 / t.dt()) * (field_new - field_old) - velo_old; | ||
| // if (method_ == SecondOrderTimeIntegrationMethod::IMPLICIT_NEWMARK) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dead code?
| { | ||
| auto dt = t.dt(); | ||
| return (4.0 / (dt * dt)) * (field_new - field_old) - (4.0 / dt) * velo_old - accel_old; | ||
| // auto accel = (4.0 / (dt * dt)) * (field_new - field_old) - (4.0 / dt) * velo_old - accel_old; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More
| size_t cycle() const { return cycle_; } | ||
|
|
||
| /// @brief return the time info corresponding to the end of this cycle (time + dt, dt, cycle) | ||
| TimeInfo end_time_info() const { return TimeInfo(time() + dt(), dt(), cycle()); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong case
|
The moving of |
| SLIC_ERROR_IF( | ||
| reaction_name_to_reaction_index_.find(dual_name) == reaction_name_to_reaction_index_.end(), | ||
| axom::fmt::format("Could not find dual named {0} in mesh with tag \"{1}\" to get", dual_name, mesh_->tag())); | ||
| size_t reaction_index = reaction_name_to_reaction_index_.at(dual_name); | ||
| SLIC_ERROR_IF( | ||
| reaction_index >= reaction_names_.size(), | ||
| "Dual reactions not correctly allocated yet, cannot get dual until after initializationStep is called."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second error check appears unnecessary to me: the constructor generates the indices in 1:1 correspondence with the names. Also, I don't see a method called initializationStep in this class or the base class. The first error check is not strictly needed either, since the at method raises an exception if the key is not found.
More generally, I prefer having the data validity checking on the data structure itself to keep these kinds of checks from being duplicated at every use.
| SLIC_ERROR_IF(state_name_to_field_index_.find(field_name) == state_name_to_field_index_.end(), | ||
| axom::fmt::format("Could not find dual named {0} in mesh with tag {1}", field_name, mesh_->tag())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the error check duplication I was referring to. There are several more.
| /// @brief destructor | ||
| virtual ~DifferentiableSolver() {} | ||
|
|
||
| /// @brief required for certain solvers/preconditions, e.g. when multigrid algorithms want a near null-space |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| /// @brief required for certain solvers/preconditions, e.g. when multigrid algorithms want a near null-space | |
| /// @brief required for certain solvers/preconditioners, e.g. when multigrid algorithms want a near null-space |
| // there should be one less input state, as the higher time derivative term (e.g., acceleration), does not have a | ||
| // predictor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this comment up to date? The check below ensures things have the same size, not "one less" as the comment states. If the comment is correct, then I don't understand what it's trying to say. Can you rephrase?
| std::function<std::unique_ptr<mfem::HypreParMatrix>(const smith::FiniteElementState&)> jacobian) const override; | ||
|
|
||
| /// @overload | ||
| std::shared_ptr<smith::FiniteElementState> solveAdjoint( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is not a point requiring changes in the PR, just a conversation I want to start while it's in mind: Now that we have an abstraction for a solver and adjoint solver, it could be a natural way to remove the memory-intensive copy of the sparse jacobian (for the sparse jacobian transpose). The solveAdjoint method could take the jacobian and use TransposeOperator or something similar to get the action of the transpose. We've been noting and complaining about this memory usage for a while. Should I open an issue or this for follow-up?
I like the idea of an abstraction like adjointSolve taking the responsibility of transposing (instead of putting it on the caller), since that's the main difference from the solve method.
| /// smith::tensor<double,spatial_dim> corresponding to the spatial coordinate. The functor must return a double. For | ||
| /// example: [](double t, smith::tensor<double, dim> X) { return 1.0; } | ||
| template <int spatial_dim, typename AppliedDisplacementFunction> | ||
| void setScalarBCs(const Domain& domain, int component, AppliedDisplacementFunction applied_displacement) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it confusing to have a method named setScalarBCs take an argument for a component. In my view, this is an overload for setVectorBCs for the special case of setting one component, saving the typing of { and } characters around the index.
| { | ||
| int field_dim = space_.GetVDim(); | ||
| for (auto component : components) { | ||
| SLIC_ERROR_IF(component >= field_dim, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should probably also check if component < 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's great that this is factored out for all the physics modules! 👍
| DoubleState evaluateObjective(const ScalarObjective& objective, const FieldState& shape_disp, | ||
| const std::vector<FieldState>& inputs, const TimeInfo& time_info) | ||
| { | ||
| const ScalarObjective* objective_ptr = &objective; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the indirection? You can't capture objective by reference in the lambdas? I'm not worried about overhead, just trying to clear up my understanding of gretl.
| for (auto& p : params) allFields.push_back(p); | ||
| allFields.push_back(shape_disp); | ||
|
|
||
| bool have_bc_field = bc_field; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought: in the case where BCs are done the classic way, could you use the bc_manager to populate bc_field? Then the code would be unified, no conditionals for have_bc_field.
|
Sorry! wrong button! |
| } | ||
| setVectorBCs<spatial_dim>(domain, components, applied_displacement); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For adding dirichlet bc on all components, should we use
bcs_.addEssential(bc_set, coefficient, space)?
| auto constrained_dofs = bc_manager->allEssentialTrueDofs(); | ||
| if (bc_field_ptr) { | ||
| for (int i = 0; i < constrained_dofs.Size(); i++) { | ||
| int j = constrained_dofs[i]; | ||
| (*primal_field)[j] = (*bc_field_ptr)(j); | ||
| } | ||
| } else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| auto constrained_dofs = bc_manager->allEssentialTrueDofs(); | |
| if (bc_field_ptr) { | |
| for (int i = 0; i < constrained_dofs.Size(); i++) { | |
| int j = constrained_dofs[i]; | |
| (*primal_field)[j] = (*bc_field_ptr)(j); | |
| } | |
| } else { | |
| if (bc_field_ptr) { | |
| auto constrained_dofs = bc_manager->allEssentialTrueDofs(); | |
| for (int i = 0; i < constrained_dofs.Size(); i++) { | |
| int j = constrained_dofs[i]; | |
| (*primal_field)[j] = (*bc_field_ptr)(j); | |
| } | |
| } else { |
| } | ||
| } | ||
|
|
||
| TEST_F(SolidMechanicsMeshFixture, SensitivitiesBasePhysics) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be an example instead?
Add implicit (differentiable) linear and nonlinear solvers. Add time discretization for second order systems. Add the ability to compute resultant forces. Dynamic patch test and design sensitivity tests are included.