Program Listing for File ConservedLEObliquityEvolution.h

Return to documentation for file (/home/kpenev/projects/git/poet/poet_src/unit_tests/testEvolve/ConservedLEObliquityEvolution.h)

#ifndef __CONSERVED_LE_OBLIQUITY_EVOLUTION_H
#define __CONSERVED_LE_OBLIQUITY_EVOLUTION_H

#include "../../Core/Functions.h"
#include "../../Core/InterpSolutionIterator.h"

class ConservedLEConvObliquityEvolution : public Core::OneArgumentDiffFunction {
private:
    const Core::OneArgumentDiffFunction &__lconv_evol;

    double __orbital_angmom;

    double __total2_minus_orbital2;

    double __disk_lifetime;

    double value(double lconv) const
    {
        return std::acos((__total2_minus_orbital2 - lconv * lconv)
                         /
                         (2.0 * lconv * __orbital_angmom));
    }

public:
    ConservedLEConvObliquityEvolution(
        const Core::OneArgumentDiffFunction &lconv_evol,

        double orbital_angmom,

        double total_angmom,

        double disk_lifetime
    ) :
        __lconv_evol(lconv_evol),
        __orbital_angmom(orbital_angmom),
        __total2_minus_orbital2(std::pow(total_angmom, 2)
                                -
                                std::pow(orbital_angmom, 2)),
        __disk_lifetime(disk_lifetime)
    {}

    double operator()(double age) const
    {
        return (age  < __disk_lifetime
                ? 0.0
                : value(__lconv_evol(age)));
    }

    double range_high() const {return __lconv_evol.range_high();}
    double range_low() const {return __lconv_evol.range_low();}

    Core::InterpSolutionIterator crossings(double = 0) const
    {
        throw Core::Error::Runtime(
            "Finding all solutinos of ConservedLEConvObliquityEvolution "
            "not supported!"
        );
    };

    const Core::FunctionDerivatives *deriv(double age) const
    {
        throw Core::Error::Runtime(
            "Derivatives not implemented for 1-0 obliquity evolution."
        );
        if(age < __disk_lifetime)
            return new Core::CubicSplineDerivatives(0.0, 0.0, 0.0);
        const Core::FunctionDerivatives *lconv_deriv = __lconv_evol.deriv(age);
        double obliquity = value(lconv_deriv->order(0)),
               order1 =  - 1.0 / std::sin(obliquity) * (
                   __total2_minus_orbital2
                   /
                   (2.0 * __orbital_angmom * std::pow(lconv_deriv->order(0), 2))
                   -
                   1.0 / (2.0 * __orbital_angmom)
               ),
               order2;
        delete lconv_deriv;
        return new Core::CubicSplineDerivatives(obliquity, order1, order2);
    }

};

class ConservedLERadObliquityEvolution : public Core::OneArgumentDiffFunction {
private:
    const Core::OneArgumentDiffFunction &__lconv_evol;

    const ConservedLEConvObliquityEvolution &__conv_obliq_evol;

    double __orbital_angmom;

    double __initial_obliquity;

    double __initial_lconv_perp;

    double __disk_lifetime;

    double value(
        double lconv,

        double conv_obliq
    ) const
    {
        double lconv_perp = lconv * std::sin(conv_obliq),
               lconv_par = lconv * std::cos(conv_obliq),
               repeated = (std::pow(__orbital_angmom, 2)
                           +
                           std::pow(lconv, 2)
                           +
                           2.0 * __orbital_angmom * lconv_par);

        return __initial_obliquity - std::acos(
            (
                (__orbital_angmom + lconv_par)
                *
                std::sqrt(
                    repeated
                    -
                    std::pow(__initial_lconv_perp, 2)
                )
                +
                __initial_lconv_perp * lconv_perp
            )
            /
            repeated
        );
    }

public:
    ConservedLERadObliquityEvolution(
        const Core::OneArgumentDiffFunction &lconv_evol,

        const ConservedLEConvObliquityEvolution &conv_obliq_evol,

        double orbital_angmom,

        double disk_lifetime
    ) :
        __lconv_evol(lconv_evol),
        __conv_obliq_evol(conv_obliq_evol),
        __orbital_angmom(orbital_angmom),
        __initial_obliquity(conv_obliq_evol(disk_lifetime)),
        __initial_lconv_perp(lconv_evol(disk_lifetime)
                             *
                             std::sin(__initial_obliquity)),
        __disk_lifetime(disk_lifetime)
    {}

    double operator()(double age) const
    {
        return (age < __disk_lifetime
                ? 0.0
                : value(__lconv_evol(age), __conv_obliq_evol(age)));
    }

    double range_high() const {return std::min(__lconv_evol.range_high(),
                                               __conv_obliq_evol.range_high());}
    double range_low() const {return std::max(__lconv_evol.range_low(),
                                              __conv_obliq_evol.range_low());}

    Core::InterpSolutionIterator crossings(double = 0) const
    {
        throw Core::Error::Runtime(
            "Solving ConservedLERadObliquityEvolution not implemented!"
        );
    };

    const Core::FunctionDerivatives *deriv(double) const
    {
        throw Core::Error::Runtime(
            "Differentiating ConservedLERadObliquityEvolution not implemented!"
        );
    }
};

#endif