Refactor the mutable struct CharacteristicSection as a Dictionary

development
Max Kannenberg 2022-01-03 11:54:07 +01:00
parent e1ad3f917d
commit 28605abd4c
7 changed files with 507 additions and 427 deletions

View File

@ -89,35 +89,34 @@ function calculateRecoveryTime(s_MS::Real, t_MS::AbstractFloat, train::Dict)
end # if train[:trainType] end # if train[:trainType]
end #function calculateRecoveryTime end #function calculateRecoveryTime
function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
if (haskey(csOriginal.behaviorSections, :cruising) || haskey(csOriginal.behaviorSections, :diminishing)) && haskey(csOriginal.behaviorSections, :braking) BSsOriginal = csOriginal[:behaviorSections]
if (haskey(BSsOriginal, :cruising) || haskey(BSsOriginal, :diminishing)) && haskey(BSsOriginal, :braking)
# check if cruising or diminishing should be reduced for coasting # check if cruising or diminishing should be reduced for coasting
if haskey(csOriginal.behaviorSections, :cruising) && haskey(csOriginal.behaviorSections, :diminishing) if haskey(BSsOriginal, :cruising) && haskey(BSsOriginal, :diminishing)
if csOriginal.behaviorSections[:cruising].dataPoints[1] > csOriginal.behaviorSections[:diminishing].dataPoints[1] if BSsOriginal[:cruising].dataPoints[1] > BSsOriginal[:diminishing].dataPoints[1]
reduceCruising=true reduceCruising=true
reduceDiminishing=false reduceDiminishing=false
else else
reduceDiminishing=true reduceDiminishing=true
reduceCruising=false reduceCruising=false
end end
elseif haskey(csOriginal.behaviorSections, :cruising) elseif haskey(BSsOriginal, :cruising)
reduceCruising=true reduceCruising=true
reduceDiminishing=false reduceDiminishing=false
elseif haskey(csOriginal.behaviorSections, :diminishing) elseif haskey(BSsOriginal, :diminishing)
reduceDiminishing=true reduceDiminishing=true
reduceCruising=false reduceCruising=false
end end
if reduceCruising if reduceCruising
cruisingReduction = settings[:stepSize] cruisingReduction = settings[:stepSize]
while cruisingReduction>=settings[:stepSize]/10^approximationLevel while cruisingReduction>=settings[:stepSize]/10^approximationLevel
#while cruisingReduction>=settings[:stepSize]/100 #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_exit) -> see below at the end of the while loop 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_exit]) -> see below at the end of the while loop
# create a copy for the characteristic sections drivingCourse # create a copy for the characteristic sections drivingCourse
energySavingStartId=get(csOriginal.behaviorSections, :cruising, BehaviorSection()).dataPoints[1] energySavingStartId=get(BSsOriginal, :cruising, BehaviorSection()).dataPoints[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
@ -131,44 +130,59 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
# calculating the new length of the cruising section # calculating the new length of the cruising section
if settings[:stepVariable]=="s in m" # distance step method if settings[:stepVariable]=="s in m" # distance step method
s_cruising = csOriginal.behaviorSections[:cruising].length - cruisingReduction s_cruising = BSsOriginal[:cruising].length - cruisingReduction
elseif settings[:stepVariable]=="t in s" # time step method elseif settings[:stepVariable]=="t in s" # time step method
# 09/20 old: doesn't work for non constant cruising -> TODO: should work now # 09/20 old: doesn't work for non constant cruising -> TODO: should work now
# t_cruising=csOriginal.behaviorSections[:cruising].t-cruisingReduction # t_cruising=BSsOriginal[:cruising].t-cruisingReduction
# s_cruising=t_cruising*drivingCourseModified[end].v # s_cruising=t_cruising*drivingCourseModified[end].v
distanceReduction = drivingCourse(csOriginal.behaviorSections[:cruising].dataPoints[end]).v*cruisingReduction distanceReduction = drivingCourse(BSsOriginal[:cruising].dataPoints[end]).v*cruisingReduction
s_cruising = csOriginal.behaviorSections[:cruising].length-distanceReduction s_cruising = BSsOriginal[:cruising].length-distanceReduction
elseif settings[:stepVariable]=="v in m/s" # velocity step method elseif settings[:stepVariable]=="v in m/s" # velocity step method
s_cruising=csOriginal.behaviorSections[:cruising].length-cruisingReduction*10 # TODO: or better: *100 ? s_cruising=BSsOriginal[:cruising].length-cruisingReduction*10 # TODO: or better: *100 ?
end #if end #if
s_cruising=max(0.0, s_cruising) s_cruising=max(0.0, s_cruising)
# copy csOriginal to csModified # 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_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}()) # 12/28 old: 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) #TODO after removing the mutable structs: Is it possible to just "copy"? with some changes
breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree]) csModified=Dict(:id => csOriginal[:id], # identifier
merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection)) :s_entry => csOriginal[:s_entry], # first position (in m)
csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E :s_exit => csOriginal[:s_exit], # last position (in m)
csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t :length => csOriginal[:length], # total length (in m)
:r_path => csOriginal[:r_path], # path resistance (in ‰)
:behaviorSections => Dict(), # empty list of containing behavior sections
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:v_limit => csOriginal[:v_limit], # speed limit (in m/s)
:v_peak => csOriginal[:v_peak], # maximum reachable speed (in m/s)
:v_entry => csOriginal[:v_entry], # maximum entry speed (in m/s)
:v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s)
BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree)
breakFreeSection=BehaviorSection(BSsOriginal[:breakFree])
merge!(BSsModified, Dict(:breakFree=>breakFreeSection))
csModified[:E] = csModified[:E] + BSsModified[:breakFree].E
csModified[:t] = csModified[:t] + BSsModified[:breakFree].t
end end
if haskey(csOriginal.behaviorSections, :clearing) # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located if haskey(BSsOriginal, :clearing) # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located
clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing]) clearingSection=BehaviorSection(BSsOriginal[:clearing])
merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection)) merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified.E = csModified.E + csModified.behaviorSections[:clearing].E csModified[:E] = csModified[:E] + BSsModified[:clearing].E
csModified.t = csModified.t + csModified.behaviorSections[:clearing].t csModified[:t] = csModified[:t] + BSsModified[:clearing].t
end end
if haskey(csOriginal.behaviorSections, :acceleration) if haskey(BSsOriginal, :acceleration)
accelerationSection=BehaviorSection(csOriginal.behaviorSections[:acceleration]) accelerationSection=BehaviorSection(BSsOriginal[:acceleration])
merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection)) merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E csModified[:E] = csModified[:E] + BSsModified[:acceleration].E
csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t csModified[:t] = csModified[:t] + BSsModified[:acceleration].t
end end
if haskey(csOriginal.behaviorSections, :diminishing) if haskey(BSsOriginal, :diminishing)
diminishingSection=BehaviorSection(csOriginal.behaviorSections[:diminishing]) diminishingSection=BehaviorSection(BSsOriginal[:diminishing])
merge!(csModified.behaviorSections, Dict(:diminishing=>diminishingSection)) merge!(BSsModified, Dict(:diminishing=>diminishingSection))
csModified.E = csModified.E + csModified.behaviorSections[:diminishing].E csModified[:E] = csModified[:E] + BSsModified[:diminishing].E
csModified.t = csModified.t + csModified.behaviorSections[:diminishing].t csModified[:t] = csModified[:t] + BSsModified[:diminishing].t
end end
@ -180,7 +194,7 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
# calculate the coasting phase until the point the train needs to brake # calculate the coasting phase until the point the train needs to brake
(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_exit if drivingCourseModified[end].v < csModified[:v_exit] || drivingCourseModified[end].s > csModified[:s_exit]
# the train reaches v_exit before reaching s_exit. 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_exit. 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
@ -189,16 +203,16 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
end # while cruisingReduction end # while cruisingReduction
# calculate the moving phase between coasting and the end of the CS # calculate the moving phase between coasting and the end of the CS
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)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].v == csModified.v_exit && drivingCourseModified[end].s < csModified.s_exit elseif drivingCourseModified[end].v == csModified[:v_exit] && drivingCourseModified[end].s < csModified[:s_exit]
# v_exit is already reached. Now cruise till the end of the CS # v_exit is already reached. Now cruise till the end of the CS
s_cruisingAfterCoasting=csModified.s_exit-drivingCourseModified[end].s s_cruisingAfterCoasting=csModified[:s_exit]-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-csOriginal.t || drivingCourseModified[end].v != csModified.v_exit || drivingCourseModified[end].s != csModified.s_exit # 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_exit are not reached excatly if t_recoveryAvailable < csModified[:t]-csOriginal[:t] || drivingCourseModified[end].v != csModified[:v_exit] || drivingCourseModified[end].s != csModified[:s_exit] # 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_exit are not reached excatly
cruisingReduction=cruisingReduction/10 cruisingReduction=cruisingReduction/10
else else
return (csModified, drivingCourseModified, true) return (csModified, drivingCourseModified, true)
@ -210,33 +224,47 @@ 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. # 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 # 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_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}()) # 12/28 old: 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) csModified=Dict(:id => csOriginal[:id], # identifier
breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree]) :s_entry => csOriginal[:s_entry], # first position (in m)
merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection)) :s_exit => csOriginal[:s_exit], # last position (in m)
csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E :length => csOriginal[:length], # total length (in m)
csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t :r_path => csOriginal[:r_path], # path resistance (in ‰)
:behaviorSections => Dict(), # empty list of containing behavior sections
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:v_limit => csOriginal[:v_limit], # speed limit (in m/s)
:v_peak => csOriginal[:v_peak], # maximum reachable speed (in m/s)
:v_entry => csOriginal[:v_entry], # maximum entry speed (in m/s)
:v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s)
BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree)
breakFreeSection=BehaviorSection(BSsOriginal[:breakFree])
merge!(BSsModified, Dict(:breakFree=>breakFreeSection))
csModified[:E] = csModified[:E] + BSsModified[:breakFree].E
csModified[:t] = csModified[:t] + BSsModified[:breakFree].t
end end
if haskey(csOriginal.behaviorSections, :clearing) # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located if haskey(BSsOriginal, :clearing) # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located
clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing]) clearingSection=BehaviorSection(BSsOriginal[:clearing])
merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection)) merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified.E = csModified.E + csModified.behaviorSections[:clearing].E csModified[:E] = csModified[:E] + BSsModified[:clearing].E
csModified.t = csModified.t + csModified.behaviorSections[:clearing].t csModified[:t] = csModified[:t] + BSsModified[:clearing].t
end end
if haskey(csOriginal.behaviorSections, :acceleration) if haskey(BSsOriginal, :acceleration)
accelerationSection=BehaviorSection(csOriginal.behaviorSections[:acceleration]) accelerationSection=BehaviorSection(BSsOriginal[:acceleration])
merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection)) merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E csModified[:E] = csModified[:E] + BSsModified[:acceleration].E
csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t csModified[:t] = csModified[:t] + BSsModified[:acceleration].t
end end
if haskey(csOriginal.behaviorSections, :cruising) if haskey(BSsOriginal, :cruising)
cruisingSection=BehaviorSection(csOriginal.behaviorSections[:cruising]) cruisingSection=BehaviorSection(BSsOriginal[:cruising])
merge!(csModified.behaviorSections, Dict(:cruising=>cruisingSection)) merge!(BSsModified, Dict(:cruising=>cruisingSection))
csModified.E = csModified.E + csModified.behaviorSections[:cruising].E csModified[:E] = csModified[:E] + BSsModified[:cruising].E
csModified.t = csModified.t + csModified.behaviorSections[:cruising].t csModified[:t] = csModified[:t] + BSsModified[:cruising].t
end end
diminishingSection=BehaviorSection(csOriginal.behaviorSections[:diminishing]) diminishingSection=BehaviorSection(BSsOriginal[:diminishing])
if length(diminishingSection.dataPoints) > 2 if length(diminishingSection.dataPoints) > 2
# remove the last diminishing waypoint # remove the last diminishing waypoint
pop!(diminishingSection.dataPoints) pop!(diminishingSection.dataPoints)
@ -247,14 +275,14 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
diminishingSection.t=drivingCourse[diminishingSection.dataPoints[end]].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s) diminishingSection.t=drivingCourse[diminishingSection.dataPoints[end]].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
diminishingSection.E=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws) diminishingSection.E=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
merge!(csModified.behaviorSections, Dict(:diminishing => diminishingSection)) merge!(BSsModified, Dict(:diminishing => diminishingSection))
csModified.E = csModified.E + csModified.behaviorSections[:diminishing].E csModified[:E] = csModified[:E] + BSsModified[:diminishing].E
csModified.t = csModified.t + csModified.behaviorSections[:diminishing].t csModified[:t] = csModified[:t] + BSsModified[:diminishing].t
energySavingStartId=diminishingSection.dataPoints[end] energySavingStartId=diminishingSection.dataPoints[end]
else else
# The diminishing section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section. # The diminishing section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section.
energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :diminishing, BehaviorSection())).dataPoints[1] energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :diminishing, BehaviorSection())).dataPoints[1]
end end
# copy the driving course till the beginning of energy saving # copy the driving course till the beginning of energy saving
@ -267,60 +295,77 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
(csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs)
# calculate the moving phase between coasting and the end of the CS # calculate the moving phase between coasting and the end of the CS
if drivingCourseModified[end].v > csModified.v_exit if drivingCourseModified[end].v > csModified[:v_exit]
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].v == csModified.v_exit && drivingCourseModified[end].s < csModified.s_exit elseif drivingCourseModified[end].v == csModified[:v_exit] && drivingCourseModified[end].s < csModified[:s_exit]
# v_exit is already reached. Now cruise till the end of the CS # v_exit is already reached. Now cruise till the end of the CS
s_cruisingAfterCoasting=csModified.s_exit-drivingCourseModified[end].s s_cruisingAfterCoasting=csModified[:s_exit]-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-csOriginal.t) if t_recoveryAvailable>=(csModified[:t]-csOriginal[:t])
return (csModified, drivingCourseModified, true) 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 else # time loss is to high. so there is no energy saving modification for this CS with the available recovery time
# TODO: just return false or take smaller steps? # TODO: just return false or take smaller steps?
return (CharacteristicSection(), [], false) # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end end
end end
# there is no energy saving modification for this CS with the available recovery time # there is no energy saving modification for this CS with the available recovery time
return (CharacteristicSection(), [], false) # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
else else
# there is no energy saving modification for this CS because a cruising section AND a braking section are needed to be transformed into a coasting section # there is no energy saving modification for this CS because a cruising section AND a braking section are needed to be transformed into a coasting section
return (CharacteristicSection(), [], false) # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end end
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::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, 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_peak > csOriginal.v_entry && csOriginal.v_peak > csOriginal.v_exit BSsOriginal = csOriginal[:behaviorSections]
accelerationSection = BehaviorSection(csOriginal.behaviorSections[:acceleration]) if haskey(BSsOriginal, :acceleration) && csOriginal[:v_peak] > csOriginal[:v_entry] && csOriginal[:v_peak] > csOriginal[:v_exit]
if drivingCourse[accelerationSection.dataPoints[end]-1].v < csOriginal.v_exit accelerationSection = BehaviorSection(BSsOriginal[:acceleration])
return (CharacteristicSection(), [], false) if drivingCourse[accelerationSection.dataPoints[end]-1].v < csOriginal[:v_exit]
# 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
# TODO: or calculate a new acceleration phase with v_exit as v_peak? 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 end
# copy csOriginal to csModified # 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_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}()) # 12/28 old: 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}())
csModified=Dict(:id => csOriginal[:id], # identifier
if haskey(csOriginal.behaviorSections, :breakFree) :s_entry => csOriginal[:s_entry], # first position (in m)
breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree]) :s_exit => csOriginal[:s_exit], # last position (in m)
merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection)) :length => csOriginal[:length], # total length (in m)
csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E :r_path => csOriginal[:r_path], # path resistance (in ‰)
csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t :behaviorSections => Dict(), # empty list of containing behavior sections
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:v_limit => csOriginal[:v_limit], # speed limit (in m/s)
:v_peak => csOriginal[:v_peak], # maximum reachable speed (in m/s)
:v_entry => csOriginal[:v_entry], # maximum entry speed (in m/s)
:v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s)
BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree)
breakFreeSection=BehaviorSection(BSsOriginal[:breakFree])
merge!(BSsModified, Dict(:breakFree=>breakFreeSection))
csModified[:E] = csModified[:E] + BSsModified[:breakFree].E
csModified[:t] = csModified[:t] + BSsModified[:breakFree].t
end end
#accelerationSection = BehaviorSection(get(csOriginal.behaviorSections, :acceleration, BehaviorSection())) #accelerationSection = BehaviorSection(get(BSsOriginal, :acceleration, BehaviorSection()))
if length(accelerationSection.dataPoints) > 2 if length(accelerationSection.dataPoints) > 2
if haskey(csOriginal.behaviorSections, :clearing) if haskey(BSsOriginal, :clearing)
clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing]) clearingSection=BehaviorSection(BSsOriginal[:clearing])
merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection)) merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified.E = csModified.E + csModified.behaviorSections[:clearing].E csModified[:E] = csModified[:E] + BSsModified[:clearing].E
csModified.t = csModified.t + csModified.behaviorSections[:clearing].t csModified[:t] = csModified[:t] + BSsModified[:clearing].t
end end
# remove the last acceleration waypoint # remove the last acceleration waypoint
@ -332,14 +377,14 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
accelerationSection.t=drivingCourse[accelerationSection.dataPoints[end]].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) accelerationSection.t=drivingCourse[accelerationSection.dataPoints[end]].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s)
accelerationSection.E=drivingCourse[accelerationSection.dataPoints[end]].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws) accelerationSection.E=drivingCourse[accelerationSection.dataPoints[end]].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection)) merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E csModified[:E] = csModified[:E] + BSsModified[:acceleration].E
csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t csModified[:t] = csModified[:t] + BSsModified[:acceleration].t
energySavingStartId=accelerationSection.dataPoints[end] energySavingStartId=accelerationSection.dataPoints[end]
else else
# The acceleration section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section. # The acceleration section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section.
energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :acceleration, BehaviorSection())).dataPoints[1] energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :acceleration, BehaviorSection())).dataPoints[1]
end end
# TODO: should v_peak be reduced or is it enough to pop the data points? # TODO: should v_peak be reduced or is it enough to pop the data points?
@ -351,58 +396,85 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
end end
#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-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_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 s_cruising=csModified[:s_exit]-drivingCourseModified[end].s-s_braking
if s_cruising >0.001 if s_cruising >0.001
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising") (csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end #if 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 # 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 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)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].s<csModified.s_exit elseif drivingCourseModified[end].s<csModified[:s_exit]
if (csModified.s_exit-drivingCourseModified[end].s)>0.001 if (csModified[:s_exit]-drivingCourseModified[end].s)>0.001
# if (csModified.s_exit-drivingCourseModified[end].s)>10^(-approximationLevel) # 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_peak.") # 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.") # println(" Therefore the calculation of this method can not continue for this CS.")
return (CharacteristicSection(), [], false) # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end end
println("WARNING: The end of new CS",csModified.id," is not reached while saving energy with lowering v_peak.") 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(" 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") println(" v=",drivingCourseModified[end].v," m/s v_exit=",csOriginal[:v_exit] ," m/s")
drivingCourseModified[end].s=csModified.s_exit # rounding up to s_exit drivingCourseModified[end].s=csModified[:s_exit] # rounding up to s_exit
end #if end #if
if t_recoveryAvailable>=(csModified.t-csOriginal.t) if t_recoveryAvailable>=(csModified[:t]-csOriginal[:t])
return (csModified, drivingCourseModified, true) 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 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: 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_peak-csModified.v_entry, csModified.v_peak-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? # TODO: just return false or take smaller steps?
return (CharacteristicSection(), [], false) # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end end
# 09/06 old: end #while # 09/06 old: end #while
# #
# 09/06 old: # there is no energy saving modification for this CS with the available recovery time # 09/06 old: # there is no energy saving modification for this CS with the available recovery time
# 09/06 old: return (CharacteristicSection(), [], false) # 09/06 old: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
# 12/29 new, now not with empty but with original CS and DC: return (csOriginal, drivingCourse, false)
else else
# 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 # 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) # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end #if haskey end #if haskey
end # function decreaseMaximumVelocity end # function decreaseMaximumVelocity
# combination of method 1 and method 2 # combination of method 1 and method 2
function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) function combineEnergySavingMethods(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
# 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 BSsOriginal = csOriginal[:behaviorSections]
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) # if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && csOriginal[:v_peak]>csOriginal[:v_entry] && csOriginal[:v_peak]>csOriginal[:v_exit]
csCombined=CharacteristicSection(csOriginal) if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && drivingCourse[get(BSsOriginal, :acceleration, BehaviorSection()).dataPoints[end]].v > max(csOriginal[:v_entry], csOriginal[:v_exit])
# 12/28 old: csCombined=CharacteristicSection(csOriginal)
#TODO after removing the mutable structs: Is it possible to just "copy"?
csCombined=Dict(:id => csOriginal[:id], # identifier
:s_entry => csOriginal[:s_entry], # first position (in m)
:s_exit => csOriginal[:s_exit], # last position (in m)
:length => csOriginal[:length], # total length (in m)
:r_path => csOriginal[:r_path], # path resistance (in ‰)
:behaviorSections => Dict(), # empty list of containing behavior sections
:t => csOriginal[:t], # total running time (in s)
:E => csOriginal[:E], # total energy consumption (in Ws)
:v_limit => csOriginal[:v_limit], # speed limit (in m/s)
:v_peak => csOriginal[:v_peak], # maximum reachable speed (in m/s)
:v_entry => csOriginal[:v_entry], # maximum entry speed (in m/s)
:v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s)
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for bs in 1: length(allBs)
if haskey(BSsOriginal, allBs[bs])
merge!(csCombined[:behaviorSections], Dict(allBs[bs] => BehaviorSection(BSsOriginal[allBs[bs]])))
end #if
end #for
drivingCourseCombined=Vector{DataPoint}() drivingCourseCombined=Vector{DataPoint}()
for i in 1:length(drivingCourse) for i in 1:length(drivingCourse)
# TODO: 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]))
@ -414,26 +486,28 @@ function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCo
while (Δt<t_recoveryAvailable && (Δt<=0.0 || ΔE<=0.0)) #Δ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-csCombined.E # saved energy (in Ws) ΔE=csOriginal[:E]-csCombined[:E] # saved energy (in Ws)
Δt=csCombined.t-csOriginal.t # time loss (in s) Δt=csCombined[:t]-csOriginal[:t] # time loss (in s)
while (haskey(csOriginal.behaviorSections, :cruising) && (Δt<=0.0 || ΔE<=0.0)) #Δt<=0.0) #&& ΔE<=0.0) # && Δt<=0.0) while (haskey(BSsOriginal, :cruising) && (Δt<=0.0 || ΔE<=0.0)) #Δt<=0.0) #&& ΔE<=0.0) # && Δt<=0.0)
(csCombined, drivingCourseCombined, newCoasting)=increaseCoastingSection(csCombined, drivingCourseCombined, settings, train, allCSs, t_recoveryAvailable-Δt) (csCombined, drivingCourseCombined, newCoasting)=increaseCoastingSection(csCombined, drivingCourseCombined, settings, train, allCSs, t_recoveryAvailable-Δt)
if newCoasting if newCoasting
ΔE=csOriginal.E-csCombined.E # saved energy (in Ws) ΔE=csOriginal[:E]-csCombined[:E] # saved energy (in Ws)
Δt=csCombined.t-csOriginal.t # time loss (in s) Δt=csCombined[:t]-csOriginal[:t] # time loss (in s)
else else
break break
end # if newCoasting end # if newCoasting
end # while haskey end # while haskey
else else
return (CharacteristicSection(), [], false) # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end # if newMaximumVelocity end # if newMaximumVelocity
end # while end # while
return (csCombined, drivingCourseCombined, (ΔE>0.0))# && Δt>0.0)) return (csCombined, drivingCourseCombined, (ΔE>0.0))# && Δt>0.0))
else else
# 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 # 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) # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes?
return (csOriginal, drivingCourse, false)
end #if end #if
end #function combineEnergySavingMethods end #function combineEnergySavingMethods

