-
Notifications
You must be signed in to change notification settings - Fork 34
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
Add adjoint load for the case of adjoints associated with resultant/dual forces. #1238
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
7cfdb16
Add adjoint load for the case of adjoints associated with resultant/d…
tupek2 a5d237b
Apply style updates
296166c
Add test that combined reaction and displacement adjoint gives correc…
tupek2 e0cf1f8
Remove exactnes test which is no longer appropriate.
tupek2 2126672
Apply style updates
06d2f03
Significantly simplify dual adjoint calculations.
tupek2 55c2b8a
Simplify reaction adjoint implementation even more.
tupek2 ab4ea41
Even more simplification of reaction adjoint loads, rename to setDual…
tupek2 d97afa9
Addition cleanup, reset sparse matrices to avoid highwater memory.
tupek2 a43765c
Test that reaction forces in qois are working when nonlinear and tran…
tupek2 396d791
Apply style updates
8efdcec
Small naming fix.
tupek2 6ed26e9
Fix docs.
tupek2 1a67141
Apply style updates
a8beeb6
Merge branch 'develop' into tupek/reaction_sensitivities
tupek2 9e6fc06
Merge branch 'develop' into tupek/reaction_sensitivities
tupek2 72c4868
Merge branch 'develop' into tupek/reaction_sensitivities
tupek2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -182,7 +182,7 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
implicit_sensitivity_displacement_start_of_step_(displacement_.space(), "total_deriv_wrt_displacement."), | ||
implicit_sensitivity_velocity_start_of_step_(displacement_.space(), "total_deriv_wrt_velocity."), | ||
reactions_(StateManager::newDual(H1<order, dim>{}, detail::addPrefix(physics_name, "reactions"), mesh_tag_)), | ||
reactions_adjoint_load_(reactions_.space(), "reactions_shape_sensitivity"), | ||
reactions_adjoint_bcs_(reactions_.space(), "reactions_shape_sensitivity"), | ||
nonlin_solver_(std::move(solver)), | ||
ode2_(displacement_.space().TrueVSize(), | ||
{.time = time_, .c0 = c0_, .c1 = c1_, .u = u_, .du_dt = v_, .d2u_dt2 = acceleration_}, *nonlin_solver_, | ||
|
@@ -216,7 +216,7 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
|
||
adjoints_.push_back(&adjoint_displacement_); | ||
duals_.push_back(&reactions_); | ||
dual_adjoints_.push_back(&reactions_adjoint_load_); | ||
dual_adjoints_.push_back(&reactions_adjoint_bcs_); | ||
|
||
// Create a pack of the primal field and parameter finite element spaces | ||
mfem::ParFiniteElementSpace* test_space = &displacement_.space(); | ||
|
@@ -385,7 +385,8 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
implicit_sensitivity_displacement_start_of_step_ = 0.0; | ||
implicit_sensitivity_velocity_start_of_step_ = 0.0; | ||
|
||
reactions_ = 0.0; | ||
reactions_ = 0.0; | ||
reactions_adjoint_bcs_ = 0.0; | ||
|
||
u_ = 0.0; | ||
v_ = 0.0; | ||
|
@@ -753,15 +754,40 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
} | ||
|
||
/// @overload | ||
const FiniteElementDual& dualAdjoint(const std::string& dual_name) const override | ||
const FiniteElementState& dualAdjoint(const std::string& dual_name) const override | ||
{ | ||
if (dual_name == "reactions") { | ||
return reactions_adjoint_load_; | ||
return reactions_adjoint_bcs_; | ||
} | ||
|
||
SLIC_ERROR_ROOT(axom::fmt::format( | ||
"dualAdjoint '{}' requested from solid mechanics module '{}', but it doesn't exist", dual_name, name_)); | ||
return reactions_adjoint_load_; | ||
return reactions_adjoint_bcs_; | ||
} | ||
|
||
/// @overload | ||
FiniteElementDual loadCheckpointedDual(const std::string& dual_name, int cycle) const override | ||
{ | ||
if (dual_name == "reactions") { | ||
auto checkpointed_sol = getCheckpointedStates(cycle); | ||
|
||
FiniteElementDual reactions(reactions_.space(), "reactions_tmp"); | ||
|
||
if (is_quasistatic_) { | ||
reactions = (*residual_)(time_, shape_displacement_, checkpointed_sol.at("displacement"), acceleration_, | ||
*parameters_[parameter_indices].state...); | ||
} else { | ||
reactions = (*residual_)(time_, shape_displacement_, checkpointed_sol.at("displacement"), | ||
checkpointed_sol.at("acceleration"), *parameters_[parameter_indices].state...); | ||
} | ||
|
||
return reactions; | ||
} | ||
|
||
SLIC_ERROR_ROOT( | ||
axom::fmt::format("loadCheckpointedDual '{}' requested from solid mechanics module '{}', but it doesn't exist", | ||
dual_name, name_)); | ||
return reactions_; | ||
} | ||
|
||
/** | ||
|
@@ -1134,8 +1160,10 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
SERAC_MARK_FUNCTION; | ||
auto [r, drdu] = (*residual_)(time_, shape_displacement_, differentiate_wrt(u), acceleration_, | ||
*parameters_[parameter_indices].state...); | ||
J_ = assemble(drdu); | ||
J_e_ = bcs_.eliminateAllEssentialDofsFromMatrix(*J_); | ||
J_.reset(); | ||
J_ = assemble(drdu); | ||
J_e_.reset(); | ||
J_e_ = bcs_.eliminateAllEssentialDofsFromMatrix(*J_); | ||
return *J_; | ||
}); | ||
} | ||
|
@@ -1201,7 +1229,9 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
std::unique_ptr<mfem::HypreParMatrix> m_mat(assemble(M)); | ||
|
||
// J = M + c0 * K | ||
J_.reset(); | ||
J_.reset(mfem::Add(1.0, *m_mat, c0_, *k_mat)); | ||
J_e_.reset(); | ||
J_e_ = bcs_.eliminateAllEssentialDofsFromMatrix(*J_); | ||
|
||
return *J_; | ||
|
@@ -1316,9 +1346,11 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
|
||
SLIC_ERROR_ROOT_IF(disp_adjoint_load == loads.end(), "Adjoint load for \"displacement\" not found."); | ||
|
||
displacement_adjoint_load_ = disp_adjoint_load->second; | ||
// Add the sign correction to move the term to the RHS | ||
displacement_adjoint_load_ *= -1.0; | ||
if (disp_adjoint_load != loads.end()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check and the |
||
displacement_adjoint_load_ = disp_adjoint_load->second; | ||
// Add the sign correction to move the term to the RHS | ||
displacement_adjoint_load_ *= -1.0; | ||
} | ||
|
||
auto velo_adjoint_load = loads.find("velocity"); | ||
|
||
|
@@ -1337,15 +1369,24 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
} | ||
} | ||
|
||
virtual void setDualAdjointBcs(std::unordered_map<std::string, const serac::FiniteElementState&> bcs) override | ||
{ | ||
SLIC_ERROR_ROOT_IF(bcs.size() == 0, "Adjoint load container size must be greater than 0 in the solid mechanics."); | ||
|
||
auto reaction_adjoint_load = bcs.find("reactions"); | ||
|
||
SLIC_ERROR_ROOT_IF(reaction_adjoint_load == bcs.end(), "Adjoint load for \"reaction\" not found."); | ||
|
||
if (reaction_adjoint_load != bcs.end()) { | ||
reactions_adjoint_bcs_ = reaction_adjoint_load->second; | ||
} | ||
} | ||
|
||
/// @overload | ||
void reverseAdjointTimestep() override | ||
{ | ||
auto& lin_solver = nonlin_solver_->linearSolver(); | ||
|
||
// By default, use a homogeneous essential boundary condition | ||
mfem::HypreParVector adjoint_essential(displacement_adjoint_load_); | ||
adjoint_essential = 0.0; | ||
|
||
SLIC_ERROR_ROOT_IF(cycle_ <= min_cycle_, | ||
"Maximum number of adjoint timesteps exceeded! The number of adjoint timesteps must equal the " | ||
"number of forward timesteps"); | ||
|
@@ -1361,11 +1402,20 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
if (is_quasistatic_) { | ||
auto [_, drdu] = (*residual_)(time_, shape_displacement_, differentiate_wrt(displacement_), acceleration_, | ||
*parameters_[parameter_indices].state...); | ||
auto jacobian = assemble(drdu); | ||
auto J_T = std::unique_ptr<mfem::HypreParMatrix>(jacobian->Transpose()); | ||
J_.reset(); | ||
J_ = assemble(drdu); | ||
|
||
auto J_T = std::unique_ptr<mfem::HypreParMatrix>(J_->Transpose()); | ||
|
||
J_e_.reset(); | ||
J_e_ = bcs_.eliminateAllEssentialDofsFromMatrix(*J_T); | ||
|
||
auto& constrained_dofs = bcs_.allEssentialTrueDofs(); | ||
|
||
for (const auto& bc : bcs_.essentials()) { | ||
bc.apply(*J_T, displacement_adjoint_load_, adjoint_essential); | ||
mfem::EliminateBC(*J_T, *J_e_, constrained_dofs, reactions_adjoint_bcs_, displacement_adjoint_load_); | ||
for (int i = 0; i < constrained_dofs.Size(); i++) { | ||
int j = constrained_dofs[i]; | ||
displacement_adjoint_load_[j] = reactions_adjoint_bcs_[j]; | ||
} | ||
|
||
lin_solver.SetOperator(*J_T); | ||
|
@@ -1396,7 +1446,7 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
solid_mechanics::detail::adjoint_integrate( | ||
dt_n_to_np1, dt_np1_to_np2, m_mat.get(), k_mat.get(), displacement_adjoint_load_, velocity_adjoint_load_, | ||
acceleration_adjoint_load_, adjoint_displacement_, implicit_sensitivity_displacement_start_of_step_, | ||
implicit_sensitivity_velocity_start_of_step_, adjoint_essential, bcs_, lin_solver); | ||
implicit_sensitivity_velocity_start_of_step_, reactions_adjoint_bcs_, bcs_, lin_solver); | ||
} | ||
|
||
time_end_step_ = time_; | ||
|
@@ -1462,47 +1512,6 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
/// @brief getter for nodal forces (before zeroing-out essential dofs) | ||
const serac::FiniteElementDual& reactions() const { return reactions_; }; | ||
|
||
/// @overload | ||
void computeDualAdjointLoad(const std::string& dual_name, | ||
const serac::FiniteElementState& reaction_direction) override | ||
{ | ||
SLIC_ERROR_ROOT_IF(dual_name != "reactions", "Solid mechanics has reactions as its only dual"); | ||
|
||
auto [_, drdu] = (*residual_)(time_, shape_displacement_, differentiate_wrt(displacement_), acceleration_, | ||
*parameters_[parameter_indices].state...); | ||
std::unique_ptr<mfem::HypreParMatrix> jacobian = assemble(drdu); | ||
reactions_adjoint_load_ = 0.0; | ||
jacobian->MultTranspose(reaction_direction, reactions_adjoint_load_); | ||
setAdjointLoad({{"displacement", reactions_adjoint_load_}}); | ||
} | ||
|
||
/// @overload | ||
const serac::FiniteElementDual& computeDualSensitivity(const serac::FiniteElementState& reaction_direction, | ||
size_t parameter_field) override | ||
{ | ||
SLIC_ASSERT_MSG(parameter_field < sizeof...(parameter_indices), | ||
axom::fmt::format("Invalid parameter index '{}' requested for reaction sensitivity.")); | ||
|
||
auto drdparam = serac::get<DERIVATIVE>(d_residual_d_[parameter_field](time_end_step_)); | ||
auto drdparam_mat = assemble(drdparam); | ||
|
||
drdparam_mat->MultTranspose(reaction_direction, *parameters_[parameter_field].sensitivity); | ||
|
||
return *parameters_[parameter_field].sensitivity; | ||
}; | ||
|
||
/// @overload | ||
const serac::FiniteElementDual& computeDualShapeSensitivity( | ||
const serac::FiniteElementState& reaction_direction) override | ||
{ | ||
auto drdshape = | ||
serac::get<DERIVATIVE>((*residual_)(time_end_step_, differentiate_wrt(shape_displacement_), displacement_, | ||
acceleration_, *parameters_[parameter_indices].state...)); | ||
auto drdshape_mat = assemble(drdshape); | ||
drdshape_mat->MultTranspose(reaction_direction, *shape_displacement_sensitivity_); | ||
return *shape_displacement_sensitivity_; | ||
}; | ||
|
||
protected: | ||
/// The compile-time finite element trial space for displacement and velocity (H1 of order p) | ||
using trial = H1<order, dim>; | ||
|
@@ -1546,7 +1555,7 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
FiniteElementDual reactions_; | ||
|
||
/// sensitivity of qoi with respect to reaction forces | ||
FiniteElementDual reactions_adjoint_load_; | ||
FiniteElementState reactions_adjoint_bcs_; | ||
|
||
/// serac::Functional that is used to calculate the residual and its derivatives | ||
std::unique_ptr<ShapeAwareFunctional<shape_trial, test(trial, trial, parameter_space...)>> residual_; | ||
|
@@ -1748,8 +1757,10 @@ class SolidMechanics<order, dim, Parameters<parameter_space...>, std::integer_se | |
// use the most recently evaluated Jacobian | ||
auto [_, drdu] = (*residual_)(time_, shape_displacement_, differentiate_wrt(displacement_), acceleration_, | ||
*parameters_[parameter_indices].previous_state...); | ||
J_ = assemble(drdu); | ||
J_e_ = bcs_.eliminateAllEssentialDofsFromMatrix(*J_); | ||
J_.reset(); | ||
J_ = assemble(drdu); | ||
J_e_.reset(); | ||
J_e_ = bcs_.eliminateAllEssentialDofsFromMatrix(*J_); | ||
|
||
r *= -1.0; | ||
|
||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 fixing a bug? Because the heat transfer module still does it the old way. If so, can you open an issue?