use gmt_dos_clients_fem::{DiscreteStateSpace, StateSpaceError, solvers::ExponentialMatrix};
mod facesheet;
mod reference_body;
mod voice_coils;
pub use facesheet::{Facesheet, FacesheetOptions};
pub use reference_body::ReferenceBody;
pub use voice_coils::VoiceCoils;
use facesheet::FacesheetError;
use super::Include;
#[derive(Debug, thiserror::Error)]
pub enum AsmsServoError {
#[error("Failed to build the ASMS facesheets")]
Facesheet(#[from] FacesheetError),
}
#[derive(Debug, Clone, Default)]
pub struct AsmsServo {
pub(crate) voice_coils: Option<VoiceCoils>,
facesheet: Option<Facesheet>,
reference_body: Option<ReferenceBody>,
}
impl AsmsServo {
pub fn new() -> Self {
Default::default()
}
pub fn facesheet(mut self, facesheet: Facesheet) -> Self {
self.facesheet = Some(facesheet);
self
}
pub fn reference_body(mut self, reference_body: ReferenceBody) -> Self {
self.reference_body = Some(reference_body);
self
}
pub fn voice_coils(mut self, voice_coils: VoiceCoils) -> Self {
self.voice_coils = Some(voice_coils);
self
}
pub fn build(&mut self, fem: &gmt_fem::FEM) -> Result<(), AsmsServoError> {
if let Some(facesheet) = self.facesheet.as_mut() {
if facesheet.options.remove_rigid_body_motions() && self.reference_body.is_none() {
self.reference_body = Some(ReferenceBody::new());
}
facesheet.build(fem)?;
}
Ok(())
}
pub fn n_modes(&self) -> Option<Vec<usize>> {
self.voice_coils.as_ref().and_then(VoiceCoils::n_modes)
}
}
impl<'a> Include<'a, AsmsServo> for DiscreteStateSpace<'a, ExponentialMatrix> {
fn including(self, asms_servo: Option<&'a mut AsmsServo>) -> Result<Self, StateSpaceError> {
let Some(asms_servo) = asms_servo else {
return Ok(self.including_asms(Some(vec![1, 2, 3, 4, 5, 6, 7]), None, None)?);
};
self.including(asms_servo.voice_coils.as_mut())?
.including(asms_servo.facesheet.as_mut())?
.including(asms_servo.reference_body.as_mut())
}
}