Source code for GUIBRUSHR.General_Constants.FunctionsAndConstants.radvel_g
"""
Credit to radvel software
RadVel: The Radial Velocity Modeling Toolkit
10.1088/1538-3873/aaaaa8
"""
import numpy as np
[docs]
def rv_drive(t, orbel):
"""RV Drive
Args:
t (array of floats): times of observations
orbel (array of floats): [per, tp, e, om, K].\
Omega is expected to be\
in radians
Returns:
rv: (array of floats): radial velocity model
"""
# unpack array of parameters
per, tp, e, om, k = orbel
# Performance boost for circular orbits
if e == 0.0:
m = 2 * np.pi * (((t - tp) / per) - np.floor((t - tp) / per))
return k * np.cos(m + om)
if per < 0:
per = 1e-4
if e < 0:
e = 0
if e > 0.99:
e = 0.99
nu = true_anomaly(t, tp, per, e)
rv = k * (np.cos(nu + om) + e * np.cos(om))
return rv
[docs]
def true_anomaly(t, tp, per, e):
"""
Calculate the true anomaly for a given time, period, eccentricity.
Args:
t (array): array of times in JD
tp (float): time of periastron, same units as t
per (float): orbital period in days
e (float): eccentricity
Returns:
array: true anomoly at each time
"""
# f in Murray and Dermott p. 27
m = 2 * np.pi * (((t - tp) / per) - np.floor((t - tp) / per))
eccarr = np.zeros(t.size) + e
e1 = kepler(m, eccarr)
n1 = 1.0 + e
n2 = 1.0 - e
nu = 2.0 * np.arctan((n1 / n2)**0.5 * np.tan(e1 / 2.0))
return nu
[docs]
def kepler(Marr, eccarr):
"""Solve Kepler's Equation
Args:
Marr (array): input Mean anomaly
eccarr (array): eccentricity
Returns:
array: eccentric anomaly
"""
conv = 1.0e-12 # convergence criterion
k = 0.85
Earr = Marr + np.sign(np.sin(Marr)) * k * eccarr # first guess at E
# fiarr should go to zero when converges
fiarr = ( Earr - eccarr * np.sin(Earr) - Marr)
convd = np.where(np.abs(fiarr) > conv)[0] # which indices have not converged
nd = len(convd) # number of unconverged elements
count = 0
while nd > 0: # while unconverged elements exist
count += 1
# M = Marr[convd] # just the unconverged elements ...
ecc = eccarr[convd]
E = Earr[convd]
fi = fiarr[convd] # fi = E - e*np.sin(E)-M ; should go to 0
fip = 1 - ecc * np.cos(E) # d/dE(fi) ;i.e., fi^(prime)
fipp = ecc * np.sin(E) # d/dE(d/dE(fi)) ;i.e., fi^(\prime\prime)
fippp = 1 - fip # d/dE(d/dE(d/dE(fi))) ;i.e., fi^(\prime\prime\prime)
# first, second, and third order corrections to E
d1 = -fi / fip
d2 = -fi / (fip + d1 * fipp / 2.0)
d3 = -fi / (fip + d2 * fipp / 2.0 + d2 * d2 * fippp / 6.0)
E = E + d3
Earr[convd] = E
fiarr = ( Earr - eccarr * np.sin( Earr ) - Marr) # how well did we do?
convd = np.abs(fiarr) > conv # test for convergence
nd = np.sum(convd)
if Earr.size > 1:
return Earr
else:
return Earr[0]
[docs]
def timetrans_to_timeperi(tc, per, ecc, omega):
"""
Convert Time of Transit to Time of Periastron Passage
Args:
tc (float): time of transit
per (float): period [days]
ecc (float): eccentricity
omega (float): longitude of periastron (radians)
Returns:
float: time of periastron passage
"""
try:
if ecc >= 1:
return tc
except ValueError:
pass
f = np.pi/2 - omega
ee = 2 * np.arctan(np.tan(f/2) * np.sqrt((1-ecc)/(1+ecc))) # eccentric anomaly
tp = tc - per/(2*np.pi) * (ee - ecc*np.sin(ee)) # time of periastron
return tp