Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
thermal_system.hpp
Go to the documentation of this file.
1 // Copyright (c) Lawrence Livermore National Security, LLC and
2 // other Smith Project Developers. See the top-level LICENSE file for
3 // details.
4 //
5 // SPDX-License-Identifier: (BSD-3-Clause)
6 
12 #pragma once
13 
14 #include "smith/differentiable_numerics/field_store.hpp"
17 #include "smith/differentiable_numerics/multiphysics_time_integrator.hpp"
23 
24 namespace smith {
25 
38 template <int dim, int temp_order, typename TemperatureTimeRule = QuasiStaticFirstOrderTimeIntegrationRule,
39  typename... parameter_space>
40 struct ThermalSystem : public SystemBase {
41  static_assert(TemperatureTimeRule::num_states == 2, "ThermalSystem requires a 2-state time integration rule");
42 
47 
48  std::shared_ptr<ThermalWeakFormType> thermal_weak_form;
49  std::shared_ptr<DirichletBoundaryConditions> temperature_bc;
50  std::shared_ptr<TemperatureTimeRule> temperature_time_rule;
51 
56  std::vector<FieldState> getStateFields() const
57  {
58  return {field_store->getField(prefix("temperature_solve_state")), field_store->getField(prefix("temperature"))};
59  }
60 
65  std::vector<FieldState> getOutputFieldStates() const { return {field_store->getField(prefix("temperature"))}; }
66 
71  std::vector<ReactionInfo> getReactionInfos() const
72  {
73  return {{prefix("thermal_flux"), &field_store->getField(prefix("temperature")).get()->space()}};
74  }
75 
81  std::unique_ptr<DifferentiablePhysics> createDifferentiablePhysics(std::string physics_name)
82  {
83  return std::make_unique<DifferentiablePhysics>(field_store->getMesh(), field_store->graph(),
84  field_store->getShapeDisp(), getStateFields(), getParameterFields(),
85  advancer, physics_name, getReactionInfos());
86  }
87 
101  template <typename MaterialType>
102  void setMaterial(const MaterialType& material, const std::string& domain_name)
103  {
104  auto captured_temp_rule = temperature_time_rule;
105 
106  thermal_weak_form->addBodyIntegral(
107  domain_name, [=](auto t_info, auto /*X*/, auto temperature, auto temperature_old, auto... params) {
108  auto [T_current, T_dot] = captured_temp_rule->interpolate(t_info, temperature, temperature_old);
109  auto [heat_capacity, heat_flux] = material(get<VALUE>(T_current), get<DERIVATIVE>(T_current), params...);
110  return smith::tuple{heat_capacity * get<VALUE>(T_dot), -heat_flux};
111  });
112  }
113 
120  template <int... active_parameters, typename HeatSourceType>
121  void addHeatSource(DependsOn<active_parameters...> depends_on, const std::string& domain_name,
122  HeatSourceType source_function)
123  {
124  auto captured_temp_rule = temperature_time_rule;
125 
126  thermal_weak_form->addBodySource(depends_on, domain_name,
127  [=](auto t_info, auto X, auto temperature, auto temperature_old, auto... params) {
128  auto T = captured_temp_rule->value(t_info, temperature, temperature_old);
129  return source_function(t_info.time(), X, T, params...);
130  });
131  }
132 
138  template <typename HeatSourceType>
139  void addHeatSource(const std::string& domain_name, HeatSourceType source_function)
140  {
141  addHeatSourceAllParams(domain_name, source_function, std::make_index_sequence<2 + sizeof...(parameter_space)>{});
142  }
143 
150  template <int... active_parameters, typename HeatFluxType>
151  void addHeatFlux(DependsOn<active_parameters...> depends_on, const std::string& boundary_name,
152  HeatFluxType flux_function)
153  {
154  auto captured_temp_rule = temperature_time_rule;
155 
156  thermal_weak_form->addBoundaryFlux(
157  depends_on, boundary_name,
158  [=](auto t_info, auto X, auto n, auto temperature, auto temperature_old, auto... params) {
159  auto T = captured_temp_rule->value(t_info, temperature, temperature_old);
160  return -flux_function(t_info.time(), X, n, T, params...);
161  });
162  }
163 
169  template <typename HeatFluxType>
170  void addHeatFlux(const std::string& boundary_name, HeatFluxType flux_function)
171  {
172  addHeatFluxAllParams(boundary_name, flux_function, std::make_index_sequence<2 + sizeof...(parameter_space)>{});
173  }
174 
175  private:
176  template <typename HeatSourceType, std::size_t... Is>
177  void addHeatSourceAllParams(const std::string& domain_name, HeatSourceType f, std::index_sequence<Is...>)
178  {
179  addHeatSource(DependsOn<static_cast<int>(Is)...>{}, domain_name, f);
180  }
181 
182  template <typename HeatFluxType, std::size_t... Is>
183  void addHeatFluxAllParams(const std::string& boundary_name, HeatFluxType f, std::index_sequence<Is...>)
184  {
185  addHeatFlux(DependsOn<static_cast<int>(Is)...>{}, boundary_name, f);
186  }
187 };
188 
202 template <int dim, int temp_order, typename TemperatureTimeRule, typename... parameter_space>
203 ThermalSystem<dim, temp_order, TemperatureTimeRule, parameter_space...> buildThermalSystem(
204  std::shared_ptr<Mesh> mesh, std::shared_ptr<CoupledSystemSolver> solver, TemperatureTimeRule temp_rule,
205  std::string prepend_name = "", FieldType<parameter_space>... parameter_types)
206 {
207  auto field_store = std::make_shared<FieldStore>(mesh, 100);
208 
209  auto prefix = [&](const std::string& name) {
210  if (prepend_name.empty()) {
211  return name;
212  }
213  return prepend_name + "_" + name;
214  };
215 
216  FieldType<H1<1, dim>> shape_disp_type(prefix("shape_displacement"));
217  field_store->addShapeDisp(shape_disp_type);
218 
219  auto temperature_time_rule = std::make_shared<TemperatureTimeRule>(temp_rule);
220  FieldType<H1<temp_order>> temperature_type(prefix("temperature_solve_state"));
221  auto temperature_bc = field_store->addIndependent(temperature_type, temperature_time_rule);
222  auto temperature_old_type =
223  field_store->addDependent(temperature_type, FieldStore::TimeDerivative::VAL, prefix("temperature"));
224 
225  std::vector<FieldState> parameter_fields;
226  (field_store->addParameter(FieldType<parameter_space>(prefix("param_" + parameter_types.name))), ...);
227  (parameter_fields.push_back(field_store->getField(prefix("param_" + parameter_types.name))), ...);
228 
229  std::string thermal_flux_name = prefix("thermal_flux");
230  auto thermal_weak_form = std::make_shared<
231  typename ThermalSystem<dim, temp_order, TemperatureTimeRule, parameter_space...>::ThermalWeakFormType>(
232  thermal_flux_name, field_store->getMesh(), field_store->getField(temperature_type.name).get()->space(),
233  field_store->createSpaces(thermal_flux_name, temperature_type.name, temperature_type, temperature_old_type,
234  FieldType<parameter_space>(prefix("param_" + parameter_types.name))...));
235 
236  std::vector<std::shared_ptr<WeakForm>> weak_forms{thermal_weak_form};
237  auto advancer = std::make_shared<MultiphysicsTimeIntegrator>(field_store, weak_forms, solver);
238 
239  return ThermalSystem<dim, temp_order, TemperatureTimeRule, parameter_space...>{
240  {field_store, solver, advancer, parameter_fields, prepend_name},
241  thermal_weak_form,
242  temperature_bc,
243  temperature_time_rule};
244 }
245 
249 template <int dim, int temp_order, typename... parameter_space>
250 auto buildThermalSystem(std::shared_ptr<Mesh> mesh, std::shared_ptr<CoupledSystemSolver> solver,
251  std::string prepend_name = "", FieldType<parameter_space>... parameter_types)
252 {
253  return buildThermalSystem<dim, temp_order>(mesh, solver, QuasiStaticFirstOrderTimeIntegrationRule{}, prepend_name,
254  parameter_types...);
255 }
256 
257 } // namespace smith
encodes rules for time discretizing first order odes (involving first time derivatives)....
Defines a BasePhysics implementation backed by FieldState objects and a gretl computational graph.
Contains DirichletBoundaryConditions class for interaction with the differentiable solve interfaces.
Accelerator functionality.
Definition: smith.cpp:36
ThermalSystem< dim, temp_order, TemperatureTimeRule, parameter_space... > buildThermalSystem(std::shared_ptr< Mesh > mesh, std::shared_ptr< CoupledSystemSolver > solver, TemperatureTimeRule temp_rule, std::string prepend_name="", FieldType< parameter_space >... parameter_types)
Factory function to build a thermal system.
BackwardEulerFirstOrderTimeIntegrationRule QuasiStaticFirstOrderTimeIntegrationRule
Alias for BackwardEulerFirstOrderTimeIntegrationRule for convenience. Quasi-static still should compu...
mfem::future::tuple< T... > tuple
Expose MFEM tuple in the Smith namespace.
Definition: tuple.hpp:241
decltype(detail::time_rule_params_impl< Space, Tail... >(std::make_index_sequence< Rule::num_states >{})) TimeRuleParams
Generate a Parameters<...> type with Rule::num_states copies of Space followed by additional Tail typ...
Definition: system_base.hpp:55
This file contains nonlinear block solver interfaces and helpers.
Representation of a field type with a name and an optional unknown index.
Definition: field_store.hpp:30
std::string name
Name of the field.
Definition: field_store.hpp:37
Base struct for physics systems containing common members and helper functions.
Definition: system_base.hpp:60
std::string prefix(const std::string &name) const
Helper function to prepend the physics name to a string.
Definition: system_base.hpp:78
std::shared_ptr< StateAdvancer > advancer
The state advancer.
Definition: system_base.hpp:63
std::shared_ptr< FieldStore > field_store
Field store managing the system's fields.
Definition: system_base.hpp:61
const std::vector< FieldState > & getParameterFields() const
Get the list of all parameter fields.
Definition: system_base.hpp:71
Container for a thermal system with configurable time integration.
std::shared_ptr< ThermalWeakFormType > thermal_weak_form
Thermal weak form.
std::shared_ptr< DirichletBoundaryConditions > temperature_bc
Temperature boundary conditions.
std::vector< FieldState > getStateFields() const
Get the list of all state fields (temperature_solve_state, temperature).
std::unique_ptr< DifferentiablePhysics > createDifferentiablePhysics(std::string physics_name)
Create a DifferentiablePhysics object for this system.
void addHeatFlux(const std::string &boundary_name, HeatFluxType flux_function)
Add a boundary heat flux that depends on all state and parameter fields.
void addHeatFlux(DependsOn< active_parameters... > depends_on, const std::string &boundary_name, HeatFluxType flux_function)
Add a boundary heat flux to the thermal system (with DependsOn).
void addHeatSource(const std::string &domain_name, HeatSourceType source_function)
Add a body heat source that depends on all state and parameter fields.
std::vector< ReactionInfo > getReactionInfos() const
Get information about reaction fields for this system.
void addHeatSource(DependsOn< active_parameters... > depends_on, const std::string &domain_name, HeatSourceType source_function)
Add a body heat source to the thermal system (with DependsOn).
std::vector< FieldState > getOutputFieldStates() const
Get the list of physical, non-solve state fields.
std::shared_ptr< TemperatureTimeRule > temperature_time_rule
Time integration for temperature.
void setMaterial(const MaterialType &material, const std::string &domain_name)
Set the thermal material model for a domain.
Defines the SystemBase struct for common system functionality.
Wraps FunctionalWeakForm to provide TimeInfo (time, dt, cycle) to integrands instead of just time.
Provides templated implementations for discretizing values, velocities and accelerations from current...
Specifies interface for evaluating weak form residuals and their gradients.