1 #ifndef EAGINE_EXAMPLE_ECS_DECAY_MODES_HPP // NOLINT(llvm-header-guard)
9 #define EAGINE_EXAMPLE_ECS_DECAY_MODES_HPP
15 #include <type_traits>
19 enum class decay_part {
30 template <decay_part... M>
31 using decay_mode_t = std::integer_sequence<decay_part, M...>;
33 template <decay_part... M>
34 constexpr
auto is_fission_v = (
false || ... || (M == decay_part::fission));
36 struct decay_mode_info {
38 int proton_count_diff{0};
39 int neutron_count_diff{0};
40 bool is_fission{
false};
44 struct decay_mode_traits;
46 template <decay_part... M>
47 static inline auto mode_info(decay_mode_t<M...> = {})
48 ->
const decay_mode_info& {
49 return decay_mode_traits<decay_mode_t<M...>>::info();
53 struct decay_mode_traits<decay_mode_t<decay_part::alpha>> {
54 static auto info() noexcept -> const auto& {
55 static const decay_mode_info i{
"α", -2, -2,
false};
61 struct decay_mode_traits<decay_mode_t<decay_part::beta_p>> {
62 static auto info() noexcept -> const auto& {
63 static const decay_mode_info i{
"β⁺", -1, 1,
false};
69 struct decay_mode_traits<decay_mode_t<decay_part::beta_m>> {
70 static auto info() noexcept -> const auto& {
71 static const decay_mode_info i{
"β⁻", 1, -1,
false};
77 struct decay_mode_traits<decay_mode_t<decay_part::proton_emi>> {
78 static auto info() noexcept -> const auto& {
79 static const decay_mode_info i{
"p⁺", -1, 0,
false};
85 struct decay_mode_traits<decay_mode_t<decay_part::neutron_emi>> {
86 static auto info() noexcept -> const auto& {
87 static const decay_mode_info i{
"n⁰", 0, -1,
false};
93 struct decay_mode_traits<decay_mode_t<decay_part::electron_cap>> {
94 static auto info() noexcept -> const auto& {
95 static const decay_mode_info i{
"+e⁻", -1, 1,
false};
101 struct decay_mode_traits<decay_mode_t<decay_part::fission>> {
102 static auto info() noexcept -> const auto& {
103 static const decay_mode_info i{
"≺", 0, 0,
true};
109 struct decay_mode_traits<decay_mode_t<decay_part::transition>> {
110 static auto info() noexcept -> const auto& {
111 static const decay_mode_info i{
"IT", 0, 0,
false};
116 template <decay_part... P>
117 struct decay_mode_traits<decay_mode_t<P...>> {
119 template <decay_part H>
120 static void _append_symbol(decay_mode_t<H> m, std::string& s) {
121 s.append(mode_info(m).symbol);
124 template <decay_part H, decay_part N, decay_part... T>
125 static void _append_symbol(decay_mode_t<H, N, T...>, std::string& s) {
126 s.append(mode_info(decay_mode_t<H>{}).symbol);
128 _append_symbol(decay_mode_t<N, T...>{}, s);
131 static auto _make_symbol() noexcept {
133 _append_symbol(decay_mode_t<P...>{}, s);
138 static auto info() noexcept -> const auto& {
139 static const decay_mode_info i{
141 (0 + ... + mode_info(decay_mode_t<P>{}).proton_count_diff),
142 (0 + ... + mode_info(decay_mode_t<P>{}).neutron_count_diff),
148 template <
typename DecayMode>
149 struct decay_mode_id;
152 struct decay_mode_id<decay_mode_t<decay_part::alpha>>
153 : selector<EAGINE_ID_V(AlphaDcy)> {};
156 struct decay_mode_id<decay_mode_t<decay_part::proton_emi>>
157 : selector<EAGINE_ID_V(PrtnEmissn)> {};
160 struct decay_mode_id<decay_mode_t<decay_part::neutron_emi>>
161 : selector<EAGINE_ID_V(NtrnEmissn)> {};
164 struct decay_mode_id<decay_mode_t<decay_part::electron_cap>>
165 : selector<EAGINE_ID_V(ElnCapDcy)> {};
168 struct decay_mode_id<
169 decay_mode_t<decay_part::electron_cap, decay_part::electron_cap>>
170 : selector<EAGINE_ID_V(2ElnCapDcy)> {};
173 struct decay_mode_id<decay_mode_t<decay_part::electron_cap, decay_part::fission>>
174 : selector<EAGINE_ID_V(ElnCapFisn)> {};
177 struct decay_mode_id<decay_mode_t<decay_part::beta_m>>
178 : selector<EAGINE_ID_V(BetaMDcy)> {};
181 struct decay_mode_id<decay_mode_t<decay_part::beta_m, decay_part::beta_m>>
182 : selector<EAGINE_ID_V(BetaM2Dcy)> {};
185 struct decay_mode_id<decay_mode_t<decay_part::beta_m, decay_part::alpha>>
186 : selector<EAGINE_ID_V(BtaMAlpDcy)> {};
189 struct decay_mode_id<decay_mode_t<decay_part::beta_m, decay_part::neutron_emi>>
190 : selector<EAGINE_ID_V(BetaMNDcy)> {};
193 struct decay_mode_id<decay_mode_t<
195 decay_part::neutron_emi,
196 decay_part::neutron_emi>> : selector<EAGINE_ID_V(BetaMN2Dcy)> {};
199 struct decay_mode_id<decay_mode_t<decay_part::beta_p>>
200 : selector<EAGINE_ID_V(BetaPDcy)> {};
203 struct decay_mode_id<decay_mode_t<decay_part::beta_p, decay_part::beta_p>>
204 : selector<EAGINE_ID_V(BetaP2Dcy)> {};
207 struct decay_mode_id<decay_mode_t<decay_part::beta_p, decay_part::alpha>>
208 : selector<EAGINE_ID_V(BtaPAlpDcy)> {};
211 struct decay_mode_id<decay_mode_t<decay_part::fission>>
212 : selector<EAGINE_ID_V(Fission)> {};
215 struct decay_mode_id<decay_mode_t<decay_part::transition>>
216 : selector<EAGINE_ID_V(Transition)> {};
218 struct known_decay_modes {
219 using m = decay_part;
220 using list = mp_list<
221 decay_mode_t<m::alpha>,
222 decay_mode_t<m::proton_emi>,
223 decay_mode_t<m::neutron_emi>,
224 decay_mode_t<m::electron_cap>,
225 decay_mode_t<m::electron_cap, m::electron_cap>,
226 decay_mode_t<m::electron_cap, m::fission>,
227 decay_mode_t<m::beta_m>,
228 decay_mode_t<m::beta_m, m::beta_m>,
229 decay_mode_t<m::beta_m, m::alpha>,
230 decay_mode_t<m::beta_m, m::neutron_emi>,
231 decay_mode_t<m::beta_m, m::neutron_emi, m::neutron_emi>,
232 decay_mode_t<m::beta_p>,
233 decay_mode_t<m::beta_p, m::beta_p>,
234 decay_mode_t<m::beta_p, m::alpha>,
235 decay_mode_t<m::fission>,
236 decay_mode_t<m::transition>>;
238 template <decay_part... M>
239 static auto get_id(decay_mode_t<M...> = {}) noexcept {
240 return decay_mode_id<decay_mode_t<M...>>::value;
244 return _get_id(symbol, list{});
247 static auto get_info(
identifier_t mode_id) ->
const decay_mode_info* {
248 return _get_info(mode_id, list{});
251 static auto proton_count_diff(
identifier_t mode_id) noexcept ->
int {
252 if(
auto i{get_info(mode_id)}) {
253 return extract(i).proton_count_diff;
258 static auto neutron_count_diff(
identifier_t mode_id) noexcept ->
int {
259 if(
auto i{get_info(mode_id)}) {
260 return extract(i).neutron_count_diff;
267 ->
const decay_mode_info* {
271 template <
typename H,
typename... T>
272 static auto _get_info(
identifier_t id, mp_list<H, T...>)
273 ->
const decay_mode_info* {
274 if(decay_mode_id<H>::value ==
id) {
275 return &mode_info(H{});
277 return _get_info(
id, mp_list<T...>{});
284 template <
typename H,
typename... T>
286 if(are_equal(
string_view(mode_info(H{}).symbol), symbol)) {
289 return _get_id(symbol, mp_list<T...>{});