View File

@ -317,7 +317,7 @@ function inputTrain(trainDirectory::String)
train= Dict(:name => name, # train's name train= Dict(:name => name, # train's name
:id => id, # train's identifier :id => id, # train's identifier
:trainType => trainType, # type of train "passenger" or "freight" or "motor coach train" :trainType => trainType, # type of train "passenger" or "freight" or "motor coach train"
:trainLength => trainLength, # total length (in m) :trainLength => trainLength,# total length (in m)
:v_limit => v_limit, # trains speed limit (in m/s) :v_limit => v_limit, # trains speed limit (in m/s)
:a_braking => a_braking, # braking acceleration (in m/s^2) :a_braking => a_braking, # braking acceleration (in m/s^2)
:m_train => m_train, # total mass (in kg) :m_train => m_train, # total mass (in kg)

View File

@ -80,10 +80,10 @@ end #function calculateWagonsResistance
""" """
calculate and return the path resistance dependend on the trains position and mass model calculate and return the path resistance dependend on the trains position and mass model
""" """
function calculatePathResistance(s::AbstractFloat, massModel::String, train::Dict, CSs::Vector{CharacteristicSection}) function calculatePathResistance(s::Real, massModel::String, train::Dict, CSs::Vector{Dict})
# looking for the characteristic section with the trains head position # looking for the characteristic section with the trains head position
id=length(CSs) id=length(CSs)
while s<CSs[id].s_entry while s<CSs[id][:s_entry]
id=id-1 id=id-1
if id==0 if id==0
println("s=",s," MS.s_entry=",CSs[1].s_entry) println("s=",s," MS.s_entry=",CSs[1].s_entry)
@ -91,11 +91,11 @@ function calculatePathResistance(s::AbstractFloat, massModel::String, train::Dic
end #while end #while
if massModel=="mass point" if massModel=="mass point"
pathResistance=CSs[id].r_path/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" elseif massModel=="homogeneous strip"
pathResistance=0.0 pathResistance=0.0
while id>0 && s-train[:trainLength]<CSs[id].s_exit while id>0 && s-train[:trainLength]<CSs[id][:s_exit]
pathResistance=pathResistance+(min(s, CSs[id].s_exit)-max(s-train[:trainLength], CSs[id].s_entry))/train[:trainLength]*(CSs[id].r_path/1000*train[:m_train]*g) # /1000 because of the unit ‰ pathResistance=pathResistance+(min(s, CSs[id][:s_exit])-max(s-train[:trainLength], CSs[id][:s_entry]))/train[:trainLength]*(CSs[id][:r_path]/1000*train[:m_train]*g) # /1000 because of the unit ‰
id=id-1 id=id-1
if id==0 if id==0
# TODO: currently for values < movingSection[:s_entry] the values of movingSection[:s_entry] will be used # TODO: currently for values < movingSection[:s_entry] the values of movingSection[:s_entry] will be used
@ -112,7 +112,7 @@ end #function pathResistance
""" """
calculate and return tractive and resisting forces for a data point calculate and return tractive and resisting forces for a data point
""" """
function calculateForces!(dataPoint::DataPoint, train::Dict, massModel::String, CSs::Vector{CharacteristicSection}, bsType::String) function calculateForces!(dataPoint::DataPoint, train::Dict, massModel::String, CSs::Vector{Dict}, bsType::String)
# calculate resisting forces # calculate resisting forces
dataPoint.R_traction=calculateTractionUnitResistance(dataPoint.v, train) dataPoint.R_traction=calculateTractionUnitResistance(dataPoint.v, train)
dataPoint.R_wagons=calculateWagonsResistance(dataPoint.v, train) dataPoint.R_wagons=calculateWagonsResistance(dataPoint.v, train)
@ -189,13 +189,13 @@ 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 # 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, trainLength::Real) function detectFormerSpeedLimits(CSs::Vector{Dict}, csWithTrainHeadId::Integer, currentPoint::DataPoint, trainLength::Real)
formerSpeedLimits=[] formerSpeedLimits=[]
if csWithTrainHeadId > 1 && currentPoint.s - trainLength < CSs[csWithTrainHeadId].s_entry if csWithTrainHeadId > 1 && currentPoint.s - trainLength < CSs[csWithTrainHeadId][:s_entry]
formerCsId=csWithTrainHeadId-1 formerCsId=csWithTrainHeadId-1
while formerCsId > 0 && currentPoint.s - trainLength < 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 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]) push!(formerSpeedLimits, [CSs[formerCsId][:s_exit], CSs[formerCsId][:v_limit]])
for i in 1:length(formerSpeedLimits)-1 for i in 1:length(formerSpeedLimits)-1
if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2] if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2]
pop!(formerSpeedLimits) pop!(formerSpeedLimits)
@ -209,34 +209,34 @@ function detectFormerSpeedLimits(CSs::Vector{CharacteristicSection}, csWithTrain
return formerSpeedLimits return formerSpeedLimits
end # function detectFormerSpeedLimits end # function detectFormerSpeedLimits
function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, formerSpeedLimits, accelerationSection::BehaviorSection) function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits, accelerationSection::BehaviorSection)
# TODO: What is the type of formerSpeedLimits? function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, formerSpeedLimits::Array{Array{AbstractFloat,1},1}, accelerationSection::BehaviorSection) # TODO: What is the type of formerSpeedLimits? function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Array{AbstractFloat,1},1}, accelerationSection::BehaviorSection)
# would work: function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, formerSpeedLimits::Array{Any,1}, accelerationSection::BehaviorSection) # would work: function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Any,1}, accelerationSection::BehaviorSection)
if length(formerSpeedLimits) > 0 if length(formerSpeedLimits) > 0
# if a former speed limit has been exceeded the acceleration steps of this CS will be removed and a clearing phase will be inserted before acceleration # if a former speed limit has been exceeded the acceleration steps of this CS will be removed and a clearing phase will be inserted before acceleration
if drivingCourse[end].v > formerSpeedLimits[end][2] if drivingCourse[end].v > formerSpeedLimits[end][2]
while drivingCourse[end].s > get(CS.behaviorSections, :clearing, accelerationSection).s_entry while drivingCourse[end].s > get(CS[:behaviorSections], :clearing, accelerationSection).s_entry
pop!(drivingCourse) pop!(drivingCourse)
end end
if haskey(CS.behaviorSections, :clearing) if haskey(CS[:behaviorSections], :clearing)
CS.t = CS.t-CS.behaviorSections[:clearing].t # reducing the total running time (in s) CS[:t] = CS[:t]-CS[:behaviorSections][:clearing].t # reducing the total running time (in s)
CS.E = CS.E-CS.behaviorSections[:clearing].E # reducing the total energy consumption (in Ws) CS[:E] = CS[:E]-CS[:behaviorSections][:clearing].E # reducing the total energy consumption (in Ws)
delete!(CS.behaviorSections, :clearing) delete!(CS[:behaviorSections], :clearing)
end end
# create a (new and longer) clearing section # 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_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[:trainLength])) s_clearing=min(CS[:s_exit]-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:trainLength]))
if s_clearing>0.0 if s_clearing>0.0
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
else else
error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS.id) error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id])
end end
# 09/22: if drivingCourse[end].s < CS.s_exit # 09/22: if drivingCourse[end].s < CS[:s_exit]
if drivingCourse[end].s < CS.s_exit-s_braking if drivingCourse[end].s < CS[:s_exit]-s_braking
# reset the accelerationSection # reset the accelerationSection
accelerationSection=BehaviorSection() accelerationSection=BehaviorSection()
accelerationSection.type="acceleration" # type of behavior section accelerationSection.type="acceleration" # type of behavior section
@ -260,8 +260,8 @@ end # function considerFormerSpeedLimits!
## This function calculates the data points of the breakFree phase. ## This function calculates the data points of the breakFree phase.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed.
# Info: currently the values of the breakFree phase will be calculated like in the acceleration phase # Info: currently the values of the breakFree phase will be calculated like in the acceleration phase
function addBreakFreePhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) function addBreakFreePhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end].v==0.0 && drivingCourse[end].s<CS.s_exit if drivingCourse[end].v==0.0 && drivingCourse[end].s<CS[:s_exit]
breakFreeSection=BehaviorSection() breakFreeSection=BehaviorSection()
breakFreeSection.type="breakFree" # type of behavior section breakFreeSection.type="breakFree" # type of behavior section
breakFreeSection.s_entry=drivingCourse[end].s # first position (in m) breakFreeSection.s_entry=drivingCourse[end].s # first position (in m)
@ -281,7 +281,7 @@ function addBreakFreePhase!(CS::CharacteristicSection, drivingCourse::Vector{Dat
end end
# creating the next data point # creating the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], settings[:stepSize], CS.id)) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], settings[:stepSize], CS[:id]))
drivingCourse[end].behavior = breakFreeSection.type drivingCourse[end].behavior = breakFreeSection.type
#= 07/30 TODO: the calculation is easier with these lines because the values that are 0 in the first step are not used in calculation but all in all the code gets easier without these lines: #= 07/30 TODO: the calculation is easier with these lines because the values that are 0 in the first step are not used in calculation but all in all the code gets easier without these lines:
push!(drivingCourse, DataPoint()) push!(drivingCourse, DataPoint())
@ -320,10 +320,10 @@ function addBreakFreePhase!(CS::CharacteristicSection, drivingCourse::Vector{Dat
breakFreeSection.t=drivingCourse[end].t-drivingCourse[breakFreeSection.dataPoints[1]].t # total running time (in s) breakFreeSection.t=drivingCourse[end].t-drivingCourse[breakFreeSection.dataPoints[1]].t # total running time (in s)
breakFreeSection.E=drivingCourse[end].E-drivingCourse[breakFreeSection.dataPoints[1]].E # total energy consumption (in Ws) breakFreeSection.E=drivingCourse[end].E-drivingCourse[breakFreeSection.dataPoints[1]].E # total energy consumption (in Ws)
CS.t=CS.t+breakFreeSection.t # total running time (in s) CS[:t]=CS[:t]+breakFreeSection.t # total running time (in s)
CS.E=CS.E+breakFreeSection.E # total energy consumption (in Ws) CS[:E]=CS[:E]+breakFreeSection.E # total energy consumption (in Ws)
merge!(CS.behaviorSections, Dict(:breakFree => breakFreeSection)) merge!(CS[:behaviorSections], Dict(:breakFree => breakFreeSection))
end # else: return the characteristic section without a breakFree section end # else: return the characteristic section without a breakFree section
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addBreakFreePhase! end #function addBreakFreePhase!
@ -331,7 +331,7 @@ end #function addBreakFreePhase!
## This function calculates the data points of the acceleration phase. ## This function calculates the data points of the acceleration phase.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the acceleration section # Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the acceleration section
function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end].v==0.0 if drivingCourse[end].v==0.0
(CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
end #if end #if
@ -343,16 +343,16 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
end 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 # 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[:trainLength]) formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:trainLength])
# conditions for acceleration phase # conditions for acceleration phase
targetSpeedReached = drivingCourse[end].v >= CS.v_peak targetSpeedReached = drivingCourse[end].v >= CS[:v_peak]
trainAtEnd = drivingCourse[end].s >= CS.s_exit trainAtEnd = drivingCourse[end].s >= CS[:s_exit]
tractionSurplus = drivingCourse[end].F_T > drivingCourse[end].F_R tractionSurplus = drivingCourse[end].F_T > drivingCourse[end].F_R
# use the conditions for the acceleration phase # use the conditions for the acceleration phase
if !targetSpeedReached && !trainAtEnd && tractionSurplus if !targetSpeedReached && !trainAtEnd && tractionSurplus
#11/23 long version: if drivingCourse[end].v < CS.v_peak && drivingCourse[end].s <CS.s_exit && drivingCourse[end].F_T > drivingCourse[end].F_R #11/23 long version: if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s <CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R
accelerationSection=BehaviorSection() accelerationSection=BehaviorSection()
accelerationSection.type="acceleration" # type of behavior section accelerationSection.type="acceleration" # type of behavior section
accelerationSection.s_entry=drivingCourse[end].s # first position (in m) 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 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 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<CS.v_peak && drivingCourse[end].s<CS.s_exit && drivingCourse[end].F_T > drivingCourse[end].F_R while drivingCourse[end].v<CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
# 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) # 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
@ -370,7 +370,7 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
# create the next data point # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = accelerationSection.type drivingCourse[end].behavior = accelerationSection.type
push!(accelerationSection.dataPoints, drivingCourse[end].i) push!(accelerationSection.dataPoints, drivingCourse[end].i)
# calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) # calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
@ -391,30 +391,30 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].s>CS.s_exit elseif drivingCourse[end].s>CS[:s_exit]
if settings[:stepVariable] == "s in m" if settings[:stepVariable] == "s in m"
currentStepSize=CS.s_exit-drivingCourse[end-1].s currentStepSize=CS[:s_exit]-drivingCourse[end-1].s
else else
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
end end
elseif drivingCourse[end].v>CS.v_peak elseif drivingCourse[end].v>CS[:v_peak]
if settings[:stepVariable]=="v in m/s" if settings[:stepVariable]=="v in m/s"
currentStepSize=CS.v_peak-drivingCourse[end-1].v currentStepSize=CS[:v_peak]-drivingCourse[end-1].v
else else
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
end end
elseif drivingCourse[end].s==CS.s_exit elseif drivingCourse[end].s==CS[:s_exit]
break break
elseif drivingCourse[end].v==CS.v_peak elseif drivingCourse[end].v==CS[:v_peak]
break break
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
else else
error("ERROR at acceleration phase: With the step variable ", settings[:stepVariable]," the while loop will be left although v<v_peak and s<s_exit in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") error("ERROR at acceleration phase: With the step variable ", settings[:stepVariable]," the while loop will be left although v<v_peak and s<s_exit in CS",CS[:id]," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
end end
# delete last data point for recalculating the last step with reduced step size # delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
@ -423,15 +423,15 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
# push!(accelerationSection.dataPoints, drivingCourse[end].i) # push!(accelerationSection.dataPoints, drivingCourse[end].i)
error("ERROR: The train stops during the acceleration phase in CS",CS.id," because the tractive effort is lower than the resistant forces.", error("ERROR: The train stops during the acceleration phase in CS",CS[:id]," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.") " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.")
elseif drivingCourse[end].v>CS.v_peak elseif drivingCourse[end].v>CS[:v_peak]
pop!(drivingCourse) pop!(drivingCourse)
pop!(accelerationSection.dataPoints) pop!(accelerationSection.dataPoints)
elseif drivingCourse[end].s>CS.s_exit elseif drivingCourse[end].s>CS[:s_exit]
drivingCourse[end].s=CS.s_exit # rounding s down to s_exit drivingCourse[end].s=CS[:s_exit] # rounding s down to s_exit
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
(CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
@ -450,15 +450,15 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
accelerationSection.length=accelerationSection.s_exit-accelerationSection.s_entry # total length (in m) accelerationSection.length=accelerationSection.s_exit-accelerationSection.s_entry # total length (in m)
accelerationSection.t=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) 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) accelerationSection.E=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
CS.t=CS.t+accelerationSection.t # total running time (in s) CS[:t]=CS[:t]+accelerationSection.t # total running time (in s)
CS.E=CS.E+accelerationSection.E # total energy consumption (in Ws) CS[:E]=CS[:E]+accelerationSection.E # total energy consumption (in Ws)
# TODO: this warning schould not be needed. just for testing # TODO: this warning schould not be needed. just for testing
if CS.v_peak < drivingCourse[end].v 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) println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_peak=",CS[:v_peak])
end end
merge!(CS.behaviorSections, Dict(:acceleration=>accelerationSection)) merge!(CS[:behaviorSections], Dict(:acceleration=>accelerationSection))
end end
end # else: just return the given data point number without changes due to the acceleration phase end # else: just return the given data point number without changes due to the acceleration phase
@ -467,7 +467,7 @@ end #function addAccelerationPhase!
## This function calculates the data points of the acceleration phase. ## This function calculates the data points of the acceleration phase.
function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end].v==0.0 if drivingCourse[end].v==0.0
(CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
end #if end #if
@ -479,11 +479,11 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
end 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 # 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[:trainLength]) formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:trainLength])
# 11/23 old without F_T>F_R: if drivingCourse[end].v < CS.v_peak && drivingCourse[end].s<CS.s_exit # 11/23 old without F_T>F_R: if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s<CS[:s_exit]
if drivingCourse[end].v < CS.v_peak && drivingCourse[end].s<CS.s_exit && drivingCourse[end].F_T > drivingCourse[end].F_R if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R
accelerationSection=BehaviorSection() accelerationSection=BehaviorSection()
accelerationSection.type="acceleration" # type of behavior section accelerationSection.type="acceleration" # type of behavior section
accelerationSection.s_entry=drivingCourse[end].s # first position (in m) accelerationSection.s_entry=drivingCourse[end].s # first position (in m)
@ -493,9 +493,9 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections 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 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)) 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_peak && drivingCourse[end].s+s_braking<CS.s_exit && 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<CS[:s_exit] && drivingCourse[end].F_T > 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_braking<CS.s_exit && drivingCourse[end].v>0.0 && drivingCourse[end].F_T > 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_braking<CS[:s_exit] && drivingCourse[end].v>0.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) #11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
@ -506,7 +506,7 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
# end # end
# create the next data point # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = accelerationSection.type drivingCourse[end].behavior = accelerationSection.type
push!(accelerationSection.dataPoints, drivingCourse[end].i) push!(accelerationSection.dataPoints, drivingCourse[end].i)
# 12/03: was moved behind considerFormerSpeedLimits: calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) # 12/03: was moved behind considerFormerSpeedLimits: calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
@ -518,7 +518,7 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
end end
end end
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
end #while end #while
# check which limit was reached and adjust the currentStepSize for the next cycle # check which limit was reached and adjust the currentStepSize for the next cycle
@ -526,27 +526,27 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].s +s_braking > CS.s_exit elseif drivingCourse[end].s +s_braking > CS[:s_exit]
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].v>CS.v_peak elseif drivingCourse[end].v>CS[:v_peak]
if settings[:stepVariable]=="v in m/s" if settings[:stepVariable]=="v in m/s"
currentStepSize= CS.v_peak-drivingCourse[end-1].v currentStepSize= CS[:v_peak]-drivingCourse[end-1].v
else else
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
end end
elseif drivingCourse[end].s==CS.s_exit elseif drivingCourse[end].s==CS[:s_exit]
break break
elseif drivingCourse[end].v==CS.v_peak elseif drivingCourse[end].v==CS[:v_peak]
break break
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
else else
error("ERROR at acceleration until braking phase: With the step variable ",settings[:stepVariable]," the while loop will be left although v<v_peak and s<s_exit in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") error("ERROR at acceleration until braking phase: With the step variable ",settings[:stepVariable]," the while loop will be left although v<v_peak and s<s_exit in CS",CS[:id]," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
end end
# delete last data point for recalculating the last step with reduced step size # delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
@ -555,14 +555,14 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
# push!(accelerationSection.dataPoints, drivingCourse[end].i) # push!(accelerationSection.dataPoints, drivingCourse[end].i)
error("ERROR: The train stops during the acceleration phase in CS",CS.id," because the tractive effort is lower than the resistant forces.", error("ERROR: The train stops during the acceleration phase in CS",CS[:id]," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.") " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.")
elseif drivingCourse[end].v>CS.v_peak elseif drivingCourse[end].v>CS[:v_peak]
pop!(drivingCourse) pop!(drivingCourse)
pop!(accelerationSection.dataPoints) pop!(accelerationSection.dataPoints)
elseif drivingCourse[end].s + s_braking > CS.s_exit elseif drivingCourse[end].s + s_braking > CS[:s_exit]
pop!(drivingCourse) pop!(drivingCourse)
pop!(accelerationSection.dataPoints) pop!(accelerationSection.dataPoints)
@ -584,11 +584,11 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
accelerationSection.t=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) 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) accelerationSection.E=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
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[: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[:t]=CS[:t]+accelerationSection.t # total running time (in s)
CS.E=CS.E+accelerationSection.E # total energy consumption (in Ws) CS[:E]=CS[:E]+accelerationSection.E # total energy consumption (in Ws)
merge!(CS.behaviorSections, Dict(:acceleration=>accelerationSection)) merge!(CS[:behaviorSections], Dict(:acceleration=>accelerationSection))
end end
end # else: just return the given data point number without changes due to the acceleration phase end # else: just return the given data point number without changes due to the acceleration phase
return (CS, drivingCourse) return (CS, drivingCourse)
@ -597,37 +597,37 @@ end #function addAccelerationPhaseUntilBraking!
## This function calculates the data points of the cruising phase. ## This function calculates the data points of the cruising phase.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for cruising if needed. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for cruising if needed.
function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, s_cruising::AbstractFloat, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, cruisingType::String) function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruising::Real, settings::Dict, train::Dict, CSs::Vector{Dict}, cruisingType::String)
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"? calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"?
if drivingCourse[end].F_T < drivingCourse[end].F_R if drivingCourse[end].F_T < drivingCourse[end].F_R
(CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")) drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising"))
s_cruising = max(0.0, s_cruising-get(CS.behaviorSections, :diminishing, BehaviorSection()).length) s_cruising = max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, BehaviorSection()).length)
end end
if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s<CS.s_exit && drivingCourse[end].F_T >= drivingCourse[end].F_R if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] && drivingCourse[end].F_T >= drivingCourse[end].F_R
# 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s<CS.s_exit # 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit]
cruisingSection=BehaviorSection() cruisingSection=BehaviorSection()
cruisingSection.type=cruisingType # type of behavior section cruisingSection.type=cruisingType # type of behavior section
cruisingSection.s_entry=drivingCourse[end].s # first position (in m) cruisingSection.s_entry=drivingCourse[end].s # first position (in m)
# 11/22: now it is at the end of the BS: cruisingSection.s_exit=min(drivingCourse[end].s+s_cruising, CS.s_exit) # last position (in m) # 11/22: now it is at the end of the BS: cruisingSection.s_exit=min(drivingCourse[end].s+s_cruising, CS[:s_exit]) # last position (in m)
cruisingSection.v_entry=drivingCourse[end].v # entry speed (in m/s) cruisingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(cruisingSection.dataPoints, drivingCourse[end].i) push!(cruisingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = cruisingSection.type drivingCourse[end].behavior = cruisingSection.type
# TODO: necessary? # TODO: necessary?
s_cruising=min(s_cruising, CS.s_exit-cruisingSection.s_entry) s_cruising=min(s_cruising, CS[:s_exit]-cruisingSection.s_entry)
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"? calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"?
# 11/05 old: drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")) # 11/05 old: drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising"))
if settings[:massModel]=="homogeneous strip" && CS.id > 1 if settings[:massModel]=="homogeneous strip" && CS[:id] > 1
currentStepSize=settings[:stepSize] 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 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[:trainLength] && drivingCourse[end].s<cruisingSection.s_entry+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s<CS.s_exit while drivingCourse[end].s < CS[:s_entry] + train[:trainLength] && drivingCourse[end].s<cruisingSection.s_entry+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit]
# TODO: whithout CSs should work as well, no? while drivingCourse[end].s < CSs[CS.id].s_entry + train[:trainLength] && drivingCourse[end].s<cruisingSection.s_entry+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s<CS.s_exit # TODO: whithout CSs should work as well, no? while drivingCourse[end].s < CSs[CS[:id]].s_entry + train[:trainLength] && drivingCourse[end].s<cruisingSection.s_entry+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit]
# the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_peak OR the mass model homogeneous strip is used and parts of the train are still in former CS # the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_peak OR the mass model homogeneous strip is used and parts of the train are still in former CS
#TODO: maybe just consider former CS with different path resistance? #TODO: maybe just consider former CS with different path resistance?
#TODO: what about the case: After leaving a former CS with steep gradient the train can accelerate. Now in this tool the train will cruise at v_i. Just accelerating until v_peak could make problems for energy saving by shortening the acceleration phase #TODO: what about the case: After leaving a former CS with steep gradient the train can accelerate. Now in this tool the train will cruise at v_i. Just accelerating until v_peak could make problems for energy saving by shortening the acceleration phase
@ -637,9 +637,9 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
# create the next data point # create the next data point
if settings[:stepVariable]=="s in m" if settings[:stepVariable]=="s in m"
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", currentStepSize, CS.id)) push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", currentStepSize, CS[:id]))
else else
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train[:trainLength]/(10.0^cycle), CS.id)) # TODO which step size should be used? push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train[:trainLength]/(10.0^cycle), CS[:id])) # TODO which step size should be used?
end end
drivingCourse[end].behavior = cruisingSection.type drivingCourse[end].behavior = cruisingSection.type
push!(cruisingSection.dataPoints, drivingCourse[end].i) push!(cruisingSection.dataPoints, drivingCourse[end].i)
@ -655,13 +655,13 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
# check which limit was reached and adjust the currentStepSize for the next cycle # check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1 if cycle < approximationLevel+1
if drivingCourse[end].s>cruisingSection.s_entry+s_cruising # TODO also the following? drivingCourse[end].s > CSs[CS.id].s_entry + train[:trainLength])) 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" if settings[:stepVariable] == "s in m"
currentStepSize=cruisingSection.s_entry+s_cruising-drivingCourse[end-1].s currentStepSize=cruisingSection.s_entry+s_cruising-drivingCourse[end-1].s
else else
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
end end
elseif drivingCourse[end].s==cruisingSection.s_entry+s_cruising # || drivingCourse[end].s==CS.s_exit elseif drivingCourse[end].s==cruisingSection.s_entry+s_cruising # || drivingCourse[end].s==CS[:s_exit]
break break
elseif drivingCourse[end].F_T < drivingCourse[end].F_R elseif drivingCourse[end].F_T < drivingCourse[end].F_R
# if settings[:stepVariable] == "s in m" # if settings[:stepVariable] == "s in m"
@ -669,11 +669,11 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
# else # else
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
# end # end
elseif drivingCourse[end].s >= CS.s_entry + train[:trainLength] 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] # TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS[:id]].s_entry + train[:trainLength]
break break
else # TODO copied from addAccelerationPhase -> probably not needed here !? 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") 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")
end end
# delete last data point for recalculating the last step with reduced step size # delete last data point for recalculating the last step with reduced step size
@ -696,7 +696,7 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
(CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")
# s_cruising=max(0.0, s_cruising-get(CS.behaviorSections, :diminishing, BehaviorSection()).length) # s_cruising=max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, BehaviorSection()).length)
else else
@ -714,7 +714,7 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
s_cruisingRemaining=cruisingSection.s_entry+s_cruising-drivingCourse[end].s s_cruisingRemaining=cruisingSection.s_entry+s_cruising-drivingCourse[end].s
# create the next data point # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS.id)) push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS[:id]))
drivingCourse[end].behavior = cruisingSection.type drivingCourse[end].behavior = cruisingSection.type
push!(cruisingSection.dataPoints, drivingCourse[end].i) push!(cruisingSection.dataPoints, drivingCourse[end].i)
end end
@ -726,10 +726,10 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
cruisingSection.t=drivingCourse[end].t-drivingCourse[cruisingSection.dataPoints[1]].t # total running time (in s) cruisingSection.t=drivingCourse[end].t-drivingCourse[cruisingSection.dataPoints[1]].t # total running time (in s)
cruisingSection.E=drivingCourse[end].E-drivingCourse[cruisingSection.dataPoints[1]].E # total energy consumption (in Ws) cruisingSection.E=drivingCourse[end].E-drivingCourse[cruisingSection.dataPoints[1]].E # total energy consumption (in Ws)
CS.t=CS.t+cruisingSection.t # total running time (in s) CS[:t]=CS[:t]+cruisingSection.t # total running time (in s)
CS.E=CS.E+cruisingSection.E # total energy consumption (in Ws) CS[:E]=CS[:E]+cruisingSection.E # total energy consumption (in Ws)
merge!(CS.behaviorSections, Dict(Symbol(cruisingSection.type) => cruisingSection)) merge!(CS[:behaviorSections], Dict(Symbol(cruisingSection.type) => cruisingSection))
end # else: return the characteristic section without a cruising section end # else: return the characteristic section without a cruising section
return (CS, drivingCourse) return (CS, drivingCourse)
@ -737,11 +737,11 @@ end #function addCruisingPhase!
## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower ## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower
function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing") calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing")
if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s<CS.s_exit if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s<CS[:s_exit]
#drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s<CS.s_exit #drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit]
diminishingSection=BehaviorSection() diminishingSection=BehaviorSection()
diminishingSection.type="diminishing" # type of behavior section diminishingSection.type="diminishing" # type of behavior section
diminishingSection.s_entry=drivingCourse[end].s # first position (in m) diminishingSection.s_entry=drivingCourse[end].s # first position (in m)
@ -751,9 +751,9 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections 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 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)) s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
while drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].s+s_braking<CS.s_exit && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend while drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].s+s_braking<CS[:s_exit] && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
# 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking<CS.s_exit && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend # 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking<CS[:s_exit] && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type) #11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type)
@ -765,11 +765,11 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
#end #end
# create the next data point # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = diminishingSection.type drivingCourse[end].behavior = diminishingSection.type
push!(diminishingSection.dataPoints, drivingCourse[end].i) push!(diminishingSection.dataPoints, drivingCourse[end].i)
s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type)
end #while end #while
@ -778,18 +778,18 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].s + s_braking > CS.s_exit elseif drivingCourse[end].s + s_braking > CS[:s_exit]
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].s + s_braking==CS.s_exit elseif drivingCourse[end].s + s_braking==CS[:s_exit]
# 11/21 old without s_braking: elseif drivingCourse[end].s==CS.s_exit # 11/21 old without s_braking: elseif drivingCourse[end].s==CS[:s_exit]
break break
elseif drivingCourse[end].F_T > drivingCourse[end].F_R elseif drivingCourse[end].F_T > drivingCourse[end].F_R
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
else else
error("ERROR during diminishing run: With the step variable ",settings[:stepVariable]," the while loop will be left although s+s_braking<s_exit && v>0.0 in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") error("ERROR during diminishing run: With the step variable ",settings[:stepVariable]," the while loop will be left although s+s_braking<s_exit && v>0.0 in CS",CS[:id]," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
end end
# delete last data point for recalculating the last step with reduced step size # delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
@ -798,11 +798,11 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
# push!(diminishingSection.dataPoints, drivingCourse[end].i) # push!(diminishingSection.dataPoints, drivingCourse[end].i)
error("ERROR: The train stops during diminishing run in CS",CS.id," because the maximum tractive effort is lower than the resistant forces.", error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.") " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.")
elseif drivingCourse[end].s + s_braking > CS.s_exit elseif drivingCourse[end].s + s_braking > CS[:s_exit]
pop!(drivingCourse) pop!(drivingCourse)
pop!(diminishingSection.dataPoints) pop!(diminishingSection.dataPoints)
@ -822,10 +822,10 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m) diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m)
diminishingSection.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s) diminishingSection.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws) diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
CS.t=CS.t+diminishingSection.t # total running time (in s) CS[:t]=CS[:t]+diminishingSection.t # total running time (in s)
CS.E=CS.E+diminishingSection.E # total energy consumption (in Ws) CS[:E]=CS[:E]+diminishingSection.E # total energy consumption (in Ws)
merge!(CS.behaviorSections, Dict(:diminishing=>diminishingSection)) merge!(CS[:behaviorSections], Dict(:diminishing=>diminishingSection))
end end
end end
@ -835,11 +835,11 @@ end #function addDiminishingPhase!
## This function calculates the data points of the coasting phase. ## This function calculates the data points of the coasting phase.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section # 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}) function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
## 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 ## 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[:trainLength]) #formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:trainLength])
if drivingCourse[end].v>CS.v_exit && drivingCourse[end].s<CS.s_exit if drivingCourse[end].v>CS[:v_exit] && drivingCourse[end].s<CS[:s_exit]
coastingSection=BehaviorSection() coastingSection=BehaviorSection()
coastingSection.type="coasting" # type of behavior section coastingSection.type="coasting" # type of behavior section
coastingSection.s_entry=drivingCourse[end].s # first position (in m) coastingSection.s_entry=drivingCourse[end].s # first position (in m)
@ -850,8 +850,8 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse:
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
# 08/24 old for cycle in 1:3 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size # 08/24 old for cycle in 1:3 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size
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 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=ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel) s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)
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 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): # traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, coastingSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, coastingSection.type)
@ -859,38 +859,38 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse:
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
# creating the next data point # creating the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = coastingSection.type drivingCourse[end].behavior = coastingSection.type
push!(coastingSection.dataPoints, drivingCourse[end].i) push!(coastingSection.dataPoints, drivingCourse[end].i)
s_braking=ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking]) s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking])
end # while end # while
# check which limit was reached and adjust the currentStepSize for the next cycle # check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1 if cycle < approximationLevel+1
if drivingCourse[end].s + s_braking > CS.s_exit if drivingCourse[end].s + s_braking > CS[:s_exit]
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].v < CS.v_exit # TODO: if accelereation and coasting functions will be combined this case is only for coasting 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 currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].v > CS.v_peak elseif drivingCourse[end].v > CS[:v_peak]
if settings[:stepVariable]=="v in m/s" if settings[:stepVariable]=="v in m/s"
currentStepSize = CS.v_peak-drivingCourse[end-1].v currentStepSize = CS[:v_peak]-drivingCourse[end-1].v
else else
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
end end
elseif drivingCourse[end].s + s_braking == CS.s_exit elseif drivingCourse[end].s + s_braking == CS[:s_exit]
break break
elseif drivingCourse[end].v == CS.v_exit elseif drivingCourse[end].v == CS[:v_exit]
break break
else else
# TODO: not needed. just for testing # 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<v_peak and s+s_braking<s_exit in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") error("ERROR at coasting until braking phase: With the step variable ",settings[:stepVariable]," the while loop will be left although v<v_peak and s+s_braking<s_exit in CS",CS[:id]," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
end end
# delete last data point for recalculating the last step with reduced step size # delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
@ -898,23 +898,23 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse:
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
println("INFO: The train stops during the coasting phase in CS",CS.id," ", println("INFO: The train stops during the coasting phase in CS",CS[:id]," ",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N and s_braking=",s_braking,"m.") " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N and s_braking=",s_braking,"m.")
elseif drivingCourse[end].s + s_braking > CS.s_exit elseif drivingCourse[end].s + s_braking > CS[:s_exit]
# delete last data point because it went to far # delete last data point because it went to far
pop!(drivingCourse) pop!(drivingCourse)
pop!(coastingSection.dataPoints) pop!(coastingSection.dataPoints)
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 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) # 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 drivingCourse[end-1].a=0.0
s_braking=ceil((CS.v_exit^2-drivingCourse[end-1].v^2)/2/train[:a_braking]) s_braking=ceil((CS[:v_exit]^2-drivingCourse[end-1].v^2)/2/train[:a_braking])
# recalculate s, t, v, E # recalculate s, t, v, E
#drivingCourse[end].Δs= CS.s_exit-drivingCourse[end-1].s - s_braking # step size (in m) # TODO: the coasting section is currently realised with using distance steps. For example t_braking could also be used #drivingCourse[end].Δs= CS[:s_exit]-drivingCourse[end-1].s - s_braking # step size (in m) # TODO: the coasting section is currently realised with using distance steps. For example t_braking could also be used
drivingCourse[end].Δs=min(currentStepSize, CS.s_exit-(drivingCourse[end-1].s+s_braking)) # TODO: if settings[:stepVariable]=="s in m" drivingCourse[end].Δs=min(currentStepSize, CS[:s_exit]-(drivingCourse[end-1].s+s_braking)) # TODO: if settings[:stepVariable]=="s in m"
drivingCourse[end].Δt=drivingCourse[end].Δs/drivingCourse[end-1].v # step size (in s) drivingCourse[end].Δt=drivingCourse[end].Δs/drivingCourse[end-1].v # step size (in s)
drivingCourse[end].Δv=0.0 # step size (in m/s) drivingCourse[end].Δv=0.0 # step size (in m/s)
@ -943,10 +943,10 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse:
coastingSection.t=drivingCourse[end].t-drivingCourse[coastingSection.dataPoints[1]].t # total running time (in s) coastingSection.t=drivingCourse[end].t-drivingCourse[coastingSection.dataPoints[1]].t # total running time (in s)
coastingSection.E=drivingCourse[end].E-drivingCourse[coastingSection.dataPoints[1]].E # total energy consumption (in Ws) coastingSection.E=drivingCourse[end].E-drivingCourse[coastingSection.dataPoints[1]].E # total energy consumption (in Ws)
CS.t=CS.t+coastingSection.t # total running time (in s) CS[:t]=CS[:t]+coastingSection.t # total running time (in s)
CS.E=CS.E+coastingSection.E # total energy consumption (in Ws) CS[:E]=CS[:E]+coastingSection.E # total energy consumption (in Ws)
merge!(CS.behaviorSections, Dict(:coasting=>coastingSection)) merge!(CS[:behaviorSections], Dict(:coasting=>coastingSection))
end ## else: just return the given data point number without changes due to the coasting phase end ## else: just return the given data point number without changes due to the coasting phase
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addCoastingPhaseUntilBraking! end #function addCoastingPhaseUntilBraking!
@ -954,13 +954,13 @@ end #function addCoastingPhaseUntilBraking!
## This function calculates the data points of the braking phase. (standard braking phase with only two data points) ## This function calculates the data points of the braking phase. (standard braking phase with only two data points)
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed.
function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) function addBrakingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat)
# function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, massModel::String, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) # function addBrakingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, massModel::String, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat)
if drivingCourse[end].v>CS.v_exit && drivingCourse[end].s<CS.s_exit if drivingCourse[end].v>CS[:v_exit] && drivingCourse[end].s<CS[:s_exit]
brakingSection=BehaviorSection() brakingSection=BehaviorSection()
brakingSection.type="braking" # type of behavior section brakingSection.type="braking" # type of behavior section
brakingSection.s_entry=drivingCourse[end].s # first position (in m) brakingSection.s_entry=drivingCourse[end].s # first position (in m)
brakingSection.s_exit=CS.s_exit # last position (in m) brakingSection.s_exit=CS[:s_exit] # last position (in m)
brakingSection.v_entry=drivingCourse[end].v # entry speed (in m/s) brakingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(brakingSection.dataPoints, drivingCourse[end].i) # refering from the breaking section to the first of its data points push!(brakingSection.dataPoints, drivingCourse[end].i) # refering from the breaking section to the first of its data points
drivingCourse[end].behavior = brakingSection.type drivingCourse[end].behavior = brakingSection.type
@ -975,7 +975,7 @@ function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataP
# calculate s, t, v # calculate s, t, v
drivingCourse[end].s=brakingSection.s_exit # position (in m) drivingCourse[end].s=brakingSection.s_exit # position (in m)
drivingCourse[end].v=CS.v_exit # velocity (in m/s) drivingCourse[end].v=CS[:v_exit] # velocity (in m/s)
drivingCourse[end].Δs=drivingCourse[end].s-drivingCourse[end-1].s # step size (in m) drivingCourse[end].Δs=drivingCourse[end].s-drivingCourse[end-1].s # step size (in m)
drivingCourse[end].Δv=drivingCourse[end].v-drivingCourse[end-1].v # step size (in m/s) drivingCourse[end].Δv=drivingCourse[end].v-drivingCourse[end-1].v # step size (in m/s)
@ -983,9 +983,9 @@ function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataP
drivingCourse[end-1].a=(drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs drivingCourse[end-1].a=(drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs
#= if drivingCourse[end-1].a<train[:a_braking] || drivingCourse[end-1].a>=0.0 #= if drivingCourse[end-1].a<train[:a_braking] || drivingCourse[end-1].a>=0.0
println("") println("")
println("Warning: a_braking gets to high in CS ",CS.id, " with a=",drivingCourse[end-1].a ," > ",train[:a_braking]) println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1].a ," > ",train[:a_braking])
println(" v=",drivingCourse[end].v," v_i-1=",drivingCourse[end-1].v, " Δs=",drivingCourse[end].Δs) println(" v=",drivingCourse[end].v," v_i-1=",drivingCourse[end-1].v, " Δs=",drivingCourse[end].Δs)
println(" v_exit=",CS.v_exit) println(" v_exit=",CS[:v_exit])
println("") println("")
end =# end =#
drivingCourse[end].Δt=drivingCourse[end].Δv/drivingCourse[end-1].a # step size (in s) drivingCourse[end].Δt=drivingCourse[end].Δv/drivingCourse[end-1].a # step size (in s)
@ -1001,10 +1001,10 @@ function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataP
brakingSection.t=drivingCourse[end].Δt # total running time (in s) brakingSection.t=drivingCourse[end].Δt # total running time (in s)
brakingSection.E=drivingCourse[end].ΔE # total energy consumption (in Ws) brakingSection.E=drivingCourse[end].ΔE # total energy consumption (in Ws)
CS.t=CS.t+brakingSection.t # total running time (in s) CS[:t]=CS[:t]+brakingSection.t # total running time (in s)
CS.E=CS.E+brakingSection.E # total energy consumption (in Ws) CS[:E]=CS[:E]+brakingSection.E # total energy consumption (in Ws)
merge!(CS.behaviorSections, Dict(:braking=>brakingSection)) merge!(CS[:behaviorSections], Dict(:braking=>brakingSection))
end # else: return the characteristic section without a braking section end # else: return the characteristic section without a braking section
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addBrakingPhase! end #function addBrakingPhase!
@ -1012,8 +1012,8 @@ end #function addBrakingPhase!
## This function calculates the data points of the braking phase. # 09/07 new braking phase with more than two data points ## This function calculates the data points of the braking phase. # 09/07 new braking phase with more than two data points
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed.
function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat)
if drivingCourse[end].v > CS.v_exit && drivingCourse[end].s < CS.s_exit if drivingCourse[end].v > CS[:v_exit] && drivingCourse[end].s < CS[:s_exit]
brakingSection=BehaviorSection() brakingSection=BehaviorSection()
brakingSection.type="braking" # type of behavior section brakingSection.type="braking" # type of behavior section
brakingSection.s_entry=drivingCourse[end].s # first position (in m) brakingSection.s_entry=drivingCourse[end].s # first position (in m)
@ -1023,7 +1023,7 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
velocityIsPositive=true velocityIsPositive=true
while drivingCourse[end].v > CS.v_exit && drivingCourse[end].s < CS.s_exit && velocityIsPositive while drivingCourse[end].v > CS[:v_exit] && drivingCourse[end].s < CS[:s_exit] && velocityIsPositive
# traction effort and resisting forces (in N): # traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, brakingSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, brakingSection.type)
@ -1040,17 +1040,17 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect
break break
end end
end end
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = brakingSection.type drivingCourse[end].behavior = brakingSection.type
push!(brakingSection.dataPoints, drivingCourse[end].i) push!(brakingSection.dataPoints, drivingCourse[end].i)
# s_braking=ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking]) # s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking])
end # while end # while
if drivingCourse[end].v < CS.v_exit || !velocityIsPositive if drivingCourse[end].v < CS[:v_exit] || !velocityIsPositive
# calculate s, t, v # calculate s, t, v
drivingCourse[end].s=CS.s_exit # position (in m) drivingCourse[end].s=CS[:s_exit] # position (in m)
drivingCourse[end].v=CS.v_exit # velocity (in m/s) drivingCourse[end].v=CS[:v_exit] # velocity (in m/s)
drivingCourse[end].Δs=drivingCourse[end].s-drivingCourse[end-1].s # step size (in m) drivingCourse[end].Δs=drivingCourse[end].s-drivingCourse[end-1].s # step size (in m)
drivingCourse[end].Δv=drivingCourse[end].v-drivingCourse[end-1].v # step size (in m/s) drivingCourse[end].Δv=drivingCourse[end].v-drivingCourse[end-1].v # step size (in m/s)
@ -1059,7 +1059,7 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect
# println("a_braking_last=",drivingCourse[end-1].a," m/s^2 und a_braking_standard=" , train[:a_braking]) # println("a_braking_last=",drivingCourse[end-1].a," m/s^2 und a_braking_standard=" , train[:a_braking])
# if drivingCourse[end-1].a<train[:a_braking] || drivingCourse[end-1].a>=0.0 # if drivingCourse[end-1].a<train[:a_braking] || drivingCourse[end-1].a>=0.0
# println("Warning: a_braking gets to high in CS ",CS.id, " with a=",drivingCourse[end-1].a ," > ",train[:a_braking]) # println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1].a ," > ",train[:a_braking])
# end # end
drivingCourse[end].Δt=drivingCourse[end].Δv/drivingCourse[end-1].a # step size (in s) drivingCourse[end].Δt=drivingCourse[end].Δv/drivingCourse[end-1].a # step size (in s)
drivingCourse[end].t=drivingCourse[end-1].t+drivingCourse[end].Δt # point in time (in s) drivingCourse[end].t=drivingCourse[end-1].t+drivingCourse[end].Δt # point in time (in s)
@ -1068,7 +1068,7 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect
drivingCourse[end].W=drivingCourse[end-1].W+drivingCourse[end].ΔW # mechanical work (in Ws) drivingCourse[end].W=drivingCourse[end-1].W+drivingCourse[end].ΔW # mechanical work (in Ws)
drivingCourse[end].ΔE=drivingCourse[end].ΔW # energy consumption in this step (in Ws) drivingCourse[end].ΔE=drivingCourse[end].ΔW # energy consumption in this step (in Ws)
drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws) drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws)
elseif drivingCourse[end].s > CS.s_exit elseif drivingCourse[end].s > CS[:s_exit]
error("Beim Bremsen wurde das CS-Ende überschritten, aber nicht v_exit unterschritten !!") error("Beim Bremsen wurde das CS-Ende überschritten, aber nicht v_exit unterschritten !!")
else else
@ -1081,10 +1081,10 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect
brakingSection.t=drivingCourse[end].t-drivingCourse[brakingSection.dataPoints[1]].t # total running time (in s) brakingSection.t=drivingCourse[end].t-drivingCourse[brakingSection.dataPoints[1]].t # total running time (in s)
brakingSection.E=drivingCourse[end].E-drivingCourse[brakingSection.dataPoints[1]].E # total energy consumption (in Ws) brakingSection.E=drivingCourse[end].E-drivingCourse[brakingSection.dataPoints[1]].E # total energy consumption (in Ws)
CS.t=CS.t+brakingSection.t # total running time (in s) CS[:t]=CS[:t]+brakingSection.t # total running time (in s)
CS.E=CS.E+brakingSection.E # total energy consumption (in Ws) CS[:E]=CS[:E]+brakingSection.E # total energy consumption (in Ws)
merge!(CS.behaviorSections, Dict(:braking=>brakingSection)) merge!(CS[:behaviorSections], Dict(:braking=>brakingSection))
end # else: return the characteristic section without a braking section end # else: return the characteristic section without a braking section
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addBrakingPhaseStepwise! end #function addBrakingPhaseStepwise!
@ -1092,7 +1092,7 @@ end #function addBrakingPhaseStepwise!
## This function calculates the data point of the standstill. ## This function calculates the data point of the standstill.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the standstill if needed. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the standstill if needed.
function addStandstill!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) function addStandstill!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end].v == 0.0 if drivingCourse[end].v == 0.0
standstillSection=BehaviorSection() standstillSection=BehaviorSection()
@ -1112,7 +1112,7 @@ function addStandstill!(CS::CharacteristicSection, drivingCourse::Vector{DataPoi
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, standstillSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, standstillSection.type)
merge!(CS.behaviorSections, Dict(:standstill => standstillSection)) merge!(CS[:behaviorSections], Dict(:standstill => standstillSection))
end # else: return the characteristic section without a standstillSection section end # else: return the characteristic section without a standstillSection section
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addStandstill! end #function addStandstill!

View File

@ -13,81 +13,82 @@ approximationLevel = 6 # TODO: define it in TrainRun and give it to each fu
# calculate a train run focussing on using the minimum possible running time # calculate a train run focussing on using the minimum possible running time
function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict) function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict)
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections] CSs::Vector{Dict} = movingSection[:characteristicSections]
startingPoint=DataPoint() startingPoint=DataPoint()
startingPoint.i=1 startingPoint.i=1
startingPoint.s=CSs[1].s_entry startingPoint.s=CSs[1][:s_entry]
drivingCourse=[startingPoint] # List of data points drivingCourse=[startingPoint] # List of data points
# for CS in CSs # for CS in CSs
for csId in 1:length(CSs) for csId in 1:length(CSs)
# println("CS",csId)
# check if the CS has a cruising section # check if the CS has a cruising section
s_breakFree = get(CSs[csId].behaviorSections, :breakFree, BehaviorSection()).length CS = CSs[csId]
s_clearing = get(CSs[csId].behaviorSections, :clearing, BehaviorSection()).length BSs = CS[:behaviorSections]
s_acceleration = get(CSs[csId].behaviorSections, :acceleration, BehaviorSection()).length s_breakFree = get(BSs, :breakFree, BehaviorSection()).length
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 s_clearing = get(BSs, :clearing, BehaviorSection()).length
s_acceleration = get(BSs, :acceleration, BehaviorSection()).length
s_braking = max(0.0, ceil((CS[:v_exit]^2-CS[: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 # calculate the cruising sections length
s_cruising=CSs[csId].length-s_breakFree-s_clearing-s_acceleration-s_braking s_cruising=CS[: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_peak 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!(BSs, :breakFree)
delete!(CSs[csId].behaviorSections, :clearing) delete!(BSs, :clearing)
delete!(CSs[csId].behaviorSections, :acceleration) delete!(BSs, :acceleration)
delete!(CSs[csId].behaviorSections, :diminishing) delete!(BSs, :diminishing)
delete!(CSs[csId].behaviorSections, :cruising) delete!(BSs, :cruising)
CSs[csId].E=0.0 CS[:E]=0.0
CSs[csId].t=0.0 CS[:t]=0.0
if s_clearing == CSs[csId].length if s_clearing == CS[:length]
# 09/06 TODO: thought about using "cruising" because it is used in EnergySaving and not clearing (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_clearing, settings, train, CSs, "cruising") # 09/06 TODO: thought about using "cruising" because it is used in EnergySaving and not clearing (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "cruising")
(CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_clearing, settings, train, CSs, "clearing") (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
elseif s_cruising == CSs[csId].length elseif s_cruising == CS[:length]
(CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising") (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
elseif s_cruising > 0.0 || s_braking == 0.0 elseif s_cruising > 0.0 || s_braking == 0.0
# 09/21 elseif s_cruising > 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) # 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_peak if drivingCourse[end].v < CS[:v_peak]
(CSs[csId], drivingCourse)=addAccelerationPhase!(CSs[csId], drivingCourse, settings, train, CSs) (CS, drivingCourse)=addAccelerationPhase!(CS, drivingCourse, settings, train, CSs)
end #if 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 if CS[:s_exit]-drivingCourse[end].s-max(0.0, (CS[: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("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(" before acceleration in CS",csId, " with s=",drivingCourse[end].s," s_braking=",((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking])," s_exit=",CS[:s_exit])
println(" and v=",drivingCourse[end].v," v_peak=",CSs[csId].v_peak," v_exit=",CSs[csId].v_exit) println(" and v=",drivingCourse[end].v," v_peak=",CS[:v_peak]," v_exit=",CS[:v_exit])
end 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 s_braking=max(0.0, ceil((CS[: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
s_cruising=CSs[csId].s_exit-drivingCourse[end].s-s_braking s_cruising=CS[:s_exit]-drivingCourse[end].s-s_braking
if s_cruising > 0.0 if s_cruising > 0.0
(CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising") (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
end end
else else
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" if CS[:v_entry] < CS[: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 # 09/09 old (not sufficient for steep gradients): if CS[:v_entry] < CS[:v_peak]
(CSs[csId], drivingCourse)=addAccelerationPhaseUntilBraking!(CSs[csId], drivingCourse, settings, train, CSs) (CS, drivingCourse)=addAccelerationPhaseUntilBraking!(CS, drivingCourse, settings, train, CSs)
end #if end #if
end #if end #if
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 s_braking=max(0.0, ceil((CS[: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
if drivingCourse[end].v > CSs[csId].v_exit if drivingCourse[end].v > CS[:v_exit]
#(CSs[csId], drivingCourse)=addBrakingPhase!(CSs[csId], drivingCourse, settings[:massModel], train, CSs) #(CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings[:massModel], train, CSs)
(CSs[csId], drivingCourse)=addBrakingPhase!(CSs[csId], drivingCourse, settings, train, CSs) (CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings, train, CSs)
end #if end #if
#= 09/20 old and should never be used: #= 09/20 old and should never be used:
if drivingCourse[end].s < CSs[csId].s_exit if drivingCourse[end].s < CS[:s_exit]
if haskey(CSs[csId].behaviorSections, :cruising) if haskey(BSs, :cruising)
println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_exit=",CSs[csId].s_exit) println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_exit=",CS[:s_exit])
end end
(CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising") (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
end =# end =#
end #for end #for
@ -112,7 +113,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
#create a new moving section for the minimum energy consumption #create a new moving section for the minimum energy consumption
movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime) movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime)
CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections] CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections]
merge!(movingSectionOriginal, Dict(:energySavingModifications => [])) # list containing all the used energy saving modifications merge!(movingSectionOriginal, Dict(:energySavingModifications => [])) # list containing all the used energy saving modifications
# create a new driving course for the minimum energy consumption # create a new driving course for the minimum energy consumption
@ -154,7 +155,11 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
end #if end #if
end # for end # for
while movingSectionOriginal[:t_recoveryAvailable] > 0.0 # testNr=0
# 01/03 old wit too long calculation time: while movingSectionOriginal[:t_recoveryAvailable] > 0.0
while movingSectionOriginal[:t_recoveryAvailable] >= 1/(10^approximationLevel)
# testNr=testNr+1
# println("while in OpModes: ", testNr, " mit t_recoveryAvailable=",movingSectionOriginal[:t_recoveryAvailable])
# comparison of modifications # comparison of modifications
ratioMax=0.0 ratioMax=0.0
csIdMax=0 csIdMax=0
@ -182,20 +187,20 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
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, lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax][:behaviorSections], :standstill,
get(CSsOrig[csIdMax].behaviorSections, :braking, get(CSsOrig[csIdMax][:behaviorSections], :braking,
get(CSsOrig[csIdMax].behaviorSections, :cruisingAfterCoasting, get(CSsOrig[csIdMax][:behaviorSections], :cruisingAfterCoasting,
get(CSsOrig[csIdMax].behaviorSections, :coasting, get(CSsOrig[csIdMax][:behaviorSections], :coasting,
get(CSsOrig[csIdMax].behaviorSections, :cruising, get(CSsOrig[csIdMax][:behaviorSections], :cruising,
get(CSsOrig[csIdMax].behaviorSections, :acceleration, get(CSsOrig[csIdMax][:behaviorSections], :acceleration,
get(CSsOrig[csIdMax].behaviorSections, :clearing, get(CSsOrig[csIdMax][:behaviorSections], :clearing,
get(CSsOrig[csIdMax].behaviorSections, :breakFree, get(CSsOrig[csIdMax][:behaviorSections], :breakFree,
get(CSsOrig[csIdMax].behaviorSections, :diminishing, get(CSsOrig[csIdMax][:behaviorSections], :diminishing,
BehaviorSection()))))))))).dataPoints[end] BehaviorSection()))))))))).dataPoints[end]
# if there is a diminishing phase its location must be analysed seperately because it could be before acceleration, between acceleration and cruising or after cruising. All the other behavior sections occur in a fixed order. # if there is a diminishing phase its location must be analysed seperately because it could be before acceleration, between acceleration and cruising or after cruising. All the other behavior sections occur in a fixed order.
if haskey(CSsOrig[csIdMax].behaviorSections, :diminishing) if haskey(CSsOrig[csIdMax][:behaviorSections], :diminishing)
lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax].behaviorSections[:diminishing].dataPoints[end]) lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax][:behaviorSections][:diminishing].dataPoints[end])
end end
# create new driving course # create new driving course
@ -228,7 +233,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
# replace the original driving course and CS with the new modified ones # replace the original driving course and CS with the new modified ones
drivingCourseOriginal=drivingCourseNew drivingCourseOriginal=drivingCourseNew
CSsOrig[csIdMax]=CharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified]) CSsOrig[csIdMax]=copyCharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified])
movingSectionOriginal[:t]=drivingCourseOriginal[end].t # total running time (in s) movingSectionOriginal[:t]=drivingCourseOriginal[end].t # total running time (in s)
movingSectionOriginal[:E]=drivingCourseOriginal[end].E # total energy consumption (in Ws) movingSectionOriginal[:E]=drivingCourseOriginal[end].E # total energy consumption (in Ws)
@ -238,9 +243,9 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for csId in csIdMax+1:length(CSsOrig) for csId in csIdMax+1:length(CSsOrig)
for bs in 1: length(allBs) for bs in 1: length(allBs)
if haskey(CSsOrig[csId].behaviorSections, allBs[bs]) if haskey(CSsOrig[csId][:behaviorSections], allBs[bs])
for point in 1:length(CSsOrig[csId].behaviorSections[allBs[bs]].dataPoints) for point in 1:length(CSsOrig[csId][:behaviorSections][allBs[bs]].dataPoints)
CSsOrig[csId].behaviorSections[allBs[bs]].dataPoints[point] = CSsOrig[csId].behaviorSections[allBs[bs]].dataPoints[point]+difference CSsOrig[csId][:behaviorSections][allBs[bs]].dataPoints[point] = CSsOrig[csId][:behaviorSections][allBs[bs]].dataPoints[point]+difference
end end
end #if end #if
end #for end #for
@ -283,8 +288,8 @@ end #function calculateMinimumEnergyConsumption
function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Dict, train::Dict) function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Dict, train::Dict)
# TODO: refctor and sort this function # TODO: refactor and sort this function
CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections] CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections]
if modificationType == "increasing coasting" if modificationType == "increasing coasting"
# method 1: increase coasting # method 1: increase coasting
@ -306,8 +311,8 @@ function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{Dat
:csModified => characteristicSectionModified, # the modified characteristic section :csModified => characteristicSectionModified, # the modified characteristic section
:drivingCourseModified => drivingCourseModifiedUntilEndOfModifiedCS) # drivingCourse for 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(:Δ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) merge!(energySavingModification, Dict(:Δt => energySavingModification[:csModified][:t] - CSsOrig[csId][:t])) # time loss (in s)
if energySavingModification[:Δt] <= movingSectionOriginal[:t_recoveryAvailable] && energySavingModification[:ΔE] >= 0.0 if energySavingModification[:Δt] <= movingSectionOriginal[:t_recoveryAvailable] && energySavingModification[:ΔE] >= 0.0
@ -355,7 +360,7 @@ function createEnergySavingModification()
:Δ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)
:ratio => 0.0, # ratio of ΔE and Δt (in Ws/s) :ratio => 0.0, # ratio of ΔE and Δt (in Ws/s)
:csModified => CharacteristicSection(), # the modified characteristic section :csModified => Dict(), # the modified characteristic section
:drivingCourseModified => []) # drivingCourse for the modified characteristic section :drivingCourseModified => []) # drivingCourse for the modified characteristic section
end #createEnergySavingModification end #createEnergySavingModification
@ -365,7 +370,7 @@ function copyEnergySavingModification(original::Dict)
:ΔE => original[:ΔE], # saved energy (in Ws) :ΔE => original[:ΔE], # saved energy (in Ws)
:Δt => original[:Δt], # time loss (in s) :Δt => original[:Δt], # time loss (in s)
:ratio => original[:ratio], # ratio of ΔE and Δt (in Ws/s) :ratio => original[:ratio], # ratio of ΔE and Δt (in Ws/s)
:csModified => CharacteristicSection(original[:csModified])) # the modified characteristic section :csModified => copyCharacteristicSection(original[:csModified])) # the modified characteristic section
drivingCourseModified = DataPoint[] drivingCourseModified = DataPoint[]
for i in 1:length(original[:drivingCourseModified]) for i in 1:length(original[:drivingCourseModified])
@ -381,7 +386,7 @@ function updateEnergySavingModifications!(energySavingModifications::Vector{Dict
difference = endOfModificationId-lastIdOfSelectedCsOriginal difference = endOfModificationId-lastIdOfSelectedCsOriginal
for modNr in csIdMax+1:length(energySavingModifications) for modNr in csIdMax+1:length(energySavingModifications)
if energySavingModifications[modNr][:ratio]>0 if energySavingModifications[modNr][:ratio]>0
BSs = energySavingModifications[modNr][:csModified].behaviorSections BSs = energySavingModifications[modNr][:csModified][:behaviorSections]
# update the behavior sections of the modified charateristic section # update the behavior sections of the modified charateristic section
for bs in 1: length(allBs) for bs in 1: length(allBs)
if haskey(BSs, allBs[bs]) if haskey(BSs, allBs[bs])
@ -415,9 +420,10 @@ end #function updateEnergySavingModifications!
function copyMovingSection(original::Dict) function copyMovingSection(original::Dict)
CSsCopy = Vector{CharacteristicSection}() #TODO after removing the mutable structs: Is it possible to just "copy"?
CSsCopy = Vector{Dict}()
for csId in 1:length(original[:characteristicSections]) for csId in 1:length(original[:characteristicSections])
push!(CSsCopy, CharacteristicSection(original[:characteristicSections][csId])) push!(CSsCopy, copyCharacteristicSection(original[:characteristicSections][csId]))
end #for end #for
copy = Dict(:id => original[:id], # identifier copy = Dict(:id => original[:id], # identifier
@ -443,8 +449,31 @@ function copyMovingSection(original::Dict)
if haskey(original, :t_recoveryAvailable) # still available recovery time for energy-saving modifications (in s) if haskey(original, :t_recoveryAvailable) # still available recovery time for energy-saving modifications (in s)
merge!(copy, Dict(:t_recoveryAvailable => original[:t_recoveryAvailable])) merge!(copy, Dict(:t_recoveryAvailable => original[:t_recoveryAvailable]))
end end
return copy return copy
end #function copyMovingSection end #function copyMovingSection
function copyCharacteristicSection(original::Dict)
#TODO after removing the mutable structs: Is it possible to just "copy"?
copy = Dict(:id => original[:id], # identifier
:s_entry => original[:s_entry], # first position (in m)
:s_exit => original[:s_exit], # last position (in m)
:length => original[:length], # total length (in m)
:r_path => original[:r_path], # path resistance (in ‰)
:behaviorSections => Dict(), # empty list of containing behavior sections
:t => original[:t], # total running time (in s)
:E => original[:E], # total energy consumption (in Ws)
:v_limit => original[:v_limit], # speed limit (in m/s)
:v_peak => original[:v_peak], # maximum reachable speed (in m/s)
:v_entry => original[:v_entry], # maximum entry speed (in m/s)
:v_exit => original[:v_exit]) # maximum exit speed (in m/s)
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for bs in 1: length(allBs)
if haskey(original[:behaviorSections], allBs[bs])
merge!(copy[:behaviorSections], Dict(allBs[bs] => BehaviorSection(original[:behaviorSections][allBs[bs]])))
end #if
end #for
return copy
end #function copyCharacteristicSection
end #module OperationModes end #module OperationModes

View File

@ -255,17 +255,17 @@ function printImportantValues(drivingCourse::Vector{DataPoint})
end #function printImportantValues end #function printImportantValues
function printSectionInformation(movingSection::Dict) function printSectionInformation(movingSection::Dict)
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections] CSs::Vector{Dict} = movingSection[:characteristicSections]
println("MS mit length=", movingSection[:length]," mit t=", movingSection[:t]) println("MS mit length=", movingSection[:length]," mit t=", movingSection[:t])
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for csId in 1:length(CSs) for csId in 1:length(CSs)
println("CS ",csId," mit length=", CSs[csId].length," mit t=", CSs[csId].t) println("CS ",csId," mit length=", CSs[csId][:length]," mit t=", CSs[csId][:t])
for bs in 1: length(allBs) for bs in 1: length(allBs)
if haskey(CSs[csId].behaviorSections, allBs[bs]) if haskey(CSs[csId][:behaviorSections], allBs[bs])
println("BS ",allBs[bs], " mit s_entry=", CSs[csId].behaviorSections[allBs[bs]].s_entry, " und t=", CSs[csId].behaviorSections[allBs[bs]].t) println("BS ",allBs[bs], " mit s_entry=", CSs[csId][:behaviorSections][allBs[bs]].s_entry, " und t=", CSs[csId][:behaviorSections][allBs[bs]].t)
# for point in 1:length(CSs[csId].behaviorSections[allBs[bs]].dataPoints) # for point in 1:length(CSs[csId][:behaviorSections][allBs[bs]].dataPoints)
# println(CSs[csId].behaviorSections[allBs[bs]].dataPoints[point]) # println(CSs[csId][:behaviorSections][allBs[bs]].dataPoints[point])
# end # end
end #if end #if
end #for end #for

View File

@ -23,7 +23,7 @@ function createMovingSection(path::Dict, v_trainLimit::Real)
s_exit = path[:sections][end][:s_end] # last position (in m) s_exit = path[:sections][end][:s_end] # last position (in m)
pathLength = s_exit - s_entry # total length (in m) pathLength = s_exit - s_entry # total length (in m)
CSs=[] CSs=Vector{Dict}()
s_csStart=s_entry s_csStart=s_entry
csId=1 csId=1
for row in 2:length(path[:sections]) for row in 2:length(path[:sections])
@ -47,44 +47,41 @@ function createMovingSection(path::Dict, v_trainLimit::Real)
end #function createMovingSection end #function createMovingSection
## create a characteristic section for a path section ## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections.
function createCharacteristicSection(csId::Integer, s_csStart::Real, section::Dict, v_csLimit::Real) function createCharacteristicSection(csId::Integer, s_csStart::Real, section::Dict, v_csLimit::Real)
# this function creates and returns a characteristic section dependent on the paths attributes # Create and return a characteristic section dependent on the paths attributes
characteristicSection=CharacteristicSection() characteristicSection= Dict(:id => csId, # identifier
characteristicSection.id=csId # identifier :s_entry => s_csStart, # first position (in m)
characteristicSection.s_entry=s_csStart # first position (in m) :s_exit => section[:s_end], # last position (in m)
characteristicSection.s_exit=section[:s_end] # last position (in m) :length => section[:s_end]-s_csStart, # total length (in m)
characteristicSection.length=characteristicSection.s_exit-characteristicSection.s_entry # total length (in m) :r_path => section[:f_Rp], # path resistance (in ‰)
characteristicSection.t=0.0 # total running time (in s) :behaviorSections => Dict(), # list of containing behavior sections
characteristicSection.E=0.0 # total energy consumption (in Ws) :t => 0.0, # total running time (in s)
characteristicSection.v_limit=v_csLimit # speed limit (in m/s) :E => 0.0, # total energy consumption (in Ws)
:v_limit => v_csLimit, # speed limit (in m/s)
# initializing v_entry, v_peak and v_exit with v_limit # initializing :v_entry, :v_peak and :v_exit with :v_limit
characteristicSection.v_peak=characteristicSection.v_limit # maximum reachable speed (in m/s) :v_peak => v_csLimit, # maximum reachable speed (in m/s)
characteristicSection.v_entry=characteristicSection.v_limit # maximum entry speed (in m/s) :v_entry => v_csLimit, # maximum entry speed (in m/s)
characteristicSection.v_exit=characteristicSection.v_limit # maximum exit speed (in m/s) :v_exit => v_csLimit) # maximum exit speed (in m/s)
characteristicSection.r_path=section[:f_Rp] # path resistance (in ‰)
return characteristicSection return characteristicSection
end #function createCharacteristicSection end #function createCharacteristicSection
## define the intersection velocities between the characterisitc sections to secure braking behavior ## define the intersection velocities between the characterisitc sections to secure braking behavior
function secureBrakingBehavior!(movingSection::Dict, a_braking::Real) function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
# this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end # this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections] CSs = movingSection[:characteristicSections]
csId=length(CSs) csId=length(CSs)
CSs[csId].v_exit=0.0 # the exit velocity of the last characteristic section is 0.0 m/s CSs[csId][:v_exit]=0.0 # the exit velocity of the last characteristic section is 0.0 m/s
while csId >= 1 while csId >= 1
v_entryMax=sqrt(CSs[csId].v_exit^2-2*a_braking*CSs[csId].length) v_entryMax=sqrt(CSs[csId][:v_exit]^2-2*a_braking*CSs[csId][:length])
v_entryMax=floor(v_entryMax, digits=12) v_entryMax=floor(v_entryMax, digits=12)
CSs[csId].v_entry=min(CSs[csId].v_limit, v_entryMax) CSs[csId][:v_entry]=min(CSs[csId][:v_limit], v_entryMax)
CSs[csId].v_peak=CSs[csId].v_entry CSs[csId][:v_peak]=CSs[csId][:v_entry]
csId=csId-1 csId=csId-1
if csId >= 1 if csId >= 1
CSs[csId].v_exit=min(CSs[csId].v_limit, CSs[csId+1].v_entry) CSs[csId][:v_exit]=min(CSs[csId][:v_limit], CSs[csId+1][:v_entry])
end #if end #if
end #while end #while
return movingSection return movingSection
@ -93,30 +90,30 @@ end #function secureBrakingBehavior!
## define the intersection velocities between the characterisitc sections to secure acceleration behavior ## define the intersection velocities between the characterisitc sections to secure acceleration behavior
function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train::Dict) function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train::Dict)
# this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards # this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections] CSs = movingSection[:characteristicSections]
CSs[1].v_entry=0.0 # the entry velocity of the first characteristic section is 0.0 m/s CSs[1][:v_entry]=0.0 # the entry velocity of the first characteristic section is 0.0 m/s
startingPoint=DataPoint() startingPoint=DataPoint()
startingPoint.i=1 startingPoint.i=1
previousCSv_exit=CSs[1].v_entry previousCSv_exit=CSs[1][:v_entry]
for csId in 1:length(CSs) for csId in 1:length(CSs)
CSs[csId].v_entry=min(CSs[csId].v_entry, previousCSv_exit) CSs[csId][:v_entry]=min(CSs[csId][:v_entry], previousCSv_exit)
startingPoint.s=CSs[csId].s_entry startingPoint.s=CSs[csId][:s_entry]
startingPoint.v=CSs[csId].v_entry startingPoint.v=CSs[csId][:v_entry]
accelerationCourse=[startingPoint] # List of data points accelerationCourse=[startingPoint] # List of data points
if CSs[csId].v_entry<CSs[csId].v_peak if CSs[csId][:v_entry]<CSs[csId][:v_peak]
(CSs[csId], accelerationCourse)=addAccelerationPhase!(CSs[csId], accelerationCourse, settings, train, CSs) # this function changes the accelerationCourse (CSs[csId], accelerationCourse)=addAccelerationPhase!(CSs[csId], accelerationCourse, settings, train, CSs) # this function changes the accelerationCourse
CSs[csId].v_peak=max(CSs[csId].v_entry,accelerationCourse[end].v) CSs[csId][:v_peak]=max(CSs[csId][:v_entry],accelerationCourse[end].v)
CSs[csId].v_exit=min(CSs[csId].v_exit, CSs[csId].v_peak, accelerationCourse[end].v) CSs[csId][:v_exit]=min(CSs[csId][:v_exit], CSs[csId][:v_peak], accelerationCourse[end].v)
else #CSs[csId].v_entry==CSs[csId].v_peak else #CSs[csId][:v_entry]==CSs[csId][:v_peak]
# v_exit stays the same # v_exit stays the same
end #if end #if
previousCSv_exit=CSs[csId].v_exit previousCSv_exit=CSs[csId][:v_exit]
end #for end #for
return movingSection return movingSection
@ -127,24 +124,24 @@ end #function secureAccelerationBehavior!
## define the intersection velocities between the characterisitc sections to secure cruising behavior ## define the intersection velocities between the characterisitc sections to secure cruising behavior
function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dict) function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dict)
# limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak # limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections] CSs = movingSection[:characteristicSections]
startingPoint=DataPoint() startingPoint=DataPoint()
startingPoint.i=1 startingPoint.i=1
previousCSv_exit=CSs[1].v_entry previousCSv_exit=CSs[1][:v_entry]
for csId in 1:length(CSs) for csId in 1:length(CSs)
CSs[csId].v_entry=min(CSs[csId].v_entry, previousCSv_exit) CSs[csId][:v_entry]=min(CSs[csId][:v_entry], previousCSv_exit)
startingPoint.s=CSs[csId].s_entry startingPoint.s=CSs[csId][:s_entry]
startingPoint.v=CSs[csId].v_peak startingPoint.v=CSs[csId][:v_peak]
cruisingCourse=[startingPoint] # List of data points cruisingCourse=[startingPoint] # List of data points
(CSs[csId], cruisingCourse)=addCruisingPhase!(CSs[csId], cruisingCourse, CSs[csId].length, settings, train, CSs, "cruising") # this function changes the cruisingCourse (CSs[csId], cruisingCourse)=addCruisingPhase!(CSs[csId], cruisingCourse, CSs[csId][:length], settings, train, CSs, "cruising") # this function changes the cruisingCourse
CSs[csId].v_exit=min(CSs[csId].v_exit, cruisingCourse[end].v) CSs[csId][:v_exit]=min(CSs[csId][:v_exit], cruisingCourse[end].v)
previousCSv_exit=CSs[csId].v_exit previousCSv_exit=CSs[csId][:v_exit]
end #for end #for
return movingSection return movingSection

