Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

L to H and H to L transition in dynamic plasma actor with ActorPedestal #807

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
13 changes: 8 additions & 5 deletions src/actors/pedestal/EPED_actor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Base.@kwdef mutable struct FUSEparameters__ActorEPED{T<:Real} <: ParametersActor
T_ratio_pedestal::Entry{T} =
Entry{T}("-", "Ratio of ion to electron temperatures (or rho at which to sample for that ratio, if negative; or rho_nml-(rho_ped-rho_nml) if 0.0)"; default=1.0)
ped_factor::Entry{T} = Entry{T}("-", "Pedestal height multiplier (width scaled by sqrt of this factor)"; default=1.0)
density_factor::Entry{T} = Entry{T}("-", "Scale input density by given factor"; default=1.0)
only_powerlaw::Entry{Bool} = Entry{Bool}("-", "EPED-NN uses power-law pedestal fit (without NN correction)"; default=false)
#== data flow parameters ==#
ip_from::Switch{Symbol} = switch_get_from(:ip)
Expand Down Expand Up @@ -62,7 +63,7 @@ function _step(actor::ActorEPED{D,P}) where {D<:Real,P<:Real}
par = actor.par

cp1d = dd.core_profiles.profiles_1d[]
sol = run_EPED(dd, actor.inputs, actor.epedmod; par.ne_ped_from, par.zeff_ped_from, par.βn_from, par.ip_from, par.only_powerlaw, par.warn_nn_train_bounds)
sol = run_EPED(dd, actor.inputs, actor.epedmod; par.ne_ped_from, par.zeff_ped_from, par.βn_from, par.ip_from, par.only_powerlaw, par.warn_nn_train_bounds, par.density_factor)

if sol.pressure.GH.H < 1.1 * cp1d.pressure_thermal[end] / 1e6
actor.pped = 1.1 * cp1d.pressure_thermal[end] / 1E6
Expand Down Expand Up @@ -125,11 +126,12 @@ function run_EPED(
βn_from::Symbol,
ip_from::Symbol,
only_powerlaw::Bool,
warn_nn_train_bounds::Bool)
warn_nn_train_bounds::Bool,
density_factor::Float64)

inputs = EPEDNN.InputEPED()
epedmod = EPEDNN.loadmodelonce("EPED1NNmodel.bson")
return run_EPED(dd, inputs, epedmod; ne_ped_from, zeff_ped_from, βn_from, ip_from, only_powerlaw, warn_nn_train_bounds)
return run_EPED(dd, inputs, epedmod; ne_ped_from, zeff_ped_from, βn_from, ip_from, only_powerlaw, warn_nn_train_bounds, density_factor)
end

