Program Listing for File DissipatingZone.h

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

#ifndef __DISSIPATING_ZONE_H
#define __DISSIPATING_ZONE_H

#include "ZoneOrientation.h"
#include "../Core/SharedLibraryExportMacros.h"
#include "../Core/Error.h"
#include "TidalPotentialTerms.h"
#include "DissipationQuantities.h"
#include "SpinOrbitLockInfo.h"
#include "CombinedStoppingCondition.h"
#include "BreakLockCondition.h"
#include "SynchronizedCondition.h"
#include "../Core/Common.h"
#include <valarray>

namespace Evolve {

    enum ZoneEvolutionQuantities {
        ANGULAR_MOMENTUM,

        INCLINATION,

        PERIAPSIS,

        MOMENT_OF_INERTIA,

        MOMENT_OF_INERTIA_FIRST_DERIV,

        MOMENT_OF_INERTIA_SECOND_DERIV,

        OUTER_RADIUS,

        OUTER_RADIUS_FIRST_DERIV,

        OUTER_RADIUS_SECOND_DERIV,

        OUTER_MASS,

        OUTER_MASS_DERIV,

        NUM_REAL_EVOL_QUANTITIES,

        E_ORDER=NUM_REAL_EVOL_QUANTITIES,

        ORBITAL_FREQ_MULTIPLIER,

        SPIN_FREQ_MULTIPLIER,

        NUM_EVOL_QUANTITIES
    }; //End ZoneEvolutionQuantities enumeration.

    std::ostream &operator<<(std::ostream &os,
                             const ZoneEvolutionQuantities &evol_var);

    class BinarySystem;

    class TidalTermTriplet {
    public:
        double
            m_minus_one,

            m,

            m_plus_one;

        TidalTermTriplet(double m_minus_one_value = 0.0,
                         double m_value = 0.0,
                         double m_plus_one_value = 0.0):
            m_minus_one(m_minus_one_value),
            m(m_value),
            m_plus_one(m_plus_one_value)
        {}

        TidalTermTriplet &operator=(const TidalTermTriplet &rhs)
        {
            m_minus_one = rhs.m_minus_one;
            m = rhs.m;
            m_plus_one = rhs.m_plus_one;
            return *this;
        }
    };



    class LIB_PUBLIC DissipatingZone : public ZoneOrientation {
    private:
        unsigned __e_order;

        TidalPotentialTerms __potential_term;

        static const double __torque_x_plus_coef[];

        static const double __torque_x_minus_coef[];

        double
            __angular_momentum,

            __spin_frequency,

            __orbital_frequency,

            __orbital_angmom;


        std::valarray<double> __power,

            __torque_x,

            __torque_y,

            __torque_z;

        SpinOrbitLockInfo __lock,

                          __other_lock;

        std::vector< std::list<double> > __evolution_real;

        std::vector< std::list<int> > __evolution_integer;

        unsigned __locked_zone_index;

        bool __initializing;

        void fix_forcing_frequency(
                const SpinOrbitLockInfo &limit,

                int orbital_frequency_multiplier,

                int spin_frequency_multiplier,

                double &forcing_frequency
        ) const;

        void update_lock_to_lower_e_order(SpinOrbitLockInfo &lock);

        void update_locks_to_higher_e_order(unsigned new_e_order);

        void initialize_locks();

        void add_tidal_term(
            int m,

            int mp,

            double tidal_frequency,

            const TidalTermTriplet &U_value,

            const TidalTermTriplet &U_i_deriv,

            const TidalTermTriplet &U_e_deriv,

            const TidalTermTriplet &U_error
        );

#ifndef NDEBUG
        virtual void check_locks_consistency() const;
#endif

    protected:
        void initializing(bool flag) {__initializing = flag;}

        void configure_spin(
            double spin,

            bool spin_is_frequency
        );

    public:
        DissipatingZone();

        virtual void configure(
            bool initialize,

            double age,

            double orbital_frequency,

            double eccentricity,

            double orbital_angmom,

            double spin,

            double inclination,

            double periapsis,

            bool spin_is_frequency
        );

