def get_compiled_Hkep_Hpert_full():
        # resonance j and k
        j,k = T.lscalars('jk')
        s = (j-k) / k

        # Planet masses: m1,m2
        m1,m2 = T.dscalars(2)
        Mstar = 1
        eta0 = Mstar
        eta1 = eta0+m1
        eta2 =eta1+m2
        mtilde1 = m1 * (eta0/eta1)
        Mtilde1 = Mstar * (eta1/eta0)
        mtilde2 = m2 * (eta1/eta2)
        Mtilde2 = Mstar * (eta2/eta1)
        eps = m1 * m2 / (mtilde1 + mtilde2) / Mstar
        beta1 = mtilde1 / (mtilde1 + mtilde2)
        beta2 = mtilde2 / (mtilde1 + mtilde2)
        gamma = mtilde2/mtilde1
        

        # Dynamical variables:
        dyvars = T.vector()
        Q,sigma1, sigma2, I1, I2, amd = [dyvars[i] for i in range(6)]

        # Set lambda2=0
        l2 = T.constant(0.)
        l1 = -1 * k * Q 
        w1 = (1+s) * l2 - s * l1 - sigma1
        w2 = (1+s) * l2 - s * l1 - sigma2
        
        Gamma1 = I1
        Gamma2 = I2
        
        # Resonant semi-major axis ratio
        alpha_res = ((j-k)/j)**(2/3) * ((Mstar + m1) / (Mstar+m2))**(1/3)
        P0 = k * ( beta2 - beta1 * T.sqrt(alpha_res) ) / 2
        P = P0 - k * (s+1/2) * amd
        
        Ltot = beta1 * T.sqrt(alpha_res) + beta2 - amd
        L1 = Ltot/2 - P / k - s * (I1 + I2)
        L2 = Ltot/2 + P / k + (1 + s) * (I1 + I2)
        
        a1 = (L1 / beta1 )**2 * eta0 / eta1
        e1 = T.sqrt(1-(1-(Gamma1 / L1))**2)
        
        a2 = (L2 / beta2 )**2 * eta1 / eta2
        e2 = T.sqrt(1-(1-(Gamma2 / L2))**2)
        
        Hkep = - eta1 * beta1 / (2 * a1) / eta0  - eta2 * beta2 / (2 * a2) / eta1
        
        alpha = a1 / a2
        
        ko = KeplerOp()
        
        M1 = l1 - w1
        M2 = l2 - w2
        
        sinf1,cosf1 =  ko( M1, e1 + T.zeros_like(M1) )
        sinf2,cosf2 =  ko( M2, e2 + T.zeros_like(M2) )
        
        R = calc_DisturbingFunction_with_sinf_cosf(alpha,e1,e2,w1,w2,sinf1,cosf1,sinf2,cosf2)
        
        Hpert = -eps * R / a2
        
        omega_syn = T.sqrt(eta2/eta1)/a2**1.5 - T.sqrt(eta1/eta0) / a1**1.5
        gradHpert = T.grad(Hpert,wrt=dyvars)
        gradHkep = T.grad(Hkep,wrt=dyvars)
        grad_omega_syn = T.grad(omega_syn,wrt=dyvars)

        extra_ins = [m1,m2,j,k]
        ins = [dyvars] + extra_ins

        # Scalars
        omega_syn_fn = theano.function(
            inputs=ins,
            outputs=omega_syn,
            givens=None,
            on_unused_input='ignore'
        )
        Hpert_fn = theano.function(
            inputs=ins,
            outputs=Hpert,
            givens=None,
            on_unused_input='ignore'
        )
        Hkep_fn = theano.function(
            inputs=ins,
            outputs=Hkep,
            givens=None,
            on_unused_input='ignore'
        )
        # gradients
        grad_omega_syn_fn = theano.function(
            inputs=ins,
            outputs=grad_omega_syn,
            givens=None,
            on_unused_input='ignore'
        )
        gradHpert_fn = theano.function(
            inputs=ins,
            outputs=gradHpert,
            givens=None,
            on_unused_input='ignore'
        )
        gradHkep_fn = theano.function(
            inputs=ins,
            outputs=gradHkep,
            givens=None,
            on_unused_input='ignore'
        )
        return omega_syn_fn,Hkep_fn,Hpert_fn,grad_omega_syn_fn,gradHkep_fn,gradHpert_fn
Пример #2
0
 def setUp(self):
     super(TestKeplerSolver, self).setUp()
     self.op_class = KeplerOp
     self.op = KeplerOp()
