Program Listing for File SynchronizedCondition.cpp

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

#define BUILDING_LIBRARY
#include "SynchronizedCondition.h"
#include "BinarySystem.h"
#include "DissipatingZone.h"

namespace Evolve {

    SynchronizedCondition::SynchronizedCondition(int orbital_freq_mult,
                                                 int spin_freq_mult,
                                                 short deriv_sign,
                                                 bool primary,
                                                 unsigned zone_index,
                                                 BinarySystem &system) :
        StoppingCondition(deriv_sign),
        __orbital_freq_mult(orbital_freq_mult),
        __spin_freq_mult(spin_freq_mult),
        __primary(primary),
        __zone_index(zone_index),
        __zone((primary
                ? system.primary()
                : system.secondary()).zone(zone_index)),
        __system(system)
    {}

    std::valarray<double> SynchronizedCondition::operator()(
        Core::EvolModeType
#ifndef NDEBUG
        evol_mode
#endif
        , const std::valarray<double> &orbit,
        const std::valarray<double> &derivatives,
        std::valarray<double> &stop_deriv
    ) const
    {
#ifndef NDEBUG
        assert(evol_mode == Core::BINARY);
        if(__system.number_locked_zones())
            assert(orbit[0] == __system.semimajor());
        else assert(std::pow(std::max(0.0, orbit[0]), 1.0 / 6.5)
                    ==
                    __system.semimajor());
        assert(orbit.size() == (1
                                +
                                3 * __system.number_zones()
                                -
                                __system.number_locked_zones()));
        assert(orbit.size() == derivatives.size());
#endif
        double m1 = __system.primary().mass(),
               m2 = __system.secondary().mass(),
               semimajor = __system.semimajor(),
               worb = Core::orbital_angular_velocity(m1, m2, semimajor),
               wspin = __zone.spin_frequency(),
               dworb_dt = (Core::orbital_angular_velocity(m1,
                                                          m2,
                                                          semimajor,
                                                          true)
                           *
                           derivatives[0]
                           *
                           Core::AstroConst::solar_radius);


        unsigned angmom_ind = 1 + 2 * __system.number_zones();
        if(!__primary) angmom_ind += (__system.primary().number_zones()
                                      -
                                      __system.primary().number_locked_zones());

        const DissipatingBody &body = (__primary
                                       ? __system.primary()
                                       : __system.secondary());
        for(unsigned i = 0; i < __zone_index; ++i)
            if(!body.zone(i).locked()) ++angmom_ind;

        double dwspin_dt = (
            (derivatives[angmom_ind] - __zone.moment_of_inertia(1) * wspin)
            /
            __zone.moment_of_inertia()
        );
        if(__system.number_locked_zones() == 0)
            dworb_dt /= 6.5 * orbit[0] / semimajor;

#ifdef VERBOSE_DEBUG
        std::cerr << describe() << " angmom index: " << angmom_ind
            << " worb = " << worb
            << " dworb_dt = " << dworb_dt
            << " wspin = " << wspin
            << " dwspin_dt = " << dwspin_dt
            << " adot = " << derivatives[0] / (6.5 * orbit[0] / semimajor)
            << std::endl;
#endif

        stop_deriv.resize(
            1,
            (
                (wspin * dworb_dt - dwspin_dt * worb)
                /
                std::pow(worb, 2)
                *
                __spin_freq_mult
            )
        );
#ifndef NDEBUG
        if(
            std::isnan((__orbital_freq_mult * worb - wspin * __spin_freq_mult)
                       /
                       worb)
        ) {
            std::cerr << "Synchronized value for zone " << __zone_index << "/"
                << __system.primary().number_zones() << " for worb=" << worb
                << ", wspin=" << wspin
                << ", m'=" << __orbital_freq_mult << ", m="
                << "__spin_freq_mult is NaN."
                << ", semimajor=" << semimajor << std::endl ;
            assert(false);
        }
#endif
        return std::valarray<double>(
            (__orbital_freq_mult * worb - wspin * __spin_freq_mult) / worb,
            1
        );
    }

    void SynchronizedCondition::reached(short deriv_sign, unsigned index)
    {
#ifndef NDEBUG
        std::cerr << "Synchronization reached: "
                  << "Expected sign: " << expected_crossing_deriv_sign()
                  << "sign: " << deriv_sign
                  << std::endl;
#endif
        StoppingCondition::reached(deriv_sign, index);
#ifndef NDEBUG
        std::cerr << "Now expected sign: " << expected_crossing_deriv_sign()
                  << std::endl;
#endif
        __system.check_for_lock(__orbital_freq_mult,
                                __spin_freq_mult,
                                (__primary ? 0 : 1),
                                __zone_index,
                                (__spin_freq_mult>0 ? -deriv_sign : deriv_sign));
    }

    std::string SynchronizedCondition::describe(int ) const
    {
        std::ostringstream description;
        description << (__primary ? "Primary" : "Secondary")
                    << " body, zone "
                    << __zone_index
                    << " satisfying "
                    << __orbital_freq_mult
                    << "(orbital frequency) = "
                    << __spin_freq_mult
                    << "(spin frequency)";
        return description.str();
    }

} //End Evolve namespace.