decodaitengu 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- decodaitengu/__init__.py +107 -0
- decodaitengu/const.py +45 -0
- decodaitengu/models/__init__.py +27 -0
- decodaitengu/models/base.py +239 -0
- decodaitengu/models/zhl16b.py +150 -0
- decodaitengu/models/zhl16c.py +155 -0
- decodaitengu/planning.py +307 -0
- decodaitengu/py.typed +0 -0
- decodaitengu/tests/__init__.py +21 -0
- decodaitengu/tests/test_modern.py +303 -0
- decodaitengu/tracking/__init__.py +25 -0
- decodaitengu/tracking/cns.py +146 -0
- decodaitengu/tracking/gas_usage.py +87 -0
- decodaitengu/tracking/otu.py +47 -0
- decodaitengu/types.py +200 -0
- decodaitengu-1.0.0.dist-info/METADATA +112 -0
- decodaitengu-1.0.0.dist-info/RECORD +19 -0
- decodaitengu-1.0.0.dist-info/WHEEL +4 -0
- decodaitengu-1.0.0.dist-info/licenses/COPYING +674 -0
decodaitengu/__init__.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# DecoDaiTengu - dive decompression library.
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2013-2014 by Artur Wroblewski <wrobell@pld-linux.org>
|
|
4
|
+
# Copyright (C) 2024 Contributors
|
|
5
|
+
#
|
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
|
|
11
|
+
"""DecoDaiTengu - dive decompression library.
|
|
12
|
+
|
|
13
|
+
A modern, typed Python library for Bühlmann ZH-L16B/C decompression
|
|
14
|
+
calculations with gradient factors, CNS/OTU tracking, and trimix support.
|
|
15
|
+
|
|
16
|
+
Quick start::
|
|
17
|
+
|
|
18
|
+
from decodaitengu import plan_dive, Gas
|
|
19
|
+
|
|
20
|
+
result = plan_dive(
|
|
21
|
+
depth=35,
|
|
22
|
+
bottom_time=40,
|
|
23
|
+
back_gas=Gas(21, 0), # air
|
|
24
|
+
gf=(30, 85),
|
|
25
|
+
)
|
|
26
|
+
print(f"Runtime: {result.runtime:.0f} min")
|
|
27
|
+
print(f"Deco: {result.total_deco:.0f} min")
|
|
28
|
+
for stop in result.stops:
|
|
29
|
+
print(f" {stop.depth:.0f}m for {stop.time:.0f} min")
|
|
30
|
+
|
|
31
|
+
Trimix example::
|
|
32
|
+
|
|
33
|
+
from decodaitengu import plan_dive, Gas, ZHL16C
|
|
34
|
+
|
|
35
|
+
result = plan_dive(
|
|
36
|
+
depth=50,
|
|
37
|
+
bottom_time=25,
|
|
38
|
+
back_gas=Gas(21, 35),
|
|
39
|
+
deco_gases=[Gas(50, 0, switch_depth=21), Gas(100, 0, switch_depth=6)],
|
|
40
|
+
model=ZHL16C,
|
|
41
|
+
gf=(30, 85),
|
|
42
|
+
)
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
from .models import ZHL16B, ZHL16C, DecoModel
|
|
46
|
+
from .planning import plan_dive
|
|
47
|
+
from .tracking import CNSMethod, CNSTracker, OTUTracker
|
|
48
|
+
from .types import (
|
|
49
|
+
Cylinder,
|
|
50
|
+
DecoStop,
|
|
51
|
+
DiveSummary,
|
|
52
|
+
Gas,
|
|
53
|
+
GasUsage,
|
|
54
|
+
Phase,
|
|
55
|
+
Step,
|
|
56
|
+
TissueState,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
__version__ = "1.0.0"
|
|
60
|
+
|
|
61
|
+
__all__ = [
|
|
62
|
+
"plan_dive",
|
|
63
|
+
"Gas",
|
|
64
|
+
"ZHL16B",
|
|
65
|
+
"ZHL16C",
|
|
66
|
+
"DecoModel",
|
|
67
|
+
"Cylinder",
|
|
68
|
+
"TissueState",
|
|
69
|
+
"DiveSummary",
|
|
70
|
+
"DecoStop",
|
|
71
|
+
"Step",
|
|
72
|
+
"Phase",
|
|
73
|
+
"GasUsage",
|
|
74
|
+
"CNSTracker",
|
|
75
|
+
"CNSMethod",
|
|
76
|
+
"OTUTracker",
|
|
77
|
+
# Legacy compat
|
|
78
|
+
"create",
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def create(*args: object, **kwargs: object) -> None:
|
|
83
|
+
"""Legacy API stub — the old Engine-based API has been removed.
|
|
84
|
+
|
|
85
|
+
Raises RuntimeError with migration instructions.
|
|
86
|
+
"""
|
|
87
|
+
raise RuntimeError(
|
|
88
|
+
"decodaitengu.create() is no longer available.\n"
|
|
89
|
+
"\n"
|
|
90
|
+
"The legacy Engine API from decotengu has been replaced with a simpler\n"
|
|
91
|
+
"functional API. To migrate:\n"
|
|
92
|
+
"\n"
|
|
93
|
+
" OLD (decotengu):\n"
|
|
94
|
+
" import decotengu\n"
|
|
95
|
+
" engine = decotengu.create()\n"
|
|
96
|
+
" engine.add_gas(0, 21)\n"
|
|
97
|
+
" profile = engine.calculate(35, 40)\n"
|
|
98
|
+
" list(profile)\n"
|
|
99
|
+
" print(engine.deco_table.total)\n"
|
|
100
|
+
"\n"
|
|
101
|
+
" NEW (decodaitengu):\n"
|
|
102
|
+
" from decodaitengu import plan_dive, Gas\n"
|
|
103
|
+
" result = plan_dive(depth=35, bottom_time=40, back_gas=Gas(21, 0))\n"
|
|
104
|
+
" print(result.total_deco)\n"
|
|
105
|
+
"\n"
|
|
106
|
+
"See README.md or https://github.com/notionparallax/decodaitengu for full docs."
|
|
107
|
+
)
|
decodaitengu/const.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#
|
|
2
|
+
# DecoTengu - dive decompression library.
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2013-2014 by Artur Wroblewski <wrobell@pld-linux.org>
|
|
5
|
+
#
|
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
WATER_VAPOUR_PRESSURE_Q08 = 0.0493
|
|
21
|
+
WATER_VAPOUR_PRESSURE_Q09 = 0.0567
|
|
22
|
+
# source: [mpdfd]
|
|
23
|
+
# used in: OSTC
|
|
24
|
+
WATER_VAPOUR_PRESSURE_Q10 = 0.0627
|
|
25
|
+
WATER_VAPOUR_PRESSURE_DEFAULT = WATER_VAPOUR_PRESSURE_Q10
|
|
26
|
+
|
|
27
|
+
SURFACE_PRESSURE = 1.01325
|
|
28
|
+
|
|
29
|
+
METER_TO_BAR = 0.09985
|
|
30
|
+
LOG_2 = 0.6931471805599453
|
|
31
|
+
SCALE = 10
|
|
32
|
+
EPSILON = 10**-SCALE
|
|
33
|
+
ROUND_VALUE = 0.499999
|
|
34
|
+
MINUTE = 1
|
|
35
|
+
TIME_3M = 0.3 # time [min] to ascent/descent at 10m/min
|
|
36
|
+
|
|
37
|
+
#
|
|
38
|
+
# number based on performance test for dive profile presented in
|
|
39
|
+
# Baker "Deep Stops" paper, see also
|
|
40
|
+
#
|
|
41
|
+
# decotengu.tests.integration.test_engine.ProfileTestCase.test_deepstop
|
|
42
|
+
#
|
|
43
|
+
DECO_STOP_SEARCH_TIME = 8
|
|
44
|
+
|
|
45
|
+
# vim: sw=4:et:ai
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#
|
|
2
|
+
# DecoTengu - dive decompression library.
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2013-2014 by Artur Wroblewski <wrobell@pld-linux.org>
|
|
5
|
+
# Copyright (C) 2024 Contributors
|
|
6
|
+
#
|
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
#
|
|
20
|
+
|
|
21
|
+
"""Decompression models package."""
|
|
22
|
+
|
|
23
|
+
from .base import DecoModel
|
|
24
|
+
from .zhl16b import ZHL16B
|
|
25
|
+
from .zhl16c import ZHL16C
|
|
26
|
+
|
|
27
|
+
__all__ = ["DecoModel", "ZHL16B", "ZHL16C"]
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
#
|
|
2
|
+
# DecoTengu - dive decompression library.
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2013-2014 by Artur Wroblewski <wrobell@pld-linux.org>
|
|
5
|
+
# Copyright (C) 2024 Contributors
|
|
6
|
+
#
|
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
#
|
|
20
|
+
|
|
21
|
+
"""Base decompression model interface and shared calculations.
|
|
22
|
+
|
|
23
|
+
Implements the ZH-L16-GF decompression model framework with gradient factors
|
|
24
|
+
by Erik Baker. Subclasses provide specific coefficient tables (ZHL-16B, ZHL-16C).
|
|
25
|
+
|
|
26
|
+
Equations
|
|
27
|
+
---------
|
|
28
|
+
Schreiner Equation (tissue gas loading):
|
|
29
|
+
P = P_alv + R * (t - 1/k) - (P_alv - P_i - R/k) * e^(-k*t)
|
|
30
|
+
|
|
31
|
+
Bühlmann Equation with gradient factors (ascent ceiling):
|
|
32
|
+
P_l = (P - A * gf) / (gf / B + 1.0 - gf)
|
|
33
|
+
|
|
34
|
+
For trimix (combined N2 + He):
|
|
35
|
+
A = (A_n2 * P_n2 + A_he * P_he) / (P_n2 + P_he)
|
|
36
|
+
B = (B_n2 * P_n2 + B_he * P_he) / (P_n2 + P_he)
|
|
37
|
+
P_ceiling = (P_n2 + P_he - A * gf) / (gf / B + 1 - gf)
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
import math
|
|
41
|
+
from dataclasses import dataclass
|
|
42
|
+
from typing import Protocol
|
|
43
|
+
|
|
44
|
+
from .. import const
|
|
45
|
+
from ..types import Gas, TissueState
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True, slots=True)
|
|
49
|
+
class ModelParams:
|
|
50
|
+
"""Coefficient table for a ZH-L16 variant.
|
|
51
|
+
|
|
52
|
+
:param n2_half_life: N2 half-life times for 16 compartments [min].
|
|
53
|
+
:param n2_a: N2 Bühlmann 'a' coefficients.
|
|
54
|
+
:param n2_b: N2 Bühlmann 'b' coefficients.
|
|
55
|
+
:param he_half_life: He half-life times for 16 compartments [min].
|
|
56
|
+
:param he_a: He Bühlmann 'a' coefficients.
|
|
57
|
+
:param he_b: He Bühlmann 'b' coefficients.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
n2_half_life: tuple[float, ...]
|
|
61
|
+
n2_a: tuple[float, ...]
|
|
62
|
+
n2_b: tuple[float, ...]
|
|
63
|
+
he_half_life: tuple[float, ...]
|
|
64
|
+
he_a: tuple[float, ...]
|
|
65
|
+
he_b: tuple[float, ...]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class DecoModel(Protocol):
|
|
69
|
+
"""Protocol defining the decompression model interface."""
|
|
70
|
+
|
|
71
|
+
params: ModelParams
|
|
72
|
+
gf_low: float
|
|
73
|
+
gf_high: float
|
|
74
|
+
|
|
75
|
+
def init(self, surface_pressure: float) -> TissueState: ...
|
|
76
|
+
def load(
|
|
77
|
+
self,
|
|
78
|
+
tissues: TissueState,
|
|
79
|
+
abs_p: float,
|
|
80
|
+
time: float,
|
|
81
|
+
gas: Gas,
|
|
82
|
+
rate: float,
|
|
83
|
+
) -> TissueState: ...
|
|
84
|
+
def ceiling(self, tissues: TissueState, gf: float) -> float: ...
|
|
85
|
+
def compartment_ceilings(self, tissues: TissueState, gf: float) -> tuple[float, ...]: ...
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def eq_schreiner(
|
|
89
|
+
p_i: float,
|
|
90
|
+
p_alv: float,
|
|
91
|
+
rate: float,
|
|
92
|
+
time: float,
|
|
93
|
+
k: float,
|
|
94
|
+
) -> float:
|
|
95
|
+
"""Calculate inert gas pressure in a tissue compartment using Schreiner equation.
|
|
96
|
+
|
|
97
|
+
:param p_i: Initial inert gas pressure in tissue compartment [bar].
|
|
98
|
+
:param p_alv: Alveolar pressure of inspired inert gas [bar].
|
|
99
|
+
:param rate: Rate of change of inert gas pressure [bar/min].
|
|
100
|
+
:param time: Time of exposure [min].
|
|
101
|
+
:param k: Gas decay constant (ln2 / half_life).
|
|
102
|
+
:returns: Final inert gas pressure in tissue compartment [bar].
|
|
103
|
+
"""
|
|
104
|
+
return p_alv + rate * (time - 1.0 / k) - (p_alv - p_i - rate / k) * math.exp(-k * time)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def eq_gf_limit(
|
|
108
|
+
gf: float,
|
|
109
|
+
p_n2: float,
|
|
110
|
+
p_he: float,
|
|
111
|
+
a_n2: float,
|
|
112
|
+
b_n2: float,
|
|
113
|
+
a_he: float,
|
|
114
|
+
b_he: float,
|
|
115
|
+
) -> float:
|
|
116
|
+
"""Calculate ascent ceiling of a tissue compartment.
|
|
117
|
+
|
|
118
|
+
Uses Bühlmann equation extended with gradient factors by Erik Baker,
|
|
119
|
+
with the weighted a/b approach for combined N2 + He loading.
|
|
120
|
+
|
|
121
|
+
:param gf: Gradient factor value (0 < gf <= 1.5).
|
|
122
|
+
:param p_n2: Current tissue nitrogen pressure [bar].
|
|
123
|
+
:param p_he: Current tissue helium pressure [bar].
|
|
124
|
+
:param a_n2: Bühlmann 'a' coefficient for nitrogen.
|
|
125
|
+
:param b_n2: Bühlmann 'b' coefficient for nitrogen.
|
|
126
|
+
:param a_he: Bühlmann 'a' coefficient for helium.
|
|
127
|
+
:param b_he: Bühlmann 'b' coefficient for helium.
|
|
128
|
+
:returns: Absolute pressure of ascent ceiling [bar].
|
|
129
|
+
"""
|
|
130
|
+
p = p_n2 + p_he
|
|
131
|
+
if p <= 0:
|
|
132
|
+
return 0.0
|
|
133
|
+
a = (a_n2 * p_n2 + a_he * p_he) / p
|
|
134
|
+
b = (b_n2 * p_n2 + b_he * p_he) / p
|
|
135
|
+
return (p - a * gf) / (gf / b + 1.0 - gf)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class ZHL16GF:
|
|
139
|
+
"""Base implementation of Bühlmann ZH-L16 with gradient factors.
|
|
140
|
+
|
|
141
|
+
Subclasses must set the `params` class variable with appropriate coefficients.
|
|
142
|
+
|
|
143
|
+
:param gf_low: Gradient factor low (controls first stop depth). Default 0.30.
|
|
144
|
+
:param gf_high: Gradient factor high (controls last stop duration). Default 0.85.
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
params: ModelParams # Must be set by subclass
|
|
148
|
+
|
|
149
|
+
def __init__(self, gf_low: float = 0.30, gf_high: float = 0.85) -> None:
|
|
150
|
+
self.gf_low = gf_low
|
|
151
|
+
self.gf_high = gf_high
|
|
152
|
+
self._n2_k = tuple(const.LOG_2 / hl for hl in self.params.n2_half_life)
|
|
153
|
+
self._he_k = tuple(const.LOG_2 / hl for hl in self.params.he_half_life)
|
|
154
|
+
|
|
155
|
+
def init(self, surface_pressure: float) -> TissueState:
|
|
156
|
+
"""Initialise tissue compartments for surface saturation.
|
|
157
|
+
|
|
158
|
+
:param surface_pressure: Ambient pressure at surface [bar].
|
|
159
|
+
:returns: Initial tissue state with all compartments at surface equilibrium.
|
|
160
|
+
"""
|
|
161
|
+
# Standard air composition: 79.02% N2
|
|
162
|
+
p_n2 = 0.7902 * (surface_pressure - const.WATER_VAPOUR_PRESSURE_DEFAULT)
|
|
163
|
+
p_he = 0.0
|
|
164
|
+
return TissueState(
|
|
165
|
+
n2_pressures=tuple([p_n2] * 16),
|
|
166
|
+
he_pressures=tuple([p_he] * 16),
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
def load(
|
|
170
|
+
self,
|
|
171
|
+
tissues: TissueState,
|
|
172
|
+
abs_p: float,
|
|
173
|
+
time: float,
|
|
174
|
+
gas: Gas,
|
|
175
|
+
rate: float,
|
|
176
|
+
) -> TissueState:
|
|
177
|
+
"""Calculate tissue gas loading for all compartments.
|
|
178
|
+
|
|
179
|
+
Applies the Schreiner equation to each compartment for both N2 and He.
|
|
180
|
+
|
|
181
|
+
:param tissues: Current tissue state.
|
|
182
|
+
:param abs_p: Absolute pressure at current depth [bar].
|
|
183
|
+
:param time: Time of exposure [min].
|
|
184
|
+
:param gas: Gas mix being breathed.
|
|
185
|
+
:param rate: Pressure rate change [bar/min] (+descent, -ascent, 0=const).
|
|
186
|
+
:returns: Updated tissue state after exposure.
|
|
187
|
+
"""
|
|
188
|
+
f_n2 = gas.n2 / 100.0
|
|
189
|
+
f_he = gas.he / 100.0
|
|
190
|
+
p_alv_n2 = f_n2 * (abs_p - const.WATER_VAPOUR_PRESSURE_DEFAULT)
|
|
191
|
+
p_alv_he = f_he * (abs_p - const.WATER_VAPOUR_PRESSURE_DEFAULT)
|
|
192
|
+
r_n2 = f_n2 * rate
|
|
193
|
+
r_he = f_he * rate
|
|
194
|
+
|
|
195
|
+
new_n2 = []
|
|
196
|
+
new_he = []
|
|
197
|
+
for i in range(16):
|
|
198
|
+
new_n2.append(
|
|
199
|
+
eq_schreiner(tissues.n2_pressures[i], p_alv_n2, r_n2, time, self._n2_k[i])
|
|
200
|
+
)
|
|
201
|
+
new_he.append(
|
|
202
|
+
eq_schreiner(tissues.he_pressures[i], p_alv_he, r_he, time, self._he_k[i])
|
|
203
|
+
)
|
|
204
|
+
return TissueState(
|
|
205
|
+
n2_pressures=tuple(new_n2),
|
|
206
|
+
he_pressures=tuple(new_he),
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
def ceiling(self, tissues: TissueState, gf: float) -> float:
|
|
210
|
+
"""Calculate the overall ascent ceiling pressure.
|
|
211
|
+
|
|
212
|
+
Returns the maximum (shallowest limit) across all compartments.
|
|
213
|
+
|
|
214
|
+
:param tissues: Current tissue state.
|
|
215
|
+
:param gf: Gradient factor to use.
|
|
216
|
+
:returns: Absolute pressure of ascent ceiling [bar].
|
|
217
|
+
"""
|
|
218
|
+
return max(self.compartment_ceilings(tissues, gf))
|
|
219
|
+
|
|
220
|
+
def compartment_ceilings(self, tissues: TissueState, gf: float) -> tuple[float, ...]:
|
|
221
|
+
"""Calculate ascent ceiling for each tissue compartment.
|
|
222
|
+
|
|
223
|
+
:param tissues: Current tissue state.
|
|
224
|
+
:param gf: Gradient factor to use.
|
|
225
|
+
:returns: Tuple of ceiling pressures for each compartment.
|
|
226
|
+
"""
|
|
227
|
+
params = self.params
|
|
228
|
+
return tuple(
|
|
229
|
+
eq_gf_limit(
|
|
230
|
+
gf,
|
|
231
|
+
tissues.n2_pressures[i],
|
|
232
|
+
tissues.he_pressures[i],
|
|
233
|
+
params.n2_a[i],
|
|
234
|
+
params.n2_b[i],
|
|
235
|
+
params.he_a[i],
|
|
236
|
+
params.he_b[i],
|
|
237
|
+
)
|
|
238
|
+
for i in range(16)
|
|
239
|
+
)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#
|
|
2
|
+
# DecoTengu - dive decompression library.
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2013-2014 by Artur Wroblewski <wrobell@pld-linux.org>
|
|
5
|
+
# Copyright (C) 2024 Contributors
|
|
6
|
+
#
|
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
#
|
|
20
|
+
|
|
21
|
+
"""ZH-L16B decompression model with gradient factors.
|
|
22
|
+
|
|
23
|
+
ZH-L16B-GF is the original Bühlmann model variant used for dive table
|
|
24
|
+
calculations. Coefficients sourced from Erik Baker's gfdeco.f implementation.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from .base import ZHL16GF, ModelParams
|
|
28
|
+
|
|
29
|
+
ZHL16B_PARAMS = ModelParams(
|
|
30
|
+
n2_half_life=(
|
|
31
|
+
5.0,
|
|
32
|
+
8.0,
|
|
33
|
+
12.5,
|
|
34
|
+
18.5,
|
|
35
|
+
27.0,
|
|
36
|
+
38.3,
|
|
37
|
+
54.3,
|
|
38
|
+
77.0,
|
|
39
|
+
109.0,
|
|
40
|
+
146.0,
|
|
41
|
+
187.0,
|
|
42
|
+
239.0,
|
|
43
|
+
305.0,
|
|
44
|
+
390.0,
|
|
45
|
+
498.0,
|
|
46
|
+
635.0,
|
|
47
|
+
),
|
|
48
|
+
n2_a=(
|
|
49
|
+
1.1696,
|
|
50
|
+
1.0000,
|
|
51
|
+
0.8618,
|
|
52
|
+
0.7562,
|
|
53
|
+
0.6667,
|
|
54
|
+
0.5600,
|
|
55
|
+
0.4947,
|
|
56
|
+
0.4500,
|
|
57
|
+
0.4187,
|
|
58
|
+
0.3798,
|
|
59
|
+
0.3497,
|
|
60
|
+
0.3223,
|
|
61
|
+
0.2850,
|
|
62
|
+
0.2737,
|
|
63
|
+
0.2523,
|
|
64
|
+
0.2327,
|
|
65
|
+
),
|
|
66
|
+
n2_b=(
|
|
67
|
+
0.5578,
|
|
68
|
+
0.6514,
|
|
69
|
+
0.7222,
|
|
70
|
+
0.7825,
|
|
71
|
+
0.8126,
|
|
72
|
+
0.8434,
|
|
73
|
+
0.8693,
|
|
74
|
+
0.8910,
|
|
75
|
+
0.9092,
|
|
76
|
+
0.9222,
|
|
77
|
+
0.9319,
|
|
78
|
+
0.9403,
|
|
79
|
+
0.9477,
|
|
80
|
+
0.9544,
|
|
81
|
+
0.9602,
|
|
82
|
+
0.9653,
|
|
83
|
+
),
|
|
84
|
+
he_half_life=(
|
|
85
|
+
1.88,
|
|
86
|
+
3.02,
|
|
87
|
+
4.72,
|
|
88
|
+
6.99,
|
|
89
|
+
10.21,
|
|
90
|
+
14.48,
|
|
91
|
+
20.53,
|
|
92
|
+
29.11,
|
|
93
|
+
41.20,
|
|
94
|
+
55.19,
|
|
95
|
+
70.69,
|
|
96
|
+
90.34,
|
|
97
|
+
115.29,
|
|
98
|
+
147.42,
|
|
99
|
+
188.24,
|
|
100
|
+
240.03,
|
|
101
|
+
),
|
|
102
|
+
he_a=(
|
|
103
|
+
1.6189,
|
|
104
|
+
1.3830,
|
|
105
|
+
1.1919,
|
|
106
|
+
1.0458,
|
|
107
|
+
0.9220,
|
|
108
|
+
0.8205,
|
|
109
|
+
0.7305,
|
|
110
|
+
0.6502,
|
|
111
|
+
0.5950,
|
|
112
|
+
0.5545,
|
|
113
|
+
0.5333,
|
|
114
|
+
0.5189,
|
|
115
|
+
0.5181,
|
|
116
|
+
0.5176,
|
|
117
|
+
0.5172,
|
|
118
|
+
0.5119,
|
|
119
|
+
),
|
|
120
|
+
he_b=(
|
|
121
|
+
0.4770,
|
|
122
|
+
0.5747,
|
|
123
|
+
0.6527,
|
|
124
|
+
0.7223,
|
|
125
|
+
0.7582,
|
|
126
|
+
0.7957,
|
|
127
|
+
0.8279,
|
|
128
|
+
0.8553,
|
|
129
|
+
0.8757,
|
|
130
|
+
0.8903,
|
|
131
|
+
0.8997,
|
|
132
|
+
0.9073,
|
|
133
|
+
0.9122,
|
|
134
|
+
0.9171,
|
|
135
|
+
0.9217,
|
|
136
|
+
0.9267,
|
|
137
|
+
),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class ZHL16B(ZHL16GF):
|
|
142
|
+
"""ZH-L16B-GF decompression model.
|
|
143
|
+
|
|
144
|
+
Used for dive table calculations. This is the legacy model retained
|
|
145
|
+
for backward compatibility. Prefer ZHL16C for new applications.
|
|
146
|
+
|
|
147
|
+
Coefficients sourced from Erik Baker's gfdeco.f.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
params = ZHL16B_PARAMS
|