def get_compiled_theano_functions(N_QUAD_PTS):
        # resonance j and k
        j,k = T.lscalars('jk')
        s = (j-k) / k

        # Planet masses: m1,m2
        m1,m2 = T.dscalars(2)
        Mstar = 1
        eta0 = Mstar
        eta1 = eta0+m1
        eta2 =eta1+m2
        mtilde1 = m1 * (eta0/eta1)
        Mtilde1 = Mstar * (eta1/eta0)
        mtilde2 = m2 * (eta1/eta2)
        Mtilde2 = Mstar * (eta2/eta1)
        eps = m1 * m2 / (mtilde1 + mtilde2) / Mstar
        beta1 = mtilde1 / (mtilde1 + mtilde2)
        beta2 = mtilde2 / (mtilde1 + mtilde2)
        gamma = mtilde2/mtilde1
        
        # Angle variable for averaging over
        Q = T.dvector('Q')

        # Dynamical variables:
        dyvars = T.vector()
        sigma1, sigma2, I1, I2, amd = [dyvars[i] for i in range(5)]


        # Quadrature weights
        quad_weights = T.dvector('w')
        
        # Set lambda2=0
        l2 = T.constant(0.)
        
        l1 = -1 * k * Q 
        w1 = (1+s) * l2 - s * l1 - sigma1
        w2 = (1+s) * l2 - s * l1 - sigma2
        
        Gamma1 = I1
        Gamma2 = I2
        
        # Resonant semi-major axis ratio
        alpha_res = ((j-k)/j)**(2/3) * ((Mstar + m1) / (Mstar+m2))**(1/3)
        P0 =  k * ( beta2 - beta1 * T.sqrt(alpha_res) ) / 2
        P = P0 - k * (s+1/2) * amd
        Ltot = beta1 * T.sqrt(alpha_res) + beta2 - amd
        L1 = Ltot/2 - P / k - s * (I1 + I2)
        L2 = Ltot/2 + P / k + (1 + s) * (I1 + I2)
        
        
        a1 = (L1 / beta1 )**2 * eta0 / eta1
        e1 = T.sqrt(1-(1-(Gamma1 / L1))**2)
        
        a2 = (L2 / beta2 )**2 * eta1 / eta2
        e2 = T.sqrt(1-(1-(Gamma2 / L2))**2)
        
        Hkep = - eta1 * beta1 / (2 * a1) / eta0  - eta2 * beta2 / (2 * a2) / eta1
        
        alpha = a1 / a2
        
        ko = KeplerOp()
        
        M1 = l1 - w1
        M2 = l2 - w2
        
        sinf1,cosf1 =  ko( M1, e1 + T.zeros_like(M1) )
        sinf2,cosf2 =  ko( M2, e2 + T.zeros_like(M2) )
        
        R = calc_DisturbingFunction_with_sinf_cosf(alpha,e1,e2,w1,w2,sinf1,cosf1,sinf2,cosf2)
        Rav = R.dot(quad_weights)
        
        Hpert = -eps * Rav / a2
        Htot = Hkep + Hpert

        ######################
        # Dissipative dynamics
        ######################
        tau_alpha_0, K1, K2, p = T.dscalars(4)
        sigma1dot_dis,sigma2dot_dis,I1dot_dis,I2dot_dis,amddot_dis = T.dscalars(5)
        sigma1dot_dis,sigma2dot_dis = T.as_tensor(0.),T.as_tensor(0.)
        
        # Define timescales
        tau_e1 = tau_alpha_0 / K1
        tau_e2 = tau_alpha_0 / K2
        tau_a1_0 = -1 * tau_alpha_0 * (1+alpha_res * gamma)/ (alpha_res * gamma)
        tau_a2_0 = -1 * alpha_res * gamma * tau_a1_0
        tau_a1 = 1 / (1/tau_a1_0 + 2 * p * e1*e1 / tau_e1 )
        tau_a2 = 1 / (1/tau_a2_0 + 2 * p * e2*e2 / tau_e2 )

        # Time derivative of orbital elements
        e1dot_dis = -1*e1 / tau_e1
        e2dot_dis = -1*e2 / tau_e2
        a1dot_dis = -1*a1 / tau_a1
        a2dot_dis = -1*a2 / tau_a2

        # Time derivatives of canonical variables
        I1dot_dis = L1 * e1 * e1dot_dis / ( T.sqrt(1-e1*e1) ) - I1 / tau_a1 / 2
        I2dot_dis = L2 * e2 * e2dot_dis / ( T.sqrt(1-e2*e2) ) - I2 / tau_a2 / 2
        Pdot_dis = -1*k * ( L2 / tau_a2 - L1 / tau_a1) / 4 - k * (s + 1/2) * (I1dot_dis + I2dot_dis)
        amddot_dis = Pdot_dis / T.grad(P,amd)

        #####################################################
        # Set parameters for compiling functions with Theano
        #####################################################
        
        # Get numerical quadrature nodes and weights
        nodes,weights = np.polynomial.legendre.leggauss(N_QUAD_PTS)
        
        # Rescale for integration interval from [-1,1] to [-pi,pi]
        nodes = nodes * np.pi
        weights = weights * 0.5
        
        # 'givens' will fix some parameters of Theano functions compiled below
        givens = [(Q,nodes),(quad_weights,weights)]

        # 'ins' will set the inputs of Theano functions compiled below
        #   Note: 'extra_ins' will be passed as values of object attributes
        #   of the 'ResonanceEquations' class 'defined below
        extra_ins = [m1,m2,j,k,tau_alpha_0,K1,K2,p]
        ins = [dyvars] + extra_ins
        

        # Define flows and jacobians.

        #  Conservative flow
        gradHtot = T.grad(Htot,wrt=dyvars)
        hessHtot = theano.gradient.hessian(Htot,wrt=dyvars)
        Jtens = T.as_tensor(np.pad(getOmegaMatrix(2),(0,1),'constant'))
        H_flow_vec = Jtens.dot(gradHtot)
        H_flow_jac = Jtens.dot(hessHtot)
        
        #  Dissipative flow
        dis_flow_vec = T.stack(sigma1dot_dis,sigma2dot_dis,I1dot_dis,I2dot_dis,amddot_dis)
        dis_flow_jac = theano.gradient.jacobian(dis_flow_vec,dyvars)
        
        
        # Extras
        dis_timescales = [tau_a1_0,tau_a2_0,tau_e1,tau_e2]
        orbels = [a1,e1,sigma1*k,a2,e2,sigma2*k]
        ##########################
        # Compile Theano functions
        ##########################
        
        if not DEBUG:
            # Note that compiling can take a while
            #  so I've put a debugging switch here 
            #  to skip evaluating these functions when
            #  desired.
            Rav_fn = theano.function(
                inputs=ins,
                outputs=Rav,
                givens=givens,
                on_unused_input='ignore'
            )
            Hpert_av_fn = theano.function(
                inputs=ins,
                outputs=Hpert,
                givens=givens,
                on_unused_input='ignore'
            )
            Htot_fn = theano.function(
                inputs=ins,
                outputs=Htot,
                givens=givens,
                on_unused_input='ignore'
            )
            
            H_flow_vec_fn = theano.function(
                inputs=ins,
                outputs=H_flow_vec,
                givens=givens,
                on_unused_input='ignore'
            )
            
            H_flow_jac_fn = theano.function(
                inputs=ins,
                outputs=H_flow_jac,
                givens=givens,
                on_unused_input='ignore'
            )
            
            dis_flow_vec_fn = theano.function(
                inputs=ins,
                outputs=dis_flow_vec,
                givens=givens,
                on_unused_input='ignore'
            )
            
            dis_flow_jac_fn = theano.function(
                inputs=ins,
                outputs=dis_flow_jac,
                givens=givens,
                on_unused_input='ignore'
            )

            dis_timescales_fn =theano.function(
                inputs=extra_ins,
                outputs=dis_timescales,
                givens=givens,
                on_unused_input='ignore'
            )

            orbels_fn = theano.function(
                inputs=ins,
                outputs=orbels,
                givens=givens,
                on_unused_input='ignore'
            )

        else:
            return  [lambda x: x for _ in range(8)]
        
        return Rav_fn,Hpert_av_fn,Htot_fn,H_flow_vec_fn,H_flow_jac_fn,dis_flow_vec_fn,dis_flow_jac_fn,dis_timescales_fn,orbels_fn
