Skip to content

Commit 527bdde

Browse files
Merge pull request #980 from ProjectTorreyPines/study_TGLFdb_update
edits for study_TGLFdb
2 parents 1791a2c + 8aaaa28 commit 527bdde

File tree

2 files changed

+133
-70
lines changed

2 files changed

+133
-70
lines changed

src/actors/transport/flux_matcher_actor.jl

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,32 @@ function check_evolve_densities(cp1d::IMAS.core_profiles__profiles_1d, evolve_de
10261026
end
10271027
end
10281028

1029+
"""
1030+
evolve_densities_dict_creation(flux_match_species::Vector, fixed_species::Vector, match_ne_scale_species::Vector, replay_species::Vector; quasi_neutrality_specie::Union{Symbol,Bool}=false)
1031+
1032+
Create the density_evolution dict based on input vectors: flux_match_species, fixed_species, match_ne_scale_species, replay_species, quasi_neutrality_specie
1033+
"""
1034+
function evolve_densities_dict_creation(
1035+
flux_match_species::Vector;
1036+
fixed_species::Vector{Symbol}=Symbol[],
1037+
match_ne_scale_species::Vector{Symbol}=Symbol[],
1038+
replay_species::Vector{Symbol}=Symbol[],
1039+
quasi_neutrality_specie::Union{Symbol,Bool}=false)
1040+
1041+
parse_list = vcat(
1042+
[[sym, :flux_match] for sym in flux_match_species],
1043+
[[sym, :match_ne_scale] for sym in match_ne_scale_species],
1044+
[[sym, :fixed] for sym in fixed_species],
1045+
[[sym, :replay] for sym in replay_species]
1046+
)
1047+
if typeof(quasi_neutrality_specie) <: Symbol
1048+
parse_list = vcat(parse_list, [[quasi_neutrality_specie, :quasi_neutrality]])
1049+
end
1050+
1051+
return Dict(sym => evolve for (sym, evolve) in parse_list)
1052+
end
1053+
1054+
10291055
"""
10301056
setup_density_evolution_electron_flux_match_rest_ne_scale(cp1d::IMAS.core_profiles__profiles_1d)
10311057
@@ -1092,31 +1118,6 @@ function setup_density_evolution_replay(cp1d::IMAS.core_profiles__profiles_1d)
10921118
return evolve_densities_dict_creation(Symbol[]; replay_species=all_species, quasi_neutrality_specie=false)
10931119
end
10941120

1095-
"""
1096-
evolve_densities_dict_creation(flux_match_species::Vector, fixed_species::Vector, match_ne_scale_species::Vector, replay_species::Vector; quasi_neutrality_specie::Union{Symbol,Bool}=false)
1097-
1098-
Create the density_evolution dict based on input vectors: flux_match_species, fixed_species, match_ne_scale_species, replay_species, quasi_neutrality_specie
1099-
"""
1100-
function evolve_densities_dict_creation(
1101-
flux_match_species::Vector;
1102-
fixed_species::Vector{Symbol}=Symbol[],
1103-
match_ne_scale_species::Vector{Symbol}=Symbol[],
1104-
replay_species::Vector{Symbol}=Symbol[],
1105-
quasi_neutrality_specie::Union{Symbol,Bool}=false)
1106-
1107-
parse_list = vcat(
1108-
[[sym, :flux_match] for sym in flux_match_species],
1109-
[[sym, :match_ne_scale] for sym in match_ne_scale_species],
1110-
[[sym, :fixed] for sym in fixed_species],
1111-
[[sym, :replay] for sym in replay_species]
1112-
)
1113-
if typeof(quasi_neutrality_specie) <: Symbol
1114-
parse_list = vcat(parse_list, [[quasi_neutrality_specie, :quasi_neutrality]])
1115-
end
1116-
1117-
return Dict(sym => evolve for (sym, evolve) in parse_list)
1118-
end
1119-
11201121
"""
11211122
check_output_fluxes(output::Vector{<:Real}, what::String)
11221123

src/studies/TGLF_database.jl

Lines changed: 107 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,20 @@ import GACODE
99
"""
1010
study_parameters(::Val{:TGLFdb})
1111
"""
12-
function study_parameters(::Val{:TGLFdb})
13-
return FUSEparameters__ParametersStudyTGLFdb{Real}()
12+
function study_parameters(::Val{:TGLFdb})::Tuple{FUSEparameters__ParametersStudyTGLFdb,ParametersAllActors}
13+
sty = FUSEparameters__ParametersStudyTGLFdb{Real}()
14+
act = ParametersActors()
15+
16+
# Change act for the default TGLFdb run
17+
act.ActorCoreTransport.model = :FluxMatcher
18+
act.ActorFluxMatcher.evolve_pedestal = false
19+
act.ActorTGLF.warn_nn_train_bounds = false
20+
21+
# finalize
22+
set_new_base!(sty)
23+
set_new_base!(act)
24+
25+
return sty, act
1426
end
1527

1628
Base.@kwdef mutable struct FUSEparameters__ParametersStudyTGLFdb{T<:Real} <: ParametersStudy{T}
@@ -40,7 +52,7 @@ function TGLF_dataframe()
4052
shot=Int[], time=Int[], ne0=Float64[],
4153
Te0=Float64[], Ti0=Float64[], ne0_exp=Float64[],
4254
Te0_exp=Float64[], Ti0_exp=Float64[], WTH_exp=Float64[],
43-
rot0_exp=Float64[], WTH=Float64[], rot0=Float64[], rho=Vector{Float64}[],
55+
rot0_exp=Float64[], WTH=Float64[], rot0=Float64[], timef=Int[], rho=Vector{Float64}[],
4456
Qe_target=Vector{Float64}[], Qe_TGLF=Vector{Float64}[], Qe_neoc=Vector{Float64}[],
4557
Qi_target=Vector{Float64}[], Qi_TGLF=Vector{Float64}[], Qi_neoc=Vector{Float64}[],
4658
particle_target=Vector{Float64}[], particle_TGLF=Vector{Float64}[], particle_neoc=Vector{Float64}[],
@@ -93,14 +105,19 @@ function _run(study::StudyTGLFdb)
93105
act.ActorTGLF.tglfnn_model = item
94106
end
95107
act.ActorTGLF.lump_ions = sty.lump_ions
96-
108+
if item == "wrapped_model.onnx"
109+
act.ActorTGLF.onnx_model=true
110+
act.ActorTGLF.tglfnn_model = item
111+
end
97112
# paraller run
98113
results = pmap(filename -> run_case(filename, study, item), cases_files)
99114

100115
# populate DataFrame
101116
for row in results
102-
if !isnothing(row)
117+
if row isa NamedTuple || row isa AbstractArray || row isa DataFrameRow || row isa AbstractDict
103118
push!(study.dataframes_dict[string(item)], row)
119+
else
120+
@warn "Invalid row type encountered: $row"
104121
end
105122
end
106123

@@ -120,14 +137,29 @@ function _run(study::StudyTGLFdb)
120137
return study
121138
end
122139

140+
function _analyze(study::StudyTGLFdb)
141+
plot_xy_wth_hist2d(study; quantity=:WTH, save_fig=false, save_path="")
142+
return study
143+
end
144+
123145
function preprocess_dd(filename::AbstractString)
124-
dd = IMAS.json2imas(filename; verbose=false)
146+
dd = IMAS.json2imas(filename; show_warnings=false)
125147

126148
cp1d = dd.core_profiles.profiles_1d[]
127-
value = [interp1d(cp1d.grid.rho_tor_norm, cp1d.electrons.density_thermal).(0.9)]
128-
@ddtime(dd.summary.local.pedestal.n_e.value = value)
129-
value = [interp1d(cp1d.grid.rho_tor_norm, cp1d.electrons.zeff).(0.9)]
130-
@ddtime(dd.summary.local.pedestal.zeff.value = value)
149+
# Handle both single and multiple time slice cases
150+
ne_interp_result = IMAS.interp1d(cp1d.grid.rho_tor_norm, cp1d.electrons.density_thermal)(0.9)
151+
zeff_interp_result = IMAS.interp1d(cp1d.grid.rho_tor_norm, cp1d.zeff)(0.9)
152+
153+
# Convert to vector format: handle scalar (single time slice) or vector (multiple time slices)
154+
if ndims(ne_interp_result) == 0 || (ndims(ne_interp_result) == 2 && size(ne_interp_result) == (1,1))
155+
# Single time slice case: scalar or 1x1 matrix
156+
dd.summary.local.pedestal.n_e.value = [Float64(ne_interp_result)]
157+
dd.summary.local.pedestal.zeff.value = [Float64(zeff_interp_result)]
158+
else
159+
# Multiple time slice case: already a vector
160+
dd.summary.local.pedestal.n_e.value = vec(ne_interp_result)
161+
dd.summary.local.pedestal.zeff.value = vec(zeff_interp_result)
162+
end
131163
dd.pulse_schedule.tf.time = dd.summary.time
132164
dd.pulse_schedule.tf.b_field_tor_vacuum_r.reference = dd.equilibrium.vacuum_toroidal_field.b0
133165

@@ -140,13 +172,23 @@ function run_case(filename::AbstractString, study::StudyTGLFdb, item)
140172

141173
dd = preprocess_dd(filename)
142174

175+
act.ActorFluxMatcher.evolve_densities = FUSE.setup_density_evolution_electron_flux_match_impurities_fixed(dd.core_profiles.profiles_1d[])
176+
177+
# find time from filename
178+
timefn = match(r"(\d+)\.\w+$", filename)
179+
if timefn !== nothing
180+
timef = parse(Int,timefn.captures[1])
181+
else
182+
timef = 0
183+
end
184+
143185
cp1d = dd.core_profiles.profiles_1d[]
144186
exp_values = [
145187
cp1d.electrons.density_thermal[1],
146188
cp1d.electrons.temperature[1],
147189
cp1d.ion[1].temperature[1],
148190
@ddtime(dd.summary.global_quantities.energy_thermal.value),
149-
cp1d.rotation_frequency_tor_sonic[1]]
191+
cp1d.rotation_frequency_tor_sonic[1], timef]
150192

