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_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) 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) 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: # in m/s
v_limit_kmh: 80 # in km/h (source: https://de.wikipedia.org/wiki/DB-Baureihe_V_90) 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) 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_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) 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) 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: # in m/s
v_limit_kmh: 160 # in km/h (source: https://de.wikipedia.org/wiki/Intercity_2_(Deutsche_Bahn)#Gemeinsame_Merkmale) 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) 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_t:
rotationMassFactor_w: rotationMassFactor_w:
powerType: diesel # diesel or electric (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic) 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: # in m/s
v_limit_kmh: 120 # in km/h (source: https://de.wikipedia.org/wiki/Siemens_Desiro_Classic) 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) 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 module EnergySaving
using ..types using ..types
@ -5,13 +7,16 @@ using ..MovingPhases
export calculateRecoveryTime, increaseCoastingSection, decreaseMaximumVelocity, combineEnergySavingMethods export calculateRecoveryTime, increaseCoastingSection, decreaseMaximumVelocity, combineEnergySavingMethods
@enum trainType passenger=1 freight=2 motorCoachTrain=3
approximationLevel = 6 # value for approximation to intersections approximationLevel = 6 # value for approximation to intersections
# TODO: define it in TrainRun and give it to each function? # TODO: define it in TrainRun and give it to each function?
function calculateRecoveryTime(s_MS::Real, t_MS::AbstractFloat, train::Dict) function calculateRecoveryTime(s_MS::Real, t_MS::AbstractFloat, train::Dict)
# function for calculating the recovery time that can be used for energy saving # function for calculating the recovery time that can be used for energy saving
# MS: Moving Section # MS: Moving Section
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 if s_MS<= 30000
c_s=0.0 c_s=0.0
else s_MS> 30000 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 t_recovery=s_MS*c_s+t_MS*c_t
return t_recovery return t_recovery
elseif train[:trainType]=="freight" && train[:v_limit]<=120/3.6 # unit is m/s # 01/05 old without enum: elseif train[:type]=="freight" && train[:v_limit]<=120/3.6 # unit is m/s
t_recovery1=s_MS*0.0006 +t_MS*0.03 elseif train[:type] == freight::trainType && train[:v_limit] <= 120/3.6 # unit is m/s
t_recovery2=s_MS*0.0018 +t_MS*0.0 t_recovery1=s_MS*0.0006 +t_MS*0.03
t_recovery3=s_MS*0.0 +t_MS*0.04 t_recovery2=s_MS*0.0018 +t_MS*0.0
t_recovery=max(t_recovery1, t_recovery2, t_recovery3) t_recovery3=s_MS*0.0 +t_MS*0.04
t_recovery=max(t_recovery1, t_recovery2, t_recovery3)
return t_recovery return t_recovery
else # train[:trainType]=="passenger" || (train[:trainType]=="freight" && train[:v_limit]>120/3.6) # unit is m/s # 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 if s_MS<= 30000
c_s=0.0 c_s=0.0
else s_MS> 30000 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 t_recovery=s_MS*c_s+t_MS*c_t
return t_recovery return t_recovery
end # if train[:trainType] end # if train[:type]
end #function calculateRecoveryTime end #function calculateRecoveryTime
function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) 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) if (haskey(BSsOriginal, :cruising) || haskey(BSsOriginal, :diminishing)) && haskey(BSsOriginal, :braking)
# check if cruising or diminishing should be reduced for coasting # check if cruising or diminishing should be reduced for coasting
if haskey(BSsOriginal, :cruising) && haskey(BSsOriginal, :diminishing) 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 reduceCruising=true
reduceDiminishing=false reduceDiminishing=false
else else
@ -111,12 +118,13 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
if reduceCruising if reduceCruising
cruisingReduction = settings[:stepSize] 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]/10^approximationLevel
#while cruisingReduction>=settings[:stepSize]/100 #while cruisingReduction>=settings[:stepSize]/100
while cruisingReduction>=settings[:stepSize]/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified[:v_exit] && drivingCourseModified[end].s<csModified[:s_exit]) -> see below at the end of the while loop while cruisingReduction>=settings[:stepSize]/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified[:v_exit] && drivingCourseModified[end].s<csModified[:s_exit]) -> see below at the end of the while loop
# create a copy for the characteristic sections drivingCourse # create a copy for the characteristic sections drivingCourse
energySavingStartId=get(BSsOriginal, :cruising, BehaviorSection()).dataPoints[1] energySavingStartId=get(BSsOriginal, :cruising, Dict(:dataPoints=>[0]))[:dataPoints][1]
if energySavingStartId==0 if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !") error("ERROR at creating a new driving course for energy saving with coasting !")
end end
@ -130,21 +138,21 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
# calculating the new length of the cruising section # calculating the new length of the cruising section
if settings[:stepVariable]=="s in m" # distance step method if settings[:stepVariable]=="s in m" # distance step method
s_cruising = BSsOriginal[:cruising].length - cruisingReduction s_cruising = BSsOriginal[:cruising][:length] - cruisingReduction
elseif settings[:stepVariable]=="t in s" # time step method elseif settings[:stepVariable]=="t in s" # time step method
# 09/20 old: doesn't work for non constant cruising -> TODO: should work now # 09/20 old: doesn't work for non constant cruising -> TODO: should work now
# t_cruising=BSsOriginal[:cruising].t-cruisingReduction # t_cruising=BSsOriginal[:cruising][:t]-cruisingReduction
# s_cruising=t_cruising*drivingCourseModified[end].v # s_cruising=t_cruising*drivingCourseModified[end].v
distanceReduction = drivingCourse(BSsOriginal[:cruising].dataPoints[end]).v*cruisingReduction distanceReduction = drivingCourse[BSsOriginal[:cruising][:dataPoints][end]].v*cruisingReduction
s_cruising = BSsOriginal[:cruising].length-distanceReduction s_cruising = BSsOriginal[:cruising][:length]-distanceReduction
elseif settings[:stepVariable]=="v in m/s" # velocity step method elseif settings[:stepVariable]=="v in m/s" # velocity step method
s_cruising=BSsOriginal[:cruising].length-cruisingReduction*10 # TODO: or better: *100 ? s_cruising=BSsOriginal[:cruising][:length]-cruisingReduction*10 # TODO: or better: *100 ?
end #if end #if
s_cruising=max(0.0, s_cruising) s_cruising=max(0.0, s_cruising)
# copy csOriginal to csModified # copy csOriginal to csModified
# 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 #TODO after removing the mutable structs: Is it possible to just "copy"? with some changes
csModified=Dict(:id => csOriginal[:id], # identifier csModified=Dict(:id => csOriginal[:id], # identifier
:s_entry => csOriginal[:s_entry], # first position (in m) :s_entry => csOriginal[:s_entry], # first position (in m)
@ -161,28 +169,28 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi
BSsModified = csModified[:behaviorSections] BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree) if haskey(BSsOriginal, :breakFree)
breakFreeSection=BehaviorSection(BSsOriginal[:breakFree]) breakFreeSection=copyBehaviorSection(BSsOriginal[:breakFree])
merge!(BSsModified, Dict(:breakFree=>breakFreeSection)) merge!(BSsModified, Dict(:breakFree=>breakFreeSection))
csModified[:E] = csModified[:E] + BSsModified[:breakFree].E csModified[:E] = csModified[:E] + BSsModified[:breakFree][:E]
csModified[:t] = csModified[:t] + BSsModified[:breakFree].t csModified[:t] = csModified[:t] + BSsModified[:breakFree][:t]
end 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 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)) merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified[:E] = csModified[:E] + BSsModified[:clearing].E csModified[:E] = csModified[:E] + BSsModified[:clearing][:E]
csModified[:t] = csModified[:t] + BSsModified[:clearing].t csModified[:t] = csModified[:t] + BSsModified[:clearing][:t]
end end
if haskey(BSsOriginal, :acceleration) if haskey(BSsOriginal, :acceleration)
accelerationSection=BehaviorSection(BSsOriginal[:acceleration]) accelerationSection=copyBehaviorSection(BSsOriginal[:acceleration])
merge!(BSsModified, Dict(:acceleration=>accelerationSection)) merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + BSsModified[:acceleration].E csModified[:E] = csModified[:E] + BSsModified[:acceleration][:E]
csModified[:t] = csModified[:t] + BSsModified[:acceleration].t csModified[:t] = csModified[:t] + BSsModified[:acceleration][:t]
end end
if haskey(BSsOriginal, :diminishing) if haskey(BSsOriginal, :diminishing)
diminishingSection=BehaviorSection(BSsOriginal[:diminishing]) diminishingSection=copyBehaviorSection(BSsOriginal[:diminishing])
merge!(BSsModified, Dict(:diminishing=>diminishingSection)) merge!(BSsModified, Dict(:diminishing=>diminishingSection))
csModified[:E] = csModified[:E] + BSsModified[:diminishing].E csModified[:E] = csModified[:E] + BSsModified[:diminishing][:E]
csModified[:t] = csModified[:t] + BSsModified[:diminishing].t csModified[:t] = csModified[:t] + BSsModified[:diminishing][:t]
end 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. # TODO: At the moment diminishing is reduced like the acceleration in decreaseMaximumVelocity. To reduce code the methods for reducing cruising phase and reducing the diminishing phase can be combined in some parts.
# copy csOriginal to csModified # copy csOriginal to csModified
# 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 csModified=Dict(:id => csOriginal[:id], # identifier
:s_entry => csOriginal[:s_entry], # first position (in m) :s_entry => csOriginal[:s_entry], # first position (in m)
:s_exit => csOriginal[:s_exit], # last 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] BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree) if haskey(BSsOriginal, :breakFree)
breakFreeSection=BehaviorSection(BSsOriginal[:breakFree]) breakFreeSection=copyBehaviorSection(BSsOriginal[:breakFree])
merge!(BSsModified, Dict(:breakFree=>breakFreeSection)) merge!(BSsModified, Dict(:breakFree=>breakFreeSection))
csModified[:E] = csModified[:E] + BSsModified[:breakFree].E csModified[:E] = csModified[:E] + BSsModified[:breakFree][:E]
csModified[:t] = csModified[:t] + BSsModified[:breakFree].t csModified[:t] = csModified[:t] + BSsModified[:breakFree][:t]
end 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 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)) merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified[:E] = csModified[:E] + BSsModified[:clearing].E csModified[:E] = csModified[:E] + BSsModified[:clearing][:E]
csModified[:t] = csModified[:t] + BSsModified[:clearing].t csModified[:t] = csModified[:t] + BSsModified[:clearing][:t]
end end
if haskey(BSsOriginal, :acceleration) if haskey(BSsOriginal, :acceleration)
accelerationSection=BehaviorSection(BSsOriginal[:acceleration]) accelerationSection=copyBehaviorSection(BSsOriginal[:acceleration])
merge!(BSsModified, Dict(:acceleration=>accelerationSection)) merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + BSsModified[:acceleration].E csModified[:E] = csModified[:E] + BSsModified[:acceleration][:E]
csModified[:t] = csModified[:t] + BSsModified[:acceleration].t csModified[:t] = csModified[:t] + BSsModified[:acceleration][:t]
end end
if haskey(BSsOriginal, :cruising) if haskey(BSsOriginal, :cruising)
cruisingSection=BehaviorSection(BSsOriginal[:cruising]) cruisingSection=copyBehaviorSection(BSsOriginal[:cruising])
merge!(BSsModified, Dict(:cruising=>cruisingSection)) merge!(BSsModified, Dict(:cruising=>cruisingSection))
csModified[:E] = csModified[:E] + BSsModified[:cruising].E csModified[:E] = csModified[:E] + BSsModified[:cruising][:E]
csModified[:t] = csModified[:t] + BSsModified[:cruising].t csModified[:t] = csModified[:t] + BSsModified[:cruising][:t]
end end
diminishingSection=BehaviorSection(BSsOriginal[:diminishing]) diminishingSection=copyBehaviorSection(BSsOriginal[:diminishing])
if length(diminishingSection.dataPoints) > 2 if length(diminishingSection[:dataPoints]) > 2
# remove the last diminishing waypoint # remove the last diminishing waypoint
pop!(diminishingSection.dataPoints) pop!(diminishingSection[:dataPoints])
diminishingSection.v_exit=drivingCourse[diminishingSection.dataPoints[end]].v # exit speed (in m/s) 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[:s_exit]=drivingCourse[diminishingSection[:dataPoints][end]].s # last position (in m)
diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m) diminishingSection[:length]=diminishingSection[:s_exit]-diminishingSection[:s_entry] # total length (in m)
diminishingSection.t=drivingCourse[diminishingSection.dataPoints[end]].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s) diminishingSection[:t]=drivingCourse[diminishingSection[:dataPoints][end]].t-drivingCourse[diminishingSection[:dataPoints][1]].t # total running time (in s)
diminishingSection.E=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws) diminishingSection[:E]=drivingCourse[diminishingSection[:dataPoints][end]].E-drivingCourse[diminishingSection[:dataPoints][1]].E # total energy consumption (in Ws)
merge!(BSsModified, Dict(:diminishing => diminishingSection)) merge!(BSsModified, Dict(:diminishing => diminishingSection))
csModified[:E] = csModified[:E] + BSsModified[:diminishing].E csModified[:E] = csModified[:E] + BSsModified[:diminishing][:E]
csModified[:t] = csModified[:t] + BSsModified[:diminishing].t csModified[:t] = csModified[:t] + BSsModified[:diminishing][:t]
energySavingStartId=diminishingSection.dataPoints[end] energySavingStartId=diminishingSection[:dataPoints][end]
else else
# The diminishing section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section. # The diminishing section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section.
energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :diminishing, BehaviorSection())).dataPoints[1] energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :diminishing, Dict(:dataPoints =>[0])))[:dataPoints][1]
end end
# copy the driving course till the beginning of energy saving # 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) #function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
BSsOriginal = csOriginal[:behaviorSections] BSsOriginal = csOriginal[:behaviorSections]
if haskey(BSsOriginal, :acceleration) && csOriginal[:v_peak] > csOriginal[:v_entry] && csOriginal[:v_peak] > csOriginal[:v_exit] if haskey(BSsOriginal, :acceleration) && csOriginal[:v_peak] > csOriginal[:v_entry] && csOriginal[:v_peak] > csOriginal[:v_exit]
accelerationSection = BehaviorSection(BSsOriginal[:acceleration]) accelerationSection = copyBehaviorSection(BSsOriginal[:acceleration])
if drivingCourse[accelerationSection.dataPoints[end]-1].v < csOriginal[:v_exit] 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? # 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) return (csOriginal, drivingCourse, false)
# TODO: or calculate a new acceleration phase with v_exit as v_peak? it will be very short, shorter than the step size. # TODO: or calculate a new acceleration phase with v_exit as v_peak? it will be very short, shorter than the step size.
end end
# copy csOriginal to csModified # copy csOriginal to csModified
# 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 csModified=Dict(:id => csOriginal[:id], # identifier
:s_entry => csOriginal[:s_entry], # first position (in m) :s_entry => csOriginal[:s_entry], # first position (in m)
:s_exit => csOriginal[:s_exit], # last 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) :v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s)
BSsModified = csModified[:behaviorSections] BSsModified = csModified[:behaviorSections]
if haskey(BSsOriginal, :breakFree) if haskey(BSsOriginal, :breakFree)
breakFreeSection=BehaviorSection(BSsOriginal[:breakFree]) breakFreeSection=copyBehaviorSection(BSsOriginal[:breakFree])
merge!(BSsModified, Dict(:breakFree=>breakFreeSection)) merge!(BSsModified, Dict(:breakFree=>breakFreeSection))
csModified[:E] = csModified[:E] + BSsModified[:breakFree].E csModified[:E] = csModified[:E] + BSsModified[:breakFree][:E]
csModified[:t] = csModified[:t] + BSsModified[:breakFree].t csModified[:t] = csModified[:t] + BSsModified[:breakFree][:t]
end 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) if haskey(BSsOriginal, :clearing)
clearingSection=BehaviorSection(BSsOriginal[:clearing]) clearingSection=copyBehaviorSection(BSsOriginal[:clearing])
merge!(BSsModified, Dict(:clearing=>clearingSection)) merge!(BSsModified, Dict(:clearing=>clearingSection))
csModified[:E] = csModified[:E] + BSsModified[:clearing].E csModified[:E] = csModified[:E] + BSsModified[:clearing][:E]
csModified[:t] = csModified[:t] + BSsModified[:clearing].t csModified[:t] = csModified[:t] + BSsModified[:clearing][:t]
end end
# remove the last acceleration waypoint # 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[: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[:s_exit]=drivingCourse[accelerationSection[:dataPoints][end]].s # last position (in m)
accelerationSection.length=accelerationSection.s_exit-accelerationSection.s_entry # total length (in m) accelerationSection[:length]=accelerationSection[:s_exit]-accelerationSection[:s_entry] # total length (in m)
accelerationSection.t=drivingCourse[accelerationSection.dataPoints[end]].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) accelerationSection[:t]=drivingCourse[accelerationSection[:dataPoints][end]].t-drivingCourse[accelerationSection[:dataPoints][1]].t # total running time (in s)
accelerationSection.E=drivingCourse[accelerationSection.dataPoints[end]].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws) accelerationSection[:E]=drivingCourse[accelerationSection[:dataPoints][end]].E-drivingCourse[accelerationSection[:dataPoints][1]].E # total energy consumption (in Ws)
merge!(BSsModified, Dict(:acceleration=>accelerationSection)) merge!(BSsModified, Dict(:acceleration=>accelerationSection))
csModified[:E] = csModified[:E] + BSsModified[:acceleration].E csModified[:E] = csModified[:E] + BSsModified[:acceleration][:E]
csModified[:t] = csModified[:t] + BSsModified[:acceleration].t csModified[:t] = csModified[:t] + BSsModified[:acceleration][:t]
energySavingStartId=accelerationSection.dataPoints[end] energySavingStartId=accelerationSection[:dataPoints][end]
else else
# The acceleration section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section. # The acceleration section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section.
energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :acceleration, BehaviorSection())).dataPoints[1] energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0])))[:dataPoints][1]
end end
# TODO: should v_peak be reduced or is it enough to pop the data points? # TODO: should v_peak be reduced or is it enough to pop the data points?
# 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 # copy the drivingCourse till the beginning of energy saving
drivingCourseModified=Vector{DataPoint}() 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) function combineEnergySavingMethods(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat)
BSsOriginal = csOriginal[:behaviorSections] 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)) && 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) # 12/28 old: csCombined=CharacteristicSection(csOriginal)
#TODO after removing the mutable structs: Is it possible to just "copy"? #TODO after removing the mutable structs: Is it possible to just "copy"?
csCombined=Dict(:id => csOriginal[:id], # identifier 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] allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for bs in 1: length(allBs) for bs in 1: length(allBs)
if haskey(BSsOriginal, allBs[bs]) 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 #if
end #for end #for

View File

@ -5,6 +5,8 @@ using ..types
export readInput 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. 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 id=1 # trains identifier
if haskey(data["train"],"trainType") 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") # @enum trainType passenger=1 freight=2 motorCoachTrain=3
trainType=data["train"]["trainType"] # "passenger" or "freight" or "motor coach train" 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") delete!(data["train"], "trainType")
else 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 end
else 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 end
if haskey(data["train"],"l_train") 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) # 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) # 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" if trainType=="passenger" || trainType=="motor coach train"
Δv_w=15.0/3.6 Δv_w=15.0/3.6
elseif trainType== "freight" elseif trainType== "freight"
Δv_w=0.0 Δv_w=0.0
end # if end # if
=#
# coefficient for basic resistance of the set of wagons (consist) (in ‰) # coefficient for basic resistance of the set of wagons (consist) (in ‰)
if haskey(data["train"],"f_Rw0") && data["train"]["f_Rw0"]!=nothing if haskey(data["train"],"f_Rw0") && data["train"]["f_Rw0"]!=nothing
@ -316,8 +334,9 @@ function inputTrain(trainDirectory::String)
# create the train Dictionary # create the train Dictionary
train= Dict(:name => name, # train's name train= Dict(:name => name, # train's name
:id => id, # train's identifier :id => id, # train's identifier
:trainType => trainType, # type of train "passenger" or "freight" or "motor coach train" :type => type, # type of train "passenger" or "freight" or "motorCoachTrain"
:trainLength => trainLength,# total length (in m) #= 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) :v_limit => v_limit, # trains speed limit (in m/s)
:a_braking => a_braking, # braking acceleration (in m/s^2) :a_braking => a_braking, # braking acceleration (in m/s^2)
:m_train => m_train, # total mass (in kg) :m_train => m_train, # total mass (in kg)
@ -651,13 +670,13 @@ But only if the string matches an enumerated value.
# Example # Example
```jldoctest ```jldoctest
julia> @enum trainTypes passenger freight julia> @enum trainType passenger freight
julia> myTrain = "passenger" julia> myTrain = "passenger"
"passenger" "passenger"
julia> myTrainType = getEnum(myTrain, trainTypes) julia> myTrainType = getEnum(myTrain, trainType)
passenger::trainTypes = 0 passenger::trainType = 0
``` ```
""" """
function getEnum(string::String, enum_type::DataType) 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] while s<CSs[id][:s_entry]
id=id-1 id=id-1
if id==0 if id==0
println("s=",s," MS.s_entry=",CSs[1].s_entry) println("s=",s," MS[:s_entry]=",CSs[1][:s_entry])
end end
end #while 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 ‰ pathResistance=CSs[id][:r_path]/1000*train[:m_train]*g # /1000 because of the unit ‰
elseif massModel=="homogeneous strip" elseif massModel=="homogeneous strip"
pathResistance=0.0 pathResistance=0.0
while id>0 && s-train[:trainLength]<CSs[id][:s_exit] while id>0 && s-train[:length]<CSs[id][:s_exit]
pathResistance=pathResistance+(min(s, CSs[id][:s_exit])-max(s-train[:trainLength], CSs[id][:s_entry]))/train[:trainLength]*(CSs[id][:r_path]/1000*train[:m_train]*g) # /1000 because of the unit ‰ pathResistance=pathResistance+(min(s, CSs[id][:s_exit])-max(s-train[:length], CSs[id][:s_entry]))/train[:length]*(CSs[id][:r_path]/1000*train[:m_train]*g) # /1000 because of the unit ‰
id=id-1 id=id-1
if id==0 if id==0
# TODO: currently for values < movingSection[:s_entry] the values of movingSection[:s_entry] will be used # TODO: currently for values < movingSection[:s_entry] the values of movingSection[:s_entry] will be used
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 #if
end #while end #while
else else
@ -209,25 +209,25 @@ function detectFormerSpeedLimits(CSs::Vector{Dict}, csWithTrainHeadId::Integer,
return formerSpeedLimits return formerSpeedLimits
end # function detectFormerSpeedLimits end # function detectFormerSpeedLimits
function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits, 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::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::Dict)
# would work: function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Any,1}, accelerationSection::BehaviorSection) # would work: function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Any,1}, accelerationSection::Dict)
if length(formerSpeedLimits) > 0 if length(formerSpeedLimits) > 0
# if a former speed limit has been exceeded the acceleration steps of this CS will be removed and a clearing phase will be inserted before acceleration # if a former speed limit has been exceeded the acceleration steps of this CS will be removed and a clearing phase will be inserted before acceleration
if drivingCourse[end].v > formerSpeedLimits[end][2] if drivingCourse[end].v > formerSpeedLimits[end][2]
while drivingCourse[end].s > get(CS[:behaviorSections], :clearing, accelerationSection).s_entry while drivingCourse[end].s > get(CS[:behaviorSections], :clearing, accelerationSection)[:s_entry]
pop!(drivingCourse) pop!(drivingCourse)
end end
if haskey(CS[:behaviorSections], :clearing) if haskey(CS[:behaviorSections], :clearing)
CS[:t] = CS[:t]-CS[:behaviorSections][:clearing].t # reducing the total running time (in s) CS[:t] = CS[:t]-CS[:behaviorSections][:clearing][:t] # reducing the total running time (in s)
CS[:E] = CS[:E]-CS[:behaviorSections][:clearing].E # reducing the total energy consumption (in Ws) CS[:E] = CS[:E]-CS[:behaviorSections][:clearing][:E] # reducing the total energy consumption (in Ws)
delete!(CS[:behaviorSections], :clearing) delete!(CS[:behaviorSections], :clearing)
end end
# create a (new and longer) clearing section # create a (new and longer) clearing section
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
s_clearing=min(CS[:s_exit]-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:trainLength])) s_clearing=min(CS[:s_exit]-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:length]))
if s_clearing>0.0 if s_clearing>0.0
(CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing")
@ -238,19 +238,14 @@ function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint},
# 09/22: if drivingCourse[end].s < CS[:s_exit] # 09/22: if drivingCourse[end].s < CS[:s_exit]
if drivingCourse[end].s < CS[:s_exit]-s_braking if drivingCourse[end].s < CS[:s_exit]-s_braking
# reset the accelerationSection # reset the accelerationSection
accelerationSection=BehaviorSection() accelerationSection = createBehaviorSection("acceleration", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
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
else else
return (CS, drivingCourse, formerSpeedLimits, accelerationSection, true) return (CS, drivingCourse, formerSpeedLimits, accelerationSection, true)
end end
end end
# remove former speed limits of characteristic sections the train has left during the last step from the list # 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) pop!(formerSpeedLimits)
end end
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 # 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}) function addBreakFreePhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end].v==0.0 && drivingCourse[end].s<CS[:s_exit] if drivingCourse[end].v==0.0 && drivingCourse[end].s<CS[:s_exit]
breakFreeSection=BehaviorSection() BS = createBehaviorSection("breakFree", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
breakFreeSection.type="breakFree" # type of behavior section drivingCourse[end].behavior = BS[:type]
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
drivingCourse[end].behavior = breakFreeSection.type
# traction effort and resisting forces (in N): # 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 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 # creating the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], settings[:stepSize], CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], settings[:stepSize], CS[:id]))
drivingCourse[end].behavior = breakFreeSection.type drivingCourse[end].behavior = 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: #= 07/30 TODO: the calculation is easier with these lines because the values that are 0 in the first step are not used in calculation but all in all the code gets easier without these lines:
push!(drivingCourse, DataPoint()) push!(drivingCourse, DataPoint())
drivingCourse[end].i=drivingCourse[end-1].i+1 # incrementing the number of the data point 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].ΔW # energy consumption in this step (in Ws)
drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws) drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws)
=# =#
push!(breakFreeSection.dataPoints, drivingCourse[end].i) push!(BS[:dataPoints], drivingCourse[end].i)
# calculate the accumulated breakFree section information # calculate the accumulated breakFree section information
breakFreeSection.s_exit=drivingCourse[end].s # last position (in m) merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
breakFreeSection.length=breakFreeSection.s_exit-breakFreeSection.s_entry # total length (in m) :s_exit => drivingCourse[end].s, # last position (in m)
breakFreeSection.v_exit=drivingCourse[end].v # exit speed (in m/s) :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
breakFreeSection.t=drivingCourse[end].t-drivingCourse[breakFreeSection.dataPoints[1]].t # total running time (in s) :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
breakFreeSection.E=drivingCourse[end].E-drivingCourse[breakFreeSection.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[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+breakFreeSection.E # total energy consumption (in Ws) 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 end # else: return the characteristic section without a breakFree section
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addBreakFreePhase! end #function addBreakFreePhase!
@ -343,7 +334,7 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, setti
end end
# if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept # if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:trainLength]) formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:length])
# conditions for acceleration phase # conditions for acceleration phase
targetSpeedReached = drivingCourse[end].v >= CS[:v_peak] 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 # use the conditions for the acceleration phase
if !targetSpeedReached && !trainAtEnd && tractionSurplus if !targetSpeedReached && !trainAtEnd && tractionSurplus
#11/23 long version: if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s <CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R #11/23 long version: if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s <CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R
accelerationSection=BehaviorSection() BS = createBehaviorSection("acceleration", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
accelerationSection.type="acceleration" # type of behavior section drivingCourse[end].behavior = BS[:type]
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
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 for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while drivingCourse[end].v<CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R while drivingCourse[end].v<CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
# 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) # 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
# create the next data point # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = accelerationSection.type drivingCourse[end].behavior = BS[:type]
push!(accelerationSection.dataPoints, drivingCourse[end].i) push!(BS[:dataPoints], drivingCourse[end].i)
# calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) # 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 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 if endOfCsReached
return (CS, drivingCourse) return (CS, drivingCourse)
end #if 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 end #if
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
end #while end #while
# check which limit was reached and adjust the currentStepSize for the next cycle # check which limit was reached and adjust the currentStepSize for the next cycle
@ -418,24 +405,24 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, setti
end end
# delete last data point for recalculating the last step with reduced step size # delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
pop!(accelerationSection.dataPoints) pop!(BS[:dataPoints])
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
# push!(accelerationSection.dataPoints, drivingCourse[end].i) # push!(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.", error("ERROR: The train stops during the acceleration phase in CS",CS[:id]," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.") " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.")
elseif drivingCourse[end].v>CS[:v_peak] elseif drivingCourse[end].v>CS[:v_peak]
pop!(drivingCourse) pop!(drivingCourse)
pop!(accelerationSection.dataPoints) pop!(BS[:dataPoints])
elseif drivingCourse[end].s>CS[:s_exit] elseif drivingCourse[end].s>CS[:s_exit]
drivingCourse[end].s=CS[:s_exit] # rounding s down to s_exit drivingCourse[end].s=CS[:s_exit] # rounding s down to s_exit
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
(CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
else else
@ -443,22 +430,23 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, setti
end end
end #for 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 # calculate the accumulated acceleration section information
accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s) merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
accelerationSection.s_exit=drivingCourse[end].s # last position (in m) :s_exit => drivingCourse[end].s, # last position (in m)
accelerationSection.length=accelerationSection.s_exit-accelerationSection.s_entry # total length (in m) :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
accelerationSection.t=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
accelerationSection.E=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws) :v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
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)
# TODO: this warning schould not be needed. just for testing # TODO: this warning schould not be needed. just for testing
if CS[:v_peak] < drivingCourse[end].v if CS[:v_peak] < drivingCourse[end].v
println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_peak=",CS[:v_peak]) println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_peak=",CS[:v_peak])
end end
merge!(CS[:behaviorSections], Dict(:acceleration=>accelerationSection)) merge!(CS[:behaviorSections], Dict(:acceleration=>BS))
end end
end # else: just return the given data point number without changes due to the acceleration phase end # else: just return the given data point number without changes due to the acceleration phase
@ -479,25 +467,21 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP
end end
# if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept # if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:trainLength]) formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:length])
# 11/23 old without F_T>F_R: if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] # 11/23 old without F_T>F_R: if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s<CS[:s_exit]
if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R
accelerationSection=BehaviorSection() BS = createBehaviorSection("acceleration", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
accelerationSection.type="acceleration" # type of behavior section drivingCourse[end].behavior = BS[:type]
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
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 for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
while drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s+s_braking<CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend while drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s+s_braking<CS[:s_exit] && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend
# 12/03 old with v>0 while drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s+s_braking<CS[:s_exit] && drivingCourse[end].v>0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend # 12/03 old with v>0 while drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s+s_braking<CS[:s_exit] && drivingCourse[end].v>0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) #11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
@ -507,17 +491,17 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP
# create the next data point # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = accelerationSection.type drivingCourse[end].behavior = BS[:type]
push!(accelerationSection.dataPoints, drivingCourse[end].i) push!(BS[:dataPoints], drivingCourse[end].i)
# 12/03: was moved behind considerFormerSpeedLimits: calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) # 12/03: was moved behind considerFormerSpeedLimits: calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, 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 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 if endOfCsReached
return (CS, drivingCourse) return (CS, drivingCourse)
end end
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)) s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
end #while end #while
@ -550,25 +534,25 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP
end end
# delete last data point for recalculating the last step with reduced step size # delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
pop!(accelerationSection.dataPoints) pop!(BS[:dataPoints])
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
# push!(accelerationSection.dataPoints, drivingCourse[end].i) # push!(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.", error("ERROR: The train stops during the acceleration phase in CS",CS[:id]," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.") " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.")
elseif drivingCourse[end].v>CS[:v_peak] elseif drivingCourse[end].v>CS[:v_peak]
pop!(drivingCourse) pop!(drivingCourse)
pop!(accelerationSection.dataPoints) pop!(BS[:dataPoints])
elseif drivingCourse[end].s + s_braking > CS[:s_exit] elseif drivingCourse[end].s + s_braking > CS[:s_exit]
pop!(drivingCourse) pop!(drivingCourse)
pop!(accelerationSection.dataPoints) pop!(BS[:dataPoints])
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
(CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
else else
@ -576,19 +560,19 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP
end end
end #for 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 # calculate the accumulated acceleration section information
accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s) merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
accelerationSection.s_exit=drivingCourse[end].s # last position (in m) :s_exit => drivingCourse[end].s, # last position (in m)
accelerationSection.length=accelerationSection.s_exit-accelerationSection.s_entry # total length (in m) :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
accelerationSection.t=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
accelerationSection.E=drivingCourse[end].E-drivingCourse[accelerationSection.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[:v_peak]=max(drivingCourse[end].v, CS[:v_entry]) # setting v_peak to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances
CS[:t]=CS[:t]+accelerationSection.t # total running time (in s) CS[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+accelerationSection.E # total energy consumption (in Ws) 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
end # else: just return the given data point number without changes due to the acceleration phase end # else: just return the given data point number without changes due to the acceleration phase
return (CS, drivingCourse) return (CS, drivingCourse)
@ -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. # 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) function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruising::Real, settings::Dict, train::Dict, CSs::Vector{Dict}, cruisingType::String)
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"? calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")
if drivingCourse[end].F_T < drivingCourse[end].F_R if drivingCourse[end].F_T < drivingCourse[end].F_R
(CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) (CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")) drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising"))
s_cruising = max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, BehaviorSection()).length) s_cruising = max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, Dict(:length=>0.0))[:length])
end end
if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] && drivingCourse[end].F_T >= drivingCourse[end].F_R if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] && drivingCourse[end].F_T >= drivingCourse[end].F_R
# 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] # 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit]
cruisingSection=BehaviorSection() BS = createBehaviorSection(cruisingType, drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
cruisingSection.type=cruisingType # type of behavior section drivingCourse[end].behavior = BS[:type]
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
# TODO: necessary? # 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) # 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")) # 11/05 old: drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising"))
if settings[:massModel]=="homogeneous strip" && CS[:id] > 1 if settings[:massModel]=="homogeneous strip" && CS[:id] > 1
currentStepSize=settings[:stepSize] currentStepSize=settings[:stepSize]
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
while drivingCourse[end].s < CS[:s_entry] + train[:trainLength] && drivingCourse[end].s<cruisingSection.s_entry+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] while drivingCourse[end].s < CS[:s_entry] + train[: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[: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[: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 # the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_peak OR the mass model homogeneous strip is used and parts of the train are still in former CS
#TODO: maybe just consider former CS with different path resistance? #TODO: maybe just consider former CS with different path resistance?
#TODO: what about the case: After leaving a former CS with steep gradient the train can accelerate. Now in this tool the train will cruise at v_i. Just accelerating until v_peak could make problems for energy saving by shortening the acceleration phase #TODO: what about the case: After leaving a former CS with steep gradient the train can accelerate. Now in this tool the train will cruise at v_i. Just accelerating until v_peak could make problems for energy saving by shortening the acceleration phase
@ -639,15 +618,10 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruisin
if settings[:stepVariable]=="s in m" if settings[:stepVariable]=="s in m"
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", currentStepSize, CS[:id]))
else else
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train[:trainLength]/(10.0^cycle), CS[:id])) # TODO which step size should be used? push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train[:length]/(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)
end end
drivingCourse[end].behavior = BS[:type]
push!(BS[:dataPoints], drivingCourse[end].i)
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") 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 # check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1 if cycle < approximationLevel+1
if drivingCourse[end].s>cruisingSection.s_entry+s_cruising # TODO also the following? drivingCourse[end].s > CSs[CS[:id]].s_entry + train[:trainLength])) if drivingCourse[end].s>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" 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 else
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
end end
elseif drivingCourse[end].s==cruisingSection.s_entry+s_cruising # || drivingCourse[end].s==CS[:s_exit] elseif drivingCourse[end].s==BS[:s_entry]+s_cruising # || drivingCourse[end].s==CS[:s_exit]
break break
elseif drivingCourse[end].F_T < drivingCourse[end].F_R elseif drivingCourse[end].F_T < drivingCourse[end].F_R
# if settings[:stepVariable] == "s in m" # if settings[:stepVariable] == "s in m"
# currentStepSize=cruisingSection.s_entry+s_cruising-drivingCourse[end-1].s # currentStepSize=BS[:s_entry]+s_cruising-drivingCourse[end-1].s
# else # else
currentStepSize = settings[:stepSize] / 10.0^cycle currentStepSize = settings[:stepSize] / 10.0^cycle
# end # end
elseif drivingCourse[end].s >= CS[: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[:trainLength] # TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS[:id]][:s_entry] + train[:length]
break break
else # TODO copied from addAccelerationPhase -> probably not needed here !? else # TODO copied from addAccelerationPhase -> probably not needed here !?
error("ERROR at cruising phase: With the step variable ",settings[:stepVariable]," the while loop will be left although the if cases don't apply in CS",CS[:id]," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") error("ERROR at cruising phase: With the step variable ",settings[:stepVariable]," the while loop will be left although the if cases don't apply in CS",CS[:id]," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
@ -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 # delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
pop!(cruisingSection.dataPoints) pop!(BS[:dataPoints])
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end].s>cruisingSection.s_entry+s_cruising if drivingCourse[end].s>BS[:s_entry]+s_cruising
if cruisingSection.type == "clearing" if BS[:type] == "clearing"
else else
pop!(drivingCourse) pop!(drivingCourse)
pop!(cruisingSection.dataPoints) pop!(BS[:dataPoints])
end end
# 11/21 |-> # 11/21 |->
elseif drivingCourse[end].s==cruisingSection.s_entry+s_cruising elseif drivingCourse[end].s==BS[:s_entry]+s_cruising
break break
# 11/21 ->| # 11/21 ->|
elseif drivingCourse[end].F_T < drivingCourse[end].F_R 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) (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")
# s_cruising=max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, BehaviorSection()).length) # s_cruising=max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, Dict(length=>0.0))[:length])
else else
@ -706,30 +680,30 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruisin
end #if 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 # 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<BS[: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 && drivingCourse[end].F_T >= drivingCourse[end].F_R
drivingCourse[end].a=0.0 # acceleration (in m/s^2) drivingCourse[end].a=0.0 # acceleration (in m/s^2)
# calculate the remaining cruising way # 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 # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS[:id]))
drivingCourse[end].behavior = cruisingSection.type drivingCourse[end].behavior = BS[:type]
push!(cruisingSection.dataPoints, drivingCourse[end].i) push!(BS[:dataPoints], drivingCourse[end].i)
end end
# calculate the accumulated cruising section information # calculate the accumulated cruising section information
cruisingSection.v_exit=drivingCourse[end].v # exit speed (in m/s) merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
cruisingSection.s_exit=drivingCourse[end].s # last position (in m) :s_exit => drivingCourse[end].s, # last position (in m)
cruisingSection.length=cruisingSection.s_exit-cruisingSection.s_entry # total length (in m) :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
cruisingSection.t=drivingCourse[end].t-drivingCourse[cruisingSection.dataPoints[1]].t # total running time (in s) :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
cruisingSection.E=drivingCourse[end].E-drivingCourse[cruisingSection.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[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+cruisingSection.E # total energy consumption (in Ws) 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 end # else: return the characteristic section without a cruising section
return (CS, drivingCourse) return (CS, drivingCourse)
@ -741,21 +715,16 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settin
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing") calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing")
if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s<CS[:s_exit] if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s<CS[:s_exit]
#drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s<CS[:s_exit] BS = createBehaviorSection("diminishing", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
diminishingSection=BehaviorSection() drivingCourse[end].behavior = BS[:type]
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
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 for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel))
while drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].s+s_braking<CS[:s_exit] && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend while drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].s+s_braking<CS[:s_exit] && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
# 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking<CS[:s_exit] && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend # 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking<CS[:s_exit] && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
#11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type) #11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
@ -766,11 +735,11 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settin
# create the next data point # create the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = diminishingSection.type drivingCourse[end].behavior = BS[:type]
push!(diminishingSection.dataPoints, drivingCourse[end].i) 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)) 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 end #while
# check which limit was reached and adjust the currentStepSize for the next cycle # check which limit was reached and adjust the currentStepSize for the next cycle
@ -793,18 +762,18 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settin
end end
# delete last data point for recalculating the last step with reduced step size # delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
pop!(diminishingSection.dataPoints) pop!(BS[:dataPoints])
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
# push!(diminishingSection.dataPoints, drivingCourse[end].i) # push!(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.", error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.") " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.")
elseif drivingCourse[end].s + s_braking > CS[:s_exit] elseif drivingCourse[end].s + s_braking > CS[:s_exit]
pop!(drivingCourse) pop!(drivingCourse)
pop!(diminishingSection.dataPoints) pop!(BS[:dataPoints])
elseif drivingCourse[end].F_T > drivingCourse[end].F_R elseif drivingCourse[end].F_T > drivingCourse[end].F_R
break break
@ -815,17 +784,18 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settin
end end
end #for 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 # calculate the accumulated diminishing section information
diminishingSection.v_exit=drivingCourse[end].v # exit speed (in m/s) merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
diminishingSection.s_exit=drivingCourse[end].s # last position (in m) :s_exit => drivingCourse[end].s, # last position (in m)
diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m) :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
diminishingSection.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s) :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws) :v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
CS[:t]=CS[:t]+diminishingSection.t # total running time (in s)
CS[:E]=CS[:E]+diminishingSection.E # total energy consumption (in Ws)
merge!(CS[:behaviorSections], Dict(:diminishing=>diminishingSection)) 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
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 # 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}) function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
## if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept ## if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
#formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:trainLength]) #formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:length])
if drivingCourse[end].v>CS[:v_exit] && drivingCourse[end].s<CS[:s_exit] if drivingCourse[end].v>CS[:v_exit] && drivingCourse[end].s<CS[:s_exit]
coastingSection=BehaviorSection() BS = createBehaviorSection("coasting", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
coastingSection.type="coasting" # type of behavior section drivingCourse[end].behavior = BS[:type]
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
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 # 08/24 old for cycle in 1:3 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel) s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)
while drivingCourse[end].v>CS[:v_exit] && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s + s_braking < CS[:s_exit] # as long as s_i + s_braking < s_CSend while drivingCourse[end].v>CS[:v_exit] && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s + s_braking < CS[:s_exit] # as long as s_i + s_braking < s_CSend
# traction effort and resisting forces (in N): # traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, coastingSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
# creating the next data point # creating the next data point
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = coastingSection.type drivingCourse[end].behavior = BS[:type]
push!(coastingSection.dataPoints, drivingCourse[end].i) push!(BS[:dataPoints], drivingCourse[end].i)
s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking]) s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking])
@ -894,7 +860,7 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint
end end
# delete last data point for recalculating the last step with reduced step size # delete last data point for recalculating the last step with reduced step size
pop!(drivingCourse) pop!(drivingCourse)
pop!(coastingSection.dataPoints) pop!(BS[:dataPoints])
else # if the level of approximation is reached else # if the level of approximation is reached
if drivingCourse[end].v<=0.0 if drivingCourse[end].v<=0.0
@ -905,7 +871,7 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint
elseif drivingCourse[end].s + s_braking > CS[:s_exit] elseif drivingCourse[end].s + s_braking > CS[:s_exit]
# delete last data point because it went to far # delete last data point because it went to far
pop!(drivingCourse) pop!(drivingCourse)
pop!(coastingSection.dataPoints) pop!(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 elseif drivingCourse[end].v > CS[:v_peak] # if the train gets to fast it has to brake # TODO: if accelereation and coasting functions will be combined this case is different for coasting and also the order of if cases is different
# while coasting the train brakes to hold v_peak (only one data point in the end of coasting is calculated like cruising at v_peak) # while coasting the train brakes to hold v_peak (only one data point in the end of coasting is calculated like cruising at v_peak)
@ -937,16 +903,16 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint
end #for end #for
# calculate the accumulated coasting section information # calculate the accumulated coasting section information
coastingSection.v_exit=drivingCourse[end].v # exit speed (in m/s) merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
coastingSection.s_exit=drivingCourse[end].s # last position (in m) :s_exit => drivingCourse[end].s, # last position (in m)
coastingSection.length=coastingSection.s_exit-coastingSection.s_entry # total length (in m) :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
coastingSection.t=drivingCourse[end].t-drivingCourse[coastingSection.dataPoints[1]].t # total running time (in s) :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
coastingSection.E=drivingCourse[end].E-drivingCourse[coastingSection.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[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+coastingSection.E # total energy consumption (in Ws) 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 end ## else: just return the given data point number without changes due to the coasting phase
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addCoastingPhaseUntilBraking! end #function addCoastingPhaseUntilBraking!
@ -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}, 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) # function addBrakingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, massModel::String, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat)
if drivingCourse[end].v>CS[:v_exit] && drivingCourse[end].s<CS[:s_exit] if drivingCourse[end].v>CS[:v_exit] && drivingCourse[end].s<CS[:s_exit]
brakingSection=BehaviorSection() BS = createBehaviorSection("braking", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
brakingSection.type="braking" # type of behavior section BS[:s_exit]=CS[:s_exit] # last position (in m)
brakingSection.s_entry=drivingCourse[end].s # first position (in m) drivingCourse[end].behavior = BS[:type]
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
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, brakingSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
push!(drivingCourse, DataPoint()) push!(drivingCourse, DataPoint())
drivingCourse[end].i = drivingCourse[end-1].i+1 # incrementing the number of the data point drivingCourse[end].i = drivingCourse[end-1].i+1 # incrementing the number of the data point
drivingCourse[end].behavior = brakingSection.type drivingCourse[end].behavior = BS[:type]
push!(brakingSection.dataPoints, drivingCourse[end].i) # refering from the breaking section to the last of its data points push!(BS[:dataPoints], drivingCourse[end].i) # refering from the breaking section to the last of its data points
# calculate s, t, v # 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].v=CS[:v_exit] # velocity (in m/s)
drivingCourse[end].Δs=drivingCourse[end].s-drivingCourse[end-1].s # step size (in m) drivingCourse[end].Δs=drivingCourse[end].s-drivingCourse[end-1].s # step size (in m)
drivingCourse[end].Δv=drivingCourse[end].v-drivingCourse[end-1].v # step size (in m/s) drivingCourse[end].Δv=drivingCourse[end].v-drivingCourse[end-1].v # step size (in m/s)
@ -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].ΔW # energy consumption in this step (in Ws)
drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws) drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws)
brakingSection.v_exit=drivingCourse[end].v # exit speed (in m/s) merge!(BS, Dict(:length => drivingCourse[end].Δs, # total length (in m)
brakingSection.length=drivingCourse[end].Δs # total length (in m) #:s_exit => drivingCourse[end].s, # last position (in m)
brakingSection.t=drivingCourse[end].Δt # total running time (in s) :t => drivingCourse[end].Δt, # total running time (in s)
brakingSection.E=drivingCourse[end].ΔE # total energy consumption (in Ws) :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[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+brakingSection.E # total energy consumption (in Ws) 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 end # else: return the characteristic section without a braking section
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addBrakingPhase! 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. # 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) function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat)
if drivingCourse[end].v > CS[:v_exit] && drivingCourse[end].s < CS[:s_exit] if drivingCourse[end].v > CS[:v_exit] && drivingCourse[end].s < CS[:s_exit]
brakingSection=BehaviorSection() BS = createBehaviorSection("braking", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
brakingSection.type="braking" # type of behavior section drivingCourse[end].behavior = BS[:type]
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
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 velocityIsPositive=true
while drivingCourse[end].v > CS[:v_exit] && drivingCourse[end].s < CS[:s_exit] && velocityIsPositive while drivingCourse[end].v > CS[:v_exit] && drivingCourse[end].s < CS[:s_exit] && velocityIsPositive
# traction effort and resisting forces (in N): # traction effort and resisting forces (in N):
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, brakingSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
# acceleration (in m/s^2): # acceleration (in m/s^2):
drivingCourse[end].a=train[:a_braking] drivingCourse[end].a=train[:a_braking]
@ -1041,8 +1000,8 @@ function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{DataPoint}, se
end end
end end
push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id]))
drivingCourse[end].behavior = brakingSection.type drivingCourse[end].behavior = BS[:type]
push!(brakingSection.dataPoints, drivingCourse[end].i) push!(BS[:dataPoints], drivingCourse[end].i)
# s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking]) # s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking])
end # while end # while
@ -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=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) 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 # if drivingCourse[end-1].a<train[:a_braking] || drivingCourse[end-1].a>=0.0
# println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1].a ," > ",train[:a_braking]) # println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1].a ," > ",train[:a_braking])
@ -1075,16 +1033,16 @@ function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{DataPoint}, se
end end
# calculate the accumulated coasting section information # calculate the accumulated coasting section information
brakingSection.v_exit=drivingCourse[end].v # exit speed (in m/s) merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m)
brakingSection.s_exit=drivingCourse[end].s # last position (in m) :s_exit => drivingCourse[end].s, # last position (in m)
brakingSection.length=brakingSection.s_exit-brakingSection.s_entry # total length (in m) :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s)
brakingSection.t=drivingCourse[end].t-drivingCourse[brakingSection.dataPoints[1]].t # total running time (in s) :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws)
brakingSection.E=drivingCourse[end].E-drivingCourse[brakingSection.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[:t]=CS[:t]+BS[:t] # total running time (in s)
CS[:E]=CS[:E]+brakingSection.E # total energy consumption (in Ws) 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 end # else: return the characteristic section without a braking section
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addBrakingPhaseStepwise! end #function addBrakingPhaseStepwise!
@ -1095,26 +1053,34 @@ end #function addBrakingPhaseStepwise!
function addStandstill!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) function addStandstill!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict})
if drivingCourse[end].v == 0.0 if drivingCourse[end].v == 0.0
standstillSection=BehaviorSection() BS = createBehaviorSection("standstill", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i)
standstillSection.type="standstill" # type of behavior section merge!(BS, Dict(:length => 0.0, # total length (in m)
standstillSection.s_entry=drivingCourse[end].s # first position (in m) :t => 0.0, # total running time (in s)
standstillSection.s_exit=drivingCourse[end].s # last position (in m) :E => 0.0, # total energy consumption (in Ws)
standstillSection.v_entry=drivingCourse[end].v # entry speed (in m/s) :s_exit => drivingCourse[end].s, # last position (in m)
standstillSection.v_exit=drivingCourse[end].v # exit speed (in m/s) :v_exit => drivingCourse[end].v)) # exit speed (in m/s)))
standstillSection.length=0.0 # total length (in m) drivingCourse[end].behavior = BS[:type]
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
# traction effort and resisting forces (in N) # traction effort and resisting forces (in N)
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, standstillSection.type) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type])
merge!(CS[:behaviorSections], Dict(:standstill => standstillSection)) merge!(CS[:behaviorSections], Dict(:standstill => BS))
end # else: return the characteristic section without a standstillSection section end # else: return the characteristic section without a standstillSection section
return (CS, drivingCourse) return (CS, drivingCourse)
end #function addStandstill! end #function addStandstill!
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 end #module MovingPhases

