SEFluidCompartment.hxx
1 /* Distributed under the Apache License, Version 2.0.
2  See accompanying NOTICE file for details.*/
3 
4 #include "cdm/properties/SEScalarVolumePerTime.h"
5 #include "cdm/properties/SEScalarPressure.h"
6 #include "cdm/properties/SEScalarVolume.h"
7 #include "cdm/properties/SERunningAverage.h"
8 
9 template<FLUID_COMPARTMENT_TEMPLATE>
10 SEFluidCompartment<FLUID_COMPARTMENT_TYPES>::SEFluidCompartment(const std::string& name, Logger* logger) : SECompartment(name, logger), m_Nodes(logger)
11 {
12  m_SampleFlow = false;
13  m_InFlow = nullptr;
14  m_OutFlow = nullptr;
15  m_AverageInFlow = nullptr;
16  m_AverageOutFlow = nullptr;
17  m_AverageInFlow_mL_Per_s = nullptr;
18  m_AverageOutFlow_mL_Per_s = nullptr;
19  m_Pressure = nullptr;
20  m_Volume = nullptr;
21 }
22 template<FLUID_COMPARTMENT_TEMPLATE>
24 {
25  Clear();
26 }
27 
28 template<FLUID_COMPARTMENT_TEMPLATE>
30 {
32  m_SampleFlow = false;
33  SAFE_DELETE(m_InFlow);
34  SAFE_DELETE(m_OutFlow);
35  SAFE_DELETE(m_AverageInFlow);
36  SAFE_DELETE(m_AverageOutFlow);
37  SAFE_DELETE(m_AverageInFlow_mL_Per_s);
38  SAFE_DELETE(m_AverageOutFlow_mL_Per_s);
39  SAFE_DELETE(m_Pressure);
40  SAFE_DELETE(m_Volume);
41  m_Links.clear();
42  m_FluidChildren.clear();
43  DELETE_VECTOR(m_SubstanceQuantities);
44  m_Nodes.Clear();
45 }
46 
47 template<FLUID_COMPARTMENT_TEMPLATE>
49 {
50  if (name.compare("InFlow") == 0)
51  return &GetInFlow();
52  if (name.compare("OutFlow") == 0)
53  return &GetOutFlow();
54  if (name.compare("AverageInFlow") == 0)
55  return &GetAverageInFlow();
56  if (name.compare("AverageOutFlow") == 0)
57  return &GetAverageOutFlow();
58  if (name.compare("Pressure") == 0)
59  return &GetPressure();
60  if (name.compare("Volume") == 0)
61  return &GetVolume();
62  return nullptr;
63 }
64 
65 template<FLUID_COMPARTMENT_TEMPLATE>
67 {
68  if (HasChildren())
69  Fatal("You cannot map nodes to compartments with children.");
70  else
71  m_Nodes.MapNode(node);
72 }
73 
74 template<FLUID_COMPARTMENT_TEMPLATE>
76 {
77  if (m_SampleFlow)
78  {
79  m_AverageInFlow_mL_Per_s->Sample(GetInFlow(VolumePerTimeUnit::mL_Per_s));
80  m_AverageOutFlow_mL_Per_s->Sample(GetOutFlow(VolumePerTimeUnit::mL_Per_s));
81  if (StartCycle)
82  {
83  m_AverageInFlow->SetValue(m_AverageInFlow_mL_Per_s->Value(), VolumePerTimeUnit::mL_Per_s);
84  m_AverageOutFlow->SetValue(m_AverageOutFlow_mL_Per_s->Value(), VolumePerTimeUnit::mL_Per_s);
85  m_AverageInFlow_mL_Per_s->Invalidate();
86  m_AverageOutFlow_mL_Per_s->Invalidate();
87  }
88  }
89 }
90 
91 template<FLUID_COMPARTMENT_TEMPLATE>
93 {
94  m_SampleFlow = true;
95  GetAverageInFlow();
96  GetAverageOutFlow();
97 }
98 
99 template<FLUID_COMPARTMENT_TEMPLATE>
101 {
102  if (m_Links.empty())
103  return false;
104  for (auto* link : m_Links)
105  if (link->HasFlow())
106  return true;
107  return false;
108 }
109 template<FLUID_COMPARTMENT_TEMPLATE>
111 {
112  if (m_InFlow == nullptr)
113  m_InFlow = new SEScalarVolumePerTime();
114  m_InFlow->SetReadOnly(false);
115  if (m_Links.empty())
116  m_InFlow->Invalidate();
117  else
118  m_InFlow->SetValue(CalculateInFlow_mL_Per_s(), VolumePerTimeUnit::mL_Per_s);
119  m_InFlow->SetReadOnly(true);
120  return *m_InFlow;
121 }
122 template<FLUID_COMPARTMENT_TEMPLATE>
124 {
125  if (m_Links.empty())
126  return SEScalar::dNaN();
127  return Convert(CalculateInFlow_mL_Per_s(), VolumePerTimeUnit::mL_Per_s, unit);
128 }
129 
130 template<FLUID_COMPARTMENT_TEMPLATE>
132 {
133  return m_AverageInFlow == nullptr ? false : m_AverageInFlow->IsValid();
134 }
135 template<FLUID_COMPARTMENT_TEMPLATE>
137 {
138  if (m_AverageInFlow == nullptr)
139  {
140  m_AverageInFlow = new SEScalarVolumePerTime();
141  m_AverageInFlow_mL_Per_s = new SERunningAverage();
142  }
143  return *m_AverageInFlow;
144 }
145 template<FLUID_COMPARTMENT_TEMPLATE>
147 {
148  if (m_AverageInFlow == nullptr)
149  return SEScalar::dNaN();
150  return m_AverageInFlow->GetValue(unit);
151 }
152 
153 template<FLUID_COMPARTMENT_TEMPLATE>
155 {
156  if (m_Links.empty())
157  return false;
158  for (auto* link : m_Links)
159  if (link->HasFlow())
160  return true;
161  return false;
162 }
163 template<FLUID_COMPARTMENT_TEMPLATE>
165 {
166  if (m_OutFlow == nullptr)
167  m_OutFlow = new SEScalarVolumePerTime();
168  m_OutFlow->SetReadOnly(false);
169  if (m_Links.empty())
170  m_OutFlow->Invalidate();
171  else
172  m_OutFlow->SetValue(CalculateOutFlow_mL_Per_s(), VolumePerTimeUnit::mL_Per_s);
173  m_OutFlow->SetReadOnly(true);
174  return *m_OutFlow;
175 }
176 template<FLUID_COMPARTMENT_TEMPLATE>
178 {
179  if (m_Links.empty())
180  return SEScalar::dNaN();
181  return Convert(CalculateOutFlow_mL_Per_s(), VolumePerTimeUnit::mL_Per_s, unit);
182 }
183 
184 template<FLUID_COMPARTMENT_TEMPLATE>
186 {
187  return m_AverageOutFlow == nullptr ? false : m_AverageOutFlow->IsValid();
188 }
189 template<FLUID_COMPARTMENT_TEMPLATE>
191 {
192  if (m_AverageOutFlow == nullptr)
193  {
194  m_AverageOutFlow = new SEScalarVolumePerTime();
195  m_AverageOutFlow_mL_Per_s = new SERunningAverage();
196  }
197  return *m_AverageOutFlow;
198 }
199 template<FLUID_COMPARTMENT_TEMPLATE>
201 {
202  if (m_AverageOutFlow == nullptr)
203  return SEScalar::dNaN();
204  return m_AverageOutFlow->GetValue(unit);
205 }
206 
207 template<FLUID_COMPARTMENT_TEMPLATE>
209 {
210  double flow_mL_Per_s = 0;
211 
213  for (auto* link : m_IncomingLinks)
214  {
215  // Positive flow on an incoming path, is flow into the compartment
216  f = &link->GetFlow();
217  if (f->IsPositive() || f->IsZero())
218  flow_mL_Per_s += f->GetValue(VolumePerTimeUnit::mL_Per_s);
219  }
220  for (auto* link : m_OutgoingLinks)
221  {// Negative flow on an outgoing path, is flow into the compartment
222  f = &link->GetFlow();
223  if (f->IsNegative() || f->IsZero())
224  flow_mL_Per_s += -f->GetValue(VolumePerTimeUnit::mL_Per_s);
225 
226  }
227  if (flow_mL_Per_s < 0)
228  flow_mL_Per_s = 0;// This number is something like x.e-12, which we treat as 0
229  return flow_mL_Per_s;
230 }
231 
232 template<FLUID_COMPARTMENT_TEMPLATE>
234 {
235  double flow_mL_Per_s = 0;
236 
238  for (auto* link : m_IncomingLinks)
239  {
240  // Negative flow on an incoming path, is flow out of the compartment
241  f = &link->GetFlow();
242  if (f->IsNegative() || f->IsZero())
243  flow_mL_Per_s += -f->GetValue(VolumePerTimeUnit::mL_Per_s);
244  }
245  for (auto* link : m_OutgoingLinks)
246  {// Positive flow on an outgoing path, is flow out of the compartment
247  f = &link->GetFlow();
248  if (f->IsPositive() || f->IsZero())
249  flow_mL_Per_s += f->GetValue(VolumePerTimeUnit::mL_Per_s);
250  }
251  if (flow_mL_Per_s < 0)
252  flow_mL_Per_s = 0;// This number is something like x.e-12, which we treat as 0
253  return flow_mL_Per_s;
254 }
255 
256 template<FLUID_COMPARTMENT_TEMPLATE>
258 {
259  if (m_Nodes.HasMapping())
260  return m_Nodes.HasPotential();
261  if (!m_FluidChildren.empty())
262  {
263  for (auto* child : m_FluidChildren)
264  if (child->HasPressure())
265  return true;
266  return false;
267  }
268  return m_Pressure == nullptr ? false : m_Pressure->IsValid();
269 }
270 template<FLUID_COMPARTMENT_TEMPLATE>
272 {
273  if (m_Nodes.HasMapping())
274  return m_Nodes.GetPotential();
275  if (m_Pressure == nullptr)
276  m_Pressure = new SEScalarPressure();
277  if (!m_FluidChildren.empty())
278  {
279  m_Pressure->SetReadOnly(false);
280  m_Pressure->Invalidate();
281  const PressureUnit* pUnit = nullptr;
282  for (SEFluidCompartment* child : m_FluidChildren)
283  {
284  if (child->HasPressure())
285  {
286  pUnit = child->GetPressure().GetUnit();
287  break;
288  }
289  }
290  if(pUnit!=nullptr)
291  m_Pressure->SetValue(GetPressure(*pUnit),*pUnit);
292  m_Pressure->SetReadOnly(true);
293  }
294  return *m_Pressure;
295 }
296 template<FLUID_COMPARTMENT_TEMPLATE>
298 {
299  if (!HasPressure())
300  return SEScalar::dNaN();
301  if (m_Nodes.HasMapping())
302  return m_Nodes.GetPotential(unit);
303  if (!m_FluidChildren.empty())
304  {
305  double Pressure = 0;
306  if (HasVolume())
307  {
308  double totalVolume_mL = GetVolume(VolumeUnit::mL);
309  for (SEFluidCompartment* child : m_FluidChildren)
310  {
311  if (child->HasPressure() && child->HasVolume())
312  {
313  Pressure += child->GetPressure(unit) * (child->GetVolume(VolumeUnit::mL) / totalVolume_mL);
314  }
315  }
316  return Pressure;
317  }
318  else
319  {
320  int numHas = 0;
321  for (SEFluidCompartment* child : m_FluidChildren)
322  {
323  if (child->HasPressure())
324  {
325  numHas++;
326  Pressure += child->GetPressure(unit);
327  }
328  Pressure /= numHas;
329  }
330  return Pressure;
331  }
332  }
333  if (m_Pressure == nullptr)
334  return SEScalar::dNaN();
335  return m_Pressure->GetValue(unit);
336 }
337 
338 template<FLUID_COMPARTMENT_TEMPLATE>
340 {
341  if (m_Nodes.HasMapping())
342  return m_Nodes.HasQuantity();
343  if (!m_FluidChildren.empty())
344  {
345  for (auto* child : m_FluidChildren)
346  if (child->HasVolume())
347  return true;
348  return false;
349  }
350  return m_Volume == nullptr ? false : m_Volume->IsValid();
351 }
352 template<FLUID_COMPARTMENT_TEMPLATE>
354 {
355  if (m_Nodes.HasMapping())
356  return m_Nodes.GetQuantity();
357  if (m_Volume == nullptr)
358  m_Volume = new SEScalarVolume();
359  if (!m_FluidChildren.empty())
360  {
361  m_Volume->SetReadOnly(false);
362  m_Volume->Invalidate();
363  for (SEFluidCompartment* child : m_FluidChildren)
364  if (child->HasVolume())
365  m_Volume->Increment(child->GetVolume());
366  m_Volume->SetReadOnly(true);
367  }
368  return *m_Volume;
369 }
370 template<FLUID_COMPARTMENT_TEMPLATE>
372 {
373  if (m_Nodes.HasMapping())
374  return m_Nodes.GetQuantity(unit);
375  if (!m_FluidChildren.empty())
376  {
377  double volume = 0;
378  for (SEFluidCompartment* child : m_FluidChildren)
379  if (child->HasVolume())
380  volume += child->GetVolume(unit);
381  return volume;
382  }
383  if (m_Volume == nullptr)
384  return SEScalar::dNaN();
385  return m_Volume->GetValue(unit);
386 }
387 
388 template<FLUID_COMPARTMENT_TEMPLATE>
390 {
391  return !m_SubstanceQuantities.empty();
392 }
393 template<FLUID_COMPARTMENT_TEMPLATE>
395 {
396  for (SubstanceQuantityType* sq : m_SubstanceQuantities)
397  {
398  if (&sq->GetSubstance() == &substance)
399  return true;
400  }
401  return false;
402 }
403 
404 template<FLUID_COMPARTMENT_TEMPLATE>
405 SubstanceQuantityType* SEFluidCompartment<FLUID_COMPARTMENT_TYPES>::GetSubstanceQuantity(const SESubstance& substance) const
406 {
407  for (SubstanceQuantityType* sq : m_SubstanceQuantities)
408  {
409  if (&sq->GetSubstance() == &substance)
410  return sq;
411  }
412  return nullptr;
413 }
414 template<FLUID_COMPARTMENT_TEMPLATE>
415 const std::vector<SubstanceQuantityType*>& SEFluidCompartment<FLUID_COMPARTMENT_TYPES>::GetSubstanceQuantities() const
416 {
417  return m_SubstanceQuantities;
418 }
419 template<FLUID_COMPARTMENT_TEMPLATE>
421 {
422  for (size_t i = 0; i < m_SubstanceQuantities.size(); i++)
423  {
424  if (&m_SubstanceQuantities[i]->GetSubstance() == &substance)
425  {
426  SAFE_DELETE(m_SubstanceQuantities[i]);
427  SAFE_DELETE(m_TransportSubstances[i]);// Assumes these are in sync
428  m_SubstanceQuantities.erase(m_SubstanceQuantities.begin()+i);
429  m_TransportSubstances.erase(m_TransportSubstances.begin()+i);
430 
431  }
432  }
433 }
434 template<FLUID_COMPARTMENT_TEMPLATE>
436 {
437  for (SubstanceQuantityType* sq : m_SubstanceQuantities)
438  {
439  sq->SetToZero();
440  }
441 }
442 
443 template<FLUID_COMPARTMENT_TEMPLATE>
445 {
446  if (!Contains(m_Links, link))
447  {
448  m_Links.push_back(&link);
449  if (HasChildren())
450  {
451  SEFluidCompartment& src = link.GetSourceCompartment();
452  SEFluidCompartment& tgt = link.GetTargetCompartment();
453 
454  if(this!= &src && !HasChild(src))
455  m_IncomingLinks.push_back(&link);
456  else if (this!=&tgt && !HasChild(tgt))
457  m_OutgoingLinks.push_back(&link);
458  }
459  else
460  {
461  // Is it incoming or out going?
462  if (this == &link.GetSourceCompartment())
463  m_OutgoingLinks.push_back(&link);
464  else if (this == &link.GetTargetCompartment())
465  m_IncomingLinks.push_back(&link);
466  }
467  }
468 }
469 template<FLUID_COMPARTMENT_TEMPLATE>
471 {
472  Remove(m_Links, &link);
473  Remove(m_IncomingLinks, &link);
474  Remove(m_OutgoingLinks, &link);
475 }
476 template<FLUID_COMPARTMENT_TEMPLATE>
478 {
479  m_Links.clear();
480 }
481 template<FLUID_COMPARTMENT_TEMPLATE>
482 const std::vector<LinkType*>& SEFluidCompartment<FLUID_COMPARTMENT_TYPES>::GetLinks()
483 {
484  return m_Links;
485 }
486 
487 template<FLUID_COMPARTMENT_TEMPLATE>
489 {
490  for (SEFluidCompartment* child : m_FluidChildren)
491  {
492  if (&cmpt == child)
493  return true;
494  if (child->HasChild(cmpt))
495  return true;
496  }
497  return false;
498 }
Definition: Logger.h:71
Definition: SEScalarPressure.h:8
Definition: SECompartment.h:14
virtual void Clear()
Definition: SECompartment.cpp:18
Definition: SEFluidCircuitNode.h:10
Definition: SEFluidCompartment.h:19
virtual double CalculateOutFlow_mL_Per_s() const
Definition: SEFluidCompartment.cpp:236
virtual bool HasVolume() const
Definition: SEFluidCompartment.cpp:342
virtual void ZeroSubstanceQuantities()
Definition: SEFluidCompartment.cpp:438
virtual void RemoveSubstanceQuantity(const SESubstance &substance)
Definition: SEFluidCompartment.cpp:423
virtual ~SEFluidCompartment()
Definition: SEFluidCompartment.cpp:26
virtual SEScalarPressure & GetPressure()
Definition: SEFluidCompartment.cpp:274
virtual void RemoveLink(LinkType &link)
Definition: SEFluidCompartment.cpp:473
virtual bool HasAverageOutFlow() const
Definition: SEFluidCompartment.cpp:188
virtual bool HasInFlow() const
Definition: SEFluidCompartment.cpp:103
virtual void AddLink(LinkType &link)
Definition: SEFluidCompartment.cpp:447
virtual const std::vector< SubstanceQuantityType * > & GetSubstanceQuantities() const
Definition: SEFluidCompartment.cpp:418
virtual bool HasSubstanceQuantity(const SESubstance &substance) const
Definition: SEFluidCompartment.cpp:397
virtual bool HasAverageInFlow() const
Definition: SEFluidCompartment.cpp:134
virtual void RemoveLinks()
Definition: SEFluidCompartment.cpp:480
virtual bool HasSubstanceQuantities() const
Definition: SEFluidCompartment.cpp:392
virtual const SEScalarVolumePerTime & GetAverageInFlow() const
Definition: SEFluidCompartment.cpp:139
virtual void MapNode(SEFluidCircuitNode &node)
Definition: SEFluidCompartment.cpp:69
virtual const SEScalarVolumePerTime & GetInFlow() const
Definition: SEFluidCompartment.cpp:113
virtual const SEScalarVolumePerTime & GetAverageOutFlow() const
Definition: SEFluidCompartment.cpp:193
virtual bool HasPressure() const
Definition: SEFluidCompartment.cpp:260
virtual bool HasChild(const SEFluidCompartment &cmpt)
Definition: SEFluidCompartment.cpp:491
virtual SEScalarVolume & GetVolume()
Definition: SEFluidCompartment.cpp:356
void Clear() override
Definition: SEFluidCompartment.cpp:32
SEFluidCompartment(const std::string &name, Logger *logger)
Definition: SEFluidCompartment.cpp:13
virtual const std::vector< LinkType * > & GetLinks()
Definition: SEFluidCompartment.cpp:485
virtual SubstanceQuantityType * GetSubstanceQuantity(const SESubstance &substance) const
Definition: SEFluidCompartment.cpp:408
virtual void SampleFlow()
Definition: SEFluidCompartment.cpp:95
virtual const SEScalarVolumePerTime & GetOutFlow() const
Definition: SEFluidCompartment.cpp:167
virtual void Sample(bool CycleStart)
Definition: SEFluidCompartment.cpp:78
const SEScalar * GetScalar(const std::string &name) override
Definition: SEFluidCompartment.cpp:51
virtual double CalculateInFlow_mL_Per_s() const
Definition: SEFluidCompartment.cpp:211
virtual bool HasOutFlow() const
Definition: SEFluidCompartment.cpp:157
Definition: SERunningAverage.h:8
Definition: SEScalar.h:19
static double dNaN()
Definition: SEScalar.cpp:10
bool IsPositive() const
Definition: SEScalar.cpp:115
bool IsZero(double limit=ZERO_APPROX) const
Definition: SEScalar.cpp:108
bool IsNegative() const
Definition: SEScalar.cpp:122
Definition: SEScalarPressure.h:29
double GetValue(const CCompoundUnit &unit) const override
Definition: SEScalar.hxx:125
Definition: SEScalarVolume.h:28
Definition: SEScalarVolumePerTime.h:32
Definition: SESubstance.h:15
Definition: SEScalarVolumePerTime.h:8
static const VolumePerTimeUnit mL_Per_s
Definition: SEScalarVolumePerTime.h:23
Definition: SEScalarVolume.h:8
static const VolumeUnit mL
Definition: SEScalarVolume.h:22

Distributed under the Apache License, Version 2.0.

See accompanying NOTICE file for details.