Пример #4
0
def get_compiled_theano_functions(N_QUAD_PTS):
    # resonance j and k
    j, k = T.lscalars('jk')

    # Planet masses: m1,m2
    m1, m2 = T.dscalars(2)

    # resonance f and g coefficients
    f, g = T.dscalars(2)

    # Planet and star mass variables
    Mstar = 1
    mu1 = m1 / (Mstar + m1)
    mu2 = m2 / (Mstar + m2)
    eps = m1 * mu2 / (mu1 + mu2) / Mstar

    # Resonant semi-major axis ratio
    alpha = ((j - k) / j)**(2 / 3) * ((Mstar + m1) / (Mstar + m2))**(1 / 3)

    # Constants in Eq. (15)
    fTilde = T.sqrt((mu1 + mu2) / (mu1 * T.sqrt(alpha))) * f
    gTilde = T.sqrt((mu1 + mu2) / mu2) * g

    # Constant in Eq. (8)
    A = 1.5 * j * (mu1 + mu2) * (j / mu2 + (j - k) / mu1 / T.sqrt(alpha))

    # Dynamical variables:
    dyvars = T.vector()
    theta, theta_star, J, J_star = [dyvars[i] for i in range(4)]

    # Angle variable to average disturbing function over
    kappa = T.dvector()

    # Quadrature weights
    quad_weights = T.dvector('w')

    # Convert dynamical variables to eccentricities and angles:
    # Note:
    #   Q is set to zero since it does not
    #   enter disturbing function except in combinations
    #   with z and w.
    Q = T.as_tensor(0)
    z = Q / k - theta

    # See Eq. 20
    Zsq = J * (fTilde * fTilde + gTilde * gTilde) / (f * f + g * g)
    Z = T.sqrt(Zsq)

    # Set W to zero
    Wsinw, Wcosw = 0, 0
    Zsinz, Zcosz = Z * T.sin(z), Z * T.cos(z)

    # Convert Z and W to planet eccentricities
    atan_f_g = T.arctan2(g, f)
    c, s = T.cos(atan_f_g), T.sin(atan_f_g)

    e1cos = c * Zcosz - s * Wcosw
    e1sin = c * Zsinz - s * Wsinw

    e2cos = s * Zcosz + c * Wcosw
    e2sin = s * Zsinz + c * Wsinw

    w1 = T.arctan2(e1sin, e1cos)
    w2 = T.arctan2(e2sin, e2cos)

    e1 = T.sqrt(e1sin * e1sin + e1cos * e1cos)
    e2 = T.sqrt(e2sin * e2sin + e2cos * e2cos)

    # Planets' mean longitudes
    l1 = Q / k - j * kappa
    l2 = Q / k + (k - j) * kappa

    # Planets mean anomalies
    M1 = l1 - w1
    M2 = l2 - w2

    # Convert mean to true anomalies using
    # function 'exoplanet.theano_ops.kepler.KeplerOp'
    ko = KeplerOp()
    sinf1, cosf1 = ko(M1, e1 + T.zeros_like(M1))
    sinf2, cosf2 = ko(M2, e2 + T.zeros_like(M2))

    # Vector of distrubing function values with same dimension as kappa vector
    DFfull = calc_DisturbingFunction_with_sinf_cosf(alpha, e1, e2, w1, w2,
                                                    sinf1, cosf1, sinf2, cosf2)

    # Average distrubing function by weighting values with user-specified
    # quadrature weights.
    DFav = DFfull.dot(quad_weights)

    # Hamiltonian
    Hkep = -0.5 * A / k / k * (J - J_star) * (J - J_star)
    Hres = -2 * eps * DFav
    # ******************IMPORTANT NOTE*************************
    # I have *NOT* subtraced off the secular component of
    # the disturbing function. This means that the Hamiltonian
    # differs slightly from the one defined in the paper.
    # This is generally of little consequence to the resonant
    # dynamics but should be borne in mind when exploring
    # secular dynamics.
    # *********************************************************
    H = Hkep + Hres

    # Gradient and hessian of Hamiltonian w.r.t. phase space variables
    gradHtot = T.grad(H, wrt=dyvars)
    hessHtot = theano.gradient.hessian(H, wrt=dyvars)

    # Flow vector and Jacobian for equations of motion
    OmegaTens = T.as_tensor(getOmegaMatrix(2))
    H_flow_vec = OmegaTens.dot(gradHtot)
    H_flow_jac = OmegaTens.dot(hessHtot)

    #####################################################
    # Set parameters for compiling functions with Theano
    #####################################################

    # Get numerical quadrature nodes and weights
    nodes, weights = np.polynomial.legendre.leggauss(N_QUAD_PTS)

    # Rescale for integration interval from [-1,1] to [-pi,pi]
    nodes = nodes * np.pi
    weights = weights * 0.5

    # 'ins' will set the inputs of Theano functions compiled below
    extra_ins = [m1, m2, j, k, f, g]
    ins = [dyvars] + extra_ins

    # 'givens' will fix some parameters of Theano functions compiled below
    givens = [(kappa, nodes), (quad_weights, weights)]

    ##########################
    # Compile Theano functions
    ##########################

    if not DEBUG:
        # Note that compiling can take a while
        #  so I've put a debugging switch here
        #  to skip evaluating these functions when
        #  desired.
        H_fn = theano.function(inputs=ins, outputs=H, givens=givens)

        H_flow_vec_fn = theano.function(inputs=ins,
                                        outputs=H_flow_vec,
                                        givens=givens)

        H_flow_jac_fn = theano.function(inputs=ins,
                                        outputs=H_flow_jac,
                                        givens=givens)
    else:
        H_fn, H_flow_vec_fn, H_flow_jac_fn = [lambda x: x for _ in range(3)]

    # Some convenience functions...
    Zsq_to_J_Eq20 = (f * f + g * g) / (fTilde * fTilde + gTilde * gTilde)
    dJ_to_Delta_Eq21 = 1.5 * (mu1 + mu2) * (j * mu1 * T.sqrt(alpha) +
                                            (j - k) * mu2) / (
                                                k * T.sqrt(alpha) * mu1 * mu2)
    ecc_vars_fn = theano.function(inputs=ins,
                                  outputs=[e1, w1, e2, w2],
                                  on_unused_input='ignore')
    Zsq_to_J_Eq20_fn = theano.function(inputs=extra_ins,
                                       outputs=Zsq_to_J_Eq20,
                                       on_unused_input='ignore')
    dJ_to_Delta_Eq21_fn = theano.function(inputs=extra_ins,
                                          outputs=dJ_to_Delta_Eq21,
                                          on_unused_input='ignore')
    return (H_fn, H_flow_vec_fn, H_flow_jac_fn, Zsq_to_J_Eq20_fn,
            dJ_to_Delta_Eq21_fn, ecc_vars_fn)
