Skip to content

Commit 3ffd9a2

Browse files
committed
Merge remote-tracking branch 'origin' into study_TGLFdb_update
Conflicts: src/actors/transport/flux_matcher_actor.jl
2 parents 6aeaf67 + 8b3983f commit 3ffd9a2

File tree

1 file changed

+49
-34
lines changed

1 file changed

+49
-34
lines changed

src/actors/transport/flux_matcher_actor.jl

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ Base.@kwdef mutable struct FUSEparameters__ActorFluxMatcher{T<:Real} <: Paramete
3333
xtol::Entry{T} = Entry{T}("-", "Tolerance on the solution vector"; default=1E-3, check=x -> @assert x > 0.0 "must be: xtol > 0.0")
3434
algorithm::Switch{Symbol} =
3535
Switch{Symbol}(
36-
[:basic_polyalg, :polyalg, :broyden, :anderson, :simple_trust, :trust, :simple, :old_anderson, :custom, :none],
36+
[:default, :basic_polyalg, :polyalg, :broyden, :anderson, :simple_trust, :simple_dfsane, :trust, :simple, :old_anderson, :custom, :none],
3737
"-",
3838
"Optimizing algorithm used for the flux matching";
39-
default=:basic_polyalg
39+
default=:default
4040
)
4141
custom_algorithm::Entry{NonlinearSolve.AbstractNonlinearSolveAlgorithm} =
4242
Entry{NonlinearSolve.AbstractNonlinearSolveAlgorithm}("-", "User-defined custom solver from NonlinearSolve")
@@ -116,7 +116,7 @@ function _step(actor::ActorFluxMatcher{D,P}) where {D<:Real,P<:Real}
116116

117117
# Apply replay profiles if any evolve options are set to :replay
118118
evolve_densities = evolve_densities_dictionary(cp1d, par)
119-
if par.evolve_Te == :replay || par.evolve_Ti == :replay || par.evolve_rotation == :replay ||
119+
if par.evolve_Te == :replay || par.evolve_Ti == :replay || par.evolve_rotation == :replay ||
120120
(!isempty(evolve_densities) && any(evolve == :replay for (_, evolve) in evolve_densities))
121121
finalize(step(actor.actor_replay))
122122
end
@@ -160,24 +160,36 @@ function _step(actor::ActorFluxMatcher{D,P}) where {D<:Real,P<:Real}
160160
end
161161

162162
autodiff = NonlinearSolve.ADTypes.AutoFiniteDiff()
163-
if typeof(dd).parameters[1] <: ForwardDiff.Dual
163+
if D <: ForwardDiff.Dual
164164
autodiff = NonlinearSolve.ADTypes.AutoForwardDiff()
165165
end
166166

167+
algorithm = if par.algorithm === :default
168+
if actor.actor_ct.actor_turb.par.model === :TGLFNN
169+
# combines speed and robustness, but needs smooth derivatives
170+
:basic_polyalg
171+
else
172+
# derivative-free method
173+
:simple_dfsane
174+
end
175+
else
176+
par.algorithm
177+
end
178+
167179
# Different defaults for gradient-based methods
168180
if par.max_iterations != 0
169181
max_iterations = abs(par.max_iterations)
170-
elseif par.algorithm in (:trust, :simple_trust, :broyden, :polyalg)
182+
elseif algorithm in (:trust, :simple_trust, :broyden, :polyalg)
171183
max_iterations = 50
172184
else
173185
max_iterations = 500
174186
end
175187

176188
res = try
177-
if par.algorithm == :none
189+
if algorithm == :none
178190
res = (zero=opt_parameters,)
179191

180-
elseif par.algorithm == :simple
192+
elseif algorithm == :simple
181193
ftol = Inf # always use xtol condition as in NonlinearSolve.jl
182194
res = flux_match_simple(actor, opt_parameters, initial_cp1d, z_scaled_history, err_history, max_iterations, ftol, par.xtol, prog)
183195

@@ -198,10 +210,10 @@ function _step(actor::ActorFluxMatcher{D,P}) where {D<:Real,P<:Real}
198210
problem = NonlinearSolve.NonlinearProblem(f!, opt_parameters, initial_cp1d)
199211

