Refactor and fix modules EnergySaving, OperationModes and MovingPhases

pull/1/head v0.4
Max Kannenberg 2021-12-08 21:35:27 +01:00
parent 5c9bb29aa6
commit d71a1e882b
4 changed files with 549 additions and 597 deletions

View File

@ -23,6 +23,20 @@ See folder examples.
# History # History
## Version 0.4
Refactor and fix modules EnergySaving, OperationModes and MovingPhases
The general used level of accuracy from v0.3 was added to EnergySaving and OperationModes. OperationModes and MovingPhases were fixed for steep ascents were a train runs with maximum tractive effort while the driving resistances are even higher.
## Version 0.3
Refactor module MovingPhases
Repeatedly occuring code lines were extracted and smaller functions created (e.g. the function moveAStep). A new approach for calculating the waypoints near intersections was integrated (e.g. including an editable level of accuracy).
## Version 0.2 ## Version 0.2
Modules and variables were renamed. Modules and variables were renamed.
@ -36,7 +50,7 @@ Proof of concept and master thesis submission.
# Acknowledgement # Acknowledgement
This work was supervides by South Westphalia University of Applied Sciences and Technical University Braunschweig. This work was supervised by South Westphalia University of Applied Sciences and Technical University Braunschweig.
------------ ------------

View File