View File

@ -1,6 +1,6 @@
module types module types
# definition of all the additional types and their constructors # definition of all the additional types and their constructors
export DataPoint, BehaviorSection, CharacteristicSection, EnergySavingModification export DataPoint, BehaviorSection #, CharacteristicSection
## a data point is the smallest element of the driving course. One step of the step approach is between two data points ## a data point is the smallest element of the driving course. One step of the step approach is between two data points
@ -54,7 +54,7 @@ function BehaviorSection(original::BehaviorSection)
return BehaviorSection(original.type, original.length, original.s_entry, original.s_exit, original.t, original.E, original.v_entry, original.v_exit, bsDataPoints) return BehaviorSection(original.type, original.length, original.s_entry, original.s_exit, original.t, original.E, original.v_entry, original.v_exit, bsDataPoints)
end end
## a characteristic section is a part of the moving section. It contains behavior sections. #= # a characteristic section is a part of the moving section. It contains behavior sections.
mutable struct CharacteristicSection mutable struct CharacteristicSection
id::Integer # identifier id::Integer # identifier
length::AbstractFloat # total length (in m) length::AbstractFloat # total length (in m)
@ -80,26 +80,6 @@ function CharacteristicSection(original::CharacteristicSection)
end #for end #for
return copy return copy
end #function CharacteristicSection end #function CharacteristicSection
#= for the energy saving operation mode it is nesserary to compare different energy saving modifications. These are part of the moving section.
mutable struct EnergySavingModification
csId::Integer # identifier of the characteristic section
type::String # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting"
ΔE::AbstractFloat # saved energy (in Ws)
Δt::AbstractFloat # time loss (in s)
ratio::AbstractFloat # ratio of ΔE and Δt (in Ws/s)
csModified::CharacteristicSection # the modified characteristic section
drivingCourseModified::Vector{DataPoint} # drivingCourse for the modified characteristic section
end # mutable struct EnergySavingModification
EnergySavingModification()=EnergySavingModification(0, "", 0.0, 0.0, 0.0, CharacteristicSection(), [])
function EnergySavingModification(original::EnergySavingModification)
copy=EnergySavingModification(original.csId, original.type, original.ΔE, original.Δt, original.ratio, CharacteristicSection(), DataPoint[])
copy.csModified=CharacteristicSection(original.csModified)
for i in 1:length(original.drivingCourseModified)
push!(copy.drivingCourseModified, DataPoint(original.drivingCourseModified[i]))
end
return copy
end #function EnergySavingModification
=# =#
end #module end #module