View File

@ -25,22 +25,24 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
# check if the CS has a cruising section # check if the CS has a cruising section
CS = CSs[csId] CS = CSs[csId]
BSs = CS[:behaviorSections] BSs = CS[:behaviorSections]
s_breakFree = get(BSs, :breakFree, BehaviorSection()).length
s_clearing = get(BSs, :clearing, BehaviorSection()).length s_breakFree = get(BSs, :breakFree, Dict(:length=>0.0))[:length]
s_acceleration = get(BSs, :acceleration, BehaviorSection()).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 s_braking = max(0.0, ceil((CS[:v_exit]^2-CS[:v_peak]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
# calculate the cruising sections length # calculate the cruising sections length
s_cruising=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 # reset the characteristic section (CS), delete behavior sections (BS) that were used during the preperation for setting v_entry, v_peak and v_exit
delete!(BSs, :breakFree) # 01/07 old: delete!(BSs, :breakFree)
delete!(BSs, :clearing) # 01/07 old: delete!(BSs, :clearing)
delete!(BSs, :acceleration) # 01/07 old: delete!(BSs, :acceleration)
delete!(BSs, :diminishing) # 01/07 old: delete!(BSs, :diminishing)
delete!(BSs, :cruising) # 01/07 old: delete!(BSs, :cruising)
CS[:E]=0.0 CS[:behaviorSections] = Dict()
CS[:t]=0.0 CS[:E] = 0.0
CS[:t] = 0.0
if s_clearing == CS[:length] if s_clearing == CS[:length]
@ -113,6 +115,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
#create a new moving section for the minimum energy consumption #create a new moving section for the minimum energy consumption
movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime) movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime)
# 01/01 new when Datapoint is a Dict: movingSectionOriginal=copy(movingSectionMinimumRunningTime)
CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections] CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections]
merge!(movingSectionOriginal, Dict(:energySavingModifications => [])) # list containing all the used energy saving modifications merge!(movingSectionOriginal, Dict(:energySavingModifications => [])) # list containing all the used energy saving modifications
@ -196,11 +199,11 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
get(CSsOrig[csIdMax][:behaviorSections], :clearing, get(CSsOrig[csIdMax][:behaviorSections], :clearing,
get(CSsOrig[csIdMax][:behaviorSections], :breakFree, get(CSsOrig[csIdMax][:behaviorSections], :breakFree,
get(CSsOrig[csIdMax][:behaviorSections], :diminishing, get(CSsOrig[csIdMax][:behaviorSections], :diminishing,
BehaviorSection()))))))))).dataPoints[end] 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) if haskey(CSsOrig[csIdMax][:behaviorSections], :diminishing)
lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax][:behaviorSections][:diminishing].dataPoints[end]) lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax][:behaviorSections][:diminishing][:dataPoints][end])
end end
# create new driving course # create new driving course
@ -233,7 +236,8 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
# replace the original driving course and CS with the new modified ones # replace the original driving course and CS with the new modified ones
drivingCourseOriginal=drivingCourseNew drivingCourseOriginal=drivingCourseNew
CSsOrig[csIdMax]=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[:t]=drivingCourseOriginal[end].t # total running time (in s)
movingSectionOriginal[:E]=drivingCourseOriginal[end].E # total energy consumption (in Ws) movingSectionOriginal[:E]=drivingCourseOriginal[end].E # total energy consumption (in Ws)
@ -244,8 +248,8 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
for csId in csIdMax+1:length(CSsOrig) for csId in csIdMax+1:length(CSsOrig)
for bs in 1: length(allBs) for bs in 1: length(allBs)
if haskey(CSsOrig[csId][:behaviorSections], allBs[bs]) if haskey(CSsOrig[csId][:behaviorSections], allBs[bs])
for point in 1:length(CSsOrig[csId][:behaviorSections][allBs[bs]].dataPoints) for point in 1:length(CSsOrig[csId][:behaviorSections][allBs[bs]][:dataPoints])
CSsOrig[csId][:behaviorSections][allBs[bs]].dataPoints[point] = CSsOrig[csId][:behaviorSections][allBs[bs]].dataPoints[point]+difference CSsOrig[csId][:behaviorSections][allBs[bs]][:dataPoints][point] = CSsOrig[csId][:behaviorSections][allBs[bs]][:dataPoints][point]+difference
end end
end #if end #if
end #for end #for
@ -370,7 +374,8 @@ function copyEnergySavingModification(original::Dict)
:ΔE => original[:ΔE], # saved energy (in Ws) :ΔE => original[:ΔE], # saved energy (in Ws)
:Δt => original[:Δt], # time loss (in s) :Δt => original[:Δt], # time loss (in s)
:ratio => original[:ratio], # ratio of ΔE and Δt (in Ws/s) :ratio => original[:ratio], # ratio of ΔE and Δt (in Ws/s)
:csModified => 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[] drivingCourseModified = DataPoint[]
for i in 1:length(original[:drivingCourseModified]) for i in 1:length(original[:drivingCourseModified])
@ -378,8 +383,7 @@ function copyEnergySavingModification(original::Dict)
end end
merge!(copy, Dict(:drivingCourseModified => drivingCourseModified)) # drivingCourse for the modified characteristic section merge!(copy, Dict(:drivingCourseModified => drivingCourseModified)) # drivingCourse for the modified characteristic section
return copy return copy
end #function EnergySavingModification end #function copyEnergySavingModification
function updateEnergySavingModifications!(energySavingModifications::Vector{Dict}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer) function updateEnergySavingModifications!(energySavingModifications::Vector{Dict}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer)
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] 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 # update the behavior sections of the modified charateristic section
for bs in 1: length(allBs) for bs in 1: length(allBs)
if haskey(BSs, allBs[bs]) if haskey(BSs, allBs[bs])
for point in 1:length(BSs[allBs[bs]].dataPoints) for point in 1:length(BSs[allBs[bs]][:dataPoints])
BSs[allBs[bs]].dataPoints[point] = BSs[allBs[bs]].dataPoints[point] + difference BSs[allBs[bs]][:dataPoints][point] = BSs[allBs[bs]][:dataPoints][point] + difference
end end
end #if end #if
end #for end #for
@ -423,10 +427,11 @@ function copyMovingSection(original::Dict)
#TODO after removing the mutable structs: Is it possible to just "copy"? #TODO after removing the mutable structs: Is it possible to just "copy"?
CSsCopy = Vector{Dict}() CSsCopy = Vector{Dict}()
for csId in 1:length(original[:characteristicSections]) 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 end #for
copy = Dict(:id => original[:id], # identifier copiedMS = Dict(:id => original[:id], # identifier
:length => original[:length], # total length (in m) :length => original[:length], # total length (in m)
:s_entry => original[:s_entry], # first position (in m) :s_entry => original[:s_entry], # first position (in m)
:s_exit => original[:s_exit], # last 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 if haskey(original, :energySavingModifications) # list of containing all the used energy saving modifications
ModificationsCopy = Dict[] ModificationsCopy = Dict[]
for modId in 1:length(original[:energySavingModifications]) 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 end #for
merge!(copy, Dict(:energySavingModifications => ModificationsCopy)) merge!(copiedMS, Dict(:energySavingModifications => ModificationsCopy))
end end
if haskey(original, :t_recovery) # total recovery time for energy-saving modifications (in s) 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 end
if haskey(original, :t_recoveryAvailable) # still available recovery time for energy-saving modifications (in s) if haskey(original, :t_recoveryAvailable) # still available recovery time for energy-saving modifications (in s)
merge!(copy, Dict(:t_recoveryAvailable => original[:t_recoveryAvailable])) merge!(copiedMS, Dict(:t_recoveryAvailable => original[:t_recoveryAvailable]))
end end
return copy return copiedMS
end #function copyMovingSection end #function copyMovingSection
#=
function copyCharacteristicSection(original::Dict) function copyCharacteristicSection(original::Dict)
#TODO after removing the mutable structs: Is it possible to just "copy"? #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_entry => original[:s_entry], # first position (in m)
:s_exit => original[:s_exit], # last position (in m) :s_exit => original[:s_exit], # last position (in m)
:length => original[:length], # total length (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 :behaviorSections => Dict(), # empty list of containing behavior sections
:t => original[:t], # total running time (in s) :t => original[:t], # total running time (in s)
:E => original[:E], # total energy consumption (in Ws) :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] allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for bs in 1: length(allBs) for bs in 1: length(allBs)
if haskey(original[:behaviorSections], allBs[bs]) 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 #if
end #for end #for
return copy return copiedCS
end #function copyCharacteristicSection end #function copyCharacteristicSection
=#
end #module OperationModes 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]) println("CS ",csId," mit length=", CSs[csId][:length]," mit t=", CSs[csId][:t])
for bs in 1: length(allBs) for bs in 1: length(allBs)
if haskey(CSs[csId][:behaviorSections], allBs[bs]) if haskey(CSs[csId][:behaviorSections], allBs[bs])
println("BS ",allBs[bs], " mit s_entry=", CSs[csId][:behaviorSections][allBs[bs]].s_entry, " und t=", CSs[csId][:behaviorSections][allBs[bs]].t) println("BS ",allBs[bs], " mit s_entry=", CSs[csId][:behaviorSections][allBs[bs]][:s_entry], " und t=", CSs[csId][:behaviorSections][allBs[bs]][:t])
# for point in 1:length(CSs[csId][:behaviorSections][allBs[bs]].dataPoints) # for point in 1:length(CSs[csId][:behaviorSections][allBs[bs]][:dataPoints])
# println(CSs[csId][:behaviorSections][allBs[bs]].dataPoints[point]) # println(CSs[csId][:behaviorSections][allBs[bs]][:dataPoints][point])
# end # end
end #if end #if
end #for end #for

View File

@ -6,7 +6,7 @@ using .MovingPhases
export preparateSections 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) function preparateSections(path::Dict, train::Dict, settings::Dict)
movingSection=createMovingSection(path, train[:v_limit]) movingSection=createMovingSection(path, train[:v_limit])
movingSection=secureBrakingBehavior!(movingSection, train[:a_braking]) movingSection=secureBrakingBehavior!(movingSection, train[:a_braking])
@ -104,11 +104,10 @@ function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train:
startingPoint.v=CSs[csId][:v_entry] startingPoint.v=CSs[csId][:v_entry]
accelerationCourse=[startingPoint] # List of data points accelerationCourse=[startingPoint] # List of data points
if CSs[csId][:v_entry]<CSs[csId][:v_peak] if CSs[csId][:v_entry] < CSs[csId][:v_peak]
(CSs[csId], accelerationCourse)=addAccelerationPhase!(CSs[csId], accelerationCourse, settings, train, CSs) # this function changes the accelerationCourse (CSs[csId], accelerationCourse) = addAccelerationPhase!(CSs[csId], accelerationCourse, settings, train, CSs) # this function changes the accelerationCourse
CSs[csId][:v_peak]=max(CSs[csId][:v_entry],accelerationCourse[end].v) CSs[csId][:v_peak] = max(CSs[csId][:v_entry], accelerationCourse[end].v)
CSs[csId][:v_exit] = min(CSs[csId][:v_exit], CSs[csId][:v_peak], accelerationCourse[end].v)
CSs[csId][:v_exit]=min(CSs[csId][:v_exit], CSs[csId][:v_peak], accelerationCourse[end].v)
else #CSs[csId][:v_entry]==CSs[csId][:v_peak] else #CSs[csId][:v_entry]==CSs[csId][:v_peak]
# v_exit stays the same # v_exit stays the same
end #if end #if

