Refactor the mutable struct BehaviorSection as a Dictionary

development
Max Kannenberg 2022-01-08 02:11:08 +01:00
parent 792bfea614
commit f590206226
11 changed files with 394 additions and 423 deletions

View File

@ -10,7 +10,7 @@ train:
rotationMassFactor_t: 1.09 # (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for the traction unit)
rotationMassFactor_w: 1.03 # (source: "Fahrdynamik des Schienenverkehrs" by Wende, 2003, p. 13 for "Güterwagenzug beladen" -> 1.03 to 1.04)
powerType: diesel # diesel or electric (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90)
trainType: freight # "freight" or "passenger" or "motor coach train" (source: https://dybas.de/dybas/gw/gw_f_1/g124.html)
trainType: freight # "freight" or "passenger" or "motorCoachTrain" (source: https://dybas.de/dybas/gw/gw_f_1/g124.html)
v_limit: # in m/s
v_limit_kmh: 80 # in km/h (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90)
a_braking: -0.4124 # in m/s^2 (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB 290 with with 10x Facs124)

View File

@ -10,7 +10,7 @@ train:
rotationMassFactor_t: 1.09 # (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for the traction unit)
rotationMassFactor_w: 1.06 # (source: "Railway Timetabling & Operations" by Hansen, et al., 2014, p. 71 for freight wagons)
powerType: electric # diesel or electric (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn)#Gemeinsame_Merkmale)
trainType: passenger # "freight" or "passenger" or "motor coach train" (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn))
trainType: passenger # "freight" or "passenger" or "motorCoachTrain" (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn))
v_limit: # in m/s
v_limit_kmh: 160 # in km/h (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn)#Gemeinsame_Merkmale)
a_braking: -0.3507 # in m/s^2 (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB146.5 with 1x DApza687.2, 3x DBpza668.2, 1x DBpbzfa668.2)

View File

@ -10,7 +10,7 @@ train:
rotationMassFactor_t:
rotationMassFactor_w:
powerType: diesel # diesel or electric (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
trainType: motor coach train # "freight" or "passenger" or "motor coach train" (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
trainType: motorCoachTrain # "freight" or "passenger" or "motorCoachTrain" (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
v_limit: # in m/s
v_limit_kmh: 120 # in km/h (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic)
a_braking: -0.4253 # in m/s^2 (source: FBS -> using the information from the "Fahrschaubild" of a long path without gradient or speed limit for DB 642)

View File

