gmt_dos-clients_windloads 2.2.0

GMT DOS Windloads Client
Documentation
use std::fmt::Display;

use gmt_dos_actors::{
    actor::{Actor, Initiator, PlainActor},
    framework::{
        model::{Check, SystemFlowChart, Task},
        network::{AddActorOutput, AddOuput, TryIntoInputs},
    },
    system::{Sys, System, SystemOutput},
};
use gmt_dos_clients::{signals::SignalsError, OneSignal, Signal, Signals, Weight};
use gmt_dos_clients_io::cfd_wind_loads::{CFDM1WindLoads, CFDM2WindLoads, CFDMountWindLoads};
use interface::Update;
use serde::{Deserialize, Serialize};

use crate::{Builder, CfdLoads, WindLoadsError, FOH};

mod m1;
mod m2;
mod mount;
pub use m1::M1Smoother as M1;
pub use m2::M2Smoother as M2;
pub use mount::MountSmoother as Mount;

#[derive(Debug, thiserror::Error)]
pub enum SigmoidCfdLoadsError {
    #[error("failed to create sigmoid signal")]
    Sigmoid(#[from] SignalsError),
    #[error("failed to create CFD wind loads")]
    WindLoads(#[from] WindLoadsError),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SigmoidCfdLoads<S = FOH>
where
    CfdLoads<S>: Update,
{
    cfd_loads: Initiator<CfdLoads<S>>,
    m1_smoother: Actor<M1>,
    m2_smoother: Actor<M2>,
    mount_smoother: Actor<Mount>,
    sigmoid: Initiator<OneSignal>,
}

impl TryFrom<Builder<FOH>> for SigmoidCfdLoads {
    type Error = SigmoidCfdLoadsError;

    fn try_from(builder: Builder<FOH>) -> Result<Self, Self::Error> {
        let sampling_frequency = builder.upsampling.rate * 20;
        let m1_smoother = M1::new();
        let m2_smoother = M2::new();
        let mount_smoother = Mount::new();
        let sigmoid = OneSignal::try_from(Signals::new(1, usize::MAX).channel(
            0,
            Signal::Sigmoid {
                amplitude: 1f64,
                sampling_frequency_hz: sampling_frequency as f64,
            },
        ))?;
        Ok(Self {
            cfd_loads: builder.build()?.into(),
            m1_smoother: m1_smoother.into(),
            m2_smoother: m2_smoother.into(),
            mount_smoother: mount_smoother.into(),
            sigmoid: sigmoid.into(),
        })
    }
}

impl TryFrom<Builder<FOH>> for Sys<SigmoidCfdLoads> {
    type Error = anyhow::Error;
    fn try_from(builder: Builder<FOH>) -> Result<Self, Self::Error> {
        Sys::new(builder.try_into()?).build()
    }
}

impl<S> Display for SigmoidCfdLoads<S>
where
    CfdLoads<S>: Update,
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.cfd_loads.fmt(f)
    }
}

impl System for SigmoidCfdLoads
where
    CfdLoads<FOH>: Update,
{
    fn build(&mut self) -> anyhow::Result<&mut Self> {
        self.cfd_loads
            .add_output()
            .build::<CFDM1WindLoads>()
            .into_input(&mut self.m1_smoother)?;
        self.cfd_loads
            .add_output()
            .build::<CFDM2WindLoads>()
            .into_input(&mut self.m2_smoother)?;
        self.cfd_loads
            .add_output()
            .build::<CFDMountWindLoads>()
            .into_input(&mut self.mount_smoother)?;

        self.sigmoid
            .add_output()
            .build::<Weight>()
            .into_input(&mut self.m1_smoother)?;
        self.sigmoid
            .add_output()
            .build::<Weight>()
            .into_input(&mut self.m2_smoother)?;
        self.sigmoid
            .add_output()
            .build::<Weight>()
            .into_input(&mut self.mount_smoother)?;

        Ok(self)
    }

    fn plain(&self) -> gmt_dos_actors::actor::PlainActor {
        self.flowchart();
        let mut plain = PlainActor::default();
        plain.client = self.name();
        plain.inputs_rate = 0;
        plain.outputs_rate = 1;
        plain.outputs = match (
            PlainActor::from(&self.m1_smoother).outputs,
            PlainActor::from(&self.m2_smoother).outputs,
            PlainActor::from(&self.mount_smoother).outputs,
        ) {
            (Some(mut m1), Some(m2), Some(mount)) => {
                m1.extend(m2);
                m1.extend(mount);
                Some(m1)
            }
            _ => None,
        };
        plain
    }

    fn name(&self) -> String {
        "CFD Wind Loads 💨".to_string()
    }
}

impl<'a> IntoIterator for &'a SigmoidCfdLoads {
    type Item = Box<&'a dyn Check>;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        vec![
            Box::new(&self.cfd_loads as &dyn Check),
            Box::new(&self.m1_smoother as &dyn Check),
            Box::new(&self.m2_smoother as &dyn Check),
            Box::new(&self.mount_smoother as &dyn Check),
            Box::new(&self.sigmoid as &dyn Check),
        ]
        .into_iter()
    }
}

impl IntoIterator for Box<SigmoidCfdLoads> {
    type Item = Box<dyn Task>;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        vec![
            Box::new(self.cfd_loads) as Box<dyn Task>,
            Box::new(self.m1_smoother) as Box<dyn Task>,
            Box::new(self.m2_smoother) as Box<dyn Task>,
            Box::new(self.mount_smoother) as Box<dyn Task>,
            Box::new(self.sigmoid) as Box<dyn Task>,
        ]
        .into_iter()
    }
}

impl SystemOutput<M1, 1, 1> for SigmoidCfdLoads {
    fn output(&mut self) -> &mut Actor<M1, 1, 1> {
        &mut self.m1_smoother
    }
}

impl SystemOutput<M2, 1, 1> for SigmoidCfdLoads {
    fn output(&mut self) -> &mut Actor<M2, 1, 1> {
        &mut self.m2_smoother
    }
}

impl SystemOutput<Mount, 1, 1> for SigmoidCfdLoads {
    fn output(&mut self) -> &mut Actor<Mount, 1, 1> {
        &mut self.mount_smoother
    }
}