Mercurial > public > ostc4
annotate Discovery/Src/vpm.c @ 1053:36fa1c44e597 Icon_Integration
Added upload command for icon:
It is now possible to upload a custom icon which is shown during startup and while writing settings (instead of the HW string). The icons are limited to 256 colors and 800x480 pixels. The icon may not be larger than 200kByte because of storage avability. For upload the same CRC functions as for the common firmware updates are in use,
| author | Ideenmodellierer |
|---|---|
| date | Wed, 31 Dec 2025 17:49:05 +0100 |
| parents | d91345e9c009 |
| 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 |
