Program Listing for File EccentricityExpansionCoefficients.cpp

Return to documentation for file (/home/kpenev/projects/git/poet/poet_src/Evolve/EccentricityExpansionCoefficients.cpp)

#define BUILDING_LIBRARY
#include "EccentricityExpansionCoefficients.h"

namespace Evolve {

    int EccentricityExpansionCoefficients::inner_index(int msign,
                                                       int s,
                                                       int epower) const
    {
        assert(std::abs(msign) < 2);

        return (epower - s + 2 * std::min(msign, s - msign)) / 2;
    }

    std::pair<double, double> EccentricityExpansionCoefficients::p_m2s(
        double e,
        int s,
        unsigned max_e_power,
        bool deriv
    ) const
    {
        std::pair<double, double> result(0.0, 0.0);

        double e2 = std::pow(e, 2);
        int min_n = std::max(1, -s - 1),
            gamma_ind1 = s + __max_e_power + 2,
            e_pow_ind = s + 2 * min_n - (deriv ? 1 : 0);
        assert(e_pow_ind + (deriv ? 1 : 0) >= 0);
        double e_pow = (e_pow_ind < 0 ? 0.0 : std::pow(e, e_pow_ind)),
               coef = (deriv ? s + 2 * min_n : 1);
        for(
            int gamma_ind2 = 0;
            gamma_ind2 <= inner_index(-1, s, max_e_power);
            ++gamma_ind2
        ) {
            result.second = (coef
                             *
                             __gamma_minus[gamma_ind1][gamma_ind2]
                             *
                             e_pow);
            result.first += result.second;
            e_pow *= e2;
            if(deriv) coef += 2;
        }
        return result;
    }

    std::pair<double, double> EccentricityExpansionCoefficients::p_0s(
        double e,
        int s,
        unsigned max_e_power,
        bool deriv
    ) const
    {
        std::pair<double, double> result(0.0, 0.0);

        double e2 = std::pow(e, 2);
        int min_n = std::max(0, -s),
            alpha_ind1 = s + __max_e_power,
            e_pow_ind = s + 2 * min_n - (deriv ? 1 : 0);
        assert(e_pow_ind + (deriv ? 1 : 0) >= 0);
        double e_pow = (e_pow_ind < 0 ? 0.0 : std::pow(e, e_pow_ind)),
               coef = (deriv ? s + 2 * min_n : 1);
        for(
            int alpha_ind2 = 0;
            alpha_ind2 <= inner_index(0, s, max_e_power);
            ++alpha_ind2
        ) {
            result.second = coef * __alpha[alpha_ind1][alpha_ind2] * e_pow;
            result.first += result.second;
            e_pow *= e2;
            if(deriv) coef += 2;
        }
        return result;
    }

    std::pair<double, double> EccentricityExpansionCoefficients::p_p2s(
        double e,
        int s,
        unsigned max_e_power,
        bool deriv
    ) const
    {
        std::pair<double, double> result(0.0, 0.0);

        double e2 = std::pow(e, 2);
        int min_n = std::max(-1, -s + 1),
            gamma_ind1 = s + __max_e_power - 2,
            e_pow_ind = s + 2 * min_n - (deriv ? 1 : 0);
        assert(e_pow_ind + (deriv ? 1 : 0) >= 0);
        double e_pow = (e_pow_ind < 0 ? 0.0 : std::pow(e, e_pow_ind)),
               coef = (deriv ? s + 2 * min_n : 1);
        for(
            int gamma_ind2 = 0;
            gamma_ind2 <= inner_index(1, s, max_e_power);
            ++gamma_ind2
        ) {
            result.second = coef * __gamma_plus[gamma_ind1][gamma_ind2] * e_pow;
            result.first += result.second;
            e_pow *= e2;
            if(deriv) coef += 2;
        }
        return result;
    }

