Program Listing for File testGravitationalPotential.cpp

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

#include "testGravitationalPotential.h"

namespace Evolve {

    void test_GravitationalPotential::print_orbit(
        const EccentricOrbit &orbit
    ) const
    {
        std::cout << std::setw(25) << "phase"
                  << std::setw(25) << "x"
                  << std::setw(25) << "y"
                  << std::setw(25) << "z"
                  << std::endl;
        for(double phase = 0.0; phase < 4.0 * M_PI; phase += 0.001 * M_PI) {
            Eigen::Vector3d secondary_position = orbit.secondary_position(phase);
            std::cout << std::setw(25) << phase
                      << std::setw(25) << secondary_position[0]
                      << std::setw(25) << secondary_position[1]
                      << std::setw(25) << secondary_position[2]
                      << std::endl;
        }
    }

    void test_GravitationalPotential::print_tidal_potential(
        double primary_mass,
        double secondary_mass,
        double semimajor,
        double eccentricity,
        double inclination,
        double arg_of_periapsis,
        const Eigen::Vector3d &position,
        unsigned e_order
    ) const
    {
        TidalPotential exact_potential(primary_mass,
                                       secondary_mass,
                                       semimajor,
                                       eccentricity,
                                       inclination,
                                       arg_of_periapsis);
        TidalPotentialExpansion approx_potential(primary_mass,
                                                 secondary_mass,
                                                 semimajor,
                                                 eccentricity,
                                                 inclination,
                                                 arg_of_periapsis);
        approx_potential.set_eccentricity_order(e_order);


        double orbital_period = exact_potential.orbit().orbital_period();
        std::ostringstream Uexact_label, Uapprox_label;
        Uexact_label << "Uexact("
                     << "x=" << position[0]
                     << ", y=" << position[1]
                     << ", z=" << position[2]
                     << ", t=time)";
        Uapprox_label << "Uapprox("
                      << "x=" << position[0]
                      << ", y=" << position[1]
                      << ", z=" << position[2]
                      << ", t=time)";
        std::cout << std::setw(35) << "time/Porb"
                  << std::setw(35) << Uexact_label.str()
                  << std::setw(35) << Uapprox_label.str()
                  << std::endl;
        for(
            double time = 0;
            time < 5.0 * orbital_period;
            time += 0.01 * orbital_period
        ) {
            std::cout << std::setw(35) << time/orbital_period
                      << std::setw(35) << exact_potential(position, time)
                      << std::setw(35) << approx_potential(position, time)
                      << std::endl;
        }
    }


    double test_GravitationalPotential::abs_expected_precision(
        const Eigen::Vector3d &position,
        const EccentricOrbit &orbit
    ) const
    {
        const double safety = 1.1;
        return safety * (
            (
                Core::AstroConst::G
                *
                orbit.secondary_mass() * Core::AstroConst::solar_mass
                /
                (
                    orbit.semimajor() * Core::AstroConst::solar_radius
                    *
                    (1.0 - orbit.eccentricity())
                )
            )
            *
            std::pow(
                (
                    position.norm()
                    /
                    (orbit.semimajor() * (1.0 - orbit.eccentricity()))
                ),
                3
            )
        );
    }

    void test_GravitationalPotential::test_single_point(
        TidalPotentialExpansion &approx_potential,
        const TidalPotential &exact_potential,
        const Eigen::Vector3d &position
    )
    {
        double orbital_period = exact_potential.orbit().orbital_period(),
               abs_tolerance = abs_expected_precision(position,
                                                      exact_potential.orbit());

        std::ostringstream message_start;
        message_start << "M = " << exact_potential.orbit().primary_mass()
                      << "; M' = " << exact_potential.orbit().secondary_mass()
                      << "; a = " << exact_potential.orbit().semimajor()
                      << "; e = " << exact_potential.orbit().eccentricity()
                      << "; inclination = " << exact_potential.inclination()
                      << "; periapsis = " << exact_potential.arg_of_periapsis()
                      << "; U(x = " << position[0]
                      << ", y = " << position[1]
                      << ", z = " << position[2];

        for(
            double time = 0;
            time < 5.0 * orbital_period;
            time += 0.03 * M_PI * orbital_period
        ) {
            double expected = exact_potential(position, time);
            double got = approx_potential(position, time);

            std::ostringstream message;
            message << message_start.str()
                    << ", t = " << time
                    << " = " << time / orbital_period
                    << " Porb): expected " << expected
                    << "; got " << got
                    << "; difference " << got - expected
                    << " > " << abs_tolerance;

            TEST_ASSERT_MSG(
                check_diff(got,
                           expected,
                           0.0,
                           abs_tolerance),
                message.str().c_str()
            );
        }
    }

    void test_GravitationalPotential::test_system(
        double primary_mass,
        double secondary_mass,
        double semimajor,
        double eccentricity,
        double inclination,
        double arg_of_periapsis,
        unsigned e_order
    )
    {
        TidalPotential exact_potential(primary_mass,
                                       secondary_mass,
                                       semimajor,
                                       eccentricity,
                                       inclination,
                                       arg_of_periapsis);
        TidalPotentialExpansion approx_potential(primary_mass,
                                                 secondary_mass,
                                                 semimajor,
                                                 eccentricity,
                                                 inclination,
                                                 arg_of_periapsis);
        approx_potential.set_eccentricity_order(e_order);

        double test_offsets[]= {-0.01, -0.001, 0.0, 0.001, 0.01};
        unsigned num_offsets = sizeof(test_offsets) / sizeof(double);
        for(unsigned z_index = 0; z_index < num_offsets; ++z_index)
            for(unsigned y_index = 0; y_index < num_offsets; ++y_index)
                for(unsigned x_index = 0; x_index < num_offsets; ++x_index) {
                    test_single_point(approx_potential,
                                      exact_potential,
                                      Eigen::Vector3d(test_offsets[x_index],
                                                      test_offsets[y_index],
                                                      test_offsets[z_index]));
                }
    }

    void test_GravitationalPotential::test_expansion()
    {
        double test_angles[] = {-M_PI/2, -1.0, -0.1, 0.0, 0.1, 1.0, M_PI/2};
        unsigned num_angles = sizeof(test_angles) / sizeof(double);
        for(
            double e = 0.0;
            e <= 0.55;
            e += 0.1
        ) {
            unsigned e_order = 0;
            if(e > 0.05) e_order = 10;
            if(e > 0.25) e_order = 20;
            if(e > 0.45) e_order = 35;
            std::cout << "Eccentricity : " << e << std::endl;

            for(
                unsigned inclination_i = 0;
                inclination_i < num_angles;
                ++inclination_i
            ) {
                for(
                    unsigned periapsis_i = 0;
                    periapsis_i < num_angles;
                    ++periapsis_i
                ) {
                    test_system(1.0,
                                0.1,
                                M_PI,
                                e,
                                test_angles[inclination_i],
                                2.0 * test_angles[periapsis_i],
                                e_order);
                }
            }
        }
    }

    test_GravitationalPotential::test_GravitationalPotential()
    {
        TEST_ADD(test_GravitationalPotential::test_expansion);
    }

} //End Evolve namespace.