"""
Expand All @@ -155,7 +157,8 @@ function run_EPED(
βn_from::Symbol,
ip_from::Symbol,
only_powerlaw::Bool,
warn_nn_train_bounds::Bool)
warn_nn_train_bounds::Bool,
density_factor::Float64)

cp1d = dd.core_profiles.profiles_1d[]
eqt = dd.equilibrium.time_slice[]
Expand All @@ -165,7 +168,7 @@ function run_EPED(
@warn "EPED-NN is only trained on m_effective = 2.0 & 2.5 , m_effective = $m"
end

neped = IMAS.get_from(dd, Val{:ne_ped}, ne_ped_from, nothing)
neped = IMAS.get_from(dd, Val{:ne_ped}, ne_ped_from, nothing) * density_factor
zeffped = IMAS.get_from(dd, Val{:zeff_ped}, zeff_ped_from, nothing)
βn = IMAS.get_from(dd, Val{:βn}, βn_from)
ip = IMAS.get_from(dd, Val{:ip}, ip_from)
Expand Down
5 changes: 3 additions & 2 deletions src/actors/pedestal/WPED_actor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#== actor parameters ==#
ped_to_core_fraction::Entry{T} = Entry{T}("-", "Ratio of edge (@rho=0.9) to core stored energy [0.05 for L-mode, 0.3 for neg-T plasmas, missing keeps original ratio]")
rho_ped::Entry{T} = Entry{T}("-", "Defines rho at which the edge region starts")
density_factor::Entry{T} = Entry{T}("-", "Scale input density by given factor"; default=1.0)
#== data flow parameters ==#
ne_ped_from::Switch{Symbol} = switch_get_from(:ne_ped)
zeff_ped_from::Switch{Symbol} = switch_get_from(:zeff_ped)
Expand Down Expand Up @@ -55,10 +56,10 @@
par = actor.par

cp1d = dd.core_profiles.profiles_1d[]

summary_ped = dd.summary.local.pedestal

@ddtime summary_ped.position.rho_tor_norm = par.rho_ped
@ddtime summary_ped.n_e.value = IMAS.get_from(dd, Val{:ne_ped}, par.ne_ped_from, par.rho_ped)
@ddtime summary_ped.n_e.value = IMAS.get_from(dd, Val{:ne_ped}, par.ne_ped_from, par.rho_ped) * par.density_factor

Check warning on line 62 in src/actors/pedestal/WPED_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/WPED_actor.jl#L62

Added line #L62 was not covered by tests
@ddtime summary_ped.zeff.value = IMAS.get_from(dd, Val{:zeff_ped}, par.zeff_ped_from, par.rho_ped)
IMAS.blend_core_edge(:L_mode, cp1d, summary_ped, NaN, par.rho_ped; what=:densities)

Expand Down
123 changes: 104 additions & 19 deletions src/actors/pedestal/pedestal_actor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@
rho_nml::Entry{T} = Entry{T}("-", "Defines rho at which the no man's land region starts")
rho_ped::Entry{T} = Entry{T}("-", "Defines rho at which the pedestal region starts") # rho_nml < rho_ped
density_match::Switch{Symbol} = Switch{Symbol}([:ne_line, :ne_ped], "-", "Matching density based on ne_ped or line averaged density"; default=:ne_ped)
model::Switch{Symbol} = Switch{Symbol}([:EPED, :WPED, :auto, :none], "-", "Pedestal model to use"; default=:EPED)
model::Switch{Symbol} = Switch{Symbol}([:EPED, :WPED, :dynamic, :none], "-", "Pedestal model to use"; default=:EPED)
#== data flow parameters ==#
ip_from::Switch{Symbol} = switch_get_from(:ip)
βn_from::Switch{Symbol} = switch_get_from(:βn)
ne_from::Switch{Symbol} = switch_get_from(:ne_ped)
zeff_ped_from::Switch{Symbol} = switch_get_from(:zeff_ped)

#== L to H and H to L transition model ==#
tau_t::Entry{T} = Entry{T}("[s]", "pedestal temperature LH transition tanh evolution time (95% of full transition)")
tau_n::Entry{T} = Entry{T}("[s]", "pedestal density LH transition tanh evolution time (95% of full transition)")
density_ratio_L_over_H::Entry{T} = Entry{T}("[-]", "n_Lmode / n_Hmode")
#== display and debugging parameters ==#
do_plot::Entry{Bool} = act_common_parameters(; do_plot=false)
end
Expand All @@ -29,6 +34,10 @@
none_actor::ActorNoOperation{D,P}
eped_actor::ActorEPED{D,P}
wped_actor::ActorWPED{D,P}
state::Vector{Symbol}
t_lh::Float64
t_hl::Float64
cp1d_transition::IMAS.core_profiles__profiles_1d{D}
end

"""
Expand All @@ -49,7 +58,7 @@
eped_actor = ActorEPED(dd, act.ActorEPED; ne_ped_from=par.ne_from, par.zeff_ped_from, par.βn_from, par.ip_from, par.rho_nml, par.rho_ped)
wped_actor = ActorWPED(dd, act.ActorWPED; ne_ped_from=par.ne_from, par.zeff_ped_from, par.rho_ped, par.do_plot)
none_actor = ActorNoOperation(dd, act.ActorNoOperation)
return ActorPedestal(dd, par, act, none_actor, none_actor, eped_actor, wped_actor)
return ActorPedestal(dd, par, act, none_actor, none_actor, eped_actor, wped_actor, Symbol[], -Inf, -Inf, IMAS.core_profiles__profiles_1d())
end

