Refactor some of the mutable structs from types.jl as Dictionaries

pull/1/head v0.6
Max Kannenberg 2021-12-16 14:39:25 +01:00
parent dab7e3495a
commit bee38ec311
11 changed files with 837 additions and 1131 deletions

View File

@ -1,7 +1,7 @@
name = "TrainRun" name = "TrainRun"
uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92" uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92"
authors = ["Max Kannenberg"] authors = ["Max Kannenberg"]
version = "0.5.3" version = "0.6.0"
[deps] [deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"

View File

@ -31,6 +31,14 @@ train_run = calculateDrivingDynamics(train, running_path, settings)
# History # History
## Version 0.6
Refactor some of the mutable structs from types.jl as Dictionaries
- Remove the mutable structs Train, Path, PathSection, Settings and MovingSection
- Create Dictionaries for train, path an settings in Input.jl
- Create a Dictionary for the whole moving section in Preperation.jl and a function for copying the moving section in OperationModes.jl
- Change the type of existing Dictionary keys from String to Symbol
## Version 0.5.3 ## Version 0.5.3
Rename variables in every .jl an .yaml file Rename variables in every .jl an .yaml file

View File

@ -13,6 +13,6 @@ running_path = "data/paths/path_1_10km_nConst_vConst.yaml"
settings = "data/settings.yaml" settings = "data/settings.yaml"
train_run = calculateDrivingDynamics(train, running_path, settings) train_run = calculateDrivingDynamics(train, running_path, settings)
runtime = last(train_run["outputArrayMinimumRunningTime"])[5] runtime = last(train_run[:outputArrayMinimumRunningTime])[5]
println("The V 90 with 10 ore wagons needs $runtime seconds for 10 km with no gradient.") println("The V 90 with 10 ore wagons needs $runtime seconds for 10 km with no gradient.")

View File

@ -8,102 +8,102 @@ export calculateRecoveryTime, increaseCoastingSection, decreaseMaximumVelocity,
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::AbstractFloat, t_MS::AbstractFloat, train::Train) 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" if train[:trainType]=="motor coach train"
if s_MS<= 30000 if s_MS<= 30000
c_s=0.0 c_s=0.0
else s_MS> 30000 else s_MS> 30000
c_s=0.0006 c_s=0.0006
end # if s_MS end # if s_MS
if train.v_limit<=140/3.6 # unit is m/s if train[:v_limit]<=140/3.6 # unit is m/s
c_t=0.03 c_t=0.03
elseif train.v_limit<=160/3.6 # unit is m/s elseif train[:v_limit]<=160/3.6 # unit is m/s
c_t=0.04 c_t=0.04
elseif train.v_limit<=200/3.6 # unit is m/s elseif train[:v_limit]<=200/3.6 # unit is m/s
c_t=0.05 c_t=0.05
elseif train.v_limit<=250/3.6 # unit is m/s elseif train[:v_limit]<=250/3.6 # unit is m/s
c_t=0.06 c_t=0.06
else # train.v_limit>120/3.6 # unit is m/s else # train[:v_limit]>120/3.6 # unit is m/s
c_t=0.07 c_t=0.07
end # if train.v_limit end # if train[:v_limit]
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 elseif train[:trainType]=="freight" && train[:v_limit]<=120/3.6 # unit is m/s
t_recovery1=s_MS*0.0006 +t_MS*0.03 t_recovery1=s_MS*0.0006 +t_MS*0.03
t_recovery2=s_MS*0.0018 +t_MS*0.0 t_recovery2=s_MS*0.0018 +t_MS*0.0
t_recovery3=s_MS*0.0 +t_MS*0.04 t_recovery3=s_MS*0.0 +t_MS*0.04
t_recovery=max(t_recovery1, t_recovery2, t_recovery3) 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 else # train[:trainType]=="passenger" || (train[:trainType]=="freight" && 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
c_s=0.0009 c_s=0.0009
end # if s_MS end # if s_MS
if train.v_limit<=140/3.6 # unit is m/s if train[:v_limit]<=140/3.6 # unit is m/s
if train.m_train<=300000 # unit is kg if train[:m_train]<=300000 # unit is kg
c_t=0.03 c_t=0.03
elseif train.m_train<=500000 # unit is kg elseif train[:m_train]<=500000 # unit is kg
c_t=0.04 c_t=0.04
elseif train.m_train<=700000 # unit is kg elseif train[:m_train]<=700000 # unit is kg
c_t=0.04 c_t=0.04
else # train.m_train>700000 # unit is kg else # train[:m_train]>700000 # unit is kg
c_t=0.05 c_t=0.05
end # if train.m_train end # if train[:m_train]
elseif train.v_limit<=160/3.6 # unit is m/s elseif train[:v_limit]<=160/3.6 # unit is m/s
if train.m_train<=300000 # unit is kg if train[:m_train]<=300000 # unit is kg
c_t=0.03 c_t=0.03
elseif train.m_train<=500000 # unit is kg elseif train[:m_train]<=500000 # unit is kg
c_t=0.04 c_t=0.04
else # train.m_train>500000 # unit is kg else # train[:m_train]>500000 # unit is kg
c_t=0.0 c_t=0.0
end # if train.m_train end # if train[:m_train]
elseif train.v_limit<=200/3.6 # unit is m/s elseif train[:v_limit]<=200/3.6 # unit is m/s
if train.m_train<=300000 # unit is kg if train[:m_train]<=300000 # unit is kg
c_t=0.04 c_t=0.04
elseif train.m_train<=500000 # unit is kg elseif train[:m_train]<=500000 # unit is kg
c_t=0.05 c_t=0.05
else # train.m_train>500000 # unit is kg else # train[:m_train]>500000 # unit is kg
c_t=0.06 c_t=0.06
end # if train.m_train end # if train[:m_train]
else # train.v_limit>200/3.6 # unit is m/s else # train[:v_limit]>200/3.6 # unit is m/s
if train.m_train<=300000 # unit is kg if train[:m_train]<=300000 # unit is kg
c_t=0.05 c_t=0.05
elseif train.m_train<=500000 # unit is kg elseif train[:m_train]<=500000 # unit is kg
c_t=0.06 c_t=0.06
else # train.m_train>500000 # unit is kg else # train[:m_train]>500000 # unit is kg
c_t=0.07 c_t=0.07
end # if train.m_train end # if train[:m_train]
end # if train.v_limit end # if train[:v_limit]
c_tMin=s_MS/t_MS*0.0012 c_tMin=s_MS/t_MS*0.0012
c_t=max(c_t, c_tMin) c_t=max(c_t, c_tMin)
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[:trainType]
end #function calculateRecoveryTime end #function calculateRecoveryTime
function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if (haskey(csOriginal.behaviorSections, "cruising") || haskey(csOriginal.behaviorSections, "diminishing")) && haskey(csOriginal.behaviorSections, "braking") if (haskey(csOriginal.behaviorSections, :cruising) || haskey(csOriginal.behaviorSections, :diminishing)) && haskey(csOriginal.behaviorSections, :braking)
# check if cruising or diminishing should be reduced for coasting # check if cruising or diminishing should be reduced for coasting
if haskey(csOriginal.behaviorSections, "cruising") && haskey(csOriginal.behaviorSections, "diminishing") if haskey(csOriginal.behaviorSections, :cruising) && haskey(csOriginal.behaviorSections, :diminishing)
if get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[1] > get(csOriginal.behaviorSections, "diminishing", BehaviorSection()).dataPoints[1] if csOriginal.behaviorSections[:cruising].dataPoints[1] > csOriginal.behaviorSections[:diminishing].dataPoints[1]
reduceCruising=true reduceCruising=true
reduceDiminishing=false reduceDiminishing=false
else else
reduceDiminishing=true reduceDiminishing=true
reduceCruising=false reduceCruising=false
end end
elseif haskey(csOriginal.behaviorSections, "cruising") elseif haskey(csOriginal.behaviorSections, :cruising)
reduceCruising=true reduceCruising=true
reduceDiminishing=false reduceDiminishing=false
elseif haskey(csOriginal.behaviorSections, "diminishing") elseif haskey(csOriginal.behaviorSections, :diminishing)
reduceDiminishing=true reduceDiminishing=true
reduceCruising=false reduceCruising=false
end end
@ -111,13 +111,13 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
if reduceCruising if reduceCruising
cruisingReduction=settings.stepSize cruisingReduction = settings[:stepSize]
while cruisingReduction>=settings.stepSize/10^approximationLevel while cruisingReduction>=settings[:stepSize]/10^approximationLevel
#while cruisingReduction>=settings.stepSize/100 #while cruisingReduction>=settings[:stepSize]/100
while cruisingReduction>=settings.stepSize/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified.v_exit && drivingCourseModified[end].s<csModified.s_exit) -> see below at the end of the while loop while cruisingReduction>=settings[:stepSize]/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified.v_exit && drivingCourseModified[end].s<csModified.s_exit) -> see below at the end of the while loop
# create a copy for the characteristic sections drivingCourse # create a copy for the characteristic sections drivingCourse
energySavingStartId=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[1] energySavingStartId=get(csOriginal.behaviorSections, :cruising, BehaviorSection()).dataPoints[1]
if energySavingStartId==0 if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !") error("ERROR at creating a new driving course for energy saving with coasting !")
end end
@ -130,46 +130,45 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
end end
# 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=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).length-cruisingReduction s_cruising = csOriginal.behaviorSections[: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 # 09/20 old: doesn't work for non constant cruising -> TODO: should work now
# t_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).t-cruisingReduction # t_cruising=csOriginal.behaviorSections[:cruising].t-cruisingReduction
# s_cruising=t_cruising*drivingCourseModified[end].v # s_cruising=t_cruising*drivingCourseModified[end].v
wayReduction=drivingCourse(get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[end]).v*cruisingReduction distanceReduction = drivingCourse(csOriginal.behaviorSections[:cruising].dataPoints[end]).v*cruisingReduction
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).length-wayReduction s_cruising = csOriginal.behaviorSections[: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=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).length-cruisingReduction*10 # TODO: or better: *100 ? s_cruising=csOriginal.behaviorSections[:cruising].length-cruisingReduction*10 # TODO: or better: *100 ?
end #if end #if
s_cruising=max(0.0, s_cruising) s_cruising=max(0.0, s_cruising)
# copy csOriginal to csModified # copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}()) csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{Symbol, BehaviorSection}())
if haskey(csOriginal.behaviorSections, "breakFree") if haskey(csOriginal.behaviorSections, :breakFree)
breakFreeSection=BehaviorSection(get(csOriginal.behaviorSections, "breakFree", BehaviorSection())) breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree])
merge!(csModified.behaviorSections, Dict("breakFree"=>breakFreeSection)) merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "breakFree", BehaviorSection()).E csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E
csModified.t=csModified.t+get(csModified.behaviorSections, "breakFree", BehaviorSection()).t csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t
end end
if haskey(csOriginal.behaviorSections, "clearing") # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located if haskey(csOriginal.behaviorSections, :clearing) # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located
clearingSection=BehaviorSection(get(csOriginal.behaviorSections, "clearing", BehaviorSection())) clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing])
merge!(csModified.behaviorSections, Dict("clearing"=>clearingSection)) merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "clearing", BehaviorSection()).E csModified.E = csModified.E + csModified.behaviorSections[:clearing].E
csModified.t=csModified.t+get(csModified.behaviorSections, "clearing", BehaviorSection()).t csModified.t = csModified.t + csModified.behaviorSections[:clearing].t
end end
if haskey(csOriginal.behaviorSections, "acceleration") if haskey(csOriginal.behaviorSections, :acceleration)
accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection())) accelerationSection=BehaviorSection(csOriginal.behaviorSections[:acceleration])
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection)) merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E
csModified.t=csModified.t+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t
end end
if haskey(csOriginal.behaviorSections, :diminishing)
if haskey(csOriginal.behaviorSections, "diminishing") diminishingSection=BehaviorSection(csOriginal.behaviorSections[:diminishing])
diminishingSection=BehaviorSection(get(csOriginal.behaviorSections, "diminishing", BehaviorSection())) merge!(csModified.behaviorSections, Dict(:diminishing=>diminishingSection))
merge!(csModified.behaviorSections, Dict("diminishing"=>diminishingSection)) csModified.E = csModified.E + csModified.behaviorSections[:diminishing].E
csModified.E=csModified.E+get(csModified.behaviorSections, "diminishing", BehaviorSection()).E csModified.t = csModified.t + csModified.behaviorSections[:diminishing].t
csModified.t=csModified.t+get(csModified.behaviorSections, "diminishing", BehaviorSection()).t
end end
@ -191,7 +190,7 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
# calculate the moving phase between coasting and the end of the CS # calculate the moving phase between coasting and the end of the CS
if drivingCourseModified[end].v > csModified.v_exit if drivingCourseModified[end].v > csModified.v_exit
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs) #(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].v == csModified.v_exit && drivingCourseModified[end].s < csModified.s_exit elseif drivingCourseModified[end].v == csModified.v_exit && drivingCourseModified[end].s < csModified.s_exit
# v_exit is already reached. Now cruise till the end of the CS # v_exit is already reached. Now cruise till the end of the CS
@ -208,39 +207,36 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
elseif reduceDiminishing elseif reduceDiminishing
# TODO: At the moment diminishing is reduced like the acceleration in decreaseMaximumVelocity. To reduce code, the methods for reducing cruising phase an reducing the diminishing pahse can be combined in some parts. # TODO: At the moment diminishing is reduced like the acceleration in decreaseMaximumVelocity. To reduce code the methods for reducing cruising phase and reducing the diminishing phase can be combined in some parts.
# copy csOriginal to csModified # copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}()) csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{Symbol, BehaviorSection}())
if haskey(csOriginal.behaviorSections, :breakFree)
if haskey(csOriginal.behaviorSections, "breakFree") breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree])
breakFreeSection=BehaviorSection(get(csOriginal.behaviorSections, "breakFree", BehaviorSection())) merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection))
merge!(csModified.behaviorSections, Dict("breakFree"=>breakFreeSection)) csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E
csModified.E=csModified.E+get(csModified.behaviorSections, "breakFree", BehaviorSection()).E csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t
csModified.t=csModified.t+get(csModified.behaviorSections, "breakFree", BehaviorSection()).t end
if haskey(csOriginal.behaviorSections, :clearing) # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located
clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing])
merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection))
csModified.E = csModified.E + csModified.behaviorSections[:clearing].E
csModified.t = csModified.t + csModified.behaviorSections[:clearing].t
end
if haskey(csOriginal.behaviorSections, :acceleration)
accelerationSection=BehaviorSection(csOriginal.behaviorSections[:acceleration])
merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection))
csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E
csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t
end
if haskey(csOriginal.behaviorSections, :cruising)
cruisingSection=BehaviorSection(csOriginal.behaviorSections[:cruising])
merge!(csModified.behaviorSections, Dict(:cruising=>cruisingSection))
csModified.E = csModified.E + csModified.behaviorSections[:cruising].E
csModified.t = csModified.t + csModified.behaviorSections[:cruising].t
end end
if haskey(csOriginal.behaviorSections, "clearing") # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located diminishingSection=BehaviorSection(csOriginal.behaviorSections[:diminishing])
clearingSection=BehaviorSection(get(csOriginal.behaviorSections, "clearing", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("clearing"=>clearingSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "clearing", BehaviorSection()).E
csModified.t=csModified.t+get(csModified.behaviorSections, "clearing", BehaviorSection()).t
end
if haskey(csOriginal.behaviorSections, "acceleration")
accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E
csModified.t=csModified.t+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t
end
if haskey(csOriginal.behaviorSections, "cruising")
cruisingSection=BehaviorSection(get(csOriginal.behaviorSections, "cruising", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("cruising"=>cruisingSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "cruising", BehaviorSection()).E
csModified.t=csModified.t+get(csModified.behaviorSections, "cruising", BehaviorSection()).t
end
diminishingSection=BehaviorSection(get(csOriginal.behaviorSections, "diminishing", BehaviorSection()))
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)
@ -251,14 +247,14 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
diminishingSection.t=drivingCourse[diminishingSection.dataPoints[end]].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s) diminishingSection.t=drivingCourse[diminishingSection.dataPoints[end]].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
diminishingSection.E=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws) diminishingSection.E=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
merge!(csModified.behaviorSections, Dict("diminishing"=>diminishingSection)) merge!(csModified.behaviorSections, Dict(:diminishing => diminishingSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "diminishing", BehaviorSection()).E csModified.E = csModified.E + csModified.behaviorSections[:diminishing].E
csModified.t=csModified.t+get(csModified.behaviorSections, "diminishing", BehaviorSection()).t csModified.t = csModified.t + csModified.behaviorSections[:diminishing].t
energySavingStartId=diminishingSection.dataPoints[end] energySavingStartId=diminishingSection.dataPoints[end]
else else
# The diminishing section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section. # The diminishing section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section.
energySavingStartId=get(csOriginal.behaviorSections, "clearing", get(csOriginal.behaviorSections, "diminishing", BehaviorSection())).dataPoints[1] energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :diminishing, BehaviorSection())).dataPoints[1]
end end
# copy the driving course till the beginning of energy saving # copy the driving course till the beginning of energy saving
@ -297,131 +293,34 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
end end
end # function increaseCoastingSection end # function increaseCoastingSection
#= 12/03 old without diminishing: function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "cruising") && haskey(csOriginal.behaviorSections, "braking")
cruisingReduction=settings.stepSize
while cruisingReduction>=settings.stepSize/10^approximationLevel
#while cruisingReduction>=settings.stepSize/100
while cruisingReduction>=settings.stepSize/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified.v_exit && drivingCourseModified[end].s<csModified.s_exit) -> see below at the end of the while loop
# create a copy for the characteristic sections drivingCourse
energySavingStartId=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[1]
if energySavingStartId==0
error("ERROR at creating a new driving course for energy saving with coasting !")
end
drivingCourseModified=[DataPoint(drivingCourse[1])]
# TODO: tried to insert copy on 15.07.2021 drivingCourseModified=[copy(drivingCourse[1])]
for i in 2:energySavingStartId
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
# TODO: tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of data points till the start of energy saving
end
# calculating the new length of the cruising section
if settings.stepVariable=="s in m" # distance step method
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).length-cruisingReduction
elseif settings.stepVariable=="t in s" # time step method
# 09/20 old: doesn't work for non constant cruising
# t_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).t-cruisingReduction
# s_cruising=t_cruising*drivingCourseModified[end].v
wayReduction=drivingCourse(get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[end]).v*cruisingReduction
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).length-wayReduction
elseif settings.stepVariable=="v in m/s" # velocity step method
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).length-cruisingReduction*10 # TODO: or better: *100 ?
end #if
s_cruising=max(0.0, s_cruising)
# copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}())
if haskey(csOriginal.behaviorSections, "breakFree")
breakFreeSection=BehaviorSection(get(csOriginal.behaviorSections, "breakFree", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("breakFree"=>breakFreeSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "breakFree", BehaviorSection()).E
csModified.t=csModified.t+get(csModified.behaviorSections, "breakFree", BehaviorSection()).t
end
if haskey(csOriginal.behaviorSections, "clearing") # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located
clearingSection=BehaviorSection(get(csOriginal.behaviorSections, "clearing", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("clearing"=>clearingSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "clearing", BehaviorSection()).E
csModified.t=csModified.t+get(csModified.behaviorSections, "clearing", BehaviorSection()).t
end
if haskey(csOriginal.behaviorSections, "acceleration")
accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E
csModified.t=csModified.t+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t
end
# calculate the new and now shorter cruising section
if s_cruising>0.0
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end
(csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs)
if drivingCourseModified[end].v < csModified.v_exit || drivingCourseModified[end].s > csModified.s_exit
# the train reaches v_exit before reaching s_exit. The cruising and coasting sections have to be calculated again with a larger cruising section (so with a smaller reduction of the cruising section)
cruisingReduction=cruisingReduction/10
else
break
end
end # while cruisingReduction
if drivingCourseModified[end].v > csModified.v_exit
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].v == csModified.v_exit && drivingCourseModified[end].s < csModified.s_exit
# v_exit is already reached. Now cruise till the end of the CS
s_cruisingAfterCoasting=csModified.s_exit-drivingCourseModified[end].s
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
end
if t_recoveryAvailable < csModified.t-csOriginal.t || drivingCourseModified[end].v != csModified.v_exit || drivingCourseModified[end].s != csModified.s_exit # time loss is to high and the CS has to be calculated again with larger cruising section (so with a smaller reduction of the cruising section) or v_exit or s_exit are not reached excatly
cruisingReduction=cruisingReduction/10
else
return (csModified, drivingCourseModified, true)
end
end #while
# there is no energy saving modification for this CS with the available recovery time
return (CharacteristicSection(), [], false)
else
# there is no energy saving modification for this CS because a cruising section AND a braking section are needed to be transformed into a coasting section
return (CharacteristicSection(), [], false)
end
end # function increaseCoastingSection
=#
# method 2 with shortening the acceleration by stepsize # method 2 with shortening the acceleration by stepsize
function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) #function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "acceleration") && csOriginal.v_target > csOriginal.v_entry && csOriginal.v_target > csOriginal.v_exit if haskey(csOriginal.behaviorSections, :acceleration) && csOriginal.v_target > csOriginal.v_entry && csOriginal.v_target > csOriginal.v_exit
accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection())) accelerationSection = BehaviorSection(csOriginal.behaviorSections[:acceleration])
if drivingCourse[accelerationSection.dataPoints[end]-1].v < csOriginal.v_exit if drivingCourse[accelerationSection.dataPoints[end]-1].v < csOriginal.v_exit
return (CharacteristicSection(), [], false) return (CharacteristicSection(), [], false)
# TODO: or calculate a new acceleration phase with v_exit as v_target? it will be very short, shorter than the step size. # TODO: or calculate a new acceleration phase with v_exit as v_target? it will be very short, shorter than the step size.
end end
# copy csOriginal to csModified # copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}()) csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{Symbol, BehaviorSection}())
if haskey(csOriginal.behaviorSections, "breakFree") if haskey(csOriginal.behaviorSections, :breakFree)
breakFreeSection=BehaviorSection(get(csOriginal.behaviorSections, "breakFree", BehaviorSection())) breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree])
merge!(csModified.behaviorSections, Dict("breakFree"=>breakFreeSection)) merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "breakFree", BehaviorSection()).E csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E
csModified.t=csModified.t+get(csModified.behaviorSections, "breakFree", BehaviorSection()).t csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t
end end
#accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection())) #accelerationSection = BehaviorSection(get(csOriginal.behaviorSections, :acceleration, BehaviorSection()))
if length(accelerationSection.dataPoints) > 2 if length(accelerationSection.dataPoints) > 2
if haskey(csOriginal.behaviorSections, "clearing") if haskey(csOriginal.behaviorSections, :clearing)
clearingSection=BehaviorSection(get(csOriginal.behaviorSections, "clearing", BehaviorSection())) clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing])
merge!(csModified.behaviorSections, Dict("clearing"=>clearingSection)) merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "clearing", BehaviorSection()).E csModified.E = csModified.E + csModified.behaviorSections[:clearing].E
csModified.t=csModified.t+get(csModified.behaviorSections, "clearing", BehaviorSection()).t csModified.t = csModified.t + csModified.behaviorSections[:clearing].t
end end
# remove the last acceleration waypoint # remove the last acceleration waypoint
@ -433,14 +332,14 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
accelerationSection.t=drivingCourse[accelerationSection.dataPoints[end]].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) accelerationSection.t=drivingCourse[accelerationSection.dataPoints[end]].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s)
accelerationSection.E=drivingCourse[accelerationSection.dataPoints[end]].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws) accelerationSection.E=drivingCourse[accelerationSection.dataPoints[end]].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection)) merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E
csModified.t=csModified.t+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t
energySavingStartId=accelerationSection.dataPoints[end] energySavingStartId=accelerationSection.dataPoints[end]
else else
# The acceleration section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section. # The acceleration section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section.
energySavingStartId=get(csOriginal.behaviorSections, "clearing", get(csOriginal.behaviorSections, "acceleration", BehaviorSection())).dataPoints[1] energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :acceleration, BehaviorSection())).dataPoints[1]
end end
# TODO: should v_target be reduced or is it enough to pop the data points? # TODO: should v_target be reduced or is it enough to pop the data points?
@ -452,17 +351,17 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
end end
#s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_target^2)/2/train.a_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors #s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_target^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
s_braking=max(0.0, ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train.a_braking, digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors s_braking=max(0.0, ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
s_cruising=csModified.s_exit-drivingCourseModified[end].s-s_braking s_cruising=csModified.s_exit-drivingCourseModified[end].s-s_braking
if s_cruising >0.001 if s_cruising >0.001
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising") (csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end #if end #if
# s_brakingAfterCruising=ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train.a_braking, digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same # s_brakingAfterCruising=ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train[:a_braking], digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end].v>csModified.v_exit if drivingCourseModified[end].v>csModified.v_exit
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs) #(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].s<csModified.s_exit elseif drivingCourseModified[end].s<csModified.s_exit
if (csModified.s_exit-drivingCourseModified[end].s)>0.001 if (csModified.s_exit-drivingCourseModified[end].s)>0.001
@ -500,9 +399,9 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
end # function decreaseMaximumVelocity end # function decreaseMaximumVelocity
# combination of method 1 and method 2 # combination of method 1 and method 2
function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
# if haskey(csOriginal.behaviorSections, "acceleration") && (haskey(csOriginal.behaviorSections, "braking") || haskey(csOriginal.behaviorSections, "coasting")) && csOriginal.v_target>csOriginal.v_entry && csOriginal.v_target>csOriginal.v_exit # if haskey(csOriginal.behaviorSections, :acceleration) && (haskey(csOriginal.behaviorSections, :braking) || haskey(csOriginal.behaviorSections, :coasting)) && csOriginal.v_target>csOriginal.v_entry && csOriginal.v_target>csOriginal.v_exit
if haskey(csOriginal.behaviorSections, "acceleration") && (haskey(csOriginal.behaviorSections, "braking") || haskey(csOriginal.behaviorSections, "coasting")) && drivingCourse[get(csOriginal.behaviorSections, "acceleration", BehaviorSection()).dataPoints[end]].v > max(csOriginal.v_entry, csOriginal.v_exit) if haskey(csOriginal.behaviorSections, :acceleration) && (haskey(csOriginal.behaviorSections, :braking) || haskey(csOriginal.behaviorSections, :coasting)) && drivingCourse[get(csOriginal.behaviorSections, :acceleration, BehaviorSection()).dataPoints[end]].v > max(csOriginal.v_entry, csOriginal.v_exit)
csCombined=CharacteristicSection(csOriginal) csCombined=CharacteristicSection(csOriginal)
drivingCourseCombined=Vector{DataPoint}() drivingCourseCombined=Vector{DataPoint}()
for i in 1:length(drivingCourse) for i in 1:length(drivingCourse)
@ -518,7 +417,7 @@ function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCo
ΔE=csOriginal.E-csCombined.E # saved energy (in Ws) ΔE=csOriginal.E-csCombined.E # saved energy (in Ws)
Δt=csCombined.t-csOriginal.t # time loss (in s) Δt=csCombined.t-csOriginal.t # time loss (in s)
while (haskey(csOriginal.behaviorSections, "cruising") && (Δt<=0.0 || ΔE<=0.0)) #Δt<=0.0) #&& ΔE<=0.0) # && Δt<=0.0) while (haskey(csOriginal.behaviorSections, :cruising) && (Δt<=0.0 || ΔE<=0.0)) #Δt<=0.0) #&& ΔE<=0.0) # && Δt<=0.0)
(csCombined, drivingCourseCombined, newCoasting)=increaseCoastingSection(csCombined, drivingCourseCombined, settings, train, allCSs, t_recoveryAvailable-Δt) (csCombined, drivingCourseCombined, newCoasting)=increaseCoastingSection(csCombined, drivingCourseCombined, settings, train, allCSs, t_recoveryAvailable-Δt)
if newCoasting if newCoasting
ΔE=csOriginal.E-csCombined.E # saved energy (in Ws) ΔE=csOriginal.E-csCombined.E # saved energy (in Ws)

View File

@ -6,7 +6,7 @@ using ..types
export readInput export readInput
""" """
Read the input information from YAML files for train, path and settings, save it in different objects and return them. Read the input information from YAML files for train, path and settings, save it in different dictionaries and return them.
""" """
function readInput(trainDirectory::String, pathDirectory::String, settingsDirectory::String) function readInput(trainDirectory::String, pathDirectory::String, settingsDirectory::String)
train=inputTrain(trainDirectory) train=inputTrain(trainDirectory)
@ -17,25 +17,25 @@ function readInput(trainDirectory::String, pathDirectory::String, settingsDirect
end #function readInput end #function readInput
""" """
Read the train information from a YAML file, save it in a Train object and return it. Read the train information from a YAML file, save it in a train Dict and return it.
""" """
function inputTrain(trainDirectory::String) function inputTrain(trainDirectory::String)
data = YAML.load(open(trainDirectory)) data = YAML.load(open(trainDirectory))
collect(keys(data)) collect(keys(data))
collect(values(data)) collect(values(data))
train=Train()
if haskey(data["train"],"name") if haskey(data["train"],"name")
train.name=data["train"]["name"] # trains name name=data["train"]["name"] # trains name
delete!(data["train"], "name") delete!(data["train"], "name")
else else
error("ERROR at reading the train yaml file: The keyword name is missing. It has to be added.") error("ERROR at reading the train yaml file: The keyword name is missing. It has to be added.")
end end
train.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") if typeof(data["train"]["trainType"])==String && (data["train"]["trainType"]=="freight" || data["train"]["trainType"]=="motor coach train" || data["train"]["trainType"]=="passenger")
train.trainType=data["train"]["trainType"] # "passenger" or "freight" or "motor coach train" trainType=data["train"]["trainType"] # "passenger" or "freight" or "motor coach train"
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, motor coach train or passenger.")
@ -46,7 +46,7 @@ function inputTrain(trainDirectory::String)
if haskey(data["train"],"l_train") if haskey(data["train"],"l_train")
if typeof(data["train"]["l_train"]) <: Real && data["train"]["l_train"]>0.0 if typeof(data["train"]["l_train"]) <: Real && data["train"]["l_train"]>0.0
train.l_train=data["train"]["l_train"] # total length (in m) l_train=data["train"]["l_train"] # total length (in m)
delete!(data["train"], "l_train") delete!(data["train"], "l_train")
else else
error("ERROR at reading the train yaml file: The value of the length is no real number >0.0.") error("ERROR at reading the train yaml file: The value of the length is no real number >0.0.")
@ -78,34 +78,34 @@ function inputTrain(trainDirectory::String)
end end
if v_limit_temp > 0.0 && v_limit_kmh_temp > 0.0 if v_limit_temp > 0.0 && v_limit_kmh_temp > 0.0
train.v_limit=v_limit_temp v_limit=v_limit_temp
difference=abs(v_limit_temp-v_limit_kmh_temp/3.6) difference=abs(v_limit_temp-v_limit_kmh_temp/3.6)
if difference >0.0 if difference >0.0
println("WARNING at reading the train yaml file: The values of v_limit and v_limit_kmh differ by ",difference," m/s. The value v_limit=",train.v_limit," m/s is used." ) println("WARNING at reading the train yaml file: The values of v_limit and v_limit_kmh differ by ",difference," m/s. The value v_limit=",v_limit," m/s is used." )
end end
elseif v_limit_temp > 0.0 elseif v_limit_temp > 0.0
train.v_limit=v_limit_temp v_limit=v_limit_temp
elseif v_limit_kmh_temp > 0.0 elseif v_limit_kmh_temp > 0.0
train.v_limit=v_limit_kmh_temp/3.6 v_limit=v_limit_kmh_temp/3.6
else else
train.v_limit=1000/3.6 v_limit=1000/3.6
println("WARNING at reading the train yaml file: There is no value for the trains speed limit (v_limit or v_limit_kmh). The value v_limit=1000 km/h =",train.v_limit," m/s is used." ) println("WARNING at reading the train yaml file: There is no value for the trains speed limit (v_limit or v_limit_kmh). The value v_limit=1000 km/h =",v_limit," m/s is used." )
end end
# a_braking # a_braking
if haskey(data["train"],"a_braking") if haskey(data["train"],"a_braking")
if typeof(data["train"]["a_braking"]) <: Real if typeof(data["train"]["a_braking"]) <: Real
train.a_braking=data["train"]["a_braking"] a_braking=data["train"]["a_braking"]
else else
error("ERROR at reading the train yaml file: The value of the a_braking is no real floating point number <0.0.") error("ERROR at reading the train yaml file: The value of the a_braking is no real floating point number <0.0.")
end end
delete!(data["train"], "a_braking") delete!(data["train"], "a_braking")
if train.a_braking > 0.0 if a_braking > 0.0
train.a_braking =-train.a_braking a_braking =-a_braking
println("WARNING at reading the train yaml file: The value for a_braking is >0.0. The braking acceleration has to be <0.0. Therefore a_braking =",train.a_braking," m/s^2 is used." ) println("WARNING at reading the train yaml file: The value for a_braking is >0.0. The braking acceleration has to be <0.0. Therefore a_braking =",a_braking," m/s^2 is used." )
elseif train.a_braking == 0.0 elseif a_braking == 0.0
error("ERROR at reading the train yaml file: The value for a_braking is 0.0. The braking acceleration has to be <0.0.") error("ERROR at reading the train yaml file: The value for a_braking is 0.0. The braking acceleration has to be <0.0.")
end end
else else
@ -115,7 +115,7 @@ function inputTrain(trainDirectory::String)
# mass on the traction units driving axles (in kg) # mass on the traction units driving axles (in kg)
if haskey(data["train"],"m_td") if haskey(data["train"],"m_td")
if typeof(data["train"]["m_td"]) <: Real && data["train"]["m_td"]>0.0 if typeof(data["train"]["m_td"]) <: Real && data["train"]["m_td"]>0.0
train.m_td=data["train"]["m_td"] m_td=data["train"]["m_td"]
else else
error("ERROR at reading the train yaml file: The value of m_td is no real floating point number >0.0.") error("ERROR at reading the train yaml file: The value of m_td is no real floating point number >0.0.")
end end
@ -128,7 +128,7 @@ function inputTrain(trainDirectory::String)
# mass on the traction units carrying axles (in kg) # mass on the traction units carrying axles (in kg)
if haskey(data["train"],"m_tc") if haskey(data["train"],"m_tc")
if typeof(data["train"]["m_tc"]) <: Real && data["train"]["m_tc"]>=0.0 if typeof(data["train"]["m_tc"]) <: Real && data["train"]["m_tc"]>=0.0
train.m_tc=data["train"]["m_tc"] m_tc=data["train"]["m_tc"]
else else
error("ERROR at reading the train yaml file: The value of m_tc is no real floating point number >=0.0.") error("ERROR at reading the train yaml file: The value of m_tc is no real floating point number >=0.0.")
end end
@ -138,47 +138,49 @@ function inputTrain(trainDirectory::String)
delete!(data["train"], "m_tc") delete!(data["train"], "m_tc")
# mass of the traction unit (in kg) # mass of the traction unit (in kg)
train.m_t=train.m_td+train.m_tc m_t=m_td+m_tc
# mass of the consist (set of wagons) (in kg) # mass of the consist (set of wagons) (in kg)
if haskey(data["train"],"m_w") if haskey(data["train"],"m_w")
if typeof(data["train"]["m_w"]) <: Real && data["train"]["m_w"]>=0.0 if typeof(data["train"]["m_w"]) <: Real && data["train"]["m_w"]>=0.0
train.m_w=data["train"]["m_w"] m_w=data["train"]["m_w"]
else else
error("ERROR at reading the train yaml file: The value of m_w is no real floating point number >=0.0.") error("ERROR at reading the train yaml file: The value of m_w is no real floating point number >=0.0.")
end end
else else
train.m_w=0.0 m_w=0.0
println("WARNING at reading the train yaml file: The keyword m_w is missing. Therefore m_w =",train.m_w," kg is used.") println("WARNING at reading the train yaml file: The keyword m_w is missing. Therefore m_w =",m_w," kg is used.")
end end
delete!(data["train"], "m_w") delete!(data["train"], "m_w")
# total mass (in kg) # total mass (in kg)
train.m_train=train.m_t+train.m_w m_train=m_t+m_w
if haskey(data["train"],"rotationMassFactor_train") && typeof(data["train"]["rotationMassFactor_train"]) <: Real if haskey(data["train"],"rotationMassFactor_train") && typeof(data["train"]["rotationMassFactor_train"]) <: Real
if data["train"]["rotationMassFactor_train"]>0.0 if data["train"]["rotationMassFactor_train"]>0.0
train.ξ_train=data["train"]["rotationMassFactor_train"] ξ_train=data["train"]["rotationMassFactor_train"]
ξ_t=0.0
ξ_w=0.0
else else
error("ERROR at reading the train yaml file: The value of rotationMassFactor_train is no real floating point number >0.0.") error("ERROR at reading the train yaml file: The value of rotationMassFactor_train is no real floating point number >0.0.")
end end
elseif haskey(data["train"],"rotationMassFactor_t") && typeof(data["train"]["rotationMassFactor_t"]) <: Real && (train.m_w==0.0 || (haskey(data["train"],"rotationMassFactor_w") && typeof(data["train"]["rotationMassFactor_w"]) <: Real)) elseif haskey(data["train"],"rotationMassFactor_t") && typeof(data["train"]["rotationMassFactor_t"]) <: Real && (m_w==0.0 || (haskey(data["train"],"rotationMassFactor_w") && typeof(data["train"]["rotationMassFactor_w"]) <: Real))
if data["train"]["rotationMassFactor_t"]>0.0 if data["train"]["rotationMassFactor_t"]>0.0
train.ξ_t=data["train"]["rotationMassFactor_t"] ξ_t=data["train"]["rotationMassFactor_t"]
else else
error("ERROR at reading the train yaml file: The value of rotationMassFactor_t is no real floating point number >0.0.") error("ERROR at reading the train yaml file: The value of rotationMassFactor_t is no real floating point number >0.0.")
end end
if train.m_w>0.0 if m_w>0.0
if data["train"]["rotationMassFactor_w"]>=0.0 if data["train"]["rotationMassFactor_w"]>=0.0
train.ξ_w=data["train"]["rotationMassFactor_w"] ξ_w=data["train"]["rotationMassFactor_w"]
else else
error("ERROR at reading the train yaml file: The value of rotationMassFactor_w is no real floating point number >=0.0.") error("ERROR at reading the train yaml file: The value of rotationMassFactor_w is no real floating point number >=0.0.")
end end
else else
train.ξ_w=0.0 ξ_w=0.0
end end
train.ξ_train=(train.ξ_t*train.m_t + train.ξ_w*train.m_w)/train.m_train # rotation mass factor of the whole train (without unit) ξ_train=(ξ_t*m_t + ξ_w*m_w)/m_train # rotation mass factor of the whole train (without unit)
else else
error("ERROR at reading the train yaml file: The keywords rotationMassFactor_train or rotationMassFactor_t and rotationMassFactor_w are missing. They has to be added with a value of type real floating point number.") error("ERROR at reading the train yaml file: The keywords rotationMassFactor_train or rotationMassFactor_t and rotationMassFactor_w are missing. They has to be added with a value of type real floating point number.")
end end
@ -191,70 +193,7 @@ function inputTrain(trainDirectory::String)
if haskey(data["train"],"F_T_pairs") && data["train"]["F_T_pairs"]!=nothing if haskey(data["train"],"F_T_pairs") && data["train"]["F_T_pairs"]!=nothing
F_T_pairs=data["train"]["F_T_pairs"] F_T_pairs=data["train"]["F_T_pairs"]
train.tractiveEffortVelocityPairs=checkAndDefineTractiveEffortInput(F_T_pairs, 1.0) tractiveEffortVelocityPairs=checkAndDefineTractiveEffortInput(F_T_pairs, 1.0)
#= old 2021-11-04: now it is pairs and no scope
# check if the elements of the array have the correct type
errorDetected=false
for row in 1:length(F_T_pairs)
if typeof(F_T_pairs[row][1]) <: Real && F_T_pairs[row][1]>=0.0
else
errorDetected=true
println("ERROR at reading the train yaml file: The speed value of F_T_pairs in row ", row ," is no real floating point number >=0.0.")
end
if typeof(F_T_pairs[row][2]) <: Real && F_T_pairs[row][2]>=0.0
else
errorDetected=true
println("ERROR at reading the train yaml file: The tractive effort value of F_T_pairs in row ", row ," is no real floating point number >=0.0.")
end
if row>=2 && F_T_pairs[row][1] <= F_T_pairs[row-1][1]
errorDetected=true
println("ERROR at reading the train yaml file: The speed value of F_T_pairs in row ", row ," (v=",F_T_pairs[row][1]," m/s) is not higher than the speed value in the previous row (v=",F_T_pairs[row-1][1]," m/s).")
end
end # for
if errorDetected
error("ERROR at reading the train yaml file: Only real floating point number >=0.0 are allowed for speed and tractive effort. The speed values have to be listed from low to high.")
end
# create tractiveEffortVelocityPairs
if F_T_pairs[1][1]>0.0 # if there is no F_T for v=0.0, the first known value is used
push!(train.tractiveEffortVelocityPairs, [0.0, F_T_pairs[1][2]])
println("WARNING at reading the train yaml file: The tractive effort for v=0 m/s is missing. Therefore the first given value F_T(v=",F_T_pairs[1][1]," m/s)=",F_T_pairs[1][2]," N will be used." )
end
for row in 1:length(F_T_pairs)
push!(train.tractiveEffortVelocityPairs, [F_T_pairs[row][1]], F_T_pairs[row][2]])
end # for
# create tractiveEffortArray
train.tractiveEffortArray=[]
if F_T_pairs[1][1]==0.0
push!(train.tractiveEffortArray, [F_T_pairs[1][1], F_T_pairs[1][1], F_T_pairs[1][2]])
elseif F_T_pairs[1][1]>0.0 # if there is no F_T for v=0.0, the first value is used
push!(train.tractiveEffortArray, [0.0, F_T_pairs[1][1], F_T_pairs[1][2]])
println("WARNING at reading the train yaml file: The tractive effort for v=0 m/s is missing. Therefore the first given value F_T(v=",F_T_pairs[1][1]," m/s)=",F_T_pairs[1][2]," N will be used." )
else
error("ERROR at reading the train yaml file: There is a negative speed value in the list. Only positive values for speed and tractive effort are allowed in F_T_pairs.")
end
for row in 2:length(F_T_pairs)
if F_T_pairs[row][1]>F_T_pairs[row-1][1]
if F_T_pairs[row][2]==train.tractiveEffortArray[end][3]
train.tractiveEffortArray[end][2]=F_T_pairs[row][1]
else
push!(train.tractiveEffortArray, [F_T_pairs[row][1], F_T_pairs[row][1], F_T_pairs[row][2]])
end
else
error("ERROR at reading the train yaml file: The F_T_pairs are not in the correct order. They have to be arranged by speed values from low to high.")
end
end # for
if length(F_T_pairs[1])>2
println("INFO according the train yaml file: Only the first two columns of F_T_pairs are used in this tool.")
end
=#
if haskey(data["train"],"F_T_pairs_kmh") && data["train"]["F_T_pairs_kmh"]!=nothing if haskey(data["train"],"F_T_pairs_kmh") && data["train"]["F_T_pairs_kmh"]!=nothing
println("WARNING at reading the train yaml file: There are values for F_T_pairs and F_T_pairs_kmh. The values for F_T_pairs are used." ) println("WARNING at reading the train yaml file: There are values for F_T_pairs and F_T_pairs_kmh. The values for F_T_pairs are used." )
@ -263,50 +202,7 @@ function inputTrain(trainDirectory::String)
elseif haskey(data["train"],"F_T_pairs_kmh") && data["train"]["F_T_pairs_kmh"]!=nothing elseif haskey(data["train"],"F_T_pairs_kmh") && data["train"]["F_T_pairs_kmh"]!=nothing
F_T_pairs_kmh=data["train"]["F_T_pairs_kmh"] F_T_pairs_kmh=data["train"]["F_T_pairs_kmh"]
train.tractiveEffortVelocityPairs=checkAndDefineTractiveEffortInput(F_T_pairs_kmh, 1000/3600) tractiveEffortVelocityPairs=checkAndDefineTractiveEffortInput(F_T_pairs_kmh, 1000/3600)
#= old 2021-11-04: now it is pairs and no scope
# check if the elements of the array have the correct type
errorDetected=false
for row in 1:length(F_T_pairs_kmh)
if typeof(F_T_pairs_kmh[row][1]) <: Real && F_T_pairs_kmh[row][1]>=0.0
else
errorDetected=true
println("ERROR at reading the train yaml file: The speed value of F_T_pairs_kmh in row ", row ," is no real floating point number >=0.0.")
end
if typeof(F_T_pairs_kmh[row][2]) <: Real && F_T_pairs_kmh[row][2]>=0.0
else
errorDetected=true
println("ERROR at reading the train yaml file: The tractive effort value of F_T_pairs_kmh in row ", row ," is no real floating point number >=0.0.")
end
end # for
if errorDetected
error("ERROR at reading the train yaml file: Only real floating point number >=0.0 are allowed for speed and tractive effort in F_T_pairs_kmh.")
end
# create tractiveEffortArray
train.tractiveEffortArray=[]
if F_T_pairs_kmh[1][1]==0.0
push!(train.tractiveEffortArray, [F_T_pairs_kmh[1][1]/3.6, F_T_pairs_kmh[1][1]/3.6, F_T_pairs_kmh[1][2]])
elseif F_T_pairs_kmh[1][1]>0.0 # if there is no F_T for v=0.0, the first value is used
push!(train.tractiveEffortArray, [0.0, F_T_pairs_kmh[1][1]/3.6, F_T_pairs_kmh[1][2]])
println("WARNING at reading the train yaml file: The tractive effort for v=0 km/h is missing. Therefore the first given value F_T(v=",F_T_pairs_kmh[1][1]," km/h)=",F_T_pairs_kmh[1][2]," N will be used." )
end
for row in 2:length(F_T_pairs_kmh)
if F_T_pairs_kmh[row][1]>F_T_pairs_kmh[row-1][1]
if F_T_pairs_kmh[row][2]==train.tractiveEffortArray[end][3]
train.tractiveEffortArray[end][2]=F_T_pairs_kmh[row][1]/3.6
else
push!(train.tractiveEffortArray, [F_T_pairs_kmh[row][1]/3.6, F_T_pairs_kmh[row][1]/3.6, F_T_pairs_kmh[row][2]])
end
else
error("ERROR at reading the train yaml file: The F_T_pairs_kmh are not in the correct order. They have to be arranged by speed values from low to high.")
end
end # for
if length(F_T_pairs_kmh[1])>2
println("INFO at reading the train yaml file: Only the first two columns of F_T_pairs_kmh are used in this tool.")
end
=#
else else
error("ERROR at reading the train yaml file: There has to be one of the keywords F_T_pairs or F_T_pairs_kmh filled with a list of pairs of velocity and tractive effort.") error("ERROR at reading the train yaml file: There has to be one of the keywords F_T_pairs or F_T_pairs_kmh filled with a list of pairs of velocity and tractive effort.")
end # if end # if
@ -317,17 +213,17 @@ function inputTrain(trainDirectory::String)
# coefficients for the vehicle resistance of the traction unit # coefficients for the vehicle resistance of the traction unit
# coefficient for velocitiy difference between traction unit and outdoor air # coefficient for velocitiy difference between traction unit and outdoor air
train.Δv_t=15.0/3.6 Δv_t=15.0/3.6
# coefficient for basic resistance due to the traction units driving axles (in ‰) # coefficient for basic resistance due to the traction units driving axles (in ‰)
if haskey(data["train"],"f_Rtd0") && data["train"]["f_Rtd0"]!=nothing if haskey(data["train"],"f_Rtd0") && data["train"]["f_Rtd0"]!=nothing
if typeof(data["train"]["f_Rtd0"]) <: Real && data["train"]["f_Rtd0"]>=0.0 if typeof(data["train"]["f_Rtd0"]) <: Real && data["train"]["f_Rtd0"]>=0.0
train.f_Rtd0=data["train"]["f_Rtd0"] f_Rtd0=data["train"]["f_Rtd0"]
else else
error("ERROR at reading the train yaml file: The value of f_Rtd0 is no real floating point number >=0.0.") error("ERROR at reading the train yaml file: The value of f_Rtd0 is no real floating point number >=0.0.")
end end
else else
train.f_Rtd0=0.0 f_Rtd0=0.0
println("WARNING at reading the train yaml file: The keyword f_Rtd0 is missing. Therefore f_Rtd0=0.0 ‰ will be assumed and used." ) println("WARNING at reading the train yaml file: The keyword f_Rtd0 is missing. Therefore f_Rtd0=0.0 ‰ will be assumed and used." )
end end
delete!(data["train"], "f_Rtd0") delete!(data["train"], "f_Rtd0")
@ -335,12 +231,12 @@ function inputTrain(trainDirectory::String)
# coefficient for basic resistance due to the traction units carring axles (in ‰) # coefficient for basic resistance due to the traction units carring axles (in ‰)
if haskey(data["train"],"f_Rtc0") && data["train"]["f_Rtc0"]!=nothing if haskey(data["train"],"f_Rtc0") && data["train"]["f_Rtc0"]!=nothing
if typeof(data["train"]["f_Rtc0"]) <: Real && data["train"]["f_Rtc0"]>=0.0 if typeof(data["train"]["f_Rtc0"]) <: Real && data["train"]["f_Rtc0"]>=0.0
train.f_Rtc0=data["train"]["f_Rtc0"] f_Rtc0=data["train"]["f_Rtc0"]
else else
error("ERROR at reading the train yaml file: The value of f_Rtc0 is no real floating point number >=0.0.") error("ERROR at reading the train yaml file: The value of f_Rtc0 is no real floating point number >=0.0.")
end end
else else
train.f_Rtc0=0.0 f_Rtc0=0.0
println("WARNING at reading the train yaml file: The keyword f_Rtc0 is missing. Therefore f_Rtc0=0.0 ‰ will be assumed and used." ) println("WARNING at reading the train yaml file: The keyword f_Rtc0 is missing. Therefore f_Rtc0=0.0 ‰ will be assumed and used." )
end end
delete!(data["train"], "f_Rtc0") delete!(data["train"], "f_Rtc0")
@ -348,12 +244,12 @@ function inputTrain(trainDirectory::String)
# coefficient for air resistance of the traction units (in N) # coefficient for air resistance of the traction units (in N)
if haskey(data["train"],"F_Rt2") && data["train"]["F_Rt2"]!=nothing if haskey(data["train"],"F_Rt2") && data["train"]["F_Rt2"]!=nothing
if typeof(data["train"]["F_Rt2"]) <: Real && data["train"]["F_Rt2"]>=0.0 if typeof(data["train"]["F_Rt2"]) <: Real && data["train"]["F_Rt2"]>=0.0
train.F_Rt2=data["train"]["F_Rt2"] F_Rt2=data["train"]["F_Rt2"]
else else
error("ERROR at reading the train yaml file: The value of F_Rt2 is no real floating point number >=0.0.") error("ERROR at reading the train yaml file: The value of F_Rt2 is no real floating point number >=0.0.")
end end
else else
train.F_Rt2=0.0 F_Rt2=0.0
println("WARNING at reading the train yaml file: The keyword F_Rt2 is missing. Therefore F_Rt2=0.0 N will be assumed and used." ) println("WARNING at reading the train yaml file: The keyword F_Rt2 is missing. Therefore F_Rt2=0.0 N will be assumed and used." )
end end
delete!(data["train"], "F_Rt2") delete!(data["train"], "F_Rt2")
@ -363,21 +259,21 @@ function inputTrain(trainDirectory::String)
# coefficients for the vehicle resistance of the consist (set of wagons) # coefficients for the vehicle resistance of the consist (set of wagons)
# coefficient for velocitiy difference between consist (set of wagons) and outdoor air (in m/s) # coefficient for velocitiy difference between consist (set of wagons) and outdoor air (in m/s)
if train.trainType=="passenger" || train.trainType=="motor coach train" if trainType=="passenger" || trainType=="motor coach train"
train.Δv_w=15.0/3.6 Δv_w=15.0/3.6
elseif train.trainType== "freight" elseif trainType== "freight"
train.Δv_w=0.0 Δv_w=0.0
end # if end # if
# coefficient for basic resistance of the consist (set of wagons) (in ‰) # coefficient for basic resistance of the consist (set of wagons) (in ‰)
if haskey(data["train"],"f_Rw0") && data["train"]["f_Rw0"]!=nothing if haskey(data["train"],"f_Rw0") && data["train"]["f_Rw0"]!=nothing
if typeof(data["train"]["f_Rw0"]) <: Real && data["train"]["f_Rw0"]>=0.0 if typeof(data["train"]["f_Rw0"]) <: Real && data["train"]["f_Rw0"]>=0.0
train.f_Rw0=data["train"]["f_Rw0"] f_Rw0=data["train"]["f_Rw0"]
else else
error("ERROR at reading the train yaml file: The value of f_Rw0 is no real floating point number >=0.0.") error("ERROR at reading the train yaml file: The value of f_Rw0 is no real floating point number >=0.0.")
end end
else else
train.f_Rw0=0.0 f_Rw0=0.0
println("WARNING at reading the train yaml file: The keyword f_Rw0 is missing. Therefore f_Rw0=0.0 ‰ will be assumed and used." ) println("WARNING at reading the train yaml file: The keyword f_Rw0 is missing. Therefore f_Rw0=0.0 ‰ will be assumed and used." )
end end
delete!(data["train"], "f_Rw0") delete!(data["train"], "f_Rw0")
@ -385,12 +281,12 @@ function inputTrain(trainDirectory::String)
# coefficient for basic resistance of the consist (set of wagons) (in ‰) # coefficient for basic resistance of the consist (set of wagons) (in ‰)
if haskey(data["train"],"f_Rw1") && data["train"]["f_Rw1"]!=nothing if haskey(data["train"],"f_Rw1") && data["train"]["f_Rw1"]!=nothing
if typeof(data["train"]["f_Rw1"]) <: Real && data["train"]["f_Rw1"]>=0.0 if typeof(data["train"]["f_Rw1"]) <: Real && data["train"]["f_Rw1"]>=0.0
train.f_Rw1=data["train"]["f_Rw1"] f_Rw1=data["train"]["f_Rw1"]
else else
error("ERROR at reading the train yaml file: The value of f_Rw1 is no real floating point number >=0.0.") error("ERROR at reading the train yaml file: The value of f_Rw1 is no real floating point number >=0.0.")
end end
else else
train.f_Rw1=0.0 f_Rw1=0.0
println("WARNING at reading the train yaml file: The keyword f_Rw1 is missing. Therefore f_Rw1=0.0 ‰ will be assumed and used." ) println("WARNING at reading the train yaml file: The keyword f_Rw1 is missing. Therefore f_Rw1=0.0 ‰ will be assumed and used." )
end end
delete!(data["train"], "f_Rw1") delete!(data["train"], "f_Rw1")
@ -398,12 +294,12 @@ function inputTrain(trainDirectory::String)
# coefficient for basic resistance of the consist (set of wagons) (in ‰) # coefficient for basic resistance of the consist (set of wagons) (in ‰)
if haskey(data["train"],"f_Rw2") && data["train"]["f_Rw2"]!=nothing if haskey(data["train"],"f_Rw2") && data["train"]["f_Rw2"]!=nothing
if typeof(data["train"]["f_Rw2"]) <: Real && data["train"]["f_Rw2"]>=0.0 if typeof(data["train"]["f_Rw2"]) <: Real && data["train"]["f_Rw2"]>=0.0
train.f_Rw2=data["train"]["f_Rw2"] f_Rw2=data["train"]["f_Rw2"]
else else
error("ERROR at reading the train yaml file: The value of f_Rw2 is no real floating point number >=0.0.") error("ERROR at reading the train yaml file: The value of f_Rw2 is no real floating point number >=0.0.")
end end
else else
train.f_Rw2=0.0 f_Rw2=0.0
println("WARNING at reading the train yaml file: The keyword f_Rw2 is missing. Therefore f_Rw2=0.0 ‰ will be assumed and used." ) println("WARNING at reading the train yaml file: The keyword f_Rw2 is missing. Therefore f_Rw2=0.0 ‰ will be assumed and used." )
end end
delete!(data["train"], "f_Rw2") delete!(data["train"], "f_Rw2")
@ -417,6 +313,39 @@ function inputTrain(trainDirectory::String)
end end
end end
# create the train Dictionary
train= Dict(:name => name, # train's name
:id => id, # train's identifier
:trainType => trainType, # type of train "passenger" or "freight" or "motor coach train"
:l_train => l_train, # total length (in m)
:v_limit => v_limit, # trains speed limit (in m/s)
:a_braking => a_braking, # braking acceleration (in m/s^2)
:m_train => m_train, # total mass (in kg)
:ξ_train => ξ_train, # rotation mass factor of the whole train (without unit)
# if not available use ξ_t and ξ_w
# traction unit
:m_t => m_t, # mass of the traction unit (in kg)
:m_td => m_td, # mass on the traction units driving axles (in kg)
:m_tc => m_tc, # mass on the traction units carrying axles (in kg)
:ξ_t => ξ_t, # rotation mass factor of the traction unit (without unit)
# in case ξ_train is not available
:tractiveEffortVelocityPairs => tractiveEffortVelocityPairs, # list of velocities and their corresponding tractive effort (in [m/s , N])
:f_Rtd0 => f_Rtd0, # coefficient for basic resistance due to the traction units driving axles (in ‰)
:f_Rtc0 => f_Rtc0, # coefficient for basic resistance due to the traction units carring axles (in ‰)
:F_Rt2 => F_Rt2, # coefficient for air resistance of the traction units (in N)
:Δv_t => Δv_t, # coefficient for velocitiy difference between traction unit and outdoor air
# set of wagons
:m_w => m_w, # mass of the set of wagons (in kg)
:ξ_w => ξ_w, # rotation mass factor of the set of wagons (without unit)
# in case ξ_train is not available
:f_Rw0 => f_Rw0, # coefficient for basic resistance of the set of wagons (in ‰)
:f_Rw1 => f_Rw1, # coefficient for resistance to rolling of the set of wagons (in ‰)
:f_Rw2 => f_Rw2, # coefficient for air resistance of the set of wagons (in ‰)
:Δv_w => Δv_w) # coefficient for velocitiy difference between set of wagons and outdoor air (in m/s)
return train return train
end #function inputTrain end #function inputTrain
@ -465,7 +394,7 @@ end #function checkAndDefineTractiveEffortInput
function inputPath(pathDirectory::String) function inputPath(pathDirectory::String)
# this function reads path information from a YAML file, saves it in a Path object and returns it # read path information from a YAML file, save it in a path Dict and return it
data = YAML.load(open(pathDirectory)) data = YAML.load(open(pathDirectory))
collect(keys(data)) collect(keys(data))
collect(values(data)) collect(values(data))
@ -479,7 +408,6 @@ function inputPath(pathDirectory::String)
delete!(data["path"], "name") delete!(data["path"], "name")
id=1 # path identifier id=1 # path identifier
path=Path(name, id, [])
# read the section starting positions and corresponding information # read the section starting positions and corresponding information
if haskey(data["path"],"sectionStarts") && data["path"]["sectionStarts"]!=nothing if haskey(data["path"],"sectionStarts") && data["path"]["sectionStarts"]!=nothing
@ -544,16 +472,22 @@ function inputPath(pathDirectory::String)
error("ERROR at reading the path yaml file: The values of ",valueKey," have to be corrected.") error("ERROR at reading the path yaml file: The values of ",valueKey," have to be corrected.")
end end
# save values in the path object # save values in the path Dict
sections=[]
for row in 2:length(sectionStartsArray) for row in 2:length(sectionStartsArray)
s_start=sectionStartsArray[row-1][1] # first point of the section (in m) s_start=sectionStartsArray[row-1][1] # first point of the section (in m)
s_end=sectionStartsArray[row][1] # first point of the next section (in m) s_end=sectionStartsArray[row][1] # first point of the next section (in m)
v_limit=sectionStartsArray[row-1][2]*conversionFactor # paths speed limt (in m/s) v_limit=sectionStartsArray[row-1][2]*conversionFactor # paths speed limt (in m/s)
f_Rp=sectionStartsArray[row-1][3] # specific path resistance of the section (in ‰) f_Rp=sectionStartsArray[row-1][3] # specific path resistance of the section (in ‰)
section=PathSection(s_start, s_end, v_limit, f_Rp) section=Dict(:s_start => s_start, :s_end => s_end, :v_limit => v_limit, :f_Rp => f_Rp)
push!(path.sections, section) push!(sections, section)
end # for end # for
# s_start in first entry defines the path's beginning
# s_end in last entry defines the path's ending
path = Dict(:name => name,
:id => id,
:sections => sections)
# inform the user which keywords of the input data are not used in this tool: # inform the user which keywords of the input data are not used in this tool:
if length(data["path"])>0 if length(data["path"])>0
@ -567,19 +501,28 @@ end # function inputPath
## settings for the calculation
function inputSettings(settingsDirectory::String) function inputSettings(settingsDirectory::String)
# this function reads setting information from a YAML file, saves it in a Setting object and returns it # read setting information from a YAML file, save it in a settings Dict and return it
data = YAML.load(open(settingsDirectory)) data = YAML.load(open(settingsDirectory))
collect(keys(data)) collect(keys(data))
collect(values(data)) collect(values(data))
settings=Settings() # initialize the settings Dictionary
settings = Dict(:massModel => "", # model type of the unions mass "mass point" or "homogeneous strip"
:stepVariable => "", # step variable of the step method "s in m", "t in s" or "v in m/s"
:stepSize => 0.0, # step size (unit depends on steapVariable s in m, t in s and v in m/s)
:operationModeMinimumRunningTime => false, # operation mode "minimum running time"
:operationModeMinimumEnergyConsumption => false, # operation mode "minimum energy consumption"
:typeOfOutput => "", # output as "julia dictionary" or as "CSV"
:csvDirectory => "", # path of the folder in which the CSV files willl be saved
:detailOfOutput => "") # detail of output "minimal" or "everything"
# model type of the train's mass "mass point" or "homogeneous strip" # model type of the train's mass "mass point" or "homogeneous strip"
if haskey(data["settings"],"massModel") if haskey(data["settings"],"massModel")
if typeof(data["settings"]["massModel"])==String && (data["settings"]["massModel"]=="mass point" || data["settings"]["massModel"]=="homogeneous strip") if typeof(data["settings"]["massModel"])==String && (data["settings"]["massModel"]=="mass point" || data["settings"]["massModel"]=="homogeneous strip")
settings.massModel=data["settings"]["massModel"] # "mass point" or "homogeneous strip" # 12/15 old, not needed if already initialized: merge!(settings, Dict(:massModel => data["settings"]["massModel"])) # "mass point" or "homogeneous strip"
settings[:massModel] = data["settings"]["massModel"] # "mass point" or "homogeneous strip"
else else
error("ERROR at reading the settings yaml file: The value of massModel is wrong. It has to be mass point or homogeneous strip.") error("ERROR at reading the settings yaml file: The value of massModel is wrong. It has to be mass point or homogeneous strip.")
end end
@ -589,11 +532,11 @@ function inputSettings(settingsDirectory::String)
delete!(data["settings"], "massModel") delete!(data["settings"], "massModel")
# step variable of the step method "s in m", "t in s" or "v in m/s" # step variable of the step method "s in m", "t in s" or "v in m/s"
if haskey(data["settings"],"stepVariable") if haskey(data["settings"],"stepVariable")
if typeof(data["settings"]["stepVariable"])==String && (data["settings"]["stepVariable"]=="s in m" || data["settings"]["stepVariable"]=="t in s" || data["settings"]["stepVariable"]=="v in m/s") if typeof(data["settings"]["stepVariable"])==String && (data["settings"]["stepVariable"]=="s in m" || data["settings"]["stepVariable"]=="t in s" || data["settings"]["stepVariable"]=="v in m/s")
settings.stepVariable=data["settings"]["stepVariable"] # "s in m", "t in s" or "v in m/s" # 12/15 old, not needed if already initialized: merge!(settings, Dict(:stepVariable => data["settings"]["stepVariable"])) # "s in m", "t in s" or "v in m/s"
settings[:stepVariable] = data["settings"]["stepVariable"] # "s in m", "t in s" or "v in m/s"
else else
error("ERROR at reading the settings yaml file: The value of stepVariable is wrong. It has to be s in m, t in s or v in m/s.") error("ERROR at reading the settings yaml file: The value of stepVariable is wrong. It has to be s in m, t in s or v in m/s.")
end end
@ -603,10 +546,11 @@ function inputSettings(settingsDirectory::String)
delete!(data["settings"], "stepVariable") delete!(data["settings"], "stepVariable")
# step size (unit depends on steapVariable: s in m, t in s and v in m/s) # step size (unit depends on steapVariable: s in m, t in s and v in m/s)
if haskey(data["settings"],"stepSize") if haskey(data["settings"],"stepSize")
if typeof(data["settings"]["stepSize"]) <: Real && data["settings"]["stepSize"]>0.0 if typeof(data["settings"]["stepSize"]) <: Real && data["settings"]["stepSize"]>0.0
settings.stepSize=data["settings"]["stepSize"] # 12/15 old, not needed if already initialized: merge!(settings, Dict(:stepSize => data["settings"]["stepSize"]))
settings[:stepSize] = data["settings"]["stepSize"]
else else
error("ERROR at reading the settings yaml file: The value of the stepSize is no real floating point number >0.0.") error("ERROR at reading the settings yaml file: The value of the stepSize is no real floating point number >0.0.")
end end
@ -616,17 +560,17 @@ function inputSettings(settingsDirectory::String)
delete!(data["settings"], "stepSize") delete!(data["settings"], "stepSize")
# operation mode "minimum running time" # operation mode "minimum running time"
if haskey(data["settings"],"operationModeMinimumRunningTime") && data["settings"]["operationModeMinimumRunningTime"]!=nothing if haskey(data["settings"],"operationModeMinimumRunningTime") && data["settings"]["operationModeMinimumRunningTime"]!=nothing
if typeof(data["settings"]["operationModeMinimumRunningTime"])==Bool if typeof(data["settings"]["operationModeMinimumRunningTime"])==Bool
settings.operationModeMinimumRunningTime=data["settings"]["operationModeMinimumRunningTime"] # 12/15 old, not needed if already initialized: merge!(settings, Dict(:operationModeMinimumRunningTime => data["settings"]["operationModeMinimumRunningTime"]))
settings[:operationModeMinimumRunningTime] = data["settings"]["operationModeMinimumRunningTime"]
else else
error("ERROR at reading the settings yaml file: The value of the keyword operationModeMinimumRunningTime is not correct. The value has to be of type boolean.") error("ERROR at reading the settings yaml file: The value of the keyword operationModeMinimumRunningTime is not correct. The value has to be of type boolean.")
end end
else else
settings.operationModeMinimumRunningTime=false settings[:operationModeMinimumRunningTime]=false
println("WARNING at reading the settings yaml file: The keyword operationModeMinimumRunningTime or its value is missing. Therefore operationModeMinimumRunningTime=",settings.operationModeMinimumRunningTime," is assumed and used.") println("WARNING at reading the settings yaml file: The keyword operationModeMinimumRunningTime or its value is missing. Therefore operationModeMinimumRunningTime=",settings[:operationModeMinimumRunningTime]," is assumed and used.")
end end
delete!(data["settings"], "operationModeMinimumRunningTime") delete!(data["settings"], "operationModeMinimumRunningTime")
@ -634,20 +578,22 @@ function inputSettings(settingsDirectory::String)
# operation mode "minimum energy consumption" # operation mode "minimum energy consumption"
if haskey(data["settings"],"operationModeMinimumEnergyConsumption") && data["settings"]["operationModeMinimumEnergyConsumption"]!=nothing if haskey(data["settings"],"operationModeMinimumEnergyConsumption") && data["settings"]["operationModeMinimumEnergyConsumption"]!=nothing
if typeof(data["settings"]["operationModeMinimumEnergyConsumption"])==Bool if typeof(data["settings"]["operationModeMinimumEnergyConsumption"])==Bool
settings.operationModeMinimumEnergyConsumption=data["settings"]["operationModeMinimumEnergyConsumption"] # 12/15 old, not needed if already initialized: merge!(settings, Dict(:operationModeMinimumEnergyConsumption => data["settings"]["operationModeMinimumEnergyConsumption"]))
settings[:operationModeMinimumEnergyConsumption] = data["settings"]["operationModeMinimumEnergyConsumption"]
else else
error("ERROR at reading the settings yaml file: The value of the keyword operationModeMinimumEnergyConsumption is not correct. The value has to be of type boolean.") error("ERROR at reading the settings yaml file: The value of the keyword operationModeMinimumEnergyConsumption is not correct. The value has to be of type boolean.")
end end
else else
settings.operationModeMinimumEnergyConsumption=false settings[:operationModeMinimumEnergyConsumption] = false
println("WARNING at reading the settings yaml file: The keyword operationModeMinimumEnergyConsumption or its value is missing. Therefore operationModeMinimumEnergyConsumption=",settings.operationModeMinimumEnergyConsumption," is assumed and used.") println("WARNING at reading the settings yaml file: The keyword operationModeMinimumEnergyConsumption or its value is missing. Therefore operationModeMinimumEnergyConsumption=", settings[:operationModeMinimumEnergyConsumption]," is assumed and used.")
end end
delete!(data["settings"], "operationModeMinimumEnergyConsumption") delete!(data["settings"], "operationModeMinimumEnergyConsumption")
# output as "julia dictionary" or as "CSV" # output as "julia dictionary" or as "CSV"
if haskey(data["settings"],"typeOfOutput") if haskey(data["settings"],"typeOfOutput")
if typeof(data["settings"]["typeOfOutput"])==String && (data["settings"]["typeOfOutput"]=="julia dictionary" || data["settings"]["typeOfOutput"]=="CSV") if typeof(data["settings"]["typeOfOutput"])==String && (data["settings"]["typeOfOutput"]=="julia dictionary" || data["settings"]["typeOfOutput"]=="CSV")
settings.typeOfOutput=data["settings"]["typeOfOutput"] # "julia dictionary" or "CSV" # 12/15 old, not needed if already initialized: merge!(settings, Dict(:typeOfOutput => data["settings"]["typeOfOutput"])) # "julia dictionary" or "CSV"
settings[:typeOfOutput] = data["settings"]["typeOfOutput"] # "julia dictionary" or "CSV"
else else
error("ERROR at reading the settings yaml file: The value of typeOfOutput is wrong. It has to be julia dictionary or CSV.") error("ERROR at reading the settings yaml file: The value of typeOfOutput is wrong. It has to be julia dictionary or CSV.")
end end
@ -657,10 +603,11 @@ function inputSettings(settingsDirectory::String)
delete!(data["settings"], "typeOfOutput") delete!(data["settings"], "typeOfOutput")
# TODO: it could be checked if the path is existing on the pc # TODO: it could be checked if the path is existing on the pc
if settings.typeOfOutput=="CSV" if settings[:typeOfOutput] == "CSV"
if haskey(data["settings"],"csvDirectory") if haskey(data["settings"],"csvDirectory")
if typeof(data["settings"]["csvDirectory"])==String if typeof(data["settings"]["csvDirectory"])==String
settings.csvDirectory=data["settings"]["csvDirectory"] # 12/15 old, not needed if already initialized: merge!(settings, Dict(:csvDirectory => data["settings"]["csvDirectory"]))
settings[:csvDirectory] = data["settings"]["csvDirectory"]
else else
error("ERROR at reading the settings yaml file: The value of csvDirectory is wrong. It has to be of type String.") error("ERROR at reading the settings yaml file: The value of csvDirectory is wrong. It has to be of type String.")
end end
@ -673,8 +620,9 @@ function inputSettings(settingsDirectory::String)
# should the output be "minimal" or "driving course" # should the output be "minimal" or "driving course"
if haskey(data["settings"],"detailOfOutput") if haskey(data["settings"],"detailOfOutput")
if typeof(data["settings"]["detailOfOutput"])==String && (data["settings"]["detailOfOutput"]=="minimal" || data["settings"]["detailOfOutput"]=="driving course") if typeof(data["settings"]["detailOfOutput"])==String && (data["settings"]["detailOfOutput"]=="minimal" || data["settings"]["detailOfOutput"]=="driving course")
settings.detailOfOutput=data["settings"]["detailOfOutput"] # "minimal" or "driving course" # 12/15 old, not needed if already initialized: merge!(settings, Dict(:detailOfOutput => data["settings"]["detailOfOutput"])) # "minimal" or "driving course"
settings[:detailOfOutput] = data["settings"]["detailOfOutput"]
else else
error("ERROR at reading the settings yaml file: The value of detailOfOutput is wrong. It has to be minimal or driving course.") error("ERROR at reading the settings yaml file: The value of detailOfOutput is wrong. It has to be minimal or driving course.")
end end

File diff suppressed because it is too large Load Diff

View File

@ -12,95 +12,96 @@ export calculateMinimumRunningTime!, calculateMinimumEnergyConsumption
approximationLevel = 6 # TODO: define it in TrainRun and give it to each function? approximationLevel = 6 # TODO: define it in TrainRun and give it to each function?
# calculate a train run focussing on using the minimum possible running time # calculate a train run focussing on using the minimum possible running time
function calculateMinimumRunningTime!(movingSection::MovingSection, settings::Settings, train::Train) function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict)
# CSs=movingSection.characteristicSections CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
startingPoint=DataPoint() startingPoint=DataPoint()
startingPoint.i=1 startingPoint.i=1
startingPoint.s=movingSection.characteristicSections[1].s_entry startingPoint.s=CSs[1].s_entry
drivingCourse=[startingPoint] # List of data points drivingCourse=[startingPoint] # List of data points
# for CS in CSs # for CS in CSs
for csId in 1:length(movingSection.characteristicSections) for csId in 1:length(CSs)
# println("CS",csId) # println("CS",csId)
# check if the CS has a cruising section # check if the CS has a cruising section
s_breakFree=get(movingSection.characteristicSections[csId].behaviorSections, "breakFree", BehaviorSection()).length s_breakFree = get(CSs[csId].behaviorSections, :breakFree, BehaviorSection()).length
s_clearing=get(movingSection.characteristicSections[csId].behaviorSections, "clearing", BehaviorSection()).length s_clearing = get(CSs[csId].behaviorSections, :clearing, BehaviorSection()).length
s_acceleration=get(movingSection.characteristicSections[csId].behaviorSections, "acceleration", BehaviorSection()).length s_acceleration = get(CSs[csId].behaviorSections, :acceleration, BehaviorSection()).length
s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-movingSection.characteristicSections[csId].v_target^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((CSs[csId].v_exit^2-CSs[csId].v_target^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=movingSection.characteristicSections[csId].length-s_breakFree-s_clearing-s_acceleration-s_braking s_cruising=CSs[csId].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_target and v_exit # reset the moving section (MS), delete characteristic sections (CS) that were used during the preperation for setting v_entry, v_target and v_exit
delete!(movingSection.characteristicSections[csId].behaviorSections, "breakFree") delete!(CSs[csId].behaviorSections, :breakFree)
delete!(movingSection.characteristicSections[csId].behaviorSections, "clearing") delete!(CSs[csId].behaviorSections, :clearing)
delete!(movingSection.characteristicSections[csId].behaviorSections, "acceleration") delete!(CSs[csId].behaviorSections, :acceleration)
delete!(movingSection.characteristicSections[csId].behaviorSections, "diminishing") delete!(CSs[csId].behaviorSections, :diminishing)
delete!(movingSection.characteristicSections[csId].behaviorSections, "cruising") delete!(CSs[csId].behaviorSections, :cruising)
movingSection.characteristicSections[csId].E=0.0 CSs[csId].E=0.0
movingSection.characteristicSections[csId].t=0.0 CSs[csId].t=0.0
if s_clearing == movingSection.characteristicSections[csId].length if s_clearing == CSs[csId].length
# 09/06 TODO: thought about using "cruising" because it is used in EnergySaving and not clearing (movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_clearing, settings, train, movingSection.characteristicSections, "cruising") # 09/06 TODO: thought about using "cruising" because it is used in EnergySaving and not clearing (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_clearing, settings, train, CSs, "cruising")
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_clearing, settings, train, movingSection.characteristicSections, "clearing") (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_clearing, settings, train, CSs, "clearing")
elseif s_cruising == movingSection.characteristicSections[csId].length elseif s_cruising == CSs[csId].length
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, train, movingSection.characteristicSections, "cruising") (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising")
elseif s_cruising > 0.0 || s_braking == 0.0 elseif s_cruising > 0.0 || s_braking == 0.0
# 09/21 elseif s_cruising > 0.0 # 09/21 elseif s_cruising > 0.0
# 09/21 elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0) # 09/21 elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0)
if drivingCourse[end].v < movingSection.characteristicSections[csId].v_target if drivingCourse[end].v < CSs[csId].v_target
(movingSection.characteristicSections[csId], drivingCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections) (CSs[csId], drivingCourse)=addAccelerationPhase!(CSs[csId], drivingCourse, settings, train, CSs)
end #if end #if
if movingSection.characteristicSections[csId].s_exit-drivingCourse[end].s-max(0.0, (movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/train.a_braking) < -0.001 # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors if CSs[csId].s_exit-drivingCourse[end].s-max(0.0, (CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking]) < -0.001 # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
println("ERROR: After accelerating in CS ",csId," the braking distance is too short!") println("ERROR: After accelerating in CS ",csId," the braking distance is too short!")
println(" before acceleration in CS",csId, " with s=",drivingCourse[end].s," s_braking=",((movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/train.a_braking)," s_exit=",movingSection.characteristicSections[csId].s_exit) println(" before acceleration in CS",csId, " with s=",drivingCourse[end].s," s_braking=",((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking])," s_exit=",CSs[csId].s_exit)
println(" and v=",drivingCourse[end].v," v_target=",movingSection.characteristicSections[csId].v_target," v_exit=",movingSection.characteristicSections[csId].v_exit) println(" and v=",drivingCourse[end].v," v_target=",CSs[csId].v_target," v_exit=",CSs[csId].v_exit)
end end
s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=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((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
s_cruising=movingSection.characteristicSections[csId].s_exit-drivingCourse[end].s-s_braking s_cruising=CSs[csId].s_exit-drivingCourse[end].s-s_braking
if s_cruising > 0.0 if s_cruising > 0.0
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, train, movingSection.characteristicSections, "cruising") (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising")
end end
else else
if movingSection.characteristicSections[csId].v_entry < movingSection.characteristicSections[csId].v_target || s_acceleration > 0.0 # or instead of " || s_acceleration > 0.0" use "v_entry <= v_target" or "v_i <= v_target" if CSs[csId].v_entry < CSs[csId].v_target || s_acceleration > 0.0 # or instead of " || s_acceleration > 0.0" use "v_entry <= v_target" or "v_i <= v_target"
# 09/09 old (not sufficient for steep gradients): if movingSection.characteristicSections[csId].v_entry < movingSection.characteristicSections[csId].v_target # 09/09 old (not sufficient for steep gradients): if CSs[csId].v_entry < CSs[csId].v_target
(movingSection.characteristicSections[csId], drivingCourse)=addAccelerationPhaseUntilBraking!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections) (CSs[csId], drivingCourse)=addAccelerationPhaseUntilBraking!(CSs[csId], drivingCourse, settings, train, CSs)
end #if end #if
end #if end #if
s_braking=max(0.0, ceil((movingSection.characteristicSections[csId].v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=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((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
if drivingCourse[end].v > movingSection.characteristicSections[csId].v_exit if drivingCourse[end].v > CSs[csId].v_exit
#(movingSection.characteristicSections[csId], drivingCourse)=addBrakingPhase!(movingSection.characteristicSections[csId], drivingCourse, settings.massModel, train, movingSection.characteristicSections) #(CSs[csId], drivingCourse)=addBrakingPhase!(CSs[csId], drivingCourse, settings[:massModel], train, CSs)
(movingSection.characteristicSections[csId], drivingCourse)=addBrakingPhase!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections) (CSs[csId], drivingCourse)=addBrakingPhase!(CSs[csId], drivingCourse, settings, train, CSs)
end #if end #if
#= 09/20 old and should never be used: #= 09/20 old and should never be used:
if drivingCourse[end].s < movingSection.characteristicSections[csId].s_exit if drivingCourse[end].s < CSs[csId].s_exit
if haskey(movingSection.characteristicSections[csId].behaviorSections, "cruising") if haskey(CSs[csId].behaviorSections, :cruising)
println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_exit=",movingSection.characteristicSections[csId].s_exit) println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_exit=",CSs[csId].s_exit)
end end
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, train, movingSection.characteristicSections, "cruising") (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising")
end =# end =#
end #for end #for
# calculate the last data points resiting forces # calculate the last data points resiting forces
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, movingSection.characteristicSections, "braking")) drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "braking"))
movingSection.t=drivingCourse[end].t # total running time (in s) movingSection[:t] = drivingCourse[end].t # total running time (in s)
movingSection.E=drivingCourse[end].E # total energy consumption (in Ws) movingSection[:E] = drivingCourse[end].E # total energy consumption (in Ws)
return (movingSection, drivingCourse) return (movingSection, drivingCourse)
end #function calculateMinimumRunningTime end #function calculateMinimumRunningTime
function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumRunningTime::Vector{DataPoint}, settings::Settings, train::Train) function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict, drivingCourseMinimumRunningTime::Vector{DataPoint}, settings::Dict, train::Dict)
# calculate a train run focussing on using the minimum possible energy consumption # calculate a train run focussing on using the minimum possible energy consumption
# booleans for choosing which methods are used for saving energy # booleans for choosing which methods are used for saving energy
doMethod1=true doMethod1=true
@ -111,7 +112,8 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
#doCombinationOfMethods=false #doCombinationOfMethods=false
#create a new moving section for the minimum energy consumption #create a new moving section for the minimum energy consumption
movingSectionOriginal=MovingSection(movingSectionMinimumRunningTime) movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime)
CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections]
# create a new driving course for the minimum energy consumption # create a new driving course for the minimum energy consumption
drivingCourseOriginal=DataPoint[] drivingCourseOriginal=DataPoint[]
@ -120,15 +122,15 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
end end
# calculate the recovery time # calculate the recovery time
movingSectionOriginal.t_recovery=calculateRecoveryTime(movingSectionOriginal.length, movingSectionOriginal.t, train) movingSectionOriginal[:t_recovery]=calculateRecoveryTime(movingSectionOriginal[:length], movingSectionOriginal[:t], train)
movingSectionOriginal.t_recoveryAvailable=movingSectionOriginal.t_recovery movingSectionOriginal[:t_recoveryAvailable]=movingSectionOriginal[:t_recovery]
# create arrays for each method with all the available energy saving modifications # create arrays for each method with all the available energy saving modifications
energySavingModificationsWithCoasting=EnergySavingModification[] energySavingModificationsWithCoasting=EnergySavingModification[]
energySavingModificationsWithMaximumSpeed=EnergySavingModification[] energySavingModificationsWithMaximumSpeed=EnergySavingModification[]
energySavingModificationsWithCombination=EnergySavingModification[] energySavingModificationsWithCombination=EnergySavingModification[]
for csId in 1:length(movingSectionOriginal.characteristicSections) for csId in 1:length(CSsOrig)
# method 1: increase coasting # method 1: increase coasting
if doMethod1 == true if doMethod1 == true
modificationType = "increasing coasting" modificationType = "increasing coasting"
@ -151,62 +153,14 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
end #if end #if
end # for end # for
while movingSectionOriginal.t_recoveryAvailable > 0.0 while movingSectionOriginal[:t_recoveryAvailable] > 0.0
# comparison of modifications # comparison of modifications
ratioMax=0.0 ratioMax=0.0
csIdMax=0 csIdMax=0
typeMax="none" typeMax="none"
(energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax, movingSectionOriginal.t_recoveryAvailable) (energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax, movingSectionOriginal[:t_recoveryAvailable])
# 09/14 Three if cases for testing: (energySavingModificationsWithCoasting, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithCoasting, ratioMax, csIdMax, typeMax, movingSectionOriginal[:t_recoveryAvailable])
#= if length(movingSectionOriginal.energySavingModifications)==895 && ratioMax>0.0 (energySavingModificationsWithCombination, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithCombination, ratioMax, csIdMax, typeMax, movingSectionOriginal[:t_recoveryAvailable])
println("")
println("typeMax=",typeMax)
println("ratioMax=",ratioMax)
println("csIdMax=",csIdMax)
println("---")
println("type=",energySavingModificationsWithMaximumSpeed[csIdMax].type)
println(" csId=",energySavingModificationsWithMaximumSpeed[csIdMax].csId)
println(" ΔE=",energySavingModificationsWithMaximumSpeed[csIdMax].ΔE)
println(" Δt=",energySavingModificationsWithMaximumSpeed[csIdMax].Δt)
println(" ratio=",energySavingModificationsWithMaximumSpeed[csIdMax].ratio)
println(" DC-length=",length(energySavingModificationsWithMaximumSpeed[csIdMax].drivingCourseModified))
end
=#
(energySavingModificationsWithCoasting, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithCoasting, ratioMax, csIdMax, typeMax, movingSectionOriginal.t_recoveryAvailable)
#= if length(movingSectionOriginal.energySavingModifications)==895 && ratioMax>0.0
println("typeMax=",typeMax)
println("ratioMax=",ratioMax)
println("csIdMax=",csIdMax)
println("---")
println("type=",energySavingModificationsWithCoasting[csIdMax].type)
println(" csId=",energySavingModificationsWithCoasting[csIdMax].csId)
println(" ΔE=",energySavingModificationsWithCoasting[csIdMax].ΔE)
println(" Δt=",energySavingModificationsWithCoasting[csIdMax].Δt)
println(" ratio=",energySavingModificationsWithCoasting[csIdMax].ratio)
println(" DC-length=",length(energySavingModificationsWithCoasting[csIdMax].drivingCourseModified))
end
=#
(energySavingModificationsWithCombination, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithCombination, ratioMax, csIdMax, typeMax, movingSectionOriginal.t_recoveryAvailable)
#= if length(movingSectionOriginal.energySavingModifications)==895 && ratioMax>0.0
println("typeMax=",typeMax)
println("ratioMax=",ratioMax)
println("csIdMax=",csIdMax)
println("---")
println("type=",energySavingModificationsWithCombination[csIdMax].type)
println(" csId=",energySavingModificationsWithCombination[csIdMax].csId)
println(" ΔE=",energySavingModificationsWithCombination[csIdMax].ΔE)
println(" Δt=",energySavingModificationsWithCombination[csIdMax].Δt)
println(" ratio=",energySavingModificationsWithCombination[csIdMax].ratio)
println(" DC-length=",length(energySavingModificationsWithCombination[csIdMax].drivingCourseModified))
end
=#
# select the most efficient modification and update the original characteristicSection, drivingCourse and movingSection # select the most efficient modification and update the original characteristicSection, drivingCourse and movingSection
@ -214,53 +168,39 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
if typeMax=="none" if typeMax=="none"
break break
elseif typeMax=="increasing coasting" elseif typeMax=="increasing coasting"
# println("Energy saving modification number ",length(movingSectionOriginal.energySavingModifications)+1," (coasting) in CS ",csIdMax ," Δt=",energySavingModificationsWithCoasting[csIdMax].Δt," ΔE=", energySavingModificationsWithCoasting[csIdMax].ΔE," t_recoveryAvailable=", movingSectionOriginal.t_recoveryAvailable-energySavingModificationsWithCoasting[csIdMax].Δt) # println("Energy saving modification number ",length(movingSectionOriginal[:energySavingModifications])+1," (coasting) in CS ",csIdMax ," Δt=",energySavingModificationsWithCoasting[csIdMax].Δt," ΔE=", energySavingModificationsWithCoasting[csIdMax].ΔE," t_recoveryAvailable=", movingSectionOriginal[:t_recoveryAvailable]-energySavingModificationsWithCoasting[csIdMax].Δt)
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithCoasting[csIdMax]) push!(movingSectionOriginal[:energySavingModifications], energySavingModificationsWithCoasting[csIdMax])
# println("Nr. ",length(movingSectionOriginal.energySavingModifications),": typeMax=increasing coasting") # println("Nr. ",length(movingSectionOriginal[:energySavingModifications]),": typeMax=increasing coasting")
elseif typeMax=="decreasing maximum velocity" elseif typeMax=="decreasing maximum velocity"
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithMaximumSpeed[csIdMax]) push!(movingSectionOriginal[:energySavingModifications], energySavingModificationsWithMaximumSpeed[csIdMax])
# println("Nr. ",length(movingSectionOriginal.energySavingModifications),": typeMax=decreasing maximum velocity") # println("Nr. ",length(movingSectionOriginal[:energySavingModifications]),": typeMax=decreasing maximum velocity")
elseif typeMax=="combination of energy saving methods" elseif typeMax=="combination of energy saving methods"
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithCombination[csIdMax]) push!(movingSectionOriginal[:energySavingModifications], energySavingModificationsWithCombination[csIdMax])
# println("Nr. ",length(movingSectionOriginal.energySavingModifications),": typeMax=combination of energy saving methods") # println("Nr. ",length(movingSectionOriginal[:energySavingModifications]),": typeMax=combination of energy saving methods")
end #if end #if
movingSectionOriginal.t_recoveryAvailable = movingSectionOriginal.t_recoveryAvailable - movingSectionOriginal.energySavingModifications[end].Δt movingSectionOriginal[:t_recoveryAvailable] = movingSectionOriginal[:t_recoveryAvailable] - movingSectionOriginal[:energySavingModifications][end].Δt
lastIdOfSelectedCsOriginal = get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "braking", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "cruisingAfterCoasting", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "coasting", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "cruising", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "acceleration", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "clearing", get(movingSectionOriginal.characteristicSections[csIdMax].behaviorSections, "breakFree", BehaviorSection()))))))).dataPoints[end] lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax].behaviorSections, :standStill,
get(CSsOrig[csIdMax].behaviorSections, :braking,
get(CSsOrig[csIdMax].behaviorSections, :cruisingAfterCoasting,
get(CSsOrig[csIdMax].behaviorSections, :coasting,
get(CSsOrig[csIdMax].behaviorSections, :cruising,
get(CSsOrig[csIdMax].behaviorSections, :acceleration,
get(CSsOrig[csIdMax].behaviorSections, :clearing,
get(CSsOrig[csIdMax].behaviorSections, :breakFree,
get(CSsOrig[csIdMax].behaviorSections, :diminishing,
BehaviorSection()))))))))).dataPoints[end]
# if there is a diminishing phase its location must be analysed seperately because it could be before acceleration, between acceleration and cruising or after cruising. All the other behavior sections occur in a fixed order.
if haskey(CSsOrig[csIdMax].behaviorSections, :diminishing)
lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax].behaviorSections[:diminishing].dataPoints[end])
end
# create new driving course # create new driving course
drivingCourseNew=Vector{DataPoint}() drivingCourseNew=Vector{DataPoint}()
for i in 1:length(movingSectionOriginal.energySavingModifications[end].drivingCourseModified) for i in 1:length(movingSectionOriginal[:energySavingModifications][end].drivingCourseModified)
push!(drivingCourseNew, DataPoint(movingSectionOriginal.energySavingModifications[end].drivingCourseModified[i])) push!(drivingCourseNew, DataPoint(movingSectionOriginal[:energySavingModifications][end].drivingCourseModified[i]))
end
# # for testing if the modifications driving course and the original one have the same speed value at their transition point
# if lastIdOfSelectedCsOriginal+1<=drivingCourseOriginal[end].i
# if drivingCourseOriginal[lastIdOfSelectedCsOriginal].v-drivingCourseNew[end].v!=0.0
# println("INFO: Inconsistency while adding the CS",csIdMax," that has been modified for consuming less energy. The difference at its end is ",(drivingCourseOriginal[lastIdOfSelectedCsOriginal].v-drivingCourseNew[end].v)," m/s."
# end
# end # for testing
# for testing 09/09
if length(drivingCourseNew) == 0
#= println("typeMax=",typeMax)
println("ratioMax=",ratioMax)
println("csIdMax=",csIdMax)
println("---")
println("type=",energySavingModificationsWithCombination[csIdMax].type)
println(" csId=",energySavingModificationsWithCombination[csIdMax].csId)
println(" ΔE=",energySavingModificationsWithCombination[csIdMax].ΔE)
println(" Δt=",energySavingModificationsWithCombination[csIdMax].Δt)
println(" ratio=",energySavingModificationsWithCombination[csIdMax].ratio)
println(" DC-length=",length(energySavingModificationsWithCombination[csIdMax].drivingCourseModified))
=#
println("---")
println("energySavingModificationsWithCoasting:",length(energySavingModificationsWithCoasting[csIdMax].drivingCourseModified))
println("energySavingModificationsWithMaximumSpeed:",length(energySavingModificationsWithMaximumSpeed[csIdMax].drivingCourseModified))
println("energySavingModificationsWithCombination:",length(energySavingModificationsWithCombination[csIdMax].drivingCourseModified))
end end
#fill up the rest of the driving course with information from the original course #fill up the rest of the driving course with information from the original course
@ -287,19 +227,19 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
# 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
movingSectionOriginal.characteristicSections[csIdMax]=CharacteristicSection(movingSectionOriginal.energySavingModifications[end].csModified) CSsOrig[csIdMax]=CharacteristicSection(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)
# update all the data point references in the behaviour sections of the following characteristic sections and the other modified characteristic sections # update all the data point references in the behaviour sections of the following characteristic sections and the other modified characteristic sections
if difference!= 0 if difference!= 0
# update the data point references in the behaviour sections of the following characteristic sections # update the data point references in the behaviour sections of the following characteristic sections
allBs=["breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting","cruisingAfterCoasting", "braking", "standStill"] allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill]
for csId in csIdMax+1:length(movingSectionOriginal.characteristicSections) for csId in csIdMax+1:length(CSsOrig)
for bs in 1: length(allBs) for bs in 1: length(allBs)
if haskey(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs]) if haskey(CSsOrig[csId].behaviorSections, allBs[bs])
for point in 1:length(get(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).dataPoints) for point in 1:length(CSsOrig[csId].behaviorSections[allBs[bs]].dataPoints)
get(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).dataPoints[point]=get(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).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
@ -335,22 +275,23 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
end # while end # while
println("t_recoveryAvailable=",movingSectionOriginal.t_recoveryAvailable) println("t_recoveryAvailable=",movingSectionOriginal[:t_recoveryAvailable])
return (movingSectionOriginal, drivingCourseOriginal) return (movingSectionOriginal, drivingCourseOriginal)
end #function calculateMinimumEnergyConsumption end #function calculateMinimumEnergyConsumption
function modifyCs(movingSectionOriginal::MovingSection, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Settings, train::Train) function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Dict, train::Dict)
#println("drin: ",modificationType) CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections]
if modificationType == "increasing coasting" if modificationType == "increasing coasting"
# method 1: increase coasting # method 1: increase coasting
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=increaseCoastingSection(movingSectionOriginal.characteristicSections[csId], drivingCourseOriginal, settings, train, movingSectionOriginal.characteristicSections, movingSectionOriginal.t_recoveryAvailable) (characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=increaseCoastingSection(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable])
elseif modificationType == "decreasing maximum velocity" elseif modificationType == "decreasing maximum velocity"
# method 2: accelerate to a lower v_target # method 2: accelerate to a lower v_target
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=decreaseMaximumVelocity(movingSectionOriginal.characteristicSections[csId], drivingCourseOriginal, settings, train, movingSectionOriginal.characteristicSections, movingSectionOriginal.t_recoveryAvailable) (characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=decreaseMaximumVelocity(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable])
elseif modificationType == "combination of energy saving methods" elseif modificationType == "combination of energy saving methods"
# calculate the combination of the previous methods # calculate the combination of the previous methods
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=combineEnergySavingMethods(movingSectionOriginal.characteristicSections[csId], drivingCourseOriginal, settings, train, movingSectionOriginal.characteristicSections, movingSectionOriginal.t_recoveryAvailable) (characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=combineEnergySavingMethods(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable])
else else
return EnergySavingModification() return EnergySavingModification()
end end
@ -361,9 +302,9 @@ function modifyCs(movingSectionOriginal::MovingSection, drivingCourseOriginal::V
energySavingModification.type = modificationType # type of energy saving modification: "increasing coasting" or "decreasing maximum velocity" or "combination of energy saving methods" energySavingModification.type = modificationType # type of energy saving modification: "increasing coasting" or "decreasing maximum velocity" or "combination of energy saving methods"
energySavingModification.csModified = characteristicSectionModified # the modified characteristic section energySavingModification.csModified = characteristicSectionModified # the modified characteristic section
energySavingModification.drivingCourseModified = drivingCourseModifiedUntilEndOfModifiedCS # drivingCourse of the modified characteristic section energySavingModification.drivingCourseModified = drivingCourseModifiedUntilEndOfModifiedCS # drivingCourse of the modified characteristic section
energySavingModification.ΔE = movingSectionOriginal.characteristicSections[csId].E - energySavingModification.csModified.E # saved energy (in Ws) energySavingModification.ΔE = CSsOrig[csId].E - energySavingModification.csModified.E # saved energy (in Ws)
energySavingModification.Δt = energySavingModification.csModified.t - movingSectionOriginal.characteristicSections[csId].t # time loss (in s) energySavingModification.Δt = energySavingModification.csModified.t - CSsOrig[csId].t # time loss (in s)
if energySavingModification.Δt <= movingSectionOriginal.t_recoveryAvailable && energySavingModification.ΔE >= 0.0 if energySavingModification.Δt <= movingSectionOriginal[:t_recoveryAvailable] && energySavingModification.ΔE >= 0.0
#*** TODO: check why "sign" is needed here #*** TODO: check why "sign" is needed here
# if modificationType == "combination of energy saving methods" # if modificationType == "combination of energy saving methods"
energySavingModification.ratio=sign(energySavingModification.Δt)*energySavingModification.ΔE/energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s) energySavingModification.ratio=sign(energySavingModification.Δt)*energySavingModification.ΔE/energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s)
@ -397,15 +338,15 @@ function findBestModification(energySavingModifications::Vector{EnergySavingModi
end #function findBestModification end #function findBestModification
function updateEnergySavingModifications(energySavingModifications::Vector{EnergySavingModification}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer) function updateEnergySavingModifications(energySavingModifications::Vector{EnergySavingModification}, 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]
difference = endOfModificationId-lastIdOfSelectedCsOriginal difference = endOfModificationId-lastIdOfSelectedCsOriginal
for modNr in csIdMax+1:length(energySavingModifications) for modNr in csIdMax+1:length(energySavingModifications)
if energySavingModifications[modNr].ratio>0 if energySavingModifications[modNr].ratio>0
# 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(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs]) if haskey(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs])
for point in 1:length(get(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).dataPoints) for point in 1:length(energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints)
get(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).dataPoints[point] = get(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).dataPoints[point]+difference energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints[point] = energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints[point]+difference
end end
end #if end #if
end #for end #for
@ -432,4 +373,28 @@ function updateEnergySavingModifications(energySavingModifications::Vector{Energ
return energySavingModifications return energySavingModifications
end #function updateEnergySavingModifications end #function updateEnergySavingModifications
function copyMovingSection(original::Dict)
CSsCopy = Vector{CharacteristicSection}()
for csId in 1:length(original[:characteristicSections])
push!(CSsCopy, CharacteristicSection(original[:characteristicSections][csId]))
end #for
ModificationsCopy = Vector{EnergySavingModification}()
for modId in 1:length(original[:energySavingModifications])
push!(ModificationsCopy, EnergySavingModification(original[:energySavingModifications][modId]))
end #for
copy = Dict(:id => original[:id], # identifier
:length => original[:length], # total length (in m)
:s_entry => original[:s_entry], # first position (in m)
:s_exit => original[:s_exit], # last position (in m)
:t => original[:t], # total running time (in s)
:E => original[:E], # total energy consumption (in Ws)
:t_recovery => original[:t_recovery], # total recovery time for energy-saving modifications (in s)
:t_recoveryAvailable => original[:t_recoveryAvailable], # still available recovery time for energy-saving modifications (in s)
:characteristicSections => CSsCopy, # list of containing characteristic sections
:energySavingModifications => ModificationsCopy) # list of containing all the used energy saving modifications
return copy
end #function copyMovingSection
end #module OperationModes end #module OperationModes

View File

@ -7,18 +7,18 @@ using CSV, DataFrames, Dates
export createOutput export createOutput
export plotDrivingCourse, printImportantValues, printSectionInformation # functions for showing results during the development export plotDrivingCourse, printImportantValues, printSectionInformation # functions for showing results during the development
function createOutput(settings::Settings, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::MovingSection) function createOutput(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::Dict)
# method of function createOutput for one operation mode # method of function createOutput for one operation mode
if settings.typeOfOutput == "CSV" if settings[:typeOfOutput] == "CSV"
return createOutputCsv(settings, pathName, trainName, drivingCourse, movingSection) return createOutputCsv(settings, pathName, trainName, drivingCourse, movingSection)
else else
return createOutputDict(settings, pathName, trainName, drivingCourse, movingSection) return createOutputDict(settings, pathName, trainName, drivingCourse, movingSection)
end end
end # funtion createOutput end # funtion createOutput
function createOutput(settings::Settings, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::MovingSection) function createOutput(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::Dict)
# method of function createOutput for two operation modes # method of function createOutput for two operation modes
if settings.typeOfOutput == "CSV" if settings[:typeOfOutput] == "CSV"
return createOutputCsv(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption) return createOutputCsv(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
else else
return createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption) return createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
@ -26,16 +26,16 @@ function createOutput(settings::Settings, pathName::String, trainName::String, d
end # funtion createOutput end # funtion createOutput
function createOutputDict(settings::Settings, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::MovingSection) function createOutputDict(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::Dict)
# method of function createOutputDict for one operation mode # method of function createOutputDict for one operation mode
if settings.operationModeMinimumRunningTime if settings[:operationModeMinimumRunningTime]
if settings.operationModeMinimumEnergyConsumption if settings[:operationModeMinimumEnergyConsumption]
operationMode="minimum running time and minimum energy consumption" operationMode="minimum running time and minimum energy consumption"
else else
operationMode="minimum running time" operationMode="minimum running time"
end end
else else
if settings.operationModeMinimumEnergyConsumption if settings[:operationModeMinimumEnergyConsumption]
operationMode="minimum energy consumption" operationMode="minimum energy consumption"
else else
# should never be the case # should never be the case
@ -44,17 +44,18 @@ function createOutputDict(settings::Settings, pathName::String, trainName::Strin
end end
end end
outputDict=Dict([("path name", pathName), ("train name", trainName), ("operation mode", operationMode), ("mass model", settings.massModel), ("step variable", settings.stepVariable), ("step size", settings.stepSize)]) outputDict=Dict([(:pathName, pathName), (:trainName, trainName), (:operationMode, operationMode), (:massModel, settings[:massModel]), (:stepVariable, settings[:stepVariable]), (:stepSize, settings[:stepSize])])
#outputDict=Dict([("path name", pathName), ("train name", trainName), ("operation mode", operationMode), ("mass model", settings[:massModel]), ("step variable", settings[:stepVariable]), ("step size", settings[:stepSize])])
# creating an output array # creating an output array
outputArray=Array{Any, 1}[] outputArray=Array{Any, 1}[]
if settings.detailOfOutput=="minimal" if settings[:detailOfOutput]=="minimal"
push!(outputArray, ["s (in m)", "t (in s)","E (in Ws)"]) # push header to outputArray push!(outputArray, ["s (in m)", "t (in s)","E (in Ws)"]) # push header to outputArray
row=[movingSection.length, movingSection.t, movingSection.E] row=[movingSection[:length], movingSection[:t], movingSection[:E]]
push!(outputArray, row) # push row to outputArray push!(outputArray, row) # push row to outputArray
elseif settings.detailOfOutput=="driving course" elseif settings[:detailOfOutput]=="driving course"
push!(outputArray, ["i", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArray push!(outputArray, ["i", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArray
for point in drivingCourse for point in drivingCourse
row=[point.i, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_consist, point.ΔW, point.W, point.ΔE, point.E, point.a] row=[point.i, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_consist, point.ΔW, point.W, point.ΔE, point.E, point.a]
@ -62,29 +63,29 @@ function createOutputDict(settings::Settings, pathName::String, trainName::Strin
end end
end end
if length(movingSection.energySavingModifications)>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption if length(movingSection[:energySavingModifications])>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption
merge!(outputDict, Dict("outputArrayMinimumEnergyConsumption"=>outputArray)) merge!(outputDict, Dict(:outputArrayMinimumEnergyConsumption => outputArray))
else else
merge!(outputDict, Dict("outputArrayMinimumRunningTime"=>outputArray)) merge!(outputDict, Dict(:outputArrayMinimumRunningTime => outputArray))
end end
println("The output dictionary has been created for ",operationMode,".") println("The output dictionary has been created for ", operationMode,".")
return outputDict return outputDict
end # function createOutputDict end # function createOutputDict
function createOutputDict(settings::Settings, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::MovingSection) function createOutputDict(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::Dict)
# method of function createOutputDict for two operation modes # method of function createOutputDict for two operation modes
if settings.operationModeMinimumRunningTime if settings[:operationModeMinimumRunningTime]
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime) outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime)
if settings.operationModeMinimumEnergyConsumption if settings[:operationModeMinimumEnergyConsumption]
# creating the second output array # creating the second output array
outputArrayMinimumEnergyConsumption=Array{Any, 1}[] outputArrayMinimumEnergyConsumption=Array{Any, 1}[]
if settings.detailOfOutput=="minimal" if settings[:detailOfOutput]=="minimal"
push!(outputArrayMinimumEnergyConsumption, ["s (in m)", "t (in s)","E (in Ws)"]) # push header to outputArrayMinimumEnergyConsumption push!(outputArrayMinimumEnergyConsumption, ["s (in m)", "t (in s)","E (in Ws)"]) # push header to outputArrayMinimumEnergyConsumption
row=[movingSectionMinimumEnergyConsumption.length, movingSectionMinimumEnergyConsumption.t, movingSectionMinimumEnergyConsumption.E] row=[movingSectionMinimumEnergyConsumption[:length], movingSectionMinimumEnergyConsumption[:t], movingSectionMinimumEnergyConsumption[:E]]
push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption
elseif settings.detailOfOutput=="driving course" elseif settings[:detailOfOutput]=="driving course"
push!(outputArrayMinimumEnergyConsumption, ["i", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArrayMinimumEnergyConsumption push!(outputArrayMinimumEnergyConsumption, ["i", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArrayMinimumEnergyConsumption
for point in drivingCourseMinimumEnergyConsumption for point in drivingCourseMinimumEnergyConsumption
row=[point.i, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_consist, point.ΔW, point.W, point.ΔE, point.E, point.a] row=[point.i, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_consist, point.ΔW, point.W, point.ΔE, point.E, point.a]
@ -92,7 +93,7 @@ function createOutputDict(settings::Settings, pathName::String, trainName::Strin
end end
end end
merge!(outputDict, Dict("outputArrayMinimumEnergyConsumption"=>outputArrayMinimumEnergyConsumption)) merge!(outputDict, Dict(:outputArrayMinimumEnergyConsumption => outputArrayMinimumEnergyConsumption))
end end
else else
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption) outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
@ -103,36 +104,36 @@ function createOutputDict(settings::Settings, pathName::String, trainName::Strin
end # function createOutputDict end # function createOutputDict
function createOutputCsv(settings::Settings, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::MovingSection) function createOutputCsv(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::Dict)
# method of function createOutputDict for one operation mode # method of function createOutputDict for one operation mode
outputDict=createOutputDict(settings, pathName, trainName, drivingCourse, movingSection) outputDict=createOutputDict(settings, pathName, trainName, drivingCourse, movingSection)
if length(movingSection.energySavingModifications)>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption if length(movingSection[:energySavingModifications])>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption
operationMode="minimum energy consumption" operationMode="minimum energy consumption"
outputArray="outputArrayMinimumEnergyConsumption" outputArray=:outputArrayMinimumEnergyConsumption
date = Dates.now() date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS") dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvDirectory*"/"*dateString*"_MinimumEnergyConsumption.csv" csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumEnergyConsumption.csv"
else else
operationMode="minimum running time" operationMode="minimum running time"
outputArray="outputArrayMinimumRunningTime" outputArray=:outputArrayMinimumRunningTime
date = Dates.now() date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS") dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvDirectory*"/"*dateString*"_MinimumRunningTime.csv" csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumRunningTime.csv"
end end
# creating information block # creating information block
infoColumns=Array{Any,1}[] infoColumns=Array{Any,1}[]
push!(infoColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""]) push!(infoColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""])
push!(infoColumns, [pathName, trainName, operationMode, settings.massModel, settings.stepVariable, string(settings.stepSize), ""]) push!(infoColumns, [pathName, trainName, operationMode, settings[:massModel], settings[:stepVariable], string(settings[:stepSize]), ""])
for column in 3:length(outputDict[outputArray][1]) for column in 3:length(outputDict[outputArray][1])
push!(infoColumns, ["", "", "", "", "", "", ""]) push!(infoColumns, ["", "", "", "", "", "", ""])
end # for end # for
allColumns=Array{Any,1}[] allColumns=Array{Any,1}[]
if settings.detailOfOutput=="minimal" if settings[:detailOfOutput]=="minimal"
header=outputDict["outputArrayMinimumRunningTime"][1] header=outputDict[:outputArrayMinimumRunningTime][1]
elseif settings.detailOfOutput=="driving course" elseif settings[:detailOfOutput]=="driving course"
header=["i", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"] header=["i", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
end end
for column in 1:length(outputDict[outputArray][1]) for column in 1:length(outputDict[outputArray][1])
@ -145,9 +146,9 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
# combining the columns in a data frame and saving it as a CSV-file at csvDirectory # combining the columns in a data frame and saving it as a CSV-file at csvDirectory
if settings.detailOfOutput=="minimal" if settings[:detailOfOutput]=="minimal"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3]) df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
elseif settings.detailOfOutput=="driving course" elseif settings[:detailOfOutput]=="driving course"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18]) df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18])
end end
CSV.write(csvFilePath, df, header=false) CSV.write(csvFilePath, df, header=false)
@ -156,89 +157,89 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
return outputDict return outputDict
end #function createOutputCsv end #function createOutputCsv
function createOutputCsv(settings::Settings, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::MovingSection) function createOutputCsv(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::Dict)
# method of function createOutputDict for two operation modes # method of function createOutputDict for two operation modes
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption) outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
if settings.operationModeMinimumRunningTime if settings[:operationModeMinimumRunningTime]
#creating information block #creating information block
infoColumns=Array{Any,1}[] infoColumns=Array{Any,1}[]
push!(infoColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""]) push!(infoColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""])
#push!(infoColumns, [pathName, trainName, "minimum running time", settings.massModel, settings.stepVariable, settings.stepSize, ""]) #push!(infoColumns, [pathName, trainName, "minimum running time", settings[:massModel], settings[:stepVariable], settings[:stepSize], ""])
push!(infoColumns, [pathName, trainName, "minimum running time", settings.massModel, settings.stepVariable, string(settings.stepSize), ""]) push!(infoColumns, [pathName, trainName, "minimum running time", settings[:massModel], settings[:stepVariable], string(settings[:stepSize]), ""])
for column in 3:length(outputDict["outputArrayMinimumRunningTime"][1]) for column in 3:length(outputDict[:outputArrayMinimumRunningTime][1])
push!(infoColumns, ["", "", "", "", "", "", ""]) push!(infoColumns, ["", "", "", "", "", "", ""])
# println("push wird ausgeführt") # println("push wird ausgeführt")
end # for end # for
allColumns=Array{Any,1}[] allColumns=Array{Any,1}[]
if settings.detailOfOutput=="minimal" if settings[:detailOfOutput]=="minimal"
header=outputDict["outputArrayMinimumRunningTime"][1] header=outputDict[:outputArrayMinimumRunningTime][1]
elseif settings.detailOfOutput=="driving course" elseif settings[:detailOfOutput]=="driving course"
header=["i", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"] header=["i", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
end end
for column in 1:length(outputDict["outputArrayMinimumRunningTime"][1]) for column in 1:length(outputDict[:outputArrayMinimumRunningTime][1])
push!(infoColumns[column], header[column]) push!(infoColumns[column], header[column])
for row in outputDict["outputArrayMinimumRunningTime"][2:end] for row in outputDict[:outputArrayMinimumRunningTime][2:end]
push!(infoColumns[column], row[column]) push!(infoColumns[column], row[column])
end end
push!(allColumns, infoColumns[column]) push!(allColumns, infoColumns[column])
end # for end # for
#combining the columns in a data frame and saving it as a CSV-file at csvDirectory #combining the columns in a data frame and saving it as a CSV-file at csvDirectory
if settings.detailOfOutput=="minimal" if settings[:detailOfOutput]=="minimal"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3]) df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
elseif settings.detailOfOutput=="driving course" elseif settings[:detailOfOutput]=="driving course"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18]) df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18])
end end
date = Dates.now() date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS") dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvDirectory*"/"*dateString*"_dataMinimumRunningTime.csv" csvFilePath=settings[:csvDirectory]*"/"*dateString*"_dataMinimumRunningTime.csv"
CSV.write(csvFilePath, df, header=false) CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created for minimum running time at ",csvFilePath) println("The output CSV file has been created for minimum running time at ",csvFilePath)
end #if settings.operationModeMinimumRunningTime end #if settings[:operationModeMinimumRunningTime]
if settings.operationModeMinimumEnergyConsumption if settings[:operationModeMinimumEnergyConsumption]
#creating information block #creating information block
infoColumns=Array{Any,1}[] infoColumns=Array{Any,1}[]
push!(infoColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""]) push!(infoColumns, ["path name", "train name", "operation mode", "mass model", "step variable", "step size", ""])
push!(infoColumns, [pathName, trainName, "minimum energy consumption", settings.massModel, settings.stepVariable, settings.stepSize, ""]) push!(infoColumns, [pathName, trainName, "minimum energy consumption", settings[:massModel], settings[:stepVariable], settings[:stepSize], ""])
for column in 3:length(outputDict["outputArrayMinimumEnergyConsumption"][1]) for column in 3:length(outputDict[:outputArrayMinimumEnergyConsumption][1])
push!(infoColumns, ["", "", "", "", "", "", ""]) push!(infoColumns, ["", "", "", "", "", "", ""])
end # for end # for
allColumns=Array{Any,1}[] allColumns=Array{Any,1}[]
if settings.detailOfOutput=="minimal" if settings[:detailOfOutput]=="minimal"
header=outputDict["outputArrayMinimumRunningTime"][1] header=outputDict[:outputArrayMinimumRunningTime][1]
elseif settings.detailOfOutput=="driving course" elseif settings[:detailOfOutput]=="driving course"
header=["i", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"] header=["i", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
end end
for column in 1:length(outputDict["outputArrayMinimumEnergyConsumption"][1]) for column in 1:length(outputDict[:outputArrayMinimumEnergyConsumption][1])
push!(infoColumns[column], header[column]) push!(infoColumns[column], header[column])
for row in outputDict["outputArrayMinimumEnergyConsumption"][2:end] for row in outputDict[:outputArrayMinimumEnergyConsumption][2:end]
push!(infoColumns[column], row[column]) push!(infoColumns[column], row[column])
end end
push!(allColumns, infoColumns[column]) push!(allColumns, infoColumns[column])
end # for end # for
#combining the columns in a data frame #combining the columns in a data frame
if settings.detailOfOutput=="minimal" if settings[:detailOfOutput]=="minimal"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3]) df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
elseif settings.detailOfOutput=="driving course" elseif settings[:detailOfOutput]=="driving course"
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18]) df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18])
end end
# creating a CSV-file at csvDirectory # creating a CSV-file at csvDirectory
date = Dates.now() date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS") dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvDirectory*"/"*dateString*"_dataMinimumEnergyConsumption.csv" csvFilePath=settings[:csvDirectory]*"/"*dateString*"_dataMinimumEnergyConsumption.csv"
CSV.write(csvFilePath, df, header=false) CSV.write(csvFilePath, df, header=false)
println("The output CSV file has been created for minimum energy consumption at ",csvFilePath) println("The output CSV file has been created for minimum energy consumption at ",csvFilePath)
end # if settings.operationModeMinimumEnergyConsumption end # if settings[:operationModeMinimumEnergyConsumption]
return outputDict return outputDict
end #function createOutputCsv end #function createOutputCsv
@ -253,16 +254,18 @@ function printImportantValues(drivingCourse::Vector{DataPoint})
println("i s in m v in km/h t in min a in m/s^2 F_R in k N F_T in k N E in k Wh") println("i s in m v in km/h t in min a in m/s^2 F_R in k N F_T in k N E in k Wh")
end #function printImportantValues end #function printImportantValues
function printSectionInformation(movingSection::MovingSection) function printSectionInformation(movingSection::Dict)
println("MS mit length=", movingSection.length," mit t=", movingSection.t) CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
allBs=["breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting","cruisingAfterCoasting", "braking", "standStill"]
for csId in 1:length(movingSection.characteristicSections) println("MS mit length=", movingSection[:length]," mit t=", movingSection[:t])
println("CS ",csId," mit length=", movingSection.characteristicSections[csId].length," mit t=", movingSection.characteristicSections[csId].t) allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill]
for csId in 1:length(CSs)
println("CS ",csId," mit length=", CSs[csId].length," mit t=", CSs[csId].t)
for bs in 1: length(allBs) for bs in 1: length(allBs)
if haskey(movingSection.characteristicSections[csId].behaviorSections, allBs[bs]) if haskey(CSs[csId].behaviorSections, allBs[bs])
println("BS ",allBs[bs], " mit s_entry=",get(movingSection.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).s_entry, " und t=",get(movingSection.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).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(get(movingSection.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).dataPoints) # for point in 1:length(CSs[csId].behaviorSections[allBs[bs]].dataPoints)
# println(get(movingSection.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).dataPoints[point]) # println(CSs[csId].behaviorSections[allBs[bs]].dataPoints[point])
# end # end
end #if end #if
end #for end #for
@ -287,21 +290,21 @@ function plotDrivingCourse(drivingCourse::Vector{DataPoint})
p2=plot([t], [v], title = "v in m/s", label = ["v"], xlabel = "t in s") p2=plot([t], [v], title = "v in m/s", label = ["v"], xlabel = "t in s")
# p3=plot([s], [t], title = "t in s", label = ["t"], xlabel = "s in m") # p3=plot([s], [t], title = "t in s", label = ["t"], xlabel = "s in m")
# p4=plot([t], [s], title = "s in m", label = ["s"], xlabel = "t in s") # p4=plot([t], [s], title = "s in m", label = ["s"], xlabel = "t in s")
p5=plot([s], [E], title = "E in Ws", label = ["E"], xlabel = "s in m") p5=plot([s], [E], title = "E in Ws", label = ["E"], xlabel = "s in m")
p6=plot([t], [E], title = "E in Ws", label = ["E"], xlabel = "t in s") p6=plot([t], [E], title = "E in Ws", label = ["E"], xlabel = "t in s")
all=plot(p1, p2, p5, p6, layout = (2, 2), legend = false) all=plot(p1, p2, p5, p6, layout = (2, 2), legend = false)
# all=plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false) # all=plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false)
display(all) display(all)
println("Plots for different variables have been created.") println("Plots for different variables have been created.")
end #function plotDrivingCourse end #function plotDrivingCourse
function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{DataPoint},drivingCourseMinimumEnergyConsumption::Vector{DataPoint}) #,movingSection1::MovingSection,movingSection2::MovingSection) function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{DataPoint},drivingCourseMinimumEnergyConsumption::Vector{DataPoint})
a_minTime=[] a_minTime=[]
E_minTime=[] E_minTime=[]
s_minTime=[] s_minTime=[]
@ -340,17 +343,17 @@ function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{DataPoint},dr
label = ["v for t_min" "v for E_min"], label = ["v for t_min" "v for E_min"],
xlabel = "t in s") xlabel = "t in s")
# p3=plot([s_minTime,s_minEnergy], # p3=plot([s_minTime,s_minEnergy],
# [t_minTime,t_minEnergy], # [t_minTime,t_minEnergy],
# title = "t in s", # title = "t in s",
# label = ["t for t_min" "t for E_min"], # label = ["t for t_min" "t for E_min"],
# xlabel = "s in m") # xlabel = "s in m")
# p4=plot([t_minTime,t_minEnergy], # p4=plot([t_minTime,t_minEnergy],
# [s_minTime,s_minEnergy], # [s_minTime,s_minEnergy],
# title = "s in m", # title = "s in m",
# label = ["s for t_min" "s for E_min"], # label = ["s for t_min" "s for E_min"],
# xlabel = "t in s") # xlabel = "t in s")
p5=plot([s_minTime,s_minEnergy], p5=plot([s_minTime,s_minEnergy],
[E_minTime,E_minEnergy], [E_minTime,E_minEnergy],
@ -364,7 +367,7 @@ function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{DataPoint},dr
label = ["E for t_min" "E for E_min"], label = ["E for t_min" "E for E_min"],
xlabel = "t in s") xlabel = "t in s")
# all=plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false) # all=plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false)
all=plot(p1, p2, p5, p6, layout = (2, 2), legend = false) all=plot(p1, p2, p5, p6, layout = (2, 2), legend = false)
display(all) display(all)
println("Plots for different variables have been created.") println("Plots for different variables have been created.")

