diff --git a/Project.toml b/Project.toml index 4a993bf29..15b737b79 100644 --- a/Project.toml +++ b/Project.toml @@ -42,6 +42,7 @@ NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" NNeutronics = "a9424c20-d414-11ec-167b-9106c24d956c" Optim = "429524aa-4258-5aef-a3af-852621145aeb" OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" +PAM = "8217f67a-9bf0-495c-a6dc-30c3fb73287a" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" PolygonOps = "647866c9-e3ac-4575-94e7-e3d426903924" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" diff --git a/src/FUSE.jl b/src/FUSE.jl index bfc884dfd..58c2bfe60 100644 --- a/src/FUSE.jl +++ b/src/FUSE.jl @@ -108,6 +108,7 @@ include(joinpath("actors", "hcd", "ic_simple_actor.jl")) include(joinpath("actors", "hcd", "lh_simple_actor.jl")) include(joinpath("actors", "hcd", "nbi", "nb_simple_actor.jl")) include(joinpath("actors", "hcd", "pellet_simple_actor.jl")) +include(joinpath("actors", "hcd", "pam_actor.jl")) include(joinpath("actors", "hcd", "nbi", "rabbit_actor.jl")) include(joinpath("actors", "hcd", "nbi", "nbi_actor.jl")) include(joinpath("actors", "hcd", "hcd_actor.jl")) diff --git a/src/actors/hcd/pam_actor.jl b/src/actors/hcd/pam_actor.jl new file mode 100644 index 000000000..61623b515 --- /dev/null +++ b/src/actors/hcd/pam_actor.jl @@ -0,0 +1,102 @@ + import PAM + + +# #= ====== =# +# # PELLET # +# #= ====== =# + Base.@kwdef mutable struct FUSEparameters__ActorPAM{T<:Real} <: ParametersActor{T} + _parent::WeakRef = WeakRef(nothing) + _name::Symbol = :not_set + _time::Float64 = NaN + drift_model::Switch{Symbol} = Switch{Symbol}([:HPI2, :Parks, :none], "-", "drift model"; default=:none) + time_from:: Switch{Symbol} = Switch{Symbol}([:pulse_schedule, :pellet_time, :none], "-", "initialize time for the pellet calculations"; default=:none) + time_step::Entry{Float64} = Entry{Float64}("-", "Time step [s]"; default=0.00001) + time_end::Entry{Float64} = Entry{Float64}("-", "Time end [s]"; default=0.0008) + density_update::Entry{Bool} = Entry{Bool}("-", "Update plasma density"; default=false) + end + + mutable struct ActorPAM{D,P} <: SingleAbstractActor{D,P} + dd::IMAS.dd{D} + par::FUSEparameters__ActorPAM{P} + outputs::Union{PAM.Pellet1,Vector{<:PAM.Pellet1}} + + + function ActorPAM(dd::IMAS.dd{D}, par::FUSEparameters__ActorPAM{P}; kw...) where {D<:Real,P<:Real} + logging_actor_init(ActorPAM) + par = par(kw...) + return new{D,P}(dd, par, PAM.Pellet1[]) + end + end + + """ + ActorPAM(dd::IMAS.dd, act::ParametersAllActors; kw...) + + Estimates the Pellet particle direction, ablation rate, density source deposition + + !!! note + + Reads data in `dd.pellet`, 'dd.equilibrium', and stores data in ... + """ + function ActorPAM(dd::IMAS.dd, act::ParametersAllActors; kw...) + par = act.ActorPAM(kw...) + actor = ActorPAM(dd, par) + step(actor) + finalize(actor) + return actor + end + + function _step(actor::ActorPAM) + dd = actor.dd + par = actor.par + + if par.time_from == :none + t0 = 0 + end + + inputs=( + t0 = t0, + tf = par.time_end, + dt = par.time_step, + drift_model=par.drift_model, + BtDependance=false + ) + + actor.outputs = PAM.run_PAM(dd, inputs) + + + return actor + end + """ + _finalize(actor::ActorPAM) + + Update plasma density in dd + """ + function _finalize(actor::ActorPAM) + dd = actor.dd + cs = dd.core_sources + eqt = dd.equilibrium.time_slice[] + output = actor.outputs + rho = eqt.profiles_1d.rho_tor_norm + volume = IMAS.interp1d(eqt.profiles_1d.rho_tor_norm, eqt.profiles_1d.volume).(rho) + area = IMAS.interp1d(eqt.profiles_1d.rho_tor_norm, eqt.profiles_1d.area).(rho) + + for (ps, pll) in zip(dd.pulse_schedule.pellet.launcher, dd.pellets.launcher) + electrons_particles = vec(sum(output.density_source; dims=1)) + + source = resize!(cs.source, :pellet, "identifier.name" => pll.name; wipe=false) + + IMAS.new_source( + source, + source.identifier.index, + pll.name, + rho, + volume, + area; + electrons_particles, + ) + end + + return actor + end + +