mod config;
mod result;
pub use config::{
AdvancedIntegratorConfig, DiagnosticsConfig, EventConfig, ForceModelTier, IntegratorChoice,
OriginSwitchingConfig, PropagationConfig, UncertaintyMethod,
};
pub use result::{
CovarianceKind, CovarianceQuality, Event, PropagatedState, PropagationResult, TaggedCovariance,
TargetFunctional,
};
pub(crate) use config::PropConfigKeep;
use std::ffi::CStr;
use crate::context::Context;
use crate::error::{Error, Result};
use crate::orbit::Orbit;
impl Context {
pub fn propagate(
&self,
orbits: &[Orbit],
epochs: &[crate::Epoch],
config: &PropagationConfig,
) -> Result<PropagationResult> {
let (ffi_orbits, _orbit_keep) = crate::orbit::orbits_to_ffi(orbits)?;
let (ffi_config, _config_keep) = config.to_ffi_with();
let epochs_mjd_tdb: Vec<f64> = epochs
.iter()
.map(|e| e.mjd_tdb())
.collect::<Result<Vec<_>>>()?;
let mut ffi_result = empyrean_sys::EmpyreanPropagationResult {
states: std::ptr::null_mut(),
num_states: 0,
object_ids: std::ptr::null_mut(),
events: std::ptr::null_mut(),
num_events: 0,
mixtures: std::ptr::null_mut(),
num_mixtures: 0,
lazy_handle: std::ptr::null_mut(),
};
let code = unsafe {
empyrean_sys::empyrean_propagate(
self.as_raw(),
ffi_orbits.as_ptr(),
ffi_orbits.len(),
epochs_mjd_tdb.as_ptr(),
epochs_mjd_tdb.len(),
&ffi_config,
&mut ffi_result,
)
};
if code != 0 {
return Err(Error::capture(code));
}
marshal_propagation_result(ffi_result, orbits.len())
}
}
pub(crate) fn marshal_propagation_result(
ffi_result: empyrean_sys::EmpyreanPropagationResult,
num_orbits: usize,
) -> Result<PropagationResult> {
let states: Vec<PropagatedState> = if ffi_result.states.is_null() {
Vec::new()
} else {
unsafe { std::slice::from_raw_parts(ffi_result.states, ffi_result.num_states) }
.iter()
.map(PropagatedState::from_ffi)
.collect::<Result<_>>()?
};
let object_ids = if ffi_result.object_ids.is_null() {
Vec::new()
} else {
unsafe { std::slice::from_raw_parts(ffi_result.object_ids, num_orbits) }
.iter()
.map(|&p| {
if p.is_null() {
String::new()
} else {
unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned()
}
})
.collect()
};
let events = if ffi_result.events.is_null() {
Vec::new()
} else {
unsafe { std::slice::from_raw_parts(ffi_result.events, ffi_result.num_events) }
.iter()
.map(Event::from_ffi)
.collect()
};
Ok(PropagationResult::new(
states, object_ids, events, ffi_result,
))
}