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"
24 
25 namespace smith {
26 
41 template <int dim, int temp_order, typename TemperatureTimeRule = QuasiStaticFirstOrderTimeIntegrationRule,
42  typename Coupling = std::tuple<>>
43 struct ThermalSystem : public SystemBase {
45 
46  static_assert(TemperatureTimeRule::num_states == 2, "ThermalSystem requires a 2-state time integration rule");
47 
51 
52  std::shared_ptr<ThermalWeakFormType> thermal_weak_form;
53  std::shared_ptr<DirichletBoundaryConditions> temperature_bc;
54  std::shared_ptr<TemperatureTimeRule> temperature_time_rule;
55  std::shared_ptr<const Coupling> coupling;
56 
70  template <typename MaterialType>
71  void setMaterial(const MaterialType& material, const std::string& domain_name)
72  {
73  auto captured_temp_rule = temperature_time_rule;
74  auto captured_coupling = coupling;
75 
76  thermal_weak_form->addBodyIntegral(domain_name, [=](auto t_info, auto /*X*/, auto... raw_args) {
78  *captured_temp_rule, *captured_coupling, t_info,
79  [&](auto T_current, auto T_dot, auto... interpolated_params) {
80  auto [heat_capacity, heat_flux] =
81  material(t_info, get<VALUE>(T_current), get<DERIVATIVE>(T_current), interpolated_params...);
82  return smith::tuple{heat_capacity * get<VALUE>(T_dot), -heat_flux};
83  },
84  raw_args...);
85  });
86  }
87 
102  template <typename MaterialType>
103  void setMaterialAndHeatSource(const MaterialType& material, const std::string& domain_name)
104  {
105  auto captured_temp_rule = temperature_time_rule;
106  auto captured_coupling = coupling;
107 
108  thermal_weak_form->addBodyIntegral(domain_name, [=](auto t_info, auto /*X*/, auto... raw_args) {
110  *captured_temp_rule, *captured_coupling, t_info,
111  [&](auto T_current, auto T_dot, auto... interpolated_params) {
112  auto [heat_capacity, heat_flux, heat_source] =
113  material(t_info, get<VALUE>(T_current), get<DERIVATIVE>(T_current), interpolated_params...);
114  return smith::tuple{heat_capacity * get<VALUE>(T_dot) - heat_source, -heat_flux};
115  },
116  raw_args...);
117  });
118  }
119 
125  template <typename HeatSourceType>
126  void addHeatSource(const std::string& domain_name, HeatSourceType source_function)
127  {
128  auto captured_rule = temperature_time_rule;
129  auto captured_coupling = coupling;
130  thermal_weak_form->addBodySource(domain_name, [=](auto t_info, auto X, auto... raw_args) {
132  *captured_rule, *captured_coupling, t_info,
133  [&](auto T_current, auto /*T_dot*/, auto... interpolated_params) {
134  return source_function(t_info.time(), X, T_current, interpolated_params...);
135  },
136  raw_args...);
137  });
138  }
139 
145  template <typename HeatFluxType>
146  void addHeatFlux(const std::string& boundary_name, HeatFluxType flux_function)
147  {
148  auto captured_rule = temperature_time_rule;
149  auto captured_coupling = coupling;
150  thermal_weak_form->addBoundaryFlux(boundary_name, [=](auto t_info, auto X, auto n, auto... raw_args) {
152  *captured_rule, *captured_coupling, t_info,
153  [&](auto T_current, auto /*T_dot*/, auto... interpolated_params) {
154  return flux_function(t_info.time(), X, n, T_current, interpolated_params...);
155  },
156  raw_args...);
157  });
158  }
159 
161  void setTemperatureBC(const Domain& domain) { temperature_bc->template setFixedScalarBCs<dim>(domain); }
162 
164  template <typename AppliedTemperatureFunction>
165  void setTemperatureBC(const Domain& domain, AppliedTemperatureFunction f)
166  {
167  temperature_bc->template setScalarBCs<dim>(domain, f);
168  }
169 
170  private:
171 };
172 
173 struct ThermalOptions {};
174 
182 template <int dim, int temp_order, typename TemperatureTimeRule>
183 auto registerThermalFields(std::shared_ptr<FieldStore> field_store,
184  const ThermalOptions& /*options*/ = ThermalOptions{})
185 {
186  FieldType<H1<1, dim>> shape_disp_type("shape_displacement");
187  if (!field_store->hasField(field_store->prefix(shape_disp_type.name))) {
188  field_store->addShapeDisp(shape_disp_type);
189  }
190 
191  auto temperature_time_rule_ptr = std::make_shared<TemperatureTimeRule>();
192  FieldType<H1<temp_order>> temperature_type("temperature_solve_state");
193  field_store->addIndependent(temperature_type, temperature_time_rule_ptr);
194  field_store->addDependent(temperature_type, FieldStore::TimeDerivative::VAL, "temperature");
195 
196  return PhysicsFields<dim, temp_order, TemperatureTimeRule, H1<temp_order>, H1<temp_order>>{
197  field_store, FieldType<H1<temp_order>>(field_store->prefix("temperature_solve_state")),
198  FieldType<H1<temp_order>>(field_store->prefix("temperature"))};
199 }
200 
206 namespace detail {
207 
209 template <int dim, int temp_order, typename TemperatureTimeRule, typename Coupling>
210  requires detail::is_coupling_packs_v<Coupling>
211 auto buildThermalSystemImpl(std::shared_ptr<FieldStore> field_store, const Coupling& coupling,
212  std::shared_ptr<SystemSolver> solver, const ThermalOptions& /*options*/)
213 {
214  auto temperature_time_rule_ptr = std::make_shared<TemperatureTimeRule>();
215 
216  FieldType<H1<1, dim>> shape_disp_type(field_store->prefix("shape_displacement"));
217  FieldType<H1<temp_order>> temperature_type(field_store->prefix("temperature_solve_state"), true);
218  FieldType<H1<temp_order>> temperature_old_type(field_store->prefix("temperature"));
219 
220  auto temperature_bc = field_store->getBoundaryConditions(temperature_type.name);
221 
223 
224  std::string thermal_flux_name = field_store->prefix("thermal_flux");
225  auto thermal_weak_form = detail::buildWeakFormWithCoupling<typename SystemType::ThermalWeakFormType>(
226  field_store, thermal_flux_name, temperature_type.name, temperature_type, temperature_old_type,
228 
229  auto sys =
230  std::make_shared<SystemType>(field_store, solver, std::vector<std::shared_ptr<WeakForm>>{thermal_weak_form});
231  sys->temperature_bc = temperature_bc;
232  sys->temperature_time_rule = temperature_time_rule_ptr;
233  sys->coupling = std::make_shared<Coupling>(coupling);
234  sys->thermal_weak_form = thermal_weak_form;
235 
236  return sys;
237 }
238 
239 } // namespace detail
240 
252 template <typename SelfFields>
253  requires(detail::has_time_rule_v<SelfFields>)
254 auto buildThermalSystem(std::shared_ptr<SystemSolver> solver, const ThermalOptions& options,
255  const SelfFields& self_fields)
256 {
257  constexpr int dim = SelfFields::dim;
258  constexpr int temp_order = SelfFields::order;
259  using TemperatureTimeRule = typename std::decay_t<SelfFields>::time_rule_type;
260  auto field_store = self_fields.field_store;
261  auto coupling = detail::collectCouplingFields();
262  return detail::buildThermalSystemImpl<dim, temp_order, TemperatureTimeRule>(field_store, coupling, solver, options);
263 }
264 
268 template <typename SelfFields, typename... PFs>
269  requires(detail::has_time_rule_v<SelfFields>)
270 auto buildThermalSystem(std::shared_ptr<SystemSolver> solver, const ThermalOptions& options,
271  const SelfFields& self_fields, const CouplingFields<PFs...>& coupled)
272 {
273  constexpr int dim = SelfFields::dim;
274  constexpr int temp_order = SelfFields::order;
275  using TemperatureTimeRule = typename std::decay_t<SelfFields>::time_rule_type;
276  auto field_store = self_fields.field_store;
277  auto coupling = detail::collectCouplingFields(coupled);
278  return detail::buildThermalSystemImpl<dim, temp_order, TemperatureTimeRule>(field_store, coupling, solver, options);
279 }
280 
284 template <typename SelfFields, typename... ParamSpaces>
285  requires(detail::has_time_rule_v<SelfFields>)
286 auto buildThermalSystem(std::shared_ptr<SystemSolver> solver, const ThermalOptions& options,
287  const SelfFields& self_fields, const ParamFields<ParamSpaces...>& params)
288 {
289  constexpr int dim = SelfFields::dim;
290  constexpr int temp_order = SelfFields::order;
291  using TemperatureTimeRule = typename std::decay_t<SelfFields>::time_rule_type;
292  auto field_store = self_fields.field_store;
293  auto coupling = detail::collectCouplingFields(params);
294  return detail::buildThermalSystemImpl<dim, temp_order, TemperatureTimeRule>(field_store, coupling, solver, options);
295 }
296 
300 template <typename SelfFields, typename... PFs, typename... ParamSpaces>
301  requires(detail::has_time_rule_v<SelfFields>)
302 auto buildThermalSystem(std::shared_ptr<SystemSolver> solver, const ThermalOptions& options,
303  const SelfFields& self_fields, const CouplingFields<PFs...>& coupled,
304  const ParamFields<ParamSpaces...>& params)
305 {
306  constexpr int dim = SelfFields::dim;
307  constexpr int temp_order = SelfFields::order;
308  using TemperatureTimeRule = typename std::decay_t<SelfFields>::time_rule_type;
309  auto field_store = self_fields.field_store;
310  auto coupling = detail::collectCouplingFields(coupled, params);
311  return detail::buildThermalSystemImpl<dim, temp_order, TemperatureTimeRule>(field_store, coupling, solver, options);
312 }
313 
325 template <int dim, int temp_order, typename TemperatureTimeRule = QuasiStaticFirstOrderTimeIntegrationRule,
326  typename... ParamSpaces>
327 auto buildThermalSystem(const NonlinearSolverOptions& nonlinear_opts, const LinearSolverOptions& linear_opts,
328  const ThermalOptions& options, std::shared_ptr<smith::Mesh> mesh,
329  FieldType<ParamSpaces>... params)
330 {
331  auto field_store = std::make_shared<FieldStore>(mesh);
332  auto solver = std::make_shared<SystemSolver>(buildNonlinearBlockSolver(nonlinear_opts, linear_opts, *mesh));
333  auto thermal_fields = registerThermalFields<dim, temp_order, TemperatureTimeRule>(field_store, options);
334  if constexpr (sizeof...(ParamSpaces) > 0) {
335  auto param_fields = registerParameterFields(field_store, std::move(params)...);
336  return buildThermalSystem(solver, options, thermal_fields, param_fields);
337  } else {
338  return buildThermalSystem(solver, options, thermal_fields);
339  }
340 }
341 
342 } // namespace smith
Coupling pack types and helpers for injecting explicit coupled-physics fields into weak form paramete...
Defines a BasePhysics implementation backed by FieldState objects and a gretl computational graph.
Contains DirichletBoundaryConditions class for interaction with the differentiable solve interfaces.
Implements the WeakForm interface using smith::ShapeAwareFunctional. Allows for generic specification...
requires detail::is_coupling_packs_v< Coupling > auto buildThermalSystemImpl(std::shared_ptr< FieldStore > field_store, const Coupling &coupling, std::shared_ptr< SystemSolver > solver, const ThermalOptions &)
Internal thermal builder after coupling fields are assembled.
decltype(auto) applyTimeRuleAndCoupling(const Rule &rule, const Coupling &coupling, const TimeInfoT &t_info, Callback &&callback, const RawArgs &... raw_args)
Interpolate self time-rule states then coupling segments, then invoke callback.
auto collectCouplingFields()
Collect no coupling or parameter packs.
typename TimeRuleParamsImpl< Rule, Space, flatten_coupling_t< PacksTuple > >::type TimeRuleParams
Typedef for TimeRuleParams.
auto flattenCouplingFields(const PacksTuple &packs)
Concatenate each pack's .fields tuple — used to derive trailing weak-form parameter spaces.
Accelerator functionality.
Definition: smith.cpp:36
std::shared_ptr< NonlinearBlockSolver > buildNonlinearBlockSolver(NonlinearSolverOptions nonlinear_opts, LinearSolverOptions linear_opts, const smith::Mesh &mesh)
Create an equation-backed nonlinear block solver.
auto buildThermalSystem(const NonlinearSolverOptions &nonlinear_opts, const LinearSolverOptions &linear_opts, const ThermalOptions &options, std::shared_ptr< smith::Mesh > mesh, FieldType< ParamSpaces >... params)
Build a ThermalSystem from solver options and a mesh, registering parameter fields inline.
requires(detail::has_time_rule_v< SelfFields >) auto buildSolidMechanicsSystem(std
Build a SolidMechanicsSystem from already-registered field packs.
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
auto registerThermalFields(std::shared_ptr< FieldStore > field_store, const ThermalOptions &=ThermalOptions{})
Register all thermal fields into a FieldStore.
auto registerParameterFields(const std::shared_ptr< FieldStore > &field_store, FieldType< ParamSpaces >... param_types)
Register parameter fields as type-level tokens.
This file contains nonlinear block solver interfaces and helpers.
a class for representing a geometric region that can be used for integration
Definition: domain.hpp:33
Representation of a field type with a name and a flag indicating whether it is an active Jacobian unk...
Definition: field_store.hpp:47
std::string name
Name of the field.
Definition: field_store.hpp:56
Parameters for an iterative linear solution scheme.
Nonlinear solution scheme parameters.
Base struct for physics systems containing common members and helper functions.
Definition: system_base.hpp:52
SystemBase()=default
Construct an empty system shell.
Container for a thermal system with configurable time integration.
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.
void setMaterialAndHeatSource(const MaterialType &material, const std::string &domain_name)
Set thermal material and a coincident body heat source from a single callable.
std::shared_ptr< ThermalWeakFormType > thermal_weak_form
Thermal weak form.
void addHeatSource(const std::string &domain_name, HeatSourceType source_function)
Add a body heat source that depends on all state and parameter fields.
void addHeatFlux(const std::string &boundary_name, HeatFluxType flux_function)
Add a boundary heat flux that depends on all state and parameter fields.
std::shared_ptr< const Coupling > coupling
Coupling metadata for callback interpolation.
void setTemperatureBC(const Domain &domain, AppliedTemperatureFunction f)
Set temperature BC with a prescribed function.
std::shared_ptr< DirichletBoundaryConditions > temperature_bc
Temperature boundary conditions.
void setTemperatureBC(const Domain &domain)
Set zero-temperature Dirichlet BC.
Defines the SystemBase struct for common system functionality.
Provides templated implementations for discretizing values, velocities and accelerations from current...
Specifies interface for evaluating weak form residuals and their gradients.