Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
coupling_params.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 
18 #pragma once
19 
20 #include <tuple>
21 #include <type_traits>
22 #include <utility>
23 
24 #include "smith/differentiable_numerics/field_store.hpp"
26 
27 namespace smith {
28 
36 template <int Dim, int Order, typename TimeRule, typename... Spaces>
37 struct PhysicsFields {
38  using time_rule_type = TimeRule;
39  static constexpr int dim = Dim;
40  static constexpr int order = Order;
41  static constexpr std::size_t num_fields = sizeof...(Spaces);
42  std::shared_ptr<FieldStore> field_store;
43  std::tuple<FieldType<Spaces>...> fields;
44 
46  PhysicsFields(std::shared_ptr<FieldStore> fs, FieldType<Spaces>... f)
47  : field_store(std::move(fs)), fields(std::move(f)...)
48  {
49  }
50 };
51 
55 template <typename... Spaces>
56 struct ParamFields {
57  static constexpr std::size_t num_fields = sizeof...(Spaces);
58  std::tuple<FieldType<Spaces>...> fields;
60  ParamFields(FieldType<Spaces>... fs) : fields(std::move(fs)...) {}
61 };
62 
64 template <typename... Spaces>
66 
73 template <typename... PFs>
75  std::tuple<PFs...> packs;
76 };
77 
78 namespace detail {
79 
80 template <typename T>
81 struct is_physics_fields_impl : std::false_type {};
82 
83 template <int D, int O, typename R, typename... S>
84 struct is_physics_fields_impl<PhysicsFields<D, O, R, S...>> : std::true_type {};
85 
87 template <typename T>
89 
90 } // namespace detail
91 
93 template <typename... PFs>
94 auto couplingFields(const PFs&... pfs)
95 {
96  static_assert((detail::is_physics_fields_v<PFs> && ...), "couplingFields(...) only accepts PhysicsFields packs");
97  return CouplingFields<PFs...>{std::make_tuple(pfs...)};
98 }
99 
103 template <typename... ParamSpaces>
104 auto registerParameterFields(const std::shared_ptr<FieldStore>& field_store, FieldType<ParamSpaces>... param_types)
105 {
106  auto register_one = [&](auto param_type) {
107  param_type.name = "param_" + param_type.name;
108  field_store->addParameter(param_type);
109  return param_type;
110  };
111  return ParamFields<ParamSpaces...>{register_one(std::move(param_types))...};
112 }
113 
114 namespace detail {
115 
116 template <typename T>
117 struct is_parameter_pack_impl : std::false_type {};
118 
119 template <typename... S>
120 struct is_parameter_pack_impl<ParamFields<S...>> : std::true_type {};
121 
123 template <typename T>
125 
126 template <typename T>
127 struct is_coupling_fields_impl : std::false_type {};
128 
129 template <typename... PFs>
130 struct is_coupling_fields_impl<CouplingFields<PFs...>> : std::true_type {};
131 
133 template <typename T>
135 
137 template <typename T>
138 struct is_coupling_packs_impl : std::false_type {};
139 
140 template <typename... Packs>
141 struct is_coupling_packs_impl<std::tuple<Packs...>> : std::true_type {};
142 
144 template <typename T>
146 
148 template <typename T, typename = void>
149 inline constexpr bool has_time_rule_v = false;
150 
152 template <typename T>
153 inline constexpr bool has_time_rule_v<T, std::enable_if_t<is_physics_fields_v<T>>> = true;
154 
155 // -------------------------------------------------------------------------
156 // Trailing-arg extraction
157 // -------------------------------------------------------------------------
158 
160 template <typename PacksTuple>
161 auto flattenCouplingFields(const PacksTuple& packs)
162 {
163  return std::apply([](const auto&... pack) { return std::tuple_cat(pack.fields...); }, packs);
164 }
165 
167 inline auto collectCouplingFields() { return std::tuple<>{}; }
168 
169 template <typename... PFs>
172 {
173  return coupled.packs;
174 }
175 
176 template <typename... Spaces>
179 {
180  return std::make_tuple(params);
181 }
182 
183 template <typename... PFs, typename... Spaces>
186 {
187  return std::tuple_cat(coupled.packs, std::make_tuple(params));
188 }
189 
190 // -------------------------------------------------------------------------
191 // Time-rule interpolation
192 // -------------------------------------------------------------------------
193 
195 template <typename Rule, typename TimeInfoT, typename ArgsTuple, typename Callback, std::size_t... StateIs,
196  std::size_t... TailIs>
197 decltype(auto) applyTimeRuleToPrefixImpl(const Rule& rule, const TimeInfoT& t_info, const ArgsTuple& raw_args,
198  Callback&& callback, std::index_sequence<StateIs...>,
199  std::index_sequence<TailIs...>)
200 {
201  auto interpolated = rule.interpolate(t_info, std::get<StateIs>(raw_args)...);
202  return std::apply(
203  [&](auto&&... values) -> decltype(auto) {
204  return std::forward<Callback>(callback)(std::forward<decltype(values)>(values)...,
205  std::get<Rule::num_states + TailIs>(raw_args)...);
206  },
207  interpolated);
208 }
209 
211 template <typename Rule, typename TimeInfoT, typename Callback, typename... RawArgs>
212 decltype(auto) applyTimeRuleToPrefix(const Rule& rule, const TimeInfoT& t_info, Callback&& callback,
213  const RawArgs&... raw_args)
214 {
215  static_assert(sizeof...(RawArgs) >= Rule::num_states, "Not enough raw arguments for time-rule interpolation");
216  auto raw_tuple = std::forward_as_tuple(raw_args...);
217  constexpr std::size_t tail_count = sizeof...(RawArgs) - Rule::num_states;
218  return applyTimeRuleToPrefixImpl(rule, t_info, raw_tuple, std::forward<Callback>(callback),
219  std::make_index_sequence<Rule::num_states>{},
220  std::make_index_sequence<tail_count>{});
221 }
222 
224 template <std::size_t Offset, typename Pack, typename TimeInfoT, typename RawTuple, std::size_t... Is>
225 auto evaluateCouplingPack(const Pack& /*pack*/, const TimeInfoT& t_info, const RawTuple& raw_args,
226  std::index_sequence<Is...>)
227 {
228  if constexpr (is_physics_fields_v<Pack>) {
229  using Rule = typename Pack::time_rule_type;
230  Rule rule;
231  return rule.interpolate(t_info, std::get<Offset + Is>(raw_args)...);
232  } else {
233  return std::forward_as_tuple(std::get<Offset + Is>(raw_args)...);
234  }
235 }
236 
238 template <std::size_t I, std::size_t Offset, typename PacksTuple, typename TimeInfoT, typename RawTuple>
239 auto evaluateCouplingPacks(const PacksTuple& packs, const TimeInfoT& t_info, const RawTuple& raw_args)
240 {
241  if constexpr (I == std::tuple_size_v<std::decay_t<PacksTuple>>) {
242  return std::tuple{};
243  } else {
244  const auto& pack = std::get<I>(packs);
245  using Pack = std::decay_t<decltype(pack)>;
246  auto head = evaluateCouplingPack<Offset>(pack, t_info, raw_args, std::make_index_sequence<Pack::num_fields>{});
247  auto tail = evaluateCouplingPacks<I + 1, Offset + Pack::num_fields>(packs, t_info, raw_args);
248  return std::tuple_cat(head, tail);
249  }
250 }
251 
253 template <typename PacksTuple, typename TimeInfoT, typename Callback, typename... RawArgs>
254 decltype(auto) applyCouplingTimeRules(const PacksTuple& packs, const TimeInfoT& t_info, Callback&& callback,
255  const RawArgs&... raw_args)
256 {
257  auto raw_tuple = std::forward_as_tuple(raw_args...);
258  auto interpolated_tail = evaluateCouplingPacks<0, 0>(packs, t_info, raw_tuple);
259  return std::apply(std::forward<Callback>(callback), interpolated_tail);
260 }
261 
270 template <typename Rule, typename Coupling, typename TimeInfoT, typename Callback, typename... RawArgs>
271 decltype(auto) applyTimeRuleAndCoupling(const Rule& rule, const Coupling& coupling, const TimeInfoT& t_info,
272  Callback&& callback, const RawArgs&... raw_args)
273 {
274  constexpr std::size_t tail_count = sizeof...(RawArgs) - Rule::num_states;
275  return applyTimeRuleToPrefix(
276  rule, t_info,
277  [&](auto... self_states_and_tail) {
278  constexpr std::size_t n_self = sizeof...(self_states_and_tail) - tail_count;
279  auto all = std::forward_as_tuple(self_states_and_tail...);
280  return [&]<std::size_t... Si, std::size_t... Ti>(std::index_sequence<Si...>, std::index_sequence<Ti...>) {
281  return applyCouplingTimeRules(
282  coupling, t_info,
283  [&](auto... interpolated_coupling) {
284  return std::forward<Callback>(callback)(std::get<Si>(all)..., interpolated_coupling...);
285  },
286  std::get<n_self + Ti>(all)...);
287  }(std::make_index_sequence<n_self>{}, std::make_index_sequence<tail_count>{});
288  },
289  raw_args...);
290 }
291 
292 // -------------------------------------------------------------------------
293 // Type-level coupling-space extraction (used by weak-form parameter type computation)
294 // -------------------------------------------------------------------------
295 
297 template <typename PacksTuple>
299 
301 template <typename Tuple>
303 
305 template <typename... Spaces>
306 struct TupleToParameters<std::tuple<Spaces...>> {
307  using type = Parameters<Spaces...>;
308 };
309 
311 template <typename Tuple>
313 
315 template <typename Pack>
316 struct pack_tuple;
317 
319 template <int D, int O, typename R, typename... Spaces>
320 struct pack_tuple<PhysicsFields<D, O, R, Spaces...>> {
321  using type = std::tuple<Spaces...>;
322 };
323 
325 template <typename... Spaces>
326 struct pack_tuple<ParamFields<Spaces...>> {
327  using type = std::tuple<Spaces...>;
328 };
329 
331 template <typename Pack>
333 
335 template <typename... Tuples>
336 using tuple_cat_t = decltype(std::tuple_cat(std::declval<Tuples>()...));
337 
339 template <typename CouplingParams, typename FixedParams>
341 
343 template <typename... Coupled, typename... Fixed>
344 struct AppendParameters<Parameters<Coupled...>, Parameters<Fixed...>> {
345  using type = Parameters<Fixed..., Coupled...>;
346 };
347 
349 template <typename... Packs>
350 struct FlattenCoupling<std::tuple<Packs...>> {
351  public:
354 };
355 
357 template <typename PacksTuple>
359 
361 template <typename Rule, typename Space, typename PacksTuple>
363 
365 template <typename Rule, typename Space, typename... CS>
366 struct TimeRuleParamsImpl<Rule, Space, Parameters<CS...>> {
367  using type = smith::TimeRuleParams<Rule, Space, CS...>;
368 };
369 
371 template <typename Rule, typename Space, typename PacksTuple>
373 
375 template <typename PacksTuple, typename FixedParams>
377 
379 template <typename PacksTuple, typename... Fixed>
380 struct AppendCouplingToParams<PacksTuple, Parameters<Fixed...>> {
383 };
384 
385 } // namespace detail
386 
387 } // namespace smith
decltype(auto) applyCouplingTimeRules(const PacksTuple &packs, const TimeInfoT &t_info, Callback &&callback, const RawArgs &... raw_args)
Interpolate coupling packs and invoke the callback.
constexpr bool is_coupling_fields_v
True if T is a CouplingFields type.
auto evaluateCouplingPack(const Pack &, const TimeInfoT &t_info, const RawTuple &raw_args, std::index_sequence< Is... >)
Evaluate a single coupling pack's time rule.
typename pack_tuple< std::decay_t< Pack > >::type pack_tuple_t
Typedef for extracting a tuple of spaces from a coupling pack.
constexpr bool is_coupling_packs_v
True if T is a tuple of coupling packs.
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.
decltype(std::tuple_cat(std::declval< Tuples >()...)) tuple_cat_t
Typedef for concatenating space tuples with std::tuple_cat.
auto collectCouplingFields()
Collect no coupling or parameter packs.
decltype(auto) applyTimeRuleToPrefixImpl(const Rule &rule, const TimeInfoT &t_info, const ArgsTuple &raw_args, Callback &&callback, std::index_sequence< StateIs... >, std::index_sequence< TailIs... >)
Implementation of time rule prefix application.
typename FlattenCoupling< std::decay_t< PacksTuple > >::parameters flatten_coupling_t
Typedef for flattened coupling parameter spaces.
constexpr bool is_physics_fields_v
True when T is a PhysicsFields pack.
typename TupleToParameters< std::decay_t< Tuple > >::type tuple_to_parameters_t
Typedef for converting a tuple of spaces into Parameters<...>.
decltype(auto) applyTimeRuleToPrefix(const Rule &rule, const TimeInfoT &t_info, Callback &&callback, const RawArgs &... raw_args)
Apply time rule interpolation to the leading prefix of raw arguments.
constexpr bool has_time_rule_v
Base case: T does not have a time rule.
typename TimeRuleParamsImpl< Rule, Space, flatten_coupling_t< PacksTuple > >::type TimeRuleParams
Typedef for TimeRuleParams.
auto evaluateCouplingPacks(const PacksTuple &packs, const TimeInfoT &t_info, const RawTuple &raw_args)
Evaluate all coupling packs over their corresponding raw arguments.
auto flattenCouplingFields(const PacksTuple &packs)
Concatenate each pack's .fields tuple — used to derive trailing weak-form parameter spaces.
constexpr bool is_parameter_pack_v
True if T is a ParamFields type.
Accelerator functionality.
Definition: smith.cpp:36
mfem::future::tuple< T... > tuple
Expose MFEM tuple in the Smith namespace.
Definition: tuple.hpp:241
auto couplingFields(const PFs &... pfs)
Helper to construct a CouplingFields bundle.
auto registerParameterFields(const std::shared_ptr< FieldStore > &field_store, FieldType< ParamSpaces >... param_types)
Register parameter fields as type-level tokens.
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:47
ParamFields(FieldType< Spaces >...) -> ParamFields< Spaces... >
Deduction guide for ParamFields.
Bundle of coupled PhysicsFields packs supplied to a builder as a single coupling arg.
std::tuple< PFs... > packs
The coupling packs.
Representation of a field type with a name and a flag indicating whether it is an active Jacobian unk...
Definition: field_store.hpp:47
Registered parameter-only field bundle.
ParamFields(FieldType< Spaces >... fs)
Constructor.
std::tuple< FieldType< Spaces >... > fields
static constexpr std::size_t num_fields
Number of fields.
a struct that is used in the physics modules to clarify which template arguments are user-controlled ...
Definition: common.hpp:59
Fields returned by a physics register function, carrying time rule type information.
static constexpr int order
Spatial order.
static constexpr int dim
Spatial dimension.
PhysicsFields(std::shared_ptr< FieldStore > fs, FieldType< Spaces >... f)
Constructor.
std::tuple< FieldType< Spaces >... > fields
The fields.
std::shared_ptr< FieldStore > field_store
Pointer to the field store.
static constexpr std::size_t num_fields
Number of fields.
TimeRule time_rule_type
The time integration rule type.
typename AppendParameters< flatten_coupling_t< PacksTuple >, Parameters< Fixed... > >::type type
The appended parameter list.
Type trait to append coupling parameter spaces to fixed parameters.
Appends coupling parameter spaces to an existing Parameters<...> list.
tuple_to_parameters_t< tuple_type > parameters
Flattened parameter spaces.
tuple_cat_t< pack_tuple_t< Packs >... > tuple_type
The flattened tuple of coupling spaces.
Flatten a tuple<Packs...> type into Parameters<all_pack_spaces...>.
smith::TimeRuleParams< Rule, Space, CS... > type
The constructed TimeRuleParams type.
Type trait to construct Parameters<Space, packed_coupling_spaces...> for a weak form's parameter list...
Converts a std::tuple<...> of spaces into Parameters<...>.
True for a std::tuple<Packs...> returned by collectCouplingFields.
std::tuple< Spaces... > type
The parameter spaces as a tuple.
std::tuple< Spaces... > type
The coupling spaces as a tuple.
Maps a coupling pack type to a std::tuple<...> of its spaces.
Defines the SystemBase struct for common system functionality.