151193
name = split(splitpath(filename)[end], ".")[1]
152194
output_case = joinpath(sty.save_folder, name)
@@ -200,44 +242,64 @@ function create_data_frame_row(dd::IMAS.dd, exp_values::AbstractArray)
200242
eqt = dd.equilibrium.time_slice[]
201243

202244
rho_transport = dd.core_transport.model[1].profiles_1d[].grid_flux.rho_tor_norm
203-
204-
ct1d_tglf = dd.core_transport.model[1].profiles_1d[]
205-
ct1d_target = IMAS.total_fluxes(dd.core_transport, cp1d, rho_transport; time0=dd.global_time)
206-
207-
qybro_bohms = [GACODE.gyrobohm_energy_flux(cp1d, eqt), GACODE.gyrobohm_particle_flux(cp1d, eqt), GACODE.gyrobohm_momentum_flux(cp1d, eqt)]
245+
ct1d_tglf = dd.core_transport.model[1].profiles_1d[]
246+
247+
gyro_bohms = [GACODE.gyrobohm_energy_flux(cp1d, eqt), GACODE.gyrobohm_particle_flux(cp1d, eqt), GACODE.gyrobohm_momentum_flux(cp1d, eqt)]
248+
ini, act_temp = FUSE.case_parameters(:ITER; init_from = :scalars)
249+
act_fm = OverrideParameters(act_temp.ActorFluxMatcher;
250+
rho_transport = rho_transport,
251+
evolve_rotation = :flux_match)
252+
253+
nr = length(rho_transport)
254+
q_mat = reshape(
255+
FUSE.flux_match_targets(dd, act_fm),
256+
nr, 4
257+
)
258+
qi, qe, qp, qg = eachcol(q_mat)
259+
gyro_bohms = [
260+
GACODE.gyrobohm_energy_flux(cp1d, eqt),
261+
GACODE.gyrobohm_particle_flux(cp1d, eqt),
262+
GACODE.gyrobohm_momentum_flux(cp1d, eqt),
263+
]
208264
rho_cp = cp1d.grid.rho_tor_norm
209265

