7 #include "smith/differentiable_numerics/multiphysics_time_integrator.hpp"
10 #include "smith/differentiable_numerics/coupled_system_solver.hpp"
20 const std::vector<std::shared_ptr<WeakForm>>& weak_forms,
21 std::shared_ptr<smith::CoupledSystemSolver> solver,
22 std::shared_ptr<WeakForm> cycle_zero_weak_form,
23 std::shared_ptr<smith::CoupledSystemSolver> cycle_zero_solver)
24 : field_store_(field_store),
25 weak_forms_(weak_forms),
27 cycle_zero_weak_form_(cycle_zero_weak_form),
28 cycle_zero_solver_(cycle_zero_solver)
33 const TimeInfo& time_info,
const FieldState& shape_disp,
const std::vector<FieldState>& states,
34 const std::vector<FieldState>& params)
const
36 std::vector<FieldState> current_states = states;
39 const bool requires_cycle_zero_solve =
40 std::any_of(field_store_->getTimeIntegrationRules().begin(), field_store_->getTimeIntegrationRules().end(),
41 [](
const auto& rule_and_mapping) {
42 return rule_and_mapping.first && rule_and_mapping.first->requiresInitialAccelerationSolve();
44 if (time_info.
cycle() == 0 && cycle_zero_weak_form_ && requires_cycle_zero_solve) {
45 for (
size_t i = 0; i < current_states.size(); ++i) {
46 field_store_->setField(i, current_states[i]);
49 std::string test_field_name = field_store_->getWeakFormReaction(cycle_zero_weak_form_->name());
50 std::vector<FieldState> wf_fields = field_store_->getStates(cycle_zero_weak_form_->name());
52 FieldState test_field = field_store_->getField(test_field_name);
53 size_t test_field_idx_in_wf = invalid_block_index;
54 for (
size_t j = 0; j < wf_fields.size(); ++j) {
55 if (wf_fields[j].
get() == test_field.get()) {
56 test_field_idx_in_wf = j;
60 SLIC_ERROR_IF(test_field_idx_in_wf == invalid_block_index,
"Test field '" << test_field_name
61 <<
"' not found in cycle-zero weak form '"
62 << cycle_zero_weak_form_->name() <<
"'");
64 std::vector<WeakForm*> wf_ptrs = {cycle_zero_weak_form_.get()};
65 std::vector<std::vector<size_t>> block_indices = {{test_field_idx_in_wf}};
67 std::vector<const BoundaryConditionManager*> bcs;
68 auto all_bcs = field_store_->getBoundaryConditionManagers();
69 size_t test_field_unknown_idx = invalid_block_index;
71 test_field_unknown_idx = field_store_->getUnknownIndex(test_field_name);
72 }
catch (
const std::out_of_range&) {
73 for (
const auto& [rule, mapping] : field_store_->getTimeIntegrationRules()) {
74 static_cast<void>(rule);
75 if (mapping.primary_name == test_field_name || mapping.history_name == test_field_name ||
76 mapping.dot_name == test_field_name || mapping.ddot_name == test_field_name) {
77 test_field_unknown_idx = field_store_->getUnknownIndex(mapping.primary_name);
82 SLIC_ERROR_IF(test_field_unknown_idx == invalid_block_index,
83 "Could not map cycle-zero test field '" << test_field_name <<
"' to an independent unknown.");
84 SLIC_ERROR_IF(test_field_unknown_idx >= all_bcs.size(),
85 "Cycle-zero test field '" << test_field_name <<
"' has unknown index " << test_field_unknown_idx
86 <<
", but only " << all_bcs.size() <<
" BC managers are registered.");
87 bcs.push_back(all_bcs[test_field_unknown_idx]);
89 std::vector<std::vector<FieldState>> states_vec = {wf_fields};
90 std::vector<std::vector<FieldState>> params_vec = {params};
92 auto& cz_solver = cycle_zero_solver_ ? cycle_zero_solver_ : solver_;
93 auto result = cz_solver->solve(wf_ptrs, block_indices, shape_disp, states_vec, params_vec, time_info, bcs);
95 size_t test_field_state_idx = field_store_->getFieldIndex(test_field_name);
96 current_states[test_field_state_idx] = result[0];
100 for (
size_t i = 0; i < current_states.size(); ++i) {
101 field_store_->setField(i, current_states[i]);
104 std::vector<FieldState> primary_unknowns =
solve(weak_forms_, *field_store_, solver_.get(), time_info, params);
107 std::vector<FieldState> states_for_reactions = current_states;
108 for (
const auto& [rule, mapping] : field_store_->getTimeIntegrationRules()) {
109 size_t u_idx = field_store_->getFieldIndex(mapping.primary_name);
110 size_t unknown_idx = field_store_->getUnknownIndex(mapping.primary_name);
111 FieldState u_new = primary_unknowns[unknown_idx];
112 states_for_reactions[u_idx] = u_new;
116 std::vector<ReactionState> reactions;
117 for (
const auto& wf : weak_forms_) {
118 std::vector<FieldState> wf_fields = field_store_->getStatesFromVectors(wf->name(), states_for_reactions, params);
119 std::string test_field_name = field_store_->getWeakFormReaction(wf->name());
120 size_t test_field_idx = field_store_->getFieldIndex(test_field_name);
121 FieldState test_field = states_for_reactions[test_field_idx];
126 const auto& all_current_states = field_store_->getAllFields();
127 std::vector<FieldState> new_states = current_states;
128 for (
size_t i = 0; i < current_states.size(); ++i) {
129 new_states[i] = all_current_states[i];
132 for (
const auto& [rule, mapping] : field_store_->getTimeIntegrationRules()) {
133 size_t u_idx = field_store_->getFieldIndex(mapping.primary_name);
134 size_t unknown_idx = field_store_->getUnknownIndex(mapping.primary_name);
135 FieldState u_new = primary_unknowns[unknown_idx];
136 new_states[u_idx] = u_new;
138 std::vector<FieldState> rule_inputs;
139 rule_inputs.push_back(u_new);
140 if (rule->num_args() >= 2) {
141 rule_inputs.push_back(current_states[u_idx]);
144 if (rule->num_args() >= 3 && !mapping.dot_name.empty()) {
145 size_t v_idx = field_store_->getFieldIndex(mapping.dot_name);
146 rule_inputs.push_back(current_states[v_idx]);
149 if (rule->num_args() >= 4 && !mapping.ddot_name.empty()) {
150 size_t a_idx = field_store_->getFieldIndex(mapping.ddot_name);
151 rule_inputs.push_back(current_states[a_idx]);
154 if (!mapping.dot_name.empty()) {
155 size_t v_idx = field_store_->getFieldIndex(mapping.dot_name);
156 new_states[v_idx] = rule->corrected_dot(time_info, rule_inputs);
159 if (!mapping.ddot_name.empty()) {
160 size_t a_idx = field_store_->getFieldIndex(mapping.ddot_name);
161 new_states[a_idx] = rule->corrected_ddot(time_info, rule_inputs);
164 if (!mapping.history_name.empty()) {
165 size_t hist_idx = field_store_->getFieldIndex(mapping.history_name);
166 new_states[hist_idx] = u_new;
170 return {new_states, reactions};
173 std::vector<FieldState>
solve(
const std::vector<std::shared_ptr<WeakForm>>& weak_forms,
const FieldStore& field_store,
175 const std::vector<FieldState>& params)
177 std::vector<std::string> weak_form_names;
178 for (
const auto& wf : weak_forms) {
179 weak_form_names.push_back(wf->name());
181 std::vector<std::vector<size_t>> index_map = field_store.
indexMap(weak_form_names);
183 std::vector<std::vector<FieldState>> inputs;
184 for (
size_t i = 0; i < weak_forms.size(); ++i) {
185 std::string wf_name = weak_forms[i]->name();
186 std::vector<FieldState> fields_for_wk = field_store.
getStates(wf_name);
187 inputs.push_back(fields_for_wk);
189 std::vector<std::vector<FieldState>> wk_params(weak_forms.size(), params);
191 std::vector<WeakForm*> weak_form_ptrs;
192 for (
auto& p : weak_forms) {
193 weak_form_ptrs.push_back(p.get());
195 return solver->
solve(weak_form_ptrs, index_map, field_store.
getShapeDisp(), inputs, wk_params, time_info,
Orchestrates staggered solution for multiphysics systems.
std::vector< FieldState > solve(const std::vector< WeakForm * > &residual_evals, const std::vector< std::vector< size_t >> &block_indices, const FieldState &shape_disp, const std::vector< std::vector< FieldState >> &states, const std::vector< std::vector< FieldState >> ¶ms, const TimeInfo &time_info, const std::vector< const BoundaryConditionManager * > &bc_managers) const
Solves the multiphysics system using staggered iterations.
std::pair< std::vector< FieldState >, std::vector< ReactionState > > advanceState(const TimeInfo &time_info, const FieldState &shape_disp, const std::vector< FieldState > &states, const std::vector< FieldState > ¶ms) const override
Advance the multiphysics state by one time step.
MultiphysicsTimeIntegrator(std::shared_ptr< FieldStore > field_store, const std::vector< std::shared_ptr< WeakForm >> &weak_forms, std::shared_ptr< smith::CoupledSystemSolver > solver, std::shared_ptr< WeakForm > cycle_zero_weak_form=nullptr, std::shared_ptr< smith::CoupledSystemSolver > cycle_zero_solver=nullptr)
Construct a new MultiphysicsTimeIntegrator object.
Contains DirichletBoundaryConditions class for interaction with the differentiable solve interfaces.
Accelerator functionality.
constexpr T & get(variant< T0, T1 > &v)
Returns the variant member of specified type.
auto evaluateWeakForm(const std::shared_ptr< WeakForm > &weak_form, const TimeInfo &time_info, FieldState shape_disp, const std::vector< FieldState > &field_states, FieldState field_for_residual_space)
gretl-function implementation which evaluates the residual force (which is minus the mechanical force...
gretl::State< FEFieldPtr, FEDualPtr > FieldState
typedef
std::vector< FieldState > solve(const std::vector< std::shared_ptr< WeakForm >> &weak_forms, const FieldStore &field_store, const CoupledSystemSolver *solver, const TimeInfo &time_info, const std::vector< FieldState > ¶ms)
Solve a set of weak forms.
This file contains nonlinear block solver interfaces and helpers.
Methods for solving systems of equations as given by WeakForms. Tracks these operations on the gretl ...
Reaction class which is a names combination of a weak form and a set of dirichlet constrained nodes.
Manages storage and metadata for fields, parameters, and weak forms.
std::vector< std::vector< size_t > > indexMap(const std::vector< std::string > &residual_names) const
Generate an index map for the residuals.
std::vector< const BoundaryConditionManager * > getBoundaryConditionManagers() const
Get the boundary condition managers for all independent fields.
std::vector< FieldState > getStates(const std::string &weak_form_name) const
Get the state fields associated with a weak form.
FieldState getShapeDisp() const
Get the shape displacement field.
struct storing time and timestep information
size_t cycle() const
accessor for cycle