IAP GITLAB

Skip to content
Snippets Groups Projects
BaseExponential.h 3.97 KiB
Newer Older
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
/*
ralfulrich's avatar
ralfulrich committed
 * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
 *
 * 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.
   */
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
  template <class TDerived>
  class BaseExponential {
  protected:
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
    units::si::MassDensityType const fRho0;
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
    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)
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
     * direction \f$ \vec{u} \f$ is given by
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
     *   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.
     * 
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
     * 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
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
    units::si::GrammageType IntegratedGrammage(
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
        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());
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
      if (uDotA == 0) {
        return vL * rhoStart;
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
      } else {
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
        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)
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
     * direction \f$ \vec{u} \f$ corresponding to grammage \f$ X \f$ is given by
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
     *   \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.
     * 
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
     * 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
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
    units::si::LengthType ArclengthFromGrammage(
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
        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());
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
      if (uDotA == 0) {
        return vGrammage / rhoStart;
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
      } else {
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
        auto const logArg = vGrammage * fInvLambda * uDotA / rhoStart + 1;
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
        if (logArg > 0) {
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
          return fLambda / uDotA * log(logArg);
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
        } else {
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
          return std::numeric_limits<typename decltype(
                     vGrammage)::value_type>::infinity() *
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
                 units::si::meter;
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
    BaseExponential(geometry::Point const& vP0, units::si::MassDensityType vRho,
                    units::si::LengthType vLambda)
        : fRho0(vRho)
        , fLambda(vLambda)
        , fInvLambda(1 / vLambda)
        , fP0(vP0) {}
Maximilian Reininghaus's avatar
Maximilian Reininghaus committed
  };

} // namespace corsika::environment
#endif