cmtool_assemble/parser/
pfr_mb.rs1use crate::{CMError, data::FlowDirection};
4use cmtool_data::PhaseCM;
5use std::collections::HashMap;
6
7#[derive(Default, Copy, Clone, Debug)]
9struct FlowData {
10 in_flow: f64,
11 out_flow: f64,
12}
13
14#[derive(Copy, Clone, Debug, Default)]
16pub struct PhaseFlow {
17 gas: FlowData,
18 liquid: FlowData,
19}
20
21#[derive(Default, Debug)]
23pub struct PfrGlobalMassBalance {
24 flows: HashMap<String, PhaseFlow>,
25 validated: bool,
26}
27
28impl PfrGlobalMassBalance {
29 pub(super) fn new(pfr_names: &[String]) -> Self {
30 let mut flows = HashMap::new();
31 for name in pfr_names {
32 flows.insert(name.clone(), PhaseFlow::default());
33 }
34 PfrGlobalMassBalance {
35 flows,
36 validated: false,
37 }
38 }
39
40 pub(super) fn validate(&mut self) -> Result<(), CMError> {
41 for (i, flow) in &self.flows {
42 if flow.gas.in_flow != flow.gas.out_flow {
43 return Err(CMError::MassBalance(i.clone(), "gas".to_owned()));
44 }
45 if flow.liquid.in_flow != flow.liquid.out_flow {
46 return Err(CMError::MassBalance(i.clone(), "liquid".to_owned()));
47 }
48 }
49 self.validated = true;
50 Ok(())
51 }
52
53 pub(crate) fn update_flow(
54 &mut self,
55 id: &str,
56 phase: PhaseCM,
57 direction: FlowDirection,
58 vflow: f64,
59 ) {
60 self.validated = false;
61 if let Some(phase_flow) = self.flows.get_mut(id) {
62 let flow_data = match phase {
63 PhaseCM::Gas => &mut phase_flow.gas,
64 PhaseCM::Liquid => &mut phase_flow.liquid,
65 };
66
67 match direction {
68 FlowDirection::In => flow_data.in_flow += vflow,
69 FlowDirection::Out => flow_data.out_flow += vflow,
70 }
71 }
72 }
73 pub fn get_flow(&self, id: &str, phase: PhaseCM) -> Result<f64, CMError> {
74 if !self.validated {
75 return Err(CMError::Custom(
76 "Mass balance needs to be validated before being accessed".to_owned(),
77 ));
78 }
79
80 if let Some(phase_flow) = self.flows.get(id) {
81 return Ok(match phase {
82 PhaseCM::Gas => phase_flow.gas.in_flow,
83 PhaseCM::Liquid => phase_flow.liquid.in_flow,
84 });
85 }
86 Err(CMError::Custom(format!(
87 "Mass balance does not provide {} pfr",
88 id
89 )))
90 }
91}
92
93#[cfg(test)]
94mod test {
95 use super::*;
96
97 #[test]
98 fn test_pfr_mass_balance() {
99 let names = ["name1".to_owned(), "name2".to_owned()];
100 let mut mb = PfrGlobalMassBalance::new(&names);
101
102 let expected_ok = mb.validate(); assert!(expected_ok.is_ok());
104
105 mb.update_flow("name1", PhaseCM::Gas, FlowDirection::In, 4.);
106 let expected_err = mb.validate();
107 assert!(expected_err.is_err());
108
109 mb.update_flow("name1", PhaseCM::Gas, FlowDirection::Out, 2.);
110 mb.update_flow("name1", PhaseCM::Gas, FlowDirection::Out, 2.);
111
112 let expected_ok = mb.validate();
113 assert!(expected_ok.is_ok());
114
115 let pfr_flow = mb.get_flow("name1", PhaseCM::Gas).unwrap();
116 assert!(pfr_flow == 4.)
117 }
118}