diff --git a/src/EnergySaving.jl b/src/EnergySaving.jl index 3ee9eca..342d460 100644 --- a/src/EnergySaving.jl +++ b/src/EnergySaving.jl @@ -89,35 +89,34 @@ function calculateRecoveryTime(s_MS::Real, t_MS::AbstractFloat, train::Dict) end # if train[:trainType] end #function calculateRecoveryTime -function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) - if (haskey(csOriginal.behaviorSections, :cruising) || haskey(csOriginal.behaviorSections, :diminishing)) && haskey(csOriginal.behaviorSections, :braking) +function increaseCoastingSection(csOriginal::Dict, drivingCourse::Vector{DataPoint}, 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 - if haskey(csOriginal.behaviorSections, :cruising) && haskey(csOriginal.behaviorSections, :diminishing) - if csOriginal.behaviorSections[:cruising].dataPoints[1] > csOriginal.behaviorSections[:diminishing].dataPoints[1] + 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(csOriginal.behaviorSections, :cruising) + elseif haskey(BSsOriginal, :cruising) reduceCruising=true reduceDiminishing=false - elseif haskey(csOriginal.behaviorSections, :diminishing) + elseif haskey(BSsOriginal, :diminishing) reduceDiminishing=true reduceCruising=false end - - if reduceCruising cruisingReduction = settings[:stepSize] while cruisingReduction>=settings[:stepSize]/10^approximationLevel #while cruisingReduction>=settings[:stepSize]/100 - while cruisingReduction>=settings[:stepSize]/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified.v_exit && drivingCourseModified[end].s see below at the end of the while loop + while cruisingReduction>=settings[:stepSize]/10^approximationLevel # will be done once and then depending on approximationLevel repeated with smaller cruisingReduction unless !(drivingCourseModified[end].v<=csModified[:v_exit] && drivingCourseModified[end].s see below at the end of the while loop # create a copy for the characteristic sections drivingCourse - energySavingStartId=get(csOriginal.behaviorSections, :cruising, BehaviorSection()).dataPoints[1] + energySavingStartId=get(BSsOriginal, :cruising, BehaviorSection()).dataPoints[1] if energySavingStartId==0 error("ERROR at creating a new driving course for energy saving with coasting !") end @@ -131,44 +130,59 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours # calculating the new length of the cruising section if settings[:stepVariable]=="s in m" # distance step method - s_cruising = csOriginal.behaviorSections[:cruising].length - cruisingReduction + 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=csOriginal.behaviorSections[:cruising].t-cruisingReduction + # t_cruising=BSsOriginal[:cruising].t-cruisingReduction # s_cruising=t_cruising*drivingCourseModified[end].v - distanceReduction = drivingCourse(csOriginal.behaviorSections[:cruising].dataPoints[end]).v*cruisingReduction - s_cruising = csOriginal.behaviorSections[:cruising].length-distanceReduction + 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=csOriginal.behaviorSections[:cruising].length-cruisingReduction*10 # TODO: or better: *100 ? + s_cruising=BSsOriginal[:cruising].length-cruisingReduction*10 # TODO: or better: *100 ? end #if s_cruising=max(0.0, s_cruising) # copy csOriginal to csModified - csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}()) - if haskey(csOriginal.behaviorSections, :breakFree) - breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree]) - merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection)) - csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E - csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t + # 12/28 old: csModified=CharacteristicSection(csOriginal[:id], csOriginal[:length], csOriginal[:s_entry], csOriginal[:s_exit], 0.0, 0.0, csOriginal[:v_limit], csOriginal[:v_peak], csOriginal[:v_entry], csOriginal[:v_exit], csOriginal[:r_path], Dict{Symbol, BehaviorSection}()) + #TODO after removing the mutable structs: Is it possible to just "copy"? with some changes + 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 => 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) + + BSsModified = csModified[:behaviorSections] + if haskey(BSsOriginal, :breakFree) + breakFreeSection=BehaviorSection(BSsOriginal[:breakFree]) + merge!(BSsModified, Dict(:breakFree=>breakFreeSection)) + csModified[:E] = csModified[:E] + BSsModified[:breakFree].E + csModified[:t] = csModified[:t] + BSsModified[:breakFree].t end - if haskey(csOriginal.behaviorSections, :clearing) # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located - clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing]) - merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection)) - csModified.E = csModified.E + csModified.behaviorSections[:clearing].E - csModified.t = csModified.t + csModified.behaviorSections[:clearing].t + if haskey(BSsOriginal, :clearing) # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located + clearingSection=BehaviorSection(BSsOriginal[:clearing]) + merge!(BSsModified, Dict(:clearing=>clearingSection)) + csModified[:E] = csModified[:E] + BSsModified[:clearing].E + csModified[:t] = csModified[:t] + BSsModified[:clearing].t end - if haskey(csOriginal.behaviorSections, :acceleration) - accelerationSection=BehaviorSection(csOriginal.behaviorSections[:acceleration]) - merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection)) - csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E - csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t + if haskey(BSsOriginal, :acceleration) + accelerationSection=BehaviorSection(BSsOriginal[:acceleration]) + merge!(BSsModified, Dict(:acceleration=>accelerationSection)) + csModified[:E] = csModified[:E] + BSsModified[:acceleration].E + csModified[:t] = csModified[:t] + BSsModified[:acceleration].t end - if haskey(csOriginal.behaviorSections, :diminishing) - diminishingSection=BehaviorSection(csOriginal.behaviorSections[:diminishing]) - merge!(csModified.behaviorSections, Dict(:diminishing=>diminishingSection)) - csModified.E = csModified.E + csModified.behaviorSections[:diminishing].E - csModified.t = csModified.t + csModified.behaviorSections[:diminishing].t + if haskey(BSsOriginal, :diminishing) + diminishingSection=BehaviorSection(BSsOriginal[:diminishing]) + merge!(BSsModified, Dict(:diminishing=>diminishingSection)) + csModified[:E] = csModified[:E] + BSsModified[:diminishing].E + csModified[:t] = csModified[:t] + BSsModified[:diminishing].t end @@ -180,7 +194,7 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours # 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 @@ -189,16 +203,16 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours 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) @@ -210,33 +224,47 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours # TODO: At the moment diminishing is reduced like the acceleration in decreaseMaximumVelocity. To reduce code the methods for reducing cruising phase and reducing the diminishing phase can be combined in some parts. # copy csOriginal to csModified - csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}()) - if haskey(csOriginal.behaviorSections, :breakFree) - breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree]) - merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection)) - csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E - csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t + # 12/28 old: csModified=CharacteristicSection(csOriginal[:id], csOriginal[:length], csOriginal[:s_entry], csOriginal[:s_exit], 0.0, 0.0, csOriginal[:v_limit], csOriginal[:v_peak], csOriginal[:v_entry], csOriginal[:v_exit], csOriginal[:r_path], Dict{Symbol, BehaviorSection}()) + 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 => 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) + + BSsModified = csModified[:behaviorSections] + if haskey(BSsOriginal, :breakFree) + breakFreeSection=BehaviorSection(BSsOriginal[:breakFree]) + merge!(BSsModified, Dict(:breakFree=>breakFreeSection)) + csModified[:E] = csModified[:E] + BSsModified[:breakFree].E + csModified[:t] = csModified[:t] + BSsModified[:breakFree].t end - if haskey(csOriginal.behaviorSections, :clearing) # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located - clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing]) - merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection)) - csModified.E = csModified.E + csModified.behaviorSections[:clearing].E - csModified.t = csModified.t + csModified.behaviorSections[:clearing].t + if haskey(BSsOriginal, :clearing) # this section is needed before acceleration if the train wants to accelerate to a speed higher than the limit in a previous CS where parts of the train are still located + clearingSection=BehaviorSection(BSsOriginal[:clearing]) + merge!(BSsModified, Dict(:clearing=>clearingSection)) + csModified[:E] = csModified[:E] + BSsModified[:clearing].E + csModified[:t] = csModified[:t] + BSsModified[:clearing].t end - if haskey(csOriginal.behaviorSections, :acceleration) - accelerationSection=BehaviorSection(csOriginal.behaviorSections[:acceleration]) - merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection)) - csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E - csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t + if haskey(BSsOriginal, :acceleration) + accelerationSection=BehaviorSection(BSsOriginal[:acceleration]) + merge!(BSsModified, Dict(:acceleration=>accelerationSection)) + csModified[:E] = csModified[:E] + BSsModified[:acceleration].E + csModified[:t] = csModified[:t] + BSsModified[:acceleration].t end - if haskey(csOriginal.behaviorSections, :cruising) - cruisingSection=BehaviorSection(csOriginal.behaviorSections[:cruising]) - merge!(csModified.behaviorSections, Dict(:cruising=>cruisingSection)) - csModified.E = csModified.E + csModified.behaviorSections[:cruising].E - csModified.t = csModified.t + csModified.behaviorSections[:cruising].t + if haskey(BSsOriginal, :cruising) + cruisingSection=BehaviorSection(BSsOriginal[:cruising]) + merge!(BSsModified, Dict(:cruising=>cruisingSection)) + csModified[:E] = csModified[:E] + BSsModified[:cruising].E + csModified[:t] = csModified[:t] + BSsModified[:cruising].t end - diminishingSection=BehaviorSection(csOriginal.behaviorSections[:diminishing]) + diminishingSection=BehaviorSection(BSsOriginal[:diminishing]) if length(diminishingSection.dataPoints) > 2 # remove the last diminishing waypoint pop!(diminishingSection.dataPoints) @@ -247,14 +275,14 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours diminishingSection.t=drivingCourse[diminishingSection.dataPoints[end]].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s) diminishingSection.E=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws) - merge!(csModified.behaviorSections, Dict(:diminishing => diminishingSection)) - csModified.E = csModified.E + csModified.behaviorSections[:diminishing].E - csModified.t = csModified.t + csModified.behaviorSections[:diminishing].t + merge!(BSsModified, Dict(:diminishing => diminishingSection)) + csModified[:E] = csModified[:E] + BSsModified[:diminishing].E + csModified[:t] = csModified[:t] + BSsModified[:diminishing].t energySavingStartId=diminishingSection.dataPoints[end] else # The diminishing section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section. - energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :diminishing, BehaviorSection())).dataPoints[1] + energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :diminishing, BehaviorSection())).dataPoints[1] end # copy the driving course till the beginning of energy saving @@ -267,60 +295,77 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours (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 - if t_recoveryAvailable>=(csModified.t-csOriginal.t) + 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? - return (CharacteristicSection(), [], false) + # 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 - return (CharacteristicSection(), [], false) + # 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 - return (CharacteristicSection(), [], false) + # 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 # method 2 with shortening the acceleration by stepsize -function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) - #function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) - if haskey(csOriginal.behaviorSections, :acceleration) && csOriginal.v_peak > csOriginal.v_entry && csOriginal.v_peak > csOriginal.v_exit - accelerationSection = BehaviorSection(csOriginal.behaviorSections[:acceleration]) - if drivingCourse[accelerationSection.dataPoints[end]-1].v < csOriginal.v_exit - return (CharacteristicSection(), [], false) +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) + BSsOriginal = csOriginal[:behaviorSections] + if haskey(BSsOriginal, :acceleration) && csOriginal[:v_peak] > csOriginal[:v_entry] && csOriginal[:v_peak] > csOriginal[:v_exit] + accelerationSection = BehaviorSection(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 - csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_peak, csOriginal.v_entry, csOriginal.v_exit, csOriginal.r_path, Dict{Symbol, BehaviorSection}()) - - if haskey(csOriginal.behaviorSections, :breakFree) - breakFreeSection=BehaviorSection(csOriginal.behaviorSections[:breakFree]) - merge!(csModified.behaviorSections, Dict(:breakFree=>breakFreeSection)) - csModified.E = csModified.E + csModified.behaviorSections[:breakFree].E - csModified.t = csModified.t + csModified.behaviorSections[:breakFree].t + # 12/28 old: csModified=CharacteristicSection(csOriginal[:id], csOriginal[:length], csOriginal[:s_entry], csOriginal[:s_exit], 0.0, 0.0, csOriginal[:v_limit], csOriginal[:v_peak], csOriginal[:v_entry], csOriginal[:v_exit], csOriginal[:r_path], Dict{Symbol, BehaviorSection}()) + 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 => 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) + BSsModified = csModified[:behaviorSections] + if haskey(BSsOriginal, :breakFree) + breakFreeSection=BehaviorSection(BSsOriginal[:breakFree]) + merge!(BSsModified, Dict(:breakFree=>breakFreeSection)) + csModified[:E] = csModified[:E] + BSsModified[:breakFree].E + csModified[:t] = csModified[:t] + BSsModified[:breakFree].t end - #accelerationSection = BehaviorSection(get(csOriginal.behaviorSections, :acceleration, BehaviorSection())) + #accelerationSection = BehaviorSection(get(BSsOriginal, :acceleration, BehaviorSection())) if length(accelerationSection.dataPoints) > 2 - if haskey(csOriginal.behaviorSections, :clearing) - clearingSection=BehaviorSection(csOriginal.behaviorSections[:clearing]) - merge!(csModified.behaviorSections, Dict(:clearing=>clearingSection)) - csModified.E = csModified.E + csModified.behaviorSections[:clearing].E - csModified.t = csModified.t + csModified.behaviorSections[:clearing].t + if haskey(BSsOriginal, :clearing) + clearingSection=BehaviorSection(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 @@ -332,14 +377,14 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours accelerationSection.t=drivingCourse[accelerationSection.dataPoints[end]].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) accelerationSection.E=drivingCourse[accelerationSection.dataPoints[end]].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws) - merge!(csModified.behaviorSections, Dict(:acceleration=>accelerationSection)) - csModified.E = csModified.E + csModified.behaviorSections[:acceleration].E - csModified.t = csModified.t + csModified.behaviorSections[:acceleration].t + merge!(BSsModified, Dict(:acceleration=>accelerationSection)) + csModified[:E] = csModified[:E] + BSsModified[:acceleration].E + csModified[:t] = csModified[:t] + BSsModified[:acceleration].t energySavingStartId=accelerationSection.dataPoints[end] else # The acceleration section is only one step. This step is removed and if there is a clearing section it will be combined with the new cruising section. - energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :acceleration, BehaviorSection())).dataPoints[1] + energySavingStartId=get(BSsOriginal, :clearing, get(BSsOriginal, :acceleration, BehaviorSection())).dataPoints[1] end # TODO: should v_peak be reduced or is it enough to pop the data points? @@ -351,58 +396,85 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving end - #s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_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-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 >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) - # println("INFO: The end of new CS",csModified.id," is not reached while saving energy with lowering v_peak.") + elseif drivingCourseModified[end].s0.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.") - return (CharacteristicSection(), [], false) + # 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("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 + drivingCourseModified[end].s=csModified[:s_exit] # rounding up to s_exit end #if - if t_recoveryAvailable>=(csModified.t-csOriginal.t) + 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) + # 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? - return (CharacteristicSection(), [], false) + # 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 - # 09/06 old: return (CharacteristicSection(), [], false) + # 09/06 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 - return (CharacteristicSection(), [], false) + # 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::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat) - # if haskey(csOriginal.behaviorSections, :acceleration) && (haskey(csOriginal.behaviorSections, :braking) || haskey(csOriginal.behaviorSections, :coasting)) && csOriginal.v_peak>csOriginal.v_entry && csOriginal.v_peak>csOriginal.v_exit - if haskey(csOriginal.behaviorSections, :acceleration) && (haskey(csOriginal.behaviorSections, :braking) || haskey(csOriginal.behaviorSections, :coasting)) && drivingCourse[get(csOriginal.behaviorSections, :acceleration, BehaviorSection()).dataPoints[end]].v > max(csOriginal.v_entry, csOriginal.v_exit) - csCombined=CharacteristicSection(csOriginal) +function combineEnergySavingMethods(csOriginal::Dict, drivingCourse::Vector{DataPoint}, 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, BehaviorSection()).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 + :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) + :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] => BehaviorSection(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])) @@ -414,26 +486,28 @@ function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCo while (Δt0.0))# && Δt>0.0)) 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 and braking section or coasting section that can be transformed into a cruising section or coasting section - return (CharacteristicSection(), [], false) + # 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 end #function combineEnergySavingMethods diff --git a/src/Input.jl b/src/Input.jl index b390e37..cd683dd 100644 --- a/src/Input.jl +++ b/src/Input.jl @@ -317,7 +317,7 @@ function inputTrain(trainDirectory::String) train= Dict(:name => name, # train's name :id => id, # train's identifier :trainType => trainType, # type of train "passenger" or "freight" or "motor coach train" - :trainLength => trainLength, # total length (in m) + :trainLength => trainLength,# total length (in m) :v_limit => v_limit, # trains speed limit (in m/s) :a_braking => a_braking, # braking acceleration (in m/s^2) :m_train => m_train, # total mass (in kg) diff --git a/src/MovingPhases.jl b/src/MovingPhases.jl index 580b51c..8e701cd 100644 --- a/src/MovingPhases.jl +++ b/src/MovingPhases.jl @@ -80,10 +80,10 @@ end #function calculateWagonsResistance """ calculate and return the path resistance dependend on the trains position and mass model """ -function calculatePathResistance(s::AbstractFloat, massModel::String, train::Dict, CSs::Vector{CharacteristicSection}) +function calculatePathResistance(s::Real, massModel::String, train::Dict, CSs::Vector{Dict}) # looking for the characteristic section with the trains head position id=length(CSs) - while s0 && s-train[:trainLength]0 && s-train[:trainLength] 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 - 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]) + 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 if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2] pop!(formerSpeedLimits) @@ -209,34 +209,34 @@ function detectFormerSpeedLimits(CSs::Vector{CharacteristicSection}, csWithTrain return formerSpeedLimits end # function detectFormerSpeedLimits -function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, formerSpeedLimits, accelerationSection::BehaviorSection) - # TODO: What is the type of formerSpeedLimits? function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, formerSpeedLimits::Array{Array{AbstractFloat,1},1}, accelerationSection::BehaviorSection) - # would work: function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, formerSpeedLimits::Array{Any,1}, accelerationSection::BehaviorSection) +function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits, accelerationSection::BehaviorSection) + # TODO: What is the type of formerSpeedLimits? function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Array{AbstractFloat,1},1}, accelerationSection::BehaviorSection) + # would work: function considerFormerSpeedLimits!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}, formerSpeedLimits::Array{Any,1}, accelerationSection::BehaviorSection) if length(formerSpeedLimits) > 0 # if a former speed limit has been exceeded the acceleration steps of this CS will be removed and a clearing phase will be inserted before acceleration if drivingCourse[end].v > formerSpeedLimits[end][2] - while drivingCourse[end].s > get(CS.behaviorSections, :clearing, accelerationSection).s_entry + while drivingCourse[end].s > get(CS[:behaviorSections], :clearing, accelerationSection).s_entry pop!(drivingCourse) end - if haskey(CS.behaviorSections, :clearing) - CS.t = CS.t-CS.behaviorSections[:clearing].t # reducing the total running time (in s) - CS.E = CS.E-CS.behaviorSections[:clearing].E # reducing the total energy consumption (in Ws) - delete!(CS.behaviorSections, :clearing) + if haskey(CS[:behaviorSections], :clearing) + CS[:t] = CS[:t]-CS[:behaviorSections][:clearing].t # reducing the total running time (in s) + CS[:E] = CS[:E]-CS[:behaviorSections][:clearing].E # reducing the total energy consumption (in Ws) + delete!(CS[:behaviorSections], :clearing) end # create a (new and longer) clearing section - s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) - s_clearing=min(CS.s_exit-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:trainLength])) + s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + s_clearing=min(CS[:s_exit]-drivingCourse[end].s-s_braking, formerSpeedLimits[end][1]-(drivingCourse[end].s-train[:trainLength])) if s_clearing>0.0 (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") else - error("ERROR: clearing <=0.0 although it has to be >0.0 in CS ",CS.id) + 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=BehaviorSection() accelerationSection.type="acceleration" # type of behavior section @@ -260,8 +260,8 @@ 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::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) - if drivingCourse[end].v==0.0 && drivingCourse[end].s breakFreeSection)) + merge!(CS[:behaviorSections], Dict(:breakFree => breakFreeSection)) end # else: return the characteristic section without a breakFree section return (CS, drivingCourse) end #function addBreakFreePhase! @@ -331,7 +331,7 @@ 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::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) +function addAccelerationPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) if drivingCourse[end].v==0.0 (CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs) end #if @@ -343,16 +343,16 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ end # if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept - formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:trainLength]) + formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:trainLength]) # conditions for acceleration phase - targetSpeedReached = drivingCourse[end].v >= CS.v_peak - trainAtEnd = drivingCourse[end].s >= CS.s_exit + 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 + #11/23 long version: if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s drivingCourse[end].F_R accelerationSection=BehaviorSection() accelerationSection.type="acceleration" # type of behavior section accelerationSection.s_entry=drivingCourse[end].s # first position (in m) @@ -362,7 +362,7 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - while drivingCourse[end].v drivingCourse[end].F_R + while drivingCourse[end].v drivingCourse[end].F_R # traction effort and resisting forces (in N) # 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) @@ -370,7 +370,7 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ 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)) + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) drivingCourse[end].behavior = accelerationSection.type push!(accelerationSection.dataPoints, drivingCourse[end].i) # calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) @@ -391,30 +391,30 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ 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 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!(accelerationSection.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 (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) @@ -450,15 +450,15 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{ accelerationSection.length=accelerationSection.s_exit-accelerationSection.s_entry # total length (in m) accelerationSection.t=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) accelerationSection.E=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws) - CS.t=CS.t+accelerationSection.t # total running time (in s) - CS.E=CS.E+accelerationSection.E # total energy consumption (in Ws) + CS[:t]=CS[:t]+accelerationSection.t # total running time (in s) + CS[:E]=CS[:E]+accelerationSection.E # total energy consumption (in Ws) # TODO: this warning schould not be needed. just for testing - if 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=>accelerationSection)) + merge!(CS[:behaviorSections], Dict(:acceleration=>accelerationSection)) end end # else: just return the given data point number without changes due to the acceleration phase @@ -467,7 +467,7 @@ end #function addAccelerationPhase! ## This function calculates the data points of the acceleration phase. -function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) +function addAccelerationPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) if drivingCourse[end].v==0.0 (CS, drivingCourse)=addBreakFreePhase!(CS, drivingCourse, settings, train, CSs) end #if @@ -479,11 +479,11 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou end # if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept - formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:trainLength]) + formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:trainLength]) - # 11/23 old without F_T>F_R: if drivingCourse[end].v < CS.v_peak && drivingCourse[end].s drivingCourse[end].F_R + # 11/23 old without F_T>F_R: if drivingCourse[end].v < CS[:v_peak] && drivingCourse[end].s drivingCourse[end].F_R accelerationSection=BehaviorSection() accelerationSection.type="acceleration" # type of behavior section accelerationSection.s_entry=drivingCourse[end].s # first position (in m) @@ -493,9 +493,9 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou currentStepSize=settings[:stepSize] # initializing the step size that can be reduced near intersections for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - s_braking=max(0.0, ceil((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, accelerationSection.type) @@ -506,7 +506,7 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou # end # create the next data point - push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) drivingCourse[end].behavior = accelerationSection.type push!(accelerationSection.dataPoints, drivingCourse[end].i) # 12/03: was moved behind considerFormerSpeedLimits: calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) @@ -518,7 +518,7 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou end end calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type) - s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + 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 @@ -526,27 +526,27 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou 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 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!(accelerationSection.dataPoints) - elseif drivingCourse[end].s + s_braking > CS.s_exit + elseif drivingCourse[end].s + s_braking > CS[:s_exit] pop!(drivingCourse) pop!(accelerationSection.dataPoints) @@ -584,11 +584,11 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou accelerationSection.t=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s) accelerationSection.E=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws) - CS.v_peak=max(drivingCourse[end].v, CS.v_entry) # setting v_peak to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances - CS.t=CS.t+accelerationSection.t # total running time (in s) - CS.E=CS.E+accelerationSection.E # total energy consumption (in Ws) + CS[:v_peak]=max(drivingCourse[end].v, CS[:v_entry]) # setting v_peak to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances + CS[:t]=CS[:t]+accelerationSection.t # total running time (in s) + CS[:E]=CS[:E]+accelerationSection.E # total energy consumption (in Ws) - merge!(CS.behaviorSections, Dict(:acceleration=>accelerationSection)) + merge!(CS[:behaviorSections], Dict(:acceleration=>accelerationSection)) end end # else: just return the given data point number without changes due to the acceleration phase return (CS, drivingCourse) @@ -597,37 +597,37 @@ 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::CharacteristicSection, drivingCourse::Vector{DataPoint}, s_cruising::AbstractFloat, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}, cruisingType::String) +function addCruisingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, s_cruising::Real, settings::Dict, train::Dict, CSs::Vector{Dict}, cruisingType::String) # traction effort and resisting forces (in N) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"? if drivingCourse[end].F_T < drivingCourse[end].F_R (CS, drivingCourse) = addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising")) - s_cruising = max(0.0, s_cruising-get(CS.behaviorSections, :diminishing, BehaviorSection()).length) + s_cruising = max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, BehaviorSection()).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 + if settings[:massModel]=="homogeneous strip" && CS[:id] > 1 currentStepSize=settings[:stepSize] for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation - while drivingCourse[end].s < CS.s_entry + train[:trainLength] && 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].scruisingSection.s_entry+s_cruising # TODO also the following? drivingCourse[end].s > CSs[CS.id].s_entry + train[:trainLength])) + if drivingCourse[end].s>cruisingSection.s_entry+s_cruising # TODO also the following? drivingCourse[end].s > CSs[CS[:id]].s_entry + train[:trainLength])) if settings[:stepVariable] == "s in m" currentStepSize=cruisingSection.s_entry+s_cruising-drivingCourse[end-1].s else currentStepSize = settings[:stepSize] / 10.0^cycle end - elseif drivingCourse[end].s==cruisingSection.s_entry+s_cruising # || drivingCourse[end].s==CS.s_exit + elseif drivingCourse[end].s==cruisingSection.s_entry+s_cruising # || drivingCourse[end].s==CS[:s_exit] break elseif drivingCourse[end].F_T < drivingCourse[end].F_R # if settings[:stepVariable] == "s in m" @@ -669,11 +669,11 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data # else currentStepSize = settings[:stepSize] / 10.0^cycle # end - elseif drivingCourse[end].s >= CS.s_entry + train[:trainLength] - # TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS.id].s_entry + train[:trainLength] + elseif drivingCourse[end].s >= CS[:s_entry] + train[:trainLength] + # TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS[:id]].s_entry + train[:trainLength] 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 @@ -696,7 +696,7 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data (CS, drivingCourse)=addDiminishingPhase!(CS, drivingCourse, settings, train, CSs) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising") - # s_cruising=max(0.0, s_cruising-get(CS.behaviorSections, :diminishing, BehaviorSection()).length) + # s_cruising=max(0.0, s_cruising-get(CS[:behaviorSections], :diminishing, BehaviorSection()).length) else @@ -714,7 +714,7 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data s_cruisingRemaining=cruisingSection.s_entry+s_cruising-drivingCourse[end].s # create the next data point - push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS.id)) + push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, CS[:id])) drivingCourse[end].behavior = cruisingSection.type push!(cruisingSection.dataPoints, drivingCourse[end].i) end @@ -726,10 +726,10 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data cruisingSection.t=drivingCourse[end].t-drivingCourse[cruisingSection.dataPoints[1]].t # total running time (in s) cruisingSection.E=drivingCourse[end].E-drivingCourse[cruisingSection.dataPoints[1]].E # total energy consumption (in Ws) - CS.t=CS.t+cruisingSection.t # total running time (in s) - CS.E=CS.E+cruisingSection.E # total energy consumption (in Ws) + CS[:t]=CS[:t]+cruisingSection.t # total running time (in s) + CS[:E]=CS[:E]+cruisingSection.E # total energy consumption (in Ws) - merge!(CS.behaviorSections, Dict(Symbol(cruisingSection.type) => cruisingSection)) + merge!(CS[:behaviorSections], Dict(Symbol(cruisingSection.type) => cruisingSection)) end # else: return the characteristic section without a cruising section return (CS, drivingCourse) @@ -737,11 +737,11 @@ end #function addCruisingPhase! ## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower -function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) +function addDiminishingPhase!(CS::Dict, drivingCourse::Vector{DataPoint}, 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].s0.0 && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s 0.0 && drivingCourse[end].s0.0 && drivingCourse[end].v<=CS[:v_peak] && drivingCourse[end].s0.0 # as long as s_i + s_braking < s_CSend - # 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking0.0 # as long as s_i + s_braking < s_CSend + s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + while drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].s+s_braking0.0 # as long as s_i + s_braking < s_CSend + # 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking0.0 # as long as s_i + s_braking < s_CSend #11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type) @@ -765,11 +765,11 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D #end # create the next data point - push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) drivingCourse[end].behavior = diminishingSection.type push!(diminishingSection.dataPoints, drivingCourse[end].i) - s_braking=max(0.0, ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) + s_braking=max(0.0, ceil((CS[:v_exit]^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, diminishingSection.type) end #while @@ -778,18 +778,18 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D 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 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) @@ -798,11 +798,11 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D else # if the level of approximation is reached if drivingCourse[end].v<=0.0 # push!(diminishingSection.dataPoints, drivingCourse[end].i) - error("ERROR: The train stops during diminishing run in CS",CS.id," because the maximum tractive effort is lower than the resistant forces.", + error("ERROR: The train stops during diminishing run in CS",CS[:id]," because the maximum tractive effort is lower than the resistant forces.", " Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2", " 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!(diminishingSection.dataPoints) @@ -822,10 +822,10 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D diminishingSection.length=diminishingSection.s_exit-diminishingSection.s_entry # total length (in m) diminishingSection.t=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s) diminishingSection.E=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws) - CS.t=CS.t+diminishingSection.t # total running time (in s) - CS.E=CS.E+diminishingSection.E # total energy consumption (in Ws) + CS[:t]=CS[:t]+diminishingSection.t # total running time (in s) + CS[:E]=CS[:E]+diminishingSection.E # total energy consumption (in Ws) - merge!(CS.behaviorSections, Dict(:diminishing=>diminishingSection)) + merge!(CS[:behaviorSections], Dict(:diminishing=>diminishingSection)) end end @@ -835,11 +835,11 @@ 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::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) +function addCoastingPhaseUntilBraking!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) ## if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept - #formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:trainLength]) + #formerSpeedLimits = detectFormerSpeedLimits(CSs, CS[:id], drivingCourse[end], train[:trainLength]) - if drivingCourse[end].v>CS.v_exit && drivingCourse[end].sCS[:v_exit] && drivingCourse[end].sCS.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, coastingSection.type) @@ -859,38 +859,38 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse: 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)) + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) drivingCourse[end].behavior = coastingSection.type push!(coastingSection.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!(coastingSection.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]) + 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].Δ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) @@ -943,10 +943,10 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse: coastingSection.t=drivingCourse[end].t-drivingCourse[coastingSection.dataPoints[1]].t # total running time (in s) coastingSection.E=drivingCourse[end].E-drivingCourse[coastingSection.dataPoints[1]].E # total energy consumption (in Ws) - CS.t=CS.t+coastingSection.t # total running time (in s) - CS.E=CS.E+coastingSection.E # total energy consumption (in Ws) + CS[:t]=CS[:t]+coastingSection.t # total running time (in s) + CS[:E]=CS[:E]+coastingSection.E # total energy consumption (in Ws) - merge!(CS.behaviorSections, Dict(:coasting=>coastingSection)) + merge!(CS[:behaviorSections], Dict(:coasting=>coastingSection)) end ## else: just return the given data point number without changes due to the coasting phase return (CS, drivingCourse) end #function addCoastingPhaseUntilBraking! @@ -954,13 +954,13 @@ 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::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) - # function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataPoint}, massModel::String, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) - if drivingCourse[end].v>CS.v_exit && drivingCourse[end].sCS[:v_exit] && drivingCourse[end].s=0.0 println("") - println("Warning: a_braking gets to high in CS ",CS.id, " with a=",drivingCourse[end-1].a ," > ",train[:a_braking]) + println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1].a ," > ",train[:a_braking]) println(" v=",drivingCourse[end].v," v_i-1=",drivingCourse[end-1].v, " Δs=",drivingCourse[end].Δs) - println(" v_exit=",CS.v_exit) + println(" v_exit=",CS[:v_exit]) println("") end =# drivingCourse[end].Δt=drivingCourse[end].Δv/drivingCourse[end-1].a # step size (in s) @@ -1001,10 +1001,10 @@ function addBrakingPhase!(CS::CharacteristicSection, drivingCourse::Vector{DataP brakingSection.t=drivingCourse[end].Δt # total running time (in s) brakingSection.E=drivingCourse[end].ΔE # total energy consumption (in Ws) - CS.t=CS.t+brakingSection.t # total running time (in s) - CS.E=CS.E+brakingSection.E # total energy consumption (in Ws) + CS[:t]=CS[:t]+brakingSection.t # total running time (in s) + CS[:E]=CS[:E]+brakingSection.E # total energy consumption (in Ws) - merge!(CS.behaviorSections, Dict(:braking=>brakingSection)) + merge!(CS[:behaviorSections], Dict(:braking=>brakingSection)) end # else: return the characteristic section without a braking section return (CS, drivingCourse) end #function addBrakingPhase! @@ -1012,8 +1012,8 @@ 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::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) #, s_braking::AbstractFloat) - if drivingCourse[end].v > CS.v_exit && drivingCourse[end].s < CS.s_exit +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] brakingSection=BehaviorSection() brakingSection.type="braking" # type of behavior section brakingSection.s_entry=drivingCourse[end].s # first position (in m) @@ -1023,7 +1023,7 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect currentStepSize=settings[:stepSize] # initializing 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, brakingSection.type) @@ -1040,17 +1040,17 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect break end end - push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS.id)) + push!(drivingCourse, moveAStep(drivingCourse[end], settings[:stepVariable], currentStepSize, CS[:id])) drivingCourse[end].behavior = brakingSection.type push!(brakingSection.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=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) @@ -1059,7 +1059,7 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect # println("a_braking_last=",drivingCourse[end-1].a," m/s^2 und a_braking_standard=" , train[:a_braking]) # if drivingCourse[end-1].a=0.0 - # println("Warning: a_braking gets to high in CS ",CS.id, " with a=",drivingCourse[end-1].a ," > ",train[:a_braking]) + # println("Warning: a_braking gets to high in CS ",CS[:id], " with a=",drivingCourse[end-1].a ," > ",train[:a_braking]) # 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) @@ -1068,7 +1068,7 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect 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 + elseif drivingCourse[end].s > CS[:s_exit] error("Beim Bremsen wurde das CS-Ende überschritten, aber nicht v_exit unterschritten !!") else @@ -1081,10 +1081,10 @@ function addBrakingPhaseStepwise!(CS::CharacteristicSection, drivingCourse::Vect brakingSection.t=drivingCourse[end].t-drivingCourse[brakingSection.dataPoints[1]].t # total running time (in s) brakingSection.E=drivingCourse[end].E-drivingCourse[brakingSection.dataPoints[1]].E # total energy consumption (in Ws) - CS.t=CS.t+brakingSection.t # total running time (in s) - CS.E=CS.E+brakingSection.E # total energy consumption (in Ws) + CS[:t]=CS[:t]+brakingSection.t # total running time (in s) + CS[:E]=CS[:E]+brakingSection.E # total energy consumption (in Ws) - merge!(CS.behaviorSections, Dict(:braking=>brakingSection)) + merge!(CS[:behaviorSections], Dict(:braking=>brakingSection)) end # else: return the characteristic section without a braking section return (CS, drivingCourse) end #function addBrakingPhaseStepwise! @@ -1092,7 +1092,7 @@ 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::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{CharacteristicSection}) +function addStandstill!(CS::Dict, drivingCourse::Vector{DataPoint}, settings::Dict, train::Dict, CSs::Vector{Dict}) if drivingCourse[end].v == 0.0 standstillSection=BehaviorSection() @@ -1112,7 +1112,7 @@ function addStandstill!(CS::CharacteristicSection, drivingCourse::Vector{DataPoi # traction effort and resisting forces (in N) calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, standstillSection.type) - merge!(CS.behaviorSections, Dict(:standstill => standstillSection)) + merge!(CS[:behaviorSections], Dict(:standstill => standstillSection)) end # else: return the characteristic section without a standstillSection section return (CS, drivingCourse) end #function addStandstill! diff --git a/src/OperationModes.jl b/src/OperationModes.jl index 9491e2c..0c97abf 100644 --- a/src/OperationModes.jl +++ b/src/OperationModes.jl @@ -13,81 +13,82 @@ approximationLevel = 6 # TODO: define it in TrainRun and give it to each fu # calculate a train run focussing on using the minimum possible running time function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train::Dict) - CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections] + CSs::Vector{Dict} = movingSection[:characteristicSections] startingPoint=DataPoint() startingPoint.i=1 - startingPoint.s=CSs[1].s_entry + startingPoint.s=CSs[1][:s_entry] drivingCourse=[startingPoint] # List of data points # for CS in CSs for csId in 1:length(CSs) - # println("CS",csId) # check if the CS has a cruising section - s_breakFree = get(CSs[csId].behaviorSections, :breakFree, BehaviorSection()).length - s_clearing = get(CSs[csId].behaviorSections, :clearing, BehaviorSection()).length - s_acceleration = get(CSs[csId].behaviorSections, :acceleration, BehaviorSection()).length - s_braking = max(0.0, ceil((CSs[csId].v_exit^2-CSs[csId].v_peak^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors + CS = CSs[csId] + BSs = CS[:behaviorSections] + s_breakFree = get(BSs, :breakFree, BehaviorSection()).length + s_clearing = get(BSs, :clearing, BehaviorSection()).length + s_acceleration = get(BSs, :acceleration, BehaviorSection()).length + s_braking = max(0.0, ceil((CS[:v_exit]^2-CS[:v_peak]^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors # calculate the cruising sections length - s_cruising=CSs[csId].length-s_breakFree-s_clearing-s_acceleration-s_braking + s_cruising=CS[:length]-s_breakFree-s_clearing-s_acceleration-s_braking # reset the moving section (MS), delete characteristic sections (CS) that were used during the preperation for setting v_entry, v_peak and v_exit - delete!(CSs[csId].behaviorSections, :breakFree) - delete!(CSs[csId].behaviorSections, :clearing) - delete!(CSs[csId].behaviorSections, :acceleration) - delete!(CSs[csId].behaviorSections, :diminishing) - delete!(CSs[csId].behaviorSections, :cruising) - CSs[csId].E=0.0 - CSs[csId].t=0.0 + delete!(BSs, :breakFree) + delete!(BSs, :clearing) + delete!(BSs, :acceleration) + delete!(BSs, :diminishing) + delete!(BSs, :cruising) + CS[:E]=0.0 + CS[:t]=0.0 - if s_clearing == CSs[csId].length - # 09/06 TODO: thought about using "cruising" because it is used in EnergySaving and not clearing (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_clearing, settings, train, CSs, "cruising") - (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_clearing, settings, train, CSs, "clearing") - elseif s_cruising == CSs[csId].length - (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising") + if s_clearing == CS[:length] + # 09/06 TODO: thought about using "cruising" because it is used in EnergySaving and not clearing (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "cruising") + (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_clearing, settings, train, CSs, "clearing") + elseif s_cruising == CS[:length] + (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") elseif s_cruising > 0.0 || s_braking == 0.0 # 09/21 elseif s_cruising > 0.0 # 09/21 elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0) - if drivingCourse[end].v < CSs[csId].v_peak - (CSs[csId], drivingCourse)=addAccelerationPhase!(CSs[csId], drivingCourse, settings, train, CSs) + if drivingCourse[end].v < CS[:v_peak] + (CS, drivingCourse)=addAccelerationPhase!(CS, drivingCourse, settings, train, CSs) end #if - if CSs[csId].s_exit-drivingCourse[end].s-max(0.0, (CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking]) < -0.001 # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors + 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=",((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking])," s_exit=",CSs[csId].s_exit) - println(" and v=",drivingCourse[end].v," v_peak=",CSs[csId].v_peak," v_exit=",CSs[csId].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((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors - s_cruising=CSs[csId].s_exit-drivingCourse[end].s-s_braking + 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 - (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising") + (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") end else - if CSs[csId].v_entry < CSs[csId].v_peak || s_acceleration > 0.0 # or instead of " || s_acceleration > 0.0" use "v_entry <= v_peak" or "v_i <= v_peak" - # 09/09 old (not sufficient for steep gradients): if CSs[csId].v_entry < CSs[csId].v_peak - (CSs[csId], drivingCourse)=addAccelerationPhaseUntilBraking!(CSs[csId], drivingCourse, settings, train, CSs) + if CS[:v_entry] < CS[:v_peak] || s_acceleration > 0.0 # or instead of " || s_acceleration > 0.0" use "v_entry <= v_peak" or "v_i <= v_peak" + # 09/09 old (not sufficient for steep gradients): if CS[:v_entry] < CS[:v_peak] + (CS, drivingCourse)=addAccelerationPhaseUntilBraking!(CS, drivingCourse, settings, train, CSs) end #if end #if - s_braking=max(0.0, ceil((CSs[csId].v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors + s_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 > CSs[csId].v_exit - #(CSs[csId], drivingCourse)=addBrakingPhase!(CSs[csId], drivingCourse, settings[:massModel], train, CSs) - (CSs[csId], drivingCourse)=addBrakingPhase!(CSs[csId], drivingCourse, settings, train, CSs) + 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 < CSs[csId].s_exit - if haskey(CSs[csId].behaviorSections, :cruising) - println("INFO: A second cruising section has been added to CS ", csId," from s=",drivingCourse[end].s," to s_exit=",CSs[csId].s_exit) + 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]) end - (CSs[csId], drivingCourse)=addCruisingPhase!(CSs[csId], drivingCourse, s_cruising, settings, train, CSs, "cruising") + (CS, drivingCourse)=addCruisingPhase!(CS, drivingCourse, s_cruising, settings, train, CSs, "cruising") end =# end #for @@ -112,7 +113,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict #create a new moving section for the minimum energy consumption movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime) - CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections] + 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 @@ -154,7 +155,11 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict end #if end # for - while movingSectionOriginal[:t_recoveryAvailable] > 0.0 +# 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 ratioMax=0.0 csIdMax=0 @@ -182,20 +187,20 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict movingSectionOriginal[:t_recoveryAvailable] = movingSectionOriginal[:t_recoveryAvailable] - movingSectionOriginal[:energySavingModifications][end][:Δt] - lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax].behaviorSections, :standstill, - get(CSsOrig[csIdMax].behaviorSections, :braking, - get(CSsOrig[csIdMax].behaviorSections, :cruisingAfterCoasting, - get(CSsOrig[csIdMax].behaviorSections, :coasting, - get(CSsOrig[csIdMax].behaviorSections, :cruising, - get(CSsOrig[csIdMax].behaviorSections, :acceleration, - get(CSsOrig[csIdMax].behaviorSections, :clearing, - get(CSsOrig[csIdMax].behaviorSections, :breakFree, - get(CSsOrig[csIdMax].behaviorSections, :diminishing, + lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax][:behaviorSections], :standstill, + get(CSsOrig[csIdMax][:behaviorSections], :braking, + get(CSsOrig[csIdMax][:behaviorSections], :cruisingAfterCoasting, + get(CSsOrig[csIdMax][:behaviorSections], :coasting, + get(CSsOrig[csIdMax][:behaviorSections], :cruising, + get(CSsOrig[csIdMax][:behaviorSections], :acceleration, + get(CSsOrig[csIdMax][:behaviorSections], :clearing, + get(CSsOrig[csIdMax][:behaviorSections], :breakFree, + get(CSsOrig[csIdMax][:behaviorSections], :diminishing, BehaviorSection()))))))))).dataPoints[end] # if there is a diminishing phase its location must be analysed seperately because it could be before acceleration, between acceleration and cruising or after cruising. All the other behavior sections occur in a fixed order. - if haskey(CSsOrig[csIdMax].behaviorSections, :diminishing) - lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax].behaviorSections[:diminishing].dataPoints[end]) + if haskey(CSsOrig[csIdMax][:behaviorSections], :diminishing) + lastIdOfSelectedCsOriginal = max(lastIdOfSelectedCsOriginal, CSsOrig[csIdMax][:behaviorSections][:diminishing].dataPoints[end]) end # create new driving course @@ -228,7 +233,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict # replace the original driving course and CS with the new modified ones drivingCourseOriginal=drivingCourseNew - CSsOrig[csIdMax]=CharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified]) + 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) @@ -238,9 +243,9 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] for csId in csIdMax+1:length(CSsOrig) for bs in 1: length(allBs) - if haskey(CSsOrig[csId].behaviorSections, allBs[bs]) - for point in 1:length(CSsOrig[csId].behaviorSections[allBs[bs]].dataPoints) - CSsOrig[csId].behaviorSections[allBs[bs]].dataPoints[point] = CSsOrig[csId].behaviorSections[allBs[bs]].dataPoints[point]+difference + if haskey(CSsOrig[csId][:behaviorSections], allBs[bs]) + for point in 1:length(CSsOrig[csId][:behaviorSections][allBs[bs]].dataPoints) + CSsOrig[csId][:behaviorSections][allBs[bs]].dataPoints[point] = CSsOrig[csId][:behaviorSections][allBs[bs]].dataPoints[point]+difference end end #if end #for @@ -283,8 +288,8 @@ end #function calculateMinimumEnergyConsumption function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{DataPoint}, csId::Integer, modificationType::String, settings::Dict, train::Dict) -# TODO: refctor and sort this function - CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections] +# TODO: refactor and sort this function + CSsOrig::Vector{Dict} = movingSectionOriginal[:characteristicSections] if modificationType == "increasing coasting" # method 1: increase coasting @@ -306,8 +311,8 @@ function modifyCs(movingSectionOriginal::Dict, drivingCourseOriginal::Vector{Dat :csModified => characteristicSectionModified, # the modified characteristic section :drivingCourseModified => drivingCourseModifiedUntilEndOfModifiedCS) # drivingCourse for the modified characteristic section - merge!(energySavingModification, Dict(:ΔE => CSsOrig[csId].E - energySavingModification[:csModified].E)) # saved energy (in Ws) - merge!(energySavingModification, Dict(:Δt => energySavingModification[:csModified].t - CSsOrig[csId].t)) # time loss (in s) + merge!(energySavingModification, Dict(:ΔE => CSsOrig[csId][:E] - energySavingModification[:csModified][:E])) # saved energy (in Ws) + merge!(energySavingModification, Dict(:Δt => energySavingModification[:csModified][:t] - CSsOrig[csId][:t])) # time loss (in s) if energySavingModification[:Δt] <= movingSectionOriginal[:t_recoveryAvailable] && energySavingModification[:ΔE] >= 0.0 @@ -355,7 +360,7 @@ function createEnergySavingModification() :ΔE => 0.0, # saved energy (in Ws) :Δt => 0.0, # time loss (in s) :ratio => 0.0, # ratio of ΔE and Δt (in Ws/s) - :csModified => CharacteristicSection(), # the modified characteristic section + :csModified => Dict(), # the modified characteristic section :drivingCourseModified => []) # drivingCourse for the modified characteristic section end #createEnergySavingModification @@ -365,7 +370,7 @@ function copyEnergySavingModification(original::Dict) :Δ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 => CharacteristicSection(original[:csModified])) # the modified characteristic section + :csModified => copyCharacteristicSection(original[:csModified])) # the modified characteristic section drivingCourseModified = DataPoint[] for i in 1:length(original[:drivingCourseModified]) @@ -381,7 +386,7 @@ function updateEnergySavingModifications!(energySavingModifications::Vector{Dict difference = endOfModificationId-lastIdOfSelectedCsOriginal for modNr in csIdMax+1:length(energySavingModifications) if energySavingModifications[modNr][:ratio]>0 - BSs = energySavingModifications[modNr][:csModified].behaviorSections + BSs = energySavingModifications[modNr][:csModified][:behaviorSections] # update the behavior sections of the modified charateristic section for bs in 1: length(allBs) if haskey(BSs, allBs[bs]) @@ -415,9 +420,10 @@ end #function updateEnergySavingModifications! function copyMovingSection(original::Dict) - CSsCopy = Vector{CharacteristicSection}() + #TODO after removing the mutable structs: Is it possible to just "copy"? + CSsCopy = Vector{Dict}() for csId in 1:length(original[:characteristicSections]) - push!(CSsCopy, CharacteristicSection(original[:characteristicSections][csId])) + push!(CSsCopy, copyCharacteristicSection(original[:characteristicSections][csId])) end #for copy = Dict(:id => original[:id], # identifier @@ -443,8 +449,31 @@ function copyMovingSection(original::Dict) if haskey(original, :t_recoveryAvailable) # still available recovery time for energy-saving modifications (in s) merge!(copy, Dict(:t_recoveryAvailable => original[:t_recoveryAvailable])) end - return copy end #function copyMovingSection +function copyCharacteristicSection(original::Dict) + #TODO after removing the mutable structs: Is it possible to just "copy"? + copy = 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!(copy[:behaviorSections], Dict(allBs[bs] => BehaviorSection(original[:behaviorSections][allBs[bs]]))) + end #if + end #for + return copy +end #function copyCharacteristicSection + end #module OperationModes diff --git a/src/Output.jl b/src/Output.jl index 98b38ff..74861a4 100644 --- a/src/Output.jl +++ b/src/Output.jl @@ -255,17 +255,17 @@ function printImportantValues(drivingCourse::Vector{DataPoint}) end #function printImportantValues function printSectionInformation(movingSection::Dict) - CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections] + CSs::Vector{Dict} = movingSection[:characteristicSections] println("MS mit length=", movingSection[:length]," mit t=", movingSection[:t]) allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill] for csId in 1:length(CSs) - println("CS ",csId," mit length=", CSs[csId].length," mit t=", CSs[csId].t) + println("CS ",csId," mit length=", CSs[csId][:length]," mit t=", CSs[csId][:t]) for bs in 1: length(allBs) - if haskey(CSs[csId].behaviorSections, allBs[bs]) - println("BS ",allBs[bs], " mit s_entry=", CSs[csId].behaviorSections[allBs[bs]].s_entry, " und t=", CSs[csId].behaviorSections[allBs[bs]].t) - # for point in 1:length(CSs[csId].behaviorSections[allBs[bs]].dataPoints) - # println(CSs[csId].behaviorSections[allBs[bs]].dataPoints[point]) + if haskey(CSs[csId][:behaviorSections], allBs[bs]) + println("BS ",allBs[bs], " mit s_entry=", CSs[csId][:behaviorSections][allBs[bs]].s_entry, " und t=", CSs[csId][:behaviorSections][allBs[bs]].t) + # for point in 1:length(CSs[csId][:behaviorSections][allBs[bs]].dataPoints) + # println(CSs[csId][:behaviorSections][allBs[bs]].dataPoints[point]) # end end #if end #for diff --git a/src/Preparation.jl b/src/Preparation.jl index 1f33aa2..7a1c4f7 100644 --- a/src/Preparation.jl +++ b/src/Preparation.jl @@ -23,7 +23,7 @@ function createMovingSection(path::Dict, v_trainLimit::Real) s_exit = path[:sections][end][:s_end] # last position (in m) pathLength = s_exit - s_entry # total length (in m) - CSs=[] + CSs=Vector{Dict}() s_csStart=s_entry csId=1 for row in 2:length(path[:sections]) @@ -47,44 +47,41 @@ function createMovingSection(path::Dict, v_trainLimit::Real) end #function createMovingSection -## create a characteristic section for a path section +## create a characteristic section for a path section. A characteristic section is a part of the moving section. It contains behavior sections. function createCharacteristicSection(csId::Integer, s_csStart::Real, section::Dict, v_csLimit::Real) - # this function creates and returns a characteristic section dependent on the paths attributes - characteristicSection=CharacteristicSection() - characteristicSection.id=csId # identifier - characteristicSection.s_entry=s_csStart # first position (in m) - characteristicSection.s_exit=section[:s_end] # last position (in m) - characteristicSection.length=characteristicSection.s_exit-characteristicSection.s_entry # total length (in m) - characteristicSection.t=0.0 # total running time (in s) - characteristicSection.E=0.0 # total energy consumption (in Ws) - characteristicSection.v_limit=v_csLimit # speed limit (in m/s) - - # initializing v_entry, v_peak and v_exit with v_limit - characteristicSection.v_peak=characteristicSection.v_limit # maximum reachable speed (in m/s) - characteristicSection.v_entry=characteristicSection.v_limit # maximum entry speed (in m/s) - characteristicSection.v_exit=characteristicSection.v_limit # maximum exit speed (in m/s) - - characteristicSection.r_path=section[:f_Rp] # path resistance (in ‰) - + # Create and return a characteristic section dependent on the paths attributes + characteristicSection= Dict(:id => csId, # identifier + :s_entry => s_csStart, # first position (in m) + :s_exit => section[:s_end], # last position (in m) + :length => section[:s_end]-s_csStart, # total length (in m) + :r_path => section[:f_Rp], # path resistance (in ‰) + :behaviorSections => Dict(), # list of containing behavior sections + :t => 0.0, # total running time (in s) + :E => 0.0, # total energy consumption (in Ws) + :v_limit => v_csLimit, # speed limit (in m/s) + # initializing :v_entry, :v_peak and :v_exit with :v_limit + :v_peak => v_csLimit, # maximum reachable speed (in m/s) + :v_entry => v_csLimit, # maximum entry speed (in m/s) + :v_exit => v_csLimit) # maximum exit speed (in m/s) return characteristicSection end #function createCharacteristicSection ## define the intersection velocities between the characterisitc sections to secure braking behavior function secureBrakingBehavior!(movingSection::Dict, a_braking::Real) # this function limits the entry and exit velocity of the characteristic sections to secure that the train stops at the moving sections end - CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections] + CSs = movingSection[:characteristicSections] csId=length(CSs) - CSs[csId].v_exit=0.0 # the exit velocity of the last characteristic section is 0.0 m/s + CSs[csId][:v_exit]=0.0 # the exit velocity of the last characteristic section is 0.0 m/s while csId >= 1 - v_entryMax=sqrt(CSs[csId].v_exit^2-2*a_braking*CSs[csId].length) + v_entryMax=sqrt(CSs[csId][:v_exit]^2-2*a_braking*CSs[csId][:length]) v_entryMax=floor(v_entryMax, digits=12) - CSs[csId].v_entry=min(CSs[csId].v_limit, v_entryMax) - CSs[csId].v_peak=CSs[csId].v_entry + CSs[csId][:v_entry]=min(CSs[csId][:v_limit], v_entryMax) + CSs[csId][:v_peak]=CSs[csId][:v_entry] csId=csId-1 if csId >= 1 - CSs[csId].v_exit=min(CSs[csId].v_limit, CSs[csId+1].v_entry) + CSs[csId][:v_exit]=min(CSs[csId][:v_limit], CSs[csId+1][:v_entry]) end #if end #while return movingSection @@ -93,30 +90,30 @@ end #function secureBrakingBehavior! ## define the intersection velocities between the characterisitc sections to secure acceleration behavior function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train::Dict) # this function limits the entry and exit velocity of the characteristic sections in case that the train accelerates in every section and cruises aterwards - CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections] + CSs = movingSection[:characteristicSections] - CSs[1].v_entry=0.0 # the entry velocity of the first characteristic section is 0.0 m/s + CSs[1][:v_entry]=0.0 # the entry velocity of the first characteristic section is 0.0 m/s startingPoint=DataPoint() startingPoint.i=1 - previousCSv_exit=CSs[1].v_entry + previousCSv_exit=CSs[1][:v_entry] for csId in 1:length(CSs) - CSs[csId].v_entry=min(CSs[csId].v_entry, previousCSv_exit) + CSs[csId][:v_entry]=min(CSs[csId][:v_entry], previousCSv_exit) - startingPoint.s=CSs[csId].s_entry - startingPoint.v=CSs[csId].v_entry + startingPoint.s=CSs[csId][:s_entry] + startingPoint.v=CSs[csId][:v_entry] accelerationCourse=[startingPoint] # List of data points - if CSs[csId].v_entry