1use std::fmt;
4use std::sync::Arc;
5
6use crate::affine::Affine;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub enum Rung {
12 IndexOnly,
14 Regular,
16 Rectilinear,
18 Curvilinear,
20 Fitted,
22 ImplicitMesh,
24 ExplicitMesh,
26 Features,
28}
29
30#[derive(Debug, Clone, PartialEq)]
32pub struct CoordArray {
33 pub shape: Vec<usize>,
34 pub values: Vec<f64>,
35}
36
37impl CoordArray {
38 pub fn new(shape: Vec<usize>, values: Vec<f64>) -> Self {
39 assert_eq!(
40 shape.iter().product::<usize>(),
41 values.len(),
42 "CoordArray shape does not match its values"
43 );
44 Self { shape, values }
45 }
46}
47
48pub trait FittedModel: fmt::Debug + Send + Sync {
50 fn forward(&self, index: &[f64]) -> Option<Vec<f64>>;
51 fn inverse(&self, _position: &[f64]) -> Option<Vec<f64>> {
52 None
53 }
54}
55
56pub trait CellScheme: fmt::Debug + Send + Sync {
58 fn name(&self) -> &str;
60 fn centre(&self, cell: u64) -> Option<Vec<f64>>;
62}
63
64pub trait Elements: fmt::Debug + Send + Sync {
66 fn len(&self) -> usize;
67 fn is_empty(&self) -> bool {
68 self.len() == 0
69 }
70}
71
72#[derive(Debug, Clone)]
74pub enum Positions {
75 IndexOnly,
77 Affine(Affine),
79 Regular1 { origin: f64, step: f64 },
82 Rectilinear(Vec<Vec<f64>>),
84 Curvilinear(Vec<CoordArray>),
87 Fitted(Arc<dyn FittedModel>),
89 Scheme(Arc<dyn CellScheme>),
91 Explicit(Arc<dyn Elements>),
93}
94
95impl Positions {
96 pub fn rung(&self) -> Rung {
97 match self {
98 Positions::IndexOnly => Rung::IndexOnly,
99 Positions::Affine(_) | Positions::Regular1 { .. } => Rung::Regular,
100 Positions::Rectilinear(_) => Rung::Rectilinear,
101 Positions::Curvilinear(_) => Rung::Curvilinear,
102 Positions::Fitted(_) => Rung::Fitted,
103 Positions::Scheme(_) => Rung::ImplicitMesh,
104 Positions::Explicit(_) => Rung::ExplicitMesh,
105 }
106 }
107
108 pub fn stored_values(&self) -> usize {
111 match self {
112 Positions::IndexOnly => 0,
113 Positions::Affine(_) => 6,
114 Positions::Regular1 { .. } => 2,
115 Positions::Rectilinear(v) => v.iter().map(Vec::len).sum(),
116 Positions::Curvilinear(a) => a.iter().map(|c| c.values.len()).sum(),
117 Positions::Fitted(_) | Positions::Scheme(_) | Positions::Explicit(_) => 0,
118 }
119 }
120}