Mercurial > public > hwos_code
comparison src/p2_deco.c @ 521:06e9370c6d75
CHANGE: Apply safety margin parameters to both models (GF and non-GF)
Put B?hlmann constants in code for readability
Fix unused gas warning (Do not warn)
author | heinrichsweikamp |
---|---|
date | Fri, 04 Aug 2017 16:01:28 +0200 |
parents | ff1e6adf55ad |
children | 4d70a93b18cb |
comparison
equal
deleted
inserted
replaced
520:1d74d6221084 | 521:06e9370c6d75 |
---|---|
87 // 2013/05/08: [jDG] A. Salm remark: NOAA tables for CNS are in ATA, not bar. | 87 // 2013/05/08: [jDG] A. Salm remark: NOAA tables for CNS are in ATA, not bar. |
88 // 2013/12/21: [jDG] Fix CNS calculation in decoplan w/o marked gas switch | 88 // 2013/12/21: [jDG] Fix CNS calculation in decoplan w/o marked gas switch |
89 // 2014/06/16: [jDG] Fix Helium diluant. Fix volumes with many travel mix. | 89 // 2014/06/16: [jDG] Fix Helium diluant. Fix volumes with many travel mix. |
90 // 2014/06/29: [mH] Compute int_O_ceiling | 90 // 2014/06/29: [mH] Compute int_O_ceiling |
91 // 2015/06/12: [jDG] Fix NDL prediction while desaturating with the Buhlmann model. | 91 // 2015/06/12: [jDG] Fix NDL prediction while desaturating with the Buhlmann model. |
92 // 2017/08/04: [mH] Switch to absolute GF everywhere and apply safety margin parameters to both models (GF and non-GF), fixes from Ralph Lembcke | |
92 // | 93 // |
93 // TODO: | 94 // TODO: |
94 // | 95 // |
95 // Literature: | 96 // Literature: |
96 // Buhlmann, Albert: Tauchmedizin; 4. Auflage [2002]; | 97 // Buhlmann, Albert: Tauchmedizin; 4. Auflage [2002]; |
256 // | 257 // |
257 #ifndef UNIX | 258 #ifndef UNIX |
258 # pragma romdata buhlmann_tables = 0x1DD00 // Needs to be in UPPER bank. | 259 # pragma romdata buhlmann_tables = 0x1DD00 // Needs to be in UPPER bank. |
259 #endif | 260 #endif |
260 | 261 |
261 #include "p2_tables.romdata" // new table for deco_main_v.101 (var_N2_a modified) | 262 rom const float buhlmann_ab[4*16] = { |
263 // Data ZH-L16C, from Bühlmann Tauchmedizin 2002, option 1a (4mn) | |
264 // a for N2 b for N2 a of He b for He | |
265 1.2599, 0.5050, 1.7424, 0.4245, | |
266 1.0000, 0.6514, 1.3830, 0.5747, | |
267 0.8618, 0.7222, 1.1919, 0.6527, | |
268 0.7562, 0.7825, 1.0458, 0.7223, | |
269 0.6200, 0.8126, 0.9220, 0.7582, | |
270 0.5043, 0.8434, 0.8205, 0.7957, | |
271 0.4410, 0.8693, 0.7305, 0.8279, | |
272 0.4000, 0.8910, 0.6502, 0.8553, | |
273 0.3750, 0.9092, 0.5950, 0.8757, | |
274 0.3500, 0.9222, 0.5545, 0.8903, | |
275 0.3295, 0.9319, 0.5333, 0.8997, | |
276 0.3065, 0.9403, 0.5189, 0.9073, | |
277 0.2835, 0.9477, 0.5181, 0.9122, | |
278 0.2610, 0.9544, 0.5176, 0.9171, | |
279 0.2480, 0.9602, 0.5172, 0.9217, | |
280 0.2327, 0.9653, 0.5119, 0.9267 | |
281 }; | |
282 | |
283 rom const float buhlmann_ht[2*16] = { | |
284 // Compartiment half-life, in minute | |
285 //-- N2 ---- He --------------------------------------------------------------------- | |
286 4.0, 1.51, | |
287 8.0, 3.02, | |
288 12.5, 4.72, | |
289 18.5, 6.99, | |
290 27.0, 10.21, | |
291 38.3, 14.48, | |
292 54.3, 20.53, | |
293 77.0, 29.11, | |
294 109.0, 41.20, | |
295 146.0, 55.19, | |
296 187.0, 70.69, | |
297 239.0, 90.34, | |
298 305.0, 115.29, | |
299 390.0, 147.42, | |
300 498.0, 188.24, | |
301 635.0, 240.03 | |
302 }; | |
303 | |
304 rom const float e2secs[2*16] = { | |
305 // result of 1 - 2^(-1/(30sec*HT)) | |
306 //---- N2 ------------- He ------------ | |
307 5.75958E-03, 1.51848E-02, | |
308 2.88395E-03, 7.62144E-03, | |
309 1.84669E-03, 4.88315E-03, | |
310 1.24813E-03, 3.29997E-03, | |
311 8.55371E-04, 2.26041E-03, | |
312 6.03079E-04, 1.59437E-03, | |
313 4.25414E-04, 1.12479E-03, | |
314 3.00019E-04, 7.93395E-04, | |
315 2.11949E-04, 5.60641E-04, | |
316 1.58240E-04, 4.18555E-04, | |
317 1.23548E-04, 3.26795E-04, | |
318 9.66686E-05, 2.55722E-04, | |
319 7.57509E-05, 2.00387E-04, | |
320 5.92416E-05, 1.56716E-04, | |
321 4.63943E-05, 1.22734E-04, | |
322 3.63850E-05, 9.62538E-05 | |
323 //------------------------------------- | |
324 }; | |
325 | |
326 rom const float e1min[2*16] = { | |
327 // Integration constant for 1 minute, | |
328 // Ie. 1- 2^(-1/HT) | |
329 //----- N2 --------- e 1min He -------- | |
330 1.59104E-01, 3.68109E-01, | |
331 8.29960E-02, 2.05084E-01, | |
332 5.39424E-02, 1.36579E-01, | |
333 3.67742E-02, 9.44046E-02, | |
334 2.53454E-02, 6.56359E-02, | |
335 1.79351E-02, 4.67416E-02, | |
336 1.26840E-02, 3.31991E-02, | |
337 8.96152E-03, 2.35301E-02, | |
338 6.33897E-03, 1.66832E-02, | |
339 4.73633E-03, 1.24808E-02, | |
340 3.69981E-03, 9.75753E-03, | |
341 2.89600E-03, 7.64329E-03, | |
342 2.27003E-03, 5.99417E-03, | |
343 1.77572E-03, 4.69082E-03, | |
344 1.39089E-03, 3.67548E-03, | |
345 1.09097E-03, 2.88359E-03 | |
346 //------------------------------------- | |
347 }; | |
348 | |
349 rom const float e10min[2*16] = { | |
350 // The 10 min Value in float notation: | |
351 // result of 1 - 2^(-10/ht) | |
352 //---- N2 -------------- He ----------- | |
353 8.23223E-01, 9.89851E-01, | |
354 5.79552E-01, 8.99258E-01, | |
355 4.25651E-01, 7.69737E-01, | |
356 3.12487E-01, 6.29027E-01, | |
357 2.26416E-01, 4.92821E-01, | |
358 1.65547E-01, 3.80407E-01, | |
359 1.19840E-01, 2.86538E-01, | |
360 8.60863E-02, 2.11886E-01, | |
361 6.16117E-02, 1.54849E-01, | |
362 4.63665E-02, 1.18026E-01, | |
363 3.63881E-02, 9.34005E-02, | |
364 2.85855E-02, 7.38569E-02, | |
365 2.24698E-02, 5.83504E-02, | |
366 1.76160E-02, 4.59303E-02, | |
367 1.38222E-02, 3.61528E-02, | |
368 1.08563E-02, 2.84646E-02 | |
369 //------------------------------------- | |
370 }; | |
262 | 371 |
263 ////////////////////////////////////////////////////////////////////////////// | 372 ////////////////////////////////////////////////////////////////////////////// |
264 ////////////////////////////////////////////////////////////////////////////// | 373 ////////////////////////////////////////////////////////////////////////////// |
265 ////////////////////////////// THE SUBROUTINES /////////////////////////////// | 374 ////////////////////////////// THE SUBROUTINES /////////////////////////////// |
266 ////////////////////////////////////////////////////////////////////////////// | 375 ////////////////////////////////////////////////////////////////////////////// |
642 ////////////////////////////////////////////////////////////////////////////// | 751 ////////////////////////////////////////////////////////////////////////////// |
643 // temp_tissue_safety // | 752 // temp_tissue_safety // |
644 // | 753 // |
645 // outsourced in v.102 | 754 // outsourced in v.102 |
646 // | 755 // |
647 // Apply safety factors for brand ZH-L16 model. | 756 // Apply safety factors for both ZH-L16 models. |
648 // | 757 // |
649 static void temp_tissue_safety(void) | 758 static void temp_tissue_safety(void) |
650 { | 759 { |
651 assert( 0.0 < float_desaturation_multiplier && float_desaturation_multiplier <= 1.0 ); | 760 assert( 0.0 < float_desaturation_multiplier && float_desaturation_multiplier <= 1.0 ); |
652 assert( 1.0 <= float_saturation_multiplier && float_saturation_multiplier <= 2.0 ); | 761 assert( 1.0 <= float_saturation_multiplier && float_saturation_multiplier <= 2.0 ); |
653 | 762 |
654 if( char_I_deco_model == 0 ) | |
655 { | |
656 if( temp_tissue < 0.0 ) | 763 if( temp_tissue < 0.0 ) |
657 temp_tissue *= float_desaturation_multiplier; | 764 temp_tissue *= float_desaturation_multiplier; |
658 else | 765 else |
659 temp_tissue *= float_saturation_multiplier; | 766 temp_tissue *= float_saturation_multiplier; |
660 } | |
661 } | 767 } |
662 | 768 |
663 ////////////////////////////////////////////////////////////////////////////// | 769 ////////////////////////////////////////////////////////////////////////////// |
664 ////////////////////////////////////////////////////////////////////////////// | 770 ////////////////////////////////////////////////////////////////////////////// |
665 // ** THE JUMP-IN CODE ** | 771 // ** THE JUMP-IN CODE ** |
794 { | 900 { |
795 assert( !sim_gas_last_depth || sim_gas_last_depth > switch_deco ); | 901 assert( !sim_gas_last_depth || sim_gas_last_depth > switch_deco ); |
796 | 902 |
797 sim_gas_last_depth = switch_deco; | 903 sim_gas_last_depth = switch_deco; |
798 sim_gas_last_used = switch_last; | 904 sim_gas_last_used = switch_last; |
799 return 0; | |
800 } | 905 } |
801 return 0; | 906 return 0; |
802 } | 907 } |
803 | 908 |
804 ////////////////////////////////////////////////////////////////////////////// | 909 ////////////////////////////////////////////////////////////////////////////// |
905 clear_deco_table(); | 1010 clear_deco_table(); |
906 char_O_deco_status = 0; | 1011 char_O_deco_status = 0; |
907 char_O_nullzeit = 0; | 1012 char_O_nullzeit = 0; |
908 int_O_ascenttime = 0; | 1013 int_O_ascenttime = 0; |
909 char_O_gradient_factor = 0; | 1014 char_O_gradient_factor = 0; |
910 char_O_relative_gradient_GF = 0; | |
911 | 1015 |
912 calc_lead_tissue_limit = 0.0; | 1016 calc_lead_tissue_limit = 0.0; |
913 char_O_gtissue_no = 0; | 1017 char_O_gtissue_no = 0; |
914 } | 1018 } |
915 | 1019 |
1412 | 1516 |
1413 //---- Add 10min/1min to N2/He tissues | 1517 //---- Add 10min/1min to N2/He tissues |
1414 overlay float dTN2 = (ppN2 - tN2) * var_N2_e; | 1518 overlay float dTN2 = (ppN2 - tN2) * var_N2_e; |
1415 overlay float dTHe = (ppHe - tHe) * var_He_e; | 1519 overlay float dTHe = (ppHe - tHe) * var_He_e; |
1416 | 1520 |
1417 //---- Apply security margin when using the non-GF model | 1521 //---- Apply security margin for both models |
1418 if( char_I_deco_model == 0 ) | |
1419 { | |
1420 // NDL can be computed while ascending... SO we have | 1522 // NDL can be computed while ascending... SO we have |
1421 // to check wether we are saturating or desaturating. | 1523 // to check wether we are saturating or desaturating. |
1422 if( dTN2 > 0.0 ) dTN2 *= float_saturation_multiplier; | 1524 if( dTN2 > 0.0 ) dTN2 *= float_saturation_multiplier; |
1423 else dTN2 *= float_desaturation_multiplier; | 1525 else dTN2 *= float_desaturation_multiplier; |
1424 | 1526 |
1425 if( dTHe > 0.0 ) dTHe *= float_saturation_multiplier; | 1527 if( dTHe > 0.0 ) dTHe *= float_saturation_multiplier; |
1426 else dTHe *= float_saturation_multiplier; | 1528 else dTHe *= float_saturation_multiplier; |
1427 } | 1529 |
1428 else // Or GF-based model | 1530 if (char_I_deco_model != 0 ) |
1429 M0 = GF_high * (M0 - pres_surface) + pres_surface; | 1531 M0 = GF_high * (M0 - pres_surface) + pres_surface; |
1430 | 1532 |
1431 //---- Simulate off-gasing while going to surface | 1533 //---- Simulate off-gasing while going to surface |
1432 // TODO ! | 1534 // TODO ! |
1433 // dTN2 -= exp( ... ascent time ... ppN2...) | 1535 // dTN2 -= exp( ... ascent time ... ppN2...) |
1698 if( gf > 254.5 ) gf = 255.0; | 1800 if( gf > 254.5 ) gf = 255.0; |
1699 if( gf < 0.0 ) gf = 0.0; | 1801 if( gf < 0.0 ) gf = 0.0; |
1700 } | 1802 } |
1701 char_O_gradient_factor = (unsigned char)(gf+0.5f); | 1803 char_O_gradient_factor = (unsigned char)(gf+0.5f); |
1702 | 1804 |
1703 if( char_I_deco_model != 0 ) // calculate relative gradient factor | |
1704 { | |
1705 overlay float rgf; | |
1706 | |
1707 if( low_depth < 3 ) | |
1708 rgf = GF_high; | |
1709 else | |
1710 { | |
1711 overlay float temp1 = low_depth * METER_TO_BAR; | |
1712 overlay float temp2 = pres_respiration - pres_surface; | |
1713 | |
1714 if (temp2 <= 0) | |
1715 rgf = GF_high; | |
1716 else if (temp2 >= temp1) | |
1717 rgf = GF_low; | |
1718 else | |
1719 rgf = GF_low + (temp1 - temp2)/temp1*GF_delta; | |
1720 } | |
1721 | |
1722 rgf = gf / rgf; // gf is already in percent | |
1723 if( rgf < 0.0 ) rgf = 0.0; | |
1724 if( rgf > 254.5 ) rgf = 255.0; | |
1725 char_O_relative_gradient_GF = (unsigned char)(rgf+0.5f); | |
1726 } | |
1727 else | |
1728 { | |
1729 // calc relative gradient factor | |
1730 char_O_relative_gradient_GF = char_O_gradient_factor; | |
1731 } | |
1732 } | 1805 } |
1733 | 1806 |
1734 ////////////////////////////////////////////////////////////////////////////// | 1807 ////////////////////////////////////////////////////////////////////////////// |
1735 // deco_calc_desaturation_time | 1808 // deco_calc_desaturation_time |
1736 // | 1809 // |
1881 // desaturation slowed down to 70,42%. | 1954 // desaturation slowed down to 70,42%. |
1882 // | 1955 // |
1883 static void calc_dive_interval(void) | 1956 static void calc_dive_interval(void) |
1884 { | 1957 { |
1885 overlay unsigned char t; | 1958 overlay unsigned char t; |
1886 overlay unsigned char backup_model; | 1959 |
1887 | |
1888 //---- Initialize simulation parameters ---------------------------------- | 1960 //---- Initialize simulation parameters ---------------------------------- |
1889 N2_ratio = 0.7902; // FIXED, sum lt. buehlmann | 1961 N2_ratio = 0.7902; // FIXED, sum lt. buehlmann |
1890 pres_respiration = pres_surface = int_I_pres_surface * 0.001; | 1962 pres_respiration = pres_surface = int_I_pres_surface * 0.001; |
1891 ppN2 = N2_ratio * (pres_respiration - ppWater); | 1963 ppN2 = N2_ratio * (pres_respiration - ppWater); |
1892 ppHe = 0.0; | 1964 ppHe = 0.0; |
1893 float_desaturation_multiplier = char_I_desaturation_multiplier * (0.01 * SURFACE_DESAT_FACTOR); | 1965 float_desaturation_multiplier = char_I_desaturation_multiplier * (0.01 * SURFACE_DESAT_FACTOR); |
1894 float_saturation_multiplier = char_I_saturation_multiplier * 0.01; | 1966 float_saturation_multiplier = char_I_saturation_multiplier * 0.01; |
1895 | 1967 |
1896 // Make sure SURFACE_DESAT_FACTOR is applied: | |
1897 backup_model = char_I_deco_model; | |
1898 char_I_deco_model = 0; | |
1899 | |
1900 //---- Perform simulation ------------------------------------------------ | 1968 //---- Perform simulation ------------------------------------------------ |
1901 for(t=0; t<char_I_dive_interval; ++t) | 1969 for(t=0; t<char_I_dive_interval; ++t) |
1902 { | 1970 { |
1903 calc_tissue(2); // period = 10min. | 1971 calc_tissue(2); // period = 10min. |
1904 CNS_fraction = 0.92587471 * CNS_fraction; // Half-time = 90min: (1/2)^(1/9) | 1972 CNS_fraction = 0.92587471 * CNS_fraction; // Half-time = 90min: (1/2)^(1/9) |
1905 } | 1973 } |
1906 assert( 0.0 <= CNS_fraction && CNS_fraction <= 9.99 ); // 999 % | 1974 assert( 0.0 <= CNS_fraction && CNS_fraction <= 9.99 ); // 999 % |
1907 int_O_CNS_fraction = (unsigned short)(CNS_fraction * 100.0 + 0.5); | 1975 int_O_CNS_fraction = (unsigned short)(CNS_fraction * 100.0 + 0.5); |
1908 | 1976 |
1909 //---- Restore model ----------------------------------------------------- | |
1910 char_I_deco_model = backup_model; | |
1911 } | 1977 } |
1912 | 1978 |
1913 ////////////////////////////////////////////////////////////////////////////// | 1979 ////////////////////////////////////////////////////////////////////////////// |
1914 // deco_clear_CNS_fraction | 1980 // deco_clear_CNS_fraction |
1915 // | 1981 // |