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 #function calculateRecoveryTime
function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if (haskey(csOriginal.behaviorSections, :cruising) || haskey(csOriginal.behaviorSections, :diminishing)) && haskey(csOriginal.behaviorSections, :braking)
function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
BSsOriginal = csOriginal[:behaviorSections]
if (haskey(BSsOriginal, :cruising) || haskey(BSsOriginal, :diminishing)) && haskey(BSsOriginal, :braking)
# check if cruising or diminishing should be reduced for coasting
if haskey(csOriginal.behaviorSections, :cruising) && haskey(csOriginal.behaviorSections, :diminishing)
if csOriginal.behaviorSections[:cruising].dataPoints[1] > csOriginal.behaviorSections[:diminishing].dataPoints[1]
if haskey(BSsOriginal, :cruising) && haskey(BSsOriginal, :diminishing)
if BSsOriginal[:cruising].dataPoints[1] > BSsOriginal[:diminishing].dataPoints[1]
reduceCruising=true
reduceDiminishing=false
else
reduceDiminishing=true
reduceCruising=false
end
elseif haskey(csOriginal.behaviorSections, :cruising)
elseif haskey(BSsOriginal, :cruising)
reduceCruising=true
reduceDiminishing=false
elseif haskey(csOriginal.behaviorSections, :diminishing)
elseif haskey(BSsOriginal, :diminishing)
reduceDiminishing=true
reduceCruising=false
end
if reduceCruising
cruisingReduction = settings[:stepSize]
while cruisingReduction>=settings[:stepSize]/10^approximationLevel
#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
energySavingStartId=get(csOriginal.behaviorSections, :cruising, BehaviorSection()).dataPoints[1]
energySavingStartId=get(BSsOriginal, :cruising, BehaviorSection()).dataPoints[1]
if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !")
end
@ -131,44 +130,59 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
# calculating the new length of the cruising section
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
# 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
distanceReduction = drivingCourse(csOriginal.behaviorSections[:cruising].dataPoints[end]).v*cruisingReduction
s_cruising = csOriginal.behaviorSections[:cruising].length-distanceReduction
distanceReduction = drivingCourse(BSsOriginal[:cruising].dataPoints[end]).v*cruisingReduction
s_cruising = BSsOriginal[:cruising].length-distanceReduction
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
s_cruising=max(0.0, s_cruising)
# copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}())
if haskey(csOriginal.behaviorSections, :breakFree)
breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree])
merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection))
csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E
csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t
# 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}())
#TODO after removing the mutable structs: Is it possible to just "copy"? with some changes
csModified=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 => 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
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
clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing])
merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection))
csModified.E = csModified.E + csModified.behaviorSections[:clearing].E
csModified.t = csModified.t + csModified.behaviorSections[:clearing].t
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(BSsOriginal[:clearing])
merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified[:E] = csModified[:E] + BSsModified[:clearing].E
csModified[:t] = csModified[:t] + BSsModified[:clearing].t
end
if haskey(csOriginal.behaviorSections, :acceleration)
accelerationSection=BehaviorSection(csOriginal.behaviorSections[:acceleration])
merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection))
csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E
csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t
if haskey(BSsOriginal, :acceleration)
accelerationSection=BehaviorSection(BSsOriginal[:acceleration])
merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + BSsModified[:acceleration].E
csModified[:t] = csModified[:t] + BSsModified[:acceleration].t
end
if haskey(csOriginal.behaviorSections, :diminishing)
diminishingSection=BehaviorSection(csOriginal.behaviorSections[:diminishing])
merge!(csModified.behaviorSections, Dict(:diminishing=>diminishingSection))
csModified.E = csModified.E + csModified.behaviorSections[:diminishing].E
csModified.t = csModified.t + csModified.behaviorSections[:diminishing].t
if haskey(BSsOriginal, :diminishing)
diminishingSection=BehaviorSection(BSsOriginal[:diminishing])
merge!(BSsModified, Dict(:diminishing=>diminishingSection))
csModified[:E] = csModified[:E] + BSsModified[:diminishing].E
csModified[:t] = csModified[:t] + BSsModified[:diminishing].t
end
@ -180,7 +194,7 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
# calculate the coasting phase until the point the train needs to brake
(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)
cruisingReduction=cruisingReduction/10
else
@ -189,16 +203,16 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
end # while cruisingReduction
# 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, 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
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")
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
else
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.
# 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}())
if haskey(csOriginal.behaviorSections, :breakFree)
breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree])
merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection))
csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E
csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t
# 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
: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 => 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
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
clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing])
merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection))
csModified.E = csModified.E + csModified.behaviorSections[:clearing].E
csModified.t = csModified.t + csModified.behaviorSections[:clearing].t
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(BSsOriginal[:clearing])
merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified[:E] = csModified[:E] + BSsModified[:clearing].E
csModified[:t] = csModified[:t] + BSsModified[:clearing].t
end
if haskey(csOriginal.behaviorSections, :acceleration)
accelerationSection=BehaviorSection(csOriginal.behaviorSections[:acceleration])
merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection))
csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E
csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t
if haskey(BSsOriginal, :acceleration)
accelerationSection=BehaviorSection(BSsOriginal[:acceleration])
merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + BSsModified[:acceleration].E
csModified[:t] = csModified[:t] + BSsModified[:acceleration].t
end
if haskey(csOriginal.behaviorSections, :cruising)
cruisingSection=BehaviorSection(csOriginal.behaviorSections[:cruising])
merge!(csModified.behaviorSections, Dict(:cruising=>cruisingSection))
csModified.E = csModified.E + csModified.behaviorSections[:cruising].E
csModified.t = csModified.t + csModified.behaviorSections[:cruising].t
if haskey(BSsOriginal, :cruising)
cruisingSection=BehaviorSection(BSsOriginal[:cruising])
merge!(BSsModified, Dict(:cruising=>cruisingSection))
csModified[:E] = csModified[:E] + BSsModified[:cruising].E
csModified[:t] = csModified[:t] + BSsModified[:cruising].t
end
diminishingSection=BehaviorSection(csOriginal.behaviorSections[:diminishing])
diminishingSection=BehaviorSection(BSsOriginal[:diminishing])
if length(diminishingSection.dataPoints) > 2
# remove the last diminishing waypoint
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.E=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
merge!(csModified.behaviorSections, Dict(:diminishing => diminishingSection))
csModified.E = csModified.E + csModified.behaviorSections[:diminishing].E
csModified.t = csModified.t + csModified.behaviorSections[:diminishing].t
merge!(BSsModified, Dict(:diminishing => diminishingSection))
csModified[:E] = csModified[:E] + BSsModified[:diminishing].E
csModified[:t] = csModified[:t] + BSsModified[:diminishing].t
energySavingStartId=diminishingSection.dataPoints[end]
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.
energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :diminishing, BehaviorSection())).dataPoints[1]
energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :diminishing, BehaviorSection())).dataPoints[1]
end
# 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)
# 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)
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
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")
end
if t_recoveryAvailable>=(csModified.t-csOriginal.t)
if t_recoveryAvailable>=(csModified[:t]-csOriginal[:t])
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
# 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
# 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
# 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 # function increaseCoastingSection
# method 2 with shortening the acceleration by stepsize
function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, :acceleration) && csOriginal.v_peak > csOriginal.v_entry && csOriginal.v_peak > csOriginal.v_exit
accelerationSection = BehaviorSection(csOriginal.behaviorSections[:acceleration])
if drivingCourse[accelerationSection.dataPoints[end]-1].v < csOriginal.v_exit
return (CharacteristicSection(), [], false)
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)
BSsOriginal = csOriginal[:behaviorSections]
if haskey(BSsOriginal, :acceleration) && csOriginal[:v_peak] > csOriginal[:v_entry] && csOriginal[:v_peak] > csOriginal[:v_exit]
accelerationSection = BehaviorSection(BSsOriginal[:acceleration])
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.
end
# copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}())
if haskey(csOriginal.behaviorSections, :breakFree)
breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree])
merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection))
csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E
csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t
# 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
: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 => 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
#accelerationSection = BehaviorSection(get(csOriginal.behaviorSections, :acceleration, BehaviorSection()))
#accelerationSection = BehaviorSection(get(BSsOriginal, :acceleration, BehaviorSection()))
if length(accelerationSection.dataPoints) > 2
if haskey(csOriginal.behaviorSections, :clearing)
clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing])
merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection))
csModified.E = csModified.E + csModified.behaviorSections[:clearing].E
csModified.t = csModified.t + csModified.behaviorSections[:clearing].t
if haskey(BSsOriginal, :clearing)
clearingSection=BehaviorSection(BSsOriginal[:clearing])
merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified[:E] = csModified[:E] + BSsModified[:clearing].E
csModified[:t] = csModified[:t] + BSsModified[:clearing].t
end
# 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.E=drivingCourse[accelerationSection.dataPoints[end]].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection))
csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E
csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t
merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + BSsModified[:acceleration].E
csModified[:t] = csModified[:t] + BSsModified[:acceleration].t
energySavingStartId=accelerationSection.dataPoints[end]
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.
energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :acceleration, BehaviorSection())).dataPoints[1]
energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :acceleration, BehaviorSection())).dataPoints[1]
end
# 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
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-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_braking=max(0.0, ceil((csModified[:v_exit]^2-csModified[:v_peak]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
s_braking=max(0.0, ceil((csModified[:v_exit]^2-drivingCourseModified[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
s_cruising=csModified[:s_exit]-drivingCourseModified[end].s-s_braking
if s_cruising >0.001
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end #if
# s_brakingAfterCruising=ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train[:a_braking], digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end].v>csModified.v_exit
# s_brakingAfterCruising=ceil((csModified[:v_exit]^2-drivingCourseModified[end].v^2)/2/train[:a_braking], digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end].v>csModified[:v_exit]
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].s<csModified.s_exit
if (csModified.s_exit-drivingCourseModified[end].s)>0.001
# if (csModified.s_exit-drivingCourseModified[end].s)>10^(-approximationLevel)
# println("INFO: The end of new CS",csModified.id," is not reached while saving energy with lowering v_peak.")
elseif drivingCourseModified[end].s<csModified[:s_exit]
if (csModified[:s_exit]-drivingCourseModified[end].s)>0.001
# if (csModified[:s_exit]-drivingCourseModified[end].s)>10^(-approximationLevel)
# println("INFO: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.")
# 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
println("WARNING: The end of new CS",csModified.id," is not reached while saving energy with lowering v_peak.")
println(" Therefore s=",drivingCourseModified[end].s," will be set s_exit=",csModified.s_exit," because the difference is only ",csModified.s_exit-drivingCourseModified[end].s," m.")
println(" v=",drivingCourseModified[end].v," m/s v_exit=",csOriginal.v_exit ," m/s")
println("WARNING: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.")
println(" Therefore s=",drivingCourseModified[end].s," will be set s_exit=",csModified[:s_exit]," because the difference is only ",csModified[:s_exit]-drivingCourseModified[end].s," m.")
println(" v=",drivingCourseModified[end].v," m/s v_exit=",csOriginal[:v_exit] ," m/s")
drivingCourseModified[end].s=csModified.s_exit # rounding up to s_exit
drivingCourseModified[end].s=csModified[:s_exit] # rounding up to s_exit
end #if
if t_recoveryAvailable>=(csModified.t-csOriginal.t)
if t_recoveryAvailable>=(csModified[:t]-csOriginal[:t])
return (csModified, drivingCourseModified, true)
else # time loss is to high. so there is no energy saving modification for this CS with the available recovery time
# 09/06 old: else # time loss is to high and the CS has to be calculated again with larger acceleration section (so with a smaller reduction of the acceleration section)
# 09/06 old: accelerationReduction=min(accelerationReduction/10, csModified.v_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?
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
# 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: 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
# 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 # function decreaseMaximumVelocity
# combination of method 1 and method 2
function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
# if haskey(csOriginal.behaviorSections, :acceleration) && (haskey(csOriginal.behaviorSections, :braking) || haskey(csOriginal.behaviorSections, :coasting)) && csOriginal.v_peak>csOriginal.v_entry && csOriginal.v_peak>csOriginal.v_exit
if haskey(csOriginal.behaviorSections, :acceleration) && (haskey(csOriginal.behaviorSections, :braking) || haskey(csOriginal.behaviorSections, :coasting)) && drivingCourse[get(csOriginal.behaviorSections, :acceleration, BehaviorSection()).dataPoints[end]].v > max(csOriginal.v_entry, csOriginal.v_exit)
csCombined=CharacteristicSection(csOriginal)
function combineEnergySavingMethods(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
BSsOriginal = csOriginal[:behaviorSections]
# if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && csOriginal[:v_peak]>csOriginal[:v_entry] && csOriginal[:v_peak]>csOriginal[:v_exit]
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}()
for i in 1:length(drivingCourse)
# 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)
(csCombined, drivingCourseCombined, newMaximumVelocity)=decreaseMaximumVelocity(csCombined, drivingCourseCombined, settings, train, allCSs, t_recoveryAvailable)
if newMaximumVelocity
ΔE=csOriginal.E-csCombined.E # saved energy (in Ws)
Δt=csCombined.t-csOriginal.t # time loss (in s)
ΔE=csOriginal[:E]-csCombined[:E] # saved energy (in Ws)
Δ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)
if newCoasting
ΔE=csOriginal.E-csCombined.E # saved energy (in Ws)
Δt=csCombined.t-csOriginal.t # time loss (in s)
ΔE=csOriginal[:E]-csCombined[:E] # saved energy (in Ws)
Δt=csCombined[:t]-csOriginal[:t] # time loss (in s)
else
break
end # if newCoasting
end # while haskey
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 # while
return (csCombined, drivingCourseCombined, (ΔE>0.0))# && Δt>0.0))
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
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 #function combineEnergySavingMethods

View File

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

View File

@ -80,10 +80,10 @@ end #function calculateWagonsResistance
"""
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
id=length(CSs)
while s<CSs[id].s_entry
while s<CSs[id][:s_entry]
id=id-1
if id==0
println("s=",s," MS.s_entry=",CSs[1].s_entry)
@ -91,11 +91,11 @@ function calculatePathResistance(s::AbstractFloat, massModel::String, train::Dic
end #while
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"
pathResistance=0.0
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 ‰
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 ‰
id=id-1
if id==0
# 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
"""
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
dataPoint.R_traction=calculateTractionUnitResistance(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
"""
function detectFormerSpeedLimits(CSs::Vector{CharacteristicSection}, csWithTrainHeadId::Integer, currentPoint::DataPoint, trainLength::Real)
function detectFormerSpeedLimits(CSs::Vector{Dict}, csWithTrainHeadId::Integer, currentPoint::DataPoint, trainLength::Real)
formerSpeedLimits=[]
if csWithTrainHeadId > 1 && currentPoint.s - trainLength < CSs[csWithTrainHeadId].s_entry
if csWithTrainHeadId > 1 && currentPoint.s - trainLength < CSs[csWithTrainHeadId][:s_entry]
formerCsId=csWithTrainHeadId-1
while formerCsId > 0 && currentPoint.s - trainLength < CSs[formerCsId].s_exit
if CSs[formerCsId].v_limit < CSs[csWithTrainHeadId].v_limit # TODO: is the position of trains tail < movingSection[:s_entry], v_limit of the first CS is used
push!(formerSpeedLimits, [CSs[formerCsId].s_exit, CSs[formerCsId].v_limit])
while formerCsId > 0 && currentPoint.s - trainLength < CSs[formerCsId][:s_exit]
if CSs[formerCsId][:v_limit] < CSs[csWithTrainHeadId][:v_limit] # TODO: is the position of trains tail < movingSection[:s_entry], v_limit of the first CS is used
push!(formerSpeedLimits, [CSs[formerCsId][:s_exit], CSs[formerCsId][:v_limit]])
for i in 1:length(formerSpeedLimits)-1
if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2]
pop!(formerSpeedLimits)
@ -209,34 +209,34 @@ function detectFormerSpeedLimits(CSs::Vector{CharacteristicSection}, csWithTrain
return formerSpeedLimits
end # function detectFormerSpeedLimits
function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, 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)
# would work: function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, formerSpeedLimits::Array{Any,1}, 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::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Array{AbstractFloat,1},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 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]
while drivingCourse[end].s > get(CS.behaviorSections, :clearing, accelerationSection).s_entry
while drivingCourse[end].s > get(CS[:behaviorSections], :clearing, accelerationSection).s_entry
pop!(drivingCourse)
end
if haskey(CS.behaviorSections, :clearing)
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)
delete!(CS.behaviorSections, :clearing)
if haskey(CS[:behaviorSections], :clearing)
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)
delete!(CS[:behaviorSections], :clearing)
end
# create a (new and longer) clearing section
s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
s_clearing=min(CS.s_exit-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:trainLength]))
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]))
if s_clearing>0.0
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
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
# 09/22: if drivingCourse[end].s < CS.s_exit
if drivingCourse[end].s < CS.s_exit-s_braking
# 09/22: if drivingCourse[end].s < CS[:s_exit]
if drivingCourse[end].s < CS[:s_exit]-s_braking
# reset the accelerationSection
accelerationSection=BehaviorSection()
accelerationSection.type="acceleration" # type of behavior section
@ -260,8 +260,8 @@ end # function considerFormerSpeedLimits!
## This function calculates the data points of the breakFree phase.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed.
# Info: currently the values of the breakFree phase will be calculated like in the acceleration phase
function addBreakFreePhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
if drivingCourse[end].v==0.0 && drivingCourse[end].s<CS.s_exit
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]
breakFreeSection=BehaviorSection()
breakFreeSection.type="breakFree" # type of behavior section
breakFreeSection.s_entry=drivingCourse[end].s # first position (in m)
@ -281,7 +281,7 @@ function addBreakFreePhase!(CS::CharacteristicSection, drivingCourse::Vector{Dat
end
# 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
#= 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())
@ -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.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.E=CS.E+breakFreeSection.E # total energy consumption (in Ws)
CS[:t]=CS[:t]+breakFreeSection.t # total running time (in s)
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
return (CS, drivingCourse)
end #function addBreakFreePhase!
@ -331,7 +331,7 @@ end #function addBreakFreePhase!
## This function calculates the data points of the acceleration phase.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the acceleration section
function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end].v==0.0
(CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
end #if
@ -343,16 +343,16 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
end
# if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:trainLength])
formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:trainLength])
# conditions for acceleration phase
targetSpeedReached = drivingCourse[end].v >= CS.v_peak
trainAtEnd = drivingCourse[end].s >= CS.s_exit
targetSpeedReached = drivingCourse[end].v >= CS[:v_peak]
trainAtEnd = drivingCourse[end].s >= CS[:s_exit]
tractionSurplus = drivingCourse[end].F_T > drivingCourse[end].F_R
# use the conditions for the acceleration phase
if !targetSpeedReached && !trainAtEnd && tractionSurplus
#11/23 long version: if drivingCourse[end].v < CS.v_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.type="acceleration" # type of behavior section
accelerationSection.s_entry=drivingCourse[end].s # first position (in m)
@ -362,7 +362,7 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while drivingCourse[end].v<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)
# 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]
# 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
push!(accelerationSection.dataPoints, drivingCourse[end].i)
# 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
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"
currentStepSize=CS.s_exit-drivingCourse[end-1].s
currentStepSize=CS[:s_exit]-drivingCourse[end-1].s
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
elseif drivingCourse[end].v>CS.v_peak
elseif drivingCourse[end].v>CS[:v_peak]
if settings[:stepVariable]=="v in m/s"
currentStepSize=CS.v_peak-drivingCourse[end-1].v
currentStepSize=CS[:v_peak]-drivingCourse[end-1].v
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
elseif drivingCourse[end].s==CS.s_exit
elseif drivingCourse[end].s==CS[:s_exit]
break
elseif drivingCourse[end].v==CS.v_peak
elseif drivingCourse[end].v==CS[:v_peak]
break
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
currentStepSize = settings[:stepSize] / 10.0^cycle
else
error("ERROR at acceleration phase: With the step variable ", settings[:stepVariable]," the while loop will be left although 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
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
@ -423,15 +423,15 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0
# 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",
" 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!(accelerationSection.dataPoints)
elseif drivingCourse[end].s>CS.s_exit
drivingCourse[end].s=CS.s_exit # rounding s down to s_exit
elseif drivingCourse[end].s>CS[:s_exit]
drivingCourse[end].s=CS[:s_exit] # rounding s down to s_exit
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
(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.t=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s)
accelerationSection.E=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
CS.t=CS.t+accelerationSection.t # total running time (in s)
CS.E=CS.E+accelerationSection.E # total energy consumption (in Ws)
CS[:t]=CS[:t]+accelerationSection.t # total running time (in s)
CS[:E]=CS[:E]+accelerationSection.E # total energy consumption (in Ws)
# TODO: this warning schould not be needed. just for testing
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)
if CS[:v_peak] < drivingCourse[end].v
println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_peak=",CS[:v_peak])
end
merge!(CS.behaviorSections, Dict(:acceleration=>accelerationSection))
merge!(CS[:behaviorSections], Dict(:acceleration=>accelerationSection))
end
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.
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
(CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs)
end #if
@ -479,11 +479,11 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
end
# if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[: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
if drivingCourse[end].v < CS.v_peak && drivingCourse[end].s<CS.s_exit && drivingCourse[end].F_T > drivingCourse[end].F_R
# 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
accelerationSection=BehaviorSection()
accelerationSection.type="acceleration" # type of behavior section
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
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
while drivingCourse[end].v < CS.v_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
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
# 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)
@ -506,7 +506,7 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
# end
# 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
push!(accelerationSection.dataPoints, drivingCourse[end].i)
# 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
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
# 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
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
elseif drivingCourse[end].v>CS.v_peak
elseif drivingCourse[end].v>CS[:v_peak]
if settings[:stepVariable]=="v in m/s"
currentStepSize= CS.v_peak-drivingCourse[end-1].v
currentStepSize= CS[:v_peak]-drivingCourse[end-1].v
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
elseif drivingCourse[end].s==CS.s_exit
elseif drivingCourse[end].s==CS[:s_exit]
break
elseif drivingCourse[end].v==CS.v_peak
elseif drivingCourse[end].v==CS[:v_peak]
break
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
currentStepSize = settings[:stepSize] / 10.0^cycle
else
error("ERROR at acceleration until braking phase: With the step variable ",settings[:stepVariable]," the while loop will be left although 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
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
@ -555,14 +555,14 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0
# 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",
" 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!(accelerationSection.dataPoints)
elseif drivingCourse[end].s + s_braking > CS.s_exit
elseif drivingCourse[end].s + s_braking > CS[:s_exit]
pop!(drivingCourse)
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.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.t=CS.t+accelerationSection.t # total running time (in s)
CS.E=CS.E+accelerationSection.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[:t]=CS[:t]+accelerationSection.t # total running time (in s)
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 # else: just return the given data point number without changes due to the acceleration phase
return (CS, drivingCourse)
@ -597,37 +597,37 @@ end #function addAccelerationPhaseUntilBraking!
## 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.
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)
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
(CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
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
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
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]
cruisingSection=BehaviorSection()
cruisingSection.type=cruisingType # type of behavior section
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)
push!(cruisingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = cruisingSection.type
# 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)
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"))
if settings[:massModel]=="homogeneous strip" && CS.id > 1
if settings[:massModel]=="homogeneous strip" && CS[:id] > 1
currentStepSize=settings[:stepSize]
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while drivingCourse[end].s < CS.s_entry + train[: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
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]
# 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: 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
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
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
drivingCourse[end].behavior = cruisingSection.type
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
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"
currentStepSize=cruisingSection.s_entry+s_cruising-drivingCourse[end-1].s
else
currentStepSize = settings[:stepSize] / 10.0^cycle
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
elseif drivingCourse[end].F_T < drivingCourse[end].F_R
# if settings[:stepVariable] == "s in m"
@ -669,11 +669,11 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
# else
currentStepSize = settings[:stepSize] / 10.0^cycle
# end
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]
elseif drivingCourse[end].s >= CS[:s_entry] + train[:trainLength]
# TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS[:id]].s_entry + train[:trainLength]
break
else # TODO copied from addAccelerationPhase -> probably not needed here !?
error("ERROR at cruising phase: With the step variable ",settings[:stepVariable]," the while loop will be left although the if cases don't apply in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
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
# 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)
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
@ -714,7 +714,7 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
s_cruisingRemaining=cruisingSection.s_entry+s_cruising-drivingCourse[end].s
# 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
push!(cruisingSection.dataPoints, drivingCourse[end].i)
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.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.E=CS.E+cruisingSection.E # total energy consumption (in Ws)
CS[:t]=CS[:t]+cruisingSection.t # total running time (in s)
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
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
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")
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
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]
diminishingSection=BehaviorSection()
diminishingSection.type="diminishing" # type of behavior section
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
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
while drivingCourse[end].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
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
# 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)
@ -765,11 +765,11 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
#end
# 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
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)
end #while
@ -778,18 +778,18 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
if drivingCourse[end].v<=0.0
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
elseif drivingCourse[end].s + s_braking==CS.s_exit
# 11/21 old without s_braking: elseif drivingCourse[end].s==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]
break
elseif drivingCourse[end].F_T > drivingCourse[end].F_R
currentStepSize = settings[:stepSize] / 10.0^cycle
else
error("ERROR during diminishing run: With the step variable ",settings[:stepVariable]," the while loop will be left although s+s_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
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
@ -798,11 +798,11 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0
# push!(diminishingSection.dataPoints, drivingCourse[end].i)
error("ERROR: The train stops during diminishing run in CS",CS.id," because the maximum tractive effort is lower than the resistant forces.",
error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_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!(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.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
CS.t=CS.t+diminishingSection.t # total running time (in s)
CS.E=CS.E+diminishingSection.E # total energy consumption (in Ws)
CS[:t]=CS[:t]+diminishingSection.t # total running time (in s)
CS[:E]=CS[:E]+diminishingSection.E # total energy consumption (in Ws)
merge!(CS.behaviorSections, Dict(:diminishing=>diminishingSection))
merge!(CS[:behaviorSections], Dict(:diminishing=>diminishingSection))
end
end
@ -835,11 +835,11 @@ end #function addDiminishingPhase!
## This function calculates the data points of the coasting phase.
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section
function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
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
#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.type="coasting" # type of behavior section
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
# 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
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
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
# traction effort and resisting forces (in N):
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]
# 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
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
# check which limit was reached and adjust the currentStepSize for the next cycle
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
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
elseif drivingCourse[end].v > CS.v_peak
elseif drivingCourse[end].v > CS[:v_peak]
if settings[:stepVariable]=="v in m/s"
currentStepSize = CS.v_peak-drivingCourse[end-1].v
currentStepSize = CS[:v_peak]-drivingCourse[end-1].v
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
elseif drivingCourse[end].s + s_braking == CS.s_exit
elseif drivingCourse[end].s + s_braking == CS[:s_exit]
break
elseif drivingCourse[end].v == CS.v_exit
elseif drivingCourse[end].v == CS[:v_exit]
break
else
# TODO: not needed. just for testing
error("ERROR at coasting until braking phase: With the step variable ",settings[:stepVariable]," the while loop will be left although v<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
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
@ -898,23 +898,23 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse:
else # if the level of approximation is reached
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",
" 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
pop!(drivingCourse)
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)
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
#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= 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].Δt=drivingCourse[end].Δs/drivingCourse[end-1].v # step size (in 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.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.E=CS.E+coastingSection.E # total energy consumption (in Ws)
CS[:t]=CS[:t]+coastingSection.t # total running time (in s)
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
return (CS, drivingCourse)
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)
# 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::CharacteristicSection, drivingCourse::Vector{DataPoint}, massModel::String, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat)
if drivingCourse[end].v>CS.v_exit && drivingCourse[end].s<CS.s_exit
function addBrakingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) #, 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]
brakingSection=BehaviorSection()
brakingSection.type="braking" # type of behavior section
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)
push!(brakingSection.dataPoints, drivingCourse[end].i) # refering from the breaking section to the first of its data points
drivingCourse[end].behavior = brakingSection.type
@ -975,7 +975,7 @@ function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataP
# calculate s, t, v
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].Δ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
#= if drivingCourse[end-1].a<train[:a_braking] || drivingCourse[end-1].a>=0.0
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_exit=",CS.v_exit)
println(" v_exit=",CS[:v_exit])
println("")
end =#
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.E=drivingCourse[end].ΔE # total energy consumption (in Ws)
CS.t=CS.t+brakingSection.t # total running time (in s)
CS.E=CS.E+brakingSection.E # total energy consumption (in Ws)
CS[:t]=CS[:t]+brakingSection.t # total running time (in s)
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
return (CS, drivingCourse)
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
# 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)
if drivingCourse[end].v > CS.v_exit && drivingCourse[end].s < CS.s_exit
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]
brakingSection=BehaviorSection()
brakingSection.type="braking" # type of behavior section
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
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):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, brakingSection.type)
@ -1040,17 +1040,17 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect
break
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
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
if drivingCourse[end].v < CS.v_exit || !velocityIsPositive
if drivingCourse[end].v < CS[:v_exit] || !velocityIsPositive
# calculate s, t, v
drivingCourse[end].s=CS.s_exit # position (in m)
drivingCourse[end].v=CS.v_exit # velocity (in m/s)
drivingCourse[end].s=CS[:s_exit] # position (in m)
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].Δ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])
# 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
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)
@ -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].Δ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)
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 !!")
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.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.E=CS.E+brakingSection.E # total energy consumption (in Ws)
CS[:t]=CS[:t]+brakingSection.t # total running time (in s)
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
return (CS, drivingCourse)
end #function addBrakingPhaseStepwise!
@ -1092,7 +1092,7 @@ end #function addBrakingPhaseStepwise!
## This function calculates the data point of the standstill.
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the standstill if needed.
function addStandstill!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection})
function addStandstill!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end].v == 0.0
standstillSection=BehaviorSection()
@ -1112,7 +1112,7 @@ function addStandstill!(CS::CharacteristicSection, drivingCourse::Vector{DataPoi
# traction effort and resisting forces (in N)
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
return (CS, drivingCourse)
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
function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict)
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
CSs::Vector{Dict} = movingSection[:characteristicSections]
startingPoint=DataPoint()
startingPoint.i=1
startingPoint.s=CSs[1].s_entry
startingPoint.s=CSs[1][:s_entry]
drivingCourse=[startingPoint] # List of data points
# for CS in CSs
for csId in 1:length(CSs)
# println("CS",csId)
# check if the CS has a cruising section
s_breakFree = get(CSs[csId].behaviorSections, :breakFree, BehaviorSection()).length
s_clearing = get(CSs[csId].behaviorSections, :clearing, BehaviorSection()).length
s_acceleration = get(CSs[csId].behaviorSections, :acceleration, BehaviorSection()).length
s_braking = max(0.0, ceil((CSs[csId].v_exit^2-CSs[csId].v_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
CS = CSs[csId]
BSs = CS[:behaviorSections]
s_breakFree = get(BSs, :breakFree, BehaviorSection()).length
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
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
delete!(CSs[csId].behaviorSections, :breakFree)
delete!(CSs[csId].behaviorSections, :clearing)
delete!(CSs[csId].behaviorSections, :acceleration)
delete!(CSs[csId].behaviorSections, :diminishing)
delete!(CSs[csId].behaviorSections, :cruising)
CSs[csId].E=0.0
CSs[csId].t=0.0
delete!(BSs, :breakFree)
delete!(BSs, :clearing)
delete!(BSs, :acceleration)
delete!(BSs, :diminishing)
delete!(BSs, :cruising)
CS[:E]=0.0
CS[:t]=0.0
if s_clearing == CSs[csId].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")
(CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_clearing, settings, train, CSs, "clearing")
elseif s_cruising == CSs[csId].length
(CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising")
if s_clearing == CS[:length]
# 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")
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
elseif s_cruising == CS[:length]
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising")
elseif s_cruising > 0.0 || s_braking == 0.0
# 09/21 elseif s_cruising > 0.0
# 09/21 elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0)
if drivingCourse[end].v < CSs[csId].v_peak
(CSs[csId], drivingCourse)=addAccelerationPhase!(CSs[csId], drivingCourse, settings, train, CSs)
if drivingCourse[end].v < CS[:v_peak]
(CS, drivingCourse)=addAccelerationPhase!(CS, drivingCourse, settings, train, CSs)
end #if
if CSs[csId].s_exit-drivingCourse[end].s-max(0.0, (CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking]) < -0.001 # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
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(" before acceleration in CS",csId, " with s=",drivingCourse[end].s," s_braking=",((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking])," s_exit=",CSs[csId].s_exit)
println(" and v=",drivingCourse[end].v," v_peak=",CSs[csId].v_peak," v_exit=",CSs[csId].v_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=",CS[:v_peak]," v_exit=",CS[:v_exit])
end
s_braking=max(0.0, ceil((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
s_cruising=CSs[csId].s_exit-drivingCourse[end].s-s_braking
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=CS[:s_exit]-drivingCourse[end].s-s_braking
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
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"
# 09/09 old (not sufficient for steep gradients): if CSs[csId].v_entry < CSs[csId].v_peak
(CSs[csId], drivingCourse)=addAccelerationPhaseUntilBraking!(CSs[csId], drivingCourse, settings, train, CSs)
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 CS[:v_entry] < CS[:v_peak]
(CS, drivingCourse)=addAccelerationPhaseUntilBraking!(CS, drivingCourse, settings, train, CSs)
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
#(CSs[csId], drivingCourse)=addBrakingPhase!(CSs[csId], drivingCourse, settings[:massModel], train, CSs)
(CSs[csId], drivingCourse)=addBrakingPhase!(CSs[csId], drivingCourse, settings, train, CSs)
if drivingCourse[end].v > CS[:v_exit]
#(CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings[:massModel], train, CSs)
(CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings, train, CSs)
end #if
#= 09/20 old and should never be used:
if drivingCourse[end].s < CSs[csId].s_exit
if haskey(CSs[csId].behaviorSections, :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)
if drivingCourse[end].s < CS[:s_exit]
if haskey(BSs, :cruising)
println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_exit=",CS[:s_exit])
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 #for
@ -112,7 +113,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
#create a new moving section for the minimum energy consumption
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
# create a new driving course for the minimum energy consumption
@ -154,7 +155,11 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
end #if
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
ratioMax=0.0
csIdMax=0
@ -182,20 +187,20 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
movingSectionOriginal[:t_recoveryAvailable] = movingSectionOriginal[:t_recoveryAvailable] - movingSectionOriginal[:energySavingModifications][end][:Δt]
lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax].behaviorSections, :standstill,
get(CSsOrig[csIdMax].behaviorSections, :braking,
get(CSsOrig[csIdMax].behaviorSections, :cruisingAfterCoasting,
get(CSsOrig[csIdMax].behaviorSections, :coasting,
get(CSsOrig[csIdMax].behaviorSections, :cruising,
get(CSsOrig[csIdMax].behaviorSections, :acceleration,
get(CSsOrig[csIdMax].behaviorSections, :clearing,
get(CSsOrig[csIdMax].behaviorSections, :breakFree,
get(CSsOrig[csIdMax].behaviorSections, :diminishing,
lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax][:behaviorSections], :standstill,
get(CSsOrig[csIdMax][:behaviorSections], :braking,
get(CSsOrig[csIdMax][:behaviorSections], :cruisingAfterCoasting,
get(CSsOrig[csIdMax][:behaviorSections], :coasting,
get(CSsOrig[csIdMax][:behaviorSections], :cruising,
get(CSsOrig[csIdMax][:behaviorSections], :acceleration,
get(CSsOrig[csIdMax][:behaviorSections], :clearing,
get(CSsOrig[csIdMax][:behaviorSections], :breakFree,
get(CSsOrig[csIdMax][:behaviorSections], :diminishing,
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 haskey(CSsOrig[csIdMax].behaviorSections, :diminishing)
lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax].behaviorSections[:diminishing].dataPoints[end])
if haskey(CSsOrig[csIdMax][:behaviorSections], :diminishing)
lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax][:behaviorSections][:diminishing].dataPoints[end])
end
# create new driving course
@ -228,7 +233,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
# replace the original driving course and CS with the new modified ones
drivingCourseOriginal=drivingCourseNew
CSsOrig[csIdMax]=CharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified])
CSsOrig[csIdMax]=copyCharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified])
movingSectionOriginal[:t]=drivingCourseOriginal[end].t # total running time (in s)
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]
for csId in csIdMax+1:length(CSsOrig)
for bs in 1: length(allBs)
if haskey(CSsOrig[csId].behaviorSections, allBs[bs])
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
if haskey(CSsOrig[csId][:behaviorSections], allBs[bs])
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
end
end #if
end #for
@ -283,8 +288,8 @@ end #function calculateMinimumEnergyConsumption
function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Dict, train::Dict)
# TODO: refctor and sort this function
CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections]
# TODO: refactor and sort this function
CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections]
if modificationType == "increasing coasting"
# method 1: increase coasting
@ -306,8 +311,8 @@ function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{Dat
:csModified => characteristicSectionModified, # the modified characteristic section
:drivingCourseModified => drivingCourseModifiedUntilEndOfModifiedCS) # drivingCourse for the modified characteristic section
merge!(energySavingModification, Dict(:ΔE => CSsOrig[csId].E - energySavingModification[:csModified].E)) # saved energy (in Ws)
merge!(energySavingModification, Dict(:Δt => energySavingModification[:csModified].t - CSsOrig[csId].t)) # time loss (in s)
merge!(energySavingModification, Dict(:ΔE => CSsOrig[csId][:E] - energySavingModification[:csModified][:E])) # saved energy (in Ws)
merge!(energySavingModification, Dict(:Δt => energySavingModification[:csModified][:t] - CSsOrig[csId][:t])) # time loss (in s)
if energySavingModification[:Δt] <= movingSectionOriginal[:t_recoveryAvailable] && energySavingModification[:ΔE] >= 0.0
@ -355,7 +360,7 @@ function createEnergySavingModification()
:ΔE => 0.0, # saved energy (in Ws)
:Δt => 0.0, # time loss (in s)
:ratio => 0.0, # ratio of ΔE and Δt (in Ws/s)
:csModified => CharacteristicSection(), # the modified characteristic section
:csModified => Dict(), # the modified characteristic section
:drivingCourseModified => []) # drivingCourse for the modified characteristic section
end #createEnergySavingModification
@ -365,7 +370,7 @@ function copyEnergySavingModification(original::Dict)
:ΔE => original[:ΔE], # saved energy (in Ws)
:Δt => original[:Δt], # time loss (in s)
:ratio => original[:ratio], # ratio of ΔE and Δt (in Ws/s)
:csModified => CharacteristicSection(original[:csModified])) # the modified characteristic section
:csModified => copyCharacteristicSection(original[:csModified])) # the modified characteristic section
drivingCourseModified = DataPoint[]
for i in 1:length(original[:drivingCourseModified])
@ -381,7 +386,7 @@ function updateEnergySavingModifications!(energySavingModifications::Vector{Dict
difference = endOfModificationId-lastIdOfSelectedCsOriginal
for modNr in csIdMax+1:length(energySavingModifications)
if energySavingModifications[modNr][:ratio]>0
BSs = energySavingModifications[modNr][:csModified].behaviorSections
BSs = energySavingModifications[modNr][:csModified][:behaviorSections]
# update the behavior sections of the modified charateristic section
for bs in 1: length(allBs)
if haskey(BSs, allBs[bs])
@ -415,9 +420,10 @@ end #function updateEnergySavingModifications!
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])
push!(CSsCopy, CharacteristicSection(original[:characteristicSections][csId]))
push!(CSsCopy, copyCharacteristicSection(original[:characteristicSections][csId]))
end #for
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)
merge!(copy, Dict(:t_recoveryAvailable => original[:t_recoveryAvailable]))
end
return copy
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

View File

@ -255,17 +255,17 @@ function printImportantValues(drivingCourse::Vector{DataPoint})
end #function printImportantValues
function printSectionInformation(movingSection::Dict)
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
CSs::Vector{Dict} = movingSection[:characteristicSections]
println("MS mit length=", movingSection[:length]," mit t=", movingSection[:t])
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for csId in 1:length(CSs)
println("CS ",csId," mit length=", CSs[csId].length," mit t=", CSs[csId].t)
println("CS ",csId," mit length=", CSs[csId][:length]," mit t=", CSs[csId][:t])
for bs in 1: length(allBs)
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)
# for point in 1:length(CSs[csId].behaviorSections[allBs[bs]].dataPoints)
# println(CSs[csId].behaviorSections[allBs[bs]].dataPoints[point])
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)
# for point in 1:length(CSs[csId][:behaviorSections][allBs[bs]].dataPoints)
# println(CSs[csId][:behaviorSections][allBs[bs]].dataPoints[point])
# end
end #if
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)
pathLength = s_exit - s_entry # total length (in m)
CSs=[]
CSs=Vector{Dict}()
s_csStart=s_entry
csId=1
for row in 2:length(path[:sections])
@ -47,44 +47,41 @@ function createMovingSection(path::Dict, v_trainLimit::Real)
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)
# this function creates and returns a characteristic section dependent on the paths attributes
characteristicSection=CharacteristicSection()
characteristicSection.id=csId # identifier
characteristicSection.s_entry=s_csStart # first position (in m)
characteristicSection.s_exit=section[:s_end] # last position (in m)
characteristicSection.length=characteristicSection.s_exit-characteristicSection.s_entry # total length (in m)
characteristicSection.t=0.0 # total running time (in s)
characteristicSection.E=0.0 # total energy consumption (in Ws)
characteristicSection.v_limit=v_csLimit # speed limit (in m/s)
# initializing v_entry, v_peak and v_exit with v_limit
characteristicSection.v_peak=characteristicSection.v_limit # maximum reachable speed (in m/s)
characteristicSection.v_entry=characteristicSection.v_limit # maximum entry speed (in m/s)
characteristicSection.v_exit=characteristicSection.v_limit # maximum exit speed (in m/s)
characteristicSection.r_path=section[:f_Rp] # path resistance (in ‰)
# Create and return a characteristic section dependent on the paths attributes
characteristicSection= Dict(:id => csId, # identifier
:s_entry => s_csStart, # first position (in m)
:s_exit => section[:s_end], # last position (in m)
:length => section[:s_end]-s_csStart, # total length (in m)
:r_path => section[:f_Rp], # path resistance (in ‰)
:behaviorSections => Dict(), # list of containing behavior sections
:t => 0.0, # total running time (in 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
:v_peak => v_csLimit, # maximum reachable speed (in m/s)
:v_entry => v_csLimit, # maximum entry speed (in m/s)
:v_exit => v_csLimit) # maximum exit speed (in m/s)
return characteristicSection
end #function createCharacteristicSection
## define the intersection velocities between the characterisitc sections to secure braking behavior
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
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
CSs = movingSection[:characteristicSections]
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
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)
CSs[csId].v_entry=min(CSs[csId].v_limit, v_entryMax)
CSs[csId].v_peak=CSs[csId].v_entry
CSs[csId][:v_entry]=min(CSs[csId][:v_limit], v_entryMax)
CSs[csId][:v_peak]=CSs[csId][:v_entry]
csId=csId-1
if csId >= 1
CSs[csId].v_exit=min(CSs[csId].v_limit, CSs[csId+1].v_entry)
CSs[csId][:v_exit]=min(CSs[csId][:v_limit], CSs[csId+1][:v_entry])
end #if
end #while
return movingSection
@ -93,30 +90,30 @@ end #function secureBrakingBehavior!
## define the intersection velocities between the characterisitc sections to secure acceleration behavior
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
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.i=1
previousCSv_exit=CSs[1].v_entry
previousCSv_exit=CSs[1][:v_entry]
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.v=CSs[csId].v_entry
startingPoint.s=CSs[csId][:s_entry]
startingPoint.v=CSs[csId][:v_entry]
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].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)
else #CSs[csId].v_entry==CSs[csId].v_peak
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]
# v_exit stays the same
end #if
previousCSv_exit=CSs[csId].v_exit
previousCSv_exit=CSs[csId][:v_exit]
end #for
return movingSection
@ -127,24 +124,24 @@ end #function secureAccelerationBehavior!
## define the intersection velocities between the characterisitc sections to secure cruising behavior
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
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
CSs = movingSection[:characteristicSections]
startingPoint=DataPoint()
startingPoint.i=1
previousCSv_exit=CSs[1].v_entry
previousCSv_exit=CSs[1][:v_entry]
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.v=CSs[csId].v_peak
startingPoint.s=CSs[csId][:s_entry]
startingPoint.v=CSs[csId][:v_peak]
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].v_exit=min(CSs[csId].v_exit, cruisingCourse[end].v)
(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)
previousCSv_exit=CSs[csId].v_exit
previousCSv_exit=CSs[csId][:v_exit]
end #for
return movingSection

View File

@ -1,6 +1,6 @@
module types
# 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
@ -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)
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
id::Integer # identifier
length::AbstractFloat # total length (in m)
@ -80,26 +80,6 @@ function CharacteristicSection(original::CharacteristicSection)
end #for
return copy
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