    void EccentricityExpansionCoefficients::read(
        const std::string &tabulated_pms_fname,
        int max_e_power
    )
    {
        std::ifstream tabulated_coef(tabulated_pms_fname.c_str());
        if(!tabulated_coef) throw Core::Error::IO(
            "Unable to open eccentricity expansion file: "
            +
            tabulated_pms_fname
            +
            "!"
        );
        tabulated_coef >> __max_e_power;
        if(max_e_power >= 0) {
            if(__max_e_power<static_cast<unsigned>(max_e_power)) {
                std::ostringstream msg;
                msg << "Eccentricity expansion file '"
                    << tabulated_pms_fname
                    << "' stops at lower eccentricity power ("
                    << __max_e_power
                    <<") than requested ("
                    << max_e_power
                    << ") in EccentricityExpansionCoefficients::read()!";
                throw Core::Error::BadFunctionArguments(msg.str());
            }
            __max_e_power = max_e_power;
        }

        __alpha.resize(2 * __max_e_power + 1);
        __gamma_plus.resize(2 * __max_e_power + 1);
        __gamma_minus.resize(2 * __max_e_power + 1);

        for(
            int epower = 0;
            epower <= static_cast<int>(__max_e_power);
            ++epower
        ) {
            for(int s = -epower - 2; s <= epower-2; s += 2) {
                if(s) {
                    assert(s + static_cast<int>(__max_e_power) + 2 >= 0);
                    assert(s + __max_e_power + 2 < __gamma_minus.size());
                    std::vector<double>
                        &destination = __gamma_minus[s + __max_e_power + 2];
                    if(destination.size() == 0)
                        destination.resize(inner_index(-1, s, __max_e_power)
                                           +
                                           1);
                    assert(inner_index(-1, s, epower) >= 0);
                    assert(inner_index(-1, s, epower)
                            <static_cast<int>(destination.size()));
                    tabulated_coef >> destination[inner_index(-1,
                                                              s,
                                                              epower)];
                }
            }
            for(int s = -epower; s <= epower; s += 2) {
                assert(s + static_cast<int>(__max_e_power) >= 0);
                assert(s + __max_e_power < __alpha.size());
                std::vector<double> &destination=__alpha[s + __max_e_power];
                if(destination.size() == 0)
                    destination.resize(inner_index(0, s, __max_e_power) + 1);
                assert(inner_index(0, s, epower) >= 0);
                assert(inner_index(0, s, epower)
                        <static_cast<int>(destination.size()));
                tabulated_coef >> destination[inner_index(0, s, epower)];
            }
            for(int s = -epower + 2; s <= epower + 2; s += 2) {
                if(s) {
                    assert(s + static_cast<int>(__max_e_power) - 2 >= 0);
                    assert(s + __max_e_power - 2 < __gamma_plus.size());
                    std::vector<double>
                        &destination=__gamma_plus[s + __max_e_power - 2];
                    if(destination.size() == 0)
                        destination.resize(inner_index(1, s, __max_e_power)
                                           +
                                           1);
                    assert(inner_index(1, s, epower) >= 0);
                    assert(inner_index(1, s, epower)
                            <static_cast<int>(destination.size()));
                    tabulated_coef >> destination[inner_index(1, s, epower)];
                }
            }
        }
        __useable = true;
    }

    std::pair<double, double> EccentricityExpansionCoefficients::operator()(
        int m,
        int s,
        double e,
        unsigned max_e_power,
        bool deriv
    ) const
    {
        if(!__useable)
            throw Core::Error::Runtime(
                "Attempting to evaluate Pms before reading in eccentricity "
                "expansion coefficients!"
            );

        std::pair<double, double> zero(0.0, 0.0);

        if(
            s < -static_cast<int>(max_e_power) + m
            ||
            s > static_cast<int>(max_e_power) + m
        )
            return zero;

        switch(m) {
            case -2 : return (s == 0 ? zero : p_m2s(e, s, max_e_power, deriv));
            case 0  : return p_0s(e, s, max_e_power, deriv);
            case 2  : return (s == 0 ? zero : p_p2s(e, s, max_e_power, deriv));
            default : throw Core::Error::BadFunctionArguments(
                          "Asking for p_{m,s} with m other than +-2 and 0"
                      );
        };
    }

} //End Evolve namespace.