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"
uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92"
authors = ["Max Kannenberg"]
version = "0.5.3"
version = "0.6.0"
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"

View File

@ -31,6 +31,14 @@ train_run = calculateDrivingDynamics(train, running_path, settings)
# 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
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"
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.")

View File

@ -8,102 +8,102 @@ export calculateRecoveryTime, increaseCoastingSection, decreaseMaximumVelocity,
approximationLevel = 6 # value for approximation to intersections
# 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
# MS: Moving Section
if train.trainType=="motor coach train"
if train[:trainType]=="motor coach train"
if s_MS<= 30000
c_s=0.0
else s_MS> 30000
c_s=0.0006
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
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
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
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
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
end # if train.v_limit
end # if train[:v_limit]
t_recovery=s_MS*c_s+t_MS*c_t
return t_recovery
elseif train.trainType=="freight" && train.v_limit<=120/3.6 # unit is m/s
elseif train[:trainType]=="freight" && train[:v_limit]<=120/3.6 # unit is m/s
t_recovery1=s_MS*0.0006 +t_MS*0.03
t_recovery2=s_MS*0.0018 +t_MS*0.0
t_recovery3=s_MS*0.0 +t_MS*0.04
t_recovery=max(t_recovery1, t_recovery2, t_recovery3)
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
c_s=0.0
else s_MS> 30000
c_s=0.0009
end # if s_MS
if train.v_limit<=140/3.6 # unit is m/s
if train.m_train<=300000 # unit is kg
if train[:v_limit]<=140/3.6 # unit is m/s
if train[:m_train]<=300000 # unit is kg
c_t=0.03
elseif train.m_train<=500000 # unit is kg
elseif train[:m_train]<=500000 # unit is kg
c_t=0.04
elseif train.m_train<=700000 # unit is kg
elseif train[:m_train]<=700000 # unit is kg
c_t=0.04
else # train.m_train>700000 # unit is kg
else # train[:m_train]>700000 # unit is kg
c_t=0.05
end # if train.m_train
elseif train.v_limit<=160/3.6 # unit is m/s
if train.m_train<=300000 # unit is kg
end # if train[:m_train]
elseif train[:v_limit]<=160/3.6 # unit is m/s
if train[:m_train]<=300000 # unit is kg
c_t=0.03
elseif train.m_train<=500000 # unit is kg
elseif train[:m_train]<=500000 # unit is kg
c_t=0.04
else # train.m_train>500000 # unit is kg
else # train[:m_train]>500000 # unit is kg
c_t=0.0
end # if train.m_train
elseif train.v_limit<=200/3.6 # unit is m/s
if train.m_train<=300000 # unit is kg
end # if train[:m_train]
elseif train[:v_limit]<=200/3.6 # unit is m/s
if train[:m_train]<=300000 # unit is kg
c_t=0.04
elseif train.m_train<=500000 # unit is kg
elseif train[:m_train]<=500000 # unit is kg
c_t=0.05
else # train.m_train>500000 # unit is kg
else # train[:m_train]>500000 # unit is kg
c_t=0.06
end # if train.m_train
else # train.v_limit>200/3.6 # unit is m/s
if train.m_train<=300000 # unit is kg
end # if train[:m_train]
else # train[:v_limit]>200/3.6 # unit is m/s
if train[:m_train]<=300000 # unit is kg
c_t=0.05
elseif train.m_train<=500000 # unit is kg
elseif train[:m_train]<=500000 # unit is kg
c_t=0.06
else # train.m_train>500000 # unit is kg
else # train[:m_train]>500000 # unit is kg
c_t=0.07
end # if train.m_train
end # if train.v_limit
end # if train[:m_train]
end # if train[:v_limit]
c_tMin=s_MS/t_MS*0.0012
c_t=max(c_t, c_tMin)
t_recovery=s_MS*c_s+t_MS*c_t
return t_recovery
end # if train.trainType
end # if train[:trainType]
end #function calculateRecoveryTime
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, "diminishing")) && haskey(csOriginal.behaviorSections, "braking")
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)
# check if cruising or diminishing should be reduced for coasting
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 haskey(csOriginal.behaviorSections, :cruising) && haskey(csOriginal.behaviorSections, :diminishing)
if csOriginal.behaviorSections[:cruising].dataPoints[1] > csOriginal.behaviorSections[:diminishing].dataPoints[1]
reduceCruising=true
reduceDiminishing=false
else
reduceDiminishing=true
reduceCruising=false
end
elseif haskey(csOriginal.behaviorSections, "cruising")
elseif haskey(csOriginal.behaviorSections, :cruising)
reduceCruising=true
reduceDiminishing=false
elseif haskey(csOriginal.behaviorSections, "diminishing")
elseif haskey(csOriginal.behaviorSections, :diminishing)
reduceDiminishing=true
reduceCruising=false
end
@ -111,13 +111,13 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
if reduceCruising
cruisingReduction=settings.stepSize
while cruisingReduction>=settings.stepSize/10^approximationLevel
#while cruisingReduction>=settings.stepSize/100
while cruisingReduction>=settings.stepSize/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified.v_exit && drivingCourseModified[end].s<csModified.s_exit) -> see below at the end of the while loop
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]
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
@ -130,46 +130,45 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
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
if settings[:stepVariable]=="s in m" # distance step method
s_cruising = csOriginal.behaviorSections[:cruising].length - cruisingReduction
elseif settings[:stepVariable]=="t in s" # time step method
# 09/20 old: doesn't work for non constant cruising -> TODO: should work now
# t_cruising=csOriginal.behaviorSections[:cruising].t-cruisingReduction
# 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
distanceReduction = drivingCourse(csOriginal.behaviorSections[:cruising].dataPoints[end]).v*cruisingReduction
s_cruising = csOriginal.behaviorSections[:cruising].length-distanceReduction
elseif settings.stepVariable=="v in m/s" # velocity step method
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).length-cruisingReduction*10 # TODO: or better: *100 ?
elseif settings[:stepVariable]=="v in m/s" # velocity step method
s_cruising=csOriginal.behaviorSections[:cruising].length-cruisingReduction*10 # TODO: or better: *100 ?
end #if
s_cruising=max(0.0, s_cruising)
# copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_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
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)
breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree])
merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection))
csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E
csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t
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
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(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
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, "diminishing")
diminishingSection=BehaviorSection(get(csOriginal.behaviorSections, "diminishing", BehaviorSection()))
merge!(csModified.behaviorSections, Dict("diminishing"=>diminishingSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "diminishing", BehaviorSection()).E
csModified.t=csModified.t+get(csModified.behaviorSections, "diminishing", BehaviorSection()).t
if haskey(csOriginal.behaviorSections, :diminishing)
diminishingSection=BehaviorSection(csOriginal.behaviorSections[:diminishing])
merge!(csModified.behaviorSections, Dict(:diminishing=>diminishingSection))
csModified.E = csModified.E + csModified.behaviorSections[:diminishing].E
csModified.t = csModified.t + csModified.behaviorSections[:diminishing].t
end
@ -191,7 +190,7 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
# calculate the moving phase between coasting and the end of the CS
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)
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
@ -208,39 +207,36 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
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
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
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)
breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree])
merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection))
csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E
csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t
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
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
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()))
diminishingSection=BehaviorSection(csOriginal.behaviorSections[:diminishing])
if length(diminishingSection.dataPoints) > 2
# remove the last diminishing waypoint
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.E=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
merge!(csModified.behaviorSections, Dict("diminishing"=>diminishingSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "diminishing", BehaviorSection()).E
csModified.t=csModified.t+get(csModified.behaviorSections, "diminishing", BehaviorSection()).t
merge!(csModified.behaviorSections, Dict(:diminishing => diminishingSection))
csModified.E = csModified.E + csModified.behaviorSections[:diminishing].E
csModified.t = csModified.t + csModified.behaviorSections[:diminishing].t
energySavingStartId=diminishingSection.dataPoints[end]
else
# The diminishing section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section.
energySavingStartId=get(csOriginal.behaviorSections, "clearing", get(csOriginal.behaviorSections, "diminishing", BehaviorSection())).dataPoints[1]
energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :diminishing, BehaviorSection())).dataPoints[1]
end
# copy the driving course till the beginning of energy saving
@ -297,131 +293,34 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
end
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
function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, "acceleration") && csOriginal.v_target > csOriginal.v_entry && csOriginal.v_target > csOriginal.v_exit
accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
#function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
if haskey(csOriginal.behaviorSections, :acceleration) && csOriginal.v_target > csOriginal.v_entry && csOriginal.v_target > csOriginal.v_exit
accelerationSection = BehaviorSection(csOriginal.behaviorSections[:acceleration])
if drivingCourse[accelerationSection.dataPoints[end]-1].v < csOriginal.v_exit
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.
end
# copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_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")
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
if haskey(csOriginal.behaviorSections, :breakFree)
breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree])
merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection))
csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E
csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t
end
#accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
#accelerationSection = BehaviorSection(get(csOriginal.behaviorSections, :acceleration, BehaviorSection()))
if length(accelerationSection.dataPoints) > 2
if haskey(csOriginal.behaviorSections, "clearing")
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
if haskey(csOriginal.behaviorSections, :clearing)
clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing])
merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection))
csModified.E = csModified.E + csModified.behaviorSections[:clearing].E
csModified.t = csModified.t + csModified.behaviorSections[:clearing].t
end
# 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.E=drivingCourse[accelerationSection.dataPoints[end]].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection))
csModified.E=csModified.E+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E
csModified.t=csModified.t+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t
merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection))
csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E
csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t
energySavingStartId=accelerationSection.dataPoints[end]
else
# The acceleration section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section.
energySavingStartId=get(csOriginal.behaviorSections, "clearing", get(csOriginal.behaviorSections, "acceleration", BehaviorSection())).dataPoints[1]
energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :acceleration, BehaviorSection())).dataPoints[1]
end
# 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
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-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-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_cruising=csModified.s_exit-drivingCourseModified[end].s-s_braking
if s_cruising >0.001
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
end #if
# s_brakingAfterCruising=ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train.a_braking, digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
# s_brakingAfterCruising=ceil((csModified.v_exit^2-drivingCourseModified[end].v^2)/2/train[:a_braking], digits=10) # TODO: check if s_braking and s_brakingAfterCruising are really always the same
if drivingCourseModified[end].v>csModified.v_exit
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs)
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs)
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
elseif drivingCourseModified[end].s<csModified.s_exit
if (csModified.s_exit-drivingCourseModified[end].s)>0.001
@ -500,9 +399,9 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
end # function decreaseMaximumVelocity
# combination of method 1 and method 2
function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, 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")) && drivingCourse[get(csOriginal.behaviorSections, "acceleration", BehaviorSection()).dataPoints[end]].v > max(csOriginal.v_entry, csOriginal.v_exit)
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)) && drivingCourse[get(csOriginal.behaviorSections, :acceleration, BehaviorSection()).dataPoints[end]].v > max(csOriginal.v_entry, csOriginal.v_exit)
csCombined=CharacteristicSection(csOriginal)
drivingCourseCombined=Vector{DataPoint}()
for i in 1:length(drivingCourse)
@ -518,7 +417,7 @@ function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCo
ΔE=csOriginal.E-csCombined.E # saved energy (in Ws)
Δt=csCombined.t-csOriginal.t # time loss (in s)
while (haskey(csOriginal.behaviorSections, "cruising") && (Δt<=0.0 || ΔE<=0.0)) #Δt<=0.0) #&& ΔE<=0.0) # && Δt<=0.0)
while (haskey(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)
if newCoasting
ΔE=csOriginal.E-csCombined.E # saved energy (in Ws)

View File

@ -6,7 +6,7 @@ using ..types
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)
train=inputTrain(trainDirectory)
@ -17,25 +17,25 @@ function readInput(trainDirectory::String, pathDirectory::String, settingsDirect
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)
data = YAML.load(open(trainDirectory))
collect(keys(data))
collect(values(data))
train=Train()
if haskey(data["train"],"name")
train.name=data["train"]["name"] # trains name
name=data["train"]["name"] # trains name
delete!(data["train"], "name")
else
error("ERROR at reading the train yaml file: The keyword name is missing. It has to be added.")
end
train.id=1 # trains identifier
id=1 # trains identifier
if haskey(data["train"],"trainType")
if typeof(data["train"]["trainType"])==String && (data["train"]["trainType"]=="freight" || data["train"]["trainType"]=="motor coach train" || data["train"]["trainType"]=="passenger")
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")
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.")
@ -46,7 +46,7 @@ function inputTrain(trainDirectory::String)
if haskey(data["train"],"l_train")
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")
else
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
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)
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
elseif v_limit_temp > 0.0
train.v_limit=v_limit_temp
v_limit=v_limit_temp
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
train.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." )
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 =",v_limit," m/s is used." )
end
# a_braking
if haskey(data["train"],"a_braking")
if typeof(data["train"]["a_braking"]) <: Real
train.a_braking=data["train"]["a_braking"]
a_braking=data["train"]["a_braking"]
else
error("ERROR at reading the train yaml file: The value of the a_braking is no real floating point number <0.0.")
end
delete!(data["train"], "a_braking")
if train.a_braking > 0.0
train.a_braking =-train.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." )
elseif train.a_braking == 0.0
if a_braking > 0.0
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 =",a_braking," m/s^2 is used." )
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.")
end
else
@ -115,7 +115,7 @@ function inputTrain(trainDirectory::String)
# mass on the traction units driving axles (in kg)
if haskey(data["train"],"m_td")
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
error("ERROR at reading the train yaml file: The value of m_td is no real floating point number >0.0.")
end
@ -128,7 +128,7 @@ function inputTrain(trainDirectory::String)
# mass on the traction units carrying axles (in kg)
if haskey(data["train"],"m_tc")
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
error("ERROR at reading the train yaml file: The value of m_tc is no real floating point number >=0.0.")
end
@ -138,47 +138,49 @@ function inputTrain(trainDirectory::String)
delete!(data["train"], "m_tc")
# 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)
if haskey(data["train"],"m_w")
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
error("ERROR at reading the train yaml file: The value of m_w is no real floating point number >=0.0.")
end
else
train.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.")
m_w=0.0
println("WARNING at reading the train yaml file: The keyword m_w is missing. Therefore m_w =",m_w," kg is used.")
end
delete!(data["train"], "m_w")
# 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 data["train"]["rotationMassFactor_train"]>0.0
train.ξ_train=data["train"]["rotationMassFactor_train"]
ξ_train=data["train"]["rotationMassFactor_train"]
ξ_t=0.0
ξ_w=0.0
else
error("ERROR at reading the train yaml file: The value of rotationMassFactor_train is no real floating point number >0.0.")
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
train.ξ_t=data["train"]["rotationMassFactor_t"]
ξ_t=data["train"]["rotationMassFactor_t"]
else
error("ERROR at reading the train yaml file: The value of rotationMassFactor_t is no real floating point number >0.0.")
end
if train.m_w>0.0
if m_w>0.0
if data["train"]["rotationMassFactor_w"]>=0.0
train.ξ_w=data["train"]["rotationMassFactor_w"]
ξ_w=data["train"]["rotationMassFactor_w"]
else
error("ERROR at reading the train yaml file: The value of rotationMassFactor_w is no real floating point number >=0.0.")
end
else
train.ξ_w=0.0
ξ_w=0.0
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
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
@ -191,70 +193,7 @@ function inputTrain(trainDirectory::String)
if haskey(data["train"],"F_T_pairs") && data["train"]["F_T_pairs"]!=nothing
F_T_pairs=data["train"]["F_T_pairs"]
train.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
=#
tractiveEffortVelocityPairs=checkAndDefineTractiveEffortInput(F_T_pairs, 1.0)
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." )
@ -263,50 +202,7 @@ function inputTrain(trainDirectory::String)
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"]
train.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
=#
tractiveEffortVelocityPairs=checkAndDefineTractiveEffortInput(F_T_pairs_kmh, 1000/3600)
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.")
end # if
@ -317,17 +213,17 @@ function inputTrain(trainDirectory::String)
# coefficients for the vehicle resistance of the traction unit
# 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 ‰)
if haskey(data["train"],"f_Rtd0") && data["train"]["f_Rtd0"]!=nothing
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
error("ERROR at reading the train yaml file: The value of f_Rtd0 is no real floating point number >=0.0.")
end
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." )
end
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 ‰)
if haskey(data["train"],"f_Rtc0") && data["train"]["f_Rtc0"]!=nothing
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
error("ERROR at reading the train yaml file: The value of f_Rtc0 is no real floating point number >=0.0.")
end
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." )
end
delete!(data["train"], "f_Rtc0")
@ -348,12 +244,12 @@ function inputTrain(trainDirectory::String)
# coefficient for air resistance of the traction units (in N)
if haskey(data["train"],"F_Rt2") && data["train"]["F_Rt2"]!=nothing
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
error("ERROR at reading the train yaml file: The value of F_Rt2 is no real floating point number >=0.0.")
end
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." )
end
delete!(data["train"], "F_Rt2")
@ -363,21 +259,21 @@ function inputTrain(trainDirectory::String)
# 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)
if train.trainType=="passenger" || train.trainType=="motor coach train"
train.Δv_w=15.0/3.6
elseif train.trainType== "freight"
train.Δv_w=0.0
if trainType=="passenger" || trainType=="motor coach train"
Δv_w=15.0/3.6
elseif trainType== "freight"
Δv_w=0.0
end # if
# coefficient for basic resistance of the consist (set of wagons) (in ‰)
if haskey(data["train"],"f_Rw0") && data["train"]["f_Rw0"]!=nothing
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
error("ERROR at reading the train yaml file: The value of f_Rw0 is no real floating point number >=0.0.")
end
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." )
end
delete!(data["train"], "f_Rw0")
@ -385,12 +281,12 @@ function inputTrain(trainDirectory::String)
# coefficient for basic resistance of the consist (set of wagons) (in ‰)
if haskey(data["train"],"f_Rw1") && data["train"]["f_Rw1"]!=nothing
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
error("ERROR at reading the train yaml file: The value of f_Rw1 is no real floating point number >=0.0.")
end
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." )
end
delete!(data["train"], "f_Rw1")
@ -398,12 +294,12 @@ function inputTrain(trainDirectory::String)
# coefficient for basic resistance of the consist (set of wagons) (in ‰)
if haskey(data["train"],"f_Rw2") && data["train"]["f_Rw2"]!=nothing
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
error("ERROR at reading the train yaml file: The value of f_Rw2 is no real floating point number >=0.0.")
end
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." )
end
delete!(data["train"], "f_Rw2")
@ -417,6 +313,39 @@ function inputTrain(trainDirectory::String)
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
end #function inputTrain
@ -465,7 +394,7 @@ end #function checkAndDefineTractiveEffortInput
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))
collect(keys(data))
collect(values(data))
@ -479,7 +408,6 @@ function inputPath(pathDirectory::String)
delete!(data["path"], "name")
id=1 # path identifier
path=Path(name, id, [])
# read the section starting positions and corresponding information
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.")
end
# save values in the path object
# save values in the path Dict
sections=[]
for row in 2:length(sectionStartsArray)
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)
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 ‰)
section=PathSection(s_start, s_end, v_limit, f_Rp)
push!(path.sections, section)
section=Dict(:s_start => s_start, :s_end => s_end, :v_limit => v_limit, :f_Rp => f_Rp)
push!(sections, section)
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:
if length(data["path"])>0
@ -567,19 +501,28 @@ end # function inputPath
## settings for the calculation
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))
collect(keys(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"
if haskey(data["settings"],"massModel")
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"
if typeof(data["settings"]["massModel"])==String && (data["settings"]["massModel"]=="mass point" || data["settings"]["massModel"]=="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
error("ERROR at reading the settings yaml file: The value of massModel is wrong. It has to be mass point or homogeneous strip.")
end
@ -589,11 +532,11 @@ function inputSettings(settingsDirectory::String)
delete!(data["settings"], "massModel")
# step variable of the step method "s in m", "t in s" or "v in m/s"
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")
settings.stepVariable=data["settings"]["stepVariable"] # "s in m", "t in s" or "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")
# 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
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
@ -603,10 +546,11 @@ function inputSettings(settingsDirectory::String)
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 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
error("ERROR at reading the settings yaml file: The value of the stepSize is no real floating point number >0.0.")
end
@ -616,17 +560,17 @@ function inputSettings(settingsDirectory::String)
delete!(data["settings"], "stepSize")
# operation mode "minimum running time"
if haskey(data["settings"],"operationModeMinimumRunningTime") && data["settings"]["operationModeMinimumRunningTime"]!=nothing
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
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
else
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.")
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.")
end
delete!(data["settings"], "operationModeMinimumRunningTime")
@ -634,20 +578,22 @@ function inputSettings(settingsDirectory::String)
# operation mode "minimum energy consumption"
if haskey(data["settings"],"operationModeMinimumEnergyConsumption") && data["settings"]["operationModeMinimumEnergyConsumption"]!=nothing
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
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
else
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.")
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.")
end
delete!(data["settings"], "operationModeMinimumEnergyConsumption")
# output as "julia dictionary" or as "CSV"
if haskey(data["settings"],"typeOfOutput")
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
error("ERROR at reading the settings yaml file: The value of typeOfOutput is wrong. It has to be julia dictionary or CSV.")
end
@ -657,10 +603,11 @@ function inputSettings(settingsDirectory::String)
delete!(data["settings"], "typeOfOutput")
# 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 typeof(data["settings"]["csvDirectory"])==String
settings.csvDirectory=data["settings"]["csvDirectory"]
if typeof(data["settings"]["csvDirectory"])==String
# 12/15 old, not needed if already initialized: merge!(settings, Dict(:csvDirectory => data["settings"]["csvDirectory"]))
settings[:csvDirectory] = data["settings"]["csvDirectory"]
else
error("ERROR at reading the settings yaml file: The value of csvDirectory is wrong. It has to be of type String.")
end
@ -673,8 +620,9 @@ function inputSettings(settingsDirectory::String)
# should the output be "minimal" or "driving course"
if haskey(data["settings"],"detailOfOutput")
if typeof(data["settings"]["detailOfOutput"])==String && (data["settings"]["detailOfOutput"]=="minimal" || data["settings"]["detailOfOutput"]=="driving course")
settings.detailOfOutput=data["settings"]["detailOfOutput"] # "minimal" or "driving course"
if typeof(data["settings"]["detailOfOutput"])==String && (data["settings"]["detailOfOutput"]=="minimal" || data["settings"]["detailOfOutput"]=="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
error("ERROR at reading the settings yaml file: The value of detailOfOutput is wrong. It has to be minimal or driving course.")
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?
# calculate a train run focussing on using the minimum possible running time
function calculateMinimumRunningTime!(movingSection::MovingSection, settings::Settings, train::Train)
# CSs=movingSection.characteristicSections
function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict)
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
startingPoint=DataPoint()
startingPoint.i=1
startingPoint.s=movingSection.characteristicSections[1].s_entry
startingPoint.s=CSs[1].s_entry
drivingCourse=[startingPoint] # List of data points
# for CS in CSs
for csId in 1:length(movingSection.characteristicSections)
for csId in 1:length(CSs)
# println("CS",csId)
# check if the CS has a cruising section
s_breakFree=get(movingSection.characteristicSections[csId].behaviorSections, "breakFree", BehaviorSection()).length
s_clearing=get(movingSection.characteristicSections[csId].behaviorSections, "clearing", BehaviorSection()).length
s_acceleration=get(movingSection.characteristicSections[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_breakFree = get(CSs[csId].behaviorSections, :breakFree, BehaviorSection()).length
s_clearing = get(CSs[csId].behaviorSections, :clearing, BehaviorSection()).length
s_acceleration = get(CSs[csId].behaviorSections, :acceleration, BehaviorSection()).length
s_braking = max(0.0, ceil((CSs[csId].v_exit^2-CSs[csId].v_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
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
delete!(movingSection.characteristicSections[csId].behaviorSections, "breakFree")
delete!(movingSection.characteristicSections[csId].behaviorSections, "clearing")
delete!(movingSection.characteristicSections[csId].behaviorSections, "acceleration")
delete!(movingSection.characteristicSections[csId].behaviorSections, "diminishing")
delete!(movingSection.characteristicSections[csId].behaviorSections, "cruising")
movingSection.characteristicSections[csId].E=0.0
movingSection.characteristicSections[csId].t=0.0
delete!(CSs[csId].behaviorSections, :breakFree)
delete!(CSs[csId].behaviorSections, :clearing)
delete!(CSs[csId].behaviorSections, :acceleration)
delete!(CSs[csId].behaviorSections, :diminishing)
delete!(CSs[csId].behaviorSections, :cruising)
CSs[csId].E=0.0
CSs[csId].t=0.0
if s_clearing == movingSection.characteristicSections[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")
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_clearing, settings, train, movingSection.characteristicSections, "clearing")
elseif s_cruising == movingSection.characteristicSections[csId].length
(movingSection.characteristicSections[csId], drivingCourse)=addCruisingPhase!(movingSection.characteristicSections[csId], drivingCourse, s_cruising, settings, train, movingSection.characteristicSections, "cruising")
if s_clearing == CSs[csId].length
# 09/06 TODO: thought about using "cruising" because it is used in EnergySaving and not clearing (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_clearing, settings, train, CSs, "cruising")
(CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_clearing, settings, train, CSs, "clearing")
elseif s_cruising == CSs[csId].length
(CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising")
elseif s_cruising > 0.0 || s_braking == 0.0
# 09/21 elseif s_cruising > 0.0
# 09/21 elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0)
if drivingCourse[end].v < movingSection.characteristicSections[csId].v_target
(movingSection.characteristicSections[csId], drivingCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections)
if drivingCourse[end].v < CSs[csId].v_target
(CSs[csId], drivingCourse)=addAccelerationPhase!(CSs[csId], drivingCourse, settings, train, CSs)
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(" 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(" and v=",drivingCourse[end].v," v_target=",movingSection.characteristicSections[csId].v_target," v_exit=",movingSection.characteristicSections[csId].v_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=",CSs[csId].v_target," v_exit=",CSs[csId].v_exit)
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_cruising=movingSection.characteristicSections[csId].s_exit-drivingCourse[end].s-s_braking
s_braking=max(0.0, ceil((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
s_cruising=CSs[csId].s_exit-drivingCourse[end].s-s_braking
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
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"
# 09/09 old (not sufficient for steep gradients): if movingSection.characteristicSections[csId].v_entry < movingSection.characteristicSections[csId].v_target
(movingSection.characteristicSections[csId], drivingCourse)=addAccelerationPhaseUntilBraking!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections)
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 CSs[csId].v_entry < CSs[csId].v_target
(CSs[csId], drivingCourse)=addAccelerationPhaseUntilBraking!(CSs[csId], drivingCourse, settings, train, CSs)
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
#(movingSection.characteristicSections[csId], drivingCourse)=addBrakingPhase!(movingSection.characteristicSections[csId], drivingCourse, settings.massModel, train, movingSection.characteristicSections)
(movingSection.characteristicSections[csId], drivingCourse)=addBrakingPhase!(movingSection.characteristicSections[csId], drivingCourse, settings, train, movingSection.characteristicSections)
if drivingCourse[end].v > CSs[csId].v_exit
#(CSs[csId], drivingCourse)=addBrakingPhase!(CSs[csId], drivingCourse, settings[:massModel], train, CSs)
(CSs[csId], drivingCourse)=addBrakingPhase!(CSs[csId], drivingCourse, settings, train, CSs)
end #if
#= 09/20 old and should never be used:
if drivingCourse[end].s < movingSection.characteristicSections[csId].s_exit
if haskey(movingSection.characteristicSections[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)
if drivingCourse[end].s < CSs[csId].s_exit
if haskey(CSs[csId].behaviorSections, :cruising)
println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_exit=",CSs[csId].s_exit)
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 #for
# 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.E=drivingCourse[end].E # total energy consumption (in Ws)
movingSection[:t] = drivingCourse[end].t # total running time (in s)
movingSection[:E] = drivingCourse[end].E # total energy consumption (in Ws)
return (movingSection, drivingCourse)
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
# booleans for choosing which methods are used for saving energy
doMethod1=true
@ -111,7 +112,8 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
#doCombinationOfMethods=false
#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
drivingCourseOriginal=DataPoint[]
@ -120,15 +122,15 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
end
# calculate the recovery time
movingSectionOriginal.t_recovery=calculateRecoveryTime(movingSectionOriginal.length, movingSectionOriginal.t, train)
movingSectionOriginal.t_recoveryAvailable=movingSectionOriginal.t_recovery
movingSectionOriginal[:t_recovery]=calculateRecoveryTime(movingSectionOriginal[:length], movingSectionOriginal[:t], train)
movingSectionOriginal[:t_recoveryAvailable]=movingSectionOriginal[:t_recovery]
# create arrays for each method with all the available energy saving modifications
energySavingModificationsWithCoasting=EnergySavingModification[]
energySavingModificationsWithMaximumSpeed=EnergySavingModification[]
energySavingModificationsWithCombination=EnergySavingModification[]
for csId in 1:length(movingSectionOriginal.characteristicSections)
for csId in 1:length(CSsOrig)
# method 1: increase coasting
if doMethod1 == true
modificationType = "increasing coasting"
@ -151,62 +153,14 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
end #if
end # for
while movingSectionOriginal.t_recoveryAvailable > 0.0
while movingSectionOriginal[:t_recoveryAvailable] > 0.0
# comparison of modifications
ratioMax=0.0
csIdMax=0
typeMax="none"
(energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax, movingSectionOriginal.t_recoveryAvailable)
# 09/14 Three if cases for testing:
#= if length(movingSectionOriginal.energySavingModifications)==895 && ratioMax>0.0
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
=#
(energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithMaximumSpeed, ratioMax, csIdMax, typeMax, movingSectionOriginal[:t_recoveryAvailable])
(energySavingModificationsWithCoasting, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithCoasting, ratioMax, csIdMax, typeMax, movingSectionOriginal[:t_recoveryAvailable])
(energySavingModificationsWithCombination, ratioMax, csIdMax, typeMax) = findBestModification(energySavingModificationsWithCombination, ratioMax, csIdMax, typeMax, movingSectionOriginal[:t_recoveryAvailable])
# select the most efficient modification and update the original characteristicSection, drivingCourse and movingSection
@ -214,53 +168,39 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
if typeMax=="none"
break
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)
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithCoasting[csIdMax])
# println("Nr. ",length(movingSectionOriginal.energySavingModifications),": 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)
push!(movingSectionOriginal[:energySavingModifications], energySavingModificationsWithCoasting[csIdMax])
# println("Nr. ",length(movingSectionOriginal[:energySavingModifications]),": typeMax=increasing coasting")
elseif typeMax=="decreasing maximum velocity"
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithMaximumSpeed[csIdMax])
# println("Nr. ",length(movingSectionOriginal.energySavingModifications),": typeMax=decreasing maximum velocity")
push!(movingSectionOriginal[:energySavingModifications], energySavingModificationsWithMaximumSpeed[csIdMax])
# println("Nr. ",length(movingSectionOriginal[:energySavingModifications]),": typeMax=decreasing maximum velocity")
elseif typeMax=="combination of energy saving methods"
push!(movingSectionOriginal.energySavingModifications, energySavingModificationsWithCombination[csIdMax])
# println("Nr. ",length(movingSectionOriginal.energySavingModifications),": typeMax=combination of energy saving methods")
push!(movingSectionOriginal[:energySavingModifications], energySavingModificationsWithCombination[csIdMax])
# println("Nr. ",length(movingSectionOriginal[:energySavingModifications]),": typeMax=combination of energy saving methods")
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
drivingCourseNew=Vector{DataPoint}()
for i in 1:length(movingSectionOriginal.energySavingModifications[end].drivingCourseModified)
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))
for i in 1:length(movingSectionOriginal[:energySavingModifications][end].drivingCourseModified)
push!(drivingCourseNew, DataPoint(movingSectionOriginal[:energySavingModifications][end].drivingCourseModified[i]))
end
#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
drivingCourseOriginal=drivingCourseNew
movingSectionOriginal.characteristicSections[csIdMax]=CharacteristicSection(movingSectionOriginal.energySavingModifications[end].csModified)
movingSectionOriginal.t=drivingCourseOriginal[end].t # total running time (in s)
movingSectionOriginal.E=drivingCourseOriginal[end].E # total energy consumption (in Ws)
CSsOrig[csIdMax]=CharacteristicSection(movingSectionOriginal[:energySavingModifications][end].csModified)
movingSectionOriginal[:t]=drivingCourseOriginal[end].t # total running time (in s)
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
if difference!= 0
# update the data point references in the behaviour sections of the following characteristic sections
allBs=["breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting","cruisingAfterCoasting", "braking", "standStill"]
for csId in csIdMax+1:length(movingSectionOriginal.characteristicSections)
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill]
for csId in csIdMax+1:length(CSsOrig)
for bs in 1: length(allBs)
if haskey(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs])
for point in 1:length(get(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).dataPoints)
get(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).dataPoints[point]=get(movingSectionOriginal.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).dataPoints[point]+difference
if haskey(CSsOrig[csId].behaviorSections, allBs[bs])
for point in 1:length(CSsOrig[csId].behaviorSections[allBs[bs]].dataPoints)
CSsOrig[csId].behaviorSections[allBs[bs]].dataPoints[point] = CSsOrig[csId].behaviorSections[allBs[bs]].dataPoints[point]+difference
end
end #if
end #for
@ -335,22 +275,23 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Movi
end # while
println("t_recoveryAvailable=",movingSectionOriginal.t_recoveryAvailable)
println("t_recoveryAvailable=",movingSectionOriginal[:t_recoveryAvailable])
return (movingSectionOriginal, drivingCourseOriginal)
end #function calculateMinimumEnergyConsumption
function modifyCs(movingSectionOriginal::MovingSection, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Settings, train::Train)
#println("drin: ",modificationType)
function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Dict, train::Dict)
CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections]
if modificationType == "increasing 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"
# 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"
# 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
return EnergySavingModification()
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.csModified = characteristicSectionModified # 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.Δt = energySavingModification.csModified.t - movingSectionOriginal.characteristicSections[csId].t # time loss (in s)
if energySavingModification.Δt <= movingSectionOriginal.t_recoveryAvailable && energySavingModification.ΔE >= 0.0
energySavingModification.ΔE = CSsOrig[csId].E - energySavingModification.csModified.E # saved energy (in Ws)
energySavingModification.Δt = energySavingModification.csModified.t - CSsOrig[csId].t # time loss (in s)
if energySavingModification.Δt <= movingSectionOriginal[:t_recoveryAvailable] && energySavingModification.ΔE >= 0.0
#*** TODO: check why "sign" is needed here
# if modificationType == "combination of energy saving methods"
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
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
for modNr in csIdMax+1:length(energySavingModifications)
if energySavingModifications[modNr].ratio>0
# update the behavior sections of the modified charateristic section
for bs in 1: length(allBs)
if haskey(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs])
for point in 1:length(get(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).dataPoints)
get(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).dataPoints[point] = get(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs], BehaviorSection()).dataPoints[point]+difference
for point in 1:length(energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints)
energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints[point] = energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints[point]+difference
end
end #if
end #for
@ -432,4 +373,28 @@ function updateEnergySavingModifications(energySavingModifications::Vector{Energ
return energySavingModifications
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

View File

@ -7,18 +7,18 @@ using CSV, DataFrames, Dates
export createOutput
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
if settings.typeOfOutput == "CSV"
if settings[:typeOfOutput] == "CSV"
return createOutputCsv(settings, pathName, trainName, drivingCourse, movingSection)
else
return createOutputDict(settings, pathName, trainName, drivingCourse, movingSection)
end
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
if settings.typeOfOutput == "CSV"
if settings[:typeOfOutput] == "CSV"
return createOutputCsv(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
else
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
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
if settings.operationModeMinimumRunningTime
if settings.operationModeMinimumEnergyConsumption
if settings[:operationModeMinimumRunningTime]
if settings[:operationModeMinimumEnergyConsumption]
operationMode="minimum running time and minimum energy consumption"
else
operationMode="minimum running time"
end
else
if settings.operationModeMinimumEnergyConsumption
if settings[:operationModeMinimumEnergyConsumption]
operationMode="minimum energy consumption"
else
# should never be the case
@ -44,17 +44,18 @@ function createOutputDict(settings::Settings, pathName::String, trainName::Strin
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
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
row=[movingSection.length, movingSection.t, movingSection.E]
row=[movingSection[:length], movingSection[:t], movingSection[:E]]
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
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]
@ -62,29 +63,29 @@ function createOutputDict(settings::Settings, pathName::String, trainName::Strin
end
end
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))
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))
else
merge!(outputDict, Dict("outputArrayMinimumRunningTime"=>outputArray))
merge!(outputDict, Dict(:outputArrayMinimumRunningTime => outputArray))
end
println("The output dictionary has been created for ",operationMode,".")
println("The output dictionary has been created for ", operationMode,".")
return outputDict
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
if settings.operationModeMinimumRunningTime
if settings[:operationModeMinimumRunningTime]
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime)
if settings.operationModeMinimumEnergyConsumption
if settings[:operationModeMinimumEnergyConsumption]
# creating the second output array
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
row=[movingSectionMinimumEnergyConsumption.length, movingSectionMinimumEnergyConsumption.t, movingSectionMinimumEnergyConsumption.E]
row=[movingSectionMinimumEnergyConsumption[:length], movingSectionMinimumEnergyConsumption[:t], movingSectionMinimumEnergyConsumption[:E]]
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
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]
@ -92,7 +93,7 @@ function createOutputDict(settings::Settings, pathName::String, trainName::Strin
end
end
merge!(outputDict, Dict("outputArrayMinimumEnergyConsumption"=>outputArrayMinimumEnergyConsumption))
merge!(outputDict, Dict(:outputArrayMinimumEnergyConsumption => outputArrayMinimumEnergyConsumption))
end
else
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
@ -103,36 +104,36 @@ function createOutputDict(settings::Settings, pathName::String, trainName::Strin
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
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"
outputArray="outputArrayMinimumEnergyConsumption"
outputArray=:outputArrayMinimumEnergyConsumption
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvDirectory*"/"*dateString*"_MinimumEnergyConsumption.csv"
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumEnergyConsumption.csv"
else
operationMode="minimum running time"
outputArray="outputArrayMinimumRunningTime"
outputArray=:outputArrayMinimumRunningTime
date = Dates.now()
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
csvFilePath=settings.csvDirectory*"/"*dateString*"_MinimumRunningTime.csv"
csvFilePath=settings[:csvDirectory]*"/"*dateString*"_MinimumRunningTime.csv"
end
# creating information block
infoColumns=Array{Any,1}[]
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])
push!(infoColumns, ["", "", "", "", "", "", ""])
end # for
allColumns=Array{Any,1}[]
if settings.detailOfOutput=="minimal"
header=outputDict["outputArrayMinimumRunningTime"][1]
elseif settings.detailOfOutput=="driving course"
if settings[:detailOfOutput]=="minimal"
header=outputDict[:outputArrayMinimumRunningTime][1]
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)"]
end
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
if settings.detailOfOutput=="minimal"
if settings[:detailOfOutput]=="minimal"
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])
end
CSV.write(csvFilePath, df, header=false)
@ -156,89 +157,89 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
return outputDict
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
outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption)
if settings.operationModeMinimumRunningTime
if settings[:operationModeMinimumRunningTime]
#creating information block
infoColumns=Array{Any,1}[]
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, string(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]), ""])
for column in 3:length(outputDict["outputArrayMinimumRunningTime"][1])
for column in 3:length(outputDict[:outputArrayMinimumRunningTime][1])
push!(infoColumns, ["", "", "", "", "", "", ""])
# println("push wird ausgeführt")
end # for
allColumns=Array{Any,1}[]
if settings.detailOfOutput=="minimal"
header=outputDict["outputArrayMinimumRunningTime"][1]
elseif settings.detailOfOutput=="driving course"
if settings[:detailOfOutput]=="minimal"
header=outputDict[:outputArrayMinimumRunningTime][1]
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)"]
end
for column in 1:length(outputDict["outputArrayMinimumRunningTime"][1])
for column in 1:length(outputDict[:outputArrayMinimumRunningTime][1])
push!(infoColumns[column], header[column])
for row in outputDict["outputArrayMinimumRunningTime"][2:end]
for row in outputDict[:outputArrayMinimumRunningTime][2:end]
push!(infoColumns[column], row[column])
end
push!(allColumns, infoColumns[column])
end # for
#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])
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])
end
date = Dates.now()
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)
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
infoColumns=Array{Any,1}[]
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, ""])
for column in 3:length(outputDict["outputArrayMinimumEnergyConsumption"][1])
push!(infoColumns, [pathName, trainName, "minimum energy consumption", settings[:massModel], settings[:stepVariable], settings[:stepSize], ""])
for column in 3:length(outputDict[:outputArrayMinimumEnergyConsumption][1])
push!(infoColumns, ["", "", "", "", "", "", ""])
end # for
allColumns=Array{Any,1}[]
if settings.detailOfOutput=="minimal"
header=outputDict["outputArrayMinimumRunningTime"][1]
elseif settings.detailOfOutput=="driving course"
if settings[:detailOfOutput]=="minimal"
header=outputDict[:outputArrayMinimumRunningTime][1]
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)"]
end
for column in 1:length(outputDict["outputArrayMinimumEnergyConsumption"][1])
for column in 1:length(outputDict[:outputArrayMinimumEnergyConsumption][1])
push!(infoColumns[column], header[column])
for row in outputDict["outputArrayMinimumEnergyConsumption"][2:end]
for row in outputDict[:outputArrayMinimumEnergyConsumption][2:end]
push!(infoColumns[column], row[column])
end
push!(allColumns, infoColumns[column])
end # for
#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])
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])
end
# creating a CSV-file at csvDirectory
date = Dates.now()
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)
println("The output CSV file has been created for minimum energy consumption at ",csvFilePath)
end # if settings.operationModeMinimumEnergyConsumption
end # if settings[:operationModeMinimumEnergyConsumption]
return outputDict
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")
end #function printImportantValues
function printSectionInformation(movingSection::MovingSection)
println("MS mit length=", movingSection.length," mit t=", movingSection.t)
allBs=["breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting","cruisingAfterCoasting", "braking", "standStill"]
for csId in 1:length(movingSection.characteristicSections)
println("CS ",csId," mit length=", movingSection.characteristicSections[csId].length," mit t=", movingSection.characteristicSections[csId].t)
function printSectionInformation(movingSection::Dict)
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
println("MS mit length=", movingSection[:length]," mit t=", movingSection[:t])
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standStill]
for csId in 1:length(CSs)
println("CS ",csId," mit length=", CSs[csId].length," mit t=", CSs[csId].t)
for bs in 1: length(allBs)
if haskey(movingSection.characteristicSections[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)
# for point in 1:length(get(movingSection.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).dataPoints)
# println(get(movingSection.characteristicSections[csId].behaviorSections, allBs[bs], BehaviorSection()).dataPoints[point])
if haskey(CSs[csId].behaviorSections, allBs[bs])
println("BS ",allBs[bs], " mit s_entry=", CSs[csId].behaviorSections[allBs[bs]].s_entry, " und t=", CSs[csId].behaviorSections[allBs[bs]].t)
# for point in 1:length(CSs[csId].behaviorSections[allBs[bs]].dataPoints)
# println(CSs[csId].behaviorSections[allBs[bs]].dataPoints[point])
# end
end #if
end #for
@ -287,21 +290,21 @@ function plotDrivingCourse(drivingCourse::Vector{DataPoint})
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")
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, p3, p4, p5, p6, layout = (3, 2), legend = false)
# all=plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false)
display(all)
println("Plots for different variables have been created.")
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=[]
E_minTime=[]
s_minTime=[]
@ -340,17 +343,17 @@ function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{DataPoint},dr
label = ["v for t_min" "v for E_min"],
xlabel = "t in s")
# p3=plot([s_minTime,s_minEnergy],
# [t_minTime,t_minEnergy],
# title = "t in s",
# label = ["t for t_min" "t for E_min"],
# xlabel = "s in m")
# p3=plot([s_minTime,s_minEnergy],
# [t_minTime,t_minEnergy],
# title = "t in s",
# label = ["t for t_min" "t for E_min"],
# xlabel = "s in m")
# p4=plot([t_minTime,t_minEnergy],
# [s_minTime,s_minEnergy],
# title = "s in m",
# label = ["s for t_min" "s for E_min"],
# xlabel = "t in s")
# p4=plot([t_minTime,t_minEnergy],
# [s_minTime,s_minEnergy],
# title = "s in m",
# label = ["s for t_min" "s for E_min"],
# xlabel = "t in s")
p5=plot([s_minTime,s_minEnergy],
[E_minTime,E_minEnergy],
@ -364,7 +367,7 @@ function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{DataPoint},dr
label = ["E for t_min" "E for E_min"],
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)
display(all)
println("Plots for different variables have been created.")

View File

@ -7,49 +7,56 @@ using .MovingPhases
export preparateSections
## create a moving section and its containing characteristic sections with securedd braking, acceleration and cruising behavior
function preparateSections(path::Path, train::Train, settings::Settings)
movingSection=createMovingSection(path, train.v_limit)
movingSection=secureBrakingBehavior!(movingSection, train.a_braking)
function preparateSections(path::Dict, train::Dict, settings::Dict)
movingSection=createMovingSection(path, train[:v_limit])
movingSection=secureBrakingBehavior!(movingSection, train[:a_braking])
movingSection=secureAccelerationBehavior!(movingSection, settings, train)
movingSection=secureCruisingBehavior!(movingSection, settings, train)
return movingSection
end #function preparateSections
## 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
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
movingSection.t=0.0 # total running time (in s)
movingSection.E=0.0 # total energy consumption (in Ws)
s_entry = path[:sections][1][:s_start] # first position (in m)
s_exit = path[:sections][end][:s_end] # last position (in m)
pathLength = s_exit - s_entry # total length (in m)
movingSection.s_entry=path.sections[1].s_start # first position (in m)
movingSection.s_exit=path.sections[length(path.sections)].s_end # last position (in m)
movingSection.length=movingSection.s_exit-movingSection.s_entry # total length (in m)
s_csStart=movingSection.s_entry
CSs=[]
s_csStart=s_entry
csId=1
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
push!(movingSection.characteristicSections, createCharacteristicSection(csId, s_csStart, path.sections[row-1], min(path.sections[row-1].v_limit, v_trainLimit)))
s_csStart=path.sections[row].s_start
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]
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]
csId=csId+1
end #if
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
end #function createMovingSection
## 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
characteristicSection=CharacteristicSection()
characteristicSection.id=csId # identifier
characteristicSection.s_entry=s_csStart # first position (in m)
characteristicSection.s_exit=section.s_end # last position (in m)
characteristicSection.s_exit=section[:s_end] # last position (in m)
characteristicSection.length=characteristicSection.s_exit-characteristicSection.s_entry # total length (in m)
characteristicSection.t=0.0 # total running time (in s)
characteristicSection.E=0.0 # total energy consumption (in Ws)
@ -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_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
end #function createCharacteristicSection
## 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
csId=length(movingSection.characteristicSections)
movingSection.characteristicSections[csId].v_exit=0.0 # the exit velocity of the last characteristic section is 0.0 m/s
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
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
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)
movingSection.characteristicSections[csId].v_entry=min(movingSection.characteristicSections[csId].v_limit, v_entryMax)
movingSection.characteristicSections[csId].v_target=movingSection.characteristicSections[csId].v_entry
CSs[csId].v_entry=min(CSs[csId].v_limit, v_entryMax)
CSs[csId].v_target=CSs[csId].v_entry
csId=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 #while
return movingSection
end #function secureBrakingBehavior!
## 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
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.i=1
previousCSv_exit=movingSection.characteristicSections[1].v_entry
for csId in 1:length(movingSection.characteristicSections)
movingSection.characteristicSections[csId].v_entry=min(movingSection.characteristicSections[csId].v_entry, previousCSv_exit)
previousCSv_exit=CSs[1].v_entry
for csId in 1:length(CSs)
CSs[csId].v_entry=min(CSs[csId].v_entry, previousCSv_exit)
startingPoint.s=movingSection.characteristicSections[csId].s_entry
startingPoint.v=movingSection.characteristicSections[csId].v_entry
startingPoint.s=CSs[csId].s_entry
startingPoint.v=CSs[csId].v_entry
accelerationCourse=[startingPoint] # List of data points
if movingSection.characteristicSections[csId].v_entry<movingSection.characteristicSections[csId].v_target
(movingSection.characteristicSections[csId], accelerationCourse)=addAccelerationPhase!(movingSection.characteristicSections[csId], accelerationCourse, settings, train, movingSection.characteristicSections) # this function changes the accelerationCourse
movingSection.characteristicSections[csId].v_target=max(movingSection.characteristicSections[csId].v_entry,accelerationCourse[end].v)
if CSs[csId].v_entry<CSs[csId].v_target
(CSs[csId], accelerationCourse)=addAccelerationPhase!(CSs[csId], accelerationCourse, settings, train, CSs) # this function changes the accelerationCourse
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)
else #movingSection.characteristicSections[csId].v_entry==movingSection.characteristicSections[csId].v_target
CSs[csId].v_exit=min(CSs[csId].v_exit, CSs[csId].v_target, accelerationCourse[end].v)
else #CSs[csId].v_entry==CSs[csId].v_target
# v_exit stays the same
end #if
previousCSv_exit=movingSection.characteristicSections[csId].v_exit
previousCSv_exit=CSs[csId].v_exit
end #for
return movingSection
@ -117,24 +128,26 @@ end #function secureAccelerationBehavior!
## 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
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
startingPoint=DataPoint()
startingPoint.i=1
previousCSv_exit=movingSection.characteristicSections[1].v_entry
previousCSv_exit=CSs[1].v_entry
for csId in 1:length(movingSection.characteristicSections)
movingSection.characteristicSections[csId].v_entry=min(movingSection.characteristicSections[csId].v_entry, previousCSv_exit)
for csId in 1:length(CSs)
CSs[csId].v_entry=min(CSs[csId].v_entry, previousCSv_exit)
startingPoint.s=movingSection.characteristicSections[csId].s_entry
startingPoint.v=movingSection.characteristicSections[csId].v_target
startingPoint.s=CSs[csId].s_entry
startingPoint.v=CSs[csId].v_target
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
movingSection.characteristicSections[csId].v_exit=min(movingSection.characteristicSections[csId].v_exit, cruisingCourse[end].v)
(CSs[csId], cruisingCourse)=addCruisingPhase!(CSs[csId], cruisingCourse, CSs[csId].length, settings, train, CSs, "cruising") # this function changes the cruisingCourse
CSs[csId].v_exit=min(CSs[csId].v_exit, cruisingCourse[end].v)
previousCSv_exit=movingSection.characteristicSections[csId].v_exit
previousCSv_exit=CSs[csId].v_exit
end #for
return movingSection

View File

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

View File

@ -1,78 +1,6 @@
module types
# 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
## 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}())
export DataPoint, BehaviorSection, CharacteristicSection, EnergySavingModification
## 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_exit::AbstractFloat # maximum exit speed (in m/s)
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
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)
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}())
allBs=["breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting", "braking", "standStill"]
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]
for bs in 1: length(allBs)
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 #for
return copy
@ -171,31 +99,4 @@ function EnergySavingModification(original::EnergySavingModification)
return copy
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