Skip to content

Commit 18a96d9

Browse files
committed
Split impl
Signed-off-by: Dmitry Sirotkin <[email protected]>
1 parent 55832ca commit 18a96d9

File tree

10 files changed

+177
-149
lines changed

10 files changed

+177
-149
lines changed

include/gas_exchange.hpp

Lines changed: 11 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,21 @@
11
#pragma once
22

33
#include <cmath>
4-
#include <numbers>
54

6-
/*
7-
The Bühlmann model uses a simplified version of the alveolar gas equation to
8-
calculate alveolar inert gas pressure.
9-
Where
10-
- water vapour pressure at 37°C (conventionally defined as 0.0627 bar),
11-
- CO2 pressure (conventionally defined as 0.0534 bar),
12-
- Q the inspired inert gas fraction, and
13-
- RQ the respiratory coefficient: the ratio of carbon dioxide production to
14-
oxygen consumption.
15-
The Buhlmann model sets RQ to 1.
16-
*/
175
namespace gas_exchange {
18-
inline double_t alveolar_gas_equation(const double_t P_amb,
19-
const double_t P_H2O_vapour,
20-
const double_t respiratory_quotient,
21-
const double_t inspired_gas_frac,
22-
const double_t P_CO2) {
6+
double_t alveolar_gas_equation(const double_t P_amb,
7+
const double_t P_H2O_vapour,
8+
const double_t respiratory_quotient,
9+
const double_t inspired_gas_frac,
10+
const double_t P_CO2);
2311

24-
// Alveolar partial pressure after change
25-
const double_t P_alv =
26-
(P_amb - P_H2O_vapour +
27-
((1 - respiratory_quotient) / respiratory_quotient) * P_CO2) *
28-
inspired_gas_frac;
12+
double_t haldane_equation(const double_t P_alv, const double_t P_tissue0,
13+
const double_t half_time, const double_t time_step);
2914

30-
return P_alv;
31-
}
15+
double_t schreiner_equation(const double_t P_alv0, const double_t P_tissue0,
16+
const double_t rate, const double_t time_step,
17+
const double_t half_time);
3218

33-
inline double_t haldane_equation(const double_t P_alv, const double_t P_tissue0,
34-
const double_t half_time,
35-
const double_t time_step) {
36-
37-
const double_t gas_elimination_k = std::numbers::ln2 / half_time;
38-
39-
const double_t tissue_gradient = P_tissue0 - P_alv;
40-
41-
const double_t gradient_decay_factor = exp(-gas_elimination_k * time_step);
42-
43-
// Tissue partial pressure after change
44-
const double_t P_tissue = P_alv + tissue_gradient * gradient_decay_factor;
45-
46-
return P_tissue;
47-
}
48-
49-
inline double_t schreiner_equation(const double_t P_alv0,
50-
const double_t P_tissue0,
51-
const double_t rate,
52-
const double_t time_step,
53-
const double_t half_time) {
54-
55-
const double_t gas_elimination_k = std::numbers::ln2 / half_time;
56-
57-
// Adjusted alveolar partial pressure during ascent/descent
58-
const double_t alv_adj = P_alv0 + rate * (time_step - 1 / gas_elimination_k);
59-
// Initial pressure difference adjusted for gas kinetics
60-
const double_t tissue_gradient =
61-
P_alv0 - P_tissue0 - rate / gas_elimination_k;
62-
63-
// Exponential decay of initial tissue-alveolar gradient
64-
const double_t gradient_decay_factor =
65-
std::exp(-gas_elimination_k * time_step);
66-
67-
// Tissue partial pressure after change
68-
const double_t P_tissue = alv_adj - tissue_gradient * gradient_decay_factor;
69-
70-
return P_tissue;
71-
}
72-
73-
inline double_t gas_ceiling(const double_t p, const double_t a,
74-
const double_t b) {
75-
return (p - a) / b;
76-
}
19+
double_t gas_ceiling(const double_t p, const double_t a, const double_t b);
7720

7821
} // namespace gas_exchange