@ -1,3 +1,5 @@
# TODO: calculation time for passenger trains on path1 is very long and should be reduced
module EnergySaving
using ..types
@ -5,13 +7,16 @@ using ..MovingPhases
export calculateRecoveryTime, increaseCoastingSection, decreaseMaximumVelocity, combineEnergySavingMethods
@enum trainType passenger=1 freight=2 motorCoachTrain=3
approximationLevel = 6 # value for approximation to intersections
# TODO: define it in TrainRun and give it to each function?
function calculateRecoveryTime(s_MS::Real, t_MS::AbstractFloat, train::Dict)
# function for calculating the recovery time that can be used for energy saving
# MS: Moving Section
if train[:trainType]=="motor coach train"
# 01/05 old without enum: if train[:type]=="motor coach train"
if train[:type] == motorCoachTrain::trainType
if s_MS<= 30000
c_s=0.0
else s_MS> 30000
@ -32,14 +37,16 @@ function calculateRecoveryTime(s_MS::Real, t_MS::AbstractFloat, train::Dict)
t_recovery=s_MS*c_s+t_MS*c_t
return t_recovery
elseif train[:trainType]=="freight" && train[:v_limit]<=120/3.6 # unit is m/s
t_recovery1=s_MS*0.0006 +t_MS*0.03
t_recovery2=s_MS*0.0018 +t_MS*0.0
t_recovery3=s_MS*0.0 +t_MS*0.04
t_recovery=max(t_recovery1, t_recovery2, t_recovery3)
# 01/05 old without enum: elseif train[:type]=="freight" && train[:v_limit]<=120/3.6 # unit is m/s
elseif train[:type] == freight::trainType && train[:v_limit] <= 120/3.6 # unit is m/s
t_recovery1=s_MS*0.0006 +t_MS*0.03
t_recovery2=s_MS*0.0018 +t_MS*0.0
t_recovery3=s_MS*0.0 +t_MS*0.04
t_recovery=max(t_recovery1, t_recovery2, t_recovery3)
return t_recovery
else # train[:trainType]=="passenger" || (train[:trainType]=="freight" && train[:v_limit]>120/3.6) # unit is m/s
return t_recovery
# 01/05 old without enum: else # train[:trainType]=="passenger" || (train[:trainType]=="freight" && train[:v_limit]>120/3.6) # unit is m/s
else # train[:type] == passenger::trainType || (train[:type] == freight::trainType && train[:v_limit]>120/3.6) # unit is m/s
if s_MS<= 30000
c_s=0.0
else s_MS> 30000
@ -86,7 +93,7 @@ function calculateRecoveryTime(s_MS::Real, t_MS::AbstractFloat, train::Dict)
t_recovery=s_MS*c_s+t_MS*c_t
return t_recovery
end # if train[:trainType]
end # if train[:type]
end #function calculateRecoveryTime
function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
@ -94,7 +101,7 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
if (haskey(BSsOriginal, :cruising) || haskey(BSsOriginal, :diminishing)) && haskey(BSsOriginal, :braking)
# check if cruising or diminishing should be reduced for coasting
if haskey(BSsOriginal, :cruising) && haskey(BSsOriginal, :diminishing)
if BSsOriginal[:cruising].dataPoints[1] > BSsOriginal[:diminishing].dataPoints[1]
if BSsOriginal[:cruising][:dataPoints][1] > BSsOriginal[:diminishing][:dataPoints][1]
reduceCruising=true
reduceDiminishing=false
else
@ -111,12 +118,13 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
if reduceCruising
cruisingReduction = settings[:stepSize]
# 01/07 test for a better calculation time: cruisingReduction = settings[:stepSize]*100
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
# create a copy for the characteristic sections drivingCourse
energySavingStartId=get(BSsOriginal, :cruising, BehaviorSection()).dataPoints[1]
energySavingStartId=get(BSsOriginal, :cruising, Dict(:dataPoints=>[0]))[:dataPoints][1]
if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !")
end
@ -130,21 +138,21 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
# calculating the new length of the cruising section
if settings[:stepVariable]=="s in m" # distance step method
s_cruising = BSsOriginal[: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=BSsOriginal[:cruising].t-cruisingReduction
# t_cruising=BSsOriginal[:cruising][:t]-cruisingReduction
# s_cruising=t_cruising*drivingCourseModified[end].v
distanceReduction = drivingCourse(BSsOriginal[:cruising].dataPoints[end]).v*cruisingReduction
s_cruising = BSsOriginal[: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=BSsOriginal[: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
# 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}())
# 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, Dict}())
#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)
@ -161,28 +169,28 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree)
breakFreeSection=BehaviorSection(BSsOriginal[:breakFree])
breakFreeSection=copyBehaviorSection(BSsOriginal[:breakFree])
merge!(BSsModified, Dict(:breakFree=>breakFreeSection))
csModified[:E] = csModified[:E] + BSsModified[:breakFree].E
csModified[:t] = csModified[:t] + BSsModified[:breakFree].t
csModified[:E] = csModified[:E] + BSsModified[:breakFree][:E]
csModified[:t] = csModified[:t] + BSsModified[:breakFree][:t]
end
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])
clearingSection=copyBehaviorSection(BSsOriginal[:clearing])
merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified[:E] = csModified[:E] + BSsModified[:clearing].E
csModified[:t] = csModified[:t] + BSsModified[:clearing].t
csModified[:E] = csModified[:E] + BSsModified[:clearing][:E]
csModified[:t] = csModified[:t] + BSsModified[:clearing][:t]
end
if haskey(BSsOriginal, :acceleration)
accelerationSection=BehaviorSection(BSsOriginal[:acceleration])
accelerationSection=copyBehaviorSection(BSsOriginal[:acceleration])
merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + BSsModified[:acceleration].E
csModified[:t] = csModified[:t] + BSsModified[:acceleration].t
csModified[:E] = csModified[:E] + BSsModified[:acceleration][:E]
csModified[:t] = csModified[:t] + BSsModified[:acceleration][:t]
end
if haskey(BSsOriginal, :diminishing)
diminishingSection=BehaviorSection(BSsOriginal[:diminishing])
diminishingSection=copyBehaviorSection(BSsOriginal[:diminishing])
merge!(BSsModified, Dict(:diminishing=>diminishingSection))
csModified[:E] = csModified[:E] + BSsModified[:diminishing].E
csModified[:t] = csModified[:t] + BSsModified[:diminishing].t
csModified[:E] = csModified[:E] + BSsModified[:diminishing][:E]
csModified[:t] = csModified[:t] + BSsModified[:diminishing][:t]
end
@ -224,7 +232,7 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
# 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
# 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}())
# 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, Dict}())
csModified=Dict(:id => csOriginal[:id], # identifier
:s_entry => csOriginal[:s_entry], # first position (in m)
:s_exit => csOriginal[:s_exit], # last position (in m)
@ -240,49 +248,49 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree)
breakFreeSection=BehaviorSection(BSsOriginal[:breakFree])
breakFreeSection=copyBehaviorSection(BSsOriginal[:breakFree])
merge!(BSsModified, Dict(:breakFree=>breakFreeSection))
csModified[:E] = csModified[:E] + BSsModified[:breakFree].E
csModified[:t] = csModified[:t] + BSsModified[:breakFree].t
csModified[:E] = csModified[:E] + BSsModified[:breakFree][:E]
csModified[:t] = csModified[:t] + BSsModified[:breakFree][:t]
end
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])
clearingSection=copyBehaviorSection(BSsOriginal[:clearing])
merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified[:E] = csModified[:E] + BSsModified[:clearing].E
csModified[:t] = csModified[:t] + BSsModified[:clearing].t
csModified[:E] = csModified[:E] + BSsModified[:clearing][:E]
csModified[:t] = csModified[:t] + BSsModified[:clearing][:t]
end
if haskey(BSsOriginal, :acceleration)
accelerationSection=BehaviorSection(BSsOriginal[:acceleration])
accelerationSection=copyBehaviorSection(BSsOriginal[:acceleration])
merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + BSsModified[:acceleration].E
csModified[:t] = csModified[:t] + BSsModified[:acceleration].t
csModified[:E] = csModified[:E] + BSsModified[:acceleration][:E]
csModified[:t] = csModified[:t] + BSsModified[:acceleration][:t]
end
if haskey(BSsOriginal, :cruising)
cruisingSection=BehaviorSection(BSsOriginal[:cruising])
cruisingSection=copyBehaviorSection(BSsOriginal[:cruising])
merge!(BSsModified, Dict(:cruising=>cruisingSection))
csModified[:E] = csModified[:E] + BSsModified[:cruising].E
csModified[:t] = csModified[:t] + BSsModified[:cruising].t
csModified[:E] = csModified[:E] + BSsModified[:cruising][:E]
csModified[:t] = csModified[:t] + BSsModified[:cruising][:t]
end
diminishingSection=BehaviorSection(BSsOriginal[:diminishing])
if length(diminishingSection.dataPoints) > 2
diminishingSection=copyBehaviorSection(BSsOriginal[:diminishing])
if length(diminishingSection[:dataPoints]) > 2
# remove the last diminishing waypoint
pop!(diminishingSection.dataPoints)
pop!(diminishingSection[:dataPoints])
diminishingSection.v_exit=drivingCourse[diminishingSection.dataPoints[end]].v # exit speed (in m/s)
diminishingSection.s_exit=drivingCourse[diminishingSection.dataPoints[end]].s # last position (in m)
diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m)
diminishingSection.t=drivingCourse[diminishingSection.dataPoints[end]].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
diminishingSection.E=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
diminishingSection[:v_exit]=drivingCourse[diminishingSection[:dataPoints][end]].v # exit speed (in m/s)
diminishingSection[:s_exit]=drivingCourse[diminishingSection[:dataPoints][end]].s # last position (in m)
diminishingSection[:length]=diminishingSection[:s_exit]-diminishingSection[:s_entry] # total length (in m)
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!(BSsModified, Dict(:diminishing => diminishingSection))
csModified[:E] = csModified[:E] + BSsModified[:diminishing].E
csModified[:t] = csModified[:t] + BSsModified[:diminishing].t
csModified[:E] = csModified[:E] + BSsModified[:diminishing][:E]
csModified[:t] = csModified[:t] + BSsModified[:diminishing][:t]
energySavingStartId=diminishingSection.dataPoints[end]
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(BSsOriginal, :clearing, get(BSsOriginal, :diminishing, BehaviorSection())).dataPoints[1]
energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :diminishing, Dict(:dataPoints =>[0])))[:dataPoints][1]
end
# copy the driving course till the beginning of energy saving
@ -329,15 +337,15 @@ function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict
#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]
accelerationSection = copyBehaviorSection(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
# 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}())
# 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, Dict}())
csModified=Dict(:id => csOriginal[:id], # identifier
:s_entry => csOriginal[:s_entry], # first position (in m)
:s_exit => csOriginal[:s_exit], # last position (in m)
@ -352,43 +360,43 @@ function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict
:v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s)
BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree)
breakFreeSection=BehaviorSection(BSsOriginal[:breakFree])
breakFreeSection=copyBehaviorSection(BSsOriginal[:breakFree])
merge!(BSsModified, Dict(:breakFree=>breakFreeSection))
csModified[:E] = csModified[:E] + BSsModified[:breakFree].E
csModified[:t] = csModified[:t] + BSsModified[:breakFree].t
csModified[:E] = csModified[:E] + BSsModified[:breakFree][:E]
csModified[:t] = csModified[:t] + BSsModified[:breakFree][:t]
end
#accelerationSection = BehaviorSection(get(BSsOriginal, :acceleration, BehaviorSection()))
#accelerationSection = copyBehaviorSection(get(BSsOriginal, :acceleration, Dict()))
if length(accelerationSection.dataPoints) > 2
if length(accelerationSection[:dataPoints]) > 2
if haskey(BSsOriginal, :clearing)
clearingSection=BehaviorSection(BSsOriginal[:clearing])
clearingSection=copyBehaviorSection(BSsOriginal[:clearing])
merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified[:E] = csModified[:E] + BSsModified[:clearing].E
csModified[:t] = csModified[:t] + BSsModified[:clearing].t
csModified[:E] = csModified[:E] + BSsModified[:clearing][:E]
csModified[:t] = csModified[:t] + BSsModified[:clearing][:t]
end
# remove the last acceleration waypoint
pop!(accelerationSection.dataPoints)
pop!(accelerationSection[:dataPoints])
accelerationSection.v_exit=drivingCourse[accelerationSection.dataPoints[end]].v # exit speed (in m/s)
accelerationSection.s_exit=drivingCourse[accelerationSection.dataPoints[end]].s # last position (in m)
accelerationSection.length=accelerationSection.s_exit-accelerationSection.s_entry # total length (in m)
accelerationSection.t=drivingCourse[accelerationSection.dataPoints[end]].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s)
accelerationSection.E=drivingCourse[accelerationSection.dataPoints[end]].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
accelerationSection[:v_exit]=drivingCourse[accelerationSection[:dataPoints][end]].v # exit speed (in m/s)
accelerationSection[:s_exit]=drivingCourse[accelerationSection[:dataPoints][end]].s # last position (in m)
accelerationSection[:length]=accelerationSection[:s_exit]-accelerationSection[:s_entry] # total length (in m)
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!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + BSsModified[:acceleration].E
csModified[:t] = csModified[:t] + BSsModified[:acceleration].t
csModified[:E] = csModified[:E] + BSsModified[:acceleration][:E]
csModified[:t] = csModified[:t] + BSsModified[:acceleration][:t]
energySavingStartId=accelerationSection.dataPoints[end]
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(BSsOriginal, :clearing, get(BSsOriginal, :acceleration, BehaviorSection())).dataPoints[1]
energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0])))[:dataPoints][1]
end
# TODO: should v_peak be reduced or is it enough to pop the data points?
# characteristicSection.v_peak=drivingCourse[end].v # setting v_peak to the last data point's velocity which is the highest reachable value in this characteristic section
# characteristicSection[:v_peak]=drivingCourse[end].v # setting v_peak to the last data point's velocity which is the highest reachable value in this characteristic section
# copy the drivingCourse till the beginning of energy saving
drivingCourseModified=Vector{DataPoint}()
@ -452,7 +460,7 @@ end # function decreaseMaximumVelocity
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])
if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && drivingCourse[get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0]))[: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
@ -471,7 +479,7 @@ function combineEnergySavingMethods(csOriginal::Dict, drivingCourse::Vector{Data
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]])))
merge!(csCombined[:behaviorSections], Dict(allBs[bs] => copyBehaviorSection(BSsOriginal[allBs[bs]])))
end #if
end #for

