From 0b15ba343d579846185fa8b233eb17823a0cf0ae Mon Sep 17 00:00:00 2001 From: Max Kannenberg <95709892+MaxKannenberg@users.noreply.github.com> Date: Mon, 10 Jan 2022 06:43:19 +0100 Subject: [PATCH] Refactor the mutable struct DataPoint as a Dictionary --- src/EnergySaving.jl | 426 +++++++++++++++++++++----- src/MovingPhases.jl | 691 ++++++++++++++++++++++-------------------- src/OperationModes.jl | 184 +++++------ src/Output.jl | 54 ++-- src/Preparation.jl | 26 +- src/TrainRun.jl | 2 +- src/types.jl | 58 ++-- 7 files changed, 859 insertions(+), 582 deletions(-) diff --git a/src/EnergySaving.jl b/src/EnergySaving.jl index 00c9973..44b1d7f 100644 --- a/src/EnergySaving.jl +++ b/src/EnergySaving.jl @@ -96,7 +96,8 @@ function calculateRecoveryTime(s_MS::Real, t_MS::AbstractFloat, train::Dict) end # if train[:type] end #function calculateRecoveryTime -function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) +# TODO: a refactoring caused worse drivingsCourses. see the commented function below +function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) BSsOriginal = csOriginal[:behaviorSections] if (haskey(BSsOriginal, :cruising) || haskey(BSsOriginal, :diminishing)) && haskey(BSsOriginal, :braking) # check if cruising or diminishing should be reduced for coasting @@ -121,7 +122,7 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi # 01/07 test for a better calculation time: cruisingReduction = settings[:stepSize]*100 while cruisingReduction>=settings[:stepSize]/10^approximationLevel #while cruisingReduction>=settings[:stepSize]/100 - while cruisingReduction>=settings[:stepSize]/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified[:v_exit] && drivingCourseModified[end].s see below at the end of the while loop + while cruisingReduction>=settings[:stepSize]/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end][:v]<=csModified[:v_exit] && drivingCourseModified[end][:s] see below at the end of the while loop # create a copy for the characteristic sections drivingCourse energySavingStartId=get(BSsOriginal, :cruising, Dict(:dataPoints=>[0]))[:dataPoints][1] @@ -130,11 +131,7 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi end # copy the driving course till the beginning of energy saving - drivingCourseModified=Vector{DataPoint}() - for i in 1: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 + drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving # calculating the new length of the cruising section if settings[:stepVariable]=="s in m" # distance step method @@ -142,8 +139,8 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi elseif settings[:stepVariable]=="t in s" # time step method # 09/20 old: doesn't work for non constant cruising -> TODO: should work now # t_cruising=BSsOriginal[:cruising][:t]-cruisingReduction - # s_cruising=t_cruising*drivingCourseModified[end].v - distanceReduction = drivingCourse[BSsOriginal[:cruising][:dataPoints][end]].v*cruisingReduction + # s_cruising=t_cruising*drivingCourseModified[end][:v] + distanceReduction = drivingCourse[BSsOriginal[:cruising][:dataPoints][end]][:v]*cruisingReduction s_cruising = BSsOriginal[:cruising][:length]-distanceReduction elseif settings[:stepVariable]=="v in m/s" # velocity step method @@ -202,7 +199,7 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi # calculate the coasting phase until the point the train needs to brake (csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs) - if drivingCourseModified[end].v < csModified[:v_exit] || drivingCourseModified[end].s > csModified[:s_exit] + 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 @@ -211,16 +208,16 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi end # while cruisingReduction # calculate the moving phase between coasting and the end of the CS - if drivingCourseModified[end].v > csModified[:v_exit] + if drivingCourseModified[end][:v] > csModified[:v_exit] #(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings[:massModel], train, allCSs) (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) - elseif drivingCourseModified[end].v == csModified[:v_exit] && drivingCourseModified[end].s < csModified[:s_exit] + elseif drivingCourseModified[end][:v] == csModified[:v_exit] && drivingCourseModified[end][:s] < csModified[:s_exit] # v_exit is already reached. Now cruise till the end of the CS - s_cruisingAfterCoasting=csModified[:s_exit]-drivingCourseModified[end].s + 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 + 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) @@ -277,11 +274,11 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi # remove the last diminishing waypoint pop!(diminishingSection[:dataPoints]) - diminishingSection[:v_exit]=drivingCourse[diminishingSection[:dataPoints][end]].v # exit speed (in m/s) - diminishingSection[:s_exit]=drivingCourse[diminishingSection[:dataPoints][end]].s # last position (in m) + diminishingSection[:v_exit]=drivingCourse[diminishingSection[:dataPoints][end]][:v] # exit speed (in m/s) + diminishingSection[:s_exit]=drivingCourse[diminishingSection[:dataPoints][end]][:s] # last position (in m) diminishingSection[:length]=diminishingSection[:s_exit]-diminishingSection[:s_entry] # total length (in m) - diminishingSection[:t]=drivingCourse[diminishingSection[:dataPoints][end]].t-drivingCourse[diminishingSection[:dataPoints][1]].t # total running time (in s) - diminishingSection[:E]=drivingCourse[diminishingSection[:dataPoints][end]].E-drivingCourse[diminishingSection[:dataPoints][1]].E # total energy consumption (in Ws) + diminishingSection[:t]=drivingCourse[diminishingSection[:dataPoints][end]][:t]-drivingCourse[diminishingSection[:dataPoints][1]][:t] # total running time (in s) + diminishingSection[:E]=drivingCourse[diminishingSection[:dataPoints][end]][:E]-drivingCourse[diminishingSection[:dataPoints][1]][:E] # total energy consumption (in Ws) merge!(BSsModified, Dict(:diminishing => diminishingSection)) csModified[:E] = csModified[:E] + BSsModified[:diminishing][:E] @@ -294,20 +291,17 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi end # copy the driving course till the beginning of energy saving - drivingCourseModified=Vector{DataPoint}() - for i in 1:energySavingStartId - push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving - end + drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving # calculate the coasting phase until the point the train needs to brake (csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs) # calculate the moving phase between coasting and the end of the CS - if drivingCourseModified[end].v > csModified[:v_exit] + if drivingCourseModified[end][:v] > csModified[:v_exit] (csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs) - elseif drivingCourseModified[end].v == csModified[:v_exit] && drivingCourseModified[end].s < csModified[:s_exit] + elseif drivingCourseModified[end][:v] == csModified[:v_exit] && drivingCourseModified[end][:s] < csModified[:s_exit] # v_exit is already reached. Now cruise till the end of the CS - s_cruisingAfterCoasting=csModified[:s_exit]-drivingCourseModified[end].s + s_cruisingAfterCoasting=csModified[:s_exit]-drivingCourseModified[end][:s] (csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting") end @@ -331,14 +325,200 @@ function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoi return (csOriginal, drivingCourse, false) end end # function increaseCoastingSection +#= +function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) + BSsOriginal = csOriginal[:behaviorSections] + if (haskey(BSsOriginal, :cruising) || (haskey(BSsOriginal, :diminishing) && get(BSsOriginal, :diminishing, Dict(:dataPoints =>[0]))[:dataPoints][1] > get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0]))[:dataPoints][1])) && haskey(BSsOriginal, :braking) + # check if cruising or diminishing should be reduced for coasting + if haskey(BSsOriginal, :cruising) && haskey(BSsOriginal, :diminishing) + if BSsOriginal[:cruising][:dataPoints][1] > BSsOriginal[:diminishing][:dataPoints][1] + reduceCruising=true + reduceDiminishing=false + else + reduceDiminishing=true + reduceCruising=false + end + elseif haskey(BSsOriginal, :cruising) + reduceCruising=true + reduceDiminishing=false + elseif haskey(BSsOriginal, :diminishing) + reduceDiminishing=true + reduceCruising=false + else + error("in increaseCoastingSection") #TODO + end -# method 2 with shortening the acceleration by stepsize + # copy csOriginal to csModifiedInitial + csModifiedInitial = copyCharacteristicSection(csOriginal) + BSsModified = csModifiedInitial[:behaviorSections] + + # delete bahavior sections that will be recalculated except breakFree, clearing, acceleration, diminishing + # and rest total running time and energy consumption + if haskey(BSsModified, :coasting) + csModifiedInitial[:E] = csModifiedInitial[:E] - BSsModified[:coasting][:E] + csModifiedInitial[:t] = csModifiedInitial[:t] - BSsModified[:coasting][:t] + delete!(BSsModified, :coasting) + end + if haskey(BSsModified, :cruisingAfterCoasting) + csModifiedInitial[:E] = csModifiedInitial[:E] - BSsModified[:cruisingAfterCoasting][:E] + csModifiedInitial[:t] = csModifiedInitial[:t] - BSsModified[:cruisingAfterCoasting][:t] + delete!(BSsModified, :cruisingAfterCoasting) + end + if haskey(BSsModified, :braking) + csModifiedInitial[:E] = csModifiedInitial[:E] - BSsModified[:braking][:E] + csModifiedInitial[:t] = csModifiedInitial[:t] - BSsModified[:braking][:t] + delete!(BSsModified, :braking) + end + if haskey(BSsModified, :standstill) + csModifiedInitial[:E] = csModifiedInitial[:E] - BSsModified[:standstill][:E] + csModifiedInitial[:t] = csModifiedInitial[:t] - BSsModified[:standstill][:t] + delete!(BSsModified, :standstill) + end + + + if reduceCruising + cruisingReduction = settings[:stepSize] + # 01/07 test for a better calculation time: cruisingReduction = settings[:stepSize]*100 + + # remove old cruising section + csModifiedInitial[:E] = csModifiedInitial[:E] - BSsModified[:cruising][:E] + csModifiedInitial[:t] = csModifiedInitial[:t] - BSsModified[:cruising][:t] + delete!(BSsModified, :cruising) + + # determine the starting point of saving energy (needed for copying the characteristic section's drivingCourse) + energySavingStartId=get(BSsOriginal, :cruising, Dict(:dataPoints=>[0]))[:dataPoints][1] + if energySavingStartId==0 + error("ERROR at creating a new driving course for energy saving with coasting !") + end + + 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 + # copy the characteristic section for being modified + csModified = copyCharacteristicSection(csModifiedInitial) + + # copy the driving course till the beginning of energy saving + drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving + + # calculating the new length of the cruising section + if settings[:stepVariable]=="s in m" # distance step method + s_cruising = BSsOriginal[:cruising][:length] - cruisingReduction + elseif settings[:stepVariable]=="t in s" # time step method + # 09/20 old: doesn't work for non constant cruising -> TODO: should work now + # t_cruising=BSsOriginal[:cruising][:t]-cruisingReduction + # s_cruising=t_cruising*drivingCourseModified[end][:v] + distanceReduction = drivingCourse[BSsOriginal[:cruising][:dataPoints][end]][:v] * cruisingReduction + s_cruising = BSsOriginal[:cruising][:length]-distanceReduction + + elseif settings[:stepVariable]=="v in m/s" # velocity step method + s_cruising=BSsOriginal[:cruising][:length]-cruisingReduction*10 # TODO: or better: *100 ? + end #if + s_cruising=max(0.0, s_cruising) + + # 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 + + # calculate the coasting phase until the point the train needs to brake + (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 + + # 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, 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 + + + elseif reduceDiminishing + # TODO: At the moment diminishing is reduced similar to the acceleration in decreaseMaximumVelocity. To reduce code the methods for reducing cruising phase and reducing the diminishing phase can be combined in some parts. + csModified = csModifiedInitial + diminishingSection = BSsModified[:diminishing] + + # remove the last diminishing waypoint + t_diff = drivingCourse[diminishingSection[:dataPoints][end]][:t] - drivingCourse[diminishingSection[:dataPoints][end-1]][:t] + E_diff = drivingCourse[diminishingSection[:dataPoints][end]][:E] - drivingCourse[diminishingSection[:dataPoints][end-1]][:E] + pop!(diminishingSection[:dataPoints]) + + diminishingSection[:v_exit] = drivingCourse[diminishingSection[:dataPoints][end]][:v] # exit speed (in m/s) + diminishingSection[:s_exit] = drivingCourse[diminishingSection[:dataPoints][end]][:s] # last position (in m) + diminishingSection[:length] = diminishingSection[:s_exit] - diminishingSection[:s_entry] # total length (in m) + diminishingSection[:t] = diminishingSection[:t] - t_diff # total running time (in s) + diminishingSection[:E] = diminishingSection[:E] - E_diff # total energy consumption (in Ws) + + # merge!(BSsModified, Dict(:diminishing => diminishingSection)) + csModified[:E] = csModified[:E] - t_diff + csModified[:t] = csModified[:t] - E_diff + + energySavingStartId = diminishingSection[:dataPoints][end] + + if length(diminishingSection[:dataPoints]) == 2 # The diminishing section was only one step. This step is removed and so the complette diminishing section. + delete!(BSsModified, :diminishing) + end + + # copy the driving course till the beginning of energy saving + drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving + + # calculate the coasting phase until the point the train needs to brake + (csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs) + + # 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, 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]) + return (csModified, drivingCourseModified, true) + else # time loss is to high. so there is no energy saving modification for this CS with the available recovery time + # TODO: just return false or take smaller steps? + + # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? + return (csOriginal, drivingCourse, false) + end + end + + # there is no energy saving modification for this CS with the available recovery time + # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? + return (csOriginal, drivingCourse, false) + 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 + # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? + return (csOriginal, drivingCourse, false) + end +end # function increaseCoastingSection +=# + +# TODO: with changing DataPoint to Dict and trying to use copy() there occured calculation errors that can't be corrected at the moment. see the code down below function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) - #function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) + #function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) BSsOriginal = csOriginal[:behaviorSections] if haskey(BSsOriginal, :acceleration) && csOriginal[:v_peak] > csOriginal[:v_entry] && csOriginal[:v_peak] > csOriginal[:v_exit] accelerationSection = copyBehaviorSection(BSsOriginal[:acceleration]) - if drivingCourse[accelerationSection[:dataPoints][end]-1].v < csOriginal[:v_exit] + if drivingCourse[accelerationSection[:dataPoints][end]-1][:v] < csOriginal[:v_exit] # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? return (csOriginal, drivingCourse, false) # TODO: or calculate a new acceleration phase with v_exit as v_peak? it will be very short, shorter than the step size. @@ -379,11 +559,11 @@ function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict # remove the last acceleration waypoint pop!(accelerationSection[:dataPoints]) - accelerationSection[:v_exit]=drivingCourse[accelerationSection[:dataPoints][end]].v # exit speed (in m/s) - accelerationSection[:s_exit]=drivingCourse[accelerationSection[:dataPoints][end]].s # last position (in m) + accelerationSection[:v_exit]=drivingCourse[accelerationSection[:dataPoints][end]][:v] # exit speed (in m/s) + accelerationSection[:s_exit]=drivingCourse[accelerationSection[:dataPoints][end]][:s] # last position (in m) accelerationSection[:length]=accelerationSection[:s_exit]-accelerationSection[:s_entry] # total length (in m) - accelerationSection[:t]=drivingCourse[accelerationSection[:dataPoints][end]].t-drivingCourse[accelerationSection[:dataPoints][1]].t # total running time (in s) - accelerationSection[:E]=drivingCourse[accelerationSection[:dataPoints][end]].E-drivingCourse[accelerationSection[:dataPoints][1]].E # total energy consumption (in Ws) + accelerationSection[:t]=drivingCourse[accelerationSection[:dataPoints][end]][:t]-drivingCourse[accelerationSection[:dataPoints][1]][:t] # total running time (in s) + accelerationSection[:E]=drivingCourse[accelerationSection[:dataPoints][end]][:E]-drivingCourse[accelerationSection[:dataPoints][1]][:E] # total energy consumption (in Ws) merge!(BSsModified, Dict(:acceleration=>accelerationSection)) csModified[:E] = csModified[:E] + BSsModified[:acceleration][:E] @@ -396,39 +576,36 @@ function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict end # TODO: should v_peak be reduced or is it enough to pop the data points? - # characteristicSection[:v_peak]=drivingCourse[end].v # setting v_peak to the last data point's velocity which is the highest reachable value in this characteristic section + # characteristicSection[:v_peak]=drivingCourse[end][:v] # setting v_peak to the last data point's velocity which is the highest reachable value in this characteristic section # copy the drivingCourse till the beginning of energy saving - drivingCourseModified=Vector{DataPoint}() - for i in 1:energySavingStartId - push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving - end + drivingCourseModified = drivingCourse[1:energySavingStartId] # List of data points till the start of energy saving #s_braking=max(0.0, ceil((csModified[:v_exit]^2-csModified[:v_peak]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors - s_braking=max(0.0, ceil((csModified[:v_exit]^2-drivingCourseModified[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors - s_cruising=csModified[:s_exit]-drivingCourseModified[end].s-s_braking + s_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 - if drivingCourseModified[end].v>csModified[:v_exit] + # 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, train, allCSs) - elseif drivingCourseModified[end].s0.001 - # if (csModified[:s_exit]-drivingCourseModified[end].s)>10^(-approximationLevel) + elseif drivingCourseModified[end][:s]0.001 + # if (csModified[:s_exit]-drivingCourseModified[end][:s])>10^(-approximationLevel) # println("INFO: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.") # println(" Therefore the calculation of this method can not continue for this CS.") # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? return (csOriginal, drivingCourse, false) end println("WARNING: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.") - println(" Therefore s=",drivingCourseModified[end].s," will be set s_exit=",csModified[:s_exit]," because the difference is only ",csModified[:s_exit]-drivingCourseModified[end].s," m.") - println(" v=",drivingCourseModified[end].v," m/s v_exit=",csOriginal[:v_exit] ," m/s") + println(" Therefore s=",drivingCourseModified[end][:s]," will be set s_exit=",csModified[:s_exit]," because the difference is only ",csModified[:s_exit]-drivingCourseModified[end][:s]," m.") + println(" v=",drivingCourseModified[end][:v]," m/s v_exit=",csOriginal[:v_exit] ," m/s") - drivingCourseModified[end].s=csModified[:s_exit] # rounding up to s_exit + drivingCourseModified[end][:s]=csModified[:s_exit] # rounding up to s_exit end #if if t_recoveryAvailable>=(csModified[:t]-csOriginal[:t]) @@ -455,39 +632,150 @@ function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict return (csOriginal, drivingCourse, false) end #if haskey end # function decreaseMaximumVelocity - -# combination of method 1 and method 2 -function combineEnergySavingMethods(csOriginal::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) +#= +# method 2 with shortening the acceleration by stepsize +function decreaseMaximumVelocity(csOriginal::Dict, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) + # TODO doesn't work that well alone. works better with combineEnergySavingMethods. why? does a while loop end to early or something like this? + #function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) BSsOriginal = csOriginal[:behaviorSections] - # if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && csOriginal[:v_peak]>csOriginal[:v_entry] && csOriginal[:v_peak]>csOriginal[:v_exit] - if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && drivingCourse[get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0]))[:dataPoints][end]].v > max(csOriginal[:v_entry], csOriginal[:v_exit]) - # 12/28 old: csCombined=CharacteristicSection(csOriginal) - #TODO after removing the mutable structs: Is it possible to just "copy"? - csCombined=Dict(:id => csOriginal[:id], # identifier + if haskey(BSsOriginal, :acceleration) && csOriginal[:v_peak] > csOriginal[:v_entry] && csOriginal[:v_peak] > csOriginal[:v_exit] + accelerationSection = copyBehaviorSection(BSsOriginal[:acceleration]) + + if drivingCourse[accelerationSection[:dataPoints][end]-1][:v] < csOriginal[:v_exit] + # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? + return (csOriginal, drivingCourse, false) + # TODO: or calculate a new acceleration phase with v_exit as v_peak? it will be very short, shorter than the step size. + end + + # copy csOriginal to csModified + # 12/28 old: csModified=CharacteristicSection(csOriginal[:id], csOriginal[:length], csOriginal[:s_entry], csOriginal[:s_exit], 0.0, 0.0, csOriginal[:v_limit], csOriginal[:v_peak], csOriginal[:v_entry], csOriginal[:v_exit], csOriginal[:r_path], Dict{Symbol, Dict}()) + csModified=Dict(:id => csOriginal[:id], # identifier :s_entry => csOriginal[:s_entry], # first position (in m) :s_exit => csOriginal[:s_exit], # last position (in m) :length => csOriginal[:length], # total length (in m) :r_path => csOriginal[:r_path], # path resistance (in ‰) :behaviorSections => Dict(), # empty list of containing behavior sections - :t => csOriginal[:t], # total running time (in s) - :E => csOriginal[:E], # total energy consumption (in Ws) + :t => 0.0, # total running time (in s) + :E => 0.0, # total energy consumption (in Ws) :v_limit => csOriginal[:v_limit], # speed limit (in m/s) :v_peak => csOriginal[:v_peak], # maximum reachable speed (in m/s) :v_entry => csOriginal[:v_entry], # maximum entry speed (in m/s) :v_exit => csOriginal[:v_exit]) # maximum exit speed (in m/s) - - allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] - for bs in 1: length(allBs) - if haskey(BSsOriginal, allBs[bs]) - merge!(csCombined[:behaviorSections], Dict(allBs[bs] => copyBehaviorSection(BSsOriginal[allBs[bs]]))) - end #if - end #for - - drivingCourseCombined=Vector{DataPoint}() - for i in 1:length(drivingCourse) - # TODO: tried to insert copy on 15.07.2021 push!(drivingCourseCombined, copy(drivingCourse[i])) - push!(drivingCourseCombined, DataPoint(drivingCourse[i])) + BSsModified = csModified[:behaviorSections] + if haskey(BSsOriginal, :breakFree) + breakFreeSection=copyBehaviorSection(BSsOriginal[:breakFree]) + merge!(BSsModified, Dict(:breakFree=>breakFreeSection)) + csModified[:E] = csModified[:E] + BSsModified[:breakFree][:E] + csModified[:t] = csModified[:t] + BSsModified[:breakFree][:t] end + if haskey(BSsOriginal, :diminishing) && BSsModified[:diminishing][:dataPoints][1] < BSsModified[:acceleration][:dataPoints][1] + diminishingSection=copyBehaviorSection(BSsOriginal[:diminishing]) + merge!(BSsModified, Dict(:diminishing=>diminishingSection)) + csModified[:E] = csModified[:E] + BSsModified[:diminishing][:E] + csModified[:t] = csModified[:t] + BSsModified[:diminishing][:t] + end + + if length(accelerationSection[:dataPoints]) > 2 + if haskey(BSsOriginal, :clearing) + clearingSection=copyBehaviorSection(BSsOriginal[:clearing]) + merge!(BSsModified, Dict(:clearing=>clearingSection)) + csModified[:E] = csModified[:E] + BSsModified[:clearing][:E] + csModified[:t] = csModified[:t] + BSsModified[:clearing][:t] + end + + # remove the last acceleration waypoint from the accelerationSection + pop!(accelerationSection[:dataPoints]) + energySavingStartId=accelerationSection[:dataPoints][end] + + accelerationSection[:v_exit]=drivingCourse[energySavingStartId][:v] # exit speed (in m/s) + accelerationSection[:s_exit]=drivingCourse[energySavingStartId][:s] # last position (in m) + accelerationSection[:length]=accelerationSection[:s_exit]-accelerationSection[:s_entry] # total length (in m) + accelerationSection[:t]=drivingCourse[energySavingStartId][:t]-drivingCourse[accelerationSection[:dataPoints][1]][:t] # total running time (in s) + accelerationSection[:E]=drivingCourse[energySavingStartId][:E]-drivingCourse[accelerationSection[:dataPoints][1]][:E] # total energy consumption (in Ws) + + merge!(BSsModified, Dict(:acceleration=>accelerationSection)) + csModified[:E] = csModified[:E] + accelerationSection[:E] + csModified[:t] = csModified[:t] + accelerationSection[:t] + + + else + # The acceleration section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section. + energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0])))[:dataPoints][1] + end + + # TODO: should v_peak be reduced or is it enough to pop the data points? + # characteristicSection[:v_peak]=drivingCourse[end][:v] # setting v_peak to the last data point's velocity which is the highest reachable value in this characteristic section + + # copy the drivingCourse till the beginning of energy saving + drivingCourseModified = copy(drivingCourse[1:energySavingStartId]) # List of data points till the start of energy saving + + #s_braking=max(0.0, ceil((csModified[:v_exit]^2-csModified[:v_peak]^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 > 1/10^approximationLevel + # old 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 + 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][:s]0.001 + # if (csModified[:s_exit]-drivingCourseModified[end][:s])>10^(-approximationLevel) + # println("INFO: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.") + # println(" Therefore the calculation of this method can not continue for this CS.") + # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? + return (csOriginal, drivingCourse, false) + end + println("WARNING: The end of new CS",csModified[:id]," is not reached while saving energy with lowering v_peak.") + println(" Therefore s=",drivingCourseModified[end][:s]," will be set s_exit=",csModified[:s_exit]," because the difference is only ",csModified[:s_exit]-drivingCourseModified[end][:s]," m.") + println(" v=",drivingCourseModified[end][:v]," m/s v_exit=",csOriginal[:v_exit] ," m/s") + + drivingCourseModified[end][:s]=csModified[:s_exit] # rounding up to s_exit + end #if + + if t_recoveryAvailable >= csModified[:t] - csOriginal[:t] + + return (csModified, drivingCourseModified, true) + else # time loss is to high. so there is no energy saving modification for this CS with the available recovery time + # 09/06 old: else # time loss is to high and the CS has to be calculated again with larger acceleration section (so with a smaller reduction of the acceleration section) + # 09/06 old: accelerationReduction=min(accelerationReduction/10, csModified[:v_peak]-csModified[:v_entry], csModified[:v_peak]-csModified[:v_exit]) + # TODO: just return false or take smaller steps? + + # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? + return (csOriginal, drivingCourse, false) + end + + # 09/06 old: end #while + # + # 09/06 old: # there is no energy saving modification for this CS with the available recovery time + # old: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? + # 12/29 new, now not with empty but with original CS and DC: return (csOriginal, drivingCourse, false) + + + else + # there is no energy saving modification for this CS because v_peak can not be lowered below v_entry or v_exit or because there is no acceleration section that can be transformed into a cruising section + # 12/29 old, now not with empty but with original CS and DC: return (Dict(), [], false) # TODO: Does the empty CS-Dict need default attributes? + return (csOriginal, drivingCourse, false) + end #if haskey +end # function decreaseMaximumVelocity +=# + +# combination of method 1 and method 2 +function combineEnergySavingMethods(csOriginal::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, allCSs::Vector{Dict}, t_recoveryAvailable::AbstractFloat) + BSsOriginal = csOriginal[:behaviorSections] + # if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && csOriginal[:v_peak]>csOriginal[:v_entry] && csOriginal[:v_peak]>csOriginal[:v_exit] + if haskey(BSsOriginal, :acceleration) && (haskey(BSsOriginal, :braking) || haskey(BSsOriginal, :coasting)) && drivingCourse[get(BSsOriginal, :acceleration, Dict(:dataPoints =>[0]))[:dataPoints][end]][:v] > max(csOriginal[:v_entry], csOriginal[:v_exit]) + # copy the characteristic section + csCombined = copyCharacteristicSection(csOriginal) + + # copy the drivingCourse + drivingCourseCombined = copy(drivingCourse) + ΔE=0.0 # saved energy (in Ws) Δt=0.0 # time loss (in s) #while (Δt - if previousPoint.a<0.0 - if ((previousPoint.v/previousPoint.a)^2+2*newPoint.Δs/previousPoint.a)<0.0 || (previousPoint.v^2+2*newPoint.Δs*previousPoint.a)<0.0 # checking if the parts of the following square roots will be <0.0 + if previousPoint[:a]<0.0 + if ((previousPoint[:v]/previousPoint[:a])^2+2*newPoint[:Δs]/previousPoint[:a])<0.0 || (previousPoint[:v]^2+2*newPoint[:Δs]*previousPoint[:a])<0.0 # checking if the parts of the following square roots will be <0.0 error("ERROR: The train stops during the acceleration phase in CS",csId," because the tractive effort is lower than the resistant forces.", - " Before the stop the last point has the values s=",previousPoint.s," m, v=",previousPoint.v," m/s, a=",previousPoint.a," m/s^2,", - " F_T=",previousPoint.F_T," N, R_traction=",previousPoint.R_traction," N, R_wagons=",previousPoint.R_wagons," N, R_path=",previousPoint.R_path," N.") + " Before the stop the last point has the values s=",previousPoint[:s]," m, v=",previousPoint[:v]," m/s, a=",previousPoint[:a]," m/s^2,", + " F_T=",previousPoint[:F_T]," N, R_traction=",previousPoint[:R_traction]," N, R_wagons=",previousPoint[:R_wagons]," N, R_path=",previousPoint[:R_path]," N.") end end # 11/21 ->| - newPoint.Δt=sign(previousPoint.a)*sqrt((previousPoint.v/previousPoint.a)^2+2*newPoint.Δs/previousPoint.a)-previousPoint.v/previousPoint.a # step size (in s) - newPoint.Δv=sqrt(previousPoint.v^2+2*newPoint.Δs*previousPoint.a)-previousPoint.v # step size (in m/s) + newPoint[:Δt]=sign(previousPoint[:a])*sqrt((previousPoint[:v]/previousPoint[:a])^2+2*newPoint[:Δs]/previousPoint[:a])-previousPoint[:v]/previousPoint[:a] # step size (in s) + newPoint[:Δv]=sqrt(previousPoint[:v]^2+2*newPoint[:Δs]*previousPoint[:a])-previousPoint[:v] # step size (in m/s) elseif stepVariable=="t in s" # time step method - newPoint.Δt=stepSize # step size (in s) - newPoint.Δs=newPoint.Δt*(2*previousPoint.v+newPoint.Δt*previousPoint.a)/2 # step size (in m) - newPoint.Δv=newPoint.Δt*previousPoint.a # step size (in m/s) + newPoint[:Δt]=stepSize # step size (in s) + newPoint[:Δs]=newPoint[:Δt]*(2*previousPoint[:v]+newPoint[:Δt]*previousPoint[:a])/2 # step size (in m) + newPoint[:Δv]=newPoint[:Δt]*previousPoint[:a] # step size (in m/s) elseif stepVariable=="v in m/s" # velocity step method - newPoint.Δv=stepSize*sign(previousPoint.a) # step size (in m/s) - newPoint.Δs=((previousPoint.v+newPoint.Δv)^2-previousPoint.v^2)/2/previousPoint.a # step size (in m) - newPoint.Δt=newPoint.Δv/previousPoint.a # step size (in s) + newPoint[:Δv]=stepSize*sign(previousPoint[:a]) # step size (in m/s) + newPoint[:Δs]=((previousPoint[:v]+newPoint[:Δv])^2-previousPoint[:v]^2)/2/previousPoint[:a] # step size (in m) + newPoint[:Δt]=newPoint[:Δv]/previousPoint[:a] # step size (in s) end #if - newPoint.s=previousPoint.s+newPoint.Δs # position (in m) - newPoint.t=previousPoint.t+newPoint.Δt # point in time (in s) - newPoint.v=previousPoint.v+newPoint.Δv # velocity (in m/s) - newPoint.ΔW=previousPoint.F_T*newPoint.Δs # mechanical work in this step (in Ws) - newPoint.W=previousPoint.W+newPoint.ΔW # mechanical work (in Ws) - newPoint.ΔE=newPoint.ΔW # energy consumption in this step (in Ws) - newPoint.E=previousPoint.E+newPoint.ΔE # energy consumption (in Ws) + newPoint[:s]=previousPoint[:s]+newPoint[:Δs] # position (in m) + newPoint[:t]=previousPoint[:t]+newPoint[:Δt] # point in time (in s) + newPoint[:v]=previousPoint[:v]+newPoint[:Δv] # velocity (in m/s) + newPoint[:ΔW]=previousPoint[:F_T]*newPoint[:Δs] # mechanical work in this step (in Ws) + newPoint[:W]=previousPoint[:W]+newPoint[:ΔW] # mechanical work (in Ws) + newPoint[:ΔE]=newPoint[:ΔW] # energy consumption in this step (in Ws) + newPoint[:E]=previousPoint[:E]+newPoint[:ΔE] # energy consumption (in Ws) return newPoint @@ -189,11 +190,11 @@ end #function moveAStep """ # 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 """ -function detectFormerSpeedLimits(CSs::Vector{Dict}, csWithTrainHeadId::Integer, currentPoint::DataPoint, trainLength::Real) +function detectFormerSpeedLimits(CSs::Vector{Dict}, csWithTrainHeadId::Integer, currentPoint::Dict, trainLength::Real) formerSpeedLimits=[] - if csWithTrainHeadId > 1 && currentPoint.s - trainLength < CSs[csWithTrainHeadId][:s_entry] + if csWithTrainHeadId > 1 && currentPoint[:s] - trainLength < CSs[csWithTrainHeadId][:s_entry] formerCsId=csWithTrainHeadId-1 - while formerCsId > 0 && currentPoint.s - trainLength < CSs[formerCsId][:s_exit] + while formerCsId > 0 && currentPoint[:s] - trainLength < 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 @@ -209,13 +210,13 @@ function detectFormerSpeedLimits(CSs::Vector{Dict}, csWithTrainHeadId::Integer, return formerSpeedLimits end # function detectFormerSpeedLimits -function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits, accelerationSection::Dict) - # TODO: What is the type of formerSpeedLimits? function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Array{AbstractFloat,1},1}, accelerationSection::Dict) - # would work: function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Any,1}, accelerationSection::Dict) +function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits, accelerationSection::Dict) + # TODO: What is the type of formerSpeedLimits? function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Array{AbstractFloat,1},1}, accelerationSection::Dict) + # would work: function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Any,1}, accelerationSection::Dict) if length(formerSpeedLimits) > 0 # if a former speed limit has been exceeded the acceleration steps of this CS will be removed and a clearing phase will be inserted before acceleration - if drivingCourse[end].v > formerSpeedLimits[end][2] - while drivingCourse[end].s > get(CS[:behaviorSections], :clearing, accelerationSection)[:s_entry] + if drivingCourse[end][:v] > formerSpeedLimits[end][2] + while drivingCourse[end][:s] > get(CS[:behaviorSections], :clearing, accelerationSection)[:s_entry] pop!(drivingCourse) end @@ -226,8 +227,8 @@ function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, end # create a (new and longer) clearing section - s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) - s_clearing=min(CS[:s_exit]-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:length])) + 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[:length])) if s_clearing>0.0 (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") @@ -235,17 +236,17 @@ function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS[:id]) end - # 09/22: if drivingCourse[end].s < CS[:s_exit] - if drivingCourse[end].s < CS[: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 = createBehaviorSection("acceleration", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i) + accelerationSection = createBehaviorSection("acceleration", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) else return (CS, drivingCourse, formerSpeedLimits, accelerationSection, true) end end # remove former speed limits of characteristic sections the train has left during the last step from the list - while length(formerSpeedLimits) > 0 && drivingCourse[end].s - train[:length] >= formerSpeedLimits[end][1] + while length(formerSpeedLimits) > 0 && drivingCourse[end][:s] - train[:length] >= formerSpeedLimits[end][1] pop!(formerSpeedLimits) end end @@ -255,61 +256,61 @@ 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 addBreakFreePhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) - if drivingCourse[end].v==0.0 && drivingCourse[end].s exact to 1 nm - drivingCourse[end].s=drivingCourse[end-1].s+drivingCourse[end].Δs # position (in m) - drivingCourse[end].t=drivingCourse[end-1].t+drivingCourse[end].Δt # point in time (in s) - drivingCourse[end].v=drivingCourse[end-1].v+drivingCourse[end].Δv # velocity (in m/s) - drivingCourse[end].ΔW=drivingCourse[end-1].F_T*drivingCourse[end].Δs # mechanical work in this step (in Ws) - 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) + #drivingCourse[end][:s]=ceil(drivingCourse[end-1][:s]+drivingCourse[end][:Δs], digits=approximationLevel) # position (in m) # rounded -> exact to 1 nm + drivingCourse[end][:s]=drivingCourse[end-1][:s]+drivingCourse[end][:Δs] # position (in m) + drivingCourse[end][:t]=drivingCourse[end-1][:t]+drivingCourse[end][:Δt] # point in time (in s) + drivingCourse[end][:v]=drivingCourse[end-1][:v]+drivingCourse[end][:Δv] # velocity (in m/s) + drivingCourse[end][:ΔW]=drivingCourse[end-1][:F_T]*drivingCourse[end][:Δs] # mechanical work in this step (in Ws) + 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) =# - push!(BS[:dataPoints], drivingCourse[end].i) + push!(BS[:dataPoints], drivingCourse[end][:i]) # calculate the accumulated breakFree section information - merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m) - :s_exit => drivingCourse[end].s, # last position (in m) - :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s) - :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws) - :v_exit => drivingCourse[end].v)) # exit speed (in m/s))) + merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) + :s_exit => drivingCourse[end][:s], # last position (in m) + :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) + :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) + :v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) @@ -322,13 +323,13 @@ end #function addBreakFreePhase! ## 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!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) - if drivingCourse[end].v==0.0 +function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) + if drivingCourse[end][:v]==0.0 (CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs) end #if calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") - if drivingCourse[end].F_T < drivingCourse[end].F_R + if drivingCourse[end][:F_T] < drivingCourse[end][:F_R] (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") end @@ -337,29 +338,29 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, setti formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:length]) # conditions for acceleration phase - targetSpeedReached = drivingCourse[end].v >= CS[:v_peak] - trainAtEnd = drivingCourse[end].s >= CS[:s_exit] - tractionSurplus = drivingCourse[end].F_T > drivingCourse[end].F_R + targetSpeedReached = drivingCourse[end][:v] >= CS[:v_peak] + 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 long version: if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s drivingCourse[end].F_R - BS = createBehaviorSection("acceleration", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i) - drivingCourse[end].behavior = BS[:type] + #11/23 long version: if drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s] drivingCourse[end][:F_R] + BS = createBehaviorSection("acceleration", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) + drivingCourse[end][:behavior] = BS[:type] currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - while drivingCourse[end].v drivingCourse[end].F_R + while drivingCourse[end][:v] drivingCourse[end][:F_R] # traction effort and resisting forces (in N) # 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) # acceleration (in m/s^2): - drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] + drivingCourse[end][:a]=(drivingCourse[end][:F_T]-drivingCourse[end][:F_R])/train[:m_train]/train[:ξ_train] # create the next data point push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) - drivingCourse[end].behavior = BS[:type] - push!(BS[:dataPoints], drivingCourse[end].i) + drivingCourse[end][:behavior] = BS[:type] + push!(BS[:dataPoints], drivingCourse[end][:i]) # calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) @@ -375,52 +376,52 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, setti # check which limit was reached and adjust the currentStepSize for the next cycle if cycle < approximationLevel+1 - if drivingCourse[end].v<=0.0 + if drivingCourse[end][:v]<=0.0 currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].s>CS[:s_exit] + elseif drivingCourse[end][:s]>CS[:s_exit] if settings[:stepVariable] == "s in m" - currentStepSize=CS[:s_exit]-drivingCourse[end-1].s + currentStepSize=CS[:s_exit]-drivingCourse[end-1][:s] else currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].v>CS[:v_peak] + elseif drivingCourse[end][:v]>CS[:v_peak] if settings[:stepVariable]=="v in m/s" - currentStepSize=CS[:v_peak]-drivingCourse[end-1].v + currentStepSize=CS[:v_peak]-drivingCourse[end-1][:v] else currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].s==CS[:s_exit] + elseif drivingCourse[end][:s]==CS[:s_exit] break - elseif drivingCourse[end].v==CS[:v_peak] + elseif drivingCourse[end][:v]==CS[:v_peak] break - elseif drivingCourse[end].F_T <= drivingCourse[end].F_R + elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] 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 vCS[:v_peak] + elseif drivingCourse[end][:v]>CS[:v_peak] pop!(drivingCourse) pop!(BS[:dataPoints]) - elseif drivingCourse[end].s>CS[:s_exit] - drivingCourse[end].s=CS[:s_exit] # rounding s down to s_exit + elseif drivingCourse[end][: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 + elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) @@ -432,18 +433,18 @@ function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, setti if length(BS[:dataPoints]) > 1 # 11/21 new: it is possible that the acceleration starts at v_peak, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section. # calculate the accumulated acceleration section information - merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m) - :s_exit => drivingCourse[end].s, # last position (in m) - :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s) - :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws) - :v_exit => drivingCourse[end].v)) # exit speed (in m/s))) + merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) + :s_exit => drivingCourse[end][:s], # last position (in m) + :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) + :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) + :v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) # TODO: this warning schould not be needed. just for testing - if CS[:v_peak] < drivingCourse[end].v - println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_peak=",CS[:v_peak]) + if CS[:v_peak] < drivingCourse[end][:v] + println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end][:v] ," > v_peak=",CS[:v_peak]) end merge!(CS[:behaviorSections], Dict(:acceleration=>BS)) @@ -455,13 +456,13 @@ end #function addAccelerationPhase! ## This function calculates the data points of the acceleration phase. -function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) - if drivingCourse[end].v==0.0 +function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) + if drivingCourse[end][:v]==0.0 (CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs) end #if calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") - if drivingCourse[end].F_T < drivingCourse[end].F_R + if drivingCourse[end][:F_T] < drivingCourse[end][:F_R] (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "acceleration") end @@ -470,29 +471,29 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:length]) - # 11/23 old without F_T>F_R: if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s drivingCourse[end].F_R - BS = createBehaviorSection("acceleration", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i) - drivingCourse[end].behavior = BS[:type] + # 11/23 old without F_T>F_R: if drivingCourse[end][:v] < CS[:v_peak] && drivingCourse[end][:s] drivingCourse[end][:F_R] + BS = createBehaviorSection("acceleration", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) + drivingCourse[end][:behavior] = BS[:type] currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) - while drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s+s_braking drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend - # 12/03 old with v>0 while drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s+s_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_peak] && 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_peak] && 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 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) # acceleration (in m/s^2): - drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] - # 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_wagons=",drivingCourse[end].R_wagons," R_path=",drivingCourse[end].R_path) + 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_wagons=",drivingCourse[end][:R_wagons]," R_path=",drivingCourse[end][:R_path]) # end # create the next data point push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) - drivingCourse[end].behavior = BS[:type] - push!(BS[:dataPoints], drivingCourse[end].i) + drivingCourse[end][:behavior] = BS[:type] + push!(BS[:dataPoints], drivingCourse[end][:i]) # 12/03: was moved behind considerFormerSpeedLimits: calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal @@ -502,55 +503,55 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP end end calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) - s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) end #while # check which limit was reached and adjust the currentStepSize for the next cycle if cycle < approximationLevel+1 - if drivingCourse[end].v<=0.0 + if drivingCourse[end][:v]<=0.0 currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].s +s_braking > CS[:s_exit] + elseif drivingCourse[end][:s] +s_braking > CS[:s_exit] currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].v>CS[:v_peak] + elseif drivingCourse[end][:v]>CS[:v_peak] if settings[:stepVariable]=="v in m/s" - currentStepSize= CS[:v_peak]-drivingCourse[end-1].v + currentStepSize= CS[:v_peak]-drivingCourse[end-1][:v] else currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].s==CS[:s_exit] + elseif drivingCourse[end][:s]==CS[:s_exit] break - elseif drivingCourse[end].v==CS[:v_peak] + elseif drivingCourse[end][:v]==CS[:v_peak] break - elseif drivingCourse[end].F_T <= drivingCourse[end].F_R + elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] 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 vCS[:v_peak] + elseif drivingCourse[end][:v]>CS[:v_peak] pop!(drivingCourse) pop!(BS[:dataPoints]) - elseif drivingCourse[end].s + s_braking > CS[:s_exit] + elseif drivingCourse[end][:s] + s_braking > CS[:s_exit] pop!(drivingCourse) pop!(BS[:dataPoints]) - elseif drivingCourse[end].F_T <= drivingCourse[end].F_R + elseif drivingCourse[end][:F_T] <= drivingCourse[end][:F_R] (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) @@ -562,13 +563,13 @@ function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataP if length(BS[:dataPoints]) > 1 # TODO: is it still possible that it is <=1 although there is a separate diminishing phase? # calculate the accumulated acceleration section information - merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m) - :s_exit => drivingCourse[end].s, # last position (in m) - :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s) - :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws) - :v_exit => drivingCourse[end].v)) # exit speed (in m/s))) + merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) + :s_exit => drivingCourse[end][:s], # last position (in m) + :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) + :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) + :v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) - CS[:v_peak]=max(drivingCourse[end].v, CS[:v_entry]) # setting v_peak to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances + CS[:v_peak]=max(drivingCourse[end][:v], CS[:v_entry]) # setting v_peak to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) @@ -581,19 +582,20 @@ 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!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruising::Real, settings::Dict, train::Dict, CSs::Vector{Dict}, cruisingType::String) +function addCruisingPhase!(CS::Dict, drivingCourse::Vector{Dict}, s_cruising::Real, settings::Dict, train::Dict, CSs::Vector{Dict}, cruisingType::String) # traction effort and resisting forces (in N) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") - if drivingCourse[end].F_T < drivingCourse[end].F_R + if drivingCourse[end][:F_T] < drivingCourse[end][:F_R] (CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) - drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")) + # 01/08 old with DataPoint as struct: old drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")) + calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") s_cruising = max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, Dict(:length=>0.0))[:length]) end - if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s= drivingCourse[end].F_R - # 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s0.0 && drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]= drivingCourse[end][:F_R] + # 11/22 old: if drivingCourse[end][:v]>0.0 && drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s] 1 currentStepSize=settings[:stepSize] for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - while drivingCourse[end].s < CS[:s_entry] + train[:length] && drivingCourse[end].s=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s=drivingCourse[end][:F_R] #&& drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]=drivingCourse[end][:F_R] #&& drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s]BS[:s_entry]+s_cruising # TODO also the following? drivingCourse[end].s > CSs[CS[:id]][:s_entry] + train[:length])) + if drivingCourse[end][:s]>BS[:s_entry]+s_cruising # TODO also the following? drivingCourse[end][:s] > CSs[CS[:id]][:s_entry] + train[:length])) if settings[:stepVariable] == "s in m" - currentStepSize=BS[:s_entry]+s_cruising-drivingCourse[end-1].s + currentStepSize=BS[:s_entry]+s_cruising-drivingCourse[end-1][:s] else currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].s==BS[:s_entry]+s_cruising # || drivingCourse[end].s==CS[:s_exit] + elseif drivingCourse[end][:s]==BS[:s_entry]+s_cruising # || drivingCourse[end][:s]==CS[:s_exit] break - elseif drivingCourse[end].F_T < drivingCourse[end].F_R + elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R] # if settings[:stepVariable] == "s in m" - # currentStepSize=BS[:s_entry]+s_cruising-drivingCourse[end-1].s + # currentStepSize=BS[:s_entry]+s_cruising-drivingCourse[end-1][:s] # else currentStepSize = settings[:stepSize] / 10.0^cycle # end - elseif drivingCourse[end].s >= CS[:s_entry] + train[:length] - # TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS[:id]][:s_entry] + train[:length] + elseif drivingCourse[end][:s] >= CS[:s_entry] + train[:length] + # TODO: whithout CSs should work as well, no? elseif drivingCourse[end][:s] >= CSs[CS[:id]][:s_entry] + train[:length] break else # TODO copied from addAccelerationPhase -> probably not needed here !? - error("ERROR at cruising phase: With the step variable ",settings[:stepVariable]," the while loop will be left although the if cases don't apply in CS",CS[:id]," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s") + 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 @@ -655,17 +657,17 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruisin pop!(BS[:dataPoints]) else # if the level of approximation is reached - if drivingCourse[end].s>BS[:s_entry]+s_cruising + if drivingCourse[end][:s]>BS[:s_entry]+s_cruising if BS[:type] == "clearing" else pop!(drivingCourse) pop!(BS[:dataPoints]) end # 11/21 |-> - elseif drivingCourse[end].s==BS[:s_entry]+s_cruising + elseif drivingCourse[end][:s]==BS[:s_entry]+s_cruising break # 11/21 ->| - elseif drivingCourse[end].F_T < drivingCourse[end].F_R + elseif drivingCourse[end][:F_T] < drivingCourse[end][:F_R] (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") @@ -680,25 +682,25 @@ function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruisin end #if # TODO oder soll das lieber nach oben in den else des letzten Durchlaufs. Noch mal genauer ansehen, ob hier was doppelt gemoppelt ist - # if drivingCourse[end].s= drivingCourse[end].F_R - drivingCourse[end].a=0.0 # acceleration (in m/s^2) + # if drivingCourse[end][:s]= drivingCourse[end][:F_R] + drivingCourse[end][:a]=0.0 # acceleration (in m/s^2) # calculate the remaining cruising way - s_cruisingRemaining=BS[:s_entry]+s_cruising-drivingCourse[end].s + s_cruisingRemaining=BS[:s_entry]+s_cruising-drivingCourse[end][:s] # create the next data point push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS[:id])) - drivingCourse[end].behavior = BS[:type] - push!(BS[:dataPoints], drivingCourse[end].i) + drivingCourse[end][:behavior] = BS[:type] + push!(BS[:dataPoints], drivingCourse[end][:i]) end # calculate the accumulated cruising section information - merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m) - :s_exit => drivingCourse[end].s, # last position (in m) - :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s) - :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws) - :v_exit => drivingCourse[end].v)) # exit speed (in m/s))) + merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) + :s_exit => drivingCourse[end][:s], # last position (in m) + :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) + :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) + :v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) @@ -711,71 +713,71 @@ end #function addCruisingPhase! ## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower -function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) +function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing") - if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s 0.0 && drivingCourse[end][:s]0.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 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) # acceleration (in m/s^2): - drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train] + 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_wagons=",drivingCourse[end].R_wagons," R_path=",drivingCourse[end].R_path) + #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_wagons=",drivingCourse[end][:R_wagons]," R_path=",drivingCourse[end][:R_path]) #end # create the next data point push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) - drivingCourse[end].behavior = BS[:type] - push!(BS[:dataPoints], drivingCourse[end].i) + drivingCourse[end][:behavior] = BS[:type] + push!(BS[:dataPoints], drivingCourse[end][:i]) - s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel)) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[: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 + if drivingCourse[end][:v]<=0.0 currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].s + s_braking > CS[:s_exit] + elseif drivingCourse[end][:s] + s_braking > CS[:s_exit] currentStepSize = settings[:stepSize] / 10.0^cycle - elseif drivingCourse[end].s + s_braking==CS[:s_exit] - # 11/21 old without s_braking: elseif drivingCourse[end].s==CS[: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 + elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R] 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",CS[: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) pop!(BS[:dataPoints]) else # if the level of approximation is reached - if drivingCourse[end].v<=0.0 - # push!(BS[:dataPoints], drivingCourse[end].i) + if drivingCourse[end][:v]<=0.0 + # push!(BS[:dataPoints], drivingCourse[end][:i]) error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.", - " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", - " F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_wagons=",drivingCourse[end-1].R_wagons," N R_path=",drivingCourse[end-1].R_path," N.") + " Before the stop the last point has the values s=",drivingCourse[end-1][:s]," m v=",drivingCourse[end-1][:v]," m/s a=",drivingCourse[end-1][:a]," m/s^2", + " F_T=",drivingCourse[end-1][:F_T]," N R_traction=",drivingCourse[end-1][:R_traction]," N R_wagons=",drivingCourse[end-1][:R_wagons]," N R_path=",drivingCourse[end-1][:R_path]," N.") - elseif drivingCourse[end].s + s_braking > CS[:s_exit] + elseif drivingCourse[end][:s] + s_braking > CS[:s_exit] pop!(drivingCourse) pop!(BS[:dataPoints]) - elseif drivingCourse[end].F_T > drivingCourse[end].F_R + elseif drivingCourse[end][:F_T] > drivingCourse[end][:F_R] break else @@ -786,11 +788,11 @@ function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settin if length(BS[:dataPoints]) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start # calculate the accumulated diminishing section information - merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m) - :s_exit => drivingCourse[end].s, # last position (in m) - :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s) - :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws) - :v_exit => drivingCourse[end].v)) # exit speed (in m/s))) + merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) + :s_exit => drivingCourse[end][:s], # last position (in m) + :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) + :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) + :v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) @@ -805,97 +807,97 @@ end #function addDiminishingPhase! ## 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!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) +function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) ## if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept #formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:length]) - if drivingCourse[end].v>CS[:v_exit] && drivingCourse[end].sCS[:v_exit] && drivingCourse[end][:s]CS[:v_exit] && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s + s_braking < CS[:s_exit] # as long as s_i + s_braking < s_CSend + s_braking=ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking], digits=approximationLevel) + while drivingCourse[end][:v]>CS[:v_exit] && drivingCourse[end][:v]<=CS[:v_peak] && drivingCourse[end][:s] + s_braking < CS[:s_exit] # as long as s_i + s_braking < s_CSend # traction effort and resisting forces (in N): calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[: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, CS[:id])) - drivingCourse[end].behavior = BS[:type] - push!(BS[:dataPoints], drivingCourse[end].i) + drivingCourse[end][:behavior] = BS[:type] + push!(BS[:dataPoints], drivingCourse[end][:i]) - s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking]) + 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 > CS[:s_exit] + if drivingCourse[end][:s] + s_braking > CS[:s_exit] 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 + 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 > CS[:v_peak] + elseif drivingCourse[end][:v] > CS[:v_peak] if settings[:stepVariable]=="v in m/s" - currentStepSize = CS[:v_peak]-drivingCourse[end-1].v + currentStepSize = CS[:v_peak]-drivingCourse[end-1][:v] else currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].s + s_braking == CS[:s_exit] + elseif drivingCourse[end][:s] + s_braking == CS[:s_exit] break - elseif drivingCourse[end].v == CS[: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 CS[:s_exit] + elseif drivingCourse[end][:s] + s_braking > CS[:s_exit] # delete last data point because it went to far pop!(drivingCourse) pop!(BS[:dataPoints]) - elseif drivingCourse[end].v > CS[:v_peak] # if the train gets to fast it has to brake # TODO: if accelereation and coasting functions will be combined this case is different for coasting and also the order of if cases is different + elseif drivingCourse[end][:v] > CS[:v_peak] # if the train gets to fast it has to brake # TODO: if accelereation and coasting functions will be combined this case is different for coasting and also the order of if cases is different # while coasting the train brakes to hold v_peak (only one data point in the end of coasting is calculated like cruising at v_peak) - drivingCourse[end-1].a=0.0 - s_braking=ceil((CS[:v_exit]^2-drivingCourse[end-1].v^2)/2/train[:a_braking]) + drivingCourse[end-1][:a]=0.0 + s_braking=ceil((CS[:v_exit]^2-drivingCourse[end-1][:v]^2)/2/train[:a_braking]) # recalculate s, t, v, E - #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) + #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) - drivingCourse[end].s=drivingCourse[end-1].s+drivingCourse[end].Δs # position (in m) - drivingCourse[end].t=drivingCourse[end-1].t+drivingCourse[end].Δt # point in time (in s) - drivingCourse[end].v=drivingCourse[end-1].v # velocity (in m/s) + drivingCourse[end][:s]=drivingCourse[end-1][:s]+drivingCourse[end][:Δs] # position (in m) + drivingCourse[end][:t]=drivingCourse[end-1][:t]+drivingCourse[end][:Δt] # point in time (in s) + drivingCourse[end][:v]=drivingCourse[end-1][:v] # velocity (in m/s) - drivingCourse[end].ΔW=drivingCourse[end-1].F_T*drivingCourse[end].Δs # mechanical work in this step (in Ws) + drivingCourse[end][:ΔW]=drivingCourse[end-1][:F_T]*drivingCourse[end][:Δs] # mechanical work in this step (in Ws) # =0.0 - drivingCourse[end].W=drivingCourse[end-1].W+drivingCourse[end].ΔW # mechanical work (in Ws) - # =drivingCourse[end-1].W - drivingCourse[end].ΔE=drivingCourse[end].ΔW # energy consumption in this step (in Ws) + drivingCourse[end][:W]=drivingCourse[end-1][:W]+drivingCourse[end][:ΔW] # mechanical work (in Ws) + # =drivingCourse[end-1][:W] + drivingCourse[end][:ΔE]=drivingCourse[end][:ΔW] # energy consumption in this step (in Ws) # =0.0 - drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws) - # =drivingCourse[end-1].E + drivingCourse[end][:E]=drivingCourse[end-1][:E]+drivingCourse[end][:ΔE] # energy consumption (in Ws) + # =drivingCourse[end-1][:E] else end @@ -903,11 +905,11 @@ function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint end #for # calculate the accumulated coasting section information - merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m) - :s_exit => drivingCourse[end].s, # last position (in m) - :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s) - :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws) - :v_exit => drivingCourse[end].v)) # exit speed (in m/s))) + merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) + :s_exit => drivingCourse[end][:s], # last position (in m) + :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) + :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) + :v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) @@ -920,49 +922,49 @@ 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!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat) - # function addBrakingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, massModel::String, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat) - if drivingCourse[end].v>CS[:v_exit] && drivingCourse[end].sCS[:v_exit] && drivingCourse[end][:s]=0.0 + # 09/21 old: rounding is not necessary. 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] + #= if drivingCourse[end-1][:a]=0.0 println("") - 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("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=",CS[:v_exit]) println("") 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) + 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) - drivingCourse[end].ΔW=0.0 # mechanical work in this step (in Ws) - 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) + drivingCourse[end][:ΔW]=0.0 # mechanical work in this step (in Ws) + 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) - merge!(BS, Dict(:length => drivingCourse[end].Δs, # total length (in m) - #:s_exit => drivingCourse[end].s, # last position (in m) - :t => drivingCourse[end].Δt, # total running time (in s) - :E => drivingCourse[end].ΔE, # total energy consumption (in Ws) - :v_exit => drivingCourse[end].v)) # exit speed (in m/s))) + merge!(BS, Dict(:length => drivingCourse[end][:Δs], # total length (in m) + #:s_exit => drivingCourse[end][:s], # last position (in m) + :t => drivingCourse[end][:Δt], # total running time (in s) + :E => drivingCourse[end][:ΔE], # total energy consumption (in Ws) + :v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) @@ -975,69 +977,69 @@ 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!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat) - if drivingCourse[end].v > CS[:v_exit] && drivingCourse[end].s < CS[:s_exit] - BS = createBehaviorSection("braking", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i) - drivingCourse[end].behavior = BS[:type] +function addBrakingPhaseStepwise!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) #, s_braking::AbstractFloat) + if drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:s] < CS[:s_exit] + BS = createBehaviorSection("braking", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) + drivingCourse[end][:behavior] = BS[:type] currentStepSize=settings[:stepSize] # initialize the step size that can be reduced near intersections velocityIsPositive=true - while drivingCourse[end].v > CS[:v_exit] && drivingCourse[end].s < CS[:s_exit] && velocityIsPositive + while drivingCourse[end][:v] > CS[:v_exit] && drivingCourse[end][:s] < CS[:s_exit] && velocityIsPositive # traction effort and resisting forces (in N): calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[: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 ((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 + 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, CS[:id])) - drivingCourse[end].behavior = BS[:type] - push!(BS[:dataPoints], drivingCourse[end].i) + drivingCourse[end][:behavior] = BS[:type] + push!(BS[:dataPoints], drivingCourse[end][:i]) - # s_braking=ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking]) + # s_braking=ceil((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking]) end # while - if drivingCourse[end].v < CS[:v_exit] || !velocityIsPositive + if drivingCourse[end][:v] < CS[:v_exit] || !velocityIsPositive # calculate s, t, v - 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][: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) + #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) - # 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]) + # 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) + 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) - drivingCourse[end].ΔW=0.0 # mechanical work in this step (in Ws) - 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 > CS[:s_exit] + drivingCourse[end][:ΔW]=0.0 # mechanical work in this step (in Ws) + 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] > CS[:s_exit] error("Beim Bremsen wurde das CS-Ende überschritten, aber nicht v_exit unterschritten !!") else end # calculate the accumulated coasting section information - merge!(BS, Dict(:length => drivingCourse[end].s - BS[:s_entry], # total length (in m) - :s_exit => drivingCourse[end].s, # last position (in m) - :t => drivingCourse[end].t - drivingCourse[BS[:dataPoints][1]].t, # total running time (in s) - :E => drivingCourse[end].E - drivingCourse[BS[:dataPoints][1]].E, # total energy consumption (in Ws) - :v_exit => drivingCourse[end].v)) # exit speed (in m/s))) + merge!(BS, Dict(:length => drivingCourse[end][:s] - BS[:s_entry], # total length (in m) + :s_exit => drivingCourse[end][:s], # last position (in m) + :t => drivingCourse[end][:t] - drivingCourse[BS[:dataPoints][1]][:t], # total running time (in s) + :E => drivingCourse[end][:E] - drivingCourse[BS[:dataPoints][1]][:E], # total energy consumption (in Ws) + :v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) CS[:t]=CS[:t]+BS[:t] # total running time (in s) CS[:E]=CS[:E]+BS[:E] # total energy consumption (in Ws) @@ -1050,16 +1052,16 @@ end #function addBrakingPhaseStepwise! ## This function calculates the data point of the standstill. # Therefore it gets its first data point and the characteristic section and returns the characteristic section including the standstill if needed. -function addStandstill!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) +function addStandstill!(CS::Dict, drivingCourse::Vector{Dict}, settings::Dict, train::Dict, CSs::Vector{Dict}) - if drivingCourse[end].v == 0.0 - BS = createBehaviorSection("standstill", drivingCourse[end].s, drivingCourse[end].v, drivingCourse[end].i) + if drivingCourse[end][:v] == 0.0 + BS = createBehaviorSection("standstill", drivingCourse[end][:s], drivingCourse[end][:v], drivingCourse[end][:i]) merge!(BS, Dict(:length => 0.0, # total length (in m) :t => 0.0, # total running time (in s) :E => 0.0, # total energy consumption (in Ws) - :s_exit => drivingCourse[end].s, # last position (in m) - :v_exit => drivingCourse[end].v)) # exit speed (in m/s))) - drivingCourse[end].behavior = BS[:type] + :s_exit => drivingCourse[end][:s], # last position (in m) + :v_exit => drivingCourse[end][:v])) # exit speed (in m/s))) + drivingCourse[end][:behavior] = BS[:type] # traction effort and resisting forces (in N) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, BS[:type]) @@ -1083,4 +1085,31 @@ function createBehaviorSection(type::String, s_entry::Real, v_entry::Real, start return BS end #function createBehaviorSection +""" +a data point is the smallest element of the driving course. One step of the step approach is between two data points +""" +function createDataPoint() + dataPoint = Dict(:i => 0, # identifier and counter variable of the dricing course + :behavior => "", # type of behavior section the data point is part of ("breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting", "braking" or "standstill") + # a data point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter + :s => 0.0, # position (in m) + :Δs => 0.0, # step size (in m) + :t => 0.0, # point in time (in s) + :Δt => 0.0, # step size (in s) + :v => 0.0, # velocity (in m/s) + :Δv => 0.0, # step size (in m/s) + :a => 0.0, # acceleration (in m/s^2) + :W => 0.0, # mechanical work (in Ws) + :ΔW => 0.0, # mechanical work in this step (in Ws) + :E => 0.0, # energy consumption (in Ws) + :ΔE => 0.0, # energy consumption in this step (in Ws) + :F_T => 0.0, # tractive effort (in N) + :F_R => 0.0, # resisting force (in N) + :R_path => 0.0, # path resistance (in N) + :R_train => 0.0, # train resistance (in N) + :R_traction => 0.0, # traction unit resistance (in N) + :R_wagons => 0.0) # set of wagons resistance (in N) + return dataPoint +end #function createDataPoint + end #module MovingPhases diff --git a/src/OperationModes.jl b/src/OperationModes.jl index e6999ca..d227b32 100644 --- a/src/OperationModes.jl +++ b/src/OperationModes.jl @@ -15,10 +15,10 @@ approximationLevel = 6 # TODO: define it in TrainRun and give it to each fu function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict) CSs::Vector{Dict} = movingSection[:characteristicSections] - startingPoint=DataPoint() - startingPoint.i=1 - startingPoint.s=CSs[1][:s_entry] - drivingCourse=[startingPoint] # List of data points + startingPoint=createDataPoint() + startingPoint[:i]=1 + startingPoint[:s]=CSs[1][:s_entry] + drivingCourse::Vector{Dict} = [startingPoint] # List of data points # for CS in CSs for csId in 1:length(CSs) @@ -53,18 +53,18 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train 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 < CS[:v_peak] + if drivingCourse[end][:v] < CS[:v_peak] (CS, drivingCourse)=addAccelerationPhase!(CS, drivingCourse, settings, train, CSs) end #if - if CS[:s_exit]-drivingCourse[end].s-max(0.0, (CS[: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 CS[:s_exit]-drivingCourse[end][:s]-max(0.0, (CS[: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=",((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking])," s_exit=",CS[:s_exit]) - println(" and v=",drivingCourse[end].v," v_peak=",CS[:v_peak]," v_exit=",CS[:v_exit]) + println(" before acceleration in CS",csId, " with s=",drivingCourse[end][:s]," s_braking=",((CS[:v_exit]^2-drivingCourse[end][:v]^2)/2/train[:a_braking])," s_exit=",CS[:s_exit]) + println(" and v=",drivingCourse[end][:v]," v_peak=",CS[:v_peak]," v_exit=",CS[:v_exit]) end - s_braking=max(0.0, ceil((CS[: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=CS[:s_exit]-drivingCourse[end].s-s_braking + s_braking=max(0.0, ceil((CS[: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=CS[:s_exit]-drivingCourse[end][:s]-s_braking if s_cruising > 0.0 (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") @@ -78,17 +78,17 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train end #if - s_braking=max(0.0, ceil((CS[: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((CS[: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 > CS[:v_exit] + if drivingCourse[end][:v] > CS[:v_exit] #(CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings[:massModel], train, CSs) (CS, drivingCourse)=addBrakingPhase!(CS, drivingCourse, settings, train, CSs) end #if #= 09/20 old and should never be used: - if drivingCourse[end].s < CS[:s_exit] + if drivingCourse[end][:s] < CS[:s_exit] if haskey(BSs, :cruising) - println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_exit=",CS[:s_exit]) + println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end][:s]," to s_exit=",CS[:s_exit]) end (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") end =# @@ -96,35 +96,34 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train (CSs[end], drivingCourse)=addStandstill!(CSs[end], drivingCourse, settings, train, CSs) - 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::Dict, drivingCourseMinimumRunningTime::Vector{DataPoint}, settings::Dict, train::Dict) +function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict, drivingCourseMinimumRunningTime::Vector{Dict}, 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 #doMethod1=false - #doMethod2=false + doMethod2=true + #doMethod2=false + doCombinationOfMethods=true #doCombinationOfMethods=false + # create a new driving course for the minimum energy consumption + drivingCourseOriginal = copy(drivingCourseMinimumRunningTime) + #create a new moving section for the minimum energy consumption movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime) - # 01/01 new when Datapoint is a Dict: movingSectionOriginal=copy(movingSectionMinimumRunningTime) + # 01/09 old not sure if just copy is enough.. : movingSectionOriginal=copy(movingSectionMinimumRunningTime) CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections] merge!(movingSectionOriginal, Dict(:energySavingModifications => [])) # list containing all the used energy saving modifications - # create a new driving course for the minimum energy consumption - drivingCourseOriginal=DataPoint[] - for i in 1:length(drivingCourseMinimumRunningTime) - push!(drivingCourseOriginal, DataPoint(drivingCourseMinimumRunningTime[i])) # List of data points till the start of energy saving - end - # calculate the recovery time t_recovery=calculateRecoveryTime(movingSectionOriginal[:length], movingSectionOriginal[:t], train) merge!(movingSectionOriginal, Dict(:t_recovery=>t_recovery)) # total recovery time for energy-saving modifications (in s) @@ -158,12 +157,9 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict end #if end # for -# testNr=0 # 01/03 old wit too long calculation time: while movingSectionOriginal[:t_recoveryAvailable] > 0.0 while movingSectionOriginal[:t_recoveryAvailable] >= 1/(10^approximationLevel) -# testNr=testNr+1 -# println("while in OpModes: ", testNr, " mit t_recoveryAvailable=",movingSectionOriginal[:t_recoveryAvailable]) - # comparison of modifications + # compare modifications ratioMax=0.0 csIdMax=0 typeMax="none" @@ -207,39 +203,36 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict end # create new driving course - drivingCourseNew=DataPoint[] - for i in 1:length(movingSectionOriginal[:energySavingModifications][end][:drivingCourseModified]) - push!(drivingCourseNew, DataPoint(movingSectionOriginal[:energySavingModifications][end][:drivingCourseModified][i])) - end + drivingCourseNew = copy(movingSectionOriginal[:energySavingModifications][end][:drivingCourseModified]) #fill up the rest of the driving course with information from the original course - drivingCourseNew[end].F_T=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_T - drivingCourseNew[end].R_traction=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_traction - drivingCourseNew[end].R_wagons=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_wagons - drivingCourseNew[end].R_train=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_train - drivingCourseNew[end].R_path=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_path - drivingCourseNew[end].F_R=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_R - drivingCourseNew[end].a=drivingCourseOriginal[lastIdOfSelectedCsOriginal].a + drivingCourseNew[end][:F_T]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:F_T] + drivingCourseNew[end][:R_traction]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:R_traction] + drivingCourseNew[end][:R_wagons]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:R_wagons] + drivingCourseNew[end][:R_train]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:R_train] + drivingCourseNew[end][:R_path]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:R_path] + drivingCourseNew[end][:F_R]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:F_R] + drivingCourseNew[end][:a]=drivingCourseOriginal[lastIdOfSelectedCsOriginal][:a] - endOfModificationId=drivingCourseNew[end].i # is needed for updating the other modified driving courses + endOfModificationId=drivingCourseNew[end][:i] # is needed for updating the other modified driving courses difference=endOfModificationId-lastIdOfSelectedCsOriginal i=lastIdOfSelectedCsOriginal+1 while i <= length(drivingCourseOriginal) - push!(drivingCourseNew, DataPoint(drivingCourseOriginal[i])) - drivingCourseNew[end].i=length(drivingCourseNew) - drivingCourseNew[end].t=drivingCourseNew[end-1].t+drivingCourseNew[end].Δt - drivingCourseNew[end].E=drivingCourseNew[end-1].E+drivingCourseNew[end].ΔE - drivingCourseNew[end].W=drivingCourseNew[end-1].W+drivingCourseNew[end].ΔW + push!(drivingCourseNew, copy(drivingCourseOriginal[i])) + drivingCourseNew[end][:i]=length(drivingCourseNew) + drivingCourseNew[end][:t]=drivingCourseNew[end-1][:t]+drivingCourseNew[end][:Δt] + drivingCourseNew[end][:E]=drivingCourseNew[end-1][:E]+drivingCourseNew[end][:ΔE] + drivingCourseNew[end][:W]=drivingCourseNew[end-1][:W]+drivingCourseNew[end][:ΔW] i=i+1 end # while # replace the original driving course and CS with the new modified ones drivingCourseOriginal=drivingCourseNew - CSsOrig[csIdMax]=copy(movingSectionOriginal[:energySavingModifications][end][:csModified]) - # 01/07 old without copy: CSsOrig[csIdMax]=copyCharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified]) - movingSectionOriginal[:t]=drivingCourseOriginal[end].t # total running time (in s) - movingSectionOriginal[:E]=drivingCourseOriginal[end].E # total energy consumption (in Ws) + CSsOrig[csIdMax]=copyCharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified]) + # 01/09 old with copy: CSsOrig[csIdMax]=copy(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 @@ -291,7 +284,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict end #function calculateMinimumEnergyConsumption -function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Dict, train::Dict) +function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{Dict}, csId::Integer, modificationType::String, settings::Dict, train::Dict) # TODO: refactor and sort this function CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections] @@ -301,6 +294,7 @@ function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{Dat elseif modificationType == "decreasing maximum velocity" # method 2: accelerate to a lower v_peak (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(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable]) @@ -368,24 +362,7 @@ function createEnergySavingModification() :drivingCourseModified => []) # drivingCourse for the modified characteristic section end #createEnergySavingModification -function copyEnergySavingModification(original::Dict) - copy = Dict(:csId => original[:csId], # identifier of the characteristic section - :type => original[:type], # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting" - :ΔE => original[:ΔE], # saved energy (in Ws) - :Δt => original[:Δt], # time loss (in s) - :ratio => original[:ratio], # ratio of ΔE and Δt (in Ws/s) - :csModified => copy(original[:csModified])) # the modified characteristic section - # 01/07 old without copy: csModified => copyCharacteristicSection(original[:csModified])) # the modified characteristic section - - drivingCourseModified = DataPoint[] - for i in 1:length(original[:drivingCourseModified]) - push!(drivingCourseModified, DataPoint(original[:drivingCourseModified][i])) - end - merge!(copy, Dict(:drivingCourseModified => drivingCourseModified)) # drivingCourse for the modified characteristic section - return copy -end #function copyEnergySavingModification - -function updateEnergySavingModifications!(energySavingModifications::Vector{Dict}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer) +function updateEnergySavingModifications!(energySavingModifications::Vector{Dict}, csIdMax::Integer, drivingCourseNew::Vector{Dict}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer) allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] difference = endOfModificationId-lastIdOfSelectedCsOriginal for modNr in csIdMax+1:length(energySavingModifications) @@ -401,17 +378,16 @@ function updateEnergySavingModifications!(energySavingModifications::Vector{Dict end #for # correct the points of previous CS in the modified driving course. Copy the new driving course till the beginning of the current CS and change total values of the current modified CS data points accordingly - drivingCourseModifiedNew=Vector{DataPoint}() - for i in 1:endOfModificationId - push!(drivingCourseModifiedNew, DataPoint(drivingCourseNew[i])) - end # for + drivingCourseModifiedNew = copy(drivingCourseNew[1:endOfModificationId]) + i=lastIdOfSelectedCsOriginal+1 while i <= length(energySavingModifications[modNr][:drivingCourseModified]) - push!(drivingCourseModifiedNew, DataPoint(energySavingModifications[modNr][:drivingCourseModified][i])) - drivingCourseModifiedNew[end].i=length(drivingCourseModifiedNew) - drivingCourseModifiedNew[end].t=drivingCourseModifiedNew[end-1].t+drivingCourseModifiedNew[end].Δt - drivingCourseModifiedNew[end].E=drivingCourseModifiedNew[end-1].E+drivingCourseModifiedNew[end].ΔE - drivingCourseModifiedNew[end].W=drivingCourseModifiedNew[end-1].W+drivingCourseModifiedNew[end].ΔW + push!(drivingCourseModifiedNew, copy(energySavingModifications[modNr][:drivingCourseModified][i])) + + drivingCourseModifiedNew[end][:i]=length(drivingCourseModifiedNew) + drivingCourseModifiedNew[end][:t]=drivingCourseModifiedNew[end-1][:t]+drivingCourseModifiedNew[end][:Δt] + drivingCourseModifiedNew[end][:E]=drivingCourseModifiedNew[end-1][:E]+drivingCourseModifiedNew[end][:ΔE] + drivingCourseModifiedNew[end][:W]=drivingCourseModifiedNew[end-1][:W]+drivingCourseModifiedNew[end][:ΔW] i=i+1 end # while @@ -425,10 +401,10 @@ end #function updateEnergySavingModifications! function copyMovingSection(original::Dict) #TODO after removing the mutable structs: Is it possible to just "copy"? - CSsCopy = Vector{Dict}() + copiedCSs = Vector{Dict}() for csId in 1:length(original[:characteristicSections]) - push!(CSsCopy, copy(original[:characteristicSections][csId])) - # 01/07 old without copy: push!(CSsCopy, copyCharacteristicSection(original[:characteristicSections][csId])) + push!(copiedCSs, copyCharacteristicSection(original[:characteristicSections][csId])) + # 01/07 old without copy: push!(copiedCSs, copyCharacteristicSection(original[:characteristicSections][csId])) end #for copiedMS = Dict(:id => original[:id], # identifier @@ -437,15 +413,14 @@ function copyMovingSection(original::Dict) :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) - :characteristicSections => CSsCopy) # list of containing characteristic sections + :characteristicSections => copiedCSs) # list of containing characteristic sections if haskey(original, :energySavingModifications) # list of containing all the used energy saving modifications - ModificationsCopy = Dict[] + copiedModifications = Dict[] for modId in 1:length(original[:energySavingModifications]) - push!(ModificationsCopy, copyEnergySavingModification(original[:energySavingModifications][modId])) # TODO or should it be copyEnergySavingModification - # 01/07 new when DataPoint is a Dict: push!(ModificationsCopy, copy(original[:energySavingModifications][modId])) + push!(copiedModifications, copyEnergySavingModification(original[:energySavingModifications][modId])) end #for - merge!(copiedMS, Dict(:energySavingModifications => ModificationsCopy)) + merge!(copiedMS, Dict(:energySavingModifications => copiedModifications)) end if haskey(original, :t_recovery) # total recovery time for energy-saving modifications (in s) @@ -457,30 +432,17 @@ function copyMovingSection(original::Dict) end return copiedMS end #function copyMovingSection -#= -function copyCharacteristicSection(original::Dict) - #TODO after removing the mutable structs: Is it possible to just "copy"? - copiedCS = Dict(:id => original[:id], # identifier - :s_entry => original[:s_entry], # first position (in m) - :s_exit => original[:s_exit], # last position (in m) - :length => original[:length], # total length (in m) - :r_path => original[:r_path], # path resistance (in ‰) - :behaviorSections => Dict(), # empty list of containing behavior sections - :t => original[:t], # total running time (in s) - :E => original[:E], # total energy consumption (in Ws) - :v_limit => original[:v_limit], # speed limit (in m/s) - :v_peak => original[:v_peak], # maximum reachable speed (in m/s) - :v_entry => original[:v_entry], # maximum entry speed (in m/s) - :v_exit => original[:v_exit]) # maximum exit speed (in m/s) - allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] - for bs in 1: length(allBs) - if haskey(original[:behaviorSections], allBs[bs]) - #merge!(copiedCS[:behaviorSections], Dict(allBs[bs] => copyBehaviorSection(original[:behaviorSections][allBs[bs]]))) - merge!(copiedCS[:behaviorSections], Dict(allBs[bs] => copy(original[:behaviorSections][allBs[bs]]))) - end #if - end #for - return copiedCS -end #function copyCharacteristicSection -=# +function copyEnergySavingModification(modificaionOriginal::Dict) + modificaionCopy = Dict(:csId => modificaionOriginal[:csId], # identifier of the characteristic section + :type => modificaionOriginal[:type], # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting" + :ΔE => modificaionOriginal[:ΔE], # saved energy (in Ws) + :Δt => modificaionOriginal[:Δt], # time loss (in s) + :ratio => modificaionOriginal[:ratio], # ratio of ΔE and Δt (in Ws/s) + :csModified => copyCharacteristicSection(modificaionOriginal[:]), # the modified characteristic section + :drivingCourseModified => copy(modificaionOriginal[:drivingCourseModified])) # drivingCourse for the modified characteristic section + + return modificaionCopy +end # copyEnergySavingModification + end #module OperationModes diff --git a/src/Output.jl b/src/Output.jl index 65ef8bc..b1a0c24 100644 --- a/src/Output.jl +++ b/src/Output.jl @@ -7,7 +7,7 @@ using CSV, DataFrames, Dates export createOutput export plotDrivingCourse, printImportantValues, printSectionInformation # functions for showing results during the development -function createOutput(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::Dict) +function createOutput(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{Dict}, movingSection::Dict) # method of function createOutput for one operation mode if settings[:typeOfOutput] == "CSV" return createOutputCsv(settings, pathName, trainName, drivingCourse, movingSection) @@ -16,7 +16,7 @@ function createOutput(settings::Dict, pathName::String, trainName::String, drivi end end # funtion createOutput -function createOutput(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::Dict) +function createOutput(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{Dict}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{Dict}, movingSectionMinimumEnergyConsumption::Dict) # method of function createOutput for two operation modes if settings[:typeOfOutput] == "CSV" return createOutputCsv(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption) @@ -26,7 +26,7 @@ function createOutput(settings::Dict, pathName::String, trainName::String, drivi end # funtion createOutput -function createOutputDict(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::Dict) +function createOutputDict(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{Dict}, movingSection::Dict) # method of function createOutputDict for one operation mode if settings[:operationModeMinimumRunningTime] if settings[:operationModeMinimumEnergyConsumption] @@ -58,7 +58,7 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d elseif settings[:detailOfOutput]=="driving course" push!(outputArray, ["i", "behavior", "Δ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_wagons (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.behavior, 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_wagons, point.ΔW, point.W, point.ΔE, point.E, point.a] + row=[point[:i], point[:behavior], 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_wagons], point[:ΔW], point[:W], point[:ΔE], point[:E], point[:a]] push!(outputArray, row) # push row to outputArray end end @@ -73,7 +73,7 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d return outputDict end # function createOutputDict -function createOutputDict(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::Dict) +function createOutputDict(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{Dict}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{Dict}, movingSectionMinimumEnergyConsumption::Dict) # method of function createOutputDict for two operation modes if settings[:operationModeMinimumRunningTime] outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime) @@ -88,7 +88,7 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d elseif settings[:detailOfOutput]=="driving course" push!(outputArrayMinimumEnergyConsumption, ["i", "behavior", "Δ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_wagons (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.behavior, 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_wagons, point.ΔW, point.W, point.ΔE, point.E, point.a] + row=[point[:i], point[:behavior], 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_wagons], point[:ΔW], point[:W], point[:ΔE], point[:E], point[:a]] push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption end end @@ -104,7 +104,7 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d end # function createOutputDict -function createOutputCsv(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{DataPoint}, movingSection::Dict) +function createOutputCsv(settings::Dict, pathName::String, trainName::String, drivingCourse::Vector{Dict}, movingSection::Dict) # method of function createOutputDict for one operation mode outputDict=createOutputDict(settings, pathName, trainName, drivingCourse, movingSection) @@ -157,7 +157,7 @@ function createOutputCsv(settings::Dict, pathName::String, trainName::String, dr return outputDict end #function createOutputCsv -function createOutputCsv(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{DataPoint}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{DataPoint}, movingSectionMinimumEnergyConsumption::Dict) +function createOutputCsv(settings::Dict, pathName::String, trainName::String, drivingCourseMinimumRunningTime::Vector{Dict}, movingSectionMinimumRunningTime::Dict, drivingCourseMinimumEnergyConsumption::Vector{Dict}, movingSectionMinimumEnergyConsumption::Dict) # method of function createOutputDict for two operation modes outputDict=createOutputDict(settings, pathName, trainName, drivingCourseMinimumRunningTime, movingSectionMinimumRunningTime, drivingCourseMinimumEnergyConsumption, movingSectionMinimumEnergyConsumption) @@ -246,10 +246,10 @@ end #function createOutputCsv -function printImportantValues(drivingCourse::Vector{DataPoint}) +function printImportantValues(drivingCourse::Vector{Dict}) println("i behavior 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") for i in 1:length(drivingCourse) - println(drivingCourse[i].i,". ",drivingCourse[i].s," ",drivingCourse[i].v*3.6," ",drivingCourse[i].t/60," ",drivingCourse[i].a," ",drivingCourse[i].F_R/1000," ",drivingCourse[i].F_T/1000," ",drivingCourse[i].E/3600/1000) + println(drivingCourse[i][:i],". ",drivingCourse[i][:s]," ",drivingCourse[i][:v]*3.6," ",drivingCourse[i][:t]/60," ",drivingCourse[i][:a]," ",drivingCourse[i][:F_R]/1000," ",drivingCourse[i][:F_T]/1000," ",drivingCourse[i][:E]/3600/1000) end #for println("i behavior 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 @@ -272,18 +272,18 @@ function printSectionInformation(movingSection::Dict) end #for end #function printSectionInformation -function plotDrivingCourse(drivingCourse::Vector{DataPoint}) +function plotDrivingCourse(drivingCourse::Vector{Dict}) a=[] E=[] s=[] t=[] v=[] for i in 1:length(drivingCourse) - push!(a, drivingCourse[i].a) - push!(E, drivingCourse[i].E) - push!(s, drivingCourse[i].s) - push!(t, drivingCourse[i].t) - push!(v, drivingCourse[i].v) + push!(a, drivingCourse[i][:a]) + push!(E, drivingCourse[i][:E]) + push!(s, drivingCourse[i][:s]) + push!(t, drivingCourse[i][:t]) + push!(v, drivingCourse[i][:v]) end #for p1=plot([s], [v], title = "v in m/s", label = ["v"], xlabel = "s in m") @@ -304,18 +304,18 @@ function plotDrivingCourse(drivingCourse::Vector{DataPoint}) println("Plots for different variables have been created.") end #function plotDrivingCourse -function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{DataPoint},drivingCourseMinimumEnergyConsumption::Vector{DataPoint}) +function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{Dict},drivingCourseMinimumEnergyConsumption::Vector{Dict}) a_minTime=[] E_minTime=[] s_minTime=[] t_minTime=[] v_minTime=[] for i in 1:length(drivingCourseMinimumRunningTime) - push!(a_minTime, drivingCourseMinimumRunningTime[i].a) - push!(E_minTime, drivingCourseMinimumRunningTime[i].E) - push!(s_minTime, drivingCourseMinimumRunningTime[i].s) - push!(t_minTime, drivingCourseMinimumRunningTime[i].t) - push!(v_minTime, drivingCourseMinimumRunningTime[i].v) + push!(a_minTime, drivingCourseMinimumRunningTime[i][:a]) + push!(E_minTime, drivingCourseMinimumRunningTime[i][:E]) + push!(s_minTime, drivingCourseMinimumRunningTime[i][:s]) + push!(t_minTime, drivingCourseMinimumRunningTime[i][:t]) + push!(v_minTime, drivingCourseMinimumRunningTime[i][:v]) end #for a_minEnergy=[] @@ -324,11 +324,11 @@ function plotDrivingCourse(drivingCourseMinimumRunningTime::Vector{DataPoint},dr t_minEnergy=[] v_minEnergy=[] for i in 1:length(drivingCourseMinimumEnergyConsumption) - push!(a_minEnergy, drivingCourseMinimumEnergyConsumption[i].a) - push!(E_minEnergy, drivingCourseMinimumEnergyConsumption[i].E) - push!(s_minEnergy, drivingCourseMinimumEnergyConsumption[i].s) - push!(t_minEnergy, drivingCourseMinimumEnergyConsumption[i].t) - push!(v_minEnergy, drivingCourseMinimumEnergyConsumption[i].v) + push!(a_minEnergy, drivingCourseMinimumEnergyConsumption[i][:a]) + push!(E_minEnergy, drivingCourseMinimumEnergyConsumption[i][:E]) + push!(s_minEnergy, drivingCourseMinimumEnergyConsumption[i][:s]) + push!(t_minEnergy, drivingCourseMinimumEnergyConsumption[i][:t]) + push!(v_minEnergy, drivingCourseMinimumEnergyConsumption[i][:v]) end #for p1=plot([s_minTime,s_minEnergy], diff --git a/src/Preparation.jl b/src/Preparation.jl index df17366..f1be898 100644 --- a/src/Preparation.jl +++ b/src/Preparation.jl @@ -93,21 +93,21 @@ function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train: CSs = 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 + startingPoint=createDataPoint() + startingPoint[:i]=1 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=CSs[csId][:s_entry] - startingPoint.v=CSs[csId][:v_entry] - accelerationCourse=[startingPoint] # List of data points + startingPoint[:s]=CSs[csId][:s_entry] + startingPoint[:v]=CSs[csId][:v_entry] + accelerationCourse::Vector{Dict} = [startingPoint] # List of data points if CSs[csId][:v_entry] < CSs[csId][:v_peak] (CSs[csId], accelerationCourse) = addAccelerationPhase!(CSs[csId], accelerationCourse, settings, train, CSs) # this function changes the accelerationCourse - CSs[csId][:v_peak] = max(CSs[csId][:v_entry], accelerationCourse[end].v) - CSs[csId][:v_exit] = min(CSs[csId][:v_exit], CSs[csId][:v_peak], accelerationCourse[end].v) + CSs[csId][:v_peak] = max(CSs[csId][:v_entry], accelerationCourse[end][:v]) + CSs[csId][:v_exit] = min(CSs[csId][:v_exit], CSs[csId][:v_peak], accelerationCourse[end][:v]) else #CSs[csId][:v_entry]==CSs[csId][:v_peak] # v_exit stays the same end #if @@ -125,20 +125,20 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic # limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak CSs = movingSection[:characteristicSections] - startingPoint=DataPoint() - startingPoint.i=1 + startingPoint=createDataPoint() + startingPoint[:i]=1 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=CSs[csId][:s_entry] - startingPoint.v=CSs[csId][:v_peak] - cruisingCourse=[startingPoint] # List of data points + startingPoint[:s]=CSs[csId][:s_entry] + startingPoint[:v]=CSs[csId][:v_peak] + cruisingCourse::Vector{Dict} = [startingPoint] # List of data points (CSs[csId], cruisingCourse)=addCruisingPhase!(CSs[csId], cruisingCourse, CSs[csId][:length], settings, train, CSs, "cruising") # this function changes the cruisingCourse - CSs[csId][:v_exit]=min(CSs[csId][:v_exit], cruisingCourse[end].v) + CSs[csId][:v_exit]=min(CSs[csId][:v_exit], cruisingCourse[end][:v]) previousCSv_exit=CSs[csId][:v_exit] end #for diff --git a/src/TrainRun.jl b/src/TrainRun.jl index ff16e3d..a4f5fdb 100644 --- a/src/TrainRun.jl +++ b/src/TrainRun.jl @@ -41,7 +41,7 @@ function calculateDrivingDynamics(trainDirectory::String, pathDirectory::String, if settings[:operationModeMinimumRunningTime] ==true || settings[:operationModeMinimumEnergyConsumption] ==true (movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime)=calculateMinimumRunningTime!(movingSection, settings, train) - # println("t=", drivingCourseMinimumRunningTime[end].t) + # println("t=", drivingCourseMinimumRunningTime[end][:t]) # printSectionInformation(movingSectionMinimumRunningTime) println("The driving course for the shortest running time has been calculated.") end #if diff --git a/src/types.jl b/src/types.jl index feed274..cd06887 100644 --- a/src/types.jl +++ b/src/types.jl @@ -1,38 +1,10 @@ module types -# definition of all the additional types and their constructors -export DataPoint#, BehaviorSection - export copyBehaviorSection # TODO is it still necessary if there is no more mutable struct? can just copy(original) be used? + +export copyCharacteristicSection, copyBehaviorSection #export trainType #@enum trainType passenger=1 freight=2 motorCoachTrain=3 #@enum behavior breakFree=1 clearing=2 acceleration=3 cruising=4diminishing=6 coasting=7 cruisingAfterCoasting=8 braking=9 standstill=10 -## a data point is the smallest element of the driving course. One step of the step approach is between two data points -mutable struct DataPoint - i::Integer # identifier and counter variable of the dricing course - behavior::String # type of behavior section the DataPoint ist part of ("breakFree", "clearing", "acceleration", "cruising", "diminishing", "coasting", "cruisingAfterCoasting", "braking" or "standstill") - # a data point which is the last point of one behavior section and the first point of the next behavior section will be attached to the latter - s::AbstractFloat # position (in m) - Δs::AbstractFloat # step size (in m) - t::AbstractFloat # point in time (in s) - Δt::AbstractFloat # step size (in s) - v::AbstractFloat # velocity (in m/s) - Δv::AbstractFloat # step size (in m/s) - a::AbstractFloat # acceleration (in m/s^2) - W::AbstractFloat # mechanical work (in Ws) - ΔW::AbstractFloat # mechanical work in this step (in Ws) - E::AbstractFloat # energy consumption (in Ws) - ΔE::AbstractFloat # energy consumption in this step (in Ws) - F_T::AbstractFloat # tractive effort (in N) - F_R::AbstractFloat # resisting force (in N) - R_path::AbstractFloat # path resistance (in N) - R_train::AbstractFloat # train resistance (in N) - R_traction::AbstractFloat # traction unit resistance (in N) - R_wagons::AbstractFloat # set of wagons resistance (in N) -end # mutable struct DataPoint -DataPoint()=DataPoint(0, "", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) -# tried to insert copy on 15.07.2021 copy(original::DataPoint)=DataPoint(original.i, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W, original.ΔW, original.E, original.ΔE, original.F_T, original.F_R, original.R_path, original.R_train, original.R_traction, original.R_wagons) -DataPoint(original::DataPoint)=DataPoint(original.i, original.behavior, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W, original.ΔW, original.E, original.ΔE, original.F_T, original.F_R, original.R_path, original.R_train, original.R_traction, original.R_wagons) - ## different sections the whole path can be devided in the following ## smallest section of the path is the behavior section. It relates to the containing data points via their identifier. @@ -54,4 +26,30 @@ function copyBehaviorSection(original::Dict) return copiedBS end +function copyCharacteristicSection(originalCS::Dict) + allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] + copiedBSs = Dict() + for bs in 1: length(allBs) + if haskey(originalCS[:behaviorSections], allBs[bs]) + merge!(copiedBSs, Dict(allBs[bs] => originalCS[:behaviorSections][allBs[bs]])) + end #if + end #for + + copiedCS=Dict(:id => originalCS[:id], # identifier + :s_entry => originalCS[:s_entry], # first position (in m) + :s_exit => originalCS[:s_exit], # last position (in m) + :length => originalCS[:length], # total length (in m) + :r_path => originalCS[:r_path], # path resistance (in ‰) + # :behaviorSections => copy(originalCS[:behaviorSections]), # list of containing behavior sections + :behaviorSections => copiedBSs, # list of containing behavior sections + :t => originalCS[:t], # total running time (in s) + :E => originalCS[:E], # total energy consumption (in Ws) + :v_limit => originalCS[:v_limit], # speed limit (in m/s) + :v_peak => originalCS[:v_peak], # maximum reachable speed (in m/s) + :v_entry => originalCS[:v_entry], # maximum entry speed (in m/s) + :v_exit => originalCS[:v_exit]) # maximum exit speed (in m/s) + + return copiedCS +end # CharacteristicSection + end #module