@ -5,6 +5,9 @@ using ..MovingPhases
export calculateRecoveryTime, increaseCoastingSection, decreaseMaximumVelocity, combineEnergySavingMethods export calculateRecoveryTime, increaseCoastingSection, decreaseMaximumVelocity, combineEnergySavingMethods
approximationLevel = 6 # value for approximation to intersections
# TODO: define it in TrainRun and give it to each function?
function calculateRecoveryTime(s_MS::AbstractFloat, t_MS::AbstractFloat, train::Train) function calculateRecoveryTime(s_MS::AbstractFloat, t_MS::AbstractFloat, train::Train)
# function for calculating the recovery time that can be used for energy saving # function for calculating the recovery time that can be used for energy saving
# MS: Moving Section # MS: Moving Section
@ -86,22 +89,22 @@ function calculateRecoveryTime(s_MS::AbstractFloat, t_MS::AbstractFloat, train::
end # if train.trainType end # if train.trainType
end #function calculateRecoveryTime end #function calculateRecoveryTime
function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "cruising") && haskey(csOriginal.behaviorSections, "braking") if haskey(csOriginal.behaviorSections, "cruising") && haskey(csOriginal.behaviorSections, "braking")
cruisingReduction=settings.stepSize cruisingReduction=settings.stepSize
while cruisingReduction>=settings.stepSize/100 while cruisingReduction>=settings.stepSize/10^approximationLevel
while cruisingReduction>=settings.stepSize/100 # will be done once and repeated twice with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified.v_exit && drivingCourseModified[end].s<csModified.s_end) -> see below at the end of the while loop #while cruisingReduction>=settings.stepSize/100
while cruisingReduction>=settings.stepSize/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified.v_exit && drivingCourseModified[end].s<csModified.s_end) -> see below at the end of the while loop
# creating a drivingCourse for the characteristic section # create a copy for the characteristic sections drivingCourse
energySavingStartId=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).waypoints[1] energySavingStartId=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).waypoints[1]
if energySavingStartId==0 if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !") error("ERROR at creating a new driving course for energy saving with coasting !")
end end
# tried to insert copy on 15.07.2021 drivingCourseModified=[copy(drivingCourse[1])] # TODO: tried to insert copy on 15.07.2021 drivingCourseModified=[copy(drivingCourse[1])]
drivingCourseModified=[Waypoint(drivingCourse[1])] drivingCourseModified=[Waypoint(drivingCourse[1])]
for i in 2:energySavingStartId for i in 2:energySavingStartId
# tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of waypoints till the start of energy saving # TODO: tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of waypoints till the start of energy saving
push!(drivingCourseModified, Waypoint(drivingCourse[i])) # List of waypoints till the start of energy saving push!(drivingCourseModified, Waypoint(drivingCourse[i])) # List of waypoints till the start of energy saving
end end
@ -109,14 +112,18 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
if settings.stepVariable=="s in m" # distance step method if settings.stepVariable=="s in m" # distance step method
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-cruisingReduction s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-cruisingReduction
elseif settings.stepVariable=="t in s" # time step method elseif settings.stepVariable=="t in s" # time step method
t_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).t_total-cruisingReduction # 09/20 old: doesn't work for non constant cruising
s_cruising=t_cruising*drivingCourseModified[end].v # t_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).t_total-cruisingReduction
# s_cruising=t_cruising*drivingCourseModified[end].v
wayReduction=drivingCourse(get(csOriginal.behaviorSections, "cruising", BehaviorSection()).waypoints[end]).v*cruisingReduction
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-wayReduction
elseif settings.stepVariable=="v in m/s" # velocity step method elseif settings.stepVariable=="v in m/s" # velocity step method
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-cruisingReduction*10 # TODO: or better: *100 ? s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-cruisingReduction*10 # TODO: or better: *100 ?
end #if end #if
s_cruising=max(0.0, s_cruising) s_cruising=max(0.0, s_cruising)
# copying csOriginal to csModified # copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.s_total, csOriginal.s_start, csOriginal.s_end, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_reach, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}()) csModified=CharacteristicSection(csOriginal.id, csOriginal.s_total, csOriginal.s_start, csOriginal.s_end, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_reach, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}())
if haskey(csOriginal.behaviorSections, "starting") if haskey(csOriginal.behaviorSections, "starting")
startingSection=BehaviorSection(get(csOriginal.behaviorSections, "starting", BehaviorSection())) startingSection=BehaviorSection(get(csOriginal.behaviorSections, "starting", BehaviorSection()))
@ -137,14 +144,14 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t_total csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t_total
end end
# calculating the new and now shorter cruising section # simulate the new and now shorter cruising section
if s_cruising>0.0 if s_cruising>0.0
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising") (csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end end
(csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs)
if drivingCourseModified[end].v<csModified.v_exit || drivingCourseModified[end].s>csModified.s_end if drivingCourseModified[end].v < csModified.v_exit || drivingCourseModified[end].s > csModified.s_end
# the train reaches v_exit before reaching s_end. The cruising and coasting sections have to be calculated again with a larger cruising section (so with a smaller reduction of the cruising section) # the train reaches v_exit before reaching s_end. The cruising and coasting sections have to be calculated again with a larger cruising section (so with a smaller reduction of the cruising section)
cruisingReduction=cruisingReduction/10 cruisingReduction=cruisingReduction/10
else else
@ -152,15 +159,16 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
end end
end # while cruisingReduction end # while cruisingReduction
if drivingCourseModified[end].v>csModified.v_exit if drivingCourseModified[end].v > csModified.v_exit
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs) #(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs)
elseif drivingCourseModified[end].v==csModified.v_exit && drivingCourseModified[end].s<csModified.s_end (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
# v_exit is already reached. Now cruising till the end of the CS elseif drivingCourseModified[end].v == csModified.v_exit && drivingCourseModified[end].s < csModified.s_end
# v_exit is already reached. Now cruise till the end of the CS
s_cruisingAfterCoasting=csModified.s_end-drivingCourseModified[end].s s_cruisingAfterCoasting=csModified.s_end-drivingCourseModified[end].s
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting") (csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
end end
if t_recoveryAvailable<(csModified.t_total-csOriginal.t_total) || drivingCourseModified[end].v!=csModified.v_exit || drivingCourseModified[end].s!=csModified.s_end # time loss is to high and the CS has to be calculated again with larger cruising section (so with a smaller reduction of the cruising section) or v_exit or s_end are not reached excatly if t_recoveryAvailable < csModified.t_total-csOriginal.t_total || drivingCourseModified[end].v != csModified.v_exit || drivingCourseModified[end].s != csModified.s_end # time loss is to high and the CS has to be calculated again with larger cruising section (so with a smaller reduction of the cruising section) or v_exit or s_end are not reached excatly
cruisingReduction=cruisingReduction/10 cruisingReduction=cruisingReduction/10
else else
return (csModified, drivingCourseModified, true) return (csModified, drivingCourseModified, true)
@ -175,70 +183,104 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
end # function increaseCoastingSection end # function increaseCoastingSection
# method 2 with shortening the acceleration by stepsize # method 2 with shortening the acceleration by stepsize
function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) #function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "acceleration") && csOriginal.v_reach>csOriginal.v_entry && csOriginal.v_reach>csOriginal.v_exit if haskey(csOriginal.behaviorSections, "acceleration") && csOriginal.v_reach > csOriginal.v_entry && csOriginal.v_reach > csOriginal.v_exit
# instead of calculating the new final velocity of the acceleration phase with the step sizes for the different step variables, the velocity of the point before the last will be the new v_reach accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
# because it it easier at the moment (TODO) if drivingCourse[accelerationSection.waypoints[end]-1].v < csOriginal.v_exit
lastIdOfOldAccelerationSection=get(csOriginal.behaviorSections, "acceleration", BehaviorSection()).waypoints[end] return (CharacteristicSection(), [], false)
accelerationReduction=drivingCourse[lastIdOfOldAccelerationSection].Δv # with step size it would be accelerationReduction=settings.stepSize # TODO: or calculate a new acceleration phase with v_exit as v_reach? it will be very short, shorter than the step size.
end
while accelerationReduction>=drivingCourse[lastIdOfOldAccelerationSection].Δv/100 # will be done once and repeated twice with smaller accelerationReduction unless t_recoveryAvailable>=(csModified.t_total-csOriginal.t_total) && 0.0<(csModified.t_total-csOriginal.t_total) -> see below at the end of the while loop # copy csOriginal to csModified
# copying csOriginal to csModified csModified=CharacteristicSection(csOriginal.id, csOriginal.s_total, csOriginal.s_start, csOriginal.s_end, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_reach, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}())
csModified=CharacteristicSection(csOriginal.id, csOriginal.s_total, csOriginal.s_start, csOriginal.s_end, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_reach, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}())
if haskey(csOriginal.behaviorSections, "starting") if haskey(csOriginal.behaviorSections, "starting")
startingSection=BehaviorSection(get(csOriginal.behaviorSections, "starting", BehaviorSection())) startingSection=BehaviorSection(get(csOriginal.behaviorSections, "starting", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("starting"=>startingSection)) merge!(csModified.behaviorSections, Dict("starting"=>startingSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "starting", BehaviorSection()).E_total csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "starting", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "starting", BehaviorSection()).t_total csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "starting", BehaviorSection()).t_total
end
#accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
if length(accelerationSection.waypoints) > 2
if haskey(csOriginal.behaviorSections, "cruisingBeforeAcceleration")
cruisingBeforeAccelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("cruisingBeforeAcceleration"=>cruisingBeforeAccelerationSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).t_total
end end
# creating a drivingCourse for the characteristic section # remove the last acceleration waypoint
pop!(accelerationSection.waypoints)
accelerationSection.v_exit=drivingCourse[accelerationSection.waypoints[end]].v # exit speed (in m/s)
accelerationSection.s_end=drivingCourse[accelerationSection.waypoints[end]].s # last position (in m)
accelerationSection.s_total=accelerationSection.s_end-accelerationSection.s_start # total length (in m)
accelerationSection.t_total=drivingCourse[accelerationSection.waypoints[end]].t-drivingCourse[accelerationSection.waypoints[1]].t # total running time (in s)
accelerationSection.E_total=drivingCourse[accelerationSection.waypoints[end]].E-drivingCourse[accelerationSection.waypoints[1]].E # total energy consumption (in Ws)
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection))
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E_total
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t_total
energySavingStartId=accelerationSection.waypoints[end]
else
# The acceleration section is only one step. This step is removed and if ther ist a cruisingBeforeAcceleration section it will be combined with the new cruising section.
energySavingStartId=get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", get(csOriginal.behaviorSections, "acceleration", BehaviorSection())).waypoints[1] energySavingStartId=get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", get(csOriginal.behaviorSections, "acceleration", BehaviorSection())).waypoints[1]
end
drivingCourseModified=Vector{Waypoint}() # TODO: should v_reach be reduced or is it enough to pop the waypoints?
for i in 1:energySavingStartId # characteristicSection.v_reach=drivingCourse[end].v # setting v_reach to the last waypoints velocity which is the highest reachable value in this characteristic section
# tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of waypoints till the start of energy saving
push!(drivingCourseModified, Waypoint(drivingCourse[i])) # List of waypoints till the start of energy saving # copy the drivingCourse till the beginning of energy saving
drivingCourseModified=Vector{Waypoint}()
for i in 1:energySavingStartId
push!(drivingCourseModified, Waypoint(drivingCourse[i])) # List of waypoints till the start of energy saving
end
#s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_reach^2)/2/train.a_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_end 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_end in spite of rounding errors
s_cruising=csModified.s_end-drivingCourseModified[end].s-s_braking
if s_cruising >0.001
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end #if
# s_brakingAfterCruising=ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train.a_braking, digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end].v>csModified.v_exit
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].s<csModified.s_end
if (csModified.s_end-drivingCourseModified[end].s)>0.001
# if (csModified.s_end-drivingCourseModified[end].s)>10^(-approximationLevel)
# println("INFO: The end of new CS",csModified.id," is not reached while saving energy with lowering v_reach.")
# println(" Therefore the calculation of this method can not continue for this CS.")
return (CharacteristicSection(), [], false)
end end
println("WARNING: The end of new CS",csModified.id," is not reached while saving energy with lowering v_reach.")
println(" Therefore s=",drivingCourseModified[end].s," will be set s_end=",csModified.s_end," because the difference is only ",csModified.s_end-drivingCourseModified[end].s," m.")
println(" v=",drivingCourseModified[end].v," m/s v_exit=",csOriginal.v_exit ," m/s")
csModified.v_reach=max(csModified.v_entry, csModified.v_exit, csOriginal.v_reach-accelerationReduction) drivingCourseModified[end].s=csModified.s_end # rounding up to s_end
end #if
# calculation of the new and now shorter acceleration section if t_recoveryAvailable>=(csModified.t_total-csOriginal.t_total)
if drivingCourseModified[end].v<csModified.v_reach return (csModified, drivingCourseModified, true)
(csModified, drivingCourseModified)=addAccelerationPhase!(csModified, drivingCourseModified, settings, train, allCSs) else # time loss is to high. so there is no energy saving modification for this CS with the available recovery time
end #if # 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)
# TODO: instead of copying the drivingCourse till the start of acceleration and calculating the acceleration again till the point before the last it would be possible to copy the drivingCouse until this point. Then it would not be necessary to calculate the accelerationPhase again. But then it is difficult to reduce accelerationReduction. # 09/06 old: accelerationReduction=min(accelerationReduction/10, csModified.v_reach-csModified.v_entry, csModified.v_reach-csModified.v_exit)
# TODO: just return false or take smaller steps?
s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_reach^2)/2/train.a_braking, digits=10)) # ceil is used to be sure that the train stops at s_end in spite of rounding errors return (CharacteristicSection(), [], false)
s_cruising=csModified.s_end-drivingCourseModified[end].s-s_braking end
if s_cruising >0.001 # 09/06 old: end #while
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising") #
end #if # 09/06 old: # there is no energy saving modification for this CS with the available recovery time
# 09/06 old: return (CharacteristicSection(), [], false)
# s_brakingAfterCruising=ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train.a_braking, digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end].v>csModified.v_exit
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs)
elseif drivingCourseModified[end].s<csModified.s_end
if (csModified.s_end-drivingCourseModified[end].s)>0.001
println("WARNING: The end of new CS",csModified.id," is not reached while saving energy with lowering v_reach.")
println(" Therefore s=",drivingCourseModified[end].s," will be set s_end=",csModified.s_end," because the difference is only ",csModified.s_end-drivingCourseModified[end].s," m.")
end
drivingCourseModified[end].s=csModified.s_end # rounding up to s_end
end #if
if t_recoveryAvailable>=(csModified.t_total-csOriginal.t_total)
return (csModified, drivingCourseModified, true)
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)
accelerationReduction=min(accelerationReduction/10, csModified.v_reach-csModified.v_entry, csModified.v_reach-csModified.v_exit)
end
end #while
# there is no energy saving modification for this CS with the available recovery time
return (CharacteristicSection(), [], false)
else else
# there is no energy saving modification for this CS because v_reach 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_reach 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
@ -248,16 +290,18 @@ end # function decreaseMaximumVelocity
# combination of method 1 and method 2 # combination of method 1 and method 2
function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{Waypoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "acceleration") && (haskey(csOriginal.behaviorSections, "braking") || haskey(csOriginal.behaviorSections, "coasting")) && csOriginal.v_reach>csOriginal.v_entry && csOriginal.v_reach>csOriginal.v_exit # if haskey(csOriginal.behaviorSections, "acceleration") && (haskey(csOriginal.behaviorSections, "braking") || haskey(csOriginal.behaviorSections, "coasting")) && csOriginal.v_reach>csOriginal.v_entry && csOriginal.v_reach>csOriginal.v_exit
if haskey(csOriginal.behaviorSections, "acceleration") && (haskey(csOriginal.behaviorSections, "braking") || haskey(csOriginal.behaviorSections, "coasting")) && drivingCourse[get(csOriginal.behaviorSections, "acceleration", BehaviorSection()).waypoints[end]].v > max(csOriginal.v_entry, csOriginal.v_exit)
csCombined=CharacteristicSection(csOriginal) csCombined=CharacteristicSection(csOriginal)
drivingCourseCombined=Vector{Waypoint}() drivingCourseCombined=Vector{Waypoint}()
for i in 1:length(drivingCourse) for i in 1:length(drivingCourse)
# tried to insert copy on 15.07.2021 push!(drivingCourseCombined, copy(drivingCourse[i])) # TODO: tried to insert copy on 15.07.2021 push!(drivingCourseCombined, copy(drivingCourse[i]))
push!(drivingCourseCombined, Waypoint(drivingCourse[i])) push!(drivingCourseCombined, Waypoint(drivingCourse[i]))
end end
ΔE=0.0 # saved energy (in Ws) ΔE=0.0 # saved energy (in Ws)
Δt=0.0 # time loss (in s) Δt=0.0 # time loss (in s)
while (Δt<t_recoveryAvailable && ΔE<=0.0) #while (Δt<t_recoveryAvailable && ΔE<=0.0)
while (Δt<t_recoveryAvailable && (Δt<=0.0 || ΔE<=0.0)) #ΔE<=0.0)
(csCombined, drivingCourseCombined, newMaximumVelocity)=decreaseMaximumVelocity(csCombined, drivingCourseCombined, settings, train, allCSs, t_recoveryAvailable) (csCombined, drivingCourseCombined, newMaximumVelocity)=decreaseMaximumVelocity(csCombined, drivingCourseCombined, settings, train, allCSs, t_recoveryAvailable)
if newMaximumVelocity if newMaximumVelocity
ΔE=csOriginal.E_total-csCombined.E_total # saved energy (in Ws) ΔE=csOriginal.E_total-csCombined.E_total # saved energy (in Ws)

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,8 @@ using .EnergySaving
export simulateMinimumRunningTime!, simulateMinimumEnergyConsumption export simulateMinimumRunningTime!, simulateMinimumEnergyConsumption
approximationLevel = 6 # TODO: define it in TrainRun and give it to each function?
function simulateMinimumRunningTime!(movingSection::MovingSection, settings::Settings, train::Train) function simulateMinimumRunningTime!(movingSection::MovingSection, settings::Settings, train::Train)
# simulate a train run focussing on using the minimum possible running time # simulate a train run focussing on using the minimum possible running time
startingPoint=Waypoint() startingPoint=Waypoint()
@ -17,11 +19,12 @@ function simulateMinimumRunningTime!(movingSection::MovingSection, settings::Set
drivingCourse=[startingPoint] # List of waypoints drivingCourse=[startingPoint] # List of waypoints
for csId in 1:length(movingSection.characteristicSections) for csId in 1:length(movingSection.characteristicSections)
# println("CS",csId)
# check if the CS has a cruising section # check if the CS has a cruising section
s_starting=get(movingSection.characteristicSections[csId].behaviorSections, "starting", BehaviorSection()).s_total s_starting=get(movingSection.characteristicSections[csId].behaviorSections, "starting", BehaviorSection()).s_total
s_cruisingBeforeAcceleration=get(movingSection.characteristicSections[csId].behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).s_total s_cruisingBeforeAcceleration=get(movingSection.characteristicSections[csId].behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).s_total
s_acceleration=get(movingSection.characteristicSections[csId].behaviorSections, "acceleration", BehaviorSection()).s_total s_acceleration=get(movingSection.characteristicSections[csId].behaviorSections, "acceleration", BehaviorSection()).s_total
s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-movingSection.characteristicSections[csId].v_reach^2)/2/train.a_braking, digits=10)) # ceil is used to be sure that the train stops at s_end in spite of rounding errors s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-movingSection.characteristicSections[csId].v_reach^2)/2/train.a_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_end in spite of rounding errors
# calculate the cruising sections length # calculate the cruising sections length
s_cruising=movingSection.characteristicSections[csId].s_total-s_starting-s_cruisingBeforeAcceleration-s_acceleration-s_braking s_cruising=movingSection.characteristicSections[csId].s_total-s_starting-s_cruisingBeforeAcceleration-s_acceleration-s_braking
@ -34,12 +37,15 @@ function simulateMinimumRunningTime!(movingSection::MovingSection, settings::Set
movingSection.characteristicSections[csId].E_total=0.0 movingSection.characteristicSections[csId].E_total=0.0
movingSection.characteristicSections[csId].t_total=0.0 movingSection.characteristicSections[csId].t_total=0.0
if s_cruisingBeforeAcceleration == movingSection.characteristicSections[csId].s_total if s_cruisingBeforeAcceleration == movingSection.characteristicSections[csId].s_total
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruisingBeforeAcceleration, settings, train, movingSection.characteristicSections, "cruising") # 09/06 TODO: thought about using "cruising" because it is used in EnergySaving and not cruisingBeforeAcceleration (movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruisingBeforeAcceleration, settings, train, movingSection.characteristicSections, "cruising")
# 09/06 "cruising" is used in EnergySaving and not cruisingBeforeAcceleration (movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruisingBeforeAcceleration, settings, train, movingSection.characteristicSections, "cruisingBeforeAcceleration") (movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruisingBeforeAcceleration, settings, train, movingSection.characteristicSections, "cruisingBeforeAcceleration")
elseif s_cruising == movingSection.characteristicSections[csId].s_total elseif s_cruising == movingSection.characteristicSections[csId].s_total
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, train, movingSection.characteristicSections, "cruising") (movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, train, movingSection.characteristicSections, "cruising")
elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0) 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 < movingSection.characteristicSections[csId].v_reach if drivingCourse[end].v < movingSection.characteristicSections[csId].v_reach
(movingSection.characteristicSections[csId], drivingCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections) (movingSection.characteristicSections[csId], drivingCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections)
end #if end #if
@ -50,38 +56,43 @@ function simulateMinimumRunningTime!(movingSection::MovingSection, settings::Set
println(" and v=",drivingCourse[end].v," v_reach=",movingSection.characteristicSections[csId].v_reach," v_exit=",movingSection.characteristicSections[csId].v_exit) println(" and v=",drivingCourse[end].v," v_reach=",movingSection.characteristicSections[csId].v_reach," v_exit=",movingSection.characteristicSections[csId].v_exit)
end end
s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=10)) # ceil is used to be sure that the train stops at s_end in spite of rounding errors s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_end in spite of rounding errors
s_cruising=movingSection.characteristicSections[csId].s_end-drivingCourse[end].s-s_braking s_cruising=movingSection.characteristicSections[csId].s_end-drivingCourse[end].s-s_braking
if s_cruising > 0.0 if s_cruising > 0.0
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, train, movingSection.characteristicSections, "cruising") (movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, train, movingSection.characteristicSections, "cruising")
end end
else else
if movingSection.characteristicSections[csId].v_entry < movingSection.characteristicSections[csId].v_reach
if movingSection.characteristicSections[csId].v_entry < movingSection.characteristicSections[csId].v_reach || s_acceleration > 0.0 # or instead of " || s_acceleration > 0.0" use "v_entry <= v_reach" or "v_i <= v_reach"
# 09/09 old (not sufficient for steep gradients): if movingSection.characteristicSections[csId].v_entry < movingSection.characteristicSections[csId].v_reach
(movingSection.characteristicSections[csId], drivingCourse)=addAccelerationPhaseUntilBraking!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections) (movingSection.characteristicSections[csId], drivingCourse)=addAccelerationPhaseUntilBraking!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections)
end #if end #if
end #if end #if
s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=10)) # ceil is used to be sure that the train stops at s_end in spite of rounding errors s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_end in spite of rounding errors
if drivingCourse[end].v > movingSection.characteristicSections[csId].v_exit if drivingCourse[end].v > movingSection.characteristicSections[csId].v_exit
(movingSection.characteristicSections[csId], drivingCourse)=addBrakingPhase!(movingSection.characteristicSections[csId], drivingCourse, settings.massModel, train, movingSection.characteristicSections) #(movingSection.characteristicSections[csId], drivingCourse)=addBrakingPhase!(movingSection.characteristicSections[csId], drivingCourse, settings.massModel, train, movingSection.characteristicSections)
(movingSection.characteristicSections[csId], drivingCourse)=addBrakingPhase!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections)
end #if end #if
#= 09/20 old and should never be used:
if drivingCourse[end].s < movingSection.characteristicSections[csId].s_end if drivingCourse[end].s < movingSection.characteristicSections[csId].s_end
if haskey(movingSection.characteristicSections[csId].behaviorSections, "cruising") if haskey(movingSection.characteristicSections[csId].behaviorSections, "cruising")
println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_end=",movingSection.characteristicSections[csId].s_end) println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_end=",movingSection.characteristicSections[csId].s_end)
end end
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, train, movingSection.characteristicSections, "cruising") (movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, train, movingSection.characteristicSections, "cruising")
end end =#
end #for end #for
# calculate the last waypoints resiting forces
drivingCourse[end]=Waypoint(calculateForces!(drivingCourse[end], train, settings.massModel, movingSection.characteristicSections, "braking"))
movingSection.t_total=drivingCourse[end].t # total running time (in s) movingSection.t_total=drivingCourse[end].t # total running time (in s)
movingSection.E_total=drivingCourse[end].E # total energy consumption (in Ws) movingSection.E_total=drivingCourse[end].E # total energy consumption (in Ws)
# TODO: calculate some values of the last waypoint
return (movingSection, drivingCourse) return (movingSection, drivingCourse)
end #function simulateMinimumRunningTime end #function simulateMinimumRunningTime
@ -90,6 +101,8 @@ function simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movin
# simulate a train run focussing on using the minimum possible energy consumption # simulate a train run focussing on using the minimum possible energy consumption
# booleans for choosing which methods are used for saving energy # booleans for choosing which methods are used for saving energy
doMethod1=true doMethod1=true
#doMethod1=false
#doMethod2=false
doMethod2=true doMethod2=true
doCombinationOfMethods=true doCombinationOfMethods=true
#doCombinationOfMethods=false #doCombinationOfMethods=false
@ -141,8 +154,57 @@ function simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movin
csIdMax=0 csIdMax=0
typeMax="none" typeMax="none"
(energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax, movingSectionOriginal.t_recoveryAvailable) (energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax, movingSectionOriginal.t_recoveryAvailable)
# 09/14 Three if cases for testing:
#= if length(movingSectionOriginal.energySavingModifications)==895 && ratioMax>0.0
println("")
println("typeMax=",typeMax)
println("ratioMax=",ratioMax)
println("csIdMax=",csIdMax)
println("---")
println("type=",energySavingModificationsWithMaximumSpeed[csIdMax].type)
println(" csId=",energySavingModificationsWithMaximumSpeed[csIdMax].csId)
println(" ΔE=",energySavingModificationsWithMaximumSpeed[csIdMax].ΔE)
println(" Δt=",energySavingModificationsWithMaximumSpeed[csIdMax].Δt)
println(" ratio=",energySavingModificationsWithMaximumSpeed[csIdMax].ratio)
println(" DC-length=",length(energySavingModificationsWithMaximumSpeed[csIdMax].drivingCourseModified))
end
=#
(energySavingModificationsWithCoasting, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithCoasting, ratioMax, csIdMax, typeMax, movingSectionOriginal.t_recoveryAvailable) (energySavingModificationsWithCoasting, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithCoasting, ratioMax, csIdMax, typeMax, movingSectionOriginal.t_recoveryAvailable)
#= if length(movingSectionOriginal.energySavingModifications)==895 && ratioMax>0.0
println("typeMax=",typeMax)
println("ratioMax=",ratioMax)
println("csIdMax=",csIdMax)
println("---")
println("type=",energySavingModificationsWithCoasting[csIdMax].type)
println(" csId=",energySavingModificationsWithCoasting[csIdMax].csId)
println(" ΔE=",energySavingModificationsWithCoasting[csIdMax].ΔE)
println(" Δt=",energySavingModificationsWithCoasting[csIdMax].Δt)
println(" ratio=",energySavingModificationsWithCoasting[csIdMax].ratio)
println(" DC-length=",length(energySavingModificationsWithCoasting[csIdMax].drivingCourseModified))
end
=#
(energySavingModificationsWithCombination, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithCombination, ratioMax, csIdMax, typeMax, movingSectionOriginal.t_recoveryAvailable) (energySavingModificationsWithCombination, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithCombination, ratioMax, csIdMax, typeMax, movingSectionOriginal.t_recoveryAvailable)
#= if length(movingSectionOriginal.energySavingModifications)==895 && ratioMax>0.0
println("typeMax=",typeMax)
println("ratioMax=",ratioMax)
println("csIdMax=",csIdMax)
println("---")
println("type=",energySavingModificationsWithCombination[csIdMax].type)
println(" csId=",energySavingModificationsWithCombination[csIdMax].csId)
println(" ΔE=",energySavingModificationsWithCombination[csIdMax].ΔE)
println(" Δt=",energySavingModificationsWithCombination[csIdMax].Δt)
println(" ratio=",energySavingModificationsWithCombination[csIdMax].ratio)
println(" DC-length=",length(energySavingModificationsWithCombination[csIdMax].drivingCourseModified))
end
=#
# select the most efficient modification and update the original characteristicSection, drivingCourse and movingSection # select the most efficient modification and update the original characteristicSection, drivingCourse and movingSection
# in case none of the modifications has a ratio>0 stop the calculation # in case none of the modifications has a ratio>0 stop the calculation
@ -151,10 +213,13 @@ function simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movin
elseif typeMax=="increasing coasting" 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]) push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithCoasting[csIdMax])
# println("Nr. ",length(movingSectionOriginal.energySavingModifications),": typeMax=increasing coasting")
elseif typeMax=="decreasing maximum velocity" elseif typeMax=="decreasing maximum velocity"
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithMaximumSpeed[csIdMax]) push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithMaximumSpeed[csIdMax])
# println("Nr. ",length(movingSectionOriginal.energySavingModifications),": typeMax=decreasing maximum velocity")
elseif typeMax=="combination of energy saving methods" elseif typeMax=="combination of energy saving methods"
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithCombination[csIdMax]) push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithCombination[csIdMax])
# println("Nr. ",length(movingSectionOriginal.energySavingModifications),": typeMax=combination of energy saving methods")
end #if end #if
movingSectionOriginal.t_recoveryAvailable = movingSectionOriginal.t_recoveryAvailable - movingSectionOriginal.energySavingModifications[end].Δt movingSectionOriginal.t_recoveryAvailable = movingSectionOriginal.t_recoveryAvailable - movingSectionOriginal.energySavingModifications[end].Δt
@ -174,6 +239,27 @@ function simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movin
# end # end
# end # for testing # end # for testing
# for testing 09/09
if length(drivingCourseNew) == 0
#= println("typeMax=",typeMax)
println("ratioMax=",ratioMax)
println("csIdMax=",csIdMax)
println("---")
println("type=",energySavingModificationsWithCombination[csIdMax].type)
println(" csId=",energySavingModificationsWithCombination[csIdMax].csId)
println(" ΔE=",energySavingModificationsWithCombination[csIdMax].ΔE)
println(" Δt=",energySavingModificationsWithCombination[csIdMax].Δt)
println(" ratio=",energySavingModificationsWithCombination[csIdMax].ratio)
println(" DC-length=",length(energySavingModificationsWithCombination[csIdMax].drivingCourseModified))
=#
println("---")
println("energySavingModificationsWithCoasting:",length(energySavingModificationsWithCoasting[csIdMax].drivingCourseModified))
println("energySavingModificationsWithMaximumSpeed:",length(energySavingModificationsWithMaximumSpeed[csIdMax].drivingCourseModified))
println("energySavingModificationsWithCombination:",length(energySavingModificationsWithCombination[csIdMax].drivingCourseModified))
end
#fill up the rest of the driving course with information from the original course #fill up the rest of the driving course with information from the original course
drivingCourseNew[end].F_T=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_T drivingCourseNew[end].F_T=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_T
drivingCourseNew[end].F_Rt=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_Rt drivingCourseNew[end].F_Rt=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_Rt
@ -245,8 +331,8 @@ function simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movin
end #if doCombinationOfMethods end #if doCombinationOfMethods
end # while end # while
# TODO: calculate some values of the last waypoint
# println("t_recoveryAvailable=",movingSectionOriginal.t_recoveryAvailable) println("t_recoveryAvailable=",movingSectionOriginal.t_recoveryAvailable)
return (movingSectionOriginal, drivingCourseOriginal) return (movingSectionOriginal, drivingCourseOriginal)
end #function simulateMinimumEnergyConsumption end #function simulateMinimumEnergyConsumption