"""
Expand All @@ -69,25 +78,106 @@
actor.ped_actor = actor.none_actor
elseif par.model == :EPED
actor.ped_actor = actor.eped_actor
mode = :H_mode
run_selected_pedstal_model(actor)
elseif par.model == :WPED
actor.ped_actor = actor.wped_actor
mode = :L_mode
elseif par.model == :auto
if IMAS.satisfies_h_mode_conditions(dd)
actor.ped_actor = actor.eped_actor
mode = :H_mode
run_selected_pedstal_model(actor)
elseif par.model == :dynamic
@assert par.ne_from == :pulse_schedule "Dyanmic requires ne_from pulse schedule"

Check warning on line 86 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L84-L86

Added lines #L84 - L86 were not covered by tests

if IMAS.satisfies_h_mode_conditions(dd; threshold_multiple=2.0)
push!(actor.state,:H_mode)
elseif !IMAS.satisfies_h_mode_conditions(dd; threshold_multiple=1.0)
push!(actor.state,:L_mode)

Check warning on line 91 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L88-L91

Added lines #L88 - L91 were not covered by tests
else
push!(actor.state,actor.state[end])

Check warning on line 93 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L93

Added line #L93 was not covered by tests
end

if length(actor.state) >= 2 && actor.state[end-1:end] == [:L_mode, :H_mode]

Check warning on line 96 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L96

Added line #L96 was not covered by tests
# L to H
actor.t_lh = dd.global_time
elseif length(actor.state) >= 2 && actor.state[end-1:end] == [:H_mode, :L_mode]

Check warning on line 99 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L98-L99

Added lines #L98 - L99 were not covered by tests
# H to L
actor.t_hl = dd.global_time

Check warning on line 101 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L101

Added line #L101 was not covered by tests

# The L to H and H to L model are triggered when hmode conditions are triggered so therefore pulse_schedule needs to be updated based on this model
if par.density_match == :ne_ped
@ddtime(dd.pulse_schedule.density_control.n_e_pedestal.reference = @ddtime(dd.summary.local.pedestal.n_e.value))
elseif par.density_match == :ne_line
@ddtime(dd.pulse_schedule.density_control.n_e_line.reference = IMAS.geometric_midplane_line_averaged_density(eqt, cp1d))

Check warning on line 107 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L104-L107

Added lines #L104 - L107 were not covered by tests
end
end

if actor.state[end] == :L_mode
α_t = LH_tanh_response(par.tau_t, dd.global_time,actor.t_hl;time_steps=100)
α_n = LH_tanh_response(par.tau_n, dd.global_time,actor.t_hl;time_steps=100)

Check warning on line 113 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L111-L113

Added lines #L111 - L113 were not covered by tests

actor.ped_actor = actor.wped_actor
mode = :L_mode
if eqt.boundary.triangularity < 0.0
actor.wped_actor.par.ped_to_core_fraction = 0.3
else
actor.wped_actor.par.ped_to_core_fraction = 0.05
actor.ped_actor.par.density_factor = 1. - α_n * (1 - par.density_ratio_L_over_H)

Check warning on line 116 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L116

Added line #L116 was not covered by tests

run_selected_pedstal_model(actor)

Check warning on line 118 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L118

Added line #L118 was not covered by tests

Te_ongoing = (1 .- α_t) .* actor.cp1d_transition.electrons.temperature .+ α_t .* dd.core_profiles.profiles_1d[].electrons.temperature
Ti_ongoing = (1 .- α_t) .* actor.cp1d_transition.ion[1].temperature .+ α_t .* dd.core_profiles.profiles_1d[].ion[1].temperature

Check warning on line 121 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L120-L121

Added lines #L120 - L121 were not covered by tests

cp1d.electrons.temperature = Te_ongoing
for ion in cp1d.ion
ion.temperature = Ti_ongoing
end

Check warning on line 126 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L123-L126

Added lines #L123 - L126 were not covered by tests
else
# H mode
α_t = LH_tanh_response(par.tau_t,dd.global_time,actor.t_lh;time_steps=100)
α_n = LH_tanh_response(par.tau_n,dd.global_time, actor.t_lh;time_steps=100)
actor.ped_actor = actor.eped_actor

Check warning on line 131 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L129-L131

Added lines #L129 - L131 were not covered by tests

actor.ped_actor.par.density_factor = 1 + (1 / par.density_ratio_L_over_H - 1) * α_n
run_selected_pedstal_model(actor)

Check warning on line 134 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L133-L134

Added lines #L133 - L134 were not covered by tests

Te_ongoing = (1 .- α_t) .* actor.cp1d_transition.electrons.temperature .+ α_t .* dd.core_profiles.profiles_1d[].electrons.temperature
Ti_ongoing = (1 .- α_t) .* actor.cp1d_transition.ion[1].temperature .+ α_t .* dd.core_profiles.profiles_1d[].ion[1].temperature

Check warning on line 137 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L136-L137

Added lines #L136 - L137 were not covered by tests

cp1d.electrons.temperature = Te_ongoing
for ion in cp1d.ion
ion.temperature = Ti_ongoing

Check warning on line 141 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L139-L141

Added lines #L139 - L141 were not covered by tests
end
end
end

return actor
end

"""
LH_tanh_response(τ::Float64,t_now::Float64, t_LH::Float64; time_steps::Int=100)

