Mercurial > public > ostc4
annotate Discovery/Src/vpm.c @ 233:9f0efc4df01e div-fixes-4-1
cleanup, bugfix: do not exit simulator on 5h dive time
The code cleaned up here caused me some confusion as over 5h dives
where silently aborted in the simulator. Ok, not many uses will
try to simulate 5h dives, but its a useless limitation.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
author | Jan Mulder <jlmulder@xs4all.nl> |
---|---|
date | Fri, 05 Apr 2019 09:12:04 +0200 |
parents | e1d66bc78f9a |
children | 3949781096d4 |
rev | line source |
---|---|
38 | 1 /////////////////////////////////////////////////////////////////////////////// |
2 /// -*- coding: UTF-8 -*- | |
3 /// | |
4 /// \file Discovery/Src/vpm.c | |
5 /// \brief critical_volume comment by hw | |
6 /// \author Heinrichs Weikamp, Erik C. Baker | |
7 /// \date 19-April-2014 | |
8 /// | |
9 /// \details | |
10 /// | |
11 /// $Id$ | |
12 /////////////////////////////////////////////////////////////////////////////// | |
13 /// \par Copyright (c) 2014-2018 Heinrichs Weikamp gmbh | |
14 /// | |
15 /// This program is free software: you can redistribute it and/or modify | |
16 /// it under the terms of the GNU General Public License as published by | |
17 /// the Free Software Foundation, either version 3 of the License, or | |
18 /// (at your option) any later version. | |
19 /// | |
20 /// This program is distributed in the hope that it will be useful, | |
21 /// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
22 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
23 /// GNU General Public License for more details. | |
24 /// | |
25 /// You should have received a copy of the GNU General Public License | |
26 /// along with this program. If not, see <http://www.gnu.org/licenses/>. | |
27 ////////////////////////////////////////////////////////////////////////////// | |
28 /// \par Varying Permeability Model (VPM) Decompression Program in c (converted from FORTRAN) | |
29 /// | |
30 /// Author: Erik C. Baker | |
31 /// | |
32 /// "DISTRIBUTE FREELY - CREDIT THE AUTHORS" | |
33 /// | |
34 /// This program extends the 1986 VPM algorithm (Yount & Hoffman) to include | |
35 /// mixed gas, repetitive, and altitude diving. Developments to the algorithm | |
36 /// were made by David E. Yount, Eric B. Maiken, and Erik C. Baker over a | |
37 /// period from 1999 to 2001. This work is dedicated in remembrance of | |
38 /// Professor David E. Yount who passed away on April 27, 2000. | |
39 /// | |
40 /// Notes: | |
41 /// 1. This program uses the sixteen (16) half-time compartments of the | |
42 /// Buhlmann ZH-L16 model. The optional Compartment 1b is used here with | |
43 /// half-times of 1.88 minutes for helium and 5.0 minutes for nitrogen. | |
44 /// | |
45 /// 2. This program uses various DEC, IBM, and Microsoft extensions which | |
46 /// may not be supported by all FORTRAN compilers. Comments are made with | |
47 /// a capital "C" in the first column or an exclamation point "!" placed | |
48 /// in a line after code. An asterisk "*" in column 6 is a continuation | |
49 /// of the previous line. All code, except for line numbers, starts in | |
50 /// column 7. | |
51 /// | |
52 /// 3. Comments and suggestions for improvements are welcome. Please | |
53 /// respond by e-mail to: EBaker@se.aeieng.com | |
54 /// | |
55 /// Acknowledgment: Thanks to Kurt Spaugh for recommendations on how to clean | |
56 /// up the code. | |
57 /// =============================================================================== | |
58 /// Converted to vpmdeco.c using f2c; R.McGinnis (CABER Swe) 5/01 | |
59 /// =============================================================================== | |
60 /// | |
61 /// ************************ Heirichs Weipkamp ************************************** | |
62 /// | |
63 /// The original Yount & Baker code has been adjusted for real life calculation. | |
64 /// | |
65 /// 1) The original main function has been split in several functions | |
66 /// | |
67 /// 2) When the deco zone is reached (while ascending) the gradient factors are kept fix | |
68 /// and critical volume algorithm is switched of. maxfirststopdepth is kept fix | |
69 /// to make shure Boeyls Law algorithm works correctly | |
70 /// | |
71 /// 4) gas_loadings_ascent_descend heeds all gaschanges and CCR support has been added | |
72 /// | |
73 | |
74 #include <stdio.h> | |
75 #include <stdlib.h> | |
76 #include <string.h> | |
77 #include <math.h> | |
78 #include <time.h> | |
79 | |
80 //#include "compiler.h" | |
81 //#include "sdramc.h" | |
82 #include "vpm.h" | |
83 //#include "buehlmann.h" | |
84 | |
85 #include "decom.h" | |
86 | |
87 //#include "decompression.h" | |
88 //#include "taskmanagement\tissue_calls.h" | |
89 #define true 1 | |
90 #define false 0 | |
91 | |
92 #define GAS_N2 0 | |
93 #define GAS_HE 1 | |
94 /* temp vars to simplify UNFMTLISTs */ | |
95 float fO2, fHe, fN2; | |
96 float dc, rc, ssc; | |
97 short mc; | |
98 | |
99 const _Bool buehlmannSafety = true; | |
100 /* Common Block Declarations */ | |
101 | |
102 extern const float SURFACE_TENSION_GAMMA; //!Adj. Range: 0.015 to 0.065 N/m | |
103 extern const float SKIN_COMPRESSION_GAMMAC; //!Adj. Range: 0.160 to 0.290 N/m | |
104 extern const float UNITS_FACTOR; | |
105 extern const float WATER_VAPOR_PRESSURE; // (Schreiner value) based on respiratory quotien | |
106 extern const float CRIT_VOLUME_PARAMETER_LAMBDA; //!Adj. Range: 6500 to 8300 fsw-min | |
107 extern const float GRADIENT_ONSET_OF_IMPERM_ATM; //!Adj. Range: 5.0 to 10.0 atm | |
108 extern const float REGENERATION_TIME_CONSTANT; //!Adj. Range: 10080 to 51840 min | |
109 extern const float PRESSURE_OTHER_GASES_MMHG; //!Constant value for PO2 up to 2 atm | |
110 extern const float CONSTANT_PRESSURE_OTHER_GASES; // PRESSURE_OTHER_GASES_MMHG / 760. * UNITS_FACTOR; | |
111 | |
112 extern const float HELIUM_TIME_CONSTANT[]; | |
113 extern const float NITROGEN_TIME_CONSTANT[]; | |
114 | |
115 float minimum_deco_stop_time; | |
116 float run_time, run_time_first_stop; | |
117 float segment_time; | |
118 short mix_number; | |
119 float barometric_pressure; | |
120 _Bool altitude_dive_algorithm_off; | |
121 _Bool units_equal_fsw, units_equal_msw; | |
122 | |
123 /* by hw 11.06.2015 to allow */ | |
124 float gCNS_VPM; | |
125 | |
126 float helium_pressure[16], nitrogen_pressure[16]; | |
127 //float helium_pressure_crush[16], nitrogen_pressure_crush[16]; | |
128 //float fraction_helium[MAX_GASMIXES + EXTRA_GASMIXES], fraction_nitrogen[MAX_GASMIXES + EXTRA_GASMIXES]; | |
129 //float initial_critical_radius_he[16], initial_critical_radius_n2[16]; | |
130 //float adjusted_critical_radius_he[16], | |
131 //adjusted_critical_radius_n2[16]; | |
132 //float max_crushing_pressure_he[16], | |
133 //max_crushing_pressure_n2[16]; | |
134 float surface_phase_volume_time[16]; | |
135 //float max_actual_gradient[16]; | |
136 //float amb_pressure_onset_of_imperm[16], | |
137 //gas_tension_onset_of_imperm[16]; | |
138 //float initial_helium_pressure_global[16], | |
139 //initial_nitrogen_pressure_global[16]; | |
140 float regenerated_radius_he[16], | |
141 regenerated_radius_n2[16]; | |
142 //float adjusted_crushing_pressure_he[16], | |
143 //adjusted_crushing_pressure_n2[16]; | |
144 float allowable_gradient_he[16], | |
145 allowable_gradient_n2[16]; | |
146 //float initial_allowable_gradient_he[16], | |
147 //initial_allowable_gradient_n2[16]; | |
148 | |
149 //_Bool deco_zone_reached; | |
150 _Bool critical_volume_algorithm_off; | |
151 float max_first_stop_depth; | |
152 float max_deco_ceiling_depth; | |
153 long vpm_time_calc_begin = 0; | |
154 //Boylslaw compensation | |
155 float deco_gradient_he[16]; | |
156 float deco_gradient_n2[16]; | |
157 int last_nullzeit; | |
158 int vpm_calc_what; | |
159 int count_critical_volume_iteration; | |
160 short number_of_changes; | |
161 float depth_change[11]; | |
162 float step_size_change[11]; | |
163 float rate_change[11]; | |
164 short mix_change[11]; | |
165 | |
166 const _Bool vpm_b = true; | |
167 | |
168 //extern | |
169 /*extern float tissue_N2_saturation[4][16]; | |
170 extern float tissue_He_saturation[4][16]; | |
171 extern long dv_divetime; | |
172 extern dive_data_t dive_data; | |
173 extern int dive_ambient_pressure_mbar; | |
174 extern long dv_seconds_since_last_dive; | |
175 extern int tts[4];*/ | |
176 extern const float float_buehlmann_N2_factor_expositon_20_seconds[]; | |
177 extern const float float_buehlmann_He_factor_expositon_20_seconds[]; | |
178 extern const float float_buehlmann_N2_factor_expositon_one_minute[]; | |
179 extern const float float_buehlmann_He_factor_expositon_one_minute[]; | |
180 extern const float float_buehlmann_N2_factor_expositon_five_minutes[]; | |
181 extern const float float_buehlmann_He_factor_expositon_five_minutes[]; | |
182 extern const float float_buehlmann_N2_factor_expositon_one_hour[]; | |
183 extern const float float_buehlmann_He_factor_expositon_one_hour[]; | |
184 | |
185 //extern buehlmann_configuration_t buehlmann_config; | |
186 | |
187 extern unsigned char CCR_mode; //0x100 // by tissue_calls.c // uchar | |
188 | |
189 //extern gaschange2_t gaschange_CCR_backup[2][BUEHLMANN_STRUCT_MAX_GASES]; | |
190 | |
191 | |
192 float starting_ambient_pressure_global; | |
193 float ending_ambient_pressure_global; | |
194 float depth_start_of_deco_calc; | |
195 float depth_start_of_deco_zone; | |
196 float first_stop_depth; | |
197 float run_time_start_of_deco_zone; | |
198 | |
199 float r_nint(float *x); | |
200 float r_int(float *x); | |
201 _Bool repetitive_variables_not_valid = false; | |
202 _Bool nullzeit_unter60; | |
203 //enum VPM_CALC_STATUS{CALC_END,CALC_BEGIN,CALC_NULLZEIT }; | |
204 int vpm_calc_status; | |
205 _Bool buehlmann_wait_exceeded = false; | |
206 | |
207 SLifeData* pInput = NULL; | |
208 SVpm* pVpm = NULL; | |
209 SDecoinfo* pDecoInfo = NULL; | |
210 SDiveSettings* pDiveSettings = NULL; | |
211 float r_nint(float *x) | |
212 { | |
213 return( (*x)>=0 ? | |
214 floorf(*x + 0.5f) : -floorf(0.5f - *x) ); | |
215 } | |
216 | |
217 float r_int(float *x) | |
218 { | |
219 return( (*x>0) ? floorf(*x) : -floorf(- *x) ); | |
220 } | |
221 | |
222 /** private functions | |
223 */ | |
224 int onset_of_impermeability(float *starting_ambient_pressure, float *ending_ambient_pressure, float *rate, short *i); | |
225 int radius_root_finder (float *a, float *b, float *c,float *low_bound, float *high_bound, float *ending_radius); | |
226 int nuclear_regeneration(float *dive_time);// clock_(); | |
227 int calc_deco_ceiling(float *deco_ceiling_depth,_Bool fallowablw); | |
228 | |
229 int calc_barometric_pressure(float *altitude); | |
230 //extern /* Subroutine */ int vpm_repetitive_algorithm(); | |
231 //extern /* Subroutine */ int gas_loadings_surface_interval(); | |
232 int critical_volume(float *deco_phase_volume_time); ; | |
233 int calc_start_of_deco_zone(float *starting_depth, float *rate, float *depth_start_of_deco_zone); | |
234 | |
235 int calc_initial_allowable_gradient(void); | |
236 void decompression_stop(float *deco_stop_depth, float *step_size, _Bool final_deco_calculation); | |
237 int gas_loadings_ascent_descen(float* helium_pressure, float* nitrogen_pressure, float starting_depth,float ending_depth, float rate,_Bool check_gas_change); | |
238 | |
239 int calc_surface_phase_volume_time(void); | |
240 int calc_max_actual_gradient(float *deco_stop_depth); | |
241 int projected_ascent(float *starting_depth, float *rate, float *deco_stop_depth, float *step_size); | |
242 void vpm_calc_deco(void); | |
243 int vpm_calc_critcal_volume(_Bool begin,_Bool calc_nulltime); | |
244 int vpm_check_converged(_Bool calc_nulltime); | |
245 int vpm_calc_final_deco(_Bool begin); | |
246 void BOYLES_LAW_COMPENSATION (float* First_Stop_Depth,float * Deco_Stop_Depth,float* Step_Size); | |
247 int vpm_calc_nullzeit(void); | |
248 int vpm_repetitive_algorithm(float *surface_interval_time); | |
249 void vpm_init_1(void); | |
250 | |
251 void vpm_calc_deco_ceiling(void); | |
252 | |
253 //extern /* Subroutine */ int gas_loadings_constant_depth(); | |
254 //extern /* Subroutine */ int vpm_altitude_dive_algorithm(); | |
255 //extern /* Subroutine */ int calc_max_actual_gradient(), | |
256 //projected_ascent(); | |
257 | |
258 void ______X_X_X___________________________________________________________(void); | |
259 | |
260 //#define ARGGG | |
261 | |
262 void vpm_reset_variables(void) | |
263 { | |
264 repetitive_variables_not_valid = true; | |
265 } | |
266 | |
267 void vpm_init_1(void) | |
268 { | |
269 units_equal_msw = true; | |
270 units_equal_fsw = false; | |
271 altitude_dive_algorithm_off= true; //!Options: ON or OFF | |
272 minimum_deco_stop_time=1.0; //!Options: float positive number | |
273 critical_volume_algorithm_off= false; //!Options: ON or OFF | |
274 run_time = 0.; | |
275 //barometric_pressure = dive_data.surface * 10; | |
276 | |
277 //mix_number = dive_data.selected_gas + 1; | |
278 | |
279 max_first_stop_depth = 0; | |
280 max_deco_ceiling_depth = 0; | |
281 //deco_zone_reached = false; | |
282 depth_start_of_deco_calc = 0; | |
283 depth_start_of_deco_zone = 0; | |
284 first_stop_depth = 0; | |
285 run_time_start_of_deco_zone = 0; | |
286 | |
287 gCNS_VPM = 0; | |
288 } | |
289 | |
290 float vpm_get_CNS(void) | |
291 { | |
292 return gCNS_VPM; | |
293 } | |
294 | |
295 int vpm_calc(SLifeData* pINPUT, | |
296 SDiveSettings* pSettings, | |
297 SVpm* pVPM, | |
298 SDecoinfo* | |
299 pDECOINFO, | |
300 int calc_what) | |
301 { | |
302 vpm_init_1(); | |
303 //decom_CreateGasChangeList(pSettings, pINPUT); | |
304 vpm_calc_what = calc_what; | |
305 /**clear decoInfo*/ | |
306 pDECOINFO->output_time_to_surface_seconds = 0; | |
307 pDECOINFO->output_ndl_seconds = 0; | |
308 pDECOINFO->output_ceiling_meter = 0; | |
309 pDECOINFO->output_relative_gradient = 0; | |
310 uint8_t tmp_calc_status; | |
311 for(int i=0;i<DECOINFO_STRUCT_MAX_STOPS;i++) | |
312 { | |
313 pDECOINFO->output_stop_length_seconds[i] = 0; | |
314 } | |
315 | |
316 if(pINPUT->dive_time_seconds < 10) | |
317 { | |
318 vpm_calc_status = CALC_NULLZEIT; | |
319 return vpm_calc_status; | |
320 } | |
321 pVpm = pVPM; | |
322 pInput = pINPUT; | |
323 pDecoInfo = pDECOINFO; | |
324 pDiveSettings = pSettings; | |
325 | |
326 if(vpm_calc_status == CALC_NULLZEIT) | |
327 { | |
328 tmp_calc_status = vpm_calc_nullzeit(); | |
329 } | |
330 else | |
331 { | |
332 tmp_calc_status = CALC_BEGIN; | |
333 } | |
334 //Normal Deco calculation | |
335 if(tmp_calc_status != CALC_NULLZEIT) | |
336 { | |
337 max_first_stop_depth = pVpm->max_first_stop_depth_save; | |
338 run_time_start_of_deco_zone = pVpm->run_time_start_of_deco_zone_save; | |
339 depth_start_of_deco_zone = pVpm->depth_start_of_deco_zone_save; | |
340 for (int i = 0; i < 16; ++i) { | |
341 helium_pressure[i] = pInput->tissue_helium_bar[i] * 10; | |
342 nitrogen_pressure[i] = pInput->tissue_nitrogen_bar[i] * 10; | |
343 } | |
344 vpm_calc_deco(); | |
345 tmp_calc_status = vpm_calc_critcal_volume(true,false); | |
346 if(vpm_calc_what == DECOSTOPS) | |
347 { | |
348 pVpm->max_first_stop_depth_save = max_first_stop_depth; | |
349 pVpm->run_time_start_of_deco_zone_save = run_time_start_of_deco_zone; | |
350 pVpm->depth_start_of_deco_zone_save = depth_start_of_deco_zone; | |
351 } | |
352 } | |
353 | |
354 //Only Decostops not futute stops | |
355 if(vpm_calc_what == DECOSTOPS) | |
356 vpm_calc_status = tmp_calc_status; | |
357 return vpm_calc_status; | |
358 } | |
359 | |
360 void vpm_saturation_after_ascent(SLifeData* input) | |
361 { | |
362 int i = 0; | |
363 for (i = 0; i < 16; ++i) { | |
364 pInput->tissue_helium_bar[i] = helium_pressure[i] / 10; | |
365 pInput->tissue_nitrogen_bar[i] = nitrogen_pressure[i] / 10; | |
366 } | |
367 pInput->pressure_ambient_bar = pInput->pressure_surface_bar; | |
368 } | |
369 /* =============================================================================== */ | |
370 /* NOTE ABOUT PRESSURE UNITS USED IN CALCULATIONS: */ | |
371 /* It is the convention in decompression calculations to compute all gas */ | |
372 /* loadings, absolute pressures, partial pressures, etc., in the units of */ | |
373 /* depth pressure that you are diving - either feet of seawater (fsw) or */ | |
374 /* meters of seawater (msw). This program follows that convention with the */ | |
375 /* the exception that all VPM calculations are performed in SI units (by */ | |
376 /* necessity). Accordingly, there are several conversions back and forth */ | |
377 /* between the diving pressure units and the SI units. */ | |
378 /* =============================================================================== */ | |
379 /* =============================================================================== */ | |
380 /* FUNCTION SUBPROGRAM FOR GAS LOADING CALCULATIONS - ASCENT AND DESCENT */ | |
381 /* =============================================================================== */ | |
382 | |
383 | |
384 | |
385 /* =============================================================================== */ | |
386 /* SUBROUTINE GAS_LOADINGS_ASCENT_DESCENT */ | |
387 /* Purpose: This subprogram applies the Schreiner equation to update the */ | |
388 /* gas loadings (partial pressures of helium and nitrogen) in the half-time */ | |
389 /* compartments due to a linear ascent or descent segment at a constant rate. */ | |
390 /* =============================================================================== */ | |
391 | |
392 int gas_loadings_ascent_descen(float* helium_pressure, | |
393 float* nitrogen_pressure, | |
394 float starting_depth, | |
395 float ending_depth, | |
396 float rate,_Bool check_gas_change) | |
397 { | |
398 short i; | |
399 float initial_inspired_n2_pressure, | |
400 initial_inspired_he_pressure, nitrogen_rate, | |
401 last_run_time, | |
402 starting_ambient_pressure, | |
403 ending_ambient_pressure; | |
404 float initial_helium_pressure[16]; | |
405 float initial_nitrogen_pressure[16]; | |
406 float helium_rate; | |
407 float fraction_helium_begin; | |
408 float fraction_helium_end; | |
409 float fraction_nitrogen_begin; | |
410 float fraction_nitrogen_end; | |
411 float ending_depth_tmp = ending_depth; | |
412 float segment_time_tmp = 0; | |
413 /* loop */ | |
414 /* =============================================================================== */ | |
415 /* CALCULATIONS */ | |
416 /* =============================================================================== */ | |
417 segment_time = (ending_depth_tmp - starting_depth) / rate; | |
418 last_run_time = run_time; | |
419 run_time = last_run_time + segment_time; | |
420 do { | |
421 ending_depth_tmp = ending_depth; | |
422 if (starting_depth > ending_depth && check_gas_change && number_of_changes > 1) | |
423 { | |
424 for (i = 1; i < number_of_changes; ++i) | |
425 { | |
426 if (depth_change[i] < starting_depth && depth_change[i] > ending_depth) | |
427 { | |
428 ending_depth_tmp = depth_change[i]; | |
429 break; | |
430 } | |
431 } | |
432 for (i = 1; i < number_of_changes; ++i) | |
433 { | |
434 if (depth_change[i] >= starting_depth) | |
435 { | |
436 mix_number = mix_change[i]; | |
437 } | |
438 } | |
439 } | |
440 segment_time_tmp = (ending_depth_tmp - starting_depth) / rate; | |
441 ending_ambient_pressure = ending_depth_tmp + barometric_pressure; | |
442 starting_ambient_pressure = starting_depth + barometric_pressure; | |
443 decom_get_inert_gases( starting_ambient_pressure / 10, (&pDiveSettings->decogaslist[mix_number]), &fraction_nitrogen_begin, &fraction_helium_begin ); | |
444 decom_get_inert_gases( ending_ambient_pressure / 10, (&pDiveSettings->decogaslist[mix_number]), &fraction_nitrogen_end, &fraction_helium_end ); | |
445 | |
446 initial_inspired_he_pressure = (starting_ambient_pressure - WATER_VAPOR_PRESSURE) * fraction_helium_begin; | |
447 initial_inspired_n2_pressure = (starting_ambient_pressure - WATER_VAPOR_PRESSURE) * fraction_nitrogen_begin; | |
448 //helium_rate = *rate * fraction_helium[mix_number - 1]; | |
449 helium_rate = ((ending_ambient_pressure - WATER_VAPOR_PRESSURE)* fraction_helium_end - initial_inspired_he_pressure)/segment_time_tmp; | |
450 //nitrogen_rate2 = *rate * fraction_nitrogen[mix_number - 1]; | |
451 nitrogen_rate = ((ending_ambient_pressure - WATER_VAPOR_PRESSURE)* fraction_nitrogen_end - initial_inspired_n2_pressure)/segment_time_tmp; | |
452 | |
453 | |
454 decom_oxygen_calculate_cns_stage_SchreinerStyle(segment_time_tmp,&pDiveSettings->decogaslist[mix_number],starting_ambient_pressure/10,ending_ambient_pressure/10,&gCNS_VPM); | |
455 //if(fabs(nitrogen_rate - nitrogen_rate2) > 0.000001) | |
456 //return -2; | |
457 for (i = 1; i <= 16; ++i) | |
458 { | |
459 initial_helium_pressure[i - 1] = helium_pressure[i - 1]; | |
460 initial_nitrogen_pressure[i - 1] = nitrogen_pressure[i - 1]; | |
461 helium_pressure[i - 1] = | |
462 schreiner_equation__2(&initial_inspired_he_pressure, | |
463 &helium_rate, | |
464 &segment_time, | |
465 &HELIUM_TIME_CONSTANT[i - 1], | |
466 &initial_helium_pressure[i - 1]); | |
467 nitrogen_pressure[i - 1] = | |
468 schreiner_equation__2(&initial_inspired_n2_pressure, | |
469 &nitrogen_rate, | |
470 &segment_time, | |
471 &NITROGEN_TIME_CONSTANT[i - 1], | |
472 &initial_nitrogen_pressure[i - 1]); | |
473 | |
474 //nextround??? | |
475 | |
476 } | |
477 starting_depth = ending_depth_tmp; | |
478 } while(ending_depth_tmp > ending_depth); | |
479 | |
480 return 0; | |
481 } /* gas_loadings_ascent_descen */ | |
482 | |
483 float last_phase_volume_time[16]; | |
484 float n2_pressure_start_of_deco_zone[16]; | |
485 float he_pressure_start_of_deco_zone[16]; | |
486 float phase_volume_time[16]; | |
487 float n2_pressure_start_of_ascent[16]; | |
488 float he_pressure_start_of_ascent[16]; | |
489 float run_time_start_of_deco_calc; | |
490 float starting_depth; | |
491 float last_run_time; | |
492 float deco_phase_volume_time; | |
493 | |
494 float run_time_start_of_ascent; | |
495 | |
496 float rate; | |
497 float step_size; | |
498 _Bool vpm_violates_buehlmann; | |
499 | |
500 void vpm_calc_deco(void) | |
501 { | |
502 /* System generated locals */ | |
503 | |
504 //float deepest_possible_stop_depth; | |
505 // altitude_of_dive, | |
506 short i; | |
507 int j = 0; | |
508 | |
509 // float rounding_operation; | |
510 | |
511 /* =============================================================================== */ | |
512 /* INPUT PARAMETERS TO BE USED FOR STAGED DECOMPRESSION AND SAVE IN ARRAYS. */ | |
513 /* ASSIGN INITAL PARAMETERS TO BE USED AT START OF ASCENT */ | |
514 /* The user has the ability to change mix, ascent rate, and step size in any */ | |
515 /* combination at any depth during the ascent. */ | |
516 /* =============================================================================== */ | |
517 | |
518 run_time = ((float)pInput->dive_time_seconds )/ 60; | |
519 count_critical_volume_iteration = 0; | |
520 number_of_changes = 1; | |
521 | |
522 barometric_pressure = pInput->pressure_surface_bar * 10; | |
523 depth_change[0] =(pInput->pressure_ambient_bar - pInput->pressure_surface_bar)* 10; | |
524 mix_change[0] = 0; | |
525 rate_change[0 ] = -10;// neu 160215 hw, zuvor: -12; | |
526 step_size_change[0] = 3; | |
527 vpm_violates_buehlmann = false; | |
528 | |
529 for (i = 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++) | |
530 { | |
531 depth_change[i] = 0; | |
532 mix_change[i] = 0; | |
533 } | |
534 j = 0; | |
535 | |
536 for (i = 1; i < BUEHLMANN_STRUCT_MAX_GASES; i++) | |
537 { | |
538 if(pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero >= depth_change[0] + 1) | |
539 continue; | |
540 | |
541 if(pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero <= 0) | |
542 break; | |
543 | |
544 j++; | |
545 number_of_changes ++; | |
546 depth_change[j] = pDiveSettings->decogaslist[i].change_during_ascent_depth_meter_otherwise_zero ; | |
547 mix_change[j] = i; | |
548 rate_change[j] = -10;// neu 160215 hw, zuvor: -12; | |
549 step_size_change[j] = 3; | |
550 } | |
551 | |
552 starting_depth = depth_change[0] ; | |
553 mix_number = mix_change[0] ; | |
554 rate = rate_change[0]; | |
555 step_size = step_size_change[0]; | |
556 | |
557 for (i = 0; i < 16; ++i) { | |
558 he_pressure_start_of_ascent[i ] = helium_pressure[i]; | |
559 n2_pressure_start_of_ascent[i] = nitrogen_pressure[i]; | |
560 } | |
561 run_time_start_of_ascent = run_time; | |
562 if(starting_depth <= depth_start_of_deco_zone && vpm_calc_what == DECOSTOPS) | |
563 { | |
564 pVpm->deco_zone_reached = true; | |
565 depth_start_of_deco_calc = starting_depth; | |
566 critical_volume_algorithm_off = true; | |
567 } | |
568 else | |
569 { | |
570 //if(deco_zone_reached) | |
571 //{ | |
572 pVpm->deco_zone_reached = false; | |
573 critical_volume_algorithm_off = false; | |
574 //max_first_stop_depth = 0; | |
575 //max_first_stop_depth_save = 0; | |
576 //} | |
577 /* =============================================================================== */ | |
578 /* BEGIN PROCESS OF ASCENT AND DECOMPRESSION */ | |
579 /* First, calculate the regeneration of critical radii that takes place over */ | |
580 /* the dive time. The regeneration time constant has a time scale of weeks */ | |
581 /* so this will have very little impact on dives of normal length, but will */ | |
582 /* have major impact for saturation dives. */ | |
583 /* =============================================================================== */ | |
584 | |
585 nuclear_regeneration(&run_time); | |
586 | |
587 /* =============================================================================== */ | |
588 /* CALCULATE INITIAL ALLOWABLE GRADIENTS FOR ASCENT */ | |
589 /* This is based on the maximum effective crushing pressure on critical radii */ | |
590 /* in each compartment achieved during the dive profile. */ | |
591 /* =============================================================================== */ | |
592 | |
593 calc_initial_allowable_gradient(); | |
594 | |
595 /* =============================================================================== */ | |
596 /* SAVE VARIABLES AT START OF ASCENT (END OF BOTTOM TIME) SINCE THESE WILL */ | |
597 /* BE USED LATER TO COMPUTE THE FINAL ASCENT PROFILE THAT IS WRITTEN TO THE */ | |
598 /* OUTPUT FILE. */ | |
599 /* The VPM uses an iterative process to compute decompression schedules so */ | |
600 /* there will be more than one pass through the decompression loop. */ | |
601 /* =============================================================================== */ | |
602 | |
603 /* =============================================================================== */ | |
604 /* CALCULATE THE DEPTH WHERE THE DECOMPRESSION ZONE BEGINS FOR THIS PROFILE */ | |
605 /* BASED ON THE INITIAL ASCENT PARAMETERS AND WRITE THE DEEPEST POSSIBLE */ | |
606 /* DECOMPRESSION STOP DEPTH TO THE OUTPUT FILE */ | |
607 /* Knowing where the decompression zone starts is very important. Below */ | |
608 /* that depth there is no possibility for bubble formation because there */ | |
609 /* will be no supersaturation gradients. Deco stops should never start */ | |
610 /* below the deco zone. The deepest possible stop deco stop depth is */ | |
611 /* defined as the next "standard" stop depth above the point where the */ | |
612 /* leading compartment enters the deco zone. Thus, the program will not */ | |
613 /* base this calculation on step sizes larger than 10 fsw or 3 msw. The */ | |
614 /* deepest possible stop depth is not used in the program, per se, rather */ | |
615 /* it is information to tell the diver where to start putting on the brakes */ | |
616 /* during ascent. This should be prominently displayed by any deco program. */ | |
617 /* =============================================================================== */ | |
618 | |
619 calc_start_of_deco_zone(&starting_depth, &rate, &depth_start_of_deco_zone); | |
620 /* =============================================================================== */ | |
621 /* TEMPORARILY ASCEND PROFILE TO THE START OF THE DECOMPRESSION ZONE, SAVE */ | |
622 /* VARIABLES AT THIS POINT, AND INITIALIZE VARIABLES FOR CRITICAL VOLUME LOOP */ | |
623 /* The iterative process of the VPM Critical Volume Algorithm will operate */ | |
624 /* only in the decompression zone since it deals with excess gas volume */ | |
625 /* released as a result of supersaturation gradients (not possible below the */ | |
626 /* decompression zone). */ | |
627 /* =============================================================================== */ | |
628 gas_loadings_ascent_descen(helium_pressure,nitrogen_pressure, starting_depth, depth_start_of_deco_zone, rate, true); | |
629 | |
630 run_time_start_of_deco_zone = run_time; | |
631 depth_start_of_deco_calc = depth_start_of_deco_zone; | |
632 | |
633 for (i = 0; i < 16; ++i) | |
634 { | |
635 pVpm->max_actual_gradient[i] = 0.; | |
636 } | |
637 } | |
638 | |
639 for (i = 0; i < 16; ++i) | |
640 { | |
641 surface_phase_volume_time[i] = 0.; | |
642 last_phase_volume_time[i] = 0.; | |
643 he_pressure_start_of_deco_zone[i] = helium_pressure[i]; | |
644 n2_pressure_start_of_deco_zone[i] = nitrogen_pressure[i]; | |
645 //pVpm->max_actual_gradient[i] = 0.; | |
646 } | |
647 run_time_start_of_deco_calc = run_time; | |
648 } | |
649 /* =============================================================================== */ | |
650 /* START OF CRITICAL VOLUME LOOP */ | |
651 /* This loop operates between Lines 50 and 100. If the Critical Volume */ | |
652 /* Algorithm is toggled "off" in the program settings, there will only be */ | |
653 /* one pass through this loop. Otherwise, there will be two or more passes */ | |
654 /* through this loop until the deco schedule is "converged" - that is when a */ | |
655 /* comparison between the phase volume time of the present iteration and the */ | |
656 /* last iteration is less than or equal to one minute. This implies that */ | |
657 /* the volume of released gas in the most recent iteration differs from the */ | |
658 /* "critical" volume limit by an acceptably small amount. The critical */ | |
659 /* volume limit is set by the Critical Volume Parameter Lambda in the program */ | |
660 /* settings (default setting is 7500 fsw-min with adjustability range from */ | |
661 /* from 6500 to 8300 fsw-min according to Bruce Wienke). */ | |
662 /* =============================================================================== */ | |
663 /* L50: */ | |
664 | |
665 float deco_stop_depth; | |
666 int vpm_calc_critcal_volume(_Bool begin, | |
667 _Bool calc_nulltime) | |
668 { /* loop will run continuous there is an exit stateme */ | |
669 | |
670 short i; | |
671 | |
672 float rounding_operation2; | |
673 //float ending_depth; | |
674 float deco_ceiling_depth; | |
675 | |
676 //float deco_time; | |
677 int count = 0; | |
678 _Bool first_stop; | |
679 int dp = 0; | |
680 float tissue_He_saturation[16]; | |
681 float tissue_N2_saturation[16]; | |
682 float vpm_buehlmann_safety_gradient = 1.0f - (((float)pDiveSettings->vpm_conservatism) / 40); | |
683 /* =============================================================================== */ | |
684 /* CALCULATE CURRENT DECO CEILING BASED ON ALLOWABLE SUPERSATURATION */ | |
685 /* GRADIENTS AND SET FIRST DECO STOP. CHECK TO MAKE SURE THAT SELECTED STEP */ | |
686 /* SIZE WILL NOT ROUND UP FIRST STOP TO A DEPTH THAT IS BELOW THE DECO ZONE. */ | |
687 /* =============================================================================== */ | |
688 if(begin) | |
689 { | |
690 if(depth_start_of_deco_calc < max_first_stop_depth ) | |
691 { | |
692 if(vpm_b) | |
693 { | |
694 BOYLES_LAW_COMPENSATION(&max_first_stop_depth, &depth_start_of_deco_calc, &step_size); | |
695 } | |
696 calc_deco_ceiling(&deco_ceiling_depth, false); | |
697 } | |
698 else | |
699 calc_deco_ceiling(&deco_ceiling_depth, true); | |
700 | |
701 | |
702 if (deco_ceiling_depth <= 0.0f) { | |
703 deco_stop_depth = 0.0f; | |
704 } else { | |
705 rounding_operation2 = deco_ceiling_depth / step_size + ( float)0.5f; | |
706 deco_stop_depth = r_nint(&rounding_operation2) * step_size; | |
707 } | |
708 | |
709 // buehlmann safety | |
710 if(buehlmannSafety) | |
711 { | |
712 for (i = 0; i < 16; i++) | |
713 { | |
714 tissue_He_saturation[i] = helium_pressure[i] / 10; | |
715 tissue_N2_saturation[i] = nitrogen_pressure[i] / 10; | |
716 } | |
717 | |
718 if(!decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (deco_stop_depth / 10.0f) + pInput->pressure_surface_bar)) | |
719 { | |
720 | |
721 vpm_violates_buehlmann = true; | |
722 do { | |
723 deco_stop_depth += 3; | |
724 } while (!decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (deco_stop_depth / 10.0f) + pInput->pressure_surface_bar)); | |
725 } | |
726 } | |
727 | |
728 /* =============================================================================== */ | |
729 /* PERFORM A SEPARATE "PROJECTED ASCENT" OUTSIDE OF THE MAIN PROGRAM TO MAKE */ | |
730 /* SURE THAT AN INCREASE IN GAS LOADINGS DURING ASCENT TO THE FIRST STOP WILL */ | |
731 /* NOT CAUSE A VIOLATION OF THE DECO CEILING. IF SO, ADJUST THE FIRST STOP */ | |
732 /* DEEPER BASED ON STEP SIZE UNTIL A SAFE ASCENT CAN BE MADE. */ | |
733 /* Note: this situation is a possibility when ascending from extremely deep */ | |
734 /* dives or due to an unusual gas mix selection. */ | |
735 /* CHECK AGAIN TO MAKE SURE THAT ADJUSTED FIRST STOP WILL NOT BE BELOW THE */ | |
736 /* DECO ZONE. */ | |
737 /* =============================================================================== */ | |
738 if (deco_stop_depth < depth_start_of_deco_calc) | |
739 { | |
740 projected_ascent(&depth_start_of_deco_calc, &rate, &deco_stop_depth, &step_size); | |
741 } | |
742 | |
743 /*if (deco_stop_depth > depth_start_of_deco_zone) { | |
744 printf("\t\n"); | |
745 printf(fmt_905); | |
746 printf(fmt_900); | |
747 printf("\nPROGRAM TERMINATED\n"); | |
748 exit(1); | |
749 }*/ | |
750 | |
751 /* =============================================================================== */ | |
752 /* HANDLE THE SPECIAL CASE WHEN NO DECO STOPS ARE REQUIRED - ASCENT CAN BE */ | |
753 /* MADE DIRECTLY TO THE SURFACE */ | |
754 /* Write ascent data to output file and exit the Critical Volume Loop. */ | |
755 /* =============================================================================== */ | |
756 | |
757 if (deco_stop_depth == 0.0f) | |
758 { | |
759 if(calc_nulltime) | |
760 { | |
761 return CALC_END; | |
762 } | |
763 if(pVpm->deco_zone_reached) | |
764 { | |
765 for(dp = 0;dp < DECOINFO_STRUCT_MAX_STOPS;dp++) | |
766 { | |
767 pDecoInfo->output_stop_length_seconds[dp] = 0; | |
768 } | |
769 pDecoInfo->output_ndl_seconds = 0; | |
770 /*max_first_stop_depth = 0; | |
771 deco_zone_reached = false; | |
772 depth_start_of_deco_calc = 0; | |
773 depth_start_of_deco_zone = 0; | |
774 first_stop_depth = 0; | |
775 max_first_stop_depth_save = 0; | |
776 depth_start_of_deco_zone_save = 0; | |
777 run_time_start_of_deco_zone_save = 0; | |
778 tts[DECOSTOPS] = 0; | |
779 tts[NULLZEIT] = 0; | |
780 tts[FUTURESTOPS] = 0; | |
781 nullzeit_unter60 = false; | |
782 vpm_calc_status = CALC_NULLZEIT; | |
783 vpm_calc_what = DECOSTOPS; | |
784 float surfacetime = 0; | |
785 vpm_repetitive_algorithm(&surfacetime);*/ | |
786 | |
787 } | |
788 | |
789 return CALC_NULLZEIT; | |
790 /* exit the critical volume l */ | |
791 } | |
792 | |
793 /* =============================================================================== */ | |
794 /* ASSIGN VARIABLES FOR ASCENT FROM START OF DECO ZONE TO FIRST STOP. SAVE */ | |
795 /* FIRST STOP DEPTH FOR LATER USE WHEN COMPUTING THE FINAL ASCENT PROFILE */ | |
796 /* =============================================================================== */ | |
797 deco_stop_depth = fmaxf(deco_stop_depth,(float)pDiveSettings->last_stop_depth_bar * 10); | |
798 starting_depth = depth_start_of_deco_calc; | |
799 first_stop_depth = deco_stop_depth; | |
800 first_stop = true; | |
801 } | |
802 /* =============================================================================== */ | |
803 /* DECO STOP LOOP BLOCK WITHIN CRITICAL VOLUME LOOP */ | |
804 /* This loop computes a decompression schedule to the surface during each */ | |
805 /* iteration of the critical volume loop. No output is written from this */ | |
806 /* loop, rather it computes a schedule from which the in-water portion of the */ | |
807 /* total phase volume time (Deco_Phase_Volume_Time) can be extracted. Also, */ | |
808 /* the gas loadings computed at the end of this loop are used the subroutine */ | |
809 /* which computes the out-of-water portion of the total phase volume time */ | |
810 /* (Surface_Phase_Volume_Time) for that schedule. */ | |
811 | |
812 /* Note that exit is made from the loop after last ascent is made to a deco */ | |
813 /* stop depth that is less than or equal to zero. A final deco stop less */ | |
814 /* than zero can happen when the user makes an odd step size change during */ | |
815 /* ascent - such as specifying a 5 msw step size change at the 3 msw stop! */ | |
816 /* =============================================================================== */ | |
817 | |
818 while(true) /* loop will run continuous there is an break statement */ | |
819 { | |
820 if(starting_depth > deco_stop_depth ) | |
821 gas_loadings_ascent_descen(helium_pressure, nitrogen_pressure, starting_depth, deco_stop_depth, rate,first_stop); | |
822 | |
823 first_stop = false; | |
824 if (deco_stop_depth <= 0.0f) | |
825 { | |
826 break; | |
827 } | |
828 if (number_of_changes > 1) | |
829 { | |
830 int i1 = number_of_changes; | |
831 for (i = 2; i <= i1; ++i) { | |
832 if (depth_change[i - 1] >= deco_stop_depth) | |
833 { | |
834 mix_number = mix_change[i - 1]; | |
835 rate = rate_change[i - 1]; | |
836 step_size = step_size_change[i - 1]; | |
837 } | |
838 } | |
839 } | |
840 if(vpm_b) | |
841 { | |
842 float fist_stop_depth2 = fmaxf(first_stop_depth,max_first_stop_depth); | |
843 BOYLES_LAW_COMPENSATION(&fist_stop_depth2, &deco_stop_depth, &step_size); | |
844 } | |
845 decompression_stop(&deco_stop_depth, &step_size, false); | |
846 starting_depth = deco_stop_depth; | |
847 | |
848 if(deco_stop_depth == (float)pDiveSettings->last_stop_depth_bar * 10) | |
849 deco_stop_depth = 0; | |
850 else | |
851 { | |
852 deco_stop_depth = deco_stop_depth - step_size; | |
853 deco_stop_depth = fmaxf(deco_stop_depth,(float)pDiveSettings->last_stop_depth_bar * 10); | |
854 } | |
855 | |
856 count++; | |
857 //if(count > 14) | |
858 //return CALC_CRITICAL2; | |
859 /* L60: */ | |
860 } | |
861 | |
862 return vpm_check_converged(calc_nulltime); | |
863 } | |
864 /* =============================================================================== */ | |
865 /* COMPUTE TOTAL PHASE VOLUME TIME AND MAKE CRITICAL VOLUME COMPARISON */ | |
866 /* The deco phase volume time is computed from the run time. The surface */ | |
867 /* phase volume time is computed in a subroutine based on the surfacing gas */ | |
868 /* loadings from previous deco loop block. Next the total phase volume time */ | |
869 /* (in-water + surface) for each compartment is compared against the previous */ | |
870 /* total phase volume time. The schedule is converged when the difference is */ | |
871 /* less than or equal to 1 minute in any one of the 16 compartments. */ | |
872 | |
873 /* Note: the "phase volume time" is somewhat of a mathematical concept. */ | |
874 /* It is the time divided out of a total integration of supersaturation */ | |
875 /* gradient x time (in-water and surface). This integration is multiplied */ | |
876 /* by the excess bubble number to represent the amount of free-gas released */ | |
877 /* as a result of allowing a certain number of excess bubbles to form. */ | |
878 /* =============================================================================== */ | |
879 /* end of deco stop loop */ | |
880 | |
881 int vpm_check_converged(_Bool calc_nulltime) | |
882 { | |
883 | |
884 short i; | |
885 float critical_volume_comparison; | |
886 float r1; | |
887 _Bool schedule_converged = false; | |
888 | |
889 | |
890 deco_phase_volume_time = run_time - run_time_start_of_deco_zone; | |
891 calc_surface_phase_volume_time(); | |
892 | |
893 for (i = 1; i <= 16; ++i) | |
894 { | |
895 phase_volume_time[i - 1] = | |
896 deco_phase_volume_time + surface_phase_volume_time[i - 1]; | |
897 critical_volume_comparison = (r1 = phase_volume_time[i - 1] - last_phase_volume_time[i - 1], fabs(r1)); | |
898 | |
899 if (critical_volume_comparison <= 1.0f) | |
900 { | |
901 schedule_converged = true; | |
902 } | |
903 } | |
904 | |
905 /* =============================================================================== */ | |
906 /* CRITICAL VOLUME DECISION TREE BETWEEN LINES 70 AND 99 */ | |
907 /* There are two options here. If the Critical Volume Agorithm setting is */ | |
908 /* "on" and the schedule is converged, or the Critical Volume Algorithm */ | |
909 /* setting was "off" in the first place, the program will re-assign variables */ | |
910 /* to their values at the start of ascent (end of bottom time) and process */ | |
911 /* a complete decompression schedule once again using all the same ascent */ | |
912 /* parameters and first stop depth. This decompression schedule will match */ | |
913 /* the last iteration of the Critical Volume Loop and the program will write */ | |
914 /* the final deco schedule to the output file. */ | |
915 | |
916 /* Note: if the Critical Volume Agorithm setting was "off", the final deco */ | |
917 /* schedule will be based on "Initial Allowable Supersaturation Gradients." */ | |
918 /* If it was "on", the final schedule will be based on "Adjusted Allowable */ | |
919 /* Supersaturation Gradients" (gradients that are "relaxed" as a result of */ | |
920 /* the Critical Volume Algorithm). */ | |
921 | |
922 /* If the Critical Volume Agorithm setting is "on" and the schedule is not */ | |
923 /* converged, the program will re-assign variables to their values at the */ | |
924 /* start of the deco zone and process another trial decompression schedule. */ | |
925 /* =============================================================================== */ | |
926 /* L70: */ | |
927 //Not more than 4 iteration allowed | |
928 count_critical_volume_iteration++; | |
929 if(count_critical_volume_iteration > 4) | |
930 { | |
931 //return CALC_FINAL_DECO; | |
932 if(calc_nulltime) | |
933 return CALC_FINAL_DECO; | |
934 else | |
935 return vpm_calc_final_deco(true); | |
936 } | |
937 if (schedule_converged || critical_volume_algorithm_off) | |
938 { | |
939 | |
940 //return CALC_FINAL_DECO; | |
941 if(calc_nulltime) | |
942 return CALC_FINAL_DECO; | |
943 else | |
944 return vpm_calc_final_deco(true); | |
945 /* final deco schedule */ | |
946 /* exit critical volume l */ | |
947 | |
948 /* =============================================================================== */ | |
949 /* IF SCHEDULE NOT CONVERGED, COMPUTE RELAXED ALLOWABLE SUPERSATURATION */ | |
950 /* GRADIENTS WITH VPM CRITICAL VOLUME ALGORITHM AND PROCESS ANOTHER */ | |
951 /* ITERATION OF THE CRITICAL VOLUME LOOP */ | |
952 /* =============================================================================== */ | |
953 | |
954 } else { | |
955 critical_volume(&deco_phase_volume_time); | |
956 deco_phase_volume_time = 0.; | |
957 run_time = run_time_start_of_deco_calc; | |
958 starting_depth = depth_start_of_deco_calc; | |
959 mix_number = mix_change[0]; | |
960 rate = rate_change[0]; | |
961 step_size = step_size_change[0]; | |
962 for (i = 1; i <= 16; ++i) | |
963 { | |
964 last_phase_volume_time[i - 1] = phase_volume_time[i - 1]; | |
965 helium_pressure[i - 1] = he_pressure_start_of_deco_zone[i - 1]; | |
966 nitrogen_pressure[i - 1] = n2_pressure_start_of_deco_zone[i - 1]; | |
967 } | |
968 if(calc_nulltime) | |
969 return CALC_CRITICAL; | |
970 else | |
971 return vpm_calc_critcal_volume(true, false); | |
972 } | |
973 /* end of critical volume decision */ | |
974 /* L100: */ | |
975 // }/* end of critical vol loop */ | |
976 } | |
977 | |
978 void vpm_calc_deco_ceiling(void) | |
979 { | |
980 | |
981 short i; | |
982 // hw 1601209 float r1; | |
983 // hw 1601209 float stop_time; | |
984 // hw 1601209 int count = 0; | |
985 //static int dp_max; | |
986 //static float surfacetime; | |
987 // _Bool first_stop = false; | |
988 float tissue_He_saturation[16]; | |
989 float tissue_N2_saturation[16]; | |
990 float vpm_buehlmann_safety_gradient = 1.0f - (((float)pDiveSettings->vpm_conservatism) / 40); | |
991 //max_first_stop_depth = fmaxf(first_stop_depth,max_first_stop_depth); | |
992 | |
993 /** CALC DECO Ceiling ******************************************************************/ | |
994 /** Not when Future stops */ | |
995 if(vpm_calc_what == DECOSTOPS) | |
996 { | |
997 | |
998 for (i = 1; i <= 16; ++i) | |
999 { | |
1000 helium_pressure[i - 1] = he_pressure_start_of_deco_zone[i - 1]; | |
1001 nitrogen_pressure[i - 1] = n2_pressure_start_of_deco_zone[i - 1]; | |
1002 } | |
1003 run_time = run_time_start_of_ascent;// run_time_start_of_ascent; | |
1004 starting_depth = depth_change[0]; | |
1005 mix_number = mix_change[0]; | |
1006 rate = rate_change[0]; | |
1007 //gas_loadings_ascent_descen(helium_pressure,nitrogen_pressure, starting_depth, depth_start_of_deco_calc, rate, true); | |
1008 | |
1009 float deco_ceiling_depth = 0.0f; | |
1010 if(depth_start_of_deco_calc > max_deco_ceiling_depth) | |
1011 { | |
1012 calc_deco_ceiling(&deco_ceiling_depth, true); | |
1013 } | |
1014 if(buehlmannSafety) | |
1015 { | |
1016 for (i = 0; i < 16; i++) | |
1017 { | |
1018 tissue_He_saturation[i] = helium_pressure[i] / 10; | |
1019 tissue_N2_saturation[i] = nitrogen_pressure[i] / 10; | |
1020 } | |
1021 | |
1022 if(!decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (deco_ceiling_depth / 10.0f) + pInput->pressure_surface_bar)) | |
1023 { | |
1024 | |
1025 vpm_violates_buehlmann = true; | |
1026 do { | |
1027 deco_ceiling_depth += 0.1f; | |
1028 } while (!decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (deco_ceiling_depth / 10.0f) + pInput->pressure_surface_bar)); | |
1029 } | |
1030 } | |
1031 | |
1032 if (deco_ceiling_depth < depth_start_of_deco_calc) | |
1033 { | |
1034 projected_ascent(&depth_start_of_deco_calc, &rate, &deco_ceiling_depth, &step_size); | |
1035 } | |
1036 | |
1037 max_deco_ceiling_depth = fmaxf(max_deco_ceiling_depth,deco_ceiling_depth); | |
1038 | |
1039 if(depth_start_of_deco_calc > deco_ceiling_depth) | |
1040 { | |
1041 gas_loadings_ascent_descen(helium_pressure,nitrogen_pressure, depth_start_of_deco_calc,deco_ceiling_depth, rate, true); | |
1042 //surfacetime += segment_time; | |
1043 } | |
1044 | |
1045 if(vpm_b) | |
1046 { | |
1047 BOYLES_LAW_COMPENSATION(&max_deco_ceiling_depth, &deco_ceiling_depth, &step_size); | |
1048 } | |
1049 calc_deco_ceiling(&deco_ceiling_depth, false); | |
1050 | |
1051 // buehlmann safety | |
1052 if(vpm_violates_buehlmann) | |
1053 { | |
1054 for (i = 0; i < 16; i++) | |
1055 { | |
1056 tissue_He_saturation[i] = helium_pressure[i] / 10; | |
1057 tissue_N2_saturation[i] = nitrogen_pressure[i] / 10; | |
1058 } | |
1059 | |
1060 if(!decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (deco_ceiling_depth / 10.0f) + pInput->pressure_surface_bar)) | |
1061 { | |
1062 | |
1063 vpm_violates_buehlmann = true; | |
1064 do { | |
1065 deco_ceiling_depth += 0.1f; | |
1066 } while (!decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (deco_ceiling_depth / 10.0f) + pInput->pressure_surface_bar)); | |
1067 } | |
1068 } | |
1069 // output_ceiling_meter | |
1070 if(deco_ceiling_depth > first_stop_depth) | |
1071 deco_ceiling_depth = first_stop_depth; | |
1072 pDecoInfo->output_ceiling_meter = deco_ceiling_depth ; | |
1073 } | |
1074 else | |
1075 { | |
1076 pDecoInfo->output_ceiling_meter = 0; | |
1077 } | |
1078 | |
1079 // fix hw 160627 | |
1080 if(pDecoInfo->output_ceiling_meter < 0) | |
1081 pDecoInfo->output_ceiling_meter = 0; | |
1082 | |
1083 /*** End CALC ceiling ***************************************************/ | |
1084 } | |
1085 | |
1086 | |
1087 /* =============================================================================== */ | |
1088 /* DECO STOP LOOP BLOCK FOR FINAL DECOMPRESSION SCHEDULE */ | |
1089 /* =============================================================================== */ | |
1090 | |
1091 int vpm_calc_final_deco(_Bool begin) | |
1092 { | |
1093 short i; | |
1094 float r1; | |
1095 float stop_time; | |
1096 int count = 0; | |
1097 static int dp_max; | |
1098 static float surfacetime; | |
1099 _Bool first_stop = false; | |
1100 max_first_stop_depth = fmaxf(first_stop_depth,max_first_stop_depth); | |
1101 if(begin) | |
1102 { | |
1103 gCNS_VPM = 0; | |
1104 dp_max = 0; | |
1105 for (i = 1; i <= 16; ++i) | |
1106 { | |
1107 helium_pressure[i - 1] = | |
1108 he_pressure_start_of_ascent[i - 1]; | |
1109 nitrogen_pressure[i - 1] = | |
1110 n2_pressure_start_of_ascent[i - 1]; | |
1111 } | |
1112 run_time = run_time_start_of_ascent;// run_time_start_of_ascent; | |
1113 starting_depth = depth_change[0]; | |
1114 mix_number = mix_change[0]; | |
1115 rate = rate_change[0]; | |
1116 step_size = step_size_change[0]; | |
1117 deco_stop_depth = first_stop_depth; | |
1118 max_first_stop_depth = fmaxf(first_stop_depth,max_first_stop_depth); | |
1119 last_run_time = 0.; | |
1120 | |
1121 | |
1122 | |
1123 /* =============================================================================== */ | |
1124 /* DECO STOP LOOP BLOCK FOR FINAL DECOMPRESSION SCHEDULE */ | |
1125 /* =============================================================================== */ | |
1126 surfacetime = 0; | |
1127 first_stop = true; | |
1128 } | |
1129 | |
1130 while(true) /* loop will run continuous until there is an break statement */ | |
1131 { | |
1132 if(starting_depth > deco_stop_depth) | |
1133 { | |
1134 gas_loadings_ascent_descen(helium_pressure,nitrogen_pressure, starting_depth,deco_stop_depth, rate, first_stop); | |
1135 surfacetime += segment_time; | |
1136 } | |
1137 | |
1138 /* =============================================================================== */ | |
1139 /* DURING FINAL DECOMPRESSION SCHEDULE PROCESS, COMPUTE MAXIMUM ACTUAL */ | |
1140 /* SUPERSATURATION GRADIENT RESULTING IN EACH COMPARTMENT */ | |
1141 /* If there is a repetitive dive, this will be used later in the VPM */ | |
1142 /* Repetitive Algorithm to adjust the values for critical radii. */ | |
1143 /* =============================================================================== */ | |
1144 if(vpm_calc_what == DECOSTOPS) | |
1145 calc_max_actual_gradient(&deco_stop_depth); | |
1146 | |
1147 if (deco_stop_depth <= 0.0f) { | |
1148 break; | |
1149 } | |
1150 if (number_of_changes > 1) | |
1151 { | |
1152 int i1 = number_of_changes; | |
1153 for (i = 2; i <= i1; ++i) | |
1154 { | |
1155 if (depth_change[i - 1] >= deco_stop_depth) | |
1156 { | |
1157 mix_number = mix_change[i - 1]; | |
1158 rate = rate_change[i - 1]; | |
1159 step_size = step_size_change[i - 1]; | |
1160 } | |
1161 } | |
1162 } | |
1163 | |
1164 if(first_stop) | |
1165 { | |
1166 run_time_first_stop = run_time; | |
1167 first_stop = false; | |
1168 } | |
1169 if(vpm_b) | |
1170 { | |
1171 BOYLES_LAW_COMPENSATION(&max_first_stop_depth, &deco_stop_depth, &step_size); | |
1172 } | |
1173 decompression_stop(&deco_stop_depth, &step_size, true); | |
1174 | |
1175 /* =============================================================================== */ | |
1176 /* This next bit justs rounds up the stop time at the first stop to be in */ | |
1177 /* whole increments of the minimum stop time (to make for a nice deco table). */ | |
1178 /* =============================================================================== */ | |
1179 | |
1180 if (last_run_time == 0.0f) | |
1181 { | |
1182 r1 = segment_time / minimum_deco_stop_time + 0.5f; | |
1183 stop_time = r_int(&r1) * minimum_deco_stop_time; | |
1184 } else { | |
1185 stop_time = run_time - last_run_time; | |
1186 } | |
1187 stop_time = segment_time; | |
1188 surfacetime += stop_time; | |
1189 if((vpm_calc_what == DECOSTOPS) || (vpm_calc_what == BAILOUTSTOPS)) | |
1190 { | |
1191 int dp = 0; | |
1192 if(deco_stop_depth == (float)pDiveSettings->last_stop_depth_bar * 10) | |
1193 { | |
1194 dp = 0; | |
1195 } | |
1196 else | |
1197 { | |
1198 dp = 1 + (int)((deco_stop_depth - (pDiveSettings->input_second_to_last_stop_depth_bar * 10)) / step_size); | |
1199 } | |
1200 dp_max = (int)fmaxf(dp_max,dp); | |
1201 if(dp < DECOINFO_STRUCT_MAX_STOPS) | |
1202 { | |
1203 int stop_time_seconds = fminf((999 * 60), (int)(stop_time *60)); | |
1204 // | |
1205 | |
1206 //if(vpm_calc_what == DECOSTOPS) | |
1207 pDecoInfo->output_stop_length_seconds[dp] = (unsigned short)stop_time_seconds; | |
1208 //else | |
1209 //decostop_bailout[dp] = (unsigned short)stop_time_seconds; | |
1210 } | |
1211 } | |
1212 | |
1213 | |
1214 /* =============================================================================== */ | |
1215 /* DURING FINAL DECOMPRESSION SCHEDULE, IF MINIMUM STOP TIME PARAMETER IS A */ | |
1216 /* WHOLE NUMBER (i.e. 1 minute) THEN WRITE DECO SCHEDULE USING short */ | |
1217 /* NUMBERS (looks nicer). OTHERWISE, USE DECIMAL NUMBERS. */ | |
1218 /* Note: per the request of a noted exploration diver(!), program now allows */ | |
1219 /* a minimum stop time of less than one minute so that total ascent time can */ | |
1220 /* be minimized on very long dives. In fact, with step size set at 1 fsw or */ | |
1221 /* 0.2 msw and minimum stop time set at 0.1 minute (6 seconds), a near */ | |
1222 /* continuous decompression schedule can be computed. */ | |
1223 /* =============================================================================== */ | |
1224 | |
1225 starting_depth = deco_stop_depth; | |
1226 if(deco_stop_depth == (float)pDiveSettings->last_stop_depth_bar * 10) | |
1227 deco_stop_depth = 0; | |
1228 else | |
1229 { | |
1230 deco_stop_depth = deco_stop_depth - step_size; | |
1231 deco_stop_depth = fmaxf(deco_stop_depth,(float)pDiveSettings->last_stop_depth_bar * 10); | |
1232 } | |
1233 | |
1234 last_run_time = run_time; | |
1235 count++; | |
1236 //if(count > 14) | |
1237 //return CALC_FINAL_DECO2; | |
1238 /* L80: */ | |
1239 } /* for final deco sche */ | |
1240 | |
1241 if( (vpm_calc_what == DECOSTOPS) || (vpm_calc_what == BAILOUTSTOPS)) | |
1242 { | |
1243 for(int dp = dp_max +1;dp < DECOINFO_STRUCT_MAX_STOPS;dp++) | |
1244 { | |
1245 //if(vpm_calc_what == DECOSTOPS) | |
1246 pDecoInfo->output_stop_length_seconds[dp] = 0; | |
1247 //else | |
1248 //decostop_bailout[dp] = 0; | |
1249 } | |
1250 } | |
1251 pDecoInfo->output_time_to_surface_seconds = (int)(surfacetime * 60); | |
1252 pDecoInfo->output_ndl_seconds = 0; | |
1253 | |
1254 vpm_calc_deco_ceiling(); | |
1255 /* end of deco stop lo */ | |
1256 return CALC_END; | |
1257 } | |
1258 | |
1259 /* =============================================================================== */ | |
1260 /* SUBROUTINE NUCLEAR_REGENERATION */ | |
1261 /* Purpose: This subprogram calculates the regeneration of VPM critical */ | |
1262 /* radii that takes place over the dive time. The regeneration time constant */ | |
1263 /* has a time scale of weeks so this will have very little impact on dives of */ | |
1264 /* normal length, but will have a major impact for saturation dives. */ | |
1265 /* =============================================================================== */ | |
1266 | |
1267 int nuclear_regeneration(float *dive_time) | |
1268 { | |
1269 /* Local variables */ | |
1270 float crush_pressure_adjust_ratio_he, | |
1271 ending_radius_n2, | |
1272 ending_radius_he; | |
1273 short i; | |
1274 float crushing_pressure_pascals_n2, | |
1275 crushing_pressure_pascals_he, | |
1276 adj_crush_pressure_n2_pascals, | |
1277 adj_crush_pressure_he_pascals, | |
1278 crush_pressure_adjust_ratio_n2; | |
1279 | |
1280 /* loop */ | |
1281 /* =============================================================================== */ | |
1282 /* CALCULATIONS */ | |
1283 /* First convert the maximum crushing pressure obtained for each compartment */ | |
1284 /* to Pascals. Next, compute the ending radius for helium and nitrogen */ | |
1285 /* critical nuclei in each compartment. */ | |
1286 /* =============================================================================== */ | |
1287 | |
1288 for (i = 1; i <= 16; ++i) | |
1289 { | |
1290 crushing_pressure_pascals_he = | |
1291 pVpm->max_crushing_pressure_he[i - 1] / UNITS_FACTOR * 101325.0f; | |
1292 crushing_pressure_pascals_n2 = | |
1293 pVpm->max_crushing_pressure_n2[i - 1] / UNITS_FACTOR * 101325.0f; | |
1294 ending_radius_he = | |
1295 1.0f / (crushing_pressure_pascals_he / | |
1296 ((SKIN_COMPRESSION_GAMMAC - SURFACE_TENSION_GAMMA) * 2.0f) + | |
1297 1.0f / pVpm->adjusted_critical_radius_he[i - 1]); | |
1298 ending_radius_n2 = | |
1299 1.0f / (crushing_pressure_pascals_n2 / | |
1300 ((SKIN_COMPRESSION_GAMMAC - SURFACE_TENSION_GAMMA) * 2.0f) + | |
1301 1.0f / pVpm->adjusted_critical_radius_n2[i - 1]); | |
1302 | |
1303 /* =============================================================================== */ | |
1304 /* A "regenerated" radius for each nucleus is now calculated based on the */ | |
1305 /* regeneration time constant. This means that after application of */ | |
1306 /* crushing pressure and reduction in radius, a nucleus will slowly grow */ | |
1307 /* back to its original initial radius over a period of time. This */ | |
1308 /* phenomenon is probabilistic in nature and depends on absolute temperature. */ | |
1309 /* It is independent of crushing pressure. */ | |
1310 /* =============================================================================== */ | |
1311 | |
1312 regenerated_radius_he[i - 1] = | |
1313 pVpm->adjusted_critical_radius_he[i - 1] + | |
1314 (ending_radius_he - pVpm->adjusted_critical_radius_he[i - 1]) * | |
1315 expf(-(*dive_time) / REGENERATION_TIME_CONSTANT); | |
1316 regenerated_radius_n2[i - 1] = | |
1317 pVpm->adjusted_critical_radius_n2[i - 1] + | |
1318 (ending_radius_n2 - pVpm->adjusted_critical_radius_n2[i - 1]) * | |
1319 expf(-(*dive_time) / REGENERATION_TIME_CONSTANT); | |
1320 | |
1321 /* =============================================================================== */ | |
1322 /* In order to preserve reference back to the initial critical radii after */ | |
1323 /* regeneration, an "adjusted crushing pressure" for the nuclei in each */ | |
1324 /* compartment must be computed. In other words, this is the value of */ | |
1325 /* crushing pressure that would have reduced the original nucleus to the */ | |
1326 /* to the present radius had regeneration not taken place. The ratio */ | |
1327 /* for adjusting crushing pressure is obtained from algebraic manipulation */ | |
1328 /* of the standard VPM equations. The adjusted crushing pressure, in lieu */ | |
1329 /* of the original crushing pressure, is then applied in the VPM Critical */ | |
1330 /* Volume Algorithm and the VPM Repetitive Algorithm. */ | |
1331 /* =============================================================================== */ | |
1332 | |
1333 crush_pressure_adjust_ratio_he = | |
1334 ending_radius_he * (pVpm->adjusted_critical_radius_he[i - 1] - | |
1335 regenerated_radius_he[i - 1]) / | |
1336 (regenerated_radius_he[i - 1] * | |
1337 (pVpm->adjusted_critical_radius_he[i - 1] - | |
1338 ending_radius_he)); | |
1339 crush_pressure_adjust_ratio_n2 = | |
1340 ending_radius_n2 * (pVpm->adjusted_critical_radius_n2[i - 1] - | |
1341 regenerated_radius_n2[i - 1]) / | |
1342 (regenerated_radius_n2[i - 1] * | |
1343 (pVpm->adjusted_critical_radius_n2[i - 1] - | |
1344 ending_radius_n2)); | |
1345 adj_crush_pressure_he_pascals = | |
1346 crushing_pressure_pascals_he * crush_pressure_adjust_ratio_he; | |
1347 adj_crush_pressure_n2_pascals = | |
1348 crushing_pressure_pascals_n2 * crush_pressure_adjust_ratio_n2; | |
1349 pVpm->adjusted_crushing_pressure_he[i - 1] = | |
1350 adj_crush_pressure_he_pascals / 101325.0f * UNITS_FACTOR; | |
1351 pVpm->adjusted_crushing_pressure_n2[i - 1] = | |
1352 adj_crush_pressure_n2_pascals / 101325.0f * UNITS_FACTOR; | |
1353 } | |
1354 return 0; | |
1355 } /* nuclear_regeneration */ | |
1356 | |
1357 /* =============================================================================== */ | |
1358 /* SUBROUTINE CALC_INITIAL_ALLOWABLE_GRADIENT */ | |
1359 /* Purpose: This subprogram calculates the initial allowable gradients for */ | |
1360 /* helium and nitrogren in each compartment. These are the gradients that */ | |
1361 /* will be used to set the deco ceiling on the first pass through the deco */ | |
1362 /* loop. If the Critical Volume Algorithm is set to "off", then these */ | |
1363 /* gradients will determine the final deco schedule. Otherwise, if the */ | |
1364 /* Critical Volume Algorithm is set to "on", these gradients will be further */ | |
1365 /* "relaxed" by the Critical Volume Algorithm subroutine. The initial */ | |
1366 /* allowable gradients are referred to as "PssMin" in the papers by Yount */ | |
1367 /* and colleauges, i.e., the minimum supersaturation pressure gradients */ | |
1368 /* that will probe bubble formation in the VPM nuclei that started with the */ | |
1369 /* designated minimum initial radius (critical radius). */ | |
1370 | |
1371 /* The initial allowable gradients are computed directly from the */ | |
1372 /* "regenerated" radii after the Nuclear Regeneration subroutine. These */ | |
1373 /* gradients are tracked separately for helium and nitrogen. */ | |
1374 /* =============================================================================== */ | |
1375 | |
1376 int calc_initial_allowable_gradient() | |
1377 { | |
1378 float initial_allowable_grad_n2_pa, | |
1379 initial_allowable_grad_he_pa; | |
1380 short i; | |
1381 | |
1382 /* loop */ | |
1383 /* =============================================================================== */ | |
1384 /* CALCULATIONS */ | |
1385 /* The initial allowable gradients are computed in Pascals and then converted */ | |
1386 /* to the diving pressure units. Two different sets of arrays are used to */ | |
1387 /* save the calculations - Initial Allowable Gradients and Allowable */ | |
1388 /* Gradients. The Allowable Gradients are assigned the values from Initial */ | |
1389 /* Allowable Gradients however the Allowable Gradients can be changed later */ | |
1390 /* by the Critical Volume subroutine. The values for the Initial Allowable */ | |
1391 /* Gradients are saved in a global array for later use by both the Critical */ | |
1392 /* Volume subroutine and the VPM Repetitive Algorithm subroutine. */ | |
1393 /* =============================================================================== */ | |
1394 | |
1395 for (i = 1; i <= 16; ++i) | |
1396 { | |
1397 initial_allowable_grad_n2_pa = | |
1398 SURFACE_TENSION_GAMMA * 2.0f * | |
1399 (SKIN_COMPRESSION_GAMMAC - SURFACE_TENSION_GAMMA) / | |
1400 (regenerated_radius_n2[i - 1] * SKIN_COMPRESSION_GAMMAC); | |
1401 | |
1402 initial_allowable_grad_he_pa = | |
1403 SURFACE_TENSION_GAMMA * 2.0f * | |
1404 (SKIN_COMPRESSION_GAMMAC - SURFACE_TENSION_GAMMA) / | |
1405 (regenerated_radius_he[i - 1] * SKIN_COMPRESSION_GAMMAC); | |
1406 | |
1407 pVpm->initial_allowable_gradient_n2[i - 1] = | |
1408 initial_allowable_grad_n2_pa / 101325.0f * UNITS_FACTOR; | |
1409 | |
1410 pVpm->initial_allowable_gradient_he[i - 1] = | |
1411 initial_allowable_grad_he_pa / 101325.0f * UNITS_FACTOR; | |
1412 | |
1413 allowable_gradient_he[i - 1] = | |
1414 pVpm->initial_allowable_gradient_he[i - 1]; | |
1415 | |
1416 allowable_gradient_n2[i - 1] = | |
1417 pVpm->initial_allowable_gradient_n2[i - 1]; | |
1418 } | |
1419 return 0; | |
1420 } /* calc_initial_allowable_gradient */ | |
1421 | |
1422 /* =============================================================================== */ | |
1423 /* SUBROUTINE CALC_DECO_CEILING */ | |
1424 /* Purpose: This subprogram calculates the deco ceiling (the safe ascent */ | |
1425 /* depth) in each compartment, based on the allowable gradients, and then */ | |
1426 /* finds the deepest deco ceiling across all compartments. This deepest */ | |
1427 /* value (Deco Ceiling Depth) is then used by the Decompression Stop */ | |
1428 /* subroutine to determine the actual deco schedule. */ | |
1429 /* =============================================================================== */ | |
1430 | |
1431 int calc_deco_ceiling(float *deco_ceiling_depth,_Bool fallowable) | |
1432 { | |
1433 /* System generated locals */ | |
1434 float r1, r2; | |
1435 /* Local variables */ | |
1436 float weighted_allowable_gradient; | |
1437 short i; | |
1438 float compartment_deco_ceiling[16], | |
1439 gas_loading, | |
1440 tolerated_ambient_pressure; | |
1441 float gradient_he, gradient_n2; | |
1442 | |
1443 if(!vpm_b) | |
1444 fallowable = true; | |
1445 /* loop */ | |
1446 /* =============================================================================== */ | |
1447 /* CALCULATIONS */ | |
1448 /* Since there are two sets of allowable gradients being tracked, one for */ | |
1449 /* helium and one for nitrogen, a "weighted allowable gradient" must be */ | |
1450 /* computed each time based on the proportions of helium and nitrogen in */ | |
1451 /* each compartment. This proportioning follows the methodology of */ | |
1452 /* Buhlmann/Keller. If there is no helium and nitrogen in the compartment, */ | |
1453 /* such as after extended periods of oxygen breathing, then the minimum value */ | |
1454 /* across both gases will be used. It is important to note that if a */ | |
1455 /* compartment is empty of helium and nitrogen, then the weighted allowable */ | |
1456 /* gradient formula cannot be used since it will result in division by zero. */ | |
1457 /* =============================================================================== */ | |
1458 | |
1459 for (i = 1; i <= 16; ++i) | |
1460 { | |
1461 | |
1462 // abfrage raus und pointer stattdessen | |
1463 if(fallowable){ | |
1464 gradient_he = allowable_gradient_he[i-1]; | |
1465 gradient_n2 = allowable_gradient_n2[i-1]; | |
1466 } | |
1467 else{ | |
1468 gradient_he = deco_gradient_he[i-1]; | |
1469 gradient_n2 = deco_gradient_n2[i-1]; | |
1470 } | |
1471 | |
1472 gas_loading = helium_pressure[i - 1] + nitrogen_pressure[i - 1]; | |
1473 | |
1474 if (gas_loading > 0) | |
1475 { | |
1476 weighted_allowable_gradient = | |
1477 (gradient_he * helium_pressure[i - 1] + | |
1478 gradient_n2 * nitrogen_pressure[i - 1]) / | |
1479 (helium_pressure[i - 1] + nitrogen_pressure[i - 1]); | |
1480 | |
1481 tolerated_ambient_pressure = | |
1482 gas_loading + | |
1483 CONSTANT_PRESSURE_OTHER_GASES - | |
1484 weighted_allowable_gradient; | |
1485 } | |
1486 else | |
1487 { | |
1488 /* Computing MIN */ | |
1489 r1 = gradient_he; | |
1490 r2 = gradient_n2; | |
1491 weighted_allowable_gradient = fminf(r1,r2); | |
1492 | |
1493 tolerated_ambient_pressure = | |
1494 CONSTANT_PRESSURE_OTHER_GASES - weighted_allowable_gradient; | |
1495 } | |
1496 | |
1497 /* =============================================================================== */ | |
1498 /* The tolerated ambient pressure cannot be less than zero absolute, i.e., */ | |
1499 /* the vacuum of outer space! */ | |
1500 /* =============================================================================== */ | |
1501 | |
1502 if (tolerated_ambient_pressure < 0) { | |
1503 tolerated_ambient_pressure = 0; | |
1504 } | |
1505 compartment_deco_ceiling[i - 1] = | |
1506 tolerated_ambient_pressure - barometric_pressure; | |
1507 } | |
1508 | |
1509 /* =============================================================================== */ | |
1510 /* The Deco Ceiling Depth is computed in a loop after all of the individual */ | |
1511 /* compartment deco ceilings have been calculated. It is important that the */ | |
1512 /* Deco Ceiling Depth (max deco ceiling across all compartments) only be */ | |
1513 /* extracted from the compartment values and not be compared against some */ | |
1514 /* initialization value. For example, if MAX(Deco_Ceiling_Depth . .) was */ | |
1515 /* compared against zero, this could cause a program lockup because sometimes */ | |
1516 /* the Deco Ceiling Depth needs to be negative (but not less than zero */ | |
1517 /* absolute ambient pressure) in order to decompress to the last stop at zero */ | |
1518 /* depth. */ | |
1519 /* =============================================================================== */ | |
1520 | |
1521 *deco_ceiling_depth = compartment_deco_ceiling[0]; | |
1522 for (i = 2; i <= 16; ++i) | |
1523 { | |
1524 /* Computing MAX */ | |
1525 r1 = *deco_ceiling_depth; | |
1526 r2 = compartment_deco_ceiling[i - 1]; | |
1527 *deco_ceiling_depth = fmaxf(r1,r2); | |
1528 } | |
1529 return 0; | |
1530 } /* calc_deco_ceiling */ | |
1531 | |
1532 | |
1533 | |
1534 /* =============================================================================== */ | |
1535 /* SUBROUTINE CALC_MAX_ACTUAL_GRADIENT */ | |
1536 /* Purpose: This subprogram calculates the actual supersaturation gradient */ | |
1537 /* obtained in each compartment as a result of the ascent profile during */ | |
1538 /* decompression. Similar to the concept with crushing pressure, the */ | |
1539 /* supersaturation gradients are not cumulative over a multi-level, staged */ | |
1540 /* ascent. Rather, it will be the maximum value obtained in any one discrete */ | |
1541 /* step of the overall ascent. Thus, the program must compute and store the */ | |
1542 /* maximum actual gradient for each compartment that was obtained across all */ | |
1543 /* steps of the ascent profile. This subroutine is invoked on the last pass */ | |
1544 /* through the deco stop loop block when the final deco schedule is being */ | |
1545 /* generated. */ | |
1546 /* */ | |
1547 /* The max actual gradients are later used by the VPM Repetitive Algorithm to */ | |
1548 /* determine if adjustments to the critical radii are required. If the max */ | |
1549 /* actual gradient did not exceed the initial alllowable gradient, then no */ | |
1550 /* adjustment will be made. However, if the max actual gradient did exceed */ | |
1551 /* the intitial allowable gradient, such as permitted by the Critical Volume */ | |
1552 /* Algorithm, then the critical radius will be adjusted (made larger) on the */ | |
1553 /* repetitive dive to compensate for the bubbling that was allowed on the */ | |
1554 /* previous dive. The use of the max actual gradients is intended to prevent */ | |
1555 /* the repetitive algorithm from being overly conservative. */ | |
1556 /* =============================================================================== */ | |
1557 | |
1558 int calc_max_actual_gradient(float *deco_stop_depth) | |
1559 { | |
1560 /* System generated locals */ | |
1561 float r1; | |
1562 | |
1563 /* Local variables */ | |
1564 short i; | |
1565 float compartment_gradient; | |
1566 | |
1567 /* loop */ | |
1568 /* =============================================================================== */ | |
1569 /* CALCULATIONS */ | |
1570 /* Note: negative supersaturation gradients are meaningless for this */ | |
1571 /* application, so the values must be equal to or greater than zero. */ | |
1572 /* =============================================================================== */ | |
1573 | |
1574 for (i = 1; i <= 16; ++i) | |
1575 { | |
1576 compartment_gradient = | |
1577 helium_pressure[i - 1] + | |
1578 nitrogen_pressure[i - 1] + | |
1579 CONSTANT_PRESSURE_OTHER_GASES - | |
1580 (*deco_stop_depth + barometric_pressure); | |
1581 if (compartment_gradient <= 0.0f) { | |
1582 compartment_gradient = 0.0f; | |
1583 } | |
1584 /* Computing MAX */ | |
1585 r1 = pVpm->max_actual_gradient[i - 1]; | |
1586 pVpm->max_actual_gradient[i - 1] = fmaxf(r1, compartment_gradient); | |
1587 } | |
1588 return 0; | |
1589 } /* calc_max_actual_gradient */ | |
1590 | |
1591 /* =============================================================================== */ | |
1592 /* SUBROUTINE CALC_SURFACE_PHASE_VOLUME_TIME */ | |
1593 /* Purpose: This subprogram computes the surface portion of the total phase */ | |
1594 /* volume time. This is the time factored out of the integration of */ | |
1595 /* supersaturation gradient x time over the surface interval. The VPM */ | |
1596 /* considers the gradients that allow bubbles to form or to drive bubble */ | |
1597 /* growth both in the water and on the surface after the dive. */ | |
1598 | |
1599 /* This subroutine is a new development to the VPM algorithm in that it */ | |
1600 /* computes the time course of supersaturation gradients on the surface */ | |
1601 /* when both helium and nitrogen are present. Refer to separate write-up */ | |
1602 /* for a more detailed explanation of this algorithm. */ | |
1603 /* =============================================================================== */ | |
1604 | |
1605 int calc_surface_phase_volume_time() | |
1606 { | |
1607 /* Local variables */ | |
1608 float decay_time_to_zero_gradient; | |
1609 short i; | |
1610 float integral_gradient_x_time, | |
1611 surface_inspired_n2_pressure; | |
1612 | |
1613 /* loop */ | |
1614 /* =============================================================================== */ | |
1615 /* CALCULATIONS */ | |
1616 /* =============================================================================== */ | |
1617 | |
1618 surface_inspired_n2_pressure = | |
1619 (barometric_pressure - WATER_VAPOR_PRESSURE) * 0.79f; | |
1620 for (i = 1; i <= 16; ++i) | |
1621 { | |
1622 if (nitrogen_pressure[i - 1] > surface_inspired_n2_pressure) | |
1623 { | |
1624 surface_phase_volume_time[i - 1] = | |
1625 (helium_pressure[i - 1] / HELIUM_TIME_CONSTANT[i - 1] + | |
1626 (nitrogen_pressure[i - 1] - surface_inspired_n2_pressure) / | |
1627 NITROGEN_TIME_CONSTANT[i - 1]) / | |
1628 (helium_pressure[i - 1] + nitrogen_pressure[i - 1] - | |
1629 surface_inspired_n2_pressure); | |
1630 } else if (nitrogen_pressure[i - 1] <= surface_inspired_n2_pressure && | |
1631 helium_pressure[i - 1] + nitrogen_pressure[i - 1] >= surface_inspired_n2_pressure) | |
1632 { | |
1633 decay_time_to_zero_gradient = | |
1634 1.0f / (NITROGEN_TIME_CONSTANT[i - 1] - HELIUM_TIME_CONSTANT[i - 1]) * | |
1635 log((surface_inspired_n2_pressure - nitrogen_pressure[i - 1]) / | |
1636 helium_pressure[i - 1]); | |
1637 integral_gradient_x_time = | |
1638 helium_pressure[i - 1] / | |
1639 HELIUM_TIME_CONSTANT[i - 1] * | |
1640 (1.0f - expf(-HELIUM_TIME_CONSTANT[i - 1] * | |
1641 decay_time_to_zero_gradient)) + | |
1642 (nitrogen_pressure[i - 1] - surface_inspired_n2_pressure) / | |
1643 NITROGEN_TIME_CONSTANT[i - 1] * | |
1644 (1.0f - expf(-NITROGEN_TIME_CONSTANT[i - 1] * | |
1645 decay_time_to_zero_gradient)); | |
1646 surface_phase_volume_time[i - 1] = | |
1647 integral_gradient_x_time / | |
1648 (helium_pressure[i - 1] + | |
1649 nitrogen_pressure[i - 1] - | |
1650 surface_inspired_n2_pressure); | |
1651 } else { | |
1652 surface_phase_volume_time[i - 1] = 0.0f; | |
1653 } | |
1654 } | |
1655 return 0; | |
1656 } /* calc_surface_phase_volume_time */ | |
1657 | |
1658 /* =============================================================================== */ | |
1659 /* SUBROUTINE CRITICAL_VOLUME */ | |
1660 /* Purpose: This subprogram applies the VPM Critical Volume Algorithm. This */ | |
1661 /* algorithm will compute "relaxed" gradients for helium and nitrogen based */ | |
1662 /* on the setting of the Critical Volume Parameter Lambda. */ | |
1663 /* =============================================================================== */ | |
1664 | |
1665 int critical_volume(float *deco_phase_volume_time) | |
1666 { | |
1667 /* System generated locals */ | |
1668 float r1; | |
1669 | |
1670 /* Local variables */ | |
1671 float initial_allowable_grad_n2_pa, | |
1672 initial_allowable_grad_he_pa, | |
1673 parameter_lambda_pascals, b, | |
1674 c; | |
1675 short i; | |
1676 float new_allowable_grad_n2_pascals, | |
1677 phase_volume_time[16], | |
1678 new_allowable_grad_he_pascals, | |
1679 adj_crush_pressure_n2_pascals, | |
1680 adj_crush_pressure_he_pascals; | |
1681 | |
1682 /* loop */ | |
1683 /* =============================================================================== */ | |
1684 /* CALCULATIONS */ | |
1685 /* Note: Since the Critical Volume Parameter Lambda was defined in units of */ | |
1686 /* fsw-min in the original papers by Yount and colleauges, the same */ | |
1687 /* convention is retained here. Although Lambda is adjustable only in units */ | |
1688 /* of fsw-min in the program settings (range from 6500 to 8300 with default */ | |
1689 /* 7500), it will convert to the proper value in Pascals-min in this */ | |
1690 /* subroutine regardless of which diving pressure units are being used in */ | |
1691 /* the main program - feet of seawater (fsw) or meters of seawater (msw). */ | |
1692 /* The allowable gradient is computed using the quadratic formula (refer to */ | |
1693 /* separate write-up posted on the Deco List web site). */ | |
1694 /* =============================================================================== */ | |
1695 | |
1696 /** | |
1697 ****************************************************************************** | |
1698 * @brief critical_volume comment by hw | |
1699 * @version V0.0.1 | |
1700 * @date 19-April-2014 | |
1701 * @retval global: allowable_gradient_he[i], allowable_gradient_n2[i] | |
1702 ****************************************************************************** | |
1703 */ | |
1704 | |
1705 parameter_lambda_pascals = | |
1706 CRIT_VOLUME_PARAMETER_LAMBDA / 33.0f * 101325.0f; | |
1707 for (i = 1; i <= 16; ++i) | |
1708 { | |
1709 phase_volume_time[i - 1] = | |
1710 *deco_phase_volume_time + surface_phase_volume_time[i - 1]; | |
1711 } | |
1712 for (i = 1; i <= 16; ++i) | |
1713 { | |
1714 | |
1715 adj_crush_pressure_he_pascals = | |
1716 pVpm->adjusted_crushing_pressure_he[i - 1] / UNITS_FACTOR * 101325.0f; | |
1717 | |
1718 initial_allowable_grad_he_pa = | |
1719 pVpm->initial_allowable_gradient_he[i - 1] / UNITS_FACTOR * 101325.0f; | |
1720 | |
1721 b = initial_allowable_grad_he_pa + parameter_lambda_pascals * | |
1722 SURFACE_TENSION_GAMMA / ( | |
1723 SKIN_COMPRESSION_GAMMAC * phase_volume_time[i - 1]); | |
1724 | |
1725 c = SURFACE_TENSION_GAMMA * ( | |
1726 SURFACE_TENSION_GAMMA * ( | |
1727 parameter_lambda_pascals * adj_crush_pressure_he_pascals)) / | |
1728 (SKIN_COMPRESSION_GAMMAC * | |
1729 (SKIN_COMPRESSION_GAMMAC * phase_volume_time[i - 1])); | |
1730 /* Computing 2nd power */ | |
1731 | |
1732 r1 = b; | |
1733 | |
1734 new_allowable_grad_he_pascals = | |
1735 (b + sqrtf(r1 * r1 - c * 4.0f)) / 2.0f; | |
1736 | |
1737 /* modify global variable */ | |
1738 allowable_gradient_he[i - 1] = | |
1739 new_allowable_grad_he_pascals / 101325.0f * UNITS_FACTOR; | |
1740 } | |
1741 | |
1742 for (i = 1; i <= 16; ++i) | |
1743 { | |
1744 adj_crush_pressure_n2_pascals = | |
1745 pVpm->adjusted_crushing_pressure_n2[i - 1] / UNITS_FACTOR * 101325.0f; | |
1746 | |
1747 initial_allowable_grad_n2_pa = | |
1748 pVpm->initial_allowable_gradient_n2[i - 1] / UNITS_FACTOR * 101325.0f; | |
1749 | |
1750 b = initial_allowable_grad_n2_pa + parameter_lambda_pascals * | |
1751 SURFACE_TENSION_GAMMA / ( | |
1752 SKIN_COMPRESSION_GAMMAC * phase_volume_time[i - 1]); | |
1753 | |
1754 c = SURFACE_TENSION_GAMMA * | |
1755 (SURFACE_TENSION_GAMMA * | |
1756 (parameter_lambda_pascals * adj_crush_pressure_n2_pascals)) / | |
1757 (SKIN_COMPRESSION_GAMMAC * | |
1758 (SKIN_COMPRESSION_GAMMAC * phase_volume_time[i - 1])); | |
1759 /* Computing 2nd power */ | |
1760 | |
1761 r1 = b; | |
1762 | |
1763 new_allowable_grad_n2_pascals = | |
1764 (b + sqrtf(r1 * r1 - c * 4.0f)) / 2.0f; | |
1765 | |
1766 /* modify global variable */ | |
1767 allowable_gradient_n2[i - 1] = | |
1768 new_allowable_grad_n2_pascals / 101325.0f * UNITS_FACTOR; | |
1769 } | |
1770 return 0; | |
1771 } /* critical_volume */ | |
1772 | |
1773 /* =============================================================================== */ | |
1774 /* SUBROUTINE CALC_START_OF_DECO_ZONE */ | |
1775 /* Purpose: This subroutine uses the Bisection Method to find the depth at */ | |
1776 /* which the leading compartment just enters the decompression zone. */ | |
1777 /* Source: "Numerical Recipes in Fortran 77", Cambridge University Press, */ | |
1778 /* 1992. */ | |
1779 /* =============================================================================== */ | |
1780 | |
1781 int calc_start_of_deco_zone(float *starting_depth, | |
1782 float *rate, | |
1783 float *depth_start_of_deco_zone) | |
1784 { | |
1785 /* Local variables */ | |
1786 float last_diff_change, | |
1787 initial_helium_pressure, | |
1788 mid_range_nitrogen_pressure; | |
1789 short i, j; | |
1790 float initial_inspired_n2_pressure, | |
1791 cpt_depth_start_of_deco_zone, | |
1792 low_bound, | |
1793 initial_inspired_he_pressure, | |
1794 high_bound_nitrogen_pressure, | |
1795 nitrogen_rate, | |
1796 function_at_mid_range, | |
1797 function_at_low_bound, | |
1798 high_bound, | |
1799 mid_range_helium_pressure, | |
1800 mid_range_time, | |
1801 starting_ambient_pressure, | |
1802 initial_nitrogen_pressure, | |
1803 function_at_high_bound; | |
1804 | |
1805 float time_to_start_of_deco_zone, | |
1806 high_bound_helium_pressure, | |
1807 helium_rate, | |
1808 differential_change; | |
1809 float fraction_helium_begin; | |
1810 float fraction_helium_end; | |
1811 float fraction_nitrogen_begin; | |
1812 float fraction_nitrogen_end; | |
1813 float ending_ambient_pressure; | |
1814 float time_test; | |
1815 | |
1816 | |
1817 /* loop */ | |
1818 /* =============================================================================== */ | |
1819 /* CALCULATIONS */ | |
1820 /* First initialize some variables */ | |
1821 /* =============================================================================== */ | |
1822 | |
1823 *depth_start_of_deco_zone = 0.0f; | |
1824 starting_ambient_pressure = *starting_depth + barometric_pressure; | |
1825 | |
1826 //>>>>>>>>>>>>>>>>>>>> | |
1827 //Test depth to calculate helium_rate and nitrogen_rate | |
1828 ending_ambient_pressure = starting_ambient_pressure/2; | |
1829 | |
1830 time_test = (ending_ambient_pressure - starting_ambient_pressure) / *rate; | |
1831 decom_get_inert_gases(starting_ambient_pressure / 10, (&pDiveSettings->decogaslist[mix_number]), &fraction_nitrogen_begin, &fraction_helium_begin ); | |
1832 decom_get_inert_gases(ending_ambient_pressure / 10, (&pDiveSettings->decogaslist[mix_number]), &fraction_nitrogen_end, &fraction_helium_end ); | |
1833 initial_inspired_he_pressure = (starting_ambient_pressure - WATER_VAPOR_PRESSURE) * fraction_helium_begin; | |
1834 initial_inspired_n2_pressure = (starting_ambient_pressure - WATER_VAPOR_PRESSURE) * fraction_nitrogen_begin; | |
1835 helium_rate = ((ending_ambient_pressure - WATER_VAPOR_PRESSURE)* fraction_helium_end - initial_inspired_he_pressure)/time_test; | |
1836 nitrogen_rate = ((ending_ambient_pressure - WATER_VAPOR_PRESSURE)* fraction_nitrogen_end - initial_inspired_n2_pressure)/time_test; | |
1837 //>>>>>>>>>>>>>>>>>>>>> | |
1838 /*initial_inspired_he_pressure = | |
1839 (starting_ambient_pressure - water_vapor_pressure) * | |
1840 fraction_helium[mix_number - 1]; | |
1841 initial_inspired_n2_pressure = | |
1842 (starting_ambient_pressure - water_vapor_pressure) * | |
1843 fraction_nitrogen[mix_number - 1]; | |
1844 helium_rate = *rate * fraction_helium[mix_number - 1]; | |
1845 nitrogen_rate = *rate * fraction_nitrogen[mix_number - 1];*/ | |
1846 | |
1847 /* =============================================================================== */ | |
1848 /* ESTABLISH THE BOUNDS FOR THE ROOT SEARCH USING THE BISECTION METHOD */ | |
1849 /* AND CHECK TO MAKE SURE THAT THE ROOT WILL BE WITHIN BOUNDS. PROCESS */ | |
1850 /* EACH COMPARTMENT INDIVIDUALLY AND FIND THE MAXIMUM DEPTH ACROSS ALL */ | |
1851 /* COMPARTMENTS (LEADING COMPARTMENT) */ | |
1852 /* In this case, we are solving for time - the time when the gas tension in */ | |
1853 /* the compartment will be equal to ambient pressure. The low bound for time */ | |
1854 /* is set at zero and the high bound is set at the time it would take to */ | |
1855 /* ascend to zero ambient pressure (absolute). Since the ascent rate is */ | |
1856 /* negative, a multiplier of -1.0 is used to make the time positive. The */ | |
1857 /* desired point when gas tension equals ambient pressure is found at a time */ | |
1858 /* somewhere between these endpoints. The algorithm checks to make sure that */ | |
1859 /* the solution lies in between these bounds by first computing the low bound */ | |
1860 /* and high bound function values. */ | |
1861 /* =============================================================================== */ | |
1862 | |
1863 low_bound = 0.; | |
1864 high_bound = starting_ambient_pressure / *rate * -1.0f; | |
1865 for (i = 1; i <= 16; ++i) | |
1866 { | |
1867 initial_helium_pressure = helium_pressure[i - 1]; | |
1868 initial_nitrogen_pressure = nitrogen_pressure[i - 1]; | |
1869 function_at_low_bound = | |
1870 initial_helium_pressure + | |
1871 initial_nitrogen_pressure + | |
1872 CONSTANT_PRESSURE_OTHER_GASES - | |
1873 starting_ambient_pressure; | |
1874 high_bound_helium_pressure = | |
1875 schreiner_equation__2(&initial_inspired_he_pressure, | |
1876 &helium_rate, | |
1877 &high_bound, | |
1878 &HELIUM_TIME_CONSTANT[i - 1], | |
1879 &initial_helium_pressure); | |
1880 high_bound_nitrogen_pressure = | |
1881 schreiner_equation__2(&initial_inspired_n2_pressure, | |
1882 &nitrogen_rate, | |
1883 &high_bound, | |
1884 &NITROGEN_TIME_CONSTANT[i - 1], | |
1885 &initial_nitrogen_pressure); | |
1886 function_at_high_bound = high_bound_helium_pressure + | |
1887 high_bound_nitrogen_pressure + | |
1888 CONSTANT_PRESSURE_OTHER_GASES; | |
1889 if (function_at_high_bound * function_at_low_bound >= 0.0f) | |
1890 { | |
1891 printf("\nERROR! ROOT IS NOT WITHIN BRACKETS"); | |
1892 } | |
1893 | |
1894 /* =============================================================================== */ | |
1895 /* APPLY THE BISECTION METHOD IN SEVERAL ITERATIONS UNTIL A SOLUTION WITH */ | |
1896 /* THE DESIRED ACCURACY IS FOUND */ | |
1897 /* Note: the program allows for up to 100 iterations. Normally an exit will */ | |
1898 /* be made from the loop well before that number. If, for some reason, the */ | |
1899 /* program exceeds 100 iterations, there will be a pause to alert the user. */ | |
1900 /* =============================================================================== */ | |
1901 | |
1902 if (function_at_low_bound < 0.0f) | |
1903 { | |
1904 time_to_start_of_deco_zone = low_bound; | |
1905 differential_change = high_bound - low_bound; | |
1906 } else { | |
1907 time_to_start_of_deco_zone = high_bound; | |
1908 differential_change = low_bound - high_bound; | |
1909 } | |
1910 for (j = 1; j <= 100; ++j) | |
1911 { | |
1912 last_diff_change = differential_change; | |
1913 differential_change = last_diff_change * 0.5f; | |
1914 mid_range_time = | |
1915 time_to_start_of_deco_zone + | |
1916 differential_change; | |
1917 mid_range_helium_pressure = | |
1918 schreiner_equation__2(&initial_inspired_he_pressure, | |
1919 &helium_rate, | |
1920 &mid_range_time, | |
1921 &HELIUM_TIME_CONSTANT[i - 1], | |
1922 &initial_helium_pressure); | |
1923 mid_range_nitrogen_pressure = | |
1924 schreiner_equation__2(&initial_inspired_n2_pressure, | |
1925 &nitrogen_rate, | |
1926 &mid_range_time, | |
1927 &NITROGEN_TIME_CONSTANT[i - 1], | |
1928 &initial_nitrogen_pressure); | |
1929 function_at_mid_range = | |
1930 mid_range_helium_pressure + | |
1931 mid_range_nitrogen_pressure + | |
1932 CONSTANT_PRESSURE_OTHER_GASES - | |
1933 (starting_ambient_pressure + *rate * mid_range_time); | |
1934 if (function_at_mid_range <= 0.0f) { | |
1935 time_to_start_of_deco_zone = mid_range_time; | |
1936 } | |
1937 if( fabs(differential_change) < 0.001f | |
1938 || function_at_mid_range == 0.0f) | |
1939 { | |
1940 goto L170; | |
1941 } | |
1942 /* L150: */ | |
1943 } | |
1944 printf("\nERROR! ROOT SEARCH EXCEEDED MAXIMUM ITERATIONS"); | |
1945 //pause(); | |
1946 | |
1947 /* =============================================================================== */ | |
1948 /* When a solution with the desired accuracy is found, the program jumps out */ | |
1949 /* of the loop to Line 170 and assigns the solution value for the individual */ | |
1950 /* compartment. */ | |
1951 /* =============================================================================== */ | |
1952 | |
1953 L170: | |
1954 cpt_depth_start_of_deco_zone = | |
1955 starting_ambient_pressure + | |
1956 *rate * time_to_start_of_deco_zone - | |
1957 barometric_pressure; | |
1958 | |
1959 /* =============================================================================== */ | |
1960 /* The overall solution will be the compartment with the maximum depth where */ | |
1961 /* gas tension equals ambient pressure (leading compartment). */ | |
1962 /* =============================================================================== */ | |
1963 | |
1964 *depth_start_of_deco_zone = | |
1965 fmaxf(*depth_start_of_deco_zone, cpt_depth_start_of_deco_zone); | |
1966 /* L200: */ | |
1967 } | |
1968 return 0; | |
1969 } /* calc_start_of_deco_zone */ | |
1970 | |
1971 /* =============================================================================== */ | |
1972 /* SUBROUTINE PROJECTED_ASCENT */ | |
1973 /* Purpose: This subprogram performs a simulated ascent outside of the main */ | |
1974 /* program to ensure that a deco ceiling will not be violated due to unusual */ | |
1975 /* gas loading during ascent (on-gassing). If the deco ceiling is violated, */ | |
1976 /* the stop depth will be adjusted deeper by the step size until a safe */ | |
1977 /* ascent can be made. */ | |
1978 /* =============================================================================== */ | |
1979 | |
1980 int projected_ascent(float *starting_depth, | |
1981 float *rate, | |
1982 float *deco_stop_depth, | |
1983 float *step_size) | |
1984 { | |
1985 /* Local variables */ | |
1986 float weighted_allowable_gradient, | |
1987 ending_ambient_pressure, | |
1988 temp_gas_loading[16]; | |
1989 int i; | |
1990 float allowable_gas_loading[16]; | |
1991 float temp_nitrogen_pressure[16]; | |
1992 float temp_helium_pressure[16]; | |
1993 float run_time_save = 0; | |
1994 | |
1995 /* loop */ | |
1996 /* =============================================================================== */ | |
1997 /* CALCULATIONS */ | |
1998 /* =============================================================================== */ | |
1999 | |
2000 | |
2001 L665: | |
2002 ending_ambient_pressure = *deco_stop_depth + barometric_pressure; | |
2003 for (i = 1; i <= 16; ++i) { | |
2004 temp_helium_pressure[i - 1] = helium_pressure[i - 1]; | |
2005 temp_nitrogen_pressure[i - 1] = nitrogen_pressure[i - 1]; | |
2006 } | |
2007 run_time_save = run_time; | |
2008 gas_loadings_ascent_descen(temp_helium_pressure, temp_nitrogen_pressure, *starting_depth,*deco_stop_depth,*rate,true); | |
2009 run_time = run_time_save; | |
2010 | |
2011 for (i = 1; i <= 16; ++i) | |
2012 { | |
2013 temp_gas_loading[i - 1] = | |
2014 temp_helium_pressure[i - 1] + | |
2015 temp_nitrogen_pressure[i - 1]; | |
2016 if (temp_gas_loading[i - 1] > 0.0f) | |
2017 { | |
2018 weighted_allowable_gradient = | |
2019 (allowable_gradient_he[i - 1] * | |
2020 temp_helium_pressure[i - 1] + | |
2021 allowable_gradient_n2[i - 1] * | |
2022 temp_nitrogen_pressure[i - 1]) / temp_gas_loading[i - 1]; | |
2023 } else { | |
2024 /* Computing MIN */ | |
2025 weighted_allowable_gradient = fminf(allowable_gradient_he[i - 1],allowable_gradient_n2[i - 1]); | |
2026 } | |
2027 allowable_gas_loading[i - 1] = | |
2028 ending_ambient_pressure + | |
2029 weighted_allowable_gradient - | |
2030 CONSTANT_PRESSURE_OTHER_GASES; | |
2031 /* L670: */ | |
2032 } | |
2033 for (i = 1; i <= 16; ++i) { | |
2034 if (temp_gas_loading[i - 1] > allowable_gas_loading[i - 1]) { | |
2035 *deco_stop_depth += *step_size; | |
2036 goto L665; | |
2037 } | |
2038 /* L671: */ | |
2039 } | |
2040 return 0; | |
2041 } /* projected_ascent */ | |
2042 | |
2043 /* =============================================================================== */ | |
2044 /* SUBROUTINE DECOMPRESSION_STOP */ | |
2045 /* Purpose: This subprogram calculates the required time at each */ | |
2046 /* decompression stop. */ | |
2047 /* =============================================================================== */ | |
2048 | |
2049 void decompression_stop(float *deco_stop_depth, | |
2050 float *step_size, | |
2051 _Bool final_deco_calculation) | |
2052 { | |
2053 /* Local variables */ | |
2054 float inspired_nitrogen_pressure; | |
2055 // short last_segment_number; | |
2056 // float weighted_allowable_gradient; | |
2057 float initial_helium_pressure[16]; | |
2058 /* by hw */ | |
51
8f8ea3a32e82
Resolved warnings pointing to possible invalid memory access
Ideenmodellierer
parents:
38
diff
changeset
|
2059 float initial_CNS = gCNS_VPM; |
38 | 2060 |
2061 //static float time_counter; | |
2062 short i; | |
2063 float ambient_pressure; | |
2064 float inspired_helium_pressure, | |
2065 next_stop; | |
2066 //last_run_time, | |
2067 //temp_segment_time; | |
2068 | |
2069 float deco_ceiling_depth, | |
2070 initial_nitrogen_pressure[16]; | |
2071 //round_up_operation; | |
2072 float fraction_helium_begin; | |
2073 float fraction_nitrogen_begin; | |
2074 int count = 0; | |
2075 _Bool buehlmann_wait = false; | |
2076 float tissue_He_saturation[16]; | |
2077 float tissue_N2_saturation[16]; | |
2078 float vpm_buehlmann_safety_gradient = 1.0f - (((float)pDiveSettings->vpm_conservatism) / 40); | |
2079 /* loop */ | |
2080 /* =============================================================================== */ | |
2081 /* CALCULATIONS */ | |
2082 /* =============================================================================== */ | |
2083 | |
2084 segment_time = 0; | |
2085 // temp_segment_time = segment_time; | |
2086 ambient_pressure = *deco_stop_depth + barometric_pressure; | |
2087 //ending_ambient_pressure = ambient_pressure; | |
2088 decom_get_inert_gases(ambient_pressure / 10, (&pDiveSettings->decogaslist[mix_number]), &fraction_nitrogen_begin, &fraction_helium_begin ); | |
2089 | |
2090 if(*deco_stop_depth == (float)(pDiveSettings->last_stop_depth_bar * 10)) | |
2091 next_stop = 0; | |
2092 else | |
2093 { | |
2094 next_stop = *deco_stop_depth - *step_size; | |
2095 next_stop = fmaxf(next_stop,(float)pDiveSettings->last_stop_depth_bar * 10); | |
2096 } | |
2097 | |
2098 inspired_helium_pressure = | |
2099 (ambient_pressure - WATER_VAPOR_PRESSURE) * fraction_helium_begin; | |
2100 inspired_nitrogen_pressure = | |
2101 (ambient_pressure - WATER_VAPOR_PRESSURE) * fraction_nitrogen_begin; | |
2102 | |
2103 /* =============================================================================== */ | |
2104 /* Check to make sure that program won't lock up if unable to decompress */ | |
2105 /* to the next stop. If so, write error message and terminate program. */ | |
2106 /* =============================================================================== */ | |
2107 | |
2108 //deco_ceiling_depth = next_stop +1; //deco_ceiling_depth = next_stop + 1; | |
2109 if(!vpm_violates_buehlmann) | |
149 | 2110 { |
38 | 2111 calc_deco_ceiling(&deco_ceiling_depth, false); //weg, weil auf jeden Fall schleife für safety und so konservativer |
149 | 2112 } |
38 | 2113 else |
149 | 2114 { |
38 | 2115 deco_ceiling_depth = next_stop + 1; |
149 | 2116 } |
38 | 2117 if(deco_ceiling_depth > next_stop) |
2118 { | |
2119 while (deco_ceiling_depth > next_stop) | |
2120 { | |
2121 | |
2122 segment_time += 60; | |
2123 if(segment_time >= 999 ) | |
2124 { | |
2125 segment_time = 999 ; | |
2126 run_time += segment_time; | |
2127 return; | |
2128 } | |
2129 //goto L700; | |
2130 initial_CNS = gCNS_VPM; | |
2131 decom_oxygen_calculate_cns_exposure(60*60,&pDiveSettings->decogaslist[mix_number],ambient_pressure/10,&gCNS_VPM); | |
2132 for (i = 0; i < 16; i++) | |
2133 { | |
2134 initial_helium_pressure[i] = helium_pressure[i]; | |
2135 initial_nitrogen_pressure[i] = nitrogen_pressure[i]; | |
2136 helium_pressure[i] += (inspired_helium_pressure - helium_pressure[i]) * float_buehlmann_He_factor_expositon_one_hour[i]; | |
2137 nitrogen_pressure[i] += (inspired_nitrogen_pressure - nitrogen_pressure[i]) * float_buehlmann_N2_factor_expositon_one_hour[i]; | |
2138 } | |
2139 calc_deco_ceiling(&deco_ceiling_depth, false); | |
2140 } | |
2141 if(deco_ceiling_depth < next_stop) | |
2142 { | |
2143 segment_time -= 60; | |
2144 gCNS_VPM = initial_CNS; | |
2145 for (i = 0; i < 16; i++) | |
2146 { | |
2147 helium_pressure[i] = initial_helium_pressure[i]; | |
2148 nitrogen_pressure[i] = initial_nitrogen_pressure[i]; | |
2149 } | |
2150 deco_ceiling_depth = next_stop +1; | |
2151 } | |
2152 count = 0; | |
2153 while (deco_ceiling_depth > next_stop && count < 13) | |
2154 { | |
2155 count++; | |
2156 segment_time += 5; | |
2157 //goto L700; | |
2158 initial_CNS = gCNS_VPM; | |
2159 decom_oxygen_calculate_cns_exposure(60*5,&pDiveSettings->decogaslist[mix_number],ambient_pressure/10,&gCNS_VPM); | |
2160 for (i = 0; i < 16; i++) | |
2161 { | |
2162 initial_helium_pressure[i] = helium_pressure[i]; | |
2163 initial_nitrogen_pressure[i] = nitrogen_pressure[i]; | |
2164 helium_pressure[i] += (inspired_helium_pressure - helium_pressure[i]) * float_buehlmann_He_factor_expositon_five_minutes[i]; | |
2165 nitrogen_pressure[i] += (inspired_nitrogen_pressure - nitrogen_pressure[i]) * float_buehlmann_N2_factor_expositon_five_minutes[i]; | |
2166 } | |
2167 calc_deco_ceiling(&deco_ceiling_depth, false); | |
2168 } | |
2169 if(deco_ceiling_depth < next_stop) | |
2170 { | |
2171 segment_time -= 5; | |
2172 gCNS_VPM = initial_CNS; | |
2173 for (i = 0; i < 16; i++) { | |
2174 helium_pressure[i] = initial_helium_pressure[i]; | |
2175 nitrogen_pressure[i] = initial_nitrogen_pressure[i]; | |
2176 } | |
2177 deco_ceiling_depth = next_stop +1; | |
2178 } | |
2179 buehlmann_wait = false; | |
2180 while (buehlmann_wait || (deco_ceiling_depth > next_stop)) | |
2181 { | |
2182 //time_counter = temp_segment_time; | |
2183 segment_time += 1; | |
2184 | |
2185 if(segment_time >= 999 ) | |
2186 { | |
2187 segment_time = 999 ; | |
2188 run_time += segment_time; | |
2189 return; | |
2190 } | |
2191 //goto L700; | |
2192 initial_CNS = gCNS_VPM; | |
2193 decom_oxygen_calculate_cns_exposure(60*1,&pDiveSettings->decogaslist[mix_number],ambient_pressure/10,&gCNS_VPM); | |
2194 for (i = 0; i < 16; i++) | |
2195 { | |
2196 initial_helium_pressure[i] = helium_pressure[i]; | |
2197 initial_nitrogen_pressure[i] = nitrogen_pressure[i]; | |
2198 helium_pressure[i] += (inspired_helium_pressure - helium_pressure[i]) * float_buehlmann_He_factor_expositon_one_minute[i]; | |
2199 nitrogen_pressure[i] += (inspired_nitrogen_pressure - nitrogen_pressure[i]) * float_buehlmann_N2_factor_expositon_one_minute[i]; | |
2200 } | |
2201 if(!buehlmann_wait) | |
2202 calc_deco_ceiling(&deco_ceiling_depth, false); | |
2203 | |
2204 if(buehlmannSafety && final_deco_calculation && !(deco_ceiling_depth > next_stop)) | |
2205 { | |
2206 for (i = 0; i < 16; i++) | |
2207 { | |
2208 tissue_He_saturation[i] = helium_pressure[i] / 10; | |
2209 tissue_N2_saturation[i] = nitrogen_pressure[i] / 10; | |
2210 } | |
2211 if( (fabsf(nitrogen_pressure[15] - inspired_nitrogen_pressure) < 0.00001f) && (fabsf(helium_pressure[15] - inspired_helium_pressure) < 0.00001f) | |
2212 && (fabsf(nitrogen_pressure[0] - inspired_nitrogen_pressure) < 0.00001f) && (fabsf(helium_pressure[0] - inspired_helium_pressure) < 0.00001f)) | |
2213 { | |
2214 buehlmann_wait_exceeded = true; | |
2215 break; | |
2216 } | |
2217 | |
2218 if(decom_tissue_test_tolerance(tissue_N2_saturation, tissue_He_saturation, vpm_buehlmann_safety_gradient, (next_stop / 10.0f) + pInput->pressure_surface_bar)) | |
2219 break; | |
2220 | |
2221 buehlmann_wait = true; | |
2222 } | |
2223 } | |
2224 if(buehlmann_wait) | |
149 | 2225 { |
38 | 2226 vpm_violates_buehlmann = true; |
149 | 2227 } |
2228 if(!buehlmann_wait) | |
38 | 2229 { |
2230 if(deco_ceiling_depth < next_stop) | |
2231 { | |
2232 segment_time -= 1; | |
2233 gCNS_VPM = initial_CNS; | |
2234 for (i = 0; i < 16; i++) { | |
2235 helium_pressure[i] = initial_helium_pressure[i]; | |
2236 nitrogen_pressure[i] = initial_nitrogen_pressure[i]; | |
2237 } | |
2238 deco_ceiling_depth = next_stop +1; | |
2239 } | |
2240 while (deco_ceiling_depth > next_stop) | |
2241 { | |
2242 //time_counter = temp_segment_time; | |
2243 segment_time += (float) 1.0f / 3.0f; | |
2244 //goto L700; | |
2245 initial_CNS = gCNS_VPM; | |
2246 decom_oxygen_calculate_cns_exposure(20,&pDiveSettings->decogaslist[mix_number],ambient_pressure/10,&gCNS_VPM); | |
2247 for (i = 0; i < 16; i++) | |
2248 { | |
2249 helium_pressure[i] += (inspired_helium_pressure - helium_pressure[i]) * float_buehlmann_He_factor_expositon_20_seconds[i]; | |
2250 nitrogen_pressure[i] += (inspired_nitrogen_pressure - nitrogen_pressure[i]) * float_buehlmann_N2_factor_expositon_20_seconds[i]; | |
2251 } | |
2252 calc_deco_ceiling(&deco_ceiling_depth, false); | |
2253 } | |
2254 } | |
2255 } | |
2256 | |
2257 /*float pressure_save =dive_data.pressure; | |
2258 dive_data.pressure = ambient_pressure/10; | |
2259 tissues_exposure_stage(st_deco_test,(int)(segment_time * 60), &dive_data, &gaslist); | |
2260 dive_data.pressure = pressure_save;*/ | |
2261 run_time += segment_time; | |
2262 return; | |
2263 } /* decompression_stop */ | |
2264 | |
2265 /* =============================================================================== */ | |
2266 // SUROUTINE BOYLES_LAW_COMPENSATION | |
2267 // Purpose: This subprogram calculates the reduction in allowable gradients | |
2268 // with decreasing ambient pressure during the decompression profile based | |
2269 // on Boyle's Law considerations. | |
2270 //=============================================================================== | |
2271 void BOYLES_LAW_COMPENSATION (float* First_Stop_Depth, | |
2272 float* Deco_Stop_Depth, | |
2273 float* Step_Size) | |
2274 { | |
2275 short i; | |
2276 | |
2277 float Next_Stop; | |
2278 float Ambient_Pressure_First_Stop, Ambient_Pressure_Next_Stop; | |
2279 float Amb_Press_First_Stop_Pascals, Amb_Press_Next_Stop_Pascals; | |
2280 float A, B, C, Low_Bound, High_Bound, Ending_Radius; | |
2281 float Deco_Gradient_Pascals; | |
2282 float Allow_Grad_First_Stop_He_Pa, Radius_First_Stop_He; | |
2283 float Allow_Grad_First_Stop_N2_Pa, Radius_First_Stop_N2; | |
2284 | |
2285 //=============================================================================== | |
2286 // LO//AL ARRAYS | |
2287 //=============================================================================== | |
2288 // float Radius1_He[16], Radius2_He[16]; | |
2289 // float Radius1_N2[16], Radius2_N2[16]; | |
2290 float root_factor; | |
2291 | |
2292 //=============================================================================== | |
2293 // CALCULATIONS | |
2294 //=============================================================================== | |
2295 Next_Stop = *Deco_Stop_Depth - *Step_Size; | |
2296 | |
2297 Ambient_Pressure_First_Stop = *First_Stop_Depth + | |
2298 barometric_pressure; | |
2299 | |
2300 Ambient_Pressure_Next_Stop = Next_Stop + barometric_pressure; | |
2301 | |
2302 Amb_Press_First_Stop_Pascals = (Ambient_Pressure_First_Stop/UNITS_FACTOR) * 101325.0f; | |
2303 | |
2304 Amb_Press_Next_Stop_Pascals = | |
2305 (Ambient_Pressure_Next_Stop/UNITS_FACTOR) * 101325.0f; | |
2306 root_factor = powf(Amb_Press_First_Stop_Pascals/Amb_Press_Next_Stop_Pascals,1.0f / 3.0f); | |
2307 | |
2308 for( i = 0; i < 16;i++) | |
2309 { | |
2310 Allow_Grad_First_Stop_He_Pa = | |
2311 (allowable_gradient_he[i]/UNITS_FACTOR) * 101325.0f; | |
2312 | |
2313 Radius_First_Stop_He = (2.0f * SURFACE_TENSION_GAMMA) / | |
2314 Allow_Grad_First_Stop_He_Pa; | |
2315 | |
2316 // Radius1_He[i] = Radius_First_Stop_He; | |
2317 A = Amb_Press_Next_Stop_Pascals; | |
2318 B = -2.0f * SURFACE_TENSION_GAMMA; | |
2319 C = (Amb_Press_First_Stop_Pascals + (2.0f * SURFACE_TENSION_GAMMA)/ | |
2320 Radius_First_Stop_He)* Radius_First_Stop_He* | |
2321 (Radius_First_Stop_He*(Radius_First_Stop_He)); | |
2322 Low_Bound = Radius_First_Stop_He; | |
2323 High_Bound = Radius_First_Stop_He * root_factor; | |
2324 //*pow(Amb_Press_First_Stop_Pascals/Amb_Press_Next_Stop_Pascals,1.0/3.0); | |
2325 //*(Amb_Press_First_Stop_Pascals/Amb_Press_Next_Stop_Pascals)**(1.0/3.0); | |
2326 | |
2327 radius_root_finder(&A,&B,&C, &Low_Bound, &High_Bound, | |
2328 &Ending_Radius); | |
2329 | |
2330 // Radius2_He[i] = Ending_Radius; | |
2331 Deco_Gradient_Pascals = (2.0f * SURFACE_TENSION_GAMMA) / | |
2332 Ending_Radius; | |
2333 | |
2334 deco_gradient_he[i] = (Deco_Gradient_Pascals / 101325.0f)* | |
2335 UNITS_FACTOR; | |
2336 | |
2337 } | |
2338 | |
2339 for( i = 0; i < 16;i++) | |
2340 { | |
2341 Allow_Grad_First_Stop_N2_Pa = | |
2342 (allowable_gradient_n2[i]/UNITS_FACTOR) * 101325.0f; | |
2343 | |
2344 Radius_First_Stop_N2 = (2.0f * SURFACE_TENSION_GAMMA) / | |
2345 Allow_Grad_First_Stop_N2_Pa; | |
2346 | |
2347 // Radius1_N2[i] = Radius_First_Stop_N2; | |
2348 A = Amb_Press_Next_Stop_Pascals; | |
2349 B = -2.0f * SURFACE_TENSION_GAMMA; | |
2350 C = (Amb_Press_First_Stop_Pascals + (2.0f * SURFACE_TENSION_GAMMA)/ | |
2351 Radius_First_Stop_N2)* Radius_First_Stop_N2* | |
2352 (Radius_First_Stop_N2*(Radius_First_Stop_N2)); | |
2353 Low_Bound = Radius_First_Stop_N2; | |
2354 High_Bound = Radius_First_Stop_N2* root_factor;//pow(Amb_Press_First_Stop_Pascals/Amb_Press_Next_Stop_Pascals,1.0/3.0); | |
2355 | |
2356 //High_Bound = Radius_First_Stop_N2*exp(log(Amb_Press_First_Stop_Pascals/Amb_Press_Next_Stop_Pascals)/3); | |
2357 radius_root_finder(&A,&B,&C, &Low_Bound, &High_Bound, | |
2358 &Ending_Radius); | |
2359 | |
2360 // Radius2_N2[i] = Ending_Radius; | |
2361 Deco_Gradient_Pascals = (2.0f * SURFACE_TENSION_GAMMA) / | |
2362 Ending_Radius; | |
2363 | |
2364 deco_gradient_n2[i] = (Deco_Gradient_Pascals / 101325.0f)* | |
2365 UNITS_FACTOR; | |
2366 } | |
2367 } | |
2368 | |
2369 /* =============================================================================== */ | |
2370 // vpm_calc_nullzeit | |
2371 // Purpose: This function calcs zero time (time where no decostops are needed) | |
2372 //=============================================================================== | |
2373 int vpm_calc_nullzeit(void) | |
2374 { | |
2375 static float future_helium_pressure[16]; | |
2376 static float future_nitrogen_pressure[16]; | |
2377 static int temp_segment_time; | |
2378 static int mix_number; | |
2379 static float inspired_helium_pressure; | |
2380 static float inspired_nitrogen_pressure; | |
2381 | |
2382 float previous_helium_pressure[16]; | |
2383 float previous_nitrogen_pressure[16]; | |
2384 float ambient_pressure; | |
2385 float fraction_helium_begin; | |
2386 float fraction_nitrogen_begin; | |
2387 int i = 0; | |
2388 int count = 0; | |
2389 int status = CALC_END; | |
2390 //if(begin) | |
2391 //{ | |
2392 for(i = 0; i < 16;i++) | |
2393 { | |
2394 future_helium_pressure[i] = pInput->tissue_helium_bar[i] * 10;//tissue_He_saturation[st_dive][i] * 10; | |
2395 future_nitrogen_pressure[i] = pInput->tissue_nitrogen_bar[i] * 10; | |
2396 } | |
2397 temp_segment_time = 0; | |
2398 | |
2399 mix_number = 0; | |
2400 ambient_pressure = pInput->pressure_ambient_bar * 10; | |
2401 // fraction_helium_begin; | |
2402 // fraction_nitrogen_begin; | |
2403 decom_get_inert_gases( ambient_pressure / 10, (&pDiveSettings->decogaslist[mix_number]) , &fraction_nitrogen_begin, &fraction_helium_begin ); | |
2404 inspired_helium_pressure =(ambient_pressure - WATER_VAPOR_PRESSURE) * fraction_helium_begin; | |
2405 inspired_nitrogen_pressure =(ambient_pressure - WATER_VAPOR_PRESSURE) *fraction_nitrogen_begin; | |
2406 | |
2407 //if(!nullzeit_unter60) | |
2408 //{ | |
2409 status = CALC_END; | |
2410 while (status == CALC_END) | |
2411 { | |
2412 count++; | |
2413 //if(count == 7) | |
2414 //return CALC_NULLZEIT2; | |
2415 temp_segment_time += 60; | |
2416 if(temp_segment_time >= 300) | |
2417 { | |
2418 pDecoInfo->output_ndl_seconds = temp_segment_time * 60; | |
2419 return CALC_NULLZEIT; | |
2420 } | |
2421 run_time += 60; | |
2422 //goto L700; | |
2423 for (i = 1; i <= 16; ++i) { | |
2424 previous_helium_pressure[i-1] = future_helium_pressure[i - 1]; | |
2425 previous_nitrogen_pressure[i - 1] = future_nitrogen_pressure[i - 1]; | |
2426 future_helium_pressure[i - 1] = future_helium_pressure[i - 1] + (inspired_helium_pressure - future_helium_pressure[i - 1]) * float_buehlmann_He_factor_expositon_one_hour[i-1]; | |
2427 future_nitrogen_pressure[i - 1] = future_nitrogen_pressure[i - 1] + (inspired_nitrogen_pressure - future_nitrogen_pressure[i - 1]) * float_buehlmann_N2_factor_expositon_one_hour[i-1]; | |
2428 helium_pressure[i - 1] = future_helium_pressure[i - 1]; | |
2429 nitrogen_pressure[i - 1] = future_nitrogen_pressure[i - 1]; | |
2430 } | |
2431 vpm_calc_deco(); | |
2432 while((status = vpm_calc_critcal_volume(true,true)) == CALC_CRITICAL); | |
2433 | |
2434 } | |
2435 | |
2436 temp_segment_time -= 60; | |
2437 run_time -= 60; | |
2438 for (i = 1; i <= 16; ++i) | |
2439 { | |
2440 future_helium_pressure[i - 1] = previous_helium_pressure[i-1]; | |
2441 future_nitrogen_pressure[i - 1] = previous_nitrogen_pressure[i - 1]; | |
2442 } | |
2443 //} | |
2444 //} | |
2445 //if(!nullzeit_unter60 || begin || temp_segment_time > 10) | |
2446 //{ | |
2447 | |
2448 status = CALC_END; | |
2449 if(temp_segment_time < 60) | |
2450 nullzeit_unter60 = true; | |
2451 | |
2452 while (status == CALC_END) | |
2453 { | |
2454 // count++; | |
2455 //if(count >= 5) | |
2456 //return CALC_NULLZEIT2; | |
2457 temp_segment_time += 5; | |
2458 if(temp_segment_time >= 300) | |
2459 { | |
2460 pDecoInfo->output_ndl_seconds = temp_segment_time * 60; | |
2461 return CALC_NULLZEIT; | |
2462 } | |
2463 if(nullzeit_unter60 && temp_segment_time > 60) | |
2464 { | |
2465 nullzeit_unter60 = false; | |
2466 //tts[NULLZEIT] = temp_segment_time * 60; | |
2467 return CALC_NULLZEIT; | |
2468 } | |
2469 run_time += 5; | |
2470 //goto L700; | |
2471 for (i = 1; i <= 16; ++i) { | |
2472 previous_helium_pressure[i-1] = future_helium_pressure[i - 1]; | |
2473 previous_nitrogen_pressure[i - 1] = future_nitrogen_pressure[i - 1]; | |
2474 future_helium_pressure[i - 1] = future_helium_pressure[i - 1] + (inspired_helium_pressure - future_helium_pressure[i - 1]) * float_buehlmann_He_factor_expositon_five_minutes[i-1]; | |
2475 future_nitrogen_pressure[i - 1] = future_nitrogen_pressure[i - 1] + (inspired_nitrogen_pressure - future_nitrogen_pressure[i - 1]) * float_buehlmann_N2_factor_expositon_five_minutes[i-1]; | |
2476 helium_pressure[i - 1] = future_helium_pressure[i - 1]; | |
2477 nitrogen_pressure[i - 1] = future_nitrogen_pressure[i - 1]; | |
2478 } | |
2479 vpm_calc_deco(); | |
2480 while((status =vpm_calc_critcal_volume(true,true)) == CALC_CRITICAL); | |
2481 } | |
2482 temp_segment_time -= 5; | |
2483 run_time -= 5; | |
2484 for (i = 1; i <= 16; ++i) { | |
2485 future_helium_pressure[i - 1] = previous_helium_pressure[i-1]; | |
2486 future_nitrogen_pressure[i - 1] = previous_nitrogen_pressure[i - 1]; | |
2487 } | |
2488 status = CALC_END; | |
2489 //if(temp_segment_time < 5) | |
2490 //count = 2; | |
2491 //} | |
2492 //else | |
2493 //count = 1; | |
2494 if(temp_segment_time <= 20) | |
2495 { | |
2496 while (status == CALC_END) | |
2497 { | |
2498 //time_counter = temp_segment_time; | |
2499 //count++; | |
2500 //if(count > 2) | |
2501 //return CALC_NULLZEIT2; | |
2502 temp_segment_time += minimum_deco_stop_time; | |
2503 run_time += minimum_deco_stop_time; | |
2504 //goto L700; | |
2505 for (i = 1; i <= 16; ++i) { | |
2506 future_helium_pressure[i - 1] = future_helium_pressure[i - 1] + (inspired_helium_pressure - future_helium_pressure[i - 1]) * float_buehlmann_He_factor_expositon_one_minute[i-1]; | |
2507 future_nitrogen_pressure[i - 1] = future_nitrogen_pressure[i - 1] + (inspired_nitrogen_pressure - future_nitrogen_pressure[i - 1]) * float_buehlmann_N2_factor_expositon_one_minute[i-1]; | |
2508 helium_pressure[i - 1] = future_helium_pressure[i - 1]; | |
2509 nitrogen_pressure[i - 1] =future_nitrogen_pressure[i - 1]; | |
2510 | |
2511 } | |
2512 vpm_calc_deco(); | |
2513 while((status =vpm_calc_critcal_volume(true,true)) == CALC_CRITICAL); | |
2514 | |
2515 } | |
2516 } | |
2517 else | |
2518 temp_segment_time += 5; | |
2519 pDecoInfo->output_ndl_seconds = temp_segment_time * 60; | |
2520 if(temp_segment_time > 1) | |
2521 return CALC_NULLZEIT; | |
2522 else | |
2523 return CALC_BEGIN; | |
2524 } |