diff --git a/src/EnergySaving.jl b/src/EnergySaving.jl index 699c0cf..3ee9eca 100644 --- a/src/EnergySaving.jl +++ b/src/EnergySaving.jl @@ -145,7 +145,7 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours s_cruising=max(0.0, s_cruising) # copy csOriginal to csModified - csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{Symbol, BehaviorSection}()) + csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}()) if haskey(csOriginal.behaviorSections, :breakFree) breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree]) merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection)) @@ -210,7 +210,7 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours # TODO: At the moment diminishing is reduced like the acceleration in decreaseMaximumVelocity. To reduce code the methods for reducing cruising phase and reducing the diminishing phase can be combined in some parts. # copy csOriginal to csModified - csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{Symbol, BehaviorSection}()) + csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}()) if haskey(csOriginal.behaviorSections, :breakFree) breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree]) merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection)) @@ -296,15 +296,15 @@ end # function increaseCoastingSection # method 2 with shortening the acceleration by stepsize function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) #function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) - if haskey(csOriginal.behaviorSections, :acceleration) && csOriginal.v_target > csOriginal.v_entry && csOriginal.v_target > csOriginal.v_exit + if haskey(csOriginal.behaviorSections, :acceleration) && csOriginal.v_peak > csOriginal.v_entry && csOriginal.v_peak > csOriginal.v_exit accelerationSection = BehaviorSection(csOriginal.behaviorSections[:acceleration]) if drivingCourse[accelerationSection.dataPoints[end]-1].v < csOriginal.v_exit return (CharacteristicSection(), [], false) - # TODO: or calculate a new acceleration phase with v_exit as v_target? it will be very short, shorter than the step size. + # TODO: or calculate a new acceleration phase with v_exit as v_peak? it will be very short, shorter than the step size. end # copy csOriginal to csModified - csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{Symbol, BehaviorSection}()) + csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}()) if haskey(csOriginal.behaviorSections, :breakFree) breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree]) @@ -342,8 +342,8 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :acceleration, BehaviorSection())).dataPoints[1] end - # TODO: should v_target be reduced or is it enough to pop the data points? - # characteristicSection.v_target=drivingCourse[end].v # setting v_target to the last data point's velocity which is the highest reachable value in this characteristic section + # TODO: should v_peak be reduced or is it enough to pop the data points? + # characteristicSection.v_peak=drivingCourse[end].v # setting v_peak to the last data point's velocity which is the highest reachable value in this characteristic section # copy the drivingCourse till the beginning of energy saving drivingCourseModified=Vector{DataPoint}() @@ -351,7 +351,7 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving end - #s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_target^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors + #s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_peak^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors s_braking=max(0.0, ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors s_cruising=csModified.s_exit-drivingCourseModified[end].s-s_braking @@ -366,11 +366,11 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours elseif drivingCourseModified[end].s0.001 # if (csModified.s_exit-drivingCourseModified[end].s)>10^(-approximationLevel) - # println("INFO: The end of new CS",csModified.id," is not reached while saving energy with lowering v_target.") + # println("INFO: The end of new CS",csModified.id," is not reached while saving energy with lowering v_peak.") # println(" Therefore the calculation of this method can not continue for this CS.") return (CharacteristicSection(), [], false) end - println("WARNING: The end of new CS",csModified.id," is not reached while saving energy with lowering v_target.") + println("WARNING: The end of new CS",csModified.id," is not reached while saving energy with lowering v_peak.") println(" Therefore s=",drivingCourseModified[end].s," will be set s_exit=",csModified.s_exit," because the difference is only ",csModified.s_exit-drivingCourseModified[end].s," m.") println(" v=",drivingCourseModified[end].v," m/s v_exit=",csOriginal.v_exit ," m/s") @@ -381,7 +381,7 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours return (csModified, drivingCourseModified, true) else # time loss is to high. so there is no energy saving modification for this CS with the available recovery time # 09/06 old: else # time loss is to high and the CS has to be calculated again with larger acceleration section (so with a smaller reduction of the acceleration section) - # 09/06 old: accelerationReduction=min(accelerationReduction/10, csModified.v_target-csModified.v_entry, csModified.v_target-csModified.v_exit) + # 09/06 old: accelerationReduction=min(accelerationReduction/10, csModified.v_peak-csModified.v_entry, csModified.v_peak-csModified.v_exit) # TODO: just return false or take smaller steps? return (CharacteristicSection(), [], false) @@ -393,14 +393,14 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours # 09/06 old: return (CharacteristicSection(), [], false) else - # there is no energy saving modification for this CS because v_target can not be lowered below v_entry or v_exit or because there is no acceleration section that can be transformed into a cruising section + # there is no energy saving modification for this CS because v_peak can not be lowered below v_entry or v_exit or because there is no acceleration section that can be transformed into a cruising section return (CharacteristicSection(), [], false) end #if haskey end # function decreaseMaximumVelocity # combination of method 1 and method 2 function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) - # if haskey(csOriginal.behaviorSections, :acceleration) && (haskey(csOriginal.behaviorSections, :braking) || haskey(csOriginal.behaviorSections, :coasting)) && csOriginal.v_target>csOriginal.v_entry && csOriginal.v_target>csOriginal.v_exit + # if haskey(csOriginal.behaviorSections, :acceleration) && (haskey(csOriginal.behaviorSections, :braking) || haskey(csOriginal.behaviorSections, :coasting)) && csOriginal.v_peak>csOriginal.v_entry && csOriginal.v_peak>csOriginal.v_exit if haskey(csOriginal.behaviorSections, :acceleration) && (haskey(csOriginal.behaviorSections, :braking) || haskey(csOriginal.behaviorSections, :coasting)) && drivingCourse[get(csOriginal.behaviorSections, :acceleration, BehaviorSection()).dataPoints[end]].v > max(csOriginal.v_entry, csOriginal.v_exit) csCombined=CharacteristicSection(csOriginal) drivingCourseCombined=Vector{DataPoint}() @@ -432,7 +432,7 @@ function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCo end # while return (csCombined, drivingCourseCombined, (ΔE>0.0))# && Δt>0.0)) else - # there is no energy saving modification for this CS because v_target can not be lowered below v_entry or v_exit or because there is no acceleration section and braking section or coasting section that can be transformed into a cruising section or coasting section + # there is no energy saving modification for this CS because v_peak can not be lowered below v_entry or v_exit or because there is no acceleration section and braking section or coasting section that can be transformed into a cruising section or coasting section return (CharacteristicSection(), [], false) end #if end #function combineEnergySavingMethods diff --git a/src/Input.jl b/src/Input.jl index dfe5a9c..b390e37 100644 --- a/src/Input.jl +++ b/src/Input.jl @@ -21,11 +21,11 @@ Read the train information from a YAML file, save it in a train Dict and return """ function inputTrain(trainDirectory::String) data = YAML.load(open(trainDirectory)) - collect(keys(data)) - collect(values(data)) + #collect(keys(data)) + #collect(values(data)) if haskey(data["train"],"name") - name=data["train"]["name"] # trains name + name=data["train"]["name"] # train's name delete!(data["train"], "name") else error("ERROR at reading the train yaml file: The keyword name is missing. It has to be added.") @@ -46,7 +46,7 @@ function inputTrain(trainDirectory::String) if haskey(data["train"],"l_train") if typeof(data["train"]["l_train"]) <: Real && data["train"]["l_train"]>0.0 - l_train=data["train"]["l_train"] # total length (in m) + trainLength=data["train"]["l_train"] # total length (in m) delete!(data["train"], "l_train") else error("ERROR at reading the train yaml file: The value of the length is no real number >0.0.") @@ -141,7 +141,7 @@ function inputTrain(trainDirectory::String) m_t=m_td+m_tc - # mass of the consist (set of wagons) (in kg) + # mass of the set of wagons (consist) (in kg) if haskey(data["train"],"m_w") if typeof(data["train"]["m_w"]) <: Real && data["train"]["m_w"]>=0.0 m_w=data["train"]["m_w"] @@ -256,16 +256,16 @@ function inputTrain(trainDirectory::String) - # coefficients for the vehicle resistance of the consist (set of wagons) + # coefficients for the vehicle resistance of the set of wagons (consist) - # coefficient for velocitiy difference between consist (set of wagons) and outdoor air (in m/s) + # coefficient for velocitiy difference between set of wagons (consist) and outdoor air (in m/s) if trainType=="passenger" || trainType=="motor coach train" Δv_w=15.0/3.6 elseif trainType== "freight" Δv_w=0.0 end # if - # coefficient for basic resistance of the consist (set of wagons) (in ‰) + # coefficient for basic resistance of the set of wagons (consist) (in ‰) if haskey(data["train"],"f_Rw0") && data["train"]["f_Rw0"]!=nothing if typeof(data["train"]["f_Rw0"]) <: Real && data["train"]["f_Rw0"]>=0.0 f_Rw0=data["train"]["f_Rw0"] @@ -278,7 +278,7 @@ function inputTrain(trainDirectory::String) end delete!(data["train"], "f_Rw0") - # coefficient for basic resistance of the consist (set of wagons) (in ‰) + # coefficient for basic resistance of the set of wagons (consist) (in ‰) if haskey(data["train"],"f_Rw1") && data["train"]["f_Rw1"]!=nothing if typeof(data["train"]["f_Rw1"]) <: Real && data["train"]["f_Rw1"]>=0.0 f_Rw1=data["train"]["f_Rw1"] @@ -291,7 +291,7 @@ function inputTrain(trainDirectory::String) end delete!(data["train"], "f_Rw1") - # coefficient for basic resistance of the consist (set of wagons) (in ‰) + # coefficient for basic resistance of the set of wagons (consist) (in ‰) if haskey(data["train"],"f_Rw2") && data["train"]["f_Rw2"]!=nothing if typeof(data["train"]["f_Rw2"]) <: Real && data["train"]["f_Rw2"]>=0.0 f_Rw2=data["train"]["f_Rw2"] @@ -317,7 +317,7 @@ function inputTrain(trainDirectory::String) train= Dict(:name => name, # train's name :id => id, # train's identifier :trainType => trainType, # type of train "passenger" or "freight" or "motor coach train" - :l_train => l_train, # total length (in m) + :trainLength => trainLength, # total length (in m) :v_limit => v_limit, # trains speed limit (in m/s) :a_braking => a_braking, # braking acceleration (in m/s^2) :m_train => m_train, # total mass (in kg) @@ -396,8 +396,8 @@ end #function checkAndDefineTractiveEffortInput function inputPath(pathDirectory::String) # read path information from a YAML file, save it in a path Dict and return it data = YAML.load(open(pathDirectory)) - collect(keys(data)) - collect(values(data)) + #collect(keys(data)) + #collect(values(data)) if haskey(data["path"],"name") && data["path"]["name"]!=nothing @@ -505,8 +505,8 @@ end # function inputPath function inputSettings(settingsDirectory::String) # read setting information from a YAML file, save it in a settings Dict and return it data = YAML.load(open(settingsDirectory)) - collect(keys(data)) - collect(values(data)) + #collect(keys(data)) + #collect(values(data)) # initialize the settings Dictionary settings = Dict(:massModel => "", # model type of the unions mass "mass point" or "homogeneous strip" diff --git a/src/MovingPhases.jl b/src/MovingPhases.jl index 09c2ad4..580b51c 100644 --- a/src/MovingPhases.jl +++ b/src/MovingPhases.jl @@ -91,15 +91,15 @@ function calculatePathResistance(s::AbstractFloat, massModel::String, train::Dic end #while if massModel=="mass point" - pathResistance=CSs[id].f_Rp/1000*train[:m_train]*g # /1000 because of the unit ‰ + pathResistance=CSs[id].r_path/1000*train[:m_train]*g # /1000 because of the unit ‰ elseif massModel=="homogeneous strip" pathResistance=0.0 - while id>0 && s-train[:l_train]0 && s-train[:trainLength]| @@ -189,11 +189,11 @@ end #function moveAStep """ # if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept """ -function detectFormerSpeedLimits(CSs::Vector{CharacteristicSection}, csWithTrainHeadId::Integer, currentPoint::DataPoint, l_train::Real) +function detectFormerSpeedLimits(CSs::Vector{CharacteristicSection}, csWithTrainHeadId::Integer, currentPoint::DataPoint, trainLength::Real) formerSpeedLimits=[] - if csWithTrainHeadId > 1 && currentPoint.s - l_train < CSs[csWithTrainHeadId].s_entry + if csWithTrainHeadId > 1 && currentPoint.s - trainLength < CSs[csWithTrainHeadId].s_entry formerCsId=csWithTrainHeadId-1 - while formerCsId > 0 && currentPoint.s - l_train < CSs[formerCsId].s_exit + while formerCsId > 0 && currentPoint.s - trainLength < CSs[formerCsId].s_exit if CSs[formerCsId].v_limit < CSs[csWithTrainHeadId].v_limit # TODO: is the position of trains tail < movingSection[:s_entry], v_limit of the first CS is used push!(formerSpeedLimits, [CSs[formerCsId].s_exit, CSs[formerCsId].v_limit]) for i in 1:length(formerSpeedLimits)-1 @@ -227,7 +227,7 @@ function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Ve # create a (new and longer) clearing section s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) - s_clearing=min(CS.s_exit-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:l_train])) + s_clearing=min(CS.s_exit-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:trainLength])) if s_clearing>0.0 (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") @@ -250,7 +250,7 @@ function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Ve end # remove former speed limits of characteristic sections the train has left during the last step from the list - while length(formerSpeedLimits) > 0 && drivingCourse[end].s - train[:l_train] >= formerSpeedLimits[end][1] + while length(formerSpeedLimits) > 0 && drivingCourse[end].s - train[:trainLength] >= formerSpeedLimits[end][1] pop!(formerSpeedLimits) end end @@ -343,16 +343,16 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ end # if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept - formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:l_train]) + formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:trainLength]) # conditions for acceleration phase - targetSpeedReached = drivingCourse[end].v >= CS.v_target + targetSpeedReached = drivingCourse[end].v >= CS.v_peak trainAtEnd = drivingCourse[end].s >= CS.s_exit tractionSurplus = drivingCourse[end].F_T > drivingCourse[end].F_R # use the conditions for the acceleration phase if !targetSpeedReached && !trainAtEnd && tractionSurplus - #11/23 long version: if drivingCourse[end].v < CS.v_target && drivingCourse[end].s drivingCourse[end].F_R + #11/23 long version: if drivingCourse[end].v < CS.v_peak && drivingCourse[end].s drivingCourse[end].F_R accelerationSection=BehaviorSection() accelerationSection.type="acceleration" # type of behavior section accelerationSection.s_entry=drivingCourse[end].s # first position (in m) @@ -362,7 +362,7 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - while drivingCourse[end].v drivingCourse[end].F_R + while drivingCourse[end].v drivingCourse[end].F_R # traction effort and resisting forces (in N) # 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) @@ -398,9 +398,9 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].v>CS.v_target + elseif drivingCourse[end].v>CS.v_peak if settings[:stepVariable]=="v in m/s" - currentStepSize=CS.v_target-drivingCourse[end-1].v + currentStepSize=CS.v_peak-drivingCourse[end-1].v else currentStepSize = settings[:stepSize] / 10.0^cycle end @@ -408,13 +408,13 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ elseif drivingCourse[end].s==CS.s_exit break - elseif drivingCourse[end].v==CS.v_target + elseif drivingCourse[end].v==CS.v_peak break elseif drivingCourse[end].F_T <= drivingCourse[end].F_R currentStepSize = settings[:stepSize] / 10.0^cycle else - error("ERROR at acceleration phase: With the step variable ", settings[:stepVariable]," the while loop will be left although vCS.v_target + elseif drivingCourse[end].v>CS.v_peak pop!(drivingCourse) pop!(accelerationSection.dataPoints) elseif drivingCourse[end].s>CS.s_exit @@ -443,7 +443,7 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ end end #for - if length(accelerationSection.dataPoints) > 1 # 11/21 new: it is possible that the acceleration starts at v_target, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section. + if length(accelerationSection.dataPoints) > 1 # 11/21 new: it is possible that the acceleration starts at v_peak, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section. # calculate the accumulated acceleration section information accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s) accelerationSection.s_exit=drivingCourse[end].s # last position (in m) @@ -454,8 +454,8 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ CS.E=CS.E+accelerationSection.E # total energy consumption (in Ws) # TODO: this warning schould not be needed. just for testing - if CS.v_target < drivingCourse[end].v - println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_target=",CS.v_target) + if CS.v_peak < drivingCourse[end].v + println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_peak=",CS.v_peak) end merge!(CS.behaviorSections, Dict(:acceleration=>accelerationSection)) @@ -479,11 +479,11 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou end # if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept - formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:l_train]) + formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:trainLength]) - # 11/23 old without F_T>F_R: if drivingCourse[end].v < CS.v_target && drivingCourse[end].s drivingCourse[end].F_R + # 11/23 old without F_T>F_R: if drivingCourse[end].v < CS.v_peak && drivingCourse[end].s drivingCourse[end].F_R accelerationSection=BehaviorSection() accelerationSection.type="acceleration" # type of behavior section accelerationSection.s_entry=drivingCourse[end].s # first position (in m) @@ -494,15 +494,15 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) - while drivingCourse[end].v < CS.v_target && drivingCourse[end].s+s_braking drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend - # 12/03 old with v>0 while drivingCourse[end].v < CS.v_target && drivingCourse[end].s+s_braking0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend + while drivingCourse[end].v < CS.v_peak && drivingCourse[end].s+s_braking drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend + # 12/03 old with v>0 while drivingCourse[end].v < CS.v_peak && drivingCourse[end].s+s_braking0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend #11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) # acceleration (in m/s^2): drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] # if drivingCourse[end].a==0.0 - # error("ERROR: a=0 m/s^2 in the acceleration 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) + # error("ERROR: a=0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_wagons=",drivingCourse[end].R_wagons," R_path=",drivingCourse[end].R_path) # end # create the next data point @@ -529,9 +529,9 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou elseif drivingCourse[end].s +s_braking > CS.s_exit currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].v>CS.v_target + elseif drivingCourse[end].v>CS.v_peak if settings[:stepVariable]=="v in m/s" - currentStepSize= CS.v_target-drivingCourse[end-1].v + currentStepSize= CS.v_peak-drivingCourse[end-1].v else currentStepSize = settings[:stepSize] / 10.0^cycle end @@ -539,14 +539,14 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou elseif drivingCourse[end].s==CS.s_exit break - elseif drivingCourse[end].v==CS.v_target + elseif drivingCourse[end].v==CS.v_peak break elseif drivingCourse[end].F_T <= drivingCourse[end].F_R currentStepSize = settings[:stepSize] / 10.0^cycle else - error("ERROR at acceleration until braking phase: With the step variable ",settings[:stepVariable]," the while loop will be left although vCS.v_target + elseif drivingCourse[end].v>CS.v_peak pop!(drivingCourse) pop!(accelerationSection.dataPoints) elseif drivingCourse[end].s + s_braking > CS.s_exit @@ -584,7 +584,7 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou accelerationSection.t=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) accelerationSection.E=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws) - CS.v_target=max(drivingCourse[end].v, CS.v_entry) # setting v_target to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances + CS.v_peak=max(drivingCourse[end].v, CS.v_entry) # setting v_peak to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances CS.t=CS.t+accelerationSection.t # total running time (in s) CS.E=CS.E+accelerationSection.E # total energy consumption (in Ws) @@ -606,8 +606,8 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")) s_cruising = max(0.0, s_cruising-get(CS.behaviorSections, :diminishing, BehaviorSection()).length) end - if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s= drivingCourse[end].F_R - # 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s0.0 && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s= drivingCourse[end].F_R + # 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s 1 currentStepSize=settings[:stepSize] for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - while drivingCourse[end].s < CS.s_entry + train[:l_train] && drivingCourse[end].s=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_target && drivingCourse[end].s=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_target && drivingCourse[end].s=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_peak && drivingCourse[end].scruisingSection.s_entry+s_cruising # TODO also the following? drivingCourse[end].s > CSs[CS.id].s_entry + train[:l_train])) + if drivingCourse[end].s>cruisingSection.s_entry+s_cruising # TODO also the following? drivingCourse[end].s > CSs[CS.id].s_entry + train[:trainLength])) if settings[:stepVariable] == "s in m" currentStepSize=cruisingSection.s_entry+s_cruising-drivingCourse[end-1].s else @@ -669,8 +669,8 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data # else currentStepSize = settings[:stepSize] / 10.0^cycle # end - elseif drivingCourse[end].s >= CS.s_entry + train[:l_train] - # TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS.id].s_entry + train[:l_train] + elseif drivingCourse[end].s >= CS.s_entry + train[:trainLength] + # TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS.id].s_entry + train[:trainLength] break else # TODO copied from addAccelerationPhase -> probably not needed here !? error("ERROR at cruising phase: With the step variable ",settings[:stepVariable]," the while loop will be left although the if cases don't apply in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") @@ -741,7 +741,7 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D 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 && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s CS.s_exit pop!(drivingCourse) @@ -837,7 +837,7 @@ end #function addDiminishingPhase! # 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}) ## if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept - #formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:l_train]) + #formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:trainLength]) if drivingCourse[end].v>CS.v_exit && drivingCourse[end].sCS.v_exit && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s + s_braking < CS.s_exit # as long as s_i + s_braking < s_CSend + while drivingCourse[end].v>CS.v_exit && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s + s_braking < CS.s_exit # as long as s_i + s_braking < s_CSend # traction effort and resisting forces (in N): calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, coastingSection.type) @@ -876,9 +876,9 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse: elseif drivingCourse[end].v < CS.v_exit # TODO: if accelereation and coasting functions will be combined this case is only for coasting currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].v > CS.v_target + elseif drivingCourse[end].v > CS.v_peak if settings[:stepVariable]=="v in m/s" - currentStepSize = CS.v_target-drivingCourse[end-1].v + currentStepSize = CS.v_peak-drivingCourse[end-1].v else currentStepSize = settings[:stepSize] / 10.0^cycle end @@ -890,7 +890,7 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse: else # TODO: not needed. just for testing - error("ERROR at coasting until braking phase: With the step variable ",settings[:stepVariable]," the while loop will be left although v CS.s_exit # delete last data point because it went to far pop!(drivingCourse) pop!(coastingSection.dataPoints) - elseif drivingCourse[end].v > CS.v_target # if the train gets to fast it has to brake # TODO: if accelereation and coasting functions will be combined this case is different for coasting and also the order of if cases is different - # while coasting the train brakes to hold v_target (only one data point in the end of coasting is calculated like cruising at v_target) + elseif drivingCourse[end].v > CS.v_peak # if the train gets to fast it has to brake # TODO: if accelereation and coasting functions will be combined this case is different for coasting and also the order of if cases is different + # while coasting the train brakes to hold v_peak (only one data point in the end of coasting is calculated like cruising at v_peak) drivingCourse[end-1].a=0.0 s_braking=ceil((CS.v_exit^2-drivingCourse[end-1].v^2)/2/train[:a_braking]) diff --git a/src/OperationModes.jl b/src/OperationModes.jl index 6e13e49..9491e2c 100644 --- a/src/OperationModes.jl +++ b/src/OperationModes.jl @@ -27,12 +27,12 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train s_breakFree = get(CSs[csId].behaviorSections, :breakFree, BehaviorSection()).length s_clearing = get(CSs[csId].behaviorSections, :clearing, BehaviorSection()).length s_acceleration = get(CSs[csId].behaviorSections, :acceleration, BehaviorSection()).length - s_braking = max(0.0, ceil((CSs[csId].v_exit^2-CSs[csId].v_target^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors + s_braking = max(0.0, ceil((CSs[csId].v_exit^2-CSs[csId].v_peak^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors # calculate the cruising sections length s_cruising=CSs[csId].length-s_breakFree-s_clearing-s_acceleration-s_braking - # reset the moving section (MS), delete characteristic sections (CS) that were used during the preperation for setting v_entry, v_target and v_exit + # reset the moving section (MS), delete characteristic sections (CS) that were used during the preperation for setting v_entry, v_peak and v_exit delete!(CSs[csId].behaviorSections, :breakFree) delete!(CSs[csId].behaviorSections, :clearing) delete!(CSs[csId].behaviorSections, :acceleration) @@ -50,14 +50,14 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train elseif s_cruising > 0.0 || s_braking == 0.0 # 09/21 elseif s_cruising > 0.0 # 09/21 elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0) - if drivingCourse[end].v < CSs[csId].v_target + if drivingCourse[end].v < CSs[csId].v_peak (CSs[csId], drivingCourse)=addAccelerationPhase!(CSs[csId], drivingCourse, settings, train, CSs) end #if if CSs[csId].s_exit-drivingCourse[end].s-max(0.0, (CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking]) < -0.001 # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors println("ERROR: After accelerating in CS ",csId," the braking distance is too short!") println(" before acceleration in CS",csId, " with s=",drivingCourse[end].s," s_braking=",((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking])," s_exit=",CSs[csId].s_exit) - println(" and v=",drivingCourse[end].v," v_target=",CSs[csId].v_target," v_exit=",CSs[csId].v_exit) + println(" and v=",drivingCourse[end].v," v_peak=",CSs[csId].v_peak," v_exit=",CSs[csId].v_exit) end s_braking=max(0.0, ceil((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors @@ -68,8 +68,8 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train end else - if CSs[csId].v_entry < CSs[csId].v_target || s_acceleration > 0.0 # or instead of " || s_acceleration > 0.0" use "v_entry <= v_target" or "v_i <= v_target" - # 09/09 old (not sufficient for steep gradients): if CSs[csId].v_entry < CSs[csId].v_target + if CSs[csId].v_entry < CSs[csId].v_peak || s_acceleration > 0.0 # or instead of " || s_acceleration > 0.0" use "v_entry <= v_peak" or "v_i <= v_peak" + # 09/09 old (not sufficient for steep gradients): if CSs[csId].v_entry < CSs[csId].v_peak (CSs[csId], drivingCourse)=addAccelerationPhaseUntilBraking!(CSs[csId], drivingCourse, settings, train, CSs) end #if end #if @@ -113,6 +113,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict #create a new moving section for the minimum energy consumption movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime) CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections] + merge!(movingSectionOriginal, Dict(:energySavingModifications => [])) # list containing all the used energy saving modifications # create a new driving course for the minimum energy consumption drivingCourseOriginal=DataPoint[] @@ -121,13 +122,14 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict end # calculate the recovery time - movingSectionOriginal[:t_recovery]=calculateRecoveryTime(movingSectionOriginal[:length], movingSectionOriginal[:t], train) - movingSectionOriginal[:t_recoveryAvailable]=movingSectionOriginal[:t_recovery] + t_recovery=calculateRecoveryTime(movingSectionOriginal[:length], movingSectionOriginal[:t], train) + merge!(movingSectionOriginal, Dict(:t_recovery=>t_recovery)) # total recovery time for energy-saving modifications (in s) + merge!(movingSectionOriginal, Dict(:t_recoveryAvailable => t_recovery)) # still available recovery time for energy-saving modifications (in s) initialized with the total recovery time # create arrays for each method with all the available energy saving modifications - energySavingModificationsWithCoasting=EnergySavingModification[] - energySavingModificationsWithMaximumSpeed=EnergySavingModification[] - energySavingModificationsWithCombination=EnergySavingModification[] + energySavingModificationsWithCoasting=Dict[] + energySavingModificationsWithMaximumSpeed=Dict[] + energySavingModificationsWithCombination=Dict[] for csId in 1:length(CSsOrig) # method 1: increase coasting @@ -137,7 +139,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict push!(energySavingModificationsWithCoasting, energySavingModification) end #if doMethod1 - # method 2: accelerate to a lower v_target + # method 2: accelerate to a lower v_peak if doMethod2 == true modificationType = "decreasing maximum velocity" energySavingModification = modifyCs(movingSectionOriginal, drivingCourseOriginal, csId, modificationType, settings, train) @@ -167,7 +169,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict if typeMax=="none" break elseif typeMax=="increasing coasting" - # println("Energy saving modification number ",length(movingSectionOriginal[:energySavingModifications])+1," (coasting) in CS ",csIdMax ," Δt=",energySavingModificationsWithCoasting[csIdMax].Δt," ΔE=", energySavingModificationsWithCoasting[csIdMax].ΔE," t_recoveryAvailable=", movingSectionOriginal[:t_recoveryAvailable]-energySavingModificationsWithCoasting[csIdMax].Δt) + # println("Energy saving modification number ",length(movingSectionOriginal[:energySavingModifications])+1," (coasting) in CS ",csIdMax ," Δt=",energySavingModificationsWithCoasting[csIdMax][:Δt]," ΔE=", energySavingModificationsWithCoasting[csIdMax][:ΔE]," t_recoveryAvailable=", movingSectionOriginal[:t_recoveryAvailable]-energySavingModificationsWithCoasting[csIdMax][:Δt]) push!(movingSectionOriginal[:energySavingModifications], energySavingModificationsWithCoasting[csIdMax]) # println("Nr. ",length(movingSectionOriginal[:energySavingModifications]),": typeMax=increasing coasting") elseif typeMax=="decreasing maximum velocity" @@ -178,7 +180,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict # println("Nr. ",length(movingSectionOriginal[:energySavingModifications]),": typeMax=combination of energy saving methods") end #if - movingSectionOriginal[:t_recoveryAvailable] = movingSectionOriginal[:t_recoveryAvailable] - movingSectionOriginal[:energySavingModifications][end].Δt + movingSectionOriginal[:t_recoveryAvailable] = movingSectionOriginal[:t_recoveryAvailable] - movingSectionOriginal[:energySavingModifications][end][:Δt] lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax].behaviorSections, :standstill, get(CSsOrig[csIdMax].behaviorSections, :braking, @@ -197,15 +199,15 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict end # create new driving course - drivingCourseNew=Vector{DataPoint}() - for i in 1:length(movingSectionOriginal[:energySavingModifications][end].drivingCourseModified) - push!(drivingCourseNew, DataPoint(movingSectionOriginal[:energySavingModifications][end].drivingCourseModified[i])) + drivingCourseNew=DataPoint[] + for i in 1:length(movingSectionOriginal[:energySavingModifications][end][:drivingCourseModified]) + push!(drivingCourseNew, DataPoint(movingSectionOriginal[:energySavingModifications][end][:drivingCourseModified][i])) end #fill up the rest of the driving course with information from the original course drivingCourseNew[end].F_T=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_T drivingCourseNew[end].R_traction=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_traction - drivingCourseNew[end].R_consist=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_consist + drivingCourseNew[end].R_wagons=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_wagons drivingCourseNew[end].R_train=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_train drivingCourseNew[end].R_path=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_path drivingCourseNew[end].F_R=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_R @@ -226,7 +228,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict # replace the original driving course and CS with the new modified ones drivingCourseOriginal=drivingCourseNew - CSsOrig[csIdMax]=CharacteristicSection(movingSectionOriginal[:energySavingModifications][end].csModified) + CSsOrig[csIdMax]=CharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified]) movingSectionOriginal[:t]=drivingCourseOriginal[end].t # total running time (in s) movingSectionOriginal[:E]=drivingCourseOriginal[end].E # total energy consumption (in Ws) @@ -245,9 +247,9 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict end #for # update the data points in the following modified charateristic sections and the following points in the driving course - energySavingModificationsWithCoasting = updateEnergySavingModifications(energySavingModificationsWithCoasting, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal) - energySavingModificationsWithMaximumSpeed = updateEnergySavingModifications(energySavingModificationsWithMaximumSpeed, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal) - energySavingModificationsWithCombination = updateEnergySavingModifications(energySavingModificationsWithCombination, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal) + energySavingModificationsWithCoasting = updateEnergySavingModifications!(energySavingModificationsWithCoasting, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal) + energySavingModificationsWithMaximumSpeed = updateEnergySavingModifications!(energySavingModificationsWithMaximumSpeed, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal) + energySavingModificationsWithCombination = updateEnergySavingModifications!(energySavingModificationsWithCombination, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal) end # if difference # modify new CS for the considered methods @@ -258,7 +260,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict energySavingModificationsWithCoasting[csIdMax]=energySavingModification end #if if doMethod1 - # method 2: accelerate to a lower v_target + # method 2: accelerate to a lower v_peak if doMethod2==true modificationType = "decreasing maximum velocity" energySavingModification = modifyCs(movingSectionOriginal, drivingCourseOriginal, csIdMax, modificationType, settings, train) @@ -281,72 +283,110 @@ end #function calculateMinimumEnergyConsumption function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Dict, train::Dict) +# TODO: refctor and sort this function CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections] if modificationType == "increasing coasting" # method 1: increase coasting (characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=increaseCoastingSection(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable]) elseif modificationType == "decreasing maximum velocity" - # method 2: accelerate to a lower v_target + # method 2: accelerate to a lower v_peak (characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=decreaseMaximumVelocity(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable]) elseif modificationType == "combination of energy saving methods" # calculate the combination of the previous methods (characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=combineEnergySavingMethods(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable]) else - return EnergySavingModification() + return createEnergySavingModification() end - energySavingModification = EnergySavingModification() + #energySavingModification = createEnergySavingModification() if new - energySavingModification.csId = csId # identifier of the characteristic section - energySavingModification.type = modificationType # type of energy saving modification: "increasing coasting" or "decreasing maximum velocity" or "combination of energy saving methods" - energySavingModification.csModified = characteristicSectionModified # the modified characteristic section - energySavingModification.drivingCourseModified = drivingCourseModifiedUntilEndOfModifiedCS # drivingCourse of the modified characteristic section - energySavingModification.ΔE = CSsOrig[csId].E - energySavingModification.csModified.E # saved energy (in Ws) - energySavingModification.Δt = energySavingModification.csModified.t - CSsOrig[csId].t # time loss (in s) - if energySavingModification.Δt <= movingSectionOriginal[:t_recoveryAvailable] && energySavingModification.ΔE >= 0.0 + energySavingModification = Dict(:csId => csId, # identifier of the characteristic section + :type => modificationType, # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting" + :csModified => characteristicSectionModified, # the modified characteristic section + :drivingCourseModified => drivingCourseModifiedUntilEndOfModifiedCS) # drivingCourse for the modified characteristic section + + merge!(energySavingModification, Dict(:ΔE => CSsOrig[csId].E - energySavingModification[:csModified].E)) # saved energy (in Ws) + merge!(energySavingModification, Dict(:Δt => energySavingModification[:csModified].t - CSsOrig[csId].t)) # time loss (in s) + + + if energySavingModification[:Δt] <= movingSectionOriginal[:t_recoveryAvailable] && energySavingModification[:ΔE] >= 0.0 #*** TODO: check why "sign" is needed here # if modificationType == "combination of energy saving methods" - energySavingModification.ratio=sign(energySavingModification.Δt)*energySavingModification.ΔE/energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s) + ratio=sign(energySavingModification[:Δt])*energySavingModification[:ΔE]/energySavingModification[:Δt] # ratio of ΔE and Δt (in Ws/s) + # else - # energySavingModification.ratio = energySavingModification.ΔE / energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s) + # ratio = energySavingModification[:ΔE] / energySavingModification[:Δt] # ratio of ΔE and Δt (in Ws/s) # end # *** - elseif energySavingModification.Δt == 0.0 - energySavingModification.ratio = energySavingModification.ΔE/0.000000001 + elseif energySavingModification[:Δt] == 0.0 + ratio = energySavingModification[:ΔE]/0.000000001 else # Δt is to high or ΔE < 0.0 Ws - energySavingModification.ratio = 0.0 + ratio = 0.0 end + merge!(energySavingModification, Dict(:ratio => ratio)) # ratio of ΔE and Δt (in Ws/s) + return energySavingModification + else + return createEnergySavingModification() end - return energySavingModification end #function modifyCs -function findBestModification(energySavingModifications::Vector{EnergySavingModification}, ratioMax::AbstractFloat, csIdMax::Integer, typeMax::String, t_recoveryAvailable::AbstractFloat) +function findBestModification(energySavingModifications::Vector{Dict}, ratioMax::AbstractFloat, csIdMax::Integer, typeMax::String, t_recoveryAvailable::AbstractFloat) for modNr in 1:length(energySavingModifications) - if energySavingModifications[modNr].ratio > ratioMax - if energySavingModifications[modNr].Δt <= t_recoveryAvailable - ratioMax=energySavingModifications[modNr].ratio - csIdMax=energySavingModifications[modNr].csId - typeMax=energySavingModifications[modNr].type + if energySavingModifications[modNr][:ratio] > ratioMax + if energySavingModifications[modNr][:Δt] <= t_recoveryAvailable + ratioMax = energySavingModifications[modNr][:ratio] + csIdMax = energySavingModifications[modNr][:csId] + typeMax = energySavingModifications[modNr][:type] else # Δt is to high - energySavingModifications[modNr].ratio=0.0 + energySavingModifications[modNr][:ratio]=0.0 end #if end #if end #for return (energySavingModifications, ratioMax, csIdMax, typeMax) end #function findBestModification -function updateEnergySavingModifications(energySavingModifications::Vector{EnergySavingModification}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer) + +## for the energy saving operation mode it is nesserary to compare different energy saving modifications. These are part of the moving section. +function createEnergySavingModification() + energySavingModification = Dict(:csId => 0, # identifier of the characteristic section + :type => "", # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting" + :ΔE => 0.0, # saved energy (in Ws) + :Δt => 0.0, # time loss (in s) + :ratio => 0.0, # ratio of ΔE and Δt (in Ws/s) + :csModified => CharacteristicSection(), # the modified characteristic section + :drivingCourseModified => []) # drivingCourse for the modified characteristic section +end #createEnergySavingModification + +function copyEnergySavingModification(original::Dict) + copy = Dict(:csId => original[:csId], # identifier of the characteristic section + :type => original[:type], # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting" + :ΔE => original[:ΔE], # saved energy (in Ws) + :Δt => original[:Δt], # time loss (in s) + :ratio => original[:ratio], # ratio of ΔE and Δt (in Ws/s) + :csModified => CharacteristicSection(original[:csModified])) # the modified characteristic section + + drivingCourseModified = DataPoint[] + for i in 1:length(original[:drivingCourseModified]) + push!(drivingCourseModified, DataPoint(original[:drivingCourseModified][i])) + end + merge!(copy, Dict(:drivingCourseModified => drivingCourseModified)) # drivingCourse for the modified characteristic section + return copy +end #function EnergySavingModification + + +function updateEnergySavingModifications!(energySavingModifications::Vector{Dict}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer) 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 + if energySavingModifications[modNr][:ratio]>0 + BSs = energySavingModifications[modNr][:csModified].behaviorSections # update the behavior sections of the modified charateristic section for bs in 1: length(allBs) - if haskey(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs]) - for point in 1:length(energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints) - energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints[point] = energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints[point]+difference + if haskey(BSs, allBs[bs]) + for point in 1:length(BSs[allBs[bs]].dataPoints) + BSs[allBs[bs]].dataPoints[point] = BSs[allBs[bs]].dataPoints[point] + difference end end #if end #for @@ -357,8 +397,8 @@ function updateEnergySavingModifications(energySavingModifications::Vector{Energ push!(drivingCourseModifiedNew, DataPoint(drivingCourseNew[i])) end # for i=lastIdOfSelectedCsOriginal+1 - while i <= length(energySavingModifications[modNr].drivingCourseModified) - push!(drivingCourseModifiedNew, DataPoint(energySavingModifications[modNr].drivingCourseModified[i])) + while i <= length(energySavingModifications[modNr][:drivingCourseModified]) + push!(drivingCourseModifiedNew, DataPoint(energySavingModifications[modNr][:drivingCourseModified][i])) drivingCourseModifiedNew[end].i=length(drivingCourseModifiedNew) drivingCourseModifiedNew[end].t=drivingCourseModifiedNew[end-1].t+drivingCourseModifiedNew[end].Δt drivingCourseModifiedNew[end].E=drivingCourseModifiedNew[end-1].E+drivingCourseModifiedNew[end].ΔE @@ -366,12 +406,13 @@ function updateEnergySavingModifications(energySavingModifications::Vector{Energ i=i+1 end # while - energySavingModifications[modNr].drivingCourseModified = drivingCourseModifiedNew + energySavingModifications[modNr][:drivingCourseModified] = drivingCourseModifiedNew end #if end #for return energySavingModifications -end #function updateEnergySavingModifications +end #function updateEnergySavingModifications! + function copyMovingSection(original::Dict) CSsCopy = Vector{CharacteristicSection}() @@ -379,21 +420,30 @@ function copyMovingSection(original::Dict) push!(CSsCopy, CharacteristicSection(original[:characteristicSections][csId])) end #for - ModificationsCopy = Vector{EnergySavingModification}() - for modId in 1:length(original[:energySavingModifications]) - push!(ModificationsCopy, EnergySavingModification(original[:energySavingModifications][modId])) - end #for - copy = Dict(:id => original[:id], # identifier :length => original[:length], # total length (in m) :s_entry => original[:s_entry], # first position (in m) :s_exit => original[:s_exit], # last position (in m) :t => original[:t], # total running time (in s) :E => original[:E], # total energy consumption (in Ws) - :t_recovery => original[:t_recovery], # total recovery time for energy-saving modifications (in s) - :t_recoveryAvailable => original[:t_recoveryAvailable], # still available recovery time for energy-saving modifications (in s) - :characteristicSections => CSsCopy, # list of containing characteristic sections - :energySavingModifications => ModificationsCopy) # list of containing all the used energy saving modifications + :characteristicSections => CSsCopy) # list of containing characteristic sections + + if haskey(original, :energySavingModifications) # list of containing all the used energy saving modifications + ModificationsCopy = Dict[] + for modId in 1:length(original[:energySavingModifications]) + push!(ModificationsCopy, EnergySavingModification(original[:energySavingModifications][modId])) + end #for + merge!(copy, Dict(:energySavingModifications => ModificationsCopy)) + end + + if haskey(original, :t_recovery) # total recovery time for energy-saving modifications (in s) + merge!(copy, Dict(:t_recovery => original[:t_recovery])) + end + + if haskey(original, :t_recoveryAvailable) # still available recovery time for energy-saving modifications (in s) + merge!(copy, Dict(:t_recoveryAvailable => original[:t_recoveryAvailable])) + end + return copy end #function copyMovingSection diff --git a/src/Output.jl b/src/Output.jl index 99f6f89..98b38ff 100644 --- a/src/Output.jl +++ b/src/Output.jl @@ -56,14 +56,14 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d row=[movingSection[:length], movingSection[:t], movingSection[:E]] push!(outputArray, row) # push row to outputArray elseif settings[:detailOfOutput]=="driving course" - push!(outputArray, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArray + push!(outputArray, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArray for point in drivingCourse - row=[point.i, point.behavior, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_consist, point.ΔW, point.W, point.ΔE, point.E, point.a] + row=[point.i, point.behavior, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_wagons, point.ΔW, point.W, point.ΔE, point.E, point.a] push!(outputArray, row) # push row to outputArray end end - if length(movingSection[:energySavingModifications])>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption + if haskey(movingSection, :energySavingModifications) && length(movingSection[:energySavingModifications])>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption merge!(outputDict, Dict(:outputArrayMinimumEnergyConsumption => outputArray)) else merge!(outputDict, Dict(:outputArrayMinimumRunningTime => outputArray)) @@ -86,9 +86,9 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d row=[movingSectionMinimumEnergyConsumption[:length], movingSectionMinimumEnergyConsumption[:t], movingSectionMinimumEnergyConsumption[:E]] push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption elseif settings[:detailOfOutput]=="driving course" - push!(outputArrayMinimumEnergyConsumption, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArrayMinimumEnergyConsumption + push!(outputArrayMinimumEnergyConsumption, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArrayMinimumEnergyConsumption for point in drivingCourseMinimumEnergyConsumption - row=[point.i, point.behavior, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_consist, point.ΔW, point.W, point.ΔE, point.E, point.a] + row=[point.i, point.behavior, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_wagons, point.ΔW, point.W, point.ΔE, point.E, point.a] push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption end end @@ -134,7 +134,7 @@ function createOutputCsv(settings::Dict, pathName::String, trainName::String, dr if settings[:detailOfOutput]=="minimal" header=outputDict[:outputArrayMinimumRunningTime][1] elseif settings[:detailOfOutput]=="driving course" - header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"] + header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"] end for column in 1:length(outputDict[outputArray][1]) push!(infoColumns[column], header[column]) @@ -177,7 +177,7 @@ function createOutputCsv(settings::Dict, pathName::String, trainName::String, dr if settings[:detailOfOutput]=="minimal" header=outputDict[:outputArrayMinimumRunningTime][1] elseif settings[:detailOfOutput]=="driving course" - header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"] + header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"] end for column in 1:length(outputDict[:outputArrayMinimumRunningTime][1]) @@ -215,7 +215,7 @@ function createOutputCsv(settings::Dict, pathName::String, trainName::String, dr if settings[:detailOfOutput]=="minimal" header=outputDict[:outputArrayMinimumRunningTime][1] elseif settings[:detailOfOutput]=="driving course" - header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"] + header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"] end for column in 1:length(outputDict[:outputArrayMinimumEnergyConsumption][1]) diff --git a/src/Preparation.jl b/src/Preparation.jl index ee0b2e1..1f33aa2 100644 --- a/src/Preparation.jl +++ b/src/Preparation.jl @@ -41,10 +41,7 @@ function createMovingSection(path::Dict, v_trainLimit::Real) :s_exit => s_exit, # last position (in m) :t => 0.0, # total running time (in s) :E => 0.0, # total energy consumption (in Ws) - :t_recovery => 0.0, # total recovery time for energy-saving modifications (in s) - :t_recoveryAvailable => 0.0, # still available recovery time for energy-saving modifications (in s) - :characteristicSections => CSs, # list of containing characteristic sections - :energySavingModifications => EnergySavingModification[]) # list of containing all the used energy saving modifications + :characteristicSections => CSs) # list of containing characteristic sections return movingSection end #function createMovingSection @@ -62,12 +59,12 @@ function createCharacteristicSection(csId::Integer, s_csStart::Real, section::Di characteristicSection.E=0.0 # total energy consumption (in Ws) characteristicSection.v_limit=v_csLimit # speed limit (in m/s) - # initializing v_entry, v_target and v_exit with v_limit - characteristicSection.v_target=characteristicSection.v_limit # maximum target speed (in m/s) + # initializing v_entry, v_peak and v_exit with v_limit + characteristicSection.v_peak=characteristicSection.v_limit # maximum reachable speed (in m/s) characteristicSection.v_entry=characteristicSection.v_limit # maximum entry speed (in m/s) characteristicSection.v_exit=characteristicSection.v_limit # maximum exit speed (in m/s) - characteristicSection.f_Rp=section[:f_Rp] # path resistance (in ‰) + characteristicSection.r_path=section[:f_Rp] # path resistance (in ‰) return characteristicSection end #function createCharacteristicSection @@ -84,7 +81,7 @@ function secureBrakingBehavior!(movingSection::Dict, a_braking::Real) v_entryMax=floor(v_entryMax, digits=12) CSs[csId].v_entry=min(CSs[csId].v_limit, v_entryMax) - CSs[csId].v_target=CSs[csId].v_entry + CSs[csId].v_peak=CSs[csId].v_entry csId=csId-1 if csId >= 1 CSs[csId].v_exit=min(CSs[csId].v_limit, CSs[csId+1].v_entry) @@ -110,12 +107,12 @@ function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train: startingPoint.v=CSs[csId].v_entry accelerationCourse=[startingPoint] # List of data points - if CSs[csId].v_entry