Returns a parameter that follows a tanh like response where τ represent the value of 0.95 @ τ time starting from t_LH
"""
function LH_tanh_response(τ::Float64,t_now::Float64, t_LH::Float64; time_steps::Int=100)
if isinf(t_LH)
return 0.0

Check warning on line 156 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L154-L156

Added lines #L154 - L156 were not covered by tests
end
t, α = LH_tanh_response(τ, t_LH; time_steps)
return maximum([minimum([IMAS.interp1d(t,α).(t_now),1.0]),0.0])

Check warning on line 159 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L158-L159

Added lines #L158 - L159 were not covered by tests
end

function LH_tanh_response(τ::Float64,t_LH::Float64; time_steps::Int=100)
t = (0:τ/time_steps:τ) .+ t_LH
α = tanh.((2pi.*(t .- t_LH .- τ / 4.0)) ./ τ)
α = ((α .- α[1]) ./ (α[end]-α[1]))
return t, α

Check warning on line 166 in src/actors/pedestal/pedestal_actor.jl

View check run for this annotation

Codecov / codecov/patch

src/actors/pedestal/pedestal_actor.jl#L162-L166

Added lines #L162 - L166 were not covered by tests
end

"""
run_selected_pedstal_model(actor::ActorPedestal)

Runs selected pedestal model this prevents code duplication for using different par.model settings
"""
function run_selected_pedstal_model(actor::ActorPedestal)
dd = actor.dd
par = actor.par

eq = dd.equilibrium
eqt = eq.time_slice[]
cp1d = dd.core_profiles.profiles_1d[]
if par.density_match == :ne_ped
finalize(step(actor.ped_actor))

Expand Down Expand Up @@ -125,10 +215,5 @@
# turn pressures back into expressions
IMAS.empty!(cp1d, :pressure_thermal)
IMAS.empty!(cp1d, :pressure)

else
error("act.ActorPedestal.density_match can be either one of [:ne_ped, :ne_line]")
end

return actor
end
end
6 changes: 5 additions & 1 deletion src/optimization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@

# create working directory
original_dir = pwd()
savedir = abspath(joinpath(save_folder, "$(generation)__$(Dates.now())__$(getpid())"))
if Sys.iswindows()
savedir = abspath(joinpath(save_folder, "$(generation)__$(join(split(string(Dates.now()),":"),"-"))__$(getpid())"))

Check warning on line 36 in src/optimization.jl

View check run for this annotation

Codecov / codecov/patch

src/optimization.jl#L35-L36

Added lines #L35 - L36 were not covered by tests
else
savedir = abspath(joinpath(save_folder, "$(generation)__$(Dates.now())__$(getpid())"))

Check warning on line 38 in src/optimization.jl

View check run for this annotation

Codecov / codecov/patch

src/optimization.jl#L38

Added line #L38 was not covered by tests
end
mkdir(savedir)
cd(savedir)

Expand Down
11 changes: 6 additions & 5 deletions src/utils_begin.jl
Original file line number Diff line number Diff line change
Expand Up @@ -324,19 +324,20 @@
function localhost_memory()
if Sys.isapple()
cmd = `sysctl hw.memsize` # for OSX
mem_size = parse(Int, match(r"\d+", readchomp(cmd)).match) / 1024^3
mem_size = parse(Int, match(r"\d+", readchomp(cmd)).match) / 1024^3 # GiB

Check warning on line 327 in src/utils_begin.jl

View check run for this annotation

Codecov / codecov/patch

src/utils_begin.jl#L327

Added line #L327 was not covered by tests
elseif Sys.isunix()
# General Unix command (including macOS and Linux)
cmd = `free -b` # get memory in bytes
mem_size = parse(Int, match(r"\d+", readchomp(cmd)).match) / 1024^3
mem_size = parse(Int, match(r"\d+", readchomp(cmd)).match) / 1024^3 # GiB

Check warning on line 331 in src/utils_begin.jl

View check run for this annotation

Codecov / codecov/patch

src/utils_begin.jl#L331

Added line #L331 was not covered by tests
elseif Sys.iswindows()
# Windows command
cmd = `wmic ComputerSystem get TotalPhysicalMemory`
mem_size = parse(Int, match(r"\d+", readchomp(cmd)).match) / 1024^3
cmd = `powershell -Command "Get-CimInstance Win32_ComputerSystem | Select-Object -ExpandProperty TotalPhysicalMemory"`
mem_bytes = parse(Int, readchomp(cmd))
mem_size = mem_bytes / 1024^3 # GiB

Check warning on line 336 in src/utils_begin.jl

View check run for this annotation

Codecov / codecov/patch

src/utils_begin.jl#L334-L336

Added lines #L334 - L336 were not covered by tests
elseif Sys.islinux()
# Linux-specific command
cmd = `grep MemTotal /proc/meminfo`
mem_size = parse(Int, match(r"\d+", readchomp(cmd)).match) / 1024^2 # Linux reports in KB
mem_size = parse(Int, match(r"\d+", readchomp(cmd)).match) / 1024^2 # GiB

Check warning on line 340 in src/utils_begin.jl

View check run for this annotation

Codecov / codecov/patch

src/utils_begin.jl#L340

Added line #L340 was not covered by tests
else
error("couldn't determine the mem_size")
end
Expand Down
17 changes: 13 additions & 4 deletions src/utils_end.jl
Original file line number Diff line number Diff line change
Expand Up @@ -808,19 +808,28 @@
[], []
end
end

"""
get_julia_process_memory_usage()