def _get_compiled_theano_functions():
    # Planet masses: m1,m2
    m1, m2 = T.dscalars(2)
    mstar = 1
    mu1 = m1 * mstar / (mstar + m1)
    mu2 = m2 * mstar / (mstar + m2)
    eta1 = mstar + m1
    eta2 = mstar + m2
    beta1 = mu1 * T.sqrt(eta1 / mstar) / (mu1 + mu2)
    beta2 = mu2 * T.sqrt(eta2 / mstar) / (mu1 + mu2)

    # Dynamical variables:
    dyvars = T.vector()
    l1, l2, y1, y2, Omega, L1, L2, x1, x2, Rtilde = [
        dyvars[i] for i in range(10)
    ]

    Gamma1 = 0.5 * (x1 * x1 + y1 * y1)
    Gamma2 = 0.5 * (x2 * x2 + y2 * y2)
    gamma1 = T.arctan2(y1, x1)
    gamma2 = T.arctan2(y2, x2)

    Cz = -1 * Rtilde

    R1 = Gamma1
    R2 = Gamma2
    R = L1 + L2 - R1 - R2 - Cz
    G1 = L1 - Gamma1
    G2 = L2 - Gamma2

    r2_by_r1 = (L2 - L1 - R2 + R1) / (L1 + L2 - R1 - R2 - R)
    rho1 = 0.5 * R * (1 + r2_by_r1)
    rho2 = 0.5 * R * (1 - r2_by_r1)

    a1 = (L1 / beta1)**2
    e1 = T.sqrt(1 - (1 - (Gamma1 / L1))**2)

    a2 = (L2 / beta2)**2
    e2 = T.sqrt(1 - (1 - (Gamma2 / L2))**2)

    cos_inc1 = 1 - rho1 / G1
    cos_inc2 = 1 - rho2 / G2
    inc1 = T.arccos(cos_inc1)
    inc2 = T.arccos(cos_inc2)

    l1_r = l1 - Omega
    l2_r = l2 - Omega

    Omega1_r = T.constant(np.pi / 2) - Omega
    Omega2_r = Omega1_r - T.constant(np.pi)

    pomega1 = -1 * gamma1
    pomega2 = -1 * gamma2

    pomega1_r = pomega1 - Omega
    pomega2_r = pomega2 - Omega

    omega1 = pomega1_r - Omega1_r
    omega2 = pomega2_r - Omega2_r

    Hkep = -0.5 * T.sqrt(eta1) * beta1 / a1 - 0.5 * T.sqrt(eta2) * beta2 / a2

    ko = KeplerOp()
    M1 = l1_r - pomega1_r
    M2 = l2_r - pomega2_r
    sinf1, cosf1 = ko(M1, e1 + T.zeros_like(M1))
    sinf2, cosf2 = ko(M2, e2 + T.zeros_like(M2))
    #
    n1 = T.sqrt(eta1 / mstar) * a1**(-3 / 2)
    n2 = T.sqrt(eta2 / mstar) * a2**(-3 / 2)
    Hint_dir, Hint_ind, r1, r2, v1, v2 = calc_Hint_components_sinf_cosf(
        a1, a2, e1, e2, inc1, inc2, omega1, omega2, Omega1_r, Omega2_r, n1, n2,
        sinf1, cosf1, sinf2, cosf2)
    eps = m1 * m2 / (mu1 + mu2) / T.sqrt(mstar)
    Hpert = (Hint_dir + Hint_ind / mstar)
    Htot = Hkep + eps * Hpert

    #####################################################
    # Set parameters for compiling functions with Theano
    #####################################################

    # 'ins' will set the inputs of Theano functions compiled below
    #   Note: 'extra_ins' will be passed as values of object attributes
    #   of the 'ResonanceEquations' class 'defined below
    extra_ins = [m1, m2]
    givens = []
    ins = [dyvars] + extra_ins
    orbels = [
        a1, e1, inc1, l1_r, pomega1_r, Omega1_r, a2, e2, inc2, l2_r, pomega2_r,
        Omega2_r
    ]
    orbels_dict = dict(
        zip([
            'a1', 'e1', 'inc1', 'l1', 'pomega1', 'Omega1', 'a2', 'e2', 'inc2',
            'l2', 'pomega2', 'Omega2'
        ], orbels))
    actions = [L1, L2, Gamma1, Gamma2, rho1, rho2]
    actions_dict = dict(
        zip(['L1', 'L2', 'Gamma1', 'Gamma2', 'Q1', 'Q2'], actions))
    #  Conservative flow
    gradHtot = T.grad(Htot, wrt=dyvars)
    hessHtot = theano.gradient.hessian(Htot, wrt=dyvars)
    Jtens = T.as_tensor(_get_Omega_matrix(5))
    H_flow_vec = Jtens.dot(gradHtot)
    H_flow_jac = Jtens.dot(hessHtot)

    ##########################
    # Compile Theano functions
    ##########################
    orbels_fn = theano.function(inputs=ins,
                                outputs=orbels_dict,
                                givens=givens,
                                on_unused_input='ignore')
    actions_fn = theano.function(inputs=ins,
                                 outputs=actions_dict,
                                 givens=givens,
                                 on_unused_input='ignore')
    rv1_fn = theano.function(inputs=ins,
                             outputs=r1 + v1,
                             givens=givens,
                             on_unused_input='ignore')
    rv2_fn = theano.function(inputs=ins,
                             outputs=r2 + v2,
                             givens=givens,
                             on_unused_input='ignore')

    Htot_fn = theano.function(inputs=ins,
                              outputs=Htot,
                              givens=givens,
                              on_unused_input='ignore')

    Hpert_fn = theano.function(inputs=ins,
                               outputs=Hpert,
                               givens=givens,
                               on_unused_input='ignore')

    Hpert_components_fn = theano.function(inputs=ins,
                                          outputs=[Hint_dir, Hint_ind],
                                          givens=givens,
                                          on_unused_input='ignore')

    H_flow_vec_fn = theano.function(inputs=ins,
                                    outputs=H_flow_vec,
                                    givens=givens,
                                    on_unused_input='ignore')

    H_flow_jac_fn = theano.function(inputs=ins,
                                    outputs=H_flow_jac,
                                    givens=givens,
                                    on_unused_input='ignore')
    return dict({
        'orbital_elements': orbels_fn,
        'actions': actions_fn,
        'Hamiltonian': Htot_fn,
        'Hpert': Hpert_fn,
        'Hpert_components': Hpert_components_fn,
        'Hamiltonian_flow': H_flow_vec_fn,
        'Hamiltonian_flow_jacobian': H_flow_jac_fn,
        'positions_and_velocities1': rv1_fn,
        'positions_and_velocities2': rv2_fn
    })
