Refactor the mutable struct EnergySaving and rename some variables

pull/1/head
Max Kannenberg 2021-12-22 15:10:36 +01:00
parent fd0476ad1f
commit e1ad3f917d
8 changed files with 234 additions and 188 deletions

View File

@ -145,7 +145,7 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
s_cruising=max(0.0, s_cruising)
# copy csOriginal to csModified
csModified=CharacteristicSection(csOriginal.id, csOriginal.length, csOriginal.s_entry, csOriginal.s_exit, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{Symbol, BehaviorSection}())
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))
@ -210,7 +210,7 @@ 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_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{Symbol, BehaviorSection}())
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))
@ -296,15 +296,15 @@ 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_target > csOriginal.v_entry && csOriginal.v_target > csOriginal.v_exit
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)
# TODO: or calculate a new acceleration phase with v_exit as v_target? it will be very short, shorter than the step size.
# TODO: or calculate a new acceleration phase with v_exit as v_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_target, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{Symbol, BehaviorSection}())
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])
@ -342,8 +342,8 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
energySavingStartId=get(csOriginal.behaviorSections, :clearing, get(csOriginal.behaviorSections, :acceleration, BehaviorSection())).dataPoints[1]
end
# TODO: should v_target be reduced or is it enough to pop the data points?
# characteristicSection.v_target=drivingCourse[end].v # setting v_target to the last data point's velocity which is the highest reachable value in this characteristic section
# TODO: should v_peak be reduced or is it enough to pop the data points?
# characteristicSection.v_peak=drivingCourse[end].v # setting v_peak to the last data point's velocity which is the highest reachable value in this characteristic section
# copy the drivingCourse till the beginning of energy saving
drivingCourseModified=Vector{DataPoint}()
@ -351,7 +351,7 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
end
#s_braking=max(0.0, ceil((csModified.v_exit^2-csModified.v_target^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train stops at s_exit in spite of rounding errors
#s_braking=max(0.0, ceil((csModified.v_exit^2-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
@ -366,11 +366,11 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
elseif drivingCourseModified[end].s<csModified.s_exit
if (csModified.s_exit-drivingCourseModified[end].s)>0.001
# if (csModified.s_exit-drivingCourseModified[end].s)>10^(-approximationLevel)
# println("INFO: The end of new CS",csModified.id," is not reached while saving energy with lowering v_target.")
# 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)
end
println("WARNING: The end of new CS",csModified.id," is not reached while saving energy with lowering v_target.")
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")
@ -381,7 +381,7 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
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_target-csModified.v_entry, csModified.v_target-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)
@ -393,14 +393,14 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
# 09/06 old: return (CharacteristicSection(), [], false)
else
# there is no energy saving modification for this CS because v_target 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
# 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)
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_target>csOriginal.v_entry && csOriginal.v_target>csOriginal.v_exit
# if haskey(csOriginal.behaviorSections, :acceleration) && (haskey(csOriginal.behaviorSections, :braking) || haskey(csOriginal.behaviorSections, :coasting)) && csOriginal.v_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)
drivingCourseCombined=Vector{DataPoint}()
@ -432,7 +432,7 @@ function combineEnergySavingMethods(csOriginal::CharacteristicSection, drivingCo
end # while
return (csCombined, drivingCourseCombined, (ΔE>0.0))# && Δt>0.0))
else
# there is no energy saving modification for this CS because v_target 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
# 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)
end #if
end #function combineEnergySavingMethods

View File

@ -21,11 +21,11 @@ Read the train information from a YAML file, save it in a train Dict and return
"""
function inputTrain(trainDirectory::String)
data = YAML.load(open(trainDirectory))
collect(keys(data))
collect(values(data))
#collect(keys(data))
#collect(values(data))
if haskey(data["train"],"name")
name=data["train"]["name"] # trains name
name=data["train"]["name"] # train's name
delete!(data["train"], "name")
else
error("ERROR at reading the train yaml file: The keyword name is missing. It has to be added.")
@ -46,7 +46,7 @@ function inputTrain(trainDirectory::String)
if haskey(data["train"],"l_train")
if typeof(data["train"]["l_train"]) <: Real && data["train"]["l_train"]>0.0
l_train=data["train"]["l_train"] # total length (in m)
trainLength=data["train"]["l_train"] # total length (in m)
delete!(data["train"], "l_train")
else
error("ERROR at reading the train yaml file: The value of the length is no real number >0.0.")
@ -141,7 +141,7 @@ function inputTrain(trainDirectory::String)
m_t=m_td+m_tc
# mass of the consist (set of wagons) (in kg)
# mass of the set of wagons (consist) (in kg)
if haskey(data["train"],"m_w")
if typeof(data["train"]["m_w"]) <: Real && data["train"]["m_w"]>=0.0
m_w=data["train"]["m_w"]
@ -256,16 +256,16 @@ function inputTrain(trainDirectory::String)
# coefficients for the vehicle resistance of the consist (set of wagons)
# coefficients for the vehicle resistance of the set of wagons (consist)
# coefficient for velocitiy difference between consist (set of wagons) and outdoor air (in m/s)
# coefficient for velocitiy difference between set of wagons (consist) and outdoor air (in m/s)
if trainType=="passenger" || trainType=="motor coach train"
Δv_w=15.0/3.6
elseif trainType== "freight"
Δv_w=0.0
end # if
# coefficient for basic resistance of the consist (set of wagons) (in ‰)
# coefficient for basic resistance of the set of wagons (consist) (in ‰)
if haskey(data["train"],"f_Rw0") && data["train"]["f_Rw0"]!=nothing
if typeof(data["train"]["f_Rw0"]) <: Real && data["train"]["f_Rw0"]>=0.0
f_Rw0=data["train"]["f_Rw0"]
@ -278,7 +278,7 @@ function inputTrain(trainDirectory::String)
end
delete!(data["train"], "f_Rw0")
# coefficient for basic resistance of the consist (set of wagons) (in ‰)
# coefficient for basic resistance of the set of wagons (consist) (in ‰)
if haskey(data["train"],"f_Rw1") && data["train"]["f_Rw1"]!=nothing
if typeof(data["train"]["f_Rw1"]) <: Real && data["train"]["f_Rw1"]>=0.0
f_Rw1=data["train"]["f_Rw1"]
@ -291,7 +291,7 @@ function inputTrain(trainDirectory::String)
end
delete!(data["train"], "f_Rw1")
# coefficient for basic resistance of the consist (set of wagons) (in ‰)
# coefficient for basic resistance of the set of wagons (consist) (in ‰)
if haskey(data["train"],"f_Rw2") && data["train"]["f_Rw2"]!=nothing
if typeof(data["train"]["f_Rw2"]) <: Real && data["train"]["f_Rw2"]>=0.0
f_Rw2=data["train"]["f_Rw2"]
@ -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"
:l_train => l_train, # 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)
@ -396,8 +396,8 @@ end #function checkAndDefineTractiveEffortInput
function inputPath(pathDirectory::String)
# read path information from a YAML file, save it in a path Dict and return it
data = YAML.load(open(pathDirectory))
collect(keys(data))
collect(values(data))
#collect(keys(data))
#collect(values(data))
if haskey(data["path"],"name") && data["path"]["name"]!=nothing
@ -505,8 +505,8 @@ end # function inputPath
function inputSettings(settingsDirectory::String)
# read setting information from a YAML file, save it in a settings Dict and return it
data = YAML.load(open(settingsDirectory))
collect(keys(data))
collect(values(data))
#collect(keys(data))
#collect(values(data))
# initialize the settings Dictionary
settings = Dict(:massModel => "", # model type of the unions mass "mass point" or "homogeneous strip"

View File

@ -91,15 +91,15 @@ function calculatePathResistance(s::AbstractFloat, massModel::String, train::Dic
end #while
if massModel=="mass point"
pathResistance=CSs[id].f_Rp/1000*train[:m_train]*g # /1000 because of the unit ‰
pathResistance=CSs[id].r_path/1000*train[:m_train]*g # /1000 because of the unit ‰
elseif massModel=="homogeneous strip"
pathResistance=0.0
while id>0 && s-train[:l_train]<CSs[id].s_exit
pathResistance=pathResistance+(min(s, CSs[id].s_exit)-max(s-train[:l_train], CSs[id].s_entry))/train[:l_train]*(CSs[id].f_Rp/1000*train[:m_train]*g) # /1000 because of the unit ‰
while id>0 && s-train[:trainLength]<CSs[id].s_exit
pathResistance=pathResistance+(min(s, CSs[id].s_exit)-max(s-train[:trainLength], CSs[id].s_entry))/train[:trainLength]*(CSs[id].r_path/1000*train[:m_train]*g) # /1000 because of the unit ‰
id=id-1
if id==0
# TODO: currently for values < movingSection[:s_entry] the values of movingSection[:s_entry] will be used
return pathResistance+(CSs[1].s_entry-(s-train[:l_train]))/train[:l_train]*(CSs[1].f_Rp/1000*train[:m_train]*g) # /1000 because of the unit ‰
return pathResistance+(CSs[1].s_entry-(s-train[:trainLength]))/train[:trainLength]*(CSs[1].r_path/1000*train[:m_train]*g) # /1000 because of the unit ‰
end #if
end #while
else
@ -115,8 +115,8 @@ calculate and return tractive and resisting forces for a data point
function calculateForces!(dataPoint::DataPoint, train::Dict, massModel::String, CSs::Vector{CharacteristicSection}, bsType::String)
# calculate resisting forces
dataPoint.R_traction=calculateTractionUnitResistance(dataPoint.v, train)
dataPoint.R_consist=calculateWagonsResistance(dataPoint.v, train)
dataPoint.R_train=dataPoint.R_traction+dataPoint.R_consist
dataPoint.R_wagons=calculateWagonsResistance(dataPoint.v, train)
dataPoint.R_train=dataPoint.R_traction+dataPoint.R_wagons
dataPoint.R_path=calculatePathResistance(dataPoint.s, massModel, train, CSs)
dataPoint.F_R=dataPoint.R_train+dataPoint.R_path
@ -157,7 +157,7 @@ function moveAStep(previousPoint::DataPoint, stepVariable::String, stepSize::Rea
if ((previousPoint.v/previousPoint.a)^2+2*newPoint.Δs/previousPoint.a)<0.0 || (previousPoint.v^2+2*newPoint.Δs*previousPoint.a)<0.0 # checking if the parts of the following square roots will be <0.0
error("ERROR: The train stops during the acceleration phase in CS",csId," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",previousPoint.s," m, v=",previousPoint.v," m/s, a=",previousPoint.a," m/s^2,",
" F_T=",previousPoint.F_T," N, R_traction=",previousPoint.R_traction," N, R_consist=",previousPoint.R_consist," N, R_path=",previousPoint.R_path," N.")
" F_T=",previousPoint.F_T," N, R_traction=",previousPoint.R_traction," N, R_wagons=",previousPoint.R_wagons," N, R_path=",previousPoint.R_path," N.")
end
end
# 11/21 ->|
@ -189,11 +189,11 @@ end #function moveAStep
"""
# if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
"""
function detectFormerSpeedLimits(CSs::Vector{CharacteristicSection}, csWithTrainHeadId::Integer, currentPoint::DataPoint, l_train::Real)
function detectFormerSpeedLimits(CSs::Vector{CharacteristicSection}, csWithTrainHeadId::Integer, currentPoint::DataPoint, trainLength::Real)
formerSpeedLimits=[]
if csWithTrainHeadId > 1 && currentPoint.s - l_train < CSs[csWithTrainHeadId].s_entry
if csWithTrainHeadId > 1 && currentPoint.s - trainLength < CSs[csWithTrainHeadId].s_entry
formerCsId=csWithTrainHeadId-1
while formerCsId > 0 && currentPoint.s - l_train < CSs[formerCsId].s_exit
while formerCsId > 0 && currentPoint.s - trainLength < CSs[formerCsId].s_exit
if CSs[formerCsId].v_limit < CSs[csWithTrainHeadId].v_limit # TODO: is the position of trains tail < movingSection[:s_entry], v_limit of the first CS is used
push!(formerSpeedLimits, [CSs[formerCsId].s_exit, CSs[formerCsId].v_limit])
for i in 1:length(formerSpeedLimits)-1
@ -227,7 +227,7 @@ function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Ve
# 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[:l_train]))
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")
@ -250,7 +250,7 @@ function considerFormerSpeedLimits!(CS::CharacteristicSection, drivingCourse::Ve
end
# remove former speed limits of characteristic sections the train has left during the last step from the list
while length(formerSpeedLimits) > 0 && drivingCourse[end].s - train[:l_train] >= formerSpeedLimits[end][1]
while length(formerSpeedLimits) > 0 && drivingCourse[end].s - train[:trainLength] >= formerSpeedLimits[end][1]
pop!(formerSpeedLimits)
end
end
@ -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[:l_train])
formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:trainLength])
# conditions for acceleration phase
targetSpeedReached = drivingCourse[end].v >= CS.v_target
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_target && drivingCourse[end].s <CS.s_exit && drivingCourse[end].F_T > drivingCourse[end].F_R
#11/23 long version: if drivingCourse[end].v < CS.v_peak && drivingCourse[end].s <CS.s_exit && drivingCourse[end].F_T > 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<CS.v_target && drivingCourse[end].s<CS.s_exit && drivingCourse[end].F_T > drivingCourse[end].F_R
while drivingCourse[end].v<CS.v_peak && drivingCourse[end].s<CS.s_exit && drivingCourse[end].F_T > drivingCourse[end].F_R
# traction effort and resisting forces (in N)
# 11/22 calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, accelerationSection.type)
@ -398,9 +398,9 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
currentStepSize = settings[:stepSize] / 10.0^cycle
end
elseif drivingCourse[end].v>CS.v_target
elseif drivingCourse[end].v>CS.v_peak
if settings[:stepVariable]=="v in m/s"
currentStepSize=CS.v_target-drivingCourse[end-1].v
currentStepSize=CS.v_peak-drivingCourse[end-1].v
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
@ -408,13 +408,13 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
elseif drivingCourse[end].s==CS.s_exit
break
elseif drivingCourse[end].v==CS.v_target
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 v<v_target and s<s_exit in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
error("ERROR at acceleration phase: With the step variable ", settings[:stepVariable]," the while loop will be left although v<v_peak and s<s_exit 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)
@ -425,9 +425,9 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
# push!(accelerationSection.dataPoints, drivingCourse[end].i)
error("ERROR: The train stops during the acceleration phase in CS",CS.id," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_consist=",drivingCourse[end-1].R_consist," N R_path=",drivingCourse[end-1].R_path," N.")
" 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].v>CS.v_target
elseif drivingCourse[end].v>CS.v_peak
pop!(drivingCourse)
pop!(accelerationSection.dataPoints)
elseif drivingCourse[end].s>CS.s_exit
@ -443,7 +443,7 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
end
end #for
if length(accelerationSection.dataPoints) > 1 # 11/21 new: it is possible that the acceleration starts at v_target, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section.
if length(accelerationSection.dataPoints) > 1 # 11/21 new: it is possible that the acceleration starts at v_peak, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section.
# calculate the accumulated acceleration section information
accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
accelerationSection.s_exit=drivingCourse[end].s # last position (in m)
@ -454,8 +454,8 @@ function addAccelerationPhase!(CS::CharacteristicSection, drivingCourse::Vector{
CS.E=CS.E+accelerationSection.E # total energy consumption (in Ws)
# TODO: this warning schould not be needed. just for testing
if CS.v_target < drivingCourse[end].v
println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_target=",CS.v_target)
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))
@ -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[:l_train])
formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:trainLength])
# 11/23 old without F_T>F_R: if drivingCourse[end].v < CS.v_target && drivingCourse[end].s<CS.s_exit
if drivingCourse[end].v < CS.v_target && drivingCourse[end].s<CS.s_exit && drivingCourse[end].F_T > drivingCourse[end].F_R
# 11/23 old without F_T>F_R: if drivingCourse[end].v < CS.v_peak && drivingCourse[end].s<CS.s_exit
if drivingCourse[end].v < CS.v_peak && drivingCourse[end].s<CS.s_exit && drivingCourse[end].F_T > drivingCourse[end].F_R
accelerationSection=BehaviorSection()
accelerationSection.type="acceleration" # type of behavior section
accelerationSection.s_entry=drivingCourse[end].s # first position (in m)
@ -494,15 +494,15 @@ 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_target && drivingCourse[end].s+s_braking<CS.s_exit && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend
# 12/03 old with v>0 while drivingCourse[end].v < CS.v_target && drivingCourse[end].s+s_braking<CS.s_exit && drivingCourse[end].v>0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend
while drivingCourse[end].v < CS.v_peak && drivingCourse[end].s+s_braking<CS.s_exit && drivingCourse[end].F_T > 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_braking<CS.s_exit && drivingCourse[end].v>0.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)
# acceleration (in m/s^2):
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
# if drivingCourse[end].a==0.0
# error("ERROR: a=0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_consist=",drivingCourse[end].R_consist," R_path=",drivingCourse[end].R_path)
# error("ERROR: a=0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_wagons=",drivingCourse[end].R_wagons," R_path=",drivingCourse[end].R_path)
# end
# create the next data point
@ -529,9 +529,9 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
elseif drivingCourse[end].s +s_braking > CS.s_exit
currentStepSize = settings[:stepSize] / 10.0^cycle
elseif drivingCourse[end].v>CS.v_target
elseif drivingCourse[end].v>CS.v_peak
if settings[:stepVariable]=="v in m/s"
currentStepSize= CS.v_target-drivingCourse[end-1].v
currentStepSize= CS.v_peak-drivingCourse[end-1].v
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
@ -539,14 +539,14 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
elseif drivingCourse[end].s==CS.s_exit
break
elseif drivingCourse[end].v==CS.v_target
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 v<v_target and s<s_exit in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
error("ERROR at acceleration until braking phase: With the step variable ",settings[:stepVariable]," the while loop will be left although v<v_peak and s<s_exit 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)
@ -557,9 +557,9 @@ function addAccelerationPhaseUntilBraking!(CS::CharacteristicSection, drivingCou
# push!(accelerationSection.dataPoints, drivingCourse[end].i)
error("ERROR: The train stops during the acceleration phase in CS",CS.id," because the tractive effort is lower than the resistant forces.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_consist=",drivingCourse[end-1].R_consist," N R_path=",drivingCourse[end-1].R_path," N.")
" 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].v>CS.v_target
elseif drivingCourse[end].v>CS.v_peak
pop!(drivingCourse)
pop!(accelerationSection.dataPoints)
elseif drivingCourse[end].s + s_braking > CS.s_exit
@ -584,7 +584,7 @@ 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_target=max(drivingCourse[end].v, CS.v_entry) # setting v_target to the last data points velocity which is the highest reachable value in this characteristic section or to v_entry in case it is higher when driving on a path with high resistances
CS.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)
@ -606,8 +606,8 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
drivingCourse[end] = DataPoint(calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "cruising"))
s_cruising = max(0.0, s_cruising-get(CS.behaviorSections, :diminishing, BehaviorSection()).length)
end
if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s<CS.s_exit && drivingCourse[end].F_T >= drivingCourse[end].F_R
# 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s<CS.s_exit
if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s<CS.s_exit && drivingCourse[end].F_T >= drivingCourse[end].F_R
# 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s<CS.s_exit
cruisingSection=BehaviorSection()
cruisingSection.type=cruisingType # type of behavior section
cruisingSection.s_entry=drivingCourse[end].s # first position (in m)
@ -626,11 +626,11 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
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[:l_train] && drivingCourse[end].s<cruisingSection.s_entry+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_target && drivingCourse[end].s<CS.s_exit
# TODO: whithout CSs should work as well, no? while drivingCourse[end].s < CSs[CS.id].s_entry + train[:l_train] && drivingCourse[end].s<cruisingSection.s_entry+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_target && drivingCourse[end].s<CS.s_exit
# the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_target OR the mass model homogeneous strip is used and parts of the train are still in former CS
while drivingCourse[end].s < CS.s_entry + train[:trainLength] && drivingCourse[end].s<cruisingSection.s_entry+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s<CS.s_exit
# TODO: whithout CSs should work as well, no? while drivingCourse[end].s < CSs[CS.id].s_entry + train[:trainLength] && drivingCourse[end].s<cruisingSection.s_entry+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s<CS.s_exit
# the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_peak OR the mass model homogeneous strip is used and parts of the train are still in former CS
#TODO: maybe just consider former CS with different path resistance?
#TODO: what about the case: After leaving a former CS with steep gradient the train can accelerate. Now in this tool the train will cruise at v_i. Just accelerating until v_target could make problems for energy saving by shortening the acceleration phase
#TODO: what about the case: After leaving a former CS with steep gradient the train can accelerate. Now in this tool the train will cruise at v_i. Just accelerating until v_peak could make problems for energy saving by shortening the acceleration phase
# acceleration (in m/s^2):
drivingCourse[end].a=0.0
@ -639,7 +639,7 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
if settings[:stepVariable]=="s in m"
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", currentStepSize, CS.id))
else
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train[:l_train]/(10.0^cycle), CS.id)) # TODO which step size should be used?
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train[:trainLength]/(10.0^cycle), CS.id)) # TODO which step size should be used?
end
drivingCourse[end].behavior = cruisingSection.type
push!(cruisingSection.dataPoints, drivingCourse[end].i)
@ -655,7 +655,7 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
# check which limit was reached and adjust the currentStepSize for the next cycle
if cycle < approximationLevel+1
if drivingCourse[end].s>cruisingSection.s_entry+s_cruising # TODO also the following? drivingCourse[end].s > CSs[CS.id].s_entry + train[:l_train]))
if 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
@ -669,8 +669,8 @@ function addCruisingPhase!(CS::CharacteristicSection, drivingCourse::Vector{Data
# else
currentStepSize = settings[:stepSize] / 10.0^cycle
# end
elseif drivingCourse[end].s >= CS.s_entry + train[:l_train]
# TODO: whithout CSs should work as well, no? elseif drivingCourse[end].s >= CSs[CS.id].s_entry + train[:l_train]
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")
@ -741,7 +741,7 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
calculateForces!(drivingCourse[end], train, settings[:massModel], CSs, "diminishing")
if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s<CS.s_exit
#drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s<CS.s_exit
#drivingCourse[end].v>0.0 && drivingCourse[end].v<=CS.v_peak && drivingCourse[end].s<CS.s_exit
diminishingSection=BehaviorSection()
diminishingSection.type="diminishing" # type of behavior section
diminishingSection.s_entry=drivingCourse[end].s # first position (in m)
@ -761,7 +761,7 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train[:m_train]/train[:ξ_train]
# 11/21: old, only for cruising:
#if drivingCourse[end].a==0.0
# error("ERROR: a=0 m/s^2 in the diminishing phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_consist=",drivingCourse[end].R_consist," R_path=",drivingCourse[end].R_path)
# error("ERROR: a=0 m/s^2 in the diminishing phase ! with F_T=",drivingCourse[end].F_T," R_traction=",drivingCourse[end].R_traction," R_wagons=",drivingCourse[end].R_wagons," R_path=",drivingCourse[end].R_path)
#end
# create the next data point
@ -800,7 +800,7 @@ function addDiminishingPhase!(CS::CharacteristicSection, drivingCourse::Vector{D
# 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.",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_consist=",drivingCourse[end-1].R_consist," N R_path=",drivingCourse[end-1].R_path," N.")
" 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
pop!(drivingCourse)
@ -837,7 +837,7 @@ end #function addDiminishingPhase!
# 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})
## 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[:l_train])
#formerSpeedLimits = detectFormerSpeedLimits(CSs, CS.id, drivingCourse[end], train[:trainLength])
if drivingCourse[end].v>CS.v_exit && drivingCourse[end].s<CS.s_exit
coastingSection=BehaviorSection()
@ -851,7 +851,7 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse:
# 08/24 old for cycle in 1:3 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size
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=ceil((CS.v_exit^2-drivingCourse[end].v^2)/2/train[:a_braking], digits=approximationLevel)
while drivingCourse[end].v>CS.v_exit && drivingCourse[end].v<=CS.v_target && drivingCourse[end].s + s_braking < CS.s_exit # as long as s_i + s_braking < s_CSend
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)
@ -876,9 +876,9 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse:
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_target
elseif drivingCourse[end].v > CS.v_peak
if settings[:stepVariable]=="v in m/s"
currentStepSize = CS.v_target-drivingCourse[end-1].v
currentStepSize = CS.v_peak-drivingCourse[end-1].v
else
currentStepSize = settings[:stepSize] / 10.0^cycle
end
@ -890,7 +890,7 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse:
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<v_target and s+s_braking<s_exit in CS",CS.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
error("ERROR at coasting until braking phase: With the step variable ",settings[:stepVariable]," the while loop will be left although v<v_peak and s+s_braking<s_exit 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)
@ -900,15 +900,15 @@ function addCoastingPhaseUntilBraking!(CS::CharacteristicSection, drivingCourse:
if drivingCourse[end].v<=0.0
println("INFO: The train stops during the coasting phase in CS",CS.id," ",
" Before the stop the last point has the values s=",drivingCourse[end-1].s," m v=",drivingCourse[end-1].v," m/s a=",drivingCourse[end-1].a," m/s^2",
" F_T=",drivingCourse[end-1].F_T," N R_traction=",drivingCourse[end-1].R_traction," N R_consist=",drivingCourse[end-1].R_consist," N R_path=",drivingCourse[end-1].R_path," N and s_braking=",s_braking,"m.")
" 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 and s_braking=",s_braking,"m.")
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_target # if the train gets to fast it has to brake # TODO: if accelereation and coasting functions will be combined this case is different for coasting and also the order of if cases is different
# while coasting the train brakes to hold v_target (only one data point in the end of coasting is calculated like cruising at v_target)
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])

View File

@ -27,12 +27,12 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
s_breakFree = get(CSs[csId].behaviorSections, :breakFree, BehaviorSection()).length
s_clearing = get(CSs[csId].behaviorSections, :clearing, BehaviorSection()).length
s_acceleration = get(CSs[csId].behaviorSections, :acceleration, BehaviorSection()).length
s_braking = max(0.0, ceil((CSs[csId].v_exit^2-CSs[csId].v_target^2)/2/train[:a_braking], digits=approximationLevel)) # ceil is used to be sure that the train reaches v_exit at s_exit in spite of rounding errors
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
# calculate the cruising sections length
s_cruising=CSs[csId].length-s_breakFree-s_clearing-s_acceleration-s_braking
# reset the moving section (MS), delete characteristic sections (CS) that were used during the preperation for setting v_entry, v_target and v_exit
# reset the moving section (MS), delete characteristic sections (CS) that were used during the preperation for setting v_entry, v_peak and v_exit
delete!(CSs[csId].behaviorSections, :breakFree)
delete!(CSs[csId].behaviorSections, :clearing)
delete!(CSs[csId].behaviorSections, :acceleration)
@ -50,14 +50,14 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
elseif s_cruising > 0.0 || s_braking == 0.0
# 09/21 elseif s_cruising > 0.0
# 09/21 elseif s_cruising > 0.01 # if the cruising section is longer than 1 cm (because of rounding issues not >0.0)
if drivingCourse[end].v < CSs[csId].v_target
if drivingCourse[end].v < CSs[csId].v_peak
(CSs[csId], drivingCourse)=addAccelerationPhase!(CSs[csId], 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
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_target=",CSs[csId].v_target," v_exit=",CSs[csId].v_exit)
println(" and v=",drivingCourse[end].v," v_peak=",CSs[csId].v_peak," v_exit=",CSs[csId].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
@ -68,8 +68,8 @@ function calculateMinimumRunningTime!(movingSection::Dict, settings::Dict, train
end
else
if CSs[csId].v_entry < CSs[csId].v_target || s_acceleration > 0.0 # or instead of " || s_acceleration > 0.0" use "v_entry <= v_target" or "v_i <= v_target"
# 09/09 old (not sufficient for steep gradients): if CSs[csId].v_entry < CSs[csId].v_target
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)
end #if
end #if
@ -113,6 +113,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
#create a new moving section for the minimum energy consumption
movingSectionOriginal=copyMovingSection(movingSectionMinimumRunningTime)
CSsOrig::Vector{CharacteristicSection} = movingSectionOriginal[:characteristicSections]
merge!(movingSectionOriginal, Dict(:energySavingModifications => [])) # list containing all the used energy saving modifications
# create a new driving course for the minimum energy consumption
drivingCourseOriginal=DataPoint[]
@ -121,13 +122,14 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
end
# calculate the recovery time
movingSectionOriginal[:t_recovery]=calculateRecoveryTime(movingSectionOriginal[:length], movingSectionOriginal[:t], train)
movingSectionOriginal[:t_recoveryAvailable]=movingSectionOriginal[:t_recovery]
t_recovery=calculateRecoveryTime(movingSectionOriginal[:length], movingSectionOriginal[:t], train)
merge!(movingSectionOriginal, Dict(:t_recovery=>t_recovery)) # total recovery time for energy-saving modifications (in s)
merge!(movingSectionOriginal, Dict(:t_recoveryAvailable => t_recovery)) # still available recovery time for energy-saving modifications (in s) initialized with the total recovery time
# create arrays for each method with all the available energy saving modifications
energySavingModificationsWithCoasting=EnergySavingModification[]
energySavingModificationsWithMaximumSpeed=EnergySavingModification[]
energySavingModificationsWithCombination=EnergySavingModification[]
energySavingModificationsWithCoasting=Dict[]
energySavingModificationsWithMaximumSpeed=Dict[]
energySavingModificationsWithCombination=Dict[]
for csId in 1:length(CSsOrig)
# method 1: increase coasting
@ -137,7 +139,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
push!(energySavingModificationsWithCoasting, energySavingModification)
end #if doMethod1
# method 2: accelerate to a lower v_target
# method 2: accelerate to a lower v_peak
if doMethod2 == true
modificationType = "decreasing maximum velocity"
energySavingModification = modifyCs(movingSectionOriginal, drivingCourseOriginal, csId, modificationType, settings, train)
@ -167,7 +169,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
if typeMax=="none"
break
elseif typeMax=="increasing coasting"
# println("Energy saving modification number ",length(movingSectionOriginal[:energySavingModifications])+1," (coasting) in CS ",csIdMax ," Δt=",energySavingModificationsWithCoasting[csIdMax].Δt," ΔE=", energySavingModificationsWithCoasting[csIdMax].ΔE," t_recoveryAvailable=", movingSectionOriginal[:t_recoveryAvailable]-energySavingModificationsWithCoasting[csIdMax].Δt)
# println("Energy saving modification number ",length(movingSectionOriginal[:energySavingModifications])+1," (coasting) in CS ",csIdMax ," Δt=",energySavingModificationsWithCoasting[csIdMax][:Δt]," ΔE=", energySavingModificationsWithCoasting[csIdMax][:ΔE]," t_recoveryAvailable=", movingSectionOriginal[:t_recoveryAvailable]-energySavingModificationsWithCoasting[csIdMax][:Δt])
push!(movingSectionOriginal[:energySavingModifications], energySavingModificationsWithCoasting[csIdMax])
# println("Nr. ",length(movingSectionOriginal[:energySavingModifications]),": typeMax=increasing coasting")
elseif typeMax=="decreasing maximum velocity"
@ -178,7 +180,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
# println("Nr. ",length(movingSectionOriginal[:energySavingModifications]),": typeMax=combination of energy saving methods")
end #if
movingSectionOriginal[:t_recoveryAvailable] = movingSectionOriginal[:t_recoveryAvailable] - movingSectionOriginal[:energySavingModifications][end].Δt
movingSectionOriginal[:t_recoveryAvailable] = movingSectionOriginal[:t_recoveryAvailable] - movingSectionOriginal[:energySavingModifications][end][:Δt]
lastIdOfSelectedCsOriginal = get(CSsOrig[csIdMax].behaviorSections, :standstill,
get(CSsOrig[csIdMax].behaviorSections, :braking,
@ -197,15 +199,15 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
end
# create new driving course
drivingCourseNew=Vector{DataPoint}()
for i in 1:length(movingSectionOriginal[:energySavingModifications][end].drivingCourseModified)
push!(drivingCourseNew, DataPoint(movingSectionOriginal[:energySavingModifications][end].drivingCourseModified[i]))
drivingCourseNew=DataPoint[]
for i in 1:length(movingSectionOriginal[:energySavingModifications][end][:drivingCourseModified])
push!(drivingCourseNew, DataPoint(movingSectionOriginal[:energySavingModifications][end][:drivingCourseModified][i]))
end
#fill up the rest of the driving course with information from the original course
drivingCourseNew[end].F_T=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_T
drivingCourseNew[end].R_traction=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_traction
drivingCourseNew[end].R_consist=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_consist
drivingCourseNew[end].R_wagons=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_wagons
drivingCourseNew[end].R_train=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_train
drivingCourseNew[end].R_path=drivingCourseOriginal[lastIdOfSelectedCsOriginal].R_path
drivingCourseNew[end].F_R=drivingCourseOriginal[lastIdOfSelectedCsOriginal].F_R
@ -226,7 +228,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]=CharacteristicSection(movingSectionOriginal[:energySavingModifications][end][:csModified])
movingSectionOriginal[:t]=drivingCourseOriginal[end].t # total running time (in s)
movingSectionOriginal[:E]=drivingCourseOriginal[end].E # total energy consumption (in Ws)
@ -245,9 +247,9 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
end #for
# update the data points in the following modified charateristic sections and the following points in the driving course
energySavingModificationsWithCoasting = updateEnergySavingModifications(energySavingModificationsWithCoasting, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal)
energySavingModificationsWithMaximumSpeed = updateEnergySavingModifications(energySavingModificationsWithMaximumSpeed, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal)
energySavingModificationsWithCombination = updateEnergySavingModifications(energySavingModificationsWithCombination, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal)
energySavingModificationsWithCoasting = updateEnergySavingModifications!(energySavingModificationsWithCoasting, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal)
energySavingModificationsWithMaximumSpeed = updateEnergySavingModifications!(energySavingModificationsWithMaximumSpeed, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal)
energySavingModificationsWithCombination = updateEnergySavingModifications!(energySavingModificationsWithCombination, csIdMax, drivingCourseNew, endOfModificationId, lastIdOfSelectedCsOriginal)
end # if difference
# modify new CS for the considered methods
@ -258,7 +260,7 @@ function calculateMinimumEnergyConsumption(movingSectionMinimumRunningTime::Dict
energySavingModificationsWithCoasting[csIdMax]=energySavingModification
end #if if doMethod1
# method 2: accelerate to a lower v_target
# method 2: accelerate to a lower v_peak
if doMethod2==true
modificationType = "decreasing maximum velocity"
energySavingModification = modifyCs(movingSectionOriginal, drivingCourseOriginal, csIdMax, modificationType, settings, train)
@ -281,72 +283,110 @@ 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]
if modificationType == "increasing coasting"
# method 1: increase coasting
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=increaseCoastingSection(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable])
elseif modificationType == "decreasing maximum velocity"
# method 2: accelerate to a lower v_target
# method 2: accelerate to a lower v_peak
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=decreaseMaximumVelocity(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable])
elseif modificationType == "combination of energy saving methods"
# calculate the combination of the previous methods
(characteristicSectionModified, drivingCourseModifiedUntilEndOfModifiedCS, new)=combineEnergySavingMethods(CSsOrig[csId], drivingCourseOriginal, settings, train, CSsOrig, movingSectionOriginal[:t_recoveryAvailable])
else
return EnergySavingModification()
return createEnergySavingModification()
end
energySavingModification = EnergySavingModification()
#energySavingModification = createEnergySavingModification()
if new
energySavingModification.csId = csId # identifier of the characteristic section
energySavingModification.type = modificationType # type of energy saving modification: "increasing coasting" or "decreasing maximum velocity" or "combination of energy saving methods"
energySavingModification.csModified = characteristicSectionModified # the modified characteristic section
energySavingModification.drivingCourseModified = drivingCourseModifiedUntilEndOfModifiedCS # drivingCourse of the modified characteristic section
energySavingModification.ΔE = CSsOrig[csId].E - energySavingModification.csModified.E # saved energy (in Ws)
energySavingModification.Δt = energySavingModification.csModified.t - CSsOrig[csId].t # time loss (in s)
if energySavingModification.Δt <= movingSectionOriginal[:t_recoveryAvailable] && energySavingModification.ΔE >= 0.0
energySavingModification = Dict(:csId => csId, # identifier of the characteristic section
:type => modificationType, # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting"
: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)
if energySavingModification[:Δt] <= movingSectionOriginal[:t_recoveryAvailable] && energySavingModification[:ΔE] >= 0.0
#*** TODO: check why "sign" is needed here
# if modificationType == "combination of energy saving methods"
energySavingModification.ratio=sign(energySavingModification.Δt)*energySavingModification.ΔE/energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s)
ratio=sign(energySavingModification[:Δt])*energySavingModification[:ΔE]/energySavingModification[:Δt] # ratio of ΔE and Δt (in Ws/s)
# else
# energySavingModification.ratio = energySavingModification.ΔE / energySavingModification.Δt # ratio of ΔE and Δt (in Ws/s)
# ratio = energySavingModification[:ΔE] / energySavingModification[:Δt] # ratio of ΔE and Δt (in Ws/s)
# end
# ***
elseif energySavingModification.Δt == 0.0
energySavingModification.ratio = energySavingModification.ΔE/0.000000001
elseif energySavingModification[:Δt] == 0.0
ratio = energySavingModification[:ΔE]/0.000000001
else # Δt is to high or ΔE < 0.0 Ws
energySavingModification.ratio = 0.0
ratio = 0.0
end
merge!(energySavingModification, Dict(:ratio => ratio)) # ratio of ΔE and Δt (in Ws/s)
return energySavingModification
else
return createEnergySavingModification()
end
return energySavingModification
end #function modifyCs
function findBestModification(energySavingModifications::Vector{EnergySavingModification}, ratioMax::AbstractFloat, csIdMax::Integer, typeMax::String, t_recoveryAvailable::AbstractFloat)
function findBestModification(energySavingModifications::Vector{Dict}, ratioMax::AbstractFloat, csIdMax::Integer, typeMax::String, t_recoveryAvailable::AbstractFloat)
for modNr in 1:length(energySavingModifications)
if energySavingModifications[modNr].ratio > ratioMax
if energySavingModifications[modNr].Δt <= t_recoveryAvailable
ratioMax=energySavingModifications[modNr].ratio
csIdMax=energySavingModifications[modNr].csId
typeMax=energySavingModifications[modNr].type
if energySavingModifications[modNr][:ratio] > ratioMax
if energySavingModifications[modNr][:Δt] <= t_recoveryAvailable
ratioMax = energySavingModifications[modNr][:ratio]
csIdMax = energySavingModifications[modNr][:csId]
typeMax = energySavingModifications[modNr][:type]
else # Δt is to high
energySavingModifications[modNr].ratio=0.0
energySavingModifications[modNr][:ratio]=0.0
end #if
end #if
end #for
return (energySavingModifications, ratioMax, csIdMax, typeMax)
end #function findBestModification
function updateEnergySavingModifications(energySavingModifications::Vector{EnergySavingModification}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer)
## for the energy saving operation mode it is nesserary to compare different energy saving modifications. These are part of the moving section.
function createEnergySavingModification()
energySavingModification = Dict(:csId => 0, # identifier of the characteristic section
:type => "", # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting"
:Δ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
:drivingCourseModified => []) # drivingCourse for the modified characteristic section
end #createEnergySavingModification
function copyEnergySavingModification(original::Dict)
copy = Dict(:csId => original[:csId], # identifier of the characteristic section
:type => original[:type], # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting"
:ΔE => original[:ΔE], # saved energy (in Ws)
:Δt => original[:Δt], # time loss (in s)
:ratio => original[:ratio], # ratio of ΔE and Δt (in Ws/s)
:csModified => CharacteristicSection(original[:csModified])) # the modified characteristic section
drivingCourseModified = DataPoint[]
for i in 1:length(original[:drivingCourseModified])
push!(drivingCourseModified, DataPoint(original[:drivingCourseModified][i]))
end
merge!(copy, Dict(:drivingCourseModified => drivingCourseModified)) # drivingCourse for the modified characteristic section
return copy
end #function EnergySavingModification
function updateEnergySavingModifications!(energySavingModifications::Vector{Dict}, csIdMax::Integer, drivingCourseNew::Vector{DataPoint}, endOfModificationId::Integer, lastIdOfSelectedCsOriginal::Integer)
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
difference = endOfModificationId-lastIdOfSelectedCsOriginal
for modNr in csIdMax+1:length(energySavingModifications)
if energySavingModifications[modNr].ratio>0
if energySavingModifications[modNr][:ratio]>0
BSs = energySavingModifications[modNr][:csModified].behaviorSections
# update the behavior sections of the modified charateristic section
for bs in 1: length(allBs)
if haskey(energySavingModifications[modNr].csModified.behaviorSections, allBs[bs])
for point in 1:length(energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints)
energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints[point] = energySavingModifications[modNr].csModified.behaviorSections[allBs[bs]].dataPoints[point]+difference
if haskey(BSs, allBs[bs])
for point in 1:length(BSs[allBs[bs]].dataPoints)
BSs[allBs[bs]].dataPoints[point] = BSs[allBs[bs]].dataPoints[point] + difference
end
end #if
end #for
@ -357,8 +397,8 @@ function updateEnergySavingModifications(energySavingModifications::Vector{Energ
push!(drivingCourseModifiedNew, DataPoint(drivingCourseNew[i]))
end # for
i=lastIdOfSelectedCsOriginal+1
while i <= length(energySavingModifications[modNr].drivingCourseModified)
push!(drivingCourseModifiedNew, DataPoint(energySavingModifications[modNr].drivingCourseModified[i]))
while i <= length(energySavingModifications[modNr][:drivingCourseModified])
push!(drivingCourseModifiedNew, DataPoint(energySavingModifications[modNr][:drivingCourseModified][i]))
drivingCourseModifiedNew[end].i=length(drivingCourseModifiedNew)
drivingCourseModifiedNew[end].t=drivingCourseModifiedNew[end-1].t+drivingCourseModifiedNew[end].Δt
drivingCourseModifiedNew[end].E=drivingCourseModifiedNew[end-1].E+drivingCourseModifiedNew[end].ΔE
@ -366,12 +406,13 @@ function updateEnergySavingModifications(energySavingModifications::Vector{Energ
i=i+1
end # while
energySavingModifications[modNr].drivingCourseModified = drivingCourseModifiedNew
energySavingModifications[modNr][:drivingCourseModified] = drivingCourseModifiedNew
end #if
end #for
return energySavingModifications
end #function updateEnergySavingModifications
end #function updateEnergySavingModifications!
function copyMovingSection(original::Dict)
CSsCopy = Vector{CharacteristicSection}()
@ -379,21 +420,30 @@ function copyMovingSection(original::Dict)
push!(CSsCopy, CharacteristicSection(original[:characteristicSections][csId]))
end #for
ModificationsCopy = Vector{EnergySavingModification}()
for modId in 1:length(original[:energySavingModifications])
push!(ModificationsCopy, EnergySavingModification(original[:energySavingModifications][modId]))
end #for
copy = Dict(:id => original[:id], # identifier
:length => original[:length], # total length (in m)
:s_entry => original[:s_entry], # first position (in m)
:s_exit => original[:s_exit], # last position (in m)
:t => original[:t], # total running time (in s)
:E => original[:E], # total energy consumption (in Ws)
:t_recovery => original[:t_recovery], # total recovery time for energy-saving modifications (in s)
:t_recoveryAvailable => original[:t_recoveryAvailable], # still available recovery time for energy-saving modifications (in s)
:characteristicSections => CSsCopy, # list of containing characteristic sections
:energySavingModifications => ModificationsCopy) # list of containing all the used energy saving modifications
:characteristicSections => CSsCopy) # list of containing characteristic sections
if haskey(original, :energySavingModifications) # list of containing all the used energy saving modifications
ModificationsCopy = Dict[]
for modId in 1:length(original[:energySavingModifications])
push!(ModificationsCopy, EnergySavingModification(original[:energySavingModifications][modId]))
end #for
merge!(copy, Dict(:energySavingModifications => ModificationsCopy))
end
if haskey(original, :t_recovery) # total recovery time for energy-saving modifications (in s)
merge!(copy, Dict(:t_recovery => original[:t_recovery]))
end
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

View File

@ -56,14 +56,14 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d
row=[movingSection[:length], movingSection[:t], movingSection[:E]]
push!(outputArray, row) # push row to outputArray
elseif settings[:detailOfOutput]=="driving course"
push!(outputArray, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArray
push!(outputArray, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArray
for point in drivingCourse
row=[point.i, point.behavior, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_consist, point.ΔW, point.W, point.ΔE, point.E, point.a]
row=[point.i, point.behavior, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_wagons, point.ΔW, point.W, point.ΔE, point.E, point.a]
push!(outputArray, row) # push row to outputArray
end
end
if length(movingSection[:energySavingModifications])>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption
if haskey(movingSection, :energySavingModifications) && length(movingSection[:energySavingModifications])>0 # if the moving section hast energy saving modifications the moving section is modified for minimum energy consumption
merge!(outputDict, Dict(:outputArrayMinimumEnergyConsumption => outputArray))
else
merge!(outputDict, Dict(:outputArrayMinimumRunningTime => outputArray))
@ -86,9 +86,9 @@ function createOutputDict(settings::Dict, pathName::String, trainName::String, d
row=[movingSectionMinimumEnergyConsumption[:length], movingSectionMinimumEnergyConsumption[:t], movingSectionMinimumEnergyConsumption[:E]]
push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption
elseif settings[:detailOfOutput]=="driving course"
push!(outputArrayMinimumEnergyConsumption, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArrayMinimumEnergyConsumption
push!(outputArrayMinimumEnergyConsumption, ["i", "behavior", "Δs (in m)", "s (in m)", "Δt (in s)","t (in s)","Δv (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)", "ΔW (in Ws)","W (in Ws)","ΔE (in Ws)","E (in Ws)","a (in m/s^2)"]) # push header to outputArrayMinimumEnergyConsumption
for point in drivingCourseMinimumEnergyConsumption
row=[point.i, point.behavior, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_consist, point.ΔW, point.W, point.ΔE, point.E, point.a]
row=[point.i, point.behavior, point.Δs, point.s, point.Δt, point.t, point.Δv, point.v, point.F_T, point.F_R, point.R_path, point.R_train, point.R_traction, point.R_wagons, point.ΔW, point.W, point.ΔE, point.E, point.a]
push!(outputArrayMinimumEnergyConsumption, row) # push row to outputArrayMinimumEnergyConsumption
end
end
@ -134,7 +134,7 @@ function createOutputCsv(settings::Dict, pathName::String, trainName::String, dr
if settings[:detailOfOutput]=="minimal"
header=outputDict[:outputArrayMinimumRunningTime][1]
elseif settings[:detailOfOutput]=="driving course"
header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
end
for column in 1:length(outputDict[outputArray][1])
push!(infoColumns[column], header[column])
@ -177,7 +177,7 @@ function createOutputCsv(settings::Dict, pathName::String, trainName::String, dr
if settings[:detailOfOutput]=="minimal"
header=outputDict[:outputArrayMinimumRunningTime][1]
elseif settings[:detailOfOutput]=="driving course"
header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
end
for column in 1:length(outputDict[:outputArrayMinimumRunningTime][1])
@ -215,7 +215,7 @@ function createOutputCsv(settings::Dict, pathName::String, trainName::String, dr
if settings[:detailOfOutput]=="minimal"
header=outputDict[:outputArrayMinimumRunningTime][1]
elseif settings[:detailOfOutput]=="driving course"
header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_consist (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
header=["i", "behavior", "Delta s (in m)", "s (in m)", "Delta t (in s)","t (in s)","Delta v (in m/s)","v (in m/s)","F_T (in N)","F_R (in N)","R_path (in N)","R_train (in N)","R_traction (in N)","R_wagons (in N)"," Delta W (in Ws)","W (in Ws)","Delta E (in Ws)","E (in Ws)","a (in m/s^2)"]
end
for column in 1:length(outputDict[:outputArrayMinimumEnergyConsumption][1])

View File

@ -41,10 +41,7 @@ function createMovingSection(path::Dict, v_trainLimit::Real)
:s_exit => s_exit, # last position (in m)
:t => 0.0, # total running time (in s)
:E => 0.0, # total energy consumption (in Ws)
:t_recovery => 0.0, # total recovery time for energy-saving modifications (in s)
:t_recoveryAvailable => 0.0, # still available recovery time for energy-saving modifications (in s)
:characteristicSections => CSs, # list of containing characteristic sections
:energySavingModifications => EnergySavingModification[]) # list of containing all the used energy saving modifications
:characteristicSections => CSs) # list of containing characteristic sections
return movingSection
end #function createMovingSection
@ -62,12 +59,12 @@ function createCharacteristicSection(csId::Integer, s_csStart::Real, section::Di
characteristicSection.E=0.0 # total energy consumption (in Ws)
characteristicSection.v_limit=v_csLimit # speed limit (in m/s)
# initializing v_entry, v_target and v_exit with v_limit
characteristicSection.v_target=characteristicSection.v_limit # maximum target speed (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.f_Rp=section[:f_Rp] # path resistance (in ‰)
characteristicSection.r_path=section[:f_Rp] # path resistance (in ‰)
return characteristicSection
end #function createCharacteristicSection
@ -84,7 +81,7 @@ function secureBrakingBehavior!(movingSection::Dict, a_braking::Real)
v_entryMax=floor(v_entryMax, digits=12)
CSs[csId].v_entry=min(CSs[csId].v_limit, v_entryMax)
CSs[csId].v_target=CSs[csId].v_entry
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)
@ -110,12 +107,12 @@ function secureAccelerationBehavior!(movingSection::Dict, settings::Dict, train:
startingPoint.v=CSs[csId].v_entry
accelerationCourse=[startingPoint] # List of data points
if CSs[csId].v_entry<CSs[csId].v_target
if CSs[csId].v_entry<CSs[csId].v_peak
(CSs[csId], accelerationCourse)=addAccelerationPhase!(CSs[csId], accelerationCourse, settings, train, CSs) # this function changes the accelerationCourse
CSs[csId].v_target=max(CSs[csId].v_entry,accelerationCourse[end].v)
CSs[csId].v_peak=max(CSs[csId].v_entry,accelerationCourse[end].v)
CSs[csId].v_exit=min(CSs[csId].v_exit, CSs[csId].v_target, accelerationCourse[end].v)
else #CSs[csId].v_entry==CSs[csId].v_target
CSs[csId].v_exit=min(CSs[csId].v_exit, CSs[csId].v_peak, accelerationCourse[end].v)
else #CSs[csId].v_entry==CSs[csId].v_peak
# v_exit stays the same
end #if
@ -129,7 +126,7 @@ end #function secureAccelerationBehavior!
## define the intersection velocities between the characterisitc sections to secure cruising behavior
function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dict)
# limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_target
# limit the exit velocity of the characteristic sections in case that the train cruises in every section at v_peak
CSs::Vector{CharacteristicSection} = movingSection[:characteristicSections]
startingPoint=DataPoint()
@ -141,7 +138,7 @@ function secureCruisingBehavior!(movingSection::Dict, settings::Dict, train::Dic
CSs[csId].v_entry=min(CSs[csId].v_entry, previousCSv_exit)
startingPoint.s=CSs[csId].s_entry
startingPoint.v=CSs[csId].v_target
startingPoint.v=CSs[csId].v_peak
cruisingCourse=[startingPoint] # List of data points
(CSs[csId], cruisingCourse)=addCruisingPhase!(CSs[csId], cruisingCourse, CSs[csId].length, settings, train, CSs, "cruising") # this function changes the cruisingCourse

View File

@ -30,8 +30,6 @@ todo !!!
```
"""
function calculateDrivingDynamics(trainDirectory::String, pathDirectory::String, settingsDirectory::String)
print("\n\n\n")
# input
(train, path, settings)=readInput(trainDirectory, pathDirectory, settingsDirectory)
println("The input has been saved.")

View File

@ -19,16 +19,16 @@ mutable struct DataPoint
ΔW::AbstractFloat # mechanical work in this step (in Ws)
E::AbstractFloat # energy consumption (in Ws)
ΔE::AbstractFloat # energy consumption in this step (in Ws)
F_T::AbstractFloat # tractive effort (in N)
F_R::AbstractFloat # resisting force (in N)
R_path::AbstractFloat # path resistance (in N)
R_train::AbstractFloat # train resistance (in N)
R_traction::AbstractFloat # traction unit resistance (in N)
R_consist::AbstractFloat # set of wagons resistance (in N)
F_T::AbstractFloat # tractive effort (in N)
F_R::AbstractFloat # resisting force (in N)
R_path::AbstractFloat # path resistance (in N)
R_train::AbstractFloat # train resistance (in N)
R_traction::AbstractFloat # traction unit resistance (in N)
R_wagons::AbstractFloat # set of wagons resistance (in N)
end # mutable struct DataPoint
DataPoint()=DataPoint(0, "", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
# tried to insert copy on 15.07.2021 copy(original::DataPoint)=DataPoint(original.i, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W, original.ΔW, original.E, original.ΔE, original.F_T, original.F_R, original.R_path, original.R_train, original.R_traction, original.R_consist)
DataPoint(original::DataPoint)=DataPoint(original.i, original.behavior, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W, original.ΔW, original.E, original.ΔE, original.F_T, original.F_R, original.R_path, original.R_train, original.R_traction, original.R_consist)
# tried to insert copy on 15.07.2021 copy(original::DataPoint)=DataPoint(original.i, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W, original.ΔW, original.E, original.ΔE, original.F_T, original.F_R, original.R_path, original.R_train, original.R_traction, original.R_wagons)
DataPoint(original::DataPoint)=DataPoint(original.i, original.behavior, original.s, original.Δs, original.t, original.Δt, original.v, original.Δv, original.a, original.W, original.ΔW, original.E, original.ΔE, original.F_T, original.F_R, original.R_path, original.R_train, original.R_traction, original.R_wagons)
@ -63,15 +63,15 @@ mutable struct CharacteristicSection
t::AbstractFloat # total running time (in s)
E::AbstractFloat # total energy consumption (in Ws)
v_limit::AbstractFloat # speed limit (in m/s)
v_target::AbstractFloat # maximum target speed (in m/s)
v_peak::AbstractFloat # maximum reachable speed (in m/s)
v_entry::AbstractFloat # maximum entry speed (in m/s)
v_exit::AbstractFloat # maximum exit speed (in m/s)
f_Rp::AbstractFloat # spedific path resistance (in ‰)
r_path::AbstractFloat # spedific path resistance (in ‰)
behaviorSections::AbstractDict{Symbol, BehaviorSection} # list of containing behavior sections
end # mutable struct CharacteristicSection
CharacteristicSection()=CharacteristicSection(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Dict{Symbol, BehaviorSection}())
function CharacteristicSection(original::CharacteristicSection)
copy=CharacteristicSection(original.id, original.length, original.s_entry, original.s_exit, original.t, original.E, original.v_limit, original.v_target, original.v_entry, original.v_exit, original.f_Rp, Dict{Symbol, BehaviorSection}())
copy=CharacteristicSection(original.id, original.length, original.s_entry, original.s_exit, original.t, original.E, original.v_limit, original.v_peak, original.v_entry, original.v_exit, original.r_path, Dict{Symbol, BehaviorSection}())
allBs=[:breakFree, :clearing, :acceleration, :cruising, :diminishing, :coasting, :cruisingAfterCoasting, :braking, :standstill]
for bs in 1: length(allBs)
if haskey(original.behaviorSections, allBs[bs])
@ -81,7 +81,7 @@ function CharacteristicSection(original::CharacteristicSection)
return copy
end #function CharacteristicSection
## for the energy saving operation mode it is nesserary to compare different energy saving modifications. These are part of the moving section.
#= for the energy saving operation mode it is nesserary to compare different energy saving modifications. These are part of the moving section.
mutable struct EnergySavingModification
csId::Integer # identifier of the characteristic section
type::String # type of energy saving modification: "increasing coasting" "decreasing maximum velocity" or "combination of decreasing maximum velocity and coasting"
@ -100,5 +100,6 @@ function EnergySavingModification(original::EnergySavingModification)
end
return copy
end #function EnergySavingModification
=#
end #module