Mercurial > public > ostc4
comparison Discovery/Src/vpm.c @ 902:d4622533271d Evo_2_23
VPM table mode:
Because of the model maths, usage of float data type and so on it may happen that the TTS decreases during ascent and continues calculation of the vpm. To keep the values stable the vpm table mode has been introduces. Instead of continously calculation of the stops the stop time is decreased if the diver is close to a deco stop. If the table is violated (e.g. by not doing gas change) the table will be updated to the new, longer runtime. The table will not be switch back to a shorter version in case e.g. the missed gas change is performed
author | Ideenmodellierer |
---|---|
date | Wed, 02 Oct 2024 22:18:19 +0200 |
parents | a0900e4df15c |
children | 46a21ff3f5ab |
comparison
equal
deleted
inserted
replaced
901:e4e9acfde839 | 902:d4622533271d |
---|---|
130 static float rate_change[11]; | 130 static float rate_change[11]; |
131 static short mix_change[11]; | 131 static short mix_change[11]; |
132 | 132 |
133 static const _Bool vpm_b = true; | 133 static const _Bool vpm_b = true; |
134 | 134 |
135 static SDecoinfo vpmTable; | |
136 | |
135 extern const float float_buehlmann_N2_factor_expositon_20_seconds[]; | 137 extern const float float_buehlmann_N2_factor_expositon_20_seconds[]; |
136 extern const float float_buehlmann_He_factor_expositon_20_seconds[]; | 138 extern const float float_buehlmann_He_factor_expositon_20_seconds[]; |
137 extern const float float_buehlmann_N2_factor_expositon_one_minute[]; | 139 extern const float float_buehlmann_N2_factor_expositon_one_minute[]; |
138 extern const float float_buehlmann_He_factor_expositon_one_minute[]; | 140 extern const float float_buehlmann_He_factor_expositon_one_minute[]; |
139 extern const float float_buehlmann_N2_factor_expositon_five_minutes[]; | 141 extern const float float_buehlmann_N2_factor_expositon_five_minutes[]; |
217 float vpm_get_CNS(void) | 219 float vpm_get_CNS(void) |
218 { | 220 { |
219 return gCNS_VPM; | 221 return gCNS_VPM; |
220 } | 222 } |
221 | 223 |
224 | |
225 void vpm_maintainTable(SLifeData* pLifeData,SDecoinfo* pDecoInfo) | |
226 { | |
227 static uint32_t lastDiveSecond = 0; | |
228 uint8_t actual_deco_stop = 0; | |
229 int8_t index = 0; | |
230 uint8_t decreaseStopTime = 1; | |
231 | |
232 if(lastDiveSecond < pLifeData->dive_time_seconds) | |
233 { | |
234 lastDiveSecond = pLifeData->dive_time_seconds; | |
235 actual_deco_stop = decom_get_actual_deco_stop((SDiveState*)stateUsed); | |
236 | |
237 pDecoInfo->output_time_to_surface_seconds = 0; | |
238 for(index = DECOINFO_STRUCT_MAX_STOPS -1 ;index >= 0; index--) | |
239 { | |
240 if(pDecoInfo->output_stop_length_seconds[index] > 0) | |
241 { | |
242 if(decreaseStopTime) | |
243 { | |
244 if((pLifeData->depth_meter > (float)(actual_deco_stop - 0.5)) | |
245 && (pLifeData->depth_meter < (float)actual_deco_stop + 1.5)) | |
246 { | |
247 pDecoInfo->output_stop_length_seconds[index]--; | |
248 decreaseStopTime = 0; | |
249 } | |
250 } | |
251 pDecoInfo->output_time_to_surface_seconds += pDecoInfo->output_stop_length_seconds[index]; | |
252 } | |
253 } | |
254 pDecoInfo->output_time_to_surface_seconds += pLifeData->depth_meter / 10.0 * 60.0; | |
255 } | |
256 else if(lastDiveSecond > pLifeData->dive_time_seconds) | |
257 { | |
258 lastDiveSecond = pLifeData->dive_time_seconds; | |
259 } | |
260 } | |
261 | |
222 int vpm_calc(SLifeData* pINPUT, | 262 int vpm_calc(SLifeData* pINPUT, |
223 SDiveSettings* pSettings, | 263 SDiveSettings* pSettings, |
224 SVpm* pVPM, | 264 SVpm* pVPM, |
225 SDecoinfo* | 265 SDecoinfo* |
226 pDECOINFO, | 266 pDECOINFO, |
227 int calc_what) | 267 int calc_what) |
228 { | 268 { |
269 static uint8_t vpmTableActive = 0; | |
270 | |
229 vpm_init_1(); | 271 vpm_init_1(); |
230 //decom_CreateGasChangeList(pSettings, pINPUT); | 272 //decom_CreateGasChangeList(pSettings, pINPUT); |
231 vpm_calc_what = calc_what; | 273 vpm_calc_what = calc_what; |
232 /**clear decoInfo*/ | 274 /**clear decoInfo*/ |
275 | |
276 if((vpmTableActive) && (vpm_calc_what == DECOSTOPS)) | |
277 { | |
278 memcpy(&vpmTable, pDECOINFO, sizeof(SDecoinfo)); /* save changes done by e.g. the simulator */ | |
279 } | |
233 pDECOINFO->output_time_to_surface_seconds = 0; | 280 pDECOINFO->output_time_to_surface_seconds = 0; |
234 pDECOINFO->output_ndl_seconds = 0; | 281 pDECOINFO->output_ndl_seconds = 0; |
235 pDECOINFO->output_ceiling_meter = 0; | 282 pDECOINFO->output_ceiling_meter = 0; |
236 pDECOINFO->super_saturation = 0; | 283 pDECOINFO->super_saturation = 0; |
237 uint8_t tmp_calc_status; | 284 uint8_t tmp_calc_status; |
278 } | 325 } |
279 } | 326 } |
280 | 327 |
281 //Only Decostops not futute stops | 328 //Only Decostops not futute stops |
282 if(vpm_calc_what == DECOSTOPS) | 329 if(vpm_calc_what == DECOSTOPS) |
330 { | |
283 vpm_calc_status = tmp_calc_status; | 331 vpm_calc_status = tmp_calc_status; |
332 if(pSettings->vpm_tableMode) /* store the most conservative deco plan and stick to it. */ | |
333 { | |
334 if((int16_t)(pDECOINFO->output_time_to_surface_seconds - vpmTable.output_time_to_surface_seconds) > 60) | |
335 { | |
336 memcpy(&vpmTable, pDECOINFO, sizeof(SDecoinfo)); | |
337 vpmTableActive = 1; | |
338 } | |
339 else | |
340 { | |
341 if(vpmTable.output_time_to_surface_seconds > 0) | |
342 { | |
343 vpm_maintainTable(pINPUT, &vpmTable); | |
344 vpmTable.output_ceiling_meter = pDECOINFO->output_ceiling_meter; | |
345 memcpy(pDECOINFO, &vpmTable, sizeof(SDecoinfo)); | |
346 } | |
347 } | |
348 } | |
349 } | |
284 return vpm_calc_status; | 350 return vpm_calc_status; |
285 } | 351 } |
286 | 352 |
287 void vpm_saturation_after_ascent(SLifeData* input) | 353 void vpm_saturation_after_ascent(SLifeData* input) |
288 { | 354 { |
1003 float stop_time; | 1069 float stop_time; |
1004 int count = 0; | 1070 int count = 0; |
1005 static int dp_max; | 1071 static int dp_max; |
1006 static float surfacetime; | 1072 static float surfacetime; |
1007 _Bool first_stop = false; | 1073 _Bool first_stop = false; |
1008 | 1074 float roundingValue = 0.0; |
1009 short stop_time_seconds; | 1075 |
1076 uint16_t stop_time_seconds; | |
1010 | 1077 |
1011 max_first_stop_depth = fmaxf(first_stop_depth,max_first_stop_depth); | 1078 max_first_stop_depth = fmaxf(first_stop_depth,max_first_stop_depth); |
1012 if(begin) | 1079 if(begin) |
1013 { | 1080 { |
1014 gCNS_VPM = 0; | 1081 gCNS_VPM = 0; |
1104 { | 1171 { |
1105 dp = 0; | 1172 dp = 0; |
1106 } | 1173 } |
1107 else | 1174 else |
1108 { | 1175 { |
1109 dp = 1 + (short)((deco_stop_depth - (pDiveSettings->input_second_to_last_stop_depth_bar * 10.0)) / step_size); | 1176 roundingValue = (deco_stop_depth - (pDiveSettings->input_second_to_last_stop_depth_bar * 10.0)) / step_size; |
1177 dp = 1 + r_nint(&roundingValue); | |
1110 } | 1178 } |
1111 | 1179 |
1112 //dp_max = (int)fmaxf(dp_max,dp); | 1180 //dp_max = (int)fmaxf(dp_max,dp); |
1113 if(dp > dp_max) | 1181 if(dp > dp_max) |
1114 { | 1182 { |
1115 dp_max = dp; | 1183 dp_max = dp; |
1116 } | 1184 } |
1117 if(dp < DECOINFO_STRUCT_MAX_STOPS) | 1185 if(dp < DECOINFO_STRUCT_MAX_STOPS) |
1118 { | 1186 { |
1119 stop_time_seconds = (short) fminf((999.9 * 60.0), (stop_time *60.0)); | 1187 stop_time_seconds = (uint16_t)(fminf((999.9 * 60.0), (stop_time *60.0))); |
1120 // | 1188 // |
1121 | 1189 |
1122 //if(vpm_calc_what == DECOSTOPS) | 1190 //if(vpm_calc_what == DECOSTOPS) |
1123 pDecoInfo->output_stop_length_seconds[dp] = stop_time_seconds; | 1191 pDecoInfo->output_stop_length_seconds[dp] = stop_time_seconds; |
1124 //else | 1192 //else |
2415 if(temp_segment_time > 1) | 2483 if(temp_segment_time > 1) |
2416 return CALC_NDL; | 2484 return CALC_NDL; |
2417 else | 2485 else |
2418 return CALC_BEGIN; | 2486 return CALC_BEGIN; |
2419 } | 2487 } |
2488 | |
2489 void vpm_table_init() | |
2490 { | |
2491 vpmTable.output_time_to_surface_seconds = 0; | |
2492 } | |
2493 |