Mercurial > public > ostc4
annotate Discovery/Src/buehlmann.c @ 224:ceecabfddb57 div-fixes-3
Bugfix, deco: fix 2 (small) problems with calculated ceiling
This fixes 1 trivial, and 1 not really trivial bug in the calculation
of the ceiling. When simulating a bounce dive to 80m, things become
clear (tried this on a CCR dive, fixed setpoint 1.2bar, about 15 minutes
of bottom time). Closely watch the behavior of the ceiling data. At some
point during the ascent, the ceiling begins to decrease in 10cm steps.
Then suddenly (while still ascending), the ceiling increases again with 1m,
does not change for some time, and then suddenly steps 1.1m less deep.
While not very relevant to real deco diving, it is simply wrong.
The reason for this is subtle. The algorithm used to find the ceiling
is a sort of linear search, stepping down a meter, overshoot the depth, and
search back in 10cm steps. It seems some numerical instability. Fixing
this, was a bit more computational intensive search by stepping up down in
equal steps of 10cm. But, I'm pretty sure that things can be speeded up here, as a
ceiling does not change fast, so it should be not that difficult to limit
the search space, or use a binary search algorithm instead.
The trivial second problem fixed, is that the ceiling ends at the surface
and not at 1m depth. This small issue became visible after changing the step
down size above.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
author | Jan Mulder <jlmulder@xs4all.nl> |
---|---|
date | Sun, 31 Mar 2019 19:35:51 +0200 |
parents | b7689d9e888a |
children | ff0d23625cd5 |
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 | |
409 // hw 161121 for relative gradient | |
410 float tissue_tolerance_without_gf_correction(float *tissue_inertgas_saturation_output) | |
411 { | |
412 float tissue_inertgas_saturation; | |
413 float inertgas_a; | |
414 float inertgas_b; | |
415 float ceiling; | |
416 float global_ceiling; | |
417 int ci; | |
418 | |
419 global_ceiling = -1; | |
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 // | |
427 inertgas_a = buehlmann_N2_a[ci]; | |
428 inertgas_b = buehlmann_N2_b[ci]; | |
429 } | |
430 else | |
431 { | |
432 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci]; | |
433 // | |
434 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
435 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
436 } | |
437 // | |
438 ceiling = inertgas_b * ( tissue_inertgas_saturation - inertgas_a ); | |
439 if(ceiling > global_ceiling) | |
440 { | |
441 global_ceiling = ceiling; | |
442 if(tissue_inertgas_saturation_output) | |
443 { | |
444 *tissue_inertgas_saturation_output = tissue_inertgas_saturation; | |
445 } | |
446 } | |
447 } | |
448 return global_ceiling; | |
449 } | |
450 | |
451 | |
452 uint8_t buehlmann_tissue_test_tolerance(float depth_in_bar_absolute) | |
453 { | |
454 float tissue_inertgas_saturation; | |
455 float inertgas_a; | |
456 float inertgas_b; | |
457 float inertgas_tolerance; | |
458 float gf_minus_1; | |
459 | |
460 gf_minus_1 = gGF_value - 1.0f; | |
461 | |
462 for (int ci = 0; ci < 16; ci++) | |
463 { | |
464 if(gTissue_helium_bar[ci] == 0) | |
465 { | |
466 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci]; | |
467 // | |
468 inertgas_a = buehlmann_N2_a[ci]; | |
469 inertgas_b = buehlmann_N2_b[ci]; | |
470 } | |
471 else | |
472 { | |
473 tissue_inertgas_saturation = gTissue_nitrogen_bar[ci] + gTissue_helium_bar[ci]; | |
474 // | |
475 inertgas_a = ( ( buehlmann_N2_a[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_a[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
476 inertgas_b = ( ( buehlmann_N2_b[ci] * gTissue_nitrogen_bar[ci]) + ( buehlmann_He_b[ci] * gTissue_helium_bar[ci]) ) / tissue_inertgas_saturation; | |
477 } | |
478 // | |
479 inertgas_tolerance = ( (gGF_value / inertgas_b - gf_minus_1) * depth_in_bar_absolute ) + ( gGF_value * inertgas_a ); | |
480 // | |
481 if(inertgas_tolerance < tissue_inertgas_saturation) | |
482 return 0; | |
483 } | |
484 return 1; | |
485 } | |
486 | |
487 | |
488 void ambient_bar_to_deco_stop_depth_bar(float ceiling) | |
489 { | |
490 int i; | |
491 | |
492 ceiling -= gSurface_pressure_bar; | |
493 | |
494 if(ceiling <= 0) | |
495 { | |
496 gStop.depth = pBuDiveSettings->last_stop_depth_bar; | |
497 gStop.id = 0; | |
498 return; | |
499 } | |
500 | |
501 | |
502 //for(int i = 1; i < 10; i++) | |
503 | |
504 if((ceiling - pBuDiveSettings->last_stop_depth_bar) <= 0) | |
505 { | |
506 gStop.depth = pBuDiveSettings->last_stop_depth_bar; | |
507 gStop.id = 0; | |
508 return; | |
509 } | |
510 | |
511 gStop.depth = pBuDiveSettings->input_second_to_last_stop_depth_bar; | |
512 gStop.id = 1; | |
513 ceiling -= pBuDiveSettings->input_second_to_last_stop_depth_bar; | |
514 | |
515 if(ceiling <= 0) | |
516 return; | |
517 | |
518 for(i = 1; i < (DECOINFO_STRUCT_MAX_STOPS - 2); i++) | |
519 { | |
520 ceiling -= pBuDiveSettings->input_next_stop_increment_depth_bar; | |
521 if(ceiling <= 0) | |
522 break; | |
523 } | |
524 gStop.depth += i * pBuDiveSettings->input_next_stop_increment_depth_bar; | |
525 gStop.id += i; | |
526 return; | |
527 } | |
528 | |
529 float next_stop_depth_input_is_actual_stop_id(int actual_id) | |
530 { | |
531 if(actual_id == 0) | |
532 return 0; | |
533 | |
534 if(actual_id == 1) | |
535 return pBuDiveSettings->last_stop_depth_bar; | |
536 | |
537 actual_id -= 2; | |
538 return pBuDiveSettings->input_second_to_last_stop_depth_bar + (actual_id * pBuDiveSettings->input_next_stop_increment_depth_bar); | |
539 } | |
540 | |
541 int ascend_with_all_gaschanges(float pressure_decrease) | |
542 { | |
543 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
|
544 int time_for_ascend = 0; |
38 | 545 int seconds; |
546 int i; | |
547 | |
548 ascendrate_in_seconds_for_one_bar = 60 * 10 / pBuDiveSettings->ascentRate_meterperminute; | |
549 | |
550 if(fabsf(gPressure - gSurface_pressure_bar) < PRESSURE_HALF_METER) | |
551 { | |
552 gPressure = gSurface_pressure_bar; | |
553 return 0; | |
554 } | |
555 | |
556 pressureTop = gPressure - pressure_decrease; | |
557 if( gSurface_pressure_bar > pressureTop) | |
558 pressureTop = gSurface_pressure_bar; | |
559 pressureBottom = gPressure; | |
560 seconds = 0; | |
561 do{ | |
562 pressureTop_tmp = pressureTop; | |
563 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++) | |
564 { | |
565 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) | |
566 break; | |
567 pressureChange = gSurface_pressure_bar + ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero) / 10; | |
568 if(pressureBottom <= pressureChange) | |
569 { | |
570 gGas_id = i; | |
571 } | |
572 else | |
573 { | |
574 break; | |
575 } | |
576 | |
577 } | |
578 for(i = gGas_id + 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++) | |
579 { | |
580 if(pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero == 0) | |
581 break; | |
582 pressureChange = gSurface_pressure_bar + ((float)pBuDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero)/ 10; | |
583 if((pressureChange < pressureBottom) && (pressureChange > pressureTop)) | |
584 { | |
585 pressureTop_tmp = pressureChange; | |
586 } | |
587 } | |
588 pressure_difference = pressureBottom - pressureTop_tmp; | |
589 if(pressure_difference > 0.0001f) | |
590 { | |
591 time_for_ascend = (int)ceilf(pressure_difference * ascendrate_in_seconds_for_one_bar); | |
592 decom_tissues_exposure_stage_schreiner(time_for_ascend, &pBuDiveSettings->decogaslist[gGas_id], | |
593 pressureBottom, pressureTop_tmp, gTissue_nitrogen_bar, gTissue_helium_bar); | |
594 decom_oxygen_calculate_cns_stage_SchreinerStyle(time_for_ascend,&pBuDiveSettings->decogaslist[gGas_id], | |
595 pressureBottom, pressureTop_tmp, &gCNS); | |
596 } | |
597 pressureBottom = pressureTop_tmp; | |
598 seconds += time_for_ascend; | |
599 }while(pressureTop_tmp > pressureTop); | |
600 gPressure = pressureTop; | |
601 return seconds; | |
602 } | |
603 | |
604 | |
605 float get_gf_at_pressure(float pressure) | |
606 { | |
607 float gfSteigung = 0.0f; | |
608 | |
609 if(gGF_low_depth_bar < 0) | |
610 gGF_low_depth_bar = PRESSURE_THREE_METER; // just to prevent erratic behaviour if variable is not set | |
611 | |
612 gfSteigung = ((float)(pBuDiveSettings->gf_high - pBuDiveSettings->gf_low))/ gGF_low_depth_bar; | |
613 | |
614 | |
615 if((pressure - gSurface_pressure_bar) <= PRESSURE_HALF_METER) | |
616 return ((float)pBuDiveSettings->gf_high) / 100.0f; | |
617 | |
618 if(pressure >= gSurface_pressure_bar + gGF_low_depth_bar) | |
619 return ((float)pBuDiveSettings->gf_low) / 100.0f; | |
620 | |
621 return (pBuDiveSettings->gf_high - gfSteigung * (pressure - gSurface_pressure_bar) )/ 100.0f; | |
622 } | |
623 | |
624 | |
625 void buehlmann_calc_ndl(void) | |
626 { | |
627 float local_tissue_nitrogen_bar[16]; | |
628 float local_tissue_helium_bar[16]; | |
629 int i; | |
630 | |
631 gNDL = 0; | |
632 //Check ndl always use gHigh | |
633 gGF_value = ((float)pBuDiveSettings->gf_high) / 100.0f; | |
634 //10 minutes steps | |
635 while(gNDL < (300 * 60)) | |
636 { | |
637 memcpy(local_tissue_nitrogen_bar, gTissue_nitrogen_bar, (4*16)); | |
638 memcpy(local_tissue_helium_bar, gTissue_helium_bar, (4*16)); | |
639 // | |
640 gNDL += 600; | |
641 decom_tissues_exposure2(600, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar); | |
642 decom_oxygen_calculate_cns_exposure(600,&pBuDiveSettings->decogaslist[gGas_id],gPressure,&gCNS); | |
643 //tissues_exposure_at_gPressure_seconds(600); | |
644 buehlmann_backup_and_restore(true); | |
645 if(dive1_check_deco() == true) | |
646 { | |
647 buehlmann_backup_and_restore(false); | |
648 break; | |
649 } | |
650 buehlmann_backup_and_restore(false); | |
651 } | |
652 | |
653 if(gNDL < (300 * 60)) | |
654 gNDL -= 600; | |
655 | |
656 if(gNDL > (150 * 60)) | |
657 return; | |
658 | |
659 // refine | |
660 memcpy(gTissue_nitrogen_bar, local_tissue_nitrogen_bar, (4*16)); | |
661 memcpy(gTissue_helium_bar, local_tissue_helium_bar, (4*16)); | |
662 | |
663 //One minutes step | |
664 for(i = 0; i < 20; i++) | |
665 { | |
666 gNDL += 60; | |
667 //tissues_exposure_at_gPressure_seconds(60); | |
668 decom_tissues_exposure2(60, &pBuDiveSettings->decogaslist[gGas_id], gPressure,gTissue_nitrogen_bar,gTissue_helium_bar); | |
669 decom_oxygen_calculate_cns_exposure(60,&pBuDiveSettings->decogaslist[gGas_id],gPressure,&gCNS); | |
670 buehlmann_backup_and_restore(true); | |
671 if(dive1_check_deco() == true) | |
672 break; | |
673 buehlmann_backup_and_restore(false); | |
674 } | |
675 //gNDL -= 60; | |
676 return; | |
677 } | |
678 | |
679 | |
680 // =============================================================================== | |
681 // dive1_check_deco | |
682 /// @brief for NDL calculations | |
683 /// 160614 using ceilingOther and not ceiling | |
684 // =============================================================================== | |
685 _Bool dive1_check_deco(void) | |
686 { | |
687 // gGF_value is set in call routine; | |
688 // internes Backup! | |
689 | |
690 // calc like in deco | |
691 float ceiling; | |
692 float ceilingOther; // new hw 160614 | |
693 | |
694 ceiling = tissue_tolerance(); | |
695 ambient_bar_to_deco_stop_depth_bar(ceiling); // this will set gStop.depth :-) (and gStop.id) | |
696 | |
697 // set the base for all upcoming parameters | |
698 ceilingOther = gStop.depth + gSurface_pressure_bar; | |
699 | |
700 // modify parameters if there is ascend or parameter fine adjustment | |
701 if(ceilingOther < (gPressure - PRESSURE_150_CM)) // more than 1.5 meter below ceiling | |
702 { | |
703 // ascend within 10 mtr to GF_low // speed 12 mtr/min -> 50 sec / 10 mtr; 15 sec / 3 mtr. | |
704 while(((gPressure - PRESSURE_TEN_METER ) > gSurface_pressure_bar) && (ceiling < (gPressure - PRESSURE_TEN_METER))) | |
705 { | |
706 ascend_with_all_gaschanges(PRESSURE_TEN_METER); | |
707 ceiling = tissue_tolerance(); | |
708 } | |
709 while(((gPressure - PRESSURE_THREE_METER )> gSurface_pressure_bar) && (ceiling < gPressure)) | |
710 { | |
711 ascend_with_all_gaschanges(PRESSURE_THREE_METER); | |
712 ceiling = tissue_tolerance(); | |
713 } | |
714 } | |
715 if(ceiling <= gSurface_pressure_bar) | |
716 return false; | |
717 else | |
718 return true; | |
719 } | |
720 | |
721 | |
722 void buehlmann_ceiling_calculator(SLifeData* pLifeData, SDiveSettings * pDiveSettings, SDecoinfo * pDecoInfo) | |
723 { | |
724 float gf_low; | |
725 float gf_high; | |
726 float gf_delta; | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
727 float dv_gf_low_stop_meter; |
38 | 728 _Bool test_result; |
729 float next_gf_value; | |
730 float next_pressure_absolute; | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
731 float depth_in_meter; |
38 | 732 |
733 gf_low = pDiveSettings->gf_low; | |
734 gf_high = pDiveSettings->gf_high; | |
735 | |
736 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
|
737 |
38 | 738 if(dv_gf_low_stop_meter < 1) |
739 { | |
740 next_gf_value = gf_high; // fix hw 161024 | |
741 gf_delta = 0; | |
742 } | |
743 else | |
744 { | |
745 next_gf_value = gf_high; | |
746 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
|
747 gf_delta /= (dv_gf_low_stop_meter * 10); // gf_delta is delta for 10 cm !! |
38 | 748 } |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
749 |
38 | 750 depth_in_meter = 0; |
751 next_pressure_absolute = pLifeData->pressure_surface_bar; | |
752 | |
753 memcpy(gTissue_nitrogen_bar, pLifeData->tissue_nitrogen_bar, (4*16)); | |
754 memcpy(gTissue_helium_bar, pLifeData->tissue_helium_bar, (4*16)); | |
755 gGF_value = next_gf_value / 100.0f; | |
756 // | |
757 test_result = buehlmann_tissue_test_tolerance(next_pressure_absolute); | |
758 // | |
759 while(!test_result && depth_in_meter < 200) | |
760 { | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
761 depth_in_meter += 0.1; |
38 | 762 next_gf_value = fmaxf(gf_low, next_gf_value - gf_delta); |
763 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
|
764 next_pressure_absolute += 0.01f; // 0.1 meter down |
38 | 765 test_result = buehlmann_tissue_test_tolerance(next_pressure_absolute); |
766 } | |
224
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
767 |
38 | 768 if(test_result) |
769 { | |
770 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
|
771 |
ceecabfddb57
Bugfix, deco: fix 2 (small) problems with calculated ceiling
Jan Mulder <jlmulder@xs4all.nl>
parents:
130
diff
changeset
|
772 if(depth_in_meter >= 0) |
38 | 773 { |
774 for(int i = 0; i < 10; i++) | |
775 { | |
776 next_gf_value += gf_delta/10.0f; | |
777 gGF_value = next_gf_value / 100.0f; | |
778 next_pressure_absolute -= 0.01f; // 0.1 meter up | |
779 if(!buehlmann_tissue_test_tolerance(next_pressure_absolute)) | |
780 { | |
781 pDecoInfo->output_ceiling_meter -= ((float)i)/10.0f; | |
782 break; | |
783 } | |
784 } | |
785 } | |
786 } | |
787 else | |
788 { | |
789 pDecoInfo->output_ceiling_meter = 999; | |
790 } | |
791 } | |
792 | |
793 | |
794 void buehlmann_relative_gradient_calculator(SLifeData* pLifeData, SDiveSettings * pDiveSettings, SDecoinfo * pDecoInfo) | |
795 { | |
796 float gf_low; | |
797 float gf_high; | |
798 float gf_delta; | |
799 int dv_gf_low_stop_meter; | |
800 | |
801 float rgf; // relative gradient factor by hwOS p2_deco.c | |
802 float temp_tissue; | |
803 float limit; | |
804 float pres_respiration; | |
805 float gf; | |
806 | |
807 gf_low = pDiveSettings->gf_low; | |
808 gf_high = pDiveSettings->gf_high; | |
809 | |
810 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); | |
811 | |
812 if(dv_gf_low_stop_meter < 1) | |
813 { | |
814 gf_delta = 0; | |
815 } | |
816 else | |
817 { | |
818 gf_delta = gf_high - gf_low; | |
819 gf_delta /= dv_gf_low_stop_meter; // gf_delta is delta for each meter now!! | |
820 } | |
821 | |
822 | |
823 limit = tissue_tolerance_without_gf_correction(&temp_tissue); | |
824 pres_respiration = pLifeData->pressure_ambient_bar; | |
825 | |
826 if( temp_tissue <= pres_respiration ) | |
827 { | |
828 gf = 0.0; | |
829 } | |
830 else | |
831 { | |
832 gf = (temp_tissue - pres_respiration) | |
833 / (temp_tissue - limit) | |
834 * 100.0f; | |
835 } | |
836 | |
837 if(dv_gf_low_stop_meter < 1) | |
838 { | |
839 rgf = gf_high; | |
840 } | |
841 else | |
842 { | |
843 float temp1 = dv_gf_low_stop_meter; | |
844 float temp2 = pLifeData->depth_meter; | |
845 | |
846 if (temp2 <= 0) | |
847 rgf = gf_high; | |
848 else if (temp2 >= temp1) | |
849 rgf = gf_low; | |
850 else | |
851 rgf = gf_low + (temp1 - temp2)*gf_delta; | |
852 } | |
853 | |
854 rgf = gf / rgf; | |
855 | |
856 // avoid discussions about values > 100 below next deco stop | |
857 if((rgf > 1.0f) && (pLifeData->depth_meter >= pDecoInfo->output_ceiling_meter)) | |
858 rgf = 1.0f; | |
859 | |
860 pDecoInfo->output_relative_gradient = rgf; | |
861 } |