Пример #6
0
def _get_compiled_theano_functions(N_QUAD_PTS):
    # Planet masses: m1,m2
    m1, m2 = T.dscalars(2)
    mstar = 1
    mu1 = m1 * mstar / (mstar + m1)
    mu2 = m2 * mstar / (mstar + m2)
    eta1 = mstar + m1
    eta2 = mstar + m2
    beta1 = mu1 * T.sqrt(eta1 / mstar) / (mu1 + mu2)
    beta2 = mu2 * T.sqrt(eta2 / mstar) / (mu1 + mu2)
    j, k = T.lscalars('jk')
    s = (j - k) / k

    # Angle variable for averaging over
    psi = T.dvector('psi')

    # Quadrature weights
    quad_weights = T.dvector('w')

    # Dynamical variables:
    Ndof = 3
    Nconst = 1
    dyvars = T.vector()
    s1, s2, phi, I1, I2, Phi, dRtilde = [
        dyvars[i] for i in range(2 * Ndof + Nconst)
    ]

    a20 = T.constant(1.)
    a10 = ((j - k) / j)**(2 / 3) * (eta1 / eta2)**(1 / 3) * a20
    L10 = beta1 * T.sqrt(a10)
    L20 = beta2 * T.sqrt(a20)
    Psi = s * L20 + (1 + s) * L10
    Rtilde = dRtilde - L10 - L20
    ####
    # angles
    ####
    rtilde = T.constant(0.)
    Omega = -1 * rtilde
    l1 = phi + k * (1 + s) * psi + Omega
    l2 = phi + k * s * psi + Omega
    gamma1 = s1 - phi - Omega
    gamma2 = s2 - phi - Omega
    q1 = 0.5 * np.pi - Omega
    q2 = -0.5 * np.pi - Omega

    pomega1 = -1 * gamma1
    pomega2 = -1 * gamma2
    Omega1 = -1 * q1
    Omega2 = -1 * q2
    omega1 = pomega1 - Omega1
    omega2 = pomega2 - Omega2

    ###
    # actions
    ###
    Gamma1 = I1
    Gamma2 = I2
    L1 = Psi / k - s * (I1 + I2) - s * Phi
    L2 = -1 * Psi / k + (1 + s) * (I1 + I2) + (1 + s) * Phi
    Cz = -1 * Rtilde

    R = L1 + L2 - Gamma1 - Gamma2 - Cz
    G1 = L1 - Gamma1
    G2 = L2 - Gamma2

    r2_by_r1 = (L2 - L1 - Gamma2 + Gamma1) / (L1 + L2 - Gamma1 - Gamma2 - R)
    rho1 = 0.5 * R * (1 + r2_by_r1)
    rho2 = 0.5 * R * (1 - r2_by_r1)

    a1 = (L1 / beta1)**2
    e1 = T.sqrt(1 - (1 - (Gamma1 / L1))**2)

    a2 = (L2 / beta2)**2
    e2 = T.sqrt(1 - (1 - (Gamma2 / L2))**2)

    cos_inc1 = 1 - rho1 / G1
    cos_inc2 = 1 - rho2 / G2
    inc1 = T.arccos(cos_inc1)
    inc2 = T.arccos(cos_inc2)

    Hkep = -0.5 * T.sqrt(eta1) * beta1 / a1 - 0.5 * T.sqrt(eta2) * beta2 / a2

    ko = KeplerOp()
    M1 = l1 - pomega1
    M2 = l2 - pomega2
    sinf1, cosf1 = ko(M1, e1 + T.zeros_like(M1))
    sinf2, cosf2 = ko(M2, e2 + T.zeros_like(M2))
    #
    n1 = T.sqrt(eta1 / mstar) * a1**(-3 / 2)
    n2 = T.sqrt(eta2 / mstar) * a2**(-3 / 2)
    Hint_dir, Hint_ind, r1, r2, v1, v2 = calc_Hint_components_sinf_cosf(
        a1, a2, e1, e2, inc1, inc2, omega1, omega2, Omega1, Omega2, n1, n2,
        sinf1, cosf1, sinf2, cosf2)
    eps = m1 * m2 / (mu1 + mu2) / T.sqrt(mstar)
    Hpert = (Hint_dir + Hint_ind / mstar)
    Hpert_av = Hpert.dot(quad_weights)
    Htot = Hkep + eps * Hpert_av

    #####################################################
    # Set parameters for compiling functions with Theano
    #####################################################

    # Get numerical quadrature nodes and weights
    nodes, weights = np.polynomial.legendre.leggauss(N_QUAD_PTS)

    # Rescale for integration interval from [-1,1] to [-pi,pi]
    nodes = nodes * np.pi
    weights = weights * 0.5

    # 'givens' will fix some parameters of Theano functions compiled below
    givens = [(psi, nodes), (quad_weights, weights)]

    # 'ins' will set the inputs of Theano functions compiled below
    #   Note: 'extra_ins' will be passed as values of object attributes
    #   of the 'ResonanceEquations' class 'defined below
    extra_ins = [m1, m2, j, k]
    ins = [dyvars] + extra_ins
    orbels = [a1, e1, inc1, k * s1, a2, e2, inc2, k * s2, phi, Omega]
    orbels_dict = dict(
        zip([
            'a1', 'e1', 'inc1', 'theta1', 'a2', 'e2', 'inc2', 'theta2', 'phi'
        ], orbels))
    actions = [L1, L2, Gamma1, Gamma2, rho1, rho2]
    actions_dict = dict(
        zip(['L1', 'L2', 'Gamma1', 'Gamma2', 'Q1', 'Q2'], actions))

    #  Conservative flow
    gradHtot = T.grad(Htot, wrt=dyvars)
    hessHtot = theano.gradient.hessian(Htot, wrt=dyvars)
    Jtens = T.as_tensor(
        np.pad(_get_Omega_matrix(Ndof), (0, Nconst), 'constant'))
    H_flow_vec = Jtens.dot(gradHtot)
    H_flow_jac = Jtens.dot(hessHtot)

    ##########################
    # Compile Theano functions
    ##########################
    orbels_fn = theano.function(inputs=ins,
                                outputs=orbels_dict,
                                givens=givens,
                                on_unused_input='ignore')
    actions_fn = theano.function(inputs=ins,
                                 outputs=actions_dict,
                                 givens=givens,
                                 on_unused_input='ignore')
    Rtilde_fn = theano.function(inputs=ins,
                                outputs=Rtilde,
                                givens=givens,
                                on_unused_input='ignore')

    Htot_fn = theano.function(inputs=ins,
                              outputs=Htot,
                              givens=givens,
                              on_unused_input='ignore')

    Hpert_fn = theano.function(inputs=ins,
                               outputs=Hpert_av,
                               givens=givens,
                               on_unused_input='ignore')

    Hpert_components_fn = theano.function(
        inputs=ins,
        outputs=[Hint_dir.dot(quad_weights),
                 Hint_ind.dot(quad_weights)],
        givens=givens,
        on_unused_input='ignore')

    H_flow_vec_fn = theano.function(inputs=ins,
                                    outputs=H_flow_vec,
                                    givens=givens,
                                    on_unused_input='ignore')

    H_flow_jac_fn = theano.function(inputs=ins,
                                    outputs=H_flow_jac,
                                    givens=givens,
                                    on_unused_input='ignore')

    return dict({
        'orbital_elements': orbels_fn,
        'actions': actions_fn,
        'Rtilde': Rtilde_fn,
        'Hamiltonian': Htot_fn,
        'Hpert': Hpert_fn,
        'Hpert_components': Hpert_components_fn,
        'Hamiltonian_flow': H_flow_vec_fn,
        'Hamiltonian_flow_jacobian': H_flow_jac_fn
    })