View File

@ -7,49 +7,56 @@ 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 securedd braking, acceleration and cruising behavior
function preparateSections(path::Path, train::Train, settings::Settings) 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])
movingSection=secureAccelerationBehavior!(movingSection, settings, train) movingSection=secureAccelerationBehavior!(movingSection, settings, train)
movingSection=secureCruisingBehavior!(movingSection, settings, train) movingSection=secureCruisingBehavior!(movingSection, settings, train)
return movingSection return movingSection
end #function preparateSections end #function preparateSections
## create a moving section containing characteristic sections ## create a moving section containing characteristic sections
function createMovingSection(path::Path, v_trainLimit::AbstractFloat) function createMovingSection(path::Dict, v_trainLimit::Real)
# this function creates and returns a moving section dependent on the paths attributes # this function creates and returns a moving section dependent on the paths attributes
movingSection=MovingSection()
movingSection.id=1 # identifier # if there is more than one moving section in a later version of this tool the id should not be constant anymore s_entry = path[:sections][1][:s_start] # first position (in m)
movingSection.t=0.0 # total running time (in s) s_exit = path[:sections][end][:s_end] # last position (in m)
movingSection.E=0.0 # total energy consumption (in Ws) pathLength = s_exit - s_entry # total length (in m)
movingSection.s_entry=path.sections[1].s_start # first position (in m) CSs=[]
movingSection.s_exit=path.sections[length(path.sections)].s_end # last position (in m) s_csStart=s_entry
movingSection.length=movingSection.s_exit-movingSection.s_entry # total length (in m)
s_csStart=movingSection.s_entry
csId=1 csId=1
for row in 2:length(path.sections) for row in 2:length(path[:sections])
if min(path.sections[row-1].v_limit, v_trainLimit) != min(path.sections[row].v_limit, v_trainLimit) || path.sections[row-1].f_Rp != path.sections[row].f_Rp if min(path[:sections][row-1][:v_limit], v_trainLimit) != min(path[:sections][row][:v_limit], v_trainLimit) || path[:sections][row-1][:f_Rp] != path[:sections][row][:f_Rp]
push!(movingSection.characteristicSections, createCharacteristicSection(csId, s_csStart, path.sections[row-1], min(path.sections[row-1].v_limit, v_trainLimit))) push!(CSs, createCharacteristicSection(csId, s_csStart, path[:sections][row-1], min(path[:sections][row-1][:v_limit], v_trainLimit)))
s_csStart=path.sections[row].s_start s_csStart=path[:sections][row][:s_start]
csId=csId+1 csId=csId+1
end #if end #if
end #for end #for
push!(movingSection.characteristicSections, createCharacteristicSection(csId, s_csStart, path.sections[end], min(path.sections[end].v_limit, v_trainLimit))) push!(CSs, createCharacteristicSection(csId, s_csStart, path[:sections][end], min(path[:sections][end][:v_limit], v_trainLimit)))
movingSection= Dict(:id => 1, # identifier # if there is more than one moving section in a later version of this tool the id should not be constant anymore
:length => pathLength, # total length (in m)
:s_entry => s_entry, # first position (in m)
:s_exit => s_exit, # last position (in m)
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:t_recovery => 0.0, # total recovery time for energy-saving modifications (in s)
:t_recoveryAvailable => 0.0, # still available recovery time for energy-saving modifications (in s)
:characteristicSections => CSs, # list of containing characteristic sections
:energySavingModifications => EnergySavingModification[]) # list of containing all the used energy saving modifications
return movingSection return movingSection
end #function createMovingSection end #function createMovingSection
## create a characteristic section for a path section ## create a characteristic section for a path section
function createCharacteristicSection(csId::Integer, s_csStart::AbstractFloat, section::PathSection, v_csLimit::AbstractFloat) function createCharacteristicSection(csId::Integer, s_csStart::Real, section::Dict, v_csLimit::Real)
# this function creates and returns a characteristic section dependent on the paths attributes # this function creates and returns a characteristic section dependent on the paths attributes
characteristicSection=CharacteristicSection() characteristicSection=CharacteristicSection()
characteristicSection.id=csId # identifier characteristicSection.id=csId # identifier
characteristicSection.s_entry=s_csStart # first position (in m) characteristicSection.s_entry=s_csStart # first position (in m)
characteristicSection.s_exit=section.s_end # last position (in m) characteristicSection.s_exit=section[:s_end] # last position (in m)
characteristicSection.length=characteristicSection.s_exit-characteristicSection.s_entry # total length (in m) characteristicSection.length=characteristicSection.s_exit-characteristicSection.s_entry # total length (in m)
characteristicSection.t=0.0 # total running time (in s) characteristicSection.t=0.0 # total running time (in s)
characteristicSection.E=0.0 # total energy consumption (in Ws) characteristicSection.E=0.0 # total energy consumption (in Ws)
@ -60,55 +67,59 @@ function createCharacteristicSection(csId::Integer, s_csStart::AbstractFloat, se
characteristicSection.v_entry=characteristicSection.v_limit # maximum entry speed (in m/s) characteristicSection.v_entry=characteristicSection.v_limit # maximum entry speed (in m/s)
characteristicSection.v_exit=characteristicSection.v_limit # maximum exit speed (in m/s) characteristicSection.v_exit=characteristicSection.v_limit # maximum exit speed (in m/s)
characteristicSection.f_Rp=section.f_Rp # path resistance (in ‰) characteristicSection.f_Rp=section[:f_Rp] # path resistance (in ‰)
return characteristicSection return characteristicSection
end #function createCharacteristicSection end #function createCharacteristicSection
## define the intersection velocities between the characterisitc sections to secure braking behavior ## define the intersection velocities between the characterisitc sections to secure braking behavior
function secureBrakingBehavior!(movingSection::MovingSection, a_braking::AbstractFloat) function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
# this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end # this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end
csId=length(movingSection.characteristicSections) CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
movingSection.characteristicSections[csId].v_exit=0.0 # the exit velocity of the last characteristic section is 0.0 m/s
csId=length(CSs)
CSs[csId].v_exit=0.0 # the exit velocity of the last characteristic section is 0.0 m/s
while csId >= 1 while csId >= 1
v_entryMax=sqrt(movingSection.characteristicSections[csId].v_exit^2-2*a_braking*movingSection.characteristicSections[csId].length) v_entryMax=sqrt(CSs[csId].v_exit^2-2*a_braking*CSs[csId].length)
v_entryMax=floor(v_entryMax, digits=12) v_entryMax=floor(v_entryMax, digits=12)
movingSection.characteristicSections[csId].v_entry=min(movingSection.characteristicSections[csId].v_limit, v_entryMax) CSs[csId].v_entry=min(CSs[csId].v_limit, v_entryMax)
movingSection.characteristicSections[csId].v_target=movingSection.characteristicSections[csId].v_entry CSs[csId].v_target=CSs[csId].v_entry
csId=csId-1 csId=csId-1
if csId >= 1 if csId >= 1
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_limit, movingSection.characteristicSections[csId+1].v_entry) CSs[csId].v_exit=min(CSs[csId].v_limit, CSs[csId+1].v_entry)
end #if end #if
end #while end #while
return movingSection return movingSection
end #function secureBrakingBehavior! end #function secureBrakingBehavior!
## define the intersection velocities between the characterisitc sections to secure acceleration behavior ## define the intersection velocities between the characterisitc sections to secure acceleration behavior
function secureAccelerationBehavior!(movingSection::MovingSection, settings::Settings, train::Train) function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train::Dict)
# this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards # this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards
movingSection.characteristicSections[1].v_entry=0.0 # the entry velocity of the first characteristic section is 0.0 m/s CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
CSs[1].v_entry=0.0 # the entry velocity of the first characteristic section is 0.0 m/s
startingPoint=DataPoint() startingPoint=DataPoint()
startingPoint.i=1 startingPoint.i=1
previousCSv_exit=movingSection.characteristicSections[1].v_entry previousCSv_exit=CSs[1].v_entry
for csId in 1:length(movingSection.characteristicSections) for csId in 1:length(CSs)
movingSection.characteristicSections[csId].v_entry=min(movingSection.characteristicSections[csId].v_entry, previousCSv_exit) CSs[csId].v_entry=min(CSs[csId].v_entry, previousCSv_exit)
startingPoint.s=movingSection.characteristicSections[csId].s_entry startingPoint.s=CSs[csId].s_entry
startingPoint.v=movingSection.characteristicSections[csId].v_entry startingPoint.v=CSs[csId].v_entry
accelerationCourse=[startingPoint] # List of data points accelerationCourse=[startingPoint] # List of data points
if movingSection.characteristicSections[csId].v_entry<movingSection.characteristicSections[csId].v_target if CSs[csId].v_entry<CSs[csId].v_target
(movingSection.characteristicSections[csId], accelerationCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], accelerationCourse, settings, train, movingSection.characteristicSections) # this function changes the accelerationCourse (CSs[csId], accelerationCourse)=addAccelerationPhase!(CSs[csId], accelerationCourse, settings, train, CSs) # this function changes the accelerationCourse
movingSection.characteristicSections[csId].v_target=max(movingSection.characteristicSections[csId].v_entry,accelerationCourse[end].v) CSs[csId].v_target=max(CSs[csId].v_entry,accelerationCourse[end].v)
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_exit, movingSection.characteristicSections[csId].v_target, accelerationCourse[end].v) CSs[csId].v_exit=min(CSs[csId].v_exit, CSs[csId].v_target, accelerationCourse[end].v)
else #movingSection.characteristicSections[csId].v_entry==movingSection.characteristicSections[csId].v_target else #CSs[csId].v_entry==CSs[csId].v_target
# v_exit stays the same # v_exit stays the same
end #if end #if
previousCSv_exit=movingSection.characteristicSections[csId].v_exit previousCSv_exit=CSs[csId].v_exit
end #for end #for
return movingSection return movingSection
@ -117,24 +128,26 @@ end #function secureAccelerationBehavior!
## define the intersection velocities between the characterisitc sections to secure cruising behavior ## define the intersection velocities between the characterisitc sections to secure cruising behavior
function secureCruisingBehavior!(movingSection::MovingSection, settings::Settings, train::Train) function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dict)
# limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_target # limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_target
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
startingPoint=DataPoint() startingPoint=DataPoint()
startingPoint.i=1 startingPoint.i=1
previousCSv_exit=movingSection.characteristicSections[1].v_entry previousCSv_exit=CSs[1].v_entry
for csId in 1:length(movingSection.characteristicSections) for csId in 1:length(CSs)
movingSection.characteristicSections[csId].v_entry=min(movingSection.characteristicSections[csId].v_entry, previousCSv_exit) CSs[csId].v_entry=min(CSs[csId].v_entry, previousCSv_exit)
startingPoint.s=movingSection.characteristicSections[csId].s_entry startingPoint.s=CSs[csId].s_entry
startingPoint.v=movingSection.characteristicSections[csId].v_target startingPoint.v=CSs[csId].v_target
cruisingCourse=[startingPoint] # List of data points cruisingCourse=[startingPoint] # List of data points
(movingSection.characteristicSections[csId], cruisingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], cruisingCourse, movingSection.characteristicSections[csId].length, settings, train, movingSection.characteristicSections, "cruising") # this function changes the cruisingCourse (CSs[csId], cruisingCourse)=addCruisingPhase!(CSs[csId], cruisingCourse, CSs[csId].length, settings, train, CSs, "cruising") # this function changes the cruisingCourse
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_exit, cruisingCourse[end].v) CSs[csId].v_exit=min(CSs[csId].v_exit, cruisingCourse[end].v)
previousCSv_exit=movingSection.characteristicSections[csId].v_exit previousCSv_exit=CSs[csId].v_exit
end #for end #for
return movingSection return movingSection