include/gas_mixture.hpp

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,15 @@
11
#pragma once
22

3-
#include "constants.hpp"
4-
#include "pressure.hpp"
5-
#include <algorithm>
3+
#include <constants.hpp>
4+
#include <pressure.hpp>
65

76
struct gas_mixture {
87
pressure _ambient;
98
volume_t _O2;
109
volume_t _N2;
1110
volume_t _He;
1211

13-
/*
14-
Mixture calibration:
15-
- Compensate N2 and O2 with He based on safety constraints
16-
*/
17-
explicit gas_mixture(const pressure &ambient)
18-
: _ambient{ambient},
19-
_O2{std::clamp((PPO2_MIN_LIMIT_PRESSURE.to_ata() * ambient.to_ata()),
20-
PPO2_MIN_LIMIT_PRESSURE.to_ata(),
21-
PPO2_MAX_LIMIT_PRESSURE.to_ata()) /
22-
ambient.to_ata()},
23-
_N2{std::clamp(MAX_VOLUME_RATIO - _O2, PPN2_MIN_LIMIT_PRESSURE.to_ata(),
24-
PPN2_MAX_LIMIT_PRESSURE.to_ata() / ambient.to_ata())},
25-
_He{std::max(MAX_VOLUME_RATIO - _O2 - _N2,
26-
PPHE_MIN_LIMIT_PRESSURE.to_ata())} {}
12+
gas_mixture(const pressure &ambient);
2713
};
2814

2915
template <>

include/pressure.hpp

Lines changed: 15 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22

3-
#include "constants.hpp"
3+
#include <constants.hpp>
44
#include <format>
55
#include <iostream>
66