200212
# 3. Algorithm selection
201-
alg = if par.algorithm == :old_anderson
213+
alg = if algorithm == :old_anderson
202214
NonlinearSolve.NLsolveJL(; method=:anderson, m=4, beta=-par.step_size * 5)
203215

204-
elseif par.algorithm == :anderson
216+
elseif algorithm == :anderson
205217
NonlinearSolve.FixedPointAccelerationJL(;
206218
algorithm=:Anderson,
207219
m=5, # history length
@@ -210,29 +222,32 @@ function _step(actor::ActorFluxMatcher{D,P}) where {D<:Real,P<:Real}
210222
replace_invalids=:ReplaceVector
211223
)
212224

213-
elseif par.algorithm == :broyden
225+
elseif algorithm == :broyden
214226
NonlinearSolve.Broyden(; autodiff)
215227

216-
elseif par.algorithm == :trust
228+
elseif algorithm == :trust
217229
NonlinearSolve.TrustRegion(; autodiff)
218230

219-
elseif par.algorithm == :simple_trust
231+
elseif algorithm == :simple_trust
220232
NonlinearSolve.SimpleTrustRegion(; autodiff)
221233

222-
elseif par.algorithm === :basic_polyalg
234+
elseif algorithm == :simple_dfsane
235+
NonlinearSolve.SimpleDFSane()
236+
237+
elseif algorithm === :basic_polyalg
223238
NonlinearSolve.NonlinearSolvePolyAlgorithm((NonlinearSolve.Broyden(; autodiff),
224239
NonlinearSolve.SimpleTrustRegion(; autodiff)))
225240

226-
elseif par.algorithm == :polyalg
241+
elseif algorithm == :polyalg
227242
# Default NonlinearSolve algorithm
228243
NonlinearSolve.FastShortcutNonlinearPolyalg(; autodiff)
229244

230-
elseif par.algorithm == :custom
245+
elseif algorithm == :custom
231246
ismissing(par.custom_algorithm) && error("custom_algorithm must be set to a NonlinearSolve algorithm for algorithm=:custom")
232247
par.custom_algorithm
233248

234249
else
235-
error("Unsupported algorithm: $(par.algorithm)")
250+
error("Unsupported algorithm: $(algorithm)")
236251
end
237252

238253
# 4. Solve with matching tolerances and iteration limits
@@ -268,7 +283,7 @@ function _step(actor::ActorFluxMatcher{D,P}) where {D<:Real,P<:Real}
268283
end
269284