View File

@ -41,7 +41,7 @@ function calculateDrivingDynamics(trainDirectory::String, pathDirectory::String,
movingSection=preparateSections(path, train, settings) movingSection=preparateSections(path, train, settings)
println("The moving section has been prepared.") println("The moving section has been prepared.")
if settings.operationModeMinimumRunningTime==true || settings.operationModeMinimumEnergyConsumption==true if settings[:operationModeMinimumRunningTime] ==true || settings[:operationModeMinimumEnergyConsumption] ==true
(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime)=calculateMinimumRunningTime!(movingSection, settings, train) (movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime)=calculateMinimumRunningTime!(movingSection, settings, train)
# println("t=", drivingCourseMinimumRunningTime[end].t) # println("t=", drivingCourseMinimumRunningTime[end].t)
# printSectionInformation(movingSectionMinimumRunningTime) # printSectionInformation(movingSectionMinimumRunningTime)
@ -50,22 +50,22 @@ function calculateDrivingDynamics(trainDirectory::String, pathDirectory::String,
# oparation mode "minimum energy consumption" # oparation mode "minimum energy consumption"
if settings.operationModeMinimumEnergyConsumption==true if settings[:operationModeMinimumEnergyConsumption] == true
(movingSectionMinimumEnergyConsumption, drivingCourseMinimumEnergyConsumption)=calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime, settings, train) (movingSectionMinimumEnergyConsumption, drivingCourseMinimumEnergyConsumption)=calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime, settings, train)
# printSectionInformation(movingSectionMinimumEnergyConsumption) # printSectionInformation(movingSectionMinimumEnergyConsumption)
println("The driving course for the lowest energy consumption has been calculated.") println("The driving course for the lowest energy consumption has been calculated.")
end #if end #if
#output #output
if settings.operationModeMinimumRunningTime==true && settings.operationModeMinimumEnergyConsumption==true if settings[:operationModeMinimumRunningTime] == true && settings[:operationModeMinimumEnergyConsumption] == true
plotDrivingCourse(drivingCourseMinimumRunningTime, drivingCourseMinimumEnergyConsumption) plotDrivingCourse(drivingCourseMinimumRunningTime, drivingCourseMinimumEnergyConsumption)
return createOutput(settings, path.name, train.name, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption) return createOutput(settings, path[:name], train[:name], drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
elseif settings.operationModeMinimumRunningTime==true elseif settings[:operationModeMinimumRunningTime] == true
plotDrivingCourse(drivingCourseMinimumRunningTime) plotDrivingCourse(drivingCourseMinimumRunningTime)
return createOutput(settings, path.name, train.name, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime) return createOutput(settings, path[:name], train[:name], drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime)
elseif settings.operationModeMinimumEnergyConsumption==true elseif settings[:operationModeMinimumEnergyConsumption] == true
plotDrivingCourse(drivingCourseMinimumEnergyConsumption) plotDrivingCourse(drivingCourseMinimumEnergyConsumption)
return createOutput(settings, path.name, train.name, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption) return createOutput(settings, path[:name], train[:name], drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
else else
println("No Output was demanded. So no output is created.") println("No Output was demanded. So no output is created.")
return Dict() return Dict()

View File

@ -1,78 +1,6 @@
module types module types
# definition of all the additional types and their constructors # definition of all the additional types and their constructors
export Settings, Train, PathSection, Path, DataPoint, BehaviorSection, CharacteristicSection, EnergySavingModification, MovingSection # tried to insert copy on 15.07.2021 , copy export DataPoint, BehaviorSection, CharacteristicSection, EnergySavingModification
## settings for the calculation
mutable struct Settings
massModel::String # model type of the trains mass "mass point" or "homogeneous strip"
stepVariable::String # step variable of the step method "s in m", "t in s" or "v in m/s"
stepSize::AbstractFloat # step size (unit depends on steapVariable s in m, t in s and v in m/s)
operationModeMinimumRunningTime::Bool # operation mode "minimum running time"
operationModeMinimumEnergyConsumption::Bool # operation mode "minimum energy consumption"
# output:
typeOfOutput::String # output as "julia dictionary" or as "CSV"
csvDirectory::String # directory in which the CSV files will be saved
detailOfOutput::String # detail of output "minimal" or "driving course"
end # mutable struct Settings
Settings()=Settings("", "", 0.0, false, false, "", "", "")
## train
mutable struct Train
name::String # trains name
id # trains identifier
trainType::String # type of train "passenger" or "freight" or "motor coach train"
l_train::AbstractFloat # total length (in m)
v_limit::AbstractFloat # trains speed limit (in m/s)
a_braking::AbstractFloat # braking acceleration (in m/s^2)
m_train::AbstractFloat # total mass (in kg)
ξ_train::AbstractFloat # rotation mass factor of the whole train (without unit)
# if not available use ξ_t and ξ_w
# traction unit
m_t::AbstractFloat # mass of the traction unit (in kg)
m_td::AbstractFloat # mass on the traction units driving axles (in kg)
m_tc::AbstractFloat # mass on the traction units carrying axles (in kg)
ξ_t::AbstractFloat # rotation mass factor of the traction unit (without unit)
# in case ξ_train is not available
tractiveEffortVelocityPairs # list of velocities and their corresponding tractive effort (in [m/s , N])
f_Rtd0::AbstractFloat # coefficient for basic resistance due to the traction units driving axles (in ‰)
f_Rtc0::AbstractFloat # coefficient for basic resistance due to the traction units carring axles (in ‰)
F_Rt2::AbstractFloat # coefficient for air resistance of the traction units (in N)
Δv_t::AbstractFloat # coefficient for velocitiy difference between traction unit and outdoor air
# set of wagons
m_w::AbstractFloat # mass of the set of wagons (in kg)
ξ_w::AbstractFloat # rotation mass factor of the set of wagons (without unit)
# in case ξ_train is not available
f_Rw0::AbstractFloat # coefficient for basic resistance of the set of wagons (in ‰)
f_Rw1::AbstractFloat # coefficient for resistance to rolling of the set of wagons (in ‰)
f_Rw2::AbstractFloat # coefficient for air resistance of the set of wagons (in ‰)
Δv_w::AbstractFloat # coefficient for velocitiy difference between set of wagons and outdoor air (in m/s)
end # mutable struct Train
Train()=Train("", 0, "", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, [], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
## path separated in smaler sections
struct PathSection
s_start::AbstractFloat # starting point of the section (in m)
s_end::AbstractFloat # starting point of the next section (in m)
v_limit::AbstractFloat # paths speed limt (in m/s)
f_Rp::AbstractFloat # specific path resistance of the section (in ‰)
end # struct pathSection
PathSection()=(0.0, 0.0, 0.0, 0.0)
struct Path
name::String # paths name
id # paths identifier
sections::Vector{PathSection} # list of PathSection elements
# s_start in first entry defines the path's beginning
# s_end in last entry defines the path's ending
end # struct Path
Path()=("", 0, Vector{PathSection}())
## 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
@ -137,15 +65,15 @@ mutable struct CharacteristicSection
v_entry::AbstractFloat # maximum entry speed (in m/s) v_entry::AbstractFloat # maximum entry speed (in m/s)
v_exit::AbstractFloat # maximum exit speed (in m/s) v_exit::AbstractFloat # maximum exit speed (in m/s)
f_Rp::AbstractFloat # spedific path resistance (in ‰) f_Rp::AbstractFloat # spedific path resistance (in ‰)
behaviorSections::AbstractDict{String, BehaviorSection} # list of containing behavior sections behaviorSections::AbstractDict{Symbol, BehaviorSection} # list of containing behavior sections
end # mutable struct CharacteristicSection 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{String, BehaviorSection}()) 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) 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_target, original.v_entry, original.v_exit, original.f_Rp, Dict{String, BehaviorSection}()) copy=CharacteristicSection(original.id, original.length, original.s_entry, original.s_exit, original.t, original.E, original.v_limit, original.v_target, original.v_entry, original.v_exit, original.f_Rp, Dict{Symbol, BehaviorSection}())
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(get(original.behaviorSections, allBs[bs], BehaviorSection())))) merge!(copy.behaviorSections, Dict(allBs[bs] => BehaviorSection(original.behaviorSections[allBs[bs]])))
end #if end #if
end #for end #for
return copy return copy
@ -171,31 +99,4 @@ function EnergySavingModification(original::EnergySavingModification)
return copy return copy
end #function EnergySavingModification end #function EnergySavingModification
## a moving section contains all the smaller sections from one stop to an other
mutable struct MovingSection
id # 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)
t_recovery::AbstractFloat # total recovery time for energy-saving modifications (in s)
t_recoveryAvailable::AbstractFloat # still available recovery time for energy-saving modifications (in s)
characteristicSections::Vector{CharacteristicSection} # list of containing characteristic sections
energySavingModifications::Vector{EnergySavingModification} # list of containing all the used energy saving modifications
end # mutable struct MovingSection
MovingSection()=MovingSection(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, [], [])
function MovingSection(original::MovingSection)
copy=MovingSection(original.id, original.length, original.s_entry, original.s_exit, original.t, original.E, original.t_recovery, original.t_recoveryAvailable, [], [])
for csId in 1:length(original.characteristicSections)
push!(copy.characteristicSections, CharacteristicSection(original.characteristicSections[csId]))
end #for
for modId in 1:length(original.energySavingModifications)
push!(copy.energySavingModifications, EnergySavingModification(original.energySavingModifications[modId]))
end #for
return copy
end #function CharacteristicSection
end #module end #module