Refactor modules for diminishing run and tractive effort velocity pairs
parent
fb942260d2
commit
7eed749d49
|
@ -1,7 +1,7 @@
|
|||
name = "TrainRun"
|
||||
uuid = "e4541106-d44c-4e00-b50b-ecdf479fcf92"
|
||||
authors = ["Max Kannenberg"]
|
||||
version = "0.2.0"
|
||||
version = "0.5.0"
|
||||
|
||||
[deps]
|
||||
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
||||
|
|
16
README.md
16
README.md
|
@ -23,18 +23,28 @@ See folder examples.
|
|||
|
||||
# History
|
||||
|
||||
## Version 0.5
|
||||
|
||||
Refactor modules for diminishing run and tractive effort velocity pairs
|
||||
|
||||
- Add the seperate moving phase "diminishing run" for steep ascents where a train runs with maximum tractive effort while the driving resistances are even higher
|
||||
- Refactor tractiveEffortArray to tractiveEffortVelocityPairs
|
||||
- Rename file path and folder path to directory
|
||||
|
||||
|
||||
## Version 0.4.1
|
||||
|
||||
Rename waypoints
|
||||
|
||||
- rename "waypoints" to "dataPoints" and "Waypoint" to "DataPoint"
|
||||
|
||||
|
||||
## Version 0.4
|
||||
|
||||
Refactor and fix modules EnergySaving, OperationModes and MovingPhases
|
||||
|
||||
- add the general used level of accuracy from v0.3 to EnergySaving and OperationModes.
|
||||
- fix OperationModes and MovingPhases for steep ascents where a train runs with maximum tractive effort while the driving resistances are even higher.
|
||||
- add the general used level of accuracy from v0.3 to EnergySaving and OperationModes
|
||||
- fix OperationModes and MovingPhases for steep ascents where a train runs with maximum tractive effort while the driving resistances are even higher
|
||||
|
||||
|
||||
## Version 0.3
|
||||
|
@ -42,7 +52,7 @@ Refactor and fix modules EnergySaving, OperationModes and MovingPhases
|
|||
Refactor module MovingPhases
|
||||
|
||||
- extract repeatedly occuring code lines and create smaller functions (e.g. the function moveAStep)
|
||||
- integrate a new approach for calculating the waypoints near intersections (e.g. including an editable level of accuracy).
|
||||
- integrate a new approach for calculating the waypoints near intersections (e.g. including an editable level of accuracy)
|
||||
|
||||
|
||||
## Version 0.2
|
||||
|
|
|
@ -90,6 +90,214 @@ function calculateRecoveryTime(s_MS::AbstractFloat, t_MS::AbstractFloat, train::
|
|||
end #function calculateRecoveryTime
|
||||
|
||||
function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
|
||||
if (haskey(csOriginal.behaviorSections, "cruising") || haskey(csOriginal.behaviorSections, "diminishing")) && haskey(csOriginal.behaviorSections, "braking")
|
||||
# check if cruising or diminishing should be reduced for coasting
|
||||
if haskey(csOriginal.behaviorSections, "cruising") && haskey(csOriginal.behaviorSections, "diminishing")
|
||||
if get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[1] > get(csOriginal.behaviorSections, "diminishing", BehaviorSection()).dataPoints[1]
|
||||
reduceCruising=true
|
||||
reduceDiminishing=false
|
||||
else
|
||||
reduceDiminishing=true
|
||||
reduceCruising=false
|
||||
end
|
||||
elseif haskey(csOriginal.behaviorSections, "cruising")
|
||||
reduceCruising=true
|
||||
reduceDiminishing=false
|
||||
elseif haskey(csOriginal.behaviorSections, "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<csModified.s_end) -> see below at the end of the while loop
|
||||
|
||||
# create a copy for the characteristic sections drivingCourse
|
||||
energySavingStartId=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[1]
|
||||
if energySavingStartId==0
|
||||
error("ERROR at creating a new driving course for energy saving with coasting !")
|
||||
end
|
||||
|
||||
# copy the driving course till the beginning of energy saving
|
||||
drivingCourseModified=Vector{DataPoint}()
|
||||
for i in 1:energySavingStartId
|
||||
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
|
||||
# TODO: tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of data points till the start of energy saving
|
||||
end
|
||||
|
||||
# calculating the new length of the cruising section
|
||||
if settings.stepVariable=="s in m" # distance step method
|
||||
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-cruisingReduction
|
||||
elseif settings.stepVariable=="t in s" # time step method
|
||||
# 09/20 old: doesn't work for non constant cruising
|
||||
# t_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).t_total-cruisingReduction
|
||||
# s_cruising=t_cruising*drivingCourseModified[end].v
|
||||
wayReduction=drivingCourse(get(csOriginal.behaviorSections, "cruising", BehaviorSection()).dataPoints[end]).v*cruisingReduction
|
||||
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-wayReduction
|
||||
|
||||
elseif settings.stepVariable=="v in m/s" # velocity step method
|
||||
s_cruising=get(csOriginal.behaviorSections, "cruising", BehaviorSection()).s_total-cruisingReduction*10 # TODO: or better: *100 ?
|
||||
end #if
|
||||
s_cruising=max(0.0, s_cruising)
|
||||
|
||||
# copy csOriginal to csModified
|
||||
csModified=CharacteristicSection(csOriginal.id, csOriginal.s_total, csOriginal.s_start, csOriginal.s_end, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_reach, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}())
|
||||
if haskey(csOriginal.behaviorSections, "starting")
|
||||
startingSection=BehaviorSection(get(csOriginal.behaviorSections, "starting", BehaviorSection()))
|
||||
merge!(csModified.behaviorSections, Dict("starting"=>startingSection))
|
||||
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "starting", BehaviorSection()).E_total
|
||||
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "starting", BehaviorSection()).t_total
|
||||
end
|
||||
if haskey(csOriginal.behaviorSections, "cruisingBeforeAcceleration") # this section is needed before acceleration if the mass strip model is used and if the train wants to accelerate to a velocity higher than the limit in the other CS where parts of the union are still located
|
||||
cruisingBeforeAccelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()))
|
||||
merge!(csModified.behaviorSections, Dict("cruisingBeforeAcceleration"=>cruisingBeforeAccelerationSection))
|
||||
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).E_total
|
||||
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).t_total
|
||||
end
|
||||
if haskey(csOriginal.behaviorSections, "acceleration")
|
||||
accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
|
||||
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection))
|
||||
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E_total
|
||||
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t_total
|
||||
end
|
||||
|
||||
if haskey(csOriginal.behaviorSections, "diminishing")
|
||||
diminishingSection=BehaviorSection(get(csOriginal.behaviorSections, "diminishing", BehaviorSection()))
|
||||
merge!(csModified.behaviorSections, Dict("diminishing"=>diminishingSection))
|
||||
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "diminishing", BehaviorSection()).E_total
|
||||
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "diminishing", BehaviorSection()).t_total
|
||||
end
|
||||
|
||||
|
||||
# calculate the new and now shorter cruising section
|
||||
if s_cruising>0.0
|
||||
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruising, settings, train, allCSs, "cruising")
|
||||
end
|
||||
|
||||
# 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_end
|
||||
# the train reaches v_exit before reaching s_end. The cruising and coasting sections have to be calculated again with a larger cruising section (so with a smaller reduction of the cruising section)
|
||||
cruisingReduction=cruisingReduction/10
|
||||
else
|
||||
break
|
||||
end
|
||||
end # while cruisingReduction
|
||||
|
||||
# calculate the moving phase between coasting and the end of the CS
|
||||
if drivingCourseModified[end].v > csModified.v_exit
|
||||
#(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings.massModel, train, allCSs)
|
||||
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
|
||||
elseif drivingCourseModified[end].v == csModified.v_exit && drivingCourseModified[end].s < csModified.s_end
|
||||
# v_exit is already reached. Now cruise till the end of the CS
|
||||
s_cruisingAfterCoasting=csModified.s_end-drivingCourseModified[end].s
|
||||
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
|
||||
end
|
||||
|
||||
if t_recoveryAvailable < csModified.t_total-csOriginal.t_total || drivingCourseModified[end].v != csModified.v_exit || drivingCourseModified[end].s != csModified.s_end # 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_end are not reached excatly
|
||||
cruisingReduction=cruisingReduction/10
|
||||
else
|
||||
return (csModified, drivingCourseModified, true)
|
||||
end
|
||||
end #while
|
||||
|
||||
|
||||
elseif reduceDiminishing
|
||||
# TODO: At the moment diminishing is reduced like the acceleration in decreaseMaximumVelocity. To reduce code, the methods for reducing cruising phase an reducing the diminishing pahse can be combined in some parts.
|
||||
|
||||
# copy csOriginal to csModified
|
||||
csModified=CharacteristicSection(csOriginal.id, csOriginal.s_total, csOriginal.s_start, csOriginal.s_end, 0.0, 0.0, csOriginal.v_limit, csOriginal.v_reach, csOriginal.v_entry, csOriginal.v_exit, csOriginal.f_Rp, Dict{String, BehaviorSection}())
|
||||
|
||||
if haskey(csOriginal.behaviorSections, "starting")
|
||||
startingSection=BehaviorSection(get(csOriginal.behaviorSections, "starting", BehaviorSection()))
|
||||
merge!(csModified.behaviorSections, Dict("starting"=>startingSection))
|
||||
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "starting", BehaviorSection()).E_total
|
||||
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "starting", BehaviorSection()).t_total
|
||||
end
|
||||
|
||||
if haskey(csOriginal.behaviorSections, "cruisingBeforeAcceleration") # this section is needed before acceleration if the mass strip model is used and if the train wants to accelerate to a velocity higher than the limit in the other CS where parts of the union are still located
|
||||
cruisingBeforeAccelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()))
|
||||
merge!(csModified.behaviorSections, Dict("cruisingBeforeAcceleration"=>cruisingBeforeAccelerationSection))
|
||||
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).E_total
|
||||
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "cruisingBeforeAcceleration", BehaviorSection()).t_total
|
||||
end
|
||||
if haskey(csOriginal.behaviorSections, "acceleration")
|
||||
accelerationSection=BehaviorSection(get(csOriginal.behaviorSections, "acceleration", BehaviorSection()))
|
||||
merge!(csModified.behaviorSections, Dict("acceleration"=>accelerationSection))
|
||||
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).E_total
|
||||
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "acceleration", BehaviorSection()).t_total
|
||||
end
|
||||
|
||||
if haskey(csOriginal.behaviorSections, "cruising")
|
||||
cruisingSection=BehaviorSection(get(csOriginal.behaviorSections, "cruising", BehaviorSection()))
|
||||
merge!(csModified.behaviorSections, Dict("cruising"=>cruisingSection))
|
||||
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "cruising", BehaviorSection()).E_total
|
||||
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "cruising", BehaviorSection()).t_total
|
||||
end
|
||||
|
||||
diminishingSection=BehaviorSection(get(csOriginal.behaviorSections, "diminishing", BehaviorSection()))
|
||||
if length(diminishingSection.dataPoints) > 2
|
||||
# remove the last diminishing waypoint
|
||||
pop!(diminishingSection.dataPoints)
|
||||
|
||||
diminishingSection.v_exit=drivingCourse[diminishingSection.dataPoints[end]].v # exit speed (in m/s)
|
||||
diminishingSection.s_end=drivingCourse[diminishingSection.dataPoints[end]].s # last position (in m)
|
||||
diminishingSection.s_total=diminishingSection.s_end-diminishingSection.s_start # total length (in m)
|
||||
diminishingSection.t_total=drivingCourse[diminishingSection.dataPoints[end]].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
|
||||
diminishingSection.E_total=drivingCourse[diminishingSection.dataPoints[end]].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
|
||||
|
||||
merge!(csModified.behaviorSections, Dict("diminishing"=>diminishingSection))
|
||||
csModified.E_total=csModified.E_total+get(csModified.behaviorSections, "diminishing", BehaviorSection()).E_total
|
||||
csModified.t_total=csModified.t_total+get(csModified.behaviorSections, "diminishing", BehaviorSection()).t_total
|
||||
|
||||
energySavingStartId=diminishingSection.dataPoints[end]
|
||||
else
|
||||
# The diminishing section is only one step. This step is removed and if there is a cruisingBeforeAcceleration section it will be combined with the new cruising section.
|
||||
energySavingStartId=get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", get(csOriginal.behaviorSections, "diminishing", BehaviorSection())).dataPoints[1]
|
||||
end
|
||||
|
||||
# copy the driving course till the beginning of energy saving
|
||||
drivingCourseModified=Vector{DataPoint}()
|
||||
for i in 1:energySavingStartId
|
||||
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
|
||||
end
|
||||
|
||||
# calculate the coasting phase until the point the train needs to brake
|
||||
(csModified, drivingCourseModified)=addCoastingPhaseUntilBraking!(csModified, drivingCourseModified, settings, train, allCSs)
|
||||
|
||||
# calculate the moving phase between coasting and the end of the CS
|
||||
if drivingCourseModified[end].v > csModified.v_exit
|
||||
(csModified, drivingCourseModified)=addBrakingPhase!(csModified, drivingCourseModified, settings, train, allCSs)
|
||||
elseif drivingCourseModified[end].v == csModified.v_exit && drivingCourseModified[end].s < csModified.s_end
|
||||
# v_exit is already reached. Now cruise till the end of the CS
|
||||
s_cruisingAfterCoasting=csModified.s_end-drivingCourseModified[end].s
|
||||
(csModified, drivingCourseModified)=addCruisingPhase!(csModified, drivingCourseModified, s_cruisingAfterCoasting, settings, train, allCSs, "cruisingAfterCoasting")
|
||||
end
|
||||
|
||||
|
||||
if t_recoveryAvailable>=(csModified.t_total-csOriginal.t_total)
|
||||
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)
|
||||
end
|
||||
end
|
||||
|
||||
# there is no energy saving modification for this CS with the available recovery time
|
||||
return (CharacteristicSection(), [], false)
|
||||
else
|
||||
# there is no energy saving modification for this CS because a cruising section AND a braking section are needed to be transformed into a coasting section
|
||||
return (CharacteristicSection(), [], false)
|
||||
end
|
||||
end # function increaseCoastingSection
|
||||
|
||||
#= 12/03 old without diminishing: function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
|
||||
if haskey(csOriginal.behaviorSections, "cruising") && haskey(csOriginal.behaviorSections, "braking")
|
||||
cruisingReduction=settings.stepSize
|
||||
while cruisingReduction>=settings.stepSize/10^approximationLevel
|
||||
|
@ -101,11 +309,13 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
|
|||
if energySavingStartId==0
|
||||
error("ERROR at creating a new driving course for energy saving with coasting !")
|
||||
end
|
||||
# TODO: tried to insert copy on 15.07.2021 drivingCourseModified=[copy(drivingCourse[1])]
|
||||
|
||||
drivingCourseModified=[DataPoint(drivingCourse[1])]
|
||||
# TODO: tried to insert copy on 15.07.2021 drivingCourseModified=[copy(drivingCourse[1])]
|
||||
for i in 2:energySavingStartId
|
||||
# TODO: tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of data points till the start of energy saving
|
||||
push!(drivingCourseModified, DataPoint(drivingCourse[i])) # List of data points till the start of energy saving
|
||||
# TODO: tried to insert copy on 15.07.2021 push!(drivingCourseModified, copy(drivingCourse[i])) # List of data points till the start of energy saving
|
||||
|
||||
end
|
||||
|
||||
# calculating the new length of the cruising section
|
||||
|
@ -182,6 +392,7 @@ function increaseCoastingSection(csOriginal::CharacteristicSection, drivingCours
|
|||
end
|
||||
end # function increaseCoastingSection
|
||||
|
||||
=#
|
||||
|
||||
# method 2 with shortening the acceleration by stepsize
|
||||
function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCourse, settings::Settings, train::Train, allCSs::Vector{CharacteristicSection}, t_recoveryAvailable::AbstractFloat)
|
||||
|
@ -228,7 +439,7 @@ function decreaseMaximumVelocity(csOriginal::CharacteristicSection, drivingCours
|
|||
|
||||
energySavingStartId=accelerationSection.dataPoints[end]
|
||||
else
|
||||
# The acceleration section is only one step. This step is removed and if ther ist a cruisingBeforeAcceleration section it will be combined with the new cruising section.
|
||||
# The acceleration section is only one step. This step is removed and if there is a cruisingBeforeAcceleration section it will be combined with the new cruising section.
|
||||
energySavingStartId=get(csOriginal.behaviorSections, "cruisingBeforeAcceleration", get(csOriginal.behaviorSections, "acceleration", BehaviorSection())).dataPoints[1]
|
||||
end
|
||||
|
||||
|
|
109
src/Input.jl
109
src/Input.jl
|
@ -8,10 +8,10 @@ export readInput
|
|||
"""
|
||||
Read the input information from YAML files for train, path and settings, save it in different objects and return them.
|
||||
"""
|
||||
function readInput(trainFilePath::String, pathFilePath::String, settingsFilePath::String)
|
||||
train=inputTrain(trainFilePath)
|
||||
path=inputPath(pathFilePath)
|
||||
settings=inputSettings(settingsFilePath)
|
||||
function readInput(trainDirectory::String, pathDirectory::String, settingsDirectory::String)
|
||||
train=inputTrain(trainDirectory)
|
||||
path=inputPath(pathDirectory)
|
||||
settings=inputSettings(settingsDirectory)
|
||||
|
||||
return (train, path, settings)
|
||||
end #function readInput
|
||||
|
@ -19,8 +19,8 @@ function readInput(trainFilePath::String, pathFilePath::String, settingsFilePath
|
|||
"""
|
||||
Read the train information from a YAML file, save it in a Train object and return it.
|
||||
"""
|
||||
function inputTrain(trainFilePath::String)
|
||||
data = YAML.load(open(trainFilePath))
|
||||
function inputTrain(trainDirectory::String)
|
||||
data = YAML.load(open(trainDirectory))
|
||||
collect(keys(data))
|
||||
collect(values(data))
|
||||
|
||||
|
@ -56,8 +56,6 @@ function inputTrain(trainFilePath::String)
|
|||
end
|
||||
|
||||
|
||||
|
||||
|
||||
# speed limit: # trains speed limit (in m/s)
|
||||
v_limit_temp=0.0
|
||||
v_limit_kmh_temp=0.0
|
||||
|
@ -189,11 +187,13 @@ function inputTrain(trainFilePath::String)
|
|||
delete!(data["train"], "rotationMassFactor_w")
|
||||
|
||||
|
||||
# input for function tractiveEffort(v)
|
||||
# TODO: Should the arrays check and the arrays copy be in the same "for" loop?
|
||||
# pairs of velocity and tractive effort
|
||||
if haskey(data["train"],"F_T_pairs") && data["train"]["F_T_pairs"]!=nothing
|
||||
F_T_pairs=data["train"]["F_T_pairs"]
|
||||
|
||||
train.tractiveEffortVelocityPairs=checkAndDefineTractiveEffortInput(F_T_pairs, 1.0)
|
||||
|
||||
#= old 2021-11-04: now it is pairs and no scope
|
||||
# check if the elements of the array have the correct type
|
||||
errorDetected=false
|
||||
for row in 1:length(F_T_pairs)
|
||||
|
@ -207,17 +207,33 @@ function inputTrain(trainFilePath::String)
|
|||
errorDetected=true
|
||||
println("ERROR at reading the train yaml file: The tractive effort value of F_T_pairs in row ", row ," is no real floating point number >=0.0.")
|
||||
end
|
||||
|
||||
if row>=2 && F_T_pairs[row][1] <= F_T_pairs[row-1][1]
|
||||
errorDetected=true
|
||||
println("ERROR at reading the train yaml file: The speed value of F_T_pairs in row ", row ," (v=",F_T_pairs[row][1]," m/s) is not higher than the speed value in the previous row (v=",F_T_pairs[row-1][1]," m/s).")
|
||||
end
|
||||
end # for
|
||||
if errorDetected
|
||||
error("ERROR at reading the train yaml file: Only real floating point number >=0.0 are allowed for speed and tractive effort.")
|
||||
error("ERROR at reading the train yaml file: Only real floating point number >=0.0 are allowed for speed and tractive effort. The speed values have to be listed from low to high.")
|
||||
end
|
||||
|
||||
# create tractiveEffortVelocityPairs
|
||||
if F_T_pairs[1][1]>0.0 # if there is no F_T for v=0.0, the first known value is used
|
||||
push!(train.tractiveEffortVelocityPairs, [0.0, F_T_pairs[1][2]])
|
||||
println("WARNING at reading the train yaml file: The tractive effort for v=0 m/s is missing. Therefore the first given value F_T(v=",F_T_pairs[1][1]," m/s)=",F_T_pairs[1][2]," N will be used." )
|
||||
end
|
||||
|
||||
for row in 1:length(F_T_pairs)
|
||||
push!(train.tractiveEffortVelocityPairs, [F_T_pairs[row][1]], F_T_pairs[row][2]])
|
||||
end # for
|
||||
|
||||
|
||||
# create tractiveEffortArray
|
||||
train.tractiveEffortArray=[]
|
||||
if F_T_pairs[1][1]==0.0
|
||||
push!(train.tractiveEffortArray, [F_T_pairs[1][1], F_T_pairs[1][1], F_T_pairs[1][2]])
|
||||
elseif F_T_pairs[1][1]>0.0 # if there is no F_T for v=0.0, the first value is used
|
||||
push!(train.tractiveEffortArray, [0.0, F_T_pairs[1][1]/3.6, F_T_pairs[1][2]])
|
||||
push!(train.tractiveEffortArray, [0.0, F_T_pairs[1][1], F_T_pairs[1][2]])
|
||||
println("WARNING at reading the train yaml file: The tractive effort for v=0 m/s is missing. Therefore the first given value F_T(v=",F_T_pairs[1][1]," m/s)=",F_T_pairs[1][2]," N will be used." )
|
||||
else
|
||||
error("ERROR at reading the train yaml file: There is a negative speed value in the list. Only positive values for speed and tractive effort are allowed in F_T_pairs.")
|
||||
|
@ -234,9 +250,11 @@ function inputTrain(trainFilePath::String)
|
|||
error("ERROR at reading the train yaml file: The F_T_pairs are not in the correct order. They have to be arranged by speed values from low to high.")
|
||||
end
|
||||
end # for
|
||||
|
||||
if length(F_T_pairs[1])>2
|
||||
println("INFO according the train yaml file: Only the first two columns of F_T_pairs are used in this tool.")
|
||||
end
|
||||
=#
|
||||
|
||||
if haskey(data["train"],"F_T_pairs_kmh") && data["train"]["F_T_pairs_kmh"]!=nothing
|
||||
println("WARNING at reading the train yaml file: There are values for F_T_pairs and F_T_pairs_kmh. The values for F_T_pairs are used." )
|
||||
|
@ -245,6 +263,9 @@ function inputTrain(trainFilePath::String)
|
|||
elseif haskey(data["train"],"F_T_pairs_kmh") && data["train"]["F_T_pairs_kmh"]!=nothing
|
||||
F_T_pairs_kmh=data["train"]["F_T_pairs_kmh"]
|
||||
|
||||
train.tractiveEffortVelocityPairs=checkAndDefineTractiveEffortInput(F_T_pairs_kmh, 1000/3600)
|
||||
|
||||
#= old 2021-11-04: now it is pairs and no scope
|
||||
# check if the elements of the array have the correct type
|
||||
errorDetected=false
|
||||
for row in 1:length(F_T_pairs_kmh)
|
||||
|
@ -285,6 +306,7 @@ function inputTrain(trainFilePath::String)
|
|||
if length(F_T_pairs_kmh[1])>2
|
||||
println("INFO at reading the train yaml file: Only the first two columns of F_T_pairs_kmh are used in this tool.")
|
||||
end
|
||||
=#
|
||||
else
|
||||
error("ERROR at reading the train yaml file: There has to be one of the keywords F_T_pairs or F_T_pairs_kmh filled with a list of pairs of velocity and tractive effort.")
|
||||
end # if
|
||||
|
@ -398,10 +420,53 @@ function inputTrain(trainFilePath::String)
|
|||
return train
|
||||
end #function inputTrain
|
||||
|
||||
function checkAndDefineTractiveEffortInput(F_T_pairs, velocityMultiplier::AbstractFloat)
|
||||
# TODO: check if its numbers are real ? function checkAndDefineTractiveEffortInput(F_T_pairs::Array{Array{Real,1},1}, velocityMultiplier::AbstractFloat)
|
||||
# check if the elements of the array have the correct type
|
||||
errorDetected=false
|
||||
for row in 1:length(F_T_pairs)
|
||||
if typeof(F_T_pairs[row][1]) <: Real && F_T_pairs[row][1]>=0.0
|
||||
else
|
||||
errorDetected=true
|
||||
println("ERROR at reading the train yaml file: The speed value of F_T_pairs in row ", row ," is no real floating point number >=0.0.")
|
||||
end
|
||||
if typeof(F_T_pairs[row][2]) <: Real && F_T_pairs[row][2]>=0.0
|
||||
else
|
||||
errorDetected=true
|
||||
println("ERROR at reading the train yaml file: The tractive effort value of F_T_pairs in row ", row ," is no real floating point number >=0.0.")
|
||||
end
|
||||
|
||||
function inputPath(pathFilePath::String)
|
||||
if row>=2 && F_T_pairs[row][1] <= F_T_pairs[row-1][1]
|
||||
errorDetected=true
|
||||
println("ERROR at reading the train yaml file: The speed value of F_T_pairs in row ", row ," (v=",F_T_pairs[row][1]," m/s) is not higher than the speed value in the previous row (v=",F_T_pairs[row-1][1]," m/s).")
|
||||
end
|
||||
end # for
|
||||
if errorDetected
|
||||
error("ERROR at reading the train yaml file: Only real floating point number >=0.0 are allowed for speed and tractive effort. The speed values have to be listed from low to high.")
|
||||
end
|
||||
|
||||
# create tractiveEffortVelocityPairs
|
||||
tractiveEffortVelocityPairs=[]
|
||||
if F_T_pairs[1][1]>0.0 # if there is no F_T for v=0.0, the first known value is used
|
||||
push!(tractiveEffortVelocityPairs, [0.0, F_T_pairs[1][2]])
|
||||
println("WARNING at reading the train yaml file: The tractive effort for v=0 m/s is missing. Therefore the first given value F_T(v=",F_T_pairs[1][1]," m/s)=",F_T_pairs[1][2]," N will be used." )
|
||||
end
|
||||
|
||||
for row in 1:length(F_T_pairs)
|
||||
push!(tractiveEffortVelocityPairs, [F_T_pairs[row][1]*velocityMultiplier, F_T_pairs[row][2]])
|
||||
end # for
|
||||
|
||||
|
||||
if length(F_T_pairs[1])>2
|
||||
println("INFO according the train yaml file: Only the first two columns of F_T_pairs are used in this tool.")
|
||||
end
|
||||
return tractiveEffortVelocityPairs
|
||||
end #function checkAndDefineTractiveEffortInput
|
||||
|
||||
|
||||
function inputPath(pathDirectory::String)
|
||||
# this function reads path information from a YAML file, saves it in a Path object and returns it
|
||||
data = YAML.load(open(pathFilePath))
|
||||
data = YAML.load(open(pathDirectory))
|
||||
collect(keys(data))
|
||||
collect(values(data))
|
||||
|
||||
|
@ -504,9 +569,9 @@ end # function inputPath
|
|||
|
||||
|
||||
|
||||
function inputSettings(settingsFilePath::String)
|
||||
function inputSettings(settingsDirectory::String)
|
||||
# this function reads setting information from a YAML file, saves it in a Setting object and returns it
|
||||
data = YAML.load(open(settingsFilePath))
|
||||
data = YAML.load(open(settingsDirectory))
|
||||
collect(keys(data))
|
||||
collect(values(data))
|
||||
|
||||
|
@ -594,16 +659,16 @@ function inputSettings(settingsFilePath::String)
|
|||
|
||||
# TODO: it could be checked if the path is existing on the pc
|
||||
if settings.typeOfOutput=="CSV"
|
||||
if haskey(data["settings"],"csvFolderPath")
|
||||
if typeof(data["settings"]["csvFolderPath"])==String
|
||||
settings.csvFolderPath=data["settings"]["csvFolderPath"]
|
||||
if haskey(data["settings"],"csvDirectory")
|
||||
if typeof(data["settings"]["csvDirectory"])==String
|
||||
settings.csvDirectory=data["settings"]["csvDirectory"]
|
||||
else
|
||||
error("ERROR at reading the settings yaml file: The value of csvFolderPath is wrong. It has to be of type String.")
|
||||
error("ERROR at reading the settings yaml file: The value of csvDirectory is wrong. It has to be of type String.")
|
||||
end
|
||||
else
|
||||
error("ERROR at reading the settings yaml file: The keyword csvFolderPath is missing. It has to be added.")
|
||||
error("ERROR at reading the settings yaml file: The keyword csvDirectory is missing. It has to be added.")
|
||||
end
|
||||
delete!(data["settings"], "csvFolderPath")
|
||||
delete!(data["settings"], "csvDirectory")
|
||||
end # if
|
||||
|
||||
|
||||
|
|
|
@ -11,16 +11,15 @@ approximationLevel = 6 # value for approximation to intersections TODO further
|
|||
# TODO: define it in TrainRun and give it to each function?
|
||||
|
||||
## functions for calculating tractive effort and resisting forces
|
||||
#TODO: change tractiveEffortArray to tractiveEffortVelocityPairs ?? Currently the example doesn't fit to the function
|
||||
"""
|
||||
calculateTractiveEffort(v, tractiveEffortArray)
|
||||
calculateTractiveEffort(v, tractiveEffortVelocityPairs)
|
||||
|
||||
Calculate the trains tractive effort from the `tractiveEffortArray` dependend on the velocity `v`.
|
||||
Calculate the trains tractive effort with the `tractiveEffortVelocityPairs` dependend on the velocity `v`.
|
||||
|
||||
...
|
||||
# Arguments
|
||||
- `v::AbstractFloat`: the current velocity in m/s.
|
||||
- `tractiveEffortArray::Array{Array{AbstractFloat,1},1}`: the trains pairs for velocity in m/s and tractive effort in N as one array containing an array for each pair.
|
||||
- `tractiveEffortVelocityPairs::Array{Array{AbstractFloat,1},1}`: the trains pairs for velocity in m/s and tractive effort in N as one array containing an array for each pair.
|
||||
...
|
||||
|
||||
# Examples
|
||||
|
@ -32,25 +31,42 @@ julia> calculateTractiveEffort(30.0, [[0.0, 180000], [20.0, 100000], [40.0, 6000
|
|||
80000
|
||||
```
|
||||
"""
|
||||
function calculateTractiveEffort(v::AbstractFloat, tractiveEffortArray)
|
||||
for row in 1:length(tractiveEffortArray)
|
||||
if tractiveEffortArray[row][1]<=v && v<=tractiveEffortArray[row][2]
|
||||
return tractiveEffortArray[row][3]
|
||||
elseif tractiveEffortArray[row][1]>v
|
||||
if row>1
|
||||
# interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-_(row-1))/(v_row-v_(row-1))+F_(row-1)
|
||||
F_T_interpolation=(v-tractiveEffortArray[row-1][2])*(tractiveEffortArray[row][3]-tractiveEffortArray[row-1][3])/(tractiveEffortArray[row][1]-tractiveEffortArray[row-1][2])+tractiveEffortArray[row-1][3]
|
||||
|
||||
return F_T_interpolation
|
||||
else
|
||||
return tractiveEffortArray[1][3]
|
||||
end #if
|
||||
function calculateTractiveEffort(v::AbstractFloat, tractiveEffortVelocityPairs)
|
||||
for row in 1:length(tractiveEffortVelocityPairs)
|
||||
if tractiveEffortVelocityPairs[row][1]==v
|
||||
return tractiveEffortVelocityPairs[row][2]
|
||||
elseif tractiveEffortVelocityPairs[row][1]>v
|
||||
# interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-F_(row-1))/(v_row-v_(row-1))+F_(row-1)
|
||||
F_T_interpolation=(v-tractiveEffortVelocityPairs[row-1][1])*(tractiveEffortVelocityPairs[row][2]-tractiveEffortVelocityPairs[row-1][2])/(tractiveEffortVelocityPairs[row][1]-tractiveEffortVelocityPairs[row-1][1])+tractiveEffortVelocityPairs[row-1][2]
|
||||
return F_T_interpolation
|
||||
end #if
|
||||
end #for
|
||||
# if v gets higher than the velocities in tractiveEffortArray the last tractive effort will be used
|
||||
# if v gets higher than the velocities in tractiveEffortVelocityPairs the last tractive effort will be used
|
||||
# TODO: also an extrapolation could be used
|
||||
return tractiveEffortArray[end][3]
|
||||
return tractiveEffortVelocityPairs[end][2]
|
||||
end #function calculateTractiveEffort
|
||||
#= old 2021-11-04: now with easier tractiveEffortVelocityPairs than previous tractiveEffortArray
|
||||
function calculateTractiveEffort(v::AbstractFloat, tractiveEffortArray)
|
||||
for row in 1:length(tractiveEffortArray)
|
||||
if tractiveEffortArray[row][1]<=v && v<=tractiveEffortArray[row][2]
|
||||
return tractiveEffortArray[row][3]
|
||||
elseif tractiveEffortArray[row][1]>v
|
||||
if row>1
|
||||
# interpolate for a straight line between the two surrounding points with the formula: F=(v-v_(row-1))*(F_row-_(row-1))/(v_row-v_(row-1))+F_(row-1)
|
||||
F_T_interpolation=(v-tractiveEffortArray[row-1][2])*(tractiveEffortArray[row][3]-tractiveEffortArray[row-1][3])/(tractiveEffortArray[row][1]-tractiveEffortArray[row-1][2])+tractiveEffortArray[row-1][3]
|
||||
|
||||
return F_T_interpolation
|
||||
else
|
||||
return tractiveEffortArray[1][3]
|
||||
end #if
|
||||
end #if
|
||||
end #for
|
||||
# if v gets higher than the velocities in tractiveEffortArray the last tractive effort will be used
|
||||
# TODO: also an extrapolation could be used
|
||||
return tractiveEffortArray[end][3]
|
||||
end #function calculateTractiveEffort
|
||||
=#
|
||||
|
||||
|
||||
#TODO: choose an explanation and replace the ? ? ?
|
||||
"""
|
||||
|
@ -125,12 +141,14 @@ function calculateForces!(dataPoint::DataPoint, train::Train, massModel::String,
|
|||
dataPoint.F_Rp=calculatePathResistance(dataPoint.s, massModel, train, allCs)
|
||||
dataPoint.F_R=dataPoint.F_Runion+dataPoint.F_Rp
|
||||
|
||||
#calculate tractive effort
|
||||
if bsType == "acceleration"
|
||||
dataPoint.F_T = calculateTractiveEffort(dataPoint.v, train.tractiveEffortArray)
|
||||
# calculate tractive effort
|
||||
if bsType == "acceleration" || bsType == "diminishing"
|
||||
# 12/03 test: if bsType == "acceleration" || bsType == "diminishing" || bsType == "maximumTraction"
|
||||
# 11/21 old without diminishing: if bsType == "acceleration"
|
||||
dataPoint.F_T = calculateTractiveEffort(dataPoint.v, train.tractiveEffortVelocityPairs)
|
||||
# println(" F_T:",dataPoint.F_T )
|
||||
elseif bsType == "cruising"
|
||||
# 09/22 println("s=",dataPoint.s, " v=",dataPoint.v, " F_R=",dataPoint.F_R, " F_T=",calculateTractiveEffort(dataPoint.v, train.tractiveEffortArray))
|
||||
dataPoint.F_T = min(max(0.0, dataPoint.F_R), calculateTractiveEffort(dataPoint.v, train.tractiveEffortArray))
|
||||
dataPoint.F_T = min(max(0.0, dataPoint.F_R), calculateTractiveEffort(dataPoint.v, train.tractiveEffortVelocityPairs))
|
||||
else
|
||||
dataPoint.F_T = 0.0
|
||||
end
|
||||
|
@ -144,6 +162,7 @@ TODO
|
|||
function moveAStep(previousPoint::DataPoint, stepVariable::String, stepSize::AbstractFloat, csId::Integer)
|
||||
# stepSize is the currentStepSize depending on the accessing function
|
||||
# TODO: csId is only for error messages. Should it be removed?
|
||||
#= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies. =#
|
||||
|
||||
# creating the next data point
|
||||
newPoint=DataPoint()
|
||||
|
@ -156,14 +175,15 @@ function moveAStep(previousPoint::DataPoint, stepVariable::String, stepSize::Abs
|
|||
newPoint.Δv=0.0 # step size (in m/s)
|
||||
elseif stepVariable=="s in m" # distance step method
|
||||
newPoint.Δs=stepSize # step size (in m)
|
||||
# TODO: is this if correct and necessary?
|
||||
#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, F_Rt=",previousPoint.F_Rt," N, F_Rw=",previousPoint.F_Rw," N, F_Rp=",previousPoint.F_Rp," N.")
|
||||
#end
|
||||
#= 08/31 TODO: How to check if the train stopps during this step? I should throw an error myself that I catch in higher hierarchies.
|
||||
=#
|
||||
# 11/21 |->
|
||||
if previousPoint.a<0.0
|
||||
if ((previousPoint.v/previousPoint.a)^2+2*newPoint.Δs/previousPoint.a)<0.0 || (previousPoint.v^2+2*newPoint.Δs*previousPoint.a)<0.0 # checking if the parts of the following square roots will be <0.0
|
||||
error("ERROR: The train stops during the acceleration phase in CS",csId," because the tractive effort is lower than the resistant forces.",
|
||||
" Before the stop the last point has the values s=",previousPoint.s," m, v=",previousPoint.v," m/s, a=",previousPoint.a," m/s^2,",
|
||||
" F_T=",previousPoint.F_T," N, F_Rt=",previousPoint.F_Rt," N, F_Rw=",previousPoint.F_Rw," N, F_Rp=",previousPoint.F_Rp," N.")
|
||||
end
|
||||
end
|
||||
# 11/21 ->|
|
||||
newPoint.Δt=sign(previousPoint.a)*sqrt((previousPoint.v/previousPoint.a)^2+2*newPoint.Δs/previousPoint.a)-previousPoint.v/previousPoint.a # step size (in s)
|
||||
newPoint.Δv=sqrt(previousPoint.v^2+2*newPoint.Δs*previousPoint.a)-previousPoint.v # step size (in m/s)
|
||||
elseif stepVariable=="t in s" # time step method
|
||||
|
@ -179,17 +199,12 @@ function moveAStep(previousPoint::DataPoint, stepVariable::String, stepSize::Abs
|
|||
newPoint.s=previousPoint.s+newPoint.Δs # position (in m)
|
||||
newPoint.t=previousPoint.t+newPoint.Δt # point in time (in s)
|
||||
newPoint.v=previousPoint.v+newPoint.Δv # velocity (in m/s)
|
||||
# 08/23 the following will be checked later
|
||||
#if newPoint.v<=0.0
|
||||
# error("ERROR: The train stops during the acceleration phase in CS",csId," m because the tractive effort is lower than the resistant forces.",
|
||||
# " Before the stop the last point has the values s=",previousPoint.s," v=",previousPoint.v," m/s a=",previousPoint.a," m/s^2",
|
||||
# " F_T=",previousPoint.F_T," N F_Rt=",previousPoint.F_Rt," N F_Rw=",previousPoint.F_Rw," N F_Rp=",previousPoint.F_Rp," N.")
|
||||
#end
|
||||
newPoint.ΔW_T=previousPoint.F_T*newPoint.Δs # mechanical work in this step (in Ws)
|
||||
newPoint.W_T=previousPoint.W_T+newPoint.ΔW_T # mechanical work (in Ws)
|
||||
newPoint.ΔE=newPoint.ΔW_T # energy consumption in this step (in Ws)
|
||||
newPoint.E=previousPoint.E+newPoint.ΔE # energy consumption (in Ws)
|
||||
|
||||
|
||||
return newPoint
|
||||
end #function moveAStep
|
||||
|
||||
|
@ -343,11 +358,23 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
|
|||
(characteristicSection, drivingCourse)=addStartingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
|
||||
end #if
|
||||
|
||||
calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration")
|
||||
if drivingCourse[end].F_T < drivingCourse[end].F_R
|
||||
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration"))
|
||||
end
|
||||
|
||||
# if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
|
||||
formerSpeedLimits = detectFormerSpeedLimits(allCs, characteristicSection.id, drivingCourse[end], train.l_union)
|
||||
|
||||
if drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s <characteristicSection.s_end
|
||||
# 09/09 new (for steep gradients "<=" is necessary but only in accelertion until breaking due to Operation modes) TODO
|
||||
# conditions for acceleration phase
|
||||
targetSpeedReached = drivingCourse[end].v >= characteristicSection.v_reach
|
||||
trainAtEnd = drivingCourse[end].s >= characteristicSection.s_end
|
||||
tractionSurplus = drivingCourse[end].F_T > drivingCourse[end].F_R
|
||||
|
||||
# use the conditions for the acceleration phase
|
||||
if !targetSpeedReached && !trainAtEnd && tractionSurplus
|
||||
#11/23 old without F_T > F_R: if drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s <characteristicSection.s_end && drivingCourse[end].F_T > drivingCourse[end].F_R
|
||||
accelerationSection=BehaviorSection()
|
||||
accelerationSection.type="acceleration" # type of behavior section
|
||||
accelerationSection.s_start=drivingCourse[end].s # first position (in m)
|
||||
|
@ -355,28 +382,20 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
|
|||
push!(accelerationSection.dataPoints, drivingCourse[end].i)
|
||||
|
||||
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
|
||||
#= 08/23 old version for intersection approximation
|
||||
for cycle in 1:5 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size and fourth cycle with the last step size calculated till the intersection
|
||||
# in the fifth cycle the interpolated values are corrected in case v_reach is still to high although s==s_end
|
||||
=#
|
||||
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 characteristicSection.v_reach - drivingCourse[end].v > 0.000001 && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0
|
||||
|
||||
while drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0
|
||||
|
||||
# 09/09 new (for steep gradients "<=" is necessary but only in accelertion until braking due to Operation modes) TODO
|
||||
while drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].F_T > drivingCourse[end].F_R
|
||||
# 12/03 old with v>0.0: while drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R
|
||||
# traction effort and resisting forces (in N)
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
|
||||
# 11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
|
||||
|
||||
# acceleration (in m/s^2):
|
||||
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
|
||||
# if drivingCourse[end].a==0.0
|
||||
# error("ERROR: a=0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," F_Rt=",drivingCourse[end].F_Rt," F_Rw=",drivingCourse[end].F_Rw," F_Rp=",drivingCourse[end].F_Rp)
|
||||
# end
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id))
|
||||
push!(accelerationSection.dataPoints, drivingCourse[end].i)
|
||||
# drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
|
||||
|
||||
|
||||
if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal
|
||||
(characteristicSection, drivingCourse, formerSpeedLimits, accelerationSection, endOfCsReached) = considerFormerSpeedLimits!(characteristicSection, drivingCourse, settings, train, allCs, formerSpeedLimits, accelerationSection)
|
||||
|
@ -385,6 +404,7 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
|
|||
end #if
|
||||
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
|
||||
end #if
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
|
||||
end #while
|
||||
|
||||
# check which limit was reached and adjust the currentStepSize for the next cycle
|
||||
|
@ -411,6 +431,8 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
|
|||
|
||||
elseif drivingCourse[end].v==characteristicSection.v_reach
|
||||
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_reach and s<s_end in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
|
||||
|
@ -432,30 +454,33 @@ function addAccelerationPhase!(characteristicSection::CharacteristicSection, dri
|
|||
elseif drivingCourse[end].s>characteristicSection.s_end
|
||||
drivingCourse[end].s=characteristicSection.s_end # rounding s down to s_end
|
||||
|
||||
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
|
||||
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
|
||||
|
||||
else
|
||||
|
||||
end
|
||||
end
|
||||
end #for
|
||||
|
||||
# if length(accelerationSection.dataPoints) > 1 # 09/09 new: it is possible that the acceleration starts at v_reach, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section. | It should only be used in addAccelerationUntilBreaking! due to Operation Modes TODO
|
||||
if length(accelerationSection.dataPoints) > 1 # 11/21 new: it is possible that the acceleration starts at v_reach, 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_end=drivingCourse[end].s # last position (in m)
|
||||
accelerationSection.s_total=accelerationSection.s_end-accelerationSection.s_start # total length (in m)
|
||||
accelerationSection.t_total=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s)
|
||||
accelerationSection.E_total=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
|
||||
characteristicSection.t_total=characteristicSection.t_total+accelerationSection.t_total # total running time (in s)
|
||||
characteristicSection.E_total=characteristicSection.E_total+accelerationSection.E_total # total energy consumption (in Ws)
|
||||
|
||||
# calculation the accumulated acceleration section information
|
||||
accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
|
||||
accelerationSection.s_end=drivingCourse[end].s # last position (in m)
|
||||
accelerationSection.s_total=accelerationSection.s_end-accelerationSection.s_start # total length (in m)
|
||||
accelerationSection.t_total=drivingCourse[end].t-drivingCourse[accelerationSection.dataPoints[1]].t # total running time (in s)
|
||||
accelerationSection.E_total=drivingCourse[end].E-drivingCourse[accelerationSection.dataPoints[1]].E # total energy consumption (in Ws)
|
||||
characteristicSection.t_total=characteristicSection.t_total+accelerationSection.t_total # total running time (in s)
|
||||
characteristicSection.E_total=characteristicSection.E_total+accelerationSection.E_total # total energy consumption (in Ws)
|
||||
# TODO: this warning schould not be needed. just for testing
|
||||
if characteristicSection.v_reach < drivingCourse[end].v
|
||||
println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_reach=",characteristicSection.v_reach)
|
||||
end
|
||||
|
||||
# TODO: this warning schould not be needed. just for testing
|
||||
if characteristicSection.v_reach<drivingCourse[end].v
|
||||
println("WARNING, v is getting to high at the end of the acceleration phase. v=",drivingCourse[end].v ," > v_reach=",characteristicSection.v_reach)
|
||||
merge!(characteristicSection.behaviorSections, Dict("acceleration"=>accelerationSection))
|
||||
end
|
||||
|
||||
merge!(characteristicSection.behaviorSections, Dict("acceleration"=>accelerationSection))
|
||||
# end
|
||||
end # else: just return the given data point number without changes due to the acceleration phase
|
||||
|
||||
return (characteristicSection, drivingCourse)
|
||||
|
@ -468,48 +493,18 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
|
|||
(characteristicSection, drivingCourse)=addStartingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
|
||||
end #if
|
||||
|
||||
calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration")
|
||||
if drivingCourse[end].F_T < drivingCourse[end].F_R
|
||||
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "acceleration"))
|
||||
end
|
||||
|
||||
# if the tail of the train is still located in a former characteristic section it has to be checked if its speed limit can be kept
|
||||
formerSpeedLimits = detectFormerSpeedLimits(allCs, characteristicSection.id, drivingCourse[end], train.l_union)
|
||||
#(formerSpeedLimits, s_cruisingBeforeAcceleration) = detectFormerSpeedLimits(allCs, characteristicSection.id, drivingCourse[end], train.l_union)
|
||||
#if s_cruisingBeforeAcceleration > 0.0
|
||||
# (characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, train, allCs, "cruisingBeforeAcceleration")
|
||||
#else
|
||||
# error("ERROR: cruisingBeforeAcceleration <=0.0 although it has to be >0.0 in CS ",csWithTrainHeadId)
|
||||
#end
|
||||
|
||||
#= 07/30 *** TODO
|
||||
# if the tail of the train is still in a former characteristic section it has to be checked if its speed limit can be kept
|
||||
formerSpeedLimits=[]
|
||||
if characteristicSection.id>1 && drivingCourse[end].s-train.l_union<characteristicSection.s_start
|
||||
if abs(allCs[characteristicSection.id-1].v_limit-drivingCourse[end].v)<0.000001
|
||||
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel))
|
||||
s_cruisingBeforeAcceleration=min(characteristicSection.s_end-drivingCourse[end].s-s_braking, train.l_union)
|
||||
|
||||
if s_cruisingBeforeAcceleration>0.0
|
||||
(characteristicSection, drivingCourse)=addCruisingPhase!(characteristicSection, drivingCourse, s_cruisingBeforeAcceleration, settings, train, allCs, "cruisingBeforeAcceleration")
|
||||
else
|
||||
error("ERROR: cruisingBeforeAcceleration <=0.0 although it has to be >0.0 in CS ",characteristicSection.id)
|
||||
end
|
||||
else # detecting the lower speed limits of former sections
|
||||
csId=characteristicSection.id-1
|
||||
while csId>0 && drivingCourse[end].s-train.l_union<allCs[csId].s_end
|
||||
if allCs[csId].v_limit<characteristicSection.v_limit # TODO: is the position of trains end < movingSection.s_start, v_limit of the first CS is used
|
||||
push!(formerSpeedLimits, [allCs[csId].s_end, allCs[csId].v_limit])
|
||||
for i in 1:length(formerSpeedLimits)-1
|
||||
if formerSpeedLimits[i][2]<=formerSpeedLimits[end][2]
|
||||
pop!(formerSpeedLimits)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
csId=csId-1
|
||||
end
|
||||
end
|
||||
end
|
||||
=#
|
||||
|
||||
# 09/09 old (for steep gradients <= is necessary): if drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
|
||||
if drivingCourse[end].v <= characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
|
||||
# 11/23 old without F_T>F_R: if drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
|
||||
if drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].F_T > drivingCourse[end].F_R
|
||||
accelerationSection=BehaviorSection()
|
||||
accelerationSection.type="acceleration" # type of behavior section
|
||||
accelerationSection.s_start=drivingCourse[end].s # first position (in m)
|
||||
|
@ -517,24 +512,23 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
|
|||
push!(accelerationSection.dataPoints, drivingCourse[end].i)
|
||||
|
||||
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
|
||||
# 08/23 : old for cycle in 1:5 # first cycle with normal step size, second cycle with reduced step size, third cycle with more reduced step size. fourth and fith are needed in case the velocity approaches 0.0 or v_reach
|
||||
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel))
|
||||
while drivingCourse[end].v <= characteristicSection.v_reach && drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
|
||||
# 09/09 old (for steep gradients <= is necessary): while drivingCourse[end].v<characteristicSection.v_reach && drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
|
||||
while drivingCourse[end].v < characteristicSection.v_reach && drivingCourse[end].s+s_braking<characteristicSection.s_end && 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 < characteristicSection.v_reach && drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].v>0.0 && drivingCourse[end].F_T > drivingCourse[end].F_R # as long as s_i + s_braking < s_CSend
|
||||
|
||||
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
|
||||
#11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
|
||||
|
||||
# acceleration (in m/s^2):
|
||||
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
|
||||
if drivingCourse[end].a==0.0
|
||||
error("ERROR: a=0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," F_Rt=",drivingCourse[end].F_Rt," F_Rw=",drivingCourse[end].F_Rw," F_Rp=",drivingCourse[end].F_Rp)
|
||||
end
|
||||
# if drivingCourse[end].a==0.0
|
||||
# error("ERROR: a=0 m/s^2 in the acceleration phase ! with F_T=",drivingCourse[end].F_T," F_Rt=",drivingCourse[end].F_Rt," F_Rw=",drivingCourse[end].F_Rw," F_Rp=",drivingCourse[end].F_Rp)
|
||||
# end
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id))
|
||||
push!(accelerationSection.dataPoints, drivingCourse[end].i)
|
||||
# 12/03: was moved behind considerFormerSpeedLimits: drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
|
||||
|
||||
if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal
|
||||
(characteristicSection, drivingCourse, formerSpeedLimits, accelerationSection, endOfCsReached) = considerFormerSpeedLimits!(characteristicSection, drivingCourse, settings, train, allCs, formerSpeedLimits, accelerationSection)
|
||||
|
@ -542,7 +536,7 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
|
|||
return (characteristicSection, drivingCourse)
|
||||
end
|
||||
end
|
||||
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
|
||||
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel))
|
||||
end #while
|
||||
|
||||
|
@ -567,6 +561,9 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
|
|||
elseif drivingCourse[end].v==characteristicSection.v_reach
|
||||
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_reach and s<s_end in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
|
||||
end
|
||||
|
@ -587,6 +584,11 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
|
|||
elseif drivingCourse[end].s + s_braking > characteristicSection.s_end
|
||||
pop!(drivingCourse)
|
||||
pop!(accelerationSection.dataPoints)
|
||||
|
||||
elseif drivingCourse[end].F_T <= drivingCourse[end].F_R
|
||||
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, accelerationSection.type))
|
||||
|
||||
else
|
||||
|
||||
end
|
||||
|
@ -594,7 +596,7 @@ function addAccelerationPhaseUntilBraking!(characteristicSection::Characteristic
|
|||
end #for
|
||||
|
||||
if length(accelerationSection.dataPoints) > 1 # 09/09 new: it is possible that the acceleration starts at v_reach, accelerates a step, is to high and drops the last point. then there is only one data point which is not a section.
|
||||
# calculation the accumulated acceleration section information
|
||||
# calculate the accumulated acceleration section information
|
||||
accelerationSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
|
||||
accelerationSection.s_end=drivingCourse[end].s # last position (in m)
|
||||
accelerationSection.s_total=accelerationSection.s_end-accelerationSection.s_start # total length (in m)
|
||||
|
@ -615,11 +617,20 @@ end #function addAccelerationPhaseUntilBraking!
|
|||
## This function calculates the data points of the cruising phase.
|
||||
# Therefore it gets its first data point and the characteristic section and returns the characteristic section including the behavior section for cruising if needed.
|
||||
function addCruisingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, s_cruising::AbstractFloat, settings::Settings, train::Train, allCs::Vector{CharacteristicSection}, cruisingType::String)
|
||||
if drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
|
||||
# traction effort and resisting forces (in N)
|
||||
calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"?
|
||||
|
||||
if drivingCourse[end].F_T < drivingCourse[end].F_R
|
||||
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising"))
|
||||
s_cruising=max(0.0, s_cruising-get(characteristicSection.behaviorSections, "diminishing", BehaviorSection()).s_total)
|
||||
end
|
||||
if drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].F_T >= drivingCourse[end].F_R
|
||||
# 11/22 old: if drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
|
||||
cruisingSection=BehaviorSection()
|
||||
cruisingSection.type=cruisingType # type of behavior section
|
||||
cruisingSection.s_start=drivingCourse[end].s # first position (in m)
|
||||
cruisingSection.s_end=min(drivingCourse[end].s+s_cruising, characteristicSection.s_end) # last position (in m)
|
||||
# 11/22: now it is at the end of the BS: cruisingSection.s_end=min(drivingCourse[end].s+s_cruising, characteristicSection.s_end) # last position (in m)
|
||||
cruisingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
|
||||
push!(cruisingSection.dataPoints, drivingCourse[end].i)
|
||||
|
||||
|
@ -627,241 +638,113 @@ function addCruisingPhase!(characteristicSection::CharacteristicSection, driving
|
|||
s_cruising=min(s_cruising, characteristicSection.s_end-cruisingSection.s_start)
|
||||
|
||||
# traction effort and resisting forces (in N)
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising")) # TODO: or give cruisingSection.type instead of "cruising"?
|
||||
calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising") # TODO: or give cruisingSection.type instead of "cruising"?
|
||||
# 11/05 old: drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising")) # TODO: or give cruisingSection.type instead of "cruising"?
|
||||
|
||||
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<cruisingSection.s_start+s_cruising && (drivingCourse[end].F_T < drivingCourse[end].F_R || (settings.massModel=="homogeneous strip" && characteristicSection.id > 1 && drivingCourse[end].s < allCs[characteristicSection.id].s_start + train.l_union)) && drivingCourse[end].v>0.0 #&& drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
|
||||
#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_reach could make problems for energy saving by shortening the acceleration phase
|
||||
# the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_reach OR the mass model homogeneous strip is used and parts of the train are still in former CS
|
||||
if settings.massModel=="homogeneous strip" && characteristicSection.id > 1
|
||||
currentStepSize=settings.stepSize
|
||||
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
while drivingCourse[end].s < characteristicSection.s_start + train.l_union && drivingCourse[end].s<cruisingSection.s_start+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
|
||||
# TODO: whithout allCs should work as well, no? while drivingCourse[end].s < allCs[characteristicSection.id].s_start + train.l_union && drivingCourse[end].s<cruisingSection.s_start+s_cruising && drivingCourse[end].F_T>=drivingCourse[end].F_R #&& drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
|
||||
# the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_reach 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_reach could make problems for energy saving by shortening the acceleration phase
|
||||
|
||||
|
||||
#09/22: neu ist der Teil beim if. alt ist der Teil beim else TODO
|
||||
if drivingCourse[end].F_T >= drivingCourse[end].F_R
|
||||
# acceleration (in m/s^2):
|
||||
drivingCourse[end].a=0.0
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train.l_union/(10.0^cycle), characteristicSection.id)) # TODO welche Schrittweite nehm ich hier?
|
||||
push!(cruisingSection.dataPoints, drivingCourse[end].i)
|
||||
else
|
||||
# acceleration (in m/s^2):
|
||||
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id))
|
||||
push!(cruisingSection.dataPoints, drivingCourse[end].i)
|
||||
end
|
||||
|
||||
|
||||
|
||||
# traction effort and resisting forces (in N)
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising"))
|
||||
end #while
|
||||
|
||||
# check which limit was reached and adjust the currentStepSize for the next cycle
|
||||
if cycle < approximationLevel+1
|
||||
if drivingCourse[end].v<=0.0
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif drivingCourse[end].s>cruisingSection.s_start+s_cruising # TODO also the following? drivingCourse[end].s > allCs[characteristicSection.id].s_start + train.l_union))
|
||||
if settings.stepVariable == "s in m"
|
||||
currentStepSize=cruisingSection.s_start+s_cruising-drivingCourse[end-1].s
|
||||
if settings.stepVariable=="s in m"
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", currentStepSize, characteristicSection.id))
|
||||
else
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", train.l_union/(10.0^cycle), characteristicSection.id)) # TODO which step size should be used?
|
||||
end
|
||||
|
||||
#elseif drivingCourse[end].s>characteristicSection.s_end #TODO: is this necesaary if s_cruising is known? # now s_cruising will be limited to the end of CS at the beginning of this function
|
||||
# if settings.stepVariable == "s in m"
|
||||
# currentStepSize=characteristicSection.s_end-drivingCourse[end-1].s
|
||||
# else
|
||||
# currentStepSize = settings.stepSize / 10.0^cycle
|
||||
# end
|
||||
|
||||
#elseif drivingCourse[end].v>characteristicSection.v_reach # copied from addAccelerationPhase. TODO is it necessary for homogeneous strip? #TODO: now, the train can't get faster in the cruising section. so v_reach can not be exceeded
|
||||
# if settings.stepVariable=="v in m/s"
|
||||
# currentStepSize=characteristicSection.v_reach-drivingCourse[end-1].v
|
||||
# else
|
||||
# currentStepSize = settings.stepSize / 10.0^cycle
|
||||
# end
|
||||
|
||||
elseif drivingCourse[end].s==cruisingSection.s_start+s_cruising # || drivingCourse[end].s==characteristicSection.s_end
|
||||
break
|
||||
|
||||
#elseif drivingCourse[end].v==characteristicSection.v_reach # copied from addAccelerationPhase. TODO 08/24 should it be used otherwise for homogeneous strip?
|
||||
# break
|
||||
|
||||
elseif drivingCourse[end].F_T>=drivingCourse[end].F_R # TODO should not be necessary: && (settings.massModel=="mass point" || characteristicSection.id == 1 || drivingCourse[end].s >= allCs[characteristicSection.id].s_start+train.l_union)
|
||||
drivingCourse[end].a=0.0 # acceleration (in m/s^2)
|
||||
|
||||
# calculate the remaining cruising way
|
||||
s_cruisingRemaining=cruisingSection.s_start+s_cruising-drivingCourse[end].s
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, characteristicSection.id))
|
||||
push!(cruisingSection.dataPoints, drivingCourse[end].i)
|
||||
|
||||
break
|
||||
|
||||
else # TODO copied from addAccelerationPhase -> probably not needed here !?
|
||||
error("ERROR at cruising phase: With the step variable ",settings.stepVariable," the while loop will be left although the if cases don't apply in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
|
||||
end
|
||||
# delete last data point for recalculating the last step with reduced step size
|
||||
pop!(drivingCourse)
|
||||
pop!(cruisingSection.dataPoints)
|
||||
|
||||
else # if the level of approximation is reached
|
||||
if drivingCourse[end].v<=0.0 # copied from addAccelerationPhase TODO: change error message?
|
||||
error("ERROR: The train stops during the cruising phase in CS",characteristicSection.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 F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
|
||||
#elseif drivingCourse[end].v > characteristicSection.v_reach # copied from addAccelerationPhase. TODO is it necessary for homogeneous strip?
|
||||
# pop!(drivingCourse)
|
||||
# pop!(cruisingSection.dataPoints)
|
||||
#elseif drivingCourse[end].s>characteristicSection.s_end
|
||||
# drivingCourse[end].s=characteristicSection.s_end # round s down to s_end
|
||||
|
||||
elseif drivingCourse[end].s>cruisingSection.s_start+s_cruising
|
||||
|
||||
if cruisingSection.type == "cruisingBeforeAcceleration"
|
||||
else
|
||||
pop!(drivingCourse)
|
||||
pop!(cruisingSection.dataPoints)
|
||||
# for testing
|
||||
if drivingCourse[end].F_T > drivingCourse[end].F_R && drivingCourse[end].F_R > 0.0
|
||||
error("In the cruising phase of CS",cruisingSection.id,": F_T=",drivingCourse[end].F_T," != F_R=",drivingCourse[end].F_R)
|
||||
end
|
||||
|
||||
|
||||
elseif drivingCourse[end].F_T>=drivingCourse[end].F_R # TODO should not be necessary: && (settings.massModel=="mass point" || characteristicSection.id == 1 || drivingCourse[end].s >= allCs[characteristicSection.id].s_start + train.l_union)
|
||||
# it is calculated the same as for the other cycles
|
||||
drivingCourse[end].a=0.0 # acceleration (in m/s^2)
|
||||
|
||||
# calculate the remaining cruising way
|
||||
s_cruisingRemaining=cruisingSection.s_start+s_cruising-drivingCourse[end].s
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, characteristicSection.id))
|
||||
push!(cruisingSection.dataPoints, drivingCourse[end].i)
|
||||
break
|
||||
else
|
||||
|
||||
end
|
||||
end
|
||||
end #for
|
||||
|
||||
#= 09/21 old. homogenous strip has to be added
|
||||
if drivingCourse[end].F_T>=drivingCourse[end].F_R
|
||||
drivingCourse[end].a=0.0 # acceleration (in m/s^2)
|
||||
|
||||
push!(drivingCourse, DataPoint())
|
||||
drivingCourse[end].i=drivingCourse[end-1].i+1 # incrementing the number of the data point
|
||||
push!(cruisingSection.dataPoints, drivingCourse[end].i)
|
||||
|
||||
# calculate s, t, v, E
|
||||
drivingCourse[end].Δs=min(s_cruising, characteristicSection.s_end-drivingCourse[end-1].s) # step size (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)
|
||||
# TODO moveAStep can not be used at the moment because of 1/a in the formulars. It has to be changed and then used with stepVariable="s in m", stepSize=min(s_cruising, characteristicSection.s_end-drivingCourse[end-1].s) -> see the three lines above
|
||||
|
||||
drivingCourse[end].s=drivingCourse[end-1].s+drivingCourse[end].Δs # position (in m)
|
||||
drivingCourse[end].t=drivingCourse[end-1].t+drivingCourse[end].Δt # point in time (in s)
|
||||
drivingCourse[end].v=drivingCourse[end-1].v # velocity (in m/s)
|
||||
|
||||
drivingCourse[end].ΔW_T=drivingCourse[end-1].F_T*drivingCourse[end].Δs # mechanical work in this step (in Ws)
|
||||
drivingCourse[end].W_T=drivingCourse[end-1].W_T+drivingCourse[end].ΔW_T # mechanical work (in Ws)
|
||||
drivingCourse[end].ΔE=drivingCourse[end].ΔW_T # energy consumption in this step (in Ws)
|
||||
drivingCourse[end].E=drivingCourse[end-1].E+drivingCourse[end].ΔE # energy consumption (in Ws)
|
||||
|
||||
|
||||
else # the tractive effort is lower than the resisiting forces and the train has use the highest possible effort to try to stay at v_reach
|
||||
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].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end && drivingCourse[end].v>0.0 # TODO: <= v_reach was inserted -> probably needed for homogeneous strip
|
||||
|
||||
# traction effort and resisting forces (in N)
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising"))
|
||||
|
||||
# acceleration (in m/s^2):
|
||||
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
|
||||
if drivingCourse[end].a==0.0
|
||||
# TODO: this part is important for mass strip
|
||||
end
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id))
|
||||
push!(cruisingSection.dataPoints, drivingCourse[end].i)
|
||||
|
||||
#= TODO: the following has probably to be considered with homogeneous strip:
|
||||
if length(formerSpeedLimits) > 0 # If the tail of the train is located in a former characteristic section with lower speed limit check if is is possible to accelerate as normal
|
||||
(characteristicSection, drivingCourse, formerSpeedLimits, cruisingSection, endOfCsReached) = considerFormerSpeedLimits!(characteristicSection, drivingCourse, settings, train, allCs, formerSpeedLimits, accelerationSection)
|
||||
|
||||
if endOfCsReached
|
||||
return (characteristicSection, drivingCourse)
|
||||
end #if
|
||||
end #if
|
||||
=#
|
||||
calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising")
|
||||
end #while
|
||||
|
||||
# check which limit was reached and adjust the currentStepSize for the next cycle
|
||||
if cycle < approximationLevel+1
|
||||
if drivingCourse[end].v<=0.0
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif drivingCourse[end].s>characteristicSection.s_end
|
||||
if drivingCourse[end].s>cruisingSection.s_start+s_cruising # TODO also the following? drivingCourse[end].s > allCs[characteristicSection.id].s_start + train.l_union))
|
||||
if settings.stepVariable == "s in m"
|
||||
currentStepSize=characteristicSection.s_end-drivingCourse[end-1].s
|
||||
currentStepSize=cruisingSection.s_start+s_cruising-drivingCourse[end-1].s
|
||||
else
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
||||
elseif drivingCourse[end].v>characteristicSection.v_reach # copied from addAccelerationPhase. TODO is it necessary for homogeneous strip?
|
||||
if settings.stepVariable=="v in m/s"
|
||||
currentStepSize=characteristicSection.v_reach-drivingCourse[end-1].v
|
||||
else
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
end
|
||||
|
||||
elseif drivingCourse[end].s==characteristicSection.s_end
|
||||
elseif drivingCourse[end].s==cruisingSection.s_start+s_cruising # || drivingCourse[end].s==characteristicSection.s_end
|
||||
break
|
||||
elseif drivingCourse[end].F_T < drivingCourse[end].F_R
|
||||
# if settings.stepVariable == "s in m"
|
||||
# currentStepSize=cruisingSection.s_start+s_cruising-drivingCourse[end-1].s
|
||||
# else
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
# end
|
||||
elseif drivingCourse[end].s >= characteristicSection.s_start + train.l_union
|
||||
# TODO: whithout allCs should work as well, no? elseif drivingCourse[end].s >= allCs[characteristicSection.id].s_start + train.l_union
|
||||
break
|
||||
|
||||
#elseif drivingCourse[end].v==characteristicSection.v_reach # copied from addAccelerationPhase. TODO should it be used otherwise for homogeneous strip?
|
||||
# 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 v<v_reach and s<s_end in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
|
||||
error("ERROR at cruising phase: With the step variable ",settings.stepVariable," the while loop will be left although the if cases don't apply in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
|
||||
end
|
||||
|
||||
# delete last data point for recalculating the last step with reduced step size
|
||||
pop!(drivingCourse)
|
||||
pop!(cruisingSection.dataPoints)
|
||||
|
||||
else # if the level of approximation is reached
|
||||
if drivingCourse[end].v<=0.0 # copied from addAccelerationPhase TODO: change error message?
|
||||
error("ERROR: The train stops during the crusing phase in CS",characteristicSection.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 F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
|
||||
elseif drivingCourse[end].v > characteristicSection.v_reach # copied from addAccelerationPhase. TODO is it necessary for homogeneous strip?
|
||||
pop!(drivingCourse)
|
||||
pop!(cruisingSection.dataPoints)
|
||||
elseif drivingCourse[end].s>characteristicSection.s_end
|
||||
drivingCourse[end].s=characteristicSection.s_end # round s down to s_end
|
||||
if drivingCourse[end].s>cruisingSection.s_start+s_cruising
|
||||
if cruisingSection.type == "cruisingBeforeAcceleration"
|
||||
else
|
||||
pop!(drivingCourse)
|
||||
pop!(cruisingSection.dataPoints)
|
||||
end
|
||||
# 11/21 |->
|
||||
elseif drivingCourse[end].s==cruisingSection.s_start+s_cruising
|
||||
break
|
||||
# 11/21 ->|
|
||||
elseif drivingCourse[end].F_T < drivingCourse[end].F_R
|
||||
|
||||
(characteristicSection, drivingCourse)=addDiminishingPhase!(characteristicSection, drivingCourse, settings, train, allCs)
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "cruising"))
|
||||
|
||||
# s_cruising=max(0.0, s_cruising-get(characteristicSection.behaviorSections, "diminishing", BehaviorSection()).s_total)
|
||||
|
||||
else
|
||||
|
||||
end
|
||||
end
|
||||
end #for
|
||||
end
|
||||
=#
|
||||
end #if
|
||||
|
||||
# TODO oder soll das lieber nach oben in den else des letzten Durchlaufs. Noch mal genauer ansehen, ob hier was doppelt gemoppelt ist
|
||||
# if drivingCourse[end].s<cruisingSection.s_start+s_cruising
|
||||
if drivingCourse[end].s<cruisingSection.s_start+s_cruising && drivingCourse[end].F_T >= drivingCourse[end].F_R
|
||||
drivingCourse[end].a=0.0 # acceleration (in m/s^2)
|
||||
|
||||
# calculate the remaining cruising way
|
||||
s_cruisingRemaining=cruisingSection.s_start+s_cruising-drivingCourse[end].s
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], "s_cruising in m", s_cruisingRemaining, characteristicSection.id))
|
||||
push!(cruisingSection.dataPoints, drivingCourse[end].i)
|
||||
end
|
||||
|
||||
# 08/24 old push!(cruisingSection.dataPoints, drivingCourse[end].i)
|
||||
|
||||
## new 09/06 TODO: if no acceleration is following the cruising it could be called cruising
|
||||
#if cruisingSection.type == "cruisingBeforeAcceleration" && drivingCourse[end].s == characteristicSection.s_end
|
||||
# cruisingSection.type = "cruising"
|
||||
#end
|
||||
|
||||
# calculation the accumulated cruising section information
|
||||
cruisingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
|
||||
cruisingSection.s_total=cruisingSection.s_end-cruisingSection.s_start # total length (in m)
|
||||
# calculate the accumulated cruising section information
|
||||
cruisingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
|
||||
cruisingSection.s_end=drivingCourse[end].s # last position (in m)
|
||||
cruisingSection.s_total=cruisingSection.s_end-cruisingSection.s_start # total length (in m)
|
||||
cruisingSection.t_total=drivingCourse[end].t-drivingCourse[cruisingSection.dataPoints[1]].t # total running time (in s)
|
||||
cruisingSection.E_total=drivingCourse[end].E-drivingCourse[cruisingSection.dataPoints[1]].E # total energy consumption (in Ws)
|
||||
|
||||
|
@ -976,7 +859,7 @@ function addCoastingPhaseUntilBraking!(characteristicSection::CharacteristicSect
|
|||
end
|
||||
end #for
|
||||
|
||||
# calculation the accumulated coasting section information
|
||||
# calculate the accumulated coasting section information
|
||||
coastingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
|
||||
coastingSection.s_end=drivingCourse[end].s # last position (in m)
|
||||
coastingSection.s_total=coastingSection.s_end-coastingSection.s_start # total length (in m)
|
||||
|
@ -1062,9 +945,7 @@ function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection,
|
|||
|
||||
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
|
||||
velocityIsPositive=true
|
||||
# println("Bremsphase")
|
||||
while drivingCourse[end].v>characteristicSection.v_exit && drivingCourse[end].s < characteristicSection.s_end && velocityIsPositive
|
||||
# println(" while-Durchlauf mit v=",drivingCourse[end].v," und v_exit=",characteristicSection.v_exit)
|
||||
# traction effort and resisting forces (in N):
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, brakingSection.type))
|
||||
|
||||
|
@ -1096,7 +977,7 @@ function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection,
|
|||
|
||||
#drivingCourse[end-1].a=round((drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs, digits=approximationLevel) # acceleration (in m/s^2) (rounding because it should not be less than a_braking)
|
||||
drivingCourse[end-1].a=(drivingCourse[end].v^2-drivingCourse[end-1].v^2)/2/drivingCourse[end].Δs # acceleration (in m/s^2)
|
||||
println("a_braking_last=",drivingCourse[end-1].a," m/s^2 und a_braking_standard=" , train.a_braking)
|
||||
# println("a_braking_last=",drivingCourse[end-1].a," m/s^2 und a_braking_standard=" , train.a_braking)
|
||||
|
||||
# if drivingCourse[end-1].a<train.a_braking || drivingCourse[end-1].a>=0.0
|
||||
# println("Warning: a_braking gets to high in CS ",characteristicSection.id, " with a=",drivingCourse[end-1].a ," > ",train.a_braking)
|
||||
|
@ -1114,7 +995,7 @@ function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection,
|
|||
|
||||
end
|
||||
|
||||
# calculation the accumulated coasting section information
|
||||
# calculate the accumulated coasting section information
|
||||
brakingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
|
||||
brakingSection.s_end=drivingCourse[end].s # last position (in m)
|
||||
brakingSection.s_total=brakingSection.s_end-brakingSection.s_start # total length (in m)
|
||||
|
@ -1130,4 +1011,99 @@ function addBrakingPhaseStepwise!(characteristicSection::CharacteristicSection,
|
|||
end #function addBrakingPhaseStepwise!
|
||||
|
||||
|
||||
## This function calculates the data points for diminishing run when using maximum tractive effort and still getting slower
|
||||
function addDiminishingPhase!(characteristicSection::CharacteristicSection, drivingCourse::Vector{DataPoint}, settings::Settings, train::Train, allCs::Vector{CharacteristicSection})
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, "diminishing"))
|
||||
|
||||
if drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].v > 0.0 && drivingCourse[end].s<characteristicSection.s_end
|
||||
#drivingCourse[end].v>0.0 && drivingCourse[end].v<=characteristicSection.v_reach && drivingCourse[end].s<characteristicSection.s_end
|
||||
diminishingSection=BehaviorSection()
|
||||
diminishingSection.type="diminishing" # type of behavior section
|
||||
diminishingSection.s_start=drivingCourse[end].s # first position (in m)
|
||||
diminishingSection.v_entry=drivingCourse[end].v # entry speed (in m/s)
|
||||
push!(diminishingSection.dataPoints, drivingCourse[end].i)
|
||||
|
||||
|
||||
currentStepSize=settings.stepSize # initializing the step size that can be reduced near intersections
|
||||
for cycle in 1:approximationLevel+1 # first cycle with normal step size followed by cycles with reduced step size depending on the level of approximation
|
||||
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel))
|
||||
while drivingCourse[end].F_T <= drivingCourse[end].F_R && drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
|
||||
# 11/22 old without F_T<=F_R while drivingCourse[end].s+s_braking<characteristicSection.s_end && drivingCourse[end].v>0.0 # as long as s_i + s_braking < s_CSend
|
||||
|
||||
#11/22 drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, diminishingSection.type))
|
||||
|
||||
# acceleration (in m/s^2):
|
||||
drivingCourse[end].a=(drivingCourse[end].F_T-drivingCourse[end].F_R)/train.m_union/train.ξ_union
|
||||
# 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," F_Rt=",drivingCourse[end].F_Rt," F_Rw=",drivingCourse[end].F_Rw," F_Rp=",drivingCourse[end].F_Rp)
|
||||
#end
|
||||
|
||||
# create the next data point
|
||||
push!(drivingCourse, moveAStep(drivingCourse[end], settings.stepVariable, currentStepSize, characteristicSection.id))
|
||||
push!(diminishingSection.dataPoints, drivingCourse[end].i)
|
||||
|
||||
s_braking=max(0.0, ceil((characteristicSection.v_exit^2-drivingCourse[end].v^2)/2/train.a_braking, digits=approximationLevel))
|
||||
drivingCourse[end]=DataPoint(calculateForces!(drivingCourse[end], train, settings.massModel, allCs, diminishingSection.type))
|
||||
end #while
|
||||
|
||||
# check which limit was reached and adjust the currentStepSize for the next cycle
|
||||
if cycle < approximationLevel+1
|
||||
if drivingCourse[end].v<=0.0
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif drivingCourse[end].s + s_braking > characteristicSection.s_end
|
||||
currentStepSize = settings.stepSize / 10.0^cycle
|
||||
|
||||
elseif drivingCourse[end].s + s_braking==characteristicSection.s_end
|
||||
# 11/21 old without s_braking: elseif drivingCourse[end].s==characteristicSection.s_end
|
||||
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_braking<s_end && v>0.0 in CS",characteristicSection.id," with s=" ,drivingCourse[end].s," m and v=",drivingCourse[end].v," m/s")
|
||||
end
|
||||
# delete last data point for recalculating the last step with reduced step size
|
||||
pop!(drivingCourse)
|
||||
pop!(diminishingSection.dataPoints)
|
||||
|
||||
else # if the level of approximation is reached
|
||||
if drivingCourse[end].v<=0.0
|
||||
# push!(diminishingSection.dataPoints, drivingCourse[end].i)
|
||||
error("ERROR: The train stops during diminishing run in CS",characteristicSection.id," because the maximum tractive effort is lower than the resistant forces.",
|
||||
" 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 F_Rt=",drivingCourse[end-1].F_Rt," N F_Rw=",drivingCourse[end-1].F_Rw," N F_Rp=",drivingCourse[end-1].F_Rp," N.")
|
||||
|
||||
elseif drivingCourse[end].s + s_braking > characteristicSection.s_end
|
||||
pop!(drivingCourse)
|
||||
pop!(diminishingSection.dataPoints)
|
||||
|
||||
elseif drivingCourse[end].F_T > drivingCourse[end].F_R
|
||||
break
|
||||
|
||||
else
|
||||
|
||||
end
|
||||
end
|
||||
end #for
|
||||
|
||||
if length(diminishingSection.dataPoints) > 1 # TODO: necessary? May it be possible that there is no diminishing because braking has to start
|
||||
# calculate the accumulated diminishing section information
|
||||
diminishingSection.v_exit=drivingCourse[end].v # exit speed (in m/s)
|
||||
diminishingSection.s_end=drivingCourse[end].s # last position (in m)
|
||||
diminishingSection.s_total=diminishingSection.s_end-diminishingSection.s_start # total length (in m)
|
||||
diminishingSection.t_total=drivingCourse[end].t-drivingCourse[diminishingSection.dataPoints[1]].t # total running time (in s)
|
||||
diminishingSection.E_total=drivingCourse[end].E-drivingCourse[diminishingSection.dataPoints[1]].E # total energy consumption (in Ws)
|
||||
characteristicSection.t_total=characteristicSection.t_total+diminishingSection.t_total # total running time (in s)
|
||||
characteristicSection.E_total=characteristicSection.E_total+diminishingSection.E_total # total energy consumption (in Ws)
|
||||
|
||||
merge!(characteristicSection.behaviorSections, Dict("diminishing"=>diminishingSection))
|
||||
end
|
||||
end
|
||||
|
||||
return (characteristicSection, drivingCourse)
|
||||
end #function addDiminishingPhase!
|
||||
|
||||
end #module MovingPhases
|
||||
|
|
|
@ -11,13 +11,15 @@ export simulateMinimumRunningTime!, simulateMinimumEnergyConsumption
|
|||
|
||||
approximationLevel = 6 # TODO: define it in TrainRun and give it to each function?
|
||||
|
||||
# simulate a train run focussing on using the minimum possible running time
|
||||
function simulateMinimumRunningTime!(movingSection::MovingSection, settings::Settings, train::Train)
|
||||
# simulate a train run focussing on using the minimum possible running time
|
||||
# CSs=movingSection.characteristicSections
|
||||
startingPoint=DataPoint()
|
||||
startingPoint.i=1
|
||||
startingPoint.s=movingSection.characteristicSections[1].s_start
|
||||
drivingCourse=[startingPoint] # List of data points
|
||||
|
||||
# for CS in CSs
|
||||
for csId in 1:length(movingSection.characteristicSections)
|
||||
# println("CS",csId)
|
||||
# check if the CS has a cruising section
|
||||
|
@ -33,6 +35,7 @@ function simulateMinimumRunningTime!(movingSection::MovingSection, settings::Set
|
|||
delete!(movingSection.characteristicSections[csId].behaviorSections, "starting")
|
||||
delete!(movingSection.characteristicSections[csId].behaviorSections, "cruisingBeforeAcceleration")
|
||||
delete!(movingSection.characteristicSections[csId].behaviorSections, "acceleration")
|
||||
delete!(movingSection.characteristicSections[csId].behaviorSections, "diminishing") # 11/22 added new
|
||||
delete!(movingSection.characteristicSections[csId].behaviorSections, "cruising")
|
||||
movingSection.characteristicSections[csId].E_total=0.0
|
||||
movingSection.characteristicSections[csId].t_total=0.0
|
||||
|
@ -98,7 +101,7 @@ end #function simulateMinimumRunningTime
|
|||
|
||||
|
||||
function simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime::MovingSection, drivingCourseMinimumRunningTime::Vector{DataPoint}, settings::Settings, train::Train)
|
||||
# simulate a train run focussing on using the minimum possible energy consumption
|
||||
# simulate a train run focussing on using the minimum possible energy consumption
|
||||
# booleans for choosing which methods are used for saving energy
|
||||
doMethod1=true
|
||||
#doMethod1=false
|
||||
|
|
|
@ -112,13 +112,13 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
|
|||
outputArray="outputArrayMinimumEnergyConsumption"
|
||||
date = Dates.now()
|
||||
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
|
||||
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_MinimumEnergyConsumption.csv"
|
||||
csvFilePath=settings.csvDirectory*"\\"*dateString*"_MinimumEnergyConsumption.csv"
|
||||
else
|
||||
operationMode="minimum running time"
|
||||
outputArray="outputArrayMinimumRunningTime"
|
||||
date = Dates.now()
|
||||
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
|
||||
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_MinimumRunningTime.csv"
|
||||
csvFilePath=settings.csvDirectory*"\\"*dateString*"_MinimumRunningTime.csv"
|
||||
end
|
||||
|
||||
# creating information block
|
||||
|
@ -144,7 +144,7 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
|
|||
end # for
|
||||
|
||||
|
||||
# combining the columns in a data frame and saving it as a CSV-file at csvFolderPath
|
||||
# combining the columns in a data frame and saving it as a CSV-file at csvDirectory
|
||||
if settings.detailOfOutput=="reduced"
|
||||
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
|
||||
elseif settings.detailOfOutput=="driving course"
|
||||
|
@ -187,7 +187,7 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
|
|||
push!(allColumns, infoColumns[column])
|
||||
end # for
|
||||
|
||||
#combining the columns in a data frame and saving it as a CSV-file at csvFolderPath
|
||||
#combining the columns in a data frame and saving it as a CSV-file at csvDirectory
|
||||
if settings.detailOfOutput=="reduced"
|
||||
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3])
|
||||
elseif settings.detailOfOutput=="driving course"
|
||||
|
@ -195,7 +195,7 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
|
|||
end
|
||||
date = Dates.now()
|
||||
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
|
||||
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_dataMinimumRunningTime.csv"
|
||||
csvFilePath=settings.csvDirectory*"\\"*dateString*"_dataMinimumRunningTime.csv"
|
||||
CSV.write(csvFilePath, df, header=false)
|
||||
println("The output CSV file has been created for minimum running time at ",csvFilePath)
|
||||
end #if settings.operationModeMinimumRunningTime
|
||||
|
@ -232,10 +232,10 @@ function createOutputCsv(settings::Settings, pathName::String, trainName::String
|
|||
df=DataFrame(c1=allColumns[1], c2=allColumns[2],c3=allColumns[3], c4=allColumns[4], c5=allColumns[5], c6=allColumns[6], c7=allColumns[7], c8=allColumns[8], c9=allColumns[9], c10=allColumns[10], c11=allColumns[11], c12=allColumns[12], c13=allColumns[13], c14=allColumns[14], c15=allColumns[15], c16=allColumns[16], c17=allColumns[17], c18=allColumns[18])
|
||||
end
|
||||
|
||||
# creating a CSV-file at csvFolderPath
|
||||
# creating a CSV-file at csvDirectory
|
||||
date = Dates.now()
|
||||
dateString=Dates.format(date, "yyyy-mm-dd_HH.MM.SS")
|
||||
csvFilePath=settings.csvFolderPath*"\\"*dateString*"_dataMinimumEnergyConsumption.csv"
|
||||
csvFilePath=settings.csvDirectory*"\\"*dateString*"_dataMinimumEnergyConsumption.csv"
|
||||
CSV.write(csvFilePath, df, header=false)
|
||||
println("The output CSV file has been created for minimum energy consumption at ",csvFilePath)
|
||||
end # if settings.operationModeMinimumEnergyConsumption
|
||||
|
@ -255,7 +255,7 @@ end #function printImportantValues
|
|||
|
||||
function printSectionInformation(movingSection::MovingSection)
|
||||
println("MS mit s_total=", movingSection.s_total," mit t_total=", movingSection.t_total)
|
||||
allBs=["starting", "cruisingBeforeAcceleration","acceleration", "cruising", "coasting","cruisingAfterCoasting", "braking"]
|
||||
allBs=["starting", "cruisingBeforeAcceleration","acceleration", "cruising", "diminishing", "coasting","cruisingAfterCoasting", "braking"]
|
||||
for csId in 1:length(movingSection.characteristicSections)
|
||||
println("CS ",csId," mit s_total=", movingSection.characteristicSections[csId].s_total," mit t_total=", movingSection.characteristicSections[csId].t_total)
|
||||
for bs in 1: length(allBs)
|
||||
|
|
|
@ -19,9 +19,9 @@ export calculateDrivingDynamics
|
|||
# TODO: define it here and give it to each function? (MovingPhases, EnergySaving)
|
||||
|
||||
"""
|
||||
calculateDrivingDynamics(trainFilePath::String, pathFilePath::String, settingsFilePath::String)
|
||||
calculateDrivingDynamics(trainDirectory::String, pathDirectory::String, settingsDirectory::String)
|
||||
|
||||
Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainFilePath`, `pathFilePath`, `settingsFilePath`.
|
||||
Calculate the driving dynamics of a train run on a path with special settings with information from the corresponding YAML files with the file paths `trainDirectory`, `pathDirectory`, `settingsDirectory`.
|
||||
|
||||
# Examples
|
||||
```julia-repl
|
||||
|
@ -29,11 +29,11 @@ julia> calculateDrivingDynamics(C:\\folder\\train.yaml, C:\\folder\\path.yaml, C
|
|||
todo !!!
|
||||
```
|
||||
"""
|
||||
function calculateDrivingDynamics(trainFilePath::String, pathFilePath::String, settingsFilePath::String)
|
||||
function calculateDrivingDynamics(trainDirectory::String, pathDirectory::String, settingsDirectory::String)
|
||||
print("\n\n\n")
|
||||
|
||||
# input
|
||||
(train, path, settings)=readInput(trainFilePath, pathFilePath, settingsFilePath)
|
||||
(train, path, settings)=readInput(trainDirectory, pathDirectory, settingsDirectory)
|
||||
println("The input has been saved.")
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ function calculateDrivingDynamics(trainFilePath::String, pathFilePath::String, s
|
|||
if settings.operationModeMinimumEnergyConsumption==true
|
||||
(movingSectionMinimumEnergyConsumption, drivingCourseMinimumEnergyConsumption)=simulateMinimumEnergyConsumption(movingSectionMinimumRunningTime, drivingCourseMinimumRunningTime, settings, train)
|
||||
# printSectionInformation(movingSectionMinimumEnergyConsumption)
|
||||
println("The driving course for lowest the energy consumption has been calculated.")
|
||||
println("The driving course for the lowest energy consumption has been calculated.")
|
||||
end #if
|
||||
|
||||
#output
|
||||
|
|
25
src/types.jl
25
src/types.jl
|
@ -11,7 +11,7 @@ mutable struct Settings
|
|||
operationModeMinimumEnergyConsumption::Bool # operation mode "minimum energy consumption"
|
||||
# output:
|
||||
typeOfOutput::String # output as "julia dictionary" or as "CSV"
|
||||
csvFolderPath::String # path of the folder in which the CSV fiiles willl be saved
|
||||
csvDirectory::String # directory in which the CSV files will be saved
|
||||
detailOfOutput::String # detail of output "reduced" or "everything"
|
||||
end # mutable struct Settings
|
||||
Settings()=Settings("", "", 0.0, false, false, "", "", "")
|
||||
|
@ -26,8 +26,10 @@ mutable struct Train
|
|||
v_limit::AbstractFloat # trains speed limit (in m/s)
|
||||
a_braking::AbstractFloat # braking acceleration (in m/s^2)
|
||||
m_union::AbstractFloat # total mass (in kg)
|
||||
# m_train
|
||||
ξ_union::AbstractFloat # rotation mass factor of the whole train union (without unit)
|
||||
# if not available use ξ_t and ξ_w
|
||||
# ξ_train
|
||||
|
||||
# traction unit
|
||||
m_t::AbstractFloat # mass of the traction unit (in kg)
|
||||
|
@ -35,7 +37,7 @@ mutable struct Train
|
|||
m_tc::AbstractFloat # mass on the traction units carrying axles (in kg)
|
||||
ξ_t::AbstractFloat # rotation mass factor of the traction unit (without unit)
|
||||
# in case ξ_union is not available
|
||||
tractiveEffortArray # list values for tractive effort (in [m/s , N])
|
||||
tractiveEffortVelocityPairs # list of velocities and their corresponding tractive effort (in [m/s , N])
|
||||
|
||||
f_Rtd0::AbstractFloat # coefficient for basic resistance due to the traction units driving axles (in ‰)
|
||||
f_Rtc0::AbstractFloat # coefficient for basic resistance due to the traction units carring axles (in ‰)
|
||||
|
@ -89,15 +91,21 @@ mutable struct DataPoint
|
|||
Δv::AbstractFloat # step size (in m/s)
|
||||
a::AbstractFloat # acceleration (in m/s^2)
|
||||
W_T::AbstractFloat # mechanical work (in Ws)
|
||||
# W
|
||||
ΔW_T::AbstractFloat # mechanical work in this step (in Ws)
|
||||
# ΔW
|
||||
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)
|
||||
F_Rp::AbstractFloat # line resistanc (in N)
|
||||
F_Runion::AbstractFloat # vehicle resistance (in N)
|
||||
F_Rp::AbstractFloat # path resistance (in N)
|
||||
# R_path
|
||||
F_Runion::AbstractFloat # train resistance (in N)
|
||||
# R_train
|
||||
F_Rt::AbstractFloat # traction unit resistance (in N)
|
||||
# R_traction
|
||||
F_Rw::AbstractFloat # set of wagons resistance (in N)
|
||||
# R_consist
|
||||
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_T, original.ΔW_T, original.E, original.ΔE, original.F_T, original.F_R, original.F_Rp, original.F_Runion, original.F_Rt, original.F_Rw)
|
||||
|
@ -109,6 +117,7 @@ DataPoint(original::DataPoint)=DataPoint(original.i, original.s, original.Δs, o
|
|||
## smallest section of the path is the behavior section. It relates to the containing data points via their identifier.
|
||||
mutable struct BehaviorSection
|
||||
type::String # type of behavior section: "starting", "cruisingBeforeAcceleration", "acceleration", "cruising", "coasting", "cruisingAfterCoasting" or "braking"
|
||||
# enum-type. breakFree, clearing, diminishing, standStill, "acceleration", "cruising", "coasting", "braking"
|
||||
s_total::AbstractFloat # total length (in m)
|
||||
s_start::AbstractFloat # first position (in m)
|
||||
s_end::AbstractFloat # last position (in m)
|
||||
|
@ -131,15 +140,21 @@ end
|
|||
mutable struct CharacteristicSection
|
||||
id::Integer # identifier
|
||||
s_total::AbstractFloat # total length (in m)
|
||||
# length::AbstractFloat # total length (in m)
|
||||
s_start::AbstractFloat # first position (in m)
|
||||
# s_entry
|
||||
s_end::AbstractFloat # last position (in m)
|
||||
# s_exit
|
||||
t_total::AbstractFloat # total running time (in s)
|
||||
# t
|
||||
E_total::AbstractFloat # total energy consumption (in Ws)
|
||||
# E
|
||||
v_limit::AbstractFloat # speed limit (in m/s)
|
||||
v_reach::AbstractFloat # maximum reachable speed (in m/s)
|
||||
# v_target
|
||||
v_entry::AbstractFloat # maximum entry speed (in m/s)
|
||||
v_exit::AbstractFloat # maximum exit speed (in m/s)
|
||||
f_Rp::AbstractFloat # spedific line resistance (in ‰)
|
||||
f_Rp::AbstractFloat # spedific path resistance (in ‰)
|
||||
behaviorSections::AbstractDict{String, BehaviorSection} # list of containing behavior sections
|
||||
end # mutable struct CharacteristicSection
|
||||
CharacteristicSection()=CharacteristicSection(0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Dict{String, BehaviorSection}())
|
||||
|
|
Loading…
Reference in New Issue