Returns memory used by current julia process
"""
function get_julia_process_memory_usage()
pid = getpid()
mem_info = read(`ps -p $pid -o rss=`, String)
mem_usage_kb = parse(Int, strip(mem_info))
if Sys.iswindows()
pid = getpid()

Check warning on line 818 in src/utils_end.jl

View check run for this annotation

Codecov / codecov/patch

src/utils_end.jl#L817-L818

Added lines #L817 - L818 were not covered by tests
# Use PowerShell to get the current process's WorkingSet (memory in bytes)
cmd = `powershell -Command "(Get-Process -Id $pid).WorkingSet64"`
mem_bytes_str = readchomp(cmd)
mem_bytes = parse(Int, mem_bytes_str)
return mem_bytes

Check warning on line 823 in src/utils_end.jl

View check run for this annotation

Codecov / codecov/patch

src/utils_end.jl#L820-L823

Added lines #L820 - L823 were not covered by tests
else
pid = getpid()
mem_info = read(`ps -p $pid -o rss=`, String)
mem_usage_kb = parse(Int, strip(mem_info))

Check warning on line 827 in src/utils_end.jl

View check run for this annotation

Codecov / codecov/patch

src/utils_end.jl#L825-L827

Added lines #L825 - L827 were not covered by tests
end
return mem_usage_kb * 1024
end


"""
save(memtrace::MemTrace, filename::String="memtrace.txt")

Expand Down