diff --git a/Project.toml b/Project.toml index c4da043..c37f583 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "TrainRun" uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92" authors = ["Max Kannenberg"] -version = "0.6.1" +version = "0.6.2" [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" diff --git a/README.md b/README.md index 1f8abc6..9c199dc 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,16 @@ train_run = calculateDrivingDynamics(train, running_path, settings) # History +## Version 0.6.2 + +Add function addStandstill! for creating the BehaviorSection standstill + +- Add function addStandstill! to MovinPhases.jl +- Use function addStandstill! in OperationModes.jl +- Rename the BehaviorSection standStill to standstill +- Fix: Rename addStartingPhase! to addBreakFreePhase! + + ## Version 0.6.1 Add an attribute to DataPoint to record the corresponding driving behavior diff --git a/src/MovingPhases.jl b/src/MovingPhases.jl index 92afcbb..09c2ad4 100644 --- a/src/MovingPhases.jl +++ b/src/MovingPhases.jl @@ -1,7 +1,7 @@ module MovingPhases using ..types -export addAccelerationPhase!, addAccelerationPhaseUntilBraking!, addCruisingPhase!, addCoastingPhaseUntilBraking!, addBrakingPhase!, addBrakingPhaseStepwise!, calculateForces! +export addAccelerationPhase!, addAccelerationPhaseUntilBraking!, addCruisingPhase!, addCoastingPhaseUntilBraking!, addBrakingPhase!, addBrakingPhaseStepwise!, addStandstill!, calculateForces! # addBrakingPhaseStepwise! is not used in the current version of the tool v00=100/3.6 # velocity constant (in m/s) @@ -260,7 +260,7 @@ end # function considerFormerSpeedLimits! ## This function calculates the data points of the breakFree phase. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed. # Info: currently the values of the breakFree phase will be calculated like in the acceleration phase -function addStartingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) +function addBreakFreePhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) if drivingCourse[end].v==0.0 && drivingCourse[end].s breakFreeSection)) end # else: return the characteristic section without a breakFree section return (CS, drivingCourse) -end #function addStartingPhase! +end #function addBreakFreePhase! ## This function calculates the data points of the acceleration phase. # Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the acceleration section function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) if drivingCourse[end].v==0.0 - (CS, drivingCourse)=addStartingPhase!(CS, drivingCourse, settings, train, CSs) + (CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs) end #if calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") @@ -469,7 +469,7 @@ end #function addAccelerationPhase! ## This function calculates the data points of the acceleration phase. function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) if drivingCourse[end].v==0.0 - (CS, drivingCourse)=addStartingPhase!(CS, drivingCourse, settings, train, CSs) + (CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs) end #if calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") @@ -736,6 +736,103 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data end #function addCruisingPhase! +## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower +function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) + calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing") + + if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s0.0 # as long as s_i + s_braking < s_CSend + # 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking0.0 # as long as s_i + s_braking < s_CSend + + #11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type) + + # acceleration (in m/s^2): + drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] + # 11/21: old, only for cruising: + #if drivingCourse[end].a==0.0 + # error("ERROR: a=0 m/s^2 in the diminishing phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_consist=",drivingCourse[end].R_consist," R_path=",drivingCourse[end].R_path) + #end + + # create the next data point + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) + drivingCourse[end].behavior = diminishingSection.type + push!(diminishingSection.dataPoints, drivingCourse[end].i) + + s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type) + end #while + + # check which limit was reached and adjust the currentStepSize for the next cycle + if cycle < approximationLevel+1 + if drivingCourse[end].v<=0.0 + currentStepSize = settings[:stepSize] / 10.0^cycle + + elseif drivingCourse[end].s + s_braking > CS.s_exit + currentStepSize = settings[:stepSize] / 10.0^cycle + + elseif drivingCourse[end].s + s_braking==CS.s_exit + # 11/21 old without s_braking: elseif drivingCourse[end].s==CS.s_exit + break + + elseif drivingCourse[end].F_T > drivingCourse[end].F_R + currentStepSize = settings[:stepSize] / 10.0^cycle + + else + error("ERROR during diminishing run: With the step variable ",settings[:stepVariable]," the while loop will be left although s+s_braking0.0 in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") + end + # delete last data point for recalculating the last step with reduced step size + pop!(drivingCourse) + pop!(diminishingSection.dataPoints) + + else # if the level of approximation is reached + if drivingCourse[end].v<=0.0 + # push!(diminishingSection.dataPoints, drivingCourse[end].i) + error("ERROR: The train stops during diminishing run in CS",CS.id," because the maximum tractive effort is lower than the resistant forces.", + " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", + " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_consist=",drivingCourse[end-1].R_consist," N R_path=",drivingCourse[end-1].R_path," N.") + + elseif drivingCourse[end].s + s_braking > CS.s_exit + pop!(drivingCourse) + pop!(diminishingSection.dataPoints) + + elseif drivingCourse[end].F_T > drivingCourse[end].F_R + break + + else + + end + end + end #for + + if length(diminishingSection.dataPoints) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start + # calculate the accumulated diminishing section information + diminishingSection.v_exit=drivingCourse[end].v # exit speed (in m/s) + diminishingSection.s_exit=drivingCourse[end].s # last position (in m) + diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m) + diminishingSection.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s) + diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws) + CS.t=CS.t+diminishingSection.t # total running time (in s) + CS.E=CS.E+diminishingSection.E # total energy consumption (in Ws) + + merge!(CS.behaviorSections, Dict(:diminishing=>diminishingSection)) + end + end + + return (CS, drivingCourse) +end #function addDiminishingPhase! + + ## This function calculates the data points of the coasting phase. # Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) @@ -855,7 +952,6 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse: end #function addCoastingPhaseUntilBraking! - ## This function calculates the data points of the braking phase. (standard braking phase with only two data points) # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed. function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) @@ -914,7 +1010,6 @@ function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataP end #function addBrakingPhase! - ## This function calculates the data points of the braking phase. # 09/07 new braking phase with more than two data points # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed. function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) @@ -995,100 +1090,31 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect end #function addBrakingPhaseStepwise! -## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower -function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) - calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing") +## This function calculates the data point of the standstill. +# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the standstill if needed. +function addStandstill!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) - if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s0.0 # as long as s_i + s_braking < s_CSend - # 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking0.0 # as long as s_i + s_braking < s_CSend - #11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type) + drivingCourse[end].behavior = standstillSection.type - # acceleration (in m/s^2): - drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] - # 11/21: old, only for cruising: - #if drivingCourse[end].a==0.0 - # error("ERROR: a=0 m/s^2 in the diminishing phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_consist=",drivingCourse[end].R_consist," R_path=",drivingCourse[end].R_path) - #end - - # create the next data point - push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) - drivingCourse[end].behavior = diminishingSection.type - push!(diminishingSection.dataPoints, drivingCourse[end].i) - - s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) - calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type) - end #while - - # check which limit was reached and adjust the currentStepSize for the next cycle - if cycle < approximationLevel+1 - if drivingCourse[end].v<=0.0 - currentStepSize = settings[:stepSize] / 10.0^cycle - - elseif drivingCourse[end].s + s_braking > CS.s_exit - currentStepSize = settings[:stepSize] / 10.0^cycle - - elseif drivingCourse[end].s + s_braking==CS.s_exit - # 11/21 old without s_braking: elseif drivingCourse[end].s==CS.s_exit - break - - elseif drivingCourse[end].F_T > drivingCourse[end].F_R - currentStepSize = settings[:stepSize] / 10.0^cycle - - else - error("ERROR during diminishing run: With the step variable ",settings[:stepVariable]," the while loop will be left although s+s_braking0.0 in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") - end - # delete last data point for recalculating the last step with reduced step size - pop!(drivingCourse) - pop!(diminishingSection.dataPoints) - - else # if the level of approximation is reached - if drivingCourse[end].v<=0.0 - # push!(diminishingSection.dataPoints, drivingCourse[end].i) - error("ERROR: The train stops during diminishing run in CS",CS.id," because the maximum tractive effort is lower than the resistant forces.", - " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", - " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_consist=",drivingCourse[end-1].R_consist," N R_path=",drivingCourse[end-1].R_path," N.") - - elseif drivingCourse[end].s + s_braking > CS.s_exit - pop!(drivingCourse) - pop!(diminishingSection.dataPoints) - - elseif drivingCourse[end].F_T > drivingCourse[end].F_R - break - - else - - end - end - end #for - - if length(diminishingSection.dataPoints) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start - # calculate the accumulated diminishing section information - diminishingSection.v_exit=drivingCourse[end].v # exit speed (in m/s) - diminishingSection.s_exit=drivingCourse[end].s # last position (in m) - diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m) - diminishingSection.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s) - diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws) - CS.t=CS.t+diminishingSection.t # total running time (in s) - CS.E=CS.E+diminishingSection.E # total energy consumption (in Ws) - - merge!(CS.behaviorSections, Dict(:diminishing=>diminishingSection)) - end - end + # traction effort and resisting forces (in N) + calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, standstillSection.type) + merge!(CS.behaviorSections, Dict(:standstill => standstillSection)) + end # else: return the characteristic section without a standstillSection section return (CS, drivingCourse) -end #function addDiminishingPhase! +end #function addStandstill! end #module MovingPhases diff --git a/src/OperationModes.jl b/src/OperationModes.jl index de3f386..6e13e49 100644 --- a/src/OperationModes.jl +++ b/src/OperationModes.jl @@ -91,11 +91,7 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train end =# end #for - # calculate the last data points resisting forces - calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "braking") - if drivingCourse[end].v == 0.0 - drivingCourse[end].behavior = "standStill" - end + (CSs[end], drivingCourse)=addStandstill!(CSs[end], drivingCourse, settings, train, CSs) movingSection[:t] = drivingCourse[end].t # total running time (in s) movingSection[:E] = drivingCourse[end].E # total energy consumption (in Ws) @@ -184,7 +180,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict movingSectionOriginal[:t_recoveryAvailable] = movingSectionOriginal[:t_recoveryAvailable] - movingSectionOriginal[:energySavingModifications][end].Δt - lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax].behaviorSections, :standStill, + lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax].behaviorSections, :standstill, get(CSsOrig[csIdMax].behaviorSections, :braking, get(CSsOrig[csIdMax].behaviorSections, :cruisingAfterCoasting, get(CSsOrig[csIdMax].behaviorSections, :coasting, @@ -237,7 +233,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict # update all the data point references in the behaviour sections of the following characteristic sections and the other modified characteristic sections if difference!= 0 # update the data point references in the behaviour sections of the following characteristic sections - allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill] + allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] for csId in csIdMax+1:length(CSsOrig) for bs in 1: length(allBs) if haskey(CSsOrig[csId].behaviorSections, allBs[bs]) @@ -277,9 +273,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict end #if doCombinationOfMethods end # while - if drivingCourseOriginal[end].v == 0.0 - drivingCourseOriginal[end].behavior = "standStill" - end + (CSsOrig[end], drivingCourseOriginal) = addStandstill!(CSsOrig[end], drivingCourseOriginal, settings, train, CSsOrig) println("t_recoveryAvailable=",movingSectionOriginal[:t_recoveryAvailable]) return (movingSectionOriginal, drivingCourseOriginal) @@ -344,7 +338,7 @@ function findBestModification(energySavingModifications::Vector{EnergySavingModi end #function findBestModification function updateEnergySavingModifications(energySavingModifications::Vector{EnergySavingModification}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer) - allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill] + allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] difference = endOfModificationId-lastIdOfSelectedCsOriginal for modNr in csIdMax+1:length(energySavingModifications) if energySavingModifications[modNr].ratio>0 diff --git a/src/Output.jl b/src/Output.jl index 23c5ea9..99f6f89 100644 --- a/src/Output.jl +++ b/src/Output.jl @@ -258,7 +258,7 @@ function printSectionInformation(movingSection::Dict) CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections] println("MS mit length=", movingSection[:length]," mit t=", movingSection[:t]) - allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill] + allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] for csId in 1:length(CSs) println("CS ",csId," mit length=", CSs[csId].length," mit t=", CSs[csId].t) for bs in 1: length(allBs) diff --git a/src/types.jl b/src/types.jl index 81476c9..635ffc6 100644 --- a/src/types.jl +++ b/src/types.jl @@ -6,7 +6,7 @@ export DataPoint, BehaviorSection, CharacteristicSection, EnergySavingModificati ## a data point is the smallest element of the driving course. One step of the step approach is between two data points mutable struct DataPoint i::Integer # identifier and counter variable of the dricing course - behavior::String # type of BehaviorSection the DataPoint ist part of ("breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting","braking" or "standStill") + behavior::String # type of BehaviorSection the DataPoint ist part of ("breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting","braking" or "standstill") # a data point which is the last point of one BehaviorSection and the first point of the next BehaviorSection will be attached to the latter s::AbstractFloat # position (in m) Δs::AbstractFloat # step size (in m) @@ -35,7 +35,7 @@ DataPoint(original::DataPoint)=DataPoint(original.i, original.behavior, original ## different sections the whole path can be devided in the following ## smallest section of the path is the behavior section. It relates to the containing data points via their identifier. mutable struct BehaviorSection - type::String # type of behavior section: "breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting","braking" or "standStill" + type::String # type of behavior section: "breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting","braking" or "standstill" length::AbstractFloat # total length (in m) s_entry::AbstractFloat # first position (in m) s_exit::AbstractFloat # last position (in m) @@ -72,7 +72,7 @@ end # mutable struct CharacteristicSection CharacteristicSection()=CharacteristicSection(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Dict{Symbol, BehaviorSection}()) function CharacteristicSection(original::CharacteristicSection) copy=CharacteristicSection(original.id, original.length, original.s_entry, original.s_exit, original.t, original.E, original.v_limit, original.v_target, original.v_entry, original.v_exit, original.f_Rp, Dict{Symbol, BehaviorSection}()) - allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill] + allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] for bs in 1: length(allBs) if haskey(original.behaviorSections, allBs[bs]) merge!(copy.behaviorSections, Dict(allBs[bs] => BehaviorSection(original.behaviorSections[allBs[bs]])))