|
| 1 | +# magic broadcast with @. |
| 2 | +# factor 3//2 due to isotropic overage of dipole |
| 3 | +dipole_moment_sq(f, ΔE) = @. 3//2 * f / ΔE |
| 4 | + |
| 5 | +# DOORWAYS |
| 6 | + |
| 7 | +# "Beware of Doors." - Neverwhere |
| 8 | + |
| 9 | +# GSB |
| 10 | +function doorway(::GSB, traj::Trajectory, pump::LaserPulse, ω_pump::Real, frame::Int) |
| 11 | + ΔE = delta_energy(traj, frame) |
| 12 | + μ² = dipole_moment_sq(traj.oscillators[:, frame], ΔE) |
| 13 | + Δω = @. ω_pump - ΔE |
| 14 | + τ_au = pump.τ * fs2au |
| 15 | + E = spectral_envelope(Δω, τ_au, pump.envelope, pump) |
| 16 | + return sum(@. E^2 * μ²) # returns a scalar, no mutation |
| 17 | +end |
| 18 | + |
| 19 | +# SE |
| 20 | +function doorway(::SE, traj::Trajectory, pump::LaserPulse, ω_pump::Real, frame::Int) |
| 21 | + s = traj.active_state[frame] |
| 22 | + ΔE = traj.energies[s + 1, frame] - traj.energies[1, frame] |
| 23 | + μ² = dipole_moment_sq(traj.oscillators[s, frame], ΔE) |
| 24 | + Δω = ω_pump - ΔE |
| 25 | + τ_au = pump.τ * fs2au |
| 26 | + E = spectral_envelope(Δω, τ_au, pump.envelope, pump) |
| 27 | + return E^2 * μ² # scalar, single active state |
| 28 | +end |
| 29 | + |
| 30 | +# WINDOWS |
| 31 | + |
| 32 | +# GSB |
| 33 | +function window(::GSB, traj::Trajectory, probe::LaserPulse, ω_probe::AbstractVector) |
| 34 | + ΔE = delta_energy(traj) # (n_states-1) x n_steps |
| 35 | + μ² = dipole_moment_sq(traj.oscillators, ΔE) # (n_states-1) x n_steps |
| 36 | + n_t = n_steps(traj) |
| 37 | + n_ω = length(ω_probe) |
| 38 | + τ_au = probe.τ * fs2au |
| 39 | + |
| 40 | + W = zeros(n_t, n_ω) |
| 41 | + for (j, ω) in enumerate(ω_probe) |
| 42 | + Δω = @. ω .- ΔE # (n_states-1) x n_steps |
| 43 | + E = spectral_envelope(Δω, τ_au, probe.envelope, probe) |
| 44 | + @views W[:, j] .= vec(sum(@. E^2 * μ²; dims=1)) # sum over states |
| 45 | + end |
| 46 | + return W |
| 47 | +end |
| 48 | + |
| 49 | +# SE |
| 50 | +function window(::SE, traj::Trajectory, probe::LaserPulse, ω_probe::AbstractVector) |
| 51 | + n_t = n_steps(traj) |
| 52 | + n_ω = length(ω_probe) |
| 53 | + τ_au = probe.τ * fs2au |
| 54 | + |
| 55 | + # Extract active-state ΔE and oscillator for each frame |
| 56 | + ΔE_active = Vector{Float64}(undef, n_t) |
| 57 | + f_active = Vector{Float64}(undef, n_t) |
| 58 | + for t in 1:n_t |
| 59 | + s = traj.active_state[t] |
| 60 | + ΔE_active[t] = traj.energies[s + 1, t] - traj.energies[1, t] |
| 61 | + f_active[t] = traj.oscillators[s, t] |
| 62 | + end |
| 63 | + |
| 64 | + μ² = dipole_moment_sq(f_active, ΔE_active) |
| 65 | + # Guard against Inf/NaN from zero ΔE (trajectory at ground state) |
| 66 | + μ² .= ifelse.(isfinite.(μ²), μ², 0.0) |
| 67 | + |
| 68 | + W = zeros(n_t, n_ω) |
| 69 | + for (j, ω) in enumerate(ω_probe) |
| 70 | + Δω = @. ω - ΔE_active |
| 71 | + E = spectral_envelope(Δω, τ_au, probe.envelope, probe) |
| 72 | + @views W[:, j] .= @. E^2 * μ² |
| 73 | + end |
| 74 | + return W |
| 75 | +end |
| 76 | + |
| 77 | +# OK, generate the spectrum! |
| 78 | + |
| 79 | +# Convenience function for same LaserPulse in both pump and probe |
| 80 | +function spectrum(sig::SignalType, traj::Trajectory, |
| 81 | + laser::LaserPulse, ω_pump::Real, ω_probe::AbstractVector) |
| 82 | + spectrum(sig, traj, laser, ω_pump, laser, ω_probe) |
| 83 | +end |
| 84 | + |
| 85 | +""" |
| 86 | +Pump-probe spectrum: doorway (n_steps,) .* window (n_steps, n_probe). |
| 87 | +
|
| 88 | +User-facing frequencies ω_pump, ω_probe are in **eV**; internally converted |
| 89 | +to Hartree to match trajectory energies. |
| 90 | +
|
| 91 | +Returns: (n_steps, n_probe) matrix. Sum over time steps for integrated signal. |
| 92 | +""" |
| 93 | +function spectrum(sig::SignalType, traj::Trajectory, |
| 94 | + pump::LaserPulse, ω_pump::Real, |
| 95 | + probe::LaserPulse, ω_probe::AbstractVector) |
| 96 | + ω_pu_au = ω_pump * eV2Ha |
| 97 | + ω_pr_au = ω_probe .* eV2Ha |
| 98 | + d = [doorway(sig, traj, pump, ω_pu_au, t) for t in 1:n_steps(traj)] |
| 99 | + W = window(sig, traj, probe, ω_pr_au) |
| 100 | + return d .* W |
| 101 | +end |
| 102 | + |
| 103 | + |
0 commit comments