Reactions  0.1.2
Handling reaction trees and decays
units.hpp
Go to the documentation of this file.
1 
4 #pragma once
6 #include "reactions/pow_enum.hpp"
7 #include <string>
8 #include <type_traits>
9 
10 namespace reactions {
11 
13  REACTIONS_POW_ENUM_WITH_UNKNOWN(energy_units, eV, keV, MeV, GeV, TeV, PeV);
15  REACTIONS_POW_ENUM_WITH_UNKNOWN(time_units, ys, zs, as, fs, ps, ns, us, ms,
16  sec, min, hour, day, year, ky, My, Gy, Ty, Py,
17  Ey, Zy, Yy);
18 
40  namespace units {
41 
43  struct none {};
44 
46  auto scale_factor_for(energy_units u) {
47  switch (u) {
48  case (energy_units::eV):
49  return 1.;
50  case (energy_units::keV):
51  return 1e3;
52  case (energy_units::MeV):
53  return 1e6;
54  case (energy_units::GeV):
55  return 1e9;
56  case (energy_units::TeV):
57  return 1e12;
58  case (energy_units::PeV):
59  return 1e12;
60  case (energy_units::unknown_energy_units):
61  break;
62  }
63 
64  throw internal_error(
65  (std::string{
66  "Attempt to compute a scale factor of an unknown unit: \""} +
68  .c_str());
69  }
70 
72  auto scale_factor_for(time_units u) {
73 
74  switch (u) {
75  case (time_units::ys):
76  return 1e-24;
77  case (time_units::zs):
78  return 1e-21;
79  case (time_units::as):
80  return 1e-18;
81  case (time_units::fs):
82  return 1e-15;
83  case (time_units::ps):
84  return 1e-12;
85  case (time_units::ns):
86  return 1e-9;
87  case (time_units::us):
88  return 1e-6;
89  case (time_units::ms):
90  return 1e-3;
91  case (time_units::sec):
92  return 1.;
93  case (time_units::min):
94  return 60. * scale_factor_for(time_units::sec);
95  case (time_units::hour):
96  return 60. * scale_factor_for(time_units::min);
97  case (time_units::day):
98  return 24. * scale_factor_for(time_units::hour);
99  case (time_units::year):
100  return 365. * scale_factor_for(time_units::day);
101  case (time_units::ky):
102  return 1e3 * scale_factor_for(time_units::year);
103  case (time_units::My):
104  return 1e6 * scale_factor_for(time_units::year);
105  case (time_units::Gy):
106  return 1e9 * scale_factor_for(time_units::year);
107  case (time_units::Ty):
108  return 1e12 * scale_factor_for(time_units::year);
109  case (time_units::Py):
110  return 1e15 * scale_factor_for(time_units::year);
111  case (time_units::Ey):
112  return 1e18 * scale_factor_for(time_units::year);
113  case (time_units::Zy):
114  return 1e21 * scale_factor_for(time_units::year);
115  case (time_units::Yy):
116  return 1e24 * scale_factor_for(time_units::year);
117  case (time_units::unknown_time_units):
118  break;
119  }
120 
121  throw internal_error(
122  (std::string{
123  "Attempt to compute a scale factor of an unknown unit: \""} +
125  .c_str());
126  }
127 
129  template <class Units, Units U> struct reference;
130 
132  template <energy_units U> struct reference<energy_units, U> {
133  using units_type = energy_units;
135  static constexpr auto scale_factor(energy_units u) {
136  if (u == U)
137  return 1.;
138  else
139  return scale_factor_for(U) / scale_factor_for(u);
140  }
141  };
142 
144  template <time_units U> struct reference<time_units, U> {
145  using units_type = time_units;
147  static constexpr auto scale_factor(time_units u) {
148  if (u == U)
149  return 1.;
150  else
151  return scale_factor_for(U) / scale_factor_for(u);
152  }
153  };
154 
156  template <class T> struct is_type_affected_by_units {
157  static constexpr auto value =
158  (std::is_class_v<std::decay_t<fields::remove_optional_t<T>>> ||
161  };
162 
164  template <class T>
165  static constexpr auto is_type_affected_by_units_v =
167 
169  template <class Field, class... Subfield> struct has_units {
170  static constexpr auto value =
171  !std::is_same_v<typename Field::units_reference_type, units::none> &&
172  is_type_affected_by_units_v<
173  fields::field_member_type_t<Field, Subfield...>>;
174  };
175 
177  template <class Field> struct has_units<Field> {
178  static constexpr auto value =
179  !std::is_same_v<typename Field::units_reference_type, units::none> &&
180  is_type_affected_by_units_v<typename Field::value_type>;
181  };
182 
184  template <class Field, class... Subfield>
185  static constexpr auto has_units_v = has_units<Field, Subfield...>::value;
186 
188  template <class Field, class... Subfield> struct return_type {
189  using type = std::conditional_t<
190  has_units_v<Field, Subfield...>,
191  fields::field_member_type_t<Field, Subfield...>,
192  fields::field_member_type_t<Field, Subfield...> const &>;
193  };
194 
196  template <class Field, class... Subfield>
197  using return_type_t = typename return_type<Field, Subfield...>::type;
198 
200  template <class Field, class... Subfield> struct accessor_t;
201 
203  template <class Field, class... Subfield>
204  static constexpr accessor_t<Field, Subfield...> accessor;
205 
207  template <class Field> struct accessor_t<Field> {
209  template <class T> constexpr auto const &operator()(T const &f) const {
210  if constexpr (fields::is_optional_v<T>)
211  return f.value();
212  else
213  return f;
214  }
215  };
216 
218  template <class Field, class Subfield, class... S>
219  struct accessor_t<Field, Subfield, S...> {
221  template <class T>
222  constexpr fields::field_member_type_t<Field, Subfield, S...> const &
223  operator()(T const &f) const {
224 
225  if constexpr (fields::is_optional_v<T>)
226  return accessor<Field, S...>(fields::get<Subfield>(f.value()));
227  else
228  return accessor<Field, S...>(fields::get<Subfield>(f));
229  }
230  };
231 
233  template <class Field, class... Subfield> struct accessor_with_units_t {
235  template <class SystemOfUnits, class T>
236  constexpr return_type_t<Field, Subfield...>
237  operator()(SystemOfUnits const &sou, T const &f) const {
238  using R = typename Field::units_reference_type;
239  using U = typename R::units_type;
240  return R::scale_factor(sou.template units<U>()) *
241  accessor<Field, Subfield...>(f);
242  }
243  };
244 
246  template <class Field, class... Subfield>
247  static constexpr accessor_with_units_t<Field, Subfield...>
249 
250  } // namespace units
251 } // namespace reactions
constexpr auto const & operator()(T const &f) const
Access a value and process the units.
Definition: units.hpp:209
static constexpr auto scale_factor(energy_units u)
Determine the scale factor from a reference.
Definition: units.hpp:135
static constexpr auto is_type_affected_by_units_v
Whether a type can be affected by units.
Definition: units.hpp:165
std::string to_string(T const &v)
Convert the given object to a string.
Definition: fields.hpp:554
static constexpr auto has_units_v
Whether a subfield must be modified due to the presence of units.
Definition: units.hpp:185
Exceptions that can be thrown when running the functions of the package.
auto scale_factor_for(energy_units u)
Compute the scale factor for the given unit.
Definition: units.hpp:46
typename return_type< Field, Subfield... >::type return_type_t
The return type after taking into account the possible units.
Definition: units.hpp:197
Raised when unexpected problems appear, which should be reported as bugs.
Definition: exceptions.hpp:38
static constexpr accessor_with_units_t< Field, Subfield... > accessor_with_units
Static object to access the fields of a tuple-like object.
Definition: units.hpp:248
energy_units units_type
Definition: units.hpp:133
STL class.
static constexpr accessor_t< Field, Subfield... > accessor
Static object to access the fields of a tuple-like object.
Definition: units.hpp:200
Use the template argument as a reference to determine scale factors.
Definition: units.hpp:129
static constexpr auto scale_factor(time_units u)
Determine the scale factor from a reference.
Definition: units.hpp:147
Contains macros to define smart enumeration types.
typename field_member_type< Field, Subfield... >::type field_member_type_t
Access the subtype of a set of fields.
Definition: fields.hpp:551
constexpr fields::field_member_type_t< Field, Subfield, S... > const & operator()(T const &f) const
Access the value of the subfield and process the units.
Definition: units.hpp:223
Main namespace of the Reactions package.
Definition: all.hpp:22
The return type after taking into account the possible units.
Definition: units.hpp:188
Object to access fields and process the units.
Definition: units.hpp:233
REACTIONS_POW_ENUM_WITH_UNKNOWN(energy_units, eV, keV, MeV, GeV, TeV, PeV)
Energy units.
Object to access fields.
Definition: units.hpp:200
Whether a type can be affected by units.
Definition: units.hpp:156
Represent the abscence of units.
Definition: units.hpp:43
constexpr return_type_t< Field, Subfield... > operator()(SystemOfUnits const &sou, T const &f) const
Access the value of the subfield and process the units.
Definition: units.hpp:237
T is_floating_point_v
time_units units_type
Definition: units.hpp:145
Whether a subfield must be modified due to the presence of units.
Definition: units.hpp:169