File indexing completed on 2025-09-18 09:09:06
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009 #include <cmath>
0010
0011 #include "corecel/data/Collection.hh"
0012 #include "corecel/grid/Interpolator.hh"
0013 #include "corecel/grid/SplineInterpolator.hh"
0014 #include "corecel/grid/UniformGrid.hh"
0015 #include "corecel/math/Quantity.hh"
0016
0017 #include "XsGridData.hh"
0018
0019 namespace celeritas
0020 {
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 class RangeCalculator
0038 {
0039 public:
0040
0041
0042 using Energy = RealQuantity<XsGridRecord::EnergyUnits>;
0043 using Values
0044 = Collection<real_type, Ownership::const_reference, MemSpace::native>;
0045
0046
0047 public:
0048
0049 inline CELER_FUNCTION
0050 RangeCalculator(XsGridRecord const& grid, Values const& values);
0051
0052
0053 inline CELER_FUNCTION real_type operator()(Energy energy) const;
0054
0055 private:
0056 UniformGridRecord const& data_;
0057 Values const& reals_;
0058
0059 CELER_FORCEINLINE_FUNCTION real_type get(size_type index) const;
0060 };
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 CELER_FUNCTION
0071 RangeCalculator::RangeCalculator(XsGridRecord const& grid, Values const& values)
0072 : data_(grid.lower), reals_(values)
0073 {
0074 CELER_EXPECT(data_);
0075 CELER_EXPECT(!grid.upper);
0076 }
0077
0078
0079
0080
0081
0082 CELER_FUNCTION real_type RangeCalculator::operator()(Energy energy) const
0083 {
0084 CELER_ASSERT(energy > zero_quantity());
0085 UniformGrid loge_grid(data_.grid);
0086 real_type const loge = std::log(energy.value());
0087
0088 if (loge <= loge_grid.front())
0089 {
0090 real_type result = this->get(0);
0091
0092 result *= std::exp(real_type(.5) * (loge - loge_grid.front()));
0093 return result;
0094 }
0095 else if (loge >= loge_grid.back())
0096 {
0097
0098 return this->get(loge_grid.size() - 1);
0099 }
0100
0101
0102 auto idx = loge_grid.find(loge);
0103 CELER_ASSERT(idx + 1 < loge_grid.size());
0104
0105 real_type result;
0106 if (data_.derivative.empty())
0107 {
0108
0109 result = LinearInterpolator<real_type>(
0110 {std::exp(loge_grid[idx]), this->get(idx)},
0111 {std::exp(loge_grid[idx + 1]), this->get(idx + 1)})(
0112 value_as<Energy>(energy));
0113 }
0114 else
0115 {
0116
0117 real_type lower_deriv = reals_[data_.derivative[idx]];
0118 real_type upper_deriv = reals_[data_.derivative[idx + 1]];
0119
0120 result = SplineInterpolator<real_type>(
0121 {std::exp(loge_grid[idx]), this->get(idx), lower_deriv},
0122 {std::exp(loge_grid[idx + 1]), this->get(idx + 1), upper_deriv})(
0123 value_as<Energy>(energy));
0124 }
0125 return result;
0126 }
0127
0128
0129
0130
0131
0132 CELER_FUNCTION real_type RangeCalculator::get(size_type index) const
0133 {
0134 CELER_EXPECT(index < reals_.size());
0135 return reals_[data_.value[index]];
0136 }
0137
0138
0139 }