Mercurial > public > ostc4
annotate Discovery/Src/buehlmann.c @ 250:822416168585 bm-2
Buelmann: new implementation for ceiling
Since my first functional fix in the ceiling computation in
commit ceecabfddb57, I noticed that the computation used a
linear search, that became rather computational expensive after
that commit. The simple question is: why not a binary search?
So, this commit implements the binary search. But there is a long
story attached to this. Comparing ceiling results from hwOS and this
OSTC4 code were very different. Basically, the original OSTC4
algorithm computed the ceiling using the same GFlow to GFhigh
slope, in such a way, that the ceiling was in sync with the
presented deco stops, where the hwOS code presents a GFhigh
based ceiling.
This said, it is more logical when the OSTC4 and hwOS code give
similar results. This new recursive algorithm gives very similar
results for the ceiling compared to hwOS.
To be complete here, the Buelmann ceiling is the depth to which
you can ascend, so that the leading tissue reaches GFhigh. This
also explains why the deepest deco stop is normally deeper than
the ceiling (unless one dives with GF like 80/80).
The code implemented here is rather straightforward recursion.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
author | Jan Mulder <jlmulder@xs4all.nl> |
---|---|
date | Thu, 11 Apr 2019 17:48:48 +0200 |
parents | 3949781096d4 |
children | 1663b3b204d7 |
rev | line source |
---|---|
51
8f8ea3a32e82
Resolved warnings pointing to possible invalid memory access
Ideenmodellierer
parents:
38
diff
changeset
|
1 /* getrennte Gase f�r die verschiedenen Modi |
8f8ea3a32e82
Resolved warnings pointing to possible invalid memory access
Ideenmodellierer
parents:
38
diff
changeset
|
2 um Gaswechsel Eintr�ge zu vereinfachen |
38 | 3 das heisst: |
4 oc == bailout in cc mode | |
5 */ | |
6 | |
7 /* Konvention: | |
8 float extExample_variable_can_be_used_with_extern; | |
9 */ | |
10 | |
11 #include <string.h> | |
12 //#include "arm_math.h" | |
13 #include <math.h> | |
14 #include <stdbool.h> | |
15 #include "buehlmann.h" | |
16 #include "decom.h" | |
17 | |
18 | |
19 extern const float buehlmann_N2_a[]; | |
20 extern const float buehlmann_N2_b[]; | |
21 extern const float buehlmann_He_a[]; | |
22 extern const float buehlmann_He_b[]; | |
23 | |
24 | |
25 /* | |
26 typedef struct | |
27 { | |
28 float *pointer_array_tissue_nitrogen_bar; | |
29 float *pointer_array_tissue_helium_bar; | |
30 char gf_value; | |
31 | |
32 float output_ceiling_ambient_bar_or_input; | |
33 _Bool output_ceiling_tolerated_if_ceiling_used_as_input; | |
34 } tissue_test_tolerance_struct; | |
35 */ | |
36 typedef struct | |
37 { | |
38 float depth; | |
39 int id; | |
40 } SStop; | |
41 | |
42 #define DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS 59940 // 999 minuten; before: 18000 // 5(h) * 60(min) * 60 sec = 18000 sec | |
43 #define DECO_STOPS_MAX_TTS_FOR_EVERY_SECOND_CALC_IN_SECONDS 7200 | |
44 #define NINETY_NINE_MINUTES_IN_SECONDS 59940 | |
45 | |
46 # define PRESSURE_TEN_METER 1.0f | |
47 # define PRESSURE_THREE_METER 0.333334f | |
48 # define PRESSURE_150_CM 0.15f | |
49 # define PRESSURE_HALF_METER 0.05f | |
50 /* | |
51 # define PRESSURE_150_CM_MBAR 150 | |
52 # define PRESSURE_TWO_M_MBAR 200 | |
53 # define PRESSURE_FIVE_M_MBAR 500 | |
54 # define PRESSURE_TEN_M_MBAR 1000 | |
55 # define PRESSURE_120_METER 12.0 | |
56 */ | |
57 /* | |
58 _____________________________________________________________ | |
59 */ | |
60 | |
61 | |
62 void buehlmann_backup_and_restore(_Bool backup_restore_otherwise); | |
63 float tissue_tolerance(void); | |
64 void ambient_bar_to_deco_stop_depth_bar(float ceiling); | |
65 int ascend_with_all_gaschanges(float pressure_decrease); | |
66 float next_stop_depth_input_is_actual_stop_id(int actual_id); | |
67 float get_gf_at_pressure(float pressure); | |
68 void buehlmann_calc_ndl(void); | |
69 _Bool dive1_check_deco(void); | |
70 | |
71 /* | |
72 _____________________________________________________________ | |
73 */ | |
74 | |
75 SDecoinfo gDecotable; | |
76 float gSurface_pressure_bar; | |
77 float gPressure; | |
78 int gGas_id; | |
79 float gTTS; | |
80 float gTissue_nitrogen_bar[16]; | |
81 float gTissue_helium_bar[16]; | |
130
b7689d9e888a
Minor changes to improved code quality and to eliminate warnings
Ideenmodellierer
parents:
51
diff
changeset
|
82 float gGF_value; |
38 | 83 float gCNS; |
84 //float gMax_ceiling_bar = 0; | |
85 int gNDL; | |
86 | |
87 | |
88 //SLifeData *pLifeData; | |
89 SDiveSettings *pBuDiveSettings; | |
90 SDecoinfo* pDecolistBuehlmann; | |
91 //signed char gGaschange_decreasing_depth_gas_id[BUEHLMANN_STRUCT_MAX_GASES]; | |
92 float gGF_low_depth_bar; | |
93 SStop gStop; | |
94 | |
95 void buehlmann_init(void) | |
96 { | |
97 //gMax_ceiling_bar = 0; | |
98 } | |
99 | |
100 void buehlmann_backup_and_restore(_Bool backup_restore_otherwise) | |
101 { | |
102 static float pressure; | |
103 static float gas_id; | |
104 static float tts; | |
105 static float tissue_nitrogen_bar[16]; | |
106 static float tissue_helium_bar[16]; | |
107 static float gf_value; | |
108 static int ndl; | |
109 static float cns; | |
110 | |
111 if(backup_restore_otherwise) | |
112 { | |
113 pressure = gPressure; | |
114 gas_id = gGas_id; | |
115 tts = gTTS; | |
116 gf_value = gGF_value; | |
117 ndl = gNDL; | |
118 cns = gCNS; | |
119 memcpy(tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16)); | |
120 memcpy(tissue_helium_bar, gTissue_helium_bar, (4*16)); | |
121 } | |
122 else | |
123 { | |
124 gPressure = pressure; | |
125 gGas_id = gas_id; | |
126 gTTS = tts; | |
127 gGF_value = gf_value; | |
128 gNDL = ndl; | |
129 gCNS = cns; | |
130 memcpy(gTissue_nitrogen_bar, tissue_nitrogen_bar, (4*16)); | |
131 memcpy(gTissue_helium_bar, tissue_helium_bar, (4*16)); | |
132 } | |
133 | |
134 } | |
135 /*void buehlmann__test__saturate_tissues(SBuehlmann *pInput, int seconds) | |
136 { | |
137 pBuehlmann = pInput; | |
138 pInput->dive_time_seconds += seconds; | |
139 // internal copying | |
140 gSurface_pressure_bar = pBuehlmann->pressure_surface_bar; | |
141 | |
142 gPressure = pBuehlmann->pressure_ambient_bar; | |
143 gGas_id = pBuehlmann->actual_gas_id; | |
144 memcpy(gTissue_nitrogen_bar, pBuehlmann->tissue_nitrogen_bar, (4*16)); | |
145 memcpy(gTissue_helium_bar, pBuehlmann->tissue_helium_bar, (4*16)); | |
146 | |
147 tissues_exposure_at_gPressure_seconds(seconds); | |
148 | |
149 memcpy(pBuehlmann->tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16)); | |
150 memcpy(pBuehlmann->tissue_helium_bar, gTissue_helium_bar, (4*16)); | |
151 }*/ | |
152 | |
153 float buehlmann_get_gCNS(void) | |
154 { | |
155 return gCNS; | |
156 } | |
157 | |
158 void buehlmann_calc_deco(SLifeData* pLifeData, SDiveSettings * pDiveSettings, SDecoinfo * pDecoInfo) | |
159 { | |
160 float ceiling; | |
161 int ascend_time; | |
162 int tts_seconds; | |
163 float pressure_delta; | |
164 float next_depth; | |
165 _Bool deco_reached = false; | |
166 // tissue_test_tolerance_struct tolerance_data; | |
167 unsigned short *stoplist; | |
168 int i; | |
169 | |
170 // decom_CreateGasChangeList(pDiveSettings, pLifeData); | |
171 | |
172 gCNS = 0; | |
173 pDecoInfo->output_time_to_surface_seconds = 0; | |
174 pDecoInfo->output_ndl_seconds = 0; | |
175 for(int i=0;i<DECOINFO_STRUCT_MAX_STOPS;i++) | |
176 { | |
177 pDecoInfo->output_stop_length_seconds[i] = 0; | |
178 } | |
179 /* make input available global*/ | |
180 pBuDiveSettings = pDiveSettings; | |
181 | |
182 pDecolistBuehlmann = pDecoInfo; | |
183 /* internal copying */ | |
184 gSurface_pressure_bar = pLifeData->pressure_surface_bar; | |
185 | |
186 gPressure = pLifeData->pressure_ambient_bar; | |
187 gGas_id = 0; | |
188 memcpy(gTissue_nitrogen_bar, pLifeData->tissue_nitrogen_bar, (4*16)); | |
189 memcpy(gTissue_helium_bar, pLifeData->tissue_helium_bar, (4*16)); | |
190 gGF_value = ((float)pBuDiveSettings->gf_low) / 100.0f; | |
191 | |
192 // | |
193 memcpy(&gDecotable, pDecolistBuehlmann, sizeof(SDecoinfo)); | |
194 stoplist = gDecotable.output_stop_length_seconds; | |
195 | |
196 | |
197 if(pLifeData->dive_time_seconds < 60) | |
198 return; | |
199 /* coupling */ | |
200 | |
201 /* functions */ | |
202 | |
203 // clean stop list | |
204 for(i = 0; i < DECOINFO_STRUCT_MAX_STOPS; i++) | |
205 stoplist[i] = 0; | |
206 gTTS = 0; | |
207 gNDL = 0; | |
208 | |
209 if(pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero >= (gPressure - PRESSURE_150_CM)) | |
210 { | |
211 deco_reached = true; | |
212 } | |
213 | |
214 | |
215 //ascend_with_all_gaschanges(gPressure - gSurface_pressure_bar); | |
216 gGF_value = ((float)pBuDiveSettings->gf_high) / 100.0f; | |
217 //iling = tissue_tolerance(); | |
218 // includes backup for gGF_value | |
219 // NDL | |
220 buehlmann_backup_and_restore(true); // includes backup for gGF_value | |
221 if(!dive1_check_deco() ) | |
222 { | |
223 buehlmann_backup_and_restore(false); | |
224 // no deco | |
225 pDecolistBuehlmann->output_time_to_surface_seconds = 0; | |
226 for(i = 0; i < DECOINFO_STRUCT_MAX_STOPS; i++) | |
227 pDecolistBuehlmann->output_stop_length_seconds[i] = 0; | |
228 // calc NDL | |
229 buehlmann_calc_ndl(); | |
230 pDecolistBuehlmann->output_ndl_seconds = gNDL; | |
231 return; | |
232 } | |
233 buehlmann_backup_and_restore(false); | |
234 pDecolistBuehlmann->output_ndl_seconds = 0; | |
235 | |
236 gGF_value = get_gf_at_pressure(gPressure); | |
237 //current ceiling at actual position | |
238 ceiling = tissue_tolerance(); | |
239 //if(ceiling < pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero) | |
240 //ambient_bar_to_deco_stop_depth_bar(pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero); | |
241 //else | |
242 ambient_bar_to_deco_stop_depth_bar(ceiling); | |
243 | |
244 // set the base for all upcoming parameters | |
245 ceiling = gStop.depth + gSurface_pressure_bar; | |
246 tts_seconds = 0; | |
247 | |
248 // modify parameters if there is ascend or parameter fine adjustment | |
249 if(ceiling < (gPressure - PRESSURE_150_CM)) // more than 1.5 meter below ceiling | |
250 { | |
251 // ascend within 10 mtr to GF_low // speed 12 mtr/min -> 50 sec / 10 mtr; 15 sec / 3 mtr. | |
252 if(ceiling < (gPressure - PRESSURE_TEN_METER) ) | |
253 { do { | |
254 ascend_time = ascend_with_all_gaschanges(PRESSURE_TEN_METER); | |
255 tts_seconds += ascend_time; | |
256 ceiling = tissue_tolerance(); | |
257 if(tts_seconds > DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS) | |
258 { | |
259 /* pInput == pBuehlmann */ | |
260 pDecolistBuehlmann->output_time_to_surface_seconds = NINETY_NINE_MINUTES_IN_SECONDS; | |
261 return;// NINETY_NINE_MINUTES_IN_SECONDS; | |
262 } | |
263 } while ((ascend_time > 0 ) && ((gPressure - PRESSURE_TEN_METER ) > gSurface_pressure_bar) && (ceiling < (gPressure - PRESSURE_TEN_METER))); | |
264 } | |
265 do { | |
266 buehlmann_backup_and_restore(true); | |
267 ascend_time = ascend_with_all_gaschanges(PRESSURE_THREE_METER); | |
268 tts_seconds += ascend_time; | |
269 ceiling = tissue_tolerance(); | |
270 if(tts_seconds > DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS) | |
271 { | |
272 /* pInput == pBuehlmann */ | |
273 pDecolistBuehlmann->output_time_to_surface_seconds = NINETY_NINE_MINUTES_IN_SECONDS; | |
274 return;// NINETY_NINE_MINUTES_IN_SECONDS; | |
275 } | |
276 ambient_bar_to_deco_stop_depth_bar(ceiling); | |
277 } while ((ascend_time > 0 ) && ((gStop.depth + gSurface_pressure_bar) < gPressure)); | |
278 | |
279 if(gStop.depth + gSurface_pressure_bar > gPressure) | |
280 { | |
281 gPressure += PRESSURE_THREE_METER; | |
282 buehlmann_backup_and_restore(false); | |
283 tts_seconds -= ascend_time; | |
284 } | |
285 // calculate first stop based on tissue saturation within 10 meters of stop | |
286 //ambient_bar_to_deco_stop_depth_bar(ceiling); | |
287 } | |
288 else | |
289 { | |
290 // initial values, upper code might not be executed (is within 150 cm) | |
291 } | |
292 | |
293 | |
294 | |
295 | |
296 if(ceiling > gSurface_pressure_bar) | |
297 { | |
298 | |
299 ceiling = gStop.depth + gSurface_pressure_bar; | |
300 // ascend the last meters to first stop (especially consider any gas changes around) | |
301 pressure_delta = gPressure - ceiling; | |
302 ascend_time = (int)ceil(pressure_delta * 50.0f); | |
303 tts_seconds += ascend_with_all_gaschanges(pressure_delta); | |
304 } | |
305 // NDL check | |
306 if(ceiling <= gSurface_pressure_bar) | |
307 { | |
308 /* pInput == pBuehlmann same pointer*/ | |
309 // NDL with GF_low | |
310 pDecolistBuehlmann->output_time_to_surface_seconds = 0; | |
311 return; | |
312 } | |
313 if(ceiling >pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero) | |
314 pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero = ceiling; | |
315 | |
316 // calc gf loop | |
317 if(deco_reached) | |
318 gGF_low_depth_bar = pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero - gSurface_pressure_bar; | |
319 else | |
320 gGF_low_depth_bar = ceiling - gSurface_pressure_bar; | |
321 | |
322 while(gStop.depth > 0) | |
323 { | |
324 do | |
325 { | |
326 next_depth = next_stop_depth_input_is_actual_stop_id(gStop.id); | |
327 gGF_value = get_gf_at_pressure(next_depth + gSurface_pressure_bar); | |
328 buehlmann_backup_and_restore(true); | |
329 ascend_time = ascend_with_all_gaschanges(gStop.depth - next_depth); | |
330 ceiling = tissue_tolerance(); | |
331 /* pre check actual limit */ | |
332 if(gDecotable.output_stop_length_seconds[gStop.id] >= 999*60) | |
333 { | |
334 tts_seconds -= 999*60 - gDecotable.output_stop_length_seconds[gStop.id]; | |
335 gDecotable.output_stop_length_seconds[gStop.id] = 999*60; | |
336 } | |
337 else | |
338 /* more deco on the actual depth */ | |
339 if(ceiling > next_depth + gSurface_pressure_bar) | |
340 { | |
341 next_depth = -1; | |
342 buehlmann_backup_and_restore(false); | |
343 decom_tissues_exposure2(10, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar); // some seconds at least at each stop | |
344 decom_oxygen_calculate_cns_exposure(10, &pBuDiveSettings->decogaslist[gGas_id], gPressure, &gCNS); | |
345 gDecotable.output_stop_length_seconds[gStop.id] += 10; | |
346 tts_seconds += 10; | |
347 } | |
348 } while(next_depth == -1); | |
349 tts_seconds += ascend_time; | |
350 gStop.depth = next_depth; | |
351 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++) | |
352 { | |
353 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) | |
354 break; | |
355 float pressureChange = ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero) / 10; | |
356 if(gStop.depth <= pressureChange + 0.00001f) | |
357 { | |
358 gGas_id = i; | |
359 } | |
360 else | |
361 { | |
362 break; | |
363 } | |
364 } | |
365 gStop.id--; | |
366 } | |
367 | |
368 gDecotable.output_time_to_surface_seconds = tts_seconds; | |
369 memcpy(pDecolistBuehlmann, &gDecotable, sizeof(SDecoinfo)); | |
370 } | |
371 | |
372 | |
373 float tissue_tolerance(void) | |
374 { | |
375 float tissue_inertgas_saturation; | |
376 float inertgas_a; | |
377 float inertgas_b; | |
378 float ceiling; | |
379 float global_ceiling; | |
380 int ci; | |
381 | |
382 global_ceiling = -1; | |
383 | |
384 for (ci = 0; ci < 16; ci++) | |
385 { | |
386 if(gTissue_helium_bar[ci] == 0) | |
387 { | |
388 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci]; | |
389 // | |
390 inertgas_a = buehlmann_N2_a[ci]; | |
391 inertgas_b = buehlmann_N2_b[ci]; | |
392 } | |
393 else | |
394 { | |
395 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci]; | |
396 // | |
397 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
398 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
399 } | |
400 // | |
401 ceiling = (inertgas_b * ( tissue_inertgas_saturation - gGF_value * inertgas_a ) ) / (gGF_value - (inertgas_b * gGF_value) + inertgas_b); | |
402 if(ceiling > global_ceiling) | |
403 global_ceiling = ceiling; | |
404 } | |
405 return global_ceiling; | |
406 } | |
407 | |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
408 void buehlmann_super_saturation_calculator(SLifeData* pLifeData, SDecoinfo * pDecoInfo) |
38 | 409 { |
410 float tissue_inertgas_saturation; | |
411 float inertgas_a; | |
412 float inertgas_b; | |
413 float ceiling; | |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
414 float super_saturation; |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
415 float pres_respiration = pLifeData->pressure_ambient_bar; |
38 | 416 int ci; |
417 | |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
418 pDecoInfo->super_saturation = 0; |
38 | 419 |
420 for (ci = 0; ci < 16; ci++) | |
421 { | |
422 if(gTissue_helium_bar[ci] == 0) | |
423 { | |
424 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci]; | |
425 inertgas_a = buehlmann_N2_a[ci]; | |
426 inertgas_b = buehlmann_N2_b[ci]; | |
427 } | |
428 else | |
429 { | |
430 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci]; | |
431 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
432 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
433 } | |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
434 |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
435 ceiling = pres_respiration / inertgas_b + inertgas_a; |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
436 if(tissue_inertgas_saturation > pres_respiration) |
38 | 437 { |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
438 super_saturation = |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
439 (tissue_inertgas_saturation - pres_respiration) / (ceiling - pres_respiration); |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
440 |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
441 if (super_saturation > pDecoInfo->super_saturation) |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
442 pDecoInfo->super_saturation = super_saturation; |
38 | 443 } |
444 } | |
445 } | |
446 | |
447 | |
250
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
448 float buehlmann_tissue_test_tolerance(float depth_in_bar_absolute) |
38 | 449 { |
450 float tissue_inertgas_saturation; | |
451 float inertgas_a; | |
452 float inertgas_b; | |
453 float inertgas_tolerance; | |
454 float gf_minus_1; | |
455 | |
456 gf_minus_1 = gGF_value - 1.0f; | |
457 | |
458 for (int ci = 0; ci < 16; ci++) | |
459 { | |
460 if(gTissue_helium_bar[ci] == 0) | |
461 { | |
462 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci]; | |
463 inertgas_a = buehlmann_N2_a[ci]; | |
464 inertgas_b = buehlmann_N2_b[ci]; | |
465 } | |
466 else | |
467 { | |
468 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci]; | |
469 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
470 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
471 } | |
472 inertgas_tolerance = ( (gGF_value / inertgas_b - gf_minus_1) * depth_in_bar_absolute ) + ( gGF_value * inertgas_a ); | |
473 if(inertgas_tolerance < tissue_inertgas_saturation) | |
250
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
474 return tissue_inertgas_saturation - inertgas_tolerance; // positive |
38 | 475 } |
250
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
476 return tissue_inertgas_saturation - inertgas_tolerance; // negative |
38 | 477 } |
478 | |
479 | |
480 void ambient_bar_to_deco_stop_depth_bar(float ceiling) | |
481 { | |
482 int i; | |
483 | |
484 ceiling -= gSurface_pressure_bar; | |
485 | |
486 if(ceiling <= 0) | |
487 { | |
488 gStop.depth = pBuDiveSettings->last_stop_depth_bar; | |
489 gStop.id = 0; | |
490 return; | |
491 } | |
492 | |
493 | |
494 //for(int i = 1; i < 10; i++) | |
495 | |
496 if((ceiling - pBuDiveSettings->last_stop_depth_bar) <= 0) | |
497 { | |
498 gStop.depth = pBuDiveSettings->last_stop_depth_bar; | |
499 gStop.id = 0; | |
500 return; | |
501 } | |
502 | |
503 gStop.depth = pBuDiveSettings->input_second_to_last_stop_depth_bar; | |
504 gStop.id = 1; | |
505 ceiling -= pBuDiveSettings->input_second_to_last_stop_depth_bar; | |
506 | |
507 if(ceiling <= 0) | |
508 return; | |
509 | |
510 for(i = 1; i < (DECOINFO_STRUCT_MAX_STOPS - 2); i++) | |
511 { | |
512 ceiling -= pBuDiveSettings->input_next_stop_increment_depth_bar; | |
513 if(ceiling <= 0) | |
514 break; | |
515 } | |
516 gStop.depth += i * pBuDiveSettings->input_next_stop_increment_depth_bar; | |
517 gStop.id += i; | |
518 return; | |
519 } | |
520 | |
521 float next_stop_depth_input_is_actual_stop_id(int actual_id) | |
522 { | |
523 if(actual_id == 0) | |
524 return 0; | |
525 | |
526 if(actual_id == 1) | |
527 return pBuDiveSettings->last_stop_depth_bar; | |
528 | |
529 actual_id -= 2; | |
530 return pBuDiveSettings->input_second_to_last_stop_depth_bar + (actual_id * pBuDiveSettings->input_next_stop_increment_depth_bar); | |
531 } | |
532 | |
533 int ascend_with_all_gaschanges(float pressure_decrease) | |
534 { | |
535 float pressureTop, pressureTop_tmp, pressureBottom, pressureChange, ascendrate_in_seconds_for_one_bar, pressure_difference; | |
51
8f8ea3a32e82
Resolved warnings pointing to possible invalid memory access
Ideenmodellierer
parents:
38
diff
changeset
|
536 int time_for_ascend = 0; |
38 | 537 int seconds; |
538 int i; | |
539 | |
540 ascendrate_in_seconds_for_one_bar = 60 * 10 / pBuDiveSettings->ascentRate_meterperminute; | |
541 | |
542 if(fabsf(gPressure - gSurface_pressure_bar) < PRESSURE_HALF_METER) | |
543 { | |
544 gPressure = gSurface_pressure_bar; | |
545 return 0; | |
546 } | |
547 | |
548 pressureTop = gPressure - pressure_decrease; | |
549 if( gSurface_pressure_bar > pressureTop) | |
550 pressureTop = gSurface_pressure_bar; | |
551 pressureBottom = gPressure; | |
552 seconds = 0; | |
553 do{ | |
554 pressureTop_tmp = pressureTop; | |
555 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++) | |
556 { | |
557 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) | |
558 break; | |
559 pressureChange = gSurface_pressure_bar + ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero) / 10; | |
560 if(pressureBottom <= pressureChange) | |
561 { | |
562 gGas_id = i; | |
563 } | |
564 else | |
565 { | |
566 break; | |
567 } | |
568 | |
569 } | |
570 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++) | |
571 { | |
572 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) | |
573 break; | |
574 pressureChange = gSurface_pressure_bar + ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero)/ 10; | |
575 if((pressureChange < pressureBottom) && (pressureChange > pressureTop)) | |
576 { | |
577 pressureTop_tmp = pressureChange; | |
578 } | |
579 } | |
580 pressure_difference = pressureBottom - pressureTop_tmp; | |
581 if(pressure_difference > 0.0001f) | |
582 { | |
583 time_for_ascend = (int)ceilf(pressure_difference * ascendrate_in_seconds_for_one_bar); | |
584 decom_tissues_exposure_stage_schreiner(time_for_ascend, &pBuDiveSettings->decogaslist[gGas_id], | |
585 pressureBottom, pressureTop_tmp, gTissue_nitrogen_bar, gTissue_helium_bar); | |
586 decom_oxygen_calculate_cns_stage_SchreinerStyle(time_for_ascend,&pBuDiveSettings->decogaslist[gGas_id], | |
587 pressureBottom, pressureTop_tmp, &gCNS); | |
588 } | |
589 pressureBottom = pressureTop_tmp; | |
590 seconds += time_for_ascend; | |
591 }while(pressureTop_tmp > pressureTop); | |
592 gPressure = pressureTop; | |
593 return seconds; | |
594 } | |
595 | |
596 | |
597 float get_gf_at_pressure(float pressure) | |
598 { | |
599 float gfSteigung = 0.0f; | |
600 | |
601 if(gGF_low_depth_bar < 0) | |
602 gGF_low_depth_bar = PRESSURE_THREE_METER; // just to prevent erratic behaviour if variable is not set | |
603 | |
604 gfSteigung = ((float)(pBuDiveSettings->gf_high - pBuDiveSettings->gf_low))/ gGF_low_depth_bar; | |
605 | |
606 | |
607 if((pressure - gSurface_pressure_bar) <= PRESSURE_HALF_METER) | |
608 return ((float)pBuDiveSettings->gf_high) / 100.0f; | |
609 | |
610 if(pressure >= gSurface_pressure_bar + gGF_low_depth_bar) | |
611 return ((float)pBuDiveSettings->gf_low) / 100.0f; | |
612 | |
613 return (pBuDiveSettings->gf_high - gfSteigung * (pressure - gSurface_pressure_bar) )/ 100.0f; | |
614 } | |
615 | |
616 | |
617 void buehlmann_calc_ndl(void) | |
618 { | |
619 float local_tissue_nitrogen_bar[16]; | |
620 float local_tissue_helium_bar[16]; | |
621 int i; | |
622 | |
623 gNDL = 0; | |
624 //Check ndl always use gHigh | |
625 gGF_value = ((float)pBuDiveSettings->gf_high) / 100.0f; | |
626 //10 minutes steps | |
627 while(gNDL < (300 * 60)) | |
628 { | |
629 memcpy(local_tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16)); | |
630 memcpy(local_tissue_helium_bar, gTissue_helium_bar, (4*16)); | |
631 // | |
632 gNDL += 600; | |
633 decom_tissues_exposure2(600, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar); | |
634 decom_oxygen_calculate_cns_exposure(600,&pBuDiveSettings->decogaslist[gGas_id],gPressure,&gCNS); | |
635 //tissues_exposure_at_gPressure_seconds(600); | |
636 buehlmann_backup_and_restore(true); | |
637 if(dive1_check_deco() == true) | |
638 { | |
639 buehlmann_backup_and_restore(false); | |
640 break; | |
641 } | |
642 buehlmann_backup_and_restore(false); | |
643 } | |
644 | |
645 if(gNDL < (300 * 60)) | |
646 gNDL -= 600; | |
647 | |
648 if(gNDL > (150 * 60)) | |
649 return; | |
650 | |
651 // refine | |
652 memcpy(gTissue_nitrogen_bar, local_tissue_nitrogen_bar, (4*16)); | |
653 memcpy(gTissue_helium_bar, local_tissue_helium_bar, (4*16)); | |
654 | |
655 //One minutes step | |
656 for(i = 0; i < 20; i++) | |
657 { | |
658 gNDL += 60; | |
659 //tissues_exposure_at_gPressure_seconds(60); | |
660 decom_tissues_exposure2(60, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar); | |
661 decom_oxygen_calculate_cns_exposure(60,&pBuDiveSettings->decogaslist[gGas_id],gPressure,&gCNS); | |
662 buehlmann_backup_and_restore(true); | |
663 if(dive1_check_deco() == true) | |
664 break; | |
665 buehlmann_backup_and_restore(false); | |
666 } | |
667 //gNDL -= 60; | |
668 return; | |
669 } | |
670 | |
671 | |
672 // =============================================================================== | |
673 // dive1_check_deco | |
674 /// @brief for NDL calculations | |
675 /// 160614 using ceilingOther and not ceiling | |
676 // =============================================================================== | |
677 _Bool dive1_check_deco(void) | |
678 { | |
679 // gGF_value is set in call routine; | |
680 // internes Backup! | |
681 | |
682 // calc like in deco | |
683 float ceiling; | |
684 float ceilingOther; // new hw 160614 | |
685 | |
686 ceiling = tissue_tolerance(); | |
687 ambient_bar_to_deco_stop_depth_bar(ceiling); // this will set gStop.depth :-) (and gStop.id) | |
688 | |
689 // set the base for all upcoming parameters | |
690 ceilingOther = gStop.depth + gSurface_pressure_bar; | |
691 | |
692 // modify parameters if there is ascend or parameter fine adjustment | |
693 if(ceilingOther < (gPressure - PRESSURE_150_CM)) // more than 1.5 meter below ceiling | |
694 { | |
695 // ascend within 10 mtr to GF_low // speed 12 mtr/min -> 50 sec / 10 mtr; 15 sec / 3 mtr. | |
696 while(((gPressure - PRESSURE_TEN_METER ) > gSurface_pressure_bar) && (ceiling < (gPressure - PRESSURE_TEN_METER))) | |
697 { | |
698 ascend_with_all_gaschanges(PRESSURE_TEN_METER); | |
699 ceiling = tissue_tolerance(); | |
700 } | |
701 while(((gPressure - PRESSURE_THREE_METER )> gSurface_pressure_bar) && (ceiling < gPressure)) | |
702 { | |
703 ascend_with_all_gaschanges(PRESSURE_THREE_METER); | |
704 ceiling = tissue_tolerance(); | |
705 } | |
706 } | |
707 if(ceiling <= gSurface_pressure_bar) | |
708 return false; | |
709 else | |
710 return true; | |
711 } | |
712 | |
250
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
713 // compute ceiling recursively, with a resolution of 10cm. Notice |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
714 // that the initial call shall guarantee that the found ceiling |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
715 // is between low and high parameters. |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
716 static float compute_ceiling(float low, float high) |
38 | 717 { |
250
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
718 if ((high - low) < 0.01) |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
719 return low; |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
720 else { |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
721 float next_pressure_absolute = (low + high)/2; |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
722 float test_result = buehlmann_tissue_test_tolerance(next_pressure_absolute); |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
723 if (test_result < 0) |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
724 return compute_ceiling(low, next_pressure_absolute); |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
725 else |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
726 return compute_ceiling(next_pressure_absolute, high); |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
727 } |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
728 } |
38 | 729 |
250
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
730 void buehlmann_ceiling_calculator(SLifeData *pLifeData, SDecoinfo *pDecoInfo) |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
731 { |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
732 float ceiling; |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
733 |
250
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
734 // this is just performance optimizing. The code below runs just fine |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
735 // without this. There is never a ceiling in NDL deco state |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
736 if (!pDecoInfo->output_time_to_surface_seconds) { |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
737 pDecoInfo->output_ceiling_meter = 0; |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
738 return; |
38 | 739 } |
740 | |
741 memcpy(gTissue_nitrogen_bar, pLifeData->tissue_nitrogen_bar, (4*16)); | |
742 memcpy(gTissue_helium_bar, pLifeData->tissue_helium_bar, (4*16)); | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
743 |
250
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
744 ceiling = compute_ceiling(pLifeData->pressure_surface_bar, 1.0f + pLifeData->max_depth_meter/10.0f); |
822416168585
Buelmann: new implementation for ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
247
diff
changeset
|
745 pDecoInfo->output_ceiling_meter = (ceiling - pLifeData->pressure_surface_bar) * 10.0f; |
38 | 746 } |