def _get_compiled_theano_functions():
    # Planet masses: m1,m2
    m1, m2 = T.dscalars(2)
    mstar = 1
    mu1 = m1 * mstar / (mstar + m1)
    mu2 = m2 * mstar / (mstar + m2)
    eta1 = mstar + m1
    eta2 = mstar + m2
    beta1 = mu1 * T.sqrt(eta1 / mstar) / (mu1 + mu2)
    beta2 = mu2 * T.sqrt(eta2 / mstar) / (mu1 + mu2)
    j, k = T.lscalars('jk')
    s = (j - k) / k

    # Dynamical variables:
    dyvars = T.vector()
    s1, s2, psi, phi, Omega, I1, I2, Psi, Phi, Rtilde = [
        dyvars[i] for i in range(10)
    ]
    l1 = phi - 0.5 * k * psi
    l2 = phi + 0.5 * k * psi
    gamma1 = s1 - (1 + s) * l2 + s * l1
    gamma2 = s2 - (1 + s) * l2 + s * l1
    Gamma1 = I1
    Gamma2 = I2
    L1 = Phi / 2 - Psi / k - s * (I1 + I2)
    L2 = Phi / 2 + Psi / k + (s + 1) * (I1 + I2)
    Cz = -1 * Rtilde

    R = L1 + L2 - Gamma1 - Gamma2 - Cz
    G1 = L1 - Gamma1
    G2 = L2 - Gamma2

    r2_by_r1 = (L2 - L1 - Gamma2 + Gamma1) / (L1 + L2 - Gamma1 - Gamma2 - R)
    rho1 = 0.5 * R * (1 + r2_by_r1)
    rho2 = 0.5 * R * (1 - r2_by_r1)

    a1 = (L1 / beta1)**2
    e1 = T.sqrt(1 - (1 - (Gamma1 / L1))**2)

    a2 = (L2 / beta2)**2
    e2 = T.sqrt(1 - (1 - (Gamma2 / L2))**2)

    cos_inc1 = 1 - rho1 / G1
    cos_inc2 = 1 - rho2 / G2
    inc1 = T.arccos(cos_inc1)
    inc2 = T.arccos(cos_inc2)

    l1_r = l1 - Omega
    l2_r = l2 - Omega

    Omega1_r = T.constant(np.pi / 2) - Omega
    Omega2_r = Omega1_r - T.constant(np.pi)

    pomega1 = -1 * gamma1
    pomega2 = -1 * gamma2

    pomega1_r = pomega1 - Omega
    pomega2_r = pomega2 - Omega

    omega1 = pomega1_r - Omega1_r
    omega2 = pomega2_r - Omega2_r

    Hkep = -0.5 * T.sqrt(eta1) * beta1 / a1 - 0.5 * T.sqrt(eta2) * beta2 / a2

    ko = KeplerOp()
    M1 = l1_r - pomega1_r
    M2 = l2_r - pomega2_r
    sinf1, cosf1 = ko(M1, e1 + T.zeros_like(M1))
    sinf2, cosf2 = ko(M2, e2 + T.zeros_like(M2))
    #
    n1 = T.sqrt(eta1 / mstar) * a1**(-3 / 2)
    n2 = T.sqrt(eta2 / mstar) * a2**(-3 / 2)
    Hint_dir, Hint_ind, r1, r2, v1, v2 = calc_Hint_components_sinf_cosf(
        a1, a2, e1, e2, inc1, inc2, omega1, omega2, Omega1_r, Omega2_r, n1, n2,
        sinf1, cosf1, sinf2, cosf2)
    eps = m1 * m2 / (mu1 + mu2) / T.sqrt(mstar)
    Hpert = (Hint_dir + Hint_ind / mstar)
    Htot = Hkep + eps * Hpert

    #####################################################
    # Set parameters for compiling functions with Theano
    #####################################################

    # 'ins' will set the inputs of Theano functions compiled below
    #   Note: 'extra_ins' will be passed as values of object attributes
    #   of the 'ResonanceEquations' class 'defined below
    extra_ins = [m1, m2, j, k]
    givens = []
    ins = [dyvars] + extra_ins
    orbels = [
        a1, e1, inc1, l1_r, pomega1_r, Omega1_r, a2, e2, inc2, l2_r, pomega2_r,
        Omega2_r
    ]
    #  Conservative flow
    gradHtot = T.grad(Htot, wrt=dyvars)
    hessHtot = theano.gradient.hessian(Htot, wrt=dyvars)
    Jtens = T.as_tensor(_get_Omega_matrix(5))
    H_flow_vec = Jtens.dot(gradHtot)
    H_flow_jac = Jtens.dot(hessHtot)

    ##########################
    # Compile Theano functions
    ##########################
    orbels_fn = theano.function(inputs=ins,
                                outputs=orbels,
                                givens=givens,
                                on_unused_input='ignore')

    rv1_fn = theano.function(inputs=ins,
                             outputs=r1 + v1,
                             givens=givens,
                             on_unused_input='ignore')
    rv2_fn = theano.function(inputs=ins,
                             outputs=r2 + v2,
                             givens=givens,
                             on_unused_input='ignore')

    Htot_fn = theano.function(inputs=ins,
                              outputs=Htot,
                              givens=givens,
                              on_unused_input='ignore')

    Hpert_fn = theano.function(inputs=ins,
                               outputs=Hpert,
                               givens=givens,
                               on_unused_input='ignore')

    Hpert_components_fn = theano.function(inputs=ins,
                                          outputs=[Hint_dir, Hint_ind],
                                          givens=givens,
                                          on_unused_input='ignore')

    H_flow_vec_fn = theano.function(inputs=ins,
                                    outputs=H_flow_vec,
                                    givens=givens,
                                    on_unused_input='ignore')

    H_flow_jac_fn = theano.function(inputs=ins,
                                    outputs=H_flow_jac,
                                    givens=givens,
                                    on_unused_input='ignore')
    return dict({
        'orbital_elements': orbels_fn,
        'Hamiltonian': Htot_fn,
        'Hpert': Hpert_fn,
        'Hpert_components': Hpert_components_fn,
        'Hamiltonian_flow': H_flow_vec_fn,
        'Hamiltonian_flow_jacobian': H_flow_jac_fn,
        'positions_and_velocities1': rv1_fn,
        'positions_and_velocities2': rv2_fn
    })