View File

@ -5,6 +5,8 @@ using ..types
export readInput
@enum trainType passenger=1 freight=2 motorCoachTrain=3
"""
Read the input information from YAML files for train, path and settings, save it in different dictionaries and return them.
"""
@ -34,14 +36,17 @@ function inputTrain(trainDirectory::String)
id=1 # trains identifier
if haskey(data["train"],"trainType")
if typeof(data["train"]["trainType"])==String && (data["train"]["trainType"]=="freight" || data["train"]["trainType"]=="motor coach train" || data["train"]["trainType"]=="passenger")
trainType=data["train"]["trainType"] # "passenger" or "freight" or "motor coach train"
# @enum trainType passenger=1 freight=2 motorCoachTrain=3
if typeof(data["train"]["trainType"])==String && (data["train"]["trainType"]=="freight" || data["train"]["trainType"]=="motorCoachTrain" || data["train"]["trainType"]=="passenger")
# 01/05 old without enum: if typeof(data["train"]["trainType"])==String && (data["train"]["trainType"]=="freight" || data["train"]["trainType"]=="motor coach train" || data["train"]["trainType"]=="passenger")
# 01/05 old without enum: trainType=data["train"]["trainType"] # "passenger" or "freight" or "motor coach train"
type = getEnum(data["train"]["trainType"], trainType) # "passenger" or "freight" or "motorCoachTrain"
delete!(data["train"], "trainType")
else
error("ERROR at reading the train yaml file: The value of trainType is wrong. It has to be freight, motor coach train or passenger.")
error("ERROR at reading the train yaml file: The value of trainType is wrong. It has to be freight, motorCoachTrain or passenger.")
end
else
error("ERROR at reading the train yaml file: The keyword trainType is missing. It has to be added with the value freight, motor coach train or passenger.")
error("ERROR at reading the train yaml file: The keyword trainType is missing. It has to be added with the value freight, motorCoachTrain or passenger.")
end
if haskey(data["train"],"l_train")
@ -259,11 +264,24 @@ function inputTrain(trainDirectory::String)
# coefficients for the vehicle resistance of the set of wagons (consist)
# coefficient for velocitiy difference between set of wagons (consist) and outdoor air (in m/s)
# if type == getEnum("passenger", trainType) || type == getEnum("motorCoachTrain", trainType)
if type == passenger::trainType || type == motorCoachTrain::trainType
# TODO: if type == trainType(:passenger) || type == trainType(:motorCoachTrain)
# TODO: ODER if trainType(type) == trainType(:passenger) || trainType(type) == trainType(:motorCoachTrain)
Δv_w=15.0/3.6
# elseif type == getEnum("freight", trainType)
elseif type == freight::trainType
Δv_w=0.0
end # if
#= 01/05 old without enum
# coefficient for velocitiy difference between set of wagons (consist) and outdoor air (in m/s)
if trainType=="passenger" || trainType=="motor coach train"
Δv_w=15.0/3.6
elseif trainType== "freight"
Δv_w=0.0
end # if
=#
# coefficient for basic resistance of the set of wagons (consist) (in ‰)
if haskey(data["train"],"f_Rw0") && data["train"]["f_Rw0"]!=nothing
@ -316,8 +334,9 @@ function inputTrain(trainDirectory::String)
# create the train Dictionary
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)
:type => type, # type of train "passenger" or "freight" or "motorCoachTrain"
#= 01/05 old without enum :trainType => trainType, # type of train "passenger" or "freight" or "motor coach train" =#
:length => 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)
@ -651,13 +670,13 @@ But only if the string matches an enumerated value.
# Example
```jldoctest
julia> @enum trainTypes passenger freight
julia> @enum trainType passenger freight
julia> myTrain = "passenger"
"passenger"
julia> myTrainType = getEnum(myTrain, trainTypes)
passenger::trainTypes = 0
julia> myTrainType = getEnum(myTrain, trainType)
passenger::trainType = 0
```
"""
function getEnum(string::String, enum_type::DataType)

View File

@ -86,7 +86,7 @@ function calculatePathResistance(s::Real, massModel::String, train::Dict, CSs::V
while s<CSs[id][:s_entry]
id=id-1
if id==0
println("s=",s," MS.s_entry=",CSs[1].s_entry)
println("s=",s," MS[:s_entry]=",CSs[1][:s_entry])
end
end #while
@ -94,12 +94,12 @@ function calculatePathResistance(s::Real, massModel::String, train::Dict, CSs::V
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[:length]<CSs[id][:s_exit]
pathResistance=pathResistance+(min(s, CSs[id][:s_exit])-max(s-train[:length], CSs[id][:s_entry]))/train[:length]*(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
return pathResistance+(CSs[1].s_entry-(s-train[:trainLength]))/train[:trainLength]*(CSs[1].r_path/1000*train[:m_train]*g) # /1000 because of the unit ‰
return pathResistance+(CSs[1][:s_entry]-(s-train[:length]))/train[:length]*(CSs[1].r_path/1000*train[:m_train]*g) # /1000 because of the unit ‰
end #if
end #while
else
@ -209,25 +209,25 @@ function detectFormerSpeedLimits(CSs::Vector{Dict}, csWithTrainHeadId::Integer,
return formerSpeedLimits
end # function detectFormerSpeedLimits
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)
function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits, accelerationSection::Dict)
# 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::Dict)
# would work: function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Any,1}, accelerationSection::Dict)
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)
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_clearing=min(CS[:s_exit]-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:length]))
if s_clearing>0.0
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
@ -238,19 +238,14 @@ function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint},
# 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
accelerationSection.s_entry=drivingCourse[end].s # first position (in m)
accelerationSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
#currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
accelerationSection = createBehaviorSection("acceleration", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
else
return (CS, drivingCourse, formerSpeedLimits, accelerationSection, true)
end
end
# remove former speed limits of characteristic sections the train has left during the last step from the list
while length(formerSpeedLimits) > 0 && drivingCourse[end].s - train[:trainLength] >= formerSpeedLimits[end][1]
while length(formerSpeedLimits) > 0 && drivingCourse[end].s - train[:length] >= formerSpeedLimits[end][1]
pop!(formerSpeedLimits)
end
end
@ -262,13 +257,9 @@ end # function considerFormerSpeedLimits!
# Info: currently the values of the breakFree phase will be calculated like in the acceleration phase
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)
breakFreeSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(breakFreeSection.dataPoints, drivingCourse[end].i) # list of containing data points
BS = createBehaviorSection("breakFree", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
drivingCourse[end].behavior = breakFreeSection.type
# traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") # currently the tractive effort is calculated like in the acceleration phase
@ -282,7 +273,7 @@ function addBreakFreePhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings
# creating the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], settings[:stepSize], CS[:id]))
drivingCourse[end].behavior = breakFreeSection.type
drivingCourse[end].behavior = BS[: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())
drivingCourse[end].i=drivingCourse[end-1].i+1 # incrementing the number of the data point
@ -311,19 +302,19 @@ function addBreakFreePhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings
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)
=#
push!(breakFreeSection.dataPoints, drivingCourse[end].i)
push!(BS[:dataPoints], drivingCourse[end].i)
# calculate the accumulated breakFree section information
breakFreeSection.s_exit=drivingCourse[end].s # last position (in m)
breakFreeSection.length=breakFreeSection.s_exit-breakFreeSection.s_entry # total length (in m)
breakFreeSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
breakFreeSection.t=drivingCourse[end].t-drivingCourse[breakFreeSection.dataPoints[1]].t # total running time (in s)
breakFreeSection.E=drivingCourse[end].E-drivingCourse[breakFreeSection.dataPoints[1]].E # total energy consumption (in Ws)
merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end].s, # last position (in m)
:t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
:E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
:v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
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]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:breakFree => breakFreeSection))
merge!(CS[:behaviorSections], Dict(:breakFree => BS))
end # else: return the characteristic section without a breakFree section
return (CS, drivingCourse)
end #function addBreakFreePhase!
@ -343,7 +334,7 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, setti
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[:length])
# conditions for acceleration phase
targetSpeedReached = drivingCourse[end].v >= CS[:v_peak]
@ -353,37 +344,33 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, setti
# 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
accelerationSection=BehaviorSection()
accelerationSection.type="acceleration" # type of behavior section
accelerationSection.s_entry=drivingCourse[end].s # first position (in m)
accelerationSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(accelerationSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = accelerationSection.type
BS = createBehaviorSection("acceleration", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
currentStepSize=settings[:stepSize] # initialize 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
# traction effort and resisting forces (in N)
# 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
# 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2):
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]))
drivingCourse[end].behavior = accelerationSection.type
push!(accelerationSection.dataPoints, drivingCourse[end].i)
# calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
drivingCourse[end].behavior = BS[:type]
push!(BS[:dataPoints], drivingCourse[end].i)
# calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal
(CS, drivingCourse, formerSpeedLimits, accelerationSection, endOfCsReached) = considerFormerSpeedLimits!(CS, drivingCourse, settings, train, CSs, formerSpeedLimits, accelerationSection)
(CS, drivingCourse, formerSpeedLimits, BS, endOfCsReached) = considerFormerSpeedLimits!(CS, drivingCourse, settings, train, CSs, formerSpeedLimits, BS)
if endOfCsReached
return (CS, drivingCourse)
end #if
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections
end #if
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
@ -418,24 +405,24 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, setti
end
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(accelerationSection.dataPoints)
pop!(BS[:dataPoints])
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0
# push!(accelerationSection.dataPoints, drivingCourse[end].i)
# push!(BS[: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.",
" 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]
pop!(drivingCourse)
pop!(accelerationSection.dataPoints)
pop!(BS[:dataPoints])
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)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
else
@ -443,22 +430,23 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, setti
end
end #for
if length(accelerationSection.dataPoints) > 1 # 11/21 new: it is possible that the acceleration starts at v_peak, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section.
if length(BS[:dataPoints]) > 1 # 11/21 new: it is possible that the acceleration starts at v_peak, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section.
# calculate the accumulated acceleration section information
accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
accelerationSection.s_exit=drivingCourse[end].s # last position (in m)
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)
merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end].s, # last position (in m)
:t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
:E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
:v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
CS[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[: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])
end
merge!(CS[:behaviorSections], Dict(:acceleration=>accelerationSection))
merge!(CS[:behaviorSections], Dict(:acceleration=>BS))
end
end # else: just return the given data point number without changes due to the acceleration phase
@ -479,25 +467,21 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP
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[:length])
# 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)
accelerationSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(accelerationSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = accelerationSection.type
BS = createBehaviorSection("acceleration", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
currentStepSize=settings[:stepSize] # initialize 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
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
@ -507,17 +491,17 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP
# create the next data point
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)
drivingCourse[end].behavior = BS[:type]
push!(BS[:dataPoints], drivingCourse[end].i)
# 12/03: was moved behind considerFormerSpeedLimits: calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal
(CS, drivingCourse, formerSpeedLimits, accelerationSection, endOfCsReached) = considerFormerSpeedLimits!(CS, drivingCourse, settings, train, CSs, formerSpeedLimits, accelerationSection)
(CS, drivingCourse, formerSpeedLimits, BS, endOfCsReached) = considerFormerSpeedLimits!(CS, drivingCourse, settings, train, CSs, formerSpeedLimits, BS)
if endOfCsReached
return (CS, drivingCourse)
end
end
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
end #while
@ -550,25 +534,25 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP
end
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(accelerationSection.dataPoints)
pop!(BS[:dataPoints])
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0
# push!(accelerationSection.dataPoints, drivingCourse[end].i)
# push!(BS[: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.",
" 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]
pop!(drivingCourse)
pop!(accelerationSection.dataPoints)
pop!(BS[:dataPoints])
elseif drivingCourse[end].s + s_braking > CS[:s_exit]
pop!(drivingCourse)
pop!(accelerationSection.dataPoints)
pop!(BS[:dataPoints])
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
(CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
else
@ -576,19 +560,19 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP
end
end #for
if length(accelerationSection.dataPoints) > 1 # TODO: is it still possible that it is <=1 although there is a sepaate diminishing phase?
if length(BS[:dataPoints]) > 1 # TODO: is it still possible that it is <=1 although there is a separate diminishing phase?
# calculate the accumulated acceleration section information
accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
accelerationSection.s_exit=drivingCourse[end].s # last position (in m)
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)
merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end].s, # last position (in m)
:t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
:E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
:v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
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[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:acceleration=>accelerationSection))
merge!(CS[:behaviorSections], Dict(:acceleration=>BS))
end
end # else: just return the given data point number without changes due to the acceleration phase
return (CS, drivingCourse)
@ -599,35 +583,30 @@ end #function addAccelerationPhaseUntilBraking!
# 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::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"?
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "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, Dict(:length=>0.0))[: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]
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)
cruisingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(cruisingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = cruisingSection.type
BS = createBehaviorSection(cruisingType, drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
# TODO: necessary?
s_cruising=min(s_cruising, CS[:s_exit]-cruisingSection.s_entry)
s_cruising=min(s_cruising, CS[:s_exit]-BS[: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"?
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") # TODO: or give BS[: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
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[:length] && drivingCourse[end].s<BS[: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[:length] && drivingCourse[end].s<BS[: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
@ -639,15 +618,10 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruisin
if settings[:stepVariable]=="s in m"
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?
end
drivingCourse[end].behavior = cruisingSection.type
push!(cruisingSection.dataPoints, drivingCourse[end].i)
# for testing
if drivingCourse[end].F_T > drivingCourse[end].F_R && drivingCourse[end].F_R > 0.0
error("In the cruising phase of CS",cruisingSection.id,": F_T=",drivingCourse[end].F_T," != F_R=",drivingCourse[end].F_R)
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train[:length]/(10.0^cycle), CS[:id])) # TODO which step size should be used?
end
drivingCourse[end].behavior = BS[:type]
push!(BS[:dataPoints], drivingCourse[end].i)
# traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")
@ -655,22 +629,22 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruisin
# 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>BS[:s_entry]+s_cruising # TODO also the following? drivingCourse[end].s > CSs[CS[:id]][:s_entry] + train[:length]))
if settings[:stepVariable] == "s in m"
currentStepSize=cruisingSection.s_entry+s_cruising-drivingCourse[end-1].s
currentStepSize=BS[: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==BS[: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"
# currentStepSize=cruisingSection.s_entry+s_cruising-drivingCourse[end-1].s
# currentStepSize=BS[:s_entry]+s_cruising-drivingCourse[end-1].s
# 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[:length]
# TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS[:id]][:s_entry] + train[:length]
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")
@ -678,17 +652,17 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruisin
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(cruisingSection.dataPoints)
pop!(BS[:dataPoints])
else # if the level of approximation is reached
if drivingCourse[end].s>cruisingSection.s_entry+s_cruising
if cruisingSection.type == "clearing"
if drivingCourse[end].s>BS[:s_entry]+s_cruising
if BS[:type] == "clearing"
else
pop!(drivingCourse)
pop!(cruisingSection.dataPoints)
pop!(BS[:dataPoints])
end
# 11/21 |->
elseif drivingCourse[end].s==cruisingSection.s_entry+s_cruising
elseif drivingCourse[end].s==BS[:s_entry]+s_cruising
break
# 11/21 ->|
elseif drivingCourse[end].F_T < drivingCourse[end].F_R
@ -696,7 +670,7 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruisin
(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, Dict(length=>0.0))[:length])
else
@ -706,30 +680,30 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruisin
end #if
# TODO oder soll das lieber nach oben in den else des letzten Durchlaufs. Noch mal genauer ansehen, ob hier was doppelt gemoppelt ist
# if drivingCourse[end].s<cruisingSection.s_entry+s_cruising
if drivingCourse[end].s<cruisingSection.s_entry+s_cruising && drivingCourse[end].F_T >= drivingCourse[end].F_R
# if drivingCourse[end].s<BS[:s_entry]+s_cruising
if drivingCourse[end].s<BS[:s_entry]+s_cruising && drivingCourse[end].F_T >= drivingCourse[end].F_R
drivingCourse[end].a=0.0 # acceleration (in m/s^2)
# calculate the remaining cruising way
s_cruisingRemaining=cruisingSection.s_entry+s_cruising-drivingCourse[end].s
s_cruisingRemaining=BS[: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]))
drivingCourse[end].behavior = cruisingSection.type
push!(cruisingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
push!(BS[:dataPoints], drivingCourse[end].i)
end
# calculate the accumulated cruising section information
cruisingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
cruisingSection.s_exit=drivingCourse[end].s # last position (in m)
cruisingSection.length=cruisingSection.s_exit-cruisingSection.s_entry # total length (in m)
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)
merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end].s, # last position (in m)
:t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
:E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
:v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
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]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(Symbol(cruisingSection.type) => cruisingSection))
merge!(CS[:behaviorSections], Dict(Symbol(BS[:type]) => BS))
end # else: return the characteristic section without a cruising section
return (CS, drivingCourse)
@ -741,21 +715,16 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settin
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]
diminishingSection=BehaviorSection()
diminishingSection.type="diminishing" # type of behavior section
diminishingSection.s_entry=drivingCourse[end].s # first position (in m)
diminishingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(diminishingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = diminishingSection.type
BS = createBehaviorSection("diminishing", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
currentStepSize=settings[:stepSize] # initialize 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
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type)
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
@ -766,11 +735,11 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settin
# create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = diminishingSection.type
push!(diminishingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
push!(BS[:dataPoints], drivingCourse[end].i)
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
end #while
# check which limit was reached and adjust the currentStepSize for the next cycle
@ -793,18 +762,18 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settin
end
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(diminishingSection.dataPoints)
pop!(BS[:dataPoints])
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0
# push!(diminishingSection.dataPoints, drivingCourse[end].i)
# push!(BS[:dataPoints], drivingCourse[end].i)
error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.")
elseif drivingCourse[end].s + s_braking > CS[:s_exit]
pop!(drivingCourse)
pop!(diminishingSection.dataPoints)
pop!(BS[:dataPoints])
elseif drivingCourse[end].F_T > drivingCourse[end].F_R
break
@ -815,17 +784,18 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settin
end
end #for
if length(diminishingSection.dataPoints) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start
if length(BS[:dataPoints]) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start
# calculate the accumulated diminishing section information
diminishingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
diminishingSection.s_exit=drivingCourse[end].s # last position (in m)
diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m)
diminishingSection.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
CS[:t]=CS[:t]+diminishingSection.t # total running time (in s)
CS[:E]=CS[:E]+diminishingSection.E # total energy consumption (in Ws)
merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end].s, # last position (in m)
:t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
:E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
:v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
merge!(CS[:behaviorSections], Dict(:diminishing=>diminishingSection))
CS[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:diminishing=>BS))
end
end
@ -837,31 +807,27 @@ end #function addDiminishingPhase!
# Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section
function addCoastingPhaseUntilBraking!(CS::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[:length])
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)
coastingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
push!(coastingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = coastingSection.type
BS = createBehaviorSection("coasting", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
currentStepSize=settings[:stepSize] # initialize 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
# traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, coastingSection.type)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2):
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]))
drivingCourse[end].behavior = coastingSection.type
push!(coastingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
push!(BS[:dataPoints], drivingCourse[end].i)
s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking])
@ -894,7 +860,7 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint
end
# delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse)
pop!(coastingSection.dataPoints)
pop!(BS[:dataPoints])
else # if the level of approximation is reached
if drivingCourse[end].v<=0.0
@ -905,7 +871,7 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint
elseif drivingCourse[end].s + s_braking > CS[:s_exit]
# delete last data point because it went to far
pop!(drivingCourse)
pop!(coastingSection.dataPoints)
pop!(BS[: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
# 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)
@ -937,16 +903,16 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint
end #for
# calculate the accumulated coasting section information
coastingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
coastingSection.s_exit=drivingCourse[end].s # last position (in m)
coastingSection.length=coastingSection.s_exit-coastingSection.s_entry # total length (in m)
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)
merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end].s, # last position (in m)
:t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
:E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
:v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
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]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:coasting=>coastingSection))
merge!(CS[:behaviorSections], Dict(:coasting=>BS))
end ## else: just return the given data point number without changes due to the coasting phase
return (CS, drivingCourse)
end #function addCoastingPhaseUntilBraking!
@ -957,24 +923,20 @@ end #function addCoastingPhaseUntilBraking!
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.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
BS = createBehaviorSection("braking", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
BS[:s_exit]=CS[:s_exit] # last position (in m)
drivingCourse[end].behavior = BS[:type]
# traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, brakingSection.type)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
push!(drivingCourse, DataPoint())
drivingCourse[end].i = drivingCourse[end-1].i+1 # incrementing the number of the data point
drivingCourse[end].behavior = brakingSection.type
push!(brakingSection.dataPoints, drivingCourse[end].i) # refering from the breaking section to the last of its data points
drivingCourse[end].behavior = BS[:type]
push!(BS[:dataPoints], drivingCourse[end].i) # refering from the breaking section to the last of its data points
# calculate s, t, v
drivingCourse[end].s=brakingSection.s_exit # position (in m)
drivingCourse[end].s=BS[: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)
@ -996,15 +958,16 @@ function addBrakingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::
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)
brakingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
brakingSection.length=drivingCourse[end].Δs # total length (in m)
brakingSection.t=drivingCourse[end].Δt # total running time (in s)
brakingSection.E=drivingCourse[end].ΔE # total energy consumption (in Ws)
merge!(BS, Dict(:length => drivingCourse[end].Δs, # total length (in m)
#:s_exit => drivingCourse[end].s, # last position (in m)
:t => drivingCourse[end].Δt, # total running time (in s)
:E => drivingCourse[end].ΔE, # total energy consumption (in Ws)
:v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
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]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:braking=>brakingSection))
merge!(CS[:behaviorSections], Dict(:braking=>BS))
end # else: return the characteristic section without a braking section
return (CS, drivingCourse)
end #function addBrakingPhase!
@ -1014,18 +977,14 @@ end #function addBrakingPhase!
# 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::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)
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
BS = createBehaviorSection("braking", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections
currentStepSize=settings[:stepSize] # initialize 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
# traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, brakingSection.type)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2):
drivingCourse[end].a=train[:a_braking]
@ -1041,8 +1000,8 @@ function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{DataPoint}, se
end
end
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = brakingSection.type
push!(brakingSection.dataPoints, drivingCourse[end].i)
drivingCourse[end].behavior = BS[:type]
push!(BS[:dataPoints], drivingCourse[end].i)
# s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking])
end # while
@ -1056,7 +1015,6 @@ function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{DataPoint}, se
#drivingCourse[end-1].a=round((drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs, digits=approximationLevel) # acceleration (in m/s^2) (rounding because it should not be less than a_braking)
drivingCourse[end-1].a=(drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs # acceleration (in m/s^2)
# 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])
@ -1075,16 +1033,16 @@ function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{DataPoint}, se
end
# calculate the accumulated coasting section information
brakingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
brakingSection.s_exit=drivingCourse[end].s # last position (in m)
brakingSection.length=brakingSection.s_exit-brakingSection.s_entry # total length (in m)
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)
merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
:s_exit => drivingCourse[end].s, # last position (in m)
:t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
:E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
:v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
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]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:braking=>brakingSection))
merge!(CS[:behaviorSections], Dict(:braking=>BS))
end # else: return the characteristic section without a braking section
return (CS, drivingCourse)
end #function addBrakingPhaseStepwise!
@ -1095,26 +1053,34 @@ end #function addBrakingPhaseStepwise!
function addStandstill!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end].v == 0.0
standstillSection=BehaviorSection()
standstillSection.type="standstill" # type of behavior section
standstillSection.s_entry=drivingCourse[end].s # first position (in m)
standstillSection.s_exit=drivingCourse[end].s # last position (in m)
standstillSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
standstillSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
standstillSection.length=0.0 # total length (in m)
standstillSection.t=0.0 # total running time (in s)
standstillSection.E=0.0 # total energy consumption (in Ws)
push!(standstillSection.dataPoints, drivingCourse[end].i) # refering from the breaking section to the first of its data points
drivingCourse[end].behavior = standstillSection.type
BS = createBehaviorSection("standstill", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
merge!(BS, Dict(:length => 0.0, # total length (in m)
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:s_exit => drivingCourse[end].s, # last position (in m)
:v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
drivingCourse[end].behavior = BS[:type]
# traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, standstillSection.type)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
merge!(CS[:behaviorSections], Dict(:standstill => standstillSection))
merge!(CS[:behaviorSections], Dict(:standstill => BS))
end # else: return the characteristic section without a standstillSection section
return (CS, drivingCourse)
end #function addStandstill!
function createBehaviorSection(type::String, s_entry::Real, v_entry::Real, startingPoint::Integer)
BS= Dict(#:type => behavior, # type of behavior section: breakFree, clearing, acceleration, cruising, diminishing, coasting, cruisingAfterCoasting, braking or standstill
:type => type, # type of behavior section: "breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting", "braking" or "standstill"
:length => 0.0, # total length (in m)
:s_entry => s_entry, # first position (in m)
:s_exit => 0.0, # last position (in m)
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:v_entry => v_entry, # entry speed (in m/s)
:v_exit => 0.0, # exit speed (in m/s)
:dataPoints => [startingPoint]) # list of identifiers of the containing data points starting with the initial point
return BS
end #function createBehaviorSection
end #module MovingPhases

View File

@ -25,22 +25,24 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
# check if the CS has a cruising section
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_breakFree = get(BSs, :breakFree, Dict(:length=>0.0))[:length]
s_clearing = get(BSs, :clearing, Dict(:length=>0.0))[:length]
s_acceleration = get(BSs, :acceleration, Dict(:length=>0.0))[: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=CS[: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!(BSs, :breakFree)
delete!(BSs, :clearing)
delete!(BSs, :acceleration)
delete!(BSs, :diminishing)
delete!(BSs, :cruising)
CS[:E]=0.0
CS[:t]=0.0
# reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit
# 01/07 old: delete!(BSs, :breakFree)
# 01/07 old: delete!(BSs, :clearing)
# 01/07 old: delete!(BSs, :acceleration)
# 01/07 old: delete!(BSs, :diminishing)
# 01/07 old: delete!(BSs, :cruising)
CS[:behaviorSections] = Dict()
CS[:E] = 0.0
CS[:t] = 0.0
if s_clearing == CS[:length]
@ -113,6 +115,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
#create a new moving section for the minimum energy consumption
movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime)
# 01/01 new when Datapoint is a Dict: movingSectionOriginal=copy(movingSectionMinimumRunningTime)
CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections]
merge!(movingSectionOriginal, Dict(:energySavingModifications => [])) # list containing all the used energy saving modifications
@ -196,11 +199,11 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
get(CSsOrig[csIdMax][:behaviorSections], :clearing,
get(CSsOrig[csIdMax][:behaviorSections], :breakFree,
get(CSsOrig[csIdMax][:behaviorSections], :diminishing,
BehaviorSection()))))))))).dataPoints[end]
Dict(:dataPoints => [0]))))))))))[:dataPoints][end]
# if there is a diminishing phase its location must be analysed seperately because it could be before acceleration, between acceleration and cruising or after cruising. All the other behavior sections occur in a fixed order.
# if there is a diminishing phase its location must be analysed seperately because it could be before acceleration, between acceleration and cruising or after cruising. All the other behavior sections occure in a fixed order.
if haskey(CSsOrig[csIdMax][:behaviorSections], :diminishing)
lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax][:behaviorSections][:diminishing].dataPoints[end])
lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax][:behaviorSections][:diminishing][:dataPoints][end])
end
# create new driving course
@ -233,7 +236,8 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
# replace the original driving course and CS with the new modified ones
drivingCourseOriginal=drivingCourseNew
CSsOrig[csIdMax]=copyCharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified])
CSsOrig[csIdMax]=copy(movingSectionOriginal[:energySavingModifications][end][:csModified])
# 01/07 old without copy: 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)
@ -244,8 +248,8 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
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
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
@ -370,7 +374,8 @@ 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 => copyCharacteristicSection(original[:csModified])) # the modified characteristic section
:csModified => copy(original[:csModified])) # the modified characteristic section
# 01/07 old without copy: csModified => copyCharacteristicSection(original[:csModified])) # the modified characteristic section
drivingCourseModified = DataPoint[]
for i in 1:length(original[:drivingCourseModified])
@ -378,8 +383,7 @@ function copyEnergySavingModification(original::Dict)
end
merge!(copy, Dict(:drivingCourseModified => drivingCourseModified)) # drivingCourse for the modified characteristic section
return copy
end #function EnergySavingModification
end #function copyEnergySavingModification
function updateEnergySavingModifications!(energySavingModifications::Vector{Dict}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer)
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
@ -390,8 +394,8 @@ function updateEnergySavingModifications!(energySavingModifications::Vector{Dict
# update the behavior sections of the modified charateristic section
for bs in 1: length(allBs)
if haskey(BSs, allBs[bs])
for point in 1:length(BSs[allBs[bs]].dataPoints)
BSs[allBs[bs]].dataPoints[point] = BSs[allBs[bs]].dataPoints[point] + difference
for point in 1:length(BSs[allBs[bs]][:dataPoints])
BSs[allBs[bs]][:dataPoints][point] = BSs[allBs[bs]][:dataPoints][point] + difference
end
end #if
end #for
@ -423,10 +427,11 @@ function copyMovingSection(original::Dict)
#TODO after removing the mutable structs: Is it possible to just "copy"?
CSsCopy = Vector{Dict}()
for csId in 1:length(original[:characteristicSections])
push!(CSsCopy, copyCharacteristicSection(original[:characteristicSections][csId]))
push!(CSsCopy, copy(original[:characteristicSections][csId]))
# 01/07 old without copy: push!(CSsCopy, copyCharacteristicSection(original[:characteristicSections][csId]))
end #for
copy = Dict(:id => original[:id], # identifier
copiedMS = Dict(:id => original[:id], # identifier
:length => original[:length], # total length (in m)
:s_entry => original[:s_entry], # first position (in m)
:s_exit => original[:s_exit], # last position (in m)
@ -437,28 +442,29 @@ function copyMovingSection(original::Dict)
if haskey(original, :energySavingModifications) # list of containing all the used energy saving modifications
ModificationsCopy = Dict[]
for modId in 1:length(original[:energySavingModifications])
push!(ModificationsCopy, EnergySavingModification(original[:energySavingModifications][modId]))
push!(ModificationsCopy, copyEnergySavingModification(original[:energySavingModifications][modId])) # TODO or should it be copyEnergySavingModification
# 01/07 new when DataPoint is a Dict: push!(ModificationsCopy, copy(original[:energySavingModifications][modId]))
end #for
merge!(copy, Dict(:energySavingModifications => ModificationsCopy))
merge!(copiedMS, Dict(:energySavingModifications => ModificationsCopy))
end
if haskey(original, :t_recovery) # total recovery time for energy-saving modifications (in s)
merge!(copy, Dict(:t_recovery => original[:t_recovery]))
merge!(copiedMS, Dict(:t_recovery => original[:t_recovery]))
end
if haskey(original, :t_recoveryAvailable) # still available recovery time for energy-saving modifications (in s)
merge!(copy, Dict(:t_recoveryAvailable => original[:t_recoveryAvailable]))
merge!(copiedMS, Dict(:t_recoveryAvailable => original[:t_recoveryAvailable]))
end
return copy
return copiedMS
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
copiedCS = 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 ‰)
: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)
@ -470,10 +476,11 @@ function copyCharacteristicSection(original::Dict)
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]])))
#merge!(copiedCS[:behaviorSections], Dict(allBs[bs] => copyBehaviorSection(original[:behaviorSections][allBs[bs]])))
merge!(copiedCS[:behaviorSections], Dict(allBs[bs] => copy(original[:behaviorSections][allBs[bs]])))
end #if
end #for
return copy
return copiedCS
end #function copyCharacteristicSection
=#
end #module OperationModes

View File

@ -263,9 +263,9 @@ function printSectionInformation(movingSection::Dict)
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])
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

@ -6,7 +6,7 @@ using .MovingPhases
export preparateSections
## create a moving section and its containing characteristic sections with securedd braking, acceleration and cruising behavior
## create a moving section and its containing characteristic sections with secured braking, acceleration and cruising behavior
function preparateSections(path::Dict, train::Dict, settings::Dict)
movingSection=createMovingSection(path, train[:v_limit])
movingSection=secureBrakingBehavior!(movingSection, train[:a_braking])
@ -104,11 +104,10 @@ function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train:
startingPoint.v=CSs[csId][:v_entry]
accelerationCourse=[startingPoint] # List of data points
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_exit]=min(CSs[csId][:v_exit], CSs[csId][:v_peak], accelerationCourse[end].v)
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_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

View File

@ -1,13 +1,16 @@
module types
# definition of all the additional types and their constructors
export DataPoint, BehaviorSection #, CharacteristicSection
export DataPoint#, BehaviorSection
export copyBehaviorSection # TODO is it still necessary if there is no more mutable struct? can just copy(original) be used?
#export trainType
#@enum trainType passenger=1 freight=2 motorCoachTrain=3
#@enum behavior breakFree=1 clearing=2 acceleration=3 cruising=4diminishing=6 coasting=7 cruisingAfterCoasting=8 braking=9 standstill=10
## a data point is the smallest element of the driving course. One step of the step approach is between two data points
mutable struct DataPoint
i::Integer # identifier and counter variable of the dricing course
behavior::String # type of BehaviorSection the DataPoint ist part of ("breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting","braking" or "standstill")
# a data point which is the last point of one BehaviorSection and the first point of the next BehaviorSection will be attached to the latter
behavior::String # type of behavior section the DataPoint ist part of ("breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting", "braking" or "standstill")
# a data point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter
s::AbstractFloat # position (in m)
Δs::AbstractFloat # step size (in m)
t::AbstractFloat # point in time (in s)
@ -31,55 +34,24 @@ DataPoint()=DataPoint(0, "", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0
DataPoint(original::DataPoint)=DataPoint(original.i, original.behavior, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W, original.ΔW, original.E, original.ΔE, original.F_T, original.F_R, original.R_path, original.R_train, original.R_traction, original.R_wagons)
## different sections the whole path can be devided in the following
## smallest section of the path is the behavior section. It relates to the containing data points via their identifier.
mutable struct BehaviorSection
type::String # type of behavior section: "breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting","braking" or "standstill"
length::AbstractFloat # total length (in m)
s_entry::AbstractFloat # first position (in m)
s_exit::AbstractFloat # last position (in m)
t::AbstractFloat # total running time (in s)
E::AbstractFloat # total energy consumption (in Ws)
v_entry::AbstractFloat # entry speed (in m/s)
v_exit::AbstractFloat # exit speed (in m/s)
dataPoints::Vector{Integer} # list of identifiers of the containing data points
end # mutable struct BehaviorSection
BehaviorSection()=BehaviorSection("", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, [])
function BehaviorSection(original::BehaviorSection)
function copyBehaviorSection(original::Dict)
bsDataPoints=[]
for i in 1:length(original.dataPoints)
push!(bsDataPoints, original.dataPoints[i])
for i in 1:length(original[:dataPoints])
push!(bsDataPoints, original[:dataPoints][i])
end
return BehaviorSection(original.type, original.length, original.s_entry, original.s_exit, original.t, original.E, original.v_entry, original.v_exit, bsDataPoints)
copiedBS = Dict(#:type => behavior, # type of behavior section: breakFree, clearing, acceleration, cruising, diminishing, coasting, cruisingAfterCoasting, braking or standstill
:type => original[:type], # type of behavior section: "breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting", "braking" or "standstill"
:length => original[:length], # total length (in m)
:s_entry => original[:s_entry], # first position (in m)
:s_exit => original[:s_exit], # last position (in m)
:t => original[:t], # total running time (in s)
:E => original[:E], # total energy consumption (in Ws)
:v_entry => original[:v_entry], # entry speed (in m/s)
:v_exit => original[:v_exit], # exit speed (in m/s)
:dataPoints => bsDataPoints) # list of identifiers of the containing data points
return copiedBS
end
#= # 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)
s_entry::AbstractFloat # first position (in m)
s_exit::AbstractFloat # last position (in m)
t::AbstractFloat # total running time (in s)
E::AbstractFloat # total energy consumption (in Ws)
v_limit::AbstractFloat # speed limit (in m/s)
v_peak::AbstractFloat # maximum reachable speed (in m/s)
v_entry::AbstractFloat # maximum entry speed (in m/s)
v_exit::AbstractFloat # maximum exit speed (in m/s)
r_path::AbstractFloat # spedific path resistance (in ‰)
behaviorSections::AbstractDict{Symbol, BehaviorSection} # list of containing behavior sections
end # mutable struct CharacteristicSection
CharacteristicSection()=CharacteristicSection(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Dict{Symbol, BehaviorSection}())
function CharacteristicSection(original::CharacteristicSection)
copy=CharacteristicSection(original.id, original.length, original.s_entry, original.s_exit, original.t, original.E, original.v_limit, original.v_peak, original.v_entry, original.v_exit, original.r_path, Dict{Symbol, BehaviorSection}())
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 CharacteristicSection
=#
end #module

View File

@ -11,14 +11,14 @@ include("../src/Input.jl")
using .Input
using YAML, Test
@enum trainTypes passenger=1 freight=2 motorCoachTrain=3
@enum trainType passenger=1 freight=2 motorCoachTrain=3
@test Input.getEnum("passenger", trainTypes) == passenger::trainTypes
@test Input.getEnum("freight", trainTypes) == freight::trainTypes
@test Input.getEnum("motorCoachTrain", trainTypes) == motorCoachTrain::trainTypes
@test Input.getEnum("passenger", trainType) == passenger::trainType
@test Input.getEnum("freight", trainType) == freight::trainType
@test Input.getEnum("motorCoachTrain", trainType) == motorCoachTrain::trainType
data = YAML.load(open("data/trains/train_passenger_IC2.yaml"))
@test Input.getEnum(data["train"]["trainType"], trainTypes) == passenger::trainTypes
@test Input.getEnum(data["train"]["trainType"], trainType) == passenger::trainType
data = YAML.load(open("data/trains/train_freight_V90withOreConsist.yaml"))
@test Input.getEnum(data["train"]["trainType"], trainTypes) == freight::trainTypes
@test Input.getEnum(data["train"]["trainType"], trainType) == freight::trainType