View File

@ -1,13 +1,16 @@
module types module types
# definition of all the additional types and their constructors # definition of all the additional types and their constructors
export DataPoint, BehaviorSection #, CharacteristicSection 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 ## 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 mutable struct DataPoint
i::Integer # identifier and counter variable of the dricing course 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") 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 BehaviorSection and the first point of the next BehaviorSection will be attached to the latter # 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 # position (in m)
Δs::AbstractFloat # step size (in m) Δs::AbstractFloat # step size (in m)
t::AbstractFloat # point in time (in s) 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) 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 ## 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. ## smallest section of the path is the behavior section. It relates to the containing data points via their identifier.
mutable struct BehaviorSection function copyBehaviorSection(original::Dict)
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)
bsDataPoints=[] bsDataPoints=[]
for i in 1:length(original.dataPoints) for i in 1:length(original[:dataPoints])
push!(bsDataPoints, original.dataPoints[i]) push!(bsDataPoints, original[:dataPoints][i])
end 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 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 end #module

View File

@ -11,14 +11,14 @@ include("../src/Input.jl")
using .Input using .Input
using YAML, Test 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("passenger", trainType) == passenger::trainType
@test Input.getEnum("freight", trainTypes) == freight::trainTypes @test Input.getEnum("freight", trainType) == freight::trainType
@test Input.getEnum("motorCoachTrain", trainTypes) == motorCoachTrain::trainTypes @test Input.getEnum("motorCoachTrain", trainType) == motorCoachTrain::trainType
data = YAML.load(open("data/trains/train_passenger_IC2.yaml")) 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")) 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