270285
# detect cases where all optimization calls failed
271-
if par.algorithm != :none && isempty(err_history)
286+
if algorithm != :none && isempty(err_history)
272287
flux_match_errors(actor, opt_parameters, initial_cp1d)
273288
error("FluxMatcher failed")
274289
end
@@ -825,13 +840,13 @@ function pack_z_profiles(cp1d::IMAS.core_profiles__profiles_1d{D}, par::Override
825840
#append!(z_profiles, z_rot)
826841
# Use TGYRO approach: evolve normalized rotation shear f_rot = (dω/dr) / w0_norm
827842
w0_norm = calculate_w0_norm(cp1d.electrons.temperature[1])
828-
843+
829844
# Calculate rotation shear dω/dr
830845
dw_dr = IMAS.gradient(cp1d.grid.rho_tor_norm, cp1d.rotation_frequency_tor_sonic)[cp_gridpoints]
831-
846+
832847
# Convert to normalized rotation shear f_rot
833848
f_rot = dw_dr ./ w0_norm
834-
849+
835850
append!(z_profiles, f_rot)
836851
push!(profiles_paths, (:rotation_frequency_tor_sonic,))
837852
push!(fluxes_paths, (:momentum_tor,))
@@ -910,13 +925,13 @@ function unpack_z_profiles(
910925
#cp1d.rotation_frequency_tor_sonic = IMAS.profile_from_z_transport(cp1d.rotation_frequency_tor_sonic .+ 1, cp1d.grid.rho_tor_norm, cp_rho_transport, z_profiles[counter+1:counter+N])
911926
# Use TGYRO approach: convert normalized rotation shear back to rotation frequency
912927
w0_norm = calculate_w0_norm(cp1d.electrons.temperature[1])
913-
928+
914929
# Get normalized rotation shear f_rot from z_profiles
915930
f_rot_evolved = z_profiles[counter+1:counter+N]
916-
931+
917932
# Convert to rotation shear: dω/dr = f_rot * w0_norm
918933
dw_dr_evolved = f_rot_evolved .* w0_norm
919-
934+
920935
# Use the new profile_from_rotation_shear_transport function
921936
cp1d.rotation_frequency_tor_sonic = IMAS.profile_from_rotation_shear_transport(
922937
cp1d.rotation_frequency_tor_sonic,
@@ -1133,7 +1148,7 @@ end
11331148
11341149
Calculate TGYRO normalization frequency w0_norm = cs/R₀ where:
11351150
1136-
cs = sound speed at axis = √(kB*Te(0)/md)
1151+
cs = sound speed at axis = √(kB*Te(0)/md)
11371152
"""
11381153
function calculate_w0_norm(Te_axis)
11391154
cs_axis = sqrt(IMAS.mks.k_B * Te_axis / IMAS.mks.m_d) # sound speed at axis
@@ -1149,29 +1164,29 @@ Replay profiles from replay_dd to current dd for channels set to :replay
11491164
function _step(replay_actor::ActorReplay, actor::ActorFluxMatcher, replay_dd::IMAS.dd)
11501165
dd = actor.dd
11511166
par = actor.par
1152-
1167+
11531168
time0 = dd.global_time
11541169
cp1d = dd.core_profiles.profiles_1d[time0]
11551170
replay_cp1d = replay_dd.core_profiles.profiles_1d[time0]
11561171
rho = cp1d.grid.rho_tor_norm
1157-
1172+
11581173
# Get the transport grid boundary for blending
11591174
rho_nml = par.rho_transport[end]
11601175
rho_ped = par.rho_transport[end]
1161-
1176+
11621177
# Replay electron temperature if set to :replay
11631178
if par.evolve_Te == :replay
11641179
cp1d.electrons.temperature = IMAS.blend_core_edge(replay_cp1d.electrons.temperature, cp1d.electrons.temperature, rho, rho_nml, rho_ped)
11651180
end
1166-
1167-
# Replay ion temperature if set to :replay
1181+
1182+
# Replay ion temperature if set to :replay
11681183
if par.evolve_Ti == :replay
11691184
Ti_replay = IMAS.blend_core_edge(replay_cp1d.t_i_average, cp1d.t_i_average, rho, rho_nml, rho_ped)
11701185
for ion in cp1d.ion
11711186
ion.temperature = Ti_replay
11721187
end
11731188
end
1174-
1189+
11751190
# Replay rotation if set to :replay
11761191
if par.evolve_rotation == :replay
11771192
i_nml = IMAS.argmin_abs(rho, rho_nml)
@@ -1181,15 +1196,15 @@ function _step(replay_actor::ActorReplay, actor::ActorFluxMatcher, replay_dd::IM
11811196
ω_core[1:i_nml] = ω_core[1:i_nml] .- ω_core[i_nml] .+ ω_edge[i_nml]
11821197
cp1d.rotation_frequency_tor_sonic = ω_core
11831198
end
1184-
1199+
11851200
# Handle density replays
11861201
evolve_densities = evolve_densities_dictionary(cp1d, par)
11871202
if !isempty(evolve_densities)
11881203
# Replay electron density if set to :replay
11891204
if evolve_densities[:electrons] == :replay
11901205
cp1d.electrons.density_thermal = IMAS.blend_core_edge(replay_cp1d.electrons.density_thermal, cp1d.electrons.density_thermal, rho, rho_nml, rho_ped; method=:scale)
11911206
end
1192-
1207+
11931208
# Replay ion densities if set to :replay
11941209
for (ion, replay_ion) in zip(cp1d.ion, replay_cp1d.ion)
11951210
ion_symbol = Symbol(ion.label)
@@ -1199,7 +1214,7 @@ function _step(replay_actor::ActorReplay, actor::ActorFluxMatcher, replay_dd::IM
11991214
end
12001215
end
12011216
end
1202-
1217+
12031218
# Ensure quasi neutrality if needed
12041219
for (species, evolve) in evolve_densities
12051220
if evolve == :quasi_neutrality
@@ -1208,6 +1223,6 @@ function _step(replay_actor::ActorReplay, actor::ActorFluxMatcher, replay_dd::IM
12081223
end
12091224
end
12101225
end
1211-
1226+
12121227
return replay_actor
12131228
end

0 commit comments

Comments
 (0)