Skip to content

QL-Balance ParameterScan with KIM: rescaled profiles never reach KIM (wave solution frozen at base profiles) #136

@marjohma

Description

@marjohma

Summary

In ParameterScan mode with wave_code = "KIM" and kim_profiles_from_balance = .true. (Path A), the per-point (fac_n, fac_Te) rescaled profiles are never re-injected into KIM. KIM solves the base-profile plasma at every scan point; only QL-Balance's quasilinear prefactor (evaluated from the rescaled profiles) varies. All KIM ParameterScan results produced so far are therefore not parameter scans of the plasma response.

Evidence (production runs, AUG 33353 t=2900, m=6, 5x10 factor grid, 100/200 KIM grid)

  • KIM scan output: br_abs_res and antenna_factor_res are identical across all 50 scan points (0.3519 G and 38.48), i.e. the wave solution never changed.
  • The same scan with wave_code = "KiLCA" produces 50 distinct values of both, as expected.
  • The resulting KIM "bifurcation ratio" is almost exactly linear in fac_n and nearly flat in fac_Te — consistent with pure prefactor scaling (nu_e proportional to n) on a frozen field solution.
  • The balance log shows 50 kernel-fill phases (~5 min each at 100/200): the kernels were rebuilt 50 times from the same unchanged plasma state, producing identical results each time (~5 h of redundant compute per scan).

Cause

Profiles are injected into KIM exactly once, in kim_initialize (Path A):

QL-Balance/src/base/kim_wave_code_adapter.f90:141

call set_profiles_from_arrays(r, n, Te, Ti, q, -dPhi0, dim_r)

The per-call entry point kim_run_for_all_modes deliberately skips re-injection, and the guarding comment only considers SingleStep vs TimeEvolution — ParameterScan (which rescales the wave_code_data profile arrays between wave-code calls, see QL-Balance/src/base/paramscan.f90, runParameterScan) was not considered:

QL-Balance/src/base/kim_wave_code_adapter.f90:378-387

! -------------------------------------------------------
! 0. Re-inject time-evolved QL-Balance profiles into KIM
! -------------------------------------------------------
! NOTE: Profile re-injection is only needed in TimeEvolution mode
! where profiles change between calls. For SingleStep, skip it
! because set_profiles_from_arrays deallocates derived quantities
! (B0, kp, ks, vT, nu, x1, x2, etc.) that the solver needs.
! Re-injection for TimeEvolution would require also calling
! calculate_equil and set_plasma_quantities to recompute derived
! quantities on the rg_grid.

Note this implies TimeEvolution mode with KIM is affected by the same defect (the comment describes re-injection as needed there, but it is not implemented).

Suggested fix

In kim_run_for_all_modes, when the wave_code_data profiles have changed since the last call (ParameterScan and TimeEvolution), re-run the injection chain: set_profiles_from_arrays followed by recomputation of the derived equilibrium/plasma quantities on the rg grid (calculate_equil, set_plasma_quantities), before kernel filling. A cheap change-detection (hash or first/last/sum of n, Te arrays) would avoid the cost in SingleStep.

A regression test could assert that two ParameterScan points with different fac_n produce different br_abs_res with KIM, mirroring the KiLCA behavior.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions