kriging_rs/variogram/
nested.rs1use crate::Real;
13use crate::error::KrigingError;
14use crate::variogram::models::VariogramModel;
15
16#[derive(Debug, Clone)]
18pub struct NestedVariogram {
19 components: Vec<VariogramModel>,
20}
21
22impl NestedVariogram {
23 pub fn new(components: Vec<VariogramModel>) -> Result<Self, KrigingError> {
25 if components.is_empty() {
26 return Err(KrigingError::InvalidInput(
27 "nested variogram requires at least one component".to_string(),
28 ));
29 }
30 Ok(Self { components })
31 }
32
33 pub fn components(&self) -> &[VariogramModel] {
35 &self.components
36 }
37
38 pub fn semivariance(&self, distance: Real) -> Real {
40 self.components
41 .iter()
42 .map(|m| m.semivariance(distance))
43 .sum()
44 }
45
46 pub fn covariance(&self, distance: Real) -> Real {
53 self.components.iter().map(|m| m.covariance(distance)).sum()
54 }
55
56 pub fn total_sill(&self) -> Real {
59 self.components
60 .iter()
61 .map(|m| m.covariance(0.0) + m.semivariance(0.0))
62 .sum()
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 use crate::variogram::models::VariogramType;
70
71 #[test]
72 fn new_rejects_empty_components() {
73 assert!(NestedVariogram::new(vec![]).is_err());
74 }
75
76 #[test]
77 fn semivariance_is_sum_of_components() {
78 let a = VariogramModel::new(0.1, 1.0, 5.0, VariogramType::Exponential).unwrap();
79 let b = VariogramModel::new(0.0, 2.0, 30.0, VariogramType::Gaussian).unwrap();
80 let nested = NestedVariogram::new(vec![a, b]).unwrap();
81 let h = 7.0;
82 let sum = a.semivariance(h) + b.semivariance(h);
83 assert!((nested.semivariance(h) - sum).abs() < 1e-5);
84 }
85
86 #[test]
87 fn covariance_complements_semivariance() {
88 let a = VariogramModel::new(0.1, 1.0, 5.0, VariogramType::Exponential).unwrap();
89 let b = VariogramModel::new(0.0, 2.0, 30.0, VariogramType::Gaussian).unwrap();
90 let nested = NestedVariogram::new(vec![a, b]).unwrap();
91 let h = 4.0;
92 let total = nested.total_sill();
93 assert!((nested.covariance(h) + nested.semivariance(h) - total).abs() < 1e-4);
94 }
95}