        double forcing_frequency(
            int orbital_frequency_multiplier,

            int spin_frequency_multiplier,

            double orbital_frequency
        ) const;

        void set_reference_zone_angmom(double reference_angmom)
        {__orbital_angmom=reference_angmom;}

        double periapsis_evolution(
            const Eigen::Vector3d &orbit_torque,

            const Eigen::Vector3d &zone_torque,

            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV,

            const Eigen::Vector3d &orbit_torque_deriv=
            Eigen::Vector3d(),

            const Eigen::Vector3d &zone_torque_deriv=Eigen::Vector3d()
        );

        double inclination_evolution(
            const Eigen::Vector3d &orbit_torque,

            const Eigen::Vector3d &zone_torque,

            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV,

            const Eigen::Vector3d &orbit_torque_deriv=Eigen::Vector3d(),

            const Eigen::Vector3d &zone_torque_deriv=Eigen::Vector3d()
        );


        virtual bool locked(int orbital_frequency_multiplier,
                            int spin_frequency_multiplier) const
        {return __lock(orbital_frequency_multiplier,
                       spin_frequency_multiplier);}

        virtual bool locked() const
        {return __lock;}

        const SpinOrbitLockInfo &lock_held() const {return __lock;}

        void release_lock();

        void release_lock(
            short direction
        );

        void set_lock(int orbital_frequency_multiplier,
                      int spin_frequency_multiplier)
        {
            assert(!__lock);
            __lock.set_lock(orbital_frequency_multiplier,
                            spin_frequency_multiplier);
        }

        virtual double modified_phase_lag(
                int orbital_frequency_multiplier,

                int spin_frequency_multiplier,

                double forcing_frequency,

                Dissipation::QuantityEntry entry,

                double &above_lock_value) const =0;

        virtual double love_coefficient(
            int orbital_frequency_multiplier,

            int spin_frequency_multiplier,

            Dissipation::QuantityEntry entry
        ) const =0;

        virtual double moment_of_inertia(
            int deriv_order=0
        ) const =0;

        virtual double moment_of_inertia(
            double age,

            int deriv_order=0
        ) const =0;

        double spin_frequency() const {return __spin_frequency;}

        double angular_momentum() const {return __angular_momentum;}

        double tidal_power(
            bool above,

            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV
        ) const
        {
            if(entry == Dissipation::EXPANSION_ERROR)
                entry = Dissipation::END_DIMENSIONLESS_DERIV;

            assert(entry <= Dissipation::END_DIMENSIONLESS_DERIV);
            assert(2 * entry + 1 < static_cast<int>(__power.size()));

            return __power[2 * entry + (above? 1 : 0)];
        }

        double tidal_power(
            double above_fraction,

            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV
        ) const
        {

            if(entry == Dissipation::EXPANSION_ERROR)
                entry = Dissipation::END_DIMENSIONLESS_DERIV;

            assert(!locked() || (above_fraction >= 0 && above_fraction <= 1));
            assert(entry <= Dissipation::END_DIMENSIONLESS_DERIV);
            assert(2 * entry + 1 < static_cast<int>(__power.size()));

            return (
                above_fraction * __power[2 * entry + 1]
                +
                (1.0 - above_fraction) * __power[2 * entry]
            );
        }

        double tidal_torque_x(
            bool above,
            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV
        ) const
        {
            if(entry == Dissipation::EXPANSION_ERROR)
                entry = Dissipation::END_DIMENSIONLESS_DERIV;

            assert(entry <= Dissipation::END_DIMENSIONLESS_DERIV);
            assert(2 * entry + 1 < static_cast<int>(__torque_x.size()));

            return __torque_x[2 * entry + (above ? 1 : 0)];
        }

        double tidal_torque_x(
            double above_fraction,

            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV
        ) const
        {
            if(entry == Dissipation::EXPANSION_ERROR)
                entry = Dissipation::END_DIMENSIONLESS_DERIV;

            assert(
                !locked() || (above_fraction >= 0 && above_fraction <= 1)
            );
            assert(entry <= Dissipation::END_DIMENSIONLESS_DERIV);
            assert(
                2 * entry + 1
                <
                static_cast<int>(__torque_x.size())
            );

            return (above_fraction * __torque_x[2 * entry + 1]
                    +
                    (1.0 - above_fraction) * __torque_x[2 * entry]);
        }

