![]() |
|
|||
File indexing completed on 2025-09-17 08:54:06
0001 //------------------------------- -*- C++ -*- -------------------------------// 0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details 0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 0004 //---------------------------------------------------------------------------// 0005 //! \file corecel/grid/SplineDerivCalculator.hh 0006 //---------------------------------------------------------------------------// 0007 #pragma once 0008 0009 #include <memory> 0010 #include <vector> 0011 0012 #include "corecel/Assert.hh" 0013 #include "corecel/Macros.hh" 0014 #include "corecel/Types.hh" 0015 #include "corecel/cont/Span.hh" 0016 0017 #include "GridTypes.hh" 0018 #include "UniformGrid.hh" 0019 0020 #include "detail/GridAccessor.hh" 0021 0022 namespace celeritas 0023 { 0024 //---------------------------------------------------------------------------// 0025 /*! 0026 * Calculate the second derivatives of a cubic spline. 0027 * 0028 * See section 3.3: Cubic Spline Interpolation in \cite{press-nr-1992} for a 0029 * review of interpolating cubic splines and an algorithm for calculating the 0030 * second derivatives. 0031 * 0032 * Determining the polynomial coefficients \$ a_0, a_1, a_2 \f$ and \$f a_3 \f$ 0033 * of a cubic spline \f$ S(x) \f$ (see: \sa SplineInterpolator) requires 0034 * solving a tridiagonal, linear system of equations for the second 0035 * derivatives. For \f$ n \f$ points \f$ (x_i, y_i) \f$ and \f$ n \f$ unknowns 0036 * \f$ S''_i \f$ there are \f$ n - 2 \f$ equations of the form 0037 * \f[ 0038 h_{i - 1} S''_{i - 1} + 2 (h_{i - 1} + h_i) S''i + h_i S''_{i + 1} = 6 r_i, 0039 * \f] 0040 * where \f$ r_i = frac{\Delta y_i}{h_i} - frac{\Delta y_{i - 1}}{h_{i - 1}} 0041 * \f$ and \f$ h_i = \Delta x_i = x_{i + 1} - x_i \f$. 0042 * 0043 * Specifying the boundary conditions gives the remaining two equations. 0044 * Natural boundary conditions set \f$ S''_0 = S''_{n - 1} = 0 \f$, which leads 0045 * to the following initial and final equations: 0046 * \f{align}{ 0047 2 (h_0 + h_1) S''_1 + h_1 S''_2 &= 6 r_1 // 0048 h_{n - 3} S''_{n - 3} + 2 (h_{n - 3} + h_{n - 2}) S''_{n - 2} 0049 &= 6 r_{n - 2}. 0050 * \f} 0051 * 0052 * The points \f$ x_0, x_1, \dots , x_{n - 1} \f$ where the spline changes from 0053 * one cubic to the next are called knots. "Not-a-knot" boundary conditions 0054 * require the third derivative \f$ S'''_i \f$ to be continous across the first 0055 * and final interior knots, \f$ x_1 \f$ and \f$ x_{n - 2} \f$ (the name refers 0056 * to the polynomials on the interval \f$ (x_0, x_1) \f$ and \f$ (x_1, x_2) 0057 * \f$ being the same cubic, so \f$ x_1 \f$ is "not a knot"). This constraint 0058 * gives the final two equations: 0059 * \f{align}{ 0060 \frac{(h_0 + 2 h_1)(h_0 + h_1)}{h_1} S''_1 + \frac{h_1^2 - h_0^2}{h_1} 0061 S''_2 &= 6 r_1 // 0062 \frac{h_{n - 3}^2 - h_{n - 2}^2}{h_{n - 3}} S''_{n - 3} + \frac{(h_{n - 3} 0063 + h_{n - 2})(2 h_{n - 3} + h_{n - 2})}{h_{n - 3}} S''_{n - 2} &= 6 r_{n - 2} 0064 * \f} 0065 * Once the system of equations has been solved for the second derivatives, the 0066 * derivatives \f$ S''_0 \f$ and \f$ S''_{n - 1} \f$ can be recovered: 0067 * \f{align}{ 0068 S''_0 &= \frac{(h_0 + h_1) S''_1 - h_0 S''_2}{h_1} \\ 0069 S''_{n - 1} &= \frac{(h_{n - 3} + h_{n - 2}) S''_{n - 2} - h_{n - 2} 0070 S''_{n - 3}}{h_{n - 3}} 0071 * \f} 0072 */ 0073 class SplineDerivCalculator 0074 { 0075 public: 0076 //!@{ 0077 //! \name Type aliases 0078 using SpanConstReal = detail::GridAccessor::SpanConstReal; 0079 using Values = detail::GridAccessor::Values; 0080 using VecReal = std::vector<real_type>; 0081 using BoundaryCondition = SplineBoundaryCondition; 0082 //!@} 0083 0084 public: 0085 // Construct with boundary conditions 0086 explicit SplineDerivCalculator(BoundaryCondition); 0087 0088 // Calculate the second derivatives 0089 VecReal operator()(SpanConstReal, SpanConstReal) const; 0090 VecReal operator()(UniformGridRecord const&, Values const&) const; 0091 VecReal operator()(NonuniformGridRecord const&, Values const&) const; 0092 0093 // Calculate the second derivatives from an inverted uniform grid 0094 VecReal calc_from_inverse(UniformGridRecord const&, Values const&) const; 0095 0096 //! Minimum grid size for cubic spline interpolation 0097 static CELER_CONSTEXPR_FUNCTION int min_grid_size() { return 5; } 0098 0099 private: 0100 //// TYPES //// 0101 0102 using Real3 = Array<real_type, 3>; 0103 0104 //// DATA //// 0105 0106 BoundaryCondition bc_; 0107 0108 //// HELPER FUNCTIONS //// 0109 0110 template<class GridAccessor> 0111 VecReal operator()(GridAccessor&&) const; 0112 0113 template<class GridAccessor> 0114 void calc_initial_coeffs(GridAccessor const&, Real3&, real_type&) const; 0115 template<class GridAccessor> 0116 void calc_final_coeffs(GridAccessor const&, Real3&, real_type&) const; 0117 template<class GridAccessor> 0118 void calc_boundaries(GridAccessor const&, VecReal&) const; 0119 template<class GridAccessor> 0120 VecReal calc_geant_derivatives(GridAccessor const&) const; 0121 }; 0122 0123 //---------------------------------------------------------------------------// 0124 } // namespace celeritas
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |