From bee38ec311b17c6ddcda1cd695a511009c0c3f6f Mon Sep 17 00:00:00 2001 From: Max Kannenberg <95709892+MaxKannenberg@users.noreply.github.com> Date: Thu, 16 Dec 2021 14:39:25 +0100 Subject: [PATCH] Refactor some of the mutable structs from types.jl as Dictionaries --- Project.toml | 2 +- README.md | 8 + examples/MinimalWorkingExample.jl | 2 +- src/EnergySaving.jl | 367 +++++++------------ src/Input.jl | 318 +++++++---------- src/MovingPhases.jl | 575 ++++++++++++++---------------- src/OperationModes.jl | 283 +++++++-------- src/Output.jl | 173 ++++----- src/Preparation.jl | 113 +++--- src/TrainRun.jl | 16 +- src/types.jl | 111 +----- 11 files changed, 837 insertions(+), 1131 deletions(-) diff --git a/Project.toml b/Project.toml index f8b7267..15c0270 100644 --- a/Project.toml +++ b/Project.toml @@ -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" diff --git a/README.md b/README.md index 8844c61..d7e36a5 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/examples/MinimalWorkingExample.jl b/examples/MinimalWorkingExample.jl index b3879aa..92b4954 100644 --- a/examples/MinimalWorkingExample.jl +++ b/examples/MinimalWorkingExample.jl @@ -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.") diff --git a/src/EnergySaving.jl b/src/EnergySaving.jl index 26f0da7..699c0cf 100644 --- a/src/EnergySaving.jl +++ b/src/EnergySaving.jl @@ -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 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 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 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].s0.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) diff --git a/src/Input.jl b/src/Input.jl index 054d49f..dfe5a9c 100644 --- a/src/Input.jl +++ b/src/Input.jl @@ -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 diff --git a/src/MovingPhases.jl b/src/MovingPhases.jl index f3a509a..1648a41 100644 --- a/src/MovingPhases.jl +++ b/src/MovingPhases.jl @@ -45,27 +45,6 @@ function calculateTractiveEffort(v::AbstractFloat, tractiveEffortVelocityPairs) # TODO: also an extrapolation could be used return tractiveEffortVelocityPairs[end][2] end #function calculateTractiveEffort - #= old 2021-11-04: now with easier tractiveEffortVelocityPairs than previous tractiveEffortArray - function calculateTractiveEffort(v::AbstractFloat, tractiveEffortArray) - for row in 1:length(tractiveEffortArray) - if tractiveEffortArray[row][1]<=v && v<=tractiveEffortArray[row][2] - return tractiveEffortArray[row][3] - elseif tractiveEffortArray[row][1]>v - if row>1 - # interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-_(row-1))/(v_row-v_(row-1))+F_(row-1) - F_T_interpolation=(v-tractiveEffortArray[row-1][2])*(tractiveEffortArray[row][3]-tractiveEffortArray[row-1][3])/(tractiveEffortArray[row][1]-tractiveEffortArray[row-1][2])+tractiveEffortArray[row-1][3] - - return F_T_interpolation - else - return tractiveEffortArray[1][3] - end #if - end #if - end #for - # if v gets higher than the velocities in tractiveEffortArray the last tractive effort will be used - # TODO: also an extrapolation could be used - return tractiveEffortArray[end][3] - end #function calculateTractiveEffort - =# #TODO: choose an explanation and replace the ? ? ? @@ -78,7 +57,7 @@ Calculate the vehicle resistance for the traction unit of the `train` dependend ... # Arguments - `v::AbstractFloat`: the current velocity in m/s. -- `train::Train`: ? ? ? +- `train::Dict`: ? ? ? ... # Examples @@ -87,44 +66,44 @@ julia> calculateTractionUnitResistance(30.0, ? ? ?) ? ? ? ``` """ -function calculateTractionUnitResistance(v::AbstractFloat, train::Train) - return train.f_Rtd0/1000*train.m_td*g+train.f_Rtc0/1000*train.m_tc*g+train.F_Rt2*((v+train.Δv_t)/v00)^2 # /1000 because of the unit ‰ +function calculateTractionUnitResistance(v::AbstractFloat, train::Dict) + return train[:f_Rtd0]/1000*train[:m_td]*g+train[:f_Rtc0]/1000*train[:m_tc]*g+train[:F_Rt2]*((v+train[:Δv_t])/v00)^2 # /1000 because of the unit ‰ end #function calculateTractionUnitResistance """ calculate and return the wagons vehicle resistance dependend on the velocity """ -function calculateWagonsResistance(v::AbstractFloat, train::Train) - return train.m_w*g*(train.f_Rw0/1000+train.f_Rw1/1000*v/v00+train.f_Rw2/1000*((v+train.Δv_w)/v00)^2) # /1000 because of the unit ‰ +function calculateWagonsResistance(v::AbstractFloat, train::Dict) + return train[:m_w]*g*(train[:f_Rw0]/1000+train[:f_Rw1]/1000*v/v00+train[:f_Rw2]/1000*((v+train[:Δv_w])/v00)^2) # /1000 because of the unit ‰ end #function calculateWagonsResistance """ calculate and return the path resistance dependend on the trains position and mass model """ -function calculatePathResistance(s::AbstractFloat, massModel::String, train::Train, allCs::Vector{CharacteristicSection}) +function calculatePathResistance(s::AbstractFloat, massModel::String, train::Dict, CSs::Vector{CharacteristicSection}) # looking for the characteristic section with the trains head position - id=length(allCs) - while s0 && s-train.l_train0 && s-train[:l_train] 1 && currentPoint.s - l_train < allCs[csWithTrainHeadId].s_entry + if csWithTrainHeadId > 1 && currentPoint.s - l_train < CSs[csWithTrainHeadId].s_entry formerCsId=csWithTrainHeadId-1 - while formerCsId > 0 && currentPoint.s - l_train < allCs[formerCsId].s_exit - if allCs[formerCsId].v_limit < allCs[csWithTrainHeadId].v_limit # TODO: is the position of trains tail < movingSection.s_entry, v_limit of the first CS is used - push!(formerSpeedLimits, [allCs[formerCsId].s_exit, allCs[formerCsId].v_limit]) + while formerCsId > 0 && currentPoint.s - l_train < CSs[formerCsId].s_exit + if CSs[formerCsId].v_limit < CSs[csWithTrainHeadId].v_limit # TODO: is the position of trains tail < movingSection[:s_entry], v_limit of the first CS is used + push!(formerSpeedLimits, [CSs[formerCsId].s_exit, CSs[formerCsId].v_limit]) for i in 1:length(formerSpeedLimits)-1 if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2] pop!(formerSpeedLimits) @@ -232,71 +209,70 @@ function detectFormerSpeedLimits(allCs::Vector{CharacteristicSection}, csWithTra return formerSpeedLimits end # function detectFormerSpeedLimits -function considerFormerSpeedLimits!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}, formerSpeedLimits, accelerationSection::BehaviorSection) - # TODO: What is the type of formerSpeedLimits? function considerFormerSpeedLimits!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}, formerSpeedLimits::Array{Array{AbstractFloat,1},1}, accelerationSection::BehaviorSection) - # would work: function considerFormerSpeedLimits!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}, formerSpeedLimits::Array{Any,1}, accelerationSection::BehaviorSection) +function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, formerSpeedLimits, accelerationSection::BehaviorSection) + # TODO: What is the type of formerSpeedLimits? function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, formerSpeedLimits::Array{Array{AbstractFloat,1},1}, accelerationSection::BehaviorSection) + # would work: function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, formerSpeedLimits::Array{Any,1}, accelerationSection::BehaviorSection) if length(formerSpeedLimits) > 0 # if a former speed limit has been exceeded the acceleration steps of this CS will be removed and a clearing phase will be inserted before acceleration if drivingCourse[end].v > formerSpeedLimits[end][2] - # while drivingCourse[end].s > get(characteristicSection.behaviorSections, "clearing", accelerationSection).s_entry - while drivingCourse[end].s > get(characteristicSection.behaviorSections, "clearing", accelerationSection).s_entry + while drivingCourse[end].s > get(CS.behaviorSections, :clearing, accelerationSection).s_entry pop!(drivingCourse) end - if haskey(characteristicSection.behaviorSections, "clearing") - characteristicSection.t=characteristicSection.t-characteristicSection.behaviorSections["clearing"].t # reducing the total running time (in s) - characteristicSection.E=characteristicSection.E-characteristicSection.behaviorSections["clearing"].E # reducing the total energy consumption (in Ws) - delete!(characteristicSection.behaviorSections, "clearing") + if haskey(CS.behaviorSections, :clearing) + CS.t = CS.t-CS.behaviorSections[:clearing].t # reducing the total running time (in s) + CS.E = CS.E-CS.behaviorSections[:clearing].E # reducing the total energy consumption (in Ws) + delete!(CS.behaviorSections, :clearing) end # create a (new and longer) clearing section - s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel)) - s_clearing=min(characteristicSection.s_exit-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train.l_train)) + s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + s_clearing=min(CS.s_exit-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:l_train])) if s_clearing>0.0 - (characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_clearing, settings, train, allCs, "clearing") + (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") else - error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",characteristicSection.id) + error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS.id) end - # 09/22: if drivingCourse[end].s < characteristicSection.s_exit - if drivingCourse[end].s < characteristicSection.s_exit-s_braking + # 09/22: if drivingCourse[end].s < CS.s_exit + if drivingCourse[end].s < CS.s_exit-s_braking # reset the accelerationSection accelerationSection=BehaviorSection() accelerationSection.type="acceleration" # type of behavior section accelerationSection.s_entry=drivingCourse[end].s # first position (in m) accelerationSection.v_entry=drivingCourse[end].v # entry speed (in m/s) - #currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections + #currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections else - return (characteristicSection, drivingCourse, formerSpeedLimits, accelerationSection, true) + return (CS, drivingCourse, formerSpeedLimits, accelerationSection, true) end end # remove former speed limits of characteristic sections the train has left during the last step from the list - while length(formerSpeedLimits) > 0 && drivingCourse[end].s - train.l_train >= formerSpeedLimits[end][1] + while length(formerSpeedLimits) > 0 && drivingCourse[end].s - train[:l_train] >= formerSpeedLimits[end][1] pop!(formerSpeedLimits) end end - return (characteristicSection, drivingCourse, formerSpeedLimits, accelerationSection, false) + return (CS, drivingCourse, formerSpeedLimits, accelerationSection, false) end # function considerFormerSpeedLimits! ## This function calculates the data points of the breakFree phase. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for breakFree if needed. # Info: currently the values of the breakFree phase will be calculated like in the acceleration phase -function addStartingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}) - if drivingCourse[end].v==0.0 && drivingCourse[end].sbreakFreeSection)) + merge!(CS.behaviorSections, Dict(:breakFree => breakFreeSection)) end # else: return the characteristic section without a breakFree section - return (characteristicSection, drivingCourse) + return (CS, drivingCourse) end #function addStartingPhase! ## This function calculates the data points of the acceleration phase. # Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the acceleration section -function addAccelerationPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}) +function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) if drivingCourse[end].v==0.0 - (characteristicSection, drivingCourse)=addStartingPhase!(characteristicSection, drivingCourse, settings, train, allCs) + (CS, drivingCourse)=addStartingPhase!(CS, drivingCourse, settings, train, CSs) end #if - calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration") + calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") if drivingCourse[end].F_T < drivingCourse[end].F_R - (characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs) - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration")) + (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration")) end # if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept - formerSpeedLimits = detectFormerSpeedLimits(allCs, characteristicSection.id, drivingCourse[end], train.l_train) + formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:l_train]) # conditions for acceleration phase - targetSpeedReached = drivingCourse[end].v >= characteristicSection.v_target - trainAtEnd = drivingCourse[end].s >= characteristicSection.s_exit + targetSpeedReached = drivingCourse[end].v >= CS.v_target + trainAtEnd = drivingCourse[end].s >= CS.s_exit tractionSurplus = drivingCourse[end].F_T > drivingCourse[end].F_R # use the conditions for the acceleration phase if !targetSpeedReached && !trainAtEnd && tractionSurplus - #11/23 old without F_T > F_R: if drivingCourse[end].v < characteristicSection.v_target && drivingCourse[end].s drivingCourse[end].F_R + #11/23 long version: if drivingCourse[end].v < CS.v_target && drivingCourse[end].s drivingCourse[end].F_R accelerationSection=BehaviorSection() accelerationSection.type="acceleration" # type of behavior section accelerationSection.s_entry=drivingCourse[end].s # first position (in m) accelerationSection.v_entry=drivingCourse[end].v # entry speed (in m/s) push!(accelerationSection.dataPoints, drivingCourse[end].i) - currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections + currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - while drivingCourse[end].v drivingCourse[end].F_R - # 12/03 old with v>0.0: while drivingCourse[end].v0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R + while drivingCourse[end].v drivingCourse[end].F_R # traction effort and resisting forces (in N) - # 11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type)) + # 11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)) # acceleration (in m/s^2): - drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_train/train.ξ_train + drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] # create the next data point - push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id)) + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) push!(accelerationSection.dataPoints, drivingCourse[end].i) - # drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type)) + # drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)) if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal - (characteristicSection, drivingCourse, formerSpeedLimits, accelerationSection, endOfCsReached) = considerFormerSpeedLimits!(characteristicSection, drivingCourse, settings, train, allCs, formerSpeedLimits, accelerationSection) + (CS, drivingCourse, formerSpeedLimits, accelerationSection, endOfCsReached) = considerFormerSpeedLimits!(CS, drivingCourse, settings, train, CSs, formerSpeedLimits, accelerationSection) if endOfCsReached - return (characteristicSection, drivingCourse) + return (CS, drivingCourse) end #if - currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections + currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections end #if - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type)) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)) end #while # check which limit was reached and adjust the currentStepSize for the next cycle if cycle < approximationLevel+1 if drivingCourse[end].v<=0.0 - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].s>characteristicSection.s_exit - if settings.stepVariable == "s in m" - currentStepSize=characteristicSection.s_exit-drivingCourse[end-1].s + elseif drivingCourse[end].s>CS.s_exit + if settings[:stepVariable] == "s in m" + currentStepSize=CS.s_exit-drivingCourse[end-1].s else - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].v>characteristicSection.v_target - if settings.stepVariable=="v in m/s" - currentStepSize=characteristicSection.v_target-drivingCourse[end-1].v + elseif drivingCourse[end].v>CS.v_target + if settings[:stepVariable]=="v in m/s" + currentStepSize=CS.v_target-drivingCourse[end-1].v else - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].s==characteristicSection.s_exit + elseif drivingCourse[end].s==CS.s_exit break - elseif drivingCourse[end].v==characteristicSection.v_target + elseif drivingCourse[end].v==CS.v_target break elseif drivingCourse[end].F_T <= drivingCourse[end].F_R - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle else - error("ERROR at acceleration phase: With the step variable ",settings.stepVariable," the while loop will be left although vcharacteristicSection.v_target + elseif drivingCourse[end].v>CS.v_target pop!(drivingCourse) pop!(accelerationSection.dataPoints) - elseif drivingCourse[end].s>characteristicSection.s_exit - drivingCourse[end].s=characteristicSection.s_exit # rounding s down to s_exit + elseif drivingCourse[end].s>CS.s_exit + drivingCourse[end].s=CS.s_exit # rounding s down to s_exit elseif drivingCourse[end].F_T <= drivingCourse[end].F_R - (characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs) - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type)) + (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)) else @@ -471,101 +446,101 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri accelerationSection.length=accelerationSection.s_exit-accelerationSection.s_entry # total length (in m) accelerationSection.t=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) accelerationSection.E=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws) - characteristicSection.t=characteristicSection.t+accelerationSection.t # total running time (in s) - characteristicSection.E=characteristicSection.E+accelerationSection.E # total energy consumption (in Ws) + CS.t=CS.t+accelerationSection.t # total running time (in s) + CS.E=CS.E+accelerationSection.E # total energy consumption (in Ws) # TODO: this warning schould not be needed. just for testing - if characteristicSection.v_target < drivingCourse[end].v - println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_target=",characteristicSection.v_target) + if CS.v_target < drivingCourse[end].v + println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_target=",CS.v_target) end - merge!(characteristicSection.behaviorSections, Dict("acceleration"=>accelerationSection)) + merge!(CS.behaviorSections, Dict(:acceleration=>accelerationSection)) end end # else: just return the given data point number without changes due to the acceleration phase - return (characteristicSection, drivingCourse) + return (CS, drivingCourse) end #function addAccelerationPhase! ## This function calculates the data points of the acceleration phase. -function addAccelerationPhaseUntilBraking!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}) +function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) if drivingCourse[end].v==0.0 - (characteristicSection, drivingCourse)=addStartingPhase!(characteristicSection, drivingCourse, settings, train, allCs) + (CS, drivingCourse)=addStartingPhase!(CS, drivingCourse, settings, train, CSs) end #if - calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration") + calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") if drivingCourse[end].F_T < drivingCourse[end].F_R - (characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs) - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration")) + (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration")) end # if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept - formerSpeedLimits = detectFormerSpeedLimits(allCs, characteristicSection.id, drivingCourse[end], train.l_train) + formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:l_train]) - # 11/23 old without F_T>F_R: if drivingCourse[end].v < characteristicSection.v_target && drivingCourse[end].s drivingCourse[end].F_R + # 11/23 old without F_T>F_R: if drivingCourse[end].v < CS.v_target && drivingCourse[end].s drivingCourse[end].F_R accelerationSection=BehaviorSection() accelerationSection.type="acceleration" # type of behavior section accelerationSection.s_entry=drivingCourse[end].s # first position (in m) accelerationSection.v_entry=drivingCourse[end].v # entry speed (in m/s) push!(accelerationSection.dataPoints, drivingCourse[end].i) - currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections + currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel)) - while drivingCourse[end].v < characteristicSection.v_target && drivingCourse[end].s+s_braking drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend - # 12/03 old with v>0 while drivingCourse[end].v < characteristicSection.v_target && drivingCourse[end].s+s_braking0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend + s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + while drivingCourse[end].v < CS.v_target && drivingCourse[end].s+s_braking drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend + # 12/03 old with v>0 while drivingCourse[end].v < CS.v_target && drivingCourse[end].s+s_braking0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend - #11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type)) + #11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)) # acceleration (in m/s^2): - drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_train/train.ξ_train + drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] # if drivingCourse[end].a==0.0 # error("ERROR: a=0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_consist=",drivingCourse[end].R_consist," R_path=",drivingCourse[end].R_path) # end # create the next data point - push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id)) + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) push!(accelerationSection.dataPoints, drivingCourse[end].i) - # 12/03: was moved behind considerFormerSpeedLimits: drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type)) + # 12/03: was moved behind considerFormerSpeedLimits: drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)) if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal - (characteristicSection, drivingCourse, formerSpeedLimits, accelerationSection, endOfCsReached) = considerFormerSpeedLimits!(characteristicSection, drivingCourse, settings, train, allCs, formerSpeedLimits, accelerationSection) + (CS, drivingCourse, formerSpeedLimits, accelerationSection, endOfCsReached) = considerFormerSpeedLimits!(CS, drivingCourse, settings, train, CSs, formerSpeedLimits, accelerationSection) if endOfCsReached - return (characteristicSection, drivingCourse) + return (CS, drivingCourse) end end - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type)) - s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel)) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)) + s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) end #while # check which limit was reached and adjust the currentStepSize for the next cycle if cycle < approximationLevel+1 if drivingCourse[end].v<=0.0 - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].s +s_braking > characteristicSection.s_exit - currentStepSize = settings.stepSize / 10.0^cycle + elseif drivingCourse[end].s +s_braking > CS.s_exit + currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].v>characteristicSection.v_target - if settings.stepVariable=="v in m/s" - currentStepSize= characteristicSection.v_target-drivingCourse[end-1].v + elseif drivingCourse[end].v>CS.v_target + if settings[:stepVariable]=="v in m/s" + currentStepSize= CS.v_target-drivingCourse[end-1].v else - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].s==characteristicSection.s_exit + elseif drivingCourse[end].s==CS.s_exit break - elseif drivingCourse[end].v==characteristicSection.v_target + elseif drivingCourse[end].v==CS.v_target break elseif drivingCourse[end].F_T <= drivingCourse[end].F_R - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle else - error("ERROR at acceleration until braking phase: With the step variable ",settings.stepVariable," the while loop will be left although vcharacteristicSection.v_target + elseif drivingCourse[end].v>CS.v_target pop!(drivingCourse) pop!(accelerationSection.dataPoints) - elseif drivingCourse[end].s + s_braking > characteristicSection.s_exit + elseif drivingCourse[end].s + s_braking > CS.s_exit pop!(drivingCourse) pop!(accelerationSection.dataPoints) elseif drivingCourse[end].F_T <= drivingCourse[end].F_R - (characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs) - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type)) + (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)) else @@ -603,49 +578,49 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic accelerationSection.t=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) accelerationSection.E=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws) - characteristicSection.v_target=max(drivingCourse[end].v, characteristicSection.v_entry) # setting v_target to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances - characteristicSection.t=characteristicSection.t+accelerationSection.t # total running time (in s) - characteristicSection.E=characteristicSection.E+accelerationSection.E # total energy consumption (in Ws) + CS.v_target=max(drivingCourse[end].v, CS.v_entry) # setting v_target to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances + CS.t=CS.t+accelerationSection.t # total running time (in s) + CS.E=CS.E+accelerationSection.E # total energy consumption (in Ws) - merge!(characteristicSection.behaviorSections, Dict("acceleration"=>accelerationSection)) + merge!(CS.behaviorSections, Dict(:acceleration=>accelerationSection)) end end # else: just return the given data point number without changes due to the acceleration phase - return (characteristicSection, drivingCourse) + return (CS, drivingCourse) end #function addAccelerationPhaseUntilBraking! ## This function calculates the data points of the cruising phase. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for cruising if needed. -function addCruisingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, s_cruising::AbstractFloat, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}, cruisingType::String) +function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, s_cruising::AbstractFloat, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, cruisingType::String) # traction effort and resisting forces (in N) - calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"? + calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"? if drivingCourse[end].F_T < drivingCourse[end].F_R - (characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs) - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising")) - s_cruising=max(0.0, s_cruising-get(characteristicSection.behaviorSections, "diminishing", BehaviorSection()).length) + (CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) + drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")) + s_cruising = max(0.0, s_cruising-get(CS.behaviorSections, :diminishing, BehaviorSection()).length) end - if drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_target && drivingCourse[end].s= drivingCourse[end].F_R - # 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_target && drivingCourse[end].s0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s= drivingCourse[end].F_R + # 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s 1 - currentStepSize=settings.stepSize + if settings[:massModel]=="homogeneous strip" && CS.id > 1 + currentStepSize=settings[:stepSize] for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - while drivingCourse[end].s < characteristicSection.s_entry + train.l_train && drivingCourse[end].s=drivingCourse[end].F_R #&& drivingCourse[end].v<=characteristicSection.v_target && drivingCourse[end].s=drivingCourse[end].F_R #&& drivingCourse[end].v<=characteristicSection.v_target && drivingCourse[end].s=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_target && drivingCourse[end].s=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_target && drivingCourse[end].scruisingSection.s_entry+s_cruising # TODO also the following? drivingCourse[end].s > allCs[characteristicSection.id].s_entry + train.l_train)) - if settings.stepVariable == "s in m" + if drivingCourse[end].s>cruisingSection.s_entry+s_cruising # TODO also the following? drivingCourse[end].s > CSs[CS.id].s_entry + train[:l_train])) + if settings[:stepVariable] == "s in m" currentStepSize=cruisingSection.s_entry+s_cruising-drivingCourse[end-1].s else - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].s==cruisingSection.s_entry+s_cruising # || drivingCourse[end].s==characteristicSection.s_exit + elseif drivingCourse[end].s==cruisingSection.s_entry+s_cruising # || drivingCourse[end].s==CS.s_exit break elseif drivingCourse[end].F_T < drivingCourse[end].F_R - # if settings.stepVariable == "s in m" + # if settings[:stepVariable] == "s in m" # currentStepSize=cruisingSection.s_entry+s_cruising-drivingCourse[end-1].s # else - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle # end - elseif drivingCourse[end].s >= characteristicSection.s_entry + train.l_train - # TODO: whithout allCs should work as well, no? elseif drivingCourse[end].s >= allCs[characteristicSection.id].s_entry + train.l_train + elseif drivingCourse[end].s >= CS.s_entry + train[:l_train] + # TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS.id].s_entry + train[:l_train] break else # TODO copied from addAccelerationPhase -> probably not needed here !? - error("ERROR at cruising phase: With the step variable ",settings.stepVariable," the while loop will be left although the if cases don't apply in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") + error("ERROR at cruising phase: With the step variable ",settings[:stepVariable]," the while loop will be left although the if cases don't apply in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") end # delete last data point for recalculating the last step with reduced step size @@ -710,10 +685,10 @@ function addCruisingPhase!(characteristicSection::CharacteristicSection, driving # 11/21 ->| elseif drivingCourse[end].F_T < drivingCourse[end].F_R - (characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs) - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising")) + (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")) - # s_cruising=max(0.0, s_cruising-get(characteristicSection.behaviorSections, "diminishing", BehaviorSection()).length) + # s_cruising=max(0.0, s_cruising-get(CS.behaviorSections, :diminishing, BehaviorSection()).length) else @@ -731,16 +706,10 @@ function addCruisingPhase!(characteristicSection::CharacteristicSection, driving s_cruisingRemaining=cruisingSection.s_entry+s_cruising-drivingCourse[end].s # create the next data point - push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, characteristicSection.id)) + push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS.id)) push!(cruisingSection.dataPoints, drivingCourse[end].i) end - - ## new 09/06 TODO: if no acceleration is following the cruising it could be called cruising - #if cruisingSection.type == "clearing" && drivingCourse[end].s == characteristicSection.s_exit - # cruisingSection.type = "cruising" - #end - # calculate the accumulated cruising section information cruisingSection.v_exit=drivingCourse[end].v # exit speed (in m/s) cruisingSection.s_exit=drivingCourse[end].s # last position (in m) @@ -748,72 +717,72 @@ function addCruisingPhase!(characteristicSection::CharacteristicSection, driving cruisingSection.t=drivingCourse[end].t-drivingCourse[cruisingSection.dataPoints[1]].t # total running time (in s) cruisingSection.E=drivingCourse[end].E-drivingCourse[cruisingSection.dataPoints[1]].E # total energy consumption (in Ws) - characteristicSection.t=characteristicSection.t+cruisingSection.t # total running time (in s) - characteristicSection.E=characteristicSection.E+cruisingSection.E # total energy consumption (in Ws) + CS.t=CS.t+cruisingSection.t # total running time (in s) + CS.E=CS.E+cruisingSection.E # total energy consumption (in Ws) - merge!(characteristicSection.behaviorSections, Dict(cruisingSection.type=>cruisingSection)) + merge!(CS.behaviorSections, Dict(Symbol(cruisingSection.type) => cruisingSection)) end # else: return the characteristic section without a cruising section - return (characteristicSection, drivingCourse) + return (CS, drivingCourse) end #function addCruisingPhase! ## This function calculates the data points of the coasting phase. # Therefore it gets its previous driving course and the characteristic section and returns the characteristic section and driving course including the coasting section -function addCoastingPhaseUntilBraking!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}) +function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) ## if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept - #formerSpeedLimits = detectFormerSpeedLimits(allCs, characteristicSection.id, drivingCourse[end], train.l_train) + #formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:l_train]) - if drivingCourse[end].v>characteristicSection.v_exit && drivingCourse[end].sCS.v_exit && drivingCourse[end].scharacteristicSection.v_exit && drivingCourse[end].v<=characteristicSection.v_target && drivingCourse[end].s + s_braking < characteristicSection.s_exit # as long as s_i + s_braking < s_CSend + s_braking=ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel) + while drivingCourse[end].v>CS.v_exit && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s + s_braking < CS.s_exit # as long as s_i + s_braking < s_CSend # traction effort and resisting forces (in N): - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, coastingSection.type)) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, coastingSection.type)) # acceleration (in m/s^2): - drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_train/train.ξ_train + drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] # creating the next data point - push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id)) + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) push!(coastingSection.dataPoints, drivingCourse[end].i) - s_braking=ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking) + s_braking=ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking]) end # while # check which limit was reached and adjust the currentStepSize for the next cycle if cycle < approximationLevel+1 - if drivingCourse[end].s + s_braking > characteristicSection.s_exit - currentStepSize = settings.stepSize / 10.0^cycle + if drivingCourse[end].s + s_braking > CS.s_exit + currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].v < characteristicSection.v_exit # TODO: if accelereation and coasting functions will be combined this case is only for coasting - currentStepSize = settings.stepSize / 10.0^cycle + elseif drivingCourse[end].v < CS.v_exit # TODO: if accelereation and coasting functions will be combined this case is only for coasting + currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].v > characteristicSection.v_target - if settings.stepVariable=="v in m/s" - currentStepSize = characteristicSection.v_target-drivingCourse[end-1].v + elseif drivingCourse[end].v > CS.v_target + if settings[:stepVariable]=="v in m/s" + currentStepSize = CS.v_target-drivingCourse[end-1].v else - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].s + s_braking == characteristicSection.s_exit + elseif drivingCourse[end].s + s_braking == CS.s_exit break - elseif drivingCourse[end].v == characteristicSection.v_exit + elseif drivingCourse[end].v == CS.v_exit break else # TODO: not needed. just for testing - error("ERROR at coasting until braking phase: With the step variable ",settings.stepVariable," the while loop will be left although v characteristicSection.s_exit + elseif drivingCourse[end].s + s_braking > CS.s_exit # delete last data point because it went to far pop!(drivingCourse) pop!(coastingSection.dataPoints) - elseif drivingCourse[end].v > characteristicSection.v_target # if the train gets to fast it has to brake # TODO: if accelereation and coasting functions will be combined this case is different for coasting and also the order of if cases is different + elseif drivingCourse[end].v > CS.v_target # if the train gets to fast it has to brake # TODO: if accelereation and coasting functions will be combined this case is different for coasting and also the order of if cases is different # while coasting the train brakes to hold v_target (only one data point in the end of coasting is calculated like cruising at v_target) drivingCourse[end-1].a=0.0 - s_braking=ceil((characteristicSection.v_exit^2-drivingCourse[end-1].v^2)/2/train.a_braking) + s_braking=ceil((CS.v_exit^2-drivingCourse[end-1].v^2)/2/train[:a_braking]) # recalculate s, t, v, E - #drivingCourse[end].Δs= characteristicSection.s_exit-drivingCourse[end-1].s - s_braking # step size (in m) # TODO: the coasting section is currently realised with using distance steps. For example t_braking could also be used - drivingCourse[end].Δs=min(currentStepSize, characteristicSection.s_exit-(drivingCourse[end-1].s+s_braking)) # TODO: if settings.stepVariable=="s in m" + #drivingCourse[end].Δs= CS.s_exit-drivingCourse[end-1].s - s_braking # step size (in m) # TODO: the coasting section is currently realised with using distance steps. For example t_braking could also be used + drivingCourse[end].Δs=min(currentStepSize, CS.s_exit-(drivingCourse[end-1].s+s_braking)) # TODO: if settings[:stepVariable]=="s in m" drivingCourse[end].Δt=drivingCourse[end].Δs/drivingCourse[end-1].v # step size (in s) drivingCourse[end].Δv=0.0 # step size (in m/s) @@ -866,30 +835,30 @@ function addCoastingPhaseUntilBraking!(characteristicSection::CharacteristicSect coastingSection.t=drivingCourse[end].t-drivingCourse[coastingSection.dataPoints[1]].t # total running time (in s) coastingSection.E=drivingCourse[end].E-drivingCourse[coastingSection.dataPoints[1]].E # total energy consumption (in Ws) - characteristicSection.t=characteristicSection.t+coastingSection.t # total running time (in s) - characteristicSection.E=characteristicSection.E+coastingSection.E # total energy consumption (in Ws) + CS.t=CS.t+coastingSection.t # total running time (in s) + CS.E=CS.E+coastingSection.E # total energy consumption (in Ws) - merge!(characteristicSection.behaviorSections, Dict("coasting"=>coastingSection)) + merge!(CS.behaviorSections, Dict(:coasting=>coastingSection)) end ## else: just return the given data point number without changes due to the coasting phase - return (characteristicSection, drivingCourse) + return (CS, drivingCourse) end #function addCoastingPhaseUntilBraking! ## This function calculates the data points of the braking phase. (standard braking phase with only two data points) # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed. -function addBrakingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) - # function addBrakingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, massModel::String, train::Train, allCs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) - if drivingCourse[end].v>characteristicSection.v_exit && drivingCourse[end].sCS.v_exit && drivingCourse[end].s=0.0 + #= if drivingCourse[end-1].a=0.0 println("") - println("Warning: a_braking gets to high in CS ",characteristicSection.id, " with a=",drivingCourse[end-1].a ," > ",train.a_braking) + println("Warning: a_braking gets to high in CS ",CS.id, " with a=",drivingCourse[end-1].a ," > ",train[:a_braking]) println(" v=",drivingCourse[end].v," v_i-1=",drivingCourse[end-1].v, " Δs=",drivingCourse[end].Δs) - println(" v_exit=",characteristicSection.v_exit) + println(" v_exit=",CS.v_exit) println("") end =# drivingCourse[end].Δt=drivingCourse[end].Δv/drivingCourse[end-1].a # step size (in s) @@ -923,64 +892,64 @@ function addBrakingPhase!(characteristicSection::CharacteristicSection, drivingC brakingSection.t=drivingCourse[end].Δt # total running time (in s) brakingSection.E=drivingCourse[end].ΔE # total energy consumption (in Ws) - characteristicSection.t=characteristicSection.t+brakingSection.t # total running time (in s) - characteristicSection.E=characteristicSection.E+brakingSection.E # total energy consumption (in Ws) + CS.t=CS.t+brakingSection.t # total running time (in s) + CS.E=CS.E+brakingSection.E # total energy consumption (in Ws) - merge!(characteristicSection.behaviorSections, Dict("braking"=>brakingSection)) + merge!(CS.behaviorSections, Dict(:braking=>brakingSection)) end # else: return the characteristic section without a braking section - return (characteristicSection, drivingCourse) + return (CS, drivingCourse) end #function addBrakingPhase! ## This function calculates the data points of the braking phase. # 09/07 new braking phase with more than two data points # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for braking if needed. -function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) - if drivingCourse[end].v > characteristicSection.v_exit && drivingCourse[end].s < characteristicSection.s_exit +function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) + if drivingCourse[end].v > CS.v_exit && drivingCourse[end].s < CS.s_exit brakingSection=BehaviorSection() brakingSection.type="braking" # type of behavior section brakingSection.s_entry=drivingCourse[end].s # first position (in m) brakingSection.v_entry=drivingCourse[end].v # entry speed (in m/s) push!(brakingSection.dataPoints, drivingCourse[end].i) # refering from the breaking section to the first of its data points - currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections + currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections velocityIsPositive=true - while drivingCourse[end].v > characteristicSection.v_exit && drivingCourse[end].s < characteristicSection.s_exit && velocityIsPositive + while drivingCourse[end].v > CS.v_exit && drivingCourse[end].s < CS.s_exit && velocityIsPositive # traction effort and resisting forces (in N): - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, brakingSection.type)) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, brakingSection.type)) # acceleration (in m/s^2): - drivingCourse[end].a=train.a_braking + drivingCourse[end].a=train[:a_braking] # creating the next data point #TODO moveAStep should give back true or false for success or failure e.g. with dropping below v=0 m/s #at the moment it is only for stepVariable=="s in m" - if settings.stepVariable=="s in m" + if settings[:stepVariable]=="s in m" if ((drivingCourse[end].v/drivingCourse[end].a)^2+2*currentStepSize/drivingCourse[end].a)<0.0 || (drivingCourse[end].v^2+2*currentStepSize*drivingCourse[end].a)<0.0 velocityIsPositive=false break end end - push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id)) + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) push!(brakingSection.dataPoints, drivingCourse[end].i) - # s_braking=ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking) + # s_braking=ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking]) end # while - if drivingCourse[end].v < characteristicSection.v_exit || !velocityIsPositive + if drivingCourse[end].v < CS.v_exit || !velocityIsPositive # calculate s, t, v - drivingCourse[end].s=characteristicSection.s_exit # position (in m) - drivingCourse[end].v=characteristicSection.v_exit # velocity (in m/s) + drivingCourse[end].s=CS.s_exit # position (in m) + drivingCourse[end].v=CS.v_exit # velocity (in m/s) drivingCourse[end].Δs=drivingCourse[end].s-drivingCourse[end-1].s # step size (in m) drivingCourse[end].Δv=drivingCourse[end].v-drivingCourse[end-1].v # step size (in m/s) #drivingCourse[end-1].a=round((drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs, digits=approximationLevel) # acceleration (in m/s^2) (rounding because it should not be less than a_braking) drivingCourse[end-1].a=(drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs # acceleration (in m/s^2) - # println("a_braking_last=",drivingCourse[end-1].a," m/s^2 und a_braking_standard=" , train.a_braking) + # println("a_braking_last=",drivingCourse[end-1].a," m/s^2 und a_braking_standard=" , train[:a_braking]) - # if drivingCourse[end-1].a=0.0 - # println("Warning: a_braking gets to high in CS ",characteristicSection.id, " with a=",drivingCourse[end-1].a ," > ",train.a_braking) + # if drivingCourse[end-1].a=0.0 + # println("Warning: a_braking gets to high in CS ",CS.id, " with a=",drivingCourse[end-1].a ," > ",train[:a_braking]) # end drivingCourse[end].Δt=drivingCourse[end].Δv/drivingCourse[end-1].a # step size (in s) drivingCourse[end].t=drivingCourse[end-1].t+drivingCourse[end].Δt # point in time (in s) @@ -989,7 +958,7 @@ function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection, drivingCourse[end].W=drivingCourse[end-1].W+drivingCourse[end].ΔW # mechanical work (in Ws) drivingCourse[end].ΔE=drivingCourse[end].ΔW # energy consumption in this step (in Ws) drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws) - elseif drivingCourse[end].s > characteristicSection.s_exit + elseif drivingCourse[end].s > CS.s_exit error("Beim Bremsen wurde das CS-Ende überschritten, aber nicht v_exit unterschritten !!") else @@ -1002,21 +971,21 @@ function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection, brakingSection.t=drivingCourse[end].t-drivingCourse[brakingSection.dataPoints[1]].t # total running time (in s) brakingSection.E=drivingCourse[end].E-drivingCourse[brakingSection.dataPoints[1]].E # total energy consumption (in Ws) - characteristicSection.t=characteristicSection.t+brakingSection.t # total running time (in s) - characteristicSection.E=characteristicSection.E+brakingSection.E # total energy consumption (in Ws) + CS.t=CS.t+brakingSection.t # total running time (in s) + CS.E=CS.E+brakingSection.E # total energy consumption (in Ws) - merge!(characteristicSection.behaviorSections, Dict("braking"=>brakingSection)) + merge!(CS.behaviorSections, Dict(:braking=>brakingSection)) end # else: return the characteristic section without a braking section - return (characteristicSection, drivingCourse) + return (CS, drivingCourse) end #function addBrakingPhaseStepwise! ## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower -function addDiminishingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}) - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "diminishing")) +function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing")) - if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s0.0 && drivingCourse[end].v<=characteristicSection.v_target && drivingCourse[end].s 0.0 && drivingCourse[end].s0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s0.0 # as long as s_i + s_braking < s_CSend - # 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking0.0 # as long as s_i + s_braking < s_CSend + s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + while drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].s+s_braking0.0 # as long as s_i + s_braking < s_CSend + # 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking0.0 # as long as s_i + s_braking < s_CSend - #11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, diminishingSection.type)) + #11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type)) # acceleration (in m/s^2): - drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_train/train.ξ_train + drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] # 11/21: old, only for cruising: #if drivingCourse[end].a==0.0 # error("ERROR: a=0 m/s^2 in the diminishing phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_consist=",drivingCourse[end].R_consist," R_path=",drivingCourse[end].R_path) #end # create the next data point - push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id)) + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) push!(diminishingSection.dataPoints, drivingCourse[end].i) - s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel)) - drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, diminishingSection.type)) + s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type)) end #while # check which limit was reached and adjust the currentStepSize for the next cycle if cycle < approximationLevel+1 if drivingCourse[end].v<=0.0 - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].s + s_braking > characteristicSection.s_exit - currentStepSize = settings.stepSize / 10.0^cycle + elseif drivingCourse[end].s + s_braking > CS.s_exit + currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].s + s_braking==characteristicSection.s_exit - # 11/21 old without s_braking: elseif drivingCourse[end].s==characteristicSection.s_exit + elseif drivingCourse[end].s + s_braking==CS.s_exit + # 11/21 old without s_braking: elseif drivingCourse[end].s==CS.s_exit break elseif drivingCourse[end].F_T > drivingCourse[end].F_R - currentStepSize = settings.stepSize / 10.0^cycle + currentStepSize = settings[:stepSize] / 10.0^cycle else - error("ERROR during diminishing run: With the step variable ",settings.stepVariable," the while loop will be left although s+s_braking0.0 in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") + error("ERROR during diminishing run: With the step variable ",settings[:stepVariable]," the while loop will be left although s+s_braking0.0 in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") end # delete last data point for recalculating the last step with reduced step size pop!(drivingCourse) @@ -1072,11 +1041,11 @@ function addDiminishingPhase!(characteristicSection::CharacteristicSection, driv else # if the level of approximation is reached if drivingCourse[end].v<=0.0 # push!(diminishingSection.dataPoints, drivingCourse[end].i) - error("ERROR: The train stops during diminishing run in CS",characteristicSection.id," because the maximum tractive effort is lower than the resistant forces.", + error("ERROR: The train stops during diminishing run in CS",CS.id," because the maximum tractive effort is lower than the resistant forces.", " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_consist=",drivingCourse[end-1].R_consist," N R_path=",drivingCourse[end-1].R_path," N.") - elseif drivingCourse[end].s + s_braking > characteristicSection.s_exit + elseif drivingCourse[end].s + s_braking > CS.s_exit pop!(drivingCourse) pop!(diminishingSection.dataPoints) @@ -1096,14 +1065,14 @@ function addDiminishingPhase!(characteristicSection::CharacteristicSection, driv diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m) diminishingSection.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s) diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws) - characteristicSection.t=characteristicSection.t+diminishingSection.t # total running time (in s) - characteristicSection.E=characteristicSection.E+diminishingSection.E # total energy consumption (in Ws) + CS.t=CS.t+diminishingSection.t # total running time (in s) + CS.E=CS.E+diminishingSection.E # total energy consumption (in Ws) - merge!(characteristicSection.behaviorSections, Dict("diminishing"=>diminishingSection)) + merge!(CS.behaviorSections, Dict(:diminishing=>diminishingSection)) end end - return (characteristicSection, drivingCourse) + return (CS, drivingCourse) end #function addDiminishingPhase! end #module MovingPhases diff --git a/src/OperationModes.jl b/src/OperationModes.jl index cc8783f..596ab14 100644 --- a/src/OperationModes.jl +++ b/src/OperationModes.jl @@ -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 diff --git a/src/Output.jl b/src/Output.jl index 491ea89..3d03458 100644 --- a/src/Output.jl +++ b/src/Output.jl @@ -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.") diff --git a/src/Preparation.jl b/src/Preparation.jl index 6f5db28..ee0b2e1 100644 --- a/src/Preparation.jl +++ b/src/Preparation.jl @@ -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_entryBehaviorSection(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