        double tidal_torque_y(
            bool above,
            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV
        ) const
        {
            if(entry == Dissipation::EXPANSION_ERROR)
                entry = Dissipation::END_DIMENSIONLESS_DERIV;

            assert(entry <= Dissipation::END_DIMENSIONLESS_DERIV);
            assert(
                2 * entry + 1
                <
                static_cast<int>(__torque_y.size())
            );

            return __torque_y[2 * entry + (above? 1 : 0)];
        }

        double tidal_torque_y(
            double above_fraction,

            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV
        ) const
        {
            if(entry == Dissipation::EXPANSION_ERROR)
                entry = Dissipation::END_DIMENSIONLESS_DERIV;

            assert(!locked() || (above_fraction >= 0 && above_fraction <= 1));
            assert(entry <= Dissipation::END_DIMENSIONLESS_DERIV);
            assert(2 * entry + 1 < static_cast<int>(__torque_y.size()));

            return (above_fraction * __torque_y[2 * entry + 1]
                    +
                    (1.0 - above_fraction) * __torque_y[2 * entry]);
        }

        double tidal_torque_z(
            bool above,
            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV
        ) const
        {
            if(entry == Dissipation::EXPANSION_ERROR)
                entry = Dissipation::END_DIMENSIONLESS_DERIV;

            assert(entry <= Dissipation::END_DIMENSIONLESS_DERIV);
            assert(2 * entry + 1 < static_cast<int>(__torque_z.size()));

            return __torque_z[2 * entry + (above? 1 : 0)];
        }

        double tidal_torque_z(
            double above_fraction,

            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV
        ) const
        {
            if(entry == Dissipation::EXPANSION_ERROR)
                entry = Dissipation::END_DIMENSIONLESS_DERIV;

            assert(!locked() || (above_fraction >= 0 && above_fraction <= 1));
            assert(entry < Dissipation::END_DIMENSIONLESS_DERIV);
            assert(2 * entry + 1 < static_cast<int>(__torque_z.size()));

            return (above_fraction * __torque_z[2 * entry + 1]
                    +
                    (1.0 - above_fraction) * __torque_z[2 * entry]);
        }

        //configure()).
        virtual double outer_radius(
            int deriv_order = 0
        ) const =0;

        virtual double outer_radius(double age, int deriv_order=0) const =0;

        virtual double outer_mass(
            int deriv_order=0
        ) const =0;

        virtual double outer_mass(double age, int deriv_order=0) const =0;

        virtual unsigned eccentricity_order() const {return __e_order;}

        virtual void change_e_order(
            unsigned new_e_order,

            BinarySystem &system,

            bool primary,

            unsigned zone_index
        );

        virtual void add_to_evolution();

        virtual void rewind_evolution(
            unsigned nsteps
        );

        virtual void reset_evolution();

        const std::list<double> &get_evolution_real(
            ZoneEvolutionQuantities quantity
        ) const
        {
            assert(quantity < NUM_REAL_EVOL_QUANTITIES);

            return __evolution_real[quantity];
        }

        const std::list<int> &get_evolution_integer(
            ZoneEvolutionQuantities quantity
        ) const
        {
            assert(quantity >= NUM_REAL_EVOL_QUANTITIES);

            return __evolution_integer[quantity - NUM_REAL_EVOL_QUANTITIES];
        }


        unsigned locked_zone_index() const
        {
            assert(__lock);

            return __locked_zone_index;
        }

        unsigned &locked_zone_index()
        {
            assert(__lock);

            return __locked_zone_index;
        }

        virtual bool dissipative() const =0;

        virtual CombinedStoppingCondition *stopping_conditions(
            BinarySystem &system,

            bool primary,

            unsigned zone_index
        );

        virtual void spin_jumped()
        {initialize_locks();}

        virtual void reached_critical_age(double)
        {assert(false);}

        virtual double next_stop_age() const
        {return Core::Inf;}
    }; //End DissipatingZone class.

} //End Evolve namespace.

#endif