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