Newer
Older
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _include_Environment_BaseExponential_h_
#define _include_Environment_BaseExponential_h_
#include <corsika/geometry/Line.h>
#include <corsika/geometry/Point.h>
#include <corsika/geometry/Trajectory.h>
#include <corsika/particles/ParticleProperties.h>
#include <corsika/units/PhysicalUnits.h>
#include <limits>
namespace corsika::environment {
/**
* This class provides the grammage/length conversion functionality for
* (locally) flat exponential atmospheres.
*/
template <class TDerived>
class BaseExponential {
protected:
units::si::LengthType const fLambda;
units::si::InverseLengthType const fInvLambda;
geometry::Point const fP0;
auto const& GetImplementation() const { return *static_cast<TDerived const*>(this); }
// clang-format off
/**
* For a (normalized) axis \f$ \vec{a} \f$, the grammage along a non-orthogonal line with (normalized)
* X = \frac{\varrho_0 \lambda}{\vec{u} \cdot \vec{a}} \left( \exp\left( \vec{u} \cdot \vec{a} \frac{l}{\lambda} \right) - 1 \right)
* \f], where \f$ \varrho_0 \f$ is the density at the starting point.
*
* If \f$ \vec{u} \cdot \vec{a} = 0 \f$, the calculation is just like with a homogeneous density:
* \f[
* X = \varrho_0 l;
* \f]
*/
// clang-format on
geometry::Trajectory<geometry::Line> const& vLine, units::si::LengthType vL,
geometry::Vector<units::si::dimensionless_d> const& vAxis) const {
auto const uDotA = vLine.NormalizedDirection().dot(vAxis).magnitude();
auto const rhoStart = GetImplementation().GetMassDensity(vLine.GetR0());
return rhoStart * (fLambda / uDotA) * (exp(uDotA * vL * fInvLambda) - 1);
// clang-format off
/**
* For a (normalized) axis \f$ \vec{a} \f$, the length of a non-orthogonal line with (normalized)
* direction \f$ \vec{u} \f$ corresponding to grammage \f$ X \f$ is given by
* \f[
* l = \begin{cases}
* \frac{\lambda}{\vec{u} \cdot \vec{a}} \log\left(Y \right), & \text{if} Y := 0 > 1 +
* \vec{u} \cdot \vec{a} \frac{X}{\rho_0 \lambda}
* \infty & \text{else,}
* \end{cases}
* \f] where \f$ \varrho_0 \f$ is the density at the starting point.
*
* If \f$ \vec{u} \cdot \vec{a} = 0 \f$, the calculation is just like with a homogeneous density:
* \f[
* l = \frac{X}{\varrho_0}
* \f]
*/
// clang-format on
geometry::Trajectory<geometry::Line> const& vLine,
units::si::GrammageType vGrammage,
geometry::Vector<units::si::dimensionless_d> const& vAxis) const {
auto const uDotA = vLine.NormalizedDirection().dot(vAxis).magnitude();
auto const rhoStart = GetImplementation().GetMassDensity(vLine.GetR0());
auto const logArg = vGrammage * fInvLambda * uDotA / rhoStart + 1;
return std::numeric_limits<typename decltype(
vGrammage)::value_type>::infinity() *
BaseExponential(geometry::Point const& vP0, units::si::MassDensityType vRho,
units::si::LengthType vLambda)
: fRho0(vRho)
, fLambda(vLambda)
, fInvLambda(1 / vLambda)
, fP0(vP0) {}
};
} // namespace corsika::environment
#endif