Celeritas 0.6.0-dev.115+3b60a5fd
Loading...
Searching...
No Matches
Public Types | Public Member Functions | List of all members
celeritas::SplineDerivCalculator Class Reference

Calculate the second derivatives of a cubic spline. More...

#include <SplineDerivCalculator.hh>

Public Types

enum class  BoundaryCondition { natural = 0 , not_a_knot , geant , size_ }
 Cubic spline interpolation boundary conditions. More...
 
Type aliases
using SpanConstReal = detail::SpanGridAccessor::SpanConstReal
 
using Values = detail::XsGridAccessor::Values
 
using VecReal = std::vector< real_type >
 

Public Member Functions

 SplineDerivCalculator (BoundaryCondition)
 Construct from boundary conditions.
 
VecReal operator() (SpanConstReal, SpanConstReal) const
 Calculate the second derivatives from spans.
 
VecReal operator() (XsGridData const &, Values const &) const
 Calculate the second derivatives from grid data.
 
template<class GA >
auto operator() (GA &&grid) const -> VecReal
 Calculate the second derivatives.
 
template<class GA >
void calc_initial_coeffs (GA const &grid, Real3 &tridiag, real_type &rhs) const
 Calculate the coefficients for the first row using the boundary conditions.
 
template<class GA >
void calc_final_coeffs (GA const &grid, Real3 &tridiag, real_type &rhs) const
 Calculate the coefficients for the last row using the boundary conditions.
 
template<class GA >
void calc_boundaries (GA const &grid, VecReal &deriv) const
 Calculate the first and last values of the second derivative.
 
template<class GA >
auto calc_geant_derivatives (GA const &grid) const -> VecReal
 Calculate the second derivatives.
 

Detailed Description

Calculate the second derivatives of a cubic spline.

See section 3.3: Cubic Spline Interpolation in [press-nr-1992] for a review of interpolating cubic splines and an algorithm for calculating the second derivatives.

Determining the polynomial coefficients $ a_0, a_1, a_2 \( and \$f a_3 \) of a cubic spline \( S(x) \) (see:

See also
SplineInterpolator) requires solving a tridiagonal, linear system of equations for the second derivatives. For \( n \) points \( (x_i, y_i) \) and \( n \) unknowns \( S''_i \) there are \( n - 2 \) equations of the form

\[ h_{i - 1} S''_{i - 1} + 2 (h_{i - 1} + h_i) S''i + h_i S''_{i + 1} = 6 r_i, \]

where \( r_i = frac{\Delta y_i}{h_i} - frac{\Delta y_{i - 1}}{h_{i - 1}} \) and \( h_i = \Delta x_i = x_{i + 1} - x_i \).

Specifying the boundary conditions gives the remaining two equations. Natural boundary conditions set \( S''_0 = S''_{n - 1} = 0 \), which leads to the following initial and final equations:

\begin{align} 2 (h_0 + h_1) S''_1 + h_1 S''_2 &= 6 r_1 // h_{n - 3} S''_{n - 3} + 2 (h_{n - 3} + h_{n - 2}) S''_{n - 2} &= 6 r_{n - 2}. \end{align}

The points \( x_0, x_1, \dots , x_{n - 1} \) where the spline changes from one cubic to the next are called knots. "Not-a-knot" boundary conditions require the third derivative \( S'''_i \) to be continous across the first and final interior knots, \( x_1 \) and \( x_{n - 2} \) (the name refers to the polynomials on the interval \( (x_0, x_1) \) and \( (x_1, x_2) \) being the same cubic, so \( x_1 \) is "not a knot"). This constraint gives the final two equations:

\begin{align} \frac{(h_0 + 2 h_1)(h_0 + h_1)}{h_1} S''_1 + \frac{h_1^2 - h_0^2}{h_1} S''_2 &= 6 r_1 // \frac{h_{n - 3}^2 - h_{n - 2}^2}{h_{n - 3}} S''_{n - 3} + \frac{(h_{n - 3} + h_{n - 2})(2 h_{n - 3} + h_{n - 2})}{h_{n - 3}} S''_{n - 2} &= 6 r_{n - 2} \end{align}

Once the system of equations has been solved for the second derivatives, the derivatives \( S''_0 \) and \( S''_{n - 1} \) can be recovered:

\begin{align} S''_0 &= \frac{(h_0 + h_1) S''_1 - h_0 S''_2}{h_1} \\ S''_{n - 1} &= \frac{(h_{n - 3} + h_{n - 2}) S''_{n - 2} - h_{n - 2} S''_{n - 3}}{h_{n - 3}} \end{align}

Member Enumeration Documentation

◆ BoundaryCondition

Cubic spline interpolation boundary conditions.

Enumerator
geant 

Geant4's "not-a-knot".

Member Function Documentation

◆ calc_geant_derivatives()

template<class GA >
auto celeritas::SplineDerivCalculator::calc_geant_derivatives ( GA const grid) const -> VecReal

Calculate the second derivatives.

This is a hack to produce the same interpolation results as Geant4. The calculation here is identical to Geant4's G4PhysicsVector::ComputeSecDerivative1, which is based off the algorithm for calculating the second derivatives of a cubic spline in Numerical Recipes, modified for not-a-knot boundary conditions.

Note that here the coefficients are divided by \( h_i + h_{i + 1} \).

Todo:
While Geant4 supposedly uses not-a-knot boundary conditions, these second derivatives differ from the expected values.

The documentation for this class was generated from the following files: