diff options
author | Jan Darowski <jan.darowski@gmail.com> | 2015-08-15 14:03:08 +0200 |
---|---|---|
committer | Jan Darowski <jan.darowski@gmail.com> | 2015-08-15 14:09:51 +0200 |
commit | a828d528f925cdb5c300dc176c4e6b4e24dabf67 (patch) | |
tree | c79626af6e0d4e1e4046e634b3a36862608f0dc7 | |
parent | a3e87bf1a1901f4e4a17d7344599f361a8f75743 (diff) | |
download | subsurface-a828d528f925cdb5c300dc176c4e6b4e24dabf67.tar.gz |
VPM-B: Add simple Boyle's law compensation.
This is a very basic implementation that uses bin search for solving the cubic.
It's not called anywhere at this stage, needs to be changed to analytic solution.
Signed-off-by: Jan Darowski <jan.darowski@gmail.com>
-rw-r--r-- | deco.c | 57 |
1 files changed, 48 insertions, 9 deletions
@@ -114,6 +114,11 @@ double allowable_n2_gradient[16]; double allowable_he_gradient[16]; double total_gradient[16]; +double bottom_n2_gradient[16]; +double bottom_he_gradient[16]; + +double initial_n2_gradient[16]; +double initial_he_gradient[16]; static double tissue_tolerance_calc(const struct dive *dive) { @@ -231,8 +236,8 @@ void vpmb_start_gradient() double gradient_n2, gradient_he; for (ci = 0; ci < 16; ++ci) { - allowable_n2_gradient[ci] = 2.0 * (vpmb_config.surface_tension_gamma / vpmb_config.skin_compression_gammaC) * ((vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma) / n2_regen_radius[ci]); - allowable_he_gradient[ci] = 2.0 * (vpmb_config.surface_tension_gamma / vpmb_config.skin_compression_gammaC) * ((vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma) / he_regen_radius[ci]); + initial_n2_gradient[ci] = bottom_n2_gradient[ci] = allowable_n2_gradient[ci] = 2.0 * (vpmb_config.surface_tension_gamma / vpmb_config.skin_compression_gammaC) * ((vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma) / n2_regen_radius[ci]); + initial_he_gradient[ci] = bottom_he_gradient[ci] = allowable_he_gradient[ci] = 2.0 * (vpmb_config.surface_tension_gamma / vpmb_config.skin_compression_gammaC) * ((vpmb_config.skin_compression_gammaC - vpmb_config.surface_tension_gamma) / he_regen_radius[ci]); total_gradient[ci] = ((allowable_n2_gradient[ci] * tissue_n2_sat[ci]) + (allowable_he_gradient[ci] * tissue_he_sat[ci])) / (tissue_n2_sat[ci] + tissue_he_sat[ci]); } @@ -244,19 +249,53 @@ void vpmb_next_gradient(double deco_time) double gradient_n2, gradient_he; double n2_b, n2_c; double he_b, he_c; - deco_time /= 60.0 ; + double desat_time = deco_time / 60.0; for (ci = 0; ci < 16; ++ci) { - n2_b = allowable_n2_gradient[ci] + ((vpmb_config.crit_volume_lambda * vpmb_config.surface_tension_gamma) / (vpmb_config.skin_compression_gammaC * (deco_time + buehlmann_N2_t_halflife[ci] * 60.0 / log(2.0)))); - he_b = allowable_he_gradient[ci] + ((vpmb_config.crit_volume_lambda * vpmb_config.surface_tension_gamma) / (vpmb_config.skin_compression_gammaC * (deco_time + buehlmann_He_t_halflife[ci] * 60.0 / log(2.0)))); + n2_b = initial_n2_gradient[ci] + (vpmb_config.crit_volume_lambda * vpmb_config.surface_tension_gamma) / (vpmb_config.skin_compression_gammaC * desat_time); + he_b = initial_he_gradient[ci] + (vpmb_config.crit_volume_lambda * vpmb_config.surface_tension_gamma) / (vpmb_config.skin_compression_gammaC * desat_time); n2_c = vpmb_config.surface_tension_gamma * vpmb_config.surface_tension_gamma * vpmb_config.crit_volume_lambda * max_n2_crushing_pressure[ci]; - n2_c = n2_c / (vpmb_config.skin_compression_gammaC * vpmb_config.skin_compression_gammaC * (deco_time + buehlmann_N2_t_halflife[ci] * 60.0 / log(2.0))); + n2_c = n2_c / (vpmb_config.skin_compression_gammaC * vpmb_config.skin_compression_gammaC * desat_time); he_c = vpmb_config.surface_tension_gamma * vpmb_config.surface_tension_gamma * vpmb_config.crit_volume_lambda * max_he_crushing_pressure[ci]; - he_c = he_c / (vpmb_config.skin_compression_gammaC * vpmb_config.skin_compression_gammaC * (deco_time + buehlmann_He_t_halflife[ci] * 60.0 / log(2.0))); + he_c = he_c / (vpmb_config.skin_compression_gammaC * vpmb_config.skin_compression_gammaC * desat_time); + + bottom_n2_gradient[ci] = allowable_n2_gradient[ci] = 0.5 * ( n2_b + sqrt(n2_b * n2_b - 4.0 * n2_c)); + bottom_he_gradient[ci] = allowable_he_gradient[ci] = 0.5 * ( he_b + sqrt(he_b * he_b - 4.0 * he_c)); + + total_gradient[ci] = ((allowable_n2_gradient[ci] * tissue_n2_sat[ci]) + (allowable_he_gradient[ci] * tissue_he_sat[ci])) / (tissue_n2_sat[ci] + tissue_he_sat[ci]); + } +} - allowable_n2_gradient[ci] = 0.5 * ( n2_b + sqrt(n2_b * n2_b - 4.0 * n2_c)); - allowable_he_gradient[ci] = 0.5 * ( he_b + sqrt(he_b * he_b - 4.0 * he_c)); +double update_gradient(double first_stop_pressure, double next_stop_pressure, double first_gradient) +{ + double first_radius = 2.0 * vpmb_config.surface_tension_gamma / first_gradient; + double A = next_stop_pressure; + double B = -2.0 * vpmb_config.surface_tension_gamma; + double C = (first_stop_pressure + 2.0 * vpmb_config.surface_tension_gamma / first_radius) * pow(first_radius, 3.0); + + double low = first_radius; + double high = first_radius * pow(first_stop_pressure / next_stop_pressure, (1.0/3.0)); + double next_radius; + double value; + int ci; + for (ci = 0; ci < 100; ++ci){ + next_radius = (high + low) /2.0; + value = A * pow(next_radius, 3.0) - B * next_radius * next_radius - C; + if (value < 0) + low = next_radius; + else + high = next_radius; + } + return 2.0 * vpmb_config.surface_tension_gamma / next_radius; +} + +void boyles_law(double first_stop_pressure, double next_stop_pressure) +{ + int ci; + for (ci = 0; ci < 16; ++ci) { + allowable_n2_gradient[ci] = update_gradient(first_stop_pressure, next_stop_pressure, bottom_n2_gradient[ci]); + allowable_he_gradient[ci] = update_gradient(first_stop_pressure, next_stop_pressure, bottom_he_gradient[ci]); total_gradient[ci] = ((allowable_n2_gradient[ci] * tissue_n2_sat[ci]) + (allowable_he_gradient[ci] * tissue_he_sat[ci])) / (tissue_n2_sat[ci] + tissue_he_sat[ci]); } |