use super::Builder;
use crate::{
CS, CfdLoads, M1S, M2S, MAX_DURATION, Result,
windloads::{WindLoads, WindLoadsBuilder},
};
use geotrans::{SegmentTrait, Transform};
use parse_monitors::{Exertion, Monitors, Vector};
use serde::{Deserialize, Serialize};
use std::mem;
impl<S> Builder<S> {
pub fn build(self) -> Result<CfdLoads<S>> {
let mut monitors = if let Some(time_range) = self.time_range {
Monitors::loader::<String, 2021>(self.cfd_case)
.start_time(time_range.0)
.end_time(time_range.1)
.load()?
} else {
Monitors::loader::<String, 2021>(self.cfd_case).load()?
};
let fm = monitors.forces_and_moments.remove("Cabs").unwrap();
monitors
.forces_and_moments
.get_mut("platform")
.unwrap()
.iter_mut()
.zip(fm.into_iter())
.for_each(|(p, c)| {
let u = p.clone();
*p = &u + &c;
});
let fm = monitors.forces_and_moments.remove("cabletrays").unwrap();
monitors
.forces_and_moments
.get_mut("platform")
.unwrap()
.iter_mut()
.zip(fm.into_iter())
.for_each(|(p, c)| {
let u = p.clone();
*p = &u + &c;
});
let n_sample = match self.duration {
Some(duration) => {
let d = duration.ceil() as usize;
monitors.keep_last(MAX_DURATION.min(d)); d * 20 + 1
}
None => monitors.len(),
};
let mut fm: Option<Vec<Option<Vec<f64>>>> = None;
let mut m1_fm: Option<Vec<Option<Vec<f64>>>> = None;
let mut m2_fm: Option<Vec<Option<Vec<f64>>>> = None;
let mut total_exertion: Vec<Exertion> = vec![];
if let Some(ref nodes) = self.nodes {
for i in 0..monitors.len() {
total_exertion.push(Exertion {
force: Vector::zero(),
moment: Vector::zero(),
cop: None,
});
for (key, location) in nodes.iter() {
let mut m1_cell = monitors
.forces_and_moments
.get_mut("M1cell")
.expect("M1cell not found in CFD loads")
.clone();
let exertion = monitors
.forces_and_moments
.get_mut(key)
.expect(&format!("{key} not found in CFD loads"));
let u = total_exertion[i].clone();
total_exertion[i] = &u + &exertion[i].clone();
match location {
CS::OSS(loc) => {
exertion[i].into_local(loc.into());
if let Some(fm) = fm.as_mut() {
fm.push((&exertion[i]).into());
} else {
fm = Some(vec![(&exertion[i]).into()]);
}
}
CS::M1S(j) => {
if *j < 2 {
let u = total_exertion[i].clone();
total_exertion[i] = &u + &m1_cell[i].clone();
}
let t: [f64; 3] = M1S::new(*j)?.translation().into();
exertion[i].into_local(t.into());
m1_cell[i].into_local(t.into());
if let Some(m1_cell) = &m1_cell[i] / 7f64 {
let v = &exertion[i] + &m1_cell;
exertion[i] = v;
}
if let (Some(f), Some(m)) = (
Into::<Option<[f64; 3]>>::into(&exertion[i].force),
Into::<Option<[f64; 3]>>::into(&exertion[i].moment),
) {
exertion[i].force = f.vfrov(M1S::new(*j))?.into();
exertion[i].moment = m.vfrov(M1S::new(*j))?.into();
};
if let Some(m1_fm) = m1_fm.as_mut() {
m1_fm.push((&exertion[i]).into());
} else {
m1_fm = Some(vec![(&exertion[i]).into()]);
}
}
CS::M2S(j) => {
let t: [f64; 3] = M2S::new(*j)?.translation().into();
exertion[i].into_local(t.into());
if let (Some(f), Some(m)) = (
Into::<Option<[f64; 3]>>::into(&exertion[i].force),
Into::<Option<[f64; 3]>>::into(&exertion[i].moment),
) {
exertion[i].force = f.vfrov(M2S::new(*j))?.into();
exertion[i].moment = m.vfrov(M2S::new(*j))?.into();
};
if let Some(m2_fm) = m2_fm.as_mut() {
m2_fm.push((&exertion[i]).into());
} else {
m2_fm = Some(vec![(&exertion[i]).into()]);
}
}
};
}
}
} else {
for i in 0..monitors.len() {
for exertion in monitors.forces_and_moments.values() {
if let Some(fm) = fm.as_mut() {
fm.push((&exertion[i]).into());
} else {
fm = Some(vec![(&exertion[i]).into()]);
}
}
}
}
let n = total_exertion.len() as f64;
let force_mean = (total_exertion
.iter()
.fold(Vector::zero(), |a, e| a + e.force.clone())
/ n)
.unwrap();
let mut force_std = total_exertion
.iter()
.map(|e| (e.force.clone() - force_mean.clone()).unwrap())
.map(|v| {
let a: Option<Vec<f64>> = v.into();
let a = a.unwrap();
vec![a[0] * a[0], a[1] * a[1], a[2] * a[2]]
})
.fold(vec![0f64; 3], |mut a, e| {
a.iter_mut().zip(e.iter()).for_each(|(a, e)| {
*a += e;
});
a
});
force_std.iter_mut().for_each(|x| *x = (*x / n).sqrt());
log::info!(
" OSS force: mean = {:.0?}N ; std = {:.0?}N",
force_mean,
force_std
);
let moment_mean = (total_exertion
.iter()
.fold(Vector::zero(), |a, e| a + e.moment.clone())
/ n)
.unwrap();
let mut moment_std = total_exertion
.iter()
.map(|e| (e.moment.clone() - moment_mean.clone()).unwrap())
.map(|v| {
let a: Option<Vec<f64>> = v.into();
let a = a.unwrap();
vec![a[0] * a[0], a[1] * a[1], a[2] * a[2]]
})
.fold(vec![0f64; 3], |mut a, e| {
a.iter_mut().zip(e.iter()).for_each(|(a, e)| {
*a += e;
});
a
});
moment_std.iter_mut().for_each(|x| *x = (*x / n).sqrt());
log::info!(
" OSS moment: mean = {:.0?}N.m ; std = {:.0?}N.m",
moment_mean,
moment_std
);
let mut data: Option<Vec<f64>> = if let Some(fm) = fm {
Some(fm.into_iter().filter_map(|x| x).flatten().collect())
} else {
None
};
let mut m1_loads: Option<Vec<f64>> = if let Some(fm) = m1_fm {
Some(fm.into_iter().filter_map(|x| x).flatten().collect())
} else {
None
};
let mut m2_loads: Option<Vec<f64>> = if let Some(fm) = m2_fm {
Some(fm.into_iter().filter_map(|x| x).flatten().collect())
} else {
None
};
let n = data
.as_ref()
.map_or(m1_loads.as_ref().map_or(0, |x| x.len()), |x| x.len())
/ monitors.time.len();
if n_sample > monitors.len() {
if let Some(ref mut data) = data {
let mut v = data.clone();
while n_sample * n > v.len() {
v = v
.chunks(n)
.chain(v.chunks(n).rev().skip(1))
.take(n_sample)
.flat_map(|x| x.to_vec())
.collect();
}
mem::swap(data, &mut v);
}
if let Some(ref mut data) = m1_loads {
let mut v = data.clone();
let n = 42;
while n_sample * n > v.len() {
v = v
.chunks(n)
.chain(v.chunks(n).rev().skip(1))
.take(n_sample)
.flat_map(|x| x.to_vec())
.collect();
}
mem::swap(data, &mut v);
}
if let Some(ref mut data) = m2_loads {
let mut v = data.clone();
let n = 42;
while n_sample * n > v.len() {
v = v
.chunks(n)
.chain(v.chunks(n).rev().skip(1))
.take(n_sample)
.flat_map(|x| x.to_vec())
.collect();
}
mem::swap(data, &mut v);
}
}
Ok(CfdLoads {
oss: data,
m1: m1_loads,
m2: m2_loads,
nodes: self.nodes,
n_fm: n,
step: 0,
upsampling: self.upsampling,
max_step: usize::MAX,
})
}
}