210-
IMAS.interp1d(rho_cp, qybro_bohms[1]).(rho_transport)
211-
rho_cp = cp1d.grid.rho_tor_norm
266+
IMAS.interp1d(rho_cp, gyro_bohms[1]).(rho_transport)
212267

213268
return (
214-
shot=dd.dataset_description.data_entry.pulse,
215-
time=dd.dataset_description.data_entry.pulse,
216-
ne0=cp1d.electrons.density_thermal[1],
217-
Te0=cp1d.electrons.temperature[1],
218-
Ti0=cp1d.ion[1].temperature[1],
219-
WTH=IMAS.@ddtime(dd.summary.global_quantities.energy_thermal.value),
220-
rot0=cp1d.rotation_frequency_tor_sonic[1],
221-
ne0_exp=exp_values[1],
222-
Te0_exp=exp_values[2],
223-
Ti0_exp=exp_values[3],
224-
WTH_exp=exp_values[4],
225-
rot0_exp=exp_values[5],
226-
rho=rho_transport,
227-
Qe_target=ct1d_target.electrons.energy.flux,
228-
Qe_TGLF=ct1d_tglf.electrons.energy.flux,
229-
Qe_neoc=dd.core_transport.model[2].profiles_1d[].electrons.energy.flux,
230-
Qi_target=ct1d_target.total_ion_energy.flux,
231-
Qi_TGLF=ct1d_tglf.total_ion_energy.flux,
232-
Qi_neoc=dd.core_transport.model[2].profiles_1d[].total_ion_energy.flux,
233-
particle_target=ct1d_target.electrons.particles.flux,
234-
particle_TGLF=ct1d_tglf.electrons.particles.flux,
235-
particle_neoc=dd.core_transport.model[2].profiles_1d[].electrons.particles.flux,
236-
momentum_target=ct1d_target.momentum_tor.flux,
237-
momentum_TGLF=ct1d_tglf.momentum_tor.flux,
238-
Q_GB=IMAS.interp1d(rho_cp, qybro_bohms[1]).(rho_transport),
239-
particle_GB=IMAS.interp1d(rho_cp, qybro_bohms[2]).(rho_transport),
240-
momentum_GB=IMAS.interp1d(rho_cp, qybro_bohms[3]).(rho_transport)
269+
shot = dd.dataset_description.data_entry.pulse,
270+
time = Int(dd.summary.time[1] * 1000),
271+
ne0 = cp1d.electrons.density_thermal[1],
272+
Te0 = cp1d.electrons.temperature[1],
273+
Ti0 = cp1d.ion[1].temperature[1],
274+
WTH = IMAS.@ddtime(dd.summary.global_quantities.energy_thermal.value),
275+
rot0 = cp1d.rotation_frequency_tor_sonic[1],
276+
277+
ne0_exp = exp_values[1],
278+
Te0_exp = exp_values[2],
279+
Ti0_exp = exp_values[3],
280+
WTH_exp = exp_values[4],
281+
rot0_exp = exp_values[5],
282+
timef = exp_values[6],
283+
284+
rho = rho_transport,
285+
Qe_target = qe,
286+
Qe_TGLF = ct1d_tglf.electrons.energy.flux,
287+
Qe_neoc = dd.core_transport.model[2].profiles_1d[].electrons.energy.flux,
288+
289+
Qi_target = qi,
290+
Qi_TGLF = ct1d_tglf.total_ion_energy.flux,
291+
Qi_neoc = dd.core_transport.model[2].profiles_1d[].total_ion_energy.flux,
292+
293+
particle_target = qg,
294+
particle_TGLF = ct1d_tglf.electrons.particles.flux,
295+
particle_neoc = dd.core_transport.model[2].profiles_1d[].electrons.particles.flux,
296+
297+
momentum_target = qp,
298+
momentum_TGLF = ct1d_tglf.momentum_tor.flux,
299+
300+
Q_GB = IMAS.interp1d(rho_cp, gyro_bohms[1]).(rho_transport),
301+
particle_GB = IMAS.interp1d(rho_cp, gyro_bohms[2]).(rho_transport),
302+
momentum_GB = IMAS.interp1d(rho_cp, gyro_bohms[3]).(rho_transport),
241303
)
242304
end
243305

0 commit comments

Comments
 (0)