use crate::Star;
use crate::Vec3;
use crate::errors::RocheError;
use crate::fblink;
use crate::ingress_egress;
use crate::set_earth;
use pyo3::prelude::*;
#[pyfunction]
#[pyo3(signature = (q, dphi, acc=1.0e-4, delta_i=1.0e-5))]
pub fn findi(q: f64, dphi: f64, acc: f64, delta_i: f64) -> Result<f64, RocheError> {
if q <= 0.0 {
return Err(RocheError::ParameterError(
"mass ratio must be positive".to_string(),
));
}
if dphi <= 0.0 || dphi >= 0.25 {
return Err(RocheError::ParameterError(
"phase width must be between 0 and 0.25".to_string(),
));
}
if acc <= 0.0 || acc >= 0.1 {
return Err(RocheError::ParameterError(
"accuracy must be between 0 and 0.1".to_string(),
));
}
if delta_i <= 0.0 || delta_i >= 10.0 {
return Err(RocheError::ParameterError(
"delta_i must be between 0 and 10 degrees".to_string(),
));
}
let mut ilo: f64 = 65.0;
let mut ihi: f64 = 90.0;
let phi: f64 = dphi / 2.0;
let earth1: Vec3 = set_earth::set_earth_iangle(ilo, phi);
let earth2: Vec3 = set_earth::set_earth_iangle(ihi, phi);
let r: Vec3 = Vec3::new(0.0, 0.0, 0.0);
let elo: bool = fblink::fblink(q, Star::Secondary, 1.0, 1.0, acc, &earth1, &r)?;
let ehi: bool = fblink::fblink(q, Star::Secondary, 1.0, 1.0, acc, &earth2, &r)?;
if elo && ehi {
return Ok(-2.0);
} else if !elo && !ehi {
return Ok(-1.0);
}
while (ihi - ilo) > delta_i {
let imid: f64 = (ilo + ihi) / 2.0;
let earth_mid: Vec3 = set_earth::set_earth_iangle(imid, phi);
let emid: bool = fblink::fblink(q, Star::Secondary, 1.0, 1.0, acc, &earth_mid, &r)?;
if emid {
ihi = imid;
} else {
ilo = imid;
}
}
Ok((ilo + ihi) / 2.0)
}
#[pyfunction]
#[pyo3(signature = (i, dphi, acc=1.0e-4, delta_q=1.0e-5))]
pub fn findq(i: f64, dphi: f64, acc: f64, delta_q: f64) -> Result<f64, RocheError> {
if i <= 0.0 || i >= 90.0 {
return Err(RocheError::ParameterError(
"inclination must be between 0 and 90 degrees".to_string(),
));
}
if dphi <= 0.0 || dphi >= 0.25 {
return Err(RocheError::ParameterError(
"phase width must be between 0 and 0.25".to_string(),
));
}
if acc <= 0.0 || acc >= 0.1 {
return Err(RocheError::ParameterError(
"accuracy must be between 0 and 0.1".to_string(),
));
}
if delta_q <= 0.0 || delta_q >= 0.1 {
return Err(RocheError::ParameterError(
"delta_q must be between 0 and 0.1".to_string(),
));
}
let mut qlo: f64 = 0.001;
let mut qhi: f64 = 2.0;
let phi: f64 = dphi / 2.0;
let earth: Vec3 = set_earth::set_earth_iangle(i, phi);
let r: Vec3 = Vec3::new(0.0, 0.0, 0.0);
let elo: bool = fblink::fblink(qlo, Star::Secondary, 1.0, 1.0, acc, &earth, &r)?;
let ehi: bool = fblink::fblink(qhi, Star::Secondary, 1.0, 1.0, acc, &earth, &r)?;
if elo && ehi {
return Ok(-2.0);
} else if !elo && !ehi {
return Ok(-1.0);
}
while (qhi - qlo) > delta_q {
let qmid: f64 = (qlo + qhi) / 2.0;
let emid: bool = fblink::fblink(qmid, Star::Secondary, 1.0, 1.0, acc, &earth, &r)?;
if emid {
qhi = qmid;
} else {
qlo = qmid;
}
}
Ok((qlo + qhi) / 2.0)
}
#[pyfunction]
#[pyo3(signature = (q, iangle, delta=1.0e-6))]
pub fn findphi(q: f64, iangle: f64, delta: f64) -> Result<f64, RocheError> {
let r: Vec3 = Vec3::new(0.0, 0.0, 0.0);
let mut ingress: f64 = 0.0;
let mut egress: f64 = 0.0;
let status: bool = ingress_egress::ingress_egress(
q,
Star::Secondary,
1.0,
1.0,
iangle,
delta,
&r,
&mut ingress,
&mut egress,
)?;
if !status {
return Ok(-1.0);
}
Ok(egress - ingress)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn findi_test() -> Result<(), RocheError> {
assert_eq!(findi(0.2, 0.06, 1.0e-4, 1.0e-5)?, 81.34474098682404);
assert!(findi(-0.2, 0.06, 1.0e-4, 1.0e-5).is_err());
assert!(findi(0.2, 0.4, 1.0e-4, 1.0e-5).is_err());
assert!(findi(0.2, 0.06, 0.15, 1.0e-5).is_err());
assert!(findi(0.2, 0.06, 1.0e-4, 15.0).is_err());
Ok(())
}
#[test]
fn findq_test() -> Result<(), RocheError> {
assert_eq!(findq(85.0, 0.06, 1.0e-4, 1.0e-5)?, 0.11792682838439941);
assert!(findq(91.0, 0.06, 1.0e-4, 1.0e-5).is_err());
assert!(findq(85.0, 0.4, 1.0e-4, 1.0e-5).is_err());
assert!(findq(85.0, 0.06, 0.15, 1.0e-5).is_err());
assert!(findq(85.0, 0.06, 1.0e-4, 15.0).is_err());
Ok(())
}
#[test]
fn findphi_test() -> Result<(), RocheError> {
assert_eq!(findphi(0.2, 85.0, 1.0e-6)?, 0.07246334161812373);
Ok(())
}
}