GridFire 0.0.1a General Purpose Nuclear Network

Loading...
Searching...
No Matches
partition_rauscher_thielemann.cpp
Go to the documentation of this file.
1#include "gridfire/partition/partition_rauscher_thielemann.h"
2#include "gridfire/partition/rauscher_thielemann_partition_data.h"
3#include "gridfire/partition/rauscher_thielemann_partition_data_record.h"
4
5#include "fourdst/logging/logging.h"
6#include "quill/LogMacros.h"
7
8#include <stdexcept>
9#include <algorithm>
10#include <vector>
11#include <array>
12#include <iostream>
13
14 namespace gridfire::partition {
15 static constexpr std::array<double, 24> RT_TEMPERATURE_GRID_T9 = {
16 0.01, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.5,
17 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0
18 };
19
20 RauscherThielemannPartitionFunction::RauscherThielemannPartitionFunction() {
21 constexpr size_t numRecords = rauscher_thielemann_partition_data_len / sizeof(record::RauscherThielemannPartitionDataRecord);
22 m_partitionData.reserve(numRecords);
23 const auto* records = reinterpret_cast<const record::RauscherThielemannPartitionDataRecord*>(rauscher_thielemann_partition_data);
24 for (size_t i = 0; i < numRecords; ++i) {
25 const auto&[z, a, ground_state_spin, normalized_g_values] = records[i];
26 IsotopeData data;
27 data.ground_state_spin = ground_state_spin;
28 std::ranges::copy(normalized_g_values, data.normalized_g_values.begin());
29 const int key = make_key(z, a);
30 LOG_TRACE_L3_LIMIT_EVERY_N(
31 100,
32 m_logger,
33 "(EVERY 100) Adding Rauscher-Thielemann partition data for Z={} A={} (key={})",
34 z,
35 a,
36 key
37 );
38
39 m_partitionData[key] = std::move(data);
40 }
41 }
42
43 double RauscherThielemannPartitionFunction::evaluate(
44 const int z,
45 const int a,
46 const double T9
47 ) const {
48 LOG_TRACE_L2(m_logger, "Evaluating Rauscher-Thielemann partition function for Z={} A={} T9={}", z, a, T9);
49
50 const auto [bound, data, upperIndex, lowerIndex] = find(z, a, T9);
51
52 switch (bound) {
53 case FRONT: {
54 LOG_TRACE_L2(m_logger, "Using FRONT bound for Z={} A={} T9={}", z, a, T9);
55 return data.normalized_g_values.front() * (2.0 * data.ground_state_spin + 1.0);
56 }
57 case BACK: {
58 LOG_TRACE_L2(m_logger, "Using BACK bound for Z={} A={} T9={}", z, a, T9);
59 return data.normalized_g_values.back() * (2.0 * data.ground_state_spin + 1.0);
60 }
61 case MIDDLE: {
62 LOG_TRACE_L2(m_logger, "Using MIDDLE bound for Z={} A={} T9={}", z, a, T9);
63 }
64 }
65
66 const auto [T9_high, G_norm_high, T9_low, G_norm_low] = get_interpolation_points(
67 upperIndex,
68 lowerIndex,
69 data.normalized_g_values
70 );
71
72 const double frac = (T9 - T9_low) / (T9_high - T9_low);
73 const double interpolated_g_norm = G_norm_low + frac * (G_norm_high - G_norm_low);
74
75 return interpolated_g_norm * (2.0 * data.ground_state_spin + 1.0);
76 }
77
78 double RauscherThielemannPartitionFunction::evaluateDerivative(
79 const int z,
80 const int a,
81 const double T9
82 ) const {
83 LOG_TRACE_L2(m_logger, "Evaluating derivative of Rauscher-Thielemann partition function for Z={} A={} T9={}", z, a, T9);
84 const auto [bound, data, upperIndex, lowerIndex] = find(z, a, T9);
85 if (bound == FRONT || bound == BACK) {
86 LOG_TRACE_L2(m_logger, "Derivative is zero for Z={} A={} T9={} (bound: {})", z, a, T9, bound == FRONT ? "FRONT" : "BACK");
87 return 0.0; // Derivative is zero at the boundaries
88 }
89 const auto [T9_high, G_norm_high, T9_low, G_norm_low] = get_interpolation_points(
90 upperIndex,
91 lowerIndex,
92 data.normalized_g_values
93 );
94 const double slope_g_norm = (G_norm_high - G_norm_low) / (T9_high - T9_low);
95 return slope_g_norm * (2.0 * data.ground_state_spin + 1.0);
96 }
97
98 bool RauscherThielemannPartitionFunction::supports(
99 const int z,
100 const int a
101 ) const {
102 return m_partitionData.contains(make_key(z, a));
103 }
104
105 RauscherThielemannPartitionFunction::InterpolationPoints RauscherThielemannPartitionFunction::get_interpolation_points(
106 const size_t upper_index,
107 const size_t lower_index,
108 const std::array<double, 24>& normalized_g_values
109 ) {
110 const double T_high = RT_TEMPERATURE_GRID_T9[upper_index];
111 const double G_norm_high = normalized_g_values[upper_index];
112 const double T_low = RT_TEMPERATURE_GRID_T9[lower_index];
113 const double G_norm_low = normalized_g_values[lower_index];
114 return {T_high, G_norm_high, T_low, G_norm_low};
115 }
116
117 RauscherThielemannPartitionFunction::IdentifiedIsotope RauscherThielemannPartitionFunction::find(
118 const int z,
119 const int a,
120 const double T9
121 ) const {
122 const auto key = make_key(z, a);
123 const auto it = m_partitionData.find(key);
124
125 if (it == m_partitionData.end()) {
126 LOG_ERROR(m_logger, "Rauscher-Thielemann partition function data for Z={} A={} not found.", z, a);
127 throw std::out_of_range("Partition function data not found for Z=" + std::to_string(z) + " A=" + std::to_string(a));
128 }
129
130 const IsotopeData& data = it->second;
131 const auto upper_it = std::ranges::lower_bound(RT_TEMPERATURE_GRID_T9, T9);
132 Bounds bound;
133 if (upper_it == RT_TEMPERATURE_GRID_T9.begin()) {
134 bound = FRONT; // T9 is below the first grid point
135 } else if (upper_it == RT_TEMPERATURE_GRID_T9.end()) {
136 bound = BACK; // T9 is above the last grid point
137 } else {
138 bound = MIDDLE; // T9 is within the grid
139 }
140 const size_t upper_index = std::distance(RT_TEMPERATURE_GRID_T9.begin(), upper_it);
141 const size_t lower_index = upper_index - 1;
142 return {bound, data, upper_index, lower_index};
143 }
144
145 constexpr int RauscherThielemannPartitionFunction::make_key(
146 const int z,
147 const int a
148 ) {
149 return z * 1000 + a; // Simple key generation for Z and A
150 }
151}
gridfire::partition::RauscherThielemannPartitionFunction::find
IdentifiedIsotope find(int z, int a, double T9) const
Identify isotope entry and grid indices for given T9.
Definition partition_rauscher_thielemann.cpp:117
gridfire::partition::RauscherThielemannPartitionFunction::get_interpolation_points
static InterpolationPoints get_interpolation_points(const size_t upper_index, const size_t lower_index, const std::array< double, 24 > &normalized_g_values)
Get interpolation points from normalized G array.
Definition partition_rauscher_thielemann.cpp:105
gridfire::partition::RauscherThielemannPartitionFunction::m_partitionData
std::unordered_map< int, IsotopeData > m_partitionData
Map of isotope key to data.
Definition partition_rauscher_thielemann.h:113
gridfire::partition::RauscherThielemannPartitionFunction::m_logger
quill::Logger * m_logger
Definition partition_rauscher_thielemann.h:112
gridfire::partition::RauscherThielemannPartitionFunction::supports
bool supports(int z, int a) const override
Check if partition data exists for given isotope.
Definition partition_rauscher_thielemann.cpp:98
gridfire::partition::RauscherThielemannPartitionFunction::Bounds
Bounds
Indicator for temperature grid bound position.
Definition partition_rauscher_thielemann.h:89
gridfire::partition::RauscherThielemannPartitionFunction::FRONT
@ FRONT
Below first grid point.
Definition partition_rauscher_thielemann.h:90
gridfire::partition::RauscherThielemannPartitionFunction::MIDDLE
@ MIDDLE
Between grid points.
Definition partition_rauscher_thielemann.h:92
gridfire::partition::RauscherThielemannPartitionFunction::BACK
@ BACK
Above last grid point.
Definition partition_rauscher_thielemann.h:91
gridfire::partition::RauscherThielemannPartitionFunction::evaluateDerivative
double evaluateDerivative(int z, int a, double T9) const override
Evaluate temperature derivative of partition function.
Definition partition_rauscher_thielemann.cpp:78
gridfire::partition::RauscherThielemannPartitionFunction::make_key
static constexpr int make_key(int z, int a)
Generate integer key for isotope (z,a).
Definition partition_rauscher_thielemann.cpp:145
gridfire::partition::RauscherThielemannPartitionFunction::RauscherThielemannPartitionFunction
RauscherThielemannPartitionFunction()
Construct and populate partition data.
Definition partition_rauscher_thielemann.cpp:20
gridfire::partition::RauscherThielemannPartitionFunction::evaluate
double evaluate(int z, int a, double T9) const override
Evaluate partition function for isotope at temperature.
Definition partition_rauscher_thielemann.cpp:43
gridfire::partition
Definition partition_composite.h:15
gridfire::partition::RT_TEMPERATURE_GRID_T9
static constexpr std::array< double, 24 > RT_TEMPERATURE_GRID_T9
Definition partition_rauscher_thielemann.cpp:15
partition_rauscher_thielemann.h
rauscher_thielemann_partition_data.h
rauscher_thielemann_partition_data_len
const size_t rauscher_thielemann_partition_data_len
Definition rauscher_thielemann_partition_data.h:69897
rauscher_thielemann_partition_data
const unsigned char rauscher_thielemann_partition_data[]
Definition rauscher_thielemann_partition_data.h:5
rauscher_thielemann_partition_data_record.h
gridfire::partition::RauscherThielemannPartitionFunction::IdentifiedIsotope
Definition partition_rauscher_thielemann.h:105
gridfire::partition::RauscherThielemannPartitionFunction::InterpolationPoints
Definition partition_rauscher_thielemann.h:99
gridfire::partition::RauscherThielemannPartitionFunction::IsotopeData
Definition partition_rauscher_thielemann.h:95
gridfire::partition::RauscherThielemannPartitionFunction::IsotopeData::normalized_g_values
std::array< double, 24 > normalized_g_values
Normalized G values on RT grid.
Definition partition_rauscher_thielemann.h:97
gridfire::partition::RauscherThielemannPartitionFunction::IsotopeData::ground_state_spin
double ground_state_spin
Spin of the isotope ground state.
Definition partition_rauscher_thielemann.h:96
gridfire::partition::record::RauscherThielemannPartitionDataRecord
Packed binary record of Rauscher-Thielemann partition function data for an isotope.
Definition rauscher_thielemann_partition_data_record.h:17