Mercurial > public > ostc4
annotate Discovery/Src/buehlmann.c @ 246:ff0d23625cd5 bm-1
feature: replace Relative GF by saturation, computational only
Replace Relative GF by saturation. The saturation code is derived from
the hwOS repo. This commit only contains the Buhlmann computational part. In
the simulator, the numbers does look sane. The initial ascent from the
bottom phase stops at the deepest deco stop a little over GFlow, which is
correct in my view, as we still have some time to spend on this deepest
stop, and that stop ends very close to GFlow (obviously, a deepest stop
is typically short, as in 1 or 2 minutes). The deco finally ends at the
surface with a saturation value of GFhigh.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
author | Jan Mulder <jlmulder@xs4all.nl> |
---|---|
date | Tue, 09 Apr 2019 15:38:31 +0200 |
parents | ceecabfddb57 |
children | 3949781096d4 |
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 uint8_t buehlmann_tissue_test_tolerance(float depth_in_bar_absolute); | |
71 | |
72 /* | |
73 _____________________________________________________________ | |
74 */ | |
75 | |
76 SDecoinfo gDecotable; | |
77 float gSurface_pressure_bar; | |
78 float gPressure; | |
79 int gGas_id; | |
80 float gTTS; | |
81 float gTissue_nitrogen_bar[16]; | |
82 float gTissue_helium_bar[16]; | |
130
b7689d9e888a
Minor changes to improved code quality and to eliminate warnings
Ideenmodellierer
parents:
51
diff
changeset
|
83 float gGF_value; |
38 | 84 float gCNS; |
85 //float gMax_ceiling_bar = 0; | |
86 int gNDL; | |
87 | |
88 | |
89 //SLifeData *pLifeData; | |
90 SDiveSettings *pBuDiveSettings; | |
91 SDecoinfo* pDecolistBuehlmann; | |
92 //signed char gGaschange_decreasing_depth_gas_id[BUEHLMANN_STRUCT_MAX_GASES]; | |
93 float gGF_low_depth_bar; | |
94 SStop gStop; | |
95 | |
96 void buehlmann_init(void) | |
97 { | |
98 //gMax_ceiling_bar = 0; | |
99 } | |
100 | |
101 void buehlmann_backup_and_restore(_Bool backup_restore_otherwise) | |
102 { | |
103 static float pressure; | |
104 static float gas_id; | |
105 static float tts; | |
106 static float tissue_nitrogen_bar[16]; | |
107 static float tissue_helium_bar[16]; | |
108 static float gf_value; | |
109 static int ndl; | |
110 static float cns; | |
111 | |
112 if(backup_restore_otherwise) | |
113 { | |
114 pressure = gPressure; | |
115 gas_id = gGas_id; | |
116 tts = gTTS; | |
117 gf_value = gGF_value; | |
118 ndl = gNDL; | |
119 cns = gCNS; | |
120 memcpy(tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16)); | |
121 memcpy(tissue_helium_bar, gTissue_helium_bar, (4*16)); | |
122 } | |
123 else | |
124 { | |
125 gPressure = pressure; | |
126 gGas_id = gas_id; | |
127 gTTS = tts; | |
128 gGF_value = gf_value; | |
129 gNDL = ndl; | |
130 gCNS = cns; | |
131 memcpy(gTissue_nitrogen_bar, tissue_nitrogen_bar, (4*16)); | |
132 memcpy(gTissue_helium_bar, tissue_helium_bar, (4*16)); | |
133 } | |
134 | |
135 } | |
136 /*void buehlmann__test__saturate_tissues(SBuehlmann *pInput, int seconds) | |
137 { | |
138 pBuehlmann = pInput; | |
139 pInput->dive_time_seconds += seconds; | |
140 // internal copying | |
141 gSurface_pressure_bar = pBuehlmann->pressure_surface_bar; | |
142 | |
143 gPressure = pBuehlmann->pressure_ambient_bar; | |
144 gGas_id = pBuehlmann->actual_gas_id; | |
145 memcpy(gTissue_nitrogen_bar, pBuehlmann->tissue_nitrogen_bar, (4*16)); | |
146 memcpy(gTissue_helium_bar, pBuehlmann->tissue_helium_bar, (4*16)); | |
147 | |
148 tissues_exposure_at_gPressure_seconds(seconds); | |
149 | |
150 memcpy(pBuehlmann->tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16)); | |
151 memcpy(pBuehlmann->tissue_helium_bar, gTissue_helium_bar, (4*16)); | |
152 }*/ | |
153 | |
154 float buehlmann_get_gCNS(void) | |
155 { | |
156 return gCNS; | |
157 } | |
158 | |
159 void buehlmann_calc_deco(SLifeData* pLifeData, SDiveSettings * pDiveSettings, SDecoinfo * pDecoInfo) | |
160 { | |
161 float ceiling; | |
162 int ascend_time; | |
163 int tts_seconds; | |
164 float pressure_delta; | |
165 float next_depth; | |
166 _Bool deco_reached = false; | |
167 // tissue_test_tolerance_struct tolerance_data; | |
168 unsigned short *stoplist; | |
169 int i; | |
170 | |
171 // decom_CreateGasChangeList(pDiveSettings, pLifeData); | |
172 | |
173 gCNS = 0; | |
174 pDecoInfo->output_time_to_surface_seconds = 0; | |
175 pDecoInfo->output_ndl_seconds = 0; | |
176 for(int i=0;i<DECOINFO_STRUCT_MAX_STOPS;i++) | |
177 { | |
178 pDecoInfo->output_stop_length_seconds[i] = 0; | |
179 } | |
180 /* make input available global*/ | |
181 pBuDiveSettings = pDiveSettings; | |
182 | |
183 pDecolistBuehlmann = pDecoInfo; | |
184 /* internal copying */ | |
185 gSurface_pressure_bar = pLifeData->pressure_surface_bar; | |
186 | |
187 gPressure = pLifeData->pressure_ambient_bar; | |
188 gGas_id = 0; | |
189 memcpy(gTissue_nitrogen_bar, pLifeData->tissue_nitrogen_bar, (4*16)); | |
190 memcpy(gTissue_helium_bar, pLifeData->tissue_helium_bar, (4*16)); | |
191 gGF_value = ((float)pBuDiveSettings->gf_low) / 100.0f; | |
192 | |
193 // | |
194 memcpy(&gDecotable, pDecolistBuehlmann, sizeof(SDecoinfo)); | |
195 stoplist = gDecotable.output_stop_length_seconds; | |
196 | |
197 | |
198 if(pLifeData->dive_time_seconds < 60) | |
199 return; | |
200 /* coupling */ | |
201 | |
202 /* functions */ | |
203 | |
204 // clean stop list | |
205 for(i = 0; i < DECOINFO_STRUCT_MAX_STOPS; i++) | |
206 stoplist[i] = 0; | |
207 gTTS = 0; | |
208 gNDL = 0; | |
209 | |
210 if(pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero >= (gPressure - PRESSURE_150_CM)) | |
211 { | |
212 deco_reached = true; | |
213 } | |
214 | |
215 | |
216 //ascend_with_all_gaschanges(gPressure - gSurface_pressure_bar); | |
217 gGF_value = ((float)pBuDiveSettings->gf_high) / 100.0f; | |
218 //iling = tissue_tolerance(); | |
219 // includes backup for gGF_value | |
220 // NDL | |
221 buehlmann_backup_and_restore(true); // includes backup for gGF_value | |
222 if(!dive1_check_deco() ) | |
223 { | |
224 buehlmann_backup_and_restore(false); | |
225 // no deco | |
226 pDecolistBuehlmann->output_time_to_surface_seconds = 0; | |
227 for(i = 0; i < DECOINFO_STRUCT_MAX_STOPS; i++) | |
228 pDecolistBuehlmann->output_stop_length_seconds[i] = 0; | |
229 // calc NDL | |
230 buehlmann_calc_ndl(); | |
231 pDecolistBuehlmann->output_ndl_seconds = gNDL; | |
232 return; | |
233 } | |
234 buehlmann_backup_and_restore(false); | |
235 pDecolistBuehlmann->output_ndl_seconds = 0; | |
236 | |
237 gGF_value = get_gf_at_pressure(gPressure); | |
238 //current ceiling at actual position | |
239 ceiling = tissue_tolerance(); | |
240 //if(ceiling < pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero) | |
241 //ambient_bar_to_deco_stop_depth_bar(pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero); | |
242 //else | |
243 ambient_bar_to_deco_stop_depth_bar(ceiling); | |
244 | |
245 // set the base for all upcoming parameters | |
246 ceiling = gStop.depth + gSurface_pressure_bar; | |
247 tts_seconds = 0; | |
248 | |
249 // modify parameters if there is ascend or parameter fine adjustment | |
250 if(ceiling < (gPressure - PRESSURE_150_CM)) // more than 1.5 meter below ceiling | |
251 { | |
252 // ascend within 10 mtr to GF_low // speed 12 mtr/min -> 50 sec / 10 mtr; 15 sec / 3 mtr. | |
253 if(ceiling < (gPressure - PRESSURE_TEN_METER) ) | |
254 { do { | |
255 ascend_time = ascend_with_all_gaschanges(PRESSURE_TEN_METER); | |
256 tts_seconds += ascend_time; | |
257 ceiling = tissue_tolerance(); | |
258 if(tts_seconds > DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS) | |
259 { | |
260 /* pInput == pBuehlmann */ | |
261 pDecolistBuehlmann->output_time_to_surface_seconds = NINETY_NINE_MINUTES_IN_SECONDS; | |
262 return;// NINETY_NINE_MINUTES_IN_SECONDS; | |
263 } | |
264 } while ((ascend_time > 0 ) && ((gPressure - PRESSURE_TEN_METER ) > gSurface_pressure_bar) && (ceiling < (gPressure - PRESSURE_TEN_METER))); | |
265 } | |
266 do { | |
267 buehlmann_backup_and_restore(true); | |
268 ascend_time = ascend_with_all_gaschanges(PRESSURE_THREE_METER); | |
269 tts_seconds += ascend_time; | |
270 ceiling = tissue_tolerance(); | |
271 if(tts_seconds > DECO_STOPS_MAX_TTS_CALCULATON_IN_SECONDS) | |
272 { | |
273 /* pInput == pBuehlmann */ | |
274 pDecolistBuehlmann->output_time_to_surface_seconds = NINETY_NINE_MINUTES_IN_SECONDS; | |
275 return;// NINETY_NINE_MINUTES_IN_SECONDS; | |
276 } | |
277 ambient_bar_to_deco_stop_depth_bar(ceiling); | |
278 } while ((ascend_time > 0 ) && ((gStop.depth + gSurface_pressure_bar) < gPressure)); | |
279 | |
280 if(gStop.depth + gSurface_pressure_bar > gPressure) | |
281 { | |
282 gPressure += PRESSURE_THREE_METER; | |
283 buehlmann_backup_and_restore(false); | |
284 tts_seconds -= ascend_time; | |
285 } | |
286 // calculate first stop based on tissue saturation within 10 meters of stop | |
287 //ambient_bar_to_deco_stop_depth_bar(ceiling); | |
288 } | |
289 else | |
290 { | |
291 // initial values, upper code might not be executed (is within 150 cm) | |
292 } | |
293 | |
294 | |
295 | |
296 | |
297 if(ceiling > gSurface_pressure_bar) | |
298 { | |
299 | |
300 ceiling = gStop.depth + gSurface_pressure_bar; | |
301 // ascend the last meters to first stop (especially consider any gas changes around) | |
302 pressure_delta = gPressure - ceiling; | |
303 ascend_time = (int)ceil(pressure_delta * 50.0f); | |
304 tts_seconds += ascend_with_all_gaschanges(pressure_delta); | |
305 } | |
306 // NDL check | |
307 if(ceiling <= gSurface_pressure_bar) | |
308 { | |
309 /* pInput == pBuehlmann same pointer*/ | |
310 // NDL with GF_low | |
311 pDecolistBuehlmann->output_time_to_surface_seconds = 0; | |
312 return; | |
313 } | |
314 if(ceiling >pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero) | |
315 pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero = ceiling; | |
316 | |
317 // calc gf loop | |
318 if(deco_reached) | |
319 gGF_low_depth_bar = pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero - gSurface_pressure_bar; | |
320 else | |
321 gGF_low_depth_bar = ceiling - gSurface_pressure_bar; | |
322 | |
323 while(gStop.depth > 0) | |
324 { | |
325 do | |
326 { | |
327 next_depth = next_stop_depth_input_is_actual_stop_id(gStop.id); | |
328 gGF_value = get_gf_at_pressure(next_depth + gSurface_pressure_bar); | |
329 buehlmann_backup_and_restore(true); | |
330 ascend_time = ascend_with_all_gaschanges(gStop.depth - next_depth); | |
331 ceiling = tissue_tolerance(); | |
332 /* pre check actual limit */ | |
333 if(gDecotable.output_stop_length_seconds[gStop.id] >= 999*60) | |
334 { | |
335 tts_seconds -= 999*60 - gDecotable.output_stop_length_seconds[gStop.id]; | |
336 gDecotable.output_stop_length_seconds[gStop.id] = 999*60; | |
337 } | |
338 else | |
339 /* more deco on the actual depth */ | |
340 if(ceiling > next_depth + gSurface_pressure_bar) | |
341 { | |
342 next_depth = -1; | |
343 buehlmann_backup_and_restore(false); | |
344 decom_tissues_exposure2(10, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar); // some seconds at least at each stop | |
345 decom_oxygen_calculate_cns_exposure(10, &pBuDiveSettings->decogaslist[gGas_id], gPressure, &gCNS); | |
346 gDecotable.output_stop_length_seconds[gStop.id] += 10; | |
347 tts_seconds += 10; | |
348 } | |
349 } while(next_depth == -1); | |
350 tts_seconds += ascend_time; | |
351 gStop.depth = next_depth; | |
352 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++) | |
353 { | |
354 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) | |
355 break; | |
356 float pressureChange = ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero) / 10; | |
357 if(gStop.depth <= pressureChange + 0.00001f) | |
358 { | |
359 gGas_id = i; | |
360 } | |
361 else | |
362 { | |
363 break; | |
364 } | |
365 } | |
366 gStop.id--; | |
367 } | |
368 | |
369 gDecotable.output_time_to_surface_seconds = tts_seconds; | |
370 memcpy(pDecolistBuehlmann, &gDecotable, sizeof(SDecoinfo)); | |
371 } | |
372 | |
373 | |
374 float tissue_tolerance(void) | |
375 { | |
376 float tissue_inertgas_saturation; | |
377 float inertgas_a; | |
378 float inertgas_b; | |
379 float ceiling; | |
380 float global_ceiling; | |
381 int ci; | |
382 | |
383 global_ceiling = -1; | |
384 | |
385 for (ci = 0; ci < 16; ci++) | |
386 { | |
387 if(gTissue_helium_bar[ci] == 0) | |
388 { | |
389 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci]; | |
390 // | |
391 inertgas_a = buehlmann_N2_a[ci]; | |
392 inertgas_b = buehlmann_N2_b[ci]; | |
393 } | |
394 else | |
395 { | |
396 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci]; | |
397 // | |
398 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
399 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
400 } | |
401 // | |
402 ceiling = (inertgas_b * ( tissue_inertgas_saturation - gGF_value * inertgas_a ) ) / (gGF_value - (inertgas_b * gGF_value) + inertgas_b); | |
403 if(ceiling > global_ceiling) | |
404 global_ceiling = ceiling; | |
405 } | |
406 return global_ceiling; | |
407 } | |
408 | |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
409 void buehlmann_super_saturation_calculator(SLifeData* pLifeData, SDecoinfo * pDecoInfo) |
38 | 410 { |
411 float tissue_inertgas_saturation; | |
412 float inertgas_a; | |
413 float inertgas_b; | |
414 float ceiling; | |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
415 float super_saturation; |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
416 float pres_respiration = pLifeData->pressure_ambient_bar; |
38 | 417 int ci; |
418 | |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
419 pDecoInfo->super_saturation = 0; |
38 | 420 |
421 for (ci = 0; ci < 16; ci++) | |
422 { | |
423 if(gTissue_helium_bar[ci] == 0) | |
424 { | |
425 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci]; | |
426 inertgas_a = buehlmann_N2_a[ci]; | |
427 inertgas_b = buehlmann_N2_b[ci]; | |
428 } | |
429 else | |
430 { | |
431 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci]; | |
432 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
433 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
434 } | |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
435 |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
436 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
|
437 if(tissue_inertgas_saturation > pres_respiration) |
38 | 438 { |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
439 super_saturation = |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
440 (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
|
441 |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
442 if (super_saturation > pDecoInfo->super_saturation) |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
443 pDecoInfo->super_saturation = super_saturation; |
38 | 444 } |
445 } | |
446 } | |
447 | |
448 | |
449 uint8_t buehlmann_tissue_test_tolerance(float depth_in_bar_absolute) | |
450 { | |
451 float tissue_inertgas_saturation; | |
452 float inertgas_a; | |
453 float inertgas_b; | |
454 float inertgas_tolerance; | |
455 float gf_minus_1; | |
456 | |
457 gf_minus_1 = gGF_value - 1.0f; | |
458 | |
459 for (int ci = 0; ci < 16; ci++) | |
460 { | |
461 if(gTissue_helium_bar[ci] == 0) | |
462 { | |
463 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci]; | |
464 // | |
465 inertgas_a = buehlmann_N2_a[ci]; | |
466 inertgas_b = buehlmann_N2_b[ci]; | |
467 } | |
468 else | |
469 { | |
470 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci]; | |
471 // | |
472 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
473 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
474 } | |
475 // | |
476 inertgas_tolerance = ( (gGF_value / inertgas_b - gf_minus_1) * depth_in_bar_absolute ) + ( gGF_value * inertgas_a ); | |
477 // | |
478 if(inertgas_tolerance < tissue_inertgas_saturation) | |
479 return 0; | |
480 } | |
481 return 1; | |
482 } | |
483 | |
484 | |
485 void ambient_bar_to_deco_stop_depth_bar(float ceiling) | |
486 { | |
487 int i; | |
488 | |
489 ceiling -= gSurface_pressure_bar; | |
490 | |
491 if(ceiling <= 0) | |
492 { | |
493 gStop.depth = pBuDiveSettings->last_stop_depth_bar; | |
494 gStop.id = 0; | |
495 return; | |
496 } | |
497 | |
498 | |
499 //for(int i = 1; i < 10; i++) | |
500 | |
501 if((ceiling - pBuDiveSettings->last_stop_depth_bar) <= 0) | |
502 { | |
503 gStop.depth = pBuDiveSettings->last_stop_depth_bar; | |
504 gStop.id = 0; | |
505 return; | |
506 } | |
507 | |
508 gStop.depth = pBuDiveSettings->input_second_to_last_stop_depth_bar; | |
509 gStop.id = 1; | |
510 ceiling -= pBuDiveSettings->input_second_to_last_stop_depth_bar; | |
511 | |
512 if(ceiling <= 0) | |
513 return; | |
514 | |
515 for(i = 1; i < (DECOINFO_STRUCT_MAX_STOPS - 2); i++) | |
516 { | |
517 ceiling -= pBuDiveSettings->input_next_stop_increment_depth_bar; | |
518 if(ceiling <= 0) | |
519 break; | |
520 } | |
521 gStop.depth += i * pBuDiveSettings->input_next_stop_increment_depth_bar; | |
522 gStop.id += i; | |
523 return; | |
524 } | |
525 | |
526 float next_stop_depth_input_is_actual_stop_id(int actual_id) | |
527 { | |
528 if(actual_id == 0) | |
529 return 0; | |
530 | |
531 if(actual_id == 1) | |
532 return pBuDiveSettings->last_stop_depth_bar; | |
533 | |
534 actual_id -= 2; | |
535 return pBuDiveSettings->input_second_to_last_stop_depth_bar + (actual_id * pBuDiveSettings->input_next_stop_increment_depth_bar); | |
536 } | |
537 | |
538 int ascend_with_all_gaschanges(float pressure_decrease) | |
539 { | |
540 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
|
541 int time_for_ascend = 0; |
38 | 542 int seconds; |
543 int i; | |
544 | |
545 ascendrate_in_seconds_for_one_bar = 60 * 10 / pBuDiveSettings->ascentRate_meterperminute; | |
546 | |
547 if(fabsf(gPressure - gSurface_pressure_bar) < PRESSURE_HALF_METER) | |
548 { | |
549 gPressure = gSurface_pressure_bar; | |
550 return 0; | |
551 } | |
552 | |
553 pressureTop = gPressure - pressure_decrease; | |
554 if( gSurface_pressure_bar > pressureTop) | |
555 pressureTop = gSurface_pressure_bar; | |
556 pressureBottom = gPressure; | |
557 seconds = 0; | |
558 do{ | |
559 pressureTop_tmp = pressureTop; | |
560 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++) | |
561 { | |
562 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) | |
563 break; | |
564 pressureChange = gSurface_pressure_bar + ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero) / 10; | |
565 if(pressureBottom <= pressureChange) | |
566 { | |
567 gGas_id = i; | |
568 } | |
569 else | |
570 { | |
571 break; | |
572 } | |
573 | |
574 } | |
575 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++) | |
576 { | |
577 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) | |
578 break; | |
579 pressureChange = gSurface_pressure_bar + ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero)/ 10; | |
580 if((pressureChange < pressureBottom) && (pressureChange > pressureTop)) | |
581 { | |
582 pressureTop_tmp = pressureChange; | |
583 } | |
584 } | |
585 pressure_difference = pressureBottom - pressureTop_tmp; | |
586 if(pressure_difference > 0.0001f) | |
587 { | |
588 time_for_ascend = (int)ceilf(pressure_difference * ascendrate_in_seconds_for_one_bar); | |
589 decom_tissues_exposure_stage_schreiner(time_for_ascend, &pBuDiveSettings->decogaslist[gGas_id], | |
590 pressureBottom, pressureTop_tmp, gTissue_nitrogen_bar, gTissue_helium_bar); | |
591 decom_oxygen_calculate_cns_stage_SchreinerStyle(time_for_ascend,&pBuDiveSettings->decogaslist[gGas_id], | |
592 pressureBottom, pressureTop_tmp, &gCNS); | |
593 } | |
594 pressureBottom = pressureTop_tmp; | |
595 seconds += time_for_ascend; | |
596 }while(pressureTop_tmp > pressureTop); | |
597 gPressure = pressureTop; | |
598 return seconds; | |
599 } | |
600 | |
601 | |
602 float get_gf_at_pressure(float pressure) | |
603 { | |
604 float gfSteigung = 0.0f; | |
605 | |
606 if(gGF_low_depth_bar < 0) | |
607 gGF_low_depth_bar = PRESSURE_THREE_METER; // just to prevent erratic behaviour if variable is not set | |
608 | |
609 gfSteigung = ((float)(pBuDiveSettings->gf_high - pBuDiveSettings->gf_low))/ gGF_low_depth_bar; | |
610 | |
611 | |
612 if((pressure - gSurface_pressure_bar) <= PRESSURE_HALF_METER) | |
613 return ((float)pBuDiveSettings->gf_high) / 100.0f; | |
614 | |
615 if(pressure >= gSurface_pressure_bar + gGF_low_depth_bar) | |
616 return ((float)pBuDiveSettings->gf_low) / 100.0f; | |
617 | |
618 return (pBuDiveSettings->gf_high - gfSteigung * (pressure - gSurface_pressure_bar) )/ 100.0f; | |
619 } | |
620 | |
621 | |
622 void buehlmann_calc_ndl(void) | |
623 { | |
624 float local_tissue_nitrogen_bar[16]; | |
625 float local_tissue_helium_bar[16]; | |
626 int i; | |
627 | |
628 gNDL = 0; | |
629 //Check ndl always use gHigh | |
630 gGF_value = ((float)pBuDiveSettings->gf_high) / 100.0f; | |
631 //10 minutes steps | |
632 while(gNDL < (300 * 60)) | |
633 { | |
634 memcpy(local_tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16)); | |
635 memcpy(local_tissue_helium_bar, gTissue_helium_bar, (4*16)); | |
636 // | |
637 gNDL += 600; | |
638 decom_tissues_exposure2(600, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar); | |
639 decom_oxygen_calculate_cns_exposure(600,&pBuDiveSettings->decogaslist[gGas_id],gPressure,&gCNS); | |
640 //tissues_exposure_at_gPressure_seconds(600); | |
641 buehlmann_backup_and_restore(true); | |
642 if(dive1_check_deco() == true) | |
643 { | |
644 buehlmann_backup_and_restore(false); | |
645 break; | |
646 } | |
647 buehlmann_backup_and_restore(false); | |
648 } | |
649 | |
650 if(gNDL < (300 * 60)) | |
651 gNDL -= 600; | |
652 | |
653 if(gNDL > (150 * 60)) | |
654 return; | |
655 | |
656 // refine | |
657 memcpy(gTissue_nitrogen_bar, local_tissue_nitrogen_bar, (4*16)); | |
658 memcpy(gTissue_helium_bar, local_tissue_helium_bar, (4*16)); | |
659 | |
660 //One minutes step | |
661 for(i = 0; i < 20; i++) | |
662 { | |
663 gNDL += 60; | |
664 //tissues_exposure_at_gPressure_seconds(60); | |
665 decom_tissues_exposure2(60, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar); | |
666 decom_oxygen_calculate_cns_exposure(60,&pBuDiveSettings->decogaslist[gGas_id],gPressure,&gCNS); | |
667 buehlmann_backup_and_restore(true); | |
668 if(dive1_check_deco() == true) | |
669 break; | |
670 buehlmann_backup_and_restore(false); | |
671 } | |
672 //gNDL -= 60; | |
673 return; | |
674 } | |
675 | |
676 | |
677 // =============================================================================== | |
678 // dive1_check_deco | |
679 /// @brief for NDL calculations | |
680 /// 160614 using ceilingOther and not ceiling | |
681 // =============================================================================== | |
682 _Bool dive1_check_deco(void) | |
683 { | |
684 // gGF_value is set in call routine; | |
685 // internes Backup! | |
686 | |
687 // calc like in deco | |
688 float ceiling; | |
689 float ceilingOther; // new hw 160614 | |
690 | |
691 ceiling = tissue_tolerance(); | |
692 ambient_bar_to_deco_stop_depth_bar(ceiling); // this will set gStop.depth :-) (and gStop.id) | |
693 | |
694 // set the base for all upcoming parameters | |
695 ceilingOther = gStop.depth + gSurface_pressure_bar; | |
696 | |
697 // modify parameters if there is ascend or parameter fine adjustment | |
698 if(ceilingOther < (gPressure - PRESSURE_150_CM)) // more than 1.5 meter below ceiling | |
699 { | |
700 // ascend within 10 mtr to GF_low // speed 12 mtr/min -> 50 sec / 10 mtr; 15 sec / 3 mtr. | |
701 while(((gPressure - PRESSURE_TEN_METER ) > gSurface_pressure_bar) && (ceiling < (gPressure - PRESSURE_TEN_METER))) | |
702 { | |
703 ascend_with_all_gaschanges(PRESSURE_TEN_METER); | |
704 ceiling = tissue_tolerance(); | |
705 } | |
706 while(((gPressure - PRESSURE_THREE_METER )> gSurface_pressure_bar) && (ceiling < gPressure)) | |
707 { | |
708 ascend_with_all_gaschanges(PRESSURE_THREE_METER); | |
709 ceiling = tissue_tolerance(); | |
710 } | |
711 } | |
712 if(ceiling <= gSurface_pressure_bar) | |
713 return false; | |
714 else | |
715 return true; | |
716 } | |
717 | |
718 | |
719 void buehlmann_ceiling_calculator(SLifeData* pLifeData, SDiveSettings * pDiveSettings, SDecoinfo * pDecoInfo) | |
720 { | |
721 float gf_low; | |
722 float gf_high; | |
723 float gf_delta; | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
724 float dv_gf_low_stop_meter; |
38 | 725 _Bool test_result; |
726 float next_gf_value; | |
727 float next_pressure_absolute; | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
728 float depth_in_meter; |
38 | 729 |
730 gf_low = pDiveSettings->gf_low; | |
731 gf_high = pDiveSettings->gf_high; | |
732 | |
733 dv_gf_low_stop_meter = (int)((pDiveSettings->internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero - pLifeData->pressure_surface_bar) * 10); | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
734 |
38 | 735 if(dv_gf_low_stop_meter < 1) |
736 { | |
737 next_gf_value = gf_high; // fix hw 161024 | |
738 gf_delta = 0; | |
739 } | |
740 else | |
741 { | |
742 next_gf_value = gf_high; | |
743 gf_delta = gf_high - gf_low; | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
744 gf_delta /= (dv_gf_low_stop_meter * 10); // gf_delta is delta for 10 cm !! |
38 | 745 } |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
746 |
38 | 747 depth_in_meter = 0; |
748 next_pressure_absolute = pLifeData->pressure_surface_bar; | |
749 | |
750 memcpy(gTissue_nitrogen_bar, pLifeData->tissue_nitrogen_bar, (4*16)); | |
751 memcpy(gTissue_helium_bar, pLifeData->tissue_helium_bar, (4*16)); | |
752 gGF_value = next_gf_value / 100.0f; | |
753 // | |
754 test_result = buehlmann_tissue_test_tolerance(next_pressure_absolute); | |
755 // | |
756 while(!test_result && depth_in_meter < 200) | |
757 { | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
758 depth_in_meter += 0.1; |
38 | 759 next_gf_value = fmaxf(gf_low, next_gf_value - gf_delta); |
760 gGF_value = next_gf_value / 100.0f; | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
761 next_pressure_absolute += 0.01f; // 0.1 meter down |
38 | 762 test_result = buehlmann_tissue_test_tolerance(next_pressure_absolute); |
763 } | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
764 |
38 | 765 if(test_result) |
766 { | |
767 pDecoInfo->output_ceiling_meter = depth_in_meter; | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
768 |
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
769 if(depth_in_meter >= 0) |
38 | 770 { |
771 for(int i = 0; i < 10; i++) | |
772 { | |
773 next_gf_value += gf_delta/10.0f; | |
774 gGF_value = next_gf_value / 100.0f; | |
775 next_pressure_absolute -= 0.01f; // 0.1 meter up | |
776 if(!buehlmann_tissue_test_tolerance(next_pressure_absolute)) | |
777 { | |
778 pDecoInfo->output_ceiling_meter -= ((float)i)/10.0f; | |
779 break; | |
780 } | |
781 } | |
782 } | |
783 } | |
784 else | |
785 { | |
786 pDecoInfo->output_ceiling_meter = 999; | |
787 } | |
788 } | |
789 | |
246
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
790 (??) |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
791 (??)void buehlmann_super_saturation_calculator(SLifeData* pLifeData, SDiveSettings * pDiveSettings, SDecoinfo * pDecoInfo) |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
792 (??){ |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
793 (??) float temp_tissue; |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
794 (??) float limit; |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
795 (??) float pres_respiration; |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
796 (??) float gf = 0; |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
797 (??) |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
798 (??) limit = tissue_tolerance_without_gf_correction(&temp_tissue); |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
799 (??) pres_respiration = pLifeData->pressure_ambient_bar; |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
800 (??) |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
801 (??) if( temp_tissue > pres_respiration ) |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
802 (??) { |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
803 (??) gf = (pres_respiration - temp_tissue) / (limit - temp_tissue); |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
804 (??) } |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
805 (??) |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
806 (??) pDecoInfo->super_saturation = gf; |
ff0d23625cd5
feature: replace Relative GF by saturation, computational only
Jan Mulder <jlmulder@xs4all.nl>
parents:
224
diff
changeset
|
807 (??)} |