Пример #8
0
def _get_compiled_theano_functions(N_QUAD_PTS):
    # resonance j and k
    j, k = T.lscalars('jk')
    s = (j - k) / k
    # Planet masses: m1,m2
    m1, m2 = T.dscalars(2)
    mstar = 1
    mu1 = m1 * mstar / (mstar + m1)
    mu2 = m2 * mstar / (mstar + m2)
    eta1 = mstar + m1
    eta2 = mstar + m2
    beta1 = mu1 * T.sqrt(eta1 / mstar) / (mu1 + mu2)
    beta2 = mu2 * T.sqrt(eta2 / mstar) / (mu1 + mu2)

    # Angle variable for averaging over
    psi = T.dvector('psi')

    # Dynamical variables:
    dyvars = T.vector()
    y1, y2, phi1, x1, x2, J1, amd = [dyvars[i] for i in range(7)]

    I1 = (y1 * y1 + x1 * x1) / 2
    I2 = (y2 * y2 + x2 * x2) / 2
    sigma1 = T.arctan2(y1, x1)
    sigma2 = T.arctan2(y2, x2)

    # Quadrature weights
    quad_weights = T.dvector('w')

    # Set l=0
    l = T.constant(0.)
    l1 = l - k * psi / 2
    l2 = l + k * psi / 2
    pomega1 = (1 + s) * l2 - s * l1 - sigma1
    pomega2 = (1 + s) * l2 - s * l1 - sigma2

    Gamma1 = I1
    Gamma2 = I2

    # Resonant semi-major axis ratio
    a20 = T.constant(1.0)
    a10 = (eta1 / eta2)**(1 / 3) * ((j - k) / j)**(2 / 3) * a20
    Lambda20 = beta2 * T.sqrt(a20)
    Lambda10 = beta1 * T.sqrt(a10)
    Ltot = Lambda10 + Lambda20

    Psi0 = 0.5 * k * (Lambda20 - Lambda10)
    Psi = Psi0 - k * (s + 1 / 2) * amd

    L1 = Ltot / 2 + J1 / 2 - Psi / k - s * (I1 + I2)
    L2 = Ltot / 2 + J1 / 2 + Psi / k + (1 + s) * (I1 + I2)

    # Choose z axis along direction of total angular momentum
    r2_by_r1 = (L2 - L1 - Gamma2 + Gamma1) / (L1 + L2 - Gamma1 - Gamma2 - J1)
    rho1 = 0.5 * J1 * (1 + r2_by_r1)
    rho2 = 0.5 * J1 * (1 - r2_by_r1)

    G1 = L1 - Gamma1
    G2 = L2 - Gamma1

    a1 = (L1 / beta1)**2
    e1 = T.sqrt(1 - (1 - (Gamma1 / L1))**2)

    a2 = (L2 / beta2)**2
    e2 = T.sqrt(1 - (1 - (Gamma2 / L2))**2)

    cos_inc1 = 1 - rho1 / G1
    cos_inc2 = 1 - rho2 / G2
    inc1 = T.arccos(cos_inc1)
    inc2 = T.arccos(cos_inc2)
    Omega1 = l - np.pi / 2 - phi1
    Omega2 = l + np.pi / 2 - phi1
    omega1 = pomega1 - Omega1
    omega2 = pomega2 - Omega2

    Hkep = -0.5 * T.sqrt(eta1) * beta1 / a1 - 0.5 * T.sqrt(eta2) * beta2 / a2

    ko = KeplerOp()
    M1 = l1 - pomega1
    M2 = l2 - pomega2
    sinf1, cosf1 = ko(M1, e1 + T.zeros_like(M1))
    sinf2, cosf2 = ko(M2, e2 + T.zeros_like(M2))
    #
    n1 = T.sqrt(eta1 / mstar) * a1**(-3 / 2)
    n2 = T.sqrt(eta2 / mstar) * a2**(-3 / 2)
    Hint_dir, Hint_ind = calc_Hint_components_sinf_cosf(
        a1, a2, e1, e2, inc1, inc2, omega1, omega2, Omega1, Omega2, n1, n2,
        sinf1, cosf1, sinf2, cosf2)
    eps = m1 * m2 / (mu1 + mu2) / T.sqrt(mstar * a20)
    Hpert = (Hint_dir + Hint_ind / mstar).dot(quad_weights)
    Htot = Hkep + eps * Hpert

    #####################################################
    # Set parameters for compiling functions with Theano
    #####################################################

    # Get numerical quadrature nodes and weights
    nodes, weights = np.polynomial.legendre.leggauss(N_QUAD_PTS)

    # Rescale for integration interval from [-1,1] to [-pi,pi]
    nodes = nodes * np.pi
    weights = weights * 0.5

    # 'givens' will fix some parameters of Theano functions compiled below
    givens = [(psi, nodes), (quad_weights, weights)]

    # 'ins' will set the inputs of Theano functions compiled below
    #   Note: 'extra_ins' will be passed as values of object attributes
    #   of the 'ResonanceEquations' class 'defined below
    extra_ins = [m1, m2, j, k]
    ins = [dyvars] + extra_ins

    orbels = [
        a1, e1, inc1, sigma1 * k, Omega1, a2, e2, inc2, sigma2 * k, Omega2
    ]

    #  Conservative flow
    gradHtot = T.grad(Htot, wrt=dyvars)
    hessHtot = theano.gradient.hessian(Htot, wrt=dyvars)
    Jtens = T.as_tensor(np.pad(_get_Omega_matrix(3), (0, 1), 'constant'))
    H_flow_vec = Jtens.dot(gradHtot)
    H_flow_jac = Jtens.dot(hessHtot)

    ##########################
    # Compile Theano functions
    ##########################
    actions_fn = theano.function(
        inputs=ins,
        outputs={'L1':L1,'L1':L2,'Gamma1':Gamma1,'Gamma2':Gamma2,\
                'Q1':rho1,'Q2':rho2,'Psi':Psi,'Psi0':Psi0},
        givens=givens,
        on_unused_input='ignore'
    )
    orbels_fn = theano.function(inputs=ins,
                                outputs=orbels,
                                givens=givens,
                                on_unused_input='ignore')

    Htot_fn = theano.function(inputs=ins,
                              outputs=Htot,
                              givens=givens,
                              on_unused_input='ignore')

    Hpert_fn = theano.function(inputs=ins,
                               outputs=Hpert,
                               givens=givens,
                               on_unused_input='ignore')

    H_flow_vec_fn = theano.function(inputs=ins,
                                    outputs=H_flow_vec,
                                    givens=givens,
                                    on_unused_input='ignore')

    H_flow_jac_fn = theano.function(inputs=ins,
                                    outputs=H_flow_jac,
                                    givens=givens,
                                    on_unused_input='ignore')
    return dict({
        'orbital_elements': orbels_fn,
        'actions': actions_fn,
        'Hamiltonian': Htot_fn,
        'Hpert': Hpert_fn,
        'Hamiltonian_flow': H_flow_vec_fn,
        'Hamiltonian_flow_jacobian': H_flow_jac_fn
    })