Program Listing for File DissipatingBody.h

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

#ifndef __DISSIPATING_BODY_H
#define __DISSIPATING_BODY_H

#include "../Core/SharedLibraryExportMacros.h"

#include "DissipatingZone.h"
#include "../Core/OrbitalExpressions.h"
#include "../Core/AstronomicalConstants.h"
#include "../Core/Common.h"
#include <valarray>
#include <cassert>

namespace Evolve {

    class BinarySystem;

    class LIB_PUBLIC DissipatingBody {
    private:
        double
            __power_norm,

            __orbital_frequency,

            __dorbital_frequency_da,

            __surface_lock_frequency;

        std::valarray< std::valarray<Eigen::Vector3d> >
            __angular_momentum_transfer,

            __tidal_torques_above,

            __tidal_torques_below;

        std::vector<Dissipation::QuantityEntry> __orbit_entries;

        std::valarray<double>
            __orbit_power,

            __orbit_power_correction;

        std::vector<Eigen::Vector3d> __orbit_torque,

            __orbit_torque_correction;

        unsigned __num_locked_zones;

        std::valarray<Eigen::VectorXd> __above_lock_fractions;

        double normalize_torques(
            double companion_mass,

            double semimajor,

            double orbital_frequency
        );

        void collect_orbit_rates(
            double orbital_frequency,

            double torque_norm
        );

        void calculate_orbit_rate_corrections();

        void angular_momentum_transfer(
            const DissipatingZone &outer_zone,

            const DissipatingZone &inner_zone,

            Eigen::Vector3d &outer_angmom_gain,

            Eigen::Vector3d &inner_angmom_gain,

            Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV,

            bool with_respect_to_outer=false
        ) const;

        Eigen::Vector3d angular_momentum_transfer_from_top(
            unsigned zone_index,

            Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV,

            bool with_respect_to_outer=false
        ) const;

        Eigen::Vector3d angular_momentum_transfer_from_bottom(
            unsigned zone_index,

            Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV,

            bool with_respect_to_inner=false
        ) const;

        Eigen::Vector3d angular_momentum_transfer_to_zone(
            unsigned zone_index,

            Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV,

            int deriv_zone=0
        ) const;

        void calculate_nontidal_torques();

        void correct_orbit_power(
            Eigen::VectorXd &above_lock_fractions_age_deriv,

            Eigen::VectorXd &above_lock_fractions_semimajor_deriv,

            Eigen::VectorXd &above_lock_fractions_eccentricity_deriv,

            Eigen::VectorXd &above_lock_fractions_radius_deriv
        );

        void correct_orbit_torque(
            std::valarray<Eigen::VectorXd> &above_lock_fractions
        );
    public:
        DissipatingBody();

        virtual void configure(
            bool initialize,

            double age,

            double companion_mass,

            double semimajor,

            double eccentricity,

            const double *spin_angmom,

            const double *inclination = NULL,

            const double *periapsis = NULL,

            bool locked_surface = false,

            bool zero_outer_inclination = false,

            bool zero_outer_periapsis = false
        );

        void lock_zone_spin(unsigned zone_index,
                            int orbital_frequency_multiplier,
                            int spin_frequency_multiplier)
        {
            zone(zone_index).set_lock(orbital_frequency_multiplier,
                                      spin_frequency_multiplier);
            ++__num_locked_zones;
        }

        void unlock_zone_spin(
            unsigned zone_index,

            short direction
        )
        {
            if(direction == 0) zone(zone_index).release_lock();
            else zone(zone_index).release_lock(direction);
            --__num_locked_zones;
        }

        unsigned number_locked_zones() const {return __num_locked_zones;}

        Eigen::Vector3d nontidal_torque(
            unsigned zone_index,

            Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV,

            int deriv_zone=0
        ) const;

        const Eigen::Vector3d &tidal_torque(
            unsigned zone_index,

            bool above,

            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV
        ) const
        {
            assert(zone_index<number_zones());

            return (above
                    ? __tidal_torques_above
                    : __tidal_torques_below)[zone_index][entry];
        }

        double tidal_power(
            unsigned zone_index,

            bool above,

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

        void set_above_lock_fractions(
            std::valarray<Eigen::VectorXd> &above_lock_fractions
        );

        double tidal_orbit_power(
            Dissipation::QuantityEntry entry=Dissipation::NO_DERIV,

            unsigned deriv_zone_index=0,

            const Eigen::VectorXd &
            above_lock_fraction_deriv=Eigen::VectorXd()
        ) const;

        Eigen::Vector3d tidal_orbit_torque(
            Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV,

            unsigned deriv_zone_index=0,

            const Eigen::VectorXd &
            above_lock_fraction_deriv=Eigen::VectorXd()
        ) const;

        Eigen::Vector3d tidal_orbit_torque(
            const DissipatingZone &reference_zone,

            Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV,

            unsigned deriv_zone_index=0,

            const Eigen::VectorXd &above_lock_fraction_deriv=
            Eigen::VectorXd()
        ) const;

        virtual unsigned number_zones() const =0;

        virtual const DissipatingZone &zone(
            unsigned zone_index
        ) const=0;

        virtual DissipatingZone &zone(
            unsigned zone_index
        )=0;

        virtual Eigen::Vector3d angular_momentum_coupling(
            unsigned top_zone_index,

            Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV,

            bool with_respect_to_top=false
        ) const =0;

        virtual double angular_momentum_loss(
            Dissipation::QuantityEntry deriv=Dissipation::NO_DERIV
        ) const =0;

        double radius(
            int deriv_order=0
        ) const
        {return zone(0).outer_radius(deriv_order);}

        double mass() const
        {return zone(0).outer_mass(Dissipation::NO_DERIV);}

        double spin_frequency() const {return zone(0).spin_frequency();}

        double surface_lock_frequency() const
        {return __surface_lock_frequency;}

        void set_surface_lock_frequency(double frequency)
        {__surface_lock_frequency=frequency;}

        virtual void add_to_evolution();

        virtual void rewind_evolution(
            unsigned nsteps
        );

        virtual void reset_evolution();

        virtual CombinedStoppingCondition *stopping_conditions(
            BinarySystem &system,

            bool primary
        );

        virtual void spin_jumped() {zone(0).spin_jumped();}

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

        virtual double next_stop_age() const {return Core::Inf;}

        virtual void change_e_order(
            unsigned new_e_order,

            BinarySystem &system,

            bool primary
        );

        virtual ~DissipatingBody() {}
    }; //End DissipatingBody class.

} //End Evolve namespace.
#endif