@@ -9,30 +9,19 @@ enum class pressure_unit { PA, ATA };
99
struct pressure {
1010
pressure_t _value;
1111
pressure_unit _unit;
12-
pressure(const pressure_t value, const pressure_unit unit)
13-
: _value{value}, _unit{unit} {}
12+
pressure(const pressure_t value, const pressure_unit unit);
1413

15-
pressure_t to_pascal() const {
16-
return _unit == pressure_unit::ATA ? _value * STANDARD_ATMOSPHERIC_PA
17-
: _value;
18-
}
14+
pressure_t to_pascal() const;
1915

20-
pressure_t to_ata() const {
21-
return _unit == pressure_unit::PA ? _value / STANDARD_ATMOSPHERIC_PA
22-
: _value;
23-
}
16+
pressure_t to_ata() const;
2417

25-
pressure_t to_depth() const {
26-
return _unit == pressure_unit::ATA
27-
? (_value - 1) * 10
28-
: (_value / STANDARD_ATMOSPHERIC_PA - 1) * 10;
29-
}
18+
pressure_t to_depth() const;
3019

31-
pressure_t operator()(const pressure_unit unit) const {
32-
return unit == pressure_unit::ATA ? to_ata() : to_pascal();
33-
}
20+
pressure_t operator()(const pressure_unit unit) const;
21+
22+
pressure_t operator()() const;
3423

35-
pressure_t operator()() const { return _value; }
24+
pressure partial_pressure(const volume_t gasVol) const;
3625

3726
friend pressure operator+(const pressure &lhs, const pressure &rhs) {
3827
return {lhs.to_pascal() + rhs.to_pascal(), pressure_unit::PA};
@@ -50,27 +39,12 @@ struct pressure {
5039
return os << p._value << (p._unit == pressure_unit::PA ? " Pa" : " ATA");
5140
}
5241

53-
// friend auto operator<=>(const pressure &lhs, const pressure &rhs) {
54-
// if (lhs.to_pascal() < rhs.to_pascal())
55-
// return std::strong_ordering::less;
56-
// if (lhs.to_pascal() > rhs.to_pascal())
57-
// return std::strong_ordering::greater;
58-
// return std::strong_ordering::equal;
59-
// }
60-
61-
/*
62-
Based on the Dalton's Law we can backsolve partial pressure for a given
63-
gas composition from the gas mixture:
64-
65-
P_total = Pi_1 + Pi_2 + ... + Pi_n;
66-
67-
Where:
68-
- P_total is the total pressure of the gas mixture
69-
- Pi is the partial pressure of the i-th gas in the mixture
70-
*/
71-
72-
pressure partial_pressure(const volume_t gasVol) const {
73-
return pressure{gasVol * _value, _unit};
42+
friend auto operator<=>(const pressure &lhs, const pressure &rhs) {
43+
if (lhs.to_pascal() < rhs.to_pascal())
44+
return std::strong_ordering::less;
45+
if (lhs.to_pascal() > rhs.to_pascal())
46+
return std::strong_ordering::greater;
47+
return std::strong_ordering::equal;
7448
}
7549
};
7650

src/CMakeLists.txt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
add_library(sat STATIC
2-
${CMAKE_CURRENT_SOURCE_DIR}/constants.cpp
2+
# ${CMAKE_CURRENT_SOURCE_DIR}/constants.cpp
33
${CMAKE_CURRENT_SOURCE_DIR}/gas_exchange.cpp
44
${CMAKE_CURRENT_SOURCE_DIR}/pressure.cpp
55
${CMAKE_CURRENT_SOURCE_DIR}/gas_mixture.cpp
@@ -51,17 +51,17 @@ include(ExternalProject)
5151
# FetchContent_MakeAvailable(yaml-cpp)
5252

5353

54-
set(MI_USE_CXX ON CACHE INTERNAL "Enable CXX")
55-
set(MI_BUILD_SHARED OFF CACHE INTERNAL "Disable shared mimalloc")
56-
set(MI_BUILD_TESTS OFF CACHE INTERNAL "Disable mimalloc tests")
57-
set(MI_USE_LIBATOMIC OFF CACHE INTERNAL "Disable libatomic")
54+
# set(MI_USE_CXX ON CACHE INTERNAL "Enable CXX")
55+
# set(MI_BUILD_SHARED OFF CACHE INTERNAL "Disable shared mimalloc")
56+
# set(MI_BUILD_TESTS OFF CACHE INTERNAL "Disable mimalloc tests")
57+
# set(MI_USE_LIBATOMIC OFF CACHE INTERNAL "Disable libatomic")
5858

59-
FetchContent_Declare(
60-
mimalloc
61-
GIT_REPOSITORY https://github.com/microsoft/mimalloc
62-
GIT_TAG v2.1.9
63-
)
64-
FetchContent_MakeAvailable(mimalloc)
59+
# FetchContent_Declare(
60+
# mimalloc
61+
# GIT_REPOSITORY https://github.com/microsoft/mimalloc
62+
# GIT_TAG v2.1.9
63+
# )
64+
# FetchContent_MakeAvailable(mimalloc)
6565

6666
IF(NOT DEFINED ENV{CROSS_CXX})
6767
set(ENV{CROSS_CXX} $ENV{CXX})

src/buehlmann.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
#include "gas_exchange.hpp"
2-
#include "gas_mixture.hpp"
3-
#include "pressure.hpp"
4-
#include "zhl_16c.hpp"
51
#include <algorithm>
62
#include <array>
73
#include <cmath>
84
#include <cstddef>
95
#include <cstdint>
106
#include <format>
7+
#include <gas_exchange.hpp>
8+
#include <gas_mixture.hpp>
119
#include <iostream>
10+
#include <pressure.hpp>
11+
#include <zhl_16c.hpp>
1212

1313
struct BuehlmannEngine {
1414
std::array<zhl_16c::tissue_compartment, 16> compartments;

src/constants.cpp

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/gas_exchange.cpp

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,75 @@
1-
#include "gas_exchange.hpp"
1+
#include <gas_exchange.hpp>
2+
3+
#include <numbers>
4+
5+
/*
6+
The Bühlmann model uses a simplified version of the alveolar gas equation to
7+
calculate alveolar inert gas pressure.
8+
Where
9+
- water vapour pressure at 37°C (conventionally defined as 0.0627 bar),
10+
- CO2 pressure (conventionally defined as 0.0534 bar),
11+
- Q the inspired inert gas fraction, and
12+
- RQ the respiratory coefficient: the ratio of carbon dioxide production to
13+
oxygen consumption.
14+
The Buhlmann model sets RQ to 1.
15+
*/
16+
17+
double_t gas_exchange::alveolar_gas_equation(
18+
const double_t P_amb, const double_t P_H2O_vapour,
19+
const double_t respiratory_quotient, const double_t inspired_gas_frac,
20+
const double_t P_CO2) {
21+
22+
// Alveolar partial pressure after change
23+
const double_t P_alv =
24+
(P_amb - P_H2O_vapour +
25+
((1 - respiratory_quotient) / respiratory_quotient) * P_CO2) *
26+
inspired_gas_frac;
27+
28+
return P_alv;
29+
}
30+
31+
double_t gas_exchange::haldane_equation(const double_t P_alv,
32+
const double_t P_tissue0,
33+
const double_t half_time,
34+
const double_t time_step) {
35+
36+
const double_t gas_elimination_k = std::numbers::ln2 / half_time;
37+
38+
const double_t tissue_gradient = P_tissue0 - P_alv;
39+
40+
const double_t gradient_decay_factor = exp(-gas_elimination_k * time_step);
41+
42+
// Tissue partial pressure after change
43+
const double_t P_tissue = P_alv + tissue_gradient * gradient_decay_factor;
44+
45+
return P_tissue;
46+
}
47+
48+
double_t gas_exchange::schreiner_equation(const double_t P_alv0,
49+
const double_t P_tissue0,
50+
const double_t rate,
51+
const double_t time_step,
52+
const double_t half_time) {
53+
54+
const double_t gas_elimination_k = std::numbers::ln2 / half_time;
55+
56+
// Adjusted alveolar partial pressure during ascent/descent
57+
const double_t alv_adj = P_alv0 + rate * (time_step - 1 / gas_elimination_k);
58+
// Initial pressure difference adjusted for gas kinetics
59+
const double_t tissue_gradient =
60+
P_alv0 - P_tissue0 - rate / gas_elimination_k;
61+
62+
// Exponential decay of initial tissue-alveolar gradient
63+
const double_t gradient_decay_factor =
64+
std::exp(-gas_elimination_k * time_step);
65+
66+
// Tissue partial pressure after change
67+
const double_t P_tissue = alv_adj - tissue_gradient * gradient_decay_factor;
68+
69+
return P_tissue;
70+
}
71+
72+
double_t gas_exchange::gas_ceiling(const double_t p, const double_t a,
73+
const double_t b) {
74+
return (p - a) / b;
75+
}

src/gas_mixture.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1-
#include "gas_mixture.hpp"
2-
#include <format>
3-
#include <string_view>
1+
#include <algorithm>
2+
#include <gas_mixture.hpp>
3+
4+
/*
5+
Mixture calibration:
6+
- Compensate N2 and O2 with He based on safety constraints
7+
*/
8+
gas_mixture::gas_mixture(const pressure &ambient)
9+
: _ambient{ambient},
10+
_O2{std::clamp((PPO2_MIN_LIMIT_PRESSURE.to_ata() * ambient.to_ata()),
11+
PPO2_MIN_LIMIT_PRESSURE.to_ata(),
12+
PPO2_MAX_LIMIT_PRESSURE.to_ata()) /
13+
ambient.to_ata()},
14+
_N2{std::clamp(MAX_VOLUME_RATIO - _O2, PPN2_MIN_LIMIT_PRESSURE.to_ata(),
15+
PPN2_MAX_LIMIT_PRESSURE.to_ata() / ambient.to_ata())},
16+
_He{std::max(MAX_VOLUME_RATIO - _O2 - _N2,
17+
PPHE_MIN_LIMIT_PRESSURE.to_ata